Make2DSliderWidget
Description¶
Make a 2D slider widget.
A vtkSliderRepresentation2D has a large number of properties. So it is convenient to generate a struct containing the initial properties then use a function MakeSlider2DProperties() set up slider(s) with your preferred values for the parameters. If there are multiple sliders in your application, then it is easy to modify the slider properties returned from this function as needed.
This is the approach adopted in Slider2D and KochanekSplineDemo.
This snippet provides you with:
- A struct of initial parameters: Slider2DProperties.
- A function to provide user defined values for the properties: MakeSlider2DProperties.
- A function that generates the slider widget: Make2DSliderWidget.
- A class vtkSliderCallback that uses data provided and the renderer to change the image. You will need to edit this as appropriate.
To use the snippet, click the Copy to clipboard at the upper right of the code blocks.
Declaration Section¶
#include <vtkCommand.h>
#include <vtkNamedColors.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkSliderRepresentation2D.h>
#include <vtkSliderWidget.h>
#include <array>
namespace {
/**
* @brief The Slider2DProperties struct.
*
* These are the default properties.
* Instantiate the struct and modify as appropriate.
*
* @return The properties.
*/
struct Slider2DProperties
{
struct _Colors
{
// The color of the text indicating what the slider controls.
std::string titleColor{"White"};
// The color of the text displaying the value.
std::string labelColor{"White"};
// The color of the knob that slides.
std::string sliderColor{"White"};
// The color of the bar.
std::string barColor{"White"};
// The color of the ends of the bar.
std::string barEndsColor{"White"};
// The color of the knob when the mouse is held on it.
std::string selectedColor{"HotPink"};
};
struct _Dimensions
{
double tubeWidth{0.008};
double sliderLength{0.01};
double sliderWidth{0.02};
double endCapLength{0.005};
double endCapWidth{0.05};
double titleHeight{0.03};
double labelHeight{0.025};
};
struct _Position
{
int coordinateSystem = VTK_NORMALIZED_VIEWPORT;
std::array<double, 2> point1{0.1, 0.1};
std::array<double, 2> point2{0.9, 0.1};
};
struct _Range
{
double minimumValue{0.0};
double maximumValue{1.0};
double value{0.0};
};
struct _Text
{
// Font families are: Ariel, Courier and Times
std::string title{};
std::string titleFontFamily{"Arial"};
bool titleBold{true};
bool titleItalic{false};
bool titleShadow{true};
std::string labelFontFamily{"Arial"};
bool labelBold{true};
bool labelItalic{false};
bool labelShadow{true};
};
struct _Colors Colors;
struct _Dimensions Dimensions;
struct _Position Position;
struct _Range Range;
struct _Text Text;
};
/**
* @brief MakeSlider2DProperties
*
* This applies more specific values to the default Slider2DProperties.
*
* @return The slider 2D properties.
*/
Slider2DProperties MakeSlider2DProperties();
/**
* @brief Make2DSliderWidget
*
* Make a 2D slider widget.
*
* @param properties The 2D slider properties.
* @param iren The vtkInteractor.
* @return The slider widget.
*/
vtkNew<vtkSliderWidget> Make2DSliderWidget(Slider2DProperties const& properties,
vtkRenderWindowInteractor* iren);
class vtkSliderCallback : public vtkCommand
{
public:
static vtkSliderCallback* New()
{
return new vtkSliderCallback;
}
vtkSliderCallback() : bspTree(0), polydata(0)
{
}
virtual void Execute(vtkObject* caller, unsigned long, void*)
{
vtkSliderWidget* sliderWidget = reinterpret_cast<vtkSliderWidget*>(caller);
auto level = static_cast<int>(vtkMath::Round(
static_cast<vtkSliderRepresentation*>(sliderWidget->GetRepresentation())
->GetValue()));
this->bspTree->GenerateRepresentation(level, this->polydata);
sliderWidget->GetSliderRepresentation()->SetValue(level);
}
vtkModifiedBSPTree* bspTree;
vtkPolyData* polydata;
};
} // namespace
Implementation Section¶
namespace {
Slider2DProperties MakeSlider2DProperties()
{
auto sp = Slider2DProperties();
// Set color properties:
// Change the color of the knob that slides.
sp.Colors.sliderColor = "Green";
// Change the color of the text indicating what the slider controls.
sp.Colors.titleColor = "AliceBlue";
// Change the color of the text displaying the value.
sp.Colors.labelColor = "AliceBlue";
// Change the color of the knob when the mouse is held on it.
sp.Colors.selectedColor = "DeepPink";
// Change the color of the bar.
sp.Colors.barColor = "MistyRose";
// Change the color of the ends of the bar.
sp.Colors.barEndsColor = "Yellow";
sp.Dimensions.sliderLength = 0.05;
sp.Dimensions.sliderWidth = 0.025;
sp.Dimensions.endCapLength = 0.02;
sp.Dimensions.titleHeight = 0.045;
sp.Dimensions.labelHeight = 0.035;
sp.Position.point1 = std::array<double, 2>{0.3, 0.1};
sp.Position.point2 = std::array<double, 2>{0.7, 0.1};
return sp;
}
vtkNew<vtkSliderWidget> Make2DSliderWidget(Slider2DProperties const& properties,
vtkRenderWindowInteractor* iren)
{
vtkNew<vtkNamedColors> colors;
vtkNew<vtkSliderRepresentation2D> sliderRep;
sliderRep->SetMinimumValue(properties.Range.minimumValue);
sliderRep->SetMaximumValue(properties.Range.maximumValue);
sliderRep->SetValue(properties.Range.value);
sliderRep->SetTitleText(properties.Text.title.c_str());
sliderRep->SetTubeWidth(properties.Dimensions.tubeWidth);
sliderRep->SetSliderLength(properties.Dimensions.sliderLength);
sliderRep->SetSliderWidth(properties.Dimensions.sliderWidth);
sliderRep->SetEndCapLength(properties.Dimensions.endCapLength);
sliderRep->SetEndCapWidth(properties.Dimensions.endCapWidth);
sliderRep->SetTitleHeight(properties.Dimensions.titleHeight);
sliderRep->SetLabelHeight(properties.Dimensions.labelHeight);
// Set the color properties.
sliderRep->GetTitleProperty()->SetColor(
colors->GetColor3d(properties.Colors.titleColor).GetData());
sliderRep->GetLabelProperty()->SetColor(
colors->GetColor3d(properties.Colors.labelColor).GetData());
sliderRep->GetTubeProperty()->SetColor(
colors->GetColor3d(properties.Colors.barColor).GetData());
sliderRep->GetCapProperty()->SetColor(
colors->GetColor3d(properties.Colors.barEndsColor).GetData());
sliderRep->GetSliderProperty()->SetColor(
colors->GetColor3d(properties.Colors.sliderColor).GetData());
sliderRep->GetSelectedProperty()->SetColor(
colors->GetColor3d(properties.Colors.selectedColor).GetData());
// Set the position.
sliderRep->GetPoint1Coordinate()->SetCoordinateSystem(
properties.Position.coordinateSystem);
sliderRep->GetPoint1Coordinate()->SetValue(properties.Position.point1.data());
sliderRep->GetPoint2Coordinate()->SetCoordinateSystem(
properties.Position.coordinateSystem);
sliderRep->GetPoint2Coordinate()->SetValue(properties.Position.point2.data());
std::string titleFontFamily = properties.Text.titleFontFamily;
if (titleFontFamily == "Courier")
{
sliderRep->GetLabelProperty()->SetFontFamilyToCourier();
}
else if (titleFontFamily == "Times")
{
sliderRep->GetLabelProperty()->SetFontFamilyToTimes();
}
else
{
sliderRep->GetLabelProperty()->SetFontFamilyToArial();
}
sliderRep->GetTitleProperty()->SetBold(properties.Text.titleBold);
sliderRep->GetTitleProperty()->SetItalic(properties.Text.titleItalic);
sliderRep->GetTitleProperty()->SetShadow(properties.Text.titleShadow);
std::string labelFontFamily = properties.Text.labelFontFamily;
if (labelFontFamily == "Courier")
{
sliderRep->GetLabelProperty()->SetFontFamilyToCourier();
}
else if (labelFontFamily == "Times")
{
sliderRep->GetLabelProperty()->SetFontFamilyToTimes();
}
else
{
sliderRep->GetLabelProperty()->SetFontFamilyToArial();
}
sliderRep->GetLabelProperty()->SetBold(properties.Text.labelBold);
sliderRep->GetLabelProperty()->SetItalic(properties.Text.labelItalic);
sliderRep->GetLabelProperty()->SetShadow(properties.Text.labelShadow);
vtkNew<vtkSliderWidget> widget;
widget->SetInteractor(iren);
widget->SetRepresentation(sliderRep);
widget->EnabledOn();
widget->SetAnimationModeToAnimate();
return widget;
}
} // namespace
Usage¶
Here we:
- Use MakeSlider2DProperties() to generate the base slider properties.
- Then modify some of the properties (usually ranges positioning and the title).
- Create the slider widget Make2DSliderWidget(sp, iren).
- Create the callback and set any needed parameters.
- Add the observer to the slider widget.
Of course if you have multiple sliders, you would:
- Implement the slider 2D properties for each slider, setting ranges, positioning and title as appropriate.
- Implement a widget for each slider widget.
- Create a callback for each widget.
Use the code in a similar fashion to this:
// ...
auto sp = MakeSlider2DProperties();
sp.Range.minimumValue = 0;
sp.Range.maximumValue = bspTree->GetMaxLevel();
sp.Range.value = vtkMath::Round(bspTree->GetMaxLevel() / 2.0);
sp.Text.title = "Level";
auto sliderWidget = Make2DSliderWidget(sp, iren);
vtkNew<vtkSliderCallback> callback;
callback->bspTree = bspTree;
callback->polydata = polydata;
callback->Execute(sliderWidget, 0, 0);
sliderWidget->AddObserver(vtkCommand::InteractionEvent, callback);
// ...
For examples showing the usage of this snippet and changing most of the default parameters, please see: Slider2D and KochanekSplineDemo.