--- /dev/null
+/**
+ * \file ButtonPolicy.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Allan Rae
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "ButtonPolicy.h"
+#include "debug.h"
+
+
+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) {
+ case ButtonPolicy::INITIAL:
+ return "INITIAL";
+ case ButtonPolicy::VALID:
+ return "VALID";
+ case ButtonPolicy::INVALID:
+ return "INVALID";
+ case ButtonPolicy::APPLIED:
+ return "APPLIED";
+ case ButtonPolicy::RO_INITIAL:
+ return "RO_INITIAL";
+ case ButtonPolicy::RO_VALID:
+ return "RO_VALID";
+ case ButtonPolicy::RO_INVALID:
+ return "RO_INVALID";
+ case ButtonPolicy::RO_APPLIED:
+ return "RO_APPLIED";
+ case ButtonPolicy::BOGUS:
+ return "BOGUS";
+ default:
+ return "";
+ }
+}
+
+
+static char const * printInput(ButtonPolicy::SMInput const & input)
+{
+ switch (input) {
+ case ButtonPolicy::SMI_VALID:
+ return "SMI_VALID";
+ case ButtonPolicy::SMI_INVALID:
+ return "SMI_INVALID";
+ case ButtonPolicy::SMI_OKAY:
+ return "SMI_OKAY";
+ case ButtonPolicy::SMI_APPLY:
+ return "SMI_APPLY";
+ case ButtonPolicy::SMI_CANCEL:
+ return "SMI_CANCEL";
+ case ButtonPolicy::SMI_RESTORE:
+ return "SMI_RESTORE";
+ case ButtonPolicy::SMI_HIDE:
+ return "SMI_HIDE";
+ case ButtonPolicy::SMI_READ_ONLY:
+ return "SMI_READ_ONLY";
+ case ButtonPolicy::SMI_READ_WRITE:
+ return "SMI_READ_WRITE";
+ case ButtonPolicy::SMI_NOOP:
+ return "SMI_NOOP";
+ case ButtonPolicy::SMI_TOTAL:
+ return "SMI_TOTAL";
+ default:
+ return "";
+ }
+}
+
+
+void ButtonPolicy::nextState(SMInput input)
+{
+ if (SMI_NOOP == input)
+ return;
+
+ State tmp = state_machine_[state_][input];
+
+ LYXERR(Debug::GUI) << "Transition from state "
+ << printState(state_) << " to state "
+ << printState(tmp) << " after input "
+ << printInput(input) << std::endl;
+
+ if (tmp != BOGUS) {
+ state_ = tmp;
+ } else {
+ lyxerr << functionName(policy_)
+ << ": No transition for input "
+ << printInput(input)
+ << " from state "
+ << printState(state_)
+ << std::endl;
+ }
+}
+
+
+void ButtonPolicy::initPreferences()
+{
+ outputs_ = StateOutputs(APPLIED + 1, ButtonPolicy::ALL_BUTTONS);
+ state_machine_ = StateMachine(APPLIED + 1,
+ StateArray(int(SMI_TOTAL), ButtonPolicy::BOGUS));
+
+ // Build the state output map
+ outputs_[INITIAL] = CLOSE;
+ outputs_[VALID] = RESTORE | OKAY | APPLY | CANCEL;
+ outputs_[INVALID] = RESTORE | CANCEL;
+ outputs_[APPLIED] = OKAY | 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(). This won't necessarily be true for all
+ // policies though so I'll leave those two as distinct
+ // inputs rather than merge them. For example, a dialog
+ // that doesn't update it's input fields when reshown
+ // after being hidden needs a policy where CANCEL and
+ // HIDE are treated differently.
+ //
+ // State::INITIAL
+ state_machine_[INITIAL][SMI_READ_ONLY] = INITIAL;
+ state_machine_[INITIAL][SMI_READ_WRITE] = INITIAL;
+ state_machine_[INITIAL][SMI_VALID] = VALID;
+ state_machine_[INITIAL][SMI_INVALID] = INVALID;
+ // State::VALID
+ state_machine_[VALID][SMI_VALID] = VALID;
+ state_machine_[VALID][SMI_READ_ONLY] = VALID;
+ state_machine_[VALID][SMI_READ_WRITE] = VALID;
+ state_machine_[VALID][SMI_INVALID] = INVALID;
+ state_machine_[VALID][SMI_APPLY] = APPLIED;
+ state_machine_[VALID][SMI_OKAY] = INITIAL;
+ state_machine_[VALID][SMI_RESTORE] = INITIAL;
+ // State::INVALID
+ state_machine_[INVALID][SMI_VALID] = VALID;
+ state_machine_[INVALID][SMI_INVALID] = INVALID;
+ state_machine_[INVALID][SMI_READ_ONLY] = INVALID;
+ state_machine_[INVALID][SMI_READ_WRITE] = INVALID;
+ state_machine_[INVALID][SMI_RESTORE] = INITIAL;
+ // State::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] = APPLIED;
+ state_machine_[APPLIED][SMI_READ_WRITE] = APPLIED;
+}
+
+
+void ButtonPolicy::initOkCancel()
+{
+ outputs_ = StateOutputs(INVALID + 1, ButtonPolicy::ALL_BUTTONS);
+ state_machine_ = StateMachine(INVALID + 1,
+ StateArray(int(SMI_TOTAL), ButtonPolicy::BOGUS));
+
+ // Build the state output map
+ outputs_[INITIAL] = CLOSE;
+ outputs_[VALID] = RESTORE | OKAY | CANCEL;
+ outputs_[INVALID] = RESTORE | CANCEL;
+
+ // 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_ONLY] = INITIAL;
+ state_machine_[INITIAL][SMI_READ_WRITE] = INITIAL;
+ state_machine_[INITIAL][SMI_VALID] = VALID;
+ state_machine_[INITIAL][SMI_INVALID] = INVALID;
+ // State::VALID
+ state_machine_[VALID][SMI_VALID] = VALID;
+ state_machine_[VALID][SMI_READ_ONLY] = 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::INVALID
+ state_machine_[INVALID][SMI_VALID] = VALID;
+ state_machine_[INVALID][SMI_INVALID] = INVALID;
+ state_machine_[INVALID][SMI_READ_ONLY] = INVALID;
+ state_machine_[INVALID][SMI_READ_WRITE] = INVALID;
+ state_machine_[INVALID][SMI_RESTORE] = INITIAL;
+}
+
+
+void ButtonPolicy::initOkCancelReadOnly()
+{
+ outputs_ = StateOutputs(RO_INVALID + 1, ButtonPolicy::ALL_BUTTONS);
+ state_machine_ = StateMachine(RO_INVALID + 1,
+ StateArray(int(SMI_TOTAL), ButtonPolicy::BOGUS));
+
+ // Build the state output map
+ outputs_[INITIAL] = CLOSE;
+ outputs_[VALID] = RESTORE | OKAY | CANCEL;
+ outputs_[INVALID] = RESTORE | CANCEL;
+ outputs_[RO_INITIAL] = CLOSE;
+ outputs_[RO_VALID] = RESTORE | CANCEL;
+ outputs_[RO_INVALID] = RESTORE | CANCEL;
+
+ // 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::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_READ_ONLY] = RO_VALID;
+ // 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::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::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::RO_INVALID
+ state_machine_[RO_INVALID][SMI_READ_ONLY] = RO_INVALID;
+ state_machine_[RO_INVALID][SMI_INVALID] = 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;
+}
+
+
+void ButtonPolicy::initNoRepeatedApplyReadOnly()
+{
+ outputs_ = StateOutputs(RO_INVALID + 1, ButtonPolicy::ALL_BUTTONS);
+ state_machine_ = StateMachine(RO_INVALID + 1,
+ StateArray(int(SMI_TOTAL), ButtonPolicy::BOGUS));
+
+ // Build the state output map
+ outputs_[INITIAL] = CLOSE;
+ outputs_[VALID] = RESTORE | OKAY | APPLY | CANCEL;
+ outputs_[INVALID] = RESTORE | CANCEL;
+ outputs_[RO_INITIAL] = CLOSE;
+ outputs_[RO_VALID] = RESTORE | CANCEL;
+ outputs_[RO_INVALID] = RESTORE | CANCEL;
+
+ // 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::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_APPLY] = INITIAL;
+ state_machine_[VALID][SMI_RESTORE] = INITIAL;
+ state_machine_[VALID][SMI_READ_ONLY] = RO_VALID;
+ // 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::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::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::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;
+}
+
+
+void ButtonPolicy::initOkApplyCancelReadOnly()
+{
+ outputs_ = StateOutputs(RO_APPLIED + 1, ButtonPolicy::ALL_BUTTONS);
+ state_machine_ = StateMachine(RO_APPLIED + 1,
+ StateArray(int(SMI_TOTAL), ButtonPolicy::BOGUS));
+
+ // Build the state output map
+ outputs_[INITIAL] = CLOSE;
+ outputs_[VALID] = RESTORE | OKAY | APPLY | CANCEL;
+ outputs_[INVALID] = RESTORE | CANCEL;
+ outputs_[APPLIED] = OKAY | APPLY | CLOSE;
+ outputs_[RO_INITIAL] = CLOSE;
+ outputs_[RO_VALID] = RESTORE | CANCEL;
+ outputs_[RO_INVALID] = RESTORE | CANCEL;
+ outputs_[RO_APPLIED] = 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::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::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::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::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::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::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::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;
+}
+
+
+void ButtonPolicy::initOkApplyCancel()
+{
+ outputs_ = StateOutputs(APPLIED + 1, ButtonPolicy::ALL_BUTTONS);
+ state_machine_ = StateMachine(APPLIED + 1,
+ StateArray(int(SMI_TOTAL), ButtonPolicy::BOGUS));
+
+ // Build the state output map
+ outputs_[INITIAL] = CLOSE;
+ outputs_[VALID] = RESTORE | OKAY | APPLY | CANCEL;
+ outputs_[INVALID] = RESTORE | CANCEL;
+ outputs_[APPLIED] = OKAY | APPLY | 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_ONLY] = INITIAL;
+ state_machine_[INITIAL][SMI_READ_WRITE] = INITIAL;
+ state_machine_[INITIAL][SMI_VALID] = VALID;
+ state_machine_[INITIAL][SMI_INVALID] = INVALID;
+ // State::VALID
+ state_machine_[VALID][SMI_VALID] = VALID;
+ state_machine_[VALID][SMI_READ_ONLY] = 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::INVALID
+ state_machine_[INVALID][SMI_INVALID] = INVALID;
+ state_machine_[INVALID][SMI_READ_ONLY] = INVALID;
+ state_machine_[INVALID][SMI_READ_WRITE] = INVALID;
+ state_machine_[INVALID][SMI_VALID] = VALID;
+ state_machine_[INVALID][SMI_RESTORE] = INITIAL;
+ // State::APPLIED
+ state_machine_[APPLIED][SMI_APPLY] = APPLIED;
+ state_machine_[APPLIED][SMI_READ_ONLY] = 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;
+}
+
+
+void ButtonPolicy::initNoRepeatedApply()
+{
+ outputs_ = StateOutputs(INVALID + 1, ButtonPolicy::ALL_BUTTONS);
+ state_machine_ = StateMachine(INVALID + 1,
+ StateArray(int(SMI_TOTAL), ButtonPolicy::BOGUS));
+
+ // Build the state output map
+ outputs_[INITIAL] = CLOSE;
+ outputs_[VALID] = RESTORE | OKAY | APPLY | CANCEL;
+ outputs_[INVALID] = RESTORE | CANCEL;
+
+ // 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_ONLY] = INITIAL;
+ state_machine_[INITIAL][SMI_READ_WRITE] = INITIAL;
+ state_machine_[INITIAL][SMI_VALID] = VALID;
+ state_machine_[INITIAL][SMI_INVALID] = INVALID;
+ // State::VALID
+ state_machine_[VALID][SMI_VALID] = VALID;
+ state_machine_[VALID][SMI_READ_ONLY] = VALID;
+ state_machine_[VALID][SMI_READ_WRITE] = VALID;
+ state_machine_[VALID][SMI_INVALID] = INVALID;
+ state_machine_[VALID][SMI_OKAY] = INITIAL;
+ state_machine_[VALID][SMI_APPLY] = INITIAL;
+ state_machine_[VALID][SMI_RESTORE] = INITIAL;
+ // State::INVALID
+ state_machine_[INVALID][SMI_INVALID] = INVALID;
+ state_machine_[INVALID][SMI_READ_ONLY] = INVALID;
+ state_machine_[INVALID][SMI_READ_WRITE] = INVALID;
+ state_machine_[INVALID][SMI_VALID] = VALID;
+ state_machine_[INVALID][SMI_RESTORE] = INITIAL;
+}
+
+
+} // namespace frontend
+} // namespace lyx
--- /dev/null
+// -*- C++ -*-
+/**
+ * \file ButtonPolicy.h
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Allan Rae
+ *
+ * Full author contact details are available in file CREDITS.
+ *
+ * Provides a state machine implementation of the various button policies
+ * used by the dialogs.
+ */
+
+#ifndef BUTTONPOLICY_H
+#define BUTTONPOLICY_H
+
+#include <vector>
+#include <iostream>
+
+namespace lyx {
+namespace frontend {
+
+/** A class for button policies.
+ A state machine implementation of the various button policies used by the
+ dialogs. Only the policy is implemented here. Separate ButtonController
+ classes are needed for each GUI implementation.
+
+ Policy | ReadOnly | Apply Button | Repeated Apply
+ ========================================================================
+ OkCancel | N | N | -
+ OkCancelReadOnly | Y | N | -
+ OkApplyCancel | N | Y | Y
+ OkApplyCancelReadOnly | Y | Y | Y
+ NoRepeatedApply | N | Y | N
+ NoRepeatedApplyReadOnly | Y | Y | N
+ Preferences | N | Y | No (Ok-Close)
+ Ignorant | N/A | N/A | N/A
+ ========================================================================
+
+ Policy
+ The name of the policy
+ ReadOnly
+ Does the policy treat read-only docs differently to read-write docs?
+ This usually means that when an SMI_READ_ONLY input arrives then
+ all the buttons are disabled except Cancel/Close. The state
+ machine tracks the inputs (valid/invalid) and has states for all
+ combinations. When an SMI_READ_WRITE input arrives the appropriate
+ machine state is entered (just as if the document had always been
+ read-write).
+ NOTE: If a dialog doesn't care about the read-only status of a document
+ (and uses an appropriate policy) it can never get into a read-only state
+ so isReadOnly() can only ever return false even though the document may
+ be read-only.
+ Repeated Apply
+ Simply means that it is alright to use the Apply button multiple times
+ without requiring a change of the dialog contents. If no repeating is
+ allowed the Ok+Apply buttons are deactivated. The Preferences dialog
+ has its own special version of repeated apply handling because its Ok
+ button is actually a Save button -- it is always reasonable to Save the
+ preferences if the dialog has changed since the last save.
+
+ The IgnorantPolicy is a special case that allows anything.
+ */
+
+class ButtonPolicy {
+public:
+
+ // The various poicies
+ enum Policy {
+ /** Ok and Cancel buttons for dialogs with read-only operation.
+ Note: This scheme supports the relabelling of Cancel to Close and
+ vice versa.
+ This is based on the value of the bool state of the Button::CANCEL.
+ true == Cancel, false == Close
+ */
+ OkCancelPolicy,
+
+
+ /** Ok and Cancel buttons for dialogs where read-only operation is blocked.
+ The state machine design for this policy allows changes to occur within
+ the dialog while a file is read-only -- the okay button is disabled until
+ a read-write input is given. When the file is made read-write the dialog
+ will then be in the correct state (as if the file had always been
+ read-write).
+ Note: This scheme supports the relabelling of Cancel to Close
+ and vice versa.
+ This is based on the value of the bool state of the Button::CANCEL.
+ true == Cancel, false == Close
+ */
+ OkCancelReadOnlyPolicy,
+
+ /** Ok, Apply and Cancel buttons for dialogs where read-only operation
+ is blocked.
+ Repeated Apply are not allowed. Likewise, Ok cannot follow Apply without
+ some valid input. That is, the dialog contents must change between
+ each Apply or Apply and Ok.
+ The state machine design for this policy allows changes to occur within
+ the dialog while a file is read-only -- the Ok+Apply buttons are disabled
+ until a read-write input is given. When the file is made read-write the
+ dialog will then be in the correct state (as if the file had always been
+ read-write).
+ Note: This scheme supports the relabelling of Cancel to Close
+ and vice versa.
+ This is based on the value of the bool state of the Button::CANCEL.
+ true == Cancel, false == Close
+ */
+ NoRepeatedApplyReadOnlyPolicy,
+
+ /** Ok, Apply and Cancel buttons for dialogs where read-only
+ operation is blocked.
+ Repeated Apply is allowed. Likewise, Ok can follow Apply.
+ The state machine design for this policy allows changes to occur within
+ the dialog while a file is read-only -- the Ok+Apply buttons are disabled
+ until a read-write input is given. When the file is made read-write the
+ dialog will then be in the correct state (as if the file had always been
+ read-write).
+ Note: This scheme supports the relabelling of Cancel to Close
+ and vice versa.
+ This is based on the value of the bool state of the Button::CANCEL.
+ true == Cancel, false == Close
+ */
+ OkApplyCancelReadOnlyPolicy,
+
+ /** Ok, Apply and Cancel buttons for dialogs where repeated
+ * Apply is allowed.
+ Note: This scheme supports the relabelling of Cancel to Close
+ and vice versa.
+ This is based on the value of the bool state of the Button::CANCEL.
+ true == Cancel, false == Close
+ */
+ OkApplyCancelPolicy,
+
+ /** Ok, Apply and Cancel buttons for dialogs with no repeated Apply.
+ Note: This scheme supports the relabelling of Cancel to Close
+ and vice versa.
+ This is based on the value of the bool state of the Button::CANCEL.
+ true == Cancel, false == Close
+ */
+ NoRepeatedApplyPolicy,
+
+ /** Defines the policy used by the Preferences dialog.
+ Four buttons: Ok (Save), Apply, Cancel/Close, Restore.
+ Note: This scheme supports the relabelling of Cancel to Close
+ and vice versa.
+ This is based on the value of the bool state of the Button::CANCEL.
+ true == Cancel, false == Close
+ */
+ PreferencesPolicy,
+
+ /** Defines the policy used by dialogs that are forced to support a button
+ controller when they either don't have a use for one or are not ready to
+ use one. This may be useful when testing a new button policy but wishing
+ to minimise problems to users by supplying an anything-goes policy via a
+ preprocessor directive.
+ */
+ IgnorantPolicy,
+ };
+
+ /// Constructor
+ explicit ButtonPolicy(Policy policy);
+
+ /** The various possible state names.
+ Not all state-machines have this many states. However, we need
+ to define them all here so we can share the code.
+ */
+ enum State {
+ ///
+ INITIAL = 0,
+ ///
+ VALID,
+ ///
+ INVALID,
+ ///
+ APPLIED,
+ ///
+ RO_INITIAL,
+ ///
+ RO_VALID,
+ ///
+ RO_INVALID,
+ ///
+ RO_APPLIED,
+ ///
+ BOGUS = 55
+ };
+
+ /// The various button types.
+ enum Button {
+ ///
+ CLOSE = 0, // Not a real button, but effectively !CANCEL
+ ///
+ OKAY = 1,
+ ///
+ APPLY = 2,
+ ///
+ CANCEL = 4,
+ ///
+ RESTORE = 8
+ };
+ ///
+ static const Button ALL_BUTTONS =
+ Button(OKAY | APPLY | CANCEL | RESTORE);
+
+ /** State machine inputs.
+ All the policies so far have both CANCEL and HIDE always going to
+ INITIAL. This won't necessarily be true for all [future] policies
+ though so I'll leave those two as distinct inputs rather than merge
+ them. For example, a dialog that doesn't update it's input fields
+ when reshown after being hidden needs a policy where CANCEL and
+ HIDE are treated differently.
+ */
+ enum SMInput {
+ /// the dialog contents are now valid
+ SMI_VALID = 0,
+ /// the dialog contents are now invalid
+ SMI_INVALID,
+ /// an apply-and-hide action has happened
+ SMI_OKAY,
+ /// an apply action has happened
+ SMI_APPLY,
+ /// a cancel action has happened
+ SMI_CANCEL,
+ /// a restore action has happened
+ SMI_RESTORE,
+ /// the dialog has been hidden
+ SMI_HIDE,
+ /// the dialog contents are read-only
+ SMI_READ_ONLY,
+ /// the dialog contents can be modified
+ SMI_READ_WRITE,
+ /// the state of the dialog contents has not changed
+ SMI_NOOP,
+ /// for internal use
+ SMI_TOTAL
+ };
+
+ /// Trigger a transition with this input.
+ void input(SMInput);
+ /** Activation status of a button.
+ We assume that we haven't gotten into an undefined state.
+ This is reasonable since we can only reach states defined
+ in the state machine and they should all have been defined in
+ the outputs_ variable. Perhaps we can do something at compile
+ time to check that all the states have corresponding outputs.
+ */
+ bool buttonStatus(Button) const;
+ /// Are we in a read-only state?
+ bool isReadOnly() const;
+
+private:
+ ///
+ 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_;
+
+private:
+ // Helpers
+ void nextState(SMInput input);
+
+ void initOkCancel();
+ void initOkCancelReadOnly();
+ void initNoRepeatedApplyReadOnly();
+ void initOkApplyCancelReadOnly();
+ void initOkApplyCancel();
+ void initNoRepeatedApply();
+ void initPreferences();
+};
+
+
+inline
+std::ostream & operator<<(std::ostream & os, ButtonPolicy::State st)
+{
+ return os << int(st);
+}
+
+
+inline
+std::ostream & operator<<(std::ostream & os, ButtonPolicy::SMInput smi)
+{
+ return os << int(smi);
+}
+
+
+} // namespace frontend
+} // namespace lyx
+
+#endif
--- /dev/null
+/**
+ * \file Dialog.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Angus Leeming
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "Dialog.h"
+
+#include "FuncRequest.h"
+#include "FuncStatus.h"
+#include "LyXFunc.h"
+
+#include "frontends/LyXView.h"
+#include "frontends/Dialogs.h" // FIXME
+
+#include "Buffer.h"
+
+
+namespace lyx {
+namespace frontend {
+
+
+Dialog::~Dialog()
+{}
+
+
+Controller::Controller(Dialog & parent)
+ : parent_(parent), lyxview_(0)
+{}
+
+
+Controller::Controller(Dialog * parent)
+ : parent_(*parent), lyxview_(0)
+{}
+
+
+Controller::~Controller()
+{}
+
+
+bool Controller::canApply() const
+{
+ FuncRequest const fr(getLfun(), dialog().name());
+ FuncStatus const fs(getStatus(fr));
+ return fs.enabled();
+}
+
+
+void Controller::dispatch(FuncRequest const & fr) const
+{
+ lyxview_->dispatch(fr);
+}
+
+
+void Controller::updateDialog(std::string const & name) const
+{
+ dispatch(FuncRequest(LFUN_DIALOG_UPDATE, name));
+}
+
+
+void Controller::disconnect(std::string const & name) const
+{
+ lyxview_->getDialogs().disconnect(name);
+}
+
+
+bool Controller::isBufferAvailable() const
+{
+ return lyxview_->buffer() != 0;
+}
+
+
+bool Controller::isBufferReadonly() const
+{
+ if (!lyxview_->buffer())
+ return true;
+ return lyxview_->buffer()->isReadonly();
+}
+
+
+std::string const Controller::bufferFilepath() const
+{
+ return buffer().filePath();
+}
+
+
+KernelDocType Controller::docType() const
+{
+ if (buffer().isLatex())
+ return LATEX;
+ if (buffer().isLiterate())
+ return LITERATE;
+
+ return DOCBOOK;
+}
+
+
+BufferView * Controller::bufferview()
+{
+ return lyxview_->view();
+}
+
+
+BufferView const * Controller::bufferview() const
+{
+ return lyxview_->view();
+}
+
+
+Buffer & Controller::buffer()
+{
+ BOOST_ASSERT(lyxview_->buffer());
+ return *lyxview_->buffer();
+}
+
+
+Buffer const & Controller::buffer() const
+{
+ BOOST_ASSERT(lyxview_->buffer());
+ return *lyxview_->buffer();
+}
+
+} // namespace frontend
+} // namespace lyx
--- /dev/null
+// -*- C++ -*-
+/**
+ * \file Dialog.h
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Angus Leeming
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#ifndef DIALOG_H
+#define DIALOG_H
+
+#include "lfuns.h"
+
+#include "support/docstring.h"
+#include <string>
+
+namespace lyx {
+
+class Buffer;
+class BufferView;
+class FuncRequest;
+
+namespace frontend {
+
+class LyXView;
+
+/** \enum KernelDocType used to flag the different kinds of buffer
+ * without making the kernel header files available to the
+ * dialog's Controller or View.
+ */
+enum KernelDocType
+{
+ LATEX,
+ LITERATE,
+ DOCBOOK
+};
+
+
+/** Different dialogs will have different Controllers and Views.
+ * deriving from these base classes.
+ */
+//@{
+class Controller;
+//@}
+
+/** \c Dialog collects the different parts of a Model-Controller-View
+ * split of a generic dialog together.
+ */
+class Dialog
+{
+public:
+ /// \param lv is the access point for the dialog to the LyX kernel.
+ /// \param name is the identifier given to the dialog by its parent
+ /// container.
+ Dialog() {}
+ virtual ~Dialog();
+
+ /** \name Container Access
+ * These methods are publicly accessible because they are invoked
+ * by the parent container acting on commands from the LyX kernel.
+ */
+ //@{
+ /// \param data is a string encoding of the data to be displayed.
+ /// It is passed to the Controller to be translated into a useable form.
+ virtual void showData(std::string const & /*data*/) {}
+ virtual void updateData(std::string const & /*data*/) {}
+
+ virtual void hide() {}
+
+ // Override in GuiDialog
+ virtual void slotOK() {}
+ virtual void slotApply() {}
+ virtual void slotRestore() {}
+ virtual void slotClose() {}
+
+ /** This function is called, for example, if the GUI colours
+ * have been changed.
+ */
+ virtual void redraw() {}
+ //@}
+
+ /** Check whether we may apply our data.
+ *
+ * The buttons are disabled if not and (re-)enabled if yes.
+ */
+ virtual void checkStatus() {}
+
+ /** When applying, it's useful to know whether the dialog is about
+ * to close or not (no point refreshing the display for example).
+ */
+ virtual bool isClosing() const { return false; }
+
+ /** \name Dialog Specialization
+ * Methods to set the Controller and View and so specialise
+ * to a particular dialog.
+ */
+ //@{
+ virtual Controller & controller() = 0;
+ //@}
+
+ /** \c Button controller part
+ */
+ virtual void setButtonsValid(bool /*valid*/) {}
+
+
+ /** \c View part
+ * of a Model-Controller-View split of a generic dialog.
+ * These few methods are all that a generic dialog needs of a
+ * view.
+ */
+ //@{
+ /** A request to modify the data structures stored by the
+ * accompanying Controller in preparation for their dispatch to
+ * the LyX kernel.
+ */
+ virtual void applyView() = 0;
+
+ /// Hide the dialog from sight
+ virtual void hideView() = 0;
+
+ /// Redraw the dialog (e.g. if the colors have been remapped).
+ virtual void redrawView() = 0;
+
+ /// Create the dialog if necessary, update it and display it.
+ virtual void showView() = 0;
+
+ /// Update the display of the dialog whilst it is still visible.
+ virtual void updateView() = 0;
+
+ /// \return true if the dialog is visible.
+ virtual bool isVisibleView() const = 0;
+ //@}
+
+ /** Defaults to nothing. Can be used by the Controller, however, to
+ * indicate to the View that something has changed and that the
+ * dialog therefore needs updating.
+ * \param id identifies what should be updated.
+ */
+ virtual void partialUpdateView(int /*id*/) = 0;
+
+ ///
+ virtual std::string name() const = 0;
+
+protected:
+ virtual void apply() {}
+
+private:
+ /// intentionally unimplemented, therefore uncopiable
+ Dialog(Dialog const &);
+ void operator=(Dialog const &);
+};
+
+
+/** \c Controller is an abstract base class for the Controller
+ * of a Model-Controller-View split of a generic dialog.
+ */
+class Controller
+{
+public:
+ /// \param parent Dialog owning this Controller.
+ Controller(Dialog & parent);
+ // the same. avoids ambiguity with the (non-existent) copy constructor
+ Controller(Dialog * parent);
+ virtual ~Controller();
+ void setLyXView(LyXView & lv) { lyxview_ = &lv; }
+
+ /** \name Generic Controller
+ * These few methods are all that a generic dialog needs of a
+ * controller.
+ */
+ //@{
+ /** Enable the controller to initialise its data structures.
+ * \param data is a string encoding of the parameters to be displayed.
+ * \return true if the translation was successful.
+ */
+ virtual bool initialiseParams(std::string const & data) = 0;
+
+ /// Enable the controller to clean up its data structures.
+ virtual void clearParams() = 0;
+
+ /// Enable the Controller to dispatch its data back to the LyX kernel.
+ virtual void dispatchParams() = 0;
+
+ /** \return true if the dialog should be shown only when
+ * a buffer is open.
+ */
+ virtual bool isBufferDependent() const = 0;
+
+ /** \return true if the dialog can apply data also
+ * for ReadOnly buffers.
+ * This has to be distinguished from isBufferDependent()
+ */
+ virtual bool canApplyToReadOnly() const { return false; }
+
+ /** The lfun that is sent for applying the data.
+ *
+ * This method is used by the default implementation of canApply()
+ * for buffer dependent dialogs that send one lfun when applying the
+ * data.
+ * It should be used in dispatchParams(), too for consistency reasons.
+ * \returns the lfun that is sent for applying the data.
+ */
+ virtual kb_action getLfun() const { return LFUN_INSET_APPLY; }
+
+ /** Check whether we may apply our data.
+ *
+ * The default implementation works for all dialogs that send one
+ * lfun when applying the data. Dialogs that send none or more than
+ * one lfun need to reimplement it.
+ * \returns whether the data can be applied or not.
+ */
+ virtual bool canApply() const;
+
+ /** \return true if the kernel should disconnect the dialog from
+ * a particular inset after the data has been applied to it.
+ * Clearly this makes sense only for dialogs modifying the contents
+ * of an inset :-)
+ * In practise, only a very few dialogs (e.g. the citation dialog)
+ * return true.
+ */
+ virtual bool disconnectOnApply() const { return false; }
+
+ /** \return true if Dialog::View::show() should not display the dialog
+ * after running update. Currently, only ControlSpellchecker
+ * makes use of that.
+ */
+ virtual bool exitEarly() const { return false; }
+ //@}
+public:
+ /** \name Controller Access
+ * Enable the derived classes to access the other parts of the whole.
+ */
+ //@{
+ Dialog & dialog() { return parent_; }
+ Dialog const & dialog() const { return parent_; }
+ //@}
+
+ /** \c Kernel part: a wrapper making the LyX kernel available to the dialog.
+ * (Ie, it provides an interface to the Model part of the Model-Controller-
+ * View split.
+ * In an ideal world, it will shrink as more info is passed to the
+ * Dialog::show() and Dialog::update() methods.
+ */
+
+
+ /** This method is the primary purpose of the class. It provides
+ * the "gateway" by which the dialog can send a request (of a
+ * change in the data, for more information) to the kernel.
+ * \param fr is the encoding of the request.
+ */
+ void dispatch(FuncRequest const & fr) const;
+
+ /** The dialog has received a request from the user
+ * (who pressed the "Restore" button) to update contents.
+ * It must, therefore, ask the kernel to provide this information.
+ * \param name is used to identify the dialog to the kernel.
+ */
+ void updateDialog(std::string const & name) const;
+
+ /** A request from the Controller that future changes to the data
+ * stored by the dialog are not applied to the inset currently
+ * connected to the dialog. Instead, they will be used to generate
+ * a new inset at the cursor position.
+ * \param name is used to identify the dialog to the kernel.
+ */
+ void disconnect(std::string const & name) const;
+
+ /** \name Kernel Wrappers
+ * Simple wrapper functions to Buffer methods.
+ */
+ //@{
+ bool isBufferAvailable() const;
+ bool isBufferReadonly() const;
+ std::string const bufferFilepath() const;
+ //@}
+
+ /// The type of the current buffer.
+ KernelDocType docType() const;
+
+ /** \name Kernel Nasties
+ * Unpleasantly public internals of the LyX kernel.
+ * We should aim to reduce/remove these from the interface.
+ */
+ //@{
+ LyXView & lyxview() { return *lyxview_; }
+ LyXView const & lyxview() const { return *lyxview_; }
+
+ Buffer & buffer();
+ Buffer const & buffer() const;
+
+ BufferView * bufferview();
+ BufferView const * bufferview() const;
+ //@}
+
+private:
+ /// intentionally unimplemented, therefore uncopiable
+ Controller(Controller const &);
+ void operator=(Controller const &);
+
+private:
+ Dialog & parent_;
+ LyXView * lyxview_;
+};
+
+
+} // namespace frontend
+} // namespace lyx
+
+#endif // DIALOG_H
#include <config.h>
#include "Dialogs.h"
-#include "controllers/Dialog.h"
+#include "Dialog.h"
#include <boost/signal.hpp>
#include <boost/bind.hpp>
include $(top_srcdir)/config/common.am
-SUBDIRS = controllers $(FRONTENDS_SUBDIRS)
+SUBDIRS = $(FRONTENDS_SUBDIRS)
-DIST_SUBDIRS = controllers qt4
+DIST_SUBDIRS = qt4
EXTRA_DIST = pch.h
AM_CPPFLAGS += $(PCH_FLAGS) -I$(srcdir)/.. $(BOOST_INCLUDES)
liblyxfrontends_la_SOURCES = \
+ ButtonPolicy.cpp \
+ ButtonPolicy.h \
+ Dialog.cpp \
+ Dialog.h \
+ frontend_helpers.cpp \
+ frontend_helpers.h \
alert.cpp \
alert.h \
Alert_pimpl.h \
+++ /dev/null
-/**
- * \file ButtonPolicy.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author Allan Rae
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "ButtonPolicy.h"
-#include "debug.h"
-
-
-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) {
- case ButtonPolicy::INITIAL:
- return "INITIAL";
- case ButtonPolicy::VALID:
- return "VALID";
- case ButtonPolicy::INVALID:
- return "INVALID";
- case ButtonPolicy::APPLIED:
- return "APPLIED";
- case ButtonPolicy::RO_INITIAL:
- return "RO_INITIAL";
- case ButtonPolicy::RO_VALID:
- return "RO_VALID";
- case ButtonPolicy::RO_INVALID:
- return "RO_INVALID";
- case ButtonPolicy::RO_APPLIED:
- return "RO_APPLIED";
- case ButtonPolicy::BOGUS:
- return "BOGUS";
- default:
- return "";
- }
-}
-
-
-static char const * printInput(ButtonPolicy::SMInput const & input)
-{
- switch (input) {
- case ButtonPolicy::SMI_VALID:
- return "SMI_VALID";
- case ButtonPolicy::SMI_INVALID:
- return "SMI_INVALID";
- case ButtonPolicy::SMI_OKAY:
- return "SMI_OKAY";
- case ButtonPolicy::SMI_APPLY:
- return "SMI_APPLY";
- case ButtonPolicy::SMI_CANCEL:
- return "SMI_CANCEL";
- case ButtonPolicy::SMI_RESTORE:
- return "SMI_RESTORE";
- case ButtonPolicy::SMI_HIDE:
- return "SMI_HIDE";
- case ButtonPolicy::SMI_READ_ONLY:
- return "SMI_READ_ONLY";
- case ButtonPolicy::SMI_READ_WRITE:
- return "SMI_READ_WRITE";
- case ButtonPolicy::SMI_NOOP:
- return "SMI_NOOP";
- case ButtonPolicy::SMI_TOTAL:
- return "SMI_TOTAL";
- default:
- return "";
- }
-}
-
-
-void ButtonPolicy::nextState(SMInput input)
-{
- if (SMI_NOOP == input)
- return;
-
- State tmp = state_machine_[state_][input];
-
- LYXERR(Debug::GUI) << "Transition from state "
- << printState(state_) << " to state "
- << printState(tmp) << " after input "
- << printInput(input) << std::endl;
-
- if (tmp != BOGUS) {
- state_ = tmp;
- } else {
- lyxerr << functionName(policy_)
- << ": No transition for input "
- << printInput(input)
- << " from state "
- << printState(state_)
- << std::endl;
- }
-}
-
-
-void ButtonPolicy::initPreferences()
-{
- outputs_ = StateOutputs(APPLIED + 1, ButtonPolicy::ALL_BUTTONS);
- state_machine_ = StateMachine(APPLIED + 1,
- StateArray(int(SMI_TOTAL), ButtonPolicy::BOGUS));
-
- // Build the state output map
- outputs_[INITIAL] = CLOSE;
- outputs_[VALID] = RESTORE | OKAY | APPLY | CANCEL;
- outputs_[INVALID] = RESTORE | CANCEL;
- outputs_[APPLIED] = OKAY | 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(). This won't necessarily be true for all
- // policies though so I'll leave those two as distinct
- // inputs rather than merge them. For example, a dialog
- // that doesn't update it's input fields when reshown
- // after being hidden needs a policy where CANCEL and
- // HIDE are treated differently.
- //
- // State::INITIAL
- state_machine_[INITIAL][SMI_READ_ONLY] = INITIAL;
- state_machine_[INITIAL][SMI_READ_WRITE] = INITIAL;
- state_machine_[INITIAL][SMI_VALID] = VALID;
- state_machine_[INITIAL][SMI_INVALID] = INVALID;
- // State::VALID
- state_machine_[VALID][SMI_VALID] = VALID;
- state_machine_[VALID][SMI_READ_ONLY] = VALID;
- state_machine_[VALID][SMI_READ_WRITE] = VALID;
- state_machine_[VALID][SMI_INVALID] = INVALID;
- state_machine_[VALID][SMI_APPLY] = APPLIED;
- state_machine_[VALID][SMI_OKAY] = INITIAL;
- state_machine_[VALID][SMI_RESTORE] = INITIAL;
- // State::INVALID
- state_machine_[INVALID][SMI_VALID] = VALID;
- state_machine_[INVALID][SMI_INVALID] = INVALID;
- state_machine_[INVALID][SMI_READ_ONLY] = INVALID;
- state_machine_[INVALID][SMI_READ_WRITE] = INVALID;
- state_machine_[INVALID][SMI_RESTORE] = INITIAL;
- // State::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] = APPLIED;
- state_machine_[APPLIED][SMI_READ_WRITE] = APPLIED;
-}
-
-
-void ButtonPolicy::initOkCancel()
-{
- outputs_ = StateOutputs(INVALID + 1, ButtonPolicy::ALL_BUTTONS);
- state_machine_ = StateMachine(INVALID + 1,
- StateArray(int(SMI_TOTAL), ButtonPolicy::BOGUS));
-
- // Build the state output map
- outputs_[INITIAL] = CLOSE;
- outputs_[VALID] = RESTORE | OKAY | CANCEL;
- outputs_[INVALID] = RESTORE | CANCEL;
-
- // 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_ONLY] = INITIAL;
- state_machine_[INITIAL][SMI_READ_WRITE] = INITIAL;
- state_machine_[INITIAL][SMI_VALID] = VALID;
- state_machine_[INITIAL][SMI_INVALID] = INVALID;
- // State::VALID
- state_machine_[VALID][SMI_VALID] = VALID;
- state_machine_[VALID][SMI_READ_ONLY] = 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::INVALID
- state_machine_[INVALID][SMI_VALID] = VALID;
- state_machine_[INVALID][SMI_INVALID] = INVALID;
- state_machine_[INVALID][SMI_READ_ONLY] = INVALID;
- state_machine_[INVALID][SMI_READ_WRITE] = INVALID;
- state_machine_[INVALID][SMI_RESTORE] = INITIAL;
-}
-
-
-void ButtonPolicy::initOkCancelReadOnly()
-{
- outputs_ = StateOutputs(RO_INVALID + 1, ButtonPolicy::ALL_BUTTONS);
- state_machine_ = StateMachine(RO_INVALID + 1,
- StateArray(int(SMI_TOTAL), ButtonPolicy::BOGUS));
-
- // Build the state output map
- outputs_[INITIAL] = CLOSE;
- outputs_[VALID] = RESTORE | OKAY | CANCEL;
- outputs_[INVALID] = RESTORE | CANCEL;
- outputs_[RO_INITIAL] = CLOSE;
- outputs_[RO_VALID] = RESTORE | CANCEL;
- outputs_[RO_INVALID] = RESTORE | CANCEL;
-
- // 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::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_READ_ONLY] = RO_VALID;
- // 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::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::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::RO_INVALID
- state_machine_[RO_INVALID][SMI_READ_ONLY] = RO_INVALID;
- state_machine_[RO_INVALID][SMI_INVALID] = 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;
-}
-
-
-void ButtonPolicy::initNoRepeatedApplyReadOnly()
-{
- outputs_ = StateOutputs(RO_INVALID + 1, ButtonPolicy::ALL_BUTTONS);
- state_machine_ = StateMachine(RO_INVALID + 1,
- StateArray(int(SMI_TOTAL), ButtonPolicy::BOGUS));
-
- // Build the state output map
- outputs_[INITIAL] = CLOSE;
- outputs_[VALID] = RESTORE | OKAY | APPLY | CANCEL;
- outputs_[INVALID] = RESTORE | CANCEL;
- outputs_[RO_INITIAL] = CLOSE;
- outputs_[RO_VALID] = RESTORE | CANCEL;
- outputs_[RO_INVALID] = RESTORE | CANCEL;
-
- // 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::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_APPLY] = INITIAL;
- state_machine_[VALID][SMI_RESTORE] = INITIAL;
- state_machine_[VALID][SMI_READ_ONLY] = RO_VALID;
- // 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::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::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::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;
-}
-
-
-void ButtonPolicy::initOkApplyCancelReadOnly()
-{
- outputs_ = StateOutputs(RO_APPLIED + 1, ButtonPolicy::ALL_BUTTONS);
- state_machine_ = StateMachine(RO_APPLIED + 1,
- StateArray(int(SMI_TOTAL), ButtonPolicy::BOGUS));
-
- // Build the state output map
- outputs_[INITIAL] = CLOSE;
- outputs_[VALID] = RESTORE | OKAY | APPLY | CANCEL;
- outputs_[INVALID] = RESTORE | CANCEL;
- outputs_[APPLIED] = OKAY | APPLY | CLOSE;
- outputs_[RO_INITIAL] = CLOSE;
- outputs_[RO_VALID] = RESTORE | CANCEL;
- outputs_[RO_INVALID] = RESTORE | CANCEL;
- outputs_[RO_APPLIED] = 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::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::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::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::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::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::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::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;
-}
-
-
-void ButtonPolicy::initOkApplyCancel()
-{
- outputs_ = StateOutputs(APPLIED + 1, ButtonPolicy::ALL_BUTTONS);
- state_machine_ = StateMachine(APPLIED + 1,
- StateArray(int(SMI_TOTAL), ButtonPolicy::BOGUS));
-
- // Build the state output map
- outputs_[INITIAL] = CLOSE;
- outputs_[VALID] = RESTORE | OKAY | APPLY | CANCEL;
- outputs_[INVALID] = RESTORE | CANCEL;
- outputs_[APPLIED] = OKAY | APPLY | 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_ONLY] = INITIAL;
- state_machine_[INITIAL][SMI_READ_WRITE] = INITIAL;
- state_machine_[INITIAL][SMI_VALID] = VALID;
- state_machine_[INITIAL][SMI_INVALID] = INVALID;
- // State::VALID
- state_machine_[VALID][SMI_VALID] = VALID;
- state_machine_[VALID][SMI_READ_ONLY] = 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::INVALID
- state_machine_[INVALID][SMI_INVALID] = INVALID;
- state_machine_[INVALID][SMI_READ_ONLY] = INVALID;
- state_machine_[INVALID][SMI_READ_WRITE] = INVALID;
- state_machine_[INVALID][SMI_VALID] = VALID;
- state_machine_[INVALID][SMI_RESTORE] = INITIAL;
- // State::APPLIED
- state_machine_[APPLIED][SMI_APPLY] = APPLIED;
- state_machine_[APPLIED][SMI_READ_ONLY] = 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;
-}
-
-
-void ButtonPolicy::initNoRepeatedApply()
-{
- outputs_ = StateOutputs(INVALID + 1, ButtonPolicy::ALL_BUTTONS);
- state_machine_ = StateMachine(INVALID + 1,
- StateArray(int(SMI_TOTAL), ButtonPolicy::BOGUS));
-
- // Build the state output map
- outputs_[INITIAL] = CLOSE;
- outputs_[VALID] = RESTORE | OKAY | APPLY | CANCEL;
- outputs_[INVALID] = RESTORE | CANCEL;
-
- // 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_ONLY] = INITIAL;
- state_machine_[INITIAL][SMI_READ_WRITE] = INITIAL;
- state_machine_[INITIAL][SMI_VALID] = VALID;
- state_machine_[INITIAL][SMI_INVALID] = INVALID;
- // State::VALID
- state_machine_[VALID][SMI_VALID] = VALID;
- state_machine_[VALID][SMI_READ_ONLY] = VALID;
- state_machine_[VALID][SMI_READ_WRITE] = VALID;
- state_machine_[VALID][SMI_INVALID] = INVALID;
- state_machine_[VALID][SMI_OKAY] = INITIAL;
- state_machine_[VALID][SMI_APPLY] = INITIAL;
- state_machine_[VALID][SMI_RESTORE] = INITIAL;
- // State::INVALID
- state_machine_[INVALID][SMI_INVALID] = INVALID;
- state_machine_[INVALID][SMI_READ_ONLY] = INVALID;
- state_machine_[INVALID][SMI_READ_WRITE] = INVALID;
- state_machine_[INVALID][SMI_VALID] = VALID;
- state_machine_[INVALID][SMI_RESTORE] = INITIAL;
-}
-
-
-} // namespace frontend
-} // namespace lyx
+++ /dev/null
-// -*- C++ -*-
-/**
- * \file ButtonPolicy.h
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author Allan Rae
- *
- * Full author contact details are available in file CREDITS.
- *
- * Provides a state machine implementation of the various button policies
- * used by the dialogs.
- */
-
-#ifndef BUTTONPOLICY_H
-#define BUTTONPOLICY_H
-
-#include <vector>
-#include <iostream>
-
-namespace lyx {
-namespace frontend {
-
-/** A class for button policies.
- A state machine implementation of the various button policies used by the
- dialogs. Only the policy is implemented here. Separate ButtonController
- classes are needed for each GUI implementation.
-
- Policy | ReadOnly | Apply Button | Repeated Apply
- ========================================================================
- OkCancel | N | N | -
- OkCancelReadOnly | Y | N | -
- OkApplyCancel | N | Y | Y
- OkApplyCancelReadOnly | Y | Y | Y
- NoRepeatedApply | N | Y | N
- NoRepeatedApplyReadOnly | Y | Y | N
- Preferences | N | Y | No (Ok-Close)
- Ignorant | N/A | N/A | N/A
- ========================================================================
-
- Policy
- The name of the policy
- ReadOnly
- Does the policy treat read-only docs differently to read-write docs?
- This usually means that when an SMI_READ_ONLY input arrives then
- all the buttons are disabled except Cancel/Close. The state
- machine tracks the inputs (valid/invalid) and has states for all
- combinations. When an SMI_READ_WRITE input arrives the appropriate
- machine state is entered (just as if the document had always been
- read-write).
- NOTE: If a dialog doesn't care about the read-only status of a document
- (and uses an appropriate policy) it can never get into a read-only state
- so isReadOnly() can only ever return false even though the document may
- be read-only.
- Repeated Apply
- Simply means that it is alright to use the Apply button multiple times
- without requiring a change of the dialog contents. If no repeating is
- allowed the Ok+Apply buttons are deactivated. The Preferences dialog
- has its own special version of repeated apply handling because its Ok
- button is actually a Save button -- it is always reasonable to Save the
- preferences if the dialog has changed since the last save.
-
- The IgnorantPolicy is a special case that allows anything.
- */
-
-class ButtonPolicy {
-public:
-
- // The various poicies
- enum Policy {
- /** Ok and Cancel buttons for dialogs with read-only operation.
- Note: This scheme supports the relabelling of Cancel to Close and
- vice versa.
- This is based on the value of the bool state of the Button::CANCEL.
- true == Cancel, false == Close
- */
- OkCancelPolicy,
-
-
- /** Ok and Cancel buttons for dialogs where read-only operation is blocked.
- The state machine design for this policy allows changes to occur within
- the dialog while a file is read-only -- the okay button is disabled until
- a read-write input is given. When the file is made read-write the dialog
- will then be in the correct state (as if the file had always been
- read-write).
- Note: This scheme supports the relabelling of Cancel to Close
- and vice versa.
- This is based on the value of the bool state of the Button::CANCEL.
- true == Cancel, false == Close
- */
- OkCancelReadOnlyPolicy,
-
- /** Ok, Apply and Cancel buttons for dialogs where read-only operation
- is blocked.
- Repeated Apply are not allowed. Likewise, Ok cannot follow Apply without
- some valid input. That is, the dialog contents must change between
- each Apply or Apply and Ok.
- The state machine design for this policy allows changes to occur within
- the dialog while a file is read-only -- the Ok+Apply buttons are disabled
- until a read-write input is given. When the file is made read-write the
- dialog will then be in the correct state (as if the file had always been
- read-write).
- Note: This scheme supports the relabelling of Cancel to Close
- and vice versa.
- This is based on the value of the bool state of the Button::CANCEL.
- true == Cancel, false == Close
- */
- NoRepeatedApplyReadOnlyPolicy,
-
- /** Ok, Apply and Cancel buttons for dialogs where read-only
- operation is blocked.
- Repeated Apply is allowed. Likewise, Ok can follow Apply.
- The state machine design for this policy allows changes to occur within
- the dialog while a file is read-only -- the Ok+Apply buttons are disabled
- until a read-write input is given. When the file is made read-write the
- dialog will then be in the correct state (as if the file had always been
- read-write).
- Note: This scheme supports the relabelling of Cancel to Close
- and vice versa.
- This is based on the value of the bool state of the Button::CANCEL.
- true == Cancel, false == Close
- */
- OkApplyCancelReadOnlyPolicy,
-
- /** Ok, Apply and Cancel buttons for dialogs where repeated
- * Apply is allowed.
- Note: This scheme supports the relabelling of Cancel to Close
- and vice versa.
- This is based on the value of the bool state of the Button::CANCEL.
- true == Cancel, false == Close
- */
- OkApplyCancelPolicy,
-
- /** Ok, Apply and Cancel buttons for dialogs with no repeated Apply.
- Note: This scheme supports the relabelling of Cancel to Close
- and vice versa.
- This is based on the value of the bool state of the Button::CANCEL.
- true == Cancel, false == Close
- */
- NoRepeatedApplyPolicy,
-
- /** Defines the policy used by the Preferences dialog.
- Four buttons: Ok (Save), Apply, Cancel/Close, Restore.
- Note: This scheme supports the relabelling of Cancel to Close
- and vice versa.
- This is based on the value of the bool state of the Button::CANCEL.
- true == Cancel, false == Close
- */
- PreferencesPolicy,
-
- /** Defines the policy used by dialogs that are forced to support a button
- controller when they either don't have a use for one or are not ready to
- use one. This may be useful when testing a new button policy but wishing
- to minimise problems to users by supplying an anything-goes policy via a
- preprocessor directive.
- */
- IgnorantPolicy,
- };
-
- /// Constructor
- explicit ButtonPolicy(Policy policy);
-
- /** The various possible state names.
- Not all state-machines have this many states. However, we need
- to define them all here so we can share the code.
- */
- enum State {
- ///
- INITIAL = 0,
- ///
- VALID,
- ///
- INVALID,
- ///
- APPLIED,
- ///
- RO_INITIAL,
- ///
- RO_VALID,
- ///
- RO_INVALID,
- ///
- RO_APPLIED,
- ///
- BOGUS = 55
- };
-
- /// The various button types.
- enum Button {
- ///
- CLOSE = 0, // Not a real button, but effectively !CANCEL
- ///
- OKAY = 1,
- ///
- APPLY = 2,
- ///
- CANCEL = 4,
- ///
- RESTORE = 8
- };
- ///
- static const Button ALL_BUTTONS =
- Button(OKAY | APPLY | CANCEL | RESTORE);
-
- /** State machine inputs.
- All the policies so far have both CANCEL and HIDE always going to
- INITIAL. This won't necessarily be true for all [future] policies
- though so I'll leave those two as distinct inputs rather than merge
- them. For example, a dialog that doesn't update it's input fields
- when reshown after being hidden needs a policy where CANCEL and
- HIDE are treated differently.
- */
- enum SMInput {
- /// the dialog contents are now valid
- SMI_VALID = 0,
- /// the dialog contents are now invalid
- SMI_INVALID,
- /// an apply-and-hide action has happened
- SMI_OKAY,
- /// an apply action has happened
- SMI_APPLY,
- /// a cancel action has happened
- SMI_CANCEL,
- /// a restore action has happened
- SMI_RESTORE,
- /// the dialog has been hidden
- SMI_HIDE,
- /// the dialog contents are read-only
- SMI_READ_ONLY,
- /// the dialog contents can be modified
- SMI_READ_WRITE,
- /// the state of the dialog contents has not changed
- SMI_NOOP,
- /// for internal use
- SMI_TOTAL
- };
-
- /// Trigger a transition with this input.
- void input(SMInput);
- /** Activation status of a button.
- We assume that we haven't gotten into an undefined state.
- This is reasonable since we can only reach states defined
- in the state machine and they should all have been defined in
- the outputs_ variable. Perhaps we can do something at compile
- time to check that all the states have corresponding outputs.
- */
- bool buttonStatus(Button) const;
- /// Are we in a read-only state?
- bool isReadOnly() const;
-
-private:
- ///
- 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_;
-
-private:
- // Helpers
- void nextState(SMInput input);
-
- void initOkCancel();
- void initOkCancelReadOnly();
- void initNoRepeatedApplyReadOnly();
- void initOkApplyCancelReadOnly();
- void initOkApplyCancel();
- void initNoRepeatedApply();
- void initPreferences();
-};
-
-
-inline
-std::ostream & operator<<(std::ostream & os, ButtonPolicy::State st)
-{
- return os << int(st);
-}
-
-
-inline
-std::ostream & operator<<(std::ostream & os, ButtonPolicy::SMInput smi)
-{
- return os << int(smi);
-}
-
-
-} // namespace frontend
-} // namespace lyx
-
-#endif
+++ /dev/null
-/**
- * \file Dialog.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author Angus Leeming
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "Dialog.h"
-
-#include "FuncRequest.h"
-#include "FuncStatus.h"
-#include "LyXFunc.h"
-
-#include "frontends/LyXView.h"
-#include "frontends/Dialogs.h" // FIXME
-
-#include "Buffer.h"
-
-
-namespace lyx {
-namespace frontend {
-
-
-Dialog::~Dialog()
-{}
-
-
-Controller::Controller(Dialog & parent)
- : parent_(parent), lyxview_(0)
-{}
-
-
-Controller::Controller(Dialog * parent)
- : parent_(*parent), lyxview_(0)
-{}
-
-
-Controller::~Controller()
-{}
-
-
-bool Controller::canApply() const
-{
- FuncRequest const fr(getLfun(), dialog().name());
- FuncStatus const fs(getStatus(fr));
- return fs.enabled();
-}
-
-
-void Controller::dispatch(FuncRequest const & fr) const
-{
- lyxview_->dispatch(fr);
-}
-
-
-void Controller::updateDialog(std::string const & name) const
-{
- dispatch(FuncRequest(LFUN_DIALOG_UPDATE, name));
-}
-
-
-void Controller::disconnect(std::string const & name) const
-{
- lyxview_->getDialogs().disconnect(name);
-}
-
-
-bool Controller::isBufferAvailable() const
-{
- return lyxview_->buffer() != 0;
-}
-
-
-bool Controller::isBufferReadonly() const
-{
- if (!lyxview_->buffer())
- return true;
- return lyxview_->buffer()->isReadonly();
-}
-
-
-std::string const Controller::bufferFilepath() const
-{
- return buffer().filePath();
-}
-
-
-KernelDocType Controller::docType() const
-{
- if (buffer().isLatex())
- return LATEX;
- if (buffer().isLiterate())
- return LITERATE;
-
- return DOCBOOK;
-}
-
-
-BufferView * Controller::bufferview()
-{
- return lyxview_->view();
-}
-
-
-BufferView const * Controller::bufferview() const
-{
- return lyxview_->view();
-}
-
-
-Buffer & Controller::buffer()
-{
- BOOST_ASSERT(lyxview_->buffer());
- return *lyxview_->buffer();
-}
-
-
-Buffer const & Controller::buffer() const
-{
- BOOST_ASSERT(lyxview_->buffer());
- return *lyxview_->buffer();
-}
-
-} // namespace frontend
-} // namespace lyx
+++ /dev/null
-// -*- C++ -*-
-/**
- * \file Dialog.h
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author Angus Leeming
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#ifndef DIALOG_H
-#define DIALOG_H
-
-#include "lfuns.h"
-
-#include "support/docstring.h"
-#include <string>
-
-namespace lyx {
-
-class Buffer;
-class BufferView;
-class FuncRequest;
-
-namespace frontend {
-
-class LyXView;
-
-/** \enum KernelDocType used to flag the different kinds of buffer
- * without making the kernel header files available to the
- * dialog's Controller or View.
- */
-enum KernelDocType
-{
- LATEX,
- LITERATE,
- DOCBOOK
-};
-
-
-/** Different dialogs will have different Controllers and Views.
- * deriving from these base classes.
- */
-//@{
-class Controller;
-//@}
-
-/** \c Dialog collects the different parts of a Model-Controller-View
- * split of a generic dialog together.
- */
-class Dialog
-{
-public:
- /// \param lv is the access point for the dialog to the LyX kernel.
- /// \param name is the identifier given to the dialog by its parent
- /// container.
- Dialog() {}
- virtual ~Dialog();
-
- /** \name Container Access
- * These methods are publicly accessible because they are invoked
- * by the parent container acting on commands from the LyX kernel.
- */
- //@{
- /// \param data is a string encoding of the data to be displayed.
- /// It is passed to the Controller to be translated into a useable form.
- virtual void showData(std::string const & /*data*/) {}
- virtual void updateData(std::string const & /*data*/) {}
-
- virtual void hide() {}
-
- // Override in GuiDialog
- virtual void slotOK() {}
- virtual void slotApply() {}
- virtual void slotRestore() {}
- virtual void slotClose() {}
-
- /** This function is called, for example, if the GUI colours
- * have been changed.
- */
- virtual void redraw() {}
- //@}
-
- /** Check whether we may apply our data.
- *
- * The buttons are disabled if not and (re-)enabled if yes.
- */
- virtual void checkStatus() {}
-
- /** When applying, it's useful to know whether the dialog is about
- * to close or not (no point refreshing the display for example).
- */
- virtual bool isClosing() const { return false; }
-
- /** \name Dialog Specialization
- * Methods to set the Controller and View and so specialise
- * to a particular dialog.
- */
- //@{
- virtual Controller & controller() = 0;
- //@}
-
- /** \c Button controller part
- */
- virtual void setButtonsValid(bool /*valid*/) {}
-
-
- /** \c View part
- * of a Model-Controller-View split of a generic dialog.
- * These few methods are all that a generic dialog needs of a
- * view.
- */
- //@{
- /** A request to modify the data structures stored by the
- * accompanying Controller in preparation for their dispatch to
- * the LyX kernel.
- */
- virtual void applyView() = 0;
-
- /// Hide the dialog from sight
- virtual void hideView() = 0;
-
- /// Redraw the dialog (e.g. if the colors have been remapped).
- virtual void redrawView() = 0;
-
- /// Create the dialog if necessary, update it and display it.
- virtual void showView() = 0;
-
- /// Update the display of the dialog whilst it is still visible.
- virtual void updateView() = 0;
-
- /// \return true if the dialog is visible.
- virtual bool isVisibleView() const = 0;
- //@}
-
- /** Defaults to nothing. Can be used by the Controller, however, to
- * indicate to the View that something has changed and that the
- * dialog therefore needs updating.
- * \param id identifies what should be updated.
- */
- virtual void partialUpdateView(int /*id*/) = 0;
-
- ///
- virtual std::string name() const = 0;
-
-protected:
- virtual void apply() {}
-
-private:
- /// intentionally unimplemented, therefore uncopiable
- Dialog(Dialog const &);
- void operator=(Dialog const &);
-};
-
-
-/** \c Controller is an abstract base class for the Controller
- * of a Model-Controller-View split of a generic dialog.
- */
-class Controller
-{
-public:
- /// \param parent Dialog owning this Controller.
- Controller(Dialog & parent);
- // the same. avoids ambiguity with the (non-existent) copy constructor
- Controller(Dialog * parent);
- virtual ~Controller();
- void setLyXView(LyXView & lv) { lyxview_ = &lv; }
-
- /** \name Generic Controller
- * These few methods are all that a generic dialog needs of a
- * controller.
- */
- //@{
- /** Enable the controller to initialise its data structures.
- * \param data is a string encoding of the parameters to be displayed.
- * \return true if the translation was successful.
- */
- virtual bool initialiseParams(std::string const & data) = 0;
-
- /// Enable the controller to clean up its data structures.
- virtual void clearParams() = 0;
-
- /// Enable the Controller to dispatch its data back to the LyX kernel.
- virtual void dispatchParams() = 0;
-
- /** \return true if the dialog should be shown only when
- * a buffer is open.
- */
- virtual bool isBufferDependent() const = 0;
-
- /** \return true if the dialog can apply data also
- * for ReadOnly buffers.
- * This has to be distinguished from isBufferDependent()
- */
- virtual bool canApplyToReadOnly() const { return false; }
-
- /** The lfun that is sent for applying the data.
- *
- * This method is used by the default implementation of canApply()
- * for buffer dependent dialogs that send one lfun when applying the
- * data.
- * It should be used in dispatchParams(), too for consistency reasons.
- * \returns the lfun that is sent for applying the data.
- */
- virtual kb_action getLfun() const { return LFUN_INSET_APPLY; }
-
- /** Check whether we may apply our data.
- *
- * The default implementation works for all dialogs that send one
- * lfun when applying the data. Dialogs that send none or more than
- * one lfun need to reimplement it.
- * \returns whether the data can be applied or not.
- */
- virtual bool canApply() const;
-
- /** \return true if the kernel should disconnect the dialog from
- * a particular inset after the data has been applied to it.
- * Clearly this makes sense only for dialogs modifying the contents
- * of an inset :-)
- * In practise, only a very few dialogs (e.g. the citation dialog)
- * return true.
- */
- virtual bool disconnectOnApply() const { return false; }
-
- /** \return true if Dialog::View::show() should not display the dialog
- * after running update. Currently, only ControlSpellchecker
- * makes use of that.
- */
- virtual bool exitEarly() const { return false; }
- //@}
-public:
- /** \name Controller Access
- * Enable the derived classes to access the other parts of the whole.
- */
- //@{
- Dialog & dialog() { return parent_; }
- Dialog const & dialog() const { return parent_; }
- //@}
-
- /** \c Kernel part: a wrapper making the LyX kernel available to the dialog.
- * (Ie, it provides an interface to the Model part of the Model-Controller-
- * View split.
- * In an ideal world, it will shrink as more info is passed to the
- * Dialog::show() and Dialog::update() methods.
- */
-
-
- /** This method is the primary purpose of the class. It provides
- * the "gateway" by which the dialog can send a request (of a
- * change in the data, for more information) to the kernel.
- * \param fr is the encoding of the request.
- */
- void dispatch(FuncRequest const & fr) const;
-
- /** The dialog has received a request from the user
- * (who pressed the "Restore" button) to update contents.
- * It must, therefore, ask the kernel to provide this information.
- * \param name is used to identify the dialog to the kernel.
- */
- void updateDialog(std::string const & name) const;
-
- /** A request from the Controller that future changes to the data
- * stored by the dialog are not applied to the inset currently
- * connected to the dialog. Instead, they will be used to generate
- * a new inset at the cursor position.
- * \param name is used to identify the dialog to the kernel.
- */
- void disconnect(std::string const & name) const;
-
- /** \name Kernel Wrappers
- * Simple wrapper functions to Buffer methods.
- */
- //@{
- bool isBufferAvailable() const;
- bool isBufferReadonly() const;
- std::string const bufferFilepath() const;
- //@}
-
- /// The type of the current buffer.
- KernelDocType docType() const;
-
- /** \name Kernel Nasties
- * Unpleasantly public internals of the LyX kernel.
- * We should aim to reduce/remove these from the interface.
- */
- //@{
- LyXView & lyxview() { return *lyxview_; }
- LyXView const & lyxview() const { return *lyxview_; }
-
- Buffer & buffer();
- Buffer const & buffer() const;
-
- BufferView * bufferview();
- BufferView const * bufferview() const;
- //@}
-
-private:
- /// intentionally unimplemented, therefore uncopiable
- Controller(Controller const &);
- void operator=(Controller const &);
-
-private:
- Dialog & parent_;
- LyXView * lyxview_;
-};
-
-
-} // namespace frontend
-} // namespace lyx
-
-#endif // DIALOG_H
noinst_LTLIBRARIES = liblyxcontrollers.la
-SOURCEFILES = \
- Dialog.cpp \
- ButtonPolicy.cpp \
- frontend_helpers.cpp
-
-HEADERFILES = \
- Dialog.h \
- ButtonPolicy.h \
- frontend_helpers.h
+SOURCEFILES =
+
+HEADERFILES =
if MONOLITHIC_CONTROLLERS
+++ /dev/null
-/**
- * \file frontend_helpers.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author Angus Leeming
- * \author Herbert Voß
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "frontend_helpers.h"
-
-#include "gettext.h"
-#include "Language.h"
-
-#include "frontends/FileDialog.h"
-#include "frontends/alert.h"
-
-#include "support/filetools.h"
-#include "support/lstrings.h"
-#include "support/lyxalgo.h"
-#include "support/os.h"
-#include "support/Package.h"
-#include "support/Path.h"
-#include "support/Systemcall.h"
-
-#include <boost/cregex.hpp>
-
-#include <algorithm>
-#include <fstream>
-
-using std::string;
-using std::vector;
-using std::pair;
-using std::endl;
-
-namespace lyx {
-namespace frontend {
-
-using support::addName;
-using support::bformat;
-using support::FileFilterList;
-using support::FileName;
-using support::getExtension;
-using support::getFileContents;
-using support::getVectorFromString;
-using support::libFileSearch;
-using support::makeAbsPath;
-using support::makeRelPath;
-using support::onlyFilename;
-using support::onlyPath;
-using support::package;
-using support::prefixIs;
-using support::quoteName;
-using support::removeExtension;
-using support::Systemcall;
-using support::token;
-
-
-namespace {
-
-struct Sorter
-{
- bool operator()(LanguagePair const & lhs, LanguagePair const & rhs) const {
- return lhs.first < rhs.first;
- }
-};
-
-
-} // namespace anon
-
-
-vector<LanguagePair> const getLanguageData(bool character_dlg)
-{
- vector<LanguagePair>::size_type const size = character_dlg ?
- languages.size() + 2 : languages.size();
-
- vector<LanguagePair> langs(size);
-
- if (character_dlg) {
- langs[0].first = _("No change");
- langs[0].second = "ignore";
- langs[1].first = _("Reset");
- langs[1].second = "reset";
- }
-
- vector<string>::size_type i = character_dlg ? 2 : 0;
- for (Languages::const_iterator cit = languages.begin();
- cit != languages.end(); ++cit) {
- langs[i].first = _(cit->second.display());
- langs[i].second = cit->second.lang();
- ++i;
- }
-
- // Don't sort "ignore" and "reset"
- vector<LanguagePair>::iterator begin = character_dlg ?
- langs.begin() + 2 : langs.begin();
-
- std::sort(begin, langs.end(), Sorter());
-
- return langs;
-}
-
-
-docstring const browseFile(docstring const & filename,
- docstring const & title,
- FileFilterList const & filters,
- bool save,
- pair<docstring,docstring> const & dir1,
- pair<docstring,docstring> const & dir2)
-{
- docstring lastPath = from_ascii(".");
- if (!filename.empty())
- lastPath = from_utf8(onlyPath(to_utf8(filename)));
-
- FileDialog fileDlg(title, LFUN_SELECT_FILE_SYNC, dir1, dir2);
-
- FileDialog::Result result;
-
- if (save)
- result = fileDlg.save(lastPath, filters,
- from_utf8(onlyFilename(to_utf8(filename))));
- else
- result = fileDlg.open(lastPath, filters,
- from_utf8(onlyFilename(to_utf8(filename))));
-
- return result.second;
-}
-
-
-docstring const browseRelFile(docstring const & filename,
- docstring const & refpath,
- docstring const & title,
- FileFilterList const & filters,
- bool save,
- pair<docstring,docstring> const & dir1,
- pair<docstring,docstring> const & dir2)
-{
- docstring const fname = from_utf8(makeAbsPath(
- to_utf8(filename), to_utf8(refpath)).absFilename());
-
- docstring const outname = browseFile(fname, title, filters, save,
- dir1, dir2);
- docstring const reloutname = makeRelPath(outname, refpath);
- if (prefixIs(reloutname, from_ascii("../")))
- return outname;
- else
- return reloutname;
-}
-
-
-docstring const browseLibFile(docstring const & dir,
- docstring const & name,
- docstring const & ext,
- docstring const & title,
- FileFilterList const & filters)
-{
- // FIXME UNICODE
- pair<docstring, docstring> const dir1(_("System files|#S#s"),
- from_utf8(addName(package().system_support().absFilename(), to_utf8(dir))));
-
- pair<docstring, docstring> const dir2(_("User files|#U#u"),
- from_utf8(addName(package().user_support().absFilename(), to_utf8(dir))));
-
- docstring const result = browseFile(from_utf8(
- libFileSearch(to_utf8(dir), to_utf8(name), to_utf8(ext)).absFilename()),
- title, filters, false, dir1, dir2);
-
- // remove the extension if it is the default one
- docstring noextresult;
- if (from_utf8(getExtension(to_utf8(result))) == ext)
- noextresult = from_utf8(removeExtension(to_utf8(result)));
- else
- noextresult = result;
-
- // remove the directory, if it is the default one
- docstring const file = from_utf8(onlyFilename(to_utf8(noextresult)));
- if (from_utf8(libFileSearch(to_utf8(dir), to_utf8(file), to_utf8(ext)).absFilename()) == result)
- return file;
- else
- return noextresult;
-}
-
-
-docstring const browseDir(docstring const & pathname,
- docstring const & title,
- pair<docstring,docstring> const & dir1,
- pair<docstring,docstring> const & dir2)
-{
- docstring lastPath = from_ascii(".");
- if (!pathname.empty())
- lastPath = from_utf8(onlyPath(to_utf8(pathname)));
-
- FileDialog fileDlg(title, LFUN_SELECT_FILE_SYNC, dir1, dir2);
-
- FileDialog::Result const result =
- fileDlg.opendir(lastPath, from_utf8(onlyFilename(to_utf8(pathname))));
-
- return result.second;
-}
-
-
-void rescanTexStyles()
-{
- // Run rescan in user lyx directory
- support::Path p(package().user_support());
- FileName const command = libFileSearch("scripts", "TeXFiles.py");
- Systemcall one;
- int const status = one.startscript(Systemcall::Wait,
- lyx::support::os::python() + ' ' +
- quoteName(command.toFilesystemEncoding()));
- if (status == 0)
- return;
- // FIXME UNICODE
- Alert::error(_("Could not update TeX information"),
- bformat(_("The script `%s' failed."), from_utf8(command.absFilename())));
-}
-
-
-void getTexFileList(string const & filename, std::vector<string> & list)
-{
- list.clear();
- FileName const file = libFileSearch("", filename);
- if (file.empty())
- return;
-
- list = getVectorFromString(getFileContents(file), "\n");
-
- // Normalise paths like /foo//bar ==> /foo/bar
- boost::RegEx regex("/{2,}");
- std::vector<string>::iterator it = list.begin();
- std::vector<string>::iterator end = list.end();
- for (; it != end; ++it)
- *it = regex.Merge((*it), "/");
-
- // remove empty items and duplicates
- list.erase(std::remove(list.begin(), list.end(), ""), list.end());
- eliminate_duplicates(list);
-}
-
-} // namespace frontend
-} // namespace lyx
+++ /dev/null
-// -*- C++ -*-
-/**
- * \file frontend_helpers.h
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author Angus Leeming
- * \author Herbert Voß
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#ifndef FRONTEND_HELPERS_H
-#define FRONTEND_HELPERS_H
-
-#include "support/docstring.h"
-
-#include <utility>
-#include <vector>
-#include <string>
-
-namespace lyx {
-
-namespace support { class FileFilterList; }
-
-namespace frontend {
-
-///
-typedef std::pair<docstring, std::string> LanguagePair;
-
-/** If the caller is the character dialog, add "No change" and "Reset"
-* to the vector.
-*/
-std::vector<LanguagePair> const getLanguageData(bool character_dlg);
-
-/** Launch a file dialog and return the chosen file.
- filename: a suggested filename.
- title: the title of the dialog.
- pattern: *.ps etc.
- dir1 = (name, dir), dir2 = (name, dir): extra buttons on the dialog.
-*/
-docstring const
-browseFile(docstring const & filename,
- docstring const & title,
- support::FileFilterList const & filters,
- bool save = false,
- std::pair<docstring, docstring> const & dir1 =
- std::make_pair(docstring(), docstring()),
- std::pair<docstring, docstring> const & dir2 =
- std::make_pair(docstring(), docstring()));
-
-
-/** Wrapper around browseFile which tries to provide a filename
- relative to relpath. If the relative path is of the form "foo.txt"
- or "bar/foo.txt", then it is returned as relative. OTOH, if it is
- of the form "../baz/foo.txt", an absolute path is returned. This is
- intended to be useful for insets which encapsulate files/
-*/
-docstring const
-browseRelFile(docstring const & filename,
- docstring const & refpath,
- docstring const & title,
- support::FileFilterList const & filters,
- bool save = false,
- std::pair<docstring, docstring> const & dir1 =
- std::make_pair(docstring(), docstring()),
- std::pair<docstring, docstring> const & dir2 =
- std::make_pair(docstring(), docstring()));
-
-
-/** Wrapper around browseFile which tries to provide a filename
-* relative to the user or system directory. The dir, name and ext
-* parameters have the same meaning as in the
-* support::LibFileSearch function.
-*/
-docstring const
-browseLibFile(docstring const & dir,
- docstring const & name,
- docstring const & ext,
- docstring const & title,
- support::FileFilterList const & filters);
-
-
-/** Launch a file dialog and return the chosen directory.
- pathname: a suggested pathname.
- title: the title of the dialog.
- dir1 = (name, dir), dir2 = (name, dir): extra buttons on the dialog.
-*/
-docstring const
-browseDir(docstring const & pathname,
- docstring const & title,
- std::pair<docstring, docstring> const & dir1 =
- std::make_pair(docstring(), docstring()),
- std::pair<docstring, docstring> const & dir2 =
- std::make_pair(docstring(), docstring()));
-
-
-/** Build filelists of all availabe bst/cls/sty-files. Done through
-* kpsewhich and an external script, saved in *Files.lst.
-*/
-void rescanTexStyles();
-
-/** Fill \c contents from one of the three texfiles.
- * Each entry in the file list is returned as a name_with_path
- */
-void getTexFileList(std::string const & filename, std::vector<std::string> & contents);
-
-} // namespace frontend
-} // namespace lyx
-
-#endif // FRONTEND_HELPERS_H
--- /dev/null
+/**
+ * \file frontend_helpers.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Angus Leeming
+ * \author Herbert Voß
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "frontend_helpers.h"
+
+#include "gettext.h"
+#include "Language.h"
+
+#include "frontends/FileDialog.h"
+#include "frontends/alert.h"
+
+#include "support/filetools.h"
+#include "support/lstrings.h"
+#include "support/lyxalgo.h"
+#include "support/os.h"
+#include "support/Package.h"
+#include "support/Path.h"
+#include "support/Systemcall.h"
+
+#include <boost/cregex.hpp>
+
+#include <algorithm>
+#include <fstream>
+
+using std::string;
+using std::vector;
+using std::pair;
+using std::endl;
+
+namespace lyx {
+namespace frontend {
+
+using support::addName;
+using support::bformat;
+using support::FileFilterList;
+using support::FileName;
+using support::getExtension;
+using support::getFileContents;
+using support::getVectorFromString;
+using support::libFileSearch;
+using support::makeAbsPath;
+using support::makeRelPath;
+using support::onlyFilename;
+using support::onlyPath;
+using support::package;
+using support::prefixIs;
+using support::quoteName;
+using support::removeExtension;
+using support::Systemcall;
+using support::token;
+
+
+namespace {
+
+struct Sorter
+{
+ bool operator()(LanguagePair const & lhs, LanguagePair const & rhs) const {
+ return lhs.first < rhs.first;
+ }
+};
+
+
+} // namespace anon
+
+
+vector<LanguagePair> const getLanguageData(bool character_dlg)
+{
+ vector<LanguagePair>::size_type const size = character_dlg ?
+ languages.size() + 2 : languages.size();
+
+ vector<LanguagePair> langs(size);
+
+ if (character_dlg) {
+ langs[0].first = _("No change");
+ langs[0].second = "ignore";
+ langs[1].first = _("Reset");
+ langs[1].second = "reset";
+ }
+
+ vector<string>::size_type i = character_dlg ? 2 : 0;
+ for (Languages::const_iterator cit = languages.begin();
+ cit != languages.end(); ++cit) {
+ langs[i].first = _(cit->second.display());
+ langs[i].second = cit->second.lang();
+ ++i;
+ }
+
+ // Don't sort "ignore" and "reset"
+ vector<LanguagePair>::iterator begin = character_dlg ?
+ langs.begin() + 2 : langs.begin();
+
+ std::sort(begin, langs.end(), Sorter());
+
+ return langs;
+}
+
+
+docstring const browseFile(docstring const & filename,
+ docstring const & title,
+ FileFilterList const & filters,
+ bool save,
+ pair<docstring,docstring> const & dir1,
+ pair<docstring,docstring> const & dir2)
+{
+ docstring lastPath = from_ascii(".");
+ if (!filename.empty())
+ lastPath = from_utf8(onlyPath(to_utf8(filename)));
+
+ FileDialog fileDlg(title, LFUN_SELECT_FILE_SYNC, dir1, dir2);
+
+ FileDialog::Result result;
+
+ if (save)
+ result = fileDlg.save(lastPath, filters,
+ from_utf8(onlyFilename(to_utf8(filename))));
+ else
+ result = fileDlg.open(lastPath, filters,
+ from_utf8(onlyFilename(to_utf8(filename))));
+
+ return result.second;
+}
+
+
+docstring const browseRelFile(docstring const & filename,
+ docstring const & refpath,
+ docstring const & title,
+ FileFilterList const & filters,
+ bool save,
+ pair<docstring,docstring> const & dir1,
+ pair<docstring,docstring> const & dir2)
+{
+ docstring const fname = from_utf8(makeAbsPath(
+ to_utf8(filename), to_utf8(refpath)).absFilename());
+
+ docstring const outname = browseFile(fname, title, filters, save,
+ dir1, dir2);
+ docstring const reloutname = makeRelPath(outname, refpath);
+ if (prefixIs(reloutname, from_ascii("../")))
+ return outname;
+ else
+ return reloutname;
+}
+
+
+docstring const browseLibFile(docstring const & dir,
+ docstring const & name,
+ docstring const & ext,
+ docstring const & title,
+ FileFilterList const & filters)
+{
+ // FIXME UNICODE
+ pair<docstring, docstring> const dir1(_("System files|#S#s"),
+ from_utf8(addName(package().system_support().absFilename(), to_utf8(dir))));
+
+ pair<docstring, docstring> const dir2(_("User files|#U#u"),
+ from_utf8(addName(package().user_support().absFilename(), to_utf8(dir))));
+
+ docstring const result = browseFile(from_utf8(
+ libFileSearch(to_utf8(dir), to_utf8(name), to_utf8(ext)).absFilename()),
+ title, filters, false, dir1, dir2);
+
+ // remove the extension if it is the default one
+ docstring noextresult;
+ if (from_utf8(getExtension(to_utf8(result))) == ext)
+ noextresult = from_utf8(removeExtension(to_utf8(result)));
+ else
+ noextresult = result;
+
+ // remove the directory, if it is the default one
+ docstring const file = from_utf8(onlyFilename(to_utf8(noextresult)));
+ if (from_utf8(libFileSearch(to_utf8(dir), to_utf8(file), to_utf8(ext)).absFilename()) == result)
+ return file;
+ else
+ return noextresult;
+}
+
+
+docstring const browseDir(docstring const & pathname,
+ docstring const & title,
+ pair<docstring,docstring> const & dir1,
+ pair<docstring,docstring> const & dir2)
+{
+ docstring lastPath = from_ascii(".");
+ if (!pathname.empty())
+ lastPath = from_utf8(onlyPath(to_utf8(pathname)));
+
+ FileDialog fileDlg(title, LFUN_SELECT_FILE_SYNC, dir1, dir2);
+
+ FileDialog::Result const result =
+ fileDlg.opendir(lastPath, from_utf8(onlyFilename(to_utf8(pathname))));
+
+ return result.second;
+}
+
+
+void rescanTexStyles()
+{
+ // Run rescan in user lyx directory
+ support::Path p(package().user_support());
+ FileName const command = libFileSearch("scripts", "TeXFiles.py");
+ Systemcall one;
+ int const status = one.startscript(Systemcall::Wait,
+ lyx::support::os::python() + ' ' +
+ quoteName(command.toFilesystemEncoding()));
+ if (status == 0)
+ return;
+ // FIXME UNICODE
+ Alert::error(_("Could not update TeX information"),
+ bformat(_("The script `%s' failed."), from_utf8(command.absFilename())));
+}
+
+
+void getTexFileList(string const & filename, std::vector<string> & list)
+{
+ list.clear();
+ FileName const file = libFileSearch("", filename);
+ if (file.empty())
+ return;
+
+ list = getVectorFromString(getFileContents(file), "\n");
+
+ // Normalise paths like /foo//bar ==> /foo/bar
+ boost::RegEx regex("/{2,}");
+ std::vector<string>::iterator it = list.begin();
+ std::vector<string>::iterator end = list.end();
+ for (; it != end; ++it)
+ *it = regex.Merge((*it), "/");
+
+ // remove empty items and duplicates
+ list.erase(std::remove(list.begin(), list.end(), ""), list.end());
+ eliminate_duplicates(list);
+}
+
+} // namespace frontend
+} // namespace lyx
--- /dev/null
+// -*- C++ -*-
+/**
+ * \file frontend_helpers.h
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Angus Leeming
+ * \author Herbert Voß
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#ifndef FRONTEND_HELPERS_H
+#define FRONTEND_HELPERS_H
+
+#include "support/docstring.h"
+
+#include <utility>
+#include <vector>
+#include <string>
+
+namespace lyx {
+
+namespace support { class FileFilterList; }
+
+namespace frontend {
+
+///
+typedef std::pair<docstring, std::string> LanguagePair;
+
+/** If the caller is the character dialog, add "No change" and "Reset"
+* to the vector.
+*/
+std::vector<LanguagePair> const getLanguageData(bool character_dlg);
+
+/** Launch a file dialog and return the chosen file.
+ filename: a suggested filename.
+ title: the title of the dialog.
+ pattern: *.ps etc.
+ dir1 = (name, dir), dir2 = (name, dir): extra buttons on the dialog.
+*/
+docstring const
+browseFile(docstring const & filename,
+ docstring const & title,
+ support::FileFilterList const & filters,
+ bool save = false,
+ std::pair<docstring, docstring> const & dir1 =
+ std::make_pair(docstring(), docstring()),
+ std::pair<docstring, docstring> const & dir2 =
+ std::make_pair(docstring(), docstring()));
+
+
+/** Wrapper around browseFile which tries to provide a filename
+ relative to relpath. If the relative path is of the form "foo.txt"
+ or "bar/foo.txt", then it is returned as relative. OTOH, if it is
+ of the form "../baz/foo.txt", an absolute path is returned. This is
+ intended to be useful for insets which encapsulate files/
+*/
+docstring const
+browseRelFile(docstring const & filename,
+ docstring const & refpath,
+ docstring const & title,
+ support::FileFilterList const & filters,
+ bool save = false,
+ std::pair<docstring, docstring> const & dir1 =
+ std::make_pair(docstring(), docstring()),
+ std::pair<docstring, docstring> const & dir2 =
+ std::make_pair(docstring(), docstring()));
+
+
+/** Wrapper around browseFile which tries to provide a filename
+* relative to the user or system directory. The dir, name and ext
+* parameters have the same meaning as in the
+* support::LibFileSearch function.
+*/
+docstring const
+browseLibFile(docstring const & dir,
+ docstring const & name,
+ docstring const & ext,
+ docstring const & title,
+ support::FileFilterList const & filters);
+
+
+/** Launch a file dialog and return the chosen directory.
+ pathname: a suggested pathname.
+ title: the title of the dialog.
+ dir1 = (name, dir), dir2 = (name, dir): extra buttons on the dialog.
+*/
+docstring const
+browseDir(docstring const & pathname,
+ docstring const & title,
+ std::pair<docstring, docstring> const & dir1 =
+ std::make_pair(docstring(), docstring()),
+ std::pair<docstring, docstring> const & dir2 =
+ std::make_pair(docstring(), docstring()));
+
+
+/** Build filelists of all availabe bst/cls/sty-files. Done through
+* kpsewhich and an external script, saved in *Files.lst.
+*/
+void rescanTexStyles();
+
+/** Fill \c contents from one of the three texfiles.
+ * Each entry in the file list is returned as a name_with_path
+ */
+void getTexFileList(std::string const & filename, std::vector<std::string> & contents);
+
+} // namespace frontend
+} // namespace lyx
+
+#endif // FRONTEND_HELPERS_H
#include "GuiDialog.h"
#include "ui_BibitemUi.h"
-#include "controllers/Dialog.h"
-
#include "insets/InsetCommandParams.h"
namespace lyx {