previously this operation was named 'attach', which an be confused with attching an object to this location. Indeed, the session interface even offers such an attach function. By renaming the focus moving operation into QueryFocus::shift(Scope), this ambiguity is resolved
174 lines
4.5 KiB
C++
174 lines
4.5 KiB
C++
/*
|
|
QueryFocus - management of current scope within the Session
|
|
|
|
Copyright (C) Lumiera.org
|
|
2009, Hermann Vosseler <Ichthyostega@web.de>
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License as
|
|
published by the Free Software Foundation; either version 2 of
|
|
the License, or (at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
* *****************************************************/
|
|
|
|
|
|
#include "proc/mobject/session/query-focus.hpp"
|
|
#include "proc/mobject/mobject.hpp"
|
|
|
|
#include <boost/format.hpp>
|
|
|
|
using boost::format;
|
|
using boost::str;
|
|
|
|
|
|
namespace proc {
|
|
namespace mobject {
|
|
namespace session {
|
|
|
|
|
|
|
|
/**
|
|
* 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 located 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()
|
|
{
|
|
return ScopeLocator::instance().currPath();
|
|
}
|
|
|
|
|
|
/** discard any state and navigate
|
|
* current focus path to model root
|
|
*/
|
|
QueryFocus&
|
|
QueryFocus::reset ()
|
|
{
|
|
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); ////////////////TICKET #197
|
|
}
|
|
}//(End) shortcut
|
|
|
|
|
|
|
|
/** shift this QueryFocus to a container-like scope,
|
|
* 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::shift (Scope const& container)
|
|
{
|
|
___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
|
|
* @throw error::Invalid in case of invalid or unlocatable target scope
|
|
*/
|
|
QueryFocus
|
|
QueryFocus::push (Scope const& otherContainer)
|
|
{
|
|
___check_validTaget (otherContainer);
|
|
|
|
QueryFocus newFocus (ScopeLocator::instance().pushPath());
|
|
newFocus.shift (otherContainer);
|
|
return newFocus;
|
|
}
|
|
|
|
|
|
/** push the "current QueryFocus" aside and open a new focus frame,
|
|
* which starts out at the same location as the original */
|
|
QueryFocus
|
|
QueryFocus::push ()
|
|
{
|
|
Scope currentLocation (ScopeLocator::instance().currPath().getLeaf());
|
|
ENSURE (currentLocation.isValid());
|
|
|
|
QueryFocus newFocus (ScopeLocator::instance().pushPath());
|
|
newFocus.shift (currentLocation);
|
|
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.
|
|
*/
|
|
QueryFocus&
|
|
QueryFocus::pop()
|
|
{
|
|
focus_ = 0;
|
|
focus_ = & currPath();
|
|
|
|
return *this;
|
|
}
|
|
|
|
|
|
|
|
/** diagnostic self-display based on the ScopePath */
|
|
QueryFocus::operator string() const
|
|
{
|
|
static format display("Focus(%d)--->%s");
|
|
return str ( display % ScopeLocator::instance().stackSize()
|
|
% string (*focus_));
|
|
}
|
|
|
|
|
|
|
|
}}} // namespace proc::mobject::session
|