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