LUMIERA.clone/src/proc/mobject/session/query-focus.cpp

173 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 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 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()
{
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
/** attach 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::attach (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.attach (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.attach (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 mobject::session