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.
144 SMI_TOTAL // not a real input
147 /// Trigger a transition with this input.
148 virtual void input(SMInput) = 0;
149 /// Activation status of a button
150 virtual bool buttonStatus(Button) const = 0;
151 /// Are we in a read-only state?
152 virtual bool isReadOnly() const = 0;
154 /// Transition map of the state machine.
155 typedef std::vector<State> StateArray;
157 typedef std::vector<StateArray> StateMachine;
158 /// The state outputs are the status of the buttons.
159 typedef std::vector<int> StateOutputs;
164 std::ostream & operator<<(std::ostream & os, ButtonPolicy::State st)
172 std::ostream & operator<<(std::ostream & os, ButtonPolicy::SMInput smi)
179 //--------------------- Actual Policy Classes -----------------------------
181 /** Ok and Cancel buttons for dialogs with read-only operation.
182 Note: This scheme supports the relabelling of Cancel to Close and
184 This is based on the value of the bool state of the Button::CANCEL.
185 true == Cancel, false == Close
187 class OkCancelPolicy : public ButtonPolicy {
192 //virtual ~OkCancelPolicy() {}
194 /// Trigger a transition with this input.
195 virtual void input(SMInput);
196 /** Activation status of a button.
197 We assume that we haven't gotten into an undefined state.
198 This is reasonable since we can only reach states defined
199 in the state machine and they should all have been defined in
200 the outputs_ variable. Perhaps we can do something at compile
201 time to check that all the states have corresponding outputs.
203 virtual bool buttonStatus(Button button) const {
204 return button & outputs_[state_];
206 /// Are we in a read-only state?
207 virtual bool isReadOnly() const {
213 /// Which buttons are active for a given state.
214 StateOutputs outputs_;
216 StateMachine state_machine_;
219 /** OK button policy for dialogs that can't mutate the document,
222 class OkViewPolicy : public ButtonPolicy {
226 /// Trigger a transition with this input
227 virtual void input(SMInput);
228 /// activation status
229 virtual bool buttonStatus(Button button) const {
230 return button & outputs_[state_];
232 /// are we in a read-only state ?
233 virtual bool isReadOnly() const {
239 /// which buttons are active
240 StateOutputs outputs_;
242 StateMachine state_machine_;
245 /** Ok and Cancel buttons for dialogs where read-only operation is blocked.
246 The state machine design for this policy allows changes to occur within
247 the dialog while a file is read-only -- the okay button is disabled until
248 a read-write input is given. When the file is made read-write the dialog
249 will then be in the correct state (as if the file had always been
251 Note: This scheme supports the relabelling of Cancel to Close
253 This is based on the value of the bool state of the Button::CANCEL.
254 true == Cancel, false == Close
256 class OkCancelReadOnlyPolicy : public ButtonPolicy {
259 OkCancelReadOnlyPolicy();
261 //virtual ~OkCancelReadOnlyPolicy() {}
263 /// Trigger a transition with this input.
264 virtual void input(SMInput);
265 /// Activation status of a button.
266 virtual bool buttonStatus(Button button) const {
267 return button & outputs_[state_];
269 /// Are we in a read-only state?
270 virtual bool isReadOnly() const {
271 return RO_INITIAL == state_
272 || RO_VALID == state_
273 || RO_INVALID == state_
274 || RO_APPLIED == state_;
279 /// Which buttons are active for a given state.
280 StateOutputs outputs_;
282 StateMachine state_machine_;
286 /** Ok, Apply and Cancel buttons for dialogs where read-only operation
288 Repeated Apply are not allowed. Likewise, Ok cannot follow Apply without
289 some valid input. That is, the dialog contents must change between
290 each Apply or Apply and Ok.
291 The state machine design for this policy allows changes to occur within
292 the dialog while a file is read-only -- the Ok+Apply buttons are disabled
293 until a read-write input is given. When the file is made read-write the
294 dialog will then be in the correct state (as if the file had always been
296 Note: This scheme supports the relabelling of Cancel to Close
298 This is based on the value of the bool state of the Button::CANCEL.
299 true == Cancel, false == Close
301 class NoRepeatedApplyReadOnlyPolicy : public ButtonPolicy
305 NoRepeatedApplyReadOnlyPolicy();
307 //virtual ~NoRepeatedApplyReadOnlyPolicy() {}
309 /// Trigger a transition with this input.
310 virtual void input(SMInput);
311 /// Activation status of a button.
312 virtual bool buttonStatus(Button button) const {
313 return button & outputs_[state_];
315 /// Are we in a read-only state?
316 virtual bool isReadOnly() const {
317 return RO_INITIAL == state_
318 || RO_VALID == state_
319 || RO_INVALID == state_
320 || RO_APPLIED == state_;
325 /// Which buttons are active for a given state.
326 StateOutputs outputs_;
328 StateMachine state_machine_;
332 /** Ok, Apply and Cancel buttons for dialogs where read-only
333 operation is blocked.
334 Repeated Apply is allowed. Likewise, Ok can follow Apply.
335 The state machine design for this policy allows changes to occur within
336 the dialog while a file is read-only -- the Ok+Apply buttons are disabled
337 until a read-write input is given. When the file is made read-write the
338 dialog will then be in the correct state (as if the file had always been
340 Note: This scheme supports the relabelling of Cancel to Close
342 This is based on the value of the bool state of the Button::CANCEL.
343 true == Cancel, false == Close
345 class OkApplyCancelReadOnlyPolicy : public ButtonPolicy {
348 OkApplyCancelReadOnlyPolicy();
350 //virtual ~OkApplyCancelReadOnlyPolicy() {}
352 /// Trigger a transition with this input.
353 virtual void input(SMInput);
354 /// Activation status of a button.
355 virtual bool buttonStatus(Button button) const {
356 return button & outputs_[state_];
358 /// Are we in a read-only state?
359 virtual bool isReadOnly() const {
360 return RO_INITIAL == state_
361 || RO_VALID == state_
362 || RO_INVALID == state_
363 || RO_APPLIED == state_;
368 /// Which buttons are active for a given state.
369 StateOutputs outputs_;
371 StateMachine state_machine_;
375 /** Ok, Apply and Cancel buttons for dialogs where repeated Apply is allowed.
376 Note: This scheme supports the relabelling of Cancel to Close
378 This is based on the value of the bool state of the Button::CANCEL.
379 true == Cancel, false == Close
381 class OkApplyCancelPolicy : public ButtonPolicy {
384 OkApplyCancelPolicy();
386 //virtual ~OkApplyCancelPolicy() {}
388 /// Trigger a transition with this input.
389 virtual void input(SMInput);
390 /// Activation status of a button.
391 virtual bool buttonStatus(Button button) const {
392 return button & outputs_[state_];
394 /// Are we in a read-only state?
395 virtual bool isReadOnly() const {
401 /// Which buttons are active for a given state.
402 StateOutputs outputs_;
404 StateMachine state_machine_;
408 /** Ok, Apply and Cancel buttons for dialogs with no repeated Apply.
409 Note: This scheme supports the relabelling of Cancel to Close
411 This is based on the value of the bool state of the Button::CANCEL.
412 true == Cancel, false == Close
414 class NoRepeatedApplyPolicy : public ButtonPolicy {
417 NoRepeatedApplyPolicy();
419 //virtual ~NoRepeatedApplyPolicy() {}
421 /// Trigger a transition with this input.
422 virtual void input(SMInput);
423 /// Activation status of a button.
424 virtual bool buttonStatus(Button button) const {
425 return button & outputs_[state_];
427 /// Are we in a read-only state?
428 virtual bool isReadOnly() const {
434 /// Which buttons are active for a given state.
435 StateOutputs outputs_;
437 StateMachine state_machine_;
441 /** Defines the policy used by the Preferences dialog.
442 Four buttons: Ok (Save), Apply, Cancel/Close, Restore.
443 Note: This scheme supports the relabelling of Cancel to Close
445 This is based on the value of the bool state of the Button::CANCEL.
446 true == Cancel, false == Close
448 class PreferencesPolicy : public ButtonPolicy {
453 //virtual ~PreferencesPolicy() {}
455 /// Trigger a transition with this input.
456 virtual void input(SMInput);
457 /// Activation status of a button.
458 virtual bool buttonStatus(Button button) const {
459 return button & outputs_[state_];
461 /// Are we in a read-only state?
462 virtual bool isReadOnly() const {
468 /// Which buttons are active for a given state.
469 StateOutputs outputs_;
471 StateMachine state_machine_;
475 /** Defines the policy used by dialogs that are forced to support a button
476 controller when they either don't have a use for one or are not ready to
477 use one. This may be useful when testing a new button policy but wishing
478 to minimise problems to users by supplying an anything-goes policy via a
479 preprocessor directive.
481 class IgnorantPolicy : public ButtonPolicy {
483 //virtual ~IgnorantPolicy() {}
485 /// Trigger a transition with this input.
486 virtual void input(SMInput) {}
487 /// Activation status of a button.
488 virtual bool buttonStatus(Button) const {
491 /// Are we in a read-only state?
492 virtual bool isReadOnly() const {