3 * \file ButtonPolicies.h
4 * \author Allan Rae, rae@lyx.org
6 * Provides a state machine implementation of the various button policies
10 * ======================================================
12 * LyX, The Document Processor
14 * Copyright 1995 Matthias Ettrich
15 * Copyright 1995-2001 The LyX Team.
17 * This file Copyright 2000
19 * ======================================================
22 #ifndef BUTTONPOLICIES_H
23 #define BUTTONPOLICIES_H
27 #include <boost/utility.hpp>
29 #include "support/LOstream.h"
31 /** An abstract base class for button policies.
32 A state machine implementation of the various button policies used by the
33 dialogs. Only the policy is implemented here. Separate ButtonController
34 classes are needed for each GUI implementation.
36 Policy | ReadOnly | Apply Button | Repeated Apply
37 ========================================================================
39 OkCancelReadOnly | Y | N | -
40 OkApplyCancel | N | Y | Y
41 OkApplyCancelReadOnly | Y | Y | Y
42 NoRepeatedApply | N | Y | N
43 NoRepeatedApplyReadOnly | Y | Y | N
44 Preferences | N | Y | No (Ok-Close)
45 Ignorant | N/A | N/A | N/A
46 ========================================================================
49 The name of the policy
51 Does the policy treat read-only docs differently to read-write docs?
52 This usually means that when an SMI_READ_ONLY input arrives then
53 all the buttons are disabled except Cancel/Close. The state
54 machine tracks the inputs (valid/invalid) and has states for all
55 combinations. When an SMI_READ_WRITE input arrives the appropriate
56 machine state is entered (just as if the document had always been
58 NOTE: If a dialog doesn't care about the read-only status of a document
59 (and uses an appropriate policy) it can never get into a read-only state
60 so isReadOnly() can only ever return false even though the document may
63 Simply means that it is alright to use the Apply button multiple times
64 without requiring a change of the dialog contents. If no repeating is
65 allowed the Ok+Apply buttons are deactivated. The Preferences dialog
66 has its own special version of repeated apply handling because its Ok
67 button is actually a Save button -- its always reasonable to Save the
68 preferences if the dialog has changed since the last save.
70 The IgnorantPolicy is a special case that allows anything.
72 class ButtonPolicy : boost::noncopyable {
75 virtual ~ButtonPolicy() {}
77 /** The various possible state names.
78 Not all state-machines have this many states. However, we need
79 to define them all here so we can share the code.
102 /// The various button types.
105 CLOSE = 0, // Not a real button, but effectively !CANCEL
116 static const Button ALL_BUTTONS =
117 Button(OKAY | APPLY | CANCEL | RESTORE);
119 /** State machine inputs.
120 All the policies so far have both CANCEL and HIDE always going to
121 INITIAL. This won't necessarily be true for all [future] policies
122 though so I'll leave those two as distinct inputs rather than merge
123 them. For example, a dialog that doesn't update it's input fields
124 when reshown after being hidden needs a policy where CANCEL and
125 HIDE are treated differently.
128 /// the dialog contents are now valid
130 /// the dialog contents are now invalid
132 /// an apply-and-hide action has happened
134 /// an apply action has happened
136 /// a cancel action has happened
138 /// a restore action has happened
140 /// the dialog has been hidden
142 /// the dialog contents are read-only
144 /// the dialog contents can be modified
146 /// the state of the dialog contents has not changed
152 /// Trigger a transition with this input.
153 virtual void input(SMInput) = 0;
154 /// Activation status of a button
155 virtual bool buttonStatus(Button) const = 0;
156 /// Are we in a read-only state?
157 virtual bool isReadOnly() const = 0;
159 /// Transition map of the state machine.
160 typedef std::vector<State> StateArray;
162 typedef std::vector<StateArray> StateMachine;
163 /// The state outputs are the status of the buttons.
164 typedef std::vector<int> StateOutputs;
169 std::ostream & operator<<(std::ostream & os, ButtonPolicy::State st)
177 std::ostream & operator<<(std::ostream & os, ButtonPolicy::SMInput smi)
184 //--------------------- Actual Policy Classes -----------------------------
186 /** Ok and Cancel buttons for dialogs with read-only operation.
187 Note: This scheme supports the relabelling of Cancel to Close and
189 This is based on the value of the bool state of the Button::CANCEL.
190 true == Cancel, false == Close
192 class OkCancelPolicy : public ButtonPolicy {
197 //virtual ~OkCancelPolicy() {}
199 /// Trigger a transition with this input.
200 virtual void input(SMInput);
201 /** Activation status of a button.
202 We assume that we haven't gotten into an undefined state.
203 This is reasonable since we can only reach states defined
204 in the state machine and they should all have been defined in
205 the outputs_ variable. Perhaps we can do something at compile
206 time to check that all the states have corresponding outputs.
208 virtual bool buttonStatus(Button button) const {
209 return button & outputs_[state_];
211 /// Are we in a read-only state?
212 virtual bool isReadOnly() const {
218 /// Which buttons are active for a given state.
219 StateOutputs outputs_;
221 StateMachine state_machine_;
224 /** Ok and Cancel buttons for dialogs where read-only operation is blocked.
225 The state machine design for this policy allows changes to occur within
226 the dialog while a file is read-only -- the okay button is disabled until
227 a read-write input is given. When the file is made read-write the dialog
228 will then be in the correct state (as if the file had always been
230 Note: This scheme supports the relabelling of Cancel to Close
232 This is based on the value of the bool state of the Button::CANCEL.
233 true == Cancel, false == Close
235 class OkCancelReadOnlyPolicy : public ButtonPolicy {
238 OkCancelReadOnlyPolicy();
240 //virtual ~OkCancelReadOnlyPolicy() {}
242 /// Trigger a transition with this input.
243 virtual void input(SMInput);
244 /// Activation status of a button.
245 virtual bool buttonStatus(Button button) const {
246 return button & outputs_[state_];
248 /// Are we in a read-only state?
249 virtual bool isReadOnly() const {
250 return RO_INITIAL == state_
251 || RO_VALID == state_
252 || RO_INVALID == state_
253 || RO_APPLIED == state_;
258 /// Which buttons are active for a given state.
259 StateOutputs outputs_;
261 StateMachine state_machine_;
265 /** Ok, Apply and Cancel buttons for dialogs where read-only operation
267 Repeated Apply are not allowed. Likewise, Ok cannot follow Apply without
268 some valid input. That is, the dialog contents must change between
269 each Apply or Apply and Ok.
270 The state machine design for this policy allows changes to occur within
271 the dialog while a file is read-only -- the Ok+Apply buttons are disabled
272 until a read-write input is given. When the file is made read-write the
273 dialog will then be in the correct state (as if the file had always been
275 Note: This scheme supports the relabelling of Cancel to Close
277 This is based on the value of the bool state of the Button::CANCEL.
278 true == Cancel, false == Close
280 class NoRepeatedApplyReadOnlyPolicy : public ButtonPolicy
284 NoRepeatedApplyReadOnlyPolicy();
286 //virtual ~NoRepeatedApplyReadOnlyPolicy() {}
288 /// Trigger a transition with this input.
289 virtual void input(SMInput);
290 /// Activation status of a button.
291 virtual bool buttonStatus(Button button) const {
292 return button & outputs_[state_];
294 /// Are we in a read-only state?
295 virtual bool isReadOnly() const {
296 return RO_INITIAL == state_
297 || RO_VALID == state_
298 || RO_INVALID == state_
299 || RO_APPLIED == state_;
304 /// Which buttons are active for a given state.
305 StateOutputs outputs_;
307 StateMachine state_machine_;
311 /** Ok, Apply and Cancel buttons for dialogs where read-only
312 operation is blocked.
313 Repeated Apply is allowed. Likewise, Ok can follow Apply.
314 The state machine design for this policy allows changes to occur within
315 the dialog while a file is read-only -- the Ok+Apply buttons are disabled
316 until a read-write input is given. When the file is made read-write the
317 dialog will then be in the correct state (as if the file had always been
319 Note: This scheme supports the relabelling of Cancel to Close
321 This is based on the value of the bool state of the Button::CANCEL.
322 true == Cancel, false == Close
324 class OkApplyCancelReadOnlyPolicy : public ButtonPolicy {
327 OkApplyCancelReadOnlyPolicy();
329 //virtual ~OkApplyCancelReadOnlyPolicy() {}
331 /// Trigger a transition with this input.
332 virtual void input(SMInput);
333 /// Activation status of a button.
334 virtual bool buttonStatus(Button button) const {
335 return button & outputs_[state_];
337 /// Are we in a read-only state?
338 virtual bool isReadOnly() const {
339 return RO_INITIAL == state_
340 || RO_VALID == state_
341 || RO_INVALID == state_
342 || RO_APPLIED == state_;
347 /// Which buttons are active for a given state.
348 StateOutputs outputs_;
350 StateMachine state_machine_;
354 /** Ok, Apply and Cancel buttons for dialogs where repeated Apply is allowed.
355 Note: This scheme supports the relabelling of Cancel to Close
357 This is based on the value of the bool state of the Button::CANCEL.
358 true == Cancel, false == Close
360 class OkApplyCancelPolicy : public ButtonPolicy {
363 OkApplyCancelPolicy();
365 //virtual ~OkApplyCancelPolicy() {}
367 /// Trigger a transition with this input.
368 virtual void input(SMInput);
369 /// Activation status of a button.
370 virtual bool buttonStatus(Button button) const {
371 return button & outputs_[state_];
373 /// Are we in a read-only state?
374 virtual bool isReadOnly() const {
380 /// Which buttons are active for a given state.
381 StateOutputs outputs_;
383 StateMachine state_machine_;
387 /** Ok, Apply and Cancel buttons for dialogs with no repeated Apply.
388 Note: This scheme supports the relabelling of Cancel to Close
390 This is based on the value of the bool state of the Button::CANCEL.
391 true == Cancel, false == Close
393 class NoRepeatedApplyPolicy : public ButtonPolicy {
396 NoRepeatedApplyPolicy();
398 //virtual ~NoRepeatedApplyPolicy() {}
400 /// Trigger a transition with this input.
401 virtual void input(SMInput);
402 /// Activation status of a button.
403 virtual bool buttonStatus(Button button) const {
404 return button & outputs_[state_];
406 /// Are we in a read-only state?
407 virtual bool isReadOnly() const {
413 /// Which buttons are active for a given state.
414 StateOutputs outputs_;
416 StateMachine state_machine_;
420 /** Defines the policy used by the Preferences dialog.
421 Four buttons: Ok (Save), Apply, Cancel/Close, Restore.
422 Note: This scheme supports the relabelling of Cancel to Close
424 This is based on the value of the bool state of the Button::CANCEL.
425 true == Cancel, false == Close
427 class PreferencesPolicy : public ButtonPolicy {
432 //virtual ~PreferencesPolicy() {}
434 /// Trigger a transition with this input.
435 virtual void input(SMInput);
436 /// Activation status of a button.
437 virtual bool buttonStatus(Button button) const {
438 return button & outputs_[state_];
440 /// Are we in a read-only state?
441 virtual bool isReadOnly() const {
447 /// Which buttons are active for a given state.
448 StateOutputs outputs_;
450 StateMachine state_machine_;
454 /** Defines the policy used by dialogs that are forced to support a button
455 controller when they either don't have a use for one or are not ready to
456 use one. This may be useful when testing a new button policy but wishing
457 to minimise problems to users by supplying an anything-goes policy via a
458 preprocessor directive.
460 class IgnorantPolicy : public ButtonPolicy {
462 //virtual ~IgnorantPolicy() {}
464 /// Trigger a transition with this input.
465 virtual void input(SMInput) {}
466 /// Activation status of a button.
467 virtual bool buttonStatus(Button) const {
470 /// Are we in a read-only state?
471 virtual bool isReadOnly() const {