/*=========================================================================

   Program: ParaView
   Module:    pqColorScaleEditor.cxx

   Copyright (c) 2005,2006 Sandia Corporation, Kitware Inc.
   All rights reserved.

   ParaView is a free software; you can redistribute it and/or modify it
   under the terms of the ParaView license version 1.1. 

   See License_v1.1.txt for the full ParaView license.
   A copy of this license can be obtained by contacting
   Kitware Inc.
   28 Corporate Drive
   Clifton Park, NY 12065
   USA

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

=========================================================================*/

/// \file pqColorScaleEditor.cxx
/// \date 2/14/2007

#include "pqColorScaleEditor.h"
#include "ui_pqColorScaleDialog.h"

#include "pqApplicationCore.h"
#include "pqChartValue.h"
#include "pqColorMapColorChanger.h"
#include "pqColorMapModel.h"
#include "pqColorMapWidget.h"
#include "pqColorPresetManager.h"
#include "pqColorPresetModel.h"
#include "pqGenericViewModule.h"
#include "pqLineEditNumberValidator.h"
#include "pqObjectBuilder.h"
#include "pqPipelineDisplay.h"
#include "pqPropertyLinks.h"
#include "pqRenderViewModule.h"
#include "pqRescaleRange.h"
#include "pqScalarBarDisplay.h"
#include "pqScalarsToColors.h"
#include "pqSignalAdaptors.h"
#include "pqSMAdaptor.h"

#include <QCloseEvent>
#include <QColor>
#include <QColorDialog>
#include <QGridLayout>
#include <QItemSelectionModel>
#include <QList>
#include <QMenu>
#include <QSpacerItem>
#include <QString>
#include <QtDebug>
#include <QTimer>
#include <QVariant>

#include "vtkColorTransferFunction.h"
#include "vtkEventQtSlotConnect.h"
#include "vtkPiecewiseFunction.h"
#include "vtkSMDataObjectDisplayProxy.h"
#include "vtkSMProperty.h"
#include "vtkSMProxy.h"
#include "vtkTransferFunctionViewer.h"
#include "vtkType.h"

// Temporary switch
#define USE_VTK_TFE 1


class pqColorScaleEditorForm : public Ui::pqColorScaleDialog
{
public:
  pqColorScaleEditorForm();
  ~pqColorScaleEditorForm() {}

  pqPropertyLinks Links;
  pqSignalAdaptorColor *TitleColorAdaptor;
  pqSignalAdaptorColor *LabelColorAdaptor;
  pqSignalAdaptorComboBox *TitleFontAdaptor;
  pqSignalAdaptorComboBox *LabelFontAdaptor;
  vtkEventQtSlotConnect *Listener;
  pqColorMapWidget *Gradient;
  pqColorPresetManager *Presets;
  int CurrentIndex;
  bool HasOpacity;
  bool ValueChanged;
  bool OpacityChanged;
  bool SizeChanged;
  bool InSetColors;
  bool IgnoreEditor;
};


//----------------------------------------------------------------------------
pqColorScaleEditorForm::pqColorScaleEditorForm()
  : Ui::pqColorScaleDialog(), Links()
{
  this->TitleColorAdaptor = 0;
  this->LabelColorAdaptor = 0;
  this->TitleFontAdaptor = 0;
  this->LabelFontAdaptor = 0;
  this->Listener = 0;
  this->Gradient = 0;
  this->Presets = 0;
  this->CurrentIndex = -1;
  this->HasOpacity = false;
  this->ValueChanged = false;
  this->OpacityChanged = false;
  this->SizeChanged = false;
  this->InSetColors = false;
  this->IgnoreEditor = false;
}


//----------------------------------------------------------------------------
pqColorScaleEditor::pqColorScaleEditor(QWidget *widgetParent)
  : QDialog(widgetParent)
{
  this->Form = new pqColorScaleEditorForm();
  this->Viewer = vtkTransferFunctionViewer::New();
  this->Display = 0;
  this->ColorMap = 0;
  this->Legend = 0;
  this->EditDelay = new QTimer(this);

  // Set up the ui.
  this->Form->setupUi(this);
  this->Form->Listener = vtkEventQtSlotConnect::New();
  this->Form->Presets = new pqColorPresetManager(this);
  this->Form->Presets->restoreSettings();

#if USE_VTK_TFE
  vtkRenderWindow *win = this->Form->ColorScale->GetRenderWindow();
  vtkRenderWindowInteractor *iren = this->Form->ColorScale->GetInteractor();
  this->Viewer->SetInteractor(iren);
  this->Viewer->SetRenderWindow(win);
  this->Viewer->SetTransferFunctionEditorType(vtkTransferFunctionViewer::SIMPLE_1D);
  this->Viewer->SetModificationTypeToColor();
  this->Viewer->SetWholeScalarRange(0.0, 1.0);
  this->Viewer->SetVisibleScalarRange(0.0, 1.0);
  this->Viewer->SetLockEndPoints(1);
  this->Viewer->SetShowColorFunctionInBackground(1);
  this->Viewer->SetShowColorFunctionOnLines(0);
  this->Viewer->SetBackgroundColor(1.0, 1.0, 1.0);
  this->Viewer->SetLinesColor(0.0, 0.0, 0.0);

  this->Form->Listener->Connect(this->Viewer, vtkCommand::PickEvent,
      this, SLOT(changeCurrentColor()));
  this->Form->Listener->Connect(this->Viewer,
      vtkCommand::WidgetValueChangedEvent,
      this, SLOT(handleEditorPointMoved()));
  this->Form->Listener->Connect(this->Viewer, vtkCommand::EndInteractionEvent,
      this, SLOT(handleEditorPointMoveFinished()));
  this->Form->Listener->Connect(this->Viewer, vtkCommand::PlacePointEvent,
      this, SLOT(handleEditorAddOrDelete()));
  this->Form->Listener->Connect(this->Viewer, vtkCommand::WidgetModifiedEvent,
      this, SLOT(handleEditorCurrentChanged()));
#else
  // Hide the qvtk widget and add in a color map widget.
  QGridLayout *grid = qobject_cast<QGridLayout *>(
      this->Form->ScalePage->layout());
  this->Form->Gradient = new pqColorMapWidget();
  this->Form->ColorScale->hide();
  grid->addWidget(this->Form->Gradient, 0, 0, 1, 4);
  pqColorMapModel *colorModel = new pqColorMapModel(this->Form->Gradient);
  colorModel->setObjectName("ColorModel");
  this->Form->Gradient->setModel(colorModel);

  new pqColorMapColorChanger(this->Form->Gradient);
  this->connect(this->Form->Gradient, SIGNAL(currentPointChanged(int)),
      this, SLOT(setCurrentPoint(int)));
  this->connect(colorModel, SIGNAL(colorChanged(int, const QColor &)),
      this, SLOT(setColors()));
  this->connect(colorModel, SIGNAL(pointAdded(int)),
      this, SLOT(handleEditorAdd(int)));
  this->connect(colorModel, SIGNAL(pointRemoved(int)),
      this, SLOT(handleEditorAddOrDelete()));
  this->connect(this->Form->Gradient, SIGNAL(pointMoved(int)),
      this, SLOT(handleEditorPointMoveFinished()));
#endif

  // Set up the timer. The timer is used when the user edits the
  // table size.
  this->EditDelay->setSingleShot(true);

  // Initialize the state of some of the controls.
  this->enableRescaleControls(this->Form->UseAutoRescale->isChecked());
  this->enableResolutionControls(this->Form->UseDiscreteColors->isChecked());

  this->enableLegendControls(this->Form->ShowColorLegend->isChecked());

  // Add the color space options to the combo box.
  this->Form->ColorSpace->addItem("RGB");
  this->Form->ColorSpace->addItem("HSV");
  this->Form->ColorSpace->addItem("Wrapped HSV");

  // Add the color scale presets menu.
  this->loadBuiltinColorPresets();

  // Make sure the line edits only allow number inputs.
  pqLineEditNumberValidator *validator =
      new pqLineEditNumberValidator(true, this);
  this->Form->ScalarValue->installEventFilter(validator);
  this->Form->Opacity->installEventFilter(validator);
  validator = new pqLineEditNumberValidator(false, this);
  this->Form->TableSizeText->installEventFilter(validator);

  // Connect the color scale widgets.
  this->connect(this->Form->ScalarValue, SIGNAL(textEdited(const QString &)),
      this, SLOT(handleValueEdit()));
  this->connect(this->Form->Opacity, SIGNAL(textEdited(const QString &)),
      this, SLOT(handleOpacityEdit()));

  this->connect(this->Form->ColorSpace, SIGNAL(activated(int)),
      this, SLOT(setColorSpace(int)));

  this->connect(this->Form->SaveButton, SIGNAL(clicked()),
      this, SLOT(savePreset()));
  this->connect(this->Form->PresetButton, SIGNAL(clicked()),
      this, SLOT(loadPreset()));

  this->connect(this->Form->Component, SIGNAL(activated(int)),
      this, SLOT(setComponent(int)));

  this->connect(this->Form->UseLogScale, SIGNAL(toggled(bool)),
      this, SLOT(setLogScale(bool)));

  this->connect(this->Form->UseAutoRescale, SIGNAL(toggled(bool)),
      this, SLOT(setAutoRescale(bool)));
  this->connect(this->Form->RescaleButton, SIGNAL(clicked()),
      this, SLOT(rescaleToNewRange()));
  this->connect(this->Form->RescaleToDataButton, SIGNAL(clicked()),
      this, SLOT(rescaleToDataRange()));

  this->connect(this->Form->UseDiscreteColors, SIGNAL(toggled(bool)),
      this, SLOT(setUseDiscreteColors(bool)));
  this->connect(this->Form->TableSize, SIGNAL(valueChanged(int)),
      this, SLOT(setSizeFromSlider(int)));
  this->connect(this->Form->TableSizeText, SIGNAL(textEdited(const QString &)),
      this, SLOT(handleSizeTextEdit()));

  this->connect(this->EditDelay, SIGNAL(timeout()),
      this, SLOT(applyTextChanges()));

  // Connect the color legend widgets.
  this->connect(this->Form->ShowColorLegend, SIGNAL(toggled(bool)),
      this, SLOT(setLegendVisibility(bool)));

  this->connect(this->Form->TitleName, SIGNAL(textChanged(const QString &)),
      this, SLOT(setLegendName(const QString &)));
  this->connect(this->Form->TitleComponent, SIGNAL(textChanged(const QString &)),
      this, SLOT(setLegendComponent(const QString &)));
  this->Form->TitleColorAdaptor = new pqSignalAdaptorColor(
      this->Form->TitleColorButton, "chosenColor", 
      SIGNAL(chosenColorChanged(const QColor&)), false);
  this->Form->TitleFontAdaptor = new pqSignalAdaptorComboBox(
      this->Form->TitleFont);

  this->Form->LabelColorAdaptor = new pqSignalAdaptorColor(
      this->Form->LabelColorButton, "chosenColor", 
      SIGNAL(chosenColorChanged(const QColor&)), false);
  this->Form->LabelFontAdaptor = new pqSignalAdaptorComboBox(
      this->Form->LabelFont);

  // Hook the close button up to the accept action.
  this->connect(this->Form->CloseButton, SIGNAL(clicked()),
      this, SLOT(accept()));
}

pqColorScaleEditor::~pqColorScaleEditor()
{
  // Save the color map presets.
  this->Form->Presets->saveSettings();

  delete this->Form->LabelColorAdaptor;
  delete this->Form->TitleColorAdaptor;
  delete this->Form->LabelFontAdaptor;
  delete this->Form->TitleFontAdaptor;
  this->Form->Listener->Delete();
  delete this->Form;
  this->Viewer->Delete();
  delete this->EditDelay;
}

void pqColorScaleEditor::setDisplay(pqPipelineDisplay *display)
{
  if(this->Display == display)
    {
    return;
    }

  this->setLegend(0);
  if(this->Display)
    {
    this->disconnect(this->Display, 0, this, 0);
    this->disconnect(&this->Form->Links, 0, this->Display, 0);
    if(this->ColorMap)
      {
      this->disconnect(this->ColorMap, 0, this, 0);
      this->Form->Listener->Disconnect(
          this->ColorMap->getProxy()->GetProperty("RGBPoints"));
      }

    if(this->Form->HasOpacity)
      {
      this->Form->Listener->Disconnect(
          this->Display->getScalarOpacityFunctionProxy()->GetProperty("Points"));
      }
    }

  this->Display = display;
  this->ColorMap = 0;
  if(this->Display)
    {
    this->connect(this->Display, SIGNAL(destroyed(QObject *)),
        this, SLOT(cleanupDisplay()));
    this->connect(&this->Form->Links, SIGNAL(qtWidgetChanged()),
        this->Display, SLOT(renderAllViews()));

    // Get the color map object for the display's lookup table.
    this->ColorMap = this->Display->getLookupTable();
    if(this->ColorMap)
      {
      this->connect(this->ColorMap, SIGNAL(destroyed(QObject *)),
          this, SLOT(cleanupDisplay()));
      this->Form->Listener->Connect(
          this->ColorMap->getProxy()->GetProperty("RGBPoints"),
          vtkCommand::ModifiedEvent, this, SLOT(handlePointsChanged()));
      }
    }

  // Disable the gui elements if the color map is null.
  this->Form->ColorTabs->setEnabled(this->ColorMap != 0);
  this->initColorScale();
  if(this->ColorMap)
    {
    pqRenderViewModule *renderModule = qobject_cast<pqRenderViewModule *>(
        this->Display->getViewModule(0));
    this->setLegend(this->ColorMap->getScalarBar(renderModule));
    }
}

void pqColorScaleEditor::rescaleRange()
{
  this->rescaleToDataRange();
}

void pqColorScaleEditor::showEvent(QShowEvent *e)
{
  QDialog::showEvent(e);
  //this->Viewer->Render();
}

void pqColorScaleEditor::hideEvent(QHideEvent *e)
{
  // If the edit delay timer is active, set the final user entry.
  if(this->EditDelay->isActive())
    {
    this->EditDelay->stop();
    this->applyTextChanges();
    }

  QDialog::hideEvent(e);
}

void pqColorScaleEditor::handleEditorPointMoved()
{
  if(!this->Form->IgnoreEditor)
    {
    this->updatePointValues();
    }
}

void pqColorScaleEditor::handleEditorPointMoveFinished()
{
  if(!this->Form->IgnoreEditor)
    {
    this->updatePointValues();
    this->setColors();
    }
}

void pqColorScaleEditor::handleEditorAddOrDelete()
{
  if(!this->Form->IgnoreEditor)
    {
    this->setColors();

    // Update the current point.
#if USE_VTK_TFE
    this->Form->CurrentIndex = this->Viewer->GetCurrentElementId();
#else
    this->Form->CurrentIndex = this->Form->Gradient->getCurrentPoint();
#endif

    // Update the gui controls.
    this->enablePointControls();
    this->updatePointValues();
    }
}

void pqColorScaleEditor::handleEditorAdd(int index)
{
#if !USE_VTK_TFE
  if(!this->Form->IgnoreEditor)
    {
    this->setColors();

    // Set the new point as the current point.
    this->Form->Gradient->blockSignals(true);
    this->Form->Gradient->setCurrentPoint(index);
    this->Form->Gradient->blockSignals(false);
    this->Form->CurrentIndex = this->Form->Gradient->getCurrentPoint();

    // Update the gui controls.
    this->enablePointControls();
    this->updatePointValues();
    }
#else
  index = index;
#endif
}

void pqColorScaleEditor::setColors()
{
  if(!this->ColorMap)
    {
    return;
    }

  QList<QVariant> rgbPoints;
  QList<QVariant> opacityPoints;
  this->Form->InSetColors = true;

#if USE_VTK_TFE
  double rgb[3];
  double scalar = 0.0;
  int total = this->Viewer->GetColorFunction()->GetSize();
  for(int i = 0; i < total; i++)
    {
    if(this->Viewer->GetElementRGBColor(i, rgb))
      {
      scalar = this->Viewer->GetElementScalar(i);
      rgbPoints << scalar << rgb[0] << rgb[1] << rgb[2];
      if(this->Form->HasOpacity)
        {
        double opacity = this->Viewer->GetElementOpacity(i);
        opacityPoints << scalar << opacity;
        }
      }
    }
#else
  pqColorMapModel *model = this->Form->Gradient->getModel();
  for(int i = 0; i < model->getNumberOfPoints(); ++i)
    {
    QColor color;
    pqChartValue scalar;
    model->getPointValue(i, scalar);
    model->getPointColor(i, color);
    rgbPoints << scalar.getDoubleValue() <<
        color.redF() << color.greenF() << color.blueF();
    if(this->Form->HasOpacity)
      {
      pqChartValue opacity;
      model->getPointOpacity(i, opacity);
      opacityPoints << scalar.getDoubleValue() << opacity.getDoubleValue();
      }
    }
#endif

  vtkSMProxy *lookupTable = this->ColorMap->getProxy();
  pqSMAdaptor::setMultipleElementProperty(
      lookupTable->GetProperty("RGBPoints"), rgbPoints);
  if(this->Form->HasOpacity)
    {
    vtkSMProxy *points = this->Display->getScalarOpacityFunctionProxy();
    pqSMAdaptor::setMultipleElementProperty(points->GetProperty("Points"),
        opacityPoints);
    points->UpdateVTKObjects();
    }

  this->Form->InSetColors = false;
  lookupTable->UpdateVTKObjects();
  this->Display->renderAllViews();
}

void pqColorScaleEditor::changeCurrentColor()
{
#if USE_VTK_TFE
  // Get the current index color from the viewer.
  double rgb[3];
  unsigned int index = this->Viewer->GetCurrentElementId();
  if(this->Viewer->GetElementRGBColor(index, rgb))
    {
    // Let the user choose a color.
    QColor color = QColor::fromRgbF(rgb[0], rgb[1], rgb[2]);
    color = QColorDialog::getColor(color, this);
    if(color.isValid())
      {
      this->Viewer->SetElementRGBColor(index, color.redF(), color.greenF(),
          color.blueF());
      this->setColors();
      }
    }
#endif
}

void pqColorScaleEditor::handlePointsChanged()
{
  // If the point change was not generated by setColors, update the
  // points in the editor.
  if(!this->Form->InSetColors)
    {
    // Save the current point index to use after the change.
    int index = this->Form->CurrentIndex;
    this->Form->CurrentIndex = -1;

    // Load the new points.
    this->Form->IgnoreEditor = true;
#if !USE_VTK_TFE
    pqColorMapModel *model = this->Form->Gradient->getModel();
    model->startModifyingData();
#endif
    this->loadColorPoints();

#if USE_VTK_TFE
    this->Viewer->Render();
#else
    model->finishModifyingData();
#endif

    // Set the current point on the editor.
    if(index != -1)
      {
  #if USE_VTK_TFE
      this->Viewer->SetCurrentElementId(index);
      this->Form->CurrentIndex = this->Viewer->GetCurrentElementId();
  #else
      this->Form->Gradient->blockSignals(true);
      this->Form->Gradient->setCurrentPoint(index);
      this->Form->Gradient->blockSignals(false);
      this->Form->CurrentIndex = this->Form->Gradient->getCurrentPoint();
  #endif
      }

    // Update the displayed values.
    this->Form->IgnoreEditor = false;
    this->enablePointControls();
    this->updatePointValues();
    }
}

void pqColorScaleEditor::handleEditorCurrentChanged()
{
#if USE_VTK_TFE
  // Get the current index from the viewer.
  if(!this->Form->IgnoreEditor)
    {
    unsigned int id = this->Viewer->GetCurrentElementId();
    this->setCurrentPoint((int)id);
    }
#endif
}

void pqColorScaleEditor::setCurrentPoint(int index)
{
  if(index != this->Form->CurrentIndex)
    {
    // Make sure any pending value or opacity changes are handled.
    if(this->EditDelay->isActive())
      {
      this->EditDelay->stop();
      this->applyTextChanges();
      }

    // Change the current index and update the gui elements.
    this->Form->CurrentIndex = index;
    this->enablePointControls();

    // Get the value and opacity for the current point.
    this->updatePointValues();
    }
}

void pqColorScaleEditor::handleValueEdit()
{
  // Start a timer to allow the user to enter more text. If the timer
  // is already running delay it for more text.
  this->Form->ValueChanged = true;
  this->EditDelay->start(600);
}

void pqColorScaleEditor::setValueFromText()
{
  if(this->Form->CurrentIndex == -1)
    {
    return;
    }

  // Get the value from the line edit.
  bool ok = true;
  double value = this->Form->ScalarValue->text().toDouble(&ok);
  if(!ok)
    {
    // Reset to the previous value.
    this->updatePointValues();
    return;
    }

  // Make sure the value is greater than the previous point and less
  // than the next point.
  bool endpoint = this->Form->CurrentIndex == 0;
#if USE_VTK_TFE
  if(this->Form->CurrentIndex > 0)
    {
    double prev = this->Viewer->GetElementScalar(this->Form->CurrentIndex - 1);
    if(value < prev)
      {
      value = prev;
      }
    }

  vtkColorTransferFunction *colors = this->Viewer->GetColorFunction();
  endpoint = endpoint || this->Form->CurrentIndex == colors->GetSize() - 1;
  if(this->Form->CurrentIndex < colors->GetSize() - 1)
    {
    double next = this->Viewer->GetElementScalar(this->Form->CurrentIndex + 1);
    if(value > next)
      {
      value = next;
      }
    }
#else
  pqColorMapModel *model = this->Form->Gradient->getModel();
  if(this->Form->CurrentIndex > 0)
    {
    pqChartValue prev;
    model->getPointValue(this->Form->CurrentIndex - 1, prev);
    if(value < prev)
      {
      value = prev.getDoubleValue();
      }
    }

  endpoint = endpoint ||
      this->Form->CurrentIndex == model->getNumberOfPoints() - 1;
  if(this->Form->CurrentIndex < model->getNumberOfPoints() - 1)
    {
    pqChartValue next;
    model->getPointValue(this->Form->CurrentIndex + 1, next);
    if(value > next)
      {
      value = next.getDoubleValue();
      }
    }
#endif

  // Set the new value on the point in the editor.
  this->Form->IgnoreEditor = true;
#if USE_VTK_TFE
  this->Viewer->SetElementScalar(this->Form->CurrentIndex, value);
#else
  model->setPointValue(this->Form->CurrentIndex, value);
#endif
  this->Form->IgnoreEditor = false;

  // Update the colors on the proxy.
  this->setColors();

  // Update the range if the modified point was an endpoint.
  if(endpoint)
    {
    QPair<double, double> range = this->ColorMap->getScalarRange();
    this->updateScalarRange(range.first, range.second);
    }

#if USE_VTK_TFE
  this->Viewer->Render();
#endif
}

void pqColorScaleEditor::handleOpacityEdit()
{
  // Start a timer to allow the user to enter more text. If the timer
  // is already running delay it for more text.
  this->Form->OpacityChanged = true;
  this->EditDelay->start(600);
}

void pqColorScaleEditor::setOpacityFromText()
{
  if(this->Form->CurrentIndex == -1 || !this->Form->HasOpacity)
    {
    return;
    }

  // Get the opacity from the line edit.
  bool ok = true;
  double opacity = this->Form->Opacity->text().toDouble(&ok);
  if(!ok)
    {
    // Reset to the previous opacity.
    this->updatePointValues();
    return;
    }

  // Make sure the opacity is valid (0.0 - 1.0).
  if(opacity < 0.0)
    {
    opacity = 0.0;
    }
  else if(opacity > 1.0)
    {
    opacity = 1.0;
    }

  // Set the new opacity on the point in the editor.
  this->Form->IgnoreEditor = true;
#if USE_VTK_TFE
  this->Viewer->SetElementOpacity(this->Form->CurrentIndex, opacity);
  this->Viewer->Render();
#else
  pqColorMapModel *model = this->Form->Gradient->getModel();
  model->setPointOpacity(this->Form->CurrentIndex, pqChartValue(opacity));
#endif
  this->Form->IgnoreEditor = false;

  // Update the colors on the proxy.
  this->setColors();
}

void pqColorScaleEditor::setColorSpace(int index)
{
#if USE_VTK_TFE
  this->Viewer->SetColorSpace(index);
  this->Viewer->Render();
#else
  pqColorMapModel *model = this->Form->Gradient->getModel();
  model->setColorSpaceFromInt(index);
#endif

  if(this->ColorMap)
    {
    // Set the property on the lookup table.
    int wrap = index == 2 ? 1 : 0;
    if(wrap == 1)
      {
      index = 1;
      }

    this->Form->InSetColors = true;
    vtkSMProxy *lookupTable = this->ColorMap->getProxy();
    pqSMAdaptor::setElementProperty(
        lookupTable->GetProperty("ColorSpace"), index);
    pqSMAdaptor::setElementProperty(
        lookupTable->GetProperty("HSVWrap"), wrap);
    this->Form->InSetColors = false;
    lookupTable->UpdateVTKObjects();
    this->Display->renderAllViews();
    }
}

void pqColorScaleEditor::savePreset()
{
  // Make sure the any pending text changes are handled.
  if(this->EditDelay->isActive())
    {
    this->EditDelay->stop();
    this->applyTextChanges();
    }

  // Get the color preset model from the manager.
  pqColorPresetModel *model = this->Form->Presets->getModel();

  // Save the current color scale settings as a preset.
#if USE_VTK_TFE
  double rgb[3];
  double scalar = 0.0;
  pqColorMapModel colorMap;
  colorMap.setColorSpaceFromInt(this->Form->ColorSpace->currentIndex());
  int total = this->Viewer->GetColorFunction()->GetSize();
  for(int i = 0; i < total; i++)
    {
    if(this->Viewer->GetElementRGBColor(i, rgb))
      {
      scalar = this->Viewer->GetElementScalar(i);
      if(this->Form->HasOpacity)
        {
        colorMap.addPoint(pqChartValue(scalar),
            QColor::fromRgbF(rgb[0], rgb[1], rgb[2]),
            pqChartValue(this->Viewer->GetElementOpacity(i)));
        }
      else
        {
        colorMap.addPoint(pqChartValue(scalar),
            QColor::fromRgbF(rgb[0], rgb[1], rgb[2]));
        }
      }
    }

  model->addColorMap(colorMap, "New Color Preset");
#else
  model->addColorMap(*this->Form->Gradient->getModel(), "New Color Preset");
#endif

  // Select the newly added item (the last in the list).
  QItemSelectionModel *selection = this->Form->Presets->getSelectionModel();
  selection->setCurrentIndex(model->index(model->rowCount() - 1, 0),
      QItemSelectionModel::ClearAndSelect);

  // Set up the dialog and open it.
  this->Form->Presets->setUsingCloseButton(true);
  this->Form->Presets->exec();
}

void pqColorScaleEditor::loadPreset()
{
  // Make sure the any pending text changes are handled.
  if(this->EditDelay->isActive())
    {
    this->EditDelay->stop();
    this->applyTextChanges();
    }

  this->Form->Presets->setUsingCloseButton(false);
  if(this->Form->Presets->exec() == QDialog::Accepted)
    {
    // Get the color map from the selection.
    QItemSelectionModel *selection = this->Form->Presets->getSelectionModel();
    QModelIndex index = selection->currentIndex();
    const pqColorMapModel *colorMap =
        this->Form->Presets->getModel()->getColorMap(index.row());
    if(colorMap)
      {
      this->Form->IgnoreEditor = true;
      this->Form->CurrentIndex = -1;
      int colorSpace = colorMap->getColorSpaceAsInt();

#if USE_VTK_TFE
      QColor color;
      pqChartValue value, opacity;
      pqColorMapModel temp(*colorMap);
      if(this->Form->UseAutoRescale->isChecked() ||
          colorMap->isRangeNormalized())
        {
        QPair<double, double> range = this->ColorMap->getScalarRange();
        temp.setValueRange(range.first, range.second);
        }

      vtkPiecewiseFunction *opacities = 0;
      vtkColorTransferFunction *colors = this->Viewer->GetColorFunction();
      colors->RemoveAllPoints();
      if(this->Form->HasOpacity)
        {
        opacities = this->Viewer->GetOpacityFunction();
        opacities->RemoveAllPoints();
        }

      // Update the displayed range.
      temp.getValueRange(value, opacity);
      this->updateScalarRange(value.getDoubleValue(), opacity.getDoubleValue());

      for(int i = 0; i < colorMap->getNumberOfPoints(); i++)
        {
        temp.getPointColor(i, color);
        temp.getPointValue(i, value);
        colors->AddRGBPoint(value.getDoubleValue(), color.redF(),
            color.greenF(), color.blueF());
        if(this->Form->HasOpacity)
          {
          temp.getPointOpacity(i, opacity);
          opacities->AddPoint(value.getDoubleValue(),
              opacity.getDoubleValue());
          }
        }

      // Update the color space.
      this->Viewer->SetColorSpace(colorSpace);
      this->Viewer->Render();
#else
      pqColorMapModel *model = this->Form->Gradient->getModel();
      model->startModifyingData();
      *model = *colorMap;
      if(this->Form->UseAutoRescale->isChecked() ||
          colorMap->isRangeNormalized())
        {
        QPair<double, double> range = this->ColorMap->getScalarRange();
        model->setValueRange(range.first, range.second);
        }

      pqChartValue min, max;
      model->getValueRange(min, max);
      this->updateScalarRange(min.getDoubleValue(), max.getDoubleValue());
      model->finishModifyingData();
#endif

      // Update the color space chooser.
      this->Form->ColorSpace->setCurrentIndex(colorSpace);
      if(this->ColorMap)
        {
        // Set the property on the lookup table.
        int wrap = colorSpace == 2 ? 1 : 0;
        if(wrap == 1)
          {
          colorSpace = 1;
          }

        this->Form->InSetColors = true;
        vtkSMProxy *lookupTable = this->ColorMap->getProxy();
        pqSMAdaptor::setElementProperty(
            lookupTable->GetProperty("ColorSpace"), colorSpace);
        pqSMAdaptor::setElementProperty(
            lookupTable->GetProperty("HSVWrap"), wrap);
        this->Form->InSetColors = false;
        }

      // Update the actual color map.
      this->Form->IgnoreEditor = false;
      this->setColors();

      // Set up the current point index.
#if USE_VTK_TFE
      this->Viewer->SetCurrentElementId(0);
      this->Form->CurrentIndex = this->Viewer->GetCurrentElementId();
#else
      this->Form->Gradient->blockSignals(true);
      this->Form->Gradient->setCurrentPoint(0);
      this->Form->Gradient->blockSignals(false);
      this->Form->CurrentIndex = this->Form->Gradient->getCurrentPoint();
#endif

      this->enablePointControls();
      this->updatePointValues();
      }
    }
}

void pqColorScaleEditor::setComponent(int index)
{
  int component = this->Form->Component->itemData(index).toInt();
  this->ColorMap->setVectorMode( 
    (component == -1) ? pqScalarsToColors::MAGNITUDE : pqScalarsToColors::COMPONENT,
    component);

  // Update the color legend title.
  this->setLegendComponent(this->Form->Component->itemText(index));

  // Update the scalar range if the range is set from the data.
  if(this->Form->UseAutoRescale->isChecked())
    {
    this->rescaleToDataRange();
    }

  this->Display->renderAllViews();
}

void pqColorScaleEditor::setLogScale(bool on)
{
  vtkSMProxy *lookupTable = this->ColorMap->getProxy();
  pqSMAdaptor::setElementProperty(
      lookupTable->GetProperty("UseLogScale"), on ? 1 : 0);

  // Set the log scale flag on the editor.
#if USE_VTK_TFE
  this->Viewer->GetColorFunction()->SetScale(
      on ? VTK_CTF_LOG10 : VTK_CTF_LINEAR);
  this->Viewer->Render();
#else
  // TODO
#endif

  lookupTable->UpdateVTKObjects();
  this->Display->renderAllViews();
}

void pqColorScaleEditor::setAutoRescale(bool on)
{
  this->enableRescaleControls(!on);
  this->ColorMap->setScalarRangeLock(!on);
  this->enablePointControls();
  if(on)
    {
    // Reset the range to the current.
    this->rescaleToDataRange();
    }
}

void pqColorScaleEditor::rescaleToNewRange()
{
  // Launch the rescale range dialog to get the new range.
  pqRescaleRange rescaleDialog(this);
  QPair<double, double> range = this->ColorMap->getScalarRange();
  rescaleDialog.setRange(range.first, range.second);
  if(rescaleDialog.exec() == QDialog::Accepted)
    {
    this->setScalarRange(rescaleDialog.getMinimum(),
        rescaleDialog.getMaximum());
    }
}

void pqColorScaleEditor::rescaleToDataRange()
{
  QString colorField = this->Display->getColorField();
  int component_no = -1;
  if(this->ColorMap->getVectorMode() == pqScalarsToColors::COMPONENT)
    {
    component_no = this->ColorMap->getVectorComponent();
    }

  QPair<double, double> range = 
      this->Display->getColorFieldRange(colorField, component_no);
  this->setScalarRange(range.first, range.second);
}

void pqColorScaleEditor::setUseDiscreteColors(bool on)
{
  // Update the color scale widget and gui controls.
  this->enableResolutionControls(on);
#if USE_VTK_TFE
  // TODO?
  this->Viewer->Render();
#else
  int tableSize = 0;
  if(!on)
    {
    tableSize = this->Form->TableSizeText->text().toInt();
    }

  this->Form->Gradient->setTableSize(tableSize);
#endif

  if(this->ColorMap)
    {
    // Set the property on the lookup table.
    vtkSMProxy *lookupTable = this->ColorMap->getProxy();
    pqSMAdaptor::setElementProperty(
        lookupTable->GetProperty("Discretize"), (on ? 1 : 0));
    lookupTable->UpdateVTKObjects();
    this->Display->renderAllViews();
    }
}

void pqColorScaleEditor::handleSizeTextEdit()
{
  // Start a timer to allow the user to enter more text. If the timer
  // is already running delay it for more text.
  this->Form->SizeChanged = true;
  this->EditDelay->start(600);
}

void pqColorScaleEditor::setSizeFromText()
{
  // Get the size from the text. Set the size for the slider and the
  // color scale.
  QString text = this->Form->TableSizeText->text();
  int tableSize = text.toInt();
  this->Form->TableSize->setValue(tableSize);
  this->setTableSize(tableSize);
}

void pqColorScaleEditor::setSizeFromSlider(int tableSize)
{
  QString sizeString;
  sizeString.setNum(tableSize);
  this->Form->TableSizeText->setText(sizeString);
  this->setTableSize(tableSize);
}

void pqColorScaleEditor::setTableSize(int tableSize)
{
#if USE_VTK_TFE
  // TODO?
  this->Viewer->Render();
#else
  this->Form->Gradient->setTableSize(tableSize);
#endif

  if(this->ColorMap)
    {
    vtkSMProxy *lookupTable = this->ColorMap->getProxy();
    pqSMAdaptor::setElementProperty(
        lookupTable->GetProperty("NumberOfTableValues"), QVariant(tableSize));
    lookupTable->UpdateVTKObjects();
    this->Display->renderAllViews();
    }
}

void pqColorScaleEditor::setScalarRange(double min, double max)
{
  // Update the opacity function if volume rendering.
  this->Form->InSetColors = true;
  this->Display->setScalarOpacityRange(min, max);
  this->Form->InSetColors = false;

  // Update the color map and the rendered views.
  this->ColorMap->setScalarRange(min, max);
  this->Display->renderAllViews();
}

void pqColorScaleEditor::applyTextChanges()
{
  if(this->Form->ValueChanged)
    {
    this->Form->ValueChanged = false;
    this->setValueFromText();
    }

  if(this->Form->OpacityChanged)
    {
    this->Form->OpacityChanged = false;
    this->setOpacityFromText();
    }

  if(this->Form->SizeChanged)
    {
    this->Form->SizeChanged = false;
    this->setSizeFromText();
    }
}

void pqColorScaleEditor::setLegendVisibility(bool visible)
{
  if(visible && !this->Legend)
    {
    if(this->ColorMap)
      {
      // Create a scalar bar in the current view. Use the display to
      // set up the title.
      pqObjectBuilder *builder =
          pqApplicationCore::instance()->getObjectBuilder();
      pqRenderViewModule *renderModule = qobject_cast<pqRenderViewModule *>(
          this->Display->getViewModule(0));
      pqScalarBarDisplay *legend = builder->createScalarBarDisplay(
        this->ColorMap, renderModule);
      legend->makeTitle(this->Display);
      this->setLegend(legend);
      }
    else
      {
      qDebug() << "Error: No color map to add a color legend to.";
      }
    }

  if(this->Legend)
    {
    this->Legend->setVisible(visible);
    this->Legend->renderAllViews();
    }

  this->Form->ShowColorLegend->blockSignals(true);
  this->Form->ShowColorLegend->setChecked(this->Legend && visible);
  this->Form->ShowColorLegend->blockSignals(false);
  this->enableLegendControls(this->Legend && visible);
}

void pqColorScaleEditor::setLegendName(const QString &text)
{
  this->setLegendTitle(text, this->Form->TitleComponent->text());
}

void pqColorScaleEditor::setLegendComponent(const QString &text)
{
  this->setLegendTitle(this->Form->TitleName->text(), text);
}

void pqColorScaleEditor::setLegendTitle(const QString &name,
    const QString &component)
{
  if(this->Legend)
    {
    this->Legend->setTitle(name, component);
    this->Legend->renderAllViews();
    }
}

void pqColorScaleEditor::cleanupDisplay()
{
  this->setDisplay(0);
}

void pqColorScaleEditor::cleanupLegend()
{
  this->setLegend(0);
}

void pqColorScaleEditor::loadBuiltinColorPresets()
{
  pqColorMapModel colorMap;
  pqColorPresetModel *model = this->Form->Presets->getModel();
  colorMap.addPoint(pqChartValue((double)0.0), QColor(0, 0, 255));
  colorMap.addPoint(pqChartValue((double)1.0), QColor(255, 0, 0));
  model->addBuiltinColorMap(colorMap, "Blue to Red");

  colorMap.removeAllPoints();
  colorMap.addPoint(pqChartValue((double)0.0), QColor(255, 0, 0));
  colorMap.addPoint(pqChartValue((double)1.0), QColor(0, 0, 255));
  model->addBuiltinColorMap(colorMap, "Red to Blue");

  colorMap.removeAllPoints();
  colorMap.addPoint(pqChartValue((double)0.0), QColor(0, 0, 0));
  colorMap.addPoint(pqChartValue((double)1.0), QColor(255, 255, 255));
  model->addBuiltinColorMap(colorMap, "Grayscale");

  colorMap.removeAllPoints();
  colorMap.setColorSpace(pqColorMapModel::RgbSpace);
  colorMap.addPoint(pqChartValue((double)0.0), QColor(0, 153, 191));
  colorMap.addPoint(pqChartValue((double)1.0), QColor(196, 119, 87));
  model->addBuiltinColorMap(colorMap, "CIELab Blue to Red");
}

void pqColorScaleEditor::loadColorPoints()
{
  // Clean up the previous data.
#if USE_VTK_TFE
  vtkPiecewiseFunction *opacities = 0;
  vtkColorTransferFunction *colors = this->Viewer->GetColorFunction();
  colors->RemoveAllPoints();
  if(this->Form->HasOpacity)
    {
    opacities = this->Viewer->GetOpacityFunction();
    opacities->RemoveAllPoints();
    }
#else
  pqColorMapModel *model = this->Form->Gradient->getModel();
  model->removeAllPoints();
#endif

  if(this->ColorMap)
    {
    // Update the displayed min and max.
    QPair<double, double> range = this->ColorMap->getScalarRange();
    this->updateScalarRange(range.first, range.second);

    // Add the new data to the editor.
    QList<QVariant> list;
    vtkSMProxy *lookupTable = this->ColorMap->getProxy();
    list = pqSMAdaptor::getMultipleElementProperty(
        lookupTable->GetProperty("RGBPoints"));
    for(int i = 0; (i + 3) < list.size(); i += 4)
      {
#if USE_VTK_TFE
      colors->AddRGBPoint(list[i].toDouble(), list[i + 1].toDouble(),
          list[i + 2].toDouble(), list[i + 3].toDouble());
#else
      QColor color = QColor::fromRgbF(list[i + 1].toDouble(),
          list[i + 2].toDouble(), list[i + 3].toDouble());
      model->addPoint(pqChartValue(list[i].toDouble()), color);
#endif
      }

    if(this->Form->HasOpacity)
      {
      list = pqSMAdaptor::getMultipleElementProperty(
          this->Display->getScalarOpacityFunctionProxy()->GetProperty("Points"));
      for(int j = 0; (j + 1) < list.size(); j += 2)
        {
#if USE_VTK_TFE
        opacities->AddPoint(list[j].toDouble(), list[j + 1].toDouble());
#else
        // TODO
#endif
        }
      }
    }
  else
    {
    this->Form->MinimumLabel->setText("");
    this->Form->MaximumLabel->setText("");
    }
}

void pqColorScaleEditor::initColorScale()
{
  // Set up the component combo box.
  this->Form->Component->clear();
  if(this->Display)
    {
    int numComponents = this->Display->getColorFieldNumberOfComponents(
        this->Display->getColorField());
    this->Form->Component->setEnabled(numComponents > 1);
    this->Form->ComponentLabel->setEnabled(numComponents > 1);
    if(numComponents > 1)
      {
      this->Form->Component->addItem("Magnitude", QVariant(-1));
      if(numComponents <= 3)
        {
        const char *titles[] = {"X", "Y", "Z"};
        for(int cc = 0; cc < numComponents; cc++)
          {
          this->Form->Component->addItem(titles[cc], QVariant(cc));
          }
        }
      else
        {
        for(int cc = 0; cc < numComponents; cc++)
          {
          this->Form->Component->addItem(QString::number(cc), QVariant(cc));
          }
        }

      int index = 0;
      if(this->ColorMap->getVectorMode() == pqScalarsToColors::COMPONENT)
        {
        index = this->ColorMap->getVectorComponent() + 1;
        }

      this->Form->Component->setCurrentIndex(index);
      }
    }

  // Clear any pending changes and clear the current point index.
  this->Form->ValueChanged = false;
  this->Form->OpacityChanged = false;
  this->Form->SizeChanged = false;
  this->Form->CurrentIndex = -1;

  // Ignore changes during editor setup.
  this->Form->IgnoreEditor = true;

#if !USE_VTK_TFE
  // Notify the color map model that multiple changes will take place.
  pqColorMapModel *model = this->Form->Gradient->getModel();
  model->startModifyingData();
#endif

  // See if the display supports opacity editing.
  bool usingOpacity = this->Form->HasOpacity;
  if(this->Display)
    {
    usingOpacity = this->Display->getDisplayProxy()->GetRepresentationCM() ==
        vtkSMDataObjectDisplayProxy::VOLUME;
    }

  if(usingOpacity != this->Form->HasOpacity)
    {
    this->Form->HasOpacity = usingOpacity;
#if USE_VTK_TFE
    this->Viewer->GetColorFunction()->RemoveAllPoints();
    if(this->Form->HasOpacity)
      {
      this->Viewer->SetModificationTypeToColorAndOpacity();
      }
    else
      {
      this->Viewer->GetOpacityFunction()->RemoveAllPoints();
      this->Viewer->SetModificationTypeToColor();
      }
#else
    // TODO
#endif
    }

  if(this->Form->HasOpacity)
    {
    this->Form->Listener->Connect(
        this->Display->getScalarOpacityFunctionProxy()->GetProperty("Points"),
        vtkCommand::ModifiedEvent, this, SLOT(handlePointsChanged()));
    }

  if(this->ColorMap)
    {
    // Set up the rescale controls.
    this->Form->UseAutoRescale->blockSignals(true);
    this->Form->UseAutoRescale->setChecked(
        !this->ColorMap->getScalarRangeLock());
    this->Form->UseAutoRescale->blockSignals(false);
    this->enableRescaleControls(!this->Form->UseAutoRescale->isChecked());

    // Set up the color table size elements.
    vtkSMProxy *lookupTable = this->ColorMap->getProxy();
    int tableSize = pqSMAdaptor::getElementProperty(
      lookupTable->GetProperty("NumberOfTableValues")).toInt();
    this->Form->TableSize->blockSignals(true);
    this->Form->TableSize->setValue(tableSize);
    this->Form->TableSize->blockSignals(false);
    this->Form->TableSizeText->setText(QString::number(tableSize));

    int discretize = pqSMAdaptor::getElementProperty(
        lookupTable->GetProperty("Discretize")).toInt();
    this->Form->UseDiscreteColors->blockSignals(true);
    this->Form->UseDiscreteColors->setChecked(discretize != 0);
    this->Form->UseDiscreteColors->blockSignals(false);
    this->enableResolutionControls(this->Form->UseDiscreteColors->isChecked());
#if USE_VTK_TFE
    //this->Viewer->SetTableSize(tableSize); // TODO?
#else
    if(!this->Form->UseDiscreteColors->isChecked())
      {
      tableSize = 0;
      }

    this->Form->Gradient->setTableSize(tableSize);
#endif

    // Set up the color space combo box.
    int space = pqSMAdaptor::getElementProperty(
        lookupTable->GetProperty("ColorSpace")).toInt();
    this->Form->ColorSpace->setCurrentIndex(space);
    if(pqSMAdaptor::getElementProperty(
        lookupTable->GetProperty("HSVWrap")).toInt())
      {
      this->Form->ColorSpace->setCurrentIndex(2);
      }

#if USE_VTK_TFE
    this->Viewer->SetColorSpace(this->Form->ColorSpace->currentIndex());
#else
    model->setColorSpaceFromInt(this->Form->ColorSpace->currentIndex());
#endif

    // Set up the log scale checkbox. If the log scale is not valid
    // because of the range, loadColorPoints will clear the flag.
    this->Form->UseLogScale->blockSignals(true);
    this->Form->UseLogScale->setChecked(pqSMAdaptor::getElementProperty(
        lookupTable->GetProperty("UseLogScale")).toInt() != 0);
    this->Form->UseLogScale->blockSignals(false);

    // Set the log scale flag on the editor.
#if USE_VTK_TFE
    this->Viewer->GetColorFunction()->SetScale(
        this->Form->UseLogScale->isChecked() ? VTK_CTF_LOG10 : VTK_CTF_LINEAR);
#else
    // TODO
#endif
    }

  // Load the new color points into the editor.
  this->loadColorPoints();

#if USE_VTK_TFE
  this->Viewer->Render();

  // Set the current point.
  this->Viewer->SetCurrentElementId(0);
  this->Form->CurrentIndex = this->Viewer->GetCurrentElementId();
#else
  model->finishModifyingData();

  // Set the current point.
  this->Form->Gradient->blockSignals(true);
  this->Form->Gradient->setCurrentPoint(0);
  this->Form->Gradient->blockSignals(false);
  this->Form->CurrentIndex = this->Form->Gradient->getCurrentPoint();
#endif

  // Update the displayed current point index.
  this->Form->IgnoreEditor = false;
  this->enablePointControls();
  this->updatePointValues();
}

void pqColorScaleEditor::enablePointControls()
{
  bool enable = this->Form->CurrentIndex != -1;
  this->Form->OpacityLabel->setEnabled(this->Form->HasOpacity);
  this->Form->Opacity->setEnabled(this->Form->HasOpacity && enable);

  // The endpoint values are not editable if auto rescale is on.
  if(enable && this->Form->UseAutoRescale->isChecked())
    {
    enable = this->Form->CurrentIndex > 0;
#if USE_VTK_TFE
    vtkColorTransferFunction *colors = this->Viewer->GetColorFunction();
    enable = enable && this->Form->CurrentIndex < colors->GetSize() - 1;
#else
    pqColorMapModel *model = this->Form->Gradient->getModel();
    enable = enable &&
        this->Form->CurrentIndex < model->getNumberOfPoints() - 1;
#endif
    }

  this->Form->ScalarValue->setEnabled(enable);
}

void pqColorScaleEditor::updatePointValues()
{
  if(this->Form->CurrentIndex == -1)
    {
    this->Form->ScalarValue->setText("");
    this->Form->Opacity->setText("");
    }
  else
    {
#if USE_VTK_TFE
    double value = this->Viewer->GetElementScalar(this->Form->CurrentIndex);
    this->Form->ScalarValue->setText(QString::number(value, 'g', 6));
    if(this->Form->HasOpacity)
      {
      double opacity = this->Viewer->GetElementOpacity(
          this->Form->CurrentIndex);
      this->Form->Opacity->setText(QString::number(opacity, 'g', 6));
      }
    else
      {
      this->Form->Opacity->setText("");
      }
#else
    pqChartValue value;
    pqColorMapModel *model = this->Form->Gradient->getModel();
    model->getPointValue(this->Form->CurrentIndex, value);
    this->Form->ScalarValue->setText(
        QString::number(value.getDoubleValue(), 'g', 6));
    if(this->Form->HasOpacity)
      {
      pqChartValue opacity;
      model->getPointOpacity(this->Form->CurrentIndex, opacity);
      this->Form->Opacity->setText(
          QString::number(opacity.getDoubleValue(), 'g', 6));
      }
    else
      {
      this->Form->Opacity->setText("");
      }
#endif
    }
}

void pqColorScaleEditor::enableRescaleControls(bool enable)
{
  this->Form->RescaleButton->setEnabled(enable);
}

void pqColorScaleEditor::enableResolutionControls(bool enable)
{
  this->Form->TableSizeLabel->setEnabled(enable);
  this->Form->TableSize->setEnabled(enable);
  this->Form->TableSizeText->setEnabled(enable);
}

void pqColorScaleEditor::updateScalarRange(double min, double max)
{
  // Update the spin box ranges and set the values.
  this->Form->MinimumLabel->setText(QString::number(min, 'g', 6));
  this->Form->MaximumLabel->setText(QString::number(max, 'g', 6));

#if USE_VTK_TFE
  // Update the editor scalar range.
  this->Viewer->SetWholeScalarRange(min, max);
  this->Viewer->SetVisibleScalarRange(min, max);
#endif

  // Check the range for log scale.
  this->Form->UseLogScale->setEnabled(min > 0 || max < 0);
  if(this->Form->UseLogScale->isChecked() &&
      !this->Form->UseLogScale->isEnabled())
    {
    // Clear the log scale flag on the editor and proxy.
    this->Form->UseLogScale->setChecked(false);
    this->setLogScale(false);
    }
}

void pqColorScaleEditor::setLegend(pqScalarBarDisplay *legend)
{
  if(this->Legend == legend)
    {
    return;
    }

  if(this->Legend)
    {
    // Clean up the current connections.
    this->disconnect(this->Legend, 0, this, 0);
    this->Form->Links.removeAllPropertyLinks();
    }

  this->Legend = legend;
  if(this->Legend)
    {
    this->connect(this->Legend, SIGNAL(destroyed(QObject *)),
        this, SLOT(cleanupLegend()));

    // Connect the legend controls.
    vtkSMProxy *proxy = this->Legend->getProxy();
    this->Form->Links.addPropertyLink(this->Form->TitleColorAdaptor, 
        "color", SIGNAL(colorChanged(const QVariant&)),
        proxy, proxy->GetProperty("TitleColor"));
    this->Form->Links.addPropertyLink(this->Form->TitleFontAdaptor,
        "currentText", SIGNAL(currentTextChanged(const QString&)),
        proxy, proxy->GetProperty("TitleFontFamily"));
    this->Form->Links.addPropertyLink(
        this->Form->TitleBold, "checked", SIGNAL(toggled(bool)),
        proxy, proxy->GetProperty("TitleBold"));
    this->Form->Links.addPropertyLink(
        this->Form->TitleItalic, "checked", SIGNAL(toggled(bool)),
        proxy, proxy->GetProperty("TitleItalic"));
    this->Form->Links.addPropertyLink(
        this->Form->TitleShadow, "checked", SIGNAL(toggled(bool)),
        proxy, proxy->GetProperty("TitleShadow"));   
    this->Form->Links.addPropertyLink(
        this->Form->TitleOpacity, "value", SIGNAL(valueChanged(double)),
        proxy, proxy->GetProperty("TitleOpacity"));

    this->Form->Links.addPropertyLink(
        this->Form->LabelFormat, "text", SIGNAL(textChanged(const QString&)),
        proxy, proxy->GetProperty("LabelFormat"));   
    this->Form->Links.addPropertyLink(this->Form->LabelColorAdaptor, 
        "color", SIGNAL(colorChanged(const QVariant&)),
        proxy, proxy->GetProperty("LabelColor"));
    this->Form->Links.addPropertyLink(this->Form->LabelFontAdaptor,
        "currentText", SIGNAL(currentTextChanged(const QString&)),
        proxy, proxy->GetProperty("LabelFontFamily"));
    this->Form->Links.addPropertyLink(
        this->Form->LabelBold, "checked", SIGNAL(toggled(bool)),
        proxy, proxy->GetProperty("LabelBold"));
    this->Form->Links.addPropertyLink(
        this->Form->LabelItalic, "checked", SIGNAL(toggled(bool)),
        proxy, proxy->GetProperty("LabelItalic"));
    this->Form->Links.addPropertyLink(
        this->Form->LabelShadow, "checked", SIGNAL(toggled(bool)),
        proxy, proxy->GetProperty("LabelShadow"));   
    this->Form->Links.addPropertyLink(
        this->Form->LabelOpacity, "value", SIGNAL(valueChanged(double)),
        proxy, proxy->GetProperty("LabelOpacity"));

    this->Form->Links.addPropertyLink(this->Form->NumberOfLabels,
        "value", SIGNAL(valueChanged(int)),
        proxy, proxy->GetProperty("NumberOfLabels"));

    // Update the legend title gui.
    QPair<QString, QString> title = this->Legend->getTitle();
    this->Form->TitleName->blockSignals(true);
    this->Form->TitleName->setText(title.first);
    this->Form->TitleName->blockSignals(false);

    this->Form->TitleComponent->blockSignals(true);
    this->Form->TitleComponent->setText(title.second);
    this->Form->TitleComponent->blockSignals(false);
    }

  bool showing = this->Legend && this->Legend->isVisible();
  this->Form->ShowColorLegend->blockSignals(true);
  this->Form->ShowColorLegend->setChecked(showing);
  this->Form->ShowColorLegend->blockSignals(false);
  this->enableLegendControls(showing);
}

void pqColorScaleEditor::enableLegendControls(bool enable)
{
  this->Form->TitleFrame->setEnabled(enable);
  this->Form->LabelFrame->setEnabled(enable);
  this->Form->NumberOfLabels->setEnabled(enable);
  this->Form->CountLabel->setEnabled(enable);
}


