File Coverage

blib/lib/Tk/XDialogBox.pm
Criterion Covered Total %
statement 12 12 100.0
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 16 16 100.0


line stmt bran cond sub pod time code
1             #
2             # DialogBox is similar to Dialog except that it allows any widget
3             # in the top frame. Widgets can be added with the add method. Currently
4             # there exists no way of deleting a widget once it has been added.
5             #
6             # ... and need many Features ;-) This is a patched Version from original
7             # Tk::DialogBox, written by xpix
8             #
9             # - Show - new Option 'nograb'
10             # - check_callback new Option check_callback, return true and Window is close
11             # - Focus($widget), set Focus on Widget
12             # - width and height for size from the dialogbox
13             # - from_x and from_y for koordinates to open the dialog box
14              
15             package Tk::XDialogBox;
16              
17 1     1   873 use strict;
  1         2  
  1         35  
18 1     1   5 use Carp;
  1         2  
  1         93  
19              
20 1     1   6 use vars qw($VERSION);
  1         6  
  1         62  
21             $VERSION = '3.032'; # $Id: //depot/Tk8/Tixish/DialogBox.pm#32 $
22              
23 1     1   5 use base qw(Tk::Toplevel);
  1         2  
  1         2160  
24              
25             Tk::Widget->Construct('XDialogBox');
26              
27             sub Populate {
28             my ($cw, $args) = @_;
29              
30             $cw->SUPER::Populate($args);
31             my $buttons = delete $args->{'-buttons'};
32             $buttons = ['OK'] unless defined $buttons;
33             my $default_button = delete $args->{'-default_button'};
34             $default_button = $buttons->[0] unless defined $default_button;
35             my $check_cb = delete $args->{'-check_callback'};
36             my $height = delete $args->{'-height'};
37             my $width = delete $args->{'-width'};
38             $cw->{'selected_button'} = '';
39             # $cw->transient($cw->Parent->toplevel);
40             # $cw->withdraw;
41             $cw->protocol('WM_DELETE_WINDOW' => sub {});
42              
43             # Patch: center from Mainwindow
44             my $from_x = delete $args->{'-from_x'};
45             my $from_y = delete $args->{'-from_y'};
46             my ($p_posw, $p_posh, $p_posx, $p_posy) = split(/[x\+]/,$cw->MainWindow->geometry);
47             my $new_geometry = sprintf('%s+%d+%d', (defined $width and defined $height ? sprintf('%dx%d', $width, $height) : ''), int($p_posx + ($from_x || 50)), int($p_posy + ($from_y || 50)));
48             $cw->geometry( $new_geometry );
49             # --
50              
51             # Patch: Close at Escape
52             $cw->bind('', sub{ $cw->destroy } );
53              
54            
55             # create the two frames
56             my $top = $cw->Component('Frame', 'top');
57             $top->configure(-relief => 'raised', -bd => 1) unless $Tk::platform eq 'MSWin32';
58             my $bot = $cw->Component('Frame', 'bottom');
59             $bot->configure(-relief => 'raised', -bd => 1) unless $Tk::platform eq 'MSWin32';
60             $bot->pack(qw/-side bottom -fill both -ipady 3 -ipadx 3/);
61             $top->pack(qw/-side top -fill both -ipady 3 -ipadx 3 -expand 1/);
62              
63             # create a row of buttons in the bottom.
64             my $bl; # foreach my $var: perl > 5.003_08
65             foreach $bl (@$buttons)
66             {
67             my $b = $bot->Button(
68             -text => $bl,
69             -command => sub {
70             # Patch, new Option check_callback
71             if(defined $check_cb and ref $check_cb eq 'CODE' and &$check_cb($bl)) {
72             $cw->{'selected_button'} = "$bl";
73             } elsif(! defined $check_cb) {
74             $cw->{'selected_button'} = "$bl";
75             }
76             },
77             );
78             $cw->Advertise("B_$bl" => $b);
79             if ($Tk::platform eq 'MSWin32')
80             {
81             $b->configure(-width => 10, -pady => 0);
82             }
83             if ($bl eq $default_button) {
84             if ($Tk::platform eq 'MSWin32') {
85             $b->pack(-side => 'left', -expand => 1, -padx => 1, -pady => 1);
86             } else {
87             my $db = $bot->Frame(-relief => 'sunken', -bd => 1);
88             $b->raise($db);
89             $b->pack(-in => $db, -padx => '2', -pady => '2');
90             $db->pack(-side => 'left', -expand => 1, -padx => 1, -pady => 1);
91             }
92             $cw->bind('' => [ $b, 'Invoke']);
93             $cw->bind('' => [ $b, 'Invoke']);
94             $cw->bind('', [ $b, 'Invoke'] );
95             $cw->bind('', [ $b, 'Invoke'] );
96             $cw->{'default_button'} = $b;
97             } else {
98             $b->pack(-side => 'left', -expand => 1, -padx => 1, -pady => 1);
99             }
100             }
101             $cw->ConfigSpecs(-command => ['CALLBACK', undef, undef, undef ],
102             -foreground => ['DESCENDANTS', 'foreground','Foreground', 'black'],
103             -background => ['DESCENDANTS', 'background','Background', undef],
104             );
105             $cw->Delegates('Construct',$top);
106             }
107              
108             sub add {
109             my ($cw, $wnam, @args) = @_;
110             my $w = $cw->Subwidget('top')->$wnam(@args);
111             $cw->Advertise("\L$wnam" => $w);
112             return $w;
113             }
114              
115             sub Focus {
116             my $cw = shift;
117             my $widget = shift || return $cw->{'focus'};
118             $cw->{'focus'} = $widget;
119             }
120              
121             sub Wait
122             {
123             my $cw = shift;
124             $cw->waitVariable(\$cw->{'selected_button'});
125             $cw->grabRelease;
126             $cw->withdraw;
127             $cw->Callback(-command => $cw->{'selected_button'});
128             }
129              
130             sub Show {
131             my ($cw, $grab) = @_;
132             croak 'DialogBox: "Show" method requires at least 1 argument'
133             if scalar @_ < 1;
134             my $old_focus = $cw->focusSave;
135             my $old_grab = $cw->grabSave;
136              
137             # $cw->Popup();
138             $cw->update;
139              
140             Tk::catch {
141             if (defined $grab && length $grab && ($grab =~ /global/)) {
142             $cw->grabGlobal;
143             } elsif(defined $grab && length $grab && ($grab =~ /nograb/)) {
144             # No Grab
145             } else {
146             $cw->grab;
147             }
148             };
149             if (defined $cw->{'focus'}) {
150             $cw->{'focus'}->focus;
151             } elsif (defined $cw->{'default_button'}) {
152             $cw->{'default_button'}->focus;
153             } else {
154             $cw->focus;
155             }
156             $cw->Wait;
157             &$old_focus;
158             &$old_grab;
159             return $cw->{'selected_button'};
160             }
161              
162             1;
163              
164              
165             =head1 NAME
166              
167             Tk::XDialogBox - create and manipulate a dialog screen with added Features.
168              
169             =for pm Tixish/DialogBox.pm
170              
171             =for category Tix Extensions
172              
173             =head1 SYNOPSIS
174              
175             use Tk::DialogBox
176             ...
177             $d = $top->DialogBox(
178             -title => "Title",
179             -buttons => ["OK", "Cancel"],
180             -check_callback => sub {
181             my $answer = shift;
182             if ( $answer eq 'OK') {
183             error('Col1 must be a number!');
184             return undef;
185             }
186             return 1;
187             },
188             );
189             $w = $d->add(Widget, args);
190             $d->Focus(Widget); # set new Focus on a Widget
191             $button = $d->Show;
192              
193             =head1 DESCRIPTION
194              
195             B is very similar to B except that it allows
196             any widget in the top frame. B creates two
197             frames---"top" and "bottom". The bottom frame shows all the
198             specified buttons, lined up from left to right. The top frame acts
199             as a container for all other widgets that can be added with the
200             B method. The non-standard options recognized by
201             B are as follows:
202              
203             =head1 PATCHES
204              
205             - Show - new Option 'nograb'
206              
207             - check_callback new Option check_callback, return true and Window is close
208              
209             - Focus($widget), set Focus on Widget
210              
211             - width and height for resize the dialogbox
212              
213             - from_x and from_y for coordinates to open the dialog box
214              
215              
216             =head1 OPTIONS
217              
218              
219             =over 4
220              
221             =item B<-title>
222              
223             Specify the title of the dialog box. If this is not set, then the
224             name of the program is used.
225              
226             =item B<-buttons>
227              
228             The buttons to display in the bottom frame. This is a reference to
229             an array of strings containing the text to put on each
230             button. There is no default value for this. If you do not specify
231             any buttons, no buttons will be displayed.
232              
233             =item B<-default_button>
234              
235             Specifies the default button that is considered invoked when user
236             presses on the dialog box. This button is highlighted. If
237             no default button is specified, then the first element of the
238             array whose reference is passed to the B<-buttons> option is used
239             as the default.
240              
241             =item B<-check_callback>
242              
243             Option check_callback, this will run the subroutine when submit ever
244             button. The callback have one Parameter, the buttontext. If the return undef,
245             then the dialogbox will not close.
246              
247             -check_callback => sub {
248             my $answer = shift;
249             if ( $answer eq 'Save') {
250             error('Col1 must be a number!');
251             return undef;
252             }
253             return 1;
254             },
255              
256             =item B<-width>
257              
258             Width in pixel.
259              
260             =item B<-heigth>
261              
262             Heigth in pixel.
263              
264             =item B<-from_x>
265              
266             Specifies the Coordinates to place
267             the dialogbox in the screen. It is default 50.
268              
269             =item B<-from_y>
270              
271             Specifies the Coordinates to place
272             the dialogbox in the screen. It is default 50.
273              
274              
275             =back
276              
277             =head1 METHODS
278              
279             B supports only two methods as of now:
280              
281             =over 4
282              
283             =item BI, IB<)>
284              
285             Add the widget indicated by I. I can be the name
286             of any Tk widget (standard or contributed). I are the
287             options that the widget accepts. The widget is advertized as a
288             subwidget of B.
289              
290             =item BIB< or -nograb)>
291              
292             Display the dialog box, until user invokes one of the buttons in
293             the bottom frame. If the grab type is specified in I, then
294             B uses that grab; otherwise it uses a local grab. With -nograb switch off the grabbing
295             Returns the name of the button invoked.
296              
297             =item BIB<)>
298              
299             Set the focus on the widget and not on the defaultbutton.
300              
301             =back
302              
303             =head1 BINDINGS
304              
305             =item Escape
306              
307             close the Dialogbox
308              
309             =item Return and KP_Enter
310              
311             Submit the first Button
312              
313             =item and
314              
315             Submit the first Button
316              
317              
318             =head1 BUGS
319              
320             There is no way of removing a widget once it has been added to the
321             top frame.
322              
323             There is no control over the appearance of the buttons in the
324             bottom frame nor is there any way to control the placement of the
325             two frames with respect to each other e.g. widgets to the left,
326             buttons to the right instead of widgets on the top and buttons on
327             the bottom always.
328              
329             =head1 AUTHOR
330              
331             B rsi@earthling.net
332              
333             This code is distributed under the same terms as Perl.
334              
335             Patched and additional features by Frank (xpix) Herrmann
336              
337             =cut
338