1 // -*- C++ -*- 2 /** 3 * \file ButtonPolicy.h 4 * This file is part of LyX, the document processor. 5 * Licence details can be found in the file COPYING. 6 * 7 * \author Allan Rae 8 * 9 * Full author contact details are available in file CREDITS. 10 * 11 * Provides a state machine implementation of the various button policies 12 * used by the dialogs. 13 */ 14 15 #ifndef BUTTONPOLICY_H 16 #define BUTTONPOLICY_H 17 18 namespace lyx { 19 namespace frontend { 20 21 /** A class for button policies. 22 A state machine implementation of the various button policies used by the 23 dialogs. Only the policy is implemented here. Separate ButtonController 24 classes are needed for each GUI implementation. 25 26 Policy | ReadOnly | Apply Button | Repeated Apply 27 ======================================================================== 28 OkCancel | N | N | - 29 OkCancelReadOnly | Y | N | - 30 OkApplyCancel | N | Y | Y 31 OkApplyCancelReadOnly | Y | Y | Y 32 NoRepeatedApply | N | Y | N 33 NoRepeatedApplyReadOnly | Y | Y | N 34 OkApplyCancelAutoReadOnly | Y | Y | Y 35 Preferences | N | Y | No (Ok-Close) 36 Ignorant | N/A | N/A | N/A 37 ======================================================================== 38 39 Policy 40 The name of the policy 41 ReadOnly 42 Does the policy treat read-only docs differently to read-write docs? 43 This usually means that when an SMI_READ_ONLY input arrives then 44 all the buttons are disabled except Cancel/Close. The state 45 machine tracks the inputs (valid/invalid) and has states for all 46 combinations. When an SMI_READ_WRITE input arrives the appropriate 47 machine state is entered (just as if the document had always been 48 read-write). 49 NOTE: If a dialog doesn't care about the read-only status of a document 50 (and uses an appropriate policy) it can never get into a read-only state 51 so isReadOnly() can only ever return false even though the document may 52 be read-only. 53 Repeated Apply 54 Simply means that it is alright to use the Apply button multiple times 55 without requiring a change of the dialog contents. If no repeating is 56 allowed the Ok+Apply buttons are deactivated. The Preferences dialog 57 has its own special version of repeated apply handling because its Ok 58 button is actually a Save button -- it is always reasonable to Save the 59 preferences if the dialog has changed since the last save. 60 61 The IgnorantPolicy is a special case that allows anything. 62 */ 63 64 class ButtonPolicy 65 { 66 public: 67 68 // The various poicies 69 enum Policy { 70 /** Ok and Cancel buttons for dialogs with read-only operation. 71 Note: This scheme supports the relabelling of Cancel to Close and 72 vice versa. 73 This is based on the value of the bool state of the Button::CANCEL. 74 true == Cancel, false == Close 75 */ 76 OkCancelPolicy, 77 78 79 /** Ok and Cancel buttons for dialogs where read-only operation is blocked. 80 The state machine design for this policy allows changes to occur within 81 the dialog while a file is read-only -- the okay button is disabled until 82 a read-write input is given. When the file is made read-write the dialog 83 will then be in the correct state (as if the file had always been 84 read-write). 85 Note: This scheme supports the relabelling of Cancel to Close 86 and vice versa. 87 This is based on the value of the bool state of the Button::CANCEL. 88 true == Cancel, false == Close 89 */ 90 OkCancelReadOnlyPolicy, 91 92 /** Ok, Apply and Cancel buttons for dialogs where read-only operation 93 is blocked. 94 Repeated Apply are not allowed. Likewise, Ok cannot follow Apply without 95 some valid input. That is, the dialog contents must change between 96 each Apply or Apply and Ok. 97 The state machine design for this policy allows changes to occur within 98 the dialog while a file is read-only -- the Ok+Apply buttons are disabled 99 until a read-write input is given. When the file is made read-write the 100 dialog will then be in the correct state (as if the file had always been 101 read-write). 102 Note: This scheme supports the relabelling of Cancel to Close 103 and vice versa. 104 This is based on the value of the bool state of the Button::CANCEL. 105 true == Cancel, false == Close 106 */ 107 NoRepeatedApplyReadOnlyPolicy, 108 109 /** Ok, Apply and Cancel buttons for dialogs where read-only 110 operation is blocked. 111 Repeated Apply is allowed. Likewise, Ok can follow Apply. 112 The state machine design for this policy allows changes to occur within 113 the dialog while a file is read-only -- the Ok+Apply buttons are disabled 114 until a read-write input is given. When the file is made read-write the 115 dialog will then be in the correct state (as if the file had always been 116 read-write). 117 Note: This scheme supports the relabelling of Cancel to Close 118 and vice versa. 119 This is based on the value of the bool state of the Button::CANCEL. 120 true == Cancel, false == Close 121 */ 122 OkApplyCancelReadOnlyPolicy, 123 124 /** Ok, Apply and Cancel buttons for dialogs where repeated 125 Apply is allowed. 126 Note: This scheme supports the relabelling of Cancel to Close 127 and vice versa. 128 This is based on the value of the bool state of the Button::CANCEL. 129 true == Cancel, false == Close 130 */ 131 OkApplyCancelPolicy, 132 133 /** Ok, Apply and Cancel buttons for dialogs with no repeated Apply. 134 Note: This scheme supports the relabelling of Cancel to Close 135 and vice versa. 136 This is based on the value of the bool state of the Button::CANCEL. 137 true == Cancel, false == Close 138 */ 139 NoRepeatedApplyPolicy, 140 141 /** Ok, Apply and Cancel buttons and an AutoApply checkbox. 142 Note: This scheme supports the relabelling of Cancel to Close 143 and vice versa. 144 This is based on the value of the bool state of the Button::CANCEL. 145 true == Cancel, false == Close 146 */ 147 OkApplyCancelAutoReadOnlyPolicy, 148 149 /** Defines the policy used by the Preferences dialog. 150 Four buttons: Ok (Save), Apply, Cancel/Close, Restore. 151 Note: This scheme supports the relabelling of Cancel to Close 152 and vice versa. 153 This is based on the value of the bool state of the Button::CANCEL. 154 true == Cancel, false == Close 155 */ 156 PreferencesPolicy, 157 158 /** Defines the policy used by dialogs that are forced to support a button 159 controller when they either don't have a use for one or are not ready to 160 use one. This may be useful when testing a new button policy but wishing 161 to minimise problems to users by supplying an anything-goes policy via a 162 preprocessor directive. 163 */ 164 IgnorantPolicy 165 }; 166 167 /// Constructor 168 explicit ButtonPolicy(Policy policy); 169 /// Destructor 170 ~ButtonPolicy(); 171 /// 172 void setPolicy(Policy policy); 173 174 /** The various possible state names. 175 Not all state-machines have this many states. However, we need 176 to define them all here so we can share the code. 177 */ 178 enum State { 179 /// 180 INITIAL = 0, 181 /// 182 VALID, 183 /// 184 INVALID, 185 /// 186 APPLIED, 187 /// 188 AUTOAPPLY_INITIAL, 189 /// 190 AUTOAPPLY_CHANGED, 191 /// 192 RO_INITIAL, 193 /// 194 RO_VALID, 195 /// 196 RO_INVALID, 197 /// 198 RO_APPLIED, 199 /// 200 RO_AUTOAPPLY, 201 /// 202 BOGUS = 55 203 }; 204 205 /// The various button types. 206 enum Button { 207 /// 208 CLOSE = 0, // Not a real button, but effectively !CANCEL 209 /// 210 OKAY = 1, 211 /// 212 APPLY = 2, 213 /// 214 CANCEL = 4, 215 /// 216 RESTORE = 8, 217 /// 218 AUTOAPPLY = 16 // This is usually a checkbox 219 }; 220 /// 221 static const Button ALL_BUTTONS = 222 Button(OKAY | APPLY | CANCEL | RESTORE | AUTOAPPLY); 223 224 /** State machine inputs. 225 All the policies so far have both CANCEL and HIDE always going to 226 INITIAL. This won't necessarily be true for all [future] policies 227 though so I'll leave those two as distinct inputs rather than merge 228 them. For example, a dialog that doesn't update it's input fields 229 when reshown after being hidden needs a policy where CANCEL and 230 HIDE are treated differently. 231 */ 232 enum SMInput { 233 /// the dialog contents are now valid 234 SMI_VALID = 0, 235 /// the dialog contents are now invalid 236 SMI_INVALID, 237 /// an apply-and-hide action has happened 238 SMI_OKAY, 239 /// an apply action has happened 240 SMI_APPLY, 241 /// a cancel action has happened 242 SMI_CANCEL, 243 /// a restore action has happened 244 SMI_RESTORE, 245 /// apply auto-apply 246 SMI_AUTOAPPLY, 247 /// the dialog has been hidden 248 SMI_HIDE, 249 /// the dialog contents are read-only 250 SMI_READ_ONLY, 251 /// the dialog contents can be modified 252 SMI_READ_WRITE, 253 /// the state of the dialog contents has not changed 254 SMI_NOOP, 255 /// for internal use 256 SMI_TOTAL 257 }; 258 259 /// Trigger a transition with this input. 260 void input(SMInput); 261 /** Activation status of a button. 262 We assume that we haven't gotten into an undefined state. 263 This is reasonable since we can only reach states defined 264 in the state machine and they should all have been defined in 265 the outputs_ variable. Perhaps we can do something at compile 266 time to check that all the states have corresponding outputs. 267 */ 268 bool buttonStatus(Button) const; 269 /// Are we in a read-only state? 270 bool isReadOnly() const; 271 272 private: 273 /// noncopyable 274 ButtonPolicy(ButtonPolicy const &); 275 void operator=(ButtonPolicy const &); 276 277 /// pimpl 278 class Private; 279 Private * d; 280 }; 281 282 283 } // namespace frontend 284 } // namespace lyx 285 286 #endif 287