File Coverage

blib/lib/Tk/ResizeButton.pm
Criterion Covered Total %
statement 3 3 100.0
branch n/a
condition n/a
subroutine 1 1 100.0
pod n/a
total 4 4 100.0


line stmt bran cond sub pod time code
1             package Tk::ResizeButton;
2             #------------------------------------------------
3             # automagically updated versioning variables -- CVS modifies these!
4             #------------------------------------------------
5             our $Revision = '$Revision: 1.3 $';
6             our $CheckinDate = '$Date: 2003/02/17 16:46:54 $';
7             our $CheckinUser = '$Author: xpix $';
8            
9             # we need to clean these up right here
10             $Revision =~ s/^\$\S+:\s*(.*?)\s*\$$/$1/sx;
11             $CheckinDate =~ s/^\$\S+:\s*(.*?)\s*\$$/$1/sx;
12             $CheckinUser =~ s/^\$\S+:\s*(.*?)\s*\$$/$1/sx;
13            
14             #-------------------------------------------------
15             #-- package Tk::ResizeButton ---------------------
16             #-------------------------------------------------
17            
18             =head1 NAME
19            
20             Tk::ResizeButton - provides a resizeable button to be used in an HList
21             column header.
22            
23             =head1 SYNOPSIS
24            
25             use Tk;
26             use Tk::HList;
27             use Tk::ResizeButton;
28            
29             my $mw = MainWindow->new();
30            
31             # CREATE MY HLIST
32             my $hlist = $mw->Scrolled('HList',
33             -columns=>2,
34             -header => 1
35             )->pack(-side => 'left', -expand => 'yes', -fill => 'both');
36            
37             # CREATE COLUMN HEADER 0
38             my $headerstyle = $hlist->ItemStyle('window', -padx => 0, -pady => 0);
39             my $header0 = $hlist->ResizeButton(
40             -text => 'Test Name',
41             -relief => 'flat', -pady => 0,
42             -command => sub { print "Hello, world!\n";},
43             -widget => \$hlist,
44             -column => 0
45             );
46             $hlist->header('create', 0,
47             -itemtype => 'window',
48             -widget => $header0,
49             -style=>$headerstyle
50             );
51            
52             # CREATE COLUMN HEADER 1
53             my $header1 = $hlist->ResizeButton(
54             -text => 'Status',
55             -relief => 'flat',
56             -pady => 0,
57             -command => sub { print "Hello, world!\n";},
58             -widget => \$hlist,
59             -column => 1
60             );
61             $hlist->header('create', 1,
62             -itemtype => 'window',
63             -widget => $header1,
64             -style =>$headerstyle
65             );
66            
67             =head1 DESCRIPTION
68            
69             The ResizeButton widget provides a resizeable button widget for use
70             in an HList column header. When placed in the column header, the
71             edge of the widget can be selected and dragged to a new location to
72             change the size of the HList column. When resizing the column, a
73             column bar will also be placed over the HList indicating the eventual
74             size of the HList column. A command can also be bound to the button
75             to do things like sorting the column.
76            
77             The widget takes all the options that Button does. In addition,
78             the following options must be specified:
79            
80             =over 4
81            
82             =item B<-widget>
83            
84             A reference to the HList widget must by provided via the -widget
85             option. This allows the ResizeButton to update the column width
86             after resizing.
87            
88             =item B<-column>
89            
90             The column number that this ResizeButton is associated with must
91             also be provided to resize the appropriate column.
92            
93             =back
94            
95             =head1 AUTHOR
96            
97             B
98            
99            
100             =head1 UPDATES
101            
102             Updated by Slaven Rezic and Frank Herrmann
103            
104             =over 4
105            
106             =item position columnbar correctly and only use MoveColumnBar to move it instead
107             of destroying it and re-creating with CreateColumnBar
108            
109             =item use Subwidget('scrolled') if it exists
110            
111             =item don't give error if -command is not specified
112            
113             =item don't let the user hide columns (minwidth?)
114            
115             =back
116            
117             =head1 KEYWORDS
118            
119             Tk::HList
120            
121             =cut
122            
123             #########################################################################
124             # Tk::ResizeButton
125             # Summary: This widget creates a button for use in an HList header which
126             # provides methods for resizing a column. This was heavily
127             # leveraged from Columns.pm by Damion Wilson.
128             # Author: Shaun Wandler
129             # Date: $Date: 2003/02/17 16:46:54 $
130             # Revision: $Revision: 1.3 $
131             #########################################################################=
132             #####
133             #
134             # Updated by Slaven Rezic and Frank Herrmann
135             #
136            
137             # XXX needs lot of work:
138             # * position columnbar correctly and only use MoveColumnBar to move it instead
139             # of destroying it and re-creating with CreateColumnBar
140             # * use Subwidget('scrolled') if it exists
141             # * don't give error if -command is not specified
142             # * don't let the user hide columns (minwidth?)
143            
144 1     1   796 use base qw(Tk::Derived Tk::Button);
  1         2  
  1         1707  
145            
146             Construct Tk::Widget 'ResizeButton';
147            
148             sub ClassInit {
149             my ( $class, $mw ) = @_;
150             $class->SUPER::ClassInit($mw);
151             $mw->bind( $class, '', 'ButtonRelease' );
152             $mw->bind( $class, '', 'ButtonPress' );
153             $mw->bind( $class, '', 'ButtonOver' );
154            
155             return $class;
156             }
157            
158             sub Populate {
159             my ( $this, $args ) = @_;
160            
161             # CREATE THE RESIZE CONTROLS
162             my $l_Widget;
163             for ( my $i = 0 ; $i < 2 ; ++$i ) {
164             $l_Widget = $this->Component(
165             'Frame' => 'Trim_' . $i,
166             -background => 'white',
167             -relief => 'raised',
168             -borderwidth => 2,
169             -width => 2,
170             )->place(
171             '-x' => -( $i * 3 + 2 ),
172             '-relheight' => 1.0,
173             '-anchor' => 'ne',
174             '-height' => -4,
175             '-relx' => 1.0,
176             '-y' => 2,
177             );
178             }
179            
180             $l_Widget->bind( '' => sub { $this->ButtonRelease(1); } );
181             $l_Widget->bind( '' => sub { $this->ButtonPress(1); } );
182             $l_Widget->bind( '' => sub { $this->ButtonOver(1); } );
183            
184             $this->SUPER::Populate($args);
185             $this->ConfigSpecs(
186             -widget => [ [ 'SELF', 'PASSIVE' ], 'Widget', 'Widget', undef ],
187             -column => [ [ 'SELF', 'PASSIVE' ], 'Column', 'Column', 0 ],
188             -minwidth => [ [ 'SELF', 'PASSIVE' ], 'minWidth', 'minWidth', 50 ],
189             );
190            
191             # Keep track of last trim widget
192             $this->{'m_LastTrim'} = $l_Widget;
193             }
194            
195             sub ButtonPress {
196             my ( $this, $p_Trim ) = ( shift, @_ );
197            
198             $this->{'m_relief'} = $this->cget( -relief );
199             if ( $this->ButtonEdgeSelected() || $p_Trim ) {
200             $this->{'m_EdgeSelected'} = 1;
201             $this->{m_X} = $this->pointerx() - $this->rootx();
202             CreateColumnBar($this);
203             } else {
204             $this->configure( -relief => 'sunken' );
205             $this->{m_X} = -1;
206             }
207             }
208            
209             sub ButtonRelease {
210             my ( $this, $p_Trim ) = ( shift, @_ );
211            
212             $this->{'m_EdgeSelected'} = 0;
213             $this->configure( -relief => $this->{'m_relief'} );
214            
215             if ( $this->{columnBar} ) {
216             $this->{columnBar}->destroy;
217             undef $this->{columnBar};
218             }
219             if ( $this->{m_X} >= 0 ) {
220             my $l_NewWidth = ( $this->pointerx() - $this->rootx() );
221            
222             my $hlist = $this->cget( -widget );
223             my $col = $this->cget( -column );
224             $$hlist->columnWidth( $col, $l_NewWidth + 5 )
225             if(($l_NewWidth + 5) > $this->cget( -minwidth ));
226            
227             $this->GeometryRequest( $l_NewWidth, $this->reqheight(), );
228            
229             } elsif ( !$this->ButtonEdgeSelected() ) {
230             $this->Callback( -command );
231             }
232            
233             $this->{m_X} = -1;
234             }
235            
236             # CHECK IF THE RESIZE CONTROL IS SELECTED
237             sub ButtonEdgeSelected {
238             my ($this) = @_;
239             {
240             return ( $this->pointerx() - $this->{m_LastTrim}->rootx() ) > -1;
241             }
242             }
243            
244             # CHANGE THE CURSOR OVER THE RESIZE CONTROL
245             sub ButtonOver {
246             my ( $this, $p_Trim ) = @_;
247             my ($cursor);
248             my $hlist = $this->cget( -widget );
249             if ( $this->{'m_EdgeSelected'} || $this->ButtonEdgeSelected() || $p_Trim ) {
250             if ( $this->{columnBar} ) {
251             $this->{columnBar}->destroy;
252             CreateColumnBar($this);
253             }
254             $cursor = 'sb_h_double_arrow';
255             } else {
256             $cursor = 'left_ptr';
257             }
258             $this->configure( -cursor => $cursor );
259             }
260            
261             # Create a column bar which displays on top of the HList widget
262             # to indicate the eventual size of the column.
263             sub CreateColumnBar {
264             my ($this) = @_;
265            
266             my $hlist = $this->cget( -widget );
267             my $height = $$hlist->height() - $this->height();
268             my $x = $$hlist->pointerx() - $$hlist->rootx();
269            
270             # my $x = $this->rootx + $this->width - $$hlist->rootx;
271             $this->{columnBar} = $$hlist->Frame(
272             -background => 'white',
273             -relief => 'raised',
274             -borderwidth => 2,
275             -width => 2,
276             );
277            
278             #FIXFIX: Some fudge factors were used here to place the column
279             # bar at the correct place. It appears that hlist->rootx is
280             # relative to the scrollbar, while when placing the columnbar
281             # the x location is relative to hlist widget. This definitely
282             # doesn't work when using a non-scrolled hlist.
283             $this->{columnBar}->place(
284             '-x' => $x,
285             '-height' => $height - 5,
286             '-relx' => 0.0,
287             '-rely' => 0.0,
288             '-y' => $this->height() + 5,
289             );
290             }
291            
292             1;