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