#ifndef NCL_NXS_META_CMD_OPTIONS_H #define NCL_NXS_META_CMD_OPTIONS_H #include "phycas/phycas.h" #include "ncl/nxs_defs.hpp" #include "ncl/command/nxs_command_decl.hpp" #include "ncl/command/nxs_cmd_param.hpp" #include #if defined TEMPLATED_MIXED_CMD_OPTION # error TEMPLATED version is old (does not handle a vector of sub-options) /*---------------------------------------------------------------------------------------------------------------------- | used to hold user options that can be one of multiple types (e.g. kappa = 3.0 or kappa = estimate) | */ template class NxsMixedCmdOption : public NxsCmdOption { public : virtual std::string GetCurrentValueAsString() const = 0; virtual VecString GetLegalChoices() const; virtual std::string GetDisplayType(bool includeIndefiniteArticle = false, bool plural = false) const; virtual bool AbbreviateChoices(); //base class does nothing - only choice commands do something substantive bool IsCurrentlyValid(); virtual void StorePreviousValue(readStatus); virtual bool ReadValue(NxsToken &token, bool equalsAlreadyRead = false); void ReturnValueToDefault(); virtual void RevertValueBecauseCommandFailed(); void TryToRead(NxsToken &token, bool equalsAlreadyRead); NxsMixedCmdOption(const std::string &n, boost::shared_ptr firstSub, boost::shared_ptr sectSub, bool persist, CmdPermissionLevel pLevel ); protected: boost::shared_ptr firstSubOption; boost::shared_ptr secondSubOption; bool useFirst; bool useFirstBefCmd; bool defaultUseFirst; }; template inline NxsMixedCmdOption ::NxsMixedCmdOption( const std::string &n, boost::shared_ptr firstSub, boost::shared_ptr sectSub, bool persist, CmdPermissionLevel pLevel) :NxsCmdOption(n, persist, pLevel), firstSubOption(firstSub), secondSubOption(sectSub), useFirst(true), useFirstBefCmd(true), defaultUseFirst(true) { } template std::string NxsMixedCmdOption ::GetCurrentValueAsString() const { if (useFirst) return firstSubOption->GetCurrentValueAsString(); else return secondSubOption->GetCurrentValueAsString(); } template std::string NxsMixedCmdOption ::GetDisplayType(bool indef, bool plural) const { std::string retVal = firstSubOption->GetDisplayType(indef, plural); retVal << " or " << secondSubOption->GetDisplayType(indef, plural); return retVal; } template bool NxsMixedCmdOption ::AbbreviateChoices() { return (firstSubOption->AbbreviateChoices() && secondSubOption->AbbreviateChoices()); } template bool NxsMixedCmdOption::IsCurrentlyValid() { NxsCmdOption *subToUse = ( useFirst ? firstSubOption.get() : secondSubOption.get()); if (!subToUse->IsCurrentlyValid()) { const std::string &eSnip = subToUse->GetErrorSnippet(); FlagError(subToUse->GetErrorState(), eSnip); return false; } return true; } template void NxsMixedCmdOption ::StorePreviousValue(readStatus nextStatus) { useFirstBefCmd = useFirst; firstSubOption->PrepareToRead(); secondSubOption->PrepareToRead(); } template bool NxsMixedCmdOption::ReadValue( NxsToken &token, /* the stream of tokens that are being read */ bool equalsAlreadyRead) /* true if the equals sign has already been removed from the token stream (or is NOT expected) */ { useFirst = true; NxsTokenizerState b = token.GetTokenizerState(); if (!firstSubOption->ReadValue(token, equalsAlreadyRead)) { token.SeekTokenizerState(b); if (!secondSubOption->ReadValue(token, equalsAlreadyRead)) return false; else useFirst = false; } return WasValidRead(); } template void NxsMixedCmdOption ::RevertValueBecauseCommandFailed() { useFirst = useFirstBefCmd; firstSubOption->RevertBecauseCommandFailed(); secondSubOption->RevertBecauseCommandFailed(); } template void NxsMixedCmdOption ::ReturnValueToDefault() { useFirst = defaultUseFirst; if (useFirst) firstSubOption->ReturnToDefault(); else secondSubOption->ReturnToDefault(); } #else /*---------------------------------------------------------------------------------------------------------------------- | used to hold user options that can be one of multiple types (e.g. kappa = 3.0 or kappa = estimate) | */ class NxsMixedCmdOption : public NxsCmdOption { public : NxsMixedCmdOption(const std::string &n, unsigned *optIndex, unsigned defIndex, VecNxsCmdOptionShPtr suboptionVec, bool persist, CmdPermissionLevel pLevel ); std::string GetCurrentValueAsString() const; VecString GetLegalChoices() const; std::string GetDisplayType(bool includeIndefiniteArticle = false, bool plural = false) const; VecString GetValidArgument(); bool AbbreviateChoices(); //base class does nothing - only choice commands do something substantive bool IsCurrentlyValid(); void StorePreviousValue(); bool ReadValue(NxsToken &token, bool equalsAlreadyRead = false); void ReturnValueToDefault(); void RevertValueBecauseCommandFailed(); void TryToRead(NxsToken &token, bool equalsAlreadyRead); virtual void WriteTypeInfoStateElement(NxsHiddenQueryStream & outStream) const; protected: unsigned * const subOptionIndex; VecNxsCmdOptionShPtr subOptVector; unsigned indexBefCmd; unsigned defaultIndex; }; #endif //TEMPLATED_MIXED_CMD_OPTION #endif