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

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

#include "vtkObjectFactory.h"
#include "vtkKWApplication.h"
#include "vtkKWWindow.h"
#include "vtkKWPushButton.h"
#include "vtkKWFrame.h"
#include "vtkKWLabel.h"
#include "vtkKWInternationalization.h"
#include "vtkKWTkUtilities.h"

//----------------------------------------------------------------------------
vtkStandardNewMacro( vtkKWWizard );
vtkCxxRevisionMacro(vtkKWWizard, "$Revision: 1.43 $");

//----------------------------------------------------------------------------
vtkKWWizard::vtkKWWizard()
{
  this->Done = 1;
  this->Beep = 0;
  this->BeepType = 0;

  this->ButtonFrame = 0;
  this->LayoutFrame = 0;
  this->Sep1 = 0;
  this->HelpButton = 0;
  this->NextButton = 0;
  this->BackButton = 0;
  this->CancelButton = 0;
  this->FinishButton = 0;
  this->ClientArea = 0;
  this->PreTextLabel = 0;
  this->PostTextLabel = 0;
  this->Sep2 = 0;
  this->TitleFrame = 0;
  this->TitleLabel = 0;
  this->SubTitleLabel = 0;
  this->Icon = 0;
}

//----------------------------------------------------------------------------
vtkKWWizard::~vtkKWWizard()
{
  if (this->ButtonFrame)
    {
    this->ButtonFrame->Delete();
    this->ButtonFrame = 0;
    }
  
  if (this->LayoutFrame)
    {
    this->LayoutFrame->Delete();
    this->LayoutFrame = 0;
    }
  
  if (this->Sep1)
    {
    this->Sep1->Delete();
    this->Sep1 = 0;
    }
  
  if (this->HelpButton)
    {
    this->HelpButton->Delete();
    this->HelpButton = 0;
    }
  
  if (this->NextButton)
    {
    this->NextButton->Delete();
    this->NextButton = 0;
    }
  
  if (this->BackButton)
    {
    this->BackButton->Delete();
    this->BackButton = 0;
    }
  
  if (this->CancelButton)
    {
    this->CancelButton->Delete();
    this->CancelButton = 0;
    }
  
  if (this->FinishButton)
    {
    this->FinishButton->Delete();
    this->FinishButton = 0;
    }
  
  if (this->ClientArea)
    {
    this->ClientArea->Delete();
    this->ClientArea = 0;
    }
  
  if (this->PreTextLabel)
    {
    this->PreTextLabel->Delete();
    this->PreTextLabel = 0;
    }
  
  if (this->PostTextLabel)
    {
    this->PostTextLabel->Delete();
    this->PostTextLabel = 0;
    }
  
  if (this->Sep2)
    {
    this->Sep2->Delete();
    this->Sep2 = 0;
    }
  
  if (this->TitleFrame)
    {
    this->TitleFrame->Delete();
    this->TitleFrame = 0;
    }
  
  if (this->TitleLabel)
    {
    this->TitleLabel->Delete();
    this->TitleLabel = 0;
    }
  
  if (this->SubTitleLabel)
    {
    this->SubTitleLabel->Delete();
    this->SubTitleLabel = 0;
    }
  
  if (this->Icon)
    {
    this->Icon->Delete();
    this->Icon = 0;
    }
}

//----------------------------------------------------------------------------
int vtkKWWizard::Invoke()
{
  this->Done = 0;

  this->GetApplication()->RegisterDialogUp(this);

  int width, height, x, y;
  int sw, sh;
  this->Script("concat [ winfo screenwidth . ] [ winfo screenheight . ]");
  sscanf(this->GetApplication()->GetMainInterp()->result,
         "%d %d", &sw, &sh);
  x = sw / 2;
  y = sh / 2;

  this->GetSize(&width, &height);
  if ( x > width/2 )
    {
    x -= width/2;
    }
  if ( y > height/2 )
    {
    y -= height/2;
    }

  this->SetPosition(x, y);

  this->Display();
  this->Grab();

  if ( this->Beep )
    {
    this->Script("bell");
    }

  this->BackButton->SetEnabled(0);

  // clear out any lingering BackButtonCommands
  while (!this->BackButtonCommands.empty())
    {
    this->BackButtonCommands.pop();
    }
  this->FinishButton->SetEnabled(0);
  
  // do a grab
  // wait for the end
  while (!this->Done)
    {
    Tcl_DoOneEvent(0);    
    }
  this->ReleaseGrab();

  this->GetApplication()->UnRegisterDialogUp(this);
  return (this->Done-1);
}

//----------------------------------------------------------------------------
void vtkKWWizard::Display()
{
  this->Done = 0;

  this->Superclass::Display();
}

//----------------------------------------------------------------------------
void vtkKWWizard::Cancel()
{
  this->Withdraw();
  this->ReleaseGrab();
  this->Done = 1;  
}

//----------------------------------------------------------------------------
void vtkKWWizard::OK()
{
  this->Withdraw();
  this->ReleaseGrab();
  this->Done = 2;  
}

//----------------------------------------------------------------------------
void vtkKWWizard::CloseCallback()
{
  // This callback is called when the Wizard is closed using the
  // close icon of the window decoration (WM_DELETE_WINDOW protocol)
  // It should call Cancel(), but ideally it should match the state
  // of the Cancel button. Let's check its state

  if (!this->CancelButton || this->CancelButton->GetEnabled())
    {
    this->Cancel();
    }
}

//----------------------------------------------------------------------------
void vtkKWWizard::LastStep()
{
  this->PropagateEnableState(this->FinishButton);
  this->PropagateEnableState(this->NextButton);
  this->NextButton->SetCommand(this,"OK");
}

//----------------------------------------------------------------------------
void vtkKWWizard::NoNextStep()
{
  this->FinishButton->SetEnabled(0);
  this->NextButton->SetEnabled(0);
}

//----------------------------------------------------------------------------
void vtkKWWizard::BackButtonAction()
{
  // look at the history to see where to go
  if (this->BackButtonCommands.empty())
    {
    return;
    }
  vtkstd::string cmd = this->BackButtonCommands.top();

  // disable finish since we backed up
  this->FinishButton->SetEnabled(0);

  // remove the last command
  this->BackButtonCommands.pop();
  
  if (this->BackButtonCommands.empty())
    {
    this->BackButton->SetEnabled(0);
    }
  
  // execute the command
  this->Script("%s %s",this->GetTclName(),cmd.c_str());
}

//----------------------------------------------------------------------------
void vtkKWWizard::AddBackButtonCommand(const char *cmd)
{
  if (cmd)
    {
    this->PropagateEnableState(this->BackButton);
    this->BackButtonCommands.push(cmd);
    }
}

//----------------------------------------------------------------------------
void vtkKWWizard::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();

  const char *wname = this->GetWidgetName();

  this->Script("pack propagate %s 0", wname);
  
  this->SetDeleteWindowProtocolCommand(this, "CloseCallback");

  this->SetSize(500, 340);

  this->Withdraw();
  
  // create and parent the widgets

  this->ButtonFrame = vtkKWFrame::New();
  this->LayoutFrame = vtkKWFrame::New();
  this->Sep1 = vtkKWFrame::New();

  this->HelpButton = vtkKWPushButton::New();
  this->NextButton = vtkKWPushButton::New();
  this->BackButton = vtkKWPushButton::New();
  this->CancelButton = vtkKWPushButton::New();
  this->FinishButton = vtkKWPushButton::New();

  this->ClientArea = vtkKWFrame::New();

  this->PreTextLabel = vtkKWLabel::New();

  this->PostTextLabel = vtkKWLabel::New();

  this->Sep2 = vtkKWFrame::New();
  this->TitleFrame = vtkKWFrame::New();
  this->TitleLabel = vtkKWLabel::New();
  this->SubTitleLabel = vtkKWLabel::New();
  this->Icon = vtkKWLabel::New();

  this->ButtonFrame->SetParent(this);
  this->ButtonFrame->Create();
  this->ButtonFrame->SetBorderWidth(0);

  this->LayoutFrame->SetParent(this);
  this->LayoutFrame->Create();
  this->LayoutFrame->SetBorderWidth(0);

  this->Sep1->SetParent(this);
  this->Sep1->Create();
  this->Sep1->SetHeight(2);
  this->Sep1->SetBorderWidth(2);
  this->Sep1->SetReliefToGroove();

  this->Script("pack %s -side bottom -fill x", 
               this->ButtonFrame->GetWidgetName());
  this->Script("pack %s -side bottom -fill x", 
               this->Sep1->GetWidgetName());
  this->Script("pack %s -side top -fill both -expand y", 
               this->LayoutFrame->GetWidgetName());

  this->HelpButton->SetParent(this->ButtonFrame);
  this->HelpButton->SetText(ks_("Wizard|Button|Help"));
  this->HelpButton->Create();

  this->BackButton->SetParent(this->ButtonFrame);
  vtkstd::string back("< ");
  back += ks_("Wizard|Button|Back");
  this->BackButton->SetText(back.c_str());
  this->BackButton->Create();
  this->BackButton->SetWidth(8);
  this->BackButton->SetCommand(this,"BackButtonAction");
  
  this->NextButton->SetParent(this->ButtonFrame);
  vtkstd::string next(ks_("Wizard|Button|Next"));
  next += " >";
  this->NextButton->SetText(next.c_str());
  this->NextButton->Create();
  this->NextButton->SetWidth(8);

  this->FinishButton->SetParent(this->ButtonFrame);
  this->FinishButton->SetText(ks_("Wizard|Button|Finish"));
  this->FinishButton->Create();
  this->FinishButton->SetWidth(8);
  this->FinishButton->SetCommand(this,"OK");

  this->CancelButton->SetParent(this->ButtonFrame);
  this->CancelButton->SetText(ks_("Wizard|Button|Cancel"));
  this->CancelButton->Create();
  this->CancelButton->SetWidth(8);
  this->CancelButton->SetCommand(this,"Cancel");
  
  this->Script("pack %s -side right -padx 4 -pady 8", 
               this->CancelButton->GetWidgetName());
  this->Script("pack %s -side right -padx 4 -pady 8", 
               this->FinishButton->GetWidgetName());
  this->Script("pack %s -side right -pady 8", 
               this->NextButton->GetWidgetName());
  this->Script("pack %s -side right -pady 8", 
               this->BackButton->GetWidgetName());

  this->TitleFrame->SetParent(this->LayoutFrame);
  this->TitleFrame->Create();
  this->TitleFrame->SetBackgroundColor(1.0, 1.0, 1.0);
  
  this->Sep2->SetParent(this->LayoutFrame);
  this->Sep2->Create();
  this->Sep2->SetHeight(2);
  this->Sep2->SetBorderWidth(2);
  this->Sep2->SetReliefToGroove();

  this->PreTextLabel->SetParent(this->LayoutFrame);
  this->PreTextLabel->Create();
  this->PreTextLabel->AdjustWrapLengthToWidthOn();
  this->PreTextLabel->SetPadX(0);

  this->ClientArea->SetParent(this->LayoutFrame);
  this->ClientArea->Create();

  this->PostTextLabel->SetParent(this->LayoutFrame);
  this->PostTextLabel->Create();
  this->PostTextLabel->AdjustWrapLengthToWidthOn();
  this->PostTextLabel->SetPadX(0);
  
  this->Script("grid %s -row 0 -column 0 -sticky nsew -padx 0 -pady 0",
               this->TitleFrame->GetWidgetName());
  this->Script("grid %s -row 1 -column 0 -sticky ew",
               this->Sep2->GetWidgetName());
  this->Script("grid %s -row 2 -column 0 -sticky news -padx 6 -pady 4",
               this->PreTextLabel->GetWidgetName());
  this->Script("grid %s -row 3 -column 0 -sticky news -padx 6 -pady 4",
               this->ClientArea->GetWidgetName());
  this->Script("grid %s -row 4 -column 0 -sticky news -padx 6 -pady 4",
               this->PostTextLabel->GetWidgetName());
  
  this->Script("grid columnconfigure %s 0 -weight 1", 
               this->LayoutFrame->GetWidgetName());
  this->Script("grid rowconfigure %s 0 -weight 0",
               this->LayoutFrame->GetWidgetName());
  this->Script("grid rowconfigure %s 1 -weight 0",
               this->LayoutFrame->GetWidgetName());
  this->Script("grid rowconfigure %s 2 -weight 0",
               this->LayoutFrame->GetWidgetName());
  this->Script("grid rowconfigure %s 3 -weight 1",
               this->LayoutFrame->GetWidgetName());
  this->Script("grid rowconfigure %s 4 -weight 0",
               this->LayoutFrame->GetWidgetName());
  
  this->TitleLabel->SetParent(this->TitleFrame);
  this->TitleLabel->SetText("Title");
  this->TitleLabel->Create();
  this->TitleLabel->SetBackgroundColor(1.0, 1.0, 1.0);

  vtkKWTkUtilities::ChangeFontWeightToBold(this->TitleLabel);

  this->SubTitleLabel->SetParent(this->TitleFrame);
  this->SubTitleLabel->SetText("SubTitle");
  this->SubTitleLabel->Create();
  this->SubTitleLabel->SetAnchorToNorthWest();
  this->SubTitleLabel->SetConfigurationOptionAsInt("-height", 2);
  this->SubTitleLabel->SetBackgroundColor(1.0, 1.0, 1.0);
  this->SubTitleLabel->SetPadX(15);

  this->Icon->SetParent(this->TitleFrame);
  this->Icon->Create();
  this->Icon->SetReliefToFlat();
  this->Icon->SetForegroundColor(1.0, 1.0, 1.0);
  this->Icon->SetBackgroundColor(1.0, 1.0, 1.0);
  this->Icon->SetHighlightThickness(0);
  this->Icon->SetPadX(0);
  this->Icon->SetPadY(0);

  this->Script("grid %s -row 0 -column 0 -sticky w -padx 4 -pady 2",
               this->TitleLabel->GetWidgetName());
  this->Script("grid %s -row 1 -column 0 -sticky nw -padx 4",
               this->SubTitleLabel->GetWidgetName());
  this->Script("grid %s -row 0 -column 1 -sticky nsew -rowspan 2 -padx 8",
               this->Icon->GetWidgetName());

  this->Script("grid columnconfigure %s 0 -weight 1",
               this->TitleFrame->GetWidgetName());
  this->Script("grid columnconfigure %s 1 -weight 0",
               this->TitleFrame->GetWidgetName());
  this->Script("grid rowconfigure %s 0 -weight 0",
               this->TitleFrame->GetWidgetName());
  this->Script("grid rowconfigure %s 1 -weight 1",
               this->TitleFrame->GetWidgetName());

  // the pre and post text will initially not be visible. They will pop into
  // existence if they are configured to have a value
  this->Script("grid remove %s %s",
               this->PreTextLabel->GetWidgetName(),
               this->PostTextLabel->GetWidgetName());
}

//----------------------------------------------------------------------------
void vtkKWWizard::ForgetClientArea()
{
  if (this->ClientArea)
    {
    this->Script("pack forget [pack slaves %s]",
                 this->ClientArea->GetWidgetName());
    }
}

//----------------------------------------------------------------------------
void vtkKWWizard::ClearPage()
{
  this->ForgetClientArea();
  this->SetPreText(0);
  this->SetPostText(0);
}

//----------------------------------------------------------------------------
void vtkKWWizard::SetPreText(const char* str)
{
  if (this->PreTextLabel)
    {
    this->PreTextLabel->SetText(str);
    }

  if (this->IsCreated())
    {
    this->Script("grid %s %s",
                 ((str && *str) ? "" : "remove"),
                 this->PreTextLabel->GetWidgetName());
    }
}

//----------------------------------------------------------------------------
char* vtkKWWizard::GetPreText()
{
  return this->PreTextLabel->GetText();
}

//----------------------------------------------------------------------------
void vtkKWWizard::SetPostText(const char* str)
{
  this->PostTextLabel->SetText(str);

  if (this->IsCreated())
    {
    this->Script("grid %s %s",
                 ((str && *str) ? "" : "remove"),
                 this->PostTextLabel->GetWidgetName());
    }
}

//----------------------------------------------------------------------------
char* vtkKWWizard::GetPostText()
{
  return this->PostTextLabel->GetText();
}

//----------------------------------------------------------------------------
void vtkKWWizard::SetEnabledButtons(int arg)
{
  this->HelpButton->SetEnabled(arg);
  this->NextButton->SetEnabled(arg);
  this->BackButton->SetEnabled(arg);
  this->CancelButton->SetEnabled(arg);
  this->FinishButton->SetEnabled(arg);
}

//----------------------------------------------------------------------------
void vtkKWWizard::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);
  os << indent << "Beep: " << this->GetBeep() << endl;
  os << indent << "BeepType: " << this->GetBeepType() << endl;
  os << indent << "Icon: " << this->GetIcon() << endl;
}
