1#
2# Scrolledwidget
3# ----------------------------------------------------------------------
4# Implements a general purpose base class for scrolled widgets, by
5# creating the necessary horizontal and vertical scrollbars and
6# providing protected methods for controlling their display.  The
7# derived class needs to take advantage of the fact that the grid
8# is used and the vertical scrollbar is in row 0, column 2 and the
9# horizontal scrollbar in row 2, column 0.
10#
11# ----------------------------------------------------------------------
12#  AUTHOR: Mark Ulferts                        mulferts@austin.dsccc.com
13#
14#  @(#) $Id: scrolledwidget.itk,v 1.2 2001/08/07 19:56:48 smithc Exp $
15# ----------------------------------------------------------------------
16#            Copyright (c) 1997 DSC Technologies Corporation
17# ======================================================================
18# Permission to use, copy, modify, distribute and license this software
19# and its documentation for any purpose, and without fee or written
20# agreement with DSC, is hereby granted, provided that the above copyright
21# notice appears in all copies and that both the copyright notice and
22# warranty disclaimer below appear in supporting documentation, and that
23# the names of DSC Technologies Corporation or DSC Communications
24# Corporation not be used in advertising or publicity pertaining to the
25# software without specific, written prior permission.
26#
27# DSC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
28# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, AND NON-
29# INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND THE
30# AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE MAINTENANCE,
31# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. IN NO EVENT SHALL
32# DSC BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
33# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
34# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTUOUS ACTION,
35# ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
36# SOFTWARE.
37# ======================================================================
38
39#
40# Usual options.
41#
42itk::usual Scrolledwidget {
43    keep -background -borderwidth -cursor -highlightcolor -highlightthickness
44    keep -activebackground -activerelief -jump -troughcolor
45    keep -labelfont -foreground
46}
47
48# ------------------------------------------------------------------
49#                            SCROLLEDWIDGET
50# ------------------------------------------------------------------
51itcl::class iwidgets::Scrolledwidget {
52    inherit iwidgets::Labeledwidget
53
54    constructor {args} {}
55    destructor {}
56
57    itk_option define -sbwidth sbWidth Width 15
58    itk_option define -scrollmargin scrollMargin ScrollMargin 3
59    itk_option define -vscrollmode vscrollMode VScrollMode static
60    itk_option define -hscrollmode hscrollMode HScrollMode static
61    itk_option define -width width Width 30
62    itk_option define -height height Height 30
63
64    protected method _scrollWidget {wid first last}
65    protected method _vertScrollbarDisplay {mode}
66    protected method _horizScrollbarDisplay {mode}
67    protected method _configureEvent {}
68
69    protected variable _vmode off            ;# Vertical scroll mode
70    protected variable _hmode off            ;# Vertical scroll mode
71    protected variable _recheckHoriz 1       ;# Flag to check need for
72                                             ;#  horizontal scrollbar
73    protected variable _recheckVert 1        ;# Flag to check need for
74                                             ;#  vertical scrollbar
75
76    protected variable _interior {}
77}
78
79#
80# Provide a lowercased access method for the Scrolledwidget class.
81#
82proc ::iwidgets::scrolledwidget {pathName args} {
83    uplevel ::iwidgets::Scrolledwidget $pathName $args
84}
85
86#
87# Use option database to override default resources of base classes.
88#
89option add *Scrolledwidget.labelPos n widgetDefault
90
91# ------------------------------------------------------------------
92#                        CONSTRUCTOR
93# ------------------------------------------------------------------
94itcl::body iwidgets::Scrolledwidget::constructor {args} {
95
96    #
97    # Turn off the borderwidth on the hull and save off the
98    # interior for later use.
99    #
100    component hull configure -borderwidth 0
101    set _interior $itk_interior
102
103    #
104    # Check if the scrollbars need mapping upon a configure event.
105    #
106    bind $_interior <Configure> [itcl::code $this _configureEvent]
107
108    #
109    # Turn off propagation in the containing shell.
110    #
111    # Due to a bug in the tk4.2 grid, we have to check the
112    # propagation before setting it.  Setting it to the same
113    # value it already is will cause it to toggle.
114    #
115    if {[grid propagate $_interior]} {
116	grid propagate $_interior no
117    }
118
119    #
120    # Create the vertical scroll bar
121    #
122    itk_component add vertsb {
123	scrollbar $itk_interior.vertsb -orient vertical
124    } {
125	usual
126	keep -borderwidth -elementborderwidth -jump -relief
127	rename -highlightbackground -background background Background
128    }
129
130    #
131    # Create the horizontal scrollbar
132    #
133    itk_component add horizsb {
134	scrollbar $itk_interior.horizsb -orient horizontal
135    } {
136	usual
137	keep -borderwidth -elementborderwidth -jump -relief
138	rename -highlightbackground -background background Background
139    }
140
141    #
142    # Initialize the widget based on the command line options.
143    #
144    eval itk_initialize $args
145}
146
147# ------------------------------------------------------------------
148#                           DESTURCTOR
149# ------------------------------------------------------------------
150itcl::body iwidgets::Scrolledwidget::destructor {} {
151}
152
153# ------------------------------------------------------------------
154#                             OPTIONS
155# ------------------------------------------------------------------
156
157# ------------------------------------------------------------------
158# OPTION: -sbwidth
159#
160# Set the width of the scrollbars.
161# ------------------------------------------------------------------
162itcl::configbody iwidgets::Scrolledwidget::sbwidth {
163    $itk_component(vertsb) configure -width $itk_option(-sbwidth)
164    $itk_component(horizsb) configure -width $itk_option(-sbwidth)
165}
166
167# ------------------------------------------------------------------
168# OPTION: -scrollmargin
169#
170# Set the distance between the scrollbars and the list box.
171# ------------------------------------------------------------------
172itcl::configbody iwidgets::Scrolledwidget::scrollmargin {
173    set pixels [winfo pixels $_interior	$itk_option(-scrollmargin)]
174
175    if {$_hmode == "on"} {
176	grid rowconfigure $_interior 1 -minsize $pixels
177    }
178
179    if {$_vmode == "on"} {
180	grid columnconfigure $_interior 1 -minsize $pixels
181    }
182}
183
184# ------------------------------------------------------------------
185# OPTION: -vscrollmode
186#
187# Enable/disable display and mode of veritcal scrollbars.
188# ------------------------------------------------------------------
189itcl::configbody iwidgets::Scrolledwidget::vscrollmode {
190    switch $itk_option(-vscrollmode) {
191    	static {
192    	    _vertScrollbarDisplay on
193    	}
194
195    	dynamic -
196    	none {
197    	    _vertScrollbarDisplay off
198    	}
199
200    	default {
201    	    error "bad vscrollmode option\
202		    \"$itk_option(-vscrollmode)\": should be\
203		    static, dynamic, or none"
204    	}
205    }
206}
207
208# ------------------------------------------------------------------
209# OPTION: -hscrollmode
210#
211# Enable/disable display and mode of horizontal scrollbars.
212# ------------------------------------------------------------------
213itcl::configbody iwidgets::Scrolledwidget::hscrollmode {
214    switch $itk_option(-hscrollmode) {
215    	static {
216    	    _horizScrollbarDisplay on
217    	}
218
219    	dynamic -
220    	none {
221    	    _horizScrollbarDisplay off
222    	}
223
224    	default {
225    	    error "bad hscrollmode option\
226		    \"$itk_option(-hscrollmode)\": should be\
227		    static, dynamic, or none"
228    	}
229    }
230}
231
232# ------------------------------------------------------------------
233# OPTION: -width
234#
235# Specifies the width of the scrolled widget.  The value may be
236# specified in any of the forms acceptable to Tk_GetPixels.
237# ------------------------------------------------------------------
238itcl::configbody iwidgets::Scrolledwidget::width {
239    $_interior configure -width \
240	[winfo pixels $_interior $itk_option(-width)]
241}
242
243# ------------------------------------------------------------------
244# OPTION: -height
245#
246# Specifies the height of the scrolled widget.  The value may be
247# specified in any of the forms acceptable to Tk_GetPixels.
248# ------------------------------------------------------------------
249itcl::configbody iwidgets::Scrolledwidget::height {
250    $_interior configure -height \
251	[winfo pixels $_interior $itk_option(-height)]
252}
253
254# ------------------------------------------------------------------
255#                            METHODS
256# ------------------------------------------------------------------
257
258# ------------------------------------------------------------------
259# PROTECTED METHOD: _vertScrollbarDisplay mode
260#
261# Displays the vertical scrollbar based on the input mode.
262# ------------------------------------------------------------------
263itcl::body iwidgets::Scrolledwidget::_vertScrollbarDisplay {mode} {
264    switch $mode  {
265	on {
266	    set _vmode on
267
268	    grid columnconfigure $_interior 1 -minsize \
269		    [winfo pixels $_interior $itk_option(-scrollmargin)]
270	    grid $itk_component(vertsb) -row 0 -column 2 -sticky ns
271	}
272
273	off {
274	    set _vmode off
275
276	    grid columnconfigure $_interior 1 -minsize 0
277	    grid forget $itk_component(vertsb)
278	}
279
280	default {
281	    error "invalid argument \"$mode\": should be on or off"
282	}
283    }
284}
285
286# ------------------------------------------------------------------
287# PROTECTED METHOD: _horizScrollbarDisplay mode
288#
289# Displays the horizontal scrollbar based on the input mode.
290# ------------------------------------------------------------------
291itcl::body iwidgets::Scrolledwidget::_horizScrollbarDisplay {mode} {
292    switch $mode  {
293	on {
294	    set _hmode on
295
296	    grid rowconfigure $_interior 1 -minsize \
297		    [winfo pixels $_interior $itk_option(-scrollmargin)]
298	    grid $itk_component(horizsb) -row 2 -column 0 -sticky ew
299	}
300
301	off {
302	    set _hmode off
303
304	    grid rowconfigure $_interior 1 -minsize 0
305	    grid forget $itk_component(horizsb)
306	}
307
308	default {
309	    error "invalid argument \"$mode\": should be on or off"
310	}
311    }
312}
313
314# ------------------------------------------------------------------
315# PROTECTED METHOD: _scrollWidget wid first last
316#
317# Performs scrolling and display of scrollbars based on the total
318# and maximum frame size as well as the current -vscrollmode and
319# -hscrollmode settings.  Parameters are automatic scroll parameters.
320# ------------------------------------------------------------------
321itcl::body iwidgets::Scrolledwidget::_scrollWidget {wid first last} {
322    $wid set $first $last
323
324    if {$wid == $itk_component(vertsb)} {
325	if {$itk_option(-vscrollmode) == "dynamic"} {
326	    if {($_recheckVert != 1) && ($_vmode == "on")} {
327		return
328	    } else {
329		set _recheckVert 0
330	    }
331
332	    if {($first == 0) && ($last == 1)} {
333		if {$_vmode != "off"} {
334		    _vertScrollbarDisplay off
335		}
336
337	    } else {
338		if {$_vmode != "on"} {
339		    _vertScrollbarDisplay on
340		}
341	    }
342	}
343
344    } elseif {$wid == $itk_component(horizsb)} {
345	if {$itk_option(-hscrollmode) == "dynamic"} {
346	    if {($_recheckHoriz != 1) && ($_hmode == "on")} {
347		return
348	    } else {
349		set _recheckHoriz 0
350	    }
351
352	    if {($first == 0) && ($last == 1)} {
353		if {$_hmode != "off"} {
354		    _horizScrollbarDisplay off
355		}
356
357	    } else {
358		if {$_hmode != "on"} {
359		    _horizScrollbarDisplay on
360		}
361	    }
362	}
363    }
364}
365
366# ------------------------------------------------------------------
367# PROTECTED METHOD: _configureEvent
368#
369# Resets the recheck flags which determine if we'll try and map
370# the scrollbars in dynamic mode.
371# ------------------------------------------------------------------
372itcl::body iwidgets::Scrolledwidget::_configureEvent {} {
373    update idletasks
374    set _recheckVert 1
375    set _recheckHoriz 1
376}
377