3 * Provides a state machine implementation of the various button policies
5 * Author: Allan Rae <rae@lyx.org>
7 * ======================================================
9 * LyX, The Document Processor
11 * Copyright 1995 Matthias Ettrich
12 * Copyright 1995-2000 The LyX Team.
14 * This file Copyright 2000
16 * ======================================================
19 #ifndef BUTTONPOLICIES_H
20 #define BUTTONPOLICIES_H
24 #include <boost/utility.hpp>
27 /** An abstract base class for button policies.
28 A state machine implementation of the various button policies used by the
29 dialogs. Only the policy is implemented here. Separate ButtonController
30 classes are needed for each GUI implementation.
32 Policy | ReadOnly | Apply Button | Repeated Apply
33 ========================================================================
35 OkCancelReadOnly | Y | N | -
36 OkApplyCancel | N | Y | Y
37 OkApplyCancelReadOnly | Y | Y | Y
38 NoRepeatedApply | N | Y | N
39 NoRepeatedApplyReadOnly | Y | Y | N
40 Preferences | N | Y | No (Ok-Close)
41 Ignorant | N/A | N/A | N/A
42 ========================================================================
45 The name of the policy
47 Does the policy treat read-only docs differently to read-write docs?
48 This usually means that when an SMI_READ_ONLY input arrives then
49 all the buttons are disabled except Cancel/Close. The state
50 machine tracks the inputs (valid/invalid) and has states for all
51 combinations. When an SMI_READ_WRITE input arrives the appropriate
52 machine state is entered (just as if the document had always been
54 NOTE: If a dialog doesn't care about the read-only status of a document
55 (and uses an appropriate policy) it can never get into a read-only state
56 so isReadOnly() can only ever return false even though the document may
59 Simply means that it is alright to use the Apply button multiple times
60 without requiring a change of the dialog contents. If no repeating is
61 allowed the Ok+Apply buttons are deactivated. The Preferences dialog
62 has its own special version of repeated apply handling because its Ok
63 button is actually a Save button -- its always reasonable to Save the
64 preferences if the dialog has changed since the last save.
66 The IgnorantPolicy is a special case that allows anything.
68 class ButtonPolicy : public noncopyable {
71 virtual ~ButtonPolicy() {}
73 /** The various possible state names.
74 Not all state-machines have this many states. However, we need
75 to define them all here so we can share the code.
98 /// The various button types.
101 CLOSE = 0, // Not a real button, but effectively !CANCEL
112 static const Button ALL_BUTTONS =
113 Button(OKAY | APPLY | CANCEL | UNDO_ALL);
115 /** State machine inputs.
116 All the policies so far have both CANCEL and HIDE always going to
117 INITIAL. This won't necessarily be true for all [future] policies
118 though so I'll leave those two as distinct inputs rather than merge
119 them. For example, a dialog that doesn't update it's input fields
120 when reshown after being hidden needs a policy where CANCEL and
121 HIDE are treated differently.
143 SMI_TOTAL // not a real input
146 /// Trigger a transition with this input.
147 virtual void input(SMInput) = 0;
148 /// Activation status of a button
149 virtual bool buttonStatus(Button) const = 0;
150 /// Are we in a read-only state?
151 virtual bool isReadOnly() const = 0;
153 /// Transition map of the state machine.
154 typedef std::vector<State> StateArray;
156 typedef std::vector<StateArray> StateMachine;
157 /// The state outputs are the status of the buttons.
158 typedef std::vector<int> StateOutputs;
163 ostream & operator<<(ostream & os, ButtonPolicy::SMInput smi)
170 ostream & operator<<(ostream & os, ButtonPolicy::State st)
176 //--------------------- Actual Policy Classes -----------------------------
178 /** Ok and Cancel buttons for dialogs with read-only operation.
179 Note: This scheme supports the relabelling of Cancel to Close and
181 This is based on the value of the bool state of the Button::CANCEL.
182 true == Cancel, false == Close
184 class OkCancelPolicy : public ButtonPolicy {
189 virtual ~OkCancelPolicy() {}
191 /// Trigger a transition with this input.
192 virtual void input(SMInput);
193 /** Activation status of a button.
194 We assume that we haven't gotten into an undefined state.
195 This is reasonable since we can only reach states defined
196 in the state machine and they should all have been defined in
197 the outputs_ variable. Perhaps we can do something at compile
198 time to check that all the states have corresponding outputs.
200 virtual bool buttonStatus(Button button) const {
201 return button & outputs_[state_];
203 /// Are we in a read-only state?
204 virtual bool isReadOnly() const {
210 /// Which buttons are active for a given state.
211 StateOutputs outputs_;
213 StateMachine state_machine_;
217 /** Ok and Cancel buttons for dialogs where read-only operation is blocked.
218 The state machine design for this policy allows changes to occur within
219 the dialog while a file is read-only -- the okay button is disabled until
220 a read-write input is given. When the file is made read-write the dialog
221 will then be in the correct state (as if the file had always been read-write).
222 Note: This scheme supports the relabelling of Cancel to Close and vice versa.
223 This is based on the value of the bool state of the Button::CANCEL.
224 true == Cancel, false == Close
226 class OkCancelReadOnlyPolicy : public ButtonPolicy {
229 OkCancelReadOnlyPolicy();
231 virtual ~OkCancelReadOnlyPolicy() {}
233 /// Trigger a transition with this input.
234 virtual void input(SMInput);
235 /// Activation status of a button.
236 virtual bool buttonStatus(Button button) const {
237 return button & outputs_[state_];
239 /// Are we in a read-only state?
240 virtual bool isReadOnly() const {
241 return RO_INITIAL == state_
242 || RO_VALID == state_
243 || RO_INVALID == state_
244 || RO_APPLIED == state_;
249 /// Which buttons are active for a given state.
250 StateOutputs outputs_;
252 StateMachine state_machine_;
256 /** Ok, Apply and Cancel buttons for dialogs where read-only operation is blocked.
257 Repeated Apply are not allowed. Likewise, Ok cannot follow Apply without
258 some valid input. That is, the dialog contents must change between each Apply
260 The state machine design for this policy allows changes to occur within
261 the dialog while a file is read-only -- the Ok+Apply buttons are disabled
262 until a read-write input is given. When the file is made read-write the
263 dialog will then be in the correct state (as if the file had always been
265 Note: This scheme supports the relabelling of Cancel to Close and vice versa.
266 This is based on the value of the bool state of the Button::CANCEL.
267 true == Cancel, false == Close
269 class NoRepeatedApplyReadOnlyPolicy : public ButtonPolicy
273 NoRepeatedApplyReadOnlyPolicy();
275 virtual ~NoRepeatedApplyReadOnlyPolicy() {}
277 /// Trigger a transition with this input.
278 virtual void input(SMInput);
279 /// Activation status of a button.
280 virtual bool buttonStatus(Button button) const {
281 return button & outputs_[state_];
283 /// Are we in a read-only state?
284 virtual bool isReadOnly() const {
285 return RO_INITIAL == state_
286 || RO_VALID == state_
287 || RO_INVALID == state_
288 || RO_APPLIED == state_;
293 /// Which buttons are active for a given state.
294 StateOutputs outputs_;
296 StateMachine state_machine_;
300 /** Ok, Apply and Cancel buttons for dialogs where read-only operation is blocked.
301 Repeated Apply is allowed. Likewise, Ok can follow Apply.
302 The state machine design for this policy allows changes to occur within
303 the dialog while a file is read-only -- the Ok+Apply buttons are disabled
304 until a read-write input is given. When the file is made read-write the
305 dialog will then be in the correct state (as if the file had always been
307 Note: This scheme supports the relabelling of Cancel to Close and vice versa.
308 This is based on the value of the bool state of the Button::CANCEL.
309 true == Cancel, false == Close
311 class OkApplyCancelReadOnlyPolicy : public ButtonPolicy {
314 OkApplyCancelReadOnlyPolicy();
316 virtual ~OkApplyCancelReadOnlyPolicy() {}
318 /// Trigger a transition with this input.
319 virtual void input(SMInput);
320 /// Activation status of a button.
321 virtual bool buttonStatus(Button button) const {
322 return button & outputs_[state_];
324 /// Are we in a read-only state?
325 virtual bool isReadOnly() const {
326 return RO_INITIAL == state_
327 || RO_VALID == state_
328 || RO_INVALID == state_
329 || RO_APPLIED == state_;
334 /// Which buttons are active for a given state.
335 StateOutputs outputs_;
337 StateMachine state_machine_;
341 /** Ok, Apply and Cancel buttons for dialogs where repeated Apply is allowed.
342 Note: This scheme supports the relabelling of Cancel to Close and vice versa.
343 This is based on the value of the bool state of the Button::CANCEL.
344 true == Cancel, false == Close
346 class OkApplyCancelPolicy : public ButtonPolicy {
349 OkApplyCancelPolicy();
351 virtual ~OkApplyCancelPolicy() {}
353 /// Trigger a transition with this input.
354 virtual void input(SMInput);
355 /// Activation status of a button.
356 virtual bool buttonStatus(Button button) const {
357 return button & outputs_[state_];
359 /// Are we in a read-only state?
360 virtual bool isReadOnly() const {
366 /// Which buttons are active for a given state.
367 StateOutputs outputs_;
369 StateMachine state_machine_;
373 /** Ok, Apply and Cancel buttons for dialogs with no repeated Apply.
374 Note: This scheme supports the relabelling of Cancel to Close and vice versa.
375 This is based on the value of the bool state of the Button::CANCEL.
376 true == Cancel, false == Close
378 class NoRepeatedApplyPolicy : public ButtonPolicy {
381 NoRepeatedApplyPolicy();
383 virtual ~NoRepeatedApplyPolicy() {}
385 /// Trigger a transition with this input.
386 virtual void input(SMInput);
387 /// Activation status of a button.
388 virtual bool buttonStatus(Button button) const {
389 return button & outputs_[state_];
391 /// Are we in a read-only state?
392 virtual bool isReadOnly() const {
398 /// Which buttons are active for a given state.
399 StateOutputs outputs_;
401 StateMachine state_machine_;
405 /** Defines the policy used by the Preferences dialog.
406 Four buttons: Ok (Save), Apply, Cancel/Close, Restore.
407 Note: This scheme supports the relabelling of Cancel to Close and vice versa.
408 This is based on the value of the bool state of the Button::CANCEL.
409 true == Cancel, false == Close
411 class PreferencesPolicy : public ButtonPolicy {
416 virtual ~PreferencesPolicy() {}
418 /// Trigger a transition with this input.
419 virtual void input(SMInput);
420 /// Activation status of a button.
421 virtual bool buttonStatus(Button button) const {
422 return button & outputs_[state_];
424 /// Are we in a read-only state?
425 virtual bool isReadOnly() const {
431 /// Which buttons are active for a given state.
432 StateOutputs outputs_;
434 StateMachine state_machine_;
438 /** Defines the policy used by dialogs that are forced to support a button
439 controller when they either don't have a use for one or are not ready to
440 use one. This may be useful when testing a new button policy but wishing
441 to minimise problems to users by supplying an anything-goes policy via a
442 preprocessor directive.
444 class IgnorantPolicy : public ButtonPolicy {
446 virtual ~IgnorantPolicy() {}
448 /// Trigger a transition with this input.
449 virtual void input(SMInput) {}
450 /// Activation status of a button.
451 virtual bool buttonStatus(Button) const {
454 /// Are we in a read-only state?
455 virtual bool isReadOnly() const {