1# -----------------------------------------------------------------------------
2#  scrollw.tcl
3#  This file is part of Unifix BWidget Toolkit
4#  $Id: scrollw.tcl,v 1.7 2003/05/07 06:26:59 hobbs Exp $
5# -----------------------------------------------------------------------------
6#  Index of commands:
7#     - ScrolledWindow::create
8#     - ScrolledWindow::getframe
9#     - ScrolledWindow::setwidget
10#     - ScrolledWindow::configure
11#     - ScrolledWindow::cget
12#     - ScrolledWindow::_set_hframe
13#     - ScrolledWindow::_set_vscroll
14#     - ScrolledWindow::_setData
15#     - ScrolledWindow::_setSBSize
16#     - ScrolledWindow::_realize
17# -----------------------------------------------------------------------------
18
19namespace eval ScrolledWindow {
20    Widget::declare ScrolledWindow {
21	{-background  TkResource ""   0 button}
22	{-scrollbar   Enum	 both 0 {none both vertical horizontal}}
23	{-auto	      Enum	 both 0 {none both vertical horizontal}}
24	{-sides	      Enum	 se   0 {ne en nw wn se es sw ws}}
25	{-size	      Int	 0    1 "%d >= 0"}
26	{-ipad	      Int	 1    1 "%d >= 0"}
27	{-managed     Boolean	 1    1}
28	{-relief      TkResource flat 0 frame}
29	{-borderwidth TkResource 0    0 frame}
30	{-bg	      Synonym	 -background}
31	{-bd	      Synonym	 -borderwidth}
32    }
33
34    Widget::addmap ScrolledWindow "" :cmd {-relief {} -borderwidth {}}
35
36    proc ::ScrolledWindow {path args} {
37	return [eval [list ScrolledWindow::create $path] $args]
38    }
39    proc use {} {}
40}
41
42
43# -----------------------------------------------------------------------------
44#  Command ScrolledWindow::create
45# -----------------------------------------------------------------------------
46proc ScrolledWindow::create { path args } {
47    upvar \#0 ScrolledWindow::$path data
48
49    Widget::init ScrolledWindow $path $args
50
51    set bg     [Widget::cget $path -background]
52    set sbsize [Widget::cget $path -size]
53    set sw     [frame $path \
54	    -relief flat -borderwidth 0 -background $bg \
55	    -highlightthickness 0 -takefocus 0]
56
57    scrollbar $path.hscroll \
58	    -highlightthickness 0 -takefocus 0 \
59	    -orient	 horiz	\
60	    -relief	 sunken	\
61	    -bg	 $bg
62    scrollbar $path.vscroll \
63	    -highlightthickness 0 -takefocus 0 \
64	    -orient	 vert	\
65	    -relief	 sunken	\
66	    -bg	 $bg
67
68    set data(realized) 0
69
70    _setData $path \
71	    [Widget::cget $path -scrollbar] \
72	    [Widget::cget $path -auto] \
73	    [Widget::cget $path -sides]
74
75    if {[Widget::cget $path -managed]} {
76	set data(hsb,packed) $data(hsb,present)
77	set data(vsb,packed) $data(vsb,present)
78    } else {
79	set data(hsb,packed) 0
80	set data(vsb,packed) 0
81    }
82    if {$sbsize} {
83	$path.vscroll configure -width $sbsize
84	$path.hscroll configure -width $sbsize
85    } else {
86	set sbsize [$path.vscroll cget -width]
87    }
88    set data(ipad) [Widget::cget $path -ipad]
89
90    if {$data(hsb,packed)} {
91	grid $path.hscroll -column 1 -row $data(hsb,row) \
92		-sticky ew -ipady $data(ipad)
93    }
94    if {$data(vsb,packed)} {
95	grid $path.vscroll -column $data(vsb,column) -row 1 \
96		-sticky ns -ipadx $data(ipad)
97    }
98
99    grid columnconfigure $path 1 -weight 1
100    grid rowconfigure	 $path 1 -weight 1
101
102    bind $path <Configure> [list ScrolledWindow::_realize $path]
103    bind $path <Destroy>   [list ScrolledWindow::_destroy $path]
104    rename $path ::$path:cmd
105    proc ::$path { cmd args } "return \[eval ScrolledWindow::\$cmd $path \$args\]"
106
107    return $path
108}
109
110
111# -----------------------------------------------------------------------------
112#  Command ScrolledWindow::getframe
113# -----------------------------------------------------------------------------
114proc ScrolledWindow::getframe { path } {
115    return $path
116}
117
118
119# -----------------------------------------------------------------------------
120#  Command ScrolledWindow::setwidget
121# -----------------------------------------------------------------------------
122proc ScrolledWindow::setwidget { path widget } {
123    upvar \#0 ScrolledWindow::$path data
124
125    if {[info exists data(widget)] && ![string equal $data(widget) $widget]} {
126	grid remove $data(widget)
127	$data(widget) configure -xscrollcommand "" -yscrollcommand ""
128    }
129    set data(widget) $widget
130    grid $widget -in $path -row 1 -column 1 -sticky news
131
132    $path.hscroll configure -command [list $widget xview]
133    $path.vscroll configure -command [list $widget yview]
134    $widget configure \
135	    -xscrollcommand [list ScrolledWindow::_set_hscroll $path] \
136	    -yscrollcommand [list ScrolledWindow::_set_vscroll $path]
137}
138
139
140# -----------------------------------------------------------------------------
141#  Command ScrolledWindow::configure
142# -----------------------------------------------------------------------------
143proc ScrolledWindow::configure { path args } {
144    upvar \#0 ScrolledWindow::$path data
145
146    set res [Widget::configure $path $args]
147    if { [Widget::hasChanged $path -background bg] } {
148	$path configure -background $bg
149	catch {$path.hscroll configure -background $bg}
150	catch {$path.vscroll configure -background $bg}
151    }
152
153    if {[Widget::hasChanged $path -scrollbar scrollbar] | \
154	    [Widget::hasChanged $path -auto	 auto]	| \
155	    [Widget::hasChanged $path -sides	 sides]} {
156	_setData $path $scrollbar $auto $sides
157	foreach {vmin vmax} [$path.hscroll get] { break }
158	set data(hsb,packed) [expr {$data(hsb,present) && \
159		(!$data(hsb,auto) || ($vmin != 0 || $vmax != 1))}]
160	foreach {vmin vmax} [$path.vscroll get] { break }
161	set data(vsb,packed) [expr {$data(vsb,present) && \
162		(!$data(vsb,auto) || ($vmin != 0 || $vmax != 1))}]
163
164	set data(ipad) [Widget::cget $path -ipad]
165
166	if {$data(hsb,packed)} {
167	    grid $path.hscroll -column 1 -row $data(hsb,row) \
168		    -sticky ew -ipady $data(ipad)
169	}
170	if {$data(vsb,packed)} {
171	    grid $path.vscroll -column $data(vsb,column) -row 1 \
172		    -sticky ns -ipadx $data(ipad)
173	}
174    }
175    return $res
176}
177
178
179# -----------------------------------------------------------------------------
180#  Command ScrolledWindow::cget
181# -----------------------------------------------------------------------------
182proc ScrolledWindow::cget { path option } {
183    return [Widget::cget $path $option]
184}
185
186
187# -----------------------------------------------------------------------------
188#  Command ScrolledWindow::_destroy
189# -----------------------------------------------------------------------------
190proc ScrolledWindow::_destroy { path } {
191    upvar \#0 ScrolledWindow::$path data
192
193    unset data
194    Widget::destroy $path
195    rename $path {}
196}
197
198
199# -----------------------------------------------------------------------------
200#  Command ScrolledWindow::_set_hscroll
201# -----------------------------------------------------------------------------
202proc ScrolledWindow::_set_hscroll { path vmin vmax } {
203    upvar \#0 ScrolledWindow::$path data
204
205    if {$data(realized) && $data(hsb,present)} {
206	if {$data(hsb,auto)} {
207	    if {$data(hsb,packed) && $vmin == 0 && $vmax == 1} {
208		if {![info exists data(hlock)]} {
209		    set data(hsb,packed) 0
210		    grid remove $path.hscroll
211		}
212	    } elseif {!$data(hsb,packed) && ($vmin != 0 || $vmax != 1)} {
213		set data(hsb,packed) 1
214		grid $path.hscroll -column 1 -row $data(hsb,row) \
215			-sticky ew -ipady $data(ipad)
216		set data(hlock) 1
217		update idletasks
218		unset data(hlock)
219	    }
220	}
221	$path.hscroll set $vmin $vmax
222    }
223}
224
225
226# -----------------------------------------------------------------------------
227#  Command ScrolledWindow::_set_vscroll
228# -----------------------------------------------------------------------------
229proc ScrolledWindow::_set_vscroll { path vmin vmax } {
230    upvar \#0 ScrolledWindow::$path data
231
232    if {$data(realized) && $data(vsb,present)} {
233	if {$data(vsb,auto)} {
234	    if {$data(vsb,packed) && $vmin == 0 && $vmax == 1} {
235		if {![info exists data(vlock)]} {
236		    set data(vsb,packed) 0
237		    grid remove $path.vscroll
238		}
239	    } elseif {!$data(vsb,packed) && ($vmin != 0 || $vmax != 1) } {
240		set data(vsb,packed) 1
241		grid $path.vscroll -column $data(vsb,column) -row 1 \
242			-sticky ns -ipadx $data(ipad)
243		set data(vlock) 1
244		update idletasks
245		unset data(vlock)
246	    }
247	}
248	$path.vscroll set $vmin $vmax
249    }
250}
251
252
253proc ScrolledWindow::_setData {path scrollbar auto sides} {
254    upvar \#0 ScrolledWindow::$path data
255
256    set sb    [lsearch {none horizontal vertical both} $scrollbar]
257    set auto  [lsearch {none horizontal vertical both} $auto]
258
259    set data(hsb,present)  [expr {($sb & 1) != 0}]
260    set data(hsb,auto)	   [expr {($auto & 1) != 0}]
261    set data(hsb,row)	   [expr {[string match *n* $sides] ? 0 : 2}]
262
263    set data(vsb,present)  [expr {($sb & 2) != 0}]
264    set data(vsb,auto)	   [expr {($auto & 2) != 0}]
265    set data(vsb,column)   [expr {[string match *w* $sides] ? 0 : 2}]
266}
267
268# -----------------------------------------------------------------------------
269#  Command ScrolledWindow::_realize
270# -----------------------------------------------------------------------------
271proc ScrolledWindow::_realize { path } {
272    upvar \#0 ScrolledWindow::$path data
273
274    bind $path <Configure> {}
275    set data(realized) 1
276}
277