# Arch Perl library, Copyright (C) 2004-2007 Mikhael Goikhman, Enno Cramer
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

use 5.006;
use strict;
use warnings;

package ArchWay::MainWindow::Base;

use Glib qw(TRUE FALSE);
use Gtk2;

# avoid "package is not registered" warning in newer perl-Glib
BEGIN { Glib::Type->register('Gtk2::Window', 'ArchWay::MainWindow::Base') }

use base ('Gtk2::Window', 'ArchWay::Util::Dialogs');

our $VERSION = '0.2.2';

sub new ($%) {
	my $class = shift;
	my %args = @_;

	my $self = bless $class->SUPER::new('toplevel'), $class;
	$self->{$_} = $args{$_} foreach keys %args;
	die "No session\n" unless ref($self->{session}) eq 'ArchWay::Session';

	$self->init;

	$self->add_accel_group($self->ui->get_accel_group);

	# build user interface
	my $vbox = Gtk2::VBox->new(FALSE, 0);
	my $hbox = Gtk2::HBox->new(FALSE, 0);
	$self->add($vbox);

	my $menubar = $self->menubar();
	$vbox->pack_start($menubar, FALSE, FALSE, 0) if defined $menubar;

	my $toolbar = $self->toolbar();
	$vbox->pack_start($toolbar, FALSE, FALSE, 0) if defined $toolbar;

	my $main_widget = $self->main_widget();
	if (defined $main_widget) {
		$self->set_focus_child($main_widget);
		$vbox->pack_start($main_widget, TRUE, TRUE, 0);
	}

	my $sbar = $self->statusbar;
	my $pbar = $self->progressbar;
	$hbox->pack_start($pbar, FALSE, FALSE, 0) if defined $pbar;
	$hbox->pack_start($sbar, TRUE, TRUE, 0) if defined $sbar;
	$vbox->pack_start($hbox, FALSE, FALSE, 0);

	$self->resize_children;

	if ($args{is_dialog}) {
		$self->hide;
		my $dialog = Gtk2::Dialog->new('Something', $self,
			[qw(modal destroy-with-parent)],
			'gtk-ok'     => 'ok',
			'gtk-cancel' => 'cancel',
		);
		$main_widget->reparent($dialog->vbox);
		$self->{dialog} = $dialog;
		$self->dialog_init if $self->can('dialog_init');
	}

	return $self;
}

sub init ($) {
	my $self = shift;
	my $descr = $self->gui_descr;

	# menus (name, stock id, label)
	my @menus = (
		[ "FileMenu", undef, "_File" ],
		[ "ToolsMenu", undef, "_Tools" ],
		[ "HelpMenu", undef, "_Help" ],
	);

	# items (name, stock id, label, accelerator, tooltip, callback)
	my @items = (
		[
			"Quit", "gtk-quit", "_Quit",
			"<control>Q", "Quit",
			sub { $self->destroy() }
		],
		[
			"AboutAllTools", undef, "_About ArchWay",
			undef, "About",
			sub { $self->show_about('all'); }
		],
		[
			"AboutThisTool", undef, "About $descr _Tool",
			undef, "About",
			sub { $self->show_about(); }
		],
	);
	
	# menu/toolbar layout
	my $layout = q{
		<ui>
			<menubar name="MenuBar">
				<menu action="FileMenu">
					<placeholder name="FileMenuItems" />
					<separator />
					<menuitem action="Quit" />
				</menu>
				<placeholder name="ApplicationMenus" />
				<menu action="ToolsMenu">
				</menu>
				<menu action="HelpMenu">
					<placeholder name="HelpMenuItems" />
					<separator />
					<menuitem action="AboutAllTools" />
					<menuitem action="AboutThisTool" />
				</menu>
			</menubar>
		</ui>
	};

	# add menu/toolbar to ui
	my $actions = Gtk2::ActionGroup->new("Actions");
	$actions->add_actions(\@menus, undef);
	$actions->add_actions(\@items, undef);

	# force tools menu to appear
	$actions->get_action("ToolsMenu")->set("hide-if-empty", FALSE);

	$self->ui->insert_action_group($actions, 0);
	$self->ui->add_ui_from_string($layout);

	# add real tools menu
	my $menu = $self->ui->get_widget("/MenuBar/ToolsMenu");
	$menu->set_submenu($self->session->create_tools_menu($self));

	return $self;
}

sub temp ($) {
	my $self = shift;

	$self->{temp} ||= Arch::TempFiles->new;

	return $self->{temp};
}

sub setup_config_dir ($@) {
	my $self = shift;
	require Arch::Util;
	Arch::Util::setup_config_dir(undef, 'archway', @_);
}

sub session ($) {
	my $self = shift;

	return $self->{session};
}

sub arch ($) {
	my $self = shift;

	return $self->session->get_shared_arch;
}

sub gui_exe   ($) { $_[0]->{gui_info}->{exe}   }
sub gui_title ($) { $_[0]->{gui_info}->{title} }
sub gui_name  ($) { $_[0]->{gui_info}->{name}  }
sub gui_label ($) { $_[0]->{gui_info}->{label} }
sub gui_descr ($) { $_[0]->{gui_info}->{descr} }

sub ui ($) {
	my $self = shift;

	if (! exists $self->{ui}) {
		$self->{ui} = Gtk2::UIManager->new();
	}

	return $self->{ui};
}

sub menubar ($) {
	my $self = shift;

	return $self->ui()->get_widget("/MenuBar");
}

sub toolbar ($) {
	my $self = shift;

	return $self->ui()->get_widget("/ToolBar");
}

sub main_widget ($) {
	my $self = shift;

	if (! exists $self->{main_widget}) {
		$self->{main_widget} = Gtk2::VBox->new(FALSE, 0);
	}

	return $self->{main_widget};
}

sub progressbar ($) {
	my $self = shift;

	if (! exists $self->{progressbar}) {
		$self->{progressbar} = Gtk2::ProgressBar->new;
		$self->{progressbar}->set_pulse_step(0.02);
	}

	return $self->{progressbar};
}

sub statusbar ($) {
	my $self = shift;

	if (! exists $self->{statusbar}) {
		$self->{statusbar} = Gtk2::Statusbar->new();
		my $label = (($self->{statusbar}->get_children)[0]->get_children)[0];
		$label->set_selectable(1) if $label->isa('Gtk2::Label');
	}

	return $self->{statusbar};
}

sub set_status ($$) {
	my $self = shift;
	my $msg  = shift;

	$self->statusbar()->pop(0);
	$self->statusbar()->push(0, $msg);
}

sub set_widget_sensitivity ($$@) {
	my $self = shift;
	my ($sensitivity, @widgets) = @_;

	foreach my $path (@widgets) {
		my $widget = $self->ui->get_widget($path);
		$widget->set_sensitive($sensitivity)
			if defined $widget;
	}
}

sub set_deep_widget_focus_child ($$@) {
   my $self = shift;
   my $widget = shift;
	my @idxs = @_;
	my $default_idx = $idxs[-1] || 0;

	while ($widget->isa('Gtk2::Container')) {
		my $idx = @idxs? shift @idxs: $default_idx;
		my $child = ($widget->get_children)[$idx];
		last unless $child;
		$widget->set_focus_child($child);
		$widget = $child;
	}
} 

sub show_about ($;$) {
	my $self = shift;
	my $all = shift;
	my $gui_name = $self->gui_name;

	my $up_flag_ref = \(($all? $self->session: $self)->{about_up});
	($$up_flag_ref)->deiconify, return if $$up_flag_ref;

	my $title = "About " . ($all? "ArchWay": $self->gui_descr . " Tool");
	my $dialog = Gtk2::Dialog->new(
		$title, $self, 'destroy-with-parent',
		'gtk-ok', 'ok',
	);
	$$up_flag_ref = $dialog;

	my $hbox = Gtk2::HBox->new(FALSE, 8);
	$hbox->set_border_width(8);
	$dialog->vbox->pack_start($hbox, FALSE, FALSE, 0);

	my $image = Gtk2::Image->new;
	$hbox->pack_start($image, FALSE, FALSE, 0);
	my $label = Gtk2::Label->new;
	$hbox->pack_start($label, FALSE, FALSE, 0);

	if ($all) {
		my @gui_names = $self->session->gui_names;
		die "Internal: no gui names defined\n" unless @gui_names;
		my $count = 0;
		$gui_name = $gui_names[0];
		my $slide_time = 10;
		$slide_time = 1 if $ENV{JUST_FOR_FUN};

		my $alarm_cb = sub {
			$count = ($count + 1) % @gui_names;
			$self->_set_about_text_and_logo($label, $image, $gui_names[$count]);
			alarm($slide_time);
		};
		if ($] < 5.008) {
			$SIG{ALRM} = $alarm_cb;
		} else {
			use POSIX qw(sigaction SIGALRM);
			sigaction SIGALRM, new POSIX::SigAction $alarm_cb;
		}
		$dialog->signal_connect(button_press_event => $alarm_cb);
		alarm($slide_time);
	}

	$self->_set_about_text_and_logo($label, $image, $gui_name);

	$dialog->signal_connect(response => sub {
		$dialog->destroy;
		$$up_flag_ref = undef;
		alarm(0) if $all;
	});
	$dialog->show_all;
}

sub _set_about_text_and_logo ($$$$) {
	my $self = shift;
	my $label = shift;
	my $image = shift;
	my $gui_name = shift;
	my $session = $self->session;
	my $gui_class = $session->main_window_class($gui_name) || __PACKAGE__;
	my $gui_info = $session->gui_info($gui_name);

	my @authors = $gui_class->gui_about_authors;
	my $authors_lines = join("", map { s/</&lt;/g; s/>/&gt;/g; "$_\n" } @authors);
	my $description = $gui_class->gui_about_text;
	my $text =
		"<b><big>$gui_info->{descr}"
		. (defined $gui_info->{title}
		   ? " (<i>$gui_info->{title}</i>)"
		   : "" )
		. "</big></b>\n"
		. "        <u>ArchWay $VERSION</u>\n\n\n"
		. "<b>Description:</b>\n$description\n\n"
		. "<b>Authors:</b>\n$authors_lines";
	$label->set_markup($text);

	my $logo_file = $session->gui_logo_file($gui_name);
	if (-r $logo_file) {
		$image->set_from_file($logo_file);
	} else {
		$image->set_from_stock('gtk-dialog-info', 'dialog');
	}
}

sub gui_about_authors ($) {
	'Mikhael Goikhman <migo@homemail.com>',
	'Enno Cramer <uebergeek@web.de>',
}

sub gui_about_text ($) {
	"This is a part of ArchWay - GNU Arch GUI.\n" .
	"No other description is provided.\n"
}

1;

__END__
