[3330] | 1 | # -*- mode: tcl; indent-tabs-mode: nil -*- |
---|
[1] | 2 | # ---------------------------------------------------------------------- |
---|
| 3 | # COMPONENT: pager - notebook for displaying pages of widgets |
---|
| 4 | # |
---|
| 5 | # This widget is something like a tabbed notebook, but with a little |
---|
| 6 | # more flexibility. Pages can be inserted and deleted, and then shown |
---|
| 7 | # in various arrangements. |
---|
| 8 | # ====================================================================== |
---|
| 9 | # AUTHOR: Michael McLennan, Purdue University |
---|
[3177] | 10 | # Copyright (c) 2004-2012 HUBzero Foundation, LLC |
---|
[115] | 11 | # |
---|
| 12 | # See the file "license.terms" for information on usage and |
---|
| 13 | # redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES. |
---|
[1] | 14 | # ====================================================================== |
---|
| 15 | package require Itk |
---|
| 16 | package require BLT |
---|
| 17 | |
---|
[11] | 18 | option add *Pager.arrangement "pages" widgetDefault |
---|
[1] | 19 | option add *Pager.width 0 widgetDefault |
---|
| 20 | option add *Pager.height 0 widgetDefault |
---|
[11] | 21 | option add *Pager.padding 8 widgetDefault |
---|
| 22 | option add *Pager.crumbColor black widgetDefault |
---|
| 23 | option add *Pager.crumbNumberColor white widgetDefault |
---|
| 24 | option add *Pager.dimCrumbColor gray70 widgetDefault |
---|
| 25 | option add *Pager.activeCrumbColor blue widgetDefault |
---|
| 26 | option add *Pager.crumbFont \ |
---|
[676] | 27 | -*-helvetica-bold-r-normal-*-12-* widgetDefault |
---|
[1] | 28 | |
---|
[11] | 29 | blt::bitmap define Pager-arrow { |
---|
| 30 | #define arrow_width 9 |
---|
| 31 | #define arrow_height 9 |
---|
| 32 | static unsigned char arrow_bits[] = { |
---|
| 33 | 0x10, 0x00, 0x30, 0x00, 0x70, 0x00, 0xff, 0x00, 0xff, 0x01, 0xff, 0x00, |
---|
| 34 | 0x70, 0x00, 0x30, 0x00, 0x10, 0x00}; |
---|
| 35 | } |
---|
| 36 | |
---|
[1] | 37 | itcl::class Rappture::Pager { |
---|
| 38 | inherit itk::Widget |
---|
| 39 | |
---|
| 40 | itk_option define -width width Width 0 |
---|
| 41 | itk_option define -height height Height 0 |
---|
[11] | 42 | itk_option define -padding padding Padding 0 |
---|
| 43 | itk_option define -crumbcolor crumbColor Foreground "" |
---|
| 44 | itk_option define -crumbnumbercolor crumbNumberColor Foreground "" |
---|
| 45 | itk_option define -crumbfont crumbFont Font "" |
---|
| 46 | itk_option define -dimcrumbcolor dimCrumbColor DimForeground "" |
---|
| 47 | itk_option define -activecrumbcolor activeCrumbColor ActiveForeground "" |
---|
| 48 | itk_option define -arrangement arrangement Arrangement "" |
---|
[1] | 49 | |
---|
| 50 | constructor {args} { # defined below } |
---|
| 51 | |
---|
| 52 | public method insert {pos args} |
---|
| 53 | public method delete {first {last ""}} |
---|
| 54 | public method index {name} |
---|
[11] | 55 | public method page {args} |
---|
| 56 | public method current {args} |
---|
[993] | 57 | |
---|
[992] | 58 | public method busy { bool } |
---|
[1] | 59 | |
---|
| 60 | protected method _layout {} |
---|
[11] | 61 | protected method _fixSize {} |
---|
| 62 | protected method _drawCrumbs {how} |
---|
[1] | 63 | |
---|
[11] | 64 | private variable _counter 0 ;# counter for page names |
---|
[1] | 65 | private variable _dispatcher "" ;# dispatcher for !events |
---|
| 66 | private variable _pages "" ;# list of known pages |
---|
[11] | 67 | private variable _page2info ;# maps page name => -frame,-title,-command |
---|
| 68 | private variable _current "" ;# page currently shown |
---|
[1] | 69 | } |
---|
[1929] | 70 | |
---|
[1] | 71 | itk::usual Pager { |
---|
| 72 | } |
---|
| 73 | |
---|
| 74 | # ---------------------------------------------------------------------- |
---|
| 75 | # CONSTRUCTOR |
---|
| 76 | # ---------------------------------------------------------------------- |
---|
| 77 | itcl::body Rappture::Pager::constructor {args} { |
---|
| 78 | Rappture::dispatcher _dispatcher |
---|
| 79 | $_dispatcher register !layout |
---|
| 80 | $_dispatcher dispatch $this !layout "[itcl::code $this _layout]; list" |
---|
[11] | 81 | $_dispatcher register !fixsize |
---|
| 82 | $_dispatcher dispatch $this !fixsize "[itcl::code $this _fixSize]; list" |
---|
[1] | 83 | |
---|
[11] | 84 | itk_component add controls { |
---|
[1929] | 85 | frame $itk_interior.cntls |
---|
[1] | 86 | } |
---|
| 87 | |
---|
[11] | 88 | itk_component add next { |
---|
[1929] | 89 | button $itk_component(controls).next -text "Next >" \ |
---|
| 90 | -command [itcl::code $this current next>] |
---|
[11] | 91 | } |
---|
| 92 | pack $itk_component(next) -side right |
---|
| 93 | |
---|
| 94 | itk_component add back { |
---|
[1929] | 95 | button $itk_component(controls).back -text "< Back" \ |
---|
| 96 | -command [itcl::code $this current <back] |
---|
[11] | 97 | } |
---|
| 98 | pack $itk_component(back) -side left |
---|
| 99 | |
---|
| 100 | set font [$itk_component(next) cget -font] |
---|
| 101 | set ht [font metrics $font -linespace] |
---|
[1274] | 102 | itk_component add breadcrumbarea { |
---|
[1929] | 103 | frame $itk_interior.bcarea |
---|
[1274] | 104 | } |
---|
[11] | 105 | itk_component add breadcrumbs { |
---|
[1929] | 106 | canvas $itk_component(breadcrumbarea).breadcrumbs \ |
---|
| 107 | -width 10 -height [expr {$ht+2}] |
---|
[11] | 108 | } |
---|
[1274] | 109 | pack $itk_component(breadcrumbs) -side left -expand yes -fill both \ |
---|
[1929] | 110 | -padx 8 -pady 8 |
---|
[11] | 111 | |
---|
| 112 | itk_component add line { |
---|
[1929] | 113 | frame $itk_interior.line -height 2 -borderwidth 1 -relief sunken |
---|
[11] | 114 | } |
---|
| 115 | |
---|
| 116 | |
---|
[1] | 117 | itk_component add inside { |
---|
[1929] | 118 | frame $itk_interior.inside |
---|
[1] | 119 | } |
---|
[11] | 120 | pack $itk_component(inside) -expand yes -fill both |
---|
| 121 | pack propagate $itk_component(inside) no |
---|
[1] | 122 | |
---|
| 123 | eval itk_initialize $args |
---|
[11] | 124 | $_dispatcher event -idle !layout |
---|
[1] | 125 | } |
---|
| 126 | |
---|
| 127 | # ---------------------------------------------------------------------- |
---|
[11] | 128 | # USAGE: insert <pos> ?-name <name>? ?-title <label>? ?-command <str>? |
---|
[1] | 129 | # |
---|
[11] | 130 | # Clients use this to insert a new page into this pager. The page is |
---|
| 131 | # inserted into the list at position <pos>, which can be an integer |
---|
| 132 | # starting from 0 or the keyword "end". The optional <name> can be |
---|
| 133 | # used to identify the page. If it is not supplied, a name is created |
---|
| 134 | # for the page. The -title and -command are other values associated |
---|
| 135 | # with the page. |
---|
| 136 | # |
---|
| 137 | # Returns the name used to identify the page. |
---|
[1] | 138 | # ---------------------------------------------------------------------- |
---|
| 139 | itcl::body Rappture::Pager::insert {pos args} { |
---|
| 140 | if {"end" == $pos} { |
---|
[1929] | 141 | set pos [llength $_pages] |
---|
[1] | 142 | } elseif {![string is integer $pos]} { |
---|
[1929] | 143 | error "bad index \"$pos\": should be integer or \"end\"" |
---|
[1] | 144 | } |
---|
| 145 | |
---|
[11] | 146 | Rappture::getopts args params { |
---|
[1929] | 147 | value -name page#auto |
---|
| 148 | value -title "Page #auto" |
---|
| 149 | value -command "" |
---|
[11] | 150 | } |
---|
| 151 | if {[llength $args] > 0} { |
---|
[1929] | 152 | error "wrong # args: should be \"insert pos ?-name n? ?-title t? ?-command c?\"" |
---|
[11] | 153 | } |
---|
[1] | 154 | |
---|
[11] | 155 | incr _counter |
---|
| 156 | if {$_counter > 1} { |
---|
[1929] | 157 | set subst "#$_counter" |
---|
[11] | 158 | } else { |
---|
[1929] | 159 | set subst "" |
---|
[1] | 160 | } |
---|
[11] | 161 | if {[regexp {#auto} $params(-name)]} { |
---|
[1929] | 162 | regsub -all {#auto} $params(-name) $subst params(-name) |
---|
[11] | 163 | } |
---|
| 164 | if {[regexp {#auto} $params(-title)]} { |
---|
[1929] | 165 | regsub -all {#auto} $params(-title) $subst params(-title) |
---|
[11] | 166 | } |
---|
| 167 | |
---|
| 168 | # allocate the page |
---|
| 169 | if {[info exists _page2info($params(-name)-frame)]} { |
---|
[1929] | 170 | error "page \"$params(-name)\" already exists" |
---|
[11] | 171 | } |
---|
| 172 | set win $itk_component(inside).page$_counter |
---|
| 173 | frame $win |
---|
| 174 | set _page2info($params(-name)-frame) $win |
---|
| 175 | set _page2info($params(-name)-title) $params(-title) |
---|
| 176 | set _page2info($params(-name)-command) $params(-command) |
---|
| 177 | set _pages [linsert $_pages $pos $params(-name)] |
---|
| 178 | |
---|
[24] | 179 | bind $win <Configure> \ |
---|
[1929] | 180 | [itcl::code $_dispatcher event -idle !fixsize] |
---|
[11] | 181 | |
---|
[22] | 182 | # the number of pages affects the arrangment -- force an update |
---|
| 183 | configure -arrangement $itk_option(-arrangement) |
---|
| 184 | |
---|
[1] | 185 | $_dispatcher event -idle !layout |
---|
| 186 | |
---|
[11] | 187 | return $params(-name) |
---|
[1] | 188 | } |
---|
| 189 | |
---|
| 190 | # ---------------------------------------------------------------------- |
---|
| 191 | # USAGE: delete <first> ?<last>? |
---|
| 192 | # |
---|
| 193 | # Clients use this to delete one or more pages from this widget. |
---|
| 194 | # The <first> and <last> represent the integer index of the desired |
---|
| 195 | # page. You can use the "index" method to convert a page name to |
---|
| 196 | # its integer index. If only <first> is specified, then that one |
---|
| 197 | # page is deleted. If <last> is specified, then all pages in the |
---|
| 198 | # range <first> to <last> are deleted. |
---|
| 199 | # ---------------------------------------------------------------------- |
---|
| 200 | itcl::body Rappture::Pager::delete {first {last ""}} { |
---|
| 201 | if {$last == ""} { |
---|
[1929] | 202 | set last $first |
---|
[1] | 203 | } |
---|
| 204 | if {![regexp {^[0-9]+|end$} $first]} { |
---|
[1929] | 205 | error "bad index \"$first\": should be integer or \"end\"" |
---|
[1] | 206 | } |
---|
| 207 | if {![regexp {^[0-9]+|end$} $last]} { |
---|
[1929] | 208 | error "bad index \"$last\": should be integer or \"end\"" |
---|
[1] | 209 | } |
---|
| 210 | |
---|
| 211 | foreach name [lrange $_pages $first $last] { |
---|
[1929] | 212 | if {[info exists _page2info($name-frame)]} { |
---|
| 213 | destroy $_page2info($name-frame) |
---|
| 214 | unset _page2info($name-frame) |
---|
| 215 | unset _page2info($name-title) |
---|
| 216 | unset _page2info($name-command) |
---|
| 217 | } |
---|
[1] | 218 | } |
---|
| 219 | set _pages [lreplace $_pages $first $last] |
---|
| 220 | |
---|
[22] | 221 | # the number of pages affects the arrangment -- force an update |
---|
| 222 | configure -arrangement $itk_option(-arrangement) |
---|
| 223 | |
---|
[1] | 224 | $_dispatcher event -idle !layout |
---|
| 225 | } |
---|
| 226 | |
---|
| 227 | # ---------------------------------------------------------------------- |
---|
[11] | 228 | # USAGE: index <name>|@n |
---|
[1] | 229 | # |
---|
| 230 | # Clients use this to convert a page <name> into its corresponding |
---|
[11] | 231 | # integer index. Returns an error if the <name> is not recognized. |
---|
[1] | 232 | # ---------------------------------------------------------------------- |
---|
| 233 | itcl::body Rappture::Pager::index {name} { |
---|
[11] | 234 | set i [lsearch $_pages $name] |
---|
| 235 | if {$i >= 0} { |
---|
[1929] | 236 | return $i |
---|
[11] | 237 | } |
---|
| 238 | if {[regexp {^@([0-9]+)$} $name match i]} { |
---|
[1929] | 239 | return $i |
---|
[11] | 240 | } |
---|
| 241 | error "bad page name \"$name\": should be @int or one of [join [lsort $_pages] {, }]" |
---|
[1] | 242 | } |
---|
| 243 | |
---|
| 244 | # ---------------------------------------------------------------------- |
---|
[11] | 245 | # USAGE: page |
---|
| 246 | # USAGE: page <name>|@n ?-frame|-title|-command? ?<newvalue>? |
---|
[1] | 247 | # |
---|
| 248 | # Clients use this to get information about pages. With no args, it |
---|
[11] | 249 | # returns a list of all page names. Otherwise, it returns the |
---|
| 250 | # requested information for a page specified by its <name> or index |
---|
| 251 | # @n. By default, it returns the -frame for the page, but it can |
---|
| 252 | # also return the -title and -command. The -title and -command |
---|
| 253 | # can also be set to a <newvalue>. |
---|
[1] | 254 | # ---------------------------------------------------------------------- |
---|
[11] | 255 | itcl::body Rappture::Pager::page {args} { |
---|
| 256 | if {[llength $args] == 0} { |
---|
[1929] | 257 | return $_pages |
---|
[1] | 258 | } |
---|
[11] | 259 | set i [index [lindex $args 0]] |
---|
| 260 | set name [lindex $_pages $i] |
---|
| 261 | |
---|
| 262 | set args [lrange $args 1 end] |
---|
| 263 | Rappture::getopts args params { |
---|
[1929] | 264 | flag what -frame default |
---|
| 265 | flag what -title |
---|
| 266 | flag what -command |
---|
[1] | 267 | } |
---|
[11] | 268 | |
---|
| 269 | if {[llength $args] == 0} { |
---|
[1929] | 270 | set opt $params(what) |
---|
| 271 | return $_page2info($name$opt) |
---|
[11] | 272 | } elseif {[llength $args] == 1} { |
---|
[1929] | 273 | set val [lindex $args 0] |
---|
| 274 | if {$params(-title)} { |
---|
| 275 | set _page2info($name-title) $val |
---|
| 276 | } elseif {$params(-command)} { |
---|
| 277 | set _page2info($name-command) $val |
---|
| 278 | } |
---|
[11] | 279 | } else { |
---|
[1929] | 280 | error "wrong # args: should be \"page ?which? ?-frame|-title|-command? ?newvalue?\"" |
---|
[11] | 281 | } |
---|
[1] | 282 | } |
---|
| 283 | |
---|
| 284 | # ---------------------------------------------------------------------- |
---|
[11] | 285 | # USAGE: current ?<name>|next>|<back? |
---|
| 286 | # |
---|
| 287 | # Used to query/set the current page in the notebook. With no args, |
---|
| 288 | # it returns the name of the current page. Otherwise, it sets the |
---|
| 289 | # current page. The special token "next>" is used to set the pager |
---|
| 290 | # to the next logical page, and "<back" sets to the previous. |
---|
| 291 | # ---------------------------------------------------------------------- |
---|
| 292 | itcl::body Rappture::Pager::current {args} { |
---|
| 293 | switch -- [llength $args] { |
---|
[1929] | 294 | 0 { |
---|
| 295 | return $_current |
---|
| 296 | } |
---|
| 297 | 1 { |
---|
| 298 | if {$itk_option(-arrangement) != "pages"} { |
---|
| 299 | return "" |
---|
| 300 | } |
---|
| 301 | set name [lindex $args 0] |
---|
| 302 | set index 0 |
---|
| 303 | if {$name == "next>"} { |
---|
| 304 | if {$_current == ""} { |
---|
| 305 | set index 0 |
---|
| 306 | } else { |
---|
| 307 | set i [lsearch -exact $_pages $_current] |
---|
| 308 | set index [expr {$i+1}] |
---|
| 309 | if {$index >= [llength $_pages]} { |
---|
| 310 | set index [expr {[llength $_pages]-1}] |
---|
| 311 | } |
---|
| 312 | } |
---|
| 313 | set _current [lindex $_pages $index] |
---|
| 314 | } elseif {$name == "<back"} { |
---|
| 315 | if {$_current == ""} { |
---|
| 316 | set index end |
---|
| 317 | } else { |
---|
| 318 | set i [lsearch -exact $_pages $_current] |
---|
| 319 | set index [expr {$i-1}] |
---|
| 320 | if {$index < 0} { |
---|
| 321 | set index 0 |
---|
| 322 | } |
---|
| 323 | } |
---|
| 324 | set _current [lindex $_pages $index] |
---|
| 325 | } else { |
---|
| 326 | if {$name == ""} { |
---|
| 327 | set _current "" |
---|
| 328 | set index 0 |
---|
| 329 | } else { |
---|
| 330 | set index [lsearch -exact $_pages $name] |
---|
| 331 | if {$index < 0} { |
---|
| 332 | error "can't move to page \"$name\"" |
---|
| 333 | } |
---|
| 334 | set _current [lindex $_pages $index] |
---|
| 335 | } |
---|
| 336 | } |
---|
[11] | 337 | |
---|
[1929] | 338 | foreach w [pack slaves $itk_component(inside)] { |
---|
| 339 | pack forget $w |
---|
| 340 | } |
---|
| 341 | if {$_current != ""} { |
---|
| 342 | pack $_page2info($_current-frame) -expand yes -fill both \ |
---|
| 343 | -padx $itk_option(-padding) -pady $itk_option(-padding) |
---|
| 344 | } |
---|
[11] | 345 | |
---|
[1929] | 346 | if {$index == 0} { |
---|
| 347 | pack forget $itk_component(back) |
---|
| 348 | } else { |
---|
| 349 | set prev [expr {$index-1}] |
---|
| 350 | if {$prev >= 0} { |
---|
| 351 | set label "< [page @$prev -title]" |
---|
| 352 | } else { |
---|
| 353 | set label "< Back" |
---|
| 354 | } |
---|
| 355 | $itk_component(back) configure -text $label |
---|
| 356 | pack $itk_component(back) -side left |
---|
| 357 | } |
---|
| 358 | if {$index == [expr {[llength $_pages]-1}]} { |
---|
| 359 | pack forget $itk_component(next) |
---|
| 360 | } else { |
---|
| 361 | set next [expr {$index+1}] |
---|
| 362 | if {$next <= [llength $_pages]} { |
---|
| 363 | set label "[page @$next -title] >" |
---|
| 364 | } else { |
---|
| 365 | set label "Next >" |
---|
| 366 | } |
---|
| 367 | $itk_component(next) configure -text $label |
---|
| 368 | pack $itk_component(next) -side right |
---|
| 369 | } |
---|
| 370 | _drawCrumbs current |
---|
[11] | 371 | |
---|
[1929] | 372 | # |
---|
| 373 | # If this new page has a command associated with it, then |
---|
| 374 | # invoke it now. |
---|
| 375 | # |
---|
| 376 | if {"" != $_current |
---|
| 377 | && [string length $_page2info($_current-command)] > 0} { |
---|
| 378 | uplevel #0 $_page2info($_current-command) |
---|
| 379 | } |
---|
| 380 | } |
---|
| 381 | default { |
---|
| 382 | error "wrong # args: should be \"current name|next>|<back\"" |
---|
| 383 | } |
---|
[11] | 384 | } |
---|
| 385 | } |
---|
| 386 | |
---|
| 387 | # ---------------------------------------------------------------------- |
---|
[1] | 388 | # USAGE: _layout |
---|
| 389 | # |
---|
| 390 | # Used internally to fix the current page management whenever pages |
---|
| 391 | # are added or deleted, or when the page arrangement changes. |
---|
| 392 | # ---------------------------------------------------------------------- |
---|
| 393 | itcl::body Rappture::Pager::_layout {} { |
---|
[11] | 394 | if {$itk_option(-arrangement) == "pages"} { |
---|
[1929] | 395 | if {$_current == ""} { |
---|
| 396 | set _current [lindex $_pages 0] |
---|
| 397 | if {$_current != ""} { |
---|
| 398 | current $_current |
---|
| 399 | } |
---|
| 400 | } |
---|
| 401 | _drawCrumbs all |
---|
[11] | 402 | } |
---|
| 403 | } |
---|
[1] | 404 | |
---|
[11] | 405 | # ---------------------------------------------------------------------- |
---|
| 406 | # USAGE: _fixSize |
---|
| 407 | # |
---|
| 408 | # Invoked automatically whenever a page changes size or the -width |
---|
| 409 | # or -height options change. When the -width/-height are zero, this |
---|
| 410 | # method computes the minimum size needed to accommodate all pages. |
---|
| 411 | # Otherwise, it passes the size request onto the hull. |
---|
| 412 | # ---------------------------------------------------------------------- |
---|
| 413 | itcl::body Rappture::Pager::_fixSize {} { |
---|
[26] | 414 | set sw [expr {[winfo screenwidth $itk_component(hull)]-200}] |
---|
| 415 | set sh [expr {[winfo screenheight $itk_component(hull)]-200}] |
---|
| 416 | |
---|
[53] | 417 | update ;# force layout changes so sizes are correct |
---|
[11] | 418 | switch -- $itk_option(-arrangement) { |
---|
[1929] | 419 | pages { |
---|
| 420 | if {$itk_option(-width) <= 0} { |
---|
| 421 | set maxw [expr { |
---|
| 422 | [winfo reqwidth $itk_component(next)] |
---|
| 423 | + 10 |
---|
| 424 | + [winfo reqwidth $itk_component(back)]}] |
---|
[11] | 425 | |
---|
[1929] | 426 | foreach name $_pages { |
---|
| 427 | set w [winfo reqwidth $_page2info($name-frame)] |
---|
| 428 | if {$w > $maxw} { set maxw $w } |
---|
| 429 | } |
---|
| 430 | set maxw [expr {$maxw + 2*$itk_option(-padding)}] |
---|
| 431 | if {$maxw > $sw} { set maxw $sw } |
---|
| 432 | $itk_component(inside) configure -width $maxw |
---|
| 433 | } else { |
---|
| 434 | $itk_component(inside) configure -width $itk_option(-width) |
---|
| 435 | } |
---|
[11] | 436 | |
---|
[1929] | 437 | if {$itk_option(-height) <= 0} { |
---|
| 438 | set maxh 0 |
---|
| 439 | foreach name $_pages { |
---|
| 440 | set h [winfo reqheight $_page2info($name-frame)] |
---|
| 441 | if {$h > $maxh} { set maxh $h } |
---|
| 442 | } |
---|
| 443 | set maxh [expr {$maxh + 2*$itk_option(-padding)}] |
---|
| 444 | if {$maxh > $sh} { set maxh $sh } |
---|
| 445 | $itk_component(inside) configure -height $maxh |
---|
| 446 | } else { |
---|
| 447 | $itk_component(inside) configure -height $itk_option(-height) |
---|
| 448 | } |
---|
| 449 | } |
---|
| 450 | side-by-side { |
---|
| 451 | if {$itk_option(-width) <= 0} { |
---|
| 452 | set maxw [expr { |
---|
| 453 | [winfo reqwidth $itk_component(next)] |
---|
| 454 | + 10 |
---|
| 455 | + [winfo reqwidth $itk_component(back)]}] |
---|
[11] | 456 | |
---|
[1929] | 457 | set wtotal 0 |
---|
| 458 | foreach name $_pages { |
---|
| 459 | set w [winfo reqwidth $_page2info($name-frame)] |
---|
| 460 | set wtotal [expr {$wtotal + $w + 2*$itk_option(-padding)}] |
---|
| 461 | } |
---|
| 462 | if {$wtotal > $maxw} { set maxw $wtotal } |
---|
| 463 | if {$maxw > $sw} { set maxw $sw } |
---|
| 464 | $itk_component(inside) configure -width $maxw |
---|
| 465 | } else { |
---|
| 466 | $itk_component(inside) configure -width $itk_option(-width) |
---|
| 467 | } |
---|
[11] | 468 | |
---|
[1929] | 469 | if {$itk_option(-height) <= 0} { |
---|
| 470 | set maxh 0 |
---|
| 471 | foreach name $_pages { |
---|
| 472 | set h [winfo reqheight $_page2info($name-frame)] |
---|
| 473 | if {$h > $maxh} { set maxh $h } |
---|
| 474 | } |
---|
| 475 | set maxh [expr {$maxh + 2*$itk_option(-padding)}] |
---|
| 476 | if {$maxh > $sh} { set maxh $sh } |
---|
| 477 | $itk_component(inside) configure -height $maxh |
---|
| 478 | } else { |
---|
| 479 | $itk_component(inside) configure -height $itk_option(-height) |
---|
| 480 | } |
---|
| 481 | } |
---|
[1] | 482 | } |
---|
[11] | 483 | } |
---|
[1] | 484 | |
---|
[11] | 485 | # ---------------------------------------------------------------------- |
---|
| 486 | # OPTION: -arrangement |
---|
| 487 | # ---------------------------------------------------------------------- |
---|
| 488 | itcl::configbody Rappture::Pager::arrangement { |
---|
| 489 | switch -- $itk_option(-arrangement) { |
---|
[1929] | 490 | pages { |
---|
| 491 | pack forget $itk_component(inside) |
---|
| 492 | pack $itk_component(controls) -side bottom -fill x -padx 8 -pady 8 |
---|
| 493 | pack $itk_component(breadcrumbarea) -side top -fill x |
---|
| 494 | pack $itk_component(line) -side top -fill x |
---|
| 495 | pack $itk_component(inside) -expand yes -fill both |
---|
| 496 | current [lindex $_pages 0] |
---|
| 497 | } |
---|
| 498 | side-by-side { |
---|
| 499 | pack forget $itk_component(controls) |
---|
| 500 | pack forget $itk_component(line) |
---|
| 501 | pack forget $itk_component(breadcrumbarea) |
---|
[11] | 502 | |
---|
[1929] | 503 | foreach w [pack slaves $itk_component(inside)] { |
---|
| 504 | pack forget $w |
---|
| 505 | } |
---|
| 506 | foreach name $_pages { |
---|
| 507 | pack $_page2info($name-frame) -side left \ |
---|
| 508 | -expand yes -fill both \ |
---|
| 509 | -padx $itk_option(-padding) -pady $itk_option(-padding) |
---|
| 510 | } |
---|
| 511 | } |
---|
| 512 | default { |
---|
| 513 | error "bad value \"$itk_option(-arrangement)\": should be pages or side-by-side" |
---|
| 514 | } |
---|
[1] | 515 | } |
---|
[11] | 516 | $_dispatcher event -now !fixsize |
---|
[1] | 517 | } |
---|
| 518 | |
---|
| 519 | # ---------------------------------------------------------------------- |
---|
[11] | 520 | # OPTION: -width |
---|
[1] | 521 | # ---------------------------------------------------------------------- |
---|
[11] | 522 | itcl::configbody Rappture::Pager::width { |
---|
| 523 | $_dispatcher event -idle !fixsize |
---|
| 524 | } |
---|
| 525 | |
---|
| 526 | # ---------------------------------------------------------------------- |
---|
| 527 | # OPTION: -height |
---|
| 528 | # ---------------------------------------------------------------------- |
---|
| 529 | itcl::configbody Rappture::Pager::height { |
---|
| 530 | $_dispatcher event -idle !fixsize |
---|
| 531 | } |
---|
| 532 | |
---|
| 533 | # ---------------------------------------------------------------------- |
---|
| 534 | # OPTION: -padding |
---|
| 535 | # ---------------------------------------------------------------------- |
---|
| 536 | itcl::configbody Rappture::Pager::padding { |
---|
| 537 | if {$_current != ""} { |
---|
[1929] | 538 | pack $_page2info($_current-frame) -expand yes -fill both \ |
---|
| 539 | -padx $itk_option(-padding) -pady $itk_option(-padding) |
---|
[1] | 540 | } |
---|
[11] | 541 | $_dispatcher event -idle !fixsize |
---|
[1] | 542 | } |
---|
| 543 | |
---|
[11] | 544 | # ---------------------------------------------------------------------- |
---|
| 545 | # USAGE: _drawCrumbs all|current |
---|
| 546 | # |
---|
| 547 | # Invoked automatically whenever the pages change. The value "all" |
---|
| 548 | # signifies that the number of pages has changed, so all should be |
---|
| 549 | # redrawn. The value "current" means that the current page has |
---|
| 550 | # changed, so there is just a simple color change. |
---|
| 551 | # ---------------------------------------------------------------------- |
---|
| 552 | itcl::body Rappture::Pager::_drawCrumbs {how} { |
---|
| 553 | set c $itk_component(breadcrumbs) |
---|
| 554 | set fnt $itk_option(-crumbfont) |
---|
[1] | 555 | |
---|
[11] | 556 | switch -- $how { |
---|
[1929] | 557 | all { |
---|
| 558 | $c delete all |
---|
[1] | 559 | |
---|
[1929] | 560 | set x 0 |
---|
| 561 | set y [expr {[winfo reqheight $c]/2}] |
---|
| 562 | set last [lindex $_pages end] |
---|
[1] | 563 | |
---|
[1929] | 564 | set num 1 |
---|
| 565 | foreach name $_pages { |
---|
| 566 | set ht [expr {[font metrics $fnt -linespace]+2}] |
---|
| 567 | set id [$c create oval $x [expr {$y-$ht/2}] \ |
---|
| 568 | [expr {$x+$ht}] [expr {$y+$ht/2}] \ |
---|
| 569 | -outline "" -fill $itk_option(-dimcrumbcolor) \ |
---|
| 570 | -tags $name] |
---|
| 571 | set id [$c create text [expr {$x+$ht/2}] [expr {$y+1}] \ |
---|
| 572 | -text $num -fill $itk_option(-crumbnumbercolor) \ |
---|
| 573 | -tags [list $name $name-num]] |
---|
| 574 | set x [expr {$x + $ht+2}] |
---|
[1] | 575 | |
---|
[1929] | 576 | set id [$c create text $x [expr {$y+1}] -anchor w \ |
---|
| 577 | -text [page $name -title] -font $fnt -tags $name] |
---|
[11] | 578 | |
---|
[1929] | 579 | $c bind $name <Enter> [itcl::code $this _drawCrumbs active] |
---|
| 580 | $c bind $name <Leave> [itcl::code $this _drawCrumbs current] |
---|
| 581 | $c bind $name <ButtonPress> [itcl::code $this current $name] |
---|
[11] | 582 | |
---|
[1929] | 583 | foreach {x0 y0 x1 y1} [$c bbox $id] break |
---|
| 584 | set x [expr {$x + ($x1-$x0)+6}] |
---|
[11] | 585 | |
---|
[1929] | 586 | if {$name != $last} { |
---|
| 587 | set id [$c create bitmap $x $y -anchor w \ |
---|
| 588 | -bitmap Pager-arrow \ |
---|
| 589 | -foreground $itk_option(-dimcrumbcolor)] |
---|
| 590 | foreach {x0 y0 x1 y1} [$c bbox $id] break |
---|
| 591 | set x [expr {$x + ($x1-$x0)+6}] |
---|
| 592 | } |
---|
[11] | 593 | |
---|
[1929] | 594 | incr num |
---|
| 595 | } |
---|
[11] | 596 | |
---|
[1929] | 597 | # fix the scrollregion in case we go off screen |
---|
| 598 | $c configure -scrollregion [$c bbox all] |
---|
[11] | 599 | |
---|
[1929] | 600 | _drawCrumbs current |
---|
| 601 | } |
---|
| 602 | current { |
---|
| 603 | # make all crumbs dim |
---|
| 604 | foreach name $_pages { |
---|
| 605 | $c itemconfigure $name \ |
---|
| 606 | -fill $itk_option(-dimcrumbcolor) |
---|
| 607 | $c itemconfigure $name-num \ |
---|
| 608 | -fill $itk_option(-crumbnumbercolor) |
---|
| 609 | } |
---|
[11] | 610 | |
---|
[1929] | 611 | # make all the current crumb bright |
---|
| 612 | if {$_current != ""} { |
---|
| 613 | $c itemconfigure $_current \ |
---|
| 614 | -fill $itk_option(-crumbcolor) |
---|
| 615 | $c itemconfigure $_current-num \ |
---|
| 616 | -fill $itk_option(-crumbnumbercolor) |
---|
[11] | 617 | |
---|
[1929] | 618 | # scroll the view to see the crumb |
---|
| 619 | if {[$c bbox $_current] != ""} { |
---|
| 620 | foreach {x0 y0 x1 y1} [$c bbox $_current] break |
---|
| 621 | foreach {xm0 ym0 xm1 ym1} [$c bbox all] break |
---|
| 622 | set xm [expr {double($x0)/($xm1-$xm0)}] |
---|
| 623 | $c xview moveto $xm |
---|
| 624 | } |
---|
| 625 | } else { |
---|
| 626 | $c xview moveto 0 |
---|
| 627 | } |
---|
| 628 | } |
---|
| 629 | active { |
---|
| 630 | foreach tag [$c gettags current] { |
---|
| 631 | if {[lsearch -exact $_pages $tag] >= 0} { |
---|
| 632 | $c itemconfigure $tag -fill $itk_option(-activecrumbcolor) |
---|
| 633 | $c itemconfigure $tag-num -fill white |
---|
| 634 | } |
---|
| 635 | } |
---|
| 636 | } |
---|
[11] | 637 | } |
---|
| 638 | } |
---|
[989] | 639 | |
---|
[993] | 640 | # |
---|
| 641 | # busy -- |
---|
| 642 | # |
---|
[2744] | 643 | # If true (this indicates a simulation is occurring), the widget |
---|
| 644 | # should prevent the user from |
---|
| 645 | # 1) clicking an item previous in the breadcrumbs, and |
---|
| 646 | # 2) using the "back" button. |
---|
[993] | 647 | # |
---|
[989] | 648 | itcl::body Rappture::Pager::busy { bool } { |
---|
| 649 | if { $bool } { |
---|
[1929] | 650 | blt::busy hold $itk_component(breadcrumbs) |
---|
| 651 | $itk_component(back) configure -state disabled |
---|
[989] | 652 | } else { |
---|
[1929] | 653 | blt::busy release $itk_component(breadcrumbs) |
---|
| 654 | $itk_component(back) configure -state normal |
---|
[989] | 655 | } |
---|
| 656 | } |
---|