]> git.lyx.org Git - lyx.git/blob - src/frontends/controllers/ButtonPolicies.h
Controller-view split of Graphics and Index popups.
[lyx.git] / src / frontends / controllers / ButtonPolicies.h
1 /*
2  * \file ButtonPolicies.h
3  * \author Allan Rae, rae@lyx.org
4  *
5  * Provides a state machine implementation of the various button policies
6  * used by the dialogs.
7  *
8  * This file is part of
9  * ======================================================
10  *
11  *           LyX, The Document Processor
12  *
13  *           Copyright 1995 Matthias Ettrich
14  *           Copyright 1995-2001 The LyX Team.
15  *
16  *           This file Copyright 2000
17  *           Allan Rae
18  * ======================================================
19  */
20
21 #ifndef BUTTONPOLICIES_H
22 #define BUTTONPOLICIES_H
23
24
25 #include <vector>
26 #include <boost/utility.hpp>
27
28 #include "support/LOstream.h"
29
30 /** An abstract base class for button policies.
31     A state machine implementation of the various button policies used by the
32     dialogs. Only the policy is implemented here.  Separate ButtonController
33     classes are needed for each GUI implementation.
34
35                 Policy          | ReadOnly | Apply Button | Repeated Apply
36     ========================================================================
37     OkCancel                    |       N  |    N         |     -
38     OkCancelReadOnly            |       Y  |    N         |     -
39     OkApplyCancel               |       N  |    Y         |     Y
40     OkApplyCancelReadOnly       |       Y  |    Y         |     Y
41     NoRepeatedApply             |       N  |    Y         |     N
42     NoRepeatedApplyReadOnly     |       Y  |    Y         |     N
43     Preferences                 |       N  |    Y         | No (Ok-Close)
44     Ignorant                    |      N/A |    N/A       |    N/A
45     ========================================================================
46
47     Policy
48         The name of the policy
49     ReadOnly
50         Does the policy treat read-only docs differently to read-write docs?
51         This usually means that when an SMI_READ_ONLY input arrives then
52         all the buttons are disabled except Cancel/Close.  The state
53         machine tracks the inputs (valid/invalid) and has states for all
54         combinations. When an SMI_READ_WRITE input arrives the appropriate
55         machine state is entered (just as if the document had always been
56         read-write).
57         NOTE: If a dialog doesn't care about the read-only status of a document
58         (and uses an appropriate policy) it can never get into a read-only state
59         so isReadOnly() can only ever return false even though the document may
60         be read-only.
61     Repeated Apply
62         Simply means that it is alright to use the Apply button multiple times
63         without requiring a change of the dialog contents.  If no repeating is
64         allowed the Ok+Apply buttons are deactivated.  The Preferences dialog
65         has its own special version of repeated apply handling because its Ok
66         button is actually a Save button -- its always reasonable to Save the
67         preferences if the dialog has changed since the last save.
68
69     The IgnorantPolicy is a special case that allows anything.
70  */
71 class ButtonPolicy : public boost::noncopyable {
72 public:
73         ///
74         virtual ~ButtonPolicy() {}
75
76         /** The various possible state names.
77             Not all state-machines have this many states.  However, we need
78             to define them all here so we can share the code.
79         */
80         enum State {
81                 ///
82                 INITIAL = 0,
83                 ///
84                 VALID,
85                 ///
86                 INVALID,
87                 ///
88                 APPLIED,
89                 ///
90                 RO_INITIAL,
91                 ///
92                 RO_VALID,
93                 ///
94                 RO_INVALID,
95                 ///
96                 RO_APPLIED,
97                 ///
98                 BOGUS = 55
99         };
100         
101         /// The various button types.
102         enum Button {
103                 ///
104                 CLOSE    = 0,  // Not a real button, but effectively !CANCEL
105                 ///
106                 OKAY     = 1,
107                 ///
108                 APPLY    = 2,
109                 ///
110                 CANCEL   = 4,
111                 ///
112                 UNDO_ALL = 8
113         };
114         ///
115         static const Button ALL_BUTTONS =
116                 Button(OKAY | APPLY | CANCEL | UNDO_ALL);
117   
118         /** State machine inputs.
119             All the policies so far have both CANCEL and HIDE always going to
120             INITIAL. This won't necessarily be true for all [future] policies
121             though so I'll leave those two as distinct inputs rather than merge
122             them.  For example, a dialog that doesn't update it's input fields
123             when reshown after being hidden needs a policy where CANCEL and
124             HIDE are treated differently.
125          */
126         enum SMInput {
127                 ///
128                 SMI_VALID = 0,
129                 ///
130                 SMI_INVALID,
131                 ///
132                 SMI_OKAY,
133                 ///
134                 SMI_APPLY,
135                 ///
136                 SMI_CANCEL,
137                 ///
138                 SMI_UNDO_ALL,
139                 ///
140                 SMI_HIDE,
141                 ///
142                 SMI_READ_ONLY,
143                 ///
144                 SMI_READ_WRITE,
145                 ///
146                 SMI_NOOP,
147                 ///
148                 SMI_TOTAL       // not a real input
149         };
150
151         /// Trigger a transition with this input.
152         virtual void input(SMInput) = 0;
153         /// Activation status of a button
154         virtual bool buttonStatus(Button) const = 0;
155         /// Are we in a read-only state?
156         virtual bool isReadOnly() const = 0;
157
158         /// Transition map of the state machine.
159         typedef std::vector<State> StateArray;
160         ///
161         typedef std::vector<StateArray> StateMachine;
162         /// The state outputs are the status of the buttons.
163         typedef std::vector<int> StateOutputs;
164 };
165
166
167 inline
168 std::ostream & operator<<(std::ostream & os, ButtonPolicy::State st)
169 {
170         os << int(st);
171         return os;
172 }
173
174
175 inline
176 std::ostream & operator<<(std::ostream & os, ButtonPolicy::SMInput smi)
177 {
178         os << int(smi);
179         return os;
180 }
181
182
183 //--------------------- Actual Policy Classes -----------------------------
184
185 /** Ok and Cancel buttons for dialogs with read-only operation.
186     Note: This scheme supports the relabelling of Cancel to Close and
187     vice versa.
188     This is based on the value of the bool state of the Button::CANCEL.
189     true == Cancel, false == Close
190  */
191 class OkCancelPolicy : public ButtonPolicy {
192 public:
193         ///
194         OkCancelPolicy();
195         ///
196         //virtual ~OkCancelPolicy() {}
197         
198         /// Trigger a transition with this input.
199         virtual void input(SMInput);
200         /** Activation status of a button.
201             We assume that we haven't gotten into an undefined state.
202             This is reasonable since we can only reach states defined
203             in the state machine and they should all have been defined in
204             the outputs_ variable.  Perhaps we can do something at compile
205             time to check that all the states have corresponding outputs.
206          */
207         virtual bool buttonStatus(Button button) const {
208                 return button & outputs_[state_];
209         }
210         /// Are we in a read-only state?
211         virtual bool isReadOnly() const {
212                 return false;
213         }
214 private:
215         /// Current state.
216         State state_;
217         /// Which buttons are active for a given state.
218         StateOutputs outputs_;
219         ///
220         StateMachine state_machine_;
221 };
222
223 /** Ok and Cancel buttons for dialogs where read-only operation is blocked.
224     The state machine design for this policy allows changes to occur within
225     the dialog while a file is read-only -- the okay button is disabled until
226     a read-write input is given.  When the file is made read-write the dialog
227     will then be in the correct state (as if the file had always been
228     read-write).
229     Note: This scheme supports the relabelling of Cancel to Close
230     and vice versa.
231     This is based on the value of the bool state of the Button::CANCEL.
232     true == Cancel, false == Close
233  */
234 class OkCancelReadOnlyPolicy : public ButtonPolicy {
235 public:
236         ///
237         OkCancelReadOnlyPolicy();
238         ///
239         //virtual ~OkCancelReadOnlyPolicy() {}
240         
241         /// Trigger a transition with this input.
242         virtual void input(SMInput);
243         /// Activation status of a button.
244         virtual bool buttonStatus(Button button) const {
245                 return button & outputs_[state_];
246         }
247         /// Are we in a read-only state?
248         virtual bool isReadOnly() const {
249                 return RO_INITIAL == state_
250                         || RO_VALID == state_
251                         || RO_INVALID == state_
252                         || RO_APPLIED == state_;
253         }
254 private:
255         /// Current state.
256         State state_;
257         /// Which buttons are active for a given state.
258         StateOutputs outputs_;
259         ///
260         StateMachine state_machine_;
261 };
262
263
264 /** Ok, Apply and Cancel buttons for dialogs where read-only operation
265     is blocked.
266     Repeated Apply are not allowed.  Likewise,  Ok cannot follow Apply without
267     some valid input. That is, the dialog contents must change between
268     each Apply or Apply and Ok.
269     The state machine design for this policy allows changes to occur within
270     the dialog while a file is read-only -- the Ok+Apply buttons are disabled
271     until a read-write input is given.  When the file is made read-write the
272     dialog will then be in the correct state (as if the file had always been
273     read-write).
274     Note: This scheme supports the relabelling of Cancel to Close
275     and vice versa.
276     This is based on the value of the bool state of the Button::CANCEL.
277     true == Cancel, false == Close
278  */
279 class NoRepeatedApplyReadOnlyPolicy : public ButtonPolicy
280 {
281 public:
282         ///
283         NoRepeatedApplyReadOnlyPolicy();
284         ///
285         //virtual ~NoRepeatedApplyReadOnlyPolicy() {}
286         
287         /// Trigger a transition with this input.
288         virtual void input(SMInput);
289         /// Activation status of a button.
290         virtual bool buttonStatus(Button button) const {
291                 return button & outputs_[state_];
292         }
293         /// Are we in a read-only state?
294         virtual bool isReadOnly() const {
295                 return RO_INITIAL == state_
296                         || RO_VALID == state_
297                         || RO_INVALID == state_
298                         || RO_APPLIED == state_;
299         }
300 private:
301         /// Current state.
302         State state_;
303         /// Which buttons are active for a given state.
304         StateOutputs outputs_;
305         ///
306         StateMachine state_machine_;
307 };
308
309
310 /** Ok, Apply and Cancel buttons for dialogs where read-only
311     operation is blocked.
312     Repeated Apply is allowed.  Likewise,  Ok can follow Apply.
313     The state machine design for this policy allows changes to occur within
314     the dialog while a file is read-only -- the Ok+Apply buttons are disabled
315     until a read-write input is given.  When the file is made read-write the
316     dialog will then be in the correct state (as if the file had always been
317     read-write).
318     Note: This scheme supports the relabelling of Cancel to Close
319     and vice versa.
320     This is based on the value of the bool state of the Button::CANCEL.
321     true == Cancel, false == Close
322  */
323 class OkApplyCancelReadOnlyPolicy : public ButtonPolicy {
324 public:
325         ///
326         OkApplyCancelReadOnlyPolicy();
327         ///
328         //virtual ~OkApplyCancelReadOnlyPolicy() {}
329         
330         /// Trigger a transition with this input.
331         virtual void input(SMInput);
332         /// Activation status of a button.
333         virtual bool buttonStatus(Button button) const {
334                 return button & outputs_[state_];
335         }
336         /// Are we in a read-only state?
337         virtual bool isReadOnly() const {
338                 return RO_INITIAL == state_
339                         || RO_VALID == state_
340                         || RO_INVALID == state_
341                         || RO_APPLIED == state_;
342         }
343 private:
344         /// Current state.
345         State state_;
346         /// Which buttons are active for a given state.
347         StateOutputs outputs_;
348         ///
349         StateMachine state_machine_;
350 };
351
352
353 /** Ok, Apply and Cancel buttons for dialogs where repeated Apply is allowed.
354     Note: This scheme supports the relabelling of Cancel to Close
355     and vice versa.
356     This is based on the value of the bool state of the Button::CANCEL.
357     true == Cancel, false == Close
358  */
359 class OkApplyCancelPolicy : public ButtonPolicy {
360 public:
361         ///
362         OkApplyCancelPolicy();
363         ///
364         //virtual ~OkApplyCancelPolicy() {}
365         
366         /// Trigger a transition with this input.
367         virtual void input(SMInput);
368         /// Activation status of a button.
369         virtual bool buttonStatus(Button button) const {
370                 return button & outputs_[state_];
371         }
372         /// Are we in a read-only state?
373         virtual bool isReadOnly() const {
374                 return false;
375         }
376 private:
377         /// Current state.
378         State state_;
379         /// Which buttons are active for a given state.
380         StateOutputs outputs_;
381         ///
382         StateMachine state_machine_;
383 };
384
385
386 /** Ok, Apply and Cancel buttons for dialogs with no repeated Apply.
387     Note: This scheme supports the relabelling of Cancel to Close
388     and vice versa.
389     This is based on the value of the bool state of the Button::CANCEL.
390     true == Cancel, false == Close
391  */
392 class NoRepeatedApplyPolicy : public ButtonPolicy {
393 public:
394         ///
395         NoRepeatedApplyPolicy();
396         ///
397         //virtual ~NoRepeatedApplyPolicy() {}
398         
399         /// Trigger a transition with this input.
400         virtual void input(SMInput);
401         /// Activation status of a button.
402         virtual bool buttonStatus(Button button) const {
403                 return button & outputs_[state_];
404         }
405         /// Are we in a read-only state?
406         virtual bool isReadOnly() const {
407                 return false;
408         }
409 private:
410         /// Current state.
411         State state_;
412         /// Which buttons are active for a given state.
413         StateOutputs outputs_;
414         ///
415         StateMachine state_machine_;
416 };
417
418
419 /** Defines the policy used by the Preferences dialog.
420     Four buttons: Ok (Save), Apply, Cancel/Close, Restore.
421     Note: This scheme supports the relabelling of Cancel to Close
422     and vice versa.
423     This is based on the value of the bool state of the Button::CANCEL.
424     true == Cancel, false == Close
425  */
426 class PreferencesPolicy : public ButtonPolicy {
427 public:
428         ///
429         PreferencesPolicy();
430         ///
431         //virtual ~PreferencesPolicy() {}
432         
433         /// Trigger a transition with this input.
434         virtual void input(SMInput);
435         /// Activation status of a button.
436         virtual bool buttonStatus(Button button) const {
437                 return button & outputs_[state_];
438         }
439         /// Are we in a read-only state?
440         virtual bool isReadOnly() const {
441                 return false;
442         }
443 private:
444         /// Current state.
445         State state_;
446         /// Which buttons are active for a given state.
447         StateOutputs outputs_;
448         ///
449         StateMachine state_machine_;
450 };
451
452
453 /** Defines the policy used by dialogs that are forced to support a button
454     controller when they either don't have a use for one or are not ready to
455     use one.  This may be useful when testing a new button policy but wishing
456     to minimise problems to users by supplying an anything-goes policy via a
457     preprocessor directive.
458  */
459 class IgnorantPolicy : public ButtonPolicy {
460 public:
461         //virtual ~IgnorantPolicy() {}
462         
463         /// Trigger a transition with this input.
464         virtual void input(SMInput) {}
465         /// Activation status of a button.
466         virtual bool buttonStatus(Button) const {
467                 return true;
468         }
469         /// Are we in a read-only state?
470         virtual bool isReadOnly() const {
471                 return false;
472         }
473 };
474
475 #endif