]> git.lyx.org Git - lyx.git/blob - src/frontends/controllers/ButtonPolicies.h
one small private fix in mathed, put noncopyable and tie into boost namespace
[lyx.git] / src / frontends / controllers / 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 boost::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_NOOP,
145                 ///
146                 SMI_TOTAL       // not a real input
147         };
148
149         /// Trigger a transition with this input.
150         virtual void input(SMInput) = 0;
151         /// Activation status of a button
152         virtual bool buttonStatus(Button) const = 0;
153         /// Are we in a read-only state?
154         virtual bool isReadOnly() const = 0;
155
156         /// Transition map of the state machine.
157         typedef std::vector<State> StateArray;
158         ///
159         typedef std::vector<StateArray> StateMachine;
160         /// The state outputs are the status of the buttons.
161         typedef std::vector<int> StateOutputs;
162 };
163
164
165 inline
166 std::ostream & operator<<(std::ostream & os, ButtonPolicy::State st)
167 {
168         os << int(st);
169         return os;
170 }
171
172
173 inline
174 std::ostream & operator<<(std::ostream & os, ButtonPolicy::SMInput smi)
175 {
176         os << int(smi);
177         return os;
178 }
179
180
181 //--------------------- Actual Policy Classes -----------------------------
182
183 /** Ok and Cancel buttons for dialogs with read-only operation.
184     Note: This scheme supports the relabelling of Cancel to Close and
185     vice versa.
186     This is based on the value of the bool state of the Button::CANCEL.
187     true == Cancel, false == Close
188  */
189 class OkCancelPolicy : public ButtonPolicy {
190 public:
191         ///
192         OkCancelPolicy();
193         ///
194         //virtual ~OkCancelPolicy() {}
195         
196         /// Trigger a transition with this input.
197         virtual void input(SMInput);
198         /** Activation status of a button.
199             We assume that we haven't gotten into an undefined state.
200             This is reasonable since we can only reach states defined
201             in the state machine and they should all have been defined in
202             the outputs_ variable.  Perhaps we can do something at compile
203             time to check that all the states have corresponding outputs.
204          */
205         virtual bool buttonStatus(Button button) const {
206                 return button & outputs_[state_];
207         }
208         /// Are we in a read-only state?
209         virtual bool isReadOnly() const {
210                 return false;
211         }
212 private:
213         /// Current state.
214         State state_;
215         /// Which buttons are active for a given state.
216         StateOutputs outputs_;
217         ///
218         StateMachine state_machine_;
219 };
220
221 /** Ok and Cancel buttons for dialogs where read-only operation is blocked.
222     The state machine design for this policy allows changes to occur within
223     the dialog while a file is read-only -- the okay button is disabled until
224     a read-write input is given.  When the file is made read-write the dialog
225     will then be in the correct state (as if the file had always been
226     read-write).
227     Note: This scheme supports the relabelling of Cancel to Close
228     and vice versa.
229     This is based on the value of the bool state of the Button::CANCEL.
230     true == Cancel, false == Close
231  */
232 class OkCancelReadOnlyPolicy : public ButtonPolicy {
233 public:
234         ///
235         OkCancelReadOnlyPolicy();
236         ///
237         //virtual ~OkCancelReadOnlyPolicy() {}
238         
239         /// Trigger a transition with this input.
240         virtual void input(SMInput);
241         /// Activation status of a button.
242         virtual bool buttonStatus(Button button) const {
243                 return button & outputs_[state_];
244         }
245         /// Are we in a read-only state?
246         virtual bool isReadOnly() const {
247                 return RO_INITIAL == state_
248                         || RO_VALID == state_
249                         || RO_INVALID == state_
250                         || RO_APPLIED == state_;
251         }
252 private:
253         /// Current state.
254         State state_;
255         /// Which buttons are active for a given state.
256         StateOutputs outputs_;
257         ///
258         StateMachine state_machine_;
259 };
260
261
262 /** Ok, Apply and Cancel buttons for dialogs where read-only operation
263     is blocked.
264     Repeated Apply are not allowed.  Likewise,  Ok cannot follow Apply without
265     some valid input. That is, the dialog contents must change between
266     each Apply or Apply and Ok.
267     The state machine design for this policy allows changes to occur within
268     the dialog while a file is read-only -- the Ok+Apply buttons are disabled
269     until a read-write input is given.  When the file is made read-write the
270     dialog will then be in the correct state (as if the file had always been
271     read-write).
272     Note: This scheme supports the relabelling of Cancel to Close
273     and vice versa.
274     This is based on the value of the bool state of the Button::CANCEL.
275     true == Cancel, false == Close
276  */
277 class NoRepeatedApplyReadOnlyPolicy : public ButtonPolicy
278 {
279 public:
280         ///
281         NoRepeatedApplyReadOnlyPolicy();
282         ///
283         //virtual ~NoRepeatedApplyReadOnlyPolicy() {}
284         
285         /// Trigger a transition with this input.
286         virtual void input(SMInput);
287         /// Activation status of a button.
288         virtual bool buttonStatus(Button button) const {
289                 return button & outputs_[state_];
290         }
291         /// Are we in a read-only state?
292         virtual bool isReadOnly() const {
293                 return RO_INITIAL == state_
294                         || RO_VALID == state_
295                         || RO_INVALID == state_
296                         || RO_APPLIED == state_;
297         }
298 private:
299         /// Current state.
300         State state_;
301         /// Which buttons are active for a given state.
302         StateOutputs outputs_;
303         ///
304         StateMachine state_machine_;
305 };
306
307
308 /** Ok, Apply and Cancel buttons for dialogs where read-only
309     operation is blocked.
310     Repeated Apply is allowed.  Likewise,  Ok can follow Apply.
311     The state machine design for this policy allows changes to occur within
312     the dialog while a file is read-only -- the Ok+Apply buttons are disabled
313     until a read-write input is given.  When the file is made read-write the
314     dialog will then be in the correct state (as if the file had always been
315     read-write).
316     Note: This scheme supports the relabelling of Cancel to Close
317     and vice versa.
318     This is based on the value of the bool state of the Button::CANCEL.
319     true == Cancel, false == Close
320  */
321 class OkApplyCancelReadOnlyPolicy : public ButtonPolicy {
322 public:
323         ///
324         OkApplyCancelReadOnlyPolicy();
325         ///
326         //virtual ~OkApplyCancelReadOnlyPolicy() {}
327         
328         /// Trigger a transition with this input.
329         virtual void input(SMInput);
330         /// Activation status of a button.
331         virtual bool buttonStatus(Button button) const {
332                 return button & outputs_[state_];
333         }
334         /// Are we in a read-only state?
335         virtual bool isReadOnly() const {
336                 return RO_INITIAL == state_
337                         || RO_VALID == state_
338                         || RO_INVALID == state_
339                         || RO_APPLIED == state_;
340         }
341 private:
342         /// Current state.
343         State state_;
344         /// Which buttons are active for a given state.
345         StateOutputs outputs_;
346         ///
347         StateMachine state_machine_;
348 };
349
350
351 /** Ok, Apply and Cancel buttons for dialogs where repeated Apply is allowed.
352     Note: This scheme supports the relabelling of Cancel to Close
353     and vice versa.
354     This is based on the value of the bool state of the Button::CANCEL.
355     true == Cancel, false == Close
356  */
357 class OkApplyCancelPolicy : public ButtonPolicy {
358 public:
359         ///
360         OkApplyCancelPolicy();
361         ///
362         //virtual ~OkApplyCancelPolicy() {}
363         
364         /// Trigger a transition with this input.
365         virtual void input(SMInput);
366         /// Activation status of a button.
367         virtual bool buttonStatus(Button button) const {
368                 return button & outputs_[state_];
369         }
370         /// Are we in a read-only state?
371         virtual bool isReadOnly() const {
372                 return false;
373         }
374 private:
375         /// Current state.
376         State state_;
377         /// Which buttons are active for a given state.
378         StateOutputs outputs_;
379         ///
380         StateMachine state_machine_;
381 };
382
383
384 /** Ok, Apply and Cancel buttons for dialogs with no repeated Apply.
385     Note: This scheme supports the relabelling of Cancel to Close
386     and vice versa.
387     This is based on the value of the bool state of the Button::CANCEL.
388     true == Cancel, false == Close
389  */
390 class NoRepeatedApplyPolicy : public ButtonPolicy {
391 public:
392         ///
393         NoRepeatedApplyPolicy();
394         ///
395         //virtual ~NoRepeatedApplyPolicy() {}
396         
397         /// Trigger a transition with this input.
398         virtual void input(SMInput);
399         /// Activation status of a button.
400         virtual bool buttonStatus(Button button) const {
401                 return button & outputs_[state_];
402         }
403         /// Are we in a read-only state?
404         virtual bool isReadOnly() const {
405                 return false;
406         }
407 private:
408         /// Current state.
409         State state_;
410         /// Which buttons are active for a given state.
411         StateOutputs outputs_;
412         ///
413         StateMachine state_machine_;
414 };
415
416
417 /** Defines the policy used by the Preferences dialog.
418     Four buttons: Ok (Save), Apply, Cancel/Close, Restore.
419     Note: This scheme supports the relabelling of Cancel to Close
420     and vice versa.
421     This is based on the value of the bool state of the Button::CANCEL.
422     true == Cancel, false == Close
423  */
424 class PreferencesPolicy : public ButtonPolicy {
425 public:
426         ///
427         PreferencesPolicy();
428         ///
429         //virtual ~PreferencesPolicy() {}
430         
431         /// Trigger a transition with this input.
432         virtual void input(SMInput);
433         /// Activation status of a button.
434         virtual bool buttonStatus(Button button) const {
435                 return button & outputs_[state_];
436         }
437         /// Are we in a read-only state?
438         virtual bool isReadOnly() const {
439                 return false;
440         }
441 private:
442         /// Current state.
443         State state_;
444         /// Which buttons are active for a given state.
445         StateOutputs outputs_;
446         ///
447         StateMachine state_machine_;
448 };
449
450
451 /** Defines the policy used by dialogs that are forced to support a button
452     controller when they either don't have a use for one or are not ready to
453     use one.  This may be useful when testing a new button policy but wishing
454     to minimise problems to users by supplying an anything-goes policy via a
455     preprocessor directive.
456  */
457 class IgnorantPolicy : public ButtonPolicy {
458 public:
459         //virtual ~IgnorantPolicy() {}
460         
461         /// Trigger a transition with this input.
462         virtual void input(SMInput) {}
463         /// Activation status of a button.
464         virtual bool buttonStatus(Button) const {
465                 return true;
466         }
467         /// Are we in a read-only state?
468         virtual bool isReadOnly() const {
469                 return false;
470         }
471 };
472
473 #endif