summaryrefslogtreecommitdiffstats
path: root/perl-install/interactive_newt.pm
diff options
context:
space:
mode:
Diffstat (limited to 'perl-install/interactive_newt.pm')
-rw-r--r--perl-install/interactive_newt.pm442
1 files changed, 237 insertions, 205 deletions
diff --git a/perl-install/interactive_newt.pm b/perl-install/interactive_newt.pm
index b6d5823a3..4c4c0e65e 100644
--- a/perl-install/interactive_newt.pm
+++ b/perl-install/interactive_newt.pm
@@ -1,4 +1,4 @@
-package interactive_newt;
+package interactive_newt; # $Id$
use diagnostics;
use strict;
@@ -8,221 +8,253 @@ use vars qw(@ISA);
use interactive;
use common qw(:common :functional);
-use Term::Newt;
-
-my $n = Term::Newt->new;
-$n->init;
-$n->cls;
-
-#sub ask_from_entryW {
-# my ($o, $title, $messages, $def) = @_;
-# my $w = my_gtk->new($title, %$o);
-# $w->_ask_from_entry(@$messages);
-# $w->main;
-#}
+use log;
+use Newt::Newt; #- !! provides Newt and not Newt::Newt
+
+my $width = 80;
+my $height = 25;
+my @wait_messages;
+
+sub new() {
+ Newt::Init;
+ Newt::Cls;
+ Newt::SetSuspendCallback;
+ open STDERR,">/dev/null" if $::isStandalone;
+ bless {}, $_[0];
+}
+
+sub enter_console { Newt::Suspend }
+sub leave_console { Newt::Resume }
+sub suspend { Newt::Suspend }
+sub resume { Newt::Resume }
+sub end() { Newt::Finished }
+sub exit() { end; exit($_[0]) }
+END { end() }
+
+sub myTextbox {
+ my @l = map { split "\n" } @_;
+ my $mess = Newt::Component::Textbox(1, 0, my $w = max(map { length } @l) + 1, my $h = @l, 1 << 6);
+ $mess->TextboxSetText(join("\n", @_));
+ $mess, $w + 1, $h;
+}
+
+sub separator($$) {
+ my $blank = Newt::Component::Form(\undef, '', 0);
+ $blank->FormSetWidth ($_[0]);
+ $blank->FormSetHeight($_[1]);
+ $blank;
+}
+sub checkval($) { $_[0] && $_[0] ne ' ' ? '*' : ' ' }
+
sub ask_from_listW {
my ($o, $title_, $messages, $l, $def) = @_;
my ($title, @okcancel) = ref $title_ ? @$title_ : ($title_, _("Ok"), _("Cancel"));
+
my $mesg = join("\n", @$messages);
+ my $len = 0; $len += length($_) foreach @$l;
if (@$l == 1) {
- $n->win_message($title, @$l, $mesg);
+ Newt::WinMessage($title, @$l, $mesg);
$l->[0];
- } elsif (@$l == 2) {
- $l->[$n->win_choice($title, @$l, $mesg) - 1];
- } elsif (@$l == 3) {
- $l->[$n->win_ternary($title, @$l, $mesg) - 1];
+#- because newt will not try to remove window if bigger than screen !
+ } elsif (@$l == 2 && $len < 64) {
+ $l->[Newt::WinChoice($title, @$l, $mesg) - 1];
+#- because newt will not try to remove window if bigger than screen !
+ } elsif (@$l == 3 && $len < 64) {
+ $l->[Newt::WinTernary($title, @$l, $mesg) - 1];
} else {
+ my $special = !@okcancel;
+ if ($special) {
+ $l = [ @$l ];
+ @okcancel = pop @$l;
+ }
my $i; map_index { $i = $::i if $def eq $_ } @$l;
- print STDERR "($i)\n";
- my ($r, $e) = $n->newtWinMenu($title, $mesg, 40, 5, 5, 8, $l, $i, @okcancel);
- return if $r > 1;
- $l->[$e];
+ my ($r, $e) = Newt::WinMenu($title, $mesg, 40, 5, 5, 8, $l, $i, @okcancel);
+ $r > 1 and die "ask_from_list cancel";
+ if ($special) {
+ $r ? $okcancel[0] : $l->[$e];
+ } else {
+ $l->[$e];
+ }
}
}
-#sub ask_many_from_list_refW($$$$$) {
-# my ($o, $title, $messages, $list, $val) = @_;
-# my $n = 0;
-# my $w = my_gtk->new('', %$o);
-# my $box = gtkpack(new Gtk::VBox(0,0),
-# map {
-# my $nn = $n++;
-# my $o = Gtk::CheckButton->new($_);
-# $o->set_active(${$val->[$nn]});
-# $o->signal_connect(clicked => sub { invbool \${$val->[$nn]} });
-# $o;
-# } @$list);
-# gtkadd($w->{window},
-# gtkpack_(create_box_with_title($w, @$messages),
-# 1, @$list > 11 ? gtkset_usize(createScrolledWindow($box), 0, 250) : $box,
-# 0, $w->create_okcancel,
-# )
-# );
-# $w->{ok}->grab_focus;
-# $w->main && $val;
-#}
-#
-#
-#sub ask_from_entries_refW {
-# my ($o, $title, $messages, $l, $val, %hcallback) = @_;
-# my ($title_, @okcancel) = ref $title ? @$title : $title;
-# my $num_fields = @{$l};
-# my $ignore = 0; #-to handle recursivity
-#
-# my $w = my_gtk->new($title_, %$o);
-# #-the widgets
-# my @widgets = map {
-# if ($_->{type} eq "list") {
-# my $w = new Gtk::Combo;
-# $w->set_use_arrows_always(1);
-# $w->entry->set_editable(!$_->{not_edit});
-# $w->set_popdown_strings(@{$_->{list}});
-# $w->disable_activate;
-# $_->{val} ||= $_->{list}[0];
-# $w;
-# } elsif ($_->{type} eq "bool") {
-# my $w = Gtk::CheckButton->new($_->{text});
-# $w->set_active(${$_->{val}});
-# my $i = $_; $w->signal_connect(clicked => sub { $ignore or invbool \${$i->{val}} });
-# $w;
-# } else {
-# new Gtk::Entry;
-# }
-# } @{$val};
-# my $ok = $w->create_okcancel(@okcancel);
-#
-# sub widget {
-# my ($w, $ref) = @_;
-# ($ref->{type} eq "list" && @{$ref->{list}}) ? $w->entry : $w
-# }
-# my @updates = mapn {
-# my ($w, $ref) = @_;
-# sub {
-# $ref->{type} eq "bool" and return;
-# ${$ref->{val}} = widget($w, $ref)->get_text;
-# };
-# } \@widgets, $val;
-#
-# my @updates_inv = mapn {
-# my ($w, $ref) = @_;
-# sub {
-# $ref->{type} eq "bool" ?
-# $w->set_active(${$ref->{val}}) :
-# widget($w, $ref)->set_text(${$ref->{val}})
-# };
-# } \@widgets, $val;
-#
-#
-# for (my $i = 0; $i < $num_fields; $i++) {
-# my $ind = $i; #-cos lexical bindings pb !!
-# my $widget = widget($widgets[$i], $val->[$i]);
-# my $changed_callback = sub {
-# return if $ignore; #-handle recursive deadlock
-# &{$updates[$ind]};
-# if ($hcallback{changed}) {
-# &{$hcallback{changed}}($ind);
-# #update all the value
-# $ignore = 1;
-# &$_ foreach @updates_inv;
-# $ignore = 0;
-# };
-# };
-# if ($hcallback{focus_out}) {
-# my $focusout_callback = sub {
-# return if $ignore;
-# &{$hcallback{focus_out}}($ind);
-# #update all the value
-# $ignore = 1;
-# &$_ foreach @updates_inv;
-# $ignore = 0;
-# };
-# $widget->signal_connect(focus_out_event => $focusout_callback);
-# }
-# if (ref $widget eq "Gtk::Entry") {
-# $widget->signal_connect(changed => $changed_callback);
-# my $go_to_next = sub {
-# if ($ind == ($num_fields -1)) {
-# $w->{ok}->grab_focus();
-# } else {
-# widget($widgets[$ind+1],$val->[$ind+1])->grab_focus();
-# }
-# };
-# $widget->signal_connect(activate => $go_to_next);
-# $widget->signal_connect(key_press_event => sub {
-# my ($w, $e) = @_;
-# #-don't know why it works, i believe that
-# #-i must say before &$go_to_next, but with it doen't work HACK!
-# $w->signal_emit_stop("key_press_event") if chr($e->{keyval}) eq "\x8d";
-# });
-# $widget->set_text(${$val->[$i]{val}}) if ${$val->[$i]{val}};
-# $widget->set_visibility(0) if $val->[$i]{hidden};
-# }
-# &{$updates[$i]};
-# }
-#
-# my @entry_list = mapn { [($_[0], $_[1])]} $l, \@widgets;
-#
-# gtkadd($w->{window},
-# gtkpack(
-# create_box_with_title($w, @$messages),
-# create_packtable({}, @entry_list),
-# $ok
-# ));
-# widget($widgets[0],$val->[0])->grab_focus();
-# if ($hcallback{complete}) {
-# my $callback = sub {
-# my ($error, $focus) = &{$hcallback{complete}};
-# #-update all the value
-# $ignore = 1;
-# foreach (@updates_inv) { &{$_};}
-# $ignore = 0;
-# if ($error) {
-# $focus ||= 0;
-# widget($widgets[$focus], $val->[$focus])->grab_focus();
-# } else {
-# return 1;
-# }
-# };
-# #$w->{ok}->signal_connect(clicked => $callback)
-# $w->main($callback);
-# } else {
-# $w->main();
-# }
-#}
-#
-#
-#sub wait_messageW($$$) {
-# my ($o, $title, $message) = @_;
-#
-# my $w = my_gtk->new($title, %$o, grab => 1);
-# my $W = pop @$message;
-# gtkadd($w->{window},
-# gtkpack(new Gtk::VBox(0,0),
-# @$message,
-# $w->{wait_messageW} = new Gtk::Label($W)));
-# $w->sync;
-# $w;
-#}
-#sub wait_message_nextW {
-# my ($o, $message, $w) = @_;
-# $w->{wait_messageW}->set($message);
-# $w->sync;
-#}
-#sub wait_message_endW {
-# my ($o, $w) = @_;
-# $w->destroy;
-#}
-#
-#sub kill {
-# my ($o) = @_;
-# $o->{before_killing} ||= 0;
-# while (@interactive::objects > $o->{before_killing}) {
-# my $w = pop @interactive::objects;
-# $w->destroy;
-# }
-# @my_gtk::grabbed = ();
-# $o->{before_killing} = @interactive::objects;
-#}
+sub ask_many_from_listW {
+ my ($o, $title, $messages, $l) = @_;
+ my ($list, $val) = ($l->{labels}, $l->{ref});
+ my $height = min(int @$list, 18);
+
+ my $sb = Newt::Component::VerticalScrollbar(-1, -1, $height, 9, 10);
+ my $checklist = $sb->Form('', 0);
+ $checklist->FormSetHeight($height);
+ $checklist->FormSetBackground(9);
+
+ my @l = map_index {
+ Newt::Component::Checkbox(1, $::i + 1, $_, checkval(${$val->[$::i]} ||= ''), " *");
+ } @$list;
+ $checklist->FormAddComponent($_) foreach @l;
+
+ my $listg = Newt::Grid::HCloseStacked($checklist, $height < @$list ? (separator(1, $height), $sb) : ());
+
+ my ($buttons, $ok, $cancel) = Newt::Grid::ButtonBar(_("Ok"), _("Cancel"));
+
+ my $form = Newt::Component::Form(\undef, '', 0);
+ my $window = Newt::Grid::GridBasicWindow(first(myTextbox(@$messages)), $listg, $buttons);
+ $window->GridWrappedWindow($title);
+ $window->GridAddComponentsToForm($form, 1);
+ my $r = $form->RunForm;
+
+ $form->FormDestroy;
+ Newt::PopWindow;
+
+ $$r == $$cancel and return;
+
+ mapn {
+ my ($a, $b) = @_;
+ $$a = $b->CheckboxGetValue == ord '*';
+ } $val, \@l;
+
+ 1;
+}
+
+
+sub ask_from_entries_refW {
+ my ($o, $title, $messages, $l, $val, %hcallback) = @_;
+ my ($title_, @okcancel) = deref($title);
+ my $ignore; #-to handle recursivity
+ my $old_focus = -2;
+
+ #-the widgets
+ my @widgets = map {
+#- $_->{type} = "entry" if $_->{type} eq "list" && !$_->{not_edit};
+ ${$_->{val}} ||= '';
+ if ($_->{type} eq "list") {
+ my $w = Newt::Component::Listbox(-1, -1, 1, 0);
+ $w->ListboxSetWidth(20);
+ $w->ListboxAddEntry($_) foreach @{$_->{list}};
+ $w;
+ } elsif ($_->{type} eq "bool") {
+ Newt::Component::Checkbox(-1, -1, $_->{text} || '', checkval(${$_->{val}}), " *");
+ } else {
+ Newt::Component::Entry(-1, -1, '', 20, ($_->{hidden} && 1 << 1) | 1 << 2);
+ }
+ } @$val;
+
+ my @updates = mapn {
+ my ($w, $ref) = @_;
+ sub {
+ ${$ref->{val}} =
+ $ref->{type} eq "bool" ?
+ $w->CheckboxGetValue == ord '*' :
+ $ref->{type} eq "list" ?
+ $w->ListboxGetCurrent :
+ $w->EntryGetValue;
+ };
+ } \@widgets, $val;
+
+ my @updates_inv = mapn {
+ my ($w, $ref) = @_;
+ sub {
+ my $val = ${$ref->{val}};
+ $ignore = 1;
+ if ($ref->{type} eq "bool") {
+ $w->CheckboxSetValue(checkval($val));
+ } elsif ($ref->{type} eq "list") {
+ map_index {
+ $w->ListboxSetCurrent($::i) if $val eq $_;
+ } @{$ref->{list}};
+ } else {
+ $w->EntrySet($val, 1);
+ }
+ $ignore = 0;
+ };
+ } \@widgets, $val;
+
+ &$_ foreach @updates_inv;
+
+ #- !! callbacks must be kept in a list otherwise perl will free them !!
+ #- (better handling of addCallback needed)
+ my @callbacks = map_index {
+ my $ind = $::i;
+ sub {
+ return if $ignore; #-handle recursive deadlock
+ return $old_focus++ if $old_focus == -2; #- handle special first case
+
+ &$_ foreach @updates;
+
+ #- TODO: this is very rough :(
+ if ($old_focus == $ind) {
+ $hcallback{changed}->($ind) if $hcallback{changed};
+ } else {
+ $hcallback{focus_out}->($ind) if $hcallback{focus_out};
+ }
+ &$_ foreach @updates_inv;
+ $old_focus = $ind;
+ };
+ } @widgets;
+ map_index { $_->addCallback($callbacks[$::i]) } @widgets;
+
+ my $grid = Newt::Grid::CreateGrid(3, int @$l);
+ map_index {
+ $grid->GridSetField(0, $::i, 1, ${Newt::Component::Label(-1, -1, $_)}, 0, 0, 1, 0, 1, 0);
+ $grid->GridSetField(1, $::i, 1, ${$widgets[$::i]}, 0, 0, 0, 0, 1, 0);
+ } @$l;
+
+ my ($buttons, $ok, $cancel) = Newt::Grid::ButtonBar(@okcancel);
+
+ my $form = Newt::Component::Form(\undef, '', 0) or die;
+ my $window = Newt::Grid::GridBasicWindow(first(myTextbox(@$messages)), $grid, $buttons);
+ $window->GridWrappedWindow($title_);
+ $window->GridAddComponentsToForm($form, 1);
+
+ run:
+ my $r = $form->RunForm;
+ &$_ foreach @updates;
+
+ if ($$r != $$cancel && $hcallback{complete}) {
+ my ($error, $focus) = $hcallback{complete}->();
+ #-update all the value
+ &$_ foreach @updates_inv;
+ goto run if $error;
+ }
+ $form->FormDestroy;
+ Newt::PopWindow;
+ $$r != $$cancel;
+}
+
+
+sub waitbox($$) {
+ my ($title, $messages) = @_;
+ my ($t, $w, $h) = myTextbox(@$messages);
+ my $f = Newt::Component::Form(\undef, '', 0);
+ Newt::CenteredWindow($w, $h, $title);
+ $f->FormAddComponent($t);
+ $f->DrawForm;
+ Newt::Refresh;
+ $f->FormDestroy;
+ push @wait_messages, $f;
+ $f;
+}
+
+
+sub wait_messageW($$$) {
+ my ($o, $title, $messages) = @_;
+ { form => waitbox($title, $messages), title => $title };
+}
+
+sub wait_message_nextW {
+ my ($o, $messages, $w) = @_;
+ $o->wait_message_endW($w);
+ $o->wait_messageW($w->{title}, $messages);
+}
+sub wait_message_endW {
+ my ($o, $w) = @_;
+ log::l("interactive_newt does not handle none stacked wait-messages") if $w->{form} != pop @wait_messages;
+ Newt::PopWindow;
+}
+
+sub kill {
+}
+
1;