implement state reset handlers / mock handlers

This commit is contained in:
Fischlurch 2016-02-14 03:42:10 +01:00
parent afeedfc288
commit 18b6a388a0
6 changed files with 210 additions and 71 deletions

View file

@ -64,57 +64,67 @@ namespace model {
virtual bool
doReset() override
{
UNIMPLEMENTED ("reset");
UNIMPLEMENTED ("Controller reset");
}
virtual bool
doExpand (bool yes) override
{
UNIMPLEMENTED ("mock doExpand");
UNIMPLEMENTED ("Controller doExpand");
}
virtual void
doReveal (ID child) override
{
UNIMPLEMENTED ("mock doReveal");
UNIMPLEMENTED ("Controller doReveal");
}
virtual void
doRevealYourself() override
{
UNIMPLEMENTED ("mock doRevealYourself");
UNIMPLEMENTED ("Controller doRevealYourself");
}
virtual void
virtual bool
doMsg (string text) override
{
UNIMPLEMENTED ("mock doMsg");
UNIMPLEMENTED ("Controller doMsg");
}
virtual void
virtual bool
doClearMsg () override
{
UNIMPLEMENTED ("Controller doClearMsg");
}
virtual bool
doErr (string text) override
{
UNIMPLEMENTED ("mock doErr");
UNIMPLEMENTED ("Controller doErr");
}
virtual bool
doClearErr () override
{
UNIMPLEMENTED ("Controller doClearErr");
}
virtual void
doFlash() override
{
UNIMPLEMENTED ("mock doFlash");
UNIMPLEMENTED ("Controller doFlash");
}
virtual void
doMark (GenNode const& mark) override
{
UNIMPLEMENTED ("mock doMark");
UNIMPLEMENTED ("Controller doMark");
}
public:
using Tangible::Tangible;
protected:
string maybe () const;
};

View file

@ -48,41 +48,96 @@ namespace model {
/** invoke the generic reset hook
* @note the actual subclass has to override the doReset() hook
* to perform the actual clean-up work.
* @note in case an actual reset happened, the implementation should
* return `true` from this `doReset()` hook. As a consequence,
* a new "reset" state mark is emitted, which causes the
* PresentationStateManager to discard any state
* previously recorded for this element.
* @remarks the intention is that, after invoking reset(), the
* interface element or controller is in pristine (presentation) state
*/
void
Tangible::reset()
{
this->doReset();
uiBus_.note (GenNode("reset", true));
if (this->doReset())
uiBus_.note (GenNode{"reset", true});
}
/**
* Prepare a command or action for actual invocation, once the execution context
* has been established. The action is not executed right away, but it is now ready
* and bound to the concrete arguments supplied with the [record](\ref lib::diff::Rec).
* @param prototype handle to a command instantiation, to be readied for invocation
* @param arguments suitable tuple of values, to be used to outfit the prototype
/** invoke the hook to clear error markers
* @note the actual subclass has to override the doClearErr() hook...
* @note and similar to the reset() call, also the implementation should
* return `true` in case any actual (sticky) error state has been cleared.
* Again, this causes emitting of a "resetErr" state mark, which will
* purge any sticky error state remembered within the state manager.
* @remarks usually, most error markers are _not sticky_, that is, they will
* be forgotten when the session ends. In this case, the implementation
* doesn't need to care for anything special. Only in those cases, where
* actually an error state has to be preserved, the implementation should
* - emit an "Error" state mark, with the sticky error state in payload
* - be prepared to recognise when this sticky error state is fed back
* - actually signal the sticky state has to be purged when it is cleared.
*/
void
Tangible::prepareCommand (Cmd const& prototype, Rec&& arguments)
{
uiBus_.act (prototype.bind (std::forward<Rec>(arguments)));
}
Tangible::clearErr()
{
if (this->doClearErr())
uiBus_.note (GenNode{"clearErr", true});
}
/**
* Actually trigger execution of an action or command.
* @param preparedAction handle pointing to a command definition,
* which needs to be outfitted with arguments and ready for invocation.
/** invoke the hook to clear notification messages
* @remarks everything is symmetrical to reset() and clearErr() here...
*/
void
Tangible::issueCommand (Cmd const& preparedAction)
{
uiBus_.act (preparedAction.bang());
}
Tangible::clearMsg()
{
if (this->doClearMsg())
uiBus_.note (GenNode{"clearMsg", true});
}
/** highlight the element visually to catch the user's attention
* @remarks this is meant as a short transient visual change,
* just to indicate something of relevance happened here.
*/
void
Tangible::markFlash()
{
this->doFlash();
}
/** push a notification (or warning) message to the element.
* @param message notification text
* @note the actual interface response need to be coded
* in the concrete subclass within doMsg().
* @remarks the intention is for this message to be somehow
* visible at this element, e.g. as mouse over.
* When this notification is meant to be "sticky" / permanent,
* then the mentioned doMsg() implementation function should
* return true; in this case we'll emit a "state mark notification",
* which will be recorded by the PresentationStateManager, under
* the property name "`Message`" for this UI-Element.
* This mechanism allows to persist such UI states.
*/
void
Tangible::markMsg (string message)
{
if (this->doMsg (message))
uiBus_.note (GenNode{"Message", message});
}
/** push an error state tag to the element
* @remarks everything detailed at markMsg applies here too.
*/
void
Tangible::markErr (string error)
{
if (this->doErr (error))
uiBus_.note (GenNode("Error", error));
}
/**
@ -131,6 +186,51 @@ namespace model {
}
/**
* Prepare a command or action for actual invocation, once the execution context
* has been established. The action is not executed right away, but it is now ready
* and bound to the concrete arguments supplied with the [record](\ref lib::diff::Rec).
* @param prototype handle to a command instantiation, to be readied for invocation
* @param arguments suitable tuple of values, to be used to outfit the prototype
*/
void
Tangible::prepareCommand (Cmd const& prototype, Rec&& arguments)
{
uiBus_.act (prototype.bind (std::forward<Rec>(arguments)));
}
/**
* Actually trigger execution of an action or command.
* @param preparedAction handle pointing to a command definition,
* which needs to be outfitted with arguments and ready for invocation.
*/
void
Tangible::issueCommand (Cmd const& preparedAction)
{
uiBus_.act (preparedAction.bang());
}
/** generic handler for all incoming "state mark" messages */
void
Tangible::mark (GenNode const& stateMark)
{
if (stateMark.idi.getSym() == "Flash")
this->doFlash();
else
if (stateMark.idi.getSym() == "Error")
this->markErr (stateMark.data.get<string>());
else
if (stateMark.idi.getSym() == "Message")
this->markMsg (stateMark.data.get<string>());
else
this->doMark(stateMark);
}
/**
* default implementation and catch-all handler for receiving »state mark« messages.
* Such messages serve either to cause a presentation state effect specific to this
@ -157,7 +257,13 @@ namespace model {
this->doExpand (stateMark.data.get<bool>());
else
if (stateMark.idi.getSym() == "reset")
this->doReset();
this->reset();
else
if (stateMark.idi.getSym() == "clearMsg")
this->clearMsg();
else
if (stateMark.idi.getSym() == "clearErr")
this->clearErr();
else
if (stateMark.idi.getSym() == "revealYourself")
this->doRevealYourself();

View file

@ -174,6 +174,8 @@ namespace model {
operator ID() const { return uiBus_.getID();}
void reset();
void clearMsg();
void clearErr();
template<typename...ARGS>
void prepareCommand (Cmd const& prototype, ARGS&&...);
@ -185,19 +187,21 @@ namespace model {
void slotReveal(ID child);
void markMsg (string m) { this->doMsg(m); }
void markErr (string e) { this->doErr(e); }
void markFlash() { this->doFlash();}
void markFlash();
void markMsg (string message);
void markErr (string error);
void mark(GenNode const&);
protected:
virtual bool doReset() =0;
virtual bool doClearMsg() =0;
virtual bool doClearErr() =0;
virtual bool doExpand (bool yes) =0;
virtual void doReveal (ID child) =0;
virtual void doRevealYourself () =0;
virtual void doMsg (string) =0;
virtual void doErr (string) =0;
virtual bool doMsg (string) =0;
virtual bool doErr (string) =0;
virtual void doFlash() =0;
virtual void doMark(GenNode const&) =0;
private:
@ -219,23 +223,6 @@ namespace model {
/** generic handler for all incoming "state mark" messages */
inline void
Tangible::mark (GenNode const& stateMark)
{
if (stateMark.idi.getSym() == "Flash")
this->doFlash();
else
if (stateMark.idi.getSym() == "Error")
this->doErr (stateMark.data.get<string>());
else
if (stateMark.idi.getSym() == "Message")
this->doMsg (stateMark.data.get<string>());
else
this->doMark(stateMark);
}
}} // namespace gui::model
#endif /*GUI_MODEL_TANGIBLE_H*/

View file

@ -64,57 +64,67 @@ namespace model {
virtual bool
doReset() override
{
UNIMPLEMENTED ("reset");
UNIMPLEMENTED ("Widget reset");
}
virtual bool
doExpand (bool yes) override
{
UNIMPLEMENTED ("mock doExpand");
UNIMPLEMENTED ("Widget doExpand");
}
virtual void
doReveal (ID child) override
{
UNIMPLEMENTED ("mock doReveal");
UNIMPLEMENTED ("Widget doReveal");
}
virtual void
doRevealYourself() override
{
UNIMPLEMENTED ("mock doRevealYourself");
UNIMPLEMENTED ("Widget doRevealYourself");
}
virtual void
virtual bool
doMsg (string text) override
{
UNIMPLEMENTED ("mock doMsg");
UNIMPLEMENTED ("Widget doMsg");
}
virtual void
virtual bool
doClearMsg () override
{
UNIMPLEMENTED ("Widget doClearMsg");
}
virtual bool
doErr (string text) override
{
UNIMPLEMENTED ("mock doErr");
UNIMPLEMENTED ("Widget doErr");
}
virtual bool
doClearErr () override
{
UNIMPLEMENTED ("Widget doClearErr");
}
virtual void
doFlash() override
{
UNIMPLEMENTED ("mock doFlash");
UNIMPLEMENTED ("Widget doFlash");
}
virtual void
doMark (GenNode const& mark) override
{
UNIMPLEMENTED ("mock doMark");
UNIMPLEMENTED ("Widget doMark");
}
public:
using Tangible::Tangible;
protected:
string maybe () const;
};

View file

@ -444,7 +444,7 @@ namespace test {
CHECK ("Centauri" == mockA.getMessage());
// reset all notification messages
uiBus.markAll (GenNode{"resetMsg", true});
uiBus.markAll (GenNode{"clearMsg", true});
CHECK (mockB.isExpanded());
CHECK (mockC.isError());
CHECK (isnil (mockA.getMessage()));
@ -455,7 +455,7 @@ namespace test {
mockA.slotCollapse();
// reset error state(s)
uiBus.markAll (GenNode{"resetErr", true});
uiBus.markAll (GenNode{"clearErr", true});
CHECK (not mockB.isExpanded());
CHECK (mockB.isExpanded());
CHECK ("miss" == mockB.getMessage());

View file

@ -154,7 +154,7 @@ namespace test{
UNIMPLEMENTED ("mock doRevealYourself");
}
virtual void
virtual bool
doMsg (string text) override
{
log_.call (this->identify(), "doMsg", text);
@ -162,9 +162,22 @@ namespace test{
message_ = text;
virgin_ = false;
log_.note ("type=mark", "ID=Message", text);
return false; // messages not sticky for this mock implementation
}
virtual void
virtual bool
doClearMsg () override
{
log_.call (this->identify(), "doClearMsg");
if (isnil (message_))
return false;
message_ = "";
log_.note ("type=mark", "ID=Message", "Message notification cleared");
}
virtual bool
doErr (string text) override
{
log_.call (this->identify(), "doErr", text);
@ -172,6 +185,19 @@ namespace test{
error_ = text;
virgin_ = false;
log_.note ("type=mark", "ID=Error", text);
return true; // error states are sticky for this mock implementation
}
virtual bool
doClearErr () override
{
log_.call (this->identify(), "doClearErr");
if (not isError())
return false;
error_ = "";
log_.note ("type=mark", "ID=Error", "Error state cleared");
}
virtual void