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