#!/usr/bin/perl -w

###############################################################################
# Iconbox is a comfortable one-mouse-click application launcher.	      #
# Copyright (C) 2005 Chris Mueller (iconbox@gmx.de)			      #
#									      #
# 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 Gtk2 '-init';
use Gtk2::SimpleList;
use strict;

# pixbuf array declaration
my @pb;

# list entries counter
my $ec=0;

# vars..
my ($x,$y,@pdata,@col,@font,@pos,@res,$a,$m,$s,$c,$b);

# windows declarations
my $wnd = Gtk2::Window->new('toplevel');
my $scr_wnd = Gtk2::ScrolledWindow->new(undef,undef);
my $popup = Gtk2::Window->new('toplevel');

# frame decl.
my $pos_fr = Gtk2::Frame->new("Window position of Iconbox");
my $grab_fr = Gtk2::Frame->new("Grabbing cursor");
my $text_fr = Gtk2::Frame->new("Label settings");
my $wprop_fr = Gtk2::Frame->new("Window settings");

# VBox and HBox decl.
my $vb = Gtk2::VBox->new(0,5);
my $popup_vb = Gtk2::VBox->new(0,5);
my $lst_vb = Gtk2::VBox->new(0,5);
my $logo_vb = Gtk2::VBox->new(0,5);
my $program_vb = Gtk2::VBox->new(1,5);
my $command_vb = Gtk2::VBox->new(1,5);
my $icon_vb = Gtk2::VBox->new(1,5);
my $wprop_hb = Gtk2::HBox->new(0,5);
my $icon_hb = Gtk2::HBox->new(1,5);
my $but_hb = Gtk2::HBox->new(1,5);
my $fr_hb = Gtk2::HBox->new(0,5);
my $oc_hb = Gtk2::HBox->new(0,5);
my $pci_hb = Gtk2::HBox->new(1,2);
my $xy_hb = Gtk2::HBox->new(0,5);
my $hv_vb = Gtk2::VBox->new(0,5);
my $hv_hb1 = Gtk2::HBox->new(0,5);
my $hv_hb2 = Gtk2::HBox->new(0,5);
my $text_hb1 = Gtk2::HBox->new(1,5);
my $text_hb2 = Gtk2::HBox->new(1,5);
my $text_vb = Gtk2::VBox->new(0,5);

# button decl.
my $popup_button = Gtk2::Button->new('Ok');
my $fc_but = Gtk2::Button->new("Select File...");
my $add_but = Gtk2::Button->new("Add entry");
my $edit_but = Gtk2::Button->new("Edit entry");
my $del_but = Gtk2::Button->new("Delete entry");
my $save_but = Gtk2::Button->new("       Save       ");
my $canc_but = Gtk2::Button->new(" Cancel ");
my $up_but = Gtk2::Button->new("Up");
my $down_but = Gtk2::Button->new("Down");

# label decl.
my $popup_label = Gtk2::Label->new('Please fill all text fields out!');
my $bg_label = Gtk2::Label->new('Background:');
my $x_lab = Gtk2::Label->new("X:");
my $y_lab = Gtk2::Label->new("Y:");
my $prog_label = Gtk2::Label->new("Programm:");
my $com_label = Gtk2::Label->new("Command:");
my $icon_label = Gtk2::Label->new("Icon Path:");
my $res_lab = Gtk2::Label->new("Your resolution:");
my $area_lab = Gtk2::Label->new("Area size (pixel):");
my $at_lab = Gtk2::Label->new("At:");
my $sens_lab = Gtk2::Label->new("Sensitivity (ms):");
my $nc_lab = Gtk2::Label->new("Color:");
my $ac_lab = Gtk2::Label->new("Active Color:");
my $nf_lab = Gtk2::Label->new("Font:");
my $af_lab = Gtk2::Label->new("Active Font:");
my $border_lab = Gtk2::Label->new("Border width:");
my $bordercol_lab = Gtk2::Label->new("Border color:");
my $logo_lab = Gtk2::Label->new;
my $logo2_lab = Gtk2::Label->new;


# entry decl.
my $prog_entry = Gtk2::Entry->new;
my $com_entry = Gtk2::Entry->new;
my $icon_entry = Gtk2::Entry->new;
my $x_entry = Gtk2::Entry->new_with_max_length(4);
my $y_entry = Gtk2::Entry->new_with_max_length(4);
my $area_entry = Gtk2::Entry->new_with_max_length(4);
my $sens_entry = Gtk2::Entry->new_with_max_length(6);
my $border_entry = Gtk2::Entry->new_with_max_length(3);

# combos decl.
my $cor_combo = Gtk2::ComboBox->new_text;
my $res_combo = Gtk2::ComboBox->new_text;

# color buttons delc
my $nc = Gtk2::ColorButton->new(Gtk2::Gdk::Color->new (0,0,0));
my $ac = Gtk2::ColorButton->new(Gtk2::Gdk::Color->new (0,0,0));
my $bg = Gtk2::ColorButton->new(Gtk2::Gdk::Color->new (0,0,0));
my $bor = Gtk2::ColorButton->new(Gtk2::Gdk::Color->new (0,0,0));

# font buttons decl.
my $nf = Gtk2::FontButton->new();
my $af = Gtk2::FontButton->new();

# other decl.
my $cb = Gtk2::CheckButton->new('Show labels');
my $fs = Gtk2::FileSelection->new('Pick something...');
my $align = Gtk2::Alignment->new (1, 0, 0, 0);
my $sep = Gtk2::HSeparator->new;
my $lst = Gtk2::SimpleList->new (
    'Icon'        => 'pixbuf',
    'Programm'    => 'text',
    'Command'    => 'text',
    'Icon Path'    => 'text',
    );

# setting properties etc.
$wnd->set_border_width(5);
$wnd->set_position('center');
$wnd->set_title('Iconbox Settings');
$wnd->set_default_size(0,470);
$x_entry->set_width_chars(4);
$y_entry->set_width_chars(4);
$area_entry->set_width_chars(4);
$sens_entry->set_width_chars(6);
$border_entry->set_width_chars(3);
$popup->set_modal(1);
$popup->set_border_width(5);
$popup->set_position('center');
$popup->add($popup_vb);
$logo_lab->set_markup("<span size='x-large'><b>Icon<span background='#ff0000'"
			." foreground='#ffffff'>Box</span>, v0.2</b></span>");
$logo2_lab->set_markup("<small>configuration tool</small>");
foreach('top: left corner','top: right corner',
    'bottom: left corner','bottom: right corner')
    {$cor_combo->append_text ($_)}
foreach(qw/640x480 800x600 1024x768 1152x864
    1280x960 1280x1024 1600x1200/)
    {$res_combo->append_text ($_)}


# connect the cignals
$wnd->signal_connect(destroy => sub{Gtk2->main_quit();});
$popup_button->signal_connect(clicked => sub{$popup->hide});
$fc_but->signal_connect(clicked => sub{
        $fs->set_select_multiple(0);    
        if($fs->run eq 'ok'){$icon_entry->set_text($fs->get_selections);
                    $fs->hide}
	else{$fs->hide}
});
$add_but->signal_connect(clicked => sub{
    
    if(&are_fields_empty == 0){
        $pb[$#pb+1] = Gtk2::Gdk::Pixbuf->new_from_file($icon_entry->get_text);
        push @{$lst->{data}}, [$pb[$#pb],
                    $prog_entry->get_text,
                    $com_entry->get_text,
                    $icon_entry->get_text];
    $prog_entry->set_text('');
    $com_entry->set_text('');
    $icon_entry->set_text('');
    $ec++;
    }else {return 1};
});
$edit_but->signal_connect(clicked => sub{
    
    if(&are_fields_empty == 0){
        $pb[$#pb+1] = Gtk2::Gdk::Pixbuf->new_from_file($icon_entry->get_text);
        my ($i) = $lst->get_selected_indices;
        $lst->{data}[$i] = [    $pb[$#pb],
                    $prog_entry->get_text,
                    $com_entry->get_text,
                    $icon_entry->get_text];
    $prog_entry->set_text('');
    $com_entry->set_text('');
    $icon_entry->set_text('');
    }else {return 1};
});
$del_but->signal_connect(clicked => sub{

	my ($i) = $lst->get_selected_indices;
	splice @{ $lst->{data} }, $i, 1;
	$ec--;
});
$up_but->signal_connect(clicked => sub{
	my ($i) = $lst->get_selected_indices;
	return 1 unless defined $i;
	return 1 if $i==0;
	(($lst->{data}[$i][0], $lst->{data}[$i][1],
	$lst->{data}[$i][2], $lst->{data}[$i][3]),
	($lst->{data}[$i-1][0],$lst->{data}[$i-1][1],
	$lst->{data}[$i-1][2],$lst->{data}[$i-1][3])) =
	(($lst->{data}[$i-1][0],$lst->{data}[$i-1][1],
	$lst->{data}[$i-1][2],$lst->{data}[$i-1][3]),
	($lst->{data}[$i][0],$lst->{data}[$i][1],
	$lst->{data}[$i][2],$lst->{data}[$i][3]));
	$lst->select($i-1);
});
$down_but->signal_connect(clicked => sub{
	my ($i) = $lst->get_selected_indices;
	return 1 unless defined $i;
	return 1 if $i==$ec-1;
	(($lst->{data}[$i][0],$lst->{data}[$i][1],
	$lst->{data}[$i][2],$lst->{data}[$i][3]),
	($lst->{data}[$i+1][0],$lst->{data}[$i+1][1],
	$lst->{data}[$i+1][2],$lst->{data}[$i+1][3])) =
        (($lst->{data}[$i+1][0],$lst->{data}[$i+1][1],
	$lst->{data}[$i+1][2],$lst->{data}[$i+1][3]),
        ($lst->{data}[$i][0],$lst->{data}[$i][1],
	$lst->{data}[$i][2],$lst->{data}[$i][3]));
	$lst->select($i+1);
});
$lst->signal_connect (row_activated => sub {
        my ($sl, $path, $column) = @_;
        my $row_ref = $sl->get_row_data_from_path ($path);
        $prog_entry->set_text(@$row_ref[1]);
        $com_entry->set_text(@$row_ref[2]);
        $icon_entry->set_text(@$row_ref[3]);
        });

$canc_but->signal_connect(clicked => sub{ Gtk2->main_quit; });
$save_but->signal_connect(clicked => sub{
    unless(-e "$ENV{HOME}/.iconbox"){mkdir("$ENV{HOME}/.iconbox")}
    
    open F, ">$ENV{HOME}/.iconbox/params";
    print F "X: " . $x_entry->get_text;
    print F " Y: " . $y_entry->get_text . "\n";
    print F "color: " . $nc->get_color->red . " "
        . $nc->get_color->green . " "
        . $nc->get_color->blue . "\n";
    print F "active_color: " . $ac->get_color->red . " "
        . $ac->get_color->green . " "
        . $ac->get_color->blue . "\n";
    print F "font: " . $nf->get_font_name . "\n";
    print F "active_font: " . $af->get_font_name . "\n";
    print F "location: " . $cor_combo->get_model->get_value(
                $cor_combo->get_active_iter) . "\n";
    print F "resolution: " . $res_combo->get_model->get_value(
                $res_combo->get_active_iter) . "\n";
    print F "area_size: " . $area_entry->get_text . "\n";
    print F "sensitivity: " . $sens_entry->get_text . "\n";
    print F "show_text: " . ($cb->get_active ? 1 : 0) . "\n";
    print F "background_color: " . $bg->get_color->red . " "
        . $bg->get_color->green . " "
        . $bg->get_color->blue . "\n";
    print F "border_color: " . $bor->get_color->red . " "
        . $bor->get_color->green . " "
        . $bor->get_color->blue . "\n";
    print F "border_width: " . $border_entry->get_text . "\n";
    close F;

    $lst->get_selection->set_mode ('multiple');
    $lst->get_selection->select_all;
    my @i = $lst->get_selected_indices;
    
    open F, ">$ENV{HOME}/.iconbox/progs";
    for(@i){
    print F "$lst->{data}[$_][1]\t$lst->{data}[$_][2]\t$lst->{data}[$_][3]\n";
    }
    close F;
    
    Gtk2->main_quit;
});

# packing, adding...
$xy_hb->pack_start($x_lab,1,0,0);
$xy_hb->pack_start($x_entry,1,0,0);
$xy_hb->pack_start($y_lab,1,0,1);
$xy_hb->pack_start($y_entry,1,0,0);


$wprop_hb->pack_start($bg_label,1,1,5);
$wprop_hb->pack_start($bg,1,1,0);
$wprop_hb->pack_start($bordercol_lab,1,1,0);
$wprop_hb->pack_start($bor,1,1,0);
$wprop_hb->pack_start($border_lab,1,1,0);
$wprop_hb->pack_start($border_entry,1,1,0);

$wprop_hb->pack_start($cb,0,0,0);
$wprop_fr->add($wprop_hb);

$hv_hb1->pack_start($at_lab,1,1,0);
$hv_hb1->pack_start($cor_combo,1,1,0);
$hv_hb1->pack_start($res_lab,1,1,0);
$hv_hb1->pack_start($res_combo,1,1,0);
$hv_hb2->pack_start($area_lab,1,1,0);
$hv_hb2->pack_start($area_entry,1,0,0);
$hv_hb2->pack_start($sens_lab,1,1,0);
$hv_hb2->pack_start($sens_entry,1,0,0);
$hv_vb->pack_start($hv_hb1,1,0,0);
$hv_vb->pack_start($hv_hb2,1,0,0);

$popup_vb->pack_start($popup_label,0,0,0);
$popup_vb->pack_start($popup_button,0,0,0);
$program_vb->pack_start($prog_label,0,0,2);
$program_vb->pack_start($prog_entry,0,0,2);
$pci_hb->pack_start($program_vb,1,1,2);

$command_vb->pack_start($com_label,0,0,2);
$command_vb->pack_start($com_entry,0,0,2);
$pci_hb->pack_start($command_vb,1,1,2);

$icon_hb->pack_start($icon_label,0,0,0);
$icon_hb->pack_start($fc_but,0,0,0);
$icon_vb->pack_start($icon_hb,1,1,2);
$icon_vb->pack_start($icon_entry,1,1,2);
$pci_hb->pack_start($icon_vb,1,1,2);


$lst_vb->pack_start($pci_hb,0,0,0);
$oc_hb->pack_start($canc_but,0,0,0);    
$oc_hb->pack_start($save_but,0,0,0);    
$but_hb->pack_start($add_but,1,1,0);
$but_hb->pack_start($edit_but,1,1,0);
$but_hb->pack_start($del_but,1,1,0);
$but_hb->pack_start($up_but,1,1,0);
$but_hb->pack_start($down_but,1,1,0);
$align->add($oc_hb);
$pos_fr->add($xy_hb);
$logo_vb->pack_start($logo_lab,0,0,0);
$logo_vb->pack_start($logo2_lab,0,0,0);
$fr_hb->pack_start($logo_vb,0,1,10);
$fr_hb->pack_start($pos_fr,1,1,0);

$text_hb1->pack_start($nc_lab,0,0,0);
$text_hb1->pack_start($nc,0,0,0);
$text_hb1->pack_start($ac_lab,0,0,0);
$text_hb1->pack_start($ac,0,0,0);
$text_hb2->pack_start($nf_lab,0,0,0);
$text_hb2->pack_start($nf,0,0,0);
$text_hb2->pack_start($af_lab,0,0,0);
$text_hb2->pack_start($af,0,0,0);

$text_vb->pack_start($text_hb1,0,0,0);
$text_vb->pack_start($text_hb2,0,0,0);

$text_fr->add($text_vb);
$grab_fr->add($hv_vb);
$vb->pack_start($fr_hb,0,1,0);
$vb->pack_start($wprop_fr,0,0,0);
$vb->pack_start($text_fr,0,1,0);
$vb->pack_start($grab_fr,0,0,0);
$scr_wnd->add($lst);
$vb->pack_start($scr_wnd,1,1,0);
$vb->pack_start($lst_vb,0,0,0);
$vb->pack_start($but_hb,0,0,0);
$vb->pack_start($sep,0,0,0);
$vb->pack_start($align,0,0,0);
$wnd->add($vb);

# parsing the config files...
if(-e "$ENV{HOME}/.iconbox/params"){
	open F, "<$ENV{HOME}/.iconbox/params"; @pdata = <F>; close F;
	($_,$x,$_,$y) = split " ", $pdata[0];
	$x=$y=10 if ($y eq '');
}else{ ($x,$y)=(10,10) }

$x_entry->set_text($x);
$y_entry->set_text($y);

if($#pdata == -1){
	$col[1] = $col[2] = $col[3] = 0;
}else{ @col = split " ", $pdata[1];}
$nc->set_color(Gtk2::Gdk::Color->new($col[1],$col[2],$col[3]));

if($#pdata == -1){
	$col[1] = $col[2] = $col[3] = 0;
}else{ @col = split " ", $pdata[2];}
$ac->set_color(Gtk2::Gdk::Color->new($col[1],$col[2],$col[3]));

unless($#pdata == -1){
	@font = split " ", $pdata[3];
	$nf->set_font_name("@font[1..$#font]")
}

unless($#pdata == -1){
	@font = split " ", $pdata[4];
	$af->set_font_name("@font[1..$#font]")
}

my $j=0;
if($#pdata != -1){
	@pos = split " ", $pdata[5];
	if("@pos[1..$#pos]" eq 'top: rigth corner'){$j=1}
	elsif("@pos[1..$#pos]" eq 'bottom: left corner'){$j=2}
	elsif("@pos[1..$#pos]" eq 'bottom: right corner'){$j=3}
}
	$cor_combo->set_active($j);
	
my $k=2;
if($#pdata != -1){
	@res = split " ", $pdata[6];
	if("@res[1..$#res]" eq '640x480'){$k=0}
	elsif("@res[1..$#res]" eq '800x600'){$k=1}
	elsif("@res[1..$#res]" eq '1152x864'){$k=3}
	elsif("@res[1..$#res]" eq '1280x960'){$k=4}
	elsif("@res[1..$#res]" eq '1280x1024'){$k=5}
	elsif("@res[1..$#res]" eq '1600x1200'){$k=6}
}
	$res_combo->set_active($k);

if($#pdata != -1){
	($m, $a) = split " ", $pdata[7];
}else {$a = 10}

$area_entry->set_text($a);

if($#pdata != -1){
	($m, $s) = split " ", $pdata[8];
}else{$s = 200}
$sens_entry->set_text($s);

if($#pdata != -1){
	($m,$c) = split " ", $pdata[9];
}else{$c=1}
$cb->set_active($c);

if($#pdata == -1){
	$col[1] = $col[2] = $col[3] = 0;
}else{ @col = split " ", $pdata[10];}
$bg->set_color(Gtk2::Gdk::Color->new($col[1],$col[2],$col[3]));

if($#pdata == -1){
	$col[1] = $col[2] = $col[3] = 0;
}else{ @col = split " ", $pdata[11];}
$bor->set_color(Gtk2::Gdk::Color->new($col[1],$col[2],$col[3]));

if($#pdata != -1){
	($m, $b) = split " ", $pdata[12];
}else{$b = 200}
$border_entry->set_text($b);




if(-e "$ENV{HOME}/.iconbox/progs"){
	open F, "<$ENV{HOME}/.iconbox/progs"; @pdata = <F>; close F;
}

unless($#pdata == -1){
    for my $l(@pdata){
    $ec++;
    chomp $l;
    my @ldata = split "\t", $l;
    if(-e $ldata[2]){
    	$pb[$#pb+1] = Gtk2::Gdk::Pixbuf->new_from_file($ldata[2])}
    else{print "Error: '$ldata[2]' not found!\n";$ldata[2]=undef;}
    push @{$lst->{data}}, [$pb[$#pb],$ldata[0],$ldata[1],$ldata[2]];
    }
}
# end of parsing

# let's go...
$wnd->show_all;

Gtk2->main;

0;

# checkes whether text fields are empty
sub are_fields_empty {
   if($icon_entry->get_text eq '' ||
       $com_entry->get_text eq '' ||
       $prog_entry->get_text eq ''){
       
    $popup->show_all;
      return 1;
   }
return 0;
}
