Julien Finet 14 år sedan
förälder
incheckning
553bab6472

+ 133 - 18
Libs/Visualization/VTK/Widgets/Resources/UI/ctkVTKScalarsToColorsWidget.ui

@@ -6,14 +6,20 @@
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>429</width>
+    <width>442</width>
     <height>144</height>
    </rect>
   </property>
   <property name="windowTitle">
    <string>ScalarsToColorsWidget</string>
   </property>
-  <layout class="QGridLayout" name="gridLayout">
+  <layout class="QGridLayout" name="gridLayout" columnstretch="1,0,0">
+   <property name="margin">
+    <number>0</number>
+   </property>
+   <property name="spacing">
+    <number>0</number>
+   </property>
    <item row="0" column="0" colspan="2">
     <layout class="QHBoxLayout" name="horizontalLayout">
      <item>
@@ -30,28 +36,117 @@
       </spacer>
      </item>
      <item>
-      <widget class="QLabel" name="PLabel">
+      <widget class="QLabel" name="PointIdLabel">
+       <property name="toolTip">
+        <string>Point ID</string>
+       </property>
        <property name="text">
-        <string>P:</string>
+        <string>Point:</string>
        </property>
       </widget>
      </item>
      <item>
-      <widget class="QDoubleSpinBox" name="PSpinBox">
+      <widget class="QSpinBox" name="PointIdSpinBox">
+       <property name="enabled">
+        <bool>false</bool>
+       </property>
+       <property name="toolTip">
+        <string>Point ID</string>
+       </property>
+       <property name="minimum">
+        <number>-1</number>
+       </property>
        <property name="maximum">
-        <double>255.000000000000000</double>
+        <number>-1</number>
        </property>
       </widget>
      </item>
      <item>
-      <widget class="QLabel" name="VLabel">
+      <widget class="ctkColorPickerButton" name="ColorPickerButton">
+       <property name="enabled">
+        <bool>false</bool>
+       </property>
        <property name="text">
-        <string>V:</string>
+        <string/>
+       </property>
+       <property name="displayColorName">
+        <bool>false</bool>
+       </property>
+       <property name="dialogOptions">
+        <set>ctkColorPickerButton::UseCTKColorDialog</set>
        </property>
       </widget>
      </item>
      <item>
-      <widget class="QDoubleSpinBox" name="VSpinBox">
+      <widget class="QLabel" name="OpacityLabel">
+       <property name="toolTip">
+        <string>Opacity of the current point</string>
+       </property>
+       <property name="text">
+        <string>O:</string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QDoubleSpinBox" name="OpacitySpinBox">
+       <property name="enabled">
+        <bool>false</bool>
+       </property>
+       <property name="toolTip">
+        <string>Opacity of the current point</string>
+       </property>
+       <property name="maximum">
+        <double>1.000000000000000</double>
+       </property>
+       <property name="singleStep">
+        <double>0.100000000000000</double>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QLabel" name="MidPointLabel">
+       <property name="toolTip">
+        <string>Position of the midpoint</string>
+       </property>
+       <property name="text">
+        <string>M:</string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QDoubleSpinBox" name="MidPointSpinBox">
+       <property name="enabled">
+        <bool>false</bool>
+       </property>
+       <property name="toolTip">
+        <string>Position of the midpoint</string>
+       </property>
+       <property name="maximum">
+        <double>1.000000000000000</double>
+       </property>
+       <property name="singleStep">
+        <double>0.100000000000000</double>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QLabel" name="SharpnessLabel">
+       <property name="toolTip">
+        <string>Sharpness of the midpoint</string>
+       </property>
+       <property name="text">
+        <string>S:</string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QDoubleSpinBox" name="SharpnessSpinBox">
+       <property name="enabled">
+        <bool>false</bool>
+       </property>
+       <property name="toolTip">
+        <string>Sharpness of the midpoint</string>
+       </property>
        <property name="maximum">
         <double>1.000000000000000</double>
        </property>
@@ -65,17 +160,32 @@
    <item row="1" column="0">
     <widget class="ctkVTKScalarsToColorsView" name="View"/>
    </item>
-   <item row="1" column="1">
-    <widget class="ctkRangeSlider" name="RangeSlider">
+   <item row="2" column="0">
+    <widget class="ctkDoubleRangeSlider" name="XRangeSlider">
+     <property name="maximum">
+      <double>1.000000000000000</double>
+     </property>
+     <property name="singleStep">
+      <double>0.010000000000000</double>
+     </property>
+     <property name="maximumValue">
+      <double>1.000000000000000</double>
+     </property>
      <property name="orientation">
-      <enum>Qt::Vertical</enum>
+      <enum>Qt::Horizontal</enum>
      </property>
     </widget>
    </item>
-   <item row="2" column="0">
-    <widget class="ctkRangeSlider" name="RangeSlider_2">
+   <item row="1" column="1">
+    <widget class="ctkDoubleRangeSlider" name="YRangeSlider">
+     <property name="maximum">
+      <double>1.000000000000000</double>
+     </property>
+     <property name="singleStep">
+      <double>0.010000000000000</double>
+     </property>
      <property name="orientation">
-      <enum>Qt::Horizontal</enum>
+      <enum>Qt::Vertical</enum>
      </property>
     </widget>
    </item>
@@ -88,9 +198,14 @@
    <header>ctkVTKScalarsToColorsView.h</header>
   </customwidget>
   <customwidget>
-   <class>ctkRangeSlider</class>
-   <extends>QSlider</extends>
-   <header>ctkRangeSlider.h</header>
+   <class>ctkColorPickerButton</class>
+   <extends>QPushButton</extends>
+   <header>ctkColorPickerButton.h</header>
+  </customwidget>
+  <customwidget>
+   <class>ctkDoubleRangeSlider</class>
+   <extends>QWidget</extends>
+   <header>ctkDoubleRangeSlider.h</header>
   </customwidget>
  </customwidgets>
  <resources/>

+ 2 - 0
Libs/Visualization/VTK/Widgets/Testing/Cpp/CMakeLists.txt

@@ -29,6 +29,7 @@ IF(CTK_USE_CHARTS)
       ctkVTKScalarsToColorsViewTest3.cpp
       ctkVTKScalarsToColorsViewTest4.cpp
       ctkVTKScalarsToColorsWidgetTest1.cpp
+      ctkVTKScalarsToColorsWidgetTest2.cpp
       ${TEST_SOURCES})
 ENDIF(CTK_USE_CHARTS)
 
@@ -83,6 +84,7 @@ IF (CTK_USE_CHARTS)
   SIMPLE_TEST( ctkVTKScalarsToColorsViewTest3 )
   SIMPLE_TEST( ctkVTKScalarsToColorsViewTest4 )
   SIMPLE_TEST( ctkVTKScalarsToColorsWidgetTest1 )
+  SIMPLE_TEST( ctkVTKScalarsToColorsWidgetTest2 )
 ENDIF(CTK_USE_CHARTS)
 SIMPLE_TEST( ctkVTKRenderViewTest1 )
 SIMPLE_TEST( ctkVTKSliceViewTest1 )

+ 77 - 0
Libs/Visualization/VTK/Widgets/Testing/Cpp/ctkVTKScalarsToColorsWidgetTest2.cpp

@@ -0,0 +1,77 @@
+/*=========================================================================
+
+  Library:   CTK
+
+  Copyright (c) Kitware Inc.
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+      http://www.commontk.org/LICENSE
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+=========================================================================*/
+
+// Qt includes
+#include <QApplication>
+#include <QSharedPointer>
+#include <QTimer>
+
+// CTK includes
+#include "ctkVTKScalarsToColorsView.h"
+#include "ctkVTKScalarsToColorsWidget.h"
+
+// VTK includes
+#include <vtkChartXY.h>
+#include <vtkColorTransferFunction.h>
+#include <vtkPiecewiseFunction.h>
+#include <vtkPlot.h>
+#include <vtkSmartPointer.h>
+
+// STD includes
+#include <iostream>
+
+//-----------------------------------------------------------------------------
+int ctkVTKScalarsToColorsWidgetTest2(int argc, char * argv [] )
+{
+  QApplication app(argc, argv);
+
+  // Transfer Function
+  vtkSmartPointer<vtkColorTransferFunction> ctf =
+    vtkSmartPointer<vtkColorTransferFunction>::New();
+  //
+  ctf->AddRGBPoint(0. , 171./255., 113./255.,   38./255.);
+  ctf->AddRGBPoint(0.2,   38./255., 171./255., 113./255.);
+  ctf->AddRGBPoint(0.4,  113./255., 38./255., 171./255.);
+  ctf->AddRGBPoint(0.6,  171./255., 38./255.,  140./255.);
+  ctf->AddRGBPoint(0.8,  171./255., 46./255., 38./255.);
+
+  // Opacity function
+  vtkSmartPointer<vtkPiecewiseFunction> opacityFunction =
+    vtkSmartPointer<vtkPiecewiseFunction>::New();
+  opacityFunction->AddPoint(0.,0.3);
+  opacityFunction->AddPoint(0.2, 0.55);
+  opacityFunction->AddPoint(0.4,0.87);
+  opacityFunction->AddPoint(0.6, 1.);
+  opacityFunction->AddPoint(0.8, 0.45);
+
+  ctkVTKScalarsToColorsWidget widget(0);
+  // add transfer function item
+  widget.view()->addCompositeFunction(ctf, opacityFunction);
+  widget.view()->fitAxesToBounds();
+  widget.show();
+
+  QTimer autoExit;
+  if (argc < 2 || QString(argv[1]) != "-I")
+    {
+    QObject::connect(&autoExit, SIGNAL(timeout()), &app, SLOT(quit()));
+    autoExit.start(1000);
+    }
+  return app.exec();
+}

+ 22 - 0
Libs/Visualization/VTK/Widgets/ctkVTKChartView.cpp

@@ -19,6 +19,7 @@
 =========================================================================*/
 
 // Qt includes
+#include <QMouseEvent>
 
 // CTK includes
 #include "ctkLogger.h"
@@ -28,6 +29,7 @@
 #include <vtkAxis.h>
 #include <vtkChartXY.h>
 #include <vtkContext2D.h>
+#include <vtkContextMouseEvent.h>
 #include <vtkContextScene.h>
 #include <vtkContextView.h>
 #include <vtkOpenGLContextDevice2D.h>
@@ -73,6 +75,8 @@ void ctkVTKChartViewPrivate::init()
   //q->GetRenderWindow()->SetMultiSamples(0);
   //vtkOpenGLContextDevice2D::SafeDownCast(this->ContextView->GetContext()->GetDevice())
   //                                       ->SetStringRendererToQt();
+  this->Chart->SetActionToButton(vtkChart::PAN, vtkContextMouseEvent::MIDDLE_BUTTON);
+  this->Chart->SetActionToButton(vtkChart::SELECT, vtkContextMouseEvent::RIGHT_BUTTON);
 }
 
 // ----------------------------------------------------------------------------
@@ -115,10 +119,18 @@ vtkChartXY* ctkVTKChartView::chart()const
 }
 
 // ----------------------------------------------------------------------------
+vtkContextScene* ctkVTKChartView::scene()const
+{
+  Q_D(const ctkVTKChartView);
+  return d->ContextView->GetScene();
+}
+
+// ----------------------------------------------------------------------------
 void ctkVTKChartView::addPlot(vtkPlot* plot)
 {
   Q_D(ctkVTKChartView);
   d->Chart->AddPlot(plot);
+  emit this->plotAdded(plot);
 }
 
 // ----------------------------------------------------------------------------
@@ -201,3 +213,13 @@ void ctkVTKChartView::fitAxesToBounds()
       }
     }
 }
+
+// ----------------------------------------------------------------------------
+void ctkVTKChartView::mouseDoubleClickEvent(QMouseEvent* event)
+{
+  if (event->button() == Qt::MidButton)
+    {
+    this->fitAxesToBounds();
+    }
+  this->QVTKWidget::mouseDoubleClickEvent(event);
+}

+ 7 - 1
Libs/Visualization/VTK/Widgets/ctkVTKChartView.h

@@ -30,6 +30,7 @@ class ctkVTKChartViewPrivate;
 #include <QVTKWidget.h>
 
 class vtkChartXY;
+class vtkContextScene;
 class vtkPlot;
 
 class CTK_VISUALIZATION_VTK_WIDGETS_EXPORT ctkVTKChartView : public QVTKWidget
@@ -42,11 +43,12 @@ public:
   virtual ~ctkVTKChartView();
 
   /// Generic function to add a custom plot. \a plot is added into the chart
-  void addPlot(vtkPlot* plot);
+  virtual void addPlot(vtkPlot* plot);
 
   /// Utility function that returns the view chart. It can be used for customizing
   /// the chart display options (axes, legend...)
   vtkChartXY* chart()const;
+  vtkContextScene* scene()const;
 
   /// Title that appears inside the view
   QString title()const;
@@ -54,8 +56,12 @@ public:
 
   void fitAxesToBounds();
 
+signals:
+  void plotAdded(vtkPlot* plot);
+
 protected:
   QScopedPointer<ctkVTKChartViewPrivate> d_ptr;
+  virtual void mouseDoubleClickEvent(QMouseEvent* event);
 
 private:
   Q_DECLARE_PRIVATE(ctkVTKChartView);

+ 52 - 4
Libs/Visualization/VTK/Widgets/ctkVTKScalarsToColorsView.cpp

@@ -19,6 +19,7 @@
 =========================================================================*/
 
 // Qt includes
+#include <QColorDialog>
 
 // CTK includes
 #include "ctkLogger.h"
@@ -27,8 +28,10 @@
 // VTK includes
 #include <vtkAxis.h>
 #include <vtkChartXY.h>
+#include <vtkColorTransferControlPointsItem.h>
 #include <vtkColorTransferFunction.h>
 #include <vtkColorTransferFunctionItem.h>
+#include <vtkCompositeControlPointsItem.h>
 #include <vtkCompositeTransferFunctionItem.h>
 #include <vtkLookupTable.h>
 #include <vtkLookupTableItem.h>
@@ -97,6 +100,17 @@ ctkVTKScalarsToColorsView::~ctkVTKScalarsToColorsView()
 }
 
 // ----------------------------------------------------------------------------
+void ctkVTKScalarsToColorsView::addPlot(vtkPlot* plot)
+{
+  if (vtkColorTransferControlPointsItem::SafeDownCast(plot))
+    {
+    this->qvtkConnect(plot, vtkControlPointsItem::CurrentPointEditEvent,
+                      this, SLOT(editPoint(vtkObject*, void*)));
+    }
+  this->Superclass::addPlot(plot);
+}
+
+// ----------------------------------------------------------------------------
 vtkPlot* ctkVTKScalarsToColorsView::addLookupTable(vtkLookupTable* lut)
 {
   Q_D(ctkVTKScalarsToColorsView);
@@ -114,6 +128,9 @@ vtkPlot* ctkVTKScalarsToColorsView::addColorTransferFunction(vtkColorTransferFun
   vtkSmartPointer<vtkColorTransferFunctionItem> item =
     vtkSmartPointer<vtkColorTransferFunctionItem>::New();
   item->SetColorTransferFunction(colorTF);
+  vtkSmartPointer<vtkColorTransferControlPointsItem> controlPointsItem =
+    vtkSmartPointer<vtkColorTransferControlPointsItem>::New();
+  controlPointsItem->SetColorTransferFunction(colorTF);
   this->addPlot(item);
   d->updateChart();
   return item;
@@ -139,7 +156,9 @@ vtkPlot* ctkVTKScalarsToColorsView::addOpacityFunction(vtkPiecewiseFunction* opa
 }
 
 // ----------------------------------------------------------------------------
-vtkPlot* ctkVTKScalarsToColorsView::addCompositeFunction(vtkColorTransferFunction* colorTF, vtkPiecewiseFunction* opacityTF)
+vtkPlot* ctkVTKScalarsToColorsView
+::addCompositeFunction(vtkColorTransferFunction* colorTF,
+                       vtkPiecewiseFunction* opacityTF)
 {
   Q_D(ctkVTKScalarsToColorsView);
   vtkSmartPointer<vtkCompositeTransferFunctionItem> item =
@@ -148,11 +167,40 @@ vtkPlot* ctkVTKScalarsToColorsView::addCompositeFunction(vtkColorTransferFunctio
   item->SetOpacityFunction(opacityTF);
   item->SetMaskAboveCurve(true);
   this->addPlot(item);
-  vtkSmartPointer<vtkPiecewiseControlPointsItem> controlPointsItem =
-    vtkSmartPointer<vtkPiecewiseControlPointsItem>::New();
-  controlPointsItem->SetPiecewiseFunction(opacityTF);
+  vtkSmartPointer<vtkCompositeControlPointsItem> controlPointsItem =
+    vtkSmartPointer<vtkCompositeControlPointsItem>::New();
+  controlPointsItem->SetColorTransferFunction(colorTF);
+  controlPointsItem->SetOpacityFunction(opacityTF);
   this->addPlot(controlPointsItem);
 
   d->updateChart();
   return item;
 }
+
+// ----------------------------------------------------------------------------
+void ctkVTKScalarsToColorsView::editPoint(vtkObject* caller, void* callData)
+{
+  vtkControlPointsItem* controlPoints = reinterpret_cast<vtkControlPointsItem*>(caller);
+  int pointToEdit = reinterpret_cast<unsigned long>(callData);
+  if (!controlPoints || pointToEdit < 0)
+    {
+    return;
+    }
+  vtkColorTransferControlPointsItem* colorTransferFunctionItem =
+    vtkColorTransferControlPointsItem::SafeDownCast(controlPoints);
+  if (colorTransferFunctionItem)
+    {
+    double xrgbms[6];
+    vtkColorTransferFunction* colorTF = colorTransferFunctionItem->GetColorTransferFunction();
+    colorTF->GetNodeValue(pointToEdit, xrgbms);
+    QColor oldColor = QColor::fromRgbF(xrgbms[0], xrgbms[1], xrgbms[2]);
+    QColor newColor = QColorDialog::getColor(oldColor, this);
+    if (newColor.isValid())
+      {
+      xrgbms[1] = newColor.redF();
+      xrgbms[2] = newColor.greenF();
+      xrgbms[3] = newColor.blueF();
+      colorTF->SetNodeValue(pointToEdit, xrgbms);
+      }
+    }
+}

+ 11 - 4
Libs/Visualization/VTK/Widgets/ctkVTKScalarsToColorsView.h

@@ -22,8 +22,8 @@
 #define __ctkVTKScalarsToColorsView_h
 
 // CTK includes
-#include <ctkPimpl.h>
 #include "ctkVTKChartView.h"
+#include "ctkVTKObject.h"
 class ctkVTKScalarsToColorsViewPrivate;
 
 // VTK includes
@@ -33,18 +33,25 @@ class vtkColorTransferFunction;
 class vtkLookupTable;
 class vtkPiecewiseFunction;
 
-class CTK_VISUALIZATION_VTK_WIDGETS_EXPORT ctkVTKScalarsToColorsView : public ctkVTKChartView
+class CTK_VISUALIZATION_VTK_WIDGETS_EXPORT ctkVTKScalarsToColorsView
+  : public ctkVTKChartView
 {
   Q_OBJECT
-
+  QVTK_OBJECT
 public:
+  typedef ctkVTKChartView Superclass;
   ctkVTKScalarsToColorsView(QWidget* parent = 0);
   virtual ~ctkVTKScalarsToColorsView();
 
+  virtual void addPlot(vtkPlot* plot);
   vtkPlot* addLookupTable(vtkLookupTable* lut);
   vtkPlot* addColorTransferFunction(vtkColorTransferFunction* colorTF);
   vtkPlot* addOpacityFunction(vtkPiecewiseFunction* opacityTF);
-  vtkPlot* addCompositeFunction(vtkColorTransferFunction* colorTF, vtkPiecewiseFunction* opacityTF);
+  vtkPlot* addCompositeFunction(vtkColorTransferFunction* colorTF,
+                                vtkPiecewiseFunction* opacityTF);
+
+public slots:
+  void editPoint(vtkObject* plot, void * pointId);
 
 protected:
   QScopedPointer<ctkVTKScalarsToColorsViewPrivate> d_ptr;

+ 264 - 5
Libs/Visualization/VTK/Widgets/ctkVTKScalarsToColorsWidget.cpp

@@ -19,6 +19,7 @@
 =========================================================================*/
 
 // Qt includes
+#include <QDebug>
 
 // CTK includes
 #include "ctkLogger.h"
@@ -29,9 +30,12 @@
 // VTK includes
 #include <vtkAxis.h>
 #include <vtkChartXY.h>
+#include <vtkColorTransferControlPointsItem.h>
 #include <vtkColorTransferFunction.h>
 #include <vtkColorTransferFunctionItem.h>
+#include <vtkCompositeControlPointsItem.h>
 #include <vtkCompositeTransferFunctionItem.h>
+#include <vtkContextScene.h>
 #include <vtkLookupTable.h>
 #include <vtkLookupTableItem.h>
 #include <vtkPiecewiseControlPointsItem.h>
@@ -45,25 +49,57 @@ static ctkLogger logger("org.commontk.visualization.vtk.widgets.ctkVTKScalarsToC
 class ctkVTKScalarsToColorsWidgetPrivate:
   public Ui_ctkVTKScalarsToColorsWidget
 {
+   Q_DECLARE_PUBLIC(ctkVTKScalarsToColorsWidget);
+protected:
+  ctkVTKScalarsToColorsWidget* const q_ptr;
 public:
-  ctkVTKScalarsToColorsWidgetPrivate();
+  ctkVTKScalarsToColorsWidgetPrivate(ctkVTKScalarsToColorsWidget& object);
   void setupUi(QWidget* widget);
+  vtkControlPointsItem* CurrentControlPointsItem;
 };
 
 // ----------------------------------------------------------------------------
 // ctkVTKScalarsToColorsWidgetPrivate methods
 
 // ----------------------------------------------------------------------------
-ctkVTKScalarsToColorsWidgetPrivate::ctkVTKScalarsToColorsWidgetPrivate()
+ctkVTKScalarsToColorsWidgetPrivate::ctkVTKScalarsToColorsWidgetPrivate(
+  ctkVTKScalarsToColorsWidget& object)
+  : q_ptr(&object)
 {
+  this->CurrentControlPointsItem = 0;
 }
 
 // ----------------------------------------------------------------------------
 void ctkVTKScalarsToColorsWidgetPrivate::setupUi(QWidget* widget)
 {
+  Q_Q(ctkVTKScalarsToColorsWidget);
   this->Ui_ctkVTKScalarsToColorsWidget::setupUi(widget);
-  this->PSpinBox->setValue(0.4);
-  this->VSpinBox->setValue(0.87);
+  QObject::connect(this->View, SIGNAL(plotAdded(vtkPlot*)),
+                   q, SLOT(onPlotAdded(vtkPlot*)));
+  this->PointIdSpinBox->setSpecialValueText("None");
+  QObject::connect(this->PointIdSpinBox, SIGNAL(valueChanged(int)),
+                   q, SLOT(onCurrentPointChanged(int)));
+  this->PointIdSpinBox->setValue(-1);
+  QObject::connect(this->ColorPickerButton, SIGNAL(colorChanged(const QColor&)),
+                   q, SLOT(onColorChanged(const QColor&)));
+  QObject::connect(this->OpacitySpinBox, SIGNAL(valueChanged(double)),
+                   q, SLOT(onOpacityChanged(double)));
+  QObject::connect(this->MidPointSpinBox, SIGNAL(valueChanged(double)),
+                   q, SLOT(onMidPointChanged(double)));
+  QObject::connect(this->SharpnessSpinBox, SIGNAL(valueChanged(double)),
+                   q, SLOT(onSharpnessChanged(double)));
+  this->ColorPickerButton->setVisible(false);
+  this->OpacityLabel->setVisible(false);
+  this->OpacitySpinBox->setVisible(false);
+  QObject::connect(this->XRangeSlider, SIGNAL(valuesChanged(double, double)),
+                   q, SLOT(onXRangeChanged(double, double)));
+  QObject::connect(this->YRangeSlider, SIGNAL(valuesChanged(double, double)),
+                   q, SLOT(onYRangeChanged(double, double)));
+  q->qvtkConnect(this->View->chart()->GetAxis(0),vtkCommand::ModifiedEvent,
+                    q, SLOT(onAxesModified()));
+  q->qvtkConnect(this->View->chart()->GetAxis(1),vtkCommand::ModifiedEvent,
+                    q, SLOT(onAxesModified()));
+
 }
 
 // ----------------------------------------------------------------------------
@@ -72,7 +108,7 @@ void ctkVTKScalarsToColorsWidgetPrivate::setupUi(QWidget* widget)
 // ----------------------------------------------------------------------------
 ctkVTKScalarsToColorsWidget::ctkVTKScalarsToColorsWidget(QWidget* parentWidget)
   :QWidget(parentWidget)
-  , d_ptr(new ctkVTKScalarsToColorsWidgetPrivate)
+   , d_ptr(new ctkVTKScalarsToColorsWidgetPrivate(*this))
 {
   Q_D(ctkVTKScalarsToColorsWidget);
   d->setupUi(this);
@@ -89,3 +125,226 @@ ctkVTKScalarsToColorsView* ctkVTKScalarsToColorsWidget::view()const
   Q_D(const ctkVTKScalarsToColorsWidget);
   return d->View;
 }
+
+// ----------------------------------------------------------------------------
+void ctkVTKScalarsToColorsWidget::onPlotAdded(vtkPlot* plot)
+{
+  if (vtkControlPointsItem::SafeDownCast(plot))
+    {
+    this->qvtkConnect(plot, vtkControlPointsItem::CurrentPointChangedEvent,
+                      this, SLOT(setCurrentPoint(vtkObject*, void*)));
+    }
+}
+
+// ----------------------------------------------------------------------------
+void ctkVTKScalarsToColorsWidget::setCurrentPoint(vtkObject* caller, void* callData)
+{
+  vtkControlPointsItem* controlPoints = reinterpret_cast<vtkControlPointsItem*>(caller);
+  long newPoint = reinterpret_cast<long>(callData);
+  if (!controlPoints || newPoint < -1)
+    {
+    return;
+    }
+  this->setCurrentControlPointsItem(controlPoints);
+  this->setCurrentPoint(newPoint);
+}
+
+// ----------------------------------------------------------------------------
+void ctkVTKScalarsToColorsWidget::setCurrentPoint(int newPoint)
+{
+  Q_D(ctkVTKScalarsToColorsWidget);
+  d->PointIdSpinBox->setValue(newPoint);
+}
+
+// ----------------------------------------------------------------------------
+void ctkVTKScalarsToColorsWidget::setCurrentControlPointsItem(vtkControlPointsItem* item)
+{
+  Q_D(ctkVTKScalarsToColorsWidget);
+  if (d->CurrentControlPointsItem == item)
+    {
+    return;
+    }
+  this->qvtkReconnect(d->CurrentControlPointsItem, item, vtkCommand::ModifiedEvent,
+                      this, SLOT(updateCurrentPoint()));
+  this->qvtkReconnect(d->CurrentControlPointsItem ?
+                      d->CurrentControlPointsItem->GetXAxis() : d->View->chart()->GetAxis(0),
+                      item ? item->GetXAxis() : d->View->chart()->GetAxis(0),
+                      vtkCommand::ModifiedEvent,
+                      this, SLOT(onAxesModified()));
+  this->qvtkReconnect(d->CurrentControlPointsItem ?
+                      d->CurrentControlPointsItem->GetYAxis() : d->View->chart()->GetAxis(1),
+                      item ? item->GetYAxis() : d->View->chart()->GetAxis(1),
+                      vtkCommand::ModifiedEvent,
+                      this, SLOT(onAxesModified()));
+  d->CurrentControlPointsItem = item;
+  if (item)
+    {
+    d->ColorPickerButton->setVisible(
+      vtkColorTransferControlPointsItem::SafeDownCast(item) != 0 ||
+      vtkCompositeControlPointsItem::SafeDownCast(item) != 0);
+    d->OpacityLabel->setVisible(vtkPiecewiseControlPointsItem::SafeDownCast(item) != 0 ||
+                                vtkCompositeControlPointsItem::SafeDownCast(item) != 0);
+    d->OpacitySpinBox->setVisible(vtkPiecewiseControlPointsItem::SafeDownCast(item) != 0 ||
+                                  vtkCompositeControlPointsItem::SafeDownCast(item) != 0);
+    this->onAxesModified();
+    }
+  d->PointIdSpinBox->setEnabled(item != 0);
+  d->PointIdSpinBox->setMaximum((item ? item->GetNumberOfPoints() : 0) - 1);
+  d->PointIdSpinBox->setValue(item ? item->GetCurrentPoint() : -1);
+  this->updateCurrentPoint();
+}
+
+// ----------------------------------------------------------------------------
+vtkControlPointsItem* ctkVTKScalarsToColorsWidget::currentControlPointsItem()const
+{
+  Q_D(const ctkVTKScalarsToColorsWidget);
+  return d->CurrentControlPointsItem;
+}
+
+// ----------------------------------------------------------------------------
+void ctkVTKScalarsToColorsWidget::onCurrentPointChanged(int currentPoint)
+{
+  Q_D(ctkVTKScalarsToColorsWidget);
+  if (d->CurrentControlPointsItem)
+    {
+    d->CurrentControlPointsItem->SetCurrentPoint(currentPoint);
+    }
+
+  d->ColorPickerButton->setEnabled(currentPoint != -1);
+  d->OpacitySpinBox->setEnabled(currentPoint != -1);
+  d->MidPointSpinBox->setEnabled(currentPoint != -1);
+  d->SharpnessSpinBox->setEnabled(currentPoint != -1);
+
+  if (d->CurrentControlPointsItem)
+    {
+    this->updateCurrentPoint();
+    }
+}
+
+// ----------------------------------------------------------------------------
+void ctkVTKScalarsToColorsWidget::updateCurrentPoint()
+{
+  Q_D(ctkVTKScalarsToColorsWidget);
+  Q_ASSERT(d->CurrentControlPointsItem);
+  int pointId = d->PointIdSpinBox->value();
+  if (pointId == -1)
+    {
+    return;
+    }
+
+  double point[4];
+  d->CurrentControlPointsItem->GetControlPoint(pointId, point);
+  d->OpacitySpinBox->setValue(point[1]);
+  d->MidPointSpinBox->setValue(point[2]);
+  d->SharpnessSpinBox->setValue(point[3]);
+
+  vtkColorTransferControlPointsItem* colorControlPoints =
+    vtkColorTransferControlPointsItem::SafeDownCast(d->CurrentControlPointsItem);
+  if (colorControlPoints)
+    {
+    vtkColorTransferFunction* colorTF =
+      colorControlPoints->GetColorTransferFunction();
+    double xrgbms[6];
+    colorTF->GetNodeValue(d->PointIdSpinBox->value(), xrgbms);
+    QColor color = QColor::fromRgbF(xrgbms[1], xrgbms[2], xrgbms[3]);
+    d->ColorPickerButton->setColor(color);
+    }
+}
+
+// ----------------------------------------------------------------------------
+void ctkVTKScalarsToColorsWidget::onColorChanged(const QColor& color)
+{
+  Q_D(ctkVTKScalarsToColorsWidget);
+  if (!color.isValid())
+    {
+    return;
+    }
+  Q_ASSERT(d->CurrentControlPointsItem);
+  Q_ASSERT(d->PointIdSpinBox->value() != -1);
+  Q_ASSERT(d->PointIdSpinBox->value() == d->CurrentControlPointsItem->GetCurrentPoint());
+
+  vtkColorTransferControlPointsItem* colorControlPoints =
+    vtkColorTransferControlPointsItem::SafeDownCast(d->CurrentControlPointsItem);
+  if (colorControlPoints)
+    {
+    vtkColorTransferFunction* colorTF =
+      colorControlPoints->GetColorTransferFunction();
+    double point[6];
+    colorTF->GetNodeValue(d->PointIdSpinBox->value(), point);
+    point[1] = color.redF();
+    point[2] = color.greenF();
+    point[3] = color.blueF();
+    d->CurrentControlPointsItem->SetControlPoint(
+      d->PointIdSpinBox->value(), point);
+    }
+}
+
+// ----------------------------------------------------------------------------
+void ctkVTKScalarsToColorsWidget::onOpacityChanged(double opacity)
+{
+  Q_D(ctkVTKScalarsToColorsWidget);
+  Q_ASSERT(d->CurrentControlPointsItem);
+
+  double point[4];
+  d->CurrentControlPointsItem->GetControlPoint(d->PointIdSpinBox->value(), point);
+  point[1] = opacity;
+  d->CurrentControlPointsItem->SetControlPoint(d->PointIdSpinBox->value(), point);
+}
+
+// ----------------------------------------------------------------------------
+void ctkVTKScalarsToColorsWidget::onMidPointChanged(double midPoint)
+{
+  Q_D(ctkVTKScalarsToColorsWidget);
+  Q_ASSERT(d->CurrentControlPointsItem);
+
+  double point[4];
+  d->CurrentControlPointsItem->GetControlPoint(d->PointIdSpinBox->value(), point);
+  point[2] = midPoint;
+  d->CurrentControlPointsItem->SetControlPoint(d->PointIdSpinBox->value(), point);
+}
+
+// ----------------------------------------------------------------------------
+void ctkVTKScalarsToColorsWidget::onSharpnessChanged(double sharpness)
+{
+  Q_D(ctkVTKScalarsToColorsWidget);
+  Q_ASSERT(d->CurrentControlPointsItem);
+
+  double point[4];
+  d->CurrentControlPointsItem->GetControlPoint(d->PointIdSpinBox->value(), point);
+  point[3] = sharpness;
+  d->CurrentControlPointsItem->SetControlPoint(d->PointIdSpinBox->value(), point);
+}
+
+// ----------------------------------------------------------------------------
+void ctkVTKScalarsToColorsWidget::onXRangeChanged(double min, double max)
+{
+  Q_D(ctkVTKScalarsToColorsWidget);
+  vtkAxis* xAxis = d->CurrentControlPointsItem ?
+    d->CurrentControlPointsItem->GetXAxis() : d->View->chart()->GetAxis(0);
+  Q_ASSERT(xAxis);
+  xAxis->SetRange(min, max);
+}
+
+// ----------------------------------------------------------------------------
+void ctkVTKScalarsToColorsWidget::onYRangeChanged(double min, double max)
+{
+  Q_D(ctkVTKScalarsToColorsWidget);
+  vtkAxis* yAxis = d->CurrentControlPointsItem ?
+    d->CurrentControlPointsItem->GetYAxis() : d->View->chart()->GetAxis(1);
+  Q_ASSERT(yAxis);
+  yAxis->SetRange(min, max);
+}
+
+// ----------------------------------------------------------------------------
+void ctkVTKScalarsToColorsWidget::onAxesModified()
+{
+  Q_D(ctkVTKScalarsToColorsWidget);
+  vtkAxis* xAxis = d->CurrentControlPointsItem ?
+    d->CurrentControlPointsItem->GetXAxis() : d->View->chart()->GetAxis(0);
+  Q_ASSERT(xAxis);
+  d->XRangeSlider->setValues(xAxis->GetMinimum(), xAxis->GetMaximum());
+  vtkAxis* yAxis = d->CurrentControlPointsItem ?
+    d->CurrentControlPointsItem->GetYAxis() : d->View->chart()->GetAxis(1);
+  Q_ASSERT(yAxis);
+  d->YRangeSlider->setValues(yAxis->GetMinimum(), yAxis->GetMaximum());
+}

+ 22 - 2
Libs/Visualization/VTK/Widgets/ctkVTKScalarsToColorsWidget.h

@@ -25,23 +25,43 @@
 #include <QWidget>
 
 // CTK includes
-#include <ctkPimpl.h>
+#include <ctkVTKObject.h>
 #include "ctkVisualizationVTKWidgetsExport.h"
 class ctkVTKScalarsToColorsView;
 class ctkVTKScalarsToColorsWidgetPrivate;
 
 // VTK includes
-#include <QVTKWidget.h>
+class vtkControlPointsItem;
+class vtkPlot;
 
 class CTK_VISUALIZATION_VTK_WIDGETS_EXPORT ctkVTKScalarsToColorsWidget : public QWidget
 {
   Q_OBJECT
+  QVTK_OBJECT
 
 public:
   ctkVTKScalarsToColorsWidget(QWidget* parent = 0);
   virtual ~ctkVTKScalarsToColorsWidget();
 
   ctkVTKScalarsToColorsView* view()const;
+  vtkControlPointsItem* currentControlPointsItem()const;
+
+public slots:
+  void setCurrentControlPointsItem(vtkControlPointsItem* item);
+  void setCurrentPoint(int pointId);
+
+protected slots:
+  void onPlotAdded(vtkPlot*);
+  void setCurrentPoint(vtkObject* controlPointsItem, void* pointId);
+  void updateCurrentPoint();
+  void onCurrentPointChanged(int pointId);
+  void onColorChanged(const QColor& color);
+  void onOpacityChanged(double opacity);
+  void onMidPointChanged(double midPoint);
+  void onSharpnessChanged(double sharpness);
+  void onXRangeChanged(double min, double max);
+  void onYRangeChanged(double min, double max);
+  void onAxesModified();
 protected:
   QScopedPointer<ctkVTKScalarsToColorsWidgetPrivate> d_ptr;