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

  Copyright (c) Kitware, Inc.
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/VolViewCopyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

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

#include "vtkVVInteractorWidgetSelector.h"

#include "vtkAbstractWidget.h"
#include "vtkAngleRepresentation2D.h"
#include "vtkAxisActor2D.h"
#include "vtkBiDimensionalRepresentation2D.h"
#include "vtkCaptionActor2D.h"
#include "vtkCaptionRepresentation.h"
#include "vtkCommand.h"
#include "vtkContourStatistics.h"
#include "vtkDistanceRepresentation2D.h"
#include "vtkImageActor.h"
#include "vtkImageActorPointHandleRepresentation3D.h"
#include "vtkImageData.h"
#include "vtkLeaderActor2D.h"
#include "vtkObjectFactory.h"
#include "vtkOrientedGlyphContourRepresentation.h"
#include "vtkOrientedGlyphFocalPlaneContourRepresentation.h"
#include "vtkPointHandleRepresentation3D.h"
#include "vtkProperty.h"
#include "vtkProperty2D.h"
#include "vtkStringArray.h"
#include "vtkTextProperty.h"

#include "vtkKWAngleWidget.h"
#include "vtkKWCheckButton.h"
#include "vtkKWBiDimensionalWidget.h"
#include "vtkKWCaptionWidget.h"
#include "vtkKWComboBox.h"
#include "vtkKWContourWidget.h"
#include "vtkKWDistanceWidget.h"
#include "vtkKWEvent.h"
#include "vtkKWIcon.h"
#include "vtkKWImageMapToWindowLevelColors.h"
#include "vtkKWImageWidget.h"
#include "vtkKWInternationalization.h"
#include "vtkKWMultiColumnList.h"
#include "vtkKWMultiColumnListWithScrollbars.h"
#include "vtkKWProbeImageWidget.h"
#include "vtkKWPushButton.h"
#include "vtkKWPushButtonSet.h"
#include "vtkKWRenderWidgetPro.h"
#include "vtkKWTextPropertyEditor.h"
#include "vtkKWToolbar.h"
#include "vtkKWVolumeWidget.h"

#include "vtkKWEPaintbrushWidget.h"
#include "vtkKWEPaintbrushRepresentation2D.h"
#include "vtkKWEPaintbrushDrawing.h"


#include "vtkVVHandleWidget.h"
#include "vtkVVSelectionFrame.h"
#include "vtkVVWindowBase.h"

#include <vtksys/stl/string>

// TESTING

#include "vtkKWInteractorStyle2DView.h"

//----------------------------------------------------------------------------
vtkStandardNewMacro(vtkVVInteractorWidgetSelector);
vtkCxxRevisionMacro(vtkVVInteractorWidgetSelector, "$Revision: 1.69 $");

//----------------------------------------------------------------------------
class vtkVVInteractorWidgetSelectorInternals
{
public:
  vtksys_stl::string InteractorTypeColumnName;
  vtksys_stl::string InteractionValueColumnName;
  vtksys_stl::string VisibilityColumnName;
  vtksys_stl::string ColorColumnName;
  vtksys_stl::string LockColumnName;

  vtksys_stl::string DistanceWidgetButtonLabel;
  vtksys_stl::string DistanceWidgetButtonBalloonHelp;

  vtksys_stl::string BiDimensionalWidgetButtonLabel;
  vtksys_stl::string BiDimensionalWidgetButtonBalloonHelp;

  vtksys_stl::string AngleWidgetButtonLabel;
  vtksys_stl::string AngleWidgetButtonBalloonHelp;

  vtksys_stl::string ContourWidgetButtonLabel;
  vtksys_stl::string ContourWidgetButtonBalloonHelp;

  vtksys_stl::string Label2DWidgetButtonLabel;
  vtksys_stl::string Label2DWidgetButtonBalloonHelp;

  vtksys_stl::string HandleWidgetButtonLabel;
  vtksys_stl::string HandleWidgetButtonBalloonHelp;

  vtksys_stl::string PaintbrushWidgetButtonLabel;
  vtksys_stl::string PaintbrushWidgetButtonBalloonHelp;
};

//----------------------------------------------------------------------------
vtkVVInteractorWidgetSelector::vtkVVInteractorWidgetSelector()
{
  this->Internals = new vtkVVInteractorWidgetSelectorInternals;

  this->Internals->VisibilityColumnName = "Visibility";
  this->Internals->ColorColumnName  = "Color";
  this->Internals->LockColumnName  = "Lock";
  this->Internals->InteractorTypeColumnName = "Type";
  this->Internals->InteractionValueColumnName  = "Value";

  this->Internals->DistanceWidgetButtonLabel = ks_("Measurement|Distance");
  this->Internals->DistanceWidgetButtonBalloonHelp = 
    k_("Add a distance measurement");

  this->Internals->BiDimensionalWidgetButtonLabel = 
    ks_("Measurement|Bi-Dimensional");
  this->Internals->BiDimensionalWidgetButtonBalloonHelp = 
    k_("Add a bi-dimensional measurement");

  this->Internals->AngleWidgetButtonLabel    = ks_("Measurement|Angle");
  this->Internals->AngleWidgetButtonBalloonHelp = 
    k_("Add an angle measurement");

  this->Internals->ContourWidgetButtonLabel  = ks_("Measurement|Contour");
  this->Internals->ContourWidgetButtonBalloonHelp  = 
    k_("Add a contour measurement");

  this->Internals->Label2DWidgetButtonLabel  = ks_("Measurement|2D Label");
  this->Internals->Label2DWidgetButtonBalloonHelp  = 
    k_("Add a 2D Label");

  this->Internals->HandleWidgetButtonLabel = ks_("Measurement|Handle");
  this->Internals->HandleWidgetButtonBalloonHelp = 
    k_("Add a marker/seed");
  
  this->Internals->PaintbrushWidgetButtonLabel = 
    ks_("Measurement|Paintbrush");
  this->Internals->PaintbrushWidgetButtonBalloonHelp = 
    k_("Add a paintbrush segmentation");

  this->PresetAddDefaultInteractorCommand          = NULL;
  this->PresetDefaultInteractorIsSupportedCommand  = NULL;
  this->PresetUpdateInteractorWidgetPropertiesCommand = NULL;
  this->InteractorWidgetProperties                    = NULL;
  this->ContourStatistics                         = vtkContourStatistics::New();
  this->Window                                     = NULL;

  // Tools visibility.. default to on

  this->DistanceWidgetVisibility       = 1;
  this->AngleWidgetVisibility          = 1;
  this->BiDimensionalWidgetVisibility  = 1;
  this->ContourWidgetVisibility        = 1;
  this->Label2DWidgetVisibility        = 1;
  this->HandleWidgetVisibility         = 1;
  this->PaintbrushWidgetVisibility     = 1;
}

//----------------------------------------------------------------------------
vtkVVInteractorWidgetSelector::~vtkVVInteractorWidgetSelector()
{
  delete this->Internals;
  this->Internals = NULL;

  if (this->PresetAddDefaultInteractorCommand)
    {
    delete [] this->PresetAddDefaultInteractorCommand;
    this->PresetAddDefaultInteractorCommand = NULL;
    }

  if (this->PresetDefaultInteractorIsSupportedCommand)
    {
    delete [] this->PresetDefaultInteractorIsSupportedCommand;
    this->PresetDefaultInteractorIsSupportedCommand = NULL;
    }

  if (this->PresetUpdateInteractorWidgetPropertiesCommand)
    {
    delete [] this->PresetUpdateInteractorWidgetPropertiesCommand;
    this->PresetUpdateInteractorWidgetPropertiesCommand = NULL;
    }

  if (this->InteractorWidgetProperties)
    {
    this->InteractorWidgetProperties->Delete();
    this->InteractorWidgetProperties = NULL;
    }

  // Delete all presets

  // We do not have much choice here but to call DeleteAllPresets(), even
  // though it is done in the destructor of the superclass too. The problem
  // with this code is that we override the virtual function DeAllocatePreset()
  // which is used by DeleteAllPresets(). At the time it is called by
  // the superclass, the virtual table of the subclass is gone, and
  // our DeAllocatePreset() is never called.

  this->DeleteAllPresets();

  if(this->ContourStatistics)
    {
    this->ContourStatistics->Delete();
    this->ContourStatistics = NULL;
    }
}

//----------------------------------------------------------------------------
void vtkVVInteractorWidgetSelector::DeAllocatePreset(int id)
{
  this->Superclass::DeAllocatePreset(id);

  this->SetPresetSelectionFrame(id, NULL);
  this->SetPresetInteractorWidget(id, NULL);
}

//----------------------------------------------------------------------------
int vtkVVInteractorWidgetSelector::SetPresetInteractorWidget(
  int id, vtkAbstractWidget *ptr)
{
  if (this->HasPreset(id))
    {
    vtkAbstractWidget *prev_ptr = (vtkAbstractWidget*)
      this->GetPresetUserSlotAsPointer(id, "InteractorWidget");
    if (prev_ptr == ptr)
      {
      return 1;
      }
    if (prev_ptr)
      {
      vtkVVSelectionFrame::RemoveInteractorWidgetObservers(this, prev_ptr);
      prev_ptr->UnRegister(this);
      }
    this->SetPresetUserSlotAsPointer(id, "InteractorWidget", ptr);
    if (ptr)
      {
      ptr->Register(this);
      vtkVVSelectionFrame::AddInteractorWidgetObservers(this, ptr);
      }
    return 1;
    }

  return 0;
}

//----------------------------------------------------------------------------
vtkAbstractWidget* vtkVVInteractorWidgetSelector::GetPresetInteractorWidget(
  int id)
{
  return (vtkAbstractWidget*)
    this->GetPresetUserSlotAsPointer(id, "InteractorWidget");
}

//----------------------------------------------------------------------------
int vtkVVInteractorWidgetSelector::SetPresetSelectionFrame(
  int id, vtkVVSelectionFrame *ptr)
{
  if (this->HasPreset(id))
    {
    vtkVVSelectionFrame *prev_ptr = (vtkVVSelectionFrame*)
      this->GetPresetUserSlotAsPointer(id, "SelectionFrame");
    if (prev_ptr == ptr)
      {
      return 1;
      }
    if (prev_ptr)
      {
      vtkKWProbeImageWidget *pw = vtkKWProbeImageWidget::SafeDownCast( 
                                          prev_ptr->GetRenderWidget());
      if (pw)
        {
        this->RemoveCallbackCommandObserver(
          pw, vtkKWEvent::ProbeImageTiltPlaneEvent);
        this->RemoveCallbackCommandObserver(
          pw, vtkKWEvent::ProbeImageTranslatePlaneEvent);
        this->RemoveCallbackCommandObserver(
          pw, vtkKWEvent::ProbeImageRollPlaneEvent);
        }
      vtkKWImageWidget *iw = 
        vtkKWImageWidget::SafeDownCast(prev_ptr->GetRenderWidget());
      if (iw && !pw) 
        {
        this->RemoveCallbackCommandObserver(
          iw, vtkKWEvent::ImageSliceChangedEvent);
        }
      prev_ptr->UnRegister(this);
      }
    this->SetPresetUserSlotAsPointer(id, "SelectionFrame", ptr);
    if (ptr)
      {
      ptr->Register(this);
      vtkKWProbeImageWidget *pw = vtkKWProbeImageWidget::SafeDownCast( 
                                          ptr->GetRenderWidget());
      if (pw)
        {
        this->AddCallbackCommandObserver(
          pw, vtkKWEvent::ProbeImageTiltPlaneEvent);
        this->AddCallbackCommandObserver(
          pw, vtkKWEvent::ProbeImageTranslatePlaneEvent);
        this->AddCallbackCommandObserver(
          pw, vtkKWEvent::ProbeImageRollPlaneEvent);
        }
      vtkKWImageWidget *iw = 
        vtkKWImageWidget::SafeDownCast(ptr->GetRenderWidget());
      if ( iw && 
          !pw ) // No point adding ImageSliceChangedEvent to probe widget
        {
        this->AddCallbackCommandObserver(
          iw, vtkKWEvent::ImageSliceChangedEvent);
        }
      }
    return 1;
    }

  return 0;
}

//----------------------------------------------------------------------------
vtkVVSelectionFrame* vtkVVInteractorWidgetSelector::GetPresetSelectionFrame(
  int id)
{
  return (vtkVVSelectionFrame*)
    this->GetPresetUserSlotAsPointer(id, "SelectionFrame");
}

//----------------------------------------------------------------------------
void vtkVVInteractorWidgetSelector::CreateWidget()
{
  // Check if already created

  if (this->IsCreated())
    {
    vtkErrorMacro(<< this->GetClassName() << " already created");
    return;
    }

  // Call the superclass to create the whole widget

  this->Superclass::CreateWidget();

  // --------------------------------------------------------------
  // Interactor Widget Details

  if (!this->InteractorWidgetProperties)
    {
    this->InteractorWidgetProperties = 
      vtkKWMultiColumnListWithScrollbars::New();
    }

  this->InteractorWidgetProperties->SetParent(this);
  this->InteractorWidgetProperties->Create();
  this->InteractorWidgetProperties->HorizontalScrollbarVisibilityOff();

  vtkKWMultiColumnList *list = this->InteractorWidgetProperties->GetWidget();
  list->ColumnSeparatorsVisibilityOn();
  list->SetHeight(7);

  int col;

  col = list->AddColumn(ks_("Measurement Details|Property"));
  list->SetColumnWidth(col, 20);
  list->SetColumnResizable(col, 1);
  list->SetColumnStretchable(col, 0);
  list->SetColumnEditable(col, 0);

  col = list->AddColumn(ks_("Measurement Details|Value"));
  list->SetColumnResizable(col, 1);
  list->SetColumnStretchable(col, 1);
  list->SetColumnEditable(col, 0);
  list->SetColumnFormatCommandToEmptyOutputIfWindowCommand(col);
}

//----------------------------------------------------------------------------
void vtkVVInteractorWidgetSelector::CreateToolbarPresetButtons(
  vtkKWToolbar *toolbar, int use_separators)
{
  this->Superclass::CreateToolbarPresetButtons(toolbar,use_separators);
  
  if (!toolbar)
    {
    return;
    }

  char command[256];
  vtkKWPushButton *toolbar_pb;
  vtkKWWidget *toolbar_add_pb = 
    toolbar->GetWidget(this->GetAddButtonLabel());

  // Distance widget

  toolbar_pb = vtkKWPushButton::New();
  toolbar_pb->SetParent(toolbar->GetFrame());
  toolbar_pb->Create();
  toolbar_pb->SetText(this->Internals->DistanceWidgetButtonLabel.c_str());
  sprintf(command, "InteractorWidgetAddCallback %d", 
          vtkVVInteractorWidgetSelector::DistanceWidget);
  toolbar_pb->SetCommand(this, command);
  toolbar->InsertWidget(toolbar_add_pb, toolbar_pb);
  toolbar_pb->Delete();

  // Bi-Dimensional widget

  toolbar_pb = vtkKWPushButton::New();
  toolbar_pb->SetParent(toolbar->GetFrame());
  toolbar_pb->Create();
  toolbar_pb->SetText(this->Internals->BiDimensionalWidgetButtonLabel.c_str());
  sprintf(command, "InteractorWidgetAddCallback %d", 
          vtkVVInteractorWidgetSelector::BiDimensionalWidget);
  toolbar_pb->SetCommand(this, command);
  toolbar->InsertWidget(toolbar_add_pb, toolbar_pb);
  toolbar_pb->Delete();

  // Angle widget

  toolbar_pb = vtkKWPushButton::New();
  toolbar_pb->SetParent(toolbar->GetFrame());
  toolbar_pb->Create();
  toolbar_pb->SetText(this->Internals->AngleWidgetButtonLabel.c_str());
  sprintf(command, "InteractorWidgetAddCallback %d", 
          vtkVVInteractorWidgetSelector::AngleWidget);
  toolbar_pb->SetCommand(this, command);
  toolbar->InsertWidget(toolbar_add_pb, toolbar_pb);
  toolbar_pb->Delete();

  // Contour widget

  toolbar_pb = vtkKWPushButton::New();
  toolbar_pb->SetParent(toolbar->GetFrame());
  toolbar_pb->Create();
  toolbar_pb->SetText(this->Internals->ContourWidgetButtonLabel.c_str());
  sprintf(command, "InteractorWidgetAddCallback %d", 
          vtkVVInteractorWidgetSelector::ContourWidget);
  toolbar_pb->SetCommand(this, command);
  toolbar->InsertWidget(toolbar_add_pb, toolbar_pb);
  toolbar_pb->Delete();

  // Label2D widget

  toolbar_pb = vtkKWPushButton::New();
  toolbar_pb->SetParent(toolbar->GetFrame());
  toolbar_pb->Create();
  toolbar_pb->SetText(this->Internals->Label2DWidgetButtonLabel.c_str());
  sprintf(command, "InteractorWidgetAddCallback %d", 
          vtkVVInteractorWidgetSelector::Label2DWidget);
  toolbar_pb->SetCommand(this, command);
  toolbar->InsertWidget(toolbar_add_pb, toolbar_pb);
  toolbar_pb->Delete();

  // Handle widget

  toolbar_pb = vtkKWPushButton::New();
  toolbar_pb->SetParent(toolbar->GetFrame());
  toolbar_pb->Create();
  toolbar_pb->SetText(this->Internals->HandleWidgetButtonLabel.c_str());
  sprintf(command, "InteractorWidgetAddCallback %d", 
          vtkVVInteractorWidgetSelector::HandleWidget);
  toolbar_pb->SetCommand(this, command);
  toolbar->InsertWidget(toolbar_add_pb, toolbar_pb);
  toolbar_pb->Delete();

  // Paintbrush widget

  toolbar_pb = vtkKWPushButton::New();
  toolbar_pb->SetParent(toolbar->GetFrame());
  toolbar_pb->Create();
  toolbar_pb->SetText(this->Internals->PaintbrushWidgetButtonLabel.c_str());
  sprintf(command, "InteractorWidgetAddCallback %d", 
          vtkVVInteractorWidgetSelector::PaintbrushWidget);
  toolbar_pb->SetCommand(this, command);
  toolbar->InsertWidget(toolbar_add_pb, toolbar_pb);
  toolbar_pb->Delete();
}

//---------------------------------------------------------------------------
void vtkVVInteractorWidgetSelector::UpdateToolbarPresetButtons(vtkKWToolbar *toolbar)
{
  this->Superclass::UpdateToolbarPresetButtons(toolbar);

  if (!toolbar)
    {
    return;
    }

  int has_add_command = (this->PresetAddDefaultInteractorCommand && 
                     *this->PresetAddDefaultInteractorCommand);

  int supported;
  int all_defined = this->ArePresetInteractorWidgetsDefined();

  vtkKWPushButton *toolbar_pb;

  // Distance widget

  toolbar_pb = vtkKWPushButton::SafeDownCast(
    toolbar->GetWidget(
      this->Internals->DistanceWidgetButtonLabel.c_str()));
  if (toolbar_pb)
    {
    supported = this->InvokePresetDefaultInteractorIsSupportedCommand(
      vtkVVInteractorWidgetSelector::DistanceWidget);
    toolbar->SetWidgetVisibility(
      toolbar_pb, 
      this->DistanceWidgetVisibility && has_add_command);
    toolbar_pb->SetEnabled(
      has_add_command && supported && all_defined ? this->GetEnabled() : 0);
    }

  // BiDimensional widget

  toolbar_pb = vtkKWPushButton::SafeDownCast(
    toolbar->GetWidget(
      this->Internals->BiDimensionalWidgetButtonLabel.c_str()));
  if (toolbar_pb)
    {
    supported = this->InvokePresetDefaultInteractorIsSupportedCommand(
      vtkVVInteractorWidgetSelector::BiDimensionalWidget);
    toolbar->SetWidgetVisibility(
      toolbar_pb, 
      this->BiDimensionalWidgetVisibility && has_add_command);
    toolbar_pb->SetEnabled(
      has_add_command && supported && all_defined ? this->GetEnabled() : 0);
    }

  // Angle widget

  toolbar_pb = vtkKWPushButton::SafeDownCast(
    toolbar->GetWidget(
      this->Internals->AngleWidgetButtonLabel.c_str()));    
  if (toolbar_pb)
    {
    supported = this->InvokePresetDefaultInteractorIsSupportedCommand(
      vtkVVInteractorWidgetSelector::AngleWidget);
    toolbar->SetWidgetVisibility(
      toolbar_pb, 
      this->AngleWidgetVisibility && has_add_command);
    toolbar_pb->SetEnabled(
      has_add_command && supported && all_defined ? this->GetEnabled() : 0);
    }

  // Contour widget

  toolbar_pb = vtkKWPushButton::SafeDownCast(
    toolbar->GetWidget(
      this->Internals->ContourWidgetButtonLabel.c_str()));
  if (toolbar_pb)
    {
    supported = this->InvokePresetDefaultInteractorIsSupportedCommand(
      vtkVVInteractorWidgetSelector::ContourWidget);
    toolbar->SetWidgetVisibility(
      toolbar_pb, 
      this->ContourWidgetVisibility && has_add_command);
    toolbar_pb->SetEnabled(
      has_add_command && supported && all_defined ? this->GetEnabled() : 0);
    }
  
  // Label2D widget

  toolbar_pb = vtkKWPushButton::SafeDownCast(
    toolbar->GetWidget(
      this->Internals->Label2DWidgetButtonLabel.c_str()));
  if (toolbar_pb)
    {
    supported = this->InvokePresetDefaultInteractorIsSupportedCommand(
      vtkVVInteractorWidgetSelector::Label2DWidget);
    toolbar->SetWidgetVisibility(
      toolbar_pb, 
      this->Label2DWidgetVisibility && has_add_command);
    toolbar_pb->SetEnabled(
      has_add_command && supported && all_defined ? this->GetEnabled() : 0);
    }

  // Handle widget

  toolbar_pb = vtkKWPushButton::SafeDownCast(
    toolbar->GetWidget(
      this->Internals->HandleWidgetButtonLabel.c_str()));
  if (toolbar_pb)
    {
    supported = this->InvokePresetDefaultInteractorIsSupportedCommand(
      vtkVVInteractorWidgetSelector::HandleWidget);
    toolbar->SetWidgetVisibility(
      toolbar_pb, 
      this->HandleWidgetVisibility && has_add_command);
    toolbar_pb->SetEnabled(
      has_add_command && supported && all_defined ? this->GetEnabled() : 0);
    }

  // Paintbrush widget

  toolbar_pb = vtkKWPushButton::SafeDownCast(
    toolbar->GetWidget(
      this->Internals->PaintbrushWidgetButtonLabel.c_str()));
  if (toolbar_pb)
    {
    supported = this->InvokePresetDefaultInteractorIsSupportedCommand(
      vtkVVInteractorWidgetSelector::PaintbrushWidget);
    toolbar->SetWidgetVisibility(
      toolbar_pb, 
      this->PaintbrushWidgetVisibility && has_add_command);
    toolbar_pb->SetEnabled(
      has_add_command && supported && all_defined ? this->GetEnabled() : 0);
    }
}

//----------------------------------------------------------------------------
void vtkVVInteractorWidgetSelector::SetToolbarPresetButtonsIcons(vtkKWToolbar *toolbar)
{
  this->Superclass::SetToolbarPresetButtonsIcons(toolbar);

  if (!toolbar)
    {
    return;
    }

  vtkKWPushButton *toolbar_pb;

  // Distance widget

  toolbar_pb = vtkKWPushButton::SafeDownCast(
    toolbar->GetWidget(
      this->Internals->DistanceWidgetButtonLabel.c_str()));
  if (toolbar_pb)
    {
    toolbar_pb->SetImageToPredefinedIcon(vtkKWIcon::IconDistanceTool);
    }
  
  // BiDimensional widget

  toolbar_pb = vtkKWPushButton::SafeDownCast(
    toolbar->GetWidget(
      this->Internals->BiDimensionalWidgetButtonLabel.c_str()));
  if (toolbar_pb)
    {
    toolbar_pb->SetImageToPredefinedIcon(vtkKWIcon::IconBiDimensionalTool);
    }
  
  // Angle widget

  toolbar_pb = vtkKWPushButton::SafeDownCast(
    toolbar->GetWidget(
      this->Internals->AngleWidgetButtonLabel.c_str()));
  if (toolbar_pb)
    {
    toolbar_pb->SetImageToPredefinedIcon(vtkKWIcon::IconAngleTool);
    }

  // Contour widget

  toolbar_pb = vtkKWPushButton::SafeDownCast(
    toolbar->GetWidget(
      this->Internals->ContourWidgetButtonLabel.c_str()));
  if (toolbar_pb)
    {
    toolbar_pb->SetImageToPredefinedIcon(vtkKWIcon::IconContourTool);
    }

  // Label2D widget

  toolbar_pb = vtkKWPushButton::SafeDownCast(
    toolbar->GetWidget(
      this->Internals->Label2DWidgetButtonLabel.c_str()));
  if (toolbar_pb)
    {
    toolbar_pb->SetImageToPredefinedIcon(vtkKWIcon::IconPointFinger);
    }

  // Handle widget

  toolbar_pb = vtkKWPushButton::SafeDownCast(
    toolbar->GetWidget(
      this->Internals->HandleWidgetButtonLabel.c_str()));
  if (toolbar_pb)
    {
    toolbar_pb->SetImageToPredefinedIcon(vtkKWIcon::IconSeedTool);
    }  

  // Paintbrush widget

  toolbar_pb = vtkKWPushButton::SafeDownCast(
    toolbar->GetWidget(
      this->Internals->PaintbrushWidgetButtonLabel.c_str()));
  if (toolbar_pb)
    {
    toolbar_pb->SetImageToPredefinedIcon(vtkKWIcon::IconSilkPaintbrush);
    }
}

//----------------------------------------------------------------------------
void vtkVVInteractorWidgetSelector::SetToolbarPresetButtonsHelpStrings(vtkKWToolbar *toolbar)
{
  this->Superclass::SetToolbarPresetButtonsHelpStrings(toolbar);

  if (!toolbar)
    {
    return;
    }

  vtkKWPushButton *toolbar_pb;

  toolbar_pb = vtkKWPushButton::SafeDownCast(
    toolbar->GetWidget(this->GetAddButtonLabel()));
  if (toolbar_pb)
    {
    toolbar_pb->SetBalloonHelpString(
      k_("Add a measurement"));
    }

  toolbar_pb = vtkKWPushButton::SafeDownCast(
    toolbar->GetWidget(this->GetRemoveButtonLabel()));
  if (toolbar_pb)
    {
    toolbar_pb->SetBalloonHelpString(
      k_("Delete the selected measurement"));
    }

  // Distance widget

  toolbar_pb = vtkKWPushButton::SafeDownCast(
    toolbar->GetWidget(
      this->Internals->DistanceWidgetButtonLabel.c_str()));
  if (toolbar_pb)
    {
    toolbar_pb->SetBalloonHelpString(
      this->Internals->DistanceWidgetButtonBalloonHelp.c_str());
    }
  
  // BiDimensional widget

  toolbar_pb = vtkKWPushButton::SafeDownCast(
    toolbar->GetWidget(
      this->Internals->BiDimensionalWidgetButtonLabel.c_str()));
  if (toolbar_pb)
    {
    toolbar_pb->SetBalloonHelpString(
      this->Internals->BiDimensionalWidgetButtonBalloonHelp.c_str());
    }
  
  // Angle widget

  toolbar_pb = vtkKWPushButton::SafeDownCast(
    toolbar->GetWidget(
      this->Internals->AngleWidgetButtonLabel.c_str()));    
  if (toolbar_pb)
    {
    toolbar_pb->SetBalloonHelpString(
      this->Internals->AngleWidgetButtonBalloonHelp.c_str());
    }

  // Contour widget

  toolbar_pb = vtkKWPushButton::SafeDownCast(
    toolbar->GetWidget(
      this->Internals->ContourWidgetButtonLabel.c_str()));
  if (toolbar_pb)
    {
    toolbar_pb->SetBalloonHelpString(
      this->Internals->ContourWidgetButtonBalloonHelp.c_str());
    }

  // Label2D widget

  toolbar_pb = vtkKWPushButton::SafeDownCast(
    toolbar->GetWidget(
      this->Internals->Label2DWidgetButtonLabel.c_str()));
  if (toolbar_pb)
    {
    toolbar_pb->SetBalloonHelpString(
      this->Internals->Label2DWidgetButtonBalloonHelp.c_str());
    }

  // Handle widget

  toolbar_pb = vtkKWPushButton::SafeDownCast(
    toolbar->GetWidget(
      this->Internals->HandleWidgetButtonLabel.c_str()));
  if (toolbar_pb)
    {
    toolbar_pb->SetBalloonHelpString(
      this->Internals->HandleWidgetButtonBalloonHelp.c_str());
    } 

  // Paintbrush widget

  toolbar_pb = vtkKWPushButton::SafeDownCast(
    toolbar->GetWidget(
      this->Internals->PaintbrushWidgetButtonLabel.c_str()));
  if (toolbar_pb)
    {
    toolbar_pb->SetBalloonHelpString(
      this->Internals->PaintbrushWidgetButtonBalloonHelp.c_str());
    }
}

//----------------------------------------------------------------------------
void vtkVVInteractorWidgetSelector::SetDistanceWidgetVisibility(int arg)
{
  if (this->DistanceWidgetVisibility == arg)
    {
    return;
    }

  this->DistanceWidgetVisibility = arg;
  this->Modified();

  this->Update();
}

//----------------------------------------------------------------------------
void vtkVVInteractorWidgetSelector::SetBiDimensionalWidgetVisibility(int arg)
{
  if (this->BiDimensionalWidgetVisibility == arg)
    {
    return;
    }

  this->BiDimensionalWidgetVisibility = arg;
  this->Modified();

  this->Update();
}

//----------------------------------------------------------------------------
void vtkVVInteractorWidgetSelector::SetAngleWidgetVisibility(int arg)
{
  if (this->AngleWidgetVisibility == arg)
    {
    return;
    }

  this->AngleWidgetVisibility = arg;
  this->Modified();

  this->Update();
}

//----------------------------------------------------------------------------
void vtkVVInteractorWidgetSelector::SetContourWidgetVisibility(int arg)
{
  if (this->ContourWidgetVisibility == arg)
    {
    return;
    }

  this->ContourWidgetVisibility = arg;
  this->Modified();

  this->Update();
}

//----------------------------------------------------------------------------
void vtkVVInteractorWidgetSelector::SetLabel2DWidgetVisibility(int arg)
{
  if (this->Label2DWidgetVisibility == arg)
    {
    return;
    }

  this->Label2DWidgetVisibility = arg;
  this->Modified();

  this->Update();
}

//----------------------------------------------------------------------------
void vtkVVInteractorWidgetSelector::SetHandleWidgetVisibility(int arg)
{
  if (this->HandleWidgetVisibility == arg)
    {
    return;
    }

  this->HandleWidgetVisibility = arg;
  this->Modified();

  this->Update();
}

//----------------------------------------------------------------------------
void vtkVVInteractorWidgetSelector::SetPaintbrushWidgetVisibility(int arg)
{
  if (this->PaintbrushWidgetVisibility == arg)
    {
    return;
    }

  this->PaintbrushWidgetVisibility = arg;
  this->Modified();

  this->Update();
}

//----------------------------------------------------------------------------
void vtkVVInteractorWidgetSelector::CreateColumns()
{
  this->Superclass::CreateColumns();

  vtkKWMultiColumnList *list = this->PresetList->GetWidget();

  // Needed since we are using special user-defined window for the
  // visibility and color cells

  list->SetPotentialCellColorsChangedCommand(
    list, "ScheduleRefreshColorsOfAllCellsWithWindowCommand");
  list->SetColumnSortedCommand(
    list, "ScheduleRefreshColorsOfAllCellsWithWindowCommand");
  
  int col;

  // Type

  col = list->InsertColumn(
    this->GetCommentColumnIndex(), 
    ks_("Measurement Preset Selector|Column|Type"));
  list->SetColumnName(
    col, this->Internals->InteractorTypeColumnName.c_str());
  list->SetColumnResizable(col, 0);
  list->SetColumnStretchable(col, 0);
  list->SetColumnEditable(col, 0);
  list->SetColumnFormatCommandToEmptyOutput(col);

  // Value

  col = list->InsertColumn(
    col + 1, 
    ks_("Measurement Preset Selector|Column|Value"));
  list->SetColumnName(
    col, this->Internals->InteractionValueColumnName.c_str());
  list->SetColumnWidth(col, 12);
  list->SetColumnResizable(col, 1);
  list->SetColumnStretchable(col, 0);
  list->SetColumnEditable(col, 0);

  // Visibility

  col = list->InsertColumn(col + 1, NULL);
  list->SetColumnName(
    col, this->Internals->VisibilityColumnName.c_str());
  list->SetColumnLabelImageToPredefinedIcon(
    col, vtkKWIcon::IconSilkEye);
  list->SetColumnResizable(col, 0);
  list->SetColumnStretchable(col, 0);
  list->SetColumnFormatCommandToEmptyOutput(col);
  list->SetColumnWidth(col, -20);

  // Color

  col = list->InsertColumn(col + 1, NULL);
  list->SetColumnName(
    col, this->Internals->ColorColumnName.c_str());
  list->SetColumnResizable(col, 0);
  list->SetColumnStretchable(col, 0);
  list->SetColumnEditable(col, 1);
  list->SetColumnFormatCommandToEmptyOutput(col);
  list->SetColumnLabelImageToPredefinedIcon(
    col, vtkKWIcon::IconSilkColorSwatch);

  // Lock

  col = list->InsertColumn(col + 1, NULL);
  list->SetColumnName(
    col, this->Internals->LockColumnName.c_str());
  list->SetColumnLabelImageToPredefinedIcon(
    col, vtkKWIcon::IconSilkLock);
  list->SetColumnResizable(col, 0);
  list->SetColumnStretchable(col, 0);
  list->SetColumnFormatCommandToEmptyOutput(col);
  list->SetColumnWidth(col, -20);
}

//----------------------------------------------------------------------------
int vtkVVInteractorWidgetSelector::GetInteractorTypeColumnIndex()
{
  return this->PresetList ? 
    this->PresetList->GetWidget()->GetColumnIndexWithName(
      this->Internals->InteractorTypeColumnName.c_str()) : -1;
}

//----------------------------------------------------------------------------
int vtkVVInteractorWidgetSelector::GetInteractionValueColumnIndex()
{
  return this->PresetList ? 
    this->PresetList->GetWidget()->GetColumnIndexWithName(
      this->Internals->InteractionValueColumnName.c_str()) : -1;
}

//----------------------------------------------------------------------------
int vtkVVInteractorWidgetSelector::GetVisibilityColumnIndex()
{
  return this->PresetList ? 
    this->PresetList->GetWidget()->GetColumnIndexWithName(
      this->Internals->VisibilityColumnName.c_str()) : -1;
}

//----------------------------------------------------------------------------
int vtkVVInteractorWidgetSelector::GetColorColumnIndex()
{
  return this->PresetList ?
    this->PresetList->GetWidget()->GetColumnIndexWithName(
      this->Internals->ColorColumnName.c_str()) : -1;
}

//----------------------------------------------------------------------------
int vtkVVInteractorWidgetSelector::GetLockColumnIndex()
{
  return this->PresetList ?
    this->PresetList->GetWidget()->GetColumnIndexWithName(
      this->Internals->LockColumnName.c_str()) : -1;
}

//----------------------------------------------------------------------------
int vtkVVInteractorWidgetSelector::UpdatePresetRow(int id)
{
  if (!this->Superclass::UpdatePresetRow(id))
    {
    return 0;
    }

  int row = this->GetPresetRow(id);
  if (row < 0)
    {
    return 0;
    }

  vtkKWMultiColumnList *list = this->PresetList->GetWidget();

  vtkAbstractWidget *widget = this->GetPresetInteractorWidget(id);
  vtkKWDistanceWidget *distance_widget = 
    vtkKWDistanceWidget::SafeDownCast(widget);
  vtkKWBiDimensionalWidget *bidim_widget =
    vtkKWBiDimensionalWidget::SafeDownCast(widget);
  vtkKWAngleWidget *angle_widget = 
    vtkKWAngleWidget::SafeDownCast(widget);
  vtkKWContourWidget *contour_widget = 
    vtkKWContourWidget::SafeDownCast(widget);
  vtkKWCaptionWidget *caption_widget = 
    vtkKWCaptionWidget::SafeDownCast(widget);
  vtkVVHandleWidget *handle_widget = 
    vtkVVHandleWidget::SafeDownCast(widget);
  vtkKWEPaintbrushWidget *paintbrush_widget =
    vtkKWEPaintbrushWidget::SafeDownCast(widget);

  vtkVVSelectionFrame *sel_frame = this->GetPresetSelectionFrame(id);

  int support_color = 1;

  double r = 1.0, g = 1.0, b = 1.0;
  int icon = vtkKWIcon::IconNuvola16x16ActionsNo;

  // Distance widget

  if (distance_widget)
    {
    icon = vtkKWIcon::IconDistanceTool;
    vtkDistanceRepresentation *rep = vtkDistanceRepresentation::SafeDownCast(
      distance_widget->GetRepresentation());
    vtkDistanceRepresentation2D *rep2d =
      vtkDistanceRepresentation2D::SafeDownCast(rep);
    if (rep2d)
      {
      rep2d->GetAxis()->GetProperty()->GetColor(r, g, b);
      }
    }

  // Bi-Dimensional widget

  if (bidim_widget)
    {
    icon = vtkKWIcon::IconBiDimensionalTool;
    vtkBiDimensionalRepresentation2D *rep2d =
      vtkBiDimensionalRepresentation2D::SafeDownCast(
        bidim_widget->GetRepresentation());
    if (rep2d)
      {
      rep2d->GetLineProperty()->GetColor(r, g, b);
      }
    }

  // Angle widget

  else if (angle_widget)
    {
    icon = vtkKWIcon::IconAngleTool;
    vtkAngleRepresentation *rep = vtkAngleRepresentation::SafeDownCast(
      angle_widget->GetRepresentation());
    vtkAngleRepresentation2D *rep2d =
      vtkAngleRepresentation2D::SafeDownCast(rep);
    if (rep2d)
      {
      rep2d->GetArc()->GetProperty()->GetColor(r, g, b);
      }
    }

  // Contour widget

  else if (contour_widget)
    {
    icon = vtkKWIcon::IconContourTool;
    vtkContourRepresentation *rep = vtkContourRepresentation::SafeDownCast(
      contour_widget->GetRepresentation());

    // For an image widget, the contour representation is
    // vtkOrientedGlyphContourRepresentation. For a volume widget, it
    // is vtkOrientedGlyphFocalPlaneContourRepresentation
    //
    if (sel_frame)
      {
      vtkKWRenderWidgetPro *rwp =
            vtkKWRenderWidgetPro::SafeDownCast(sel_frame->GetRenderWidget());

      if (vtkKWImageWidget::SafeDownCast(rwp))
        {
        vtkOrientedGlyphContourRepresentation *repog =
          vtkOrientedGlyphContourRepresentation::SafeDownCast(rep);
        if (repog)
          {
          repog->GetLinesProperty()->GetColor(r, g, b);
          }
        }
      else if (vtkKWVolumeWidget::SafeDownCast( rwp ))
        {
        vtkOrientedGlyphFocalPlaneContourRepresentation *repog =
          vtkOrientedGlyphFocalPlaneContourRepresentation::SafeDownCast(rep);
        if (repog)
          {
          repog->GetLinesProperty()->GetColor(r, g, b);
          }
        }
      }
    }

  // Label widget

  else if (caption_widget)
    {
    icon = vtkKWIcon::IconPointFinger;
    vtkCaptionRepresentation *rep = vtkCaptionRepresentation::SafeDownCast(
      caption_widget->GetRepresentation());
    rep->GetCaptionActor2D()->GetProperty()->GetColor(r, g, b);
    }

  // Seed widget

  else if (handle_widget)
    {
    icon = vtkKWIcon::IconSeedTool;
    vtkPointHandleRepresentation3D *rep = 
      vtkPointHandleRepresentation3D::SafeDownCast(
        handle_widget->GetRepresentation());
    if (rep)
      {
      rep->GetProperty()->GetColor(r, g, b);
      }
    }

  // Paintbrush widget

  else if (paintbrush_widget)
    {
    icon = vtkKWIcon::IconSilkPaintbrush;
    support_color = 0;
    }

  if (widget)
    {
    list->SetCellText(// for sorting
      row, this->GetInteractorTypeColumnIndex(), widget->GetClassName());
    }

  list->SetCellImageToPredefinedIcon(
    row, this->GetInteractorTypeColumnIndex(), icon);

  // Visibility

  int visibility = 
    sel_frame ? sel_frame->GetInteractorWidgetVisibility(widget) : 0;
  list->SetCellTextAsInt(row, this->GetVisibilityColumnIndex(), visibility);
  list->SetCellWindowCommandToCheckButton(
    row, this->GetVisibilityColumnIndex());
  vtkKWCheckButton *vis_button = list->GetCellWindowAsCheckButton(
    row, this->GetVisibilityColumnIndex());
  vis_button->SetBalloonHelpString("Show widget");

  // Color

  if (support_color)
    {
    char rgb[256];
    sprintf(rgb, "%g %g %g", r, g, b);
    list->SetCellText(row, this->GetColorColumnIndex(), rgb);
    list->SetCellWindowCommandToColorButton(row, this->GetColorColumnIndex());
    }
  else
    {
    list->SetCellText(row, this->GetColorColumnIndex(), NULL);
    list->SetCellWindowCommand(row, this->GetColorColumnIndex(), NULL, NULL);
    }

  // Lock

  int lock = sel_frame ? sel_frame->GetInteractorWidgetLock(widget) : -1;
  if (lock >= 0)
    {
    list->SetCellTextAsInt(row, this->GetLockColumnIndex(), lock);
    list->SetCellWindowCommandToCheckButton(row, this->GetLockColumnIndex());
    vtkKWCheckButton *lock_button = list->GetCellWindowAsCheckButton(
      row, this->GetLockColumnIndex());
    lock_button->SetBalloonHelpString(
      paintbrush_widget ? "Disable widget interaction" 
      : "Lock widget to the current slice");
    }
  else
    {
    list->SetCellText(row, this->GetLockColumnIndex(), NULL);
    list->SetCellWindowCommand(row, this->GetLockColumnIndex(), NULL, NULL);
    }
  //list->SetCellEnabledAttribute(row, this->GetLockColumnIndex(), lock >= 0 ? this->GetEnabled() : 0);

  this->UpdatePresetRowValueColumn(id);

  return 1;
}

//----------------------------------------------------------------------------
int vtkVVInteractorWidgetSelector::UpdatePresetRowValueColumn(
  int id)
{
  int row = this->GetPresetRow(id);
  if (row < 0)
    {
    return 0;
    }

  vtkKWMultiColumnList *list = this->PresetList->GetWidget();

  vtkAbstractWidget *interactor = this->GetPresetInteractorWidget(id);
  vtkKWDistanceWidget *distance_widget =
    vtkKWDistanceWidget::SafeDownCast(interactor);
  vtkKWBiDimensionalWidget *bidim_widget =
    vtkKWBiDimensionalWidget::SafeDownCast(interactor);
  vtkKWAngleWidget *angle_widget =
    vtkKWAngleWidget::SafeDownCast(interactor);
  vtkKWContourWidget *contour_widget =
    vtkKWContourWidget::SafeDownCast(interactor);
  vtkKWCaptionWidget *caption_widget =
    vtkKWCaptionWidget::SafeDownCast(interactor);
  vtkVVHandleWidget *handle_widget =
    vtkVVHandleWidget::SafeDownCast(interactor);
  vtkKWEPaintbrushWidget *paintbrush_widget =
    vtkKWEPaintbrushWidget::SafeDownCast(interactor);

  char value[256] = {"\0"};
  int editable = 0;

  // Distance widget

  if (distance_widget)
    {
    vtkDistanceRepresentation *rep = vtkDistanceRepresentation::SafeDownCast(
      distance_widget->GetRepresentation());
    if (rep)
      {
      sprintf(value, rep->GetLabelFormat(), rep->GetDistance());
      }
    }

  // Bi-Dimensional widget

  if (bidim_widget)
    {
    vtkBiDimensionalRepresentation2D *rep =
      vtkBiDimensionalRepresentation2D::SafeDownCast(
        bidim_widget->GetRepresentation());
    if (rep)
      {
      double line1Dist = rep->GetLength1();
      double line2Dist = rep->GetLength2();

      char distStr1[256];
      sprintf(distStr1,rep->GetLabelFormat(), line1Dist);

      char distStr2[256];
      sprintf(distStr2,rep->GetLabelFormat(), line2Dist);

      ostrstream label;

      if (line1Dist > line2Dist)
        {
        label << distStr1 << " x " << distStr2 << ends;
        }
      else
        {
        label << distStr2 << " x " << distStr1 << ends;
        }
   
      std::string labelString = label.str(); 
      strcpy( value, labelString.c_str());
      }
    }

  // Angle widget

  else if (angle_widget)
    {
    vtkAngleRepresentation2D *rep2d = vtkAngleRepresentation2D::SafeDownCast(
      angle_widget->GetRepresentation());
    if (rep2d && angle_widget->IsAngleValid())
      {
      //      sprintf(value, "%.2f %s", rep->GetAngle(), ks_("Unit|degrees")); // can not handle °
      sprintf(value, "%s", rep2d->GetArc()->GetLabel());
      }
    }

  // Contour widget

  else if (contour_widget)
    {
    vtkContourRepresentation *rep = vtkContourRepresentation::SafeDownCast(
      contour_widget->GetRepresentation());
    if (rep)
      {
      sprintf(value,
        ks_("Measurement Value|%d node(s)"),
        rep->GetNumberOfNodes());
      }
    }

  // label widget

  else if (caption_widget)
    {
    vtkCaptionRepresentation *rep = vtkCaptionRepresentation::SafeDownCast(
      caption_widget->GetRepresentation());
    if (rep)
      {
      sprintf(value,
        ks_("Label Text|%s"),
        rep->GetCaptionActor2D()->GetCaption());
      editable = 1;
      }
    }

  // Handle widget

  else if (handle_widget)
    {
    sprintf(value, "%s", handle_widget->GetWorldPositionAsString().c_str());
    }

  // Paintbrush widget
  // eventually bring this one back once we can be notified by the 
  // paintbrush that a sketch has been added or removed
  /*
  else if (paintbrush_widget)
    {
    vtkKWEPaintbrushRepresentation2D * rep = 
      vtkKWEPaintbrushRepresentation2D::SafeDownCast(
        paintbrush_widget->GetRepresentation());
    if (rep)
      {
      vtkKWEPaintbrushDrawing *drawing = rep->GetPaintbrushDrawing();
      int nb_items = drawing->GetNumberOfItems();
      sprintf(value, (nb_items > 1 ? "%d sketches" : "%d sketch"), nb_items);
      }
    }
  */

  int col = this->GetInteractionValueColumnIndex();
  list->SetCellText(row, col, value);
  list->SetCellEditable(row, col, editable);

  return 1;
}

//----------------------------------------------------------------------------
void vtkVVInteractorWidgetSelector::UpdateInteractorWidgetProperties(int id)
{
  if (!this->InteractorWidgetProperties)
    {
    return;
    }

  vtkKWMultiColumnList *list = this->InteractorWidgetProperties->GetWidget();
  list->DeleteAllRows();
  char buffer[200];
  sprintf(buffer, "InteractorWidgetPropertiesCellUpdatedCallback %d", id);
  list->SetCellUpdatedCommand(this, buffer);
  int row = 0;

  vtkAbstractWidget *interactor = this->GetPresetInteractorWidget(id);
  if (interactor)
    {
    vtkKWContourWidget *contour_widget =
      vtkKWContourWidget::SafeDownCast(interactor);
    vtkKWCaptionWidget *caption_widget =
      vtkKWCaptionWidget::SafeDownCast(interactor);
    vtkVVHandleWidget *handle_widget =
      vtkVVHandleWidget::SafeDownCast(interactor);
    vtkKWEPaintbrushWidget *paintbrush_widget =
      vtkKWEPaintbrushWidget::SafeDownCast(interactor);

    /*
    list->InsertCellText(
      row, 0, ks_("Priority"));
    list->SetCellTextAsFormattedDouble(row, 1, interactor->GetPriority(), 2);
    row++;
    */
    
    // Contour widget

    if (contour_widget)
      {
      vtkContourRepresentation *rep = vtkContourRepresentation::SafeDownCast(
        contour_widget->GetRepresentation());
      if (rep && rep->GetClosedLoop()) // If contour is closed
        {
        // The contour polydata *is* unmodified. Use const_cast here cause 
        // the pipeline vtkDataObjects are not const correct
        this->ContourStatistics->SetInput(
          const_cast< vtkPolyData * >(
            rep->GetContourRepresentationAsPolyData()));

        vtkVVSelectionFrame *sel_frame = this->GetPresetSelectionFrame(id);
        vtkKW2DRenderWidget *rw2d = vtkKW2DRenderWidget::SafeDownCast(
          sel_frame->GetRenderWidget());
        if (rw2d)
          {
          vtkKWImageMapToWindowLevelColors *imageMapToRGBA = 
            rw2d->GetImageMapToRGBA();
          if (imageMapToRGBA && imageMapToRGBA->GetInput())
            {
            this->ContourStatistics->SetImageData(
              (vtkImageData *)(imageMapToRGBA->GetInput()));
            this->ContourStatistics->ObtainSliceFromContourPolyDataOff();
            this->ContourStatistics->SetSlice(rw2d->GetSlice());
            }

          int precision = 5;

          list->InsertCellText(
            row, 0, ks_("Measurement Details|Area"));
          list->SetCellTextAsFormattedDouble(
            row, 1, this->ContourStatistics->GetArea(), precision);
          row++;

          list->InsertCellText(
            row, 0, ks_("Measurement Details|Perimeter"));
          list->SetCellTextAsFormattedDouble(
            row, 1, this->ContourStatistics->GetPerimeter(), precision);
          row++;
            
          // Do not bother to get the Mean/max etc if we have 
          // multi-component data or if we have 0 pixels in the contour
          if (this->ContourStatistics->GetStatisticsComputeFailed() == 0)
            {
            list->InsertCellText(
              row, 0, ks_("Measurement Details|Mean Pixel Value"));
            list->SetCellTextAsFormattedDouble(
              row, 1, this->ContourStatistics->GetMean(), precision);
            row++;

            list->InsertCellText(
              row, 0, ks_("Measurement Details|Standard Deviation"));
            list->SetCellTextAsFormattedDouble(
              row, 1, this->ContourStatistics->GetStandardDeviation(), 
              precision);
            row++;

            list->InsertCellText(
              row, 0, ks_("Measurement Details|Min Pixel Value"));
            list->SetCellTextAsFormattedDouble(
              row, 1, this->ContourStatistics->GetMinimum(), precision);
            row++;

            list->InsertCellText(
              row, 0, ks_("Measurement Details|Max Pixel Value"));
            list->SetCellTextAsFormattedDouble(
              row, 1, this->ContourStatistics->GetMaximum(), precision);
            row++;

            list->InsertCellText(
              row, 0, ks_("Measurement Details|Number Of Pixels"));
            list->SetCellTextAsInt(
              row, 1, this->ContourStatistics->GetNumberOfPixelsInContour());
            row++;
            }
          }
        }
      }

    // Label widget

    else if (caption_widget)
      {
      vtkCaptionActor2D *caption_actor = caption_widget->GetCaptionActor2D();
      if (caption_actor)
        {
        list->InsertCellText(row, 0, ks_("Measurement Details|Text"));
        list->SetCellText(row, 1, caption_actor->GetCaption());
        list->SetCellEditable(row, 1, 1);
        row++;

        vtkTextProperty *tprop = caption_actor->GetCaptionTextProperty();
        if (tprop)
          {
          const char *fonts[] =  {"Arial", "Courier", "Times"};
          list->InsertCellText(row, 0, ks_("Measurement Details|Font"));
          list->SetCellText(row, 1, tprop->GetFontFamilyAsString());
          list->SetCellWindowCommandToComboBoxWithValues(
            row, 1, sizeof(fonts) / sizeof(fonts[0]), fonts);
          row++;
          
          list->InsertCellText(row, 0, ks_("Measurement Details|Bold"));
          list->SetCellTextAsInt(row, 1, tprop->GetBold());
          list->SetCellWindowCommandToCheckButton(row, 1);
          row++;

          list->InsertCellText(row, 0, ks_("Measurement Details|Italic"));
          list->SetCellTextAsInt(row, 1, tprop->GetItalic());
          list->SetCellWindowCommandToCheckButton(row, 1);
          row++;

          list->InsertCellText(row, 0, ks_("Measurement Details|Shadow"));
          list->SetCellTextAsInt(row, 1, tprop->GetShadow());
          list->SetCellWindowCommandToCheckButton(row, 1);
          row++;
          }
        }

      vtkCaptionRepresentation* caption_rep =  
        vtkCaptionRepresentation::SafeDownCast(
          caption_widget->GetRepresentation());
      if (caption_rep)
        {
        list->InsertCellText(
          row, 0, ks_("Measurement Details|Size Scale"));
        list->SetCellTextAsFormattedDouble(
          row, 1, caption_rep->GetFontFactor(), 3);
        list->SetCellEditable(row, 1, 1);
        row++;
        }
      }

    // Handle widget

    else if (handle_widget)
      {
      list->InsertCellText
        (row, 0, ks_("Measurement Details|Location"));
      list->SetCellText(
        row, 1, handle_widget->GetWorldPositionAsString().c_str());
      row++;

      list->InsertCellText(
        row, 0, ks_("Measurement Details|Pixel Indices"));
      list->SetCellText(
        row, 1, handle_widget->GetPixelPositionAsString().c_str());
      row++;

      list->InsertCellText(
        row, 0, ks_("Measurement Details|Value"));
      list->SetCellText(
        row, 1, handle_widget->GetPixelValueAsString().c_str());
      }

    // Paintbrush widget

    else if (paintbrush_widget)
      {
      vtkKWEPaintbrushRepresentation2D * rep = 
        vtkKWEPaintbrushRepresentation2D::SafeDownCast(
          paintbrush_widget->GetRepresentation());
      // eventually bring this one back once we can be notified by the 
      // paintbrush that a sketch has been added or removed
      /*
      if (rep)
        {
        vtkKWEPaintbrushDrawing *drawing = rep->GetPaintbrushDrawing();
        list->InsertCellText(
          row, 0, ks_("Measurement Details|Number of Sketches"));
        list->SetCellTextAsInt(
          row, 1, drawing->GetNumberOfItems());
        row++;
        }
      */
      /*
      list->InsertCellText(
        row, 0, ks_("Measurement Details|Label Type"));
      list->SetCellText(
        row, 1, 
        vtkImageScalarTypeNameMacro(vtkKWEPaintbrushEnums::GetLabelType()));
      row++;
      */
      }
    }

  if (row)
    {
    this->Script(	 
      "pack %s -side top -anchor nw -fill x -expand n -padx 2 -pady 2",	 
      this->InteractorWidgetProperties->GetWidgetName());
    }
  else
    {
    this->Script("pack forget %s",
                 this->InteractorWidgetProperties->GetWidgetName());
    }

  this->InvokePresetUpdateInteractorWidgetPropertiesCommand(id);
}

//---------------------------------------------------------------------------
void vtkVVInteractorWidgetSelector::InteractorWidgetPropertiesCellUpdatedCallback(
  int id, int, int, const char *)
{
  if (!this->HasPreset(id))
    {
    return;
    }

  vtkAbstractWidget *widget = this->GetPresetInteractorWidget(id);
  if (!widget)
    {
    return;
    }

  vtkKWMultiColumnList *list = this->InteractorWidgetProperties->GetWidget();
  vtkKWCaptionWidget *caption_widget = 
    vtkKWCaptionWidget::SafeDownCast(widget);

  // Label widget

  if (caption_widget)
    {
    int row = 0;

    vtkCaptionActor2D *caption_actor = caption_widget->GetCaptionActor2D();
    if (caption_actor)
      {
      caption_actor->SetCaption(list->GetCellText(row, 1));
      this->UpdatePresetRowValueColumn(id);
      row++;

      vtkTextProperty *tprop = caption_actor->GetCaptionTextProperty();
      if (tprop)
        {
        tprop->SetFontFamily(
          vtkTextProperty::GetFontFamilyFromString(list->GetCellText(row, 1)));
        row++;

        tprop->SetBold(list->GetCellTextAsInt(row, 1));
        row++;

        tprop->SetItalic(list->GetCellTextAsInt(row, 1));
        row++;

        tprop->SetShadow(list->GetCellTextAsInt(row, 1));
        row++;
        }
      }

    vtkCaptionRepresentation* caption_rep = 
    vtkCaptionRepresentation::SafeDownCast(caption_widget->GetRepresentation());
    if (caption_rep)
      {
      caption_rep->SetFontFactor(list->GetCellTextAsDouble(row, 1));
      row++;
      }
    caption_widget->Render();
    }
}

//---------------------------------------------------------------------------
void vtkVVInteractorWidgetSelector::PresetSelectionCallback()
{
  this->Superclass::PresetSelectionCallback();

  // Jump to the location the widget was defined at.

  if (this->PresetList)
    {
    if (this->ArePresetInteractorWidgetsDefined())
      {
      int row = this->PresetList->GetWidget()->GetIndexOfFirstSelectedRow();
      int id = this->GetIdOfPresetAtRow(row);
      vtkVVSelectionFrame *sel_frame = this->GetPresetSelectionFrame(id);
      vtkAbstractWidget *widget = this->GetPresetInteractorWidget(id);
      if (sel_frame && widget)
        {
        sel_frame->GoToInteractorWidget(widget);
        }
      }
    // the below code is called already by the superclass's call to Update
    //this->UpdateInteractorWidgetProperties(this->GetIdOfSelectedPreset());
    }
}

//---------------------------------------------------------------------------
void vtkVVInteractorWidgetSelector::PresetCellUpdatedCallback(
  int row, int col, const char *text)
{
  this->Superclass::PresetCellUpdatedCallback(row, col, text);

  int id = this->GetIdOfPresetAtRow(row);
  if (!this->HasPreset(id))
    {
    return;
    }

  vtkAbstractWidget *widget = this->GetPresetInteractorWidget(id);
  if (!widget)
    {
    return;
    }

  vtkKWDistanceWidget *distance_widget = 
    vtkKWDistanceWidget::SafeDownCast(widget);
  vtkKWBiDimensionalWidget *bidim_widget =
    vtkKWBiDimensionalWidget::SafeDownCast(widget);
  vtkKWAngleWidget *angle_widget = 
    vtkKWAngleWidget::SafeDownCast(widget);
  vtkKWContourWidget *contour_widget = 
    vtkKWContourWidget::SafeDownCast(widget);
  vtkKWCaptionWidget *caption_widget = 
    vtkKWCaptionWidget::SafeDownCast(widget);
  vtkVVHandleWidget *handle_widget = 
    vtkVVHandleWidget::SafeDownCast(widget);
  vtkKWEPaintbrushWidget *paintbrush_widget =
    vtkKWEPaintbrushWidget::SafeDownCast(widget);

  vtkKWMultiColumnList *list = this->PresetList->GetWidget();

  vtkVVSelectionFrame *sel_frame = this->GetPresetSelectionFrame(id);

  // Visibility

  if (col == this->GetVisibilityColumnIndex())
    {
    sel_frame->SetInteractorWidgetVisibility(
      widget, list->GetCellTextAsInt(row, col));
    this->InvokePresetHasChangedCommand(id);
    return;
    }

  // Lock (at the current slice)

  if (col == this->GetLockColumnIndex())
    {
    int lock = list->GetCellTextAsInt(row, col);
    sel_frame->SetInteractorWidgetLock(widget, lock);
    vtkKW2DRenderWidget *rw2d =
      vtkKW2DRenderWidget::SafeDownCast(sel_frame->GetRenderWidget());
    if (rw2d && rw2d->GetHasSliceControl())
      {
      sel_frame->SetInteractorWidgetOriginalSlice(widget, rw2d->GetSlice());
      }
    this->InvokePresetHasChangedCommand(id);
    return;
    }

  // Value

  if (col == this->GetInteractionValueColumnIndex())
    {
    // label widget

    if (caption_widget)
      {
      vtkCaptionActor2D *caption_actor = caption_widget->GetCaptionActor2D();
      if (caption_actor)
        {
        caption_actor->SetCaption(list->GetCellText(row, col));
        this->UpdateInteractorWidgetProperties(id);
        caption_widget->Render();
        }
      }
    }

  // Color

  if (col == this->GetColorColumnIndex())
    {
    double r, g, b;
    if (sscanf(list->GetCellText(row, col), "%lg %lg %lg", &r, &g, &b) != 3)
      {
      return;
      }

    // Distance widget

    if (distance_widget)
      {
      vtkDistanceRepresentation *rep = vtkDistanceRepresentation::SafeDownCast(
        distance_widget->GetRepresentation());
      vtkDistanceRepresentation2D *rep2d =
        vtkDistanceRepresentation2D::SafeDownCast(rep);
      if (rep2d)
        {
        rep2d->GetAxis()->GetProperty()->SetColor(r, g, b);
        rep2d->GetAxis()->GetTitleTextProperty()->SetColor(
          rep2d->GetAxis()->GetProperty()->GetColor());
        }
      }

    // Bi-Dimensional widget

    if (bidim_widget)
      {
      vtkBiDimensionalRepresentation2D *rep2d = 
        vtkBiDimensionalRepresentation2D::SafeDownCast(
          bidim_widget->GetRepresentation());
      if (rep2d)
        {
        rep2d->GetLineProperty()->SetColor(r, g, b);
        rep2d->GetTextProperty()->SetColor(
          rep2d->GetLineProperty()->GetColor());
        }
      }

    // Angle widget

    else if (angle_widget)
      {
      vtkAngleRepresentation *rep = vtkAngleRepresentation::SafeDownCast(
        angle_widget->GetRepresentation());
      vtkAngleRepresentation2D *rep2d =
        vtkAngleRepresentation2D::SafeDownCast(rep);
      if (rep2d)
        {
        rep2d->GetArc()->GetProperty()->SetColor(r, g, b);
        rep2d->GetArc()->GetLabelTextProperty()->SetColor(
          rep2d->GetArc()->GetProperty()->GetColor());
        rep2d->GetRay1()->GetProperty()->SetColor(
          rep2d->GetArc()->GetProperty()->GetColor());
        rep2d->GetRay2()->GetProperty()->SetColor(
          rep2d->GetArc()->GetProperty()->GetColor());
        }
      }

    // Contour widget

    else if (contour_widget)
      {
      vtkContourRepresentation *rep = vtkContourRepresentation::SafeDownCast(
        contour_widget->GetRepresentation());

      // For an image widget, the contour representation is
      // vtkOrientedGlyphContourRepresentation. For a volume widget, it
      // is vtkOrientedGlyphFocalPlaneContourRepresentation
      //
      vtkKWRenderWidgetPro *rwp =
        vtkKWRenderWidgetPro::SafeDownCast(sel_frame->GetRenderWidget());

      if (vtkKWImageWidget::SafeDownCast(rwp))
        {
        vtkOrientedGlyphContourRepresentation *repog =
          vtkOrientedGlyphContourRepresentation::SafeDownCast(rep);
        if (repog)
          {
          repog->GetLinesProperty()->SetColor(r, g, b);
          }
        }
      else if (vtkKWVolumeWidget::SafeDownCast( rwp ))
        {
        vtkOrientedGlyphFocalPlaneContourRepresentation *repog =
          vtkOrientedGlyphFocalPlaneContourRepresentation::SafeDownCast(rep);
        if (repog)
          {
          repog->GetLinesProperty()->SetColor(r, g, b);
          }
        }
      }

    // label widget

    else if (caption_widget)
      {
      vtkCaptionRepresentation *rep = vtkCaptionRepresentation::SafeDownCast(
        caption_widget->GetRepresentation());

      if (rep)
        {
        rep->GetCaptionActor2D()->GetCaptionTextProperty()->SetColor(r, g, b);
        rep->GetCaptionActor2D()->GetProperty()->SetColor(r, g, b);
        }
      }

    // Handle widget

    else if (handle_widget)
      {
      handle_widget->SetColor(r, g, b);
      handle_widget->RenderAllWidgetsInGroup();
      }

    // Paintbrush widget

    if (paintbrush_widget)
      {
      }

    widget->Render();
    this->InvokePresetHasChangedCommand(id);
    return;
    }
}

//----------------------------------------------------------------------------
int vtkVVInteractorWidgetSelector::HasPresetWithGroupWithInteractorWidget(
  const char *group, vtkAbstractWidget *interactor)
{
  int i, nb_presets = this->GetNumberOfPresetsWithGroup(group);
  for (i = 0; i < nb_presets; i++)
    {
    int id = this->GetIdOfNthPresetWithGroup(i, group);
    if (this->GetPresetInteractorWidget(id) == interactor)
      {
      return 1;
      }
    }
  return 0;
}

//----------------------------------------------------------------------------
int vtkVVInteractorWidgetSelector::GetIdOfInteractorWidget(vtkAbstractWidget *w)
{
  int nb_presets = this->GetNumberOfPresets();
  for (int i = 0; i < nb_presets; i++)
    {
    int id = this->GetIdOfNthPreset(i);
    if (this->GetPresetInteractorWidget(id) == w)
      {
      return id;
      }
    }

  return -1;
}

//----------------------------------------------------------------------------
void vtkVVInteractorWidgetSelector::ProcessCallbackCommandEvents(
  vtkObject *caller,
  unsigned long event,
  void *calldata)
{
  vtkAbstractWidget *interactor = vtkAbstractWidget::SafeDownCast(caller);
  vtkKW2DRenderWidget *rw2d = vtkKW2DRenderWidget::SafeDownCast(caller);

  int sel_id = this->GetIdOfPresetAtRow(
    this->PresetList->GetWidget()->GetIndexOfFirstSelectedRow());

  if (interactor)
    {
    int i, nb_presets = this->GetNumberOfPresets();
    for (i = 0; i < nb_presets; i++)
      {
      int id = this->GetIdOfNthPreset(i);
      if (this->GetPresetInteractorWidget(id) == interactor)
        {
        if (event == vtkKWEPaintbrushWidget::ToggleSelectStateEvent)
          {
          this->UpdatePresetRow(id);
          }
        else
          {
          this->UpdatePresetRowValueColumn(id);
          }
        if (event == vtkCommand::EndInteractionEvent)
          {
          this->UpdateInteractorWidgetProperties(id);
          this->Update(); // disable us if interactor not defined
          }
        if (sel_id != id)
          {
          this->PresetList->GetWidget()->SelectSingleRow(
            this->GetPresetRow(id));
          }
        }
      }
    }

  if (rw2d)
    {
    if (   event == vtkKWEvent::ImageSliceChangedEvent
        || event == vtkKWEvent::ProbeImageTranslatePlaneEvent
        || event == vtkKWEvent::ProbeImageRollPlaneEvent
        || event == vtkKWEvent::ProbeImageTiltPlaneEvent )
      {
      // Also ensure that the event was triggered on the currently chosen
      // selection frame. For instance, it is possible to use the slider to
      // change slices on a different render widget, there would be no point
      // updating then.
      vtkVVSelectionFrame *sel_frame = this->GetPresetSelectionFrame(sel_id);
      if (sel_frame)
        {
        vtkKW2DRenderWidget *sel_frame_rw2d =
          vtkKW2DRenderWidget::SafeDownCast(sel_frame->GetRenderWidget());
        if (sel_frame_rw2d == rw2d)
          {
          this->UpdateInteractorWidgetProperties(sel_id);
          }
        }
      }
    }

  this->Superclass::ProcessCallbackCommandEvents(caller, event, calldata);
}

//----------------------------------------------------------------------------
void vtkVVInteractorWidgetSelector::InteractorWidgetAddCallback(int type)
{
  this->InvokePresetAddDefaultInteractorCommand(type);
  this->Update();
}

//----------------------------------------------------------------------------
void vtkVVInteractorWidgetSelector::SetPresetAddDefaultInteractorCommand(
  vtkObject *object, const char *method)
{
  this->SetObjectMethodCommand(
    &this->PresetAddDefaultInteractorCommand, object, method);
}

//----------------------------------------------------------------------------
void vtkVVInteractorWidgetSelector::InvokePresetAddDefaultInteractorCommand(int type)
{
  if (this->PresetAddDefaultInteractorCommand && 
      *this->PresetAddDefaultInteractorCommand && 
      this->IsCreated())
    {
    this->Script("eval %s %d", this->PresetAddDefaultInteractorCommand, type);
    }
}

//----------------------------------------------------------------------------
void vtkVVInteractorWidgetSelector::SetPresetDefaultInteractorIsSupportedCommand(
  vtkObject *object, const char *method)
{
  this->SetObjectMethodCommand(
    &this->PresetDefaultInteractorIsSupportedCommand, object, method);
  this->Update();
}

//----------------------------------------------------------------------------
int 
vtkVVInteractorWidgetSelector::InvokePresetDefaultInteractorIsSupportedCommand(
  int type)
{
  if (this->PresetDefaultInteractorIsSupportedCommand && 
      *this->PresetDefaultInteractorIsSupportedCommand && 
      this->IsCreated())
    {
    return atoi(
      this->Script("eval %s %d", 
                   this->PresetDefaultInteractorIsSupportedCommand, type));
    }
  return 0;
}

//----------------------------------------------------------------------------
void 
vtkVVInteractorWidgetSelector::SetPresetUpdateInteractorWidgetPropertiesCommand(
  vtkObject *object, const char *method)
{
  this->SetObjectMethodCommand(
    &this->PresetUpdateInteractorWidgetPropertiesCommand, object, method);
  this->Update();
}

//----------------------------------------------------------------------------
int 
vtkVVInteractorWidgetSelector::InvokePresetUpdateInteractorWidgetPropertiesCommand(
  int id)
{
  if (this->PresetUpdateInteractorWidgetPropertiesCommand && 
      *this->PresetUpdateInteractorWidgetPropertiesCommand && 
      this->IsCreated())
    {
    return atoi(this->Script("eval %s %d", 
                             this->PresetUpdateInteractorWidgetPropertiesCommand, id));
    }
  return 0;
}

//---------------------------------------------------------------------------
void vtkVVInteractorWidgetSelector::SetWindow(vtkVVWindowBase *arg)
{
  if (this->Window == arg)
    {
    return;
    }
  this->Window = arg;
  this->Modified();

  this->Update();
}

//---------------------------------------------------------------------------
int vtkVVInteractorWidgetSelector::IsPresetInteractorWidgetDefined(int id)
{
  vtkAbstractWidget *widget = this->GetPresetInteractorWidget(id);
  if (!widget)
    {
    return 0;
    }

  return this->IsPresetInteractorWidgetDefined(widget);
}

//---------------------------------------------------------------------------
int vtkVVInteractorWidgetSelector::IsPresetInteractorWidgetDefined(vtkAbstractWidget *widget)
{
  vtkKWDistanceWidget *distance_widget = 
    vtkKWDistanceWidget::SafeDownCast(widget);
  if (distance_widget)
    {
    return distance_widget->IsWidgetDefined();
    }

  vtkKWBiDimensionalWidget *bidim_widget =
    vtkKWBiDimensionalWidget::SafeDownCast(widget);
  if (bidim_widget)
    {
    return bidim_widget->IsWidgetDefined();
    }

  vtkKWAngleWidget *angle_widget = 
    vtkKWAngleWidget::SafeDownCast(widget);
  if (angle_widget)
    {
    return angle_widget->IsWidgetDefined();
    }

  vtkKWContourWidget *contour_widget = 
    vtkKWContourWidget::SafeDownCast(widget);
  if (contour_widget)
    {
    return contour_widget->IsWidgetDefined();
    }

  vtkKWCaptionWidget *caption_widget = 
    vtkKWCaptionWidget::SafeDownCast(widget);
  if (caption_widget)
    {
    return caption_widget->IsWidgetDefined();
    }

  vtkVVHandleWidget *handle_widget = 
    vtkVVHandleWidget::SafeDownCast(widget);
  if (handle_widget)
    {
    return handle_widget->IsWidgetDefined();
    }

  vtkKWEPaintbrushWidget *paintbrush_widget =
    vtkKWEPaintbrushWidget::SafeDownCast(widget);
  if (paintbrush_widget)
    {
    return 1;
    }
  
  return 0;
}

//---------------------------------------------------------------------------
int vtkVVInteractorWidgetSelector::ArePresetInteractorWidgetsDefined()
{
  int i, nb_presets = this->GetNumberOfPresets();
  for (i = 0; i < nb_presets; i++)
    {
    if (!this->IsPresetInteractorWidgetDefined(this->GetIdOfNthPreset(i)))
      {
      return 0;
      }
    }

  return 1;
}

//---------------------------------------------------------------------------
void vtkVVInteractorWidgetSelector::Update()
{
  this->Superclass::Update();
  this->UpdateInteractorWidgetProperties(this->GetIdOfSelectedPreset());
}

//----------------------------------------------------------------------------
void vtkVVInteractorWidgetSelector::UpdateEnableState()
{
  this->Superclass::UpdateEnableState();

  this->PropagateEnableState(this->InteractorWidgetProperties);
}

//----------------------------------------------------------------------------
void vtkVVInteractorWidgetSelector::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);
}
