3 * \file ButtonPolicies.h
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 BUTTONPOLICIES_H
16 #define BUTTONPOLICIES_H
20 #include <boost/utility.hpp>
22 #include "support/std_ostream.h"
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 : boost::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 | RESTORE);
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.
124 /// the dialog contents are now valid
126 /// the dialog contents are now invalid
128 /// an apply-and-hide action has happened
130 /// an apply action has happened
132 /// a cancel action has happened
134 /// a restore action has happened
136 /// the dialog has been hidden
138 /// the dialog contents are read-only
140 /// the dialog contents can be modified
142 /// the state of the dialog contents has not changed
148 /// Trigger a transition with this input.
149 virtual void input(SMInput) = 0;
150 /// Activation status of a button
151 virtual bool buttonStatus(Button) const = 0;
152 /// Are we in a read-only state?
153 virtual bool isReadOnly() const = 0;
155 /// Transition map of the state machine.
156 typedef std::vector<State> StateArray;
158 typedef std::vector<StateArray> StateMachine;
159 /// The state outputs are the status of the buttons.
160 typedef std::vector<int> StateOutputs;
165 std::ostream & operator<<(std::ostream & os, ButtonPolicy::State st)
173 std::ostream & operator<<(std::ostream & os, ButtonPolicy::SMInput smi)
180 //--------------------- Actual Policy Classes -----------------------------
182 /** Ok and Cancel buttons for dialogs with read-only operation.
183 Note: This scheme supports the relabelling of Cancel to Close and
185 This is based on the value of the bool state of the Button::CANCEL.
186 true == Cancel, false == Close
188 class OkCancelPolicy : public ButtonPolicy {
193 //virtual ~OkCancelPolicy() {}
195 /// Trigger a transition with this input.
196 virtual void input(SMInput);
197 /** Activation status of a button.
198 We assume that we haven't gotten into an undefined state.
199 This is reasonable since we can only reach states defined
200 in the state machine and they should all have been defined in
201 the outputs_ variable. Perhaps we can do something at compile
202 time to check that all the states have corresponding outputs.
204 virtual bool buttonStatus(Button button) const {
205 return button & outputs_[state_];
207 /// Are we in a read-only state?
208 virtual bool isReadOnly() const {
214 /// Which buttons are active for a given state.
215 StateOutputs outputs_;
217 StateMachine state_machine_;
220 /** Ok and Cancel buttons for dialogs where read-only operation is blocked.
221 The state machine design for this policy allows changes to occur within
222 the dialog while a file is read-only -- the okay button is disabled until
223 a read-write input is given. When the file is made read-write the dialog
224 will then be in the correct state (as if the file had always been
226 Note: This scheme supports the relabelling of Cancel to Close
228 This is based on the value of the bool state of the Button::CANCEL.
229 true == Cancel, false == Close
231 class OkCancelReadOnlyPolicy : public ButtonPolicy {
234 OkCancelReadOnlyPolicy();
236 //virtual ~OkCancelReadOnlyPolicy() {}
238 /// Trigger a transition with this input.
239 virtual void input(SMInput);
240 /// Activation status of a button.
241 virtual bool buttonStatus(Button button) const {
242 return button & outputs_[state_];
244 /// Are we in a read-only state?
245 virtual bool isReadOnly() const {
246 return RO_INITIAL == state_
247 || RO_VALID == state_
248 || RO_INVALID == state_
249 || RO_APPLIED == state_;
254 /// Which buttons are active for a given state.
255 StateOutputs outputs_;
257 StateMachine state_machine_;
261 /** Ok, Apply and Cancel buttons for dialogs where read-only operation
263 Repeated Apply are not allowed. Likewise, Ok cannot follow Apply without
264 some valid input. That is, the dialog contents must change between
265 each Apply or Apply and Ok.
266 The state machine design for this policy allows changes to occur within
267 the dialog while a file is read-only -- the Ok+Apply buttons are disabled
268 until a read-write input is given. When the file is made read-write the
269 dialog will then be in the correct state (as if the file had always been
271 Note: This scheme supports the relabelling of Cancel to Close
273 This is based on the value of the bool state of the Button::CANCEL.
274 true == Cancel, false == Close
276 class NoRepeatedApplyReadOnlyPolicy : public ButtonPolicy {
279 NoRepeatedApplyReadOnlyPolicy();
281 //virtual ~NoRepeatedApplyReadOnlyPolicy() {}
283 /// Trigger a transition with this input.
284 virtual void input(SMInput);
285 /// Activation status of a button.
286 virtual bool buttonStatus(Button button) const {
287 return button & outputs_[state_];
289 /// Are we in a read-only state?
290 virtual bool isReadOnly() const {
291 return RO_INITIAL == state_
292 || RO_VALID == state_
293 || RO_INVALID == state_
294 || RO_APPLIED == state_;
299 /// Which buttons are active for a given state.
300 StateOutputs outputs_;
302 StateMachine state_machine_;
306 /** Ok, Apply and Cancel buttons for dialogs where read-only
307 operation is blocked.
308 Repeated Apply is allowed. Likewise, Ok can follow Apply.
309 The state machine design for this policy allows changes to occur within
310 the dialog while a file is read-only -- the Ok+Apply buttons are disabled
311 until a read-write input is given. When the file is made read-write the
312 dialog will then be in the correct state (as if the file had always been
314 Note: This scheme supports the relabelling of Cancel to Close
316 This is based on the value of the bool state of the Button::CANCEL.
317 true == Cancel, false == Close
319 class OkApplyCancelReadOnlyPolicy : public ButtonPolicy {
322 OkApplyCancelReadOnlyPolicy();
324 //virtual ~OkApplyCancelReadOnlyPolicy() {}
326 /// Trigger a transition with this input.
327 virtual void input(SMInput);
328 /// Activation status of a button.
329 virtual bool buttonStatus(Button button) const {
330 return button & outputs_[state_];
332 /// Are we in a read-only state?
333 virtual bool isReadOnly() const {
334 return RO_INITIAL == state_
335 || RO_VALID == state_
336 || RO_INVALID == state_
337 || RO_APPLIED == state_;
342 /// Which buttons are active for a given state.
343 StateOutputs outputs_;
345 StateMachine state_machine_;
349 /** Ok, Apply and Cancel buttons for dialogs where repeated Apply is allowed.
350 Note: This scheme supports the relabelling of Cancel to Close
352 This is based on the value of the bool state of the Button::CANCEL.
353 true == Cancel, false == Close
355 class OkApplyCancelPolicy : public ButtonPolicy {
358 OkApplyCancelPolicy();
360 //virtual ~OkApplyCancelPolicy() {}
362 /// Trigger a transition with this input.
363 virtual void input(SMInput);
364 /// Activation status of a button.
365 virtual bool buttonStatus(Button button) const {
366 return button & outputs_[state_];
368 /// Are we in a read-only state?
369 virtual bool isReadOnly() const {
375 /// Which buttons are active for a given state.
376 StateOutputs outputs_;
378 StateMachine state_machine_;
382 /** Ok, Apply and Cancel buttons for dialogs with no repeated Apply.
383 Note: This scheme supports the relabelling of Cancel to Close
385 This is based on the value of the bool state of the Button::CANCEL.
386 true == Cancel, false == Close
388 class NoRepeatedApplyPolicy : public ButtonPolicy {
391 NoRepeatedApplyPolicy();
393 //virtual ~NoRepeatedApplyPolicy() {}
395 /// Trigger a transition with this input.
396 virtual void input(SMInput);
397 /// Activation status of a button.
398 virtual bool buttonStatus(Button button) const {
399 return button & outputs_[state_];
401 /// Are we in a read-only state?
402 virtual bool isReadOnly() const {
408 /// Which buttons are active for a given state.
409 StateOutputs outputs_;
411 StateMachine state_machine_;
415 /** Defines the policy used by the Preferences dialog.
416 Four buttons: Ok (Save), Apply, Cancel/Close, Restore.
417 Note: This scheme supports the relabelling of Cancel to Close
419 This is based on the value of the bool state of the Button::CANCEL.
420 true == Cancel, false == Close
422 class PreferencesPolicy : public ButtonPolicy {
427 //virtual ~PreferencesPolicy() {}
429 /// Trigger a transition with this input.
430 virtual void input(SMInput);
431 /// Activation status of a button.
432 virtual bool buttonStatus(Button button) const {
433 return button & outputs_[state_];
435 /// Are we in a read-only state?
436 virtual bool isReadOnly() const {
442 /// Which buttons are active for a given state.
443 StateOutputs outputs_;
445 StateMachine state_machine_;
449 /** Defines the policy used by dialogs that are forced to support a button
450 controller when they either don't have a use for one or are not ready to
451 use one. This may be useful when testing a new button policy but wishing
452 to minimise problems to users by supplying an anything-goes policy via a
453 preprocessor directive.
455 class IgnorantPolicy : public ButtonPolicy {
457 //virtual ~IgnorantPolicy() {}
459 /// Trigger a transition with this input.
460 virtual void input(SMInput) {}
461 /// Activation status of a button.
462 virtual bool buttonStatus(Button) const {
465 /// Are we in a read-only state?
466 virtual bool isReadOnly() const {
471 } // namespace frontend