#include "support/debug.h"
#include <iostream>
+#include <vector>
using namespace std;
namespace lyx {
namespace frontend {
-
-ButtonPolicy::ButtonPolicy(Policy policy)
-{
- policy_ = policy;
- state_ = INITIAL;
-
- switch (policy_) {
- case OkCancelPolicy:
- initOkCancel();
- break;
- case OkCancelReadOnlyPolicy:
- initOkCancelReadOnly();
- break;
- case OkApplyCancelPolicy:
- initOkApplyCancel();
- break;
- case OkApplyCancelReadOnlyPolicy:
- initOkApplyCancelReadOnly();
- break;
- case NoRepeatedApplyPolicy:
- initNoRepeatedApply();
- break;
- case NoRepeatedApplyReadOnlyPolicy:
- initNoRepeatedApplyReadOnly();
- break;
- case PreferencesPolicy:
- initPreferences();
- break;
- case IgnorantPolicy:
- break;
- }
-}
-
-
-char const * functionName(ButtonPolicy::Policy policy)
-{
- switch (policy) {
- case ButtonPolicy::PreferencesPolicy:
- return "PreferencesPolicy";
- case ButtonPolicy::OkCancelPolicy:
- return "OkCancelPolicy";
- case ButtonPolicy::OkCancelReadOnlyPolicy:
- return "OkCancelReadOnlyPolicy";
- case ButtonPolicy::OkApplyCancelPolicy:
- return "OkApplyCancelPolicy";
- case ButtonPolicy::OkApplyCancelReadOnlyPolicy:
- return "OkApplyCancelReadOnlyPolicy";
- case ButtonPolicy::NoRepeatedApplyPolicy:
- return "NoRepeatedApplyPolicy";
- case ButtonPolicy::NoRepeatedApplyReadOnlyPolicy:
- return "NoRepeatedApplyReadOnlyPolicy";
- case ButtonPolicy::IgnorantPolicy:
- return "IgnorantPolicy";
- default:
- return "Unknown policy";
- }
-}
-
-
-void ButtonPolicy::input(SMInput input)
-{
- switch (policy_) {
- case PreferencesPolicy:
- // The APPLIED state is persistent. Next time the dialog is opened,
- // the user will be able to press 'Save'.
- if (SMI_CANCEL == input || SMI_HIDE == input) {
- if (state_ != APPLIED)
- state_ = INITIAL;
- } else {
- nextState(input);
- }
- break;
- case IgnorantPolicy:
- break;
- default:
- // CANCEL and HIDE always take us to INITIAL for all cases
- if (SMI_CANCEL == input || SMI_HIDE == input)
- state_ = INITIAL;
- else
- nextState(input);
- break;
- }
-}
-
-
-bool ButtonPolicy::buttonStatus(Button button) const
-{
- return policy_ == IgnorantPolicy ? true : button & outputs_[state_];
-}
-
-
-bool ButtonPolicy::isReadOnly() const
-{
- switch(policy_) {
- case NoRepeatedApplyReadOnlyPolicy:
- case OkCancelReadOnlyPolicy:
- case OkApplyCancelReadOnlyPolicy:
- return RO_INITIAL == state_
- || RO_VALID == state_
- || RO_INVALID == state_
- || RO_APPLIED == state_;
- default:
- return false;
- }
-}
-
-
static char const * printState(ButtonPolicy::State const & state)
{
switch (state) {
return "INVALID";
case ButtonPolicy::APPLIED:
return "APPLIED";
+ case ButtonPolicy::AUTOAPPLY_INITIAL:
+ return "AUTOAPPLY_INITIAL";
+ case ButtonPolicy::AUTOAPPLY_CHANGED:
+ return "AUTOAPPLY_CHANGED";
case ButtonPolicy::RO_INITIAL:
return "RO_INITIAL";
case ButtonPolicy::RO_VALID:
return "RO_INVALID";
case ButtonPolicy::RO_APPLIED:
return "RO_APPLIED";
+ case ButtonPolicy::RO_AUTOAPPLY:
+ return "RO_AUTOAPPLY";
case ButtonPolicy::BOGUS:
return "BOGUS";
default:
return "SMI_CANCEL";
case ButtonPolicy::SMI_RESTORE:
return "SMI_RESTORE";
+ case ButtonPolicy::SMI_AUTOAPPLY:
+ return "SMI_AUTOAPPLY";
case ButtonPolicy::SMI_HIDE:
return "SMI_HIDE";
case ButtonPolicy::SMI_READ_ONLY:
}
-void ButtonPolicy::nextState(SMInput input)
+char const * functionName(ButtonPolicy::Policy policy)
+{
+ switch (policy) {
+ case ButtonPolicy::PreferencesPolicy:
+ return "PreferencesPolicy";
+ case ButtonPolicy::OkCancelPolicy:
+ return "OkCancelPolicy";
+ case ButtonPolicy::OkCancelReadOnlyPolicy:
+ return "OkCancelReadOnlyPolicy";
+ case ButtonPolicy::OkApplyCancelPolicy:
+ return "OkApplyCancelPolicy";
+ case ButtonPolicy::OkApplyCancelReadOnlyPolicy:
+ return "OkApplyCancelReadOnlyPolicy";
+ case ButtonPolicy::OkApplyCancelAutoReadOnlyPolicy:
+ return "OkApplyCancelAutoReadOnlyPolicy";
+ case ButtonPolicy::NoRepeatedApplyPolicy:
+ return "NoRepeatedApplyPolicy";
+ case ButtonPolicy::NoRepeatedApplyReadOnlyPolicy:
+ return "NoRepeatedApplyReadOnlyPolicy";
+ case ButtonPolicy::IgnorantPolicy:
+ return "IgnorantPolicy";
+ default:
+ return "Unknown policy";
+ }
+}
+
+
+ostream & operator<<(ostream & os, ButtonPolicy::State st)
+{
+ return os << int(st);
+}
+
+
+ostream & operator<<(ostream & os, ButtonPolicy::SMInput smi)
+{
+ return os << int(smi);
+}
+
+
+/////////////////////////////////////////////////////////////////////////
+//
+// ButtonPolicy::Private
+//
+/////////////////////////////////////////////////////////////////////////
+
+class ButtonPolicy::Private
+{
+public:
+ typedef ButtonPolicy::SMInput SMInput;
+ typedef ButtonPolicy::Policy Policy;
+ typedef ButtonPolicy::State State;
+
+ Private(Policy policy);
+
+ void nextState(SMInput input);
+
+ void initOkCancel();
+ void initOkCancelReadOnly();
+ void initNoRepeatedApplyReadOnly();
+ void initOkApplyCancelReadOnly();
+ void initOkApplyCancelAutoReadOnly();
+ void initOkApplyCancel();
+ void initNoRepeatedApply();
+ void initPreferences();
+
+public:
+ ///
+ Policy policy_;
+
+ /// Transition map of the state machine.
+ typedef std::vector<State> StateArray;
+ ///
+ typedef std::vector<StateArray> StateMachine;
+ /// The state outputs are the status of the buttons.
+ typedef std::vector<int> StateOutputs;
+
+ /// Current state.
+ State state_;
+ /// Which buttons are active for a given state.
+ StateOutputs outputs_;
+ ///
+ StateMachine state_machine_;
+};
+
+
+ButtonPolicy::Private::Private(Policy policy)
+{
+ policy_ = policy;
+ state_ = INITIAL;
+
+ switch (policy_) {
+ case OkCancelPolicy:
+ initOkCancel();
+ break;
+ case OkCancelReadOnlyPolicy:
+ initOkCancelReadOnly();
+ break;
+ case OkApplyCancelPolicy:
+ initOkApplyCancel();
+ break;
+ case OkApplyCancelReadOnlyPolicy:
+ initOkApplyCancelReadOnly();
+ break;
+ case OkApplyCancelAutoReadOnlyPolicy:
+ initOkApplyCancelAutoReadOnly();
+ break;
+ case NoRepeatedApplyPolicy:
+ initNoRepeatedApply();
+ break;
+ case NoRepeatedApplyReadOnlyPolicy:
+ initNoRepeatedApplyReadOnly();
+ break;
+ case PreferencesPolicy:
+ initPreferences();
+ break;
+ case IgnorantPolicy:
+ break;
+ }
+}
+
+
+void ButtonPolicy::Private::nextState(SMInput input)
{
if (SMI_NOOP == input)
return;
if (tmp != BOGUS) {
state_ = tmp;
} else {
- lyxerr << functionName(policy_)
- << ": No transition for input "
- << printInput(input)
- << " from state "
- << printState(state_)
- << endl;
+ LYXERR0(functionName(policy_) << ": No transition for input "
+ << printInput(input) << " from state " << printState(state_));
}
}
-void ButtonPolicy::initPreferences()
+void ButtonPolicy::Private::initPreferences()
{
outputs_ = StateOutputs(APPLIED + 1, ButtonPolicy::ALL_BUTTONS);
state_machine_ = StateMachine(APPLIED + 1,
}
-void ButtonPolicy::initOkCancel()
+void ButtonPolicy::Private::initOkCancel()
{
outputs_ = StateOutputs(INVALID + 1, ButtonPolicy::ALL_BUTTONS);
state_machine_ = StateMachine(INVALID + 1,
}
-void ButtonPolicy::initOkCancelReadOnly()
+void ButtonPolicy::Private::initOkCancelReadOnly()
{
outputs_ = StateOutputs(RO_INVALID + 1, ButtonPolicy::ALL_BUTTONS);
state_machine_ = StateMachine(RO_INVALID + 1,
}
-void ButtonPolicy::initNoRepeatedApplyReadOnly()
+void ButtonPolicy::Private::initNoRepeatedApplyReadOnly()
{
outputs_ = StateOutputs(RO_INVALID + 1, ButtonPolicy::ALL_BUTTONS);
state_machine_ = StateMachine(RO_INVALID + 1,
state_machine_[VALID][SMI_READ_ONLY] = RO_VALID;
// State::INVALID
state_machine_[INVALID][SMI_INVALID] = INVALID;
- state_machine_[INVALID][SMI_OKAY] = INVALID;
state_machine_[INVALID][SMI_READ_WRITE] = INVALID;
state_machine_[INVALID][SMI_VALID] = VALID;
+ state_machine_[INVALID][SMI_OKAY] = INITIAL;
+ state_machine_[INVALID][SMI_APPLY] = INITIAL;
state_machine_[INVALID][SMI_RESTORE] = INITIAL;
state_machine_[INVALID][SMI_READ_ONLY] = RO_INVALID;
// State::RO_INITIAL
}
-void ButtonPolicy::initOkApplyCancelReadOnly()
+void ButtonPolicy::Private::initOkApplyCancelReadOnly()
{
outputs_ = StateOutputs(RO_APPLIED + 1, ButtonPolicy::ALL_BUTTONS);
state_machine_ = StateMachine(RO_APPLIED + 1,
}
-void ButtonPolicy::initOkApplyCancel()
+void ButtonPolicy::Private::initOkApplyCancel()
{
outputs_ = StateOutputs(APPLIED + 1, ButtonPolicy::ALL_BUTTONS);
state_machine_ = StateMachine(APPLIED + 1,
}
-void ButtonPolicy::initNoRepeatedApply()
+void ButtonPolicy::Private::initOkApplyCancelAutoReadOnly()
+{
+ outputs_ = StateOutputs(RO_AUTOAPPLY + 1, ButtonPolicy::ALL_BUTTONS);
+ state_machine_ = StateMachine(RO_AUTOAPPLY + 1,
+ StateArray(int(SMI_TOTAL), ButtonPolicy::BOGUS));
+
+ // Build the state output map
+ outputs_[INITIAL] = CLOSE | AUTOAPPLY;
+ outputs_[VALID] = RESTORE | OKAY | APPLY | CANCEL | AUTOAPPLY;
+ outputs_[INVALID] = RESTORE | CANCEL | AUTOAPPLY;
+ outputs_[APPLIED] = OKAY | CLOSE | AUTOAPPLY;
+ outputs_[AUTOAPPLY_INITIAL] = CLOSE | AUTOAPPLY;
+ outputs_[AUTOAPPLY_CHANGED] = CLOSE | RESTORE | AUTOAPPLY | OKAY;
+ outputs_[RO_INITIAL] = CLOSE;
+ outputs_[RO_VALID] = RESTORE | CANCEL;
+ outputs_[RO_INVALID] = RESTORE | CANCEL;
+ outputs_[RO_APPLIED] = CLOSE;
+ outputs_[RO_AUTOAPPLY] = CLOSE;
+
+ // Build the state machine one state at a time
+ // NOTE: Since CANCEL and HIDE always go to INITIAL they are
+ // left out of the state machine and handled explicitly
+ // in input()
+ //
+ // State::INITIAL
+ state_machine_[INITIAL][SMI_READ_WRITE] = INITIAL;
+ state_machine_[INITIAL][SMI_VALID] = VALID;
+ state_machine_[INITIAL][SMI_INVALID] = INVALID;
+ state_machine_[INITIAL][SMI_READ_ONLY] = RO_INITIAL;
+ state_machine_[INITIAL][SMI_AUTOAPPLY] = AUTOAPPLY_INITIAL;
+ // State::VALID
+ state_machine_[VALID][SMI_VALID] = VALID;
+ state_machine_[VALID][SMI_READ_WRITE] = VALID;
+ state_machine_[VALID][SMI_INVALID] = INVALID;
+ state_machine_[VALID][SMI_OKAY] = INITIAL;
+ state_machine_[VALID][SMI_RESTORE] = INITIAL;
+ state_machine_[VALID][SMI_APPLY] = APPLIED;
+ state_machine_[VALID][SMI_READ_ONLY] = RO_VALID;
+ state_machine_[VALID][SMI_AUTOAPPLY] = AUTOAPPLY_INITIAL;
+ // State::INVALID
+ state_machine_[INVALID][SMI_INVALID] = INVALID;
+ state_machine_[INVALID][SMI_READ_WRITE] = INVALID;
+ state_machine_[INVALID][SMI_VALID] = VALID;
+ state_machine_[INVALID][SMI_RESTORE] = INITIAL;
+ state_machine_[INVALID][SMI_READ_ONLY] = RO_INVALID;
+ state_machine_[INVALID][SMI_AUTOAPPLY] = AUTOAPPLY_CHANGED;
+ // State::APPLIED
+ state_machine_[APPLIED][SMI_APPLY] = APPLIED;
+ state_machine_[APPLIED][SMI_READ_WRITE] = APPLIED;
+ state_machine_[APPLIED][SMI_VALID] = VALID;
+ state_machine_[APPLIED][SMI_INVALID] = INVALID;
+ state_machine_[APPLIED][SMI_OKAY] = INITIAL;
+ state_machine_[APPLIED][SMI_READ_ONLY] = RO_APPLIED;
+ state_machine_[APPLIED][SMI_AUTOAPPLY] = AUTOAPPLY_INITIAL;
+ // State::AUTOAPPLY_INITIAL
+ state_machine_[AUTOAPPLY_INITIAL][SMI_AUTOAPPLY] = APPLIED;
+ state_machine_[AUTOAPPLY_INITIAL][SMI_READ_ONLY] = RO_AUTOAPPLY;
+ state_machine_[AUTOAPPLY_INITIAL][SMI_VALID] = AUTOAPPLY_CHANGED;
+ state_machine_[AUTOAPPLY_INITIAL][SMI_INVALID] = AUTOAPPLY_CHANGED;
+ state_machine_[AUTOAPPLY_INITIAL][SMI_READ_WRITE] = AUTOAPPLY_INITIAL;
+ // State::AUTOAPPLY_CHANGED
+ state_machine_[AUTOAPPLY_CHANGED][SMI_AUTOAPPLY] = APPLIED;
+ state_machine_[AUTOAPPLY_CHANGED][SMI_READ_ONLY] = RO_AUTOAPPLY;
+ state_machine_[AUTOAPPLY_CHANGED][SMI_RESTORE] = AUTOAPPLY_INITIAL;
+ state_machine_[AUTOAPPLY_CHANGED][SMI_VALID] = AUTOAPPLY_CHANGED;
+ state_machine_[AUTOAPPLY_CHANGED][SMI_INVALID] = AUTOAPPLY_CHANGED;
+ state_machine_[AUTOAPPLY_CHANGED][SMI_READ_WRITE] = AUTOAPPLY_CHANGED;
+ state_machine_[AUTOAPPLY_CHANGED][SMI_APPLY] = AUTOAPPLY_INITIAL;
+ // State::RO_INITIAL
+ state_machine_[RO_INITIAL][SMI_READ_ONLY] = RO_INITIAL;
+ state_machine_[RO_INITIAL][SMI_VALID] = RO_VALID;
+ state_machine_[RO_INITIAL][SMI_INVALID] = RO_INVALID;
+ state_machine_[RO_INITIAL][SMI_READ_WRITE] = INITIAL;
+ state_machine_[RO_INITIAL][SMI_AUTOAPPLY] = RO_AUTOAPPLY;
+ // State::RO_VALID
+ state_machine_[RO_VALID][SMI_VALID] = RO_VALID;
+ state_machine_[RO_VALID][SMI_READ_ONLY] = RO_VALID;
+ state_machine_[RO_VALID][SMI_INVALID] = RO_INVALID;
+ state_machine_[RO_VALID][SMI_READ_WRITE] = VALID;
+ state_machine_[RO_VALID][SMI_RESTORE] = RO_INITIAL;
+ state_machine_[RO_VALID][SMI_AUTOAPPLY] = RO_AUTOAPPLY;
+ // State::RO_INVALID
+ state_machine_[RO_INVALID][SMI_INVALID] = RO_INVALID;
+ state_machine_[RO_INVALID][SMI_READ_ONLY] = RO_INVALID;
+ state_machine_[RO_INVALID][SMI_VALID] = RO_VALID;
+ state_machine_[RO_INVALID][SMI_READ_WRITE] = INVALID;
+ state_machine_[RO_INVALID][SMI_RESTORE] = RO_INITIAL;
+ state_machine_[RO_INVALID][SMI_AUTOAPPLY] = RO_AUTOAPPLY;
+ // State::RO_APPLIED
+ state_machine_[RO_APPLIED][SMI_READ_ONLY] = RO_APPLIED;
+ state_machine_[RO_APPLIED][SMI_INVALID] = RO_INVALID;
+ state_machine_[RO_APPLIED][SMI_VALID] = RO_VALID;
+ state_machine_[RO_APPLIED][SMI_READ_WRITE] = APPLIED;
+ state_machine_[RO_APPLIED][SMI_AUTOAPPLY] = RO_AUTOAPPLY;
+ // State::RO_AUTOAPPLY
+ state_machine_[RO_AUTOAPPLY][SMI_READ_WRITE] = AUTOAPPLY_INITIAL;
+}
+
+
+void ButtonPolicy::Private::initNoRepeatedApply()
{
outputs_ = StateOutputs(INVALID + 1, ButtonPolicy::ALL_BUTTONS);
state_machine_ = StateMachine(INVALID + 1,
}
-ostream & operator<<(ostream & os, ButtonPolicy::State st)
+/////////////////////////////////////////////////////////////////////////
+//
+// ButtonPolicy
+//
+/////////////////////////////////////////////////////////////////////////
+
+ButtonPolicy::ButtonPolicy(Policy policy)
+ : d(new Private(policy))
+{}
+
+
+ButtonPolicy::~ButtonPolicy()
{
- return os << int(st);
+ delete d;
}
-ostream & operator<<(ostream & os, ButtonPolicy::SMInput smi)
+void ButtonPolicy::setPolicy(Policy policy)
{
- return os << int(smi);
+ *d = Private(policy);
+}
+
+
+void ButtonPolicy::input(SMInput input)
+{
+ switch (d->policy_) {
+ case PreferencesPolicy:
+ // The APPLIED state is persistent. Next time the dialog is opened,
+ // the user will be able to press 'Save'.
+ if (SMI_CANCEL == input || SMI_HIDE == input) {
+ if (d->state_ != APPLIED)
+ d->state_ = INITIAL;
+ } else {
+ d->nextState(input);
+ }
+ break;
+ case IgnorantPolicy:
+ break;
+ default:
+ // CANCEL and HIDE always take us to INITIAL for all cases
+ if (SMI_CANCEL == input || SMI_HIDE == input) {
+ if (d->state_ == AUTOAPPLY_INITIAL
+ || d->state_ == AUTOAPPLY_CHANGED)
+ d->state_ = AUTOAPPLY_INITIAL;
+ else
+ d->state_ = INITIAL;
+ } else
+ d->nextState(input);
+ break;
+ }
}
+bool ButtonPolicy::buttonStatus(Button button) const
+{
+ return d->policy_ == IgnorantPolicy || (button & d->outputs_[d->state_]);
+}
+
+
+bool ButtonPolicy::isReadOnly() const
+{
+ switch (d->policy_) {
+ case NoRepeatedApplyReadOnlyPolicy:
+ case OkCancelReadOnlyPolicy:
+ case OkApplyCancelReadOnlyPolicy:
+ return RO_INITIAL == d->state_
+ || RO_VALID == d->state_
+ || RO_INVALID == d->state_
+ || RO_APPLIED == d->state_;
+ default:
+ return false;
+ }
+}
+
+
+
} // namespace frontend
} // namespace lyx