]> git.lyx.org Git - lyx.git/blob - src/frontends/ButtonPolicies.h
small fixes
[lyx.git] / src / frontends / ButtonPolicies.h
1 // -*- C++ -*-
2 /* ButtonPolicies.h
3  * Provides a state machine implementation of the various button policies
4  * used by the dialogs.
5  * Author: Allan Rae <rae@lyx.org>
6  * This file is part of
7  * ======================================================
8  *
9  *           LyX, The Document Processor
10  *
11  *           Copyright 1995 Matthias Ettrich
12  *           Copyright 1995-2000 The LyX Team.
13  *
14  *           This file Copyright 2000
15  *           Allan Rae
16  * ======================================================
17  */
18
19 #ifndef BUTTONPOLICIES_H
20 #define BUTTONPOLICIES_H
21
22
23 #include <vector>
24 #include <boost/utility.hpp>
25
26
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.
31
32                 Policy          | ReadOnly | Apply Button | Repeated Apply
33     ========================================================================
34     OkCancel                    |       N  |    N         |     -
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     ========================================================================
43
44     Policy
45         The name of the policy
46     ReadOnly
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
53         read-write).
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
57         be read-only.
58     Repeated Apply
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.
65
66     The IgnorantPolicy is a special case that allows anything.
67  */
68 class ButtonPolicy : public noncopyable {
69 public:
70         ///
71         virtual ~ButtonPolicy() {}
72
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.
76         */
77         enum State {
78                 ///
79                 INITIAL = 0,
80                 ///
81                 VALID,
82                 ///
83                 INVALID,
84                 ///
85                 APPLIED,
86                 ///
87                 RO_INITIAL,
88                 ///
89                 RO_VALID,
90                 ///
91                 RO_INVALID,
92                 ///
93                 RO_APPLIED,
94                 ///
95                 BOGUS = 55
96         };
97         
98         /// The various button types.
99         enum Button {
100                 ///
101                 CLOSE    = 0,  // Not a real button, but effectively !CANCEL
102                 ///
103                 OKAY     = 1,
104                 ///
105                 APPLY    = 2,
106                 ///
107                 CANCEL   = 4,
108                 ///
109                 UNDO_ALL = 8
110         };
111         ///
112         static const Button ALL_BUTTONS =
113                 Button(OKAY | APPLY | CANCEL | UNDO_ALL);
114   
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.
122          */
123         enum SMInput {
124                 ///
125                 SMI_VALID = 0,
126                 ///
127                 SMI_INVALID,
128                 ///
129                 SMI_OKAY,
130                 ///
131                 SMI_APPLY,
132                 ///
133                 SMI_CANCEL,
134                 ///
135                 SMI_UNDO_ALL,
136                 ///
137                 SMI_HIDE,
138                 ///
139                 SMI_READ_ONLY,
140                 ///
141                 SMI_READ_WRITE,
142                 ///
143                 SMI_TOTAL       // not a real input
144         };
145
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;
152
153         /// Transition map of the state machine.
154         typedef std::vector<State> StateArray;
155         ///
156         typedef std::vector<StateArray> StateMachine;
157         /// The state outputs are the status of the buttons.
158         typedef std::vector<int> StateOutputs;
159 };
160
161
162 inline
163 ostream & operator<<(ostream & os, ButtonPolicy::SMInput smi) 
164 {
165         os << int(smi);
166         return os;
167 }
168
169 inline
170 ostream & operator<<(ostream & os, ButtonPolicy::State st)
171 {
172         os << int(st);
173         return os;
174 }
175
176 //--------------------- Actual Policy Classes -----------------------------
177
178 /** Ok and Cancel buttons for dialogs with read-only operation.
179     Note: This scheme supports the relabelling of Cancel to Close and
180     vice versa.
181     This is based on the value of the bool state of the Button::CANCEL.
182     true == Cancel, false == Close
183  */
184 class OkCancelPolicy : public ButtonPolicy {
185 public:
186         ///
187         OkCancelPolicy();
188         ///
189         virtual ~OkCancelPolicy() {}
190         
191         /// Trigger a transition with this input.
192         virtual void input(SMInput);
193         /** Activation status of a button.
194             We assume that we haven't gotten into an undefined state.
195             This is reasonable since we can only reach states defined
196             in the state machine and they should all have been defined in
197             the outputs_ variable.  Perhaps we can do something at compile
198             time to check that all the states have corresponding outputs.
199          */
200         virtual bool buttonStatus(Button button) const {
201                 return button & outputs_[state_];
202         }
203         /// Are we in a read-only state?
204         virtual bool isReadOnly() const {
205                 return false;
206         }
207 private:
208         /// Current state.
209         State state_;
210         /// Which buttons are active for a given state.
211         StateOutputs outputs_;
212         ///
213         StateMachine state_machine_;
214 };
215
216
217 /** Ok and Cancel buttons for dialogs where read-only operation is blocked.
218     The state machine design for this policy allows changes to occur within
219     the dialog while a file is read-only -- the okay button is disabled until
220     a read-write input is given.  When the file is made read-write the dialog
221     will then be in the correct state (as if the file had always been read-write).
222     Note: This scheme supports the relabelling of Cancel to Close and vice versa.
223     This is based on the value of the bool state of the Button::CANCEL.
224     true == Cancel, false == Close
225  */
226 class OkCancelReadOnlyPolicy : public ButtonPolicy {
227 public:
228         ///
229         OkCancelReadOnlyPolicy();
230         ///
231         virtual ~OkCancelReadOnlyPolicy() {}
232         
233         /// Trigger a transition with this input.
234         virtual void input(SMInput);
235         /// Activation status of a button.
236         virtual bool buttonStatus(Button button) const {
237                 return button & outputs_[state_];
238         }
239         /// Are we in a read-only state?
240         virtual bool isReadOnly() const {
241                 return RO_INITIAL == state_
242                         || RO_VALID == state_
243                         || RO_INVALID == state_
244                         || RO_APPLIED == state_;
245         }
246 private:
247         /// Current state.
248         State state_;
249         /// Which buttons are active for a given state.
250         StateOutputs outputs_;
251         ///
252         StateMachine state_machine_;
253 };
254
255
256 /** Ok, Apply and Cancel buttons for dialogs where read-only operation is blocked.
257     Repeated Apply are not allowed.  Likewise,  Ok cannot follow Apply without
258     some valid input. That is, the dialog contents must change between each Apply
259     or Apply and Ok.
260     The state machine design for this policy allows changes to occur within
261     the dialog while a file is read-only -- the Ok+Apply buttons are disabled
262     until a read-write input is given.  When the file is made read-write the
263     dialog will then be in the correct state (as if the file had always been
264     read-write).
265     Note: This scheme supports the relabelling of Cancel to Close and vice versa.
266     This is based on the value of the bool state of the Button::CANCEL.
267     true == Cancel, false == Close
268  */
269 class NoRepeatedApplyReadOnlyPolicy : public ButtonPolicy
270 {
271 public:
272         ///
273         NoRepeatedApplyReadOnlyPolicy();
274         ///
275         virtual ~NoRepeatedApplyReadOnlyPolicy() {}
276         
277         /// Trigger a transition with this input.
278         virtual void input(SMInput);
279         /// Activation status of a button.
280         virtual bool buttonStatus(Button button) const {
281                 return button & outputs_[state_];
282         }
283         /// Are we in a read-only state?
284         virtual bool isReadOnly() const {
285                 return RO_INITIAL == state_
286                         || RO_VALID == state_
287                         || RO_INVALID == state_
288                         || RO_APPLIED == state_;
289         }
290 private:
291         /// Current state.
292         State state_;
293         /// Which buttons are active for a given state.
294         StateOutputs outputs_;
295         ///
296         StateMachine state_machine_;
297 };
298
299
300 /** Ok, Apply and Cancel buttons for dialogs where read-only operation is blocked.
301     Repeated Apply is allowed.  Likewise,  Ok can follow Apply.
302     The state machine design for this policy allows changes to occur within
303     the dialog while a file is read-only -- the Ok+Apply buttons are disabled
304     until a read-write input is given.  When the file is made read-write the
305     dialog will then be in the correct state (as if the file had always been
306     read-write).
307     Note: This scheme supports the relabelling of Cancel to Close and vice versa.
308     This is based on the value of the bool state of the Button::CANCEL.
309     true == Cancel, false == Close
310  */
311 class OkApplyCancelReadOnlyPolicy : public ButtonPolicy {
312 public:
313         ///
314         OkApplyCancelReadOnlyPolicy();
315         ///
316         virtual ~OkApplyCancelReadOnlyPolicy() {}
317         
318         /// Trigger a transition with this input.
319         virtual void input(SMInput);
320         /// Activation status of a button.
321         virtual bool buttonStatus(Button button) const {
322                 return button & outputs_[state_];
323         }
324         /// Are we in a read-only state?
325         virtual bool isReadOnly() const {
326                 return RO_INITIAL == state_
327                         || RO_VALID == state_
328                         || RO_INVALID == state_
329                         || RO_APPLIED == state_;
330         }
331 private:
332         /// Current state.
333         State state_;
334         /// Which buttons are active for a given state.
335         StateOutputs outputs_;
336         ///
337         StateMachine state_machine_;
338 };
339
340
341 /** Ok, Apply and Cancel buttons for dialogs where repeated Apply is allowed.
342     Note: This scheme supports the relabelling of Cancel to Close and vice versa.
343     This is based on the value of the bool state of the Button::CANCEL.
344     true == Cancel, false == Close
345  */
346 class OkApplyCancelPolicy : public ButtonPolicy {
347 public:
348         ///
349         OkApplyCancelPolicy();
350         ///
351         virtual ~OkApplyCancelPolicy() {}
352         
353         /// Trigger a transition with this input.
354         virtual void input(SMInput);
355         /// Activation status of a button.
356         virtual bool buttonStatus(Button button) const {
357                 return button & outputs_[state_];
358         }
359         /// Are we in a read-only state?
360         virtual bool isReadOnly() const {
361                 return false;
362         }
363 private:
364         /// Current state.
365         State state_;
366         /// Which buttons are active for a given state.
367         StateOutputs outputs_;
368         ///
369         StateMachine state_machine_;
370 };
371
372
373 /** Ok, Apply and Cancel buttons for dialogs with no repeated Apply.
374     Note: This scheme supports the relabelling of Cancel to Close and vice versa.
375     This is based on the value of the bool state of the Button::CANCEL.
376     true == Cancel, false == Close
377  */
378 class NoRepeatedApplyPolicy : public ButtonPolicy {
379 public:
380         ///
381         NoRepeatedApplyPolicy();
382         ///
383         virtual ~NoRepeatedApplyPolicy() {}
384         
385         /// Trigger a transition with this input.
386         virtual void input(SMInput);
387         /// Activation status of a button.
388         virtual bool buttonStatus(Button button) const {
389                 return button & outputs_[state_];
390         }
391         /// Are we in a read-only state?
392         virtual bool isReadOnly() const {
393                 return false;
394         }
395 private:
396         /// Current state.
397         State state_;
398         /// Which buttons are active for a given state.
399         StateOutputs outputs_;
400         ///
401         StateMachine state_machine_;
402 };
403
404
405 /** Defines the policy used by the Preferences dialog.
406     Four buttons: Ok (Save), Apply, Cancel/Close, Restore.
407     Note: This scheme supports the relabelling of Cancel to Close and vice versa.
408     This is based on the value of the bool state of the Button::CANCEL.
409     true == Cancel, false == Close
410  */
411 class PreferencesPolicy : public ButtonPolicy {
412 public:
413         ///
414         PreferencesPolicy();
415         ///
416         virtual ~PreferencesPolicy() {}
417         
418         /// Trigger a transition with this input.
419         virtual void input(SMInput);
420         /// Activation status of a button.
421         virtual bool buttonStatus(Button button) const {
422                 return button & outputs_[state_];
423         }
424         /// Are we in a read-only state?
425         virtual bool isReadOnly() const {
426                 return false;
427         }
428 private:
429         /// Current state.
430         State state_;
431         /// Which buttons are active for a given state.
432         StateOutputs outputs_;
433         ///
434         StateMachine state_machine_;
435 };
436
437
438 /** Defines the policy used by dialogs that are forced to support a button
439     controller when they either don't have a use for one or are not ready to
440     use one.  This may be useful when testing a new button policy but wishing
441     to minimise problems to users by supplying an anything-goes policy via a
442     preprocessor directive.
443  */
444 class IgnorantPolicy : public ButtonPolicy {
445 public:
446         virtual ~IgnorantPolicy() {}
447         
448         /// Trigger a transition with this input.
449         virtual void input(SMInput) {}
450         /// Activation status of a button.
451         virtual bool buttonStatus(Button) const {
452                 return true;
453         }
454         /// Are we in a read-only state?
455         virtual bool isReadOnly() const {
456                 return false;
457         }
458 };
459
460 #endif