Commit 166ea660 authored by Marcus D. Hanwell's avatar Marcus D. Hanwell
Browse files

ENH: Changed the custom tooltip API around a little.

Use two format strings, default and custom, and reduce down to just one
virtual function. Maintained recursive parsing of string replacements,
and set defaults when various plot parameters are modified.

Change-Id: I6c5bf09b28fed9f58dcff17078d4931acdafccf6
parent b268a73f
......@@ -79,6 +79,8 @@ int TestScatterPlot(int , char * [])
points->SetInput(table.GetPointer(), 0, 1);
points->SetColor(0, 0, 0, 255);
points->SetWidth(1.0);
points->SetIndexedLabels(labels.GetPointer());
points->SetTooltipLabelFormat("%i from %l (%x, %y)");
vtkPlotPoints::SafeDownCast(points)->SetMarkerStyle(vtkPlotPoints::CROSS);
points = chart->AddPlot(vtkChart::POINTS);
points->SetInput(table.GetPointer(), 0, 2);
......
......@@ -1277,8 +1277,8 @@ void vtkChartXY::SetTooltipInfo(const vtkContextMouseEvent& mouse,
vtkIdType segmentIndex)
{
// Have the plot generate its tooltip label
vtkStdString tooltipLabel;
plot->GetTooltipLabel(plotPos, seriesIndex, segmentIndex, &tooltipLabel);
vtkStdString tooltipLabel = plot->GetTooltipLabel(plotPos, seriesIndex,
segmentIndex);
// Set the tooltip
this->Tooltip->SetText(tooltipLabel);
......
......@@ -42,6 +42,8 @@ vtkPlot::vtkPlot()
this->Selection = NULL;
this->XAxis = NULL;
this->YAxis = NULL;
this->TooltipDefaultLabelFormat = "%l: %x, %y";
}
//-----------------------------------------------------------------------------
......@@ -86,123 +88,85 @@ vtkIdType vtkPlot::GetNearestPoint(const vtkVector2f&, const vtkVector2f&,
}
//-----------------------------------------------------------------------------
void vtkPlot::GetTooltipLabel(const vtkVector2f &plotPos,
vtkIdType seriesIndex,
vtkIdType segmentIndex,
vtkStdString* tooltipLabel)
{
if (!tooltipLabel)
{
return;
}
tooltipLabel->clear();
if (this->TooltipLabelFormat.empty())
{
this->GetDefaultTooltipLabel(plotPos, seriesIndex, segmentIndex,
tooltipLabel);
}
else
{
this->GetCustomTooltipLabel(plotPos, seriesIndex, segmentIndex,
tooltipLabel);
}
}
//-----------------------------------------------------------------------------
void vtkPlot::GetDefaultTooltipLabel(const vtkVector2f &plotPos,
vtkIdType seriesIndex,
vtkIdType segmentIndex,
vtkStdString* tooltipLabel)
vtkStdString vtkPlot::GetTooltipLabel(const vtkVector2f &plotPos,
vtkIdType seriesIndex,
vtkIdType)
{
this->TooltipLabelFormat.clear(); // Should already be empty
if (this->IndexedLabels)
{
this->TooltipLabelFormat += "%i";
}
else
{
this->TooltipLabelFormat += "%l";
}
this->TooltipLabelFormat += ": %x, %y";
this->GetCustomTooltipLabel(plotPos, seriesIndex, segmentIndex,
tooltipLabel);
this->TooltipLabelFormat.clear();
}
//-----------------------------------------------------------------------------
void vtkPlot::GetCustomTooltipLabel(const vtkVector2f &plotPos,
vtkIdType seriesIndex,
vtkIdType segmentIndex,
vtkStdString* tooltipLabel)
{
// Determine and format the X and Y position in the chart
vtksys_ios::ostringstream ostr;
ostr.imbue(vtkstd::locale::classic());
ostr.setf(ios::fixed, ios::floatfield);
ostr.precision(this->XAxis->GetPrecision());
// If axes are set to logarithmic scale we need to convert the
// axis value using 10^(axis value)
ostr << (this->XAxis->GetLogScale()?
pow(double(10.0), double(plotPos.X())):
plotPos.X());
vtkStdString chartPosX(ostr.str());
ostr.str("");
ostr.precision(this->YAxis->GetPrecision());
ostr << (this->YAxis->GetLogScale()?
pow(double(10.0), double(plotPos.Y())):
plotPos.Y());
vtkStdString chartPosY(ostr.str());
vtkStdString tooltipLabel;
vtkStdString &format = this->TooltipLabelFormat.empty() ?
this->TooltipDefaultLabelFormat : this->TooltipLabelFormat;
// Parse TooltipLabelFormat and build tooltipLabel
bool escapeNext = false;
for (int i =0; i < TooltipLabelFormat.length(); i++)
for (size_t i = 0; i < format.length(); ++i)
{
if (escapeNext)
{
switch (TooltipLabelFormat.at(i))
switch (format[i])
{
case 'x':
*tooltipLabel += chartPosX;
tooltipLabel += this->GetNumber(plotPos.X(), this->XAxis);
break;
case 'y':
*tooltipLabel += chartPosY;
tooltipLabel += this->GetNumber(plotPos.Y(), this->YAxis);
break;
case 'i':
if (this->IndexedLabels &&
seriesIndex >= 0 &&
seriesIndex < this->IndexedLabels->GetNumberOfTuples())
{
*tooltipLabel += this->IndexedLabels->GetValue(seriesIndex);
tooltipLabel += this->IndexedLabels->GetValue(seriesIndex);
}
break;
case 'l':
// GetLabel() is GetLabel(0) in this implementation
*tooltipLabel += this->GetLabel();
tooltipLabel += this->GetLabel();
break;
default: // If no match, insert the entire format tag
*tooltipLabel += "%";
*tooltipLabel += TooltipLabelFormat.at(i);
tooltipLabel += "%";
tooltipLabel += format[i];
break;
}
escapeNext = false;
}
else
{
if (TooltipLabelFormat.at(i) == '%')
if (format[i] == '%')
{
escapeNext = true;
}
else
{
*tooltipLabel += TooltipLabelFormat.at(i);
tooltipLabel += format[i];
}
}
}
return tooltipLabel;
}
//-----------------------------------------------------------------------------
vtkStdString vtkPlot::GetNumber(double position, vtkAxis *axis)
{
// Determine and format the X and Y position in the chart
vtksys_ios::ostringstream ostr;
ostr.imbue(vtkstd::locale::classic());
ostr.setf(ios::fixed, ios::floatfield);
if (axis)
{
ostr.precision(this->XAxis->GetPrecision());
}
if (axis && axis->GetLogScale())
{
// If axes are set to logarithmic scale we need to convert the
// axis value using 10^(axis value)
ostr << pow(double(10.0), double(position));
}
else
{
ostr << position;
}
return ostr.str();
}
//-----------------------------------------------------------------------------
......@@ -325,6 +289,15 @@ void vtkPlot::SetIndexedLabels(vtkStringArray *labels)
return;
}
if (labels)
{
this->TooltipDefaultLabelFormat = "%i: %x, %y";
}
else
{
this->TooltipDefaultLabelFormat = "%l: %x, %y";
}
this->IndexedLabels = labels;
this->Modified();
}
......
......@@ -69,6 +69,13 @@ public:
virtual vtkStdString GetTooltipLabelFormat();
//BTX
// Description:
// Generate and return the tooltip label string for this plot
// The segmentIndex parameter is ignored, except for vtkPlotBar
virtual vtkStdString GetTooltipLabel(const vtkVector2f &plotPos,
vtkIdType seriesIndex,
vtkIdType segmentIndex);
// Description:
// Function to query a plot for the nearest point to the specified coordinate.
// Returns the index of the data series with which the point is associated, or
......@@ -77,14 +84,6 @@ public:
const vtkVector2f& tolerance,
vtkVector2f* location);
// Description:
// Generate and return the tooltip label string for this plot
// The segmentIndex parameter is ignored, except for vtkPlotBar
virtual void GetTooltipLabel(const vtkVector2f &plotPos,
vtkIdType seriesIndex,
vtkIdType segmentIndex,
vtkStdString* tooltipLabel);
// Description:
// Select all points in the specified rectangle.
virtual bool SelectPoints(const vtkVector2f& min, const vtkVector2f& max);
......@@ -214,22 +213,8 @@ protected:
~vtkPlot();
// Description:
// Generate and return the tooltip label string for this plot.
// Called if TooltipLabelFormat is empty.
// May be reimplemented by plot types subclassing vtkPlot.
virtual void GetDefaultTooltipLabel(const vtkVector2f &plotPos,
vtkIdType seriesIndex,
vtkIdType segmentIndex,
vtkStdString* tooltipLabel);
// Description:
// Generate and return a user-formatted tooltip label string for this plot.
// Called if TooltipLabelFormat is not empty.
// May be reimplemented by plot types subclassing vtkPlot.
virtual void GetCustomTooltipLabel(const vtkVector2f &plotPos,
vtkIdType seriesIndex,
vtkIdType segmentIndex,
vtkStdString* tooltipLabel);
// Get the properly formatted number for the supplied position and axis.
vtkStdString GetNumber(double position, vtkAxis *axis);
// Description:
// This object stores the vtkPen that controls how the plot is drawn.
......@@ -278,6 +263,11 @@ protected:
// See the accessor/mutator functions for full documentation.
vtkStdString TooltipLabelFormat;
// Description:
// The default printf-style string to build custom tooltip labels from.
// See the accessor/mutator functions for full documentation.
vtkStdString TooltipDefaultLabelFormat;
private:
vtkPlot(const vtkPlot &); // Not implemented.
void operator=(const vtkPlot &); // Not implemented.
......
......@@ -782,6 +782,18 @@ bool vtkPlotBar::UpdateTableCache(vtkTable *table)
prev = this->Private->AddSegment(x,y,prev);
}
this->TooltipDefaultLabelFormat.clear();
// Set the default tooltip according to the segments
if (this->Private->Segments.size() > 1)
{
this->TooltipDefaultLabelFormat = "%s: ";
}
if (this->IndexedLabels)
{
this->TooltipDefaultLabelFormat += "%i: ";
}
this->TooltipDefaultLabelFormat += "%x, %y";
this->BuildTime.Modified();
return true;
}
......@@ -840,80 +852,45 @@ bool vtkPlotBar::SelectPoints(const vtkVector2f& min, const vtkVector2f& max)
}
//-----------------------------------------------------------------------------
void vtkPlotBar::GetDefaultTooltipLabel(const vtkVector2f &plotPos,
vtkIdType seriesIndex,
vtkIdType segmentIndex,
vtkStdString* tooltipLabel)
{
// If we are plotting stacked bars, add segment names
if (this->Private->Segments.size() > 1)
{
this->TooltipLabelFormat.clear(); // Should already be empty
this->TooltipLabelFormat += "%s";
if (this->IndexedLabels)
{
this->TooltipLabelFormat += ": %i";
}
this->TooltipLabelFormat += ": %x, %y";
this->GetCustomTooltipLabel(plotPos, seriesIndex, segmentIndex,
tooltipLabel);
this->TooltipLabelFormat.clear();
}
else // No stacked bars
{
// Use vtkPlot's implementation
Superclass::GetDefaultTooltipLabel(plotPos, seriesIndex, segmentIndex,
tooltipLabel);
}
}
//-----------------------------------------------------------------------------
void vtkPlotBar::GetCustomTooltipLabel(const vtkVector2f &plotPos,
vtkIdType seriesIndex,
vtkIdType segmentIndex,
vtkStdString* tooltipLabel)
vtkStdString vtkPlotBar::GetTooltipLabel(const vtkVector2f &plotPos,
vtkIdType seriesIndex,
vtkIdType segmentIndex)
{
// Generate most of the custom tooltip label using vtkPlot's implementation
vtkStdString baseTooltipLabel;
Superclass::GetCustomTooltipLabel(plotPos, seriesIndex, segmentIndex,
&baseTooltipLabel);
// Go through the baseTooltipLabel, and replace any vtkPlotBar-specific
// format tag
vtkStdString baseLabel = Superclass::GetTooltipLabel(plotPos, seriesIndex,
segmentIndex);
vtkStdString tooltipLabel;
bool escapeNext = false;
for (int i =0; i < baseTooltipLabel.length(); i++)
for (size_t i = 0; i < baseLabel.length(); ++i)
{
if (escapeNext)
{
switch (baseTooltipLabel.at(i))
switch (baseLabel[i])
{
case 's':
if (segmentIndex >= 0 &&
this->GetLabels() &&
if (segmentIndex >= 0 && this->GetLabels() &&
segmentIndex < this->GetLabels()->GetNumberOfTuples())
{
*tooltipLabel += this->GetLabels()->GetValue(segmentIndex);
tooltipLabel += this->GetLabels()->GetValue(segmentIndex);
}
break;
default: // If no match, insert the entire format tag
*tooltipLabel += "%";
*tooltipLabel += baseTooltipLabel.at(i);
tooltipLabel += "%";
tooltipLabel += baseLabel[i];
break;
}
escapeNext = false;
}
else
{
if (baseTooltipLabel.at(i) == '%')
if (baseLabel[i] == '%')
{
escapeNext = true;
}
else
{
*tooltipLabel += baseTooltipLabel.at(i);
tooltipLabel += baseLabel[i];
}
}
}
return tooltipLabel;
}
......@@ -119,6 +119,13 @@ public:
// Get the group name of the bar char - can be displayed on the X axis.
virtual vtkStdString GetGroupName();
// Description:
// Generate and return the tooltip label string for this plot
// The segmentIndex is implemented here.
virtual vtkStdString GetTooltipLabel(const vtkVector2f &plotPos,
vtkIdType seriesIndex,
vtkIdType segmentIndex);
// Description:
// Select all points in the specified rectangle.
virtual bool SelectPoints(const vtkVector2f& min, const vtkVector2f& max);
......@@ -147,25 +154,6 @@ protected:
vtkPlotBar();
~vtkPlotBar();
// Description:
// Generate and return the tooltip label string for this plot.
// Called if TooltipLabelFormat is empty.
// Reimplimented from vtkPlot, to use the segmentIndex parameter.
virtual void GetDefaultTooltipLabel(const vtkVector2f &plotPos,
vtkIdType seriesIndex,
vtkIdType segmentIndex,
vtkStdString* tooltipLabel);
// Description:
// Generate and return a user-formatted tooltip label string for this plot.
// Called if TooltipLabelFormat is not empty.
// Reimplimented from vtkPlot, to use the segmentIndex
// parameter ('%s' format tag).
virtual void GetCustomTooltipLabel(const vtkVector2f &plotPos,
vtkIdType seriesIndex,
vtkIdType segmentIndex,
vtkStdString* tooltipLabel);
// Description:
// Update the table cache.
bool UpdateTableCache(vtkTable *table);
......
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