diff --git a/src/proc/mobject/session/query-focus.cpp b/src/proc/mobject/session/query-focus.cpp index 9ae9c9d9f..b3ee76a7f 100644 --- a/src/proc/mobject/session/query-focus.cpp +++ b/src/proc/mobject/session/query-focus.cpp @@ -22,80 +22,118 @@ #include "proc/mobject/session/query-focus.hpp" -//#include "proc/mobject/session/track.hpp" -//#include "proc/mobject/placement.hpp" -//#include "proc/mobject/session/mobjectfactory.hpp" -//#include "proc/asset/track.hpp" + namespace mobject { namespace session { - /** TODO??? */ + /** + * create a new QueryFocus (handle) + * linked to the current focus for discovery queries. + * The existence of this QueryFocus instance keeps this + * current focus alive, but multiple instances share a + * common focus location and may change this location. + * + */ QueryFocus::QueryFocus() - { } + : focus_( & currPath()) + { } - /** */ + /** + * @internal build a new QueryFocus + * as attached to an existing path. + */ + QueryFocus::QueryFocus(ScopePath& path_to_attach) + : focus_( &path_to_attach) + { } + + + /** @internal access the path designating + * the current focus location */ ScopePath& QueryFocus::currPath() { - UNIMPLEMENTED ("dereference and access the current scope path"); + return ScopeLocator::instance().currPath(); } - - ScopePath const& - QueryFocus::currPath() const - { - UNIMPLEMENTED ("dereference and access the current scope path"); - } - - /** discard any state and clear - the current focus path */ + + /** discard any state and navigate + * current focus path to model root + */ QueryFocus& QueryFocus::reset () { - scopes_.clear(); + REQUIRE (focus_); + focus_->clear(); return *this; } + + + + namespace {// error check shortcut.... + + using lumiera::error::Invalid; + + void + ___check_validTaget (Scope const& target) + { + if (!target.isValid()) + throw Invalid ("Invalid target location for QueryFocus" + , LUMIERA_ERROR_INVALID_SCOPE); + } + }//(End) shortcut + + + /** attach this QueryFocus to a container-like scope, - causing it to \em navigate, changing the - current ScopePath as a side-effect - */ + * causing it to \em navigate, changing the + * current ScopePath as a side-effect + * @throw error::Invalid if the given container is + * invalid or can't be located within the model + */ QueryFocus& QueryFocus::attach (Scope const& container) { - UNIMPLEMENTED ("navigate this focus to attach to the given container scop"); + ___check_validTaget (container); + + REQUIRE (focus_); + focus_->navigate (container); return *this; } /** push the "current QueryFocus" aside and open a new focus frame. - This new QueryFocus will act as "current" until going out of scope + * This new QueryFocus will act as "current" until going out of scope + * @throw error::Invalid in case of invalid or unlocatable target scope */ QueryFocus QueryFocus::push (Scope const& otherContainer) { - UNIMPLEMENTED ("push current, open a new QueryFocus frame"); - QueryFocus newFocus; // = do push and open new frame + ___check_validTaget (otherContainer); + + QueryFocus newFocus (ScopeLocator::instance().pushPath()); newFocus.attach (otherContainer); return newFocus; } /** cease to use \em this specific reference to the current frame. - This operation immediately tries to re-attach to what is "current" - and readjusts the internal handle. But when the previously released - reference was the last one, releasing it will cause the QueryFocusStack - to pop, in which case we'll re-attach to the now uncovered previous stack top. - */ + * This operation immediately tries to re-attach to what is "current" + * and readjusts the internal handle. But when the previously released + * reference was the last one, releasing it will cause the QueryFocusStack + * to pop, in which case we'll re-attach to the now uncovered previous stack top. + */ QueryFocus& QueryFocus::pop() { - UNIMPLEMENTED ("pop, give up one reference, maybe drop stack top"); + focus_ = 0; + focus_ = & currPath(); + return *this; } diff --git a/src/proc/mobject/session/query-focus.hpp b/src/proc/mobject/session/query-focus.hpp index 7fd5939c2..712284da2 100644 --- a/src/proc/mobject/session/query-focus.hpp +++ b/src/proc/mobject/session/query-focus.hpp @@ -29,6 +29,7 @@ #include "proc/mobject/session/scope-path.hpp" #include "proc/mobject/session/scope-locator.hpp" +#include //#include //#include @@ -45,8 +46,7 @@ namespace session { */ class QueryFocus { - ScopePath scopes_; /////////////////////////////////////////////////////////////////TODO use intrusive pointer - /////////////////////////////////////////////////////////////////////////////////////TODO how to integrate the ref-counting handle? + boost::intrusive_ptr focus_; public: QueryFocus(); @@ -61,26 +61,44 @@ namespace session { template typename ScopeQuery::iterator - query() const - { - ScopeLocator::instance().query (*this); - } + query() const; template typename ScopeQuery::iterator - explore() const - { - ScopeLocator::instance().explore (*this); - } + explore() const; private: - ScopePath & currPath(); - ScopePath const& currPath() const; + QueryFocus (ScopePath&); + + static ScopePath& currPath(); }; ///////////////////////////TODO currently just fleshing the API + + /** discover depth-first any matching object + * within \em current focus. Resolution is + * delegate to the \em current session */ + template + typename ScopeQuery::iterator + QueryFocus::query() const + { + ScopeLocator::instance().query (*this); + } + + + /** discover any matching object contained + * as immediate Child within \em current focus. + * Resolution through \em current session */ + template + typename ScopeQuery::iterator + QueryFocus::explore() const + { + ScopeLocator::instance().explore (*this); + } + + }} // namespace mobject::session #endif diff --git a/src/proc/mobject/session/scope-locator.hpp b/src/proc/mobject/session/scope-locator.hpp index aa4d03633..c6c9aba5d 100644 --- a/src/proc/mobject/session/scope-locator.hpp +++ b/src/proc/mobject/session/scope-locator.hpp @@ -64,6 +64,7 @@ namespace session { static lib::Singleton instance; ScopePath& currPath(); + ScopePath& pushPath(); template typename ScopeQuery::iterator diff --git a/src/proc/mobject/session/scope-path.hpp b/src/proc/mobject/session/scope-path.hpp index 9ff0f911e..8087b89d1 100644 --- a/src/proc/mobject/session/scope-path.hpp +++ b/src/proc/mobject/session/scope-path.hpp @@ -86,6 +86,7 @@ #include "proc/mobject/session/scope.hpp" #include "lib/bool-checkable.hpp" #include "lib/iter-adapter.hpp" +#include "lib/error.hpp" #include diff --git a/src/proc/mobject/session/scope.cpp b/src/proc/mobject/session/scope.cpp index f8a604115..cf61747f4 100644 --- a/src/proc/mobject/session/scope.cpp +++ b/src/proc/mobject/session/scope.cpp @@ -35,6 +35,9 @@ namespace mobject { namespace session { + LUMIERA_ERROR_DEFINE (INVALID_SCOPE, "Placement scope invalid an not locatable within model"); + + /** TODO??? */ Scope::Scope (PlacementMO const& constitutingPlacement) @@ -104,10 +107,22 @@ namespace session { ScopePath& ScopeLocator::currPath() { - UNIMPLEMENTED ("how to access and handle the current focus"); + return focusStack_->top(); } + /** push aside the current focus location + * and open a new ScopePath frame, to serve + * as \em current location until released + */ + ScopePath& + ScopeLocator::pushPath() + { + return focusStack_->push (SessionServiceExploreScope::getScopeRoot()); + } + + + /** discover the enclosing scope of a given Placement */ Scope const& Scope::containing (PlacementMO const& aPlacement) diff --git a/src/proc/mobject/session/scope.hpp b/src/proc/mobject/session/scope.hpp index 592002b61..a51c0619b 100644 --- a/src/proc/mobject/session/scope.hpp +++ b/src/proc/mobject/session/scope.hpp @@ -29,6 +29,7 @@ #include "proc/mobject/placement-ref.hpp" //#include "proc/mobject/session/query-resolver.hpp" ///////////TODO: really? #include "lib/iter-adapter.hpp" +#include "lib/error.hpp" //#include "lib/singleton.hpp" #include @@ -45,6 +46,8 @@ namespace session { using lib::IterAdapter; + LUMIERA_ERROR_DECLARE (INVALID_SCOPE); ///< Placement scope invalid an not locatable within model + /**