File Coverage

blib/lib/Curses/UI/Widget.pm
Criterion Covered Total %
statement 202 500 40.4
branch 77 286 26.9
condition 29 116 25.0
subroutine 30 67 44.7
pod 32 56 57.1
total 370 1025 36.1


line stmt bran cond sub pod time code
1             # ----------------------------------------------------------------------
2             # Curses::UI::Widget
3             #
4             # (c) 2001-2002 by Maurice Makaay. All rights reserved.
5             # This file is part of Curses::UI. Curses::UI is free software.
6             # You can redistribute it and/or modify it under the same terms
7             # as perl itself.
8             #
9             # Currently maintained by Marcus Thiesen
10             # e-mail: marcus@cpan.thiesenweb.de
11             # ----------------------------------------------------------------------
12              
13             package Curses::UI::Widget;
14              
15 8     8   42 use strict;
  8         17  
  8         809  
16 8     8   45 use Carp qw(confess);
  8         17  
  8         10763  
17 8     8   125 use Term::ReadKey;
  8         17  
  8         678  
18 8     8   42 use Curses;
  8         11  
  8         25503  
19 8     8   71 use Curses::UI::Common;
  8         18  
  8         1140  
20             require Exporter;
21              
22 8         73814 use vars qw(
23             $VERSION
24             @ISA
25             @EXPORT
26 8     8   47 );
  8         17  
27              
28             $VERSION = '1.12';
29              
30             @ISA = qw(
31             Curses::UI::Common
32             Exporter
33             );
34              
35             @EXPORT = qw(
36             height_by_windowscrheight
37             width_by_windowscrwidth
38             process_padding
39             loose_focus
40             lose_focus
41             );
42              
43             sub new ()
44             {
45 19     19 1 29 my $class = shift;
46              
47 19         155 my %userargs = @_;
48 19         62 keys_to_lowercase(\%userargs);
49              
50 19         659 my %args = (
51             -parent => undef, # the parent object
52             -x => 0, # horizontal position (rel. to -parent)
53             -y => 0, # vertical position (rel. to -parent)
54             -width => undef, # horizontal size
55             -height => undef, # vertical size
56             -border => 0, # add a border?
57             -sbborder => 0, # add square bracket border?
58             -nocursor => 0, # Show a cursor?
59             -titlefullwidth => 0, # full width for title?
60             -titlereverse => 1, # reverse chars for title?
61             -title => undef, # A title to add to the widget (only for
62             # -border = 1)
63             # padding outside widget
64             -pad => undef, # all over padding
65             -padright => undef, # free space on the right side
66             -padleft => undef, # free space on the left side
67             -padtop => undef, # free space above
68             -padbottom => undef, # free space below
69              
70             # padding inside widget
71             -ipad => undef, # all over padding
72             -ipadright => undef, # free space on the right side
73             -ipadleft => undef, # free space on the left side
74             -ipadtop => undef, # free space above
75             -ipadbottom => undef, # free space below
76              
77             # scrollbars
78             -vscrollbar => 0, # vert. scrollbar (top/bottom)
79             -vscrolllen => 0, # total number of rows
80             -vscrollpos => 0, # current row position
81             -hscrollbar => 0, # hor. scrollbar (left/right)
82             -hscrolllen => 0, # total number of columns
83             -hscrollpos => 0, # current column position
84              
85             -onfocus => undef, # onFocus event handler
86             -onblur => undef, # onBlur event handler
87             -intellidraw => 1, # Support intellidraw()?
88             -focusable => 1, # This widget can get focus
89             -htmltext => 1, # Recognize HTML tags in drawn text
90              
91             #user data
92             -userdata => undef, #user internal data
93              
94             #color
95             # Border
96             -bfg => -1,
97             -bbg => -1,
98             # Scrollbar
99             -sfg => -1,
100             -sbg => -1,
101             # Titlebar
102             -tfg => -1,
103             -tbg => -1,
104              
105             %userargs,
106            
107             -focus => 0, # has the widget focus?
108             );
109              
110             # Allow the value -1 for using the full width and/or
111             # height for the widget.
112 19 50 66     114 $args{-width} = undef
113             if defined $args{-width} and $args{-width} == -1;
114 19 50 66     97 $args{-height} = undef
115             if defined $args{-height} and $args{-height} == -1;
116              
117 19 50 33     126 &Curses::UI::fatalerror(
118             "Missing or illegal parameter: -parent\n"
119             . "while creating " . caller() . "object"
120             ) unless defined $args{-parent} and ref $args{-parent};
121            
122             # Allow a square bracket border only if
123             # a normal border (-border) is disabled.
124 19 50 66     68 $args{-sbborder} = 0 if $args{-sbborder} and $args{-border};
125            
126             # Bless you! (so we can call the layout function).
127 19         68 my $this = bless \%args, $class;
128              
129 19         81 $this->layout;
130              
131 19 50       55 if ($Curses::UI::ncurses_mouse) {
132 19 50       106 $this->set_mouse_binding(\&mouse_button1, BUTTON1_CLICKED())
133             unless $this->{-mousebindings}->{BUTTON1_CLICKED()};
134             }
135              
136 19         158 return $this;
137             }
138              
139             sub DESTROY()
140             {
141 0     0   0 my $this = shift;
142 0         0 $this->delete_subwindows();
143             }
144              
145             sub userdata
146             {
147 0     0 1 0 my $this = shift;
148 0 0       0 if (defined $_[0])
149             {
150 0         0 $this->{-userdata} = $_[0];
151             }
152 0         0 return $this->{-userdata};
153             }
154              
155             sub focusable(;$) {
156 3     3 1 6 my $this = shift;
157 3         5 my $focusable = shift;
158              
159 3 100       9 if (defined $focusable)
160             {
161 1         5 $this->accessor('-focusable', $focusable);
162              
163             # Let the parent find another widget to focus
164             # if this widget is not focusable anymore.
165 1 50 33     6 if ($this->{-focus} and not $focusable) {
166 0         0 $this->parent->focus($this);
167             }
168             }
169              
170 3         13 return $this->{-focusable};
171             }
172              
173             sub layout()
174             {
175 18     18 1 87 cbreak();
176            
177 18         1192 my $this = shift;
178              
179 18 100       66 return if $Curses::UI::screen_too_small;
180              
181 14         65 $this->process_padding;
182            
183             # -------------------------------------------------------
184             # Compute the space that we have for the widget.
185             # -------------------------------------------------------
186              
187 14         132 $this->{-parentdata} = $this->{-parent}->windowparameters;
188              
189 14         41 foreach (qw(x y)) {
190 28 50       79 if (not defined $this->{"-$_"}) {$this->{"-$_"} = 0}
  0         0  
191 28 50       68 if ($this->{"-$_"} >= 0) {
192 28         87 $this->{"-real$_"} = $this->{"-$_"};
193             } else {
194 0 0       0 my $pv = ($_ eq 'x' ? '-w' : '-h');
195 0         0 $this->{"-real$_"} = $this->{-parentdata}->{$pv}
196             + $this->{"-$_"} + 1;
197             }
198             }
199              
200 14         42 my $w = $this->{-parentdata}->{-w};
201 14         40 my $h = $this->{-parentdata}->{-h};
202              
203 14         31 my $cor_h = $this->{-y};
204 14 50       47 $cor_h = abs($this->{-y}+1) if $cor_h < 0;
205 14         35 my $cor_w = $this->{-x};
206 14 50       40 $cor_w = abs($this->{-x}+1) if $cor_w < 0;
207            
208 14         31 my $avail_h = $h - $cor_h;
209 14         24 my $avail_w = $w - $cor_w;
210            
211             # Compute horizontal widget size and adjust if neccessary.
212 14 50       116 my $min_w = ($this->{-border} ? 2 : 0)
    50          
    50          
213             + ($this->{-sbborder} ? 2 : 0)
214             + (defined $this->{-vscrollbar} ? 1 : 0)
215             + $this->{-padleft}
216             + $this->{-padright};
217 14 100       40 my $width = (defined $this->{-width} ? $this->{-width} : $avail_w);
218 14 50       36 $width = $min_w if $width < $min_w;
219 14 50       41 $width = $avail_w if $width > $avail_w;
220              
221             # Compute vertical widget size and adjust if neccessary.
222 14 50       113 my $min_h = ($this->{-border} ? 2 : 0)
    50          
    50          
223             + ($this->{-hscrollbar} ? 1 : 0)
224             + (defined $this->{-hscrollbar} ? 1 : 0)
225             + $this->{-padtop}
226             + $this->{-padbottom};
227 14 100       43 my $height = (defined $this->{-height} ? $this->{-height} : $avail_h);
228 14 50       34 $height = $min_h if $height < $min_h;
229 14 50       31 $height = $avail_h if $height > $avail_h;
230              
231             # Check if the widget fits in the window.
232 14 50 33     151 if ($width > $avail_w or $height > $avail_h or
      33        
      33        
233             $width == 0 or
234             $height == 0) {
235 0         0 $Curses::UI::screen_too_small++;
236 0         0 return $this;
237             }
238              
239 14         33 $this->{-w} = $width;
240 14         31 $this->{-h} = $height;
241              
242 14 50       47 if ($this->{-x} < 0) { $this->{-realx} -= $width }
  0         0  
243 14 50       46 if ($this->{-y} < 0) { $this->{-realy} -= $height }
  0         0  
244            
245             # Take care of padding for the border.
246 14         51 $this->{-bw} = $width - $this->{-padleft} - $this->{-padright};
247 14         45 $this->{-bh} = $height - $this->{-padtop} - $this->{-padbottom};
248 14         53 $this->{-bx} = $this->{-realx} + $this->{-padleft};
249 14         80 $this->{-by} = $this->{-realy} + $this->{-padtop};
250              
251             # -------------------------------------------------------
252             # Create a window for the widget border, if a border
253             # and/or scrollbars are wanted.
254             # -------------------------------------------------------
255              
256 14 50 33     232 if ($this->{-border} or
      33        
      33        
257             $this->{-sbborder} or
258             $this->{-vscrollbar} or
259             $this->{-hscrollbar})
260             {
261 0         0 my @args = ($this->{-bh}, $this->{-bw},
262             $this->{-by}, $this->{-bx});
263              
264 0         0 $this->{-borderscr} =
265             $this->{-parent}->{-canvasscr}->derwin(@args);
266              
267 0 0       0 unless (defined $this->{-borderscr})
268             {
269 0         0 $Curses::UI::screen_too_small++;
270 0         0 return $this;
271             }
272             }
273              
274             # -------------------------------------------------------
275             # Create canvas screen region
276             # -------------------------------------------------------
277              
278 14 50 33     214 $this->{-sh} = $this->{-bh}
279             - $this->{-ipadtop}
280             - $this->{-ipadbottom}
281             - ($this->{-border}? 2 : 0)
282             - (not $this->{-border} and $this->{-hscrollbar} ? 1 : 0);
283              
284 14 50 33     139 $this->{-sw} = $this->{-bw}
    50          
285             - $this->{-ipadleft}
286             - $this->{-ipadright}
287             - ($this->{-border}? 2 : 0)
288             - ($this->{-sbborder}? 2 : 0)
289             - (not $this->{-border} and $this->{-vscrollbar} ? 1 : 0);
290              
291 14 50 33     126 $this->{-sy} = $this->{-by}
292             + $this->{-ipadtop}
293             + ($this->{-border}?1:0)
294             + (not $this->{-border} and
295             $this->{-hscrollbar} eq 'top' ? 1 : 0);
296              
297 14 50 33     130 $this->{-sx} = $this->{-bx}
    50          
298             + $this->{-ipadleft}
299             + ($this->{-border}?1:0)
300             + ($this->{-sbborder}?1:0)
301             + (not $this->{-border} and
302             $this->{-vscrollbar} eq 'left' ? 1 : 0);
303              
304             # Check if there is room left for the screen.
305 14 50 33     83 if ($this->{-sw} <= 0 or $this->{-sh} <= 0) {
306 0         0 $Curses::UI::screen_too_small++;
307 0         0 return $this;
308             }
309              
310             # Create a window for the data.
311 14         70 my @args = ($this->{-sh}, $this->{-sw},
312             $this->{-sy}, $this->{-sx});
313              
314 14         71 $this->{-canvasscr} =
315             $this->{-parent}->{-canvasscr}->derwin(@args);
316            
317 14 50       124 unless (defined $this->{-canvasscr})
318             {
319 0         0 $Curses::UI::screen_too_small++;
320 0         0 return $this;
321             }
322              
323 14 50       40 unless (defined $this->{-borderscr})
324             {
325 14         34 $this->{-bw} = $this->{-sw};
326 14         37 $this->{-bh} = $this->{-sh};
327 14         25 $this->{-bx} = $this->{-sx};
328 14         29 $this->{-by} = $this->{-sy};
329             }
330              
331 14         62 return $this;
332             }
333              
334              
335             sub process_padding($;)
336             {
337 16     16 0 24 my $this = shift;
338              
339             # Process the padding arguments.
340 16         35 foreach my $type ('-pad','-ipad') {
341 32 50       136 if (defined $this->{$type}) {
342 0         0 foreach my $side ('right','left','top','bottom') {
343 0 0       0 $this->{$type . $side} = $this->{$type}
344             unless defined $this->{$type . $side};
345             }
346             }
347             }
348 16         40 foreach my $type ('-pad','-ipad') {
349 32         48 foreach my $side ('right','left','top','bottom') {
350 128 100       343 $this->{$type . $side} = 0
351             unless defined $this->{$type . $side};
352             }
353             }
354             }
355              
356             sub width_by_windowscrwidth($@)
357             {
358 0   0 0 1 0 my $width = shift || 0;
359 0 0       0 $width = shift if ref $width; # make $this->width... possible.
360 0         0 my %args = @_;
361            
362 0 0       0 $width += 2 if $args{-border}; # border
363 0 0       0 $width += 2 if $args{-sbborder}; # sbborder
364 0 0 0     0 $width += 1 if (not $args{-border} and # scrollbar and no border
      0        
365             not $args{-sbborder} and
366             $args{-vscrollbar});
367              
368 0         0 foreach my $t ("-ipad", "-pad") # internal + external padding
369             {
370 0 0       0 if ($args{$t}) {
371 0         0 $width += 2*$args{$t};
372             } else {
373 0 0       0 $width += $args{$t . "left"} if defined $args{$t . "left"};
374 0 0       0 $width += $args{$t . "right"} if defined $args{$t . "right"};
375             }
376             }
377 0         0 return $width;
378             }
379              
380             sub height_by_windowscrheight($@)
381             {
382 1   50 1 1 3 my $height = shift || 0;
383 1 50       4 $height = shift if ref $height; # make $this->height... possible.
384 1         6 my %args = @_;
385            
386 1 50       5 $height += 2 if $args{-border}; # border
387 1 50 33     9 $height += 1 if (not $args{-border} and $args{-hscrollbar});
388 1         2 foreach my $t ("-ipad", "-pad") # internal + external padding
389             {
390 2 50       6 if ($args{$t})
391             {
392 0         0 $height += 2*$args{$t};
393             } else {
394 2 50       6 $height += $args{$t . "top"} if defined $args{$t . "top"};
395 2 50       7 $height += $args{$t . "bottom"} if defined $args{$t . "bottom"};
396             }
397             }
398 1         6 return $height;
399             }
400              
401 0     0 1 0 sub width { shift->{-w} }
402 0     0 1 0 sub height { shift->{-h} }
403 0     0 1 0 sub borderwidth { shift->{-bw} }
404 0     0 1 0 sub borderheight { shift->{-bh} }
405 15     15 1 82 sub canvaswidth { shift->{-sw} }
406 17     17 1 74 sub canvasheight { shift->{-sh} }
407              
408             sub title ($;)
409             {
410 0     0 1 0 my $this = shift;
411 0         0 my $title = shift;
412              
413 0 0       0 if (defined $title)
414             {
415 0         0 $this->{-title} = $title;
416 0         0 $this->intellidraw;
417             }
418              
419 0         0 return $this->{-title}
420             }
421              
422             sub windowparameters()
423             {
424 16     16 0 25 my $this = shift;
425 16         22 my $scr = shift;
426              
427 16 50       48 $scr = "-canvasscr" unless defined $scr;
428 16         42 my $s = $this->{$scr};
429 16         20 my ($x,$y,$w,$h);
430              
431 16         61 $s->getbegyx($y, $x);
432 16         99 $s->getmaxyx($h, $w);
433              
434             return {
435 16         128 -w => $w,
436             -h => $h,
437             -x => $x,
438             -y => $y,
439             };
440             }
441              
442             #
443             # Actually, the focus is not loose but the widget should
444             # lose the focus:
445              
446             sub lose_focus()
447             {
448 0     0 1 0 my $this = shift;
449 0         0 $this->loose_focus(@_);
450             }
451              
452              
453             sub loose_focus()
454             {
455 0     0 0 0 my $this = shift;
456 0         0 my $key = shift;
457            
458             # The focus change will draw $this anyhow and this
459             # will reset the schedule if somewhere in the middle of
460             # a binding routine loose_focus() is called (else
461             # first the focus would shift and after that $this
462             # would be redrawn).
463             #
464 0         0 $this->schedule_draw(0);
465              
466 0 0       0 if ($this->{-has_modal_focus}) {
467 0         0 $this->{-has_modal_focus} = 0;
468             } else {
469 0         0 my $parent = $this->parent;
470              
471             # If $this is not focused anymore, then it most probably
472             # has shifted focus itself using a callback routine.
473             # In that case, do not go to the next or previous object,
474             # but honour the current focus_path.
475             #
476 0 0       0 if ($this->root->focus_path(-1) ne $this) {
477 0         0 return $this;
478             }
479              
480 0 0 0     0 if (defined $key and $key eq KEY_BTAB()) {
481 0         0 $this->parent->focus_prev();
482             } else {
483 0         0 $this->parent->focus_next();
484             }
485             }
486              
487 0         0 return $this;
488             }
489              
490             sub focus()
491             {
492 3     3 1 13 my $this = shift;
493              
494             # Let the parent focus this object.
495 3         22 my $parent = $this->parent;
496 3 100       41 $parent->focus($this) if defined $parent;
497              
498 3 50       21 $this->draw(1) if ($this->root->overlapping);
499 3         8 return $this;
500             }
501              
502             sub modalfocus ()
503             {
504 0     0 1 0 my $this = shift;
505              
506             # "Fake" focus for this object.
507 0         0 $this->{-has_modal_focus} = 1;
508 0         0 $this->focus;
509 0         0 $this->draw;
510              
511             # Event loop ((too?) much like Curses::UI->mainloop)
512 0         0 while ( $this->{-has_modal_focus} ) {
513 0         0 $this->root->do_one_event($this);
514             }
515              
516 0         0 $this->{-focus} = 0;
517 0         0 $this->{-has_modal_focus} = 0;
518              
519 0         0 return $this;
520             }
521              
522              
523             sub draw(;$)
524             {
525 17     17 1 28 my $this = shift;
526 17   50     66 my $no_doupdate = shift || 0;
527              
528             # Return immediately if this object is hidden of if
529             # the screen is currently too small.
530 17 50       53 return if $Curses::UI::screen_too_small;
531 17 50       123 return if $this->hidden;
532              
533 17         29 eval { curs_set(0) }; # not available on every system.
  17         94  
534              
535             # Clear the contents of the window.
536 17 50       1570 my $scr = defined $this->{-borderscr}
537             ? $this->{-borderscr}
538             : $this->{-canvasscr};
539 17 50       47 if ($Curses::UI::color_support) {
540 0         0 my $co = $Curses::UI::color_object;
541 0         0 my $pair = $co->get_color_pair( $this->{-fg}, $this->{-bg} );
542 0 0 0     0 $scr->bkgdset(COLOR_PAIR($pair) | 32) if (defined $scr and $pair);
543             }
544 17 50       48 return unless defined $scr;
545 17         75 $scr->erase;
546 17         1661 $scr->noutrefresh();
547              
548             # Do borderstuff?
549 17 50       1437 if (defined $this->{-borderscr})
550             {
551              
552 0 0       0 if ($Curses::UI::color_support) {
553 0         0 my $co = $Curses::UI::color_object;
554 0         0 my $pair = $co->get_color_pair(
555             $this->{-bfg},
556             $this->{-bbg} );
557              
558 0         0 $this->{-borderscr}->attron(COLOR_PAIR($pair));
559             }
560              
561             # Draw a border if needed.
562 0 0       0 if ($this->{-sbborder}) # Square bracket ([,]) border
    0          
563             {
564 0 0       0 $this->{-borderscr}->attron(A_BOLD) if $this->{-focus};
565 0         0 my $offset = 1;
566 0 0       0 $offset++ if $this->{-vscrollbar};
567 0         0 for my $y (0 .. $this->{-sh}-1)
568             {
569 0         0 my $rel_y = $y + $this->{-sy} - $this->{-by};
570 0         0 $this->{-borderscr}->addstr($rel_y, 0, '[');
571 0         0 $this->{-borderscr}->addstr($rel_y, $this->{-bw}-$offset, ']');
572             }
573 0 0       0 $this->{-borderscr}->attroff(A_BOLD) if $this->{-focus};
574             }
575             elsif ($this->{-border}) # Normal border
576             {
577 0 0       0 $this->{-borderscr}->attron(A_BOLD) if $this->{-focus};
578 0 0       0 if ($this->root->compat) {
579 0         0 $this->{-borderscr}->border(
580             '|','|','-','-',
581             '+','+','+','+'
582             );
583             } else {
584 0         0 $this->{-borderscr}->box(ACS_VLINE, ACS_HLINE);
585             }
586 0 0       0 $this->{-borderscr}->attroff(A_BOLD) if $this->{-focus};
587            
588             # Draw a title if needed.
589 0 0       0 if (defined $this->{-title})
590             {
591 0 0       0 if ($Curses::UI::color_support) {
592 0         0 my $co = $Curses::UI::color_object;
593 0         0 my $pair = $co->get_color_pair(
594             $this->{-tfg},
595             $this->{-tbg} );
596              
597 0         0 $this->{-borderscr}->attron(COLOR_PAIR($pair));
598             }
599              
600 0 0       0 $this->{-borderscr}->attron(A_REVERSE)
601             if $this->{-titlereverse};
602 0 0 0     0 if ($this->{-titlefullwidth}
603             and $this->{-titlereverse}) {
604 0         0 $this->{-borderscr}->attron(A_BOLD);
605 0         0 $this->{-borderscr}->addstr(0, 1, " "x($this->{-bw}-2));
606 0         0 $this->{-borderscr}->attroff(A_BOLD);
607             }
608 0         0 my $t = $this->{-title};
609 0         0 my $l = $this->{-bw}-4;
610 0 0       0 if ($l < length($t))
611             {
612 0 0       0 $t = substr($t, 0, $l) if $l < length($t);
613 0         0 $t =~ s/.$/\$/;
614             }
615 0         0 $this->{-borderscr}->attron(A_BOLD);
616 0         0 $this->{-borderscr}->addstr(0, 1, " $t ");
617 0         0 $this->{-borderscr}->attroff(A_REVERSE);
618 0         0 $this->{-borderscr}->attroff(A_BOLD);
619             }
620             }
621            
622 0         0 $this->draw_scrollbars();
623 0         0 $this->{-borderscr}->noutrefresh();
624             }
625              
626 17 50       46 doupdate() unless $no_doupdate;
627 17         87 return $this;
628             }
629              
630             sub draw_scrollbars()
631             {
632 0     0 0 0 my $this = shift;
633              
634 0 0       0 return $this unless defined $this->{-borderscr};
635              
636 0 0 0     0 if ($this->{-vscrollbar} and defined $this->{-vscrolllen})
637             {
638              
639             # Compute the drawing range for the scrollbar.
640 0 0       0 my $xpos = $this->{-vscrollbar} eq 'left'
641             ? 0
642             : $this->borderwidth-1;
643              
644 0         0 my $ypos_min = $this->{-sy}-$this->{-by};
645 0         0 my $ypos_max = $ypos_min + $this->canvasheight - 1;
646 0         0 my $scrlen = $ypos_max - $ypos_min + 1;
647 0 0       0 my $actlen = $this->{-vscrolllen}
648             ? int($scrlen * ($scrlen/($this->{-vscrolllen}))+0.5)
649             : 0;
650 0 0 0     0 $actlen = 1 if not $actlen and $this->{-vscrolllen};
651 0 0 0     0 my $actpos = ($this->{-vscrolllen} and $this->{-vscrollpos})
652             ? int($scrlen*($this->{-vscrollpos}/$this->{-vscrolllen}))
653             + $ypos_min + 1
654             : $ypos_min;
655              
656             # Only let the marker be at the end if the
657             # scrollpos is too.
658 0 0       0 if ($this->{-vscrollpos}+$scrlen >= $this->{-vscrolllen}) {
659 0         0 $actpos = $scrlen - $actlen + $ypos_min;
660             } else {
661 0 0       0 if ($actpos + $actlen >= $scrlen) {
662 0         0 $actpos--;
663             }
664             }
665            
666             # Only let the marker be at the beginning if the
667             # scrollpos is too.
668 0 0       0 if ($this->{-vscrollpos} == 0) {
669 0         0 $actpos = $ypos_min;
670             } else {
671 0 0 0     0 if ($this->{-vscrollpos} and $actpos <= 0) {
672 0         0 $actpos = $ypos_min+1;
673             }
674             }
675            
676             # Draw the base of the scrollbar, in case
677             # there is no border.
678 0 0       0 $this->{-borderscr}->attron(A_BOLD) if $this->{-focus};
679 0         0 $this->{-borderscr}->move($ypos_min, $xpos);
680 0         0 $this->{-borderscr}->vline(ACS_VLINE,$scrlen);
681 0 0       0 if ($this->root->compat) {
682 0         0 $this->{-borderscr}->vline('|',$scrlen);
683             } else {
684 0         0 $this->{-borderscr}->vline(ACS_VLINE,$scrlen);
685             }
686 0 0       0 $this->{-borderscr}->attroff(A_BOLD) if $this->{-focus};
687              
688 0 0       0 if ($Curses::UI::color_support) {
689 0         0 my $co = $Curses::UI::color_object;
690 0         0 my $pair = $co->get_color_pair(
691             $this->{-sfg},
692             $this->{-sbg} );
693              
694 0         0 $this->{-borderscr}->attron(COLOR_PAIR($pair));
695             }
696              
697             # Should an active region be drawn?
698 0         0 my $scroll_active = ($this->{-vscrolllen} > $scrlen);
699             # Draw scrollbar base, in case there is
700             # Draw active region.
701 0 0       0 if ($scroll_active)
702             {
703 0         0 $this->{-borderscr}->attron(A_REVERSE);
704 0         0 for my $i (0 .. $actlen-1) {
705 0         0 $this->{-borderscr}->addch($i+$actpos,$xpos," ");
706             }
707 0         0 $this->{-borderscr}->attroff(A_REVERSE);
708             }
709              
710 0 0       0 if ($Curses::UI::color_support) {
711 0         0 my $co = $Curses::UI::color_object;
712 0         0 my $pair = $co->get_color_pair(
713             $this->{-bfg},
714             $this->{-bbg} );
715              
716 0         0 $this->{-borderscr}->attron(COLOR_PAIR($pair));
717             }
718              
719             }
720            
721 0 0 0     0 if ($this->{-hscrollbar} and defined $this->{-hscrolllen})
722             {
723             # Compute the drawing range for the scrollbar.
724 0 0       0 my $ypos = $this->{-hscrollbar} eq 'top'
725             ? 0
726             : $this->borderheight-1;
727              
728 0         0 my $xpos_min = $this->{-sx}-$this->{-bx};
729 0         0 my $xpos_max = $xpos_min + $this->canvaswidth - 1;
730 0         0 my $scrlen = $xpos_max - $xpos_min + 1;
731 0 0       0 my $actlen = $this->{-hscrolllen}
732             ? int($scrlen * ($scrlen/($this->{-hscrolllen}))+0.5)
733             : 0;
734 0 0 0     0 $actlen = 1 if not $actlen and $this->{-hscrolllen};
735 0 0 0     0 my $actpos = ($this->{-hscrolllen} and $this->{-hscrollpos})
736             ? int($scrlen*($this->{-hscrollpos}/$this->{-hscrolllen}))
737             + $xpos_min + 1
738             : $xpos_min;
739              
740             # Only let the marker be at the end if the
741             # scrollpos is too.
742 0 0       0 if ($this->{-hscrollpos}+$scrlen >= $this->{-hscrolllen}) {
743 0         0 $actpos = $scrlen - $actlen + $xpos_min;
744             } else {
745 0 0       0 if ($actpos + $actlen >= $scrlen) {
746 0         0 $actpos--;
747             }
748             }
749            
750             # Only let the marker be at the beginning if the
751             # scrollpos is too.
752 0 0       0 if ($this->{-hscrollpos} == 0) {
753 0         0 $actpos = $xpos_min;
754             } else {
755 0 0 0     0 if ($this->{-hscrollpos} and $actpos <= 0) {
756 0         0 $actpos = $xpos_min+1;
757             }
758             }
759            
760             # Draw the base of the scrollbar, in case
761             # there is no border.
762 0 0       0 $this->{-borderscr}->attron(A_BOLD) if $this->{-focus};
763 0         0 $this->{-borderscr}->move($ypos, $xpos_min);
764 0 0       0 if ($this->root->compat) {
765 0         0 $this->{-borderscr}->hline('-',$scrlen);
766             } else {
767 0         0 $this->{-borderscr}->hline(ACS_HLINE,$scrlen);
768             }
769 0 0       0 $this->{-borderscr}->attroff(A_BOLD) if $this->{-focus};
770              
771             # Should an active region be drawn?
772              
773 0 0       0 if ($Curses::UI::color_support) {
774 0         0 my $co = $Curses::UI::color_object;
775 0         0 my $pair = $co->get_color_pair(
776             $this->{-sfg},
777             $this->{-sbg} );
778              
779 0         0 $this->{-borderscr}->attron(COLOR_PAIR($pair));
780             }
781              
782 0         0 my $scroll_active = ($this->{-hscrolllen} > $scrlen);
783             # Draw active region.
784 0 0       0 if ($scroll_active)
785             {
786 0         0 $this->{-borderscr}->attron(A_REVERSE);
787 0         0 for my $i (0 .. $actlen-1) {
788 0         0 $this->{-borderscr}->addch($ypos, $i+$actpos," ");
789             }
790 0         0 $this->{-borderscr}->attroff(A_REVERSE);
791             }
792             }
793            
794 0         0 return $this;
795             }
796              
797 0     0 1 0 sub beep_on() { my $this = shift; $this->{-nobeep} = 0; return $this }
  0         0  
  0         0  
798 0     0 1 0 sub beep_off() { my $this = shift; $this->{-nobeep} = 1; return $this }
  0         0  
  0         0  
799             sub dobeep()
800             {
801 0     0 1 0 my $this = shift;
802 0 0       0 beep() unless $this->{-nobeep};
803 0         0 return $this;
804             }
805              
806              
807             # TODO: work out hiding of objects.
808 20     20 0 90 sub hidden() { shift()->{-hidden} }
809 0     0 0 0 sub hide() { shift()->{-hidden} = 1 }
810 0     0 0 0 sub show() { shift()->{-hidden} = 0 }
811              
812             sub intellidraw(;$)
813             {
814 2     2 1 4 my $this = shift;
815              
816 2 50 33     22 if ( $this->{-intellidraw} and
      33        
817             not $this->hidden and
818             $this->in_topwindow ) {
819 2         8 $this->draw(1);
820             }
821              
822 2         6 return $this;
823             }
824              
825             sub delete_subwindows()
826             {
827 4     4 0 4 my $this = shift;
828 4         8 delete $this->{-scr};
829 4         8 foreach my $win (qw(-borderscr -canvasscr))
830             {
831 8 100       28 if (defined $this->{$win})
832             {
833 2         12 $this->{$win}->delwin;
834 2         201 delete $this->{$win};
835             }
836             }
837             }
838              
839             sub parentwindow()
840             {
841 4     4 1 13 my $object = shift;
842              
843 4   66     57 until (not defined $object or
844             $object->isa('Curses::UI::Window')) {
845 4         27 $object = $object->parent
846             }
847              
848 4         13 return $object;
849             }
850              
851             sub in_topwindow()
852             {
853 3     3 1 6 my $this = shift;
854              
855             # Get the parent window of this widget.
856 3         15 my $win = $this->parentwindow();
857 3 50       11 return unless defined $win;
858              
859             # A modal window should always be the topwindow.
860 3 50       14 return 1 if $win->{-has_modal_focus};
861              
862             # Get the current focus path (the list of objects
863             # from the Curses::UI root up which currently
864             # have the focus). Strip non Window object from
865             # it, to find the topmost window.
866 3         26 my @path = $this->root->focus_path;
867 3   66     34 while (defined $path[-1] and
868             not $path[-1]->isa('Curses::UI::Window')) {
869 3         43 pop @path;
870             }
871              
872             # Check if the parent window is on top.
873 3   33     40 return (@path and ($win eq $path[-1]));
874             }
875              
876             # ----------------------------------------------------------------------
877             # Binding
878             # ----------------------------------------------------------------------
879              
880             sub clear_binding($;)
881             {
882 0     0 1 0 my $this = shift;
883 0         0 my $binding = shift;
884 0         0 my @delete = ();
885 0         0 while (my ($k,$v) = each %{$this->{-bindings}}) {
  0         0  
886 0 0       0 push @delete, $k if $v eq $binding;
887             }
888 0         0 foreach (@delete) {
889 0         0 delete $this->{-bindings}->{$_};
890             }
891 0         0 return $this;
892             }
893              
894             sub set_routine($$;)
895             {
896 22     22 1 513 my $this = shift;
897 22         31 my $binding = shift;
898 22         35 my $routine = shift;
899 22         146 $this->{-routines}->{$binding} = $routine;
900 22         36 return $this;
901             }
902              
903             sub set_binding($@)
904             {
905 1     1 1 9 my $this = shift;
906 1         2 my $routine = shift;
907 1         3 my @keys = @_;
908              
909             # Create a routine entry if the routine that was
910             # passed is a code reference instead of a
911             # routine name.
912 1 50       4 if (ref $routine eq 'CODE')
913             {
914 0         0 my $name = "__routine_$routine";
915 0         0 $this->set_routine($name, $routine);
916 0         0 $routine = $name;
917             }
918              
919 1 50       5 $this->root->fatalerror("set_binding(): $routine: no such routine")
920             unless defined $this->{-routines}->{$routine};
921              
922 1         3 foreach my $key (@keys) {
923 1         6 $this->{-bindings}->{$key} = $routine;
924             }
925              
926 1         4 return $this;
927             }
928              
929             sub set_mouse_binding($@)
930             {
931 24     24 0 1195 my $this = shift;
932 24         28 my $routine = shift;
933 24         37 my @mouse_events = @_;
934              
935             # Create a routine entry if the routine that was
936             # passed is a code reference instead of a
937             # routine name.
938 24 100       82 if (ref $routine eq 'CODE')
939             {
940 21         57 my $name = "__routine_$routine";
941 21         112 $this->set_routine($name, $routine);
942 21         57 $routine = $name;
943             }
944              
945 24 50       87 $this->root->fatalerror("set_binding(): $routine: no such routine")
946             unless defined $this->{-routines}->{$routine};
947              
948 24         39 foreach my $mouse_event (@mouse_events) {
949 24         105 $this->{-mousebindings}->{$mouse_event} = $routine;
950             }
951              
952 24         56 return $this;
953             }
954              
955 8     8 0 29 sub schedule_draw(;$) { shift()->accessor('-schedule_draw', shift()) }
956              
957             sub process_bindings($;$@)
958             {
959 0     0 1 0 my $this = shift;
960 0         0 my $key = shift;
961 0   0     0 my $is_mouse_event = shift || 0;
962 0         0 my @extra = @_;
963            
964             # Reset draw schedule.
965 0         0 $this->schedule_draw(0);
966              
967             # Find the binding to use.
968 0         0 my $binding;
969 0 0       0 if ($is_mouse_event)
970             {
971 0         0 $binding = $this->{-mousebindings}->{$key->{-bstate}};
972 0 0       0 if (not defined $binding) {
973             # Check for default routine.
974 0         0 $binding = $this->{-mousebindings}->{''};
975             }
976             } else {
977 0         0 $binding = $this->{-bindings}->{$key};
978 0 0       0 if (not defined $binding) {
979             # Check for default routine.
980 0         0 $binding = $this->{-bindings}->{''};
981             }
982             }
983              
984 0 0       0 if (defined $binding) {
985 0         0 my $return = $this->do_routine($binding, $key, @extra);
986             # Redraw if draw schedule is set.
987 0 0       0 $this->intellidraw if $this->schedule_draw;
988 0         0 return $return;
989             } else {
990 0         0 return 'DELEGATE';
991             }
992             }
993              
994             sub do_routine($;$)
995             {
996 0     0 0 0 my $this = shift;
997 0         0 my $binding = shift;
998 0         0 my @arguments = @_;
999              
1000             # Find the routine to call.
1001 0         0 my $routine = $this->{-routines}->{$binding};
1002            
1003 0 0       0 if (defined $routine)
1004             {
1005 0 0       0 if (ref $routine eq 'CODE') {
1006 0         0 my $return = $routine->($this, @arguments);
1007 0         0 return $return;
1008             } else {
1009 0         0 return $routine;
1010             }
1011             } else {
1012 0         0 $this->root->fatalerror(
1013             "No routine defined for keybinding \"$binding\"!"
1014             );
1015             }
1016             }
1017              
1018 0     0 1 0 sub onFocus($;$) { shift()->set_event('-onfocus', shift()) }
1019 0     0 1 0 sub onBlur($;$) { shift()->set_event('-onblur', shift()) }
1020              
1021             sub event_onfocus()
1022             {
1023 0     0 0 0 my $this = shift;
1024              
1025             # Let the parent find another widget to focus
1026             # if this widget is not focusable.
1027 0 0       0 unless ($this->focusable) {
1028 0         0 return $this->parent->focus($this);
1029             }
1030              
1031 0         0 $this->{-focus} = 1;
1032              
1033 0         0 $this->run_event('-onfocus');
1034              
1035             # Set cursor mode
1036 0 0       0 my $show_cursor = $this->{-nocursor} ? 0 : 1;
1037 0         0 $this->root->cursor_mode($show_cursor);
1038              
1039 0 0       0 $this->draw(1) if (not $this->root->overlapping);
1040              
1041 0         0 return $this;
1042             }
1043              
1044             sub event_onblur()
1045             {
1046 0     0 0 0 my $this = shift;
1047 0         0 $this->{-focus} = 0;
1048 0         0 $this->run_event('-onblur');
1049 0 0       0 $this->draw(1) if (not $this->root->overlapping);
1050 0         0 return $this;
1051             }
1052              
1053             sub event_keypress($;)
1054             {
1055 0     0 0 0 my $this = shift;
1056 0         0 my $key = shift;
1057 0         0 $this->process_bindings($key);
1058             }
1059              
1060             sub event_mouse($;)
1061             {
1062 0     0 0 0 my $this = shift;
1063 0         0 my $MEVENT = shift;
1064              
1065 0         0 my $winp = $this->windowparameters;
1066 0         0 my $abs_x = $MEVENT->{-x} - $winp->{-x};
1067 0         0 my $abs_y = $MEVENT->{-y} - $winp->{-y};
1068              
1069 0         0 $this->process_bindings($MEVENT, 1, $abs_x, $abs_y);
1070             }
1071              
1072             sub mouse_button1($$$$;)
1073             {
1074 0     0 0 0 my $this = shift;
1075 0         0 my $event = shift;
1076 0         0 my $x = shift;
1077 0         0 my $y = shift;
1078              
1079 0 0 0     0 $this->focus() if not $this->{-focus} and $this->focusable;
1080             }
1081              
1082             # ----------------------------------------------------------------------
1083             # Event handling
1084             # ----------------------------------------------------------------------
1085              
1086             sub clear_event($;)
1087             {
1088 0     0 1 0 my $this = shift;
1089 0         0 my $event = shift;
1090 0         0 $this->set_event($event, undef);
1091 0         0 return $this;
1092             }
1093              
1094             sub set_event($;$)
1095             {
1096 1     1 1 2 my $this = shift;
1097 1         2 my $event = shift;
1098 1         2 my $callback = shift;
1099              
1100 1 50       5 if (defined $callback)
1101             {
1102 1 50       22 if (ref $callback eq 'CODE') {
1103 1         9 $this->{$event} = $callback;
1104             } else {
1105 0         0 $this->root->fatalerror(
1106             "$event callback for $this "
1107             . "($callback) is no CODE reference"
1108             );
1109             }
1110             } else {
1111 0         0 $this->{$event} = undef;
1112             }
1113 1         3 return $this;
1114             }
1115              
1116             sub run_event($;)
1117             {
1118 6     6 1 7 my $this = shift;
1119 6         8 my $event = shift;
1120            
1121 6         10 my $callback = $this->{$event};
1122 6 100       16 if (defined $callback) {
1123 5 50       10 if (ref $callback eq 'CODE') {
1124 5         21 return $callback->($this);
1125             } else {
1126 0         0 $this->root->fatalerror(
1127             "$event callback for $this "
1128             . "($callback) is no CODE reference"
1129             );
1130             }
1131             }
1132 1         3 return;
1133             }
1134              
1135             ###
1136             ### Color attribute functions
1137             ###
1138              
1139             sub set_color_fg{
1140 0     0 0   my $this = shift;
1141 0           $this->{-fg} = shift;
1142 0           $this->intellidraw;
1143             }
1144              
1145             sub set_color_bg{
1146 0     0 0   my $this = shift;
1147 0           $this->{-bg} = shift;
1148 0           $this->intellidraw;
1149             }
1150              
1151             sub set_color_tfg{
1152 0     0 0   my $this = shift;
1153 0           $this->{-tfg} = shift;
1154 0           $this->intellidraw;
1155             }
1156              
1157             sub set_color_tbg{
1158 0     0 0   my $this = shift;
1159 0           $this->{-tbg} = shift;
1160 0           $this->intellidraw;
1161             }
1162              
1163             sub set_color_bfg{
1164 0     0 0   my $this = shift;
1165 0           $this->{-bfg} = shift;
1166 0           $this->intellidraw;
1167             }
1168              
1169             sub set_color_bbg{
1170 0     0 0   my $this = shift;
1171 0           $this->{-bbg} = shift;
1172 0           $this->intellidraw;
1173             }
1174              
1175             sub set_color_sfg{
1176 0     0 0   my $this = shift;
1177 0           $this->{-sfg} = shift;
1178 0           $this->intellidraw;
1179             }
1180              
1181             sub set_color_sbg{
1182 0     0 0   my $this = shift;
1183 0           $this->{-sbg} = shift;
1184 0           $this->intellidraw;
1185             }
1186              
1187             package Curses::UI::ContainerWidget;
1188              
1189             # Not special at all. This class is especially used as a flag for
1190             # container based widgets, so that we can detect these using
1191             # $object->isa('Curses::UI::ContainerWidget').
1192              
1193 8     8   114 use Curses::UI::Container;
  8         13  
  8         269  
1194 8     8   54 use Curses::UI::Widget;
  8         16  
  8         227  
1195 8         2261 use vars qw(
1196             @ISA
1197             $VERSION
1198 8     8   40 );
  8         15  
1199              
1200             $VERSION = '1.10';
1201              
1202             @ISA = qw(
1203             Curses::UI::Container
1204             Curses::UI::Widget
1205             );
1206              
1207 0     0     sub new () { shift()->SUPER::new(@_) };
1208              
1209             1;
1210              
1211              
1212             =pod
1213              
1214             =head1 NAME
1215              
1216             Curses::UI::Widget - The base class for all widgets
1217              
1218             =head1 CLASS HIERARCHY
1219              
1220             Curses::UI::Widget - base class
1221              
1222              
1223              
1224             =head1 SYNOPSIS
1225              
1226             This class is not used directly by somebody who is building an application
1227             using Curses::UI. It's a base class that is expanded by the Curses::UI widgets.
1228             See WIDGET STRUCTURE below for a basic widget framework.
1229              
1230             use Curses::UI::Widget;
1231             my $widget = new Curses::UI::Widget(
1232             -width => 15,
1233             -height => 5,
1234             -border => 1,
1235             );
1236              
1237              
1238              
1239              
1240             =head1 STANDARD OPTIONS
1241              
1242             The standard options for (most) widgets are the options that are enabled
1243             by this class. So this class doesn't really have standard options.
1244              
1245              
1246              
1247              
1248              
1249             =head1 WIDGET-SPECIFIC OPTIONS
1250              
1251             =head2 GENERAL:
1252              
1253             =over 4
1254              
1255             =item * B<-parent> < OBJECTREF >
1256              
1257             This option specifies parent of the object. This parent is
1258             the object (Curses::UI, Window, Widget(descendant), etc.)
1259             in which the widget is drawn.
1260              
1261             =item * B<-intellidraw> < BOOLEAN >
1262              
1263             If BOOLEAN has a true value (which is the default), the
1264             B method (see below) will be suported. This
1265             option is mainly used in widget building.
1266              
1267             =item * B<-userdata> < SCALAR >
1268              
1269             This option specifies a user data that can be retrieved with
1270             the B() method. It is useful to store application's
1271             internal data that otherwise would not be accessible in callbacks.
1272              
1273             =item * B<-border> < BOOLEAN >
1274              
1275             Each widget can be drawn with or without a border. To enable
1276             the border use a true value and to disable it use a
1277             false value for BOOLEAN. The default is not to use a border.
1278              
1279             =item * B<-sbborder> < BOOLEAN >
1280              
1281             If no border is used, a square bracket border may be used.
1282             This is a border which is constructed from '[' and ']'
1283             characters. This type of border is especially useful for
1284             single line widgets (like text entries and popup boxes).
1285             A square bracket border can only be enabled if -border
1286             is false. The default is not to use a square bracket border.
1287              
1288             =back
1289              
1290              
1291              
1292             =head2 POSITIONING:
1293              
1294             +---------------------------------------------------+
1295             | parent ^ |
1296             | | |
1297             | y |
1298             | | |
1299             | v |
1300             | ^ |
1301             | | |
1302             | padtop |
1303             | | |
1304             | v |
1305             | +- TITLE -------+ |
1306             | | widget ^ | |
1307             | | | | |
1308             | | | | |
1309             |<--x--><--padleft-->|<----width---->|<--padright-->|
1310             | | | | |
1311             | | | | |
1312             | | height | |
1313             | | v | |
1314             | +---------------+ |
1315             | ^ |
1316             | | |
1317             | padbottom |
1318             | | |
1319             | v |
1320             +---------------------------------------------------+
1321              
1322              
1323             =over 4
1324              
1325             =item * B<-x> < VALUE >
1326              
1327             The x-position of the widget, relative to the parent. The default
1328             is 0.
1329              
1330             =item * B<-y> < VALUE >
1331              
1332             The y-position of the widget, relative to the parent. The default
1333             is 0.
1334              
1335             =item * B<-width> < VALUE >
1336              
1337             The width of the widget. If the width is undefined or -1,
1338             the maximum available width will be used. By default the widget
1339             will use the maximum available width.
1340              
1341             =item * B<-height> < VALUE >
1342              
1343             The height of the widget. If the height is undefined or -1,
1344             the maximum available height will be used. By default the widget
1345             will use the maximum available height.
1346              
1347             =back
1348              
1349              
1350              
1351             =head2 PADDING:
1352              
1353             =over 4
1354              
1355             =item * B<-pad> < VALUE >
1356              
1357             =item * B<-padtop> < VALUE >
1358              
1359             =item * B<-padbottom> < VALUE >
1360              
1361             =item * B<-padleft> < VALUE >
1362              
1363             =item * B<-padright> < VALUE >
1364              
1365             With -pad you can specify the default padding outside the widget
1366             (the default value for -pad is 0). Using one of the -pad... options
1367             that have a direction in them, you can override the default
1368             padding.
1369              
1370             =item * B<-ipad> < VALUE >
1371              
1372             =item * B<-ipadtop> < VALUE >
1373              
1374             =item * B<-ipadbottom> < VALUE >
1375              
1376             =item * B<-ipadleft> < VALUE >
1377              
1378             =item * B<-ipadright> < VALUE >
1379              
1380             These are almost the same as the -pad... options, except these options
1381             specify the padding _inside_ the widget. Normally the available
1382             effective drawing area for a widget will be the complete area
1383             if no border is used or else the area within the border.
1384              
1385             =back
1386              
1387              
1388              
1389             =head2 TITLE:
1390              
1391             Remark:
1392              
1393             A title is drawn in the border of a widget. So a title will only
1394             be available if -border is true.
1395              
1396             =over 4
1397              
1398             =item * B<-title> < TEXT >
1399              
1400             Set the title of the widget to TEXT. If the text is longer then the
1401             available width, it will be clipped.
1402              
1403             =item * B<-titlereverse> < BOOLEAN >
1404              
1405             The title can be drawn in normal or in reverse type. If -titlereverse
1406             is true, the text will be drawn in reverse type. The default is to
1407             use reverse type.
1408              
1409             =item * B<-titlefullwidth> < BOOLEAN >
1410              
1411             If -titlereverse is true, the title can be stretched to fill the
1412             complete width of the widget by giving -titlefullwidth a true value.
1413             By default this option is disabled.
1414              
1415             =back
1416              
1417              
1418              
1419             =head2 SCROLLBARS:
1420              
1421             Remark:
1422              
1423             Since the user of a Curses::UI program has no real control over
1424             the so called "scrollbars", they aren't really scrollbars. A
1425             better name would be something like "document location indicators".
1426             But since they look so much like scrollbars I decided I could get
1427             away with this naming convention.
1428              
1429             =over 4
1430              
1431             =item * B<-vscrollbar> < VALUE >
1432              
1433             VALUE can be 'left', 'right', another true value or false.
1434              
1435             If -vscrollbar has a true value, a vertical scrollbar will
1436             be drawn by the widget. If this true value happens to be "left",
1437             the scrollbar will be drawn on the left side of the widget. In
1438             all other cases it will be drawn on the right side. The default
1439             is not to draw a vertical scrollbar.
1440              
1441             For widget programmers: To control the scrollbar, the widget
1442             data -vscrolllen (the total length of the content of the widget)
1443             and -vscrollpos (the current position in the document) should
1444             be set. If Curses::UI::Widget::draw is called, the scrollbar
1445             will be drawn.
1446              
1447             =item * B<-hscrollbar> < VALUE >
1448              
1449             VALUE can be 'top', 'bottom', another true value or false.
1450              
1451             If -hscrollbar has a true value, a horizontal scrollbar will
1452             be drawn by the widget. If this true value happens to be "top",
1453             the scrollbar will be drawn at the top of the widget. In
1454             all other cases it will be drawn at the bottom. The default
1455             is not to draw a horizontal scrollbar.
1456              
1457             For widget programmers: To control the scrollbar, the widget
1458             data -hscrolllen (the maximum width of the content of the widget)
1459             and -hscrollpos (the current horizontal position in the document)
1460             should be set. If Curses::UI::Widget::draw is called,
1461             the scrollbar will be drawn.
1462              
1463             =back
1464              
1465              
1466              
1467             =head2 EVENTS
1468              
1469             =over 4
1470              
1471             =item * B<-onfocus> < CODEREF >
1472              
1473             This sets the onFocus event handler for the widget.
1474             If the widget gets the focus, the code in CODEREF will
1475             be executed. It will get the widget reference as its
1476             argument.
1477              
1478             =item * B<-onblur> < CODEREF >
1479              
1480             This sets the onBlur event handler for the widget.
1481             If the widget loses the focus, the code in CODEREF will
1482             be executed. It will get the widget reference as its
1483             argument.
1484              
1485              
1486             =back
1487              
1488              
1489             =head1 METHODS
1490              
1491             =over 4
1492              
1493             =item * B ( OPTIONS )
1494              
1495             Create a new Curses::UI::Widget instance using the options in HASH.
1496              
1497             =item * B ( )
1498              
1499             Layout the widget. Compute the size the widget needs and see
1500             if it fits. Create the curses windows that are needed for
1501             the widget (the border and the effective drawing area).
1502              
1503             =item * B ( BOOLEAN )
1504              
1505             Draw the Curses::UI::Widget. If BOOLEAN is true, the screen
1506             will not update after drawing. By default this argument is
1507             false, so the screen will update after drawing the widget.
1508              
1509             =item * B ( )
1510              
1511             If the widget is visible (it is not hidden and it is in the
1512             window that is currently on top) and if intellidraw is not
1513             disabled for it (B<-intellidraw> has a true value) it is drawn
1514             and the curses routine doupdate() will be called to update
1515             the screen.
1516              
1517             This is useful if you change something in a widget and want
1518             it to update its state. If you simply call draw() and
1519             doupdate() yourself, then the widget will also be drawn if
1520             it is on a window that is currently not on top. This would
1521             result in the widget being drawn right through the contents
1522             of the window that is currently on top.
1523              
1524             =item * B ( )
1525              
1526             Give focus to the widget. In Curses::UI::Widget, this method
1527             immediately returns, so the widget will not get focused.
1528             A derived class that needs focus, must override this method.
1529              
1530             =item * B ( [BOOLEAN] )
1531              
1532             If BOOLEAN is set to a true value the widget will be focusable,
1533             false will make it unfocusable. If not argument is given,
1534             it will return the current state.
1535              
1536             =item * B ( )
1537              
1538             This method makes the current widget lose it's focus.
1539             It returns the current widget.
1540              
1541             =item * B ( )
1542              
1543             Gives the widget a modal focus, i.e. no other widget can be active
1544             till this widget is removed.
1545              
1546             =item * B ( TEXT ) </td> </tr> <tr> <td class="h" > <a name="1547">1547</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1548">1548</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> Change the title that is shown in the border of the widget </td> </tr> <tr> <td class="h" > <a name="1549">1549</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> to TEXT. </td> </tr> <tr> <td class="h" > <a name="1550">1550</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1551">1551</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =item * B<width> ( ) </td> </tr> <tr> <td class="h" > <a name="1552">1552</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1553">1553</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =item * B<height> ( ) </td> </tr> <tr> <td class="h" > <a name="1554">1554</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1555">1555</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> These methods return the total width and height of the widget. </td> </tr> <tr> <td class="h" > <a name="1556">1556</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> This is the space that the widget itself uses plus the space that </td> </tr> <tr> <td class="h" > <a name="1557">1557</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> is used by the outside padding. </td> </tr> <tr> <td class="h" > <a name="1558">1558</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1559">1559</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =item * B<borderwidth> ( ) </td> </tr> <tr> <td class="h" > <a name="1560">1560</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1561">1561</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =item * B<borderheight> ( ) </td> </tr> <tr> <td class="h" > <a name="1562">1562</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1563">1563</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> These methods return the width and the height of the border of the </td> </tr> <tr> <td class="h" > <a name="1564">1564</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> widget. </td> </tr> <tr> <td class="h" > <a name="1565">1565</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1566">1566</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =item * B<canvaswidth> ( ) </td> </tr> <tr> <td class="h" > <a name="1567">1567</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1568">1568</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =item * B<canvasheight> ( ) </td> </tr> <tr> <td class="h" > <a name="1569">1569</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1570">1570</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> These methods return the with and the height of the effective </td> </tr> <tr> <td class="h" > <a name="1571">1571</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> drawing area of the widget. This is the area where the </td> </tr> <tr> <td class="h" > <a name="1572">1572</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> draw() method of a widget may draw the contents of the widget </td> </tr> <tr> <td class="h" > <a name="1573">1573</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> (BTW: the curses window that is associated to this drawing </td> </tr> <tr> <td class="h" > <a name="1574">1574</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> area is $this->{-canvasscr}). </td> </tr> <tr> <td class="h" > <a name="1575">1575</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1576">1576</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =item * B<width_by_windowscrwidth> ( NEEDWIDTH, OPTIONS ) </td> </tr> <tr> <td class="h" > <a name="1577">1577</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1578">1578</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =item * B<height_by_windowscrheight> ( NEEDHEIGHT, OPTIONS ) </td> </tr> <tr> <td class="h" > <a name="1579">1579</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1580">1580</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> These methods are exported by this module. These can be used </td> </tr> <tr> <td class="h" > <a name="1581">1581</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> in child classes to easily compute the total width/height the widget </td> </tr> <tr> <td class="h" > <a name="1582">1582</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> needs in relation to the needed width/height of the effective drawing </td> </tr> <tr> <td class="h" > <a name="1583">1583</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> area ($this->{-canvasscr}). The OPTIONS contains the options that </td> </tr> <tr> <td class="h" > <a name="1584">1584</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> will be used to create the widget. So if we want a widget that </td> </tr> <tr> <td class="h" > <a name="1585">1585</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> has a drawing area height of 1 and that has a border, the -height </td> </tr> <tr> <td class="h" > <a name="1586">1586</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> option can be computed using something like: </td> </tr> <tr> <td class="h" > <a name="1587">1587</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1588">1588</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> my $height = height_by_windowscrheight(1, -border => 1); </td> </tr> <tr> <td class="h" > <a name="1589">1589</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1590">1590</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =item * B<generic_focus> ( BLOCKTIME, CTRLKEYS, CURSOR, PRECALLBACK ) </td> </tr> <tr> <td class="h" > <a name="1591">1591</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1592">1592</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> For most widgets the B<generic_focus> method will be enough to </td> </tr> <tr> <td class="h" > <a name="1593">1593</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> handle focusing. This method will do the following: </td> </tr> <tr> <td class="h" > <a name="1594">1594</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1595">1595</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> It starts a loop for reading keyboard input from the user. </td> </tr> <tr> <td class="h" > <a name="1596">1596</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> At the start of this loop the PRECALLBACK is called. This callback </td> </tr> <tr> <td class="h" > <a name="1597">1597</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> can for example be used for layouting the widget. Then, the widget </td> </tr> <tr> <td class="h" > <a name="1598">1598</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> is drawn. </td> </tr> <tr> <td class="h" > <a name="1599">1599</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1600">1600</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> Now a key is read or if the DO_KEY:<key> construction was used, </td> </tr> <tr> <td class="h" > <a name="1601">1601</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> the <key> will be used as if it was read from the keyboard (you </td> </tr> <tr> <td class="h" > <a name="1602">1602</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> can find more on this construction below). If the DO_KEY:<key> </td> </tr> <tr> <td class="h" > <a name="1603">1603</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> construction was not used, a key is read using the B<get_key> </td> </tr> <tr> <td class="h" > <a name="1604">1604</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> method which is in L<Curses::UI::Common|Curses::UI::Common>. </td> </tr> <tr> <td class="h" > <a name="1605">1605</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> The arguments BLOCKTIME, CTRLKEYS and CURSOR are passed to </td> </tr> <tr> <td class="h" > <a name="1606">1606</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> B<get_key>. </td> </tr> <tr> <td class="h" > <a name="1607">1607</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1608">1608</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> Now the key is checked. If the value of the key is -1, B<get_key> </td> </tr> <tr> <td class="h" > <a name="1609">1609</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> did not read a key at all. In that case, the program will go back </td> </tr> <tr> <td class="h" > <a name="1610">1610</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> to the start of the loop. </td> </tr> <tr> <td class="h" > <a name="1611">1611</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1612">1612</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> As soon as a key is read, this key will be handed to the </td> </tr> <tr> <td class="h" > <a name="1613">1613</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> B<process_bindings> method (see below). The returnvalue of this </td> </tr> <tr> <td class="h" > <a name="1614">1614</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> method (called RETURN from now on) will be used to determine </td> </tr> <tr> <td class="h" > <a name="1615">1615</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> what to do next. We have the following cases: </td> </tr> <tr> <td class="h" > <a name="1616">1616</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1617">1617</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> * B<RETURN matches DO_KEY:<key>> </td> </tr> <tr> <td class="h" > <a name="1618">1618</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1619">1619</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> The <key> is extracted from RETURN. The loop is restarted and </td> </tr> <tr> <td class="h" > <a name="1620">1620</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> <key> will be used as if it was entered using the keyboard. </td> </tr> <tr> <td class="h" > <a name="1621">1621</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1622">1622</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> * B<RETURN is a CODE reference> </td> </tr> <tr> <td class="h" > <a name="1623">1623</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1624">1624</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> RETURN will be returned to the caller of B<generic_focus>. </td> </tr> <tr> <td class="h" > <a name="1625">1625</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> This will have the widget lose its focus. The caller then can </td> </tr> <tr> <td class="h" > <a name="1626">1626</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> execute the code. </td> </tr> <tr> <td class="h" > <a name="1627">1627</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1628">1628</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> * B<RETURN is a SCALAR value> </td> </tr> <tr> <td class="h" > <a name="1629">1629</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1630">1630</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> RETURN will be returned to the caller of B<generic_focus>. </td> </tr> <tr> <td class="h" > <a name="1631">1631</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> This will have the widget lose its focus. </td> </tr> <tr> <td class="h" > <a name="1632">1632</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1633">1633</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> * B<anything else> </td> </tr> <tr> <td class="h" > <a name="1634">1634</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1635">1635</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> The widget will keep its focus. The loop will be restarted all </td> </tr> <tr> <td class="h" > <a name="1636">1636</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> over again. So, if you are writing a binding routine for a widget, </td> </tr> <tr> <td class="h" > <a name="1637">1637</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> you can have the focus to stay at the widget by returning the </td> </tr> <tr> <td class="h" > <a name="1638">1638</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> widget instance itself. Example: </td> </tr> <tr> <td class="h" > <a name="1639">1639</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1640">1640</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> sub myroutine() { </td> </tr> <tr> <td class="h" > <a name="1641">1641</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> my $this = shift; </td> </tr> <tr> <td class="h" > <a name="1642">1642</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> .... do your thing .... </td> </tr> <tr> <td class="h" > <a name="1643">1643</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> return $this; </td> </tr> <tr> <td class="h" > <a name="1644">1644</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> } </td> </tr> <tr> <td class="h" > <a name="1645">1645</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1646">1646</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1647">1647</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =item * B<process_bindings> ( KEY ) </td> </tr> <tr> <td class="h" > <a name="1648">1648</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1649">1649</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> KEY -> maps via binding to -> ROUTINE -> maps to -> VALUE </td> </tr> <tr> <td class="h" > <a name="1650">1650</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1651">1651</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> This method will try to find out if there is a binding defined </td> </tr> <tr> <td class="h" > <a name="1652">1652</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> for the KEY. If no binding is found, the method will return </td> </tr> <tr> <td class="h" > <a name="1653">1653</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> the widget object itself. </td> </tr> <tr> <td class="h" > <a name="1654">1654</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> If a binding is found, the method will check if there is </td> </tr> <tr> <td class="h" > <a name="1655">1655</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> an corresponding ROUTINE. If the ROUTINE can be found it </td> </tr> <tr> <td class="h" > <a name="1656">1656</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> will check if it's VALUE is a code reference. If it is, the </td> </tr> <tr> <td class="h" > <a name="1657">1657</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> code will be executed and the returnvalue of this code will </td> </tr> <tr> <td class="h" > <a name="1658">1658</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> be returned. Else the VALUE will directly be returned. </td> </tr> <tr> <td class="h" > <a name="1659">1659</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1660">1660</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =item * B<clear_binding> ( ROUTINE ) </td> </tr> <tr> <td class="h" > <a name="1661">1661</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1662">1662</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> Clear all keybindings for routine ROUTINE. </td> </tr> <tr> <td class="h" > <a name="1663">1663</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1664">1664</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =item * B<set_routine> ( ROUTINE, VALUE ) </td> </tr> <tr> <td class="h" > <a name="1665">1665</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1666">1666</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> Set the routine ROUTINE to the VALUE. The VALUE may either be a </td> </tr> <tr> <td class="h" > <a name="1667">1667</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> scalar value or a code reference. If B<process_bindings> (see above) </td> </tr> <tr> <td class="h" > <a name="1668">1668</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> sees a scalar value, it will return this value. If it sees a </td> </tr> <tr> <td class="h" > <a name="1669">1669</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> coderef, it will execute the code and return the returnvalue of </td> </tr> <tr> <td class="h" > <a name="1670">1670</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> this code. </td> </tr> <tr> <td class="h" > <a name="1671">1671</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1672">1672</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =item * B<set_binding> ( ROUTINE, KEYLIST ) </td> </tr> <tr> <td class="h" > <a name="1673">1673</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1674">1674</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> Bind the keys in the list KEYLIST to the ROUTINE. If you use an </td> </tr> <tr> <td class="h" > <a name="1675">1675</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> empty string for a key, then this routine will become the default </td> </tr> <tr> <td class="h" > <a name="1676">1676</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> routine (in case no other keybinding could be found). This </td> </tr> <tr> <td class="h" > <a name="1677">1677</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> is for example used in the TextEditor widget. </td> </tr> <tr> <td class="h" > <a name="1678">1678</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1679">1679</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =item * B<set_event> ( EVENT, [CODEREF] ) </td> </tr> <tr> <td class="h" > <a name="1680">1680</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1681">1681</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> This routine will set the callback for event EVENT to </td> </tr> <tr> <td class="h" > <a name="1682">1682</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> CODEREF. If CODEREF is omitted or undefined, the event will </td> </tr> <tr> <td class="h" > <a name="1683">1683</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> be cleared. </td> </tr> <tr> <td class="h" > <a name="1684">1684</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1685">1685</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =item * B<clear_event> ( EVENT ) </td> </tr> <tr> <td class="h" > <a name="1686">1686</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1687">1687</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> This will clear the callback for event EVENT. </td> </tr> <tr> <td class="h" > <a name="1688">1688</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1689">1689</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =item * B<run_event> ( EVENT ) </td> </tr> <tr> <td class="h" > <a name="1690">1690</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1691">1691</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> This routine will check if a callback for the event EVENT </td> </tr> <tr> <td class="h" > <a name="1692">1692</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> is set and if is a code reference. If this is the case, </td> </tr> <tr> <td class="h" > <a name="1693">1693</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> it will run the code and return its return value. </td> </tr> <tr> <td class="h" > <a name="1694">1694</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1695">1695</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =item * B<onFocus> ( CODEREF ) </td> </tr> <tr> <td class="h" > <a name="1696">1696</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1697">1697</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> This method can be used to set the B<-onfocus> event handler </td> </tr> <tr> <td class="h" > <a name="1698">1698</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> (see above) after initialization of the widget. </td> </tr> <tr> <td class="h" > <a name="1699">1699</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1700">1700</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =item * B<onBlur> ( CODEREF ) </td> </tr> <tr> <td class="h" > <a name="1701">1701</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1702">1702</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> This method can be used to set the B<-onblur> event handler </td> </tr> <tr> <td class="h" > <a name="1703">1703</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> (see above) after initialization of the widget. </td> </tr> <tr> <td class="h" > <a name="1704">1704</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1705">1705</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =item * B<parentwindow> ( ) </td> </tr> <tr> <td class="h" > <a name="1706">1706</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1707">1707</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> Returns this parent window for the widget or undef if </td> </tr> <tr> <td class="h" > <a name="1708">1708</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> no parent window can be found (this should not happen). </td> </tr> <tr> <td class="h" > <a name="1709">1709</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1710">1710</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =item * B<in_topwindow> ( ) </td> </tr> <tr> <td class="h" > <a name="1711">1711</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1712">1712</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> Returns true if the widget is in the window that is </td> </tr> <tr> <td class="h" > <a name="1713">1713</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> currently on top. </td> </tr> <tr> <td class="h" > <a name="1714">1714</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1715">1715</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =item * B<userdata> ( [ SCALAR ] ) </td> </tr> <tr> <td class="h" > <a name="1716">1716</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1717">1717</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> This method will return the user internal data stored in this widget. </td> </tr> <tr> <td class="h" > <a name="1718">1718</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> If a SCALAR parameter is specified it will also set the current user </td> </tr> <tr> <td class="h" > <a name="1719">1719</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> data to it. </td> </tr> <tr> <td class="h" > <a name="1720">1720</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1721">1721</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =item * B<beep_on> ( ) </td> </tr> <tr> <td class="h" > <a name="1722">1722</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1723">1723</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> This sets the data member $this->{B<-nobeep>} of the class instance </td> </tr> <tr> <td class="h" > <a name="1724">1724</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> to a false value. </td> </tr> <tr> <td class="h" > <a name="1725">1725</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1726">1726</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =item * B<beep_off> ( ) </td> </tr> <tr> <td class="h" > <a name="1727">1727</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1728">1728</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> This sets the data member $this->{B<-nobeep>} of the class instance </td> </tr> <tr> <td class="h" > <a name="1729">1729</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> to a true value. </td> </tr> <tr> <td class="h" > <a name="1730">1730</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1731">1731</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =item * B<dobeep> ( ) </td> </tr> <tr> <td class="h" > <a name="1732">1732</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1733">1733</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> This will call the curses beep() routine, but only if B<-nobeep> </td> </tr> <tr> <td class="h" > <a name="1734">1734</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> is false. </td> </tr> <tr> <td class="h" > <a name="1735">1735</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1736">1736</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =back </td> </tr> <tr> <td class="h" > <a name="1737">1737</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1738">1738</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1739">1739</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =head1 WIDGET STRUCTURE </td> </tr> <tr> <td class="h" > <a name="1740">1740</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1741">1741</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> Here's a basic framework for creating a new widget. You do not have </td> </tr> <tr> <td class="h" > <a name="1742">1742</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> to follow this framework. As long as your widget has the methods </td> </tr> <tr> <td class="h" > <a name="1743">1743</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> new(), layout(), draw() and focus(), it can be used in Curses::UI. </td> </tr> <tr> <td class="h" > <a name="1744">1744</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1745">1745</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> package Curses::UI::YourWidget </td> </tr> <tr> <td class="h" > <a name="1746">1746</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1747">1747</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> use Curses; </td> </tr> <tr> <td class="h" > <a name="1748">1748</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> use Curses::UI::Widget; </td> </tr> <tr> <td class="h" > <a name="1749">1749</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> use Curses::UI::Common; # some common widget routines </td> </tr> <tr> <td class="h" > <a name="1750">1750</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1751">1751</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> use vars qw($VERSION @ISA); </td> </tr> <tr> <td class="h" > <a name="1752">1752</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> $VERSION = '0.01'; </td> </tr> <tr> <td class="h" > <a name="1753">1753</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> @ISA = qw(Curses::UI::Widget Curses::UI::Common); </td> </tr> <tr> <td class="h" > <a name="1754">1754</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1755">1755</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # For a widget that can get focus, you should define </td> </tr> <tr> <td class="h" > <a name="1756">1756</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # the routines that are used to control the widget. </td> </tr> <tr> <td class="h" > <a name="1757">1757</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # Each routine has a name. This name is used in </td> </tr> <tr> <td class="h" > <a name="1758">1758</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # the definition of the bindings. </td> </tr> <tr> <td class="h" > <a name="1759">1759</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # The value can be a string or a subroutine reference. </td> </tr> <tr> <td class="h" > <a name="1760">1760</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # A string will make the widget return from focus. </td> </tr> <tr> <td class="h" > <a name="1761">1761</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # </td> </tr> <tr> <td class="h" > <a name="1762">1762</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> my %routines = ( </td> </tr> <tr> <td class="h" > <a name="1763">1763</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> 'return' => 'LOSE_FOCUS', </td> </tr> <tr> <td class="h" > <a name="1764">1764</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> 'key-a' => \&key_a, </td> </tr> <tr> <td class="h" > <a name="1765">1765</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> 'key-other' => \&other_key </td> </tr> <tr> <td class="h" > <a name="1766">1766</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> ); </td> </tr> <tr> <td class="h" > <a name="1767">1767</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1768">1768</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # Using the bindings, the routines can be binded to key- </td> </tr> <tr> <td class="h" > <a name="1769">1769</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # presses. If the keypress is an empty string, this means </td> </tr> <tr> <td class="h" > <a name="1770">1770</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # that this is the default binding. If the key is not </td> </tr> <tr> <td class="h" > <a name="1771">1771</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # handled by any other binding, it's handled by this </td> </tr> <tr> <td class="h" > <a name="1772">1772</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # default binding. </td> </tr> <tr> <td class="h" > <a name="1773">1773</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # </td> </tr> <tr> <td class="h" > <a name="1774">1774</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> my %bindings = ( </td> </tr> <tr> <td class="h" > <a name="1775">1775</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> KEY_DOWN() => 'return', # down arrow will make the </td> </tr> <tr> <td class="h" > <a name="1776">1776</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # widget lose it's focus </td> </tr> <tr> <td class="h" > <a name="1777">1777</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> 'a' => 'key-a', # a-key will trigger key_a() </td> </tr> <tr> <td class="h" > <a name="1778">1778</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> '' => 'key-other' # any other key will trigger other_key() </td> </tr> <tr> <td class="h" > <a name="1779">1779</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> ); </td> </tr> <tr> <td class="h" > <a name="1780">1780</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1781">1781</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # The creation of the widget. When doing it this way, </td> </tr> <tr> <td class="h" > <a name="1782">1782</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # it's easy to make optional and forced arguments </td> </tr> <tr> <td class="h" > <a name="1783">1783</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # possible. A forced argument could for example be </td> </tr> <tr> <td class="h" > <a name="1784">1784</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # -border => 1, which would mean that the widget </td> </tr> <tr> <td class="h" > <a name="1785">1785</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # always has a border, which can't be disabled by the </td> </tr> <tr> <td class="h" > <a name="1786">1786</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # programmer. The arguments can of course be used </td> </tr> <tr> <td class="h" > <a name="1787">1787</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # for storing the current state of the widget. </td> </tr> <tr> <td class="h" > <a name="1788">1788</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # </td> </tr> <tr> <td class="h" > <a name="1789">1789</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> sub new () { </td> </tr> <tr> <td class="h" > <a name="1790">1790</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> my $class = shift; </td> </tr> <tr> <td class="h" > <a name="1791">1791</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> my %args = ( </td> </tr> <tr> <td class="h" > <a name="1792">1792</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> -optional_argument_1 => "default value 1", </td> </tr> <tr> <td class="h" > <a name="1793">1793</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> -optional_argument_2 => "default value 2", </td> </tr> <tr> <td class="h" > <a name="1794">1794</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> ....etc.... </td> </tr> <tr> <td class="h" > <a name="1795">1795</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> @_, </td> </tr> <tr> <td class="h" > <a name="1796">1796</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> -forced_argument_1 => "forced value 1", </td> </tr> <tr> <td class="h" > <a name="1797">1797</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> -forced_argument_2 => "forced value 2", </td> </tr> <tr> <td class="h" > <a name="1798">1798</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> ....etc.... </td> </tr> <tr> <td class="h" > <a name="1799">1799</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> -bindings => {%bindings}, </td> </tr> <tr> <td class="h" > <a name="1800">1800</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> -routines => {%routines}, </td> </tr> <tr> <td class="h" > <a name="1801">1801</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> ); </td> </tr> <tr> <td class="h" > <a name="1802">1802</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1803">1803</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # Create the widget and do the layout of it. </td> </tr> <tr> <td class="h" > <a name="1804">1804</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> my $this = $class->SUPER::new( %args ); </td> </tr> <tr> <td class="h" > <a name="1805">1805</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> $this->layout; </td> </tr> <tr> <td class="h" > <a name="1806">1806</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1807">1807</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> return $this; </td> </tr> <tr> <td class="h" > <a name="1808">1808</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> } </td> </tr> <tr> <td class="h" > <a name="1809">1809</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1810">1810</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # Each widget should have a layout() routine. Here, </td> </tr> <tr> <td class="h" > <a name="1811">1811</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # the widget itself and it's contents can be layouted. </td> </tr> <tr> <td class="h" > <a name="1812">1812</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # In case of a very simple widget, this will only mean </td> </tr> <tr> <td class="h" > <a name="1813">1813</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # that the Widget has to be layouted (in which case the </td> </tr> <tr> <td class="h" > <a name="1814">1814</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # routine could be left out, since it's in the base </td> </tr> <tr> <td class="h" > <a name="1815">1815</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # class already). In other cases you will have to add </td> </tr> <tr> <td class="h" > <a name="1816">1816</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # your own layout code. This routine is very important, </td> </tr> <tr> <td class="h" > <a name="1817">1817</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # since it will enable the resizeability of the widget! </td> </tr> <tr> <td class="h" > <a name="1818">1818</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # </td> </tr> <tr> <td class="h" > <a name="1819">1819</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> sub layout () { </td> </tr> <tr> <td class="h" > <a name="1820">1820</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> my $this = shift; </td> </tr> <tr> <td class="h" > <a name="1821">1821</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1822">1822</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> $this->SUPER::layout; </td> </tr> <tr> <td class="h" > <a name="1823">1823</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> return $this if $Curses::UI::screen_too_small; </td> </tr> <tr> <td class="h" > <a name="1824">1824</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1825">1825</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> ....your own layout stuff.... </td> </tr> <tr> <td class="h" > <a name="1826">1826</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1827">1827</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # If you decide that the widget does not fit on the </td> </tr> <tr> <td class="h" > <a name="1828">1828</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # screen, then set $Curses::UI::screen_too_small </td> </tr> <tr> <td class="h" > <a name="1829">1829</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # to a true value and return. </td> </tr> <tr> <td class="h" > <a name="1830">1830</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> if ( ....the widget does not fit.... ) { </td> </tr> <tr> <td class="h" > <a name="1831">1831</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> $Curses::UI::screen_too_small++; </td> </tr> <tr> <td class="h" > <a name="1832">1832</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> return $this; </td> </tr> <tr> <td class="h" > <a name="1833">1833</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> } </td> </tr> <tr> <td class="h" > <a name="1834">1834</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1835">1835</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> return $this; </td> </tr> <tr> <td class="h" > <a name="1836">1836</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> } </td> </tr> <tr> <td class="h" > <a name="1837">1837</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1838">1838</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # The widget is drawn by the draw() routine. The </td> </tr> <tr> <td class="h" > <a name="1839">1839</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # $no_update part is used to disable screen flickering </td> </tr> <tr> <td class="h" > <a name="1840">1840</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # if a lot of widgets have to be drawn at once (for </td> </tr> <tr> <td class="h" > <a name="1841">1841</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # example on resizing or redrawing). The curses window </td> </tr> <tr> <td class="h" > <a name="1842">1842</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # which you can use for drawing the widget's contents </td> </tr> <tr> <td class="h" > <a name="1843">1843</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # is $this->{-canvasscr}. </td> </tr> <tr> <td class="h" > <a name="1844">1844</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # </td> </tr> <tr> <td class="h" > <a name="1845">1845</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> sub draw(;$) { </td> </tr> <tr> <td class="h" > <a name="1846">1846</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> my $this = shift; </td> </tr> <tr> <td class="h" > <a name="1847">1847</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> my $no_doupdate = shift || 0; </td> </tr> <tr> <td class="h" > <a name="1848">1848</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> return $this if $this->hidden; </td> </tr> <tr> <td class="h" > <a name="1849">1849</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> $this->SUPER::draw(1); </td> </tr> <tr> <td class="h" > <a name="1850">1850</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1851">1851</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> ....your own draw stuff.... </td> </tr> <tr> <td class="h" > <a name="1852">1852</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> $this->{-canvasscr}->addstr(0, 0, "Fixed string"); </td> </tr> <tr> <td class="h" > <a name="1853">1853</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> ....your own draw stuff.... </td> </tr> <tr> <td class="h" > <a name="1854">1854</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1855">1855</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> $this->{-canvasscr}->noutrefresh; </td> </tr> <tr> <td class="h" > <a name="1856">1856</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> doupdate() unless $no_doupdate; </td> </tr> <tr> <td class="h" > <a name="1857">1857</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> return $this; </td> </tr> <tr> <td class="h" > <a name="1858">1858</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> } </td> </tr> <tr> <td class="h" > <a name="1859">1859</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1860">1860</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # Focus the widget. If you do not override this routine </td> </tr> <tr> <td class="h" > <a name="1861">1861</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # from Curses::UI::Widget, the widget will not be </td> </tr> <tr> <td class="h" > <a name="1862">1862</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # focusable. Mostly you will use the generic_focus() method. </td> </tr> <tr> <td class="h" > <a name="1863">1863</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # </td> </tr> <tr> <td class="h" > <a name="1864">1864</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> sub focus() </td> </tr> <tr> <td class="h" > <a name="1865">1865</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> { </td> </tr> <tr> <td class="h" > <a name="1866">1866</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> my $this = shift; </td> </tr> <tr> <td class="h" > <a name="1867">1867</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> $this->show; # makes the widget visible if it was invisible </td> </tr> <tr> <td class="h" > <a name="1868">1868</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> return $this->generic_focus( </td> </tr> <tr> <td class="h" > <a name="1869">1869</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> undef, # delaytime, default = 2 (1/10 second). </td> </tr> <tr> <td class="h" > <a name="1870">1870</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> NO_CONTROLKEYS, # disable controlkeys like CTRL+C. To enable </td> </tr> <tr> <td class="h" > <a name="1871">1871</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # them use CONTROLKEYS instead. </td> </tr> <tr> <td class="h" > <a name="1872">1872</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> CURSOR_INVISIBLE, # do not show the cursor (if supported). To </td> </tr> <tr> <td class="h" > <a name="1873">1873</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # show the cursor use CURSOR_VISIBLE. </td> </tr> <tr> <td class="h" > <a name="1874">1874</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> \&pre_key_routine, # optional callback routine to execute </td> </tr> <tr> <td class="h" > <a name="1875">1875</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # before a key is read. Mostly unused. </td> </tr> <tr> <td class="h" > <a name="1876">1876</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> ); </td> </tr> <tr> <td class="h" > <a name="1877">1877</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> } </td> </tr> <tr> <td class="h" > <a name="1878">1878</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1879">1879</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> ....your own widget handling routines.... </td> </tr> <tr> <td class="h" > <a name="1880">1880</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1881">1881</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1882">1882</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1883">1883</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1884">1884</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =head1 SEE ALSO </td> </tr> <tr> <td class="h" > <a name="1885">1885</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1886">1886</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> L<Curses::UI|Curses::UI> </td> </tr> <tr> <td class="h" > <a name="1887">1887</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1888">1888</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1889">1889</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1890">1890</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1891">1891</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1892">1892</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1893">1893</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =head1 AUTHOR </td> </tr> <tr> <td class="h" > <a name="1894">1894</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1895">1895</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> Copyright (c) 2001-2002 Maurice Makaay. All rights reserved. </td> </tr> <tr> <td class="h" > <a name="1896">1896</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1897">1897</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> Maintained by Marcus Thiesen (marcus@cpan.thiesenweb.de) </td> </tr> <tr> <td class="h" > <a name="1898">1898</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1899">1899</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1900">1900</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> This package is free software and is provided "as is" without express </td> </tr> <tr> <td class="h" > <a name="1901">1901</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> or implied warranty. It may be used, redistributed and/or modified </td> </tr> <tr> <td class="h" > <a name="1902">1902</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> under the same terms as perl itself. </td> </tr> <tr> <td class="h" > <a name="1903">1903</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> </table> </body> </html>