]> git.lyx.org Git - lyx.git/blob - src/frontends/ButtonPolicies.C
small changes to ButtonController usage
[lyx.git] / src / frontends / ButtonPolicies.C
1 // -*- C++ -*-
2 /* ButtonPolicies.C
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 #include <config.h>
20 #include "ButtonPolicies.h"
21 #include "debug.h"
22
23
24 // Helper function
25 inline void nextState(ButtonPolicy::State & state,
26                ButtonPolicy::SMInput in,
27                ButtonPolicy::StateMachine s_m,
28                char const * function_name = "nextState")
29 {
30         ButtonPolicy::State tmp = s_m[state][in];
31         if (ButtonPolicy::BOGUS != tmp) {
32                 state = tmp;
33         } else {
34                 lyxerr << function_name
35                        << ": No transition for input "
36                        << in
37                        << " from state "
38                        << state
39                        << std::endl;
40         }
41 }
42
43
44 /*-----------------------------PreferencesPolicy-----------------------------*/
45
46
47 PreferencesPolicy::PreferencesPolicy()
48         : state_(INITIAL),
49           outputs_(APPLIED+1,
50                    static_cast<int const &>(OKAY | APPLY | CANCEL | UNDO_ALL)),
51           state_machine_(APPLIED+1,
52                          StateArray(SMI_TOTAL,
53                                     static_cast<State const &>(BOGUS)))
54 {
55         // Build the state output map
56         outputs_[INITIAL] = CLOSE;
57         outputs_[VALID] = UNDO_ALL | OKAY | APPLY | CANCEL;
58         outputs_[INVALID] = UNDO_ALL | CANCEL;
59         outputs_[APPLIED] = OKAY | CLOSE;
60
61         // Build the state machine one state at a time
62         // NOTE:  Since CANCEL and HIDE always go to INITIAL they are
63         //        left out of the state machine and handled explicitly
64         //        in input().  This won't necessarily be true for all
65         //        policies though so I'll leave those two as distinct
66         //        inputs rather than merge them.  For example, a dialog
67         //        that doesn't update it's input fields when reshown
68         //        after being hidden needs a policy where CANCEL and
69         //        HIDE are treated differently.
70         //
71         // State::INITIAL
72         state_machine_[INITIAL][SMI_READ_ONLY] = INITIAL;
73         state_machine_[INITIAL][SMI_READ_WRITE] = INITIAL;
74         state_machine_[INITIAL][SMI_VALID] = VALID;
75         state_machine_[INITIAL][SMI_INVALID] = INVALID;
76         // State::VALID
77         state_machine_[VALID][SMI_VALID] = VALID;
78         state_machine_[VALID][SMI_READ_ONLY] = VALID;
79         state_machine_[VALID][SMI_READ_WRITE] = VALID;
80         state_machine_[VALID][SMI_INVALID] = INVALID;
81         state_machine_[VALID][SMI_APPLY] = APPLIED;
82         state_machine_[VALID][SMI_OKAY] = INITIAL;
83         state_machine_[VALID][SMI_UNDO_ALL] = INITIAL;
84         // State::INVALID
85         state_machine_[INVALID][SMI_VALID] = VALID;
86         state_machine_[INVALID][SMI_INVALID] = INVALID;
87         state_machine_[INVALID][SMI_READ_ONLY] = INVALID;
88         state_machine_[INVALID][SMI_READ_WRITE] = INVALID;
89         state_machine_[INVALID][SMI_UNDO_ALL] = INITIAL;
90         // State::APPLIED
91         state_machine_[APPLIED][SMI_VALID] = VALID;
92         state_machine_[APPLIED][SMI_INVALID] = INVALID;
93         state_machine_[APPLIED][SMI_OKAY] = INITIAL;
94         state_machine_[APPLIED][SMI_READ_ONLY] = APPLIED;
95         state_machine_[APPLIED][SMI_READ_WRITE] = APPLIED;
96 }
97
98
99 void PreferencesPolicy::input(SMInput input)
100 {
101         // CANCEL and HIDE always take us to INITIAL for all cases.
102         // Note that I didn't put that special case in the helper function
103         // because it doesn't belong there.  Some other 
104         // This is probably optimising for the wrong case since it occurs as the
105         // dialog will be hidden.  It would have saved a little memory in the
106         // state machine if I could have gotten map working. ARRae 20000813
107         if (SMI_CANCEL == input
108             || SMI_HIDE == input) {
109                 state_ = INITIAL;
110         } else {
111                 nextState(state_,
112                           input,
113                           state_machine_,
114                           "PreferencesPolicy");
115         }
116 }
117
118
119 /*-------------------------------OkCancelPolicy------------------------------*/
120
121
122 OkCancelPolicy::OkCancelPolicy()
123         : state_(INITIAL),
124           outputs_(INVALID+1,
125                    static_cast<int const &>(OKAY | APPLY | CANCEL | UNDO_ALL)),
126           state_machine_(INVALID+1,
127                          StateArray(SMI_TOTAL,
128                                     static_cast<State const &>(BOGUS)))
129 {
130         // Build the state output map
131         outputs_[INITIAL] = CLOSE;
132         outputs_[VALID] = OKAY | CANCEL;
133         outputs_[INVALID] = CANCEL;
134
135         // Build the state machine one state at a time
136         // NOTE:  Since CANCEL and HIDE always go to INITIAL they are
137         //        left out of the state machine and handled explicitly
138         //        in input()
139         //
140         // State::INITIAL
141         state_machine_[INITIAL][SMI_READ_ONLY] = INITIAL;
142         state_machine_[INITIAL][SMI_READ_WRITE] = INITIAL;
143         state_machine_[INITIAL][SMI_VALID] = VALID;
144         state_machine_[INITIAL][SMI_INVALID] = INVALID;
145         // State::VALID
146         state_machine_[VALID][SMI_VALID] = VALID;
147         state_machine_[VALID][SMI_READ_ONLY] = VALID;
148         state_machine_[VALID][SMI_READ_WRITE] = VALID;
149         state_machine_[VALID][SMI_INVALID] = INVALID;
150         state_machine_[VALID][SMI_OKAY] = INITIAL;
151         // State::INVALID
152         state_machine_[INVALID][SMI_VALID] = VALID;
153         state_machine_[INVALID][SMI_INVALID] = INVALID;
154         state_machine_[INVALID][SMI_READ_ONLY] = INVALID;
155         state_machine_[INVALID][SMI_READ_WRITE] = INVALID;
156 }
157
158
159
160 void OkCancelPolicy::input(SMInput input)
161 {
162         // CANCEL and HIDE always take us to INITIAL for all cases
163         if (SMI_CANCEL == input
164             || SMI_HIDE == input) {
165                 state_ = INITIAL;
166         } else {
167                 nextState(state_, input, state_machine_, "OkCancelPolicy");
168         }
169 }
170
171
172 /*---------------------------OkCancelReadOnlyPolicy-------------------------*/
173
174
175 OkCancelReadOnlyPolicy::OkCancelReadOnlyPolicy()
176         : state_(INITIAL),
177           outputs_(RO_INVALID+1,
178                    static_cast<int const &>(OKAY | APPLY | CANCEL | UNDO_ALL)),
179           state_machine_(RO_INVALID+1,
180                          StateArray(SMI_TOTAL,
181                                     static_cast<State const &>(BOGUS)))
182 {
183         // Build the state output map
184         outputs_[INITIAL] = CLOSE;
185         outputs_[VALID] = OKAY | CANCEL;
186         outputs_[INVALID] = CANCEL;
187         outputs_[RO_INITIAL] = CLOSE;
188         outputs_[RO_VALID] = CANCEL;
189         outputs_[RO_INVALID] = CANCEL;
190
191         // Build the state machine one state at a time
192         // NOTE:  Since CANCEL and HIDE always go to INITIAL they are
193         //        left out of the state machine and handled explicitly
194         //        in input()
195         //
196         // State::INITIAL
197         state_machine_[INITIAL][SMI_READ_WRITE] = INITIAL;
198         state_machine_[INITIAL][SMI_VALID] = VALID;
199         state_machine_[INITIAL][SMI_INVALID] = INVALID;
200         state_machine_[INITIAL][SMI_READ_ONLY] = RO_INITIAL;
201         // State::VALID
202         state_machine_[VALID][SMI_VALID] = VALID;
203         state_machine_[VALID][SMI_READ_WRITE] = VALID;
204         state_machine_[VALID][SMI_INVALID] = INVALID;
205         state_machine_[VALID][SMI_OKAY] = INITIAL;
206         state_machine_[VALID][SMI_READ_ONLY] = RO_VALID;
207         // State::INVALID
208         state_machine_[INVALID][SMI_INVALID] = INVALID;
209         state_machine_[INVALID][SMI_READ_WRITE] = INVALID;
210         state_machine_[INVALID][SMI_VALID] = VALID;
211         state_machine_[INVALID][SMI_READ_ONLY] = RO_INVALID;
212         // State::RO_INITIAL
213         state_machine_[RO_INITIAL][SMI_READ_ONLY] = RO_INITIAL;
214         state_machine_[RO_INITIAL][SMI_VALID] = RO_VALID;
215         state_machine_[RO_INITIAL][SMI_INVALID] = RO_INVALID;
216         state_machine_[RO_INITIAL][SMI_READ_WRITE] = INITIAL;
217         // State::RO_VALID
218         state_machine_[RO_VALID][SMI_VALID] = RO_VALID;
219         state_machine_[RO_VALID][SMI_READ_ONLY] = RO_VALID;
220         state_machine_[RO_VALID][SMI_INVALID] = RO_INVALID;
221         state_machine_[RO_VALID][SMI_READ_WRITE] = VALID;
222         // State::RO_INVALID
223         state_machine_[RO_INVALID][SMI_READ_ONLY] = RO_INVALID;
224         state_machine_[RO_INVALID][SMI_INVALID] = RO_INVALID;
225         state_machine_[RO_INVALID][SMI_VALID] = RO_VALID;
226         state_machine_[RO_INVALID][SMI_READ_WRITE] = INVALID;
227 }
228
229
230 void OkCancelReadOnlyPolicy::input(SMInput input)
231 {
232         // CANCEL and HIDE always take us to INITIAL for all cases
233         if (SMI_CANCEL == input
234             || SMI_HIDE == input) {
235                 state_ = INITIAL;
236         } else {
237                 nextState(state_,
238                           input,
239                           state_machine_,
240                           "OkCancelReadOnlyPolicy");
241         }
242 }
243
244
245 /*--------------------------NoRepeatedApplyReadOnlyPolicy----------------------*/
246
247
248 NoRepeatedApplyReadOnlyPolicy::NoRepeatedApplyReadOnlyPolicy()
249         : state_(INITIAL),
250           outputs_(RO_INVALID+1,
251                    static_cast<int const &>(OKAY | APPLY | CANCEL | UNDO_ALL)),
252           state_machine_(RO_INVALID+1,
253                          StateArray(SMI_TOTAL,
254                                     static_cast<State const &>(BOGUS)))
255 {
256         // Build the state output map
257         outputs_[INITIAL] = CLOSE;
258         outputs_[VALID] = OKAY | APPLY | CANCEL;
259         outputs_[INVALID] = CANCEL;
260         outputs_[RO_INITIAL] = CLOSE;
261         outputs_[RO_VALID] = CANCEL;
262         outputs_[RO_INVALID] = CANCEL;
263
264         // Build the state machine one state at a time
265         // NOTE:  Since CANCEL and HIDE always go to INITIAL they are
266         //        left out of the state machine and handled explicitly
267         //        in input()
268         //
269         // State::INITIAL
270         state_machine_[INITIAL][SMI_READ_WRITE] = INITIAL;
271         state_machine_[INITIAL][SMI_VALID] = VALID;
272         state_machine_[INITIAL][SMI_INVALID] = INVALID;
273         state_machine_[INITIAL][SMI_READ_ONLY] = RO_INITIAL;
274         // State::VALID
275         state_machine_[VALID][SMI_VALID] = VALID;
276         state_machine_[VALID][SMI_READ_WRITE] = VALID;
277         state_machine_[VALID][SMI_INVALID] = INVALID;
278         state_machine_[VALID][SMI_OKAY] = INITIAL;
279         state_machine_[VALID][SMI_APPLY] = INITIAL;
280         state_machine_[VALID][SMI_READ_ONLY] = RO_VALID;
281         // State::INVALID
282         state_machine_[INVALID][SMI_INVALID] = INVALID;
283         state_machine_[INVALID][SMI_READ_WRITE] = INVALID;
284         state_machine_[INVALID][SMI_VALID] = VALID;
285         state_machine_[INVALID][SMI_READ_ONLY] = RO_INVALID;
286         // State::RO_INITIAL
287         state_machine_[RO_INITIAL][SMI_READ_ONLY] = RO_INITIAL;
288         state_machine_[RO_INITIAL][SMI_VALID] = RO_VALID;
289         state_machine_[RO_INITIAL][SMI_INVALID] = RO_INVALID;
290         state_machine_[RO_INITIAL][SMI_READ_WRITE] = INITIAL;
291         // State::RO_VALID
292         state_machine_[RO_VALID][SMI_VALID] = RO_VALID;
293         state_machine_[RO_VALID][SMI_READ_ONLY] = RO_VALID;
294         state_machine_[RO_VALID][SMI_INVALID] = RO_INVALID;
295         state_machine_[RO_VALID][SMI_READ_WRITE] = VALID;
296         // State::RO_INVALID
297         state_machine_[RO_INVALID][SMI_INVALID] = RO_INVALID;
298         state_machine_[RO_INVALID][SMI_READ_ONLY] = RO_INVALID;
299         state_machine_[RO_INVALID][SMI_VALID] = RO_VALID;
300         state_machine_[RO_INVALID][SMI_READ_WRITE] = INVALID;
301 }
302
303
304 void NoRepeatedApplyReadOnlyPolicy::input(SMInput input)
305 {
306         // CANCEL and HIDE always take us to INITIAL for all cases
307         if (SMI_CANCEL == input
308             || SMI_HIDE == input) {
309                 state_ = INITIAL;
310         } else {
311                 nextState(state_,
312                           input,
313                           state_machine_,
314                           "NoRepeatedApplyReadOnlyPolicy");
315         }
316 }
317
318
319 /*--------------------------OkApplyCancelReadOnlyPolicy----------------------*/
320
321
322 OkApplyCancelReadOnlyPolicy::OkApplyCancelReadOnlyPolicy()
323         : state_(INITIAL),
324           outputs_(RO_APPLIED+1,
325                    static_cast<int const &>(OKAY | APPLY | CANCEL | UNDO_ALL)),
326           state_machine_(RO_APPLIED+1,
327                          StateArray(SMI_TOTAL,
328                                     static_cast<State const &>(BOGUS)))
329 {
330         // Build the state output map
331         outputs_[INITIAL] = CLOSE;
332         outputs_[VALID] = OKAY | APPLY | CANCEL;
333         outputs_[INVALID] = CANCEL;
334         outputs_[APPLIED] = OKAY | APPLY | CLOSE;
335         outputs_[RO_INITIAL] = CLOSE;
336         outputs_[RO_VALID] = CANCEL;
337         outputs_[RO_INVALID] = CANCEL;
338         outputs_[RO_APPLIED] = CANCEL;
339
340         // Build the state machine one state at a time
341         // NOTE:  Since CANCEL and HIDE always go to INITIAL they are
342         //        left out of the state machine and handled explicitly
343         //        in input()
344         //
345         // State::INITIAL
346         state_machine_[INITIAL][SMI_READ_WRITE] = INITIAL;
347         state_machine_[INITIAL][SMI_VALID] = VALID;
348         state_machine_[INITIAL][SMI_INVALID] = INVALID;
349         state_machine_[INITIAL][SMI_READ_ONLY] = RO_INITIAL;
350         // State::VALID
351         state_machine_[VALID][SMI_VALID] = VALID;
352         state_machine_[VALID][SMI_READ_WRITE] = VALID;
353         state_machine_[VALID][SMI_INVALID] = INVALID;
354         state_machine_[VALID][SMI_OKAY] = INITIAL;
355         state_machine_[VALID][SMI_APPLY] = APPLIED;
356         state_machine_[VALID][SMI_READ_ONLY] = RO_VALID;
357         // State::INVALID
358         state_machine_[INVALID][SMI_INVALID] = INVALID;
359         state_machine_[INVALID][SMI_READ_WRITE] = INVALID;
360         state_machine_[INVALID][SMI_VALID] = VALID;
361         state_machine_[INVALID][SMI_READ_ONLY] = RO_INVALID;
362         // State::APPLIED
363         state_machine_[APPLIED][SMI_APPLY] = APPLIED;
364         state_machine_[APPLIED][SMI_READ_WRITE] = APPLIED;
365         state_machine_[APPLIED][SMI_VALID] = VALID;
366         state_machine_[APPLIED][SMI_INVALID] = INVALID;
367         state_machine_[APPLIED][SMI_OKAY] = INITIAL;
368         state_machine_[APPLIED][SMI_READ_ONLY] = RO_APPLIED;
369         // State::RO_INITIAL
370         state_machine_[RO_INITIAL][SMI_READ_ONLY] = RO_INITIAL;
371         state_machine_[RO_INITIAL][SMI_VALID] = RO_VALID;
372         state_machine_[RO_INITIAL][SMI_INVALID] = RO_INVALID;
373         state_machine_[RO_INITIAL][SMI_READ_WRITE] = INITIAL;
374         // State::RO_VALID
375         state_machine_[RO_VALID][SMI_VALID] = RO_VALID;
376         state_machine_[RO_VALID][SMI_READ_ONLY] = RO_VALID;
377         state_machine_[RO_VALID][SMI_INVALID] = RO_INVALID;
378         state_machine_[RO_VALID][SMI_READ_WRITE] = VALID;
379         // State::RO_INVALID
380         state_machine_[RO_INVALID][SMI_INVALID] = RO_INVALID;
381         state_machine_[RO_INVALID][SMI_READ_ONLY] = RO_INVALID;
382         state_machine_[RO_INVALID][SMI_VALID] = RO_VALID;
383         state_machine_[RO_INVALID][SMI_READ_WRITE] = INVALID;
384         // State::RO_APPLIED
385         state_machine_[RO_APPLIED][SMI_READ_ONLY] = RO_APPLIED;
386         state_machine_[RO_APPLIED][SMI_INVALID] = RO_INVALID;
387         state_machine_[RO_APPLIED][SMI_VALID] = RO_VALID;
388         state_machine_[RO_APPLIED][SMI_READ_WRITE] = APPLIED;
389 }
390
391
392 void OkApplyCancelReadOnlyPolicy::input(SMInput input)
393 {
394         // CANCEL and HIDE always take us to INITIAL for all cases
395         if (SMI_CANCEL == input
396             || SMI_HIDE == input) {
397                 state_ = INITIAL;
398         } else {
399                 nextState(state_,
400                           input,
401                           state_machine_,
402                           "OkApplyCancelReadOnlyPolicy");
403         }
404 }
405
406
407 /*--------------------------OkApplyCancelPolicy----------------------*/
408
409
410 OkApplyCancelPolicy::OkApplyCancelPolicy()
411         : state_(INITIAL),
412           outputs_(APPLIED+1,
413                    static_cast<int const &>(OKAY | APPLY | CANCEL | UNDO_ALL)),
414           state_machine_(APPLIED+1,
415                          StateArray(SMI_TOTAL,
416                                     static_cast<State const &>(BOGUS)))
417 {
418         // Build the state output map
419         outputs_[INITIAL] = CLOSE;
420         outputs_[VALID] = OKAY | APPLY | CANCEL;
421         outputs_[INVALID] = CANCEL;
422         outputs_[APPLIED] = OKAY | APPLY | CLOSE;
423
424         // Build the state machine one state at a time
425         // NOTE:  Since CANCEL and HIDE always go to INITIAL they are
426         //        left out of the state machine and handled explicitly
427         //        in input()
428         //
429         // State::INITIAL
430         state_machine_[INITIAL][SMI_READ_ONLY] = INITIAL;
431         state_machine_[INITIAL][SMI_READ_WRITE] = INITIAL;
432         state_machine_[INITIAL][SMI_VALID] = VALID;
433         state_machine_[INITIAL][SMI_INVALID] = INVALID;
434         // State::VALID
435         state_machine_[VALID][SMI_VALID] = VALID;
436         state_machine_[VALID][SMI_READ_ONLY] = VALID;
437         state_machine_[VALID][SMI_READ_WRITE] = VALID;
438         state_machine_[VALID][SMI_INVALID] = INVALID;
439         state_machine_[VALID][SMI_OKAY] = INITIAL;
440         state_machine_[VALID][SMI_APPLY] = APPLIED;
441         // State::INVALID
442         state_machine_[INVALID][SMI_INVALID] = INVALID;
443         state_machine_[INVALID][SMI_READ_ONLY] = INVALID;
444         state_machine_[INVALID][SMI_READ_WRITE] = INVALID;
445         state_machine_[INVALID][SMI_VALID] = VALID;
446         // State::APPLIED
447         state_machine_[APPLIED][SMI_APPLY] = APPLIED;
448         state_machine_[APPLIED][SMI_READ_ONLY] = APPLIED;
449         state_machine_[APPLIED][SMI_READ_WRITE] = APPLIED;
450         state_machine_[APPLIED][SMI_VALID] = VALID;
451         state_machine_[APPLIED][SMI_INVALID] = INVALID;
452         state_machine_[APPLIED][SMI_OKAY] = INITIAL;
453 }
454
455
456 void OkApplyCancelPolicy::input(SMInput input)
457 {
458         // CANCEL and HIDE always take us to INITIAL for all cases
459         if (SMI_CANCEL == input
460             || SMI_HIDE == input) {
461                 state_ = INITIAL;
462         } else {
463                 nextState(state_,
464                           input,
465                           state_machine_,
466                           "OkApplyCancelPolicy");
467         }
468 }
469
470
471 /*--------------------------NoRepeatedApplyPolicy----------------------*/
472
473
474 NoRepeatedApplyPolicy::NoRepeatedApplyPolicy()
475         : state_(INITIAL),
476           outputs_(INVALID+1,
477                    static_cast<int const &>(OKAY | APPLY | CANCEL | UNDO_ALL)),
478           state_machine_(INVALID+1,
479                          StateArray(SMI_TOTAL,
480                                     static_cast<State const &>(BOGUS)))
481 {
482         // Build the state output map
483         outputs_[INITIAL] = CLOSE;
484         outputs_[VALID] = OKAY | APPLY | CANCEL;
485         outputs_[INVALID] = CANCEL;
486
487         // Build the state machine one state at a time
488         // NOTE:  Since CANCEL and HIDE always go to INITIAL they are
489         //        left out of the state machine and handled explicitly
490         //        in input()
491         //
492         // State::INITIAL
493         state_machine_[INITIAL][SMI_READ_ONLY] = INITIAL;
494         state_machine_[INITIAL][SMI_READ_WRITE] = INITIAL;
495         state_machine_[INITIAL][SMI_VALID] = VALID;
496         state_machine_[INITIAL][SMI_INVALID] = INVALID;
497         // State::VALID
498         state_machine_[VALID][SMI_VALID] = VALID;
499         state_machine_[VALID][SMI_READ_ONLY] = VALID;
500         state_machine_[VALID][SMI_READ_WRITE] = VALID;
501         state_machine_[VALID][SMI_INVALID] = INVALID;
502         state_machine_[VALID][SMI_OKAY] = INITIAL;
503         state_machine_[VALID][SMI_APPLY] = INITIAL;
504         // State::INVALID
505         state_machine_[INVALID][SMI_INVALID] = INVALID;
506         state_machine_[INVALID][SMI_READ_ONLY] = INVALID;
507         state_machine_[INVALID][SMI_READ_WRITE] = INVALID;
508         state_machine_[INVALID][SMI_VALID] = VALID;
509 }
510
511
512 void NoRepeatedApplyPolicy::input(SMInput input)
513 {
514         // CANCEL and HIDE always take us to INITIAL for all cases
515         if (SMI_CANCEL == input
516             || SMI_HIDE == input) {
517                 state_ = INITIAL;
518         } else {
519                 nextState(state_,
520                           input,
521                           state_machine_,
522                           "NoRepeatedApplyPolicy");
523         }
524 }