2 * \file ButtonPolicies.h
3 * \author Allan Rae, rae@lyx.org
5 * Provides a state machine implementation of the various button policies
9 * ======================================================
11 * LyX, The Document Processor
13 * Copyright 1995 Matthias Ettrich
14 * Copyright 1995-2001 The LyX Team.
16 * This file Copyright 2000
18 * ======================================================
21 #ifndef BUTTONPOLICIES_H
22 #define BUTTONPOLICIES_H
26 #include <boost/utility.hpp>
28 #include "support/LOstream.h"
30 /** An abstract base class for button policies.
31 A state machine implementation of the various button policies used by the
32 dialogs. Only the policy is implemented here. Separate ButtonController
33 classes are needed for each GUI implementation.
35 Policy | ReadOnly | Apply Button | Repeated Apply
36 ========================================================================
38 OkCancelReadOnly | Y | N | -
39 OkApplyCancel | N | Y | Y
40 OkApplyCancelReadOnly | Y | Y | Y
41 NoRepeatedApply | N | Y | N
42 NoRepeatedApplyReadOnly | Y | Y | N
43 Preferences | N | Y | No (Ok-Close)
44 Ignorant | N/A | N/A | N/A
45 ========================================================================
48 The name of the policy
50 Does the policy treat read-only docs differently to read-write docs?
51 This usually means that when an SMI_READ_ONLY input arrives then
52 all the buttons are disabled except Cancel/Close. The state
53 machine tracks the inputs (valid/invalid) and has states for all
54 combinations. When an SMI_READ_WRITE input arrives the appropriate
55 machine state is entered (just as if the document had always been
57 NOTE: If a dialog doesn't care about the read-only status of a document
58 (and uses an appropriate policy) it can never get into a read-only state
59 so isReadOnly() can only ever return false even though the document may
62 Simply means that it is alright to use the Apply button multiple times
63 without requiring a change of the dialog contents. If no repeating is
64 allowed the Ok+Apply buttons are deactivated. The Preferences dialog
65 has its own special version of repeated apply handling because its Ok
66 button is actually a Save button -- its always reasonable to Save the
67 preferences if the dialog has changed since the last save.
69 The IgnorantPolicy is a special case that allows anything.
71 class ButtonPolicy : public boost::noncopyable {
74 virtual ~ButtonPolicy() {}
76 /** The various possible state names.
77 Not all state-machines have this many states. However, we need
78 to define them all here so we can share the code.
101 /// The various button types.
104 CLOSE = 0, // Not a real button, but effectively !CANCEL
115 static const Button ALL_BUTTONS =
116 Button(OKAY | APPLY | CANCEL | UNDO_ALL);
118 /** State machine inputs.
119 All the policies so far have both CANCEL and HIDE always going to
120 INITIAL. This won't necessarily be true for all [future] policies
121 though so I'll leave those two as distinct inputs rather than merge
122 them. For example, a dialog that doesn't update it's input fields
123 when reshown after being hidden needs a policy where CANCEL and
124 HIDE are treated differently.
148 SMI_TOTAL // not a real input
151 /// Trigger a transition with this input.
152 virtual void input(SMInput) = 0;
153 /// Activation status of a button
154 virtual bool buttonStatus(Button) const = 0;
155 /// Are we in a read-only state?
156 virtual bool isReadOnly() const = 0;
158 /// Transition map of the state machine.
159 typedef std::vector<State> StateArray;
161 typedef std::vector<StateArray> StateMachine;
162 /// The state outputs are the status of the buttons.
163 typedef std::vector<int> StateOutputs;
168 std::ostream & operator<<(std::ostream & os, ButtonPolicy::State st)
176 std::ostream & operator<<(std::ostream & os, ButtonPolicy::SMInput smi)
183 //--------------------- Actual Policy Classes -----------------------------
185 /** Ok and Cancel buttons for dialogs with read-only operation.
186 Note: This scheme supports the relabelling of Cancel to Close and
188 This is based on the value of the bool state of the Button::CANCEL.
189 true == Cancel, false == Close
191 class OkCancelPolicy : public ButtonPolicy {
196 //virtual ~OkCancelPolicy() {}
198 /// Trigger a transition with this input.
199 virtual void input(SMInput);
200 /** Activation status of a button.
201 We assume that we haven't gotten into an undefined state.
202 This is reasonable since we can only reach states defined
203 in the state machine and they should all have been defined in
204 the outputs_ variable. Perhaps we can do something at compile
205 time to check that all the states have corresponding outputs.
207 virtual bool buttonStatus(Button button) const {
208 return button & outputs_[state_];
210 /// Are we in a read-only state?
211 virtual bool isReadOnly() const {
217 /// Which buttons are active for a given state.
218 StateOutputs outputs_;
220 StateMachine state_machine_;
223 /** Ok and Cancel buttons for dialogs where read-only operation is blocked.
224 The state machine design for this policy allows changes to occur within
225 the dialog while a file is read-only -- the okay button is disabled until
226 a read-write input is given. When the file is made read-write the dialog
227 will then be in the correct state (as if the file had always been
229 Note: This scheme supports the relabelling of Cancel to Close
231 This is based on the value of the bool state of the Button::CANCEL.
232 true == Cancel, false == Close
234 class OkCancelReadOnlyPolicy : public ButtonPolicy {
237 OkCancelReadOnlyPolicy();
239 //virtual ~OkCancelReadOnlyPolicy() {}
241 /// Trigger a transition with this input.
242 virtual void input(SMInput);
243 /// Activation status of a button.
244 virtual bool buttonStatus(Button button) const {
245 return button & outputs_[state_];
247 /// Are we in a read-only state?
248 virtual bool isReadOnly() const {
249 return RO_INITIAL == state_
250 || RO_VALID == state_
251 || RO_INVALID == state_
252 || RO_APPLIED == state_;
257 /// Which buttons are active for a given state.
258 StateOutputs outputs_;
260 StateMachine state_machine_;
264 /** Ok, Apply and Cancel buttons for dialogs where read-only operation
266 Repeated Apply are not allowed. Likewise, Ok cannot follow Apply without
267 some valid input. That is, the dialog contents must change between
268 each Apply or Apply and Ok.
269 The state machine design for this policy allows changes to occur within
270 the dialog while a file is read-only -- the Ok+Apply buttons are disabled
271 until a read-write input is given. When the file is made read-write the
272 dialog will then be in the correct state (as if the file had always been
274 Note: This scheme supports the relabelling of Cancel to Close
276 This is based on the value of the bool state of the Button::CANCEL.
277 true == Cancel, false == Close
279 class NoRepeatedApplyReadOnlyPolicy : public ButtonPolicy
283 NoRepeatedApplyReadOnlyPolicy();
285 //virtual ~NoRepeatedApplyReadOnlyPolicy() {}
287 /// Trigger a transition with this input.
288 virtual void input(SMInput);
289 /// Activation status of a button.
290 virtual bool buttonStatus(Button button) const {
291 return button & outputs_[state_];
293 /// Are we in a read-only state?
294 virtual bool isReadOnly() const {
295 return RO_INITIAL == state_
296 || RO_VALID == state_
297 || RO_INVALID == state_
298 || RO_APPLIED == state_;
303 /// Which buttons are active for a given state.
304 StateOutputs outputs_;
306 StateMachine state_machine_;
310 /** Ok, Apply and Cancel buttons for dialogs where read-only
311 operation is blocked.
312 Repeated Apply is allowed. Likewise, Ok can follow Apply.
313 The state machine design for this policy allows changes to occur within
314 the dialog while a file is read-only -- the Ok+Apply buttons are disabled
315 until a read-write input is given. When the file is made read-write the
316 dialog will then be in the correct state (as if the file had always been
318 Note: This scheme supports the relabelling of Cancel to Close
320 This is based on the value of the bool state of the Button::CANCEL.
321 true == Cancel, false == Close
323 class OkApplyCancelReadOnlyPolicy : public ButtonPolicy {
326 OkApplyCancelReadOnlyPolicy();
328 //virtual ~OkApplyCancelReadOnlyPolicy() {}
330 /// Trigger a transition with this input.
331 virtual void input(SMInput);
332 /// Activation status of a button.
333 virtual bool buttonStatus(Button button) const {
334 return button & outputs_[state_];
336 /// Are we in a read-only state?
337 virtual bool isReadOnly() const {
338 return RO_INITIAL == state_
339 || RO_VALID == state_
340 || RO_INVALID == state_
341 || RO_APPLIED == state_;
346 /// Which buttons are active for a given state.
347 StateOutputs outputs_;
349 StateMachine state_machine_;
353 /** Ok, Apply and Cancel buttons for dialogs where repeated Apply is allowed.
354 Note: This scheme supports the relabelling of Cancel to Close
356 This is based on the value of the bool state of the Button::CANCEL.
357 true == Cancel, false == Close
359 class OkApplyCancelPolicy : public ButtonPolicy {
362 OkApplyCancelPolicy();
364 //virtual ~OkApplyCancelPolicy() {}
366 /// Trigger a transition with this input.
367 virtual void input(SMInput);
368 /// Activation status of a button.
369 virtual bool buttonStatus(Button button) const {
370 return button & outputs_[state_];
372 /// Are we in a read-only state?
373 virtual bool isReadOnly() const {
379 /// Which buttons are active for a given state.
380 StateOutputs outputs_;
382 StateMachine state_machine_;
386 /** Ok, Apply and Cancel buttons for dialogs with no repeated Apply.
387 Note: This scheme supports the relabelling of Cancel to Close
389 This is based on the value of the bool state of the Button::CANCEL.
390 true == Cancel, false == Close
392 class NoRepeatedApplyPolicy : public ButtonPolicy {
395 NoRepeatedApplyPolicy();
397 //virtual ~NoRepeatedApplyPolicy() {}
399 /// Trigger a transition with this input.
400 virtual void input(SMInput);
401 /// Activation status of a button.
402 virtual bool buttonStatus(Button button) const {
403 return button & outputs_[state_];
405 /// Are we in a read-only state?
406 virtual bool isReadOnly() const {
412 /// Which buttons are active for a given state.
413 StateOutputs outputs_;
415 StateMachine state_machine_;
419 /** Defines the policy used by the Preferences dialog.
420 Four buttons: Ok (Save), Apply, Cancel/Close, Restore.
421 Note: This scheme supports the relabelling of Cancel to Close
423 This is based on the value of the bool state of the Button::CANCEL.
424 true == Cancel, false == Close
426 class PreferencesPolicy : public ButtonPolicy {
431 //virtual ~PreferencesPolicy() {}
433 /// Trigger a transition with this input.
434 virtual void input(SMInput);
435 /// Activation status of a button.
436 virtual bool buttonStatus(Button button) const {
437 return button & outputs_[state_];
439 /// Are we in a read-only state?
440 virtual bool isReadOnly() const {
446 /// Which buttons are active for a given state.
447 StateOutputs outputs_;
449 StateMachine state_machine_;
453 /** Defines the policy used by dialogs that are forced to support a button
454 controller when they either don't have a use for one or are not ready to
455 use one. This may be useful when testing a new button policy but wishing
456 to minimise problems to users by supplying an anything-goes policy via a
457 preprocessor directive.
459 class IgnorantPolicy : public ButtonPolicy {
461 //virtual ~IgnorantPolicy() {}
463 /// Trigger a transition with this input.
464 virtual void input(SMInput) {}
465 /// Activation status of a button.
466 virtual bool buttonStatus(Button) const {
469 /// Are we in a read-only state?
470 virtual bool isReadOnly() const {