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