Commit aca5ce64 authored by Jeff Baumes's avatar Jeff Baumes

ENH: Adding general hover support to rendered views.

 - Using vtkHardwareSelector to capture the cell ids on the screen at any
   given time. This is reused as hover events occur.

 - Using vtkHoverWidget to receive timeout events when the mouse hasn't
   moved, and update the hover text then.

 - Added more functionality to vtkHardwareSelector to be able to query
   regions within the captured area (for drag selections) and being able
   to search out from a point to a given threshold distance for a cell
   (for hover text).

 - Added vertex and edge hovering to graph layout view, and edge hovering
   to tree area views.
parent 2fedc736
......@@ -100,6 +100,10 @@ static const char *vtkCommandEventStrings[] = {
"UpdateDataEvent",
"CurrentChangedEvent",
"ComputeVisiblePropBoundsEvent",
"TDxMotionEvent", // 3D Connexion device event
"TDxButtonPressEvent", // 3D Connexion device event
"TDxButtonReleaseEvent", // 3D Connexion device event
"HoverEvent",
NULL
};
......
......@@ -352,6 +352,7 @@ public:
TDxMotionEvent, // 3D Connexion device event
TDxButtonPressEvent, // 3D Connexion device event
TDxButtonReleaseEvent, // 3D Connexion device event
HoverEvent,
UserEvent = 1000
};
//ETX
......
......@@ -48,7 +48,7 @@ public:
};
vtkStandardNewMacro(vtkHardwareSelector);
vtkCxxRevisionMacro(vtkHardwareSelector, "1.7");
vtkCxxRevisionMacro(vtkHardwareSelector, "1.8");
vtkCxxSetObjectMacro(vtkHardwareSelector, Renderer, vtkRenderer);
//----------------------------------------------------------------------------
vtkHardwareSelector::vtkHardwareSelector()
......@@ -365,67 +365,122 @@ bool vtkHardwareSelector::IsPropHit(int id)
//----------------------------------------------------------------------------
bool vtkHardwareSelector::GetPixelInformation(unsigned int display_position[2],
int& processid,
vtkIdType& attrId, vtkProp*& prop)
vtkIdType& attrId, vtkProp*& prop,
int maxDist)
{
if (display_position[0] < this->Area[0] || display_position[0] > this->Area[2] ||
display_position[1] < this->Area[1] || display_position[1] > this->Area[3])
// Base case
if (maxDist == 0)
{
vtkErrorMacro("Position out of selected region.");
processid=-1;
attrId=-1;
prop = 0;
return false;
}
int width = this->Area[2] - this->Area[0] + 1;
unsigned long offset =
((display_position[1] - this->Area[1]) * width + display_position[0]-this->Area[0]);
if (display_position[0] < this->Area[0] || display_position[0] > this->Area[2] ||
display_position[1] < this->Area[1] || display_position[1] > this->Area[3])
{
processid=-1;
attrId=-1;
prop = 0;
return false;
}
processid = this->Convert(offset, this->PixBuffer[PROCESS_PASS]);
processid--;
int actorid = this->Convert(display_position[0], display_position[1], this->PixBuffer[ACTOR_PASS]);
if (actorid <= 0)
{
// the pixel did not hit any actor.
processid=-1;
attrId=-1;
prop = 0;
return false;
}
actorid--;
prop = this->Internals->Props[actorid];
int low24 = this->Convert(display_position[0], display_position[1], this->PixBuffer[ID_LOW24]);
int mid24 = this->Convert(display_position[0], display_position[1], this->PixBuffer[ID_MID24]);
int high16 = this->Convert(display_position[0], display_position[1], this->PixBuffer[ID_HIGH16]);
// id 0 is reserved for nothing present.
attrId = this->GetID(low24, mid24, high16);
attrId = (attrId - ID_OFFSET);
if (attrId < 0)
{
// the pixel did not hit any cell.
processid=-1;
attrId=-1;
prop = 0;
return false;
}
int actorid = this->Convert(offset, this->PixBuffer[ACTOR_PASS]);
if (actorid <= 0)
{
processid=-1;
attrId=-1;
prop = 0;
// nothing hit.
return false;
processid = this->Convert(display_position[0], display_position[1], this->PixBuffer[PROCESS_PASS]);
processid--;
return true;
}
actorid--;
int low24 = this->Convert(offset, this->PixBuffer[ID_LOW24]);
int mid24 = this->Convert(offset, this->PixBuffer[ID_MID24]);
int high16 = this->Convert(offset, this->PixBuffer[ID_HIGH16]);
// id 0 is reserved for nothing present.
attrId = this->GetID(low24, mid24, high16);
attrId -= ID_OFFSET;
if (attrId < 0)
// Iterate over successively growing boxes.
// They recursively call the base case to handle single pixels.
int disp_pos[2] = {display_position[0], display_position[1]};
unsigned int cur_pos[2] = {0, 0};
for (int dist = 0; dist < maxDist; ++dist)
{
processid=-1;
attrId=-1;
prop = 0;
// nothing hit.
return false;
// Vertical sides of box.
for (int y = disp_pos[1] - dist; y <= disp_pos[1] + dist; ++y)
{
cur_pos[0] = static_cast<unsigned int>(disp_pos[0] - dist);
cur_pos[1] = static_cast<unsigned int>(y);
if (this->GetPixelInformation(cur_pos, processid, attrId, prop, 0))
{
return true;
}
cur_pos[0] = static_cast<unsigned int>(disp_pos[0] + dist);
if (this->GetPixelInformation(cur_pos, processid, attrId, prop, 0))
{
return true;
}
}
// Horizontal sides of box.
for (int x = disp_pos[0] - (dist-1); x <= disp_pos[0] + (dist-1); ++x)
{
cur_pos[0] = static_cast<unsigned int>(x);
cur_pos[1] = static_cast<unsigned int>(disp_pos[1] - dist);
if (this->GetPixelInformation(cur_pos, processid, attrId, prop, 0))
{
return true;
}
cur_pos[1] = static_cast<unsigned int>(disp_pos[1] + dist);
if (this->GetPixelInformation(cur_pos, processid, attrId, prop, 0))
{
return true;
}
}
}
prop = this->Internals->Props[actorid];
return true;
// nothing hit.
processid=-1;
attrId=-1;
prop = 0;
return false;
}
//----------------------------------------------------------------------------
vtkSelection* vtkHardwareSelector::GenerateSelection()
vtkSelection* vtkHardwareSelector::GenerateSelection(
unsigned int x1, unsigned int y1,
unsigned int x2, unsigned int y2)
{
// Clamp to saved region
x1 = x1 < this->Area[0] ? this->Area[0] : x1;
x1 = x1 > this->Area[2] ? this->Area[2] : x1;
x2 = x2 < this->Area[0] ? this->Area[0] : x2;
x2 = x2 > this->Area[2] ? this->Area[2] : x2;
y1 = y1 < this->Area[1] ? this->Area[1] : y1;
y1 = y1 > this->Area[3] ? this->Area[3] : y1;
y2 = y2 < this->Area[1] ? this->Area[1] : y2;
y2 = y2 > this->Area[3] ? this->Area[3] : y2;
typedef vtkstd::map<int, vtkstd::map<int, vtkstd::set<vtkIdType> > > MapType;
MapType dataMap;
typedef vtkstd::map<int, vtkstd::map<int, vtkIdType> > PixelCountType;
PixelCountType pixelCounts;
for (int yy=0; yy <= static_cast<int>(this->Area[3]-this->Area[1]); yy++)
for (int yy = y1 - Area[1]; yy <= static_cast<int>(y2 - this->Area[1]); yy++)
{
for (int xx=0; xx <= static_cast<int>(this->Area[2]-this->Area[0]); xx++)
for (int xx = x1 - Area[0]; xx <= static_cast<int>(x2 - this->Area[0]); xx++)
{
int processid = this->Convert(xx, yy, this->PixBuffer[PROCESS_PASS]);
processid--;
......
......@@ -104,10 +104,16 @@ public:
// CaptureBuffers() to render the selection buffers and then get information
// about pixel locations suing GetPixelInformation(). Use ClearBuffers() to
// clear buffers after one's done with the scene.
// The optional final parameter maxDist will look for a cell within the specified
// number of pixels from display_position.
bool CaptureBuffers();
bool GetPixelInformation(unsigned int display_position[2],
int& processId,
vtkIdType& attrId, vtkProp*& prop);
vtkIdType& attrId, vtkProp*& prop)
{ this->GetPixelInformation(display_position, processId, attrId, prop, 0); }
bool GetPixelInformation(unsigned int display_position[2],
int& processId,
vtkIdType& attrId, vtkProp*& prop, int maxDist);
void ClearBuffers()
{ this->ReleasePixBuffers(); }
......@@ -136,6 +142,21 @@ public:
// Get the current pass number.
vtkGetMacro(CurrentPass, int);
// Description:
// Generates the vtkSelection from pixel buffers.
// Requires that CaptureBuffers() has already been called.
// Optionally you may pass a screen region (xmin, ymin, xmax, ymax)
// to generate a selection from. The region must be a subregion
// of the region specified by SetArea(), otherwise it will be
// clipped to that region.
virtual vtkSelection* GenerateSelection()
{ return GenerateSelection(this->Area); }
virtual vtkSelection* GenerateSelection(unsigned int r[4])
{ return GenerateSelection(r[0], r[1], r[2], r[3]); }
virtual vtkSelection* GenerateSelection(
unsigned int x1, unsigned int y1,
unsigned int x2, unsigned int y2);
//BTX
enum PassTypes
{
......@@ -185,7 +206,7 @@ protected:
{
return 0;
}
int offset = (yy * static_cast<int>(this->Area[2]-this->Area[0]) + xx) * 3;
int offset = (yy * static_cast<int>(this->Area[2]-this->Area[0]+1) + xx) * 3;
unsigned char rgb[3];
rgb[0] = pb[offset];
rgb[1] = pb[offset+1];
......@@ -220,10 +241,6 @@ protected:
// are not involved in the selection after the first pass.
bool IsPropHit(int propid);
// Description:
// Internal method that generates the vtkSelection from pixel buffers.
virtual vtkSelection* GenerateSelection();
// Description:
// Return a unique ID for the prop.
virtual int GetPropID(int idx, vtkProp* vtkNotUsed(prop))
......
......@@ -24,6 +24,7 @@
#include "vtkIdTypeArray.h"
#include "vtkInteractorEventRecorder.h"
#include "vtkRegressionTestImage.h"
#include "vtkRenderedGraphRepresentation.h"
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
......@@ -1126,6 +1127,9 @@ int TestGraphLayoutView(int argc, char* argv[])
view->ColorEdgesOn();
view->SetEdgeLabelArrayName("edge label");
view->EdgeLabelVisibilityOn();
vtkRenderedGraphRepresentation* rep = vtkRenderedGraphRepresentation::SafeDownCast(view->GetRepresentation());
rep->SetVertexHoverArrayName("name");
rep->SetEdgeHoverArrayName("edge label");
view->ResetCamera();
......
......@@ -22,6 +22,7 @@
#include "vtkDataRepresentation.h"
#include "vtkRenderWindow.h"
#include "vtkRegressionTestImage.h"
#include "vtkRenderedTreeAreaRepresentation.h"
#include "vtkRenderer.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkTestUtilities.h"
......@@ -46,13 +47,13 @@ int TestTreeRingView(int argc, char* argv[])
// We need to put the graph and tree edges in different domains.
VTK_CREATE(vtkXMLTreeReader, reader1);
reader1->SetFileName(treeFileName.c_str());
reader1->SetEdgePedigreeIdArrayName("tree edge");
reader1->SetEdgePedigreeIdArrayName("graph edge");
reader1->GenerateVertexPedigreeIdsOff();
reader1->SetVertexPedigreeIdArrayName("id");
VTK_CREATE(vtkXMLTreeReader, reader2);
reader2->SetFileName(graphFileName.c_str());
reader2->SetEdgePedigreeIdArrayName("graph edge");
reader2->SetEdgePedigreeIdArrayName("tree edge");
reader2->GenerateVertexPedigreeIdsOff();
reader2->SetVertexPedigreeIdArrayName("id");
......@@ -78,6 +79,7 @@ int TestTreeRingView(int argc, char* argv[])
view->SetAreaLabelVisibility(true);
view->SetAreaHoverArrayName("id");
view->SetAreaSizeArrayName("VertexDegree");
vtkRenderedTreeAreaRepresentation::SafeDownCast(view->GetRepresentation())->SetGraphHoverArrayName("graph edge");
// Apply a theme to the views
vtkViewTheme* const theme = vtkViewTheme::CreateMellowTheme();
......
......@@ -42,7 +42,7 @@
#include "vtkTextProperty.h"
#include "vtkViewTheme.h"
vtkCxxRevisionMacro(vtkHierarchicalGraphPipeline, "1.12");
vtkCxxRevisionMacro(vtkHierarchicalGraphPipeline, "1.13");
vtkStandardNewMacro(vtkHierarchicalGraphPipeline);
vtkHierarchicalGraphPipeline::vtkHierarchicalGraphPipeline()
......@@ -60,6 +60,7 @@ vtkHierarchicalGraphPipeline::vtkHierarchicalGraphPipeline()
this->ColorArrayNameInternal = 0;
this->LabelArrayNameInternal = 0;
this->HoverArrayName = 0;
/*
<graphviz>
......@@ -101,6 +102,7 @@ vtkHierarchicalGraphPipeline::~vtkHierarchicalGraphPipeline()
{
this->SetColorArrayNameInternal(0);
this->SetLabelArrayNameInternal(0);
this->SetHoverArrayName(0);
this->ApplyColors->Delete();
this->Bundle->Delete();
this->GraphToPoly->Delete();
......
......@@ -114,6 +114,11 @@ public:
// Applies the view theme to this graph.
virtual void ApplyViewTheme(vtkViewTheme* theme);
// Description:
// The array to use while hovering over an edge.
vtkSetStringMacro(HoverArrayName);
vtkGetStringMacro(HoverArrayName);
protected:
vtkHierarchicalGraphPipeline();
~vtkHierarchicalGraphPipeline();
......@@ -129,6 +134,8 @@ protected:
vtkDynamic2DLabelMapper* LabelMapper;
vtkActor2D* LabelActor;
char* HoverArrayName;
vtkSetStringMacro(ColorArrayNameInternal);
vtkGetStringMacro(ColorArrayNameInternal);
char* ColorArrayNameInternal;
......
This diff is collapsed.
......@@ -40,6 +40,8 @@ class vtkAlgorithmOutput;
class vtkArrayCalculator;
class vtkBalloonRepresentation;
class vtkDynamic2DLabelMapper;
class vtkHardwareSelector;
class vtkHoverWidget;
class vtkInteractorObserver;
class vtkLabelPlacementMapper;
class vtkPolyDataMapper2D;
......@@ -230,6 +232,17 @@ protected:
// Called in PrepareForRendering to update the hover text.
virtual void UpdateHoverText();
// Description:
// Enable or disable hovering based on DisplayHoverText ivar
// and interaction state.
virtual void UpdateHoverWidgetState();
// Description:
// Whether to render on every mouse move.
void SetRenderOnMouseMove(bool b);
vtkGetMacro(RenderOnMouseMove, bool);
vtkBooleanMacro(RenderOnMouseMove, bool);
vtkRenderer* Renderer;
vtkRenderer* LabelRenderer;
vtkRenderWindow* RenderWindow;
......@@ -237,6 +250,8 @@ protected:
int InteractionMode;
int LabelRenderMode;
bool DisplayHoverText;
bool Interacting;
bool InHoverTextRender;
vtkAbstractTransform* Transform;
vtkTexture* IconTexture;
......@@ -246,11 +261,15 @@ protected:
vtkSmartPointer<vtkBalloonRepresentation> Balloon;
vtkSmartPointer<vtkLabelPlacementMapper> LabelPlacementMapper;
vtkSmartPointer<vtkTexturedActor2D> LabelActor;
vtkSmartPointer<vtkHoverWidget> HoverWidget;
vtkSmartPointer<vtkHardwareSelector> Selector;
//ETX
private:
vtkRenderView(const vtkRenderView&); // Not implemented.
void operator=(const vtkRenderView&); // Not implemented.
bool RenderOnMouseMove;
};
#endif
......@@ -82,6 +82,7 @@
#include "vtkViewTheme.h"
#include <ctype.h> // So borland 5.6 can find tolower
#include <vtksys/ios/sstream>
/* Fix for BORLAND 5.6 bug where it wrongly chooses remove(const char *) in stdio
instead of the remove stl algorithm. */
......@@ -95,7 +96,7 @@
vtkCxxRevisionMacro(vtkRenderedGraphRepresentation, "1.28");
vtkCxxRevisionMacro(vtkRenderedGraphRepresentation, "1.29");
vtkStandardNewMacro(vtkRenderedGraphRepresentation);
vtkRenderedGraphRepresentation::vtkRenderedGraphRepresentation()
......@@ -129,6 +130,8 @@ vtkRenderedGraphRepresentation::vtkRenderedGraphRepresentation()
this->VertexIconMapper = vtkSmartPointer<vtkPolyDataMapper2D>::New();
this->VertexIconActor = vtkSmartPointer<vtkTexturedActor2D>::New();
this->VertexHoverArrayName = 0;
this->EdgeHoverArrayName = 0;
this->VertexColorArrayNameInternal = 0;
this->EdgeColorArrayNameInternal = 0;
this->ScalingArrayNameInternal = 0;
......@@ -245,6 +248,8 @@ vtkRenderedGraphRepresentation::~vtkRenderedGraphRepresentation()
this->SetEdgeColorArrayNameInternal(0);
this->SetLayoutStrategyName(0);
this->SetEdgeLayoutStrategyName(0);
this->SetVertexHoverArrayName(0);
this->SetEdgeHoverArrayName(0);
}
void vtkRenderedGraphRepresentation::SetVertexLabelArrayName(const char* name)
......@@ -1086,6 +1091,7 @@ vtkSelection* vtkRenderedGraphRepresentation::ConvertSelection(
vtkSmartPointer<vtkSelection> vertexSel =
vtkSmartPointer<vtkSelection>::New();
vertexSel->AddNode(vertexNode);
vtkPolyData* poly = vtkPolyData::SafeDownCast(
this->VertexGlyph->GetOutput());
vtkSmartPointer<vtkTable> temp =
......@@ -1392,6 +1398,32 @@ void vtkRenderedGraphRepresentation::ComputeSelectedGraphBounds(double bounds[6]
}
}
vtkUnicodeString vtkRenderedGraphRepresentation::GetHoverTextInternal(vtkSelection* sel)
{
vtkGraph* input = vtkGraph::SafeDownCast(this->GetInput());
vtkSmartPointer<vtkIdTypeArray> selectedItems = vtkSmartPointer<vtkIdTypeArray>::New();
vtkConvertSelection::GetSelectedVertices(sel, input, selectedItems);
vtkDataSetAttributes* data = input->GetVertexData();
const char* hoverArrName = this->GetVertexHoverArrayName();
if (selectedItems->GetNumberOfTuples() == 0)
{
vtkConvertSelection::GetSelectedEdges(sel, input, selectedItems);
data = input->GetEdgeData();
hoverArrName = this->GetEdgeHoverArrayName();
}
if (selectedItems->GetNumberOfTuples() == 0 || !hoverArrName)
{
return vtkUnicodeString();
}
vtkAbstractArray* arr = data->GetAbstractArray(hoverArrName);
if (!arr)
{
return vtkUnicodeString();
}
vtkIdType item = selectedItems->GetValue(0);
return arr->GetVariantValue(item).ToUnicodeString();
}
void vtkRenderedGraphRepresentation::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os, indent);
......@@ -1399,4 +1431,8 @@ void vtkRenderedGraphRepresentation::PrintSelf(ostream& os, vtkIndent indent)
<< (this->LayoutStrategyName ? this->LayoutStrategyName : "(none)") << endl;
os << indent << "EdgeLayoutStrategyName: "
<< (this->EdgeLayoutStrategyName ? this->EdgeLayoutStrategyName : "(none)") << endl;
os << indent << "VertexHoverArrayName: "
<< (this->VertexHoverArrayName ? this->VertexHoverArrayName : "(none)") << endl;
os << indent << "EdgeHoverArrayName: "
<< (this->EdgeHoverArrayName ? this->EdgeHoverArrayName : "(none)") << endl;
}
......@@ -78,6 +78,8 @@ public:
vtkBooleanMacro(VertexLabelVisibility, bool);
virtual void SetVertexLabelTextProperty(vtkTextProperty* p);
virtual vtkTextProperty* GetVertexLabelTextProperty();
vtkSetStringMacro(VertexHoverArrayName);
vtkGetStringMacro(VertexHoverArrayName);
// ------------------------------------------------------------------------
// Edge labels
......@@ -91,6 +93,8 @@ public:
vtkBooleanMacro(EdgeLabelVisibility, bool);
virtual void SetEdgeLabelTextProperty(vtkTextProperty* p);
virtual vtkTextProperty* GetEdgeLabelTextProperty();
vtkSetStringMacro(EdgeHoverArrayName);
vtkGetStringMacro(EdgeHoverArrayName);
// ------------------------------------------------------------------------
// Vertex icons
......@@ -343,6 +347,10 @@ protected:
virtual vtkSelection* ConvertSelection(vtkView* view, vtkSelection* sel);
//BTX
virtual vtkUnicodeString GetHoverTextInternal(vtkSelection* sel);
//ETX
// Description:
// Connect inputs to internal pipeline.
virtual int RequestData(
......@@ -383,6 +391,9 @@ protected:
vtkSmartPointer<vtkTexturedActor2D> VertexIconActor;
//ETX
char* VertexHoverArrayName;
char* EdgeHoverArrayName;
vtkSetStringMacro(VertexColorArrayNameInternal);
vtkGetStringMacro(VertexColorArrayNameInternal);
char* VertexColorArrayNameInternal;
......
......@@ -20,14 +20,19 @@
#include "vtkRenderedRepresentation.h"
#include "vtkIdTypeArray.h"
#include "vtkInformation.h"
#include "vtkObjectFactory.h"
#include "vtkProp.h"
#include "vtkRenderer.h"
#include "vtkRenderView.h"
#include "vtkSelection.h"
#include "vtkSelectionNode.h"
#include "vtkSmartPointer.h"
#include <vtkstd/vector>
vtkCxxRevisionMacro(vtkRenderedRepresentation, "1.3");
vtkCxxRevisionMacro(vtkRenderedRepresentation, "1.4");
vtkStandardNewMacro(vtkRenderedRepresentation);
class vtkRenderedRepresentation::Internals
......@@ -78,6 +83,26 @@ void vtkRenderedRepresentation::PrepareForRendering(vtkRenderView* view)
this->Implementation->PropsToRemove.clear();
}
vtkUnicodeString vtkRenderedRepresentation::GetHoverText(vtkView* view, vtkProp* prop, vtkIdType cell)
{
vtkSmartPointer<vtkSelection> cellSelect = vtkSmartPointer<vtkSelection>::New();
vtkSmartPointer<vtkSelectionNode> cellNode = vtkSmartPointer<vtkSelectionNode>::New();
cellNode->GetProperties()->Set(vtkSelectionNode::PROP(), prop);
cellNode->SetFieldType(vtkSelectionNode::CELL);
cellNode->SetContentType(vtkSelectionNode::INDICES);
vtkSmartPointer<vtkIdTypeArray> idArr = vtkSmartPointer<vtkIdTypeArray>::New();
idArr->InsertNextValue(cell);
cellNode->SetSelectionList(idArr);
cellSelect->AddNode(cellNode);
vtkSelection* converted = this->ConvertSelection(view, cellSelect);
vtkUnicodeString text = this->GetHoverTextInternal(converted);
if (converted != cellSelect.GetPointer())
{
converted->Delete();
}
return text;
}
void vtkRenderedRepresentation::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os, indent);
......
......@@ -26,6 +26,7 @@
#include "vtkDataRepresentation.h"
#include "vtkSmartPointer.h" // for SP ivars
#include "vtkUnicodeString.h" // for string
class vtkApplyColors;
class vtkProp;
......@@ -61,9 +62,19 @@ protected:
void AddPropOnNextRender(vtkProp* p);
void RemovePropOnNextRender(vtkProp* p);
virtual const char* GetHoverText(
vtkView* vtkNotUsed(view), int vtkNotUsed(x), int vtkNotUsed(y))
{ return 0; }
//BTX
// Description:
// Obtains the hover text for a particular prop and cell.
// If the prop is not applicable to the representation, return an empty string.
// Subclasses should override GetHoverTextInternal, in which the prop and cell
// are converted to an appropriate selection using ConvertSelection().
vtkUnicodeString GetHoverText(vtkView* view, vtkProp* prop, vtkIdType cell);
// Description:
// Subclasses may override this method to generate the hover text.
virtual vtkUnicodeString GetHoverTextInternal(vtkSelection*)
{ return vtkUnicodeString(); }
//ETX
// Description:
// The view will call this method before every render.
......
......@@ -81,7 +81,7 @@ public:
vtkstd::vector<vtkSmartPointer<vtkHierarchicalGraphPipeline> > Graphs;
};
vtkCxxRevisionMacro(vtkRenderedTreeAreaRepresentation, "1.15");
vtkCxxRevisionMacro(vtkRenderedTreeAreaRepresentation, "1.16");
vtkStandardNewMacro(vtkRenderedTreeAreaRepresentation);
vtkRenderedTreeAreaRepresentation::vtkRenderedTreeAreaRepresentation()
......@@ -313,6 +313,23 @@ bool vtkRenderedTreeAreaRepresentation::GetEdgeScalarBarVisibility()
return this->EdgeScalarBar->GetScalarBarActor()->GetVisibility() ? true : false;
}
void vtkRenderedTreeAreaRepresentation::SetGraphHoverArrayName(const char* name, int idx)
{
if (this->ValidIndex(idx))
{
this->Implementation->Graphs[idx]->SetHoverArrayName(name);
}
}
const char* vtkRenderedTreeAreaRepresentation::GetGraphHoverArrayName(int idx)
{
if (this->ValidIndex(idx))
{
return this->Implementation->Graphs[idx]->GetHoverArrayName();
}
return 0;
}
void vtkRenderedTreeAreaRepresentation::SetAreaLabelMapper(vtkLabeledDataMapper* mapper)
{
// AreaLayout -> AreaLabelMapper -> AreaLabelActor
......@@ -359,43 +376,38 @@ void vtkRenderedTreeAreaRepresentation::SetAreaToPolyData(vtkPolyDataAlgorithm*
}
}
const char* vtkRenderedTreeAreaRepresentation::GetHoverText(vtkView* view, int x, int y)
vtkUnicodeString vtkRenderedTreeAreaRepresentation::GetHoverTextInternal(vtkSelection* sel)
{
if (!this->AreaHoverArrayName)
{
return 0;
}
// Make sure we have a context.
vtkRenderer* r = vtkRenderView::SafeDownCast(view)->GetRenderer();
vtkRenderWindow* win = r->GetRenderWindow();
if (!win)
vtkGraph* input = vtkGraph::SafeDownCast(this->GetInput());
vtkSmartPointer<vtkIdTypeArray> selectedItems = vtkSmartPointer<vtkIdTypeArray>::New();
vtkConvertSelection::GetSelectedVertices(sel, input, selectedItems);
vtkDataSetAttributes* data = input->GetVertexData();
const char* hoverArrName = this->GetAreaHoverArrayName();
if (selectedItems->GetNumberOfTuples() == 0)
{
return 0;
for (int i = 0; i < this->GetNumberOfInputConnections(i); ++i)
{
vtkGraph* g = vtkGraph::SafeDownCast(this->GetInputDataObject(1, i));
vtkConvertSelection::GetSelectedEdges(sel, g, selectedItems);
if (selectedItems->GetNumberOfTuples() > 0)
{
hoverArrName = this->GetGraphHoverArrayName(i);
data = g->GetEdgeData();
break;
}
}
}
win->MakeCurrent();
if (!win->IsCurrent())
if (selectedItems->GetNumberOfTuples() == 0 || !hoverArrName)
{
return 0;
return vtkUnicodeString();
}
// Use the hardware picker to find a point in world coordinates.
this->Picker->Pick(x, y, 0, r);
double pos[3];
this->Picker->GetPickPosition(pos);
float posFloat[3] = {pos[0], pos[1], pos[2]};
this->AreaLayout->Update();
vtkIdType id = this->AreaLayout->FindVertex(posFloat);
if (id >= 0)
vtkAbstractArray* arr = data->GetAbstractArray(hoverArrName);
if (!arr)
{
vtkAbstractArray* arr = this->AreaLayout->GetOutput()->
GetVertexData()->GetAbstractArray(this->AreaHoverArrayName);
if (arr)
{
this->SetAreaHoverTextInternal(arr->GetVariantValue(id).ToString());
return this->GetAreaHoverTextInternal();
}
return vtkUnicodeString();
}
return 0;
vtkIdType item = selectedItems->GetValue(0);
return arr->GetVariantValue(item).ToUnicodeString();
}
void vtkRenderedTreeAreaRepresentation::UpdateHoverHighlight(vtkView* view, int x, int y)
......@@ -809,6 +821,10 @@ vtkSelection* vtkRenderedTreeAreaRepresentation::ConvertSelection(
for(vtkIdType j=0; j<arr->GetNumberOfTuples(); ++j)
{
vtkIdType id = arr2->LookupValue(arr->GetVariantValue(j));
if (id == -1)
{
continue;