#!/usr/bin/perl -w

use strict;

use Carp qw(&cluck);
use Data::Dumper;

use Cowed::AddSplitCell;

use Cowed::Project;
use Cowgen::VWorld::Room;

use Cwd;
use Tk;

use vars qw($VERSION);

$VERSION = "0.0.5";




use vars qw($project $cells);
use vars qw($zoom_lvl $cam_x $cam_y);

# Tels: inner drawing size and appname
use vars qw($inner_width $inner_height);

use vars qw($save_load_dir);

use vars qw($copy_buffer);
use vars qw($colors);

use vars qw($selected);

use vars qw($validation_data);

use vars qw($old_height $old_width);

use vars qw($canvas $main $scrolled);
use vars qw($sidebar $sidebar_contents $sidebar_labels);
use vars qw($popup_menu);
use vars qw($menubar $menubar_items $status_bar);


# Used to locate the cell's data hash, as Tk won't let us store the hash as a tag.
$cells = {};

# app name
my $myname = "CowEd 0.0.6 ";

# List ref containing the colors that we'll use
#Tels: disabled for debugging
#$colors = [ qw(red blue green purple white) ];
$colors = [ qw(white white) ];

# The copy buffer, for copying items.
$copy_buffer = ["empty", {}];

# Where we keep all the menubar items at.
$menubar_items = {};

# This is how we keep track of what's changed when the window is resized, so we can adjust.
$old_height = undef;
$old_width = undef;

# The dir we save/load to.
$save_load_dir = cwd();

# The item on the Canvas that's currently selected.
$selected = undef;

# Let's initialize the labels & contents of the sidebar...
$sidebar_contents = [];
$sidebar_labels = [];

# This is data used to validate fields - we should probably end up 
# putting it in a file.
$validation_data = { "proportion" => "numeric" };

# Indicates how far in/out we've zoomed and where cam center is.  
$zoom_lvl = 1;
$cam_x = 0;
$cam_y = 0;

# Create main window and canvas
$main = MainWindow->new( -title => $myname );

# We can't let the main window get any smaller than this,
# or else the sidebar can't display all pertinent data.
#$main->minsize(375, 375);

$main->gridRowconfigure(1, -minsize => 500);
$main->gridColumnconfigure(0, -minsize => 500);

# Let's make a simple 'File' drop-down.
$menubar = $main->Frame;
$menubar->grid(qw/-sticky ew -row 0 -column 0 -columnspan 2/);

$menubar->gridColumnconfigure(qw/0 -weight 1/);

$menubar_items->{Project} = $menubar->Menubutton(qw/-text Project -anchor w -tearoff 0 -menuitems/ =>
    [
	 [Button => 'Edit configuration', -command => sub { &EditProject }],
	 [Button => 'New', -command => sub { &NewProject }],
	 [Button => 'Load', -command => sub { &LoadProject }],
	 [Button => 'Save', -command => sub { &SaveProject }],
	 [Button => 'Save As', -command => sub { &SaveAsProject }],
	 '-',
	 [Button => 'Generate', -command => sub { &GenerateProject }],
	 '-',
	 [Button => 'Exit', -command => sub { &ExitProgram } ],
	])->pack( qw/-side left/); 

#Tels:
#$menubar_items->{Edit} = $menubar->Menubutton(qw/-text Edit -anchor w -tearoff 0 -menuitems/ =>
#	[
#	 '-',
#	 [Button => 'Copy selected', 
#           -command => sub { &copySelected($canvas) }], 
#	 [Button => 'Copy all below', -command => sub { &copyAll($canvas) }],
#	 [Button => 'Paste', -command => sub { &paste($canvas) }],
#	 [Button => 'Save clipboard', 
#          -command => sub { &saveClipboard($canvas) }],
#	 [Button => 'Load into clipboard', 
#          -command => sub { &loadClipboard($canvas) }],
#	])->pack( qw/-side left/ );

$menubar_items->{Goto} = $menubar->Menubutton(qw/-text Goto -anchor w -tearoff 0 -menuitems/ =>
	[
	 [Button => 'Next', -command => sub { &NextItem() }],
	 [Button => 'Prevoius', -command => sub { &PrevItem() }],
	 [Button => 'Parent', -command => sub { &ParentItem() }],
	 [Button => 'First Child/Thing', -command => sub { &FirstItem() }],
	 '-',
	 [Button => 'Mother cell', -command => sub { &MotherItem() }],
	])->pack( qw/-side left/ );
#endTels

#Tels:
$menubar_items->{Screen} = $menubar->Menubutton(qw/-text Screen -anchor w -tearoff 0 -menuitems/ =>
	[
	 [Button => 'Filter', -command => sub { &setFilter($canvas) }],
	 '-',
	 [Button => 'Recenter', -command => sub { &CenterCanvas($canvas) }],
	 [Button => 'Redraw', 
          -command => sub { &redraw_canvas($canvas,$project) }],
	 '-',
	 [Button => 'Zoom In', -command => sub { &ZoomInCanvas($canvas) }],
	 [Button => 'Zoom Out', -command => sub { &ZoomOutCanvas($canvas) }],
	 [Button => 'Unzoom', -command => sub { &NormalizeCanvas($canvas) }]
	])->pack( qw/-side left/ );

#endTels

$menubar_items->{Help} = $menubar->Menubutton(qw/-text Help -anchor w -tearoff 0 -menuitems/ =>
    [
	 [Button   => 'About', -command => sub { &AboutHelp } ]
	])->pack( qw/-side right/ );





# Now, make the scrollbar-enabled area...
$scrolled = $main->Scrolled("Canvas", -scrollbars => 'osoe');

$scrolled->grid( qw/-sticky nsew -row 1 -column 0/);

$canvas = $scrolled->Subwidget("canvas");
$canvas->configure(-background => 'black');





$sidebar = $main->Frame( qw/ -bg black -fg white / );
$sidebar->grid( qw/ -column 1 -row 1 -sticky ns/ );

# Cheat, and make a widget that forces the sidebar to be at least 90 chars wide.
$sidebar->Label( -text => ' 'x90,  qw/-bg black -fg black/ )->grid( qw/-column 0 -columnspan 2 -sticky e/ );

# Let's create 10 pairs of label widgets that we can later reconfigure with new contents.
for ( my $i = 0; $i < 10; $i++ ) {
	my ($label, $content);

	$label = $sidebar->Label( -text => " "x 20, qw/ -background black/,
							qw/-foreground white -justify left/ );
	$label->grid( qw/ -sticky w -column 0 -row /, $i );

	push( @{$sidebar_labels}, $label);

	$content = $sidebar->Label( -text => " " x 30, qw/ -background black -width 30 -height  2/,
							qw/-foreground CadetBlue2 -justify left/ );
	$content->grid( qw/ -sticky w -column 1 -row /, $i );

	push( @{$sidebar_contents}, $content);
}





$status_bar = $main->Label( -text => "", -foreground => 'red', -relief => 'groove' )->grid(
										qw/-row 2 -sticky ew -column 0 -columnspan 2/ );
$status_bar->gridPropagate(0);





# A handler in case the window's resized
$main->bind('MainWindow', '<Configure>' => [sub{ResizeWindow($canvas,$_[1], $_[2])}, Ev('h'), Ev('w')] );

# XXX # Disabled for now, until can get details on non-selected item
# Hovering over a cell or leaving its vicinity invokes a procedure
# (I've no idea why the song and dance is needed to get x & y, but it appears that it is)
#$canvas->bind('cell', '<Enter>' => [sub{handle_cell_enter($canvas, $_[1], $_[2])}, Ev('X'), Ev('Y')] );
#$canvas->bind('cell', '<Leave>' => sub{&handle_cell_leave} );

# Single-clicking with left on a cell invokes a procedure
# (I've no idea why the song and dance is needed to get x & y, but it appears that it is)
$canvas->bind('cell', '<ButtonRelease-1>' => [sub{handle_cell_left($canvas,$_[1], $_[2])}, Ev('X'), Ev('Y')] );

# Single-clicking with right on a cell invokes a procedure
# (I've no idea why the song and dance is needed to get x & y, but it appears that it is)
#Tels: canvas:
$canvas->bind('cell', '<ButtonRelease-3>' => [sub{handle_canvas_right($canvas,$_[1], $_[2])}, Ev('X'), Ev('Y')] );







# Start a new project by default.
$project = new Cowed::Project;

#Tels: just for debuggign
$project->splitCell(inX, 4, "1, 2, 3, 4", "foo, bar, baz, brutzel");
$project->selFirstChild();
$project->splitCell(inY, 2, "1, 2", "foo1, bar1");
my $r = $project->getTemplates();
foreach (keys %{$r})
  {
  print "Thing $_: $r->{$_}->{name} $r->{$_}->{description}\n";
  }

#Tels:
ResizeWindow($canvas,$canvas->cget('-width'),$canvas->cget('-width'));

MainLoop;

# EOF
1;

######################################################################
# General utility funcs that return info on the currently-evented item
######################################################################

# This returns the Tk ID number of the item on the Canvas that's been clicked upon.
sub get_TkID {
	my ($can) = @_;

	return $can->find('withtag', 'current');
}

# This returns the data hash of the clicked-upon item
# (or, if 2 args, of the item matching $TkID)
sub get_item_properties {
	my ($can, $TkID, $key) = @_;

	&get_name($can, $TkID) =~ /^\w+(\d+)$/;
	$project->setSelected($1);

	my $value;

	if ( defined($key) ) {
		$value = $project->getProperty($key);

	} else {
		$value = $project->getProperties();
	}

	&get_name($can, $selected) =~ /^\w+(\d+)$/;
	$project->setSelected($1);
}

# This gets the real name (not the type)
sub get_name {
	my ($can, $id) = @_;

	$id = ( defined($id) ? $id : $can->find('withtag', 'current') );

      #print "get_name id: $id\n";
	my @taglist = $can->gettags("cell"); #$id);
	my $name;
      #print "get_name tl: @taglist\n";

	foreach (@taglist) {
		# The name has alpha chars, and ends with a number.
      #print "get_name loop: $_\n";
		next unless $_ =~ /\w\d+$/;

		$name = $_;
		last;
	}
      #print "get_name: $name $id\n";

	return $name;
}

# This gets the type of brush we're on
sub get_type {
	my ($can, $TkID) = @_;

	$TkID = ( defined($TkID) ? $TkID : $can->find('withtag', 'current') );

	my @taglist = $can->gettags($TkID);
	my $type;

	foreach (@taglist) {
		# The type won't have a number in it.
		next if $_ =~ /\d/;

		$type = $_;
		last;
	}

	return $type;
}

######################################################################
# General-utility funcs.
######################################################################

# Create an item; use parameters as tags (this is not a default!)
# Tels: revamped
# 2000-02-03: fixed now finally (resize works as expected and always fits
# complete world in
sub draw_item 
  {
  my ($can,$name,$x,$y,$z,$width,$length,$height,$type,$level,@world) = @_;

  my ($color);

  my $dw = $inner_width-3; my $dh = $inner_height-3;
  my $dw2 = $cam_x+$dw/2; my $dh2 = $cam_y+$dh/2;
  ($dw,$dh) = ($dh,$dw) if ($dw < $dh);
  $dh = $dh*$zoom_lvl;
  $color = 'orange';
  $color = &lvl_2_color($level) if ( $type eq 'cell' );
  $color = 'red' if ( $type eq 'thing' ); 
  $color = 'magenta' if ( $type eq 'terrainpoint' ); 

  # For top-down (x-y coords), d1 == y & d2 == x
  # For right-side (y-z coords), d1 == z & d2 == y
  # For front-view (x-z coords), d1 == z & d2 == x
  my ($d1_1, $d2_1, $d1_2, $d2_2);

  # This looks odd, because Tk calculates Y with positive numbers 
  # going southwards.
    
  # normalize coords to 0..1 
  my $wx = ($x - $world[0])/($world[3]);
  my $wy = ($y - $world[1])/($world[4]);
  my $ww2 = ($width/$world[3])/2;
  my $ll2 = ($length/$world[4])/2;

  # scale to canvas
  # but fit it in the smaller one of the sizes
  
  $d1_1 = ($wx + $ll2) * $dh+$dh2-$level*2;
  $d1_2 = ($wx - $ll2) * $dh+$dh2+$level*2;
  $d2_1 = ($wy - $ww2) * $dh * ($world[3]/$world[4])+$dw2+$level*2; 
  $d2_2 = ($wy + $ww2) * $dh * ($world[3]/$world[4])+$dw2-$level*2;
       
  print "($d2_1, $d1_1), ($d2_2, $d1_2) n: $name; t: $type\n"; #XXX
  #$d1_1 += $cam_x; $d1_2 += $cam_y; $d2_1 += $cam_x; $d2_2 += $cam_y;
  # should add only if fits onto canvas
  $can->createRectangle($d2_1, $d1_1,	$d2_2, $d1_2,
    -tags => [$name, $type], qw/-fill black -outline/, $color);
  }

sub lvl_2_color {
	my ($lvl) = shift;

	return $colors->[ $lvl % $#{$colors} ]; # XXX # Add more colors
}

#Tels:
sub redraw_canvas 
  {
  my ($can, $proj) = @_;

  $can->CanvasBind('<ButtonRelease-3>', "");
  $can->delete("cell", "thing", "terrainpoint");

  my $data = $proj->getCoords();
  my @world = $project->getWorldSize(); 
  #print "Drawing size: $inner_width x $inner_height\n";
  my ( $x, $y, $z, $width, $length, $height, $type, $level, $name );
  foreach my $id ( sort keys( %{ $data } ) ) {
    $x = $data->{$id}->{x};
    $y = $data->{$id}->{y};
    $z = $data->{$id}->{z};
    $width = $data->{$id}->{w};
    $length = $data->{$id}->{l};
    $height = $data->{$id}->{h};
    $type = $data->{$id}->{type};
    $level = $data->{$id}->{level};

    if ( $type == &aCell ) {
      $type = "cell";
    } elsif ( $type == &aThing ) {
      $type = "thing";
    } elsif ( $type == &aTP ) {
      $type = "terrainpoint";
    } else { $type = "unknown"; } # Default
    $name = $type . $id;
    print "($x, $y, $z), ($width, $length, $height) '$type' '$name'\n"; #XXX
    draw_item( $can, $name, $x, $y, $z, $width, $length, $height, $type, 
     $level, @world);
    }
  $can->CanvasBind('<ButtonRelease-3>',
   [sub{handle_canvas_right($canvas, $_[1], $_[2])}, Ev('X'), Ev('Y')] );
  $selected = $project->getSelected();
  $canvas->itemconfigure($selected, -outline => 'yellow') 
   if (defined $selected);
  showClean($project);
  }
#EndTels

#Tels
sub select_item 
  {
  my ($can, $new_id) = @_;

  if ( defined($selected) ) 
    {
    $can->itemconfigure($selected,
     -outline => 
     &lvl_2_color( &get_item_properties($can, $selected, 'level' ) ) );
    }
  print "$new_id\n";
  if ( $selected != $new_id ) {
    $canvas->itemconfigure($new_id, -outline => 'yellow');
    $selected = $new_id;
  } else {
    $project->setSelected( $selected = undef );
  }
  #my $name = &get_name($can, $new_id); print "name: $name\n";
  #&get_name($can, $new_id) =~ /^\w+(\d+)$/;
  #$project->setSelected($1);
  }
#EndTels

######################################################################
# Funcs to handle mouse usage on cells
######################################################################

sub handle_cell_enter {

	for( my $i = 0; $i < 10; $i++ ) {
		$sidebar_labels->[$i]->configure( '-text', "A property:" );

		$sidebar_contents->[$i]->configure( '-text', "Foo!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" );
		$sidebar_contents->[$i]->configure( '-foreground', $colors->[ $i % ($#{$colors}+1) ] );
	}
}

sub handle_cell_leave {
	for( my $i = 0; $i < 10; $i++ ) {
		$sidebar_labels->[$i]->configure( '-text', "" );

		$sidebar_contents->[$i]->configure( '-text', "" );
		$sidebar_contents->[$i]->configure( '-foreground', "CadetBlue2" );
	}
}

# Left-clicks on cells...
sub handle_cell_left {
	my ($can, $x, $y) = @_;

	my $TkID = get_TkID($can);

	my $popup_menu;

	print "Left-clicked on cell ", get_name($can), " at $x x $y...\n";

	&select_item($can, $TkID);
}

# Right-clicks on cells...
sub handle_cell_right {
  my ($can, $popup_menu, $TkID) = @_;

  print "Right-clicked on cell ", get_name($can), "...\n";

  $popup_menu->separator();
  $popup_menu->add("command", -label => "Details", -command => sub { &DetailCell($can, $TkID) } );

  $popup_menu->separator();

  $popup_menu->add("command", -label => "Delete", -command => sub { &DelCell($can, $TkID) } );

  # Tels: Only split if there are no childs
  # If we've got subcells, then let's resize.  Otherwise, split it.
  $popup_menu->add("command", -label => 'Resize', -command => sub { &ResizeCell($can, $TkID) } );
  $popup_menu->add("command", -label => 'Add more cells', -command => sub { &AddCells($can, $TkID) } );
  #endtels
  if ( scalar @{ $project->getProperty("cells") } == 0 ) 
    {
    $popup_menu->add("command", -label => 'Split', -command => sub { &SplitCell($can, $TkID) } );
    }

  $popup_menu->separator();

  $popup_menu->add("command", -label => "Copy", -command => sub { &CopyCell($can, $TkID) } );

  # We've got a cell in our copy buffer.  Let's give the option to use it.
  if ( (ref($copy_buffer) eq "ARRAY" && $#{ $copy_buffer } == 1) &&
      (defined($copy_buffer->[0]) && $copy_buffer->[0] eq "cell") &&
      (defined($copy_buffer->[1]) && 
      ( scalar(keys(%{ $copy_buffer->[1] })) > 0 )) ) 
    {
    $popup_menu->add("command", -label => 'Paste', -command => sub { &PasteCell($can, $TkID) } );
    }
  }

#Tels:
sub handle_canvas_right 
  {
  # handle clicks on empty canvas
  my ($can, $x, $y) = @_;

  my $TkID = get_TkID($can);
  my $popup_menu;
  print "Right-clicked on canvas ", get_name($can), " at $x x $y...\n";
  $main->{'POPUP_MENU_REFERENCE'} = $popup_menu = $main->Menu(-tearoff => 0);

  $popup_menu->add("command", -label => "Set Center",
    -command => sub { &setCenter($can, $x, $y) } );

  # If the item we're right-clicking on is the selected one, then add somestuff
  # add here check if click falls into rect of $selected, because that should
  # cause handle_cell_right, too!
  handle_cell_right ($can,$popup_menu,$TkID) if ($TkID == $selected);
  $popup_menu->Post($x, $y);
  }
#endtels

######################################################################
# Funcs to pop up miscellaneous messages on the status bar & to clear them.
######################################################################

sub StatusBar {
	my ($msg, $color, $buffer);

	if ( $#_ == 0 ) {
		($msg, $color, $buffer) = ($_[0], 'red', $status_bar);
	} elsif ( $#_ == 1 ) {
		($msg, $color, $buffer) = ($_[0], $_[1], $status_bar);
	} elsif ( $#_ == 2 ) {
		($msg, $color, $buffer) = ($_[0], $_[1], $_[2]);
	} else {
		print "Incorrect use of &StatusBar!\n";
		return;
	}

	chomp($msg);

	# 1st off, clear all bindings on '<Motion>'...
	$main->bind('all', '<Motion>', '');

	$buffer->configure( '-text' => $msg );
	$buffer->configure( '-foreground' => $color ) if defined($color);

	# Get the time as it is right this second.
	my $now = time();

	$main->bind('all', '<Motion>', sub{ ClearStatusBar($now, $buffer) } );
}

sub ClearStatusBar {
	my ($then, $buffer) = @_;

	if ( (time() - $then) >= 3 ) {

		# If 3 seconds have passed, unbind the '<Motion>' binding...
		$main->bind('all', '<Motion>', '');

		# And clear the status bar.
		$buffer->configure( '-text' => "" );
		$buffer->configure( '-foreground' => 'red' );
	}
}

######################################################################
# Funcs to deal with user selections on the Menu bar.
######################################################################

#Tels:
sub showClean
  {
  # modify title to show wether project is clean or not.
  # should be on statusbar, really
  # called by redrawCanvas for simplicities sake
  my $project = shift;
  my $title = $myname;
  $title .= "(modified)" if (!$project->isClean());
  $main->configure( '-title', $title);
  }
#endtels

sub ExitProgram {

	# Note that we don't check if they have a child window open here.
	# If they want to exit, we oughta let 'em.
	exit(0);
}

sub EditProject {

&NotImplemented;
}

sub LoadProject {
	my $saveLoadWin = $main->SaveLoad( -dir => \$save_load_dir, qw/-do_what load -data_var/, \$project );
#tels:
	&redraw_canvas($canvas, $project);

&NotImplemented;
}

sub NewProject {

	$project = new Project();

	&redraw_canvas($canvas, $project);
}

#Tels:
sub SaveProject 
  {
  my $file = 
  $project->getParameter("projectpath") . $project->getParameter('name').'.prj';
  $project->saveProject($file);
  StatusBar("Project saved to '$file'.");
  showClean($project); 
  }
#endTels

sub SaveAsProject {
# my $saveLoadWin = $main->SaveLoad( -dir => \$save_load_dir, qw/ -do_what saveAs -data_var/, \$project );
  # set filename
  #$project->saveProject($file);
  showClean($project); 
  &NotImplemented;
  }

#Tels:
sub GenerateProject 
  {
  my $file = 
  $project->getParameter("outputpath") . $project->getParameter('name').'.mis';

  $project->generateMission( 
   $project->getParameter("base"),
   $project->getParameter("gamfile"), $file);
  StatusBar("Project generated as '$file'.");
  }
#endtels:

sub AboutHelp {

&NotImplemented;
}

######################################################################
# Funcs to deal with user selections on the cell-based popup menus.
######################################################################

sub CopyCell {
	my ($TkID) = shift;

	$copy_buffer = ["cell", $TkID];

	&StatusBar("Cell copied", 'black');
}

sub DelCell {
	my ($can, $TkID) = @_;

	my $name = &get_name($can, $TkID);

	$can->delete( $name );

	$name =~ /^\w+(\d+)$/;

	my $ret = $project->delCell( $1 );

	&redraw_canvas($can, $project);

	if ( $ret < 0 ) {
		&StatusBar("There was an error attempting this action.");

		return;
	}
  #Tels:
	#my $title = $main->cget('-title');
	#$main->configure( '-title', $title . "*" ) unless $title =~ /\*$/;
}

sub DetailCell {
	my ($can, $TkID) = @_;

#	my $item_data = &get_item_properties($can, $selected);

#	my $detail_items = { "room name" => $item_data->{Tk_name}, "proportion" => "0.2" };

#	&DetailItem($item_data, $detail_items);
&StatusBar("This functionality has been disbled temporarily.");
}

sub PasteCell {
	my ($TkID) = shift;

	$copy_buffer = ["empty", {}];

&StatusBar("The Paste Cell function only serves to clear the copy buffer", 'black');
}

sub ResizeCell {
	my ($can, $TkID) = @_;

	my $win = $main->AddSplitCell( qw/-do_what add -project/, \$project,
					-do_func => sub { &SplitResizeCell($can, @_) } );
}

sub SplitCell {
	my ($can, $TkID) = @_;

	my $win = $main->AddSplitCell( qw/-do_what split -project/, \$project,
					-do_func => sub { &SplitResizeCell($can, @_) } );
}

######################################################################
# Funcs for the screen menu
######################################################################

#Tels: revamped all
sub setFilter 
  {
  my $can = shift;
  NotImplemented();
  }

sub setCenter 
  {
  my ($can, $x, $y) = @_;
  # there is ONE problem: clicking at left uppe redge is NOT 0,0
  # so the calculation below goes wrong!
  print "would set cam from: $x $y $inner_width $inner_height $cam_x $cam_y";
  $cam_x -= $x-$inner_width;
  $cam_y -= $y-$inner_height;
  print " to $cam_x $cam_y\n";
  redraw_canvas($canvas,$project);
  }

sub CenterCanvas 
  {
  my $can = shift;
  $cam_x = 0; $cam_y = 0;
  redraw_canvas($canvas,$project);
  }

sub NormalizeCanvas 
  {
  # Undo all zooming...
  my $can = shift;
  $zoom_lvl = 1;
  redraw_canvas($canvas, $project);
  }

sub ZoomInCanvas 
  {
  my $can = shift;
  $zoom_lvl *= 2; redraw_canvas($canvas, $project);
  }

sub ZoomOutCanvas 
  {
  my $can = shift;
  $zoom_lvl /= 2; redraw_canvas($canvas, $project);
  }
#endTels:

######################################################################
# Funcs to deal with the backend of user selections
######################################################################

sub DetailItem {
	my ($TkID, $detail_items) = @_;

	my ($room_name, $proportion) = ("", 0);

	my ($x, $y) = ($main->rootx(), $main->rooty());
	my ($h, $w) = ($main->height(), $main->width());

	$x += int($w / 4);
	$y += int($h / 4);

	my $subwin = $main->Toplevel( -title => "Details" );
	$subwin->geometry("+$x+$y");

	foreach my $key ( sort keys %{ $detail_items } ) {
		my $subwin_f = $subwin->Frame->grid( qw/-sticky ew/ );
		$subwin_f->gridColumnconfigure(0, -minsize => 100);
		$subwin_f->gridColumnconfigure(1, -minsize => 100);

		my $value = exists($TkID->{details}->{"$key"}) ?
						$TkID->{details}->{"$key"} : $detail_items->{$key};

		$subwin_f->Label(-text => ucfirst($key) . ": " )->grid( qw/-row 0 -col 0/ );
		$subwin_f->Entry(-textvariable => \$value, -width => 10 )->grid( qw/-row 0 -col 1 -sticky w/ );
	}

	# Set up a status bar for this details window...
	my $sb = {};

	my $subwin_f_b = $subwin->Frame->grid( qw/-sticky ew/ );

	$subwin_f_b->Button(
			-text => "Ok", -command => sub { &UpdateItem($TkID, $subwin, $sb) && $subwin->destroy() }
		)->grid( qw/-padx 15 -pady 5 -row 0 -column 0/ );

	$subwin_f_b->Button(
			-text => "Cancel", -command => sub { $subwin->destroy() }
		)->grid( qw/-padx 15 -pady 5 -row 0 -column 1/ );

	$sb = $subwin->Frame->grid( qw/-sticky ew/ )->Label(
								-text => " " x 60, -foreground => 'red' )->grid();

	$subwin->focus();
	$subwin->grab();
}

sub UpdateItem {
	my ($TkID, $subwin, $buffer) = @_;

	my $ok = {};

	# Now, go thru all of $subwin's children frames, looking for ones that have 'entry'
	# children of their own that we can pull the data from.
F:	foreach my $subframe ( $subwin->children ) {
		my ($key, $value);

		foreach my $kid ( $subframe->children ) {
			my $name = $kid->name;

			next F if $name =~ /button/; # The frames we want don't have buttons.

			$value = $kid->get if $name eq "entry";
			if ($name eq "label") {
				$key = lc($kid->cget('-text'));
				$key =~ s/:\s+$//;				# Strip off the ': ' we appended to the Label's text
			}
		}

		# Update the item's details, if we have both a key and a value.
		if ( defined($key) && defined($value) ) {
			return if &ValidateData($key, $value, $buffer);

			$ok->{"$key"} = $value;
		}
	}

	# Now that all the data has been validated, let's update!
	foreach my $key ( keys %{ $ok } ) {
		$TkID->{details}->{"$key"} = $ok->{"$key"};
	}

	return 1;
}

sub ValidateData {
	my ($k, $v, $b) = @_;

	my $data_type = exists($validation_data->{"$k"}) ? $validation_data->{"$k"} : undef;

	# If we haven't been told how to validate this field, nevermind it.
	return unless defined($data_type);

	if ($data_type eq "numeric") {
		unless ($v =~ /^[\d\.]+$/) {
			&StatusBar(ucfirst($k) . " must be numeric", 'red', $b);
			return 1;
		}
	}

	return 0;
}

######################################################################
# Funcs to deal with splitting/resizing cells, and refreshing the canvas(es)
######################################################################

sub ResizeWindow {
	my ($can,$new_height, $new_width) = @_;

	unless ( defined($old_height) || defined($old_width) ) {
		$old_height = 0; $old_width = 0;
		return;
	}

	if ( $new_height != $old_height ) {
		my $menubar_height = $menubar->height;
		my $status_bar_height = $status_bar->height;

		$inner_height = $new_height - $menubar_height - $status_bar_height;

		# We have to make sure that the grid will behave, so reset row 1's minsize
		$main->gridRowconfigure(1, '-minsize' => $inner_height);

		$old_height = $new_height;
	}

	if ( $new_width != $old_width ) {
		my $sidebar_width = $sidebar->width;

		$inner_width = $new_width - $sidebar_width;

		$main->gridColumnconfigure(0, '-minsize' => $inner_width);

		$old_width = $new_width;
	}
  #Tels:
  $can->configure('-width',$new_width);
  $can->configure('-height',$new_height);
  redraw_canvas($canvas, $project);
  #endTels
}

sub SplitResizeCell {
	my ($can, $num, $sizes, $names, $split_dir) = @_;

	my $ret;

	if ( defined($split_dir) ) {
		# We're splitting the cell.
		$ret = $project->splitCell($split_dir, $num, $sizes, $names);
	} else {
		# We're just adding cells to it.
		$ret = $project->addCells($num, $sizes, $names);
	}

	if ($ret < 0) {
		&StatusBar("An error resulted from your last action.");

		return;
	}

	&redraw_canvas($can, $project);
    #Tels:
	#my $title = $main->cget('-title');
	#$main->configure( '-title', $title . "*" ) unless $title =~ /\*$/;
}

######################################################################
# Funcs to deal with features that're yet to be fully implemented.
######################################################################

sub NotImplemented {
	&StatusBar("Sorry, this feature has not yet been implemented.");
}

sub BackEnd {
	&StatusBar("This function needs to have the back-end tied in.", 'purple');
}

#Tels:
######################################################################
# Funcs for the goto menu
######################################################################

sub NextItem
  {
  select_item ( $canvas, $project->selNext() );
  }

sub PrevItem
  {
  select_item ( $canvas, $project->selPrev() ); 
  }

sub FirstItem
  {
  select_item ( $canvas, $project->selFirstChild() ); 
  }

sub MotherItem
  {
  select_item ( $canvas, $project->selMother() ); 
  }

sub ParentItem
  {
  select_item ( $canvas, $project->selParentCell() ); 
  }


