#
#
# 	Copyright (c) 1997, 1998, 1999, 2000    Spatial Software Solutions, Inc.
#
#	File:		Dialog.pm
#	Project:	MEL
#	Author:		MJD
#	Date:		10-17-00
#	Purpose:	SmartWindows MEL base class module
#				Yank in all relevant required modules
#
#	SccsId:		$RCSfile$	v$Revision: 16619 $	$Date: 2005-06-08 22:43:21 -0400 (Wed, 08 Jun 2005) $
#

package Dialog;
use Carp;
use MWS::Inherit;
use Data::Dumper;

use vars qw(@ISA);
@ISA = qw ( MWS::Inherit );

######################################################################
## Package Globals
##
$PackageName = "Dialog";
$debug = 0;
$firstPass = 1;
$registered = 0;
$id = 0;

######################################################################
## Package Constants
##
%constants = (
			 );

######################################################################
## Initialization code
##
if($firstPass){
	if(scalar(%constants)){
		MWS::RegisterConstants(\%constants);
	}
	print "$PackageName: RegisterConstants ok.\n";
	$firstPass = 0;
}else{
	print "$PackageName: RegisterConstants complete.\n";
}

if($Dialog::debug){
	print "$PackageName: my members: ", \%members, "\n";
}

######################################################################
## Member data
##
%members = (
#            'binders' => {},
#            'widgets' => {},
           );

######################################################################
## Copy methods for member data
##
%copyMethod = (
			   %MWS::Inherit::copyMethod,
               'binders' => MWS::REF_COPY,
               'widgets' => MWS::REF_COPY,
			  );


######################################################################
## Package Code
##

sub SetDebug {
  my $dbg = shift;

  $Dialog::debug = $dbg;
}

sub AttachObject {
  my $self = shift;
  my $obj = shift;
  my $widgetMap = shift;
#  print "SetData: Dumper(obj): ", Dumper($obj), "\n";

  use Gtk2::Ex::BindScalar;

  foreach my $k (keys %$obj){
    if(exists $widgetMap->{$k}){
      my $widg = $widgetMap->{$k};
      if(! exists $self->{'binders'}->{$widg}){
        $self->{'binders'}->{$widg} = 
            Gtk2::Ex::BindScalar->create(\$obj->{$k}, 
                                         $self->{'glade'}->get_widget($widg));
      }else{
        $self->{'binders'}->{$widg}->bind_var(\$obj->{$k});
      }
      print "[$widg:$k]: $obj->{$k}\n" if($Dialog::debug > 3);
    }
  }
}

sub Initialize {
  my $self = shift;

  $self->{'id'} = $Dialog::id++;
}

sub Attach {
  my $self = shift;
  my $widg = shift;
  my $obj = shift;
#  print "SetData: Dumper(obj): ", Dumper($obj), "\n";

  use Gtk2::Ex::BindScalar;

  if(! exists $self->{'binders'}->{$widg}){
    $self->{'binders'}->{$widg} = 
        Gtk2::Ex::BindScalar->create($obj,$self->{'glade'}->get_widget($widg));
  }else{
    $self->{'binders'}->{$widg}->bind_var($obj);
  }
  print "[$widg:$k]: $obj->{$k}\n" if($Dialog::debug > 3);
}

sub PackPair {
  my $self = shift;
  my $box = shift;
  my $label = shift;
  my $widg = shift;

  my $hbox = Gtk2::HBox->new();
  $hbox->set_spacing(4);
  $hbox->pack_start(Gtk2::Label->new($label), 0, 1, 0);
  $hbox->pack_start($widg, 1, 1, 0);
  $box->pack_start($hbox, 0, 1, 0);
}

#
# Create takes an argument list containing the title of the dialog,
# followed by a list of arrayref each containing one of the following:
# [ 'Label', <labelText> ]
# [ 'Entry', <labelText>, <varRef> ]
# [ 'OptionMenu', <labelText>, <varRef>, <entryMap> ]
# [ 'Toggle', <labelText>, <varRef> ]
# [ 'Check', <labelText>, <varRef> ]
# [ 'CheckList', <labelText>, <varRef>, <entryMap> ]
#
# where:
# labelText   text to show next to input widget
# varRef      reference to variable in which to store input widget value
# entryMap    hash list of optionLabel->optionValue pairs
#             optionLabel is shown in widget, optionValue is stored in varRef
#
sub Create {
  my $self = shift;
  my $title = shift;

  use Gtk2 -init;
  use Gtk2::SimpleList;
  use Gtk2::Ex::BindScalar;
  use Gtk2::Ex::Simple::OptionMenu;

  if(!$Dialog::registered){
    Gtk2::Ex::BindScalar::register_connection_info('Gtk2::Ex::Simple::OptionMenu',
                                                   [ ['changed'], ['value'] ]);
    $Dialog::registered = 1;
  }


  my $dialog = Gtk2::Window->new();
  $dialog->set_title($title);
  $dialog->set_modal(1);
  $dialog->set_position('center');
  my $winbox = Gtk2::VBox->new();
  $winbox->set_spacing(4);

  my $vbox = Gtk2::VBox->new();
  $winbox->pack_start($vbox, 0, 1, 0);
  $winbox->pack_start(Gtk2::HSeparator->new(), 0,1, 0);
  my $bbox = Gtk2::HButtonBox->new();
  $bbox->set_layout_default('end');
  $bbox->set_spacing_default(4);
  $bbox->set_spacing(4);

  my $ok = Gtk2::Button->new_from_stock('gtk-ok');
  $ok->signal_connect('clicked', sub { $self->{'result'} = 'ok'; });
  my $cancel = Gtk2::Button->new_from_stock('gtk-cancel');
  $cancel->signal_connect('clicked', sub { $self->{'result'} = 'cancel'; });
  $bbox->pack_start($cancel, 0, 1, 0);
  $bbox->pack_start($ok, 0, 1, 0);

  $winbox->pack_start($bbox, 0, 1, 0);

  $dialog->add($winbox);

  foreach my $w (@_) {
    my ($widg, $text, $var, @rest) = @$w;
    if($widg eq 'Label') {
      my $label = Gtk2::Label->new($text);
      $label->set_justify('center');
      $vbox->pack_start($label, 0, 1, 0);
    }elsif($widg eq 'OptionMenu') {
      my $om = Gtk2::OptionMenu->new();
      Gtk2::Ex::Simple::OptionMenu->new_from_widget($om, @rest);
      Gtk2::Ex::BindScalar->create($var, $om);
      $self->PackPair($vbox, $text, $om);
    }elsif($widg eq 'Entry') {
      my $entry = Gtk2::Entry->new();
      Gtk2::Ex::BindScalar->create($var, $entry);
      $self->PackPair($vbox, $text, $entry);
    }elsif($widg eq 'Toggle') {
      my $tb = Gtk2::ToggleButton->new_with_label($text);
      Gtk2::Ex::BindScalar->create($var, $tb);
      $vbox->pack_start($tb, 0, 0, 0);
    }elsif($widg eq 'Check') {
      my $tb = Gtk2::CheckButton->new_with_label($text);
      Gtk2::Ex::BindScalar->create($var, $tb);
      $vbox->pack_start($tb, 1, 1, 0);
    }elsif($widg eq 'CheckList') {
      my $label = Gtk2::Label->new($text);
      $label->set_justify('center');
      $vbox->pack_start($label, 0, 1, 0);
      my %opts = @rest;  # save the option name->hash-key map
      my @keys = ();     # capture the keys in the desired order
      while(scalar(@rest)){
        push @keys, shift @rest;
        shift @rest;
      }
      foreach my $k (@keys){
        my $tb = Gtk2::CheckButton->new_with_label($k);
        Gtk2::Ex::BindScalar->create(\$var->{$opts{$k}}, $tb);
        $vbox->pack_start($tb, 1, 1, 0);
      }
    }
  }

  $vbox->set_border_width(4);
  $vbox->set_spacing(4);
  $self->{'dialog'} = $dialog;
}



sub CreateGlade {
  my $self = shift;
  my $dialogName = shift;

  use Gtk2 -init;
  use Gtk2::GladeXML;
  use Gtk2::SimpleList;
  use Gtk2::Ex::Simple::OptionMenu;
  use Gtk2::Ex::BindScalar;

  if(!$Dialog::registered){
    Gtk2::Ex::BindScalar::register_connection_info('Gtk2::Ex::Simple::OptionMenu',
                                                   [ ['changed'], ['value'] ]);
    $Dialog::registered = 1;
  }

  my $gladeFile = "$dialogName.glade";
  my $gladeBase = "/metlab/runtime/appl/glade/MEL";
  my $gladeLocal = "/metlab/runtime/local/glade";

  if( -e "$gladeBase/$gladeFile") {
    open( INPUT, "$gladeBase/$gladeFile");
#    $glade = 
#        Gtk2::GladeXML->new("/metlab/runtime/appl/glade/MEL/$dialogName.glade",
#                            $dialogName);
  }elsif( -e "$gladeLocal/$gladeFile") {
    open( INPUT, "$gladeLocal/$gladeFile");
#    $glade = 
#        Gtk2::GladeXML->new("/metlab/runtime/local/glade/$dialogName.glade",
#                            $dialogName);
  }else{
    carp "Unable to load glade file: [$dialogName]\n";
  }

  my $xml = undef;
  read( INPUT, $xml, -s INPUT );
  close( INPUT );
  my $glade = Gtk2::GladeXML->new_from_buffer($xml, $dialogName);
  $self->{'glade'} = $glade;
  $self->{'dialog'} = $glade->get_widget($dialogName);
}

sub SetOption {
  my $self = shift;
  my $widget = shift;
  my $options = shift;

  $self->{'widgets'}->{$widget} = Gtk2::Ex::Simple::OptionMenu
      ->new_from_widget($self->{'glade'}->get_widget($widget), @$options);

}

sub Run {
  my $self = shift;

  return 0 if(!defined $self->{'dialog'});
  $self->{'dialog'}->show_all();
  $self->{'dialog'}->present();
  $self->{'dialog'}->grab_focus();
  $self->{'result'} = 'nil';
  Gtk2->main_iteration while($self->{'result'} eq 'nil');
  my $res = $self->{'result'}; #$self->{'dialog'}->run;
  print "Result: [$res]\n";
  $self->{'dialog'}->hide();
  Gtk2->main_iteration while Gtk2->events_pending;
  return($res eq 'ok');
}

sub DESTROY {
  my $self = shift;

  if(exists $self->{'dialog'} && defined $self->{'dialog'}){
    print "Destroying dialog [$self->{'id'}]...\n";
    foreach my $b (keys %{$self->{'binders'}} ){
      $self->{'binders'}->{$b}->disconnect();
    }
    $self->{'dialog'}->destroy();
    $self->{'dialog'} = undef;
  }
}

1;
