]> git.lyx.org Git - lyx.git/blob - src/frontends/ButtonPolicies.h
Small fix from Angus
[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 //--------------------- Actual Policy Classes -----------------------------
163
164 /** Ok and Cancel buttons for dialogs with read-only operation.
165     Note: This scheme supports the relabelling of Cancel to Close and
166     vice versa.
167     This is based on the value of the bool state of the Button::CANCEL.
168     true == Cancel, false == Close
169  */
170 class OkCancelPolicy : public ButtonPolicy {
171 public:
172         ///
173         OkCancelPolicy();
174         ///
175         virtual ~OkCancelPolicy() {}
176         
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.
185          */
186         virtual bool buttonStatus(Button button) const {
187                 return button & outputs_[state_];
188         }
189         /// Are we in a read-only state?
190         virtual bool isReadOnly() const {
191                 return false;
192         }
193 private:
194         /// Current state.
195         State state_;
196         /// Which buttons are active for a given state.
197         StateOutputs outputs_;
198         ///
199         StateMachine state_machine_;
200 };
201
202
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
211  */
212 class OkCancelReadOnlyPolicy : public ButtonPolicy {
213 public:
214         ///
215         OkCancelReadOnlyPolicy();
216         ///
217         virtual ~OkCancelReadOnlyPolicy() {}
218         
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_];
224         }
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_;
231         }
232 private:
233         /// Current state.
234         State state_;
235         /// Which buttons are active for a given state.
236         StateOutputs outputs_;
237         ///
238         StateMachine state_machine_;
239 };
240
241
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
245     or Apply and Ok.
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
250     read-write).
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
254  */
255 class NoRepeatedApplyReadOnlyPolicy : public ButtonPolicy
256 {
257 public:
258         ///
259         NoRepeatedApplyReadOnlyPolicy();
260         ///
261         virtual ~NoRepeatedApplyReadOnlyPolicy() {}
262         
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_];
268         }
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_;
275         }
276 private:
277         /// Current state.
278         State state_;
279         /// Which buttons are active for a given state.
280         StateOutputs outputs_;
281         ///
282         StateMachine state_machine_;
283 };
284
285
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
292     read-write).
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
296  */
297 class OkApplyCancelReadOnlyPolicy : public ButtonPolicy {
298 public:
299         ///
300         OkApplyCancelReadOnlyPolicy();
301         ///
302         virtual ~OkApplyCancelReadOnlyPolicy() {}
303         
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_];
309         }
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_;
316         }
317 private:
318         /// Current state.
319         State state_;
320         /// Which buttons are active for a given state.
321         StateOutputs outputs_;
322         ///
323         StateMachine state_machine_;
324 };
325
326
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
331  */
332 class OkApplyCancelPolicy : public ButtonPolicy {
333 public:
334         ///
335         OkApplyCancelPolicy();
336         ///
337         virtual ~OkApplyCancelPolicy() {}
338         
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_];
344         }
345         /// Are we in a read-only state?
346         virtual bool isReadOnly() const {
347                 return false;
348         }
349 private:
350         /// Current state.
351         State state_;
352         /// Which buttons are active for a given state.
353         StateOutputs outputs_;
354         ///
355         StateMachine state_machine_;
356 };
357
358
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
363  */
364 class NoRepeatedApplyPolicy : public ButtonPolicy {
365 public:
366         ///
367         NoRepeatedApplyPolicy();
368         ///
369         virtual ~NoRepeatedApplyPolicy() {}
370         
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_];
376         }
377         /// Are we in a read-only state?
378         virtual bool isReadOnly() const {
379                 return false;
380         }
381 private:
382         /// Current state.
383         State state_;
384         /// Which buttons are active for a given state.
385         StateOutputs outputs_;
386         ///
387         StateMachine state_machine_;
388 };
389
390
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
396  */
397 class PreferencesPolicy : public ButtonPolicy {
398 public:
399         ///
400         PreferencesPolicy();
401         ///
402         virtual ~PreferencesPolicy() {}
403         
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_];
409         }
410         /// Are we in a read-only state?
411         virtual bool isReadOnly() const {
412                 return false;
413         }
414 private:
415         /// Current state.
416         State state_;
417         /// Which buttons are active for a given state.
418         StateOutputs outputs_;
419         ///
420         StateMachine state_machine_;
421 };
422
423
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.
429  */
430 class IgnorantPolicy : public ButtonPolicy {
431 public:
432         virtual ~IgnorantPolicy() {}
433         
434         /// Trigger a transition with this input.
435         virtual void input(SMInput) {}
436         /// Activation status of a button.
437         virtual bool buttonStatus(Button) const {
438                 return true;
439         }
440         /// Are we in a read-only state?
441         virtual bool isReadOnly() const {
442                 return false;
443         }
444 };
445
446 #endif