Commit 0d07f53f authored by Utkarsh Ayachit's avatar Utkarsh Ayachit

BUG #13818. Updating Axis Range mangement for charts.

- Added ability to manually specify the range for any axes. Users can now
  specify a fixed range for any of the axes using the "View Settings" dialgor
  the chart views.
- By default, the views scale the axes to fit the data being shown. Thus the
  axis will be scaled over time too. To avoid scaling over time, users need to
  set the axis to use fixed range.
- This is indenpent of labels being rendered. Users can still let the label
  placement be controlled automatically or manually.
- Even with "fixed ranges", if the user interacts with the chart, the ranges are
  updated to those the user picks as a consequence of the interaction.

Added a new test "ChartAxisRangeAndLabels" that tests various configurations for
ranges and labels.

Change-Id: I3388a42aea69ed82e650167071c8fba73f5cd186
parent b7dfbe7f
......@@ -64,6 +64,7 @@ SET (TESTS_WITH_BASELINES
${CMAKE_CURRENT_SOURCE_DIR}/CalcParens.xml
${CMAKE_CURRENT_SOURCE_DIR}/Calculator.xml
${CMAKE_CURRENT_SOURCE_DIR}/CameraLink.xml
${CMAKE_CURRENT_SOURCE_DIR}/ChartAxisRangeAndLabels.xml
${CMAKE_CURRENT_SOURCE_DIR}/Clip.xml
${CMAKE_CURRENT_SOURCE_DIR}/NewColorEditor1.xml
${CMAKE_CURRENT_SOURCE_DIR}/ColorEditor2.xml
......@@ -216,6 +217,7 @@ set(AnimatePipelineTime_USE_NEW_PANELS TRUE)
set(CalcParens_USE_NEW_PANELS TRUE)
set(Calculator_USE_NEW_PANELS TRUE)
set(CameraLink_USE_NEW_PANELS TRUE)
set(ChartAxisRangeAndLabels_USE_NEW_PANELS TRUE)
set(Clip_USE_NEW_PANELS TRUE)
set(ColorEditor2_USE_NEW_PANELS TRUE)
set(ColorEditor4_USE_NEW_PANELS TRUE)
......@@ -386,6 +388,7 @@ SET (SpreadSheet1_BREAK TRUE)
SET (SPTimeseries_BREAK TRUE)
SET (XYChart_BREAK TRUE)
SET (XYHistogram_BREAK TRUE)
set (ChartAxisRangeAndLabels_BREAK TRUE)
SET(ExtractLevel_BREAK TRUE)
......@@ -401,6 +404,7 @@ SET (UndoRedo4_THRESHOLD 15)
SET (XYChart_THRESHOLD 150)
SET (XYHistogram_THRESHOLD 60)
set (ChartAxisRangeAndLabels_THRESHOLD 60)
# The color and opacity are often different on different machines.
SET (NewColorEditor1_THRESHOLD 60)
......
This diff is collapsed.
......@@ -44,7 +44,18 @@ public:
{
this->UseCustomLabels[0] = this->UseCustomLabels[1]
= this->UseCustomLabels[2] = this->UseCustomLabels[3] = false;
this->AxisRanges[0][0] =
this->AxisRanges[1][0] =
this->AxisRanges[2][0] =
this->AxisRanges[3][0] = 0.0;
this->AxisRanges[0][1] =
this->AxisRanges[1][1] =
this->AxisRanges[2][1] =
this->AxisRanges[3][1] = 6.66;
}
double AxisRanges[4][2];
};
......@@ -337,28 +348,48 @@ void vtkPVXYChartView::SetAxisLabelPrecision(int index, int precision)
//----------------------------------------------------------------------------
void vtkPVXYChartView::SetAxisRange(int index, double min, double max)
{
// cache for later use.
this->Internals->AxisRanges[index][0] = min;
this->Internals->AxisRanges[index][1] = max;
if (this->Chart)
{
vtkAxis* axis = this->Chart->GetAxis(index);
axis->SetBehavior(vtkAxis::FIXED);
axis->SetMinimum(min);
axis->SetMaximum(max);
this->Chart->RecalculateBounds();
if (axis->GetBehavior() == vtkAxis::FIXED)
{
// change only if axes behavior is indeed "FIXED" i.e.
// SetAxisUseCustomRange(...) was set to true for this axis.
if (axis->GetMinimum() != min || axis->GetMaximum() != max)
{
axis->SetMinimum(min);
axis->SetMaximum(max);
this->Chart->RecalculateBounds();
}
}
}
}
//----------------------------------------------------------------------------
void vtkPVXYChartView::UnsetAxisRange(int index)
void vtkPVXYChartView::SetAxisUseCustomRange(int index, bool useCustomRange)
{
if (this->Chart)
{
vtkAxis* axis = this->Chart->GetAxis(index);
axis->SetBehavior(vtkAxis::AUTO);
// we set some random min and max so we can notice them when they get used.
axis->SetMinimum(0.0);
axis->SetMaximum(6.66);
this->Chart->RecalculateBounds();
if (useCustomRange && (axis->GetBehavior() != vtkAxis::FIXED))
{
axis->SetBehavior(vtkAxis::FIXED);
axis->SetMinimum(this->Internals->AxisRanges[index][0]);
axis->SetMaximum(this->Internals->AxisRanges[index][1]);
this->Chart->RecalculateBounds();
}
else if (!useCustomRange && (axis->GetBehavior() != vtkAxis::AUTO))
{
axis->SetBehavior(vtkAxis::AUTO);
// set to some value so we notice when this gets used.
axis->SetMinimum(0.0);
axis->SetMaximum(6.66);
this->Chart->RecalculateBounds();
}
}
}
......
......@@ -146,10 +146,12 @@ public:
void SetAxisLabelPrecision(int index, int precision);
// Description:
// For axis ranges, ParaView overrides the VTK charts behavior. Instead of
// letting the user choose the behavior, we only have 2 modes, if any range is
// set, then the range is always used. If no range is set, then alone we let
// the chart determine the range.
// For axis ranges, ParaView overrides the VTK charts behavior.
// Users can either specify an explicit range or let the VTK chart determine
// the range based on the data. To specify a range explicitly, users should
// use SetAxisUseCustomRange() to on for the corresponding axis and then use
// these methods to set the ranges. Note these ranges are only respected when
// the corresponding AxisUseCustomRange flag it set.
void SetLeftAxisRange(double minimum, double maximum)
{ this->SetAxisRange(vtkAxis::LEFT, minimum, maximum); }
void SetRightAxisRange(double minimum, double maximum)
......@@ -158,14 +160,12 @@ public:
{ this->SetAxisRange(vtkAxis::TOP, minimum, maximum); }
void SetBottomAxisRange(double minimum, double maximum)
{ this->SetAxisRange(vtkAxis::BOTTOM, minimum, maximum); }
void UnsetLeftAxisRange()
{ this->UnsetAxisRange(vtkAxis::LEFT); }
void UnsetRightAxisRange()
{ this->UnsetAxisRange(vtkAxis::RIGHT); }
void UnsetTopAxisRange()
{ this->UnsetAxisRange(vtkAxis::TOP); }
void UnsetBottomAxisRange()
{ this->UnsetAxisRange(vtkAxis::BOTTOM); }
// Description:
// Set whether to use the range specified by SetAxisRange(..) (or variants) or
// to let the chart determine the range automatically based on the data being
// shown.
void SetAxisUseCustomRange(int index, bool useCustomRange);
// Description:
// Sets whether or not the given axis uses a log10 scale.
......
......@@ -188,18 +188,16 @@ static void update_property(vtkAxis* axis, vtkSMProperty* prop)
{
double range[2];
axis->GetRange(range);
vtkSMPropertyHelper(prop).SetNumberOfElements(2);
vtkSMPropertyHelper(prop).Set(range, 2);
}
}
//----------------------------------------------------------------------------
void vtkSMContextViewProxy::OnInteractionEvent()
void vtkSMContextViewProxy::CopyAxisRangesFromChart()
{
vtkChartXY *chartXY = vtkChartXY::SafeDownCast(this->GetContextItem());
if (chartXY)
{
// FIXME: Generalize to support charts with zero to many axes.
update_property(
chartXY->GetAxis(vtkAxis::LEFT), this->GetProperty("LeftAxisRange"));
update_property(
......@@ -209,6 +207,21 @@ void vtkSMContextViewProxy::OnInteractionEvent()
update_property(
chartXY->GetAxis(vtkAxis::BOTTOM), this->GetProperty("BottomAxisRange"));
this->UpdateVTKObjects();
}
}
//----------------------------------------------------------------------------
void vtkSMContextViewProxy::OnInteractionEvent()
{
vtkChartXY *chartXY = vtkChartXY::SafeDownCast(this->GetContextItem());
if (chartXY)
{
// On interaction, we ensure that the axis range properties reflect the
// values that the user ended up picking due to the interactions. Thus, even
// when user picks custom ranges for charts, he can still interact with the
// view, we just update the custom range that was specified.
this->CopyAxisRangesFromChart();
this->UpdateVTKObjects();
this->InvokeEvent(vtkCommand::InteractionEvent);
}
}
......@@ -216,15 +229,34 @@ void vtkSMContextViewProxy::OnInteractionEvent()
//-----------------------------------------------------------------------------
void vtkSMContextViewProxy::ResetDisplay()
{
vtkSMPropertyHelper(this, "LeftAxisRange", true).SetNumberOfElements(0);
vtkSMPropertyHelper(this, "RightAxisRange", true).SetNumberOfElements(0);
vtkSMPropertyHelper(this, "TopAxisRange", true).SetNumberOfElements(0);
vtkSMPropertyHelper(this, "BottomAxisRange", true).SetNumberOfElements(0);
this->UpdateProperty("LeftAxisRange", 1);
this->UpdateProperty("RightAxisRange", 1);
this->UpdateProperty("TopAxisRange", 1);
this->UpdateProperty("BottomAxisRange", 1);
this->StillRender();
// To simulate reset display, we turn-off using of custom ranges temporarily,
// compute the bounds and then restore the state.
vtkChartXY *chartXY = vtkChartXY::SafeDownCast(this->GetContextItem());
if (chartXY)
{
bool axis_behavior_fixed[4] = {false, false, false, false};
for (int cc=0; cc < 4; cc++)
{
vtkAxis* axis = chartXY->GetAxis(cc);
if (axis && axis->GetBehavior() == vtkAxis::FIXED)
{
axis_behavior_fixed[cc] = true;
axis->SetBehavior(vtkAxis::AUTO);
}
}
this->StillRender();
chartXY->RecalculateBounds();
this->CopyAxisRangesFromChart();
this->UpdateVTKObjects();
for (int cc=0; cc < 4; cc++)
{
vtkAxis* axis = chartXY->GetAxis(cc);
if (axis && axis_behavior_fixed[cc])
{
axis->SetBehavior(vtkAxis::FIXED);
}
}
}
}
//----------------------------------------------------------------------------
......
......@@ -78,6 +78,11 @@ protected:
private:
vtkSMContextViewProxy(const vtkSMContextViewProxy&); // Not implemented
void operator=(const vtkSMContextViewProxy&); // Not implemented
// Description:
// Copies axis ranges from each of the vtkAxis on the vtkChartXY to the
// SMproperties.
void CopyAxisRangesFromChart();
//ETX
};
......
......@@ -776,36 +776,48 @@
min="0"
name="range" />
</IntVectorProperty>
<DoubleVectorProperty clean_command="UnsetLeftAxisRange"
command="SetLeftAxisRange"
default_values="none"
<IntVectorProperty command="SetAxisUseCustomRange"
default_values="0 0 0 0"
name="AxisUseCustomRange"
number_of_elements="4"
number_of_elements_per_command="1"
repeat_command="1"
use_index="1">
<BooleanDomain name="bool" />
<Documentation>
Specify whether to use the axis range specified or whether the view
should compute the ranges automatically based on the data being shown.
The ranges specified by LeftAxisRange, RightAxisRange,
BottomAxisRange, TopAxisRange are only respected when the
corresponding flag in this property is set to 1.
</Documentation>
</IntVectorProperty>
<DoubleVectorProperty command="SetLeftAxisRange"
default_values="0 1"
ignore_synchronization="1"
name="LeftAxisRange"
number_of_elements="2">
<Documentation>Set the axis range for the Left axis. Set to empty to
let the chart determine the range automatically.</Documentation>
</DoubleVectorProperty>
<DoubleVectorProperty clean_command="UnsetRightAxisRange"
command="SetRightAxisRange"
default_values="none"
<DoubleVectorProperty command="SetRightAxisRange"
default_values="0 1"
ignore_synchronization="1"
name="RightAxisRange"
number_of_elements="2">
<Documentation>Set the axis range for the Right axis. Set to empty to
let the chart determine the range automatically.</Documentation>
</DoubleVectorProperty>
<DoubleVectorProperty clean_command="UnsetTopAxisRange"
command="SetTopAxisRange"
default_values="none"
<DoubleVectorProperty command="SetTopAxisRange"
default_values="0 1"
ignore_synchronization="1"
name="TopAxisRange"
number_of_elements="2">
<Documentation>Set the axis range for the Top axis. Set to empty to let
the chart determine the range automatically.</Documentation>
</DoubleVectorProperty>
<DoubleVectorProperty clean_command="UnsetBottomAxisRange"
command="SetBottomAxisRange"
default_values="none"
<DoubleVectorProperty command="SetBottomAxisRange"
default_values="0 1"
ignore_synchronization="1"
name="BottomAxisRange"
number_of_elements="2">
......@@ -852,28 +864,28 @@
<BooleanDomain name="bool" />
<Documentation>
Specify whether to use custom labels for each of the axis. Labels
specified by AxisLabelsLeft, AxisLabelsRight, etc. are used only when
specified by LeftAxisLabels, RightAxisLabels, etc. are used only when
the corresponding AxisUseCustomLabels flag is set to 1.
</Documentation>
</DoubleVectorProperty>
<DoubleVectorProperty command="SetAxisLabelsLeft"
name="AxisLabelsLeft"
name="LeftAxisLabels"
repeat_command="1"
set_number_command="SetAxisLabelsLeftNumber"
use_index="1"></DoubleVectorProperty>
<DoubleVectorProperty command="SetAxisLabelsBottom"
name="AxisLabelsBottom"
name="BottomAxisLabels"
repeat_command="1"
set_number_command="SetAxisLabelsBottomNumber"
use_index="1"></DoubleVectorProperty>
<DoubleVectorProperty command="SetAxisLabelsRight"
name="AxisLabelsRight"
name="RightAxisLabels"
repeat_command="1"
set_number_command="SetAxisLabelsRightNumber"
use_index="1"></DoubleVectorProperty>
<DoubleVectorProperty command="SetAxisLabelsTop"
name="AxisLabelsTop"
name="TopAxisLabels"
repeat_command="1"
set_number_command="SetAxisLabelsTopNumber"
use_index="1"></DoubleVectorProperty>
......
......@@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>466</width>
<height>731</height>
<height>405</height>
</rect>
</property>
<property name="windowTitle">
......@@ -17,7 +17,7 @@
<item>
<widget class="QStackedWidget" name="ChartPages">
<property name="currentIndex">
<number>0</number>
<number>2</number>
</property>
<widget class="QWidget" name="General">
<layout class="QGridLayout">
......@@ -710,13 +710,20 @@ p, li { white-space: pre-wrap; }
</widget>
<widget class="QWidget" name="AxisLayout">
<layout class="QGridLayout">
<property name="margin">
<number>0</number>
</property>
<property name="spacing">
<number>6</number>
</property>
<item row="1" column="0" rowspan="4">
<item row="2" column="0" colspan="2">
<widget class="QLabel" name="label_14">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Axis Labels</string>
</property>
</widget>
</item>
<item row="3" column="0">
<spacer>
<property name="orientation">
<enum>Qt::Horizontal</enum>
......@@ -732,7 +739,46 @@ p, li { white-space: pre-wrap; }
</property>
</spacer>
</item>
<item row="4" column="1">
<item row="1" column="0">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>16</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="3" column="1" colspan="3">
<widget class="QRadioButton" name="ComputeLabelsAutomatically">
<property name="whatsThis">
<string>Check this option to let the chart choose the best axis labels.</string>
</property>
<property name="text">
<string>Compute axis labels automatically</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="4" column="1" colspan="2">
<widget class="QRadioButton" name="UseFixedLabels">
<property name="whatsThis">
<string>Check this option to specify each of the axis labels. This option gives you the most control.</string>
</property>
<property name="text">
<string>Specify axis labels explicitly</string>
</property>
</widget>
</item>
<item row="5" column="1" colspan="3">
<widget class="QStackedWidget" name="AxisLayoutPages">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
......@@ -741,7 +787,7 @@ p, li { white-space: pre-wrap; }
</sizepolicy>
</property>
<property name="currentIndex">
<number>1</number>
<number>0</number>
</property>
<widget class="QWidget" name="BlankPage">
<property name="sizePolicy">
......@@ -807,38 +853,8 @@ p, li { white-space: pre-wrap; }
</widget>
</widget>
</item>
<item row="2" column="1">
<widget class="QRadioButton" name="UseChartSelect">
<property name="whatsThis">
<string>Check this option to let the chart choose the best axis labels.</string>
</property>
<property name="text">
<string>Compute axis labels automatically</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QRadioButton" name="UseFixedInterval">
<property name="whatsThis">
<string>Check this option to specify each of the axis labels. This option gives you the most control.</string>
</property>
<property name="text">
<string>Specify labels explicitly</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QCheckBox" name="UseLogScale">
<property name="text">
<string>Use Logarithmic Scale When Available</string>
</property>
</widget>
</item>
<item row="0" column="0" colspan="2">
<widget class="QLabel" name="label_14">
<widget class="QLabel" name="label_15">
<property name="font">
<font>
<weight>75</weight>
......@@ -846,10 +862,77 @@ p, li { white-space: pre-wrap; }
</font>
</property>
<property name="text">
<string>Axis Layout</string>
<string>Axis Range</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QWidget" name="widget_2" native="true">
<layout class="QVBoxLayout" name="verticalLayout_3">
<property name="margin">
<number>0</number>
</property>
<item>
<widget class="QCheckBox" name="UseLogScale">
<property name="text">
<string>Use Logarithmic Scale When Available</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="ComputeRangeAutomatically">
<property name="text">
<string>Compute axis range automatically</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="UseFixedRange">
<property name="text">
<string>Specify axis range explicitly</string>
</property>
</widget>
</item>
<item>
<widget class="QStackedWidget" name="AxisRangePages">
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="BlankPage_2"/>
<widget class="QWidget" name="MinMaxPage">
<layout class="QGridLayout">
<property name="margin">
<number>0</number>
</property>
<item row="0" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLineEdit" name="RangeMin">
</widget>
</item>
<item>
<widget class="QLabel" name="label_16">
<property name="text">
<string> - </string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="RangeMax">
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="AxisTitle">
......@@ -1079,9 +1162,8 @@ p, li { white-space: pre-wrap; }
<tabstop>LabelColor</tabstop>
<tabstop>LabelNotation</tabstop>
<tabstop>LabelPrecision</tabstop>
<tabstop>UseLogScale</tabstop>
<tabstop>UseChartSelect</tabstop>
<tabstop>UseFixedInterval</tabstop>
<tabstop>ComputeLabelsAutomatically</tabstop>
<tabstop>UseFixedLabels</tabstop>
<tabstop>LabelList</tabstop>
<tabstop>AddButton</tabstop>
<tabstop>RemoveButton</tabstop>
......
This diff is collapsed.
......@@ -81,9 +81,13 @@ public:
protected slots:
void connectGUI();
void disconnectGUI();
void changeLayoutPage(bool checked);
void changeCustomLabelsPage(bool use_custom_labels);
void updateRemoveButton();
/// called when the radio button to specify fixed range for any axis is
/// toggled.
void changeRangePage(bool use_fixed_range);
// Setters for the axis elements of the form
void setAxisVisibility(bool visible);
void setGridVisibility(bool visible);
......@@ -98,6 +102,9 @@ protected slots:
void pickAxisTitleFont();
void setAxisTitleColor(const QColor& color);
void setAxisTitle(const QString& title);
void setAxisRangeMin(const QString&);
void setAxisRangeMax(const QString&);
void addAxisLabel();
void removeSelectedLabels();
......
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