Commit d7a21234 authored by Will Schroeder's avatar Will Schroeder
Browse files

ENH:Added class to mediate resource contention (i.e., cursor shape) for...

ENH:Added class to mediate resource contention (i.e., cursor shape) for interactor observers (e.g., widgets)
parent 4ae75d58
/*=========================================================================
Program: Visualization Toolkit
Module: vtkObserverMediator.cxx
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
#include "vtkObserverMediator.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkObjectFactory.h"
#include "vtkPriorityQueue.h"
#include "vtkInteractorObserver.h"
#include <vtkstd/map>
vtkCxxRevisionMacro(vtkObserverMediator, "1.1");
vtkStandardNewMacro(vtkObserverMediator);
// PIMPL the map containing the observer priorities. Note that only observers who are
// requesting non-default cursors are placed into the map.
// Comparison functor based on observer priorities.
struct vtkObserverCompare
{
bool operator()(vtkInteractorObserver* w1, vtkInteractorObserver* w2) const
{
return (w1->GetPriority() < w2->GetPriority());
}
};
// The important feature of the map is that it sorts data (based on the functor above).
class vtkObserverMap : public vtkstd::map<vtkInteractorObserver*,int,vtkObserverCompare>
{
public:
vtkObserverMap() : vtkstd::map<vtkInteractorObserver*,int,vtkObserverCompare>() {}
};
typedef vtkObserverMap::iterator ObserverMapIterator;
//----------------------------------------------------------------------------------
vtkObserverMediator::vtkObserverMediator()
{
this->Interactor = NULL;
this->ObserverMap = new vtkObserverMap;
this->CurrentObserver = NULL;
this->CurrentCursorShape = VTK_CURSOR_DEFAULT;
}
//----------------------------------------------------------------------------------
vtkObserverMediator::~vtkObserverMediator()
{
delete this->ObserverMap;
}
//----------------------------------------------------------------------------------
void vtkObserverMediator::SetInteractor(vtkRenderWindowInteractor* i)
{
this->Interactor = i;
}
//----------------------------------------------------------------------------------
// This mediation process works by keeping track of non-default cursor requests.
// Ties are broken based on widget priority (hence the priority queue).
int vtkObserverMediator::RequestCursorShape(vtkInteractorObserver *w, int requestedShape)
{
if ( !this->Interactor || !w )
{
return 0;
}
// Cull out the trivial cases when setting to default cursor
if ( requestedShape == VTK_CURSOR_DEFAULT )
{
if ( !this->CurrentObserver || this->CurrentCursorShape == VTK_CURSOR_DEFAULT )
{
return 0; //nothing has changed
}
if ( w == this->CurrentObserver && requestedShape != this->CurrentCursorShape )
{
this->CurrentCursorShape = VTK_CURSOR_DEFAULT;
this->ObserverMap->erase(w);
this->Interactor->GetRenderWindow()->SetCurrentCursor(VTK_CURSOR_DEFAULT);
return 1;
}
return 0;
}
// For some strange reason this code causes problems. The SetCurrentCursor() method
// must be called for every move or the cursor reverts back to default.
// if ( w == this->CurrentObserver && requestedShape == this->CurrentCursorShape )
// {
// return 0;
// }
// Place request in map if non-default
ObserverMapIterator iter = this->ObserverMap->find(w);
if ( iter != this->ObserverMap->end() )
{//found something, see if request has changed. If so, erase it and reinsert into map.
if ( (*iter).second != requestedShape )
{
this->ObserverMap->erase(iter);
}
}
(*this->ObserverMap)[w] = requestedShape;
// Get the item with the highest priority off of the queue
if ( ! this->ObserverMap->empty() )
{
ObserverMapIterator iter = this->ObserverMap->end();
--iter;
this->Interactor->GetRenderWindow()->SetCurrentCursor((*iter).second);
this->CurrentObserver = w;
this->CurrentCursorShape = (*iter).second;
return 1;
}
return 0;
}
//----------------------------------------------------------------------------------
void vtkObserverMediator::PrintSelf(ostream& os, vtkIndent indent)
{
//Superclass typedef defined in vtkTypeMacro() found in vtkSetGet.h
this->Superclass::PrintSelf(os,indent);
os << indent << "Render Window Interactor: ";
if ( this->Interactor )
{
os << this->Interactor << "\n";
}
else
{
os << "(None)\n";
}
}
/*=========================================================================
Program: Visualization Toolkit
Module: vtkObserverMediator.h
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
// .NAME vtkObserverMediator - manage contention for cursors and other resources
// .SECTION Description
// The vtkObserverMediator is a helper class that manages requests for
// cursor changes from multiple interactor observers (e.g. widgets). It keeps
// a list of widgets (and their priorities) and their current requests for
// cursor shape. It then satisfies requests based on widget priority and the
// relative importance of the request (e.g., a lower priority widget
// requesting a particular cursor shape will overrule a higher priority
// widget requesting a default shape).
// .SECTION See Also
// vtkAbstractWidget vtkWidgetRepresentation
#ifndef __vtkObserverMediator_h
#define __vtkObserverMediator_h
#include "vtkObject.h"
class vtkRenderWindowInteractor;
class vtkInteractorObserver;
class vtkObserverMap;
class VTK_RENDERING_EXPORT vtkObserverMediator : public vtkObject
{
public:
// Description:
// Instantiate the class.
static vtkObserverMediator *New();
// Description:
// Standard macros.
vtkTypeRevisionMacro(vtkObserverMediator,vtkObject);
void PrintSelf(ostream& os, vtkIndent indent);
// Description:
// Specify the instance of vtkRenderWindow whose cursor shape is
// to be managed.
void SetInteractor(vtkRenderWindowInteractor* iren);
vtkGetObjectMacro(Interactor, vtkRenderWindowInteractor);
// Description:
// Method used to request a cursor shape. Note that the shape is specified
// using one of the integral values determined in vtkRenderWindow.h. The
// method returns a non-zero value if the shape was successfully changed.
int RequestCursorShape(vtkInteractorObserver*, int cursorShape);
protected:
vtkObserverMediator();
~vtkObserverMediator();
// The render window whose cursor we are controlling
vtkRenderWindowInteractor *Interactor;
// A map whose key is the observer*, and whose data value is a cursor
// request. Note that a special compare function is used to sort the
// widgets based on the observer's priority.
vtkObserverMap *ObserverMap; //given a widget*, return its data
// The current observer and cursor shape
vtkInteractorObserver *CurrentObserver;
int CurrentCursorShape;
private:
vtkObserverMediator(const vtkObserverMediator&); //Not implemented
void operator=(const vtkObserverMediator&); //Not implemented
};
#endif
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment