/usr/share/perl5/Curses/Widgets/Tutorial/Creation.pod is in libcurses-widgets-perl 1.997-6.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 | # Curses::Widget::Tutorial::Creation.pod -- Widget Creation Tutorial
#
# (c) 2001, Arthur Corliss <corliss@digitalmages.com>
#
# $Id: Creation.pod,v 0.3 2002/11/04 00:45:06 corliss Exp corliss $
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
#####################################################################
=head1 NAME
Curses::Widget::Tutorial::Creation -- Widget Creation Tutorial
=head1 POD VERSION
$Id: Creation.pod,v 0.3 2002/11/04 00:45:06 corliss Exp corliss $
=head1 DESCRIPTION
Creating a custom widget is as easy as creating a descendant class of
B<Curses::Widget> and defining as few as four methods:
Method Purpose
====================================================
_conf Validates configurations options and
initialises the internal state/data
_content Renders the widget according to the
current state
_cursor Renders the widget cursor according to the
current state
input_key Updates the state information according
to the passed character input
=head2 BASIC MODULE STRUCTURE
A decent code template for custom widgets would start with the following
(we'll call our new widget B<MyWidget>):
package MyWidget;
use strict;
use vars qw($VERSION @ISA);
use Curses;
use Curses::Widget;
($VERSION) = (q$Revision: 0.3 $ =~ /(\d+(?:\.(\d+))+)/);
@ISA = qw(Curses::Widget);
Please note that the B<use Curses::Widget;> statment provides more than just a
base class to inherit methods from, it also imports standard functions for
use in the module:
Function Purpose
===========================================================
select_colour Initialises new colour pairs, and returns
the appropriate colour pair number, for use
with $wh->attrset(COLOR_PAIR($n)) calls.
select_color, the American English spelling,
also works.
scankey This blocks until a key is pressed, and that
key returned.
textwrap Splits the text given into lines no longer
than the column limit specified.
See the B<Curses::Widget> pod for the specific syntax.
Descendent classes will automatically know the following fields (as used by
the B<new> or B<get/setField> methods):
Field Type Description
===========================================================
Y int Y coordinate of upper left corner of widget
X int X coordinate of upper left corner of widget
LINES int Number of lines in the content area of the widget
COLUMNS int Number of columsn inthe content area
BORDER boolean Whether to surround the widget with a box
CAPTION string Caption to display on top of border
FOREGROUND string Default foreground colour
BACKGROUND string Default background colour
BORDERCOL string Default border foreground colour
CAPTIONCOL string Default caption foreground colour
The colours, if not specified during widget instantiation, will default to the
colours in colour pair 0 (the terminal default). Borders will only be drawn
if BORDER is true, and that decision is made in the default B<_border> method,
not in the B<draw> method. The B<_caption> method also decides internally
whether or not to draw itself according to the value of BORDER.
=head2 METHOD SEMANTICS
The _conf method is called by the class constructor (provided by
B<Curses::Widget>, unless you override it here as well). Widget objects
should be created with all configuration options passed in a hash ref:
$widget = Curses::Widget::MyWidget->new({
OPTION1 => $value1,
OPTION2 => $value2,
[. . .]
});
The configuration hash is dereferenced and passed as arguments to the _conf
method inside of the B<new> constructor:
$rv = $self->_conf(%$conf);
Because of this, the _conf method should probably begin along these lines:
sub _conf {
my $self = shift;
my %conf = (
OPTION1 => default1,
OPTION2 => default2,
[. . .],
@_
);
my $err = 0;
# Validate and initialise the widget's state
# and store in the %conf hash
# Always include the following
$err = 1 unless $self->SUPER::_conf(%conf);
return ($err == 0) ? 1 : 0;
}
You should perform any initialisation and validation of the configuration
options here. This routine is expected to return a true or false value,
depending on whether or not any critical errors were found. A false value
will prevent the B<new> constructor from returning an object reference,
causing the instantiation request to fail.
The last two lines of code should always be included in this subroutine. The
call to the parent class' _conf method stores the final initialised state
information in %conf in the object field B<CONF>, after initialising many of
the standard colour fields, should they have been left undefined. You can
retrieve and update the state information via $self->{CONF}. A copy of that
state information will be stored in $self->{OCONF}, and can be restored with
a call to B<reset>, a method provided by B<Curses::Widgets>.
The second method you should override is the B<_content> method. This method,
as mentioned above, is responsible for rendering the widget according to its
state information. This method should handle one arguments:
$widget->_content($cwh);
The argument will be a window handle to the I<content area> of the widget.
You should always layout your widget with the upper left corner as (0, 0),
since the B<draw> method is responsible for allocating any extra space needed
for borders and captions.
If your widget doesn't support borders and/or captions you can do one of two
things: override those methods (B<_border> and B<_caption>) to immediately
return without doing anything, or override the B<draw> method to exclude those
calls. Typically, the former method of handling this would be preferred.
The third method you need to override is the B<_cursor> method. This accepts
the same window handle as the B<_content> method. The default B<draw> method
will only call this method if it was called with a true I<active> argument.
Neither of these two methods will need to allocate, refresh, or destroy window
handles, just print the content. The windows will already be erased and
initialised to specified foreground/background pairs, and those settings saved
via the B<_save> method. If at any time you need to reset the window handle's
current cursor back to those settings you can call B<_restore>:
$self->_restore($dwh);
In fact, in order to make the state of the window handle more predictable for
descendent classes you should probably call _restore at the end of each of
these methods.
The final method that should be overridden is the input_key method. This
expects a single argument, that being the keystroke captured by the keyboard
scanning function. It uses that value to update (if it's not rejected) the
widget's state information. A rough skeleton for this function would be as
follows:
sub input_key {
my $self = shift;
my $key = shift;
my $conf = $self->{CONF};
# validate/update state information
}
=head2 CONCLUSION
That, in a nutshell, is all there is to creating a custom widget. For a
working example which uses the structure noted above, look at the TextField or
ButtonSet widgets. Both consist of nothing more than the routines listed
above.
=head1 HISTORY
2001/07/07 -- First draft.
2002/11/01 -- Updated for reworked internals.
=head1 AUTHOR/COPYRIGHT
(c) 2001 Arthur Corliss (corliss@digitalmages.com),
=cut
|