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
|
set rcsId {$Id: scroll.tcl,v 2.7 2000/11/01 12:00:50 jfontain Exp $}
# generic scroll widget with automatic scrollbars for scrolling widgets with the common tk scroll interface
class scroll {
proc scroll {this scrollableClass parentPath args} composite {[new frame $parentPath] $args} {
variable ${this}first
variable ${this}last
# scrollable class widget must accept the -[xy]scrollcommand options and [xy]view commands, such as canvas, text, table, ...
set path $widget::($this,path)
composite::manage $this [new $scrollableClass $path] scrolled\
[new scrollbar $path -orient horizontal -highlightthickness 0] horizontal\
[new scrollbar $path -highlightthickness 0] vertical [new frame $path] filler
widget::configure $composite::($this,scrolled)\
-xscrollcommand "scroll::update $this 1 0" -yscrollcommand "scroll::update $this 0 1"
widget::configure $composite::($this,horizontal) -command "$composite::($this,scrolled,path) xview"
widget::configure $composite::($this,vertical) -command "$composite::($this,scrolled,path) yview"
grid propagate $widget::($this,path) 0 ;# turn off propagation so that setting width and height is possible
grid $composite::($this,scrolled,path) -sticky nsew -ipadx 0
grid rowconfigure $path 0 -weight 1
grid columnconfigure $path 0 -weight 1
set ($this,0,1,path) $composite::($this,vertical,path)
set ($this,1,0,path) $composite::($this,horizontal,path)
set ($this,0,1,map) 1
set ($this,1,0,map) 1
for {set index -1} {$index>=-3} {incr index -1} {
set ${this}first(0,1,$index) -2147483648
set ${this}last(0,1,$index) -2147483648
set ${this}first(1,0,$index) -2147483648
set ${this}last(1,0,$index) -2147483648
}
composite::complete $this
}
proc ~scroll {this} {}
proc options {this} {
return [list\
[list -automatic 1 1]\
[list -scrollbarborderwidth $widget::option(scrollbar,borderwidth) $widget::option(scrollbar,borderwidth)]\
[list\
-scrollbarelementborderwidth\
$widget::option(scrollbar,elementborderwidth) $widget::option(scrollbar,elementborderwidth)\
]\
[list -scrollbarwidth $widget::option(scrollbar,width) $widget::option(scrollbar,width)]\
[list -height $widget::option(canvas,height)]\
[list -horizontal $($this,1,0,map) $($this,1,0,map)]\
[list -vertical $($this,0,1,map) $($this,0,1,map)]\
[list -width $widget::option(canvas,width)]\
]
}
proc set-automatic {this value} {
if {$composite::($this,complete)} {
error {option -automatic cannot be set dynamically}
}
}
proc set-horizontal {this value} {
if {$composite::($this,complete)} {
error {option -horizontal cannot be set dynamically}
}
set ($this,1,0,map) $value
}
proc set-vertical {this value} {
if {$composite::($this,complete)} {
error {option -vertical cannot be set dynamically}
}
set ($this,0,1,map) $value
}
foreach option {borderwidth elementborderwidth width} {
proc set-scrollbar$option {this value} "
\$composite::(\$this,vertical,path) configure -$option \$value
\$composite::(\$this,horizontal,path) configure -$option \$value
"
}
proc set-height {this value} {
$widget::($this,path) configure -height $value
}
proc set-width {this value} {
$widget::($this,path) configure -width $value
}
proc update {this row column first last} {
set path $($this,$row,$column,path)
foreach {previousFirst previousLast} [$path get] {}
if {($first==$previousFirst)&&($last==$previousLast)} return ;# no change
$path set $first $last ;# always set so that get always return valid values
set visible [llength [grid info $path]]
if {[repetition $this $row $column $first $last]||!$composite::($this,-automatic)||(($last-$first)<1)} {
# map scrollbar to kill a starting vibration
if {!$visible&&$($this,$row,$column,map)} {
grid $path -row $row -column $column -sticky nsew
grid $composite::($this,filler,path) -sticky nsew -column 1 -row 1
}
} else {
grid remove $path
set visible [llength [grid info $($this,$column,$row,path)]] ;# look at other scrollbar
if {!$visible} {
grid remove $composite::($this,filler,path)
}
}
}
proc repetition {this row column first last} {
variable ${this}first
variable ${this}last
set return [expr {\
($first==[set ${this}first($row,$column,-2)])&&\
($last==[set ${this}last($row,$column,-2)])&&\
([set ${this}first($row,$column,-1)]==[set ${this}first($row,$column,-3)])&&\
([set ${this}last($row,$column,-1)]==[set ${this}last($row,$column,-3)])\
}]
set ${this}first($row,$column,-3) [set ${this}first($row,$column,-2)]
set ${this}last($row,$column,-3) [set ${this}last($row,$column,-2)]
set ${this}first($row,$column,-2) [set ${this}first($row,$column,-1)]
set ${this}last($row,$column,-2) [set ${this}last($row,$column,-1)]
set ${this}first($row,$column,-1) $first
set ${this}last($row,$column,-1) $last
return $return
}
}
|