]> git.lyx.org Git - lyx.git/blob - src/frontends/ButtonPolicies.h
Move LaTeX and VC logs to GUI-I on xforms
[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 /** OK button policy for dialogs that can't mutate the document,
220     and are always valid
221  */ 
222 class OkViewPolicy : public ButtonPolicy {
223 public:
224         ///
225         OkViewPolicy();
226         /// Trigger a transition with this input
227         virtual void input(SMInput);
228         /// activation status
229         virtual bool buttonStatus(Button button) const {
230                 return button & outputs_[state_];
231         }
232         /// are we in a read-only state ?
233         virtual bool isReadOnly() const { 
234                 return false;
235         }
236 private:
237         /// current state
238         State state_;
239         /// which buttons are active
240         StateOutputs outputs_;
241         ///
242         StateMachine state_machine_;
243 };
244  
245 /** Ok and Cancel buttons for dialogs where read-only operation is blocked.
246     The state machine design for this policy allows changes to occur within
247     the dialog while a file is read-only -- the okay button is disabled until
248     a read-write input is given.  When the file is made read-write the dialog
249     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
252     and vice versa.
253     This is based on the value of the bool state of the Button::CANCEL.
254     true == Cancel, false == Close
255  */
256 class OkCancelReadOnlyPolicy : public ButtonPolicy {
257 public:
258         ///
259         OkCancelReadOnlyPolicy();
260         ///
261         //virtual ~OkCancelReadOnlyPolicy() {}
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
287     is blocked.
288     Repeated Apply are not allowed.  Likewise,  Ok cannot follow Apply without
289     some valid input. That is, the dialog contents must change between
290     each Apply or Apply and Ok.
291     The state machine design for this policy allows changes to occur within
292     the dialog while a file is read-only -- the Ok+Apply buttons are disabled
293     until a read-write input is given.  When the file is made read-write the
294     dialog will then be in the correct state (as if the file had always been
295     read-write).
296     Note: This scheme supports the relabelling of Cancel to Close
297     and vice versa.
298     This is based on the value of the bool state of the Button::CANCEL.
299     true == Cancel, false == Close
300  */
301 class NoRepeatedApplyReadOnlyPolicy : public ButtonPolicy
302 {
303 public:
304         ///
305         NoRepeatedApplyReadOnlyPolicy();
306         ///
307         //virtual ~NoRepeatedApplyReadOnlyPolicy() {}
308         
309         /// Trigger a transition with this input.
310         virtual void input(SMInput);
311         /// Activation status of a button.
312         virtual bool buttonStatus(Button button) const {
313                 return button & outputs_[state_];
314         }
315         /// Are we in a read-only state?
316         virtual bool isReadOnly() const {
317                 return RO_INITIAL == state_
318                         || RO_VALID == state_
319                         || RO_INVALID == state_
320                         || RO_APPLIED == state_;
321         }
322 private:
323         /// Current state.
324         State state_;
325         /// Which buttons are active for a given state.
326         StateOutputs outputs_;
327         ///
328         StateMachine state_machine_;
329 };
330
331
332 /** Ok, Apply and Cancel buttons for dialogs where read-only
333     operation is blocked.
334     Repeated Apply is allowed.  Likewise,  Ok can follow Apply.
335     The state machine design for this policy allows changes to occur within
336     the dialog while a file is read-only -- the Ok+Apply buttons are disabled
337     until a read-write input is given.  When the file is made read-write the
338     dialog will then be in the correct state (as if the file had always been
339     read-write).
340     Note: This scheme supports the relabelling of Cancel to Close
341     and vice versa.
342     This is based on the value of the bool state of the Button::CANCEL.
343     true == Cancel, false == Close
344  */
345 class OkApplyCancelReadOnlyPolicy : public ButtonPolicy {
346 public:
347         ///
348         OkApplyCancelReadOnlyPolicy();
349         ///
350         //virtual ~OkApplyCancelReadOnlyPolicy() {}
351         
352         /// Trigger a transition with this input.
353         virtual void input(SMInput);
354         /// Activation status of a button.
355         virtual bool buttonStatus(Button button) const {
356                 return button & outputs_[state_];
357         }
358         /// Are we in a read-only state?
359         virtual bool isReadOnly() const {
360                 return RO_INITIAL == state_
361                         || RO_VALID == state_
362                         || RO_INVALID == state_
363                         || RO_APPLIED == state_;
364         }
365 private:
366         /// Current state.
367         State state_;
368         /// Which buttons are active for a given state.
369         StateOutputs outputs_;
370         ///
371         StateMachine state_machine_;
372 };
373
374
375 /** Ok, Apply and Cancel buttons for dialogs where repeated Apply is allowed.
376     Note: This scheme supports the relabelling of Cancel to Close
377     and vice versa.
378     This is based on the value of the bool state of the Button::CANCEL.
379     true == Cancel, false == Close
380  */
381 class OkApplyCancelPolicy : public ButtonPolicy {
382 public:
383         ///
384         OkApplyCancelPolicy();
385         ///
386         //virtual ~OkApplyCancelPolicy() {}
387         
388         /// Trigger a transition with this input.
389         virtual void input(SMInput);
390         /// Activation status of a button.
391         virtual bool buttonStatus(Button button) const {
392                 return button & outputs_[state_];
393         }
394         /// Are we in a read-only state?
395         virtual bool isReadOnly() const {
396                 return false;
397         }
398 private:
399         /// Current state.
400         State state_;
401         /// Which buttons are active for a given state.
402         StateOutputs outputs_;
403         ///
404         StateMachine state_machine_;
405 };
406
407
408 /** Ok, Apply and Cancel buttons for dialogs with no repeated Apply.
409     Note: This scheme supports the relabelling of Cancel to Close
410     and vice versa.
411     This is based on the value of the bool state of the Button::CANCEL.
412     true == Cancel, false == Close
413  */
414 class NoRepeatedApplyPolicy : public ButtonPolicy {
415 public:
416         ///
417         NoRepeatedApplyPolicy();
418         ///
419         //virtual ~NoRepeatedApplyPolicy() {}
420         
421         /// Trigger a transition with this input.
422         virtual void input(SMInput);
423         /// Activation status of a button.
424         virtual bool buttonStatus(Button button) const {
425                 return button & outputs_[state_];
426         }
427         /// Are we in a read-only state?
428         virtual bool isReadOnly() const {
429                 return false;
430         }
431 private:
432         /// Current state.
433         State state_;
434         /// Which buttons are active for a given state.
435         StateOutputs outputs_;
436         ///
437         StateMachine state_machine_;
438 };
439
440
441 /** Defines the policy used by the Preferences dialog.
442     Four buttons: Ok (Save), Apply, Cancel/Close, Restore.
443     Note: This scheme supports the relabelling of Cancel to Close
444     and vice versa.
445     This is based on the value of the bool state of the Button::CANCEL.
446     true == Cancel, false == Close
447  */
448 class PreferencesPolicy : public ButtonPolicy {
449 public:
450         ///
451         PreferencesPolicy();
452         ///
453         //virtual ~PreferencesPolicy() {}
454         
455         /// Trigger a transition with this input.
456         virtual void input(SMInput);
457         /// Activation status of a button.
458         virtual bool buttonStatus(Button button) const {
459                 return button & outputs_[state_];
460         }
461         /// Are we in a read-only state?
462         virtual bool isReadOnly() const {
463                 return false;
464         }
465 private:
466         /// Current state.
467         State state_;
468         /// Which buttons are active for a given state.
469         StateOutputs outputs_;
470         ///
471         StateMachine state_machine_;
472 };
473
474
475 /** Defines the policy used by dialogs that are forced to support a button
476     controller when they either don't have a use for one or are not ready to
477     use one.  This may be useful when testing a new button policy but wishing
478     to minimise problems to users by supplying an anything-goes policy via a
479     preprocessor directive.
480  */
481 class IgnorantPolicy : public ButtonPolicy {
482 public:
483         //virtual ~IgnorantPolicy() {}
484         
485         /// Trigger a transition with this input.
486         virtual void input(SMInput) {}
487         /// Activation status of a button.
488         virtual bool buttonStatus(Button) const {
489                 return true;
490         }
491         /// Are we in a read-only state?
492         virtual bool isReadOnly() const {
493                 return false;
494         }
495 };
496
497 #endif