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