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>
26 #include "support/LOstream.h"
28 /** An abstract base class for button policies.
29 A state machine implementation of the various button policies used by the
30 dialogs. Only the policy is implemented here. Separate ButtonController
31 classes are needed for each GUI implementation.
33 Policy | ReadOnly | Apply Button | Repeated Apply
34 ========================================================================
36 OkCancelReadOnly | Y | N | -
37 OkApplyCancel | N | Y | Y
38 OkApplyCancelReadOnly | Y | Y | Y
39 NoRepeatedApply | N | Y | N
40 NoRepeatedApplyReadOnly | Y | Y | N
41 Preferences | N | Y | No (Ok-Close)
42 Ignorant | N/A | N/A | N/A
43 ========================================================================
46 The name of the policy
48 Does the policy treat read-only docs differently to read-write docs?
49 This usually means that when an SMI_READ_ONLY input arrives then
50 all the buttons are disabled except Cancel/Close. The state
51 machine tracks the inputs (valid/invalid) and has states for all
52 combinations. When an SMI_READ_WRITE input arrives the appropriate
53 machine state is entered (just as if the document had always been
55 NOTE: If a dialog doesn't care about the read-only status of a document
56 (and uses an appropriate policy) it can never get into a read-only state
57 so isReadOnly() can only ever return false even though the document may
60 Simply means that it is alright to use the Apply button multiple times
61 without requiring a change of the dialog contents. If no repeating is
62 allowed the Ok+Apply buttons are deactivated. The Preferences dialog
63 has its own special version of repeated apply handling because its Ok
64 button is actually a Save button -- its always reasonable to Save the
65 preferences if the dialog has changed since the last save.
67 The IgnorantPolicy is a special case that allows anything.
69 class ButtonPolicy : public noncopyable {
72 virtual ~ButtonPolicy() {}
74 /** The various possible state names.
75 Not all state-machines have this many states. However, we need
76 to define them all here so we can share the code.
99 /// The various button types.
102 CLOSE = 0, // Not a real button, but effectively !CANCEL
113 static const Button ALL_BUTTONS =
114 Button(OKAY | APPLY | CANCEL | UNDO_ALL);
116 /** State machine inputs.
117 All the policies so far have both CANCEL and HIDE always going to
118 INITIAL. This won't necessarily be true for all [future] policies
119 though so I'll leave those two as distinct inputs rather than merge
120 them. For example, a dialog that doesn't update it's input fields
121 when reshown after being hidden needs a policy where CANCEL and
122 HIDE are treated differently.
146 SMI_TOTAL // not a real input
149 /// Trigger a transition with this input.
150 virtual void input(SMInput) = 0;
151 /// Activation status of a button
152 virtual bool buttonStatus(Button) const = 0;
153 /// Are we in a read-only state?
154 virtual bool isReadOnly() const = 0;
156 /// Transition map of the state machine.
157 typedef std::vector<State> StateArray;
159 typedef std::vector<StateArray> StateMachine;
160 /// The state outputs are the status of the buttons.
161 typedef std::vector<int> StateOutputs;
166 std::ostream & operator<<(std::ostream & os, ButtonPolicy::State st)
174 std::ostream & operator<<(std::ostream & os, ButtonPolicy::SMInput smi)
181 //--------------------- Actual Policy Classes -----------------------------
183 /** Ok and Cancel buttons for dialogs with read-only operation.
184 Note: This scheme supports the relabelling of Cancel to Close and
186 This is based on the value of the bool state of the Button::CANCEL.
187 true == Cancel, false == Close
189 class OkCancelPolicy : public ButtonPolicy {
194 //virtual ~OkCancelPolicy() {}
196 /// Trigger a transition with this input.
197 virtual void input(SMInput);
198 /** Activation status of a button.
199 We assume that we haven't gotten into an undefined state.
200 This is reasonable since we can only reach states defined
201 in the state machine and they should all have been defined in
202 the outputs_ variable. Perhaps we can do something at compile
203 time to check that all the states have corresponding outputs.
205 virtual bool buttonStatus(Button button) const {
206 return button & outputs_[state_];
208 /// Are we in a read-only state?
209 virtual bool isReadOnly() const {
215 /// Which buttons are active for a given state.
216 StateOutputs outputs_;
218 StateMachine state_machine_;
221 /** Ok and Cancel buttons for dialogs where read-only operation is blocked.
222 The state machine design for this policy allows changes to occur within
223 the dialog while a file is read-only -- the okay button is disabled until
224 a read-write input is given. When the file is made read-write the dialog
225 will then be in the correct state (as if the file had always been
227 Note: This scheme supports the relabelling of Cancel to Close
229 This is based on the value of the bool state of the Button::CANCEL.
230 true == Cancel, false == Close
232 class OkCancelReadOnlyPolicy : public ButtonPolicy {
235 OkCancelReadOnlyPolicy();
237 //virtual ~OkCancelReadOnlyPolicy() {}
239 /// Trigger a transition with this input.
240 virtual void input(SMInput);
241 /// Activation status of a button.
242 virtual bool buttonStatus(Button button) const {
243 return button & outputs_[state_];
245 /// Are we in a read-only state?
246 virtual bool isReadOnly() const {
247 return RO_INITIAL == state_
248 || RO_VALID == state_
249 || RO_INVALID == state_
250 || RO_APPLIED == state_;
255 /// Which buttons are active for a given state.
256 StateOutputs outputs_;
258 StateMachine state_machine_;
262 /** Ok, Apply and Cancel buttons for dialogs where read-only operation
264 Repeated Apply are not allowed. Likewise, Ok cannot follow Apply without
265 some valid input. That is, the dialog contents must change between
266 each Apply or Apply and Ok.
267 The state machine design for this policy allows changes to occur within
268 the dialog while a file is read-only -- the Ok+Apply buttons are disabled
269 until a read-write input is given. When the file is made read-write the
270 dialog will then be in the correct state (as if the file had always been
272 Note: This scheme supports the relabelling of Cancel to Close
274 This is based on the value of the bool state of the Button::CANCEL.
275 true == Cancel, false == Close
277 class NoRepeatedApplyReadOnlyPolicy : public ButtonPolicy
281 NoRepeatedApplyReadOnlyPolicy();
283 //virtual ~NoRepeatedApplyReadOnlyPolicy() {}
285 /// Trigger a transition with this input.
286 virtual void input(SMInput);
287 /// Activation status of a button.
288 virtual bool buttonStatus(Button button) const {
289 return button & outputs_[state_];
291 /// Are we in a read-only state?
292 virtual bool isReadOnly() const {
293 return RO_INITIAL == state_
294 || RO_VALID == state_
295 || RO_INVALID == state_
296 || RO_APPLIED == state_;
301 /// Which buttons are active for a given state.
302 StateOutputs outputs_;
304 StateMachine state_machine_;
308 /** Ok, Apply and Cancel buttons for dialogs where read-only
309 operation is blocked.
310 Repeated Apply is allowed. Likewise, Ok can follow Apply.
311 The state machine design for this policy allows changes to occur within
312 the dialog while a file is read-only -- the Ok+Apply buttons are disabled
313 until a read-write input is given. When the file is made read-write the
314 dialog will then be in the correct state (as if the file had always been
316 Note: This scheme supports the relabelling of Cancel to Close
318 This is based on the value of the bool state of the Button::CANCEL.
319 true == Cancel, false == Close
321 class OkApplyCancelReadOnlyPolicy : public ButtonPolicy {
324 OkApplyCancelReadOnlyPolicy();
326 //virtual ~OkApplyCancelReadOnlyPolicy() {}
328 /// Trigger a transition with this input.
329 virtual void input(SMInput);
330 /// Activation status of a button.
331 virtual bool buttonStatus(Button button) const {
332 return button & outputs_[state_];
334 /// Are we in a read-only state?
335 virtual bool isReadOnly() const {
336 return RO_INITIAL == state_
337 || RO_VALID == state_
338 || RO_INVALID == state_
339 || RO_APPLIED == state_;
344 /// Which buttons are active for a given state.
345 StateOutputs outputs_;
347 StateMachine state_machine_;
351 /** Ok, Apply and Cancel buttons for dialogs where repeated Apply is allowed.
352 Note: This scheme supports the relabelling of Cancel to Close
354 This is based on the value of the bool state of the Button::CANCEL.
355 true == Cancel, false == Close
357 class OkApplyCancelPolicy : public ButtonPolicy {
360 OkApplyCancelPolicy();
362 //virtual ~OkApplyCancelPolicy() {}
364 /// Trigger a transition with this input.
365 virtual void input(SMInput);
366 /// Activation status of a button.
367 virtual bool buttonStatus(Button button) const {
368 return button & outputs_[state_];
370 /// Are we in a read-only state?
371 virtual bool isReadOnly() const {
377 /// Which buttons are active for a given state.
378 StateOutputs outputs_;
380 StateMachine state_machine_;
384 /** Ok, Apply and Cancel buttons for dialogs with no repeated Apply.
385 Note: This scheme supports the relabelling of Cancel to Close
387 This is based on the value of the bool state of the Button::CANCEL.
388 true == Cancel, false == Close
390 class NoRepeatedApplyPolicy : public ButtonPolicy {
393 NoRepeatedApplyPolicy();
395 //virtual ~NoRepeatedApplyPolicy() {}
397 /// Trigger a transition with this input.
398 virtual void input(SMInput);
399 /// Activation status of a button.
400 virtual bool buttonStatus(Button button) const {
401 return button & outputs_[state_];
403 /// Are we in a read-only state?
404 virtual bool isReadOnly() const {
410 /// Which buttons are active for a given state.
411 StateOutputs outputs_;
413 StateMachine state_machine_;
417 /** Defines the policy used by the Preferences dialog.
418 Four buttons: Ok (Save), Apply, Cancel/Close, Restore.
419 Note: This scheme supports the relabelling of Cancel to Close
421 This is based on the value of the bool state of the Button::CANCEL.
422 true == Cancel, false == Close
424 class PreferencesPolicy : public ButtonPolicy {
429 //virtual ~PreferencesPolicy() {}
431 /// Trigger a transition with this input.
432 virtual void input(SMInput);
433 /// Activation status of a button.
434 virtual bool buttonStatus(Button button) const {
435 return button & outputs_[state_];
437 /// Are we in a read-only state?
438 virtual bool isReadOnly() const {
444 /// Which buttons are active for a given state.
445 StateOutputs outputs_;
447 StateMachine state_machine_;
451 /** Defines the policy used by dialogs that are forced to support a button
452 controller when they either don't have a use for one or are not ready to
453 use one. This may be useful when testing a new button policy but wishing
454 to minimise problems to users by supplying an anything-goes policy via a
455 preprocessor directive.
457 class IgnorantPolicy : public ButtonPolicy {
459 //virtual ~IgnorantPolicy() {}
461 /// Trigger a transition with this input.
462 virtual void input(SMInput) {}
463 /// Activation status of a button.
464 virtual bool buttonStatus(Button) const {
467 /// Are we in a read-only state?
468 virtual bool isReadOnly() const {