4 * This file is part of LyX, the document processor.
5 * Licence details can be found in the file COPYING.
9 * Full author contact details are available in file CREDITS.
11 * Provides a state machine implementation of the various button policies
12 * used by the dialogs.
15 #ifndef BUTTONPOLICY_H
16 #define BUTTONPOLICY_H
24 /** A class for button policies.
25 A state machine implementation of the various button policies used by the
26 dialogs. Only the policy is implemented here. Separate ButtonController
27 classes are needed for each GUI implementation.
29 Policy | ReadOnly | Apply Button | Repeated Apply
30 ========================================================================
32 OkCancelReadOnly | Y | N | -
33 OkApplyCancel | N | Y | Y
34 OkApplyCancelReadOnly | Y | Y | Y
35 NoRepeatedApply | N | Y | N
36 NoRepeatedApplyReadOnly | Y | Y | N
37 Preferences | N | Y | No (Ok-Close)
38 Ignorant | N/A | N/A | N/A
39 ========================================================================
42 The name of the policy
44 Does the policy treat read-only docs differently to read-write docs?
45 This usually means that when an SMI_READ_ONLY input arrives then
46 all the buttons are disabled except Cancel/Close. The state
47 machine tracks the inputs (valid/invalid) and has states for all
48 combinations. When an SMI_READ_WRITE input arrives the appropriate
49 machine state is entered (just as if the document had always been
51 NOTE: If a dialog doesn't care about the read-only status of a document
52 (and uses an appropriate policy) it can never get into a read-only state
53 so isReadOnly() can only ever return false even though the document may
56 Simply means that it is alright to use the Apply button multiple times
57 without requiring a change of the dialog contents. If no repeating is
58 allowed the Ok+Apply buttons are deactivated. The Preferences dialog
59 has its own special version of repeated apply handling because its Ok
60 button is actually a Save button -- it is always reasonable to Save the
61 preferences if the dialog has changed since the last save.
63 The IgnorantPolicy is a special case that allows anything.
69 // The various poicies
71 /** Ok and Cancel buttons for dialogs with read-only operation.
72 Note: This scheme supports the relabelling of Cancel to Close and
74 This is based on the value of the bool state of the Button::CANCEL.
75 true == Cancel, false == Close
80 /** Ok and Cancel buttons for dialogs where read-only operation is blocked.
81 The state machine design for this policy allows changes to occur within
82 the dialog while a file is read-only -- the okay button is disabled until
83 a read-write input is given. When the file is made read-write the dialog
84 will then be in the correct state (as if the file had always been
86 Note: This scheme supports the relabelling of Cancel to Close
88 This is based on the value of the bool state of the Button::CANCEL.
89 true == Cancel, false == Close
91 OkCancelReadOnlyPolicy,
93 /** Ok, Apply and Cancel buttons for dialogs where read-only operation
95 Repeated Apply are not allowed. Likewise, Ok cannot follow Apply without
96 some valid input. That is, the dialog contents must change between
97 each Apply or Apply and Ok.
98 The state machine design for this policy allows changes to occur within
99 the dialog while a file is read-only -- the Ok+Apply buttons are disabled
100 until a read-write input is given. When the file is made read-write the
101 dialog will then be in the correct state (as if the file had always been
103 Note: This scheme supports the relabelling of Cancel to Close
105 This is based on the value of the bool state of the Button::CANCEL.
106 true == Cancel, false == Close
108 NoRepeatedApplyReadOnlyPolicy,
110 /** Ok, Apply and Cancel buttons for dialogs where read-only
111 operation is blocked.
112 Repeated Apply is allowed. Likewise, Ok can follow Apply.
113 The state machine design for this policy allows changes to occur within
114 the dialog while a file is read-only -- the Ok+Apply buttons are disabled
115 until a read-write input is given. When the file is made read-write the
116 dialog will then be in the correct state (as if the file had always been
118 Note: This scheme supports the relabelling of Cancel to Close
120 This is based on the value of the bool state of the Button::CANCEL.
121 true == Cancel, false == Close
123 OkApplyCancelReadOnlyPolicy,
125 /** Ok, Apply and Cancel buttons for dialogs where repeated
127 Note: This scheme supports the relabelling of Cancel to Close
129 This is based on the value of the bool state of the Button::CANCEL.
130 true == Cancel, false == Close
134 /** Ok, Apply and Cancel buttons for dialogs with no repeated Apply.
135 Note: This scheme supports the relabelling of Cancel to Close
137 This is based on the value of the bool state of the Button::CANCEL.
138 true == Cancel, false == Close
140 NoRepeatedApplyPolicy,
142 /** Defines the policy used by the Preferences dialog.
143 Four buttons: Ok (Save), Apply, Cancel/Close, Restore.
144 Note: This scheme supports the relabelling of Cancel to Close
146 This is based on the value of the bool state of the Button::CANCEL.
147 true == Cancel, false == Close
151 /** Defines the policy used by dialogs that are forced to support a button
152 controller when they either don't have a use for one or are not ready to
153 use one. This may be useful when testing a new button policy but wishing
154 to minimise problems to users by supplying an anything-goes policy via a
155 preprocessor directive.
161 explicit ButtonPolicy(Policy policy);
163 /** The various possible state names.
164 Not all state-machines have this many states. However, we need
165 to define them all here so we can share the code.
188 /// The various button types.
191 CLOSE = 0, // Not a real button, but effectively !CANCEL
202 static const Button ALL_BUTTONS =
203 Button(OKAY | APPLY | CANCEL | RESTORE);
205 /** State machine inputs.
206 All the policies so far have both CANCEL and HIDE always going to
207 INITIAL. This won't necessarily be true for all [future] policies
208 though so I'll leave those two as distinct inputs rather than merge
209 them. For example, a dialog that doesn't update it's input fields
210 when reshown after being hidden needs a policy where CANCEL and
211 HIDE are treated differently.
214 /// the dialog contents are now valid
216 /// the dialog contents are now invalid
218 /// an apply-and-hide action has happened
220 /// an apply action has happened
222 /// a cancel action has happened
224 /// a restore action has happened
226 /// the dialog has been hidden
228 /// the dialog contents are read-only
230 /// the dialog contents can be modified
232 /// the state of the dialog contents has not changed
238 /// Trigger a transition with this input.
240 /** Activation status of a button.
241 We assume that we haven't gotten into an undefined state.
242 This is reasonable since we can only reach states defined
243 in the state machine and they should all have been defined in
244 the outputs_ variable. Perhaps we can do something at compile
245 time to check that all the states have corresponding outputs.
247 bool buttonStatus(Button) const;
248 /// Are we in a read-only state?
249 bool isReadOnly() const;
255 /// Transition map of the state machine.
256 typedef std::vector<State> StateArray;
258 typedef std::vector<StateArray> StateMachine;
259 /// The state outputs are the status of the buttons.
260 typedef std::vector<int> StateOutputs;
264 /// Which buttons are active for a given state.
265 StateOutputs outputs_;
267 StateMachine state_machine_;
271 void nextState(SMInput input);
274 void initOkCancelReadOnly();
275 void initNoRepeatedApplyReadOnly();
276 void initOkApplyCancelReadOnly();
277 void initOkApplyCancel();
278 void initNoRepeatedApply();
279 void initPreferences();
283 std::ostream & operator<<(std::ostream & os, ButtonPolicy::State st);
284 std::ostream & operator<<(std::ostream & os, ButtonPolicy::SMInput smi);
286 } // namespace frontend