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

  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 "vtkKW3DMarkersWidget.h"

#include "vtkActor.h"
#include "vtkAssemblyNode.h"
#include "vtkAssemblyPath.h"
#include "vtkCallbackCommand.h"
#include "vtkCamera.h"
#include "vtkCellPicker.h"
#include "vtkCylinderSource.h"
#include "vtkKWEvent.h"
#include "vtkMath.h"
#include "vtkObjectFactory.h"
#include "vtkPolyDataMapper.h"
#include "vtkProperty.h"
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkKWVolumeWidget.h"

#include <vtkstd/algorithm>

vtkCxxRevisionMacro(vtkKW3DMarkersWidget, "$Revision: 1.42 $");
vtkStandardNewMacro(vtkKW3DMarkersWidget);

#ifdef KWCommonPro_USE_XML_RW
#include "XML/vtkXMLKW3DMarkersWidgetReader.h"
#include "XML/vtkXMLKW3DMarkersWidgetWriter.h"
#endif
vtkKWGetXMLReaderWriterObjectsImplementationMacro(vtkKW3DMarkersWidget, vtkXMLKW3DMarkersWidgetReader, vtkXMLKW3DMarkersWidgetWriter);

//----------------------------------------------------------------------------
class vtkMarkerWidgetCallback : public vtkCommand
{
public:
  static vtkMarkerWidgetCallback *New()
    { return new vtkMarkerWidgetCallback; }
  virtual void Execute(vtkObject *vtkNotUsed(caller), 
                       unsigned long event, void* vtkNotUsed(v))
    {
      switch (event) 
        {
        case vtkCommand::StartEvent:
          this->Self->OnStartRender();
          break;
        case vtkCommand::LeftButtonPressEvent:
          this->Self->OnLeftButtonDown();
          break;
        case vtkCommand::LeftButtonReleaseEvent:
          this->Self->OnLeftButtonUp();
          break;
        case vtkCommand::MouseMoveEvent:
          this->Self->OnMouseMove();
          break;
        }
    }
  vtkKW3DMarkersWidget *Self;
};
  
//----------------------------------------------------------------------------
vtkKW3DMarkersWidget::vtkKW3DMarkersWidget()
{
  this->MarkerWidgetCallback = vtkMarkerWidgetCallback::New();
  this->MarkerWidgetCallback->Self = this;

  // must have two callbacks due to reentrant abort pointer issues

  this->MarkerWidgetRenderCallback = vtkMarkerWidgetCallback::New();
  this->MarkerWidgetRenderCallback->Self = this;
  this->SelectedMarker = 0;
  this->SelectedMarkerIndex = -1;
  this->Priority = 0.55;

  this->CylinderSource = vtkCylinderSource::New();
  this->CylinderSource->SetResolution(9);
  this->CylinderMapper = vtkPolyDataMapper::New();
  this->CylinderMapper->SetInput(this->CylinderSource->GetOutput());

  this->State = vtkKW3DMarkersWidget::Start;

  // Manage the picking stuff

  this->Picker = vtkCellPicker::New();
  this->Picker->SetTolerance(0.005); //need some fluff
  this->Picker->PickFromListOn();

  double defaultGroupColor[3];
  
  defaultGroupColor[0] = 0.0;
  defaultGroupColor[1] = 1.0;
  defaultGroupColor[2] = 0.0;

  // This is a persistant markers group.

  this->DefaultGroupName = "Default"; 

  this->AddMarkersGroup(this->DefaultGroupName.c_str(), defaultGroupColor); 
  
}

//----------------------------------------------------------------------------
vtkKW3DMarkersWidget::~vtkKW3DMarkersWidget()
{
  this->RemoveAllMarkers();
  this->MarkerWidgetCallback->Delete();
  this->MarkerWidgetRenderCallback->Delete();
  
  this->CylinderSource->Delete();
  this->CylinderMapper->Delete();

  MarkersGroupPropertyContainer::iterator beginProperty = this->MarkersGroupProperty.begin();
  MarkersGroupPropertyContainer::iterator endProperty   = this->MarkersGroupProperty.end();
  MarkersGroupPropertyContainer::iterator property = beginProperty;
  while( property != endProperty )
    {
    (*property)->Delete();
    ++property;
    }

  this->MarkersGroupProperty.clear();

  this->Picker->Delete();
}

//----------------------------------------------------------------------------
unsigned int vtkKW3DMarkersWidget::GetDefaultMarkersGroupId() const 
{
  return this->GetMarkersGroupId(this->DefaultGroupName.c_str());
};

//----------------------------------------------------------------------------
void vtkKW3DMarkersWidget::OnLeftButtonDown()
{
  if (!this->Interactor)
    {
    return;
    }

  int X = this->Interactor->GetEventPosition()[0];
  int Y = this->Interactor->GetEventPosition()[1];
  
  // Okay, make sure that the pick is in the current renderer
  vtkRenderer *ren = this->Interactor->FindPokedRenderer(X,Y);
  if ( ren != this->CurrentRenderer )
    {
    this->State = vtkKW3DMarkersWidget::Outside;
    return;
    }
  
  // Okay, we can process this. Try to pick handles first;
  // if no handles picked, then try to pick the sphere.
  vtkAssemblyPath *path;
  this->Picker->Pick(X,Y,0.0,this->CurrentRenderer);
  path = this->Picker->GetPath();
  if ( path == NULL )
    {
    this->State = vtkKW3DMarkersWidget::Outside;
    return;
    }
  
  // did we find a marker?, if so which one?
  unsigned int i;
  for (i = 0; i < this->Markers.size(); ++i)
    {  
    if (path->GetFirstNode()->GetViewProp() == this->Markers[i])
      {
      this->SetSelectedMarker(this->Markers[i]);
      this->State = vtkKW3DMarkersWidget::Moving;
      break;
      }
    }
  
  this->StartInteraction();
  this->InvokeEvent(vtkCommand::StartInteractionEvent,NULL);
  this->Interactor->Render();
  this->MarkerWidgetCallback->SetAbortFlag(1);
}

//----------------------------------------------------------------------------
void vtkKW3DMarkersWidget::OnMouseMove()
{
  // See whether we're active
  if ( this->State == vtkKW3DMarkersWidget::Outside || 
       this->State == vtkKW3DMarkersWidget::Start )
    {
    return;
    }
  
  if (!this->Interactor)
    {
    return;
    }

  int X = this->Interactor->GetEventPosition()[0];
  int Y = this->Interactor->GetEventPosition()[1];

  // Do different things depending on state
  // Calculations everybody does
  double focalPoint[4], pickPoint[4], prevPickPoint[4];
  double z;

  vtkRenderer *renderer = this->Interactor->FindPokedRenderer(X,Y);
  vtkCamera *camera = renderer->GetActiveCamera();
  if ( !camera )
    {
    return;
    }

  // Compute the two points defining the motion vector
  camera->GetFocalPoint(focalPoint);
  this->ComputeWorldToDisplay(focalPoint[0], focalPoint[1],
                              focalPoint[2], focalPoint);
  z = focalPoint[2];
  this->ComputeDisplayToWorld(
    double(this->Interactor->GetLastEventPosition()[0]),
    double(this->Interactor->GetLastEventPosition()[1]),
    z, prevPickPoint);
  this->ComputeDisplayToWorld(double(X), double(Y), z, pickPoint);
  
  // Process the motion
  if ( this->State == vtkKW3DMarkersWidget::Moving )
    {
    //Get the motion vector
    double v[3];
    v[0] = pickPoint[0] - prevPickPoint[0];
    v[1] = pickPoint[1] - prevPickPoint[1];
    v[2] = pickPoint[2] - prevPickPoint[2];
    
    double *center = this->SelectedMarker->GetPosition();
    
    double center1[3];
    for (int i=0; i<3; i++)
      {
      center1[i] = center[i] + v[i];
      }
    
    this->SelectedMarker->SetPosition(center1);
    }

  // Interact, if desired
  this->Update3DMarkers();
  this->InvokeEvent(vtkCommand::InteractionEvent,NULL);
  this->Interactor->Render();

  this->MarkerWidgetCallback->SetAbortFlag(1);
}

//----------------------------------------------------------------------------
void vtkKW3DMarkersWidget::OnLeftButtonUp()
{
  if ( this->State == vtkKW3DMarkersWidget::Outside )
    {
    return;
    }

  this->State = vtkKW3DMarkersWidget::Start;

  this->EndInteraction();
  this->InvokeEvent(vtkCommand::EndInteractionEvent,NULL);
  if (this->Interactor)
    {
    this->Interactor->Render();
    }

  this->MarkerWidgetCallback->SetAbortFlag(1);
}

//----------------------------------------------------------------------------
void vtkKW3DMarkersWidget::OnStartRender()
{
  // if we are in a volumewidget then there might be a scaling involved
  double scale = 1.0;
  if (this->GetParent())
    {
    vtkKWVolumeWidget *vw = vtkKWVolumeWidget::SafeDownCast(this->GetParent());
    if (vw)
      {
      //scale = vw->GetRenderScale();
      }
    }
  
  // scale the sphere if neccessary
  if (this->CurrentRenderer)
    {
    unsigned int i, j;
    for (i = 0; i < this->Markers.size(); ++i)
      {
      double *pos = this->Markers[i]->GetPosition();
    
      // what radius do we need for the resulting size
      double center[4];
      double NewPickPoint[4];
      // project the center to the display
      center[0] = pos[0];
      center[1] = pos[1];
      center[2] = pos[2];
      center[3] = 1.0;
      this->ComputeWorldToDisplay(center[0], center[1], center[2], 
                                  NewPickPoint);
      // then move one pixel away from the center and compute the world coords
      this->ComputeDisplayToWorld(NewPickPoint[0]+1.0, 
                                  NewPickPoint[1], NewPickPoint[2],
                                  NewPickPoint);
      // what is the radius hat results in one pixel difference
      double dist = sqrt(vtkMath::Distance2BetweenPoints(center,NewPickPoint));
      // make x and z scale to cover 5 pixels then y scale to be 1 percent of
      // the clipping range
      vtkCamera *camera = this->CurrentRenderer->GetActiveCamera();
      double *clippingRange = camera->GetClippingRange();
      this->Markers[i]->SetScale(10.0*dist/scale,
                                 0.01*(clippingRange[1] - clippingRange[0]),
                                 10.0*dist/scale);
      
      // we must orient the marker to face the camera
      double Rx[3], Rz[3];
      double *cpos = camera->GetPosition();
      
      if (camera->GetParallelProjection())
        {
        camera->GetDirectionOfProjection(Rz);
        Rz[0] = -Rz[0];
        Rz[1] = -Rz[1];
        Rz[2] = -Rz[2];
        }
      else
        {
        double distance = sqrt(
          (cpos[0] - pos[0])*(cpos[0] - pos[0]) +
          (cpos[1] - pos[1])*(cpos[1] - pos[1]) +
          (cpos[2] - pos[2])*(cpos[2] - pos[2]));
        for (j = 0; j < 3; j++)
          {
          Rz[j] = (cpos[j] - pos[j])/distance;
          }
        }
      
      this->Markers[i]->SetOrientation(0,0,0);
      double yaxis[3];
      yaxis[0] = 0;
      yaxis[1] = 1;
      yaxis[2] = 0;
      vtkMath::Cross(yaxis,Rz,Rx);
      vtkMath::Normalize(Rx);
      this->Markers[i]->RotateWXYZ(
        180.0*acos(vtkMath::Dot(yaxis,Rz))/3.1415926, 
        Rx[0], Rx[1], Rx[2]);
      }
    }
}

//----------------------------------------------------------------------------
void vtkKW3DMarkersWidget::SetSelectedMarker(vtkActor *sw)
{
  if (this->SelectedMarker == sw)
    {
    return;
    }
  
  vtkActor *tmp = this->SelectedMarker;
  this->SelectedMarker = sw;
  this->SelectedMarkerIndex = -1;
  
  if (sw)
    {
    sw->Register(this);
    // find the SelectedMarkerIndex
    unsigned int i;
    for (i = 0; i < this->Markers.size(); ++i)
      {
      if (this->SelectedMarker == this->Markers[i])
        {
        this->SelectedMarkerIndex = i;
        }
      }
    }
  if (tmp)
    {
    tmp->UnRegister(this);
    }
  
  this->Modified();
}

//----------------------------------------------------------------------------
void vtkKW3DMarkersWidget::SetMarkerPosition(unsigned int id, 
                                             double x, double y, double z)
{
  if (id < this->Markers.size())
    {
    this->Markers[id]->SetPosition(x, y, z);
    this->SetSelectedMarker(this->Markers[id]);
    }
}

//----------------------------------------------------------------------------
double* vtkKW3DMarkersWidget::GetMarkerPosition(unsigned int id)
{
  if (id < this->Markers.size())
    {
    return this->Markers[id]->GetPosition();
    }

  return 0;
}

//----------------------------------------------------------------------------
int vtkKW3DMarkersWidget::AddMarker(unsigned int gid, 
                                    double x, double y, double z)
{
  if (gid >= this->MarkersGroupNames.size())
    {
    return -1;
    }

  vtkActor *pw = vtkActor::New();
  pw->SetMapper( this->CylinderMapper );
  pw->SetProperty( this->MarkersGroupProperty[ gid ] );
  this->Markers.push_back(pw);
  this->MarkersGroupIds.push_back( gid );
  pw->SetPosition(x,y,z);
  this->Picker->AddPickList(pw);
  if (this->CurrentRenderer && this->Enabled)
    {
    this->CurrentRenderer->AddViewProp(pw);
    }
  // make the last added marker selected
  this->SetSelectedMarker(pw);
  
  // pw->Delete() -- no delete because the vector has it

  return (int)this->Markers.size() - 1;
}

//----------------------------------------------------------------------------
int vtkKW3DMarkersWidget::HasMarker(unsigned int gid, 
                                    double x, double y, double z)
{
  return (this->GetMarkerId(gid, x, y, z) >= 0 ? 1 : 0);
}

//----------------------------------------------------------------------------
int vtkKW3DMarkersWidget::GetMarkerId(unsigned int gid, 
                                      double x, double y, double z)
{
  unsigned int i;
  for (i = 0; i < this->Markers.size(); ++i)
    {
    double *center = this->Markers[i]->GetPosition();
    if (gid == this->MarkersGroupIds[i] && 
        center[0] == x && center[1] == y && center[2] == z)
      {
      return (int)i;
      }
    }
  
  return -1;
}

//----------------------------------------------------------------------------
int vtkKW3DMarkersWidget::GetMarkerGroupId(unsigned int id) const
{
  if (id < this->MarkersGroupIds.size())
    {
    return this->MarkersGroupIds[id];
    }
  return -1;
}

//----------------------------------------------------------------------------
int vtkKW3DMarkersWidget::DeallocateMarkerResources(unsigned int id)
{
  if (id < this->Markers.size())
    {
    if (this->CurrentRenderer)
      {
      this->CurrentRenderer->RemoveViewProp(this->Markers[id]);
      }
    this->Picker->DeletePickList(this->Markers[id]);
    this->Markers[id]->Delete();
    return 1;
    }

  return 0;
}

//----------------------------------------------------------------------------
int vtkKW3DMarkersWidget::RemoveMarker(unsigned int id)
{
  if (id < this->Markers.size())
    {
    this->DeallocateMarkerResources(id);

    MarkersContainer::iterator it = this->Markers.begin() + id;
    this->Markers.erase(it);
    MarkersGroupIdsContainer::iterator gt = this->MarkersGroupIds.begin() + id;
    this->MarkersGroupIds.erase(gt);
    return 1;
    }

  return 0;
}

//----------------------------------------------------------------------------
int vtkKW3DMarkersWidget::RemoveSelectedMarker()
{
  int status = 0;

  if (this->SelectedMarker)
    {
    typedef MarkersContainer::iterator MarkersIterator;
    MarkersIterator begin = this->Markers.begin();
    MarkersIterator end   = this->Markers.end();
    MarkersIterator found = vtkstd::find(begin, end, this->SelectedMarker);

    if (found != end)
      {
      this->RemoveMarker(found - begin);
      status = 1;
      }
    }

  this->SetSelectedMarker(0);
  return status;
}

//----------------------------------------------------------------------------
int vtkKW3DMarkersWidget::RemoveAllMarkers()
{
  this->SetSelectedMarker(0);

  int size = (int)this->Markers.size();

  unsigned int id;
  for (id = 0; id < this->Markers.size(); ++id)
    {
    this->DeallocateMarkerResources(id);
    }

  // Clear everything

  this->Markers.clear();
  this->MarkersGroupIds.clear();

  return size;
}

//----------------------------------------------------------------------------
int vtkKW3DMarkersWidget::RemoveAllMarkersInGroup( unsigned int gid )
{
  this->SetSelectedMarker(0);

  typedef MarkersContainer::iterator MarkersIterator;
  MarkersIterator markerItrBegin = this->Markers.begin();
  MarkersIterator markerItr = markerItrBegin;
  
  typedef MarkersGroupIdsContainer::iterator MarkersGroupIterator;
  MarkersGroupIterator markerGroupItr = this->MarkersGroupIds.begin();
    
  int numberOfMarkersRemoved = 0;

  while (markerGroupItr != this->MarkersGroupIds.end() &&
         markerItr      != this->Markers.end())
    {
    if (*markerGroupItr == gid) // remove if it belongs to this group
      {
      unsigned int id = markerItr - markerItrBegin;
      this->DeallocateMarkerResources(id);

      markerItr      = this->Markers.erase( markerItr );     
      markerGroupItr = this->MarkersGroupIds.erase( markerGroupItr );

      numberOfMarkersRemoved++;
      }
    else
      {
      markerItr++;
      markerGroupItr++;
      }
    }

  return numberOfMarkersRemoved;
}

//----------------------------------------------------------------------------
int vtkKW3DMarkersWidget::AddMarkersGroup(
  const char * group_name, const double * color)
{
  if (group_name == NULL || color == NULL)
    {
    return -1;
    }

  if (this->HasMarkersGroup(group_name))
    {
    int gid = this->GetMarkersGroupId(group_name);
    this->SetMarkersGroupColor(gid, color);
    return gid;
    }

  std::string name = group_name;

  this->MarkersGroupNames.push_back(name);

  vtkProperty *cylinderProperty = vtkProperty::New();
  cylinderProperty->SetColor(color[0], color[1], color[2]);
  cylinderProperty->SetAmbient(1);
  cylinderProperty->SetDiffuse(0);

  // Group color is inserted in three components
  this->MarkersGroupProperty.push_back(cylinderProperty);

  return (int)this->MarkersGroupNames.size() - 1;
}

//----------------------------------------------------------------------------
int vtkKW3DMarkersWidget::GetMarkersGroupId(const char *group_name) const
{
  if (group_name == NULL)
    {
    return -1;
    }

  MarkersGroupNameType name(group_name);
  typedef MarkersGroupNameContainer::const_iterator GroupsIterator;
  GroupsIterator beg = this->MarkersGroupNames.begin();
  GroupsIterator end = this->MarkersGroupNames.end();
  GroupsIterator it  = vtkstd::find( beg, end, name );

  return (it != end) ? (it - beg) : -1;
}

//----------------------------------------------------------------------------
int vtkKW3DMarkersWidget::HasMarkersGroup(const char *group_name)
{
  return (this->GetMarkersGroupId(group_name) >= 0) ? 1 : 0;
}

//----------------------------------------------------------------------------
int vtkKW3DMarkersWidget::RemoveMarkersGroup(const char * group_name)
{
  if (group_name == NULL)
    {
    return 0;
    }

  // The Default group should not be deleted

  MarkersGroupNameType name = group_name;
  if( name == this->DefaultGroupName )
    {
    return 0;
    }

  typedef MarkersGroupNameContainer::iterator GroupsIterator;
  GroupsIterator beg = this->MarkersGroupNames.begin();
  GroupsIterator end = this->MarkersGroupNames.end();
  GroupsIterator die = vtkstd::find( beg, end, name );

  if( die == end )
    {
    return 0;
    }

  unsigned int gid = die - beg;
  
  // The following call includes to remove all the markers that were associated
  // to this group
  const int status = this->RemoveMarkersGroup( gid );

  return status;
}


//----------------------------------------------------------------------------
int vtkKW3DMarkersWidget::RemoveMarkersGroup(unsigned int gid)
{
  if (gid < this->MarkersGroupNames.size())
    {
    // Remove the markers associated to this group.
    this->RemoveAllMarkersInGroup(gid);
    MarkersGroupNameContainer::iterator it = 
      this->MarkersGroupNames.begin() + gid;
    this->MarkersGroupNames.erase(it);

    // Since we just moved the name one row up, we have to update the
    // arrays of "marker to group id" accordingly (one up).

    typedef MarkersGroupIdsContainer::iterator MarkersGroupIterator;
    MarkersGroupIterator markerGroupItr = this->MarkersGroupIds.begin();
    while (markerGroupItr != this->MarkersGroupIds.end())
      {
      if (*markerGroupItr > gid) // remove if it belongs to this group
        {
        (*markerGroupItr)--;
        }
      markerGroupItr++;
      }
    }
  else
    {
    return 0;
    }
  
  if (gid < this->MarkersGroupProperty.size())
    {
    MarkersGroupPropertyContainer::iterator it = 
      this->MarkersGroupProperty.begin() + gid;
    (*it)->Delete();
    this->MarkersGroupProperty.erase( it );
    }
  else
    {
    return 0;
    }

  return 1; // returns 1 if the group was successfully removed
}

//----------------------------------------------------------------------------
int vtkKW3DMarkersWidget::RemoveAllMarkersGroups()
{
  for(unsigned int i=0; i< this->MarkersGroupNames.size(); i++ )
    {
    this->RemoveMarkersGroup(this->GetMarkersGroupName(i));
    }

  int res = (int)(this->MarkersGroupNames.size() +
                  this->MarkersGroupProperty.size());

  return ( res != 2 ); // the Default group should be immortal
}


//----------------------------------------------------------------------------
unsigned int 
vtkKW3DMarkersWidget::GetNumberOfMarkersGroups() const
{
  return (unsigned int)this->MarkersGroupNames.size();
}


//----------------------------------------------------------------------------
const char *
vtkKW3DMarkersWidget::GetMarkersGroupName(unsigned int gid) const
{
  if( gid >= this->GetNumberOfMarkersGroups() )
    {
    return 0;
    }
  return  this->MarkersGroupNames[gid].c_str();
}


//----------------------------------------------------------------------------
double *
vtkKW3DMarkersWidget::GetMarkersGroupColor(unsigned int gid) const
{
  if(gid >= this->GetNumberOfMarkersGroups())
    {
    return NULL;
    }
  else
    {
    return this->MarkersGroupProperty[gid]->GetColor();
    }
}


//----------------------------------------------------------------------------
void vtkKW3DMarkersWidget::SetEnabled(int enabling)
{
  if ( ! this->Interactor )
    {
    vtkErrorMacro(<<"The interactor must be set prior to enabling/disabling widget");
    return;
    }
  
  if ( enabling ) 
    {
    vtkDebugMacro(<<"Enabling distance widget");
    if ( this->Enabled ) //already enabled, just return
      {
      return;
      }
    
    this->SetCurrentRenderer( 
      this->Interactor->FindPokedRenderer(
        this->Interactor->GetLastEventPosition()[0],
        this->Interactor->GetLastEventPosition()[1]));
    if (this->CurrentRenderer == NULL)
      {
      return;
      }
    
    this->Enabled = 1;
    this->CurrentRenderer->AddObserver(vtkCommand::StartEvent, 
                                       this->MarkerWidgetRenderCallback, 
                                       this->Priority);
    this->Interactor->AddObserver(vtkCommand::MouseMoveEvent, 
                                  this->MarkerWidgetCallback, this->Priority);
    this->Interactor->AddObserver(vtkCommand::LeftButtonPressEvent, 
                                  this->MarkerWidgetCallback, this->Priority);
    this->Interactor->AddObserver(vtkCommand::LeftButtonReleaseEvent, 
                                  this->MarkerWidgetCallback, this->Priority);
    
    // Add the markers
    unsigned int j;
    for (j = 0; j < this->Markers.size(); ++j)
      {
      this->CurrentRenderer->AddViewProp(this->Markers[j]);
      }
    this->InvokeEvent(vtkCommand::EnableEvent,NULL);
    }
  else //disabling------------------------------------------
    {
    vtkDebugMacro(<<"Disabling 3D markers widget");
    if ( ! this->Enabled ) //already disabled, just return
      {
      return;
      }
    this->Enabled = 0;

    // don't listen for events any more
    this->CurrentRenderer->RemoveObserver(this->MarkerWidgetRenderCallback);
    this->Interactor->RemoveObserver(this->MarkerWidgetCallback);
    unsigned int i;
    for (i = 0; i < this->Markers.size(); ++i)
      {
      this->CurrentRenderer->RemoveViewProp(this->Markers[i]);
      }
    this->InvokeEvent(vtkCommand::DisableEvent,NULL);
    }
  this->Interactor->Render();
}

//----------------------------------------------------------------------------
void vtkKW3DMarkersWidget::Update3DMarkers()
{
  if (this->SelectedMarker)
    {
    float vals[4];
    vals[0] = this->SelectedMarkerIndex;
    double *pos = this->SelectedMarker->GetPosition();
    vals[1] = pos[0];
    vals[2] = pos[1];
    vals[3] = pos[2];
    this->InvokeEvent(vtkKWEvent::Marker3DPositionChangedEvent,vals);
    }                 
}

//----------------------------------------------------------------------------
void vtkKW3DMarkersWidget::SetMarkersGroupColor(unsigned int gid, 
                                                double r, double g, double b)
{
  if (gid < this->MarkersGroupProperty.size())
    {
    // update the color in the property container for the current group
    vtkProperty *property = this->MarkersGroupProperty[gid];
    property->SetColor( r, g, b );
    }
}


//----------------------------------------------------------------------------
unsigned int vtkKW3DMarkersWidget::GetNumberOfMarkers()
{
  return (unsigned int)this->Markers.size();
}

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

  os << indent << "SelectedMarkerIndex: " << this->SelectedMarkerIndex << endl;
}
