finialise simple state manager implementation
...and rearrange storage interface to suit
This commit is contained in:
parent
92d9a7323f
commit
94576af4df
5 changed files with 77 additions and 46 deletions
|
|
@ -39,9 +39,12 @@
|
|||
** remembers those messages, always retaining the latest state information observed for any
|
||||
** property of any [tangible interface element](\ref tangible.hpp) encountered thus far.
|
||||
**
|
||||
** @todo as of 2/2016 this is complete WIP-WIP-WIP
|
||||
** @todo as of 2/2016 this is still preliminary.
|
||||
** In the end, we want to capture and restore presentation state
|
||||
** in dependency to the current perspective and work site
|
||||
**
|
||||
** @see ////TODO_test usage example
|
||||
** @see BusTerm_test::captureStateMark() usage example
|
||||
** @see BusTerm_test::replayStateMark() usage example
|
||||
**
|
||||
*/
|
||||
|
||||
|
|
@ -50,12 +53,8 @@
|
|||
#define GUI_INTERACT_PRESENTATION_STATE_MANAGER_H
|
||||
|
||||
|
||||
#include "lib/error.hpp"
|
||||
//#include "gui/ctrl/bus-term.hpp"
|
||||
//#include "lib/idi/entry-id.hpp"
|
||||
#include "lib/idi/entry-id.hpp"
|
||||
#include "lib/diff/gen-node.hpp"
|
||||
//#include "lib/symbol.hpp"
|
||||
//#include "lib/util.hpp"
|
||||
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <string>
|
||||
|
|
@ -64,20 +63,24 @@
|
|||
namespace gui {
|
||||
namespace interact {
|
||||
|
||||
// using lib::HashVal;
|
||||
// using util::isnil;
|
||||
using std::string;
|
||||
|
||||
|
||||
/**
|
||||
* Interface: handling of persistent interface state.
|
||||
* @todo write type comment...
|
||||
* Operations to retrieve previously captured state and
|
||||
* to re-play this state towards the originating UI-elements.
|
||||
* It is assumed that the actual implementation is connected
|
||||
* to the UI-Bus and captures *state mark notifications*.
|
||||
* State is first grouped by ID of the originating interface
|
||||
* element, and recorded per distinct property within each
|
||||
* element.
|
||||
*/
|
||||
class PresentationStateManager
|
||||
: boost::noncopyable
|
||||
{
|
||||
protected:
|
||||
virtual ~PresentationStateManager(); ///< this is an interface
|
||||
virtual ~PresentationStateManager(); ///< this is an interface
|
||||
|
||||
using ID = lib::idi::BareEntryID const&;
|
||||
using StateMark = lib::diff::GenNode const&;
|
||||
|
|
|
|||
|
|
@ -74,9 +74,11 @@ namespace interact {
|
|||
struct StateMapGroupingStorage
|
||||
: boost::noncopyable
|
||||
{
|
||||
using Record = std::set<GenNode, GenNodeComparator>;
|
||||
using StateData = std::set<GenNode, GenNodeComparator>;
|
||||
|
||||
using Storage = std::unordered_map<BareEntryID, Record, BareEntryID::UseEmbeddedHash>;
|
||||
using Storage = std::unordered_map<BareEntryID, StateData, BareEntryID::UseEmbeddedHash>;
|
||||
|
||||
using Record = Storage::value_type;
|
||||
|
||||
|
||||
Storage elmTable_;
|
||||
|
|
@ -116,19 +118,19 @@ namespace interact {
|
|||
}
|
||||
|
||||
static BareEntryID const&
|
||||
getID (iterator entry)
|
||||
getID (Record entry)
|
||||
{
|
||||
return entry->first;
|
||||
return entry.first;
|
||||
}
|
||||
|
||||
static Record const&
|
||||
getState (iterator entry)
|
||||
static StateData const&
|
||||
getState (Record entry)
|
||||
{
|
||||
return entry->second;
|
||||
return entry.second;
|
||||
}
|
||||
|
||||
static GenNode const&
|
||||
getState (iterator entry, string propertyKey)
|
||||
getState (Record entry, string propertyKey)
|
||||
{
|
||||
UNIMPLEMENTED ("fetch property data from given element record");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,9 +27,23 @@
|
|||
** groups recorded message by elementID and simply overwrites
|
||||
** previous state info for a given attribute with later one.
|
||||
**
|
||||
** @todo as of 2/2016 this is complete WIP-WIP-WIP
|
||||
** \par performance
|
||||
** The storage layout was chosen under the assumption that we'll get
|
||||
** many elements with only few properties per element. The implementing
|
||||
** hash table relies on the hash function for BareEntryID, which uses
|
||||
** the embedded hash, which in turn is based on hashing the symbolicID
|
||||
** plus a hashed type string.
|
||||
**
|
||||
** @see ////TODO_test usage example
|
||||
** @todo as of 2/2016 noting but a simple data retrieval happens here.
|
||||
** Actually, on the long run, we want "intelligent" handling of
|
||||
** presentation state, we want to capture and restore state
|
||||
** with sensitivity to perspective and work site. Probably
|
||||
** this means to layer a second level of aggregation on top.
|
||||
** @warning state mark entries are added, never discarded.
|
||||
** Once we start actually persisting this state,
|
||||
** this might get us into trouble.
|
||||
**
|
||||
** @see BusTerm_test::captureStateMark usage example
|
||||
**
|
||||
*/
|
||||
|
||||
|
|
@ -39,24 +53,18 @@
|
|||
|
||||
|
||||
#include "lib/error.hpp"
|
||||
//#include "gui/ctrl/bus-term.hpp"
|
||||
#include "lib/idi/entry-id.hpp"
|
||||
#include "lib/diff/gen-node.hpp"
|
||||
#include "gui/ctrl/bus-term.hpp"
|
||||
#include "gui/interact/presentation-state-manager.hpp"
|
||||
#include "gui/interact/state-map-grouping-storage.hpp"
|
||||
#include "gui/ctrl/bus-term.hpp"
|
||||
//#include "lib/symbol.hpp"
|
||||
//#include "lib/util.hpp"
|
||||
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <string>
|
||||
|
||||
|
||||
namespace gui {
|
||||
namespace interact {
|
||||
|
||||
// using lib::HashVal;
|
||||
// using util::isnil;
|
||||
using gui::ctrl::BusTerm;
|
||||
using lib::diff::GenNode;
|
||||
using lib::diff::Ref;
|
||||
|
|
@ -68,14 +76,22 @@ namespace interact {
|
|||
/**
|
||||
* Simple map based implementation of the
|
||||
* PresentationStateManager interface.
|
||||
* Requires a permanent connection to the UI-Bus,
|
||||
* which is given as reference at construction.
|
||||
* The intention is to use such an implementation
|
||||
* embedded within the gui::ctrl::CoreService,
|
||||
* which in turn then manages the lifecycle of
|
||||
* this UI-Bus connection. Besides, a derived
|
||||
* mock implementation is available through
|
||||
* the test::Nexus
|
||||
*
|
||||
* @todo write type comment...
|
||||
* @see StateMapGroupingStorage storage implementation
|
||||
*/
|
||||
class StateRecorder
|
||||
: public PresentationStateManager
|
||||
{
|
||||
using Storage = StateMapGroupingStorage;
|
||||
using Iter = Storage::iterator;
|
||||
using Record = Storage::Record const&;
|
||||
|
||||
BusTerm& uiBus_;
|
||||
Storage storage_;
|
||||
|
|
@ -103,15 +119,18 @@ namespace interact {
|
|||
virtual void
|
||||
replayAllState() override
|
||||
{
|
||||
for (Iter entry = storage_.begin(); entry!=storage_.end(); ++entry)
|
||||
for (Record entry : storage_)
|
||||
replayPropertiesOf (entry);
|
||||
}
|
||||
|
||||
|
||||
/** replay all captured state from any element,
|
||||
* but captured especially for the given property
|
||||
*/
|
||||
virtual void
|
||||
replayAllState (string propertyKey) override
|
||||
{
|
||||
for (Iter entry = storage_.begin(); entry!=storage_.end(); ++entry)
|
||||
for (Record entry : storage_)
|
||||
{
|
||||
StateMark state = Storage::getState (entry, propertyKey);
|
||||
if (state != Ref::NO)
|
||||
|
|
@ -120,36 +139,43 @@ namespace interact {
|
|||
}
|
||||
|
||||
|
||||
/** replay all captured state from the given element. */
|
||||
virtual void
|
||||
replayAllProperties (ID uiElm) override
|
||||
{
|
||||
Iter entry = storage_.find (uiElm);
|
||||
auto entry = storage_.find (uiElm);
|
||||
if (entry != storage_.end())
|
||||
replayPropertiesOf (entry);
|
||||
replayPropertiesOf (*entry);
|
||||
}
|
||||
|
||||
|
||||
virtual void
|
||||
clearState() override
|
||||
{
|
||||
storage_.clear();
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
StateRecorder (BusTerm& busConnection)
|
||||
: uiBus_(busConnection)
|
||||
, storage_()
|
||||
{ }
|
||||
|
||||
|
||||
/** Interface for the operating facility (CoreService)
|
||||
* to feed state mark messages to be remembered.
|
||||
* @param uiElm originator of the state notification
|
||||
* @param stateMark state information to record
|
||||
*/
|
||||
void
|
||||
record (ID uiElm, StateMark stateMark)
|
||||
recordState (ID uiElm, StateMark stateMark)
|
||||
{
|
||||
storage_.record (uiElm, stateMark);
|
||||
}
|
||||
|
||||
private:
|
||||
void
|
||||
replayPropertiesOf (Iter entry)
|
||||
replayPropertiesOf (Record entry)
|
||||
{
|
||||
ID uiElm = Storage::getID (entry);
|
||||
for (auto& stateMark : Storage::getState (entry))
|
||||
|
|
|
|||
|
|
@ -117,7 +117,7 @@ namespace test {
|
|||
* from the Hub.
|
||||
*/
|
||||
void
|
||||
attachNewBusTerm ()
|
||||
attachNewBusTerm()
|
||||
{
|
||||
MARK_TEST_FUN;
|
||||
// our dummy will be linked with this identity
|
||||
|
|
@ -180,7 +180,7 @@ namespace test {
|
|||
|
||||
/** @test perform the full command binding and invocation protocol */
|
||||
void
|
||||
commandInvocation ()
|
||||
commandInvocation()
|
||||
{
|
||||
MARK_TEST_FUN
|
||||
gui::test::Nexus::startNewLog();
|
||||
|
|
@ -238,7 +238,7 @@ namespace test {
|
|||
* We use a test version of the PresentationStateManager,
|
||||
* based on the same building blocks as _the real thing_ */
|
||||
void
|
||||
captureStateMark ()
|
||||
captureStateMark()
|
||||
{
|
||||
MARK_TEST_FUN
|
||||
gui::test::Nexus::startNewLog();
|
||||
|
|
@ -279,7 +279,7 @@ namespace test {
|
|||
|
||||
/** @test replay previously captured state information" */
|
||||
void
|
||||
replayStateMark ()
|
||||
replayStateMark()
|
||||
{
|
||||
MARK_TEST_FUN
|
||||
PresentationStateManager& stateManager = gui::test::Nexus::getMockStateManager();
|
||||
|
|
@ -316,28 +316,28 @@ namespace test {
|
|||
|
||||
|
||||
void
|
||||
verifyNotifications ()
|
||||
verifyNotifications()
|
||||
{
|
||||
UNIMPLEMENTED ("send notifications to a distinct element");
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
clearStates ()
|
||||
clearStates()
|
||||
{
|
||||
UNIMPLEMENTED ("broadcast state reset");
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
pushDiff ()
|
||||
pushDiff()
|
||||
{
|
||||
UNIMPLEMENTED ("push a mutation diff towards an interface element");
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
destroy ()
|
||||
destroy()
|
||||
{
|
||||
UNIMPLEMENTED ("detach and destroy the test BusTerm");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -590,7 +590,7 @@ namespace test{
|
|||
testNexus().installStateMarkHandler(
|
||||
[&](ID const& elementID, lib::diff::GenNode const& stateMark)
|
||||
{
|
||||
stateManager().record (elementID, stateMark);
|
||||
stateManager().recordState (elementID, stateMark);
|
||||
});
|
||||
|
||||
return getMockStateManager();
|
||||
|
|
|
|||
Loading…
Reference in a new issue