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>
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 : public 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 | UNDO_ALL);
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.
143 SMI_TOTAL // not a real input
146 /// Trigger a transition with this input.
147 virtual void input(SMInput) = 0;
148 /// Activation status of a button
149 virtual bool buttonStatus(Button) const = 0;
150 /// Are we in a read-only state?
151 virtual bool isReadOnly() const = 0;
153 /// Transition map of the state machine.
154 typedef std::vector<State> StateArray;
156 typedef std::vector<StateArray> StateMachine;
157 /// The state outputs are the status of the buttons.
158 typedef std::vector<int> StateOutputs;
162 //--------------------- Actual Policy Classes -----------------------------
164 /** Ok and Cancel buttons for dialogs with read-only operation.
165 Note: This scheme supports the relabelling of Cancel to Close and
167 This is based on the value of the bool state of the Button::CANCEL.
168 true == Cancel, false == Close
170 class OkCancelPolicy : public ButtonPolicy {
175 virtual ~OkCancelPolicy() {}
177 /// Trigger a transition with this input.
178 virtual void input(SMInput);
179 /** Activation status of a button.
180 We assume that we haven't gotten into an undefined state.
181 This is reasonable since we can only reach states defined
182 in the state machine and they should all have been defined in
183 the outputs_ variable. Perhaps we can do something at compile
184 time to check that all the states have corresponding outputs.
186 virtual bool buttonStatus(Button button) const {
187 return button & outputs_[state_];
189 /// Are we in a read-only state?
190 virtual bool isReadOnly() const {
196 /// Which buttons are active for a given state.
197 StateOutputs outputs_;
199 StateMachine state_machine_;
203 /** Ok and Cancel buttons for dialogs where read-only operation is blocked.
204 The state machine design for this policy allows changes to occur within
205 the dialog while a file is read-only -- the okay button is disabled until
206 a read-write input is given. When the file is made read-write the dialog
207 will then be in the correct state (as if the file had always been read-write).
208 Note: This scheme supports the relabelling of Cancel to Close and vice versa.
209 This is based on the value of the bool state of the Button::CANCEL.
210 true == Cancel, false == Close
212 class OkCancelReadOnlyPolicy : public ButtonPolicy {
215 OkCancelReadOnlyPolicy();
217 virtual ~OkCancelReadOnlyPolicy() {}
219 /// Trigger a transition with this input.
220 virtual void input(SMInput);
221 /// Activation status of a button.
222 virtual bool buttonStatus(Button button) const {
223 return button & outputs_[state_];
225 /// Are we in a read-only state?
226 virtual bool isReadOnly() const {
227 return RO_INITIAL == state_
228 || RO_VALID == state_
229 || RO_INVALID == state_
230 || RO_APPLIED == state_;
235 /// Which buttons are active for a given state.
236 StateOutputs outputs_;
238 StateMachine state_machine_;
242 /** Ok, Apply and Cancel buttons for dialogs where read-only operation is blocked.
243 Repeated Apply are not allowed. Likewise, Ok cannot follow Apply without
244 some valid input. That is, the dialog contents must change between each Apply
246 The state machine design for this policy allows changes to occur within
247 the dialog while a file is read-only -- the Ok+Apply buttons are disabled
248 until a read-write input is given. When the file is made read-write the
249 dialog 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 and vice versa.
252 This is based on the value of the bool state of the Button::CANCEL.
253 true == Cancel, false == Close
255 class NoRepeatedApplyReadOnlyPolicy : public ButtonPolicy
259 NoRepeatedApplyReadOnlyPolicy();
261 virtual ~NoRepeatedApplyReadOnlyPolicy() {}
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 is blocked.
287 Repeated Apply is allowed. Likewise, Ok can follow Apply.
288 The state machine design for this policy allows changes to occur within
289 the dialog while a file is read-only -- the Ok+Apply buttons are disabled
290 until a read-write input is given. When the file is made read-write the
291 dialog will then be in the correct state (as if the file had always been
293 Note: This scheme supports the relabelling of Cancel to Close and vice versa.
294 This is based on the value of the bool state of the Button::CANCEL.
295 true == Cancel, false == Close
297 class OkApplyCancelReadOnlyPolicy : public ButtonPolicy {
300 OkApplyCancelReadOnlyPolicy();
302 virtual ~OkApplyCancelReadOnlyPolicy() {}
304 /// Trigger a transition with this input.
305 virtual void input(SMInput);
306 /// Activation status of a button.
307 virtual bool buttonStatus(Button button) const {
308 return button & outputs_[state_];
310 /// Are we in a read-only state?
311 virtual bool isReadOnly() const {
312 return RO_INITIAL == state_
313 || RO_VALID == state_
314 || RO_INVALID == state_
315 || RO_APPLIED == state_;
320 /// Which buttons are active for a given state.
321 StateOutputs outputs_;
323 StateMachine state_machine_;
327 /** Ok, Apply and Cancel buttons for dialogs where repeated Apply is allowed.
328 Note: This scheme supports the relabelling of Cancel to Close and vice versa.
329 This is based on the value of the bool state of the Button::CANCEL.
330 true == Cancel, false == Close
332 class OkApplyCancelPolicy : public ButtonPolicy {
335 OkApplyCancelPolicy();
337 virtual ~OkApplyCancelPolicy() {}
339 /// Trigger a transition with this input.
340 virtual void input(SMInput);
341 /// Activation status of a button.
342 virtual bool buttonStatus(Button button) const {
343 return button & outputs_[state_];
345 /// Are we in a read-only state?
346 virtual bool isReadOnly() const {
352 /// Which buttons are active for a given state.
353 StateOutputs outputs_;
355 StateMachine state_machine_;
359 /** Ok, Apply and Cancel buttons for dialogs with no repeated Apply.
360 Note: This scheme supports the relabelling of Cancel to Close and vice versa.
361 This is based on the value of the bool state of the Button::CANCEL.
362 true == Cancel, false == Close
364 class NoRepeatedApplyPolicy : public ButtonPolicy {
367 NoRepeatedApplyPolicy();
369 virtual ~NoRepeatedApplyPolicy() {}
371 /// Trigger a transition with this input.
372 virtual void input(SMInput);
373 /// Activation status of a button.
374 virtual bool buttonStatus(Button button) const {
375 return button & outputs_[state_];
377 /// Are we in a read-only state?
378 virtual bool isReadOnly() const {
384 /// Which buttons are active for a given state.
385 StateOutputs outputs_;
387 StateMachine state_machine_;
391 /** Defines the policy used by the Preferences dialog.
392 Four buttons: Ok (Save), Apply, Cancel/Close, Restore.
393 Note: This scheme supports the relabelling of Cancel to Close and vice versa.
394 This is based on the value of the bool state of the Button::CANCEL.
395 true == Cancel, false == Close
397 class PreferencesPolicy : public ButtonPolicy {
402 virtual ~PreferencesPolicy() {}
404 /// Trigger a transition with this input.
405 virtual void input(SMInput);
406 /// Activation status of a button.
407 virtual bool buttonStatus(Button button) const {
408 return button & outputs_[state_];
410 /// Are we in a read-only state?
411 virtual bool isReadOnly() const {
417 /// Which buttons are active for a given state.
418 StateOutputs outputs_;
420 StateMachine state_machine_;
424 /** Defines the policy used by dialogs that are forced to support a button
425 controller when they either don't have a use for one or are not ready to
426 use one. This may be useful when testing a new button policy but wishing
427 to minimise problems to users by supplying an anything-goes policy via a
428 preprocessor directive.
430 class IgnorantPolicy : public ButtonPolicy {
432 virtual ~IgnorantPolicy() {}
434 /// Trigger a transition with this input.
435 virtual void input(SMInput) {}
436 /// Activation status of a button.
437 virtual bool buttonStatus(Button) const {
440 /// Are we in a read-only state?
441 virtual bool isReadOnly() const {