]> git.lyx.org Git - lyx.git/blob - src/frontends/ButtonPolicy.h
Move Color::color enum to ColorCode.h
[lyx.git] / src / frontends / ButtonPolicy.h
1 // -*- C++ -*-
2 /**
3  * \file ButtonPolicy.h
4  * This file is part of LyX, the document processor.
5  * Licence details can be found in the file COPYING.
6  *
7  * \author Allan Rae
8  *
9  * Full author contact details are available in file CREDITS.
10  *
11  * Provides a state machine implementation of the various button policies
12  * used by the dialogs.
13  */
14
15 #ifndef BUTTONPOLICY_H
16 #define BUTTONPOLICY_H
17
18 #include <vector>
19 #include <iostream>
20
21 namespace lyx {
22 namespace frontend {
23
24 /** A class for button policies.
25     A state machine implementation of the various button policies used by the
26     dialogs. Only the policy is implemented here.  Separate ButtonController
27     classes are needed for each GUI implementation.
28
29                 Policy                    | ReadOnly | Apply Button | Repeated Apply
30     ========================================================================
31     OkCancel                  |     N    |      N        |      -
32     OkCancelReadOnly          |     Y    |      N        |      -
33     OkApplyCancel             |     N    |      Y        |      Y
34     OkApplyCancelReadOnly     |     Y    |      Y        |      Y
35     NoRepeatedApply           |     N    |      Y        |      N
36     NoRepeatedApplyReadOnly   |     Y    |      Y        |      N
37     Preferences               |     N    |      Y        | No (Ok-Close)
38     Ignorant                  |    N/A   |     N/A       |     N/A
39     ========================================================================
40
41     Policy
42         The name of the policy
43     ReadOnly
44         Does the policy treat read-only docs differently to read-write docs?
45         This usually means that when an SMI_READ_ONLY input arrives then
46         all the buttons are disabled except Cancel/Close.  The state
47         machine tracks the inputs (valid/invalid) and has states for all
48         combinations. When an SMI_READ_WRITE input arrives the appropriate
49         machine state is entered (just as if the document had always been
50         read-write).
51         NOTE: If a dialog doesn't care about the read-only status of a document
52         (and uses an appropriate policy) it can never get into a read-only state
53         so isReadOnly() can only ever return false even though the document may
54         be read-only.
55     Repeated Apply
56         Simply means that it is alright to use the Apply button multiple times
57         without requiring a change of the dialog contents.  If no repeating is
58         allowed the Ok+Apply buttons are deactivated.  The Preferences dialog
59         has its own special version of repeated apply handling because its Ok
60         button is actually a Save button -- it is always reasonable to Save the
61         preferences if the dialog has changed since the last save.
62
63     The IgnorantPolicy is a special case that allows anything.
64  */
65
66 class ButtonPolicy {
67 public:
68
69         // The various poicies
70         enum Policy { 
71                 /** Ok and Cancel buttons for dialogs with read-only operation.
72                         Note: This scheme supports the relabelling of Cancel to Close and
73                         vice versa.
74                         This is based on the value of the bool state of the Button::CANCEL.
75                         true == Cancel, false == Close
76                  */
77     OkCancelPolicy,
78
79
80                 /** Ok and Cancel buttons for dialogs where read-only operation is blocked.
81                         The state machine design for this policy allows changes to occur within
82                         the dialog while a file is read-only -- the okay button is disabled until
83                         a read-write input is given.  When the file is made read-write the dialog
84                         will then be in the correct state (as if the file had always been
85                         read-write).
86                         Note: This scheme supports the relabelling of Cancel to Close
87                         and vice versa.
88                         This is based on the value of the bool state of the Button::CANCEL.
89                         true == Cancel, false == Close
90                  */
91                 OkCancelReadOnlyPolicy,
92
93                 /** Ok, Apply and Cancel buttons for dialogs where read-only operation
94                         is blocked.
95                         Repeated Apply are not allowed.  Likewise,  Ok cannot follow Apply without
96                         some valid input. That is, the dialog contents must change between
97                         each Apply or Apply and Ok.
98                         The state machine design for this policy allows changes to occur within
99                         the dialog while a file is read-only -- the Ok+Apply buttons are disabled
100                         until a read-write input is given.  When the file is made read-write the
101                         dialog will then be in the correct state (as if the file had always been
102                         read-write).
103                         Note: This scheme supports the relabelling of Cancel to Close
104                         and vice versa.
105                         This is based on the value of the bool state of the Button::CANCEL.
106                         true == Cancel, false == Close
107                  */
108                 NoRepeatedApplyReadOnlyPolicy,
109
110                 /** Ok, Apply and Cancel buttons for dialogs where read-only
111                         operation is blocked.
112                         Repeated Apply is allowed.  Likewise,  Ok can follow Apply.
113                         The state machine design for this policy allows changes to occur within
114                         the dialog while a file is read-only -- the Ok+Apply buttons are disabled
115                         until a read-write input is given.  When the file is made read-write the
116                         dialog will then be in the correct state (as if the file had always been
117                         read-write).
118                         Note: This scheme supports the relabelling of Cancel to Close
119                         and vice versa.
120                         This is based on the value of the bool state of the Button::CANCEL.
121                         true == Cancel, false == Close
122                  */
123                 OkApplyCancelReadOnlyPolicy,
124
125                 /** Ok, Apply and Cancel buttons for dialogs where repeated
126  *    Apply is allowed.
127                         Note: This scheme supports the relabelling of Cancel to Close
128                         and vice versa.
129                         This is based on the value of the bool state of the Button::CANCEL.
130                         true == Cancel, false == Close
131                  */
132                 OkApplyCancelPolicy,
133
134                 /** Ok, Apply and Cancel buttons for dialogs with no repeated Apply.
135                         Note: This scheme supports the relabelling of Cancel to Close
136                         and vice versa.
137                         This is based on the value of the bool state of the Button::CANCEL.
138                         true == Cancel, false == Close
139                  */
140                 NoRepeatedApplyPolicy,
141
142                 /** Defines the policy used by the Preferences dialog.
143                         Four buttons: Ok (Save), Apply, Cancel/Close, Restore.
144                         Note: This scheme supports the relabelling of Cancel to Close
145                         and vice versa.
146                         This is based on the value of the bool state of the Button::CANCEL.
147                         true == Cancel, false == Close
148                  */
149                 PreferencesPolicy,
150
151                 /** Defines the policy used by dialogs that are forced to support a button
152                         controller when they either don't have a use for one or are not ready to
153                         use one.  This may be useful when testing a new button policy but wishing
154                         to minimise problems to users by supplying an anything-goes policy via a
155                         preprocessor directive.
156                  */
157                 IgnorantPolicy,
158         };
159
160         /// Constructor
161         explicit ButtonPolicy(Policy policy);
162
163         /** The various possible state names.
164             Not all state-machines have this many states.  However, we need
165             to define them all here so we can share the code.
166         */
167         enum State {
168                 ///
169                 INITIAL = 0,
170                 ///
171                 VALID,
172                 ///
173                 INVALID,
174                 ///
175                 APPLIED,
176                 ///
177                 RO_INITIAL,
178                 ///
179                 RO_VALID,
180                 ///
181                 RO_INVALID,
182                 ///
183                 RO_APPLIED,
184                 ///
185                 BOGUS = 55
186         };
187
188         /// The various button types.
189         enum Button {
190                 ///
191                 CLOSE    = 0,  // Not a real button, but effectively !CANCEL
192                 ///
193                 OKAY     = 1,
194                 ///
195                 APPLY    = 2,
196                 ///
197                 CANCEL   = 4,
198                 ///
199                 RESTORE  = 8
200         };
201         ///
202         static const Button ALL_BUTTONS =
203                 Button(OKAY | APPLY | CANCEL | RESTORE);
204
205         /** State machine inputs.
206             All the policies so far have both CANCEL and HIDE always going to
207             INITIAL. This won't necessarily be true for all [future] policies
208             though so I'll leave those two as distinct inputs rather than merge
209             them.  For example, a dialog that doesn't update it's input fields
210             when reshown after being hidden needs a policy where CANCEL and
211             HIDE are treated differently.
212          */
213         enum SMInput {
214                 /// the dialog contents are now valid
215                 SMI_VALID = 0,
216                 /// the dialog contents are now invalid
217                 SMI_INVALID,
218                 /// an apply-and-hide action has happened
219                 SMI_OKAY,
220                 /// an apply action has happened
221                 SMI_APPLY,
222                 /// a cancel action has happened
223                 SMI_CANCEL,
224                 /// a restore action has happened
225                 SMI_RESTORE,
226                 /// the dialog has been hidden
227                 SMI_HIDE,
228                 /// the dialog contents are read-only
229                 SMI_READ_ONLY,
230                 /// the dialog contents can be modified
231                 SMI_READ_WRITE,
232                 /// the state of the dialog contents has not changed
233                 SMI_NOOP,
234                 /// for internal use
235                 SMI_TOTAL
236         };
237
238         /// Trigger a transition with this input.
239         void input(SMInput);
240         /** Activation status of a button.
241             We assume that we haven't gotten into an undefined state.
242             This is reasonable since we can only reach states defined
243             in the state machine and they should all have been defined in
244             the outputs_ variable.  Perhaps we can do something at compile
245             time to check that all the states have corresponding outputs.
246          */
247         bool buttonStatus(Button) const;
248         /// Are we in a read-only state?
249         bool isReadOnly() const;
250
251 private:
252         ///
253         Policy policy_;
254
255         /// Transition map of the state machine.
256         typedef std::vector<State> StateArray;
257         ///
258         typedef std::vector<StateArray> StateMachine;
259         /// The state outputs are the status of the buttons.
260         typedef std::vector<int> StateOutputs;
261
262         /// Current state.
263         State state_;
264         /// Which buttons are active for a given state.
265         StateOutputs outputs_;
266         ///
267         StateMachine state_machine_;
268
269 private:
270         // Helpers
271         void nextState(SMInput input);
272
273         void initOkCancel();
274         void initOkCancelReadOnly();
275         void initNoRepeatedApplyReadOnly();
276         void initOkApplyCancelReadOnly();
277         void initOkApplyCancel();
278         void initNoRepeatedApply();
279         void initPreferences();
280 };
281
282
283 inline
284 std::ostream & operator<<(std::ostream & os, ButtonPolicy::State st)
285 {
286         return os << int(st);
287 }
288
289
290 inline
291 std::ostream & operator<<(std::ostream & os, ButtonPolicy::SMInput smi)
292 {
293         return os << int(smi);
294 }
295
296
297 } // namespace frontend
298 } // namespace lyx
299
300 #endif