#include <vector>
-#include "support/utility.hpp"
+#include <boost/utility.hpp>
+#include "support/LOstream.h"
/** An abstract base class for button policies.
A state machine implementation of the various button policies used by the
NoRepeatedApply | N | Y | N
NoRepeatedApplyReadOnly | Y | Y | N
Preferences | N | Y | No (Ok-Close)
+ Ignorant | N/A | N/A | N/A
========================================================================
Policy
has its own special version of repeated apply handling because its Ok
button is actually a Save button -- its always reasonable to Save the
preferences if the dialog has changed since the last save.
+
+ The IgnorantPolicy is a special case that allows anything.
*/
-class ButtonPolicy : public noncopyable
-{
+class ButtonPolicy : public noncopyable {
public:
- /**@name Constructors and Deconstructors */
- //@{
///
virtual ~ButtonPolicy() {}
- //@}
- /**@name Enums */
- //@{
/** The various possible state names.
Not all state-machines have this many states. However, we need
to define them all here so we can share the code.
*/
enum State {
+ ///
INITIAL = 0,
+ ///
VALID,
+ ///
INVALID,
+ ///
APPLIED,
+ ///
RO_INITIAL,
+ ///
RO_VALID,
+ ///
RO_INVALID,
+ ///
RO_APPLIED,
+ ///
BOGUS = 55
};
+
/// The various button types.
enum Button {
+ ///
CLOSE = 0, // Not a real button, but effectively !CANCEL
+ ///
OKAY = 1,
+ ///
APPLY = 2,
+ ///
CANCEL = 4,
+ ///
UNDO_ALL = 8
};
+ ///
+ static const Button ALL_BUTTONS =
+ Button(OKAY | APPLY | CANCEL | UNDO_ALL);
+
/** State machine inputs.
All the policies so far have both CANCEL and HIDE always going to
INITIAL. This won't necessarily be true for all [future] policies
HIDE are treated differently.
*/
enum SMInput {
+ ///
SMI_VALID = 0,
+ ///
SMI_INVALID,
+ ///
SMI_OKAY,
+ ///
SMI_APPLY,
+ ///
SMI_CANCEL,
+ ///
SMI_UNDO_ALL,
+ ///
SMI_HIDE,
+ ///
SMI_READ_ONLY,
+ ///
SMI_READ_WRITE,
+ ///
SMI_TOTAL // not a real input
};
- //@}
- /**@name Access Functions */
- //@{
/// Trigger a transition with this input.
virtual void input(SMInput) = 0;
/// Activation status of a button
- virtual bool buttonStatus(Button) = 0;
+ virtual bool buttonStatus(Button) const = 0;
/// Are we in a read-only state?
- virtual bool isReadOnly() = 0;
- //@}
+ virtual bool isReadOnly() const = 0;
- /**@name Typedefs */
- //@{
/// Transition map of the state machine.
typedef std::vector<State> StateArray;
+ ///
typedef std::vector<StateArray> StateMachine;
/// The state outputs are the status of the buttons.
typedef std::vector<int> StateOutputs;
- //@}
};
-//--------------------- Actual Policy Classes ----------------------------------
+inline
+std::ostream & operator<<(std::ostream & os, ButtonPolicy::State st)
+{
+ os << int(st);
+ return os;
+}
+
+
+inline
+std::ostream & operator<<(std::ostream & os, ButtonPolicy::SMInput smi)
+{
+ os << int(smi);
+ return os;
+}
+
+
+//--------------------- Actual Policy Classes -----------------------------
/** Ok and Cancel buttons for dialogs with read-only operation.
- Note: This scheme supports the relabelling of Cancel to Close and vice versa.
+ Note: This scheme supports the relabelling of Cancel to Close and
+ vice versa.
This is based on the value of the bool state of the Button::CANCEL.
true == Cancel, false == Close
*/
-class OkCancelPolicy : public ButtonPolicy
-{
+class OkCancelPolicy : public ButtonPolicy {
public:
///
OkCancelPolicy();
///
- virtual ~OkCancelPolicy() {}
+ //virtual ~OkCancelPolicy() {}
- /**@name Access Functions */
- //@{
/// Trigger a transition with this input.
virtual void input(SMInput);
/** Activation status of a button.
the outputs_ variable. Perhaps we can do something at compile
time to check that all the states have corresponding outputs.
*/
- virtual bool buttonStatus(Button button)
- { return button & outputs_[state_]; }
+ virtual bool buttonStatus(Button button) const {
+ return button & outputs_[state_];
+ }
/// Are we in a read-only state?
- virtual bool isReadOnly()
- { return false; }
- //@}
+ virtual bool isReadOnly() const {
+ return false;
+ }
private:
- /**@name Private Data Members */
- //@{
/// Current state.
State state_;
/// Which buttons are active for a given state.
StateOutputs outputs_;
///
StateMachine state_machine_;
- //@}
};
-
+/** OK button policy for dialogs that can't mutate the document,
+ and are always valid
+ */
+class OkViewPolicy : public ButtonPolicy {
+public:
+ ///
+ OkViewPolicy();
+ /// Trigger a transition with this input
+ virtual void input(SMInput);
+ /// activation status
+ virtual bool buttonStatus(Button button) const {
+ return button & outputs_[state_];
+ }
+ /// are we in a read-only state ?
+ virtual bool isReadOnly() const {
+ return false;
+ }
+private:
+ /// current state
+ State state_;
+ /// which buttons are active
+ StateOutputs outputs_;
+ ///
+ StateMachine state_machine_;
+};
+
/** Ok and Cancel buttons for dialogs where read-only operation is blocked.
The state machine design for this policy allows changes to occur within
the dialog while a file is read-only -- the okay button is disabled until
a read-write input is given. When the file is made read-write the dialog
- will then be in the correct state (as if the file had always been read-write).
- Note: This scheme supports the relabelling of Cancel to Close and vice versa.
+ will then be in the correct state (as if the file had always been
+ read-write).
+ Note: This scheme supports the relabelling of Cancel to Close
+ and vice versa.
This is based on the value of the bool state of the Button::CANCEL.
true == Cancel, false == Close
*/
-class OkCancelReadOnlyPolicy : public ButtonPolicy
-{
+class OkCancelReadOnlyPolicy : public ButtonPolicy {
public:
///
OkCancelReadOnlyPolicy();
///
- virtual ~OkCancelReadOnlyPolicy() {}
+ //virtual ~OkCancelReadOnlyPolicy() {}
- /**@name Access Functions */
- //@{
/// Trigger a transition with this input.
virtual void input(SMInput);
/// Activation status of a button.
- virtual bool buttonStatus(Button button)
- { return button & outputs_[state_]; }
+ virtual bool buttonStatus(Button button) const {
+ return button & outputs_[state_];
+ }
/// Are we in a read-only state?
- virtual bool isReadOnly()
- {
- return RO_INITIAL == state_
- || RO_VALID == state_
- || RO_INVALID == state_
- || RO_APPLIED == state_;
- }
- //@}
+ virtual bool isReadOnly() const {
+ return RO_INITIAL == state_
+ || RO_VALID == state_
+ || RO_INVALID == state_
+ || RO_APPLIED == state_;
+ }
private:
- /**@name Private Data Members */
- //@{
/// Current state.
State state_;
/// Which buttons are active for a given state.
StateOutputs outputs_;
///
StateMachine state_machine_;
- //@}
};
-/** Ok, Apply and Cancel buttons for dialogs where read-only operation is blocked.
+/** Ok, Apply and Cancel buttons for dialogs where read-only operation
+ is blocked.
Repeated Apply are not allowed. Likewise, Ok cannot follow Apply without
- some valid input. That is, the dialog contents must change between each Apply
- or Apply and Ok.
+ some valid input. That is, the dialog contents must change between
+ each Apply or Apply and Ok.
The state machine design for this policy allows changes to occur within
the dialog while a file is read-only -- the Ok+Apply buttons are disabled
until a read-write input is given. When the file is made read-write the
dialog will then be in the correct state (as if the file had always been
read-write).
- Note: This scheme supports the relabelling of Cancel to Close and vice versa.
+ Note: This scheme supports the relabelling of Cancel to Close
+ and vice versa.
This is based on the value of the bool state of the Button::CANCEL.
true == Cancel, false == Close
*/
///
NoRepeatedApplyReadOnlyPolicy();
///
- virtual ~NoRepeatedApplyReadOnlyPolicy() {}
+ //virtual ~NoRepeatedApplyReadOnlyPolicy() {}
- /**@name Access Functions */
- //@{
/// Trigger a transition with this input.
virtual void input(SMInput);
/// Activation status of a button.
- virtual bool buttonStatus(Button button)
- { return button & outputs_[state_]; }
+ virtual bool buttonStatus(Button button) const {
+ return button & outputs_[state_];
+ }
/// Are we in a read-only state?
- virtual bool isReadOnly()
- {
- return RO_INITIAL == state_
- || RO_VALID == state_
- || RO_INVALID == state_
- || RO_APPLIED == state_;
- }
- //@}
+ virtual bool isReadOnly() const {
+ return RO_INITIAL == state_
+ || RO_VALID == state_
+ || RO_INVALID == state_
+ || RO_APPLIED == state_;
+ }
private:
- /**@name Private Data Members */
- //@{
/// Current state.
State state_;
/// Which buttons are active for a given state.
StateOutputs outputs_;
///
StateMachine state_machine_;
- //@}
};
-/** Ok, Apply and Cancel buttons for dialogs where read-only operation is blocked.
+/** Ok, Apply and Cancel buttons for dialogs where read-only
+ operation is blocked.
Repeated Apply is allowed. Likewise, Ok can follow Apply.
The state machine design for this policy allows changes to occur within
the dialog while a file is read-only -- the Ok+Apply buttons are disabled
until a read-write input is given. When the file is made read-write the
dialog will then be in the correct state (as if the file had always been
read-write).
- Note: This scheme supports the relabelling of Cancel to Close and vice versa.
+ Note: This scheme supports the relabelling of Cancel to Close
+ and vice versa.
This is based on the value of the bool state of the Button::CANCEL.
true == Cancel, false == Close
*/
-class OkApplyCancelReadOnlyPolicy : public ButtonPolicy
-{
+class OkApplyCancelReadOnlyPolicy : public ButtonPolicy {
public:
///
OkApplyCancelReadOnlyPolicy();
///
- virtual ~OkApplyCancelReadOnlyPolicy() {}
+ //virtual ~OkApplyCancelReadOnlyPolicy() {}
- /**@name Access Functions */
- //@{
/// Trigger a transition with this input.
virtual void input(SMInput);
/// Activation status of a button.
- virtual bool buttonStatus(Button button)
- { return button & outputs_[state_]; }
+ virtual bool buttonStatus(Button button) const {
+ return button & outputs_[state_];
+ }
/// Are we in a read-only state?
- virtual bool isReadOnly()
- {
- return RO_INITIAL == state_
- || RO_VALID == state_
- || RO_INVALID == state_
- || RO_APPLIED == state_;
- }
- //@}
+ virtual bool isReadOnly() const {
+ return RO_INITIAL == state_
+ || RO_VALID == state_
+ || RO_INVALID == state_
+ || RO_APPLIED == state_;
+ }
private:
- /**@name Private Data Members */
- //@{
/// Current state.
State state_;
/// Which buttons are active for a given state.
StateOutputs outputs_;
///
StateMachine state_machine_;
- //@}
};
/** Ok, Apply and Cancel buttons for dialogs where repeated Apply is allowed.
- Note: This scheme supports the relabelling of Cancel to Close and vice versa.
+ Note: This scheme supports the relabelling of Cancel to Close
+ and vice versa.
This is based on the value of the bool state of the Button::CANCEL.
true == Cancel, false == Close
*/
-class OkApplyCancelPolicy : public ButtonPolicy
-{
+class OkApplyCancelPolicy : public ButtonPolicy {
public:
///
OkApplyCancelPolicy();
///
- virtual ~OkApplyCancelPolicy() {}
+ //virtual ~OkApplyCancelPolicy() {}
- /**@name Access Functions */
- //@{
/// Trigger a transition with this input.
virtual void input(SMInput);
/// Activation status of a button.
- virtual bool buttonStatus(Button button)
- { return button & outputs_[state_]; }
+ virtual bool buttonStatus(Button button) const {
+ return button & outputs_[state_];
+ }
/// Are we in a read-only state?
- virtual bool isReadOnly()
- { return false; }
- //@}
+ virtual bool isReadOnly() const {
+ return false;
+ }
private:
- /**@name Private Data Members */
- //@{
/// Current state.
State state_;
/// Which buttons are active for a given state.
StateOutputs outputs_;
///
StateMachine state_machine_;
- //@}
};
/** Ok, Apply and Cancel buttons for dialogs with no repeated Apply.
- Note: This scheme supports the relabelling of Cancel to Close and vice versa.
+ Note: This scheme supports the relabelling of Cancel to Close
+ and vice versa.
This is based on the value of the bool state of the Button::CANCEL.
true == Cancel, false == Close
*/
-class NoRepeatedApplyPolicy : public ButtonPolicy
-{
+class NoRepeatedApplyPolicy : public ButtonPolicy {
public:
///
NoRepeatedApplyPolicy();
///
- virtual ~NoRepeatedApplyPolicy() {}
+ //virtual ~NoRepeatedApplyPolicy() {}
- /**@name Access Functions */
- //@{
/// Trigger a transition with this input.
virtual void input(SMInput);
/// Activation status of a button.
- virtual bool buttonStatus(Button button)
- { return button & outputs_[state_]; }
+ virtual bool buttonStatus(Button button) const {
+ return button & outputs_[state_];
+ }
/// Are we in a read-only state?
- virtual bool isReadOnly()
- { return false; }
- //@}
+ virtual bool isReadOnly() const {
+ return false;
+ }
private:
- /**@name Private Data Members */
- //@{
/// Current state.
State state_;
/// Which buttons are active for a given state.
StateOutputs outputs_;
///
StateMachine state_machine_;
- //@}
};
/** Defines the policy used by the Preferences dialog.
Four buttons: Ok (Save), Apply, Cancel/Close, Restore.
- Note: This scheme supports the relabelling of Cancel to Close and vice versa.
+ Note: This scheme supports the relabelling of Cancel to Close
+ and vice versa.
This is based on the value of the bool state of the Button::CANCEL.
true == Cancel, false == Close
*/
-class PreferencesPolicy : public ButtonPolicy
-{
+class PreferencesPolicy : public ButtonPolicy {
public:
///
PreferencesPolicy();
///
- virtual ~PreferencesPolicy() {}
+ //virtual ~PreferencesPolicy() {}
- /**@name Access Functions */
- //@{
/// Trigger a transition with this input.
virtual void input(SMInput);
/// Activation status of a button.
- virtual bool buttonStatus(Button button)
- { return button & outputs_[state_]; }
+ virtual bool buttonStatus(Button button) const {
+ return button & outputs_[state_];
+ }
/// Are we in a read-only state?
- virtual bool isReadOnly()
- { return false; }
- //@}
+ virtual bool isReadOnly() const {
+ return false;
+ }
private:
- /**@name Private Data Members */
- //@{
/// Current state.
State state_;
/// Which buttons are active for a given state.
StateOutputs outputs_;
///
StateMachine state_machine_;
- //@}
+};
+
+
+/** Defines the policy used by dialogs that are forced to support a button
+ controller when they either don't have a use for one or are not ready to
+ use one. This may be useful when testing a new button policy but wishing
+ to minimise problems to users by supplying an anything-goes policy via a
+ preprocessor directive.
+ */
+class IgnorantPolicy : public ButtonPolicy {
+public:
+ //virtual ~IgnorantPolicy() {}
+
+ /// Trigger a transition with this input.
+ virtual void input(SMInput) {}
+ /// Activation status of a button.
+ virtual bool buttonStatus(Button) const {
+ return true;
+ }
+ /// Are we in a read-only state?
+ virtual bool isReadOnly() const {
+ return false;
+ }
};
#endif