Commit f3ede3d1 authored by Mathieu Westphal's avatar Mathieu Westphal

vtkRangeHandlesItem improvements

This adds a HandleWidth parameter and update the test
This reimplements the HoveredHandle mechanism
This adds Left/RightMouseButtonDoubleClickEvent to vtkCommand
parent c7e13dd1
......@@ -60,6 +60,8 @@ int TestColorTransferFunction(int , char * [])
vtkNew<vtkRangeHandlesItem> rangeHandlesItem;
rangeHandlesItem->SetColorTransferFunction(colorTransferFunction);
// Use very large handles to make sure the test fails if the handles fail to render
rangeHandlesItem->SetHandleWidth(40.0);
chart->AddPlot(rangeHandlesItem);
// Finally render the scene and compare the image to a reference image
......
97a34b9d4fbaa394d787193a0373cfecdec1dd1f9788aec09e941e1d86f62404722e0cdec2a48e85f97940e16b69240ef58abf803771243e3830e2e779135e28
3377ba5633b965488a10866ab1105866d10d8815478b679e83b18a42ef8f7848b015d88256ae006470d785d989db55c1a0871ffb3b8c2a3ec45b9ddf1719d738
......@@ -23,6 +23,8 @@
#include "vtkContextScene.h"
#include "vtkObjectFactory.h"
#include "vtkPen.h"
#include "vtkRenderWindow.h"
#include "vtkRenderer.h"
#include "vtkTransform2D.h"
//-----------------------------------------------------------------------------
......@@ -34,7 +36,7 @@ vtkSetObjectImplementationMacro(
vtkRangeHandlesItem::vtkRangeHandlesItem()
{
this->Brush->SetColor(125, 135, 144, 200);
this->ActiveHandleBrush->SetColor(255, 0, 255, 200);
this->HighlightBrush->SetColor(255, 0, 255, 200);
this->RangeLabelBrush->SetColor(255, 255, 255, 200);
}
......@@ -52,7 +54,17 @@ void vtkRangeHandlesItem::ComputeHandlesDrawRange()
{
double screenBounds[4];
this->GetBounds(screenBounds);
this->HandleDelta = static_cast<float>((screenBounds[1] - screenBounds[0]) / 200.0);
// Try to use the scene to produce correctly size handles
double width = 400.0;
vtkContextScene* scene = this->GetScene();
if (scene)
{
width = static_cast<double>(scene->GetSceneWidth());
}
this->HandleDelta =
this->HandleWidth * static_cast<float>((screenBounds[1] - screenBounds[0]) / width);
if (this->ActiveHandle == vtkRangeHandlesItem::LEFT_HANDLE)
{
this->LeftHandleDrawRange[0] = this->ActiveHandlePosition - this->HandleDelta;
......@@ -90,11 +102,16 @@ bool vtkRangeHandlesItem::Paint(vtkContext2D* painter)
// Compute handles draw range
this->ComputeHandlesDrawRange();
int highlightedHandle = this->ActiveHandle;
if (highlightedHandle == vtkRangeHandlesItem::NO_HANDLE)
{
highlightedHandle = this->HoveredHandle;
}
// Draw Left Handle
if (this->ActiveHandle == vtkRangeHandlesItem::LEFT_HANDLE ||
this->HoveredHandle == vtkRangeHandlesItem::LEFT_HANDLE)
if (highlightedHandle == vtkRangeHandlesItem::LEFT_HANDLE)
{
painter->ApplyBrush(this->ActiveHandleBrush);
painter->ApplyBrush(this->HighlightBrush);
}
else
{
......@@ -104,10 +121,9 @@ bool vtkRangeHandlesItem::Paint(vtkContext2D* painter)
this->LeftHandleDrawRange[1], 1, this->LeftHandleDrawRange[1], 0);
// Draw Right Handle
if (this->ActiveHandle == vtkRangeHandlesItem::RIGHT_HANDLE ||
this->HoveredHandle == vtkRangeHandlesItem::RIGHT_HANDLE)
if (highlightedHandle == vtkRangeHandlesItem::RIGHT_HANDLE)
{
painter->ApplyBrush(this->ActiveHandleBrush);
painter->ApplyBrush(this->HighlightBrush);
}
else
{
......@@ -117,9 +133,9 @@ bool vtkRangeHandlesItem::Paint(vtkContext2D* painter)
this->RightHandleDrawRange[1], 1, this->RightHandleDrawRange[1], 0);
// Draw range info
if (this->ActiveHandle != vtkRangeHandlesItem::NO_HANDLE ||
this->HoveredHandle != vtkRangeHandlesItem::NO_HANDLE)
if (highlightedHandle != vtkRangeHandlesItem::NO_HANDLE)
{
this->InvokeEvent(vtkCommand::HighlightEvent);
double range[2];
this->GetHandlesRange(range);
std::string label =
......@@ -160,6 +176,7 @@ void vtkRangeHandlesItem::PrintSelf(ostream& os, vtkIndent indent)
{
os << "(none)" << endl;
}
os << indent << "HandleWidth: " << this->HandleWidth << endl;
os << indent << "HoveredHandle: " << this->HoveredHandle << endl;
os << indent << "ActiveHandle: " << this->ActiveHandle << endl;
os << indent << "ActiveHandlePosition: " << this->ActiveHandlePosition << endl;
......@@ -199,11 +216,12 @@ bool vtkRangeHandlesItem::MouseButtonPressEvent(const vtkContextMouseEvent& mous
{
vtkVector2f vpos = mouse.GetPos();
vtkVector2f tolerance = { 2.0f * static_cast<float>(this->HandleDelta), 0 };
this->HoveredHandle = vtkRangeHandlesItem::NO_HANDLE;
this->ActiveHandle = this->FindRangeHandle(vpos, tolerance);
if (this->ActiveHandle != vtkRangeHandlesItem::NO_HANDLE)
{
this->HoveredHandle = this->ActiveHandle;
this->SetActiveHandlePosition(vpos.GetX());
this->SetCursor(VTK_CURSOR_SIZEWE);
this->GetScene()->SetDirty(true);
this->InvokeEvent(vtkCommand::StartInteractionEvent);
return true;
......@@ -218,6 +236,15 @@ bool vtkRangeHandlesItem::MouseButtonReleaseEvent(const vtkContextMouseEvent& mo
{
vtkVector2f vpos = mouse.GetPos();
this->SetActiveHandlePosition(vpos.GetX());
if (this->IsActiveHandleMoved(3.0 * this->HandleDelta))
{
this->HoveredHandle = vtkRangeHandlesItem::NO_HANDLE;
}
if (this->HoveredHandle == vtkRangeHandlesItem::NO_HANDLE)
{
this->SetCursor(VTK_CURSOR_DEFAULT);
}
this->InvokeEvent(vtkCommand::EndInteractionEvent);
this->ActiveHandle = vtkRangeHandlesItem::NO_HANDLE;
this->GetScene()->SetDirty(true);
......@@ -243,27 +270,44 @@ bool vtkRangeHandlesItem::MouseMoveEvent(const vtkContextMouseEvent& mouse)
//-----------------------------------------------------------------------------
bool vtkRangeHandlesItem::MouseEnterEvent(const vtkContextMouseEvent& mouse)
{
if (this->ActiveHandle == vtkRangeHandlesItem::NO_HANDLE)
vtkVector2f vpos = mouse.GetPos();
vtkVector2f tolerance = { 2.0f * static_cast<float>(this->HandleDelta), 0 };
this->HoveredHandle = this->FindRangeHandle(vpos, tolerance);
if (this->HoveredHandle == vtkRangeHandlesItem::NO_HANDLE)
{
vtkVector2f vpos = mouse.GetPos();
vtkVector2f tolerance = { 2.0f * static_cast<float>(this->HandleDelta), 0 };
this->HoveredHandle = this->FindRangeHandle(vpos, tolerance);
if (this->HoveredHandle != this->PreviousHoveredHandle)
{
this->GetScene()->SetDirty(true);
return true;
}
return false;
}
return false;
this->SetCursor(VTK_CURSOR_SIZEWE);
this->GetScene()->SetDirty(true);
return true;
}
//-----------------------------------------------------------------------------
bool vtkRangeHandlesItem::MouseLeaveEvent(const vtkContextMouseEvent& vtkNotUsed(mouse))
{
if (this->ActiveHandle == vtkRangeHandlesItem::NO_HANDLE &&
this->HoveredHandle != vtkRangeHandlesItem::NO_HANDLE)
if (this->HoveredHandle == vtkRangeHandlesItem::NO_HANDLE)
{
return false;
}
this->HoveredHandle = vtkRangeHandlesItem::NO_HANDLE;
this->GetScene()->SetDirty(true);
if (this->ActiveHandle == vtkRangeHandlesItem::NO_HANDLE)
{
this->SetCursor(VTK_CURSOR_DEFAULT);
}
return true;
}
//-----------------------------------------------------------------------------
bool vtkRangeHandlesItem::MouseDoubleClickEvent(const vtkContextMouseEvent& mouse)
{
if (mouse.GetButton() == vtkContextMouseEvent::LEFT_BUTTON)
{
this->HoveredHandle = vtkRangeHandlesItem::NO_HANDLE;
this->InvokeEvent(vtkCommand::LeftButtonDoubleClickEvent);
this->GetScene()->SetDirty(true);
return true;
}
......@@ -343,3 +387,34 @@ void vtkRangeHandlesItem::SetActiveHandlePosition(double position)
this->TransformScreenToData(position, 1, this->ActiveHandleRangeValue, unused);
}
}
//-----------------------------------------------------------------------------
bool vtkRangeHandlesItem::IsActiveHandleMoved(double tolerance)
{
if (this->ActiveHandle == vtkRangeHandlesItem::NO_HANDLE)
{
return false;
}
double unused, position;
this->TransformDataToScreen(this->ActiveHandleRangeValue, 1, position, unused);
double bounds[4];
this->GetBounds(bounds);
return (bounds[this->ActiveHandle] - tolerance <= position &&
position <= bounds[this->ActiveHandle] + tolerance);
}
//-----------------------------------------------------------------------------
void vtkRangeHandlesItem::SetCursor(int cursor)
{
vtkRenderer* renderer = this->GetScene()->GetRenderer();
if (renderer)
{
vtkRenderWindow* window = renderer->GetRenderWindow();
if (window)
{
window->SetCurrentCursor(cursor);
}
}
}
......@@ -24,6 +24,7 @@
* It emits a StartInteractionEvent when starting to interact with a handle,
* an InteractionEvent when interacting with a handle and an EndInteractionEvent
* when releasing a handle.
* It emits a LeftMouseButtonDoubleClickEvent when double clicked.
*
* @sa
* vtkControlPointsItem
......@@ -35,6 +36,7 @@
#define vtkRangeHandlesItem_h
#include "vtkChartsCoreModule.h" // For export macro
#include "vtkCommand.h" // For vtkCommand enum
#include "vtkPlot.h"
class vtkColorTransferFunction;
......@@ -79,8 +81,17 @@ public:
vtkGetObjectMacro(ColorTransferFunction, vtkColorTransferFunction);
//@}
//@{
/**
* Set/Get the handles width in pixels.
* Default is 2.
*/
vtkSetMacro(HandleWidth, float);
vtkGetMacro(HandleWidth, float);
//@}
/**
* Compute the handles draw range
* Compute the handles draw range by using the handle width and the transfer function
*/
void ComputeHandlesDrawRange();
......@@ -102,6 +113,7 @@ protected:
bool MouseMoveEvent(const vtkContextMouseEvent& mouse) override;
bool MouseEnterEvent(const vtkContextMouseEvent& mouse) override;
bool MouseLeaveEvent(const vtkContextMouseEvent& mouse) override;
bool MouseDoubleClickEvent(const vtkContextMouseEvent& mouse) override;
//@}
/**
......@@ -116,21 +128,32 @@ protected:
*/
void SetActiveHandlePosition(double position);
/**
* Internal method to check if the active handle have
* actually been moved.
*/
bool IsActiveHandleMoved(double tolerance);
/**
* Set the cursor shape
*/
void SetCursor(int cursor);
private:
vtkRangeHandlesItem(const vtkRangeHandlesItem&) = delete;
void operator=(const vtkRangeHandlesItem&) = delete;
vtkColorTransferFunction* ColorTransferFunction = nullptr;
float HandleWidth = 2;
float HandleDelta = 0;
float LeftHandleDrawRange[2] = { 0, 0 };
float RightHandleDrawRange[2] = { 0, 0 };
int ActiveHandle = NO_HANDLE;
int HoveredHandle = NO_HANDLE;
int PreviousHoveredHandle = NO_HANDLE;
double ActiveHandlePosition = 0;
double ActiveHandleRangeValue = 0;
vtkNew<vtkBrush> ActiveHandleBrush;
vtkNew<vtkBrush> HighlightBrush;
vtkNew<vtkBrush> RangeLabelBrush;
};
......
......@@ -358,7 +358,9 @@
_vtk_add_event(FifthButtonReleaseEvent)\
_vtk_add_event(Move3DEvent)\
_vtk_add_event(Button3DEvent)\
_vtk_add_event(TextEvent)
_vtk_add_event(TextEvent)\
_vtk_add_event(LeftButtonDoubleClickEvent)\
_vtk_add_event(RightButtonDoubleClickEvent)
#define vtkEventDeclarationMacro(_enum_name)\
enum _enum_name{\
......
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