]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/ButtonPolicy.cpp
Complete the removal of the embedding stuff. Maybe. It's hard to be sure we got every...
[lyx.git] / src / frontends / qt4 / ButtonPolicy.cpp
1 /**
2  * \file ButtonPolicy.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Allan Rae
7  *
8  * Full author contact details are available in file CREDITS.
9  */
10
11 #include <config.h>
12
13 #include "ButtonPolicy.h"
14
15 #include "support/debug.h"
16
17 #include <iostream>
18 #include <vector>
19
20 using namespace std;
21
22 namespace lyx {
23 namespace frontend {
24
25 static char const * printState(ButtonPolicy::State const & state)
26 {
27         switch (state) {
28                 case ButtonPolicy::INITIAL:
29                         return "INITIAL";
30                 case ButtonPolicy::VALID:
31                         return "VALID";
32                 case ButtonPolicy::INVALID:
33                         return "INVALID";
34                 case ButtonPolicy::APPLIED:
35                         return "APPLIED";
36                 case ButtonPolicy::RO_INITIAL:
37                         return "RO_INITIAL";
38                 case ButtonPolicy::RO_VALID:
39                         return "RO_VALID";
40                 case ButtonPolicy::RO_INVALID:
41                         return "RO_INVALID";
42                 case ButtonPolicy::RO_APPLIED:
43                         return "RO_APPLIED";
44                 case ButtonPolicy::BOGUS:
45                         return "BOGUS";
46                 default:
47                         return "";
48         }
49 }
50
51
52 static char const * printInput(ButtonPolicy::SMInput const & input)
53 {
54         switch (input) {
55                 case ButtonPolicy::SMI_VALID:
56                         return "SMI_VALID";
57                 case ButtonPolicy::SMI_INVALID:
58                         return "SMI_INVALID";
59                 case ButtonPolicy::SMI_OKAY:
60                         return "SMI_OKAY";
61                 case ButtonPolicy::SMI_APPLY:
62                         return "SMI_APPLY";
63                 case ButtonPolicy::SMI_CANCEL:
64                         return "SMI_CANCEL";
65                 case ButtonPolicy::SMI_RESTORE:
66                         return "SMI_RESTORE";
67                 case ButtonPolicy::SMI_HIDE:
68                         return "SMI_HIDE";
69                 case ButtonPolicy::SMI_READ_ONLY:
70                         return "SMI_READ_ONLY";
71                 case ButtonPolicy::SMI_READ_WRITE:
72                         return "SMI_READ_WRITE";
73                 case ButtonPolicy::SMI_NOOP:
74                         return "SMI_NOOP";
75                 case ButtonPolicy::SMI_TOTAL:
76                         return "SMI_TOTAL";
77                 default:
78                         return "";
79         }
80 }
81
82
83 char const * functionName(ButtonPolicy::Policy policy)
84 {
85         switch (policy) {
86                 case ButtonPolicy::PreferencesPolicy:
87                         return "PreferencesPolicy";
88                 case ButtonPolicy::OkCancelPolicy:
89                         return "OkCancelPolicy";
90                 case ButtonPolicy::OkCancelReadOnlyPolicy:
91                         return "OkCancelReadOnlyPolicy";
92                 case ButtonPolicy::OkApplyCancelPolicy:
93                         return "OkApplyCancelPolicy";
94                 case ButtonPolicy::OkApplyCancelReadOnlyPolicy:
95                         return "OkApplyCancelReadOnlyPolicy";
96                 case ButtonPolicy::NoRepeatedApplyPolicy:
97                         return "NoRepeatedApplyPolicy";
98                 case ButtonPolicy::NoRepeatedApplyReadOnlyPolicy:
99                         return "NoRepeatedApplyReadOnlyPolicy";
100                 case ButtonPolicy::IgnorantPolicy:
101                         return "IgnorantPolicy";
102                 default:
103                         return "Unknown policy";
104         }
105 }
106
107
108 ostream & operator<<(ostream & os, ButtonPolicy::State st)
109 {
110         return os << int(st);
111 }
112
113
114 ostream & operator<<(ostream & os, ButtonPolicy::SMInput smi)
115 {
116         return os << int(smi);
117 }
118
119
120 /////////////////////////////////////////////////////////////////////////
121 //
122 // ButtonPolicy::Private
123 //
124 /////////////////////////////////////////////////////////////////////////
125
126 class ButtonPolicy::Private
127 {
128 public:
129         typedef ButtonPolicy::SMInput SMInput;
130         typedef ButtonPolicy::Policy Policy;
131         typedef ButtonPolicy::State State;
132
133         Private(Policy policy);
134
135         void nextState(SMInput input);
136
137         void initOkCancel();
138         void initOkCancelReadOnly();
139         void initNoRepeatedApplyReadOnly();
140         void initOkApplyCancelReadOnly();
141         void initOkApplyCancel();
142         void initNoRepeatedApply();
143         void initPreferences();
144
145 public:
146         ///
147         Policy policy_;
148
149         /// Transition map of the state machine.
150         typedef std::vector<State> StateArray;
151         ///
152         typedef std::vector<StateArray> StateMachine;
153         /// The state outputs are the status of the buttons.
154         typedef std::vector<int> StateOutputs;
155
156         /// Current state.
157         State state_;
158         /// Which buttons are active for a given state.
159         StateOutputs outputs_;
160         ///
161         StateMachine state_machine_;
162 };
163
164
165 ButtonPolicy::Private::Private(Policy policy)
166 {
167         policy_ = policy;
168         state_ = INITIAL;
169
170         switch (policy_) {
171                 case OkCancelPolicy:
172                         initOkCancel();
173                         break;
174                 case OkCancelReadOnlyPolicy:
175                         initOkCancelReadOnly();
176                         break;
177                 case OkApplyCancelPolicy:
178                         initOkApplyCancel();
179                         break;
180                 case OkApplyCancelReadOnlyPolicy:
181                         initOkApplyCancelReadOnly();
182                         break;
183                 case NoRepeatedApplyPolicy:
184                         initNoRepeatedApply();
185                         break;
186                 case NoRepeatedApplyReadOnlyPolicy:
187                         initNoRepeatedApplyReadOnly();
188                         break;
189                 case PreferencesPolicy:
190                         initPreferences();
191                         break;
192                 case IgnorantPolicy:
193                         break;
194         }
195 }
196
197
198 void ButtonPolicy::Private::nextState(SMInput input)
199 {
200         if (SMI_NOOP == input)
201                 return;
202
203         State tmp = state_machine_[state_][input];
204
205         LYXERR(Debug::GUI, "Transition from state "
206                            << printState(state_) << " to state "
207                            << printState(tmp) << " after input "
208                            << printInput(input));
209
210         if (tmp != BOGUS) {
211                 state_ = tmp;
212         } else {
213                 LYXERR0(functionName(policy_) << ": No transition for input "
214             << printInput(input) << " from state " << printState(state_));
215         }
216 }
217
218
219 void ButtonPolicy::Private::initPreferences()
220 {
221         outputs_ = StateOutputs(APPLIED + 1, ButtonPolicy::ALL_BUTTONS);
222         state_machine_ = StateMachine(APPLIED + 1,
223                          StateArray(int(SMI_TOTAL), ButtonPolicy::BOGUS));
224
225         // Build the state output map
226         outputs_[INITIAL] = CLOSE;
227         outputs_[VALID] = RESTORE | OKAY | APPLY | CANCEL;
228         outputs_[INVALID] = RESTORE | CANCEL;
229         outputs_[APPLIED] = OKAY | CLOSE;
230
231         // Build the state machine one state at a time
232         // NOTE:  Since CANCEL and HIDE always go to INITIAL they are
233         //        left out of the state machine and handled explicitly
234         //        in input().  This won't necessarily be true for all
235         //        policies though so I'll leave those two as distinct
236         //        inputs rather than merge them.  For example, a dialog
237         //        that doesn't update it's input fields when reshown
238         //        after being hidden needs a policy where CANCEL and
239         //        HIDE are treated differently.
240         //
241         // State::INITIAL
242         state_machine_[INITIAL][SMI_READ_ONLY] = INITIAL;
243         state_machine_[INITIAL][SMI_READ_WRITE] = INITIAL;
244         state_machine_[INITIAL][SMI_VALID] = VALID;
245         state_machine_[INITIAL][SMI_INVALID] = INVALID;
246         // State::VALID
247         state_machine_[VALID][SMI_VALID] = VALID;
248         state_machine_[VALID][SMI_READ_ONLY] = VALID;
249         state_machine_[VALID][SMI_READ_WRITE] = VALID;
250         state_machine_[VALID][SMI_INVALID] = INVALID;
251         state_machine_[VALID][SMI_APPLY] = APPLIED;
252         state_machine_[VALID][SMI_OKAY] = INITIAL;
253         state_machine_[VALID][SMI_RESTORE] = INITIAL;
254         // State::INVALID
255         state_machine_[INVALID][SMI_VALID] = VALID;
256         state_machine_[INVALID][SMI_INVALID] = INVALID;
257         state_machine_[INVALID][SMI_READ_ONLY] = INVALID;
258         state_machine_[INVALID][SMI_READ_WRITE] = INVALID;
259         state_machine_[INVALID][SMI_RESTORE] = INITIAL;
260         // State::APPLIED
261         state_machine_[APPLIED][SMI_VALID] = VALID;
262         state_machine_[APPLIED][SMI_INVALID] = INVALID;
263         state_machine_[APPLIED][SMI_OKAY] = INITIAL;
264         state_machine_[APPLIED][SMI_READ_ONLY] = APPLIED;
265         state_machine_[APPLIED][SMI_READ_WRITE] = APPLIED;
266 }
267
268
269 void ButtonPolicy::Private::initOkCancel()
270 {
271         outputs_ = StateOutputs(INVALID + 1, ButtonPolicy::ALL_BUTTONS);
272         state_machine_ = StateMachine(INVALID + 1,
273                          StateArray(int(SMI_TOTAL), ButtonPolicy::BOGUS));
274
275         // Build the state output map
276         outputs_[INITIAL] = CLOSE;
277         outputs_[VALID] = RESTORE | OKAY | CANCEL;
278         outputs_[INVALID] = RESTORE | CANCEL;
279
280         // Build the state machine one state at a time
281         // NOTE:  Since CANCEL and HIDE always go to INITIAL they are
282         //        left out of the state machine and handled explicitly
283         //        in input()
284         //
285         // State::INITIAL
286         state_machine_[INITIAL][SMI_READ_ONLY] = INITIAL;
287         state_machine_[INITIAL][SMI_READ_WRITE] = INITIAL;
288         state_machine_[INITIAL][SMI_VALID] = VALID;
289         state_machine_[INITIAL][SMI_INVALID] = INVALID;
290         // State::VALID
291         state_machine_[VALID][SMI_VALID] = VALID;
292         state_machine_[VALID][SMI_READ_ONLY] = VALID;
293         state_machine_[VALID][SMI_READ_WRITE] = VALID;
294         state_machine_[VALID][SMI_INVALID] = INVALID;
295         state_machine_[VALID][SMI_OKAY] = INITIAL;
296         state_machine_[VALID][SMI_RESTORE] = INITIAL;
297         // State::INVALID
298         state_machine_[INVALID][SMI_VALID] = VALID;
299         state_machine_[INVALID][SMI_INVALID] = INVALID;
300         state_machine_[INVALID][SMI_READ_ONLY] = INVALID;
301         state_machine_[INVALID][SMI_READ_WRITE] = INVALID;
302         state_machine_[INVALID][SMI_RESTORE] = INITIAL;
303 }
304
305
306 void ButtonPolicy::Private::initOkCancelReadOnly()
307 {
308         outputs_ = StateOutputs(RO_INVALID + 1, ButtonPolicy::ALL_BUTTONS);
309         state_machine_ = StateMachine(RO_INVALID + 1,
310                          StateArray(int(SMI_TOTAL), ButtonPolicy::BOGUS));
311
312         // Build the state output map
313         outputs_[INITIAL] = CLOSE;
314         outputs_[VALID] = RESTORE | OKAY | CANCEL;
315         outputs_[INVALID] = RESTORE | CANCEL;
316         outputs_[RO_INITIAL] = CLOSE;
317         outputs_[RO_VALID] = RESTORE | CANCEL;
318         outputs_[RO_INVALID] = RESTORE | CANCEL;
319
320         // Build the state machine one state at a time
321         // NOTE:  Since CANCEL and HIDE always go to INITIAL they are
322         //        left out of the state machine and handled explicitly
323         //        in input()
324         //
325         // State::INITIAL
326         state_machine_[INITIAL][SMI_READ_WRITE] = INITIAL;
327         state_machine_[INITIAL][SMI_VALID] = VALID;
328         state_machine_[INITIAL][SMI_INVALID] = INVALID;
329         state_machine_[INITIAL][SMI_READ_ONLY] = RO_INITIAL;
330         // State::VALID
331         state_machine_[VALID][SMI_VALID] = VALID;
332         state_machine_[VALID][SMI_READ_WRITE] = VALID;
333         state_machine_[VALID][SMI_INVALID] = INVALID;
334         state_machine_[VALID][SMI_OKAY] = INITIAL;
335         state_machine_[VALID][SMI_RESTORE] = INITIAL;
336         state_machine_[VALID][SMI_READ_ONLY] = RO_VALID;
337         // State::INVALID
338         state_machine_[INVALID][SMI_INVALID] = INVALID;
339         state_machine_[INVALID][SMI_READ_WRITE] = INVALID;
340         state_machine_[INVALID][SMI_VALID] = VALID;
341         state_machine_[INVALID][SMI_RESTORE] = INITIAL;
342         state_machine_[INVALID][SMI_READ_ONLY] = RO_INVALID;
343         // State::RO_INITIAL
344         state_machine_[RO_INITIAL][SMI_READ_ONLY] = RO_INITIAL;
345         state_machine_[RO_INITIAL][SMI_VALID] = RO_VALID;
346         state_machine_[RO_INITIAL][SMI_INVALID] = RO_INVALID;
347         state_machine_[RO_INITIAL][SMI_READ_WRITE] = INITIAL;
348         // State::RO_VALID
349         state_machine_[RO_VALID][SMI_VALID] = RO_VALID;
350         state_machine_[RO_VALID][SMI_READ_ONLY] = RO_VALID;
351         state_machine_[RO_VALID][SMI_INVALID] = RO_INVALID;
352         state_machine_[RO_VALID][SMI_READ_WRITE] = VALID;
353         state_machine_[RO_VALID][SMI_RESTORE] = RO_INITIAL;
354         // State::RO_INVALID
355         state_machine_[RO_INVALID][SMI_READ_ONLY] = RO_INVALID;
356         state_machine_[RO_INVALID][SMI_INVALID] = RO_INVALID;
357         state_machine_[RO_INVALID][SMI_VALID] = RO_VALID;
358         state_machine_[RO_INVALID][SMI_READ_WRITE] = INVALID;
359         state_machine_[RO_INVALID][SMI_RESTORE] = RO_INITIAL;
360 }
361
362
363 void ButtonPolicy::Private::initNoRepeatedApplyReadOnly()
364 {
365         outputs_ = StateOutputs(RO_INVALID + 1, ButtonPolicy::ALL_BUTTONS);
366         state_machine_ = StateMachine(RO_INVALID + 1,
367                          StateArray(int(SMI_TOTAL), ButtonPolicy::BOGUS));
368
369         // Build the state output map
370         outputs_[INITIAL] = CLOSE;
371         outputs_[VALID] = RESTORE | OKAY | APPLY | CANCEL;
372         outputs_[INVALID] = RESTORE | CANCEL;
373         outputs_[RO_INITIAL] = CLOSE;
374         outputs_[RO_VALID] = RESTORE | CANCEL;
375         outputs_[RO_INVALID] = RESTORE | CANCEL;
376
377         // Build the state machine one state at a time
378         // NOTE:  Since CANCEL and HIDE always go to INITIAL they are
379         //        left out of the state machine and handled explicitly
380         //        in input()
381         //
382         // State::INITIAL
383         state_machine_[INITIAL][SMI_READ_WRITE] = INITIAL;
384         state_machine_[INITIAL][SMI_VALID] = VALID;
385         state_machine_[INITIAL][SMI_INVALID] = INVALID;
386         state_machine_[INITIAL][SMI_READ_ONLY] = RO_INITIAL;
387         // State::VALID
388         state_machine_[VALID][SMI_VALID] = VALID;
389         state_machine_[VALID][SMI_READ_WRITE] = VALID;
390         state_machine_[VALID][SMI_INVALID] = INVALID;
391         state_machine_[VALID][SMI_OKAY] = INITIAL;
392         state_machine_[VALID][SMI_APPLY] = INITIAL;
393         state_machine_[VALID][SMI_RESTORE] = INITIAL;
394         state_machine_[VALID][SMI_READ_ONLY] = RO_VALID;
395         // State::INVALID
396         state_machine_[INVALID][SMI_INVALID] = INVALID;
397         state_machine_[INVALID][SMI_READ_WRITE] = INVALID;
398         state_machine_[INVALID][SMI_VALID] = VALID;
399         state_machine_[INVALID][SMI_OKAY] = INITIAL;
400         state_machine_[INVALID][SMI_APPLY] = INITIAL;
401         state_machine_[INVALID][SMI_RESTORE] = INITIAL;
402         state_machine_[INVALID][SMI_READ_ONLY] = RO_INVALID;
403         // State::RO_INITIAL
404         state_machine_[RO_INITIAL][SMI_READ_ONLY] = RO_INITIAL;
405         state_machine_[RO_INITIAL][SMI_VALID] = RO_VALID;
406         state_machine_[RO_INITIAL][SMI_INVALID] = RO_INVALID;
407         state_machine_[RO_INITIAL][SMI_READ_WRITE] = INITIAL;
408         // State::RO_VALID
409         state_machine_[RO_VALID][SMI_VALID] = RO_VALID;
410         state_machine_[RO_VALID][SMI_READ_ONLY] = RO_VALID;
411         state_machine_[RO_VALID][SMI_INVALID] = RO_INVALID;
412         state_machine_[RO_VALID][SMI_READ_WRITE] = VALID;
413         state_machine_[RO_VALID][SMI_RESTORE] = RO_INITIAL;
414         // State::RO_INVALID
415         state_machine_[RO_INVALID][SMI_INVALID] = RO_INVALID;
416         state_machine_[RO_INVALID][SMI_READ_ONLY] = RO_INVALID;
417         state_machine_[RO_INVALID][SMI_VALID] = RO_VALID;
418         state_machine_[RO_INVALID][SMI_READ_WRITE] = INVALID;
419         state_machine_[RO_INVALID][SMI_RESTORE] = RO_INITIAL;
420 }
421
422
423 void ButtonPolicy::Private::initOkApplyCancelReadOnly()
424 {
425         outputs_ = StateOutputs(RO_APPLIED + 1, ButtonPolicy::ALL_BUTTONS);
426         state_machine_ = StateMachine(RO_APPLIED + 1,
427                          StateArray(int(SMI_TOTAL), ButtonPolicy::BOGUS));
428
429         // Build the state output map
430         outputs_[INITIAL] = CLOSE;
431         outputs_[VALID] = RESTORE | OKAY | APPLY | CANCEL;
432         outputs_[INVALID] = RESTORE | CANCEL;
433         outputs_[APPLIED] = OKAY | APPLY | CLOSE;
434         outputs_[RO_INITIAL] = CLOSE;
435         outputs_[RO_VALID] = RESTORE | CANCEL;
436         outputs_[RO_INVALID] = RESTORE | CANCEL;
437         outputs_[RO_APPLIED] = CLOSE;
438
439         // Build the state machine one state at a time
440         // NOTE:  Since CANCEL and HIDE always go to INITIAL they are
441         //        left out of the state machine and handled explicitly
442         //        in input()
443         //
444         // State::INITIAL
445         state_machine_[INITIAL][SMI_READ_WRITE] = INITIAL;
446         state_machine_[INITIAL][SMI_VALID] = VALID;
447         state_machine_[INITIAL][SMI_INVALID] = INVALID;
448         state_machine_[INITIAL][SMI_READ_ONLY] = RO_INITIAL;
449         // State::VALID
450         state_machine_[VALID][SMI_VALID] = VALID;
451         state_machine_[VALID][SMI_READ_WRITE] = VALID;
452         state_machine_[VALID][SMI_INVALID] = INVALID;
453         state_machine_[VALID][SMI_OKAY] = INITIAL;
454         state_machine_[VALID][SMI_RESTORE] = INITIAL;
455         state_machine_[VALID][SMI_APPLY] = APPLIED;
456         state_machine_[VALID][SMI_READ_ONLY] = RO_VALID;
457         // State::INVALID
458         state_machine_[INVALID][SMI_INVALID] = INVALID;
459         state_machine_[INVALID][SMI_READ_WRITE] = INVALID;
460         state_machine_[INVALID][SMI_VALID] = VALID;
461         state_machine_[INVALID][SMI_RESTORE] = INITIAL;
462         state_machine_[INVALID][SMI_READ_ONLY] = RO_INVALID;
463         // State::APPLIED
464         state_machine_[APPLIED][SMI_APPLY] = APPLIED;
465         state_machine_[APPLIED][SMI_READ_WRITE] = APPLIED;
466         state_machine_[APPLIED][SMI_VALID] = VALID;
467         state_machine_[APPLIED][SMI_INVALID] = INVALID;
468         state_machine_[APPLIED][SMI_OKAY] = INITIAL;
469         state_machine_[APPLIED][SMI_READ_ONLY] = RO_APPLIED;
470         // State::RO_INITIAL
471         state_machine_[RO_INITIAL][SMI_READ_ONLY] = RO_INITIAL;
472         state_machine_[RO_INITIAL][SMI_VALID] = RO_VALID;
473         state_machine_[RO_INITIAL][SMI_INVALID] = RO_INVALID;
474         state_machine_[RO_INITIAL][SMI_READ_WRITE] = INITIAL;
475         // State::RO_VALID
476         state_machine_[RO_VALID][SMI_VALID] = RO_VALID;
477         state_machine_[RO_VALID][SMI_READ_ONLY] = RO_VALID;
478         state_machine_[RO_VALID][SMI_INVALID] = RO_INVALID;
479         state_machine_[RO_VALID][SMI_READ_WRITE] = VALID;
480         state_machine_[RO_VALID][SMI_RESTORE] = RO_INITIAL;
481         // State::RO_INVALID
482         state_machine_[RO_INVALID][SMI_INVALID] = RO_INVALID;
483         state_machine_[RO_INVALID][SMI_READ_ONLY] = RO_INVALID;
484         state_machine_[RO_INVALID][SMI_VALID] = RO_VALID;
485         state_machine_[RO_INVALID][SMI_READ_WRITE] = INVALID;
486         state_machine_[RO_INVALID][SMI_RESTORE] = RO_INITIAL;
487         // State::RO_APPLIED
488         state_machine_[RO_APPLIED][SMI_READ_ONLY] = RO_APPLIED;
489         state_machine_[RO_APPLIED][SMI_INVALID] = RO_INVALID;
490         state_machine_[RO_APPLIED][SMI_VALID] = RO_VALID;
491         state_machine_[RO_APPLIED][SMI_READ_WRITE] = APPLIED;
492 }
493
494
495 void ButtonPolicy::Private::initOkApplyCancel()
496 {
497         outputs_ = StateOutputs(APPLIED + 1, ButtonPolicy::ALL_BUTTONS);
498         state_machine_ = StateMachine(APPLIED + 1,
499                          StateArray(int(SMI_TOTAL), ButtonPolicy::BOGUS));
500
501         // Build the state output map
502         outputs_[INITIAL] = CLOSE;
503         outputs_[VALID] = RESTORE | OKAY | APPLY | CANCEL;
504         outputs_[INVALID] = RESTORE | CANCEL;
505         outputs_[APPLIED] = OKAY | APPLY | CLOSE;
506
507         // Build the state machine one state at a time
508         // NOTE:  Since CANCEL and HIDE always go to INITIAL they are
509         //        left out of the state machine and handled explicitly
510         //        in input()
511         //
512         // State::INITIAL
513         state_machine_[INITIAL][SMI_READ_ONLY] = INITIAL;
514         state_machine_[INITIAL][SMI_READ_WRITE] = INITIAL;
515         state_machine_[INITIAL][SMI_VALID] = VALID;
516         state_machine_[INITIAL][SMI_INVALID] = INVALID;
517         // State::VALID
518         state_machine_[VALID][SMI_VALID] = VALID;
519         state_machine_[VALID][SMI_READ_ONLY] = VALID;
520         state_machine_[VALID][SMI_READ_WRITE] = VALID;
521         state_machine_[VALID][SMI_INVALID] = INVALID;
522         state_machine_[VALID][SMI_OKAY] = INITIAL;
523         state_machine_[VALID][SMI_RESTORE] = INITIAL;
524         state_machine_[VALID][SMI_APPLY] = APPLIED;
525         // State::INVALID
526         state_machine_[INVALID][SMI_INVALID] = INVALID;
527         state_machine_[INVALID][SMI_READ_ONLY] = INVALID;
528         state_machine_[INVALID][SMI_READ_WRITE] = INVALID;
529         state_machine_[INVALID][SMI_VALID] = VALID;
530         state_machine_[INVALID][SMI_RESTORE] = INITIAL;
531         // State::APPLIED
532         state_machine_[APPLIED][SMI_APPLY] = APPLIED;
533         state_machine_[APPLIED][SMI_READ_ONLY] = APPLIED;
534         state_machine_[APPLIED][SMI_READ_WRITE] = APPLIED;
535         state_machine_[APPLIED][SMI_VALID] = VALID;
536         state_machine_[APPLIED][SMI_INVALID] = INVALID;
537         state_machine_[APPLIED][SMI_OKAY] = INITIAL;
538 }
539
540
541 void ButtonPolicy::Private::initNoRepeatedApply()
542 {
543         outputs_ = StateOutputs(INVALID + 1, ButtonPolicy::ALL_BUTTONS);
544         state_machine_ = StateMachine(INVALID + 1,
545                          StateArray(int(SMI_TOTAL), ButtonPolicy::BOGUS));
546
547         // Build the state output map
548         outputs_[INITIAL] = CLOSE;
549         outputs_[VALID] = RESTORE | OKAY | APPLY | CANCEL;
550         outputs_[INVALID] = RESTORE | CANCEL;
551
552         // Build the state machine one state at a time
553         // NOTE:  Since CANCEL and HIDE always go to INITIAL they are
554         //        left out of the state machine and handled explicitly
555         //        in input()
556         //
557         // State::INITIAL
558         state_machine_[INITIAL][SMI_READ_ONLY] = INITIAL;
559         state_machine_[INITIAL][SMI_READ_WRITE] = INITIAL;
560         state_machine_[INITIAL][SMI_VALID] = VALID;
561         state_machine_[INITIAL][SMI_INVALID] = INVALID;
562         // State::VALID
563         state_machine_[VALID][SMI_VALID] = VALID;
564         state_machine_[VALID][SMI_READ_ONLY] = VALID;
565         state_machine_[VALID][SMI_READ_WRITE] = VALID;
566         state_machine_[VALID][SMI_INVALID] = INVALID;
567         state_machine_[VALID][SMI_OKAY] = INITIAL;
568         state_machine_[VALID][SMI_APPLY] = INITIAL;
569         state_machine_[VALID][SMI_RESTORE] = INITIAL;
570         // State::INVALID
571         state_machine_[INVALID][SMI_INVALID] = INVALID;
572         state_machine_[INVALID][SMI_READ_ONLY] = INVALID;
573         state_machine_[INVALID][SMI_READ_WRITE] = INVALID;
574         state_machine_[INVALID][SMI_VALID] = VALID;
575         state_machine_[INVALID][SMI_RESTORE] = INITIAL;
576 }
577
578
579 /////////////////////////////////////////////////////////////////////////
580 //
581 // ButtonPolicy
582 //
583 /////////////////////////////////////////////////////////////////////////
584
585 ButtonPolicy::ButtonPolicy(Policy policy)
586         : d(new Private(policy))
587 {}
588
589
590 ButtonPolicy::~ButtonPolicy()
591 {
592         delete d;
593 }
594
595
596 void ButtonPolicy::setPolicy(Policy policy)
597 {
598         *d = Private(policy);
599 }
600
601
602 void ButtonPolicy::input(SMInput input)
603 {
604         switch (d->policy_) {
605                 case PreferencesPolicy:
606                         // The APPLIED state is persistent. Next time the dialog is opened,
607                         // the user will be able to press 'Save'.
608                         if (SMI_CANCEL == input || SMI_HIDE == input) {
609                                 if (d->state_ != APPLIED)
610                                         d->state_ = INITIAL;
611                         } else {
612                                 d->nextState(input);
613                         }
614                         break;
615                 case IgnorantPolicy:
616                         break;
617                 default:
618                         // CANCEL and HIDE always take us to INITIAL for all cases
619                         if (SMI_CANCEL == input || SMI_HIDE == input)
620                                 d->state_ = INITIAL;
621                         else
622                                 d->nextState(input);
623                         break;
624         }
625 }
626
627
628 bool ButtonPolicy::buttonStatus(Button button) const
629 {
630         return d->policy_ == IgnorantPolicy || (button & d->outputs_[d->state_]);
631 }
632
633
634 bool ButtonPolicy::isReadOnly() const
635 {
636         switch (d->policy_) {
637                 case NoRepeatedApplyReadOnlyPolicy:
638                 case OkCancelReadOnlyPolicy:
639                 case OkApplyCancelReadOnlyPolicy:
640                         return RO_INITIAL == d->state_
641                                 || RO_VALID == d->state_
642                                 || RO_INVALID == d->state_
643                                 || RO_APPLIED == d->state_;
644                 default:
645                         return false;
646         }
647 }
648
649
650
651 } // namespace frontend
652 } // namespace lyx