package interactive::gtk; # $Id: gtk.pm 261628 2009-10-09 16:25:51Z tv $
use diagnostics;
use strict;
use vars qw(@ISA);
@ISA = qw(interactive);
use interactive;
use common;
use mygtk3;
use ugtk3 qw(:helpers :wrappers :create);
my $forgetTime = 1000; #- in milli-seconds
sub new {
my $w = &interactive::new;
($w->{windowwidth}, $w->{windowheight}) = mygtk3::root_window_size() if !$::isInstall;
$w;
}
sub enter_console { my ($o) = @_; $o->{suspended} = common::setVirtual(1) }
sub leave_console { my ($o) = @_; common::setVirtual(delete $o->{suspended}) }
sub adapt_markup {
#- nothing needed, the default markup is gtk3's
my ($_o, $s) = @_; return $s;
}
sub exit { ugtk3::exit(@_) }
sub ask_fileW {
my ($in, $common) = @_;
my $w = ugtk3::create_file_selector(%$common);
my $file;
$w->main(sub {
$file = $w->{chooser}->get_filename;
my $err = ugtk3::file_selected_check($common->{save}, $common->{want_a_dir}, $file);
$err and $in->ask_warn('', $err);
!$err;
}) && $file;
}
sub create_boxradio {
my ($e, $onchange_f, $double_click) = @_;
my $boxradio = gtkpack2__(Gtk3::VBox->new,
my @radios = gtkradio('', @{$e->{formatted_list}}));
mapn {
my ($txt, $w) = @_;
# workaround infamous 6 years old gnome bug #101968:
$w->get_child->set_size_request(mygtk3::get_label_width(), -1) if $e->{alignment} ne 'right' && !$e->{label};
$w->signal_connect(button_press_event => $double_click) if $double_click;
$w->signal_connect(key_press_event => $e->{may_go_to_next});
$w->signal_connect(clicked => sub {
${$e->{val}} ne $txt or return;
$onchange_f->(sub { $txt });
});
if ($e->{help}) {
$w->set_tooltip_text(
ref($e->{help}) eq 'HASH' ? $e->{help}{$txt} :
ref($e->{help}) eq 'CODE' ? $e->{help}($txt) : $e->{help});
}
} $e->{list}, \@radios;
$boxradio, sub {
my ($v, $full_struct) = @_;
mapn {
$_[0]->set_active($_[1] eq $v);
$full_struct->{focus_w} = $_[0] if $_[1] eq $v;
} \@radios, $e->{list};
}, $radios[0];
}
sub create_treeview_list {
my ($e, $onchange_f, $double_click) = @_;
my $curr;
my $list = Gtk3::ListStore->new("Glib::String");
my $list_tv = Gtk3::TreeView->new_with_model($list);
$list_tv->set_headers_visible(0);
$list_tv->get_selection->set_mode('browse');
my $textcolumn = Gtk3::TreeViewColumn->new_with_attributes("", my $renderer = Gtk3::CellRendererText->new, 'text' => 0);
$list_tv->append_column($textcolumn);
$renderer->set_property('ellipsize', 'end');
my $select = sub {
my ($path) = @_;
return if !$list_tv->get_model;
$list_tv->set_cursor($path, undef, 0);
Glib::Timeout->add(100, sub { $list_tv->scroll_to_cell($path, undef, 1, 0.5, 0); 0 });
};
my ($starting_word, $start_reg) = ('', '^');
my $timeout;
$list_tv->set_enable_search(0);
$list_tv->signal_connect(key_press_event => sub {
my ($_w, $event) = @_;
my $c = chr($event->keyval & 0xff);
Glib::Source->remove($timeout) if $timeout; $timeout = '';
if ($event->keyval >= 0x100) {
$e->{may_go_to_next}(), return 1 if member($event->keyval, (Gtk3::Gdk::KEY_Return, Gtk3::Gdk::KEY_KP_Enter));
$starting_word = '' if !member($event->keyval, (Gtk3::Gdk::KEY_Control_L, Gtk3::Gdk::KEY_Control_R));
} else {
if (member('control-mask', @{$event->state})) {
$c eq 's' or return 1;
$start_reg and $start_reg = '', return 1;
$curr++;
} else {
$e->{may_go_to_next}(), return 1 if $c eq ' ';
$curr++ if $starting_word eq '' || $starting_word eq $c;
$starting_word .= $c unless $starting_word eq $c;
}
my @l = @{$e->{formatted_list}};
my $word = quotemeta $starting_word;
my $j; for ($j = 0; $j < @l; $j++) {
$l[($j + $curr) % @l] =~ /$start_reg$word/i and last;
}
if ($j == @l) {
$starting_word = '';
} else {
$select->(Gtk3::TreePath->new_from_string(($j + $curr) % @l));
}
$timeout = Glib::Timeout->add($forgetTime, sub { $timeout = $starting_word = ''; 0 });
}
0;
});
$list_tv->show;
$list->append_set([ 0 => $_ ]) foreach @{$e->{formatted_list}};
$list_tv->get_selection->signal_connect(changed => sub {
my ($model, $iter) = $_[0]->get_selected;
$model && $iter or return;
$onchange_f->(sub {
my $row = $model->get_path_str($iter);
$e->{list}[$curr = $row];
});
});
$list_tv->signal_connect(button_press_event => $double_click) if $double_click;
|