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"
24 /** An abstract base 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 -- its 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.
65 class ButtonPolicy : boost::noncopyable {
68 virtual ~ButtonPolicy() {}
70 /** The various possible state names.
71 Not all state-machines have this many states. However, we need
72 to define them all here so we can share the code.
95 /// The various button types.
98 CLOSE = 0, // Not a real button, but effectively !CANCEL
109 static const Button ALL_BUTTONS =
110 Button(OKAY | APPLY | CANCEL | RESTORE);
112 /** State machine inputs.
113 All the policies so far have both CANCEL and HIDE always going to
114 INITIAL. This won't necessarily be true for all [future] policies
115 though so I'll leave those two as distinct inputs rather than merge
116 them. For example, a dialog that doesn't update it's input fields
117 when reshown after being hidden needs a policy where CANCEL and
118 HIDE are treated differently.
121 /// the dialog contents are now valid
123 /// the dialog contents are now invalid
125 /// an apply-and-hide action has happened
127 /// an apply action has happened
129 /// a cancel action has happened
131 /// a restore action has happened
133 /// the dialog has been hidden
135 /// the dialog contents are read-only
137 /// the dialog contents can be modified
139 /// the state of the dialog contents has not changed
145 /// Trigger a transition with this input.
146 virtual void input(SMInput) = 0;
147 /// Activation status of a button
148 virtual bool buttonStatus(Button) const = 0;
149 /// Are we in a read-only state?
150 virtual bool isReadOnly() const = 0;
152 /// Transition map of the state machine.
153 typedef std::vector<State> StateArray;
155 typedef std::vector<StateArray> StateMachine;
156 /// The state outputs are the status of the buttons.
157 typedef std::vector<int> StateOutputs;
162 std::ostream & operator<<(std::ostream & os, ButtonPolicy::State st)
170 std::ostream & operator<<(std::ostream & os, ButtonPolicy::SMInput smi)
177 //--------------------- Actual Policy Classes -----------------------------
179 /** Ok and Cancel buttons for dialogs with read-only operation.
180 Note: This scheme supports the relabelling of Cancel to Close and
182 This is based on the value of the bool state of the Button::CANCEL.
183 true == Cancel, false == Close
185 class OkCancelPolicy : public ButtonPolicy {
190 //virtual ~OkCancelPolicy() {}
192 /// Trigger a transition with this input.
193 virtual void input(SMInput);
194 /** Activation status of a button.
195 We assume that we haven't gotten into an undefined state.
196 This is reasonable since we can only reach states defined
197 in the state machine and they should all have been defined in
198 the outputs_ variable. Perhaps we can do something at compile
199 time to check that all the states have corresponding outputs.
201 virtual bool buttonStatus(Button button) const {
202 return button & outputs_[state_];
204 /// Are we in a read-only state?
205 virtual bool isReadOnly() const {
211 /// Which buttons are active for a given state.
212 StateOutputs outputs_;
214 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
223 Note: This scheme supports the relabelling of Cancel to Close
225 This is based on the value of the bool state of the Button::CANCEL.
226 true == Cancel, false == Close
228 class OkCancelReadOnlyPolicy : public ButtonPolicy {
231 OkCancelReadOnlyPolicy();
233 //virtual ~OkCancelReadOnlyPolicy() {}
235 /// Trigger a transition with this input.
236 virtual void input(SMInput);
237 /// Activation status of a button.
238 virtual bool buttonStatus(Button button) const {
239 return button & outputs_[state_];
241 /// Are we in a read-only state?
242 virtual bool isReadOnly() const {
243 return RO_INITIAL == state_
244 || RO_VALID == state_
245 || RO_INVALID == state_
246 || RO_APPLIED == state_;
251 /// Which buttons are active for a given state.
252 StateOutputs outputs_;
254 StateMachine state_machine_;
258 /** Ok, Apply and Cancel buttons for dialogs where read-only operation
260 Repeated Apply are not allowed. Likewise, Ok cannot follow Apply without
261 some valid input. That is, the dialog contents must change between
262 each Apply or Apply and Ok.
263 The state machine design for this policy allows changes to occur within
264 the dialog while a file is read-only -- the Ok+Apply buttons are disabled
265 until a read-write input is given. When the file is made read-write the
266 dialog will then be in the correct state (as if the file had always been
268 Note: This scheme supports the relabelling of Cancel to Close
270 This is based on the value of the bool state of the Button::CANCEL.
271 true == Cancel, false == Close
273 class NoRepeatedApplyReadOnlyPolicy : public ButtonPolicy {
276 NoRepeatedApplyReadOnlyPolicy();
278 //virtual ~NoRepeatedApplyReadOnlyPolicy() {}
280 /// Trigger a transition with this input.
281 virtual void input(SMInput);
282 /// Activation status of a button.
283 virtual bool buttonStatus(Button button) const {
284 return button & outputs_[state_];
286 /// Are we in a read-only state?
287 virtual bool isReadOnly() const {
288 return RO_INITIAL == state_
289 || RO_VALID == state_
290 || RO_INVALID == state_
291 || RO_APPLIED == state_;
296 /// Which buttons are active for a given state.
297 StateOutputs outputs_;
299 StateMachine state_machine_;
303 /** Ok, Apply and Cancel buttons for dialogs where read-only
304 operation is blocked.
305 Repeated Apply is allowed. Likewise, Ok can follow Apply.
306 The state machine design for this policy allows changes to occur within
307 the dialog while a file is read-only -- the Ok+Apply buttons are disabled
308 until a read-write input is given. When the file is made read-write the
309 dialog will then be in the correct state (as if the file had always been
311 Note: This scheme supports the relabelling of Cancel to Close
313 This is based on the value of the bool state of the Button::CANCEL.
314 true == Cancel, false == Close
316 class OkApplyCancelReadOnlyPolicy : public ButtonPolicy {
319 OkApplyCancelReadOnlyPolicy();
321 //virtual ~OkApplyCancelReadOnlyPolicy() {}
323 /// Trigger a transition with this input.
324 virtual void input(SMInput);
325 /// Activation status of a button.
326 virtual bool buttonStatus(Button button) const {
327 return button & outputs_[state_];
329 /// Are we in a read-only state?
330 virtual bool isReadOnly() const {
331 return RO_INITIAL == state_
332 || RO_VALID == state_
333 || RO_INVALID == state_
334 || RO_APPLIED == state_;
339 /// Which buttons are active for a given state.
340 StateOutputs outputs_;
342 StateMachine state_machine_;
346 /** Ok, Apply and Cancel buttons for dialogs where repeated Apply is allowed.
347 Note: This scheme supports the relabelling of Cancel to Close
349 This is based on the value of the bool state of the Button::CANCEL.
350 true == Cancel, false == Close
352 class OkApplyCancelPolicy : public ButtonPolicy {
355 OkApplyCancelPolicy();
357 //virtual ~OkApplyCancelPolicy() {}
359 /// Trigger a transition with this input.
360 virtual void input(SMInput);
361 /// Activation status of a button.
362 virtual bool buttonStatus(Button button) const {
363 return button & outputs_[state_];
365 /// Are we in a read-only state?
366 virtual bool isReadOnly() const {
372 /// Which buttons are active for a given state.
373 StateOutputs outputs_;
375 StateMachine state_machine_;
379 /** Ok, Apply and Cancel buttons for dialogs with no repeated Apply.
380 Note: This scheme supports the relabelling of Cancel to Close
382 This is based on the value of the bool state of the Button::CANCEL.
383 true == Cancel, false == Close
385 class NoRepeatedApplyPolicy : public ButtonPolicy {
388 NoRepeatedApplyPolicy();
390 //virtual ~NoRepeatedApplyPolicy() {}
392 /// Trigger a transition with this input.
393 virtual void input(SMInput);
394 /// Activation status of a button.
395 virtual bool buttonStatus(Button button) const {
396 return button & outputs_[state_];
398 /// Are we in a read-only state?
399 virtual bool isReadOnly() const {
405 /// Which buttons are active for a given state.
406 StateOutputs outputs_;
408 StateMachine state_machine_;
412 /** Defines the policy used by the Preferences dialog.
413 Four buttons: Ok (Save), Apply, Cancel/Close, Restore.
414 Note: This scheme supports the relabelling of Cancel to Close
416 This is based on the value of the bool state of the Button::CANCEL.
417 true == Cancel, false == Close
419 class PreferencesPolicy : public ButtonPolicy {
424 //virtual ~PreferencesPolicy() {}
426 /// Trigger a transition with this input.
427 virtual void input(SMInput);
428 /// Activation status of a button.
429 virtual bool buttonStatus(Button button) const {
430 return button & outputs_[state_];
432 /// Are we in a read-only state?
433 virtual bool isReadOnly() const {
439 /// Which buttons are active for a given state.
440 StateOutputs outputs_;
442 StateMachine state_machine_;
446 /** Defines the policy used by dialogs that are forced to support a button
447 controller when they either don't have a use for one or are not ready to
448 use one. This may be useful when testing a new button policy but wishing
449 to minimise problems to users by supplying an anything-goes policy via a
450 preprocessor directive.
452 class IgnorantPolicy : public ButtonPolicy {
454 //virtual ~IgnorantPolicy() {}
456 /// Trigger a transition with this input.
457 virtual void input(SMInput) {}
458 /// Activation status of a button.
459 virtual bool buttonStatus(Button) const {
462 /// Are we in a read-only state?
463 virtual bool isReadOnly() const {