home *** CD-ROM | disk | FTP | other *** search
/ PC World 2000 December / PCWorld_2000-12_cd.bin / Komunikace / Comanche / comanche.exe / lib / iwidgets3.0.0 / scripts / tabset.itk < prev    next >
Text File  |  1999-02-24  |  83KB  |  2,748 lines

  1. #
  2. # Tabset Widget and the Tab Class
  3. # ----------------------------------------------------------------------
  4. # A Tabset is a widget that contains a set of Tab buttons. 
  5. # It displays these tabs in a row or column depending on it tabpos. 
  6. # When a tab is clicked on, it becomes the only tab in the tab set that 
  7. # is selected. All other tabs are deselected. The Tcl command prefix 
  8. # associated with this tab (through the command tab configure option) 
  9. # is invoked with the tab index number appended to its argument list. 
  10. # This allows the Tabset to control another widget such as a Notebook.
  11. #
  12. # A Tab class is an [incr Tcl] class that displays either an image, 
  13. # bitmap, or label in a graphic object on a canvas. This graphic object 
  14. # can have a wide variety of appearances depending on the options set. 
  15. #
  16. # WISH LIST:
  17. #   This section lists possible future enhancements.
  18. #
  19. #   1) When too many tabs appear, a small scrollbar should appear to
  20. #      move the tabs over.
  21. #
  22. # ----------------------------------------------------------------------
  23. #  AUTHOR: Bill W. Scott                 EMAIL: bscott@spd.dsccc.com
  24. #
  25. #  @(#) $Id: tabset.itk,v 1.1 1998/07/27 18:53:19 stanton Exp $
  26. # ----------------------------------------------------------------------
  27. #            Copyright (c) 1995 DSC Technologies Corporation
  28. # ======================================================================
  29. # Permission to use, copy, modify, distribute and license this software 
  30. # and its documentation for any purpose, and without fee or written 
  31. # agreement with DSC, is hereby granted, provided that the above copyright 
  32. # notice appears in all copies and that both the copyright notice and 
  33. # warranty disclaimer below appear in supporting documentation, and that 
  34. # the names of DSC Technologies Corporation or DSC Communications 
  35. # Corporation not be used in advertising or publicity pertaining to the 
  36. # software without specific, written prior permission.
  37. # DSC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
  38. # ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, AND NON-
  39. # INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND THE
  40. # AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE MAINTENANCE, 
  41. # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. IN NO EVENT SHALL 
  42. # DSC BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 
  43. # ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
  44. # WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTUOUS ACTION,
  45. # ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
  46. # SOFTWARE.
  47. # ======================================================================
  48.  
  49. #
  50. # Default resources.
  51. #
  52. option add *Tabset.width          0            widgetDefault
  53. option add *Tabset.height         0            widgetDefault
  54. option add *Tabset.equalTabs      true         widgetDefault
  55. option add *Tabset.tabPos         s            widgetDefault
  56. option add *Tabset.raiseSelect    false        widgetDefault
  57. option add *Tabset.start          4            widgetDefault
  58. option add *Tabset.margin         5            widgetDefault
  59. option add *Tabset.tabBorders     true         widgetDefault
  60. option add *Tabset.bevelAmount    0            widgetDefault
  61. option add *Tabset.padX           4            widgetDefault
  62. option add *Tabset.padY           4            widgetDefault
  63. option add *Tabset.gap            overlap      widgetDefault
  64. option add *Tabset.angle          20           widgetDefault
  65. option add *Tabset.font           fixed        widgetDefault
  66. option add *Tabset.state          normal       widgetDefault
  67. option add *Tabset.disabledForeground #a3a3a3  widgetDefault
  68. option add *Tabset.foreground     black        widgetDefault
  69. option add *Tabset.background     #d9d9d9      widgetDefault
  70. option add *Tabset.selectForeground black      widgetDefault
  71. option add *Tabset.selectBackground #ececec    widgetDefault
  72.  
  73. #
  74. # Usual options.
  75. #
  76. itk::usual Tabset {
  77.     keep -backdrop -background -cursor -disabledforeground -font -foreground \
  78.      -selectbackground -selectforeground
  79. }
  80.  
  81. # ------------------------------------------------------------------
  82. #                              TABSET
  83. # ------------------------------------------------------------------
  84. class iwidgets::Tabset {
  85.     inherit itk::Widget
  86.     
  87.     constructor {args} {} 
  88.     destructor {}
  89.     
  90.     itk_option define -width width Width  0 
  91.     itk_option define -equaltabs equalTabs EqualTabs true 
  92.     itk_option define -height height Height  0
  93.     itk_option define -tabpos tabPos TabPos  s
  94.     itk_option define -raiseselect raiseSelect RaiseSelect false
  95.     itk_option define -start start Start 4
  96.     itk_option define -margin margin Margin 5
  97.     itk_option define -tabborders tabBorders TabBorders true
  98.     itk_option define -bevelamount bevelAmount BevelAmount 0
  99.     itk_option define -padx padX PadX 4
  100.     itk_option define -pady padY PadY 4
  101.     itk_option define -gap gap Gap overlap
  102.     itk_option define -angle angle Angle 20
  103.     itk_option define -font font Font fixed
  104.     itk_option define -state state State normal
  105.     itk_option define \
  106.         -disabledforeground disabledForeground DisabledForeground #a3a3a3
  107.     itk_option define -foreground foreground Foreground black
  108.     itk_option define -background background Background #d9d9d9 
  109.     itk_option define -selectforeground selectForeground Background black
  110.     itk_option define -backdrop backdrop Backdrop white 
  111.     itk_option define -selectbackground selectBackground Foreground #ececec
  112.     itk_option define -command command Command {} 
  113.     
  114.     public method configure {args} 
  115.     public method add {args} 
  116.     public method delete {args} 
  117.     public method index {index} 
  118.     public method insert {index args} 
  119.     public method prev {} 
  120.     public method next {} 
  121.     public method select {index} 
  122.     public method tabcget {index args} 
  123.     public method tabconfigure {index args} 
  124.     
  125.     protected method _selectName {tabName} 
  126.     
  127.     private method _createTab {args} 
  128.     private method _deleteTabs {fromTab toTab} 
  129.     private method _index {pathList index select} 
  130.     private method _tabConfigure {args} 
  131.     private method _relayoutTabs {} 
  132.     private method _drawBevelBorder {} 
  133.     private method _calcNextTabOffset {tabName} 
  134.     private method _tabBounds {} 
  135.     private method _recalcCanvasGeom {} 
  136.     private method _canvasReconfigure {width height} 
  137.     private method _startMove {x y} 
  138.     private method _moveTabs {x y} 
  139.     private method _endMove {x y} 
  140.     private method _configRelayout {} 
  141.     
  142.     private variable _width 0          ;# Width of the canvas in screen units
  143.     private variable _height 0         ;# Height of the canvas in screen units
  144.     private variable _selectedTop 0    ;# top edge of tab + a margin
  145.     private variable _deselectedTop 0  ;# top edge of tab + a margin&raiseamt
  146.     private variable _selectedLeft 0   ;# left edge of tab + a margin
  147.     private variable _deselectedLeft 0 ;# left edge of tab + a margin&raiseamt
  148.     private variable _tabs {}          ;# our internal list of tabs
  149.     private variable _currTab -1       ;# numerical index # of selected tab
  150.     private variable _uniqueID 0       ;# used to create unique names
  151.     private variable _cmdStr  {}       ;# holds value of itk_option(-command)
  152.     ;# do not know why I need this!
  153.     private variable _canvasWidth 0    ;# set by canvasReconfigure, is can wid
  154.     private variable _canvasHeight 0   ;# set by canvasReconfigure, is can hgt
  155.     
  156.     private variable _anchorX 0        ;# used by mouse scrolling methods
  157.     private variable _anchorY 0        ;# used by mouse scrolling methods
  158.     
  159.     private variable _margin 0         ;# -margin in screen units
  160.     private variable _start  0         ;# -start in screen units
  161.     private variable _gap overlap      ;# -gap in screen units
  162.     
  163.     private variable _relayout false   ;# flag tripped to tell whether to
  164.                                        ;# relayout tabs after the configure
  165.     private variable _skipRelayout false ;# flag that tells whether to skip
  166.                                        ;# relayouting out the tabs. used by
  167.                                        ;# _endMove.
  168. }
  169.  
  170. #
  171. # Provide a lowercase access method for the Tabset class
  172. #
  173. proc ::iwidgets::tabset {pathName args} {
  174.     uplevel ::iwidgets::Tabset $pathName $args
  175. }
  176.  
  177. # ----------------------------------------------------------------------
  178. #                              CONSTRUCTOR
  179. # ----------------------------------------------------------------------
  180. body iwidgets::Tabset::constructor {args} {
  181.     global tcl_platform
  182.  
  183.     #
  184.     # Create the canvas that holds the tabs
  185.     #
  186.     itk_component add canvas {
  187.     canvas $itk_interior.canvas -highlightthickness 0
  188.     } {
  189.     keep -cursor -width -height
  190.     }
  191.     pack $itk_component(canvas) -fill both -expand yes -anchor nw
  192.     
  193.     # ... This gives us a chance to redraw our bevel borders, etc when
  194.     # the size of our canvas changes...
  195.     bind $itk_component(canvas) <Configure> \
  196.         [code $this _canvasReconfigure %w %h]
  197.     
  198.     # ... Allow button 2 scrolling as in label widget.
  199.     if {$tcl_platform(os) != "HP-UX"} {
  200.     bind $itk_component(canvas) <2>               \
  201.         [code $this _startMove %x %y]
  202.     bind $itk_component(canvas) <B2-Motion>       \
  203.         [code $this _moveTabs %x %y]
  204.     bind $itk_component(canvas) <ButtonRelease-2> \
  205.         [code $this _endMove %x %y]
  206.     }
  207.     
  208.     # @@@ 
  209.     # @@@ Is there a better way?
  210.     # @@@
  211.     bind $itk_component(hull) <Any-Enter> "focus $itk_component(hull)"
  212.     bind $itk_component(hull) <Tab> [code $this next]
  213.     bind $itk_component(hull) <Shift-Tab> [code $this prev]
  214.     
  215.     eval itk_initialize $args
  216.     
  217.     _configRelayout 
  218.     
  219.     _recalcCanvasGeom
  220.     
  221. }
  222.  
  223. body iwidgets::Tabset::destructor {} {
  224.     foreach tab $_tabs {
  225.     itcl::delete object $tab
  226.     }
  227. }
  228.  
  229. # ----------------------------------------------------------------------
  230. #                              OPTIONS
  231. # ----------------------------------------------------------------------
  232.  
  233. # ----------------------------------------------------------------------
  234. # OPTION -width
  235. #
  236. # Sets the width explicitly for the canvas of the tabset
  237. # ----------------------------------------------------------------------
  238. configbody iwidgets::Tabset::width {
  239.     if {$itk_option(-width) != {}} {
  240.     }
  241.     set _width [winfo pixels $itk_interior $itk_option(-width)]
  242. }
  243.  
  244. # ----------------------------------------------------------------------
  245. # OPTION -equaltabs
  246. #
  247. # If set to true, causes horizontal tabs to be equal in
  248. # in width and vertical tabs to equal in height.
  249. # ----------------------------------------------------------------------
  250. configbody iwidgets::Tabset::equaltabs {
  251.     if {$itk_option(-equaltabs) != {}} {
  252.     set _relayout true
  253.     }
  254. }
  255.  
  256. # ----------------------------------------------------------------------
  257. # OPTION -height
  258. #
  259. # Sets the height explicitly for the canvas of the tabset
  260. # ----------------------------------------------------------------------
  261. configbody iwidgets::Tabset::height {
  262.     set _height [winfo pixels $itk_interior $itk_option(-height)]
  263. }
  264.  
  265. # ----------------------------------------------------------------------
  266. # OPTION -tabpos
  267. #
  268. # Sets the tab position of tabs, n, s, e, w
  269. # ----------------------------------------------------------------------
  270. configbody iwidgets::Tabset::tabpos {
  271.     if {$itk_option(-tabpos) != {}} {
  272.     switch $itk_option(-tabpos) {
  273.         n {
  274.         _tabConfigure -invert true -orient horizontal
  275.         }
  276.         s {
  277.         _tabConfigure -invert false -orient horizontal
  278.         }
  279.         w {
  280.         _tabConfigure -invert false -orient vertical
  281.         }
  282.         e {
  283.         _tabConfigure -invert true -orient vertical
  284.         }
  285.         default {
  286.         error "bad anchor position\
  287.             \"$itk_option(-tabpos)\" must be n, s, e, or w"
  288.         }
  289.     }
  290.     }
  291. }
  292.  
  293. # ----------------------------------------------------------------------
  294. # OPTION -raiseselect
  295. #
  296. # Sets whether to raise selected tabs slightly
  297. # ----------------------------------------------------------------------
  298. configbody iwidgets::Tabset::raiseselect {
  299.     if {$itk_option(-raiseselect) != {}} {
  300.     set _relayout true
  301.     }
  302. }
  303.  
  304. # ----------------------------------------------------------------------
  305. # OPTION -start
  306. #
  307. # Sets the offset to start of tab set
  308. # ----------------------------------------------------------------------
  309. configbody iwidgets::Tabset::start {
  310.     if {$itk_option(-start) != {}} {
  311.     set _start [winfo pixels $itk_interior $itk_option(-start)]
  312.     set _relayout true
  313.     } else {
  314.     set _start 4
  315.     }
  316. }
  317.  
  318. # ----------------------------------------------------------------------
  319. # OPTION -margin
  320. #
  321. # Sets the margin used above n tabs, below s tabs, left of e
  322. # tabs, right of w tabs
  323. # ----------------------------------------------------------------------
  324. configbody iwidgets::Tabset::margin {
  325.     if {$itk_option(-margin) != {}} {
  326.     set _margin [winfo pixels $itk_interior $itk_option(-margin)]
  327.     set _relayout true
  328.     } else {
  329.     set _margin 5
  330.     }
  331. }
  332.  
  333. # ----------------------------------------------------------------------
  334. # OPTION -tabborders
  335. #
  336. # Boolean that specifies whether to draw the borders of
  337. # the unselected tabs (tabs in background)
  338. # ----------------------------------------------------------------------
  339. configbody iwidgets::Tabset::tabborders {
  340.     if {$itk_option(-tabborders) != {}} {
  341.     _tabConfigure -tabborders $itk_option(-tabborders)
  342.     }
  343. }
  344.  
  345. # ----------------------------------------------------------------------
  346. # OPTION -bevelamount
  347. #
  348. # Specifies pixel size of tab corners. 0 means no corners.
  349. # ----------------------------------------------------------------------
  350. configbody iwidgets::Tabset::bevelamount {
  351.     if {$itk_option(-bevelamount) != {}} {
  352.     _tabConfigure -bevelamount $itk_option(-bevelamount)
  353.     }
  354. }
  355.  
  356. # ----------------------------------------------------------------------
  357. # OPTION -padx
  358. #
  359. # Sets the padding in each tab to the left and right of label
  360. # I don't convert for fpixels, since Tab does it for me.
  361. # ----------------------------------------------------------------------
  362. configbody iwidgets::Tabset::padx {
  363.     if {$itk_option(-padx) != {}} {
  364.     _tabConfigure -padx $itk_option(-padx)
  365.     }
  366. }
  367.  
  368. # ----------------------------------------------------------------------
  369. # OPTION -pady
  370. #
  371. # Sets the padding in each tab to the left and right of label
  372. # I don't convert for fpixels, since Tab does it for me.
  373. # ----------------------------------------------------------------------
  374. configbody iwidgets::Tabset::pady {
  375.     if {$itk_option(-pady) != {}} {
  376.     _tabConfigure -pady $itk_option(-pady)
  377.     }
  378. }
  379.  
  380. # ----------------------------------------------------------------------
  381. # OPTION -gap
  382. #
  383. # Sets the amount of spacing between tabs in pixels
  384. # ----------------------------------------------------------------------
  385. configbody iwidgets::Tabset::gap {
  386.     if {$itk_option(-gap) != {}} {
  387.     if {$itk_option(-gap) != "overlap"} {
  388.         set _gap [winfo pixels $itk_interior $itk_option(-gap)]
  389.     } else {
  390.         set _gap overlap
  391.     }
  392.     set _relayout true 
  393.     } else {
  394.     set _gap overlap
  395.     }
  396. }
  397.  
  398. # ----------------------------------------------------------------------
  399. # OPTION -angle
  400. #
  401. # Sets the angle of the tab's sides
  402. # ----------------------------------------------------------------------
  403. configbody iwidgets::Tabset::angle {
  404.     if {$itk_option(-angle) != {}} {
  405.     _tabConfigure -angle $itk_option(-angle)
  406.     }
  407. }
  408.  
  409. # ----------------------------------------------------------------------
  410. # OPTION -font
  411. #
  412. # Sets the font of the tab (SELECTED and UNSELECTED)
  413. # ----------------------------------------------------------------------
  414. configbody iwidgets::Tabset::font {
  415.     if {$itk_option(-font) != {}} {
  416.     _tabConfigure -font $itk_option(-font)
  417.     }
  418. }
  419.  
  420. # ----------------------------------------------------------------------
  421. # OPTION -state
  422. # ----------------------------------------------------------------------
  423. configbody iwidgets::Tabset::state {
  424.     if {$itk_option(-state) != {}} {
  425.     _tabConfigure -state $itk_option(-state)
  426.     }
  427. }
  428.  
  429. # ----------------------------------------------------------------------
  430. # OPTION -disabledforeground
  431. # ----------------------------------------------------------------------
  432. configbody iwidgets::Tabset::disabledforeground {
  433.     if {$itk_option(-disabledforeground) != {}} {
  434.     _tabConfigure \
  435.         -disabledforeground $itk_option(-disabledforeground)
  436.     }
  437. }
  438.  
  439. # ----------------------------------------------------------------------
  440. # OPTION -foreground
  441. #
  442. # Sets the foreground label color of UNSELECTED tabs
  443. # ----------------------------------------------------------------------
  444. configbody iwidgets::Tabset::foreground {
  445.     _tabConfigure -foreground $itk_option(-foreground)
  446. }
  447.  
  448. # ----------------------------------------------------------------------
  449. # OPTION -background
  450. #
  451. # Sets the background color of UNSELECTED tabs
  452. # ----------------------------------------------------------------------
  453. configbody iwidgets::Tabset::background {
  454.     if {$itk_option(-background) != {}} {
  455.     _tabConfigure -background $itk_option(-background)
  456.     } else {
  457.     _tabConfigure -background \
  458.         [$itk_component(canvas) cget -background]
  459.     }
  460. }
  461.  
  462. # ----------------------------------------------------------------------
  463. # OPTION -selectforeground
  464. #
  465. # Sets the foreground label color of SELECTED tabs
  466. # ----------------------------------------------------------------------
  467. configbody iwidgets::Tabset::selectforeground {
  468.     _tabConfigure -selectforeground $itk_option(-selectforeground)
  469. }
  470.  
  471. # ----------------------------------------------------------------------
  472. # OPTION -backdrop
  473. #
  474. # Sets the background color of the Tabset backdrop (behind the tabs)
  475. # ----------------------------------------------------------------------
  476. configbody iwidgets::Tabset::backdrop {
  477.     if {$itk_option(-backdrop) != {}} {
  478.     $itk_component(canvas) configure \
  479.         -background $itk_option(-backdrop)
  480.     }
  481. }
  482.  
  483. # ----------------------------------------------------------------------
  484. # OPTION -selectbackground
  485. #
  486. # Sets the background color of SELECTED tabs
  487. # ----------------------------------------------------------------------
  488. configbody iwidgets::Tabset::selectbackground {
  489.     if {$itk_option(-selectbackground) != {}} {
  490.     } else {
  491.     #set _selectBackground \
  492.         [$itk_component(canvas) cget -background]
  493.     }
  494.     _tabConfigure -selectbackground $itk_option(-selectbackground)
  495. }
  496.  
  497. # ----------------------------------------------------------------------
  498. # OPTION -command
  499. #
  500. # The command to invoke when a tab is hit.
  501. # ----------------------------------------------------------------------
  502. configbody iwidgets::Tabset::command {
  503.     if {$itk_option(-command) != {}} {
  504.     set _cmdStr $itk_option(-command)
  505.     }
  506. }
  507.  
  508. # ----------------------------------------------------------------------
  509. # METHOD: add ?option value...?
  510. #
  511. # Creates a tab and appends it to the list of tabs.
  512. # processes tabconfigure for the tab added.
  513. # ----------------------------------------------------------------------
  514. body iwidgets::Tabset::add {args} {
  515.     set tabName [eval _createTab $args]
  516.     lappend _tabs $tabName
  517.     
  518.     _relayoutTabs
  519.     
  520.     return $tabName
  521. }
  522.  
  523. # ----------------------------------------------------------------------
  524. # METHOD: configure ?option? ?value option value...?
  525. #
  526. # Acts as an addendum to the itk::Widget::configure method.
  527. #
  528. # Checks the _relayout flag to see if after configures are done
  529. # we need to relayout the tabs.
  530. #
  531. # _skipRelayout is set in the MB2 scroll methods, to avoid constant
  532. # relayout of tabs while dragging the mouse.
  533. # ----------------------------------------------------------------------
  534. body iwidgets::Tabset::configure {args} {
  535.     set result [eval itk::Archetype::configure $args]
  536.  
  537.     _configRelayout
  538.  
  539.     return $result
  540. }
  541.  
  542. body iwidgets::Tabset::_configRelayout {} {
  543.     # then relayout tabs if necessary
  544.     if { $_relayout } {
  545.     if { $_skipRelayout } {
  546.     } else {
  547.         _relayoutTabs
  548.     }
  549.     set _relayout false
  550.     }
  551. }
  552.  
  553. # ----------------------------------------------------------------------
  554. # METHOD: delete index1 ?index2?
  555. #
  556. # Deletes a tab or range of tabs from the tabset
  557. # ----------------------------------------------------------------------
  558. body iwidgets::Tabset::delete {args} {
  559.     if { $_tabs == {} } {
  560.     error "can't delete tabs,\
  561.         no tabs in the tabset named $itk_component(hull)"
  562.     }
  563.     
  564.     set len [llength $args]
  565.     switch $len {
  566.     0 {
  567.         error "wrong # args: should be\
  568.             \"$itk_component(hull) delete index1 ?index2?\""
  569.     }
  570.     
  571.     1 {
  572.         set fromTab [index [lindex $args 0]]
  573.         if { $fromTab == -1 } {
  574.         error "bad value for index1:\
  575.             [lindex $args 0] in call to delete"
  576.         }
  577.         set toTab $fromTab
  578.         _deleteTabs $fromTab $toTab
  579.     }
  580.     
  581.     2 {
  582.         set fromTab [index [lindex $args 0]]
  583.         if { $fromTab == -1 } {
  584.         error "bad value for index1:\
  585.             [lindex $args 0] in call to delete"
  586.         }
  587.         set toTab [index [lindex $args 1]]
  588.         
  589.         if { $toTab == -1 } {
  590.         error "bad value for index2:\
  591.             [lindex $args 1] in call to delete"
  592.         }
  593.         _deleteTabs $fromTab $toTab
  594.     }
  595.     
  596.     default {
  597.         error "wrong # args: should be\
  598.             \"$itk_component(hull) delete index1 ?index2?\""
  599.     }
  600.     }
  601. }
  602.  
  603. # ----------------------------------------------------------------------
  604. # METHOD: index index
  605. #
  606. # Given an index identifier returns the numeric index of the tab
  607. # ----------------------------------------------------------------------
  608. body iwidgets::Tabset::index {index} {
  609.     return [_index $_tabs $index $_currTab]
  610. }
  611.  
  612. # ----------------------------------------------------------------------
  613. # METHOD: insert index ?option value...?
  614. #
  615. # Inserts a tab before a index. The before tab may
  616. # be specified as a label or a tab position.
  617. # ----------------------------------------------------------------------
  618. body iwidgets::Tabset::insert {index args} {
  619.     if { $_tabs == {} } {
  620.     error "no tab to insert before,\
  621.         tabset '$itk_component(hull)' is empty"
  622.     }
  623.     
  624.     # get the tab
  625.     set tab [index $index]
  626.     
  627.     # catch bad value for before tab.
  628.     if { $tab < 0 || $tab >= [llength $_tabs] } {
  629.     error "bad value $tab for index:\
  630.         should be between 0 and [expr [llength $_tabs] - 1]"
  631.     }
  632.     
  633.     # create the new tab and get its name...
  634.     set tabName [eval _createTab $args]
  635.     
  636.     # grab the name of the tab currently selected. (to keep in sync)
  637.     set currTabName [lindex $_tabs $_currTab]
  638.     
  639.     # insert tabName before $tab
  640.     set _tabs [linsert $_tabs $tab $tabName]
  641.     
  642.     # keep the _currTab in sync with the insert.
  643.     set _currTab [lsearch -exact $_tabs $currTabName]
  644.     
  645.     _relayoutTabs
  646.     
  647.     return $tabName
  648. }
  649.  
  650. # ----------------------------------------------------------------------
  651. # METHOD: prev
  652. #
  653. # Selects the prev tab. Wraps at first back to last tab.
  654. # ----------------------------------------------------------------------
  655. body iwidgets::Tabset::prev {} {
  656.     if { $_tabs == {} } {
  657.     error "can't goto previous tab,\
  658.         no tabs in the tabset: $itk_component(hull)"
  659.     }
  660.     
  661.     # bump to the previous tab and wrap if necessary
  662.     set prev [expr $_currTab - 1]
  663.     if { $prev < 0 } {
  664.     set prev [expr [llength $_tabs] - 1]
  665.     }
  666.     
  667.     select $prev
  668.     
  669. }
  670.  
  671. # ----------------------------------------------------------------------
  672. # METHOD: next
  673. #
  674. # Selects the next tab. Wraps at last back to first tab.
  675. # ----------------------------------------------------------------------
  676. body iwidgets::Tabset::next {} {
  677.     if { $_tabs == {} } {
  678.     error "can't goto next tab,\
  679.         no tabs in the tabset: $itk_component(hull)"
  680.     }
  681.     
  682.     # bump to the next tab and wrap if necessary
  683.     set next [expr $_currTab + 1]
  684.     if { $next >= [llength $_tabs] } {
  685.     set next 0
  686.     }
  687.     
  688.     select $next
  689. }
  690.  
  691. # ----------------------------------------------------------------------
  692. # METHOD: select index
  693. #
  694. # Select a tab by index
  695. #
  696. # Lowers the last _currTab if it existed.
  697. # Then raises the new one if it exists.
  698. #
  699. # Returns numeric index of selection, -1 if failed.
  700. # -------------------------------------------------------------
  701. body iwidgets::Tabset::select {index} {
  702.     if { $_tabs == {} } {
  703.     error "can't activate a tab,\
  704.         no tabs in the tabset: $itk_component(hull)"
  705.     }
  706.     
  707.     # if there is not current selection just ignore trying this selection
  708.     if { $index == "select" && $_currTab == -1 } {
  709.     return -1
  710.     }
  711.     
  712.     # is selection request in range ? 
  713.     set reqTab [index $index]
  714.     if { $reqTab == -1 } {
  715.     error "bad value $index for index:\
  716.         should be from 0 to [expr [llength $_tabs] - 1]"
  717.     }
  718.     
  719.     # If already selected then ignore and return...
  720.     if { $reqTab == $_currTab } {
  721.     return $reqTab
  722.     }
  723.     
  724.     # ---- Deselect
  725.     if { $_currTab != -1 } {
  726.     set currTabName [lindex $_tabs $_currTab]
  727.     $currTabName deselect
  728.     
  729.     # handle different orientations...
  730.     if { $itk_option(-tabpos) == "n" || $itk_option(-tabpos) == "s"} {
  731.         $currTabName configure -top $_deselectedTop
  732.     } else {
  733.         $currTabName configure -left $_deselectedLeft
  734.     }
  735.     }
  736.     
  737.     # get the stacking order correct...
  738.     foreach tab $_tabs {
  739.     $tab lower
  740.     }
  741.     
  742.     # set this now so that the -command cmd can do an 'index select'
  743.     # to operate on this tab.
  744.     set _currTab $reqTab
  745.     
  746.     # ---- Select
  747.     set reqTabName [lindex $_tabs $reqTab]
  748.     $reqTabName select
  749.     if { $itk_option(-tabpos) == "n" || $itk_option(-tabpos) == "s"} {
  750.     $reqTabName configure -top $_selectedTop
  751.     } else {
  752.     $reqTabName configure -left $_selectedLeft
  753.     }
  754.     
  755.     set _currTab $reqTab
  756.     
  757.     # invoke any user command string, appended with tab index number
  758.     if { $_cmdStr != {} } {
  759.     set newCmd $_cmdStr
  760.     eval [lappend newCmd $reqTab]
  761.     }
  762.     
  763.     return $reqTab
  764. }
  765.  
  766. # ----------------------------------------------------------------------
  767. # METHOD: tabcget index ?option? 
  768. #
  769. # Returns the value for the option setting of the tab at index $index.
  770. # ----------------------------------------------------------------------
  771. body iwidgets::Tabset::tabcget {index args} {
  772.     return [lindex [eval tabconfigure $index $args] 2]
  773. }
  774.  
  775. # ----------------------------------------------------------------------
  776. # METHOD: tabconfigure index ?option? ?value option value?
  777. #
  778. # tabconfigure index : returns configuration list
  779. # tabconfigure index -option : returns option values
  780. # tabconfigure index ?option value option value ...? sets options
  781. #   and returns empty string.
  782. #
  783. # Performs configure on a given tab denoted by index.
  784. #
  785. # Index may be a tab number or a pattern matching the label
  786. # associated with a tab.
  787. # ----------------------------------------------------------------------
  788. body iwidgets::Tabset::tabconfigure {index args} {
  789.     # convert index to numeric
  790.     set tab [index $index]
  791.     
  792.     if { $tab == -1 } {
  793.     error "bad index value:\
  794.         $index for $itk_component(hull) tabconfigure"
  795.     }
  796.     
  797.     set tabName [lindex $_tabs $tab]
  798.     
  799.     set len [llength $args]
  800.     switch $len {
  801.     0 {
  802.         return [eval $tabName configure]
  803.     }
  804.     1 {
  805.         return [eval $tabName configure $args]
  806.     }
  807.     default {
  808.         eval $tabName configure $args
  809.         _relayoutTabs
  810.         select select
  811.     }
  812.     }
  813.     return ""
  814. }
  815.  
  816. # ----------------------------------------------------------------------
  817. # PROTECTED METHOD: _selectName
  818. #
  819. # internal method to allow selection by internal tab name 
  820. # rather than index. This is used by the bind methods
  821. # ----------------------------------------------------------------------
  822. body iwidgets::Tabset::_selectName {tabName} {
  823.     # if the tab is disabled, then ignore this selection...
  824.     if { [$tabName cget -state] == "disabled" } {
  825.     return
  826.     }
  827.     
  828.     set tab [lsearch -exact $_tabs $tabName]
  829.     select $tab
  830. }
  831.  
  832. # ----------------------------------------------------------------------
  833. # PRIVATE METHOD: _createTab
  834. #
  835. # Creates a tab, using unique tab naming, propagates background
  836. # and keeps unique id up to date.
  837. # ----------------------------------------------------------------------
  838. body iwidgets::Tabset::_createTab {args} {
  839.     #
  840.     # create an internal name for the tab: tab0, tab1, etc.
  841.     # these are one-up numbers they do not 
  842.     # correspond to the position the tab is located in.
  843.     #
  844.     set tabName $this-tab$_uniqueID
  845.     
  846.     switch $itk_option(-tabpos) {
  847.     n {
  848.         set invert true
  849.         set orient horizontal
  850.         set x 0
  851.         set y [expr $_margin + 1]
  852.     }
  853.     s {
  854.         set invert false
  855.         set orient horizontal
  856.         set x 0
  857.         set y 0
  858.     }
  859.     w {
  860.         set invert false
  861.         set orient vertical
  862.         set x 0 
  863.         set y 0
  864.     }
  865.     e {
  866.         set invert true
  867.         set orient vertical
  868.         set x [expr $_margin + 1]
  869.         set y 0
  870.     }
  871.     default {
  872.         error "bad anchor position\
  873.             \"$itk_option(-tabpos)\" must be n, s, e, or w"
  874.     }
  875.     }
  876.     
  877.     eval iwidgets::Tab $tabName $itk_component(canvas) \
  878.         -left             $x \
  879.         -top              $y \
  880.         -font             [list $itk_option(-font)] \
  881.         -background       $itk_option(-background) \
  882.         -foreground       $itk_option(-foreground) \
  883.         -selectforeground $itk_option(-selectforeground) \
  884.         -disabledforeground $itk_option(-disabledforeground) \
  885.         -selectbackground $itk_option(-selectbackground) \
  886.         -angle            $itk_option(-angle) \
  887.         -padx             $itk_option(-padx) \
  888.         -pady             $itk_option(-pady) \
  889.         -bevelamount      $itk_option(-bevelamount) \
  890.         -state            $itk_option(-state) \
  891.         -tabborders       $itk_option(-tabborders) \
  892.         -invert           $invert \
  893.         -orient           $orient \
  894.         $args
  895.     
  896.     $tabName lower
  897.     
  898.     $itk_component(canvas) \
  899.         bind $tabName <Button-1> [code $this _selectName $tabName]
  900.     
  901.     incr _uniqueID
  902.     
  903.     return $tabName
  904. }
  905.  
  906. # ----------------------------------------------------------------------
  907. # PRIVATE METHOD: _deleteTabs
  908. #
  909. # Deletes tabs from $fromTab to $toTab.
  910. #
  911. # Operates in two passes, destroys all the widgets
  912. # Then removes the pathName from the tab list
  913. #
  914. # Also keeps the current selection in bounds.
  915. # ----------------------------------------------------------------------
  916. body iwidgets::Tabset::_deleteTabs {fromTab toTab} {
  917.     for { set tab $fromTab } { $tab <= $toTab } { incr tab } {
  918.     set tabName [lindex $_tabs $tab]
  919.     
  920.     # unbind Button-1 from this window name
  921.     $itk_component(canvas) bind $tabName <Button-1> {}
  922.     
  923.     # Destroy the Tab class...
  924.     itcl::delete object $tabName 
  925.     }
  926.     
  927.     # physically remove the tab
  928.     set _tabs [lreplace $_tabs $fromTab $toTab]
  929.     
  930.     # If we deleted a selected tab set our selection to none
  931.     if { $_currTab >= $fromTab && $_currTab <= $toTab } {
  932.     set _currTab -1
  933.     _drawBevelBorder
  934.     }
  935.     
  936.     # make sure _currTab stays in sync with new numbering...
  937.     if { $_tabs == {} } {
  938.     # if deleted only remaining tab,
  939.     # reset current tab to undefined
  940.     set _currTab -1
  941.     
  942.     # or if the current tab was the last tab, it needs come back
  943.     } elseif { $_currTab >= [llength $_tabs] } {
  944.     incr _currTab -1
  945.     if { $_currTab < 0 } {
  946.         # but only to zero
  947.         set _currTab 0
  948.     }
  949.     }
  950.     
  951.     _relayoutTabs
  952. }
  953.  
  954. # ----------------------------------------------------------------------
  955. # PRIVATE METHOD: _index
  956. #
  957. # pathList : list of path names to search thru if index is a label
  958. # index    : either number, 'select', 'end', or pattern
  959. # select   : current selection
  960. #
  961. # _index takes takes the value $index converts it to
  962. # a numeric identifier. If the value is not already
  963. # an integer it looks it up in the $pathList array.
  964. # If it fails it returns -1
  965. # ----------------------------------------------------------------------
  966. body iwidgets::Tabset::_index {pathList index select} {
  967.     switch $index {
  968.     select {
  969.         set number $select
  970.     }
  971.     end {
  972.         set number [expr [llength $pathList] -1]
  973.     }
  974.     default {
  975.         # is it an number already?
  976.         if { [regexp {^[0-9]+$} $index] } {
  977.         set number $index
  978.         if { $number < 0 || $number >= [llength $pathList] } {
  979.             set number -1
  980.         }
  981.         
  982.         # otherwise it is a label
  983.         } else {
  984.         # look thru the pathList of pathNames and
  985.         # get each label and compare with index.
  986.         # if we get a match then set number to postion in $pathList
  987.         # and break out.
  988.         # otherwise number is still -1
  989.         set i 0
  990.         set number -1
  991.         foreach pathName $pathList {
  992.             set label [$pathName cget -label]
  993.             if { $label == $index } {
  994.             set number $i
  995.             break
  996.             }
  997.             incr i
  998.         }
  999.         }
  1000.     }
  1001.     }
  1002.     
  1003.     return $number
  1004. }
  1005.  
  1006. # ----------------------------------------------------------------------
  1007. # PRIVATE METHOD: _tabConfigure
  1008. # ----------------------------------------------------------------------
  1009. body iwidgets::Tabset::_tabConfigure {args} {
  1010.     foreach tab $_tabs {
  1011.     eval $tab configure $args
  1012.     }
  1013.     
  1014.     set _relayout true
  1015.     
  1016.     if { $_tabs != {} } {
  1017.     select select
  1018.     }
  1019. }
  1020.  
  1021. # ----------------------------------------------------------------------
  1022. # PRIVATE METHOD: _relayoutTabs
  1023. # relays out the tabs with correct spacing...
  1024. # ----------------------------------------------------------------------
  1025. body iwidgets::Tabset::_relayoutTabs {} {
  1026.     if { [llength $_tabs] == 0 } {
  1027.     return
  1028.     }
  1029.     
  1030.     # get the max width for fixed width tabs...
  1031.     set maxWidth 0
  1032.     foreach tab $_tabs {
  1033.     set width [$tab labelwidth]
  1034.     if { $width > $maxWidth } {
  1035.         set maxWidth $width
  1036.     }
  1037.     }
  1038.     
  1039.     # get the max height for fixed height tabs...
  1040.     set maxHeight 0
  1041.     foreach tab $_tabs {
  1042.     set height [$tab labelheight]
  1043.     if { $height > $maxHeight } {
  1044.         set maxHeight $height
  1045.     }
  1046.     }
  1047.     
  1048.     # get curr tab's name
  1049.     set currTabName [lindex $_tabs $_currTab]
  1050.     
  1051.     # Start with our margin offset in pixels...
  1052.     set tabStart $_start
  1053.     
  1054.     if { $itk_option(-raiseselect) } {
  1055.     set raiseAmt 2
  1056.     } else {
  1057.     set raiseAmt 0
  1058.     }
  1059.     
  1060.     #
  1061.     # Depending on the tab layout: n, s, e, or w place the tabs
  1062.     # according to orientation, raise, margins, etc.
  1063.     #
  1064.     switch $itk_option(-tabpos) {
  1065.     n {
  1066.         set _selectedTop [expr $_margin + 1]
  1067.         set _deselectedTop [expr $_selectedTop + $raiseAmt]
  1068.         
  1069.         if { $itk_option(-equaltabs) } {
  1070.         set tabWidth $maxWidth
  1071.         } else {
  1072.         set tabWidth 0
  1073.         }
  1074.         
  1075.         foreach tab $_tabs {
  1076.         if { $tab == $currTabName } {
  1077.             $tab configure -left $tabStart -top $_selectedTop \
  1078.                 -height $maxHeight -width $tabWidth -anchor c
  1079.         } else {
  1080.             $tab configure -left $tabStart -top $_deselectedTop \
  1081.                 -height $maxHeight -width $tabWidth -anchor c
  1082.         }
  1083.         set tabStart [expr $tabStart + [_calcNextTabOffset $tab]]
  1084.         }
  1085.         
  1086.     }
  1087.     s {
  1088.         set _selectedTop 0
  1089.         set _deselectedTop [expr $_selectedTop - $raiseAmt]
  1090.         
  1091.         if { $itk_option(-equaltabs) } {
  1092.         set tabWidth $maxWidth
  1093.         } else {
  1094.         set tabWidth 0
  1095.         }
  1096.         
  1097.         foreach tab $_tabs {
  1098.         if { $tab == $currTabName } {
  1099.             $tab configure -left $tabStart -top $_selectedTop \
  1100.                 -height $maxHeight -width $tabWidth -anchor c
  1101.         } else {
  1102.             $tab configure -left $tabStart -top $_deselectedTop \
  1103.                 -height $maxHeight -width $tabWidth -anchor c
  1104.         }
  1105.         set tabStart [expr $tabStart + [_calcNextTabOffset $tab]]
  1106.         }
  1107.         
  1108.     }
  1109.     w {
  1110.         set _selectedLeft [expr $_margin + 1]
  1111.         set _deselectedLeft [expr $_selectedLeft + $raiseAmt]
  1112.         
  1113.         if { $itk_option(-equaltabs) } {
  1114.         set tabHeight $maxHeight
  1115.         } else {
  1116.         set tabHeight 0
  1117.         }
  1118.         
  1119.         foreach tab $_tabs {
  1120.         # selected
  1121.         if { $tab == $currTabName } {
  1122.             $tab configure -top $tabStart -left $_selectedLeft \
  1123.                 -height $tabHeight -width $maxWidth -anchor e
  1124.             # deselected
  1125.         } else {
  1126.             $tab configure -top $tabStart -left $_deselectedLeft \
  1127.                 -height $tabHeight -width $maxWidth -anchor e
  1128.         }
  1129.         set tabStart [expr $tabStart + [_calcNextTabOffset $tab]]
  1130.         }
  1131.         
  1132.     }
  1133.     e {
  1134.         set _selectedLeft 0
  1135.         set _deselectedLeft [expr $_selectedLeft - $raiseAmt]
  1136.         
  1137.         if { $itk_option(-equaltabs) } {
  1138.         set tabHeight $maxHeight
  1139.         } else {
  1140.         set tabHeight 0
  1141.         }
  1142.         
  1143.         foreach tab $_tabs {
  1144.         # selected
  1145.         if { $tab == $currTabName } {
  1146.             $tab configure -top $tabStart -left $_selectedLeft \
  1147.                 -height $tabHeight -width $maxWidth -anchor w
  1148.             # deselected
  1149.         } else {
  1150.             $tab configure -top $tabStart -left $_deselectedLeft \
  1151.                 -height $tabHeight -width $maxWidth -anchor w
  1152.         }
  1153.         set tabStart [expr $tabStart + [_calcNextTabOffset $tab]]
  1154.         }
  1155.         
  1156.     }
  1157.     default {
  1158.         error "bad anchor position\
  1159.             \"$itk_option(-tabpos)\" must be n, s, e, or w"
  1160.     }
  1161.     }
  1162.     
  1163.     # put border on & calc our new canvas size...
  1164.     _drawBevelBorder
  1165.     _recalcCanvasGeom
  1166.     
  1167. }
  1168.  
  1169. # ----------------------------------------------------------------------
  1170. # PRIVATE METHOD: _drawBevelBorder
  1171. # draws the bevel border along tab edge (below selected tab)
  1172. # ----------------------------------------------------------------------
  1173. body iwidgets::Tabset::_drawBevelBorder {} {
  1174.     $itk_component(canvas) delete bevelBorder
  1175.     
  1176.     switch $itk_option(-tabpos) {
  1177.     n {
  1178.         $itk_component(canvas) create line \
  1179.             0 [expr $_canvasHeight - 1] \
  1180.             $_canvasWidth [expr $_canvasHeight - 1] \
  1181.             -fill [iwidgets::colors::topShadow $itk_option(-selectbackground)] \
  1182.             -tags bevelBorder
  1183.         $itk_component(canvas) create line \
  1184.             0 $_canvasHeight \
  1185.             $_canvasWidth $_canvasHeight \
  1186.             -fill [iwidgets::colors::topShadow $itk_option(-selectbackground)] \
  1187.             -tags bevelBorder
  1188.     }
  1189.     s {
  1190.         $itk_component(canvas) create line \
  1191.             0 0 \
  1192.             $_canvasWidth 0 \
  1193.             -fill [iwidgets::colors::bottomShadow $itk_option(-selectbackground)] \
  1194.             -tags bevelBorder
  1195.         $itk_component(canvas) create line \
  1196.             0 1 \
  1197.             $_canvasWidth 1 \
  1198.             -fill black \
  1199.             -tags bevelBorder
  1200.     }
  1201.     w {
  1202.         $itk_component(canvas) create line \
  1203.             $_canvasWidth 0 \
  1204.             $_canvasWidth [expr $_canvasHeight - 1] \
  1205.             -fill [iwidgets::colors::topShadow $itk_option(-selectbackground)] \
  1206.             -tags bevelBorder
  1207.         $itk_component(canvas) create line \
  1208.             [expr $_canvasWidth - 1] 0 \
  1209.             [expr $_canvasWidth - 1] [expr $_canvasHeight - 1] \
  1210.             -fill [iwidgets::colors::topShadow $itk_option(-selectbackground)] \
  1211.             -tags bevelBorder
  1212.         
  1213.     }
  1214.     e {
  1215.         $itk_component(canvas) create line \
  1216.             0 0 \
  1217.             0 [expr $_canvasHeight - 1] \
  1218.             -fill black \
  1219.             -tags bevelBorder
  1220.         $itk_component(canvas) create line \
  1221.             1 0 \
  1222.             1 [expr $_canvasHeight - 1] \
  1223.             -fill [iwidgets::colors::bottomShadow $itk_option(-selectbackground)] \
  1224.             -tags bevelBorder
  1225.         
  1226.     }
  1227.     }
  1228.     
  1229.     $itk_component(canvas) raise bevelBorder
  1230.     if { $_currTab != -1 } {
  1231.     set currTabName [lindex $_tabs $_currTab]
  1232.     $currTabName raise
  1233.     }
  1234. }
  1235.  
  1236. # ----------------------------------------------------------------------
  1237. # PRIVATE METHOD: _calcNextTabOffset
  1238. # given $tabName, determines the offset in pixels to place
  1239. # the next tab's start edge at.
  1240. # ----------------------------------------------------------------------
  1241. body iwidgets::Tabset::_calcNextTabOffset {tabName} {
  1242.     if { $_gap == "overlap" } {
  1243.     return [$tabName offset]
  1244.     } else {
  1245.     return [expr [$tabName majordim] + $_gap]
  1246.     }
  1247. }
  1248.  
  1249. # ----------------------------------------------------------------------
  1250. # PRIVATE METHOD: _tabBounds
  1251. # calculates the bounding box that will completely enclose 
  1252. # all the tabs.
  1253. # ----------------------------------------------------------------------
  1254. body iwidgets::Tabset::_tabBounds {} {
  1255.     set bbox { 100000 100000 -10000 -10000 }
  1256.     foreach tab $_tabs {
  1257.     set tabBBox [$tab bbox]
  1258.     # if this left is less use it
  1259.     if { [lindex $tabBBox 0] < [lindex $bbox 0] } {
  1260.         set bbox [lreplace $bbox 0 0 [lindex $tabBBox 0]]
  1261.     }
  1262.     # if this top is greater use it
  1263.     if { [lindex $tabBBox 1] < [lindex $bbox 1] } {
  1264.         set bbox [lreplace $bbox 1 1 [lindex $tabBBox 1]]
  1265.     }
  1266.     # if this right is less use it
  1267.     if { [lindex $tabBBox 2] > [lindex $bbox 2] } {
  1268.         set bbox [lreplace $bbox 2 2 [lindex $tabBBox 2]]
  1269.     }
  1270.     # if this bottom is greater use it
  1271.     if { [lindex $tabBBox 3] > [lindex $bbox 3] } {
  1272.         set bbox [lreplace $bbox 3 3 [lindex $tabBBox 3]]
  1273.     }
  1274.     
  1275.     }
  1276.     return $bbox
  1277. }
  1278.  
  1279. # ----------------------------------------------------------------------
  1280. # PRIVATE METHOD: _recalcCanvasGeom
  1281. # Based on size of tabs, recalculates the canvas geometry that
  1282. # will hold the tabs.
  1283. # ----------------------------------------------------------------------
  1284. body iwidgets::Tabset::_recalcCanvasGeom {} {
  1285.     if { [llength $_tabs] == 0 } {
  1286.     return
  1287.     }
  1288.     
  1289.     set bbox [_tabBounds]
  1290.     
  1291.     set width [lindex [_tabBounds] 2]
  1292.     set height [lindex [_tabBounds] 3]
  1293.     
  1294.     # now we have the dimensions of all the tabs in the canvas.
  1295.     
  1296.     
  1297.     switch $itk_option(-tabpos) {
  1298.     n {
  1299.         # height already includes margin
  1300.         $itk_component(canvas) configure \
  1301.             -width $width \
  1302.             -height $height
  1303.     }
  1304.     s {
  1305.         $itk_component(canvas) configure \
  1306.             -width $width \
  1307.             -height [expr $height + $_margin]
  1308.     }
  1309.     w {
  1310.         # width already includes margin
  1311.         $itk_component(canvas) configure \
  1312.             -width $width \
  1313.             -height [expr $height + 1]
  1314.     }
  1315.     e {
  1316.         $itk_component(canvas) configure \
  1317.             -width [expr $width + $_margin] \
  1318.             -height [expr $height + 1]
  1319.     }
  1320.     default {
  1321.     }
  1322.     }
  1323. }
  1324.  
  1325. # ----------------------------------------------------------------------
  1326. # PRIVATE METHOD: _canvasReconfigure
  1327. # Bound to the reconfigure notify event of a canvas, this 
  1328. # method resets canvas's correct width (since we are fill x)
  1329. # and redraws the beveled edge border.
  1330. # will hold the tabs.
  1331. # ----------------------------------------------------------------------
  1332. body iwidgets::Tabset::_canvasReconfigure {width height} {
  1333.     set _canvasWidth $width
  1334.     set _canvasHeight $height
  1335.     
  1336.     if { [llength $_tabs] > 0 } {
  1337.     _drawBevelBorder
  1338.     }
  1339. }
  1340.  
  1341. # ----------------------------------------------------------------------
  1342. # PRIVATE METHOD: _startMove
  1343. # This method is bound to the MB2 down in the canvas area of the
  1344. # tab set. This starts animated scrolling of the tabs along their
  1345. # major axis.
  1346. # ----------------------------------------------------------------------
  1347. body iwidgets::Tabset::_startMove {x y} {
  1348.     if { $itk_option(-tabpos) == "n" || $itk_option(-tabpos) == "s" } {
  1349.     set _anchorX $x
  1350.     } else {
  1351.     set _anchorY $y
  1352.     }
  1353. }
  1354.  
  1355. # ----------------------------------------------------------------------
  1356. # PRIVATE METHOD: _moveTabs
  1357. # This method is bound to the MB2 motion in the canvas area of the
  1358. # tab set. This causes the tabset to move with the mouse.
  1359. # ----------------------------------------------------------------------
  1360. body iwidgets::Tabset::_moveTabs {x y} {
  1361.     if { $itk_option(-tabpos) == "n" || $itk_option(-tabpos) == "s" } {
  1362.     set startX [expr $_start + $x - $_anchorX]
  1363.     foreach tab $_tabs {
  1364.         $tab configure -left $startX 
  1365.         set startX [expr $startX + [_calcNextTabOffset $tab]]
  1366.     }
  1367.     } else {
  1368.     set startY [expr $_start + $y - $_anchorY]
  1369.     foreach tab $_tabs {
  1370.         $tab configure -top $startY 
  1371.         set startY [expr $startY + [_calcNextTabOffset $tab]]
  1372.     }
  1373.     }
  1374. }
  1375.  
  1376. # ----------------------------------------------------------------------
  1377. # PRIVATE METHOD: _endMove
  1378. # This method is bound to the MB2 release in the canvas area of the
  1379. # tab set. This causes the tabset to end moving tabs.
  1380. # ----------------------------------------------------------------------
  1381. body iwidgets::Tabset::_endMove {x y} {
  1382.     if { $itk_option(-tabpos) == "n" || $itk_option(-tabpos) == "s" } {
  1383.     set startX [expr $_start + $x - $_anchorX]
  1384.     set _skipRelayout true
  1385.     configure -start $startX
  1386.     set _skipRelayout false
  1387.     } else {
  1388.     set startY [expr $_start + $y - $_anchorY]
  1389.     set _skipRelayout true
  1390.     configure -start $startY
  1391.     set _skipRelayout false
  1392.     }
  1393. }
  1394.  
  1395.  
  1396. #==============================================================
  1397. # CLASS: Tab
  1398. #==============================================================
  1399.  
  1400. class iwidgets::Tab {
  1401.     constructor {args} {}
  1402.     
  1403.     destructor {}
  1404.     
  1405.     public variable bevelamount 0 {}
  1406.     public variable state normal {}
  1407.     public variable height 0 {}
  1408.     public variable width 0 {}
  1409.     public variable anchor c {}
  1410.     public variable left 0 {}
  1411.     public variable top 0 {}
  1412.     public variable image {} {}
  1413.     public variable bitmap {} {}
  1414.     public variable label {} {}
  1415.     public variable padx 4 {}
  1416.     public variable pady 4 {}
  1417.     public variable selectbackground "gray70" {}
  1418.     public variable selectforeground "black" {}
  1419.     public variable disabledforeground "gray" {}
  1420.     public variable background "white" {}
  1421.     public variable foreground "black" {}
  1422.     public variable orient vertical {}
  1423.     public variable invert false {}
  1424.     public variable angle 20 {}
  1425.     public variable font \
  1426.        "-adobe-helvetica-bold-r-normal--34-240-100-100-p-182-iso8859-1" {}
  1427.     public variable tabborders true {}
  1428.     
  1429.     public method configure {args} 
  1430.     public method bbox  {} 
  1431.     public method deselect {} 
  1432.     public method lower {} 
  1433.     public method majordim  {} 
  1434.     public method minordim  {} 
  1435.     public method offset  {} 
  1436.     public method raise {} 
  1437.     public method select {}
  1438.     public method labelheight {}
  1439.     public method labelwidth {} 
  1440.     
  1441.     private method _makeTab {} 
  1442.     private method _createLabel {canvas tagList} 
  1443.     private method _makeEastTab {canvas} 
  1444.     private method _makeWestTab {canvas} 
  1445.     private method _makeNorthTab {canvas}
  1446.     private method _makeSouthTab {canvas}
  1447.     private method _calcLabelDim {labelItem}
  1448.     private method _itk_config  {args} @itcl-builtin-configure 
  1449.     private method _selectNoRaise {}
  1450.     private method _deselectNoLower {}
  1451.     
  1452.     private variable   _selected false
  1453.     private variable   _padX 0
  1454.     private variable   _padY 0
  1455.     
  1456.     private variable   _canvas
  1457.     
  1458.     # these are in pixels
  1459.     private variable   _left 0
  1460.     private variable   _width 0
  1461.     private variable   _height 0
  1462.     private variable   _oldLeft 0
  1463.     private variable   _top 0
  1464.     private variable   _oldTop 0
  1465.     
  1466.     private variable   _right
  1467.     private variable   _bottom
  1468.     
  1469.     private variable   _offset
  1470.     private variable   _majorDim
  1471.     private variable   _minorDim
  1472.     
  1473.     private variable   _darkShadow
  1474.     private variable   _lightShadow
  1475.     
  1476.     # 
  1477.     # graphic components that make up a tab
  1478.     #
  1479.     private variable   _gRegion
  1480.     private variable   _gLabel
  1481.     private variable   _gLightOutline {}
  1482.     private variable   _gBlackOutline {}
  1483.     private variable   _gTopLine
  1484.     private variable   _gTopLineShadow
  1485.     private variable   _gLightShadow
  1486.     private variable   _gDarkShadow
  1487.     
  1488.     private variable   _labelWidth 0
  1489.     private variable   _labelHeight 0
  1490.     
  1491.     private variable   _labelXOrigin 0
  1492.     private variable   _labelYOrigin 0
  1493.     
  1494.     private variable   _just left
  1495.     
  1496.     private variable   _configTripped true
  1497.     
  1498.     common _tan
  1499.     
  1500.     set _tan(0)  0.0
  1501.     set _tan(1)  0.0175
  1502.     set _tan(2)  0.0349
  1503.     set _tan(3)  0.0524
  1504.     set _tan(4)  0.0699
  1505.     set _tan(5)  0.0875
  1506.     set _tan(6)  0.1051
  1507.     set _tan(7)  0.1228
  1508.     set _tan(8)  0.1405
  1509.     set _tan(9)  0.1584
  1510.     set _tan(10) 0.1763
  1511.     set _tan(11) 0.1944
  1512.     set _tan(12) 0.2126
  1513.     set _tan(13) 0.2309
  1514.     set _tan(14) 0.2493
  1515.     set _tan(15) 0.2679
  1516.     set _tan(16) 0.2867
  1517.     set _tan(17) 0.3057
  1518.     set _tan(18) 0.3249
  1519.     set _tan(19) 0.3443
  1520.     set _tan(20) 0.3640
  1521.     set _tan(21) 0.3839
  1522.     set _tan(22) 0.4040
  1523.     set _tan(23) 0.4245
  1524.     set _tan(24) 0.4452
  1525.     set _tan(25) 0.4663
  1526.     set _tan(26) 0.4877
  1527.     set _tan(27) 0.5095
  1528.     set _tan(28) 0.5317
  1529.     set _tan(29) 0.5543
  1530.     set _tan(30) 0.5774
  1531.     set _tan(31) 0.6009
  1532.     set _tan(32) 0.6294
  1533.     set _tan(33) 0.6494
  1534.     set _tan(34) 0.6745
  1535.     set _tan(35) 0.7002
  1536.     set _tan(36) 0.7265
  1537.     set _tan(37) 0.7536
  1538.     set _tan(38) 0.7813
  1539.     set _tan(39) 0.8098
  1540.     set _tan(40) 0.8391
  1541.     set _tan(41) 0.8693
  1542.     set _tan(42) 0.9004
  1543.     set _tan(43) 0.9325
  1544.     set _tan(44) 0.9657
  1545.     set _tan(45) 1.0
  1546. }
  1547.  
  1548. # ----------------------------------------------------------------------
  1549. #                              CONSTRUCTOR
  1550. # ----------------------------------------------------------------------
  1551. body iwidgets::Tab::constructor {args} {
  1552.     
  1553.     set _canvas [lindex $args 0]
  1554.     set args [lrange $args 1 [llength $args]]
  1555.     
  1556.     set _darkShadow  [iwidgets::colors::bottomShadow $selectbackground]
  1557.     set _lightShadow [iwidgets::colors::topShadow $selectbackground]
  1558.     
  1559.     if { $args != "" } {
  1560.     eval configure $args
  1561.     }
  1562. }
  1563.  
  1564. # ----------------------------------------------------------------------
  1565. #                              DESTRUCTOR
  1566. # ----------------------------------------------------------------------
  1567. body iwidgets::Tab::destructor {} {
  1568.     if { [winfo exists $_canvas] } {
  1569.     $_canvas delete $this
  1570.     }
  1571. }
  1572.  
  1573. # ----------------------------------------------------------------------
  1574. #                              OPTIONS
  1575. # ----------------------------------------------------------------------
  1576. #
  1577. # Note, we trip _configTripped for every option that requires the tab
  1578. # to be remade.
  1579. #
  1580. # ----------------------------------------------------------------------
  1581. # OPTION -bevelamount
  1582. #
  1583. # Specifies the size of tab corners. A value of 0 with angle set 
  1584. # to 0 results in square tabs. A bevelAmount of 4, means that the 
  1585. # tab will be drawn with angled corners that cut in 4 pixels from 
  1586. # the edge of the tab. The default is 0.
  1587. # ----------------------------------------------------------------------
  1588. configbody iwidgets::Tab::bevelamount { 
  1589. }
  1590.  
  1591. # ----------------------------------------------------------------------
  1592. # OPTION -state
  1593. #
  1594. # sets the active state of the tab. specifying normal allows 
  1595. # the tab to be selectable. Specifying disabled disables the tab, 
  1596. # causing its image, bitmap, or label to be drawn with the 
  1597. # disabledForeground color.
  1598. # ----------------------------------------------------------------------
  1599. configbody iwidgets::Tab::state { 
  1600. }
  1601.  
  1602. # ----------------------------------------------------------------------
  1603. # OPTION -height
  1604. #
  1605. # the height of the tab. if 0, uses the font label height.
  1606. # ----------------------------------------------------------------------
  1607. configbody iwidgets::Tab::height {
  1608.     set _height [winfo pixels $_canvas $height]
  1609.     set _configTripped true
  1610. }
  1611.  
  1612. # ----------------------------------------------------------------------
  1613. # OPTION -width
  1614. #
  1615. # The width of the tab. If 0, uses the font label width.
  1616. # ----------------------------------------------------------------------
  1617. configbody iwidgets::Tab::width {
  1618.     set _width [winfo pixels $_canvas $width]
  1619.     set _configTripped true
  1620. }
  1621.  
  1622. # ----------------------------------------------------------------------
  1623. # OPTION -anchor
  1624. #
  1625. # Where the text in the tab will be anchored: n,nw,ne,s,sw,se,e,w,center
  1626. # ----------------------------------------------------------------------
  1627. configbody iwidgets::Tab::anchor { 
  1628. }
  1629.  
  1630. # ----------------------------------------------------------------------
  1631. # OPTION -left
  1632. #
  1633. # Specifies the left edge of the tab's bounding box. This value 
  1634. # may have any of the forms acceptable to Tk_GetPixels.
  1635. # ----------------------------------------------------------------------
  1636. configbody iwidgets::Tab::left {
  1637.     
  1638.     # get into pixels
  1639.     set _left [winfo pixels $_canvas $left]
  1640.     
  1641.     # move by offset from last setting
  1642.     $_canvas move $this [expr $_left - $_oldLeft] 0
  1643.     
  1644.     # update old for next time
  1645.     set _oldLeft $_left
  1646. }
  1647.  
  1648. # ----------------------------------------------------------------------
  1649. # OPTION -top
  1650. #
  1651. # Specifies the topedge of the tab's bounding box. This value may 
  1652. # have any of the forms acceptable to Tk_GetPixels.
  1653. # ----------------------------------------------------------------------
  1654. configbody iwidgets::Tab::top {
  1655.     
  1656.     # get into pixels
  1657.     set _top [winfo pixels $_canvas $top]
  1658.     
  1659.     # move by offset from last setting
  1660.     $_canvas move $this 0 [expr $_top - $_oldTop]
  1661.     
  1662.     # update old for next time
  1663.     set _oldTop $_top
  1664. }
  1665.  
  1666. # ----------------------------------------------------------------------
  1667. # OPTION -image
  1668. #
  1669. # Specifies the imageto display in the tab. 
  1670. # Images are created with the image create command. 
  1671. # ----------------------------------------------------------------------
  1672. configbody iwidgets::Tab::image { 
  1673.     set _configTripped true
  1674. }
  1675.  
  1676. # ----------------------------------------------------------------------
  1677. # OPTION -bitmap
  1678. #
  1679. # If bitmap is an empty string, specifies the bitmap to display in 
  1680. # the tab. Bitmap may be of any of the forms accepted by Tk_GetBitmap. 
  1681. # ----------------------------------------------------------------------
  1682. configbody iwidgets::Tab::bitmap { 
  1683.     set _configTripped true
  1684. }
  1685.  
  1686. # ----------------------------------------------------------------------
  1687. # OPTION -label
  1688. #
  1689. # If image is an empty string and bitmap is an empty string, 
  1690. # it specifies a text string to be placed in the tab's label. 
  1691. # This label serves as an additional identifier used to reference 
  1692. # the tab. Label may be used for the index value in widget commands.
  1693. # ----------------------------------------------------------------------
  1694. configbody iwidgets::Tab::label { 
  1695.     set _configTripped true
  1696. }
  1697.  
  1698. # ----------------------------------------------------------------------
  1699. # OPTION -padx
  1700. #
  1701. # Horizontal padding around the label (text, image, or bitmap).
  1702. # ----------------------------------------------------------------------
  1703. configbody iwidgets::Tab::padx {
  1704.     set _configTripped true
  1705.     set _padX [winfo pixels $_canvas $padx]
  1706. }
  1707.  
  1708. # ----------------------------------------------------------------------
  1709. # OPTION -pady
  1710. #
  1711. # Vertical padding around the label (text, image, or bitmap).
  1712. # ----------------------------------------------------------------------
  1713. configbody iwidgets::Tab::pady {
  1714.     set _configTripped true
  1715.     set _padY [winfo pixels $_canvas $pady]
  1716. }
  1717.  
  1718. # ----------------------------------------------------------------------
  1719. # OPTION -selectbackground
  1720. # ----------------------------------------------------------------------
  1721. configbody iwidgets::Tab::selectbackground {
  1722.     set _darkShadow  [iwidgets::colors::bottomShadow $selectbackground]
  1723.     set _lightShadow [iwidgets::colors::topShadow $selectbackground]
  1724.     
  1725.     if { $_selected } {
  1726.     _selectNoRaise
  1727.     } else {
  1728.     _deselectNoLower
  1729.     }
  1730. }
  1731.  
  1732. # ----------------------------------------------------------------------
  1733. # OPTION -selectforeground
  1734. #
  1735. # Foreground of tab when selected
  1736. # ----------------------------------------------------------------------
  1737. configbody iwidgets::Tab::selectforeground { 
  1738.     if { $_selected } {
  1739.     _selectNoRaise
  1740.     } else {
  1741.     _deselectNoLower
  1742.     }
  1743. }
  1744.  
  1745. # ----------------------------------------------------------------------
  1746. # OPTION -disabledforeground
  1747. #
  1748. # Background of tab when -state is disabled
  1749. # ----------------------------------------------------------------------
  1750. configbody iwidgets::Tab::disabledforeground { 
  1751.     if { $_selected } {
  1752.     _selectNoRaise
  1753.     } else {
  1754.     _deselectNoLower
  1755.     }
  1756. }
  1757.  
  1758. # ----------------------------------------------------------------------
  1759. # OPTION -background
  1760. #
  1761. # Normal background of tab.
  1762. # ----------------------------------------------------------------------
  1763. configbody iwidgets::Tab::background { 
  1764.     
  1765.     if { $_selected } {
  1766.     _selectNoRaise
  1767.     } else {
  1768.     _deselectNoLower
  1769.     }
  1770.     
  1771. }
  1772.  
  1773. # ----------------------------------------------------------------------
  1774. # OPTION -foreground
  1775. #
  1776. # Foreground of tabs when in normal unselected state
  1777. # ----------------------------------------------------------------------
  1778. configbody iwidgets::Tab::foreground { 
  1779.     if { $_selected } {
  1780.     _selectNoRaise
  1781.     } else {
  1782.     _deselectNoLower
  1783.     }
  1784. }
  1785.  
  1786. # ----------------------------------------------------------------------
  1787. # OPTION -orient
  1788. #
  1789. # Specifies the orientation of the tab. Orient can be either 
  1790. # horizontal or vertical. 
  1791. # ----------------------------------------------------------------------
  1792. configbody iwidgets::Tab::orient { 
  1793.     set _configTripped true
  1794. }
  1795.  
  1796. # ----------------------------------------------------------------------
  1797. # OPTION -invert
  1798. #
  1799. # Specifies the direction to draw the tab. If invert is true, 
  1800. # it draws horizontal tabs upside down and vertical tabs opening 
  1801. # to the left (pointing right). The value may have any of the 
  1802. # forms accepted by the Tcl_GetBoolean, such as true, 
  1803. # false, 0, 1, yes, or no.
  1804. # ----------------------------------------------------------------------
  1805. configbody iwidgets::Tab::invert { 
  1806.     set _configTripped true
  1807. }
  1808.  
  1809. # ----------------------------------------------------------------------
  1810. # OPTION -angle
  1811. #
  1812. # Specifes the angle of slope from the inner edge to the outer edge 
  1813. # of the tab. An angle of 0 specifies square tabs. Valid ranges are 
  1814. # 0 to 45 degrees inclusive. Default is 15 degrees. If this option 
  1815. # is specified as an empty string (the default), then the angle 
  1816. # option for the overall Tabset is used.
  1817. # ----------------------------------------------------------------------
  1818. configbody iwidgets::Tab::angle {
  1819.     if {$angle < 0 || $angle > 45 } {
  1820.     error "bad angle: must be between 0 and 45"
  1821.     }
  1822.     set _configTripped true
  1823. }
  1824.  
  1825. # ----------------------------------------------------------------------
  1826. # OPTION -font
  1827. #
  1828. # Font for tab text.
  1829. # ----------------------------------------------------------------------
  1830. configbody iwidgets::Tab::font { 
  1831. }
  1832.  
  1833.  
  1834. # ----------------------------------------------------------------------
  1835. # OPTION -tabborders
  1836. #
  1837. # Specifies whether to draw the borders of a deselected tab. 
  1838. # Specifying true (the default) draws these borders, 
  1839. # specifying false disables this drawing. If the tab is in 
  1840. # its selected state this option has no effect. 
  1841. # The value may have any of the forms accepted by the 
  1842. # Tcl_GetBoolean, such as true, false, 0, 1, yes, or no.
  1843. # ----------------------------------------------------------------------
  1844. configbody iwidgets::Tab::tabborders { 
  1845.     set _configTripped true
  1846. }
  1847.  
  1848. # ----------------------------------------------------------------------
  1849. # METHOD: configure ?option value?
  1850. #
  1851. # Configures the Tab, checks a configTripped flag to see if the tab
  1852. # needs to be remade. We take the easy way since it is so inexpensive
  1853. # to delete canvas items and remake them.
  1854. # ----------------------------------------------------------------------
  1855. body iwidgets::Tab::configure {args} {
  1856.     set len [llength $args]
  1857.     
  1858.     switch $len {
  1859.     0 {
  1860.         set result [_itk_config]
  1861.         return $result
  1862.     }
  1863.     1 {
  1864.         set result [eval _itk_config $args]
  1865.         return $result
  1866.     }
  1867.     default {
  1868.         eval _itk_config $args
  1869.         if { $_configTripped } {
  1870.         _makeTab 
  1871.         set _configTripped false
  1872.         }
  1873.         return ""
  1874.     }
  1875.     }
  1876. }
  1877.  
  1878. # ----------------------------------------------------------------------
  1879. # METHOD: bbox
  1880. #
  1881. # Returns the bounding box of the tab
  1882. # ----------------------------------------------------------------------
  1883. body iwidgets::Tab::bbox {} {
  1884.     return [lappend bbox $_left $_top $_right $_bottom]
  1885. }
  1886. # ----------------------------------------------------------------------
  1887. # METHOD: deselect
  1888. #
  1889. # Causes the given tab to be drawn as deselected and lowered
  1890. # ----------------------------------------------------------------------
  1891. body iwidgets::Tab::deselect {} {
  1892.     global tcl_platform
  1893.     $_canvas lower $this
  1894.  
  1895.     if {$tcl_platform(os) == "HP-UX"} {
  1896.     update idletasks
  1897.     }
  1898.  
  1899.     _deselectNoLower
  1900. }
  1901.  
  1902. # ----------------------------------------------------------------------
  1903. # METHOD: lower
  1904. #
  1905. # Lowers the tab below all others in the canvas.
  1906. #
  1907. # This is used as our tag name on the canvas.
  1908. # ----------------------------------------------------------------------
  1909. body iwidgets::Tab::lower {} {
  1910.     $_canvas lower $this
  1911. }
  1912.  
  1913. # ----------------------------------------------------------------------
  1914. # METHOD: majordim
  1915. #
  1916. # Returns the width for horizontal tabs and the height for
  1917. # vertical tabs.
  1918. # ----------------------------------------------------------------------
  1919. body iwidgets::Tab::majordim {} {
  1920.     return $_majorDim  
  1921. }
  1922.  
  1923. # ----------------------------------------------------------------------
  1924. # METHOD: minordim
  1925. #
  1926. # Returns the height for horizontal tabs and the width for
  1927. # vertical tabs.
  1928. # ----------------------------------------------------------------------
  1929. body iwidgets::Tab::minordim {} {
  1930.     return $_minorDim  
  1931. }
  1932.  
  1933. # ----------------------------------------------------------------------
  1934. # METHOD: offset
  1935. #
  1936. # Returns the width less the angle offset. This allows a 
  1937. # geometry manager to ask where to place a sibling tab.
  1938. # ----------------------------------------------------------------------
  1939. body iwidgets::Tab::offset {} {
  1940.     return $_offset  
  1941. }
  1942.  
  1943. # ----------------------------------------------------------------------
  1944. # METHOD: raise
  1945. #
  1946. # Raises the tab above all others in the canvas.
  1947. #
  1948. # This is used as our tag name on the canvas.
  1949. # ----------------------------------------------------------------------
  1950. body iwidgets::Tab::raise {} {
  1951.     $_canvas raise $this
  1952. }
  1953.  
  1954. # ----------------------------------------------------------------------
  1955. # METHOD: select
  1956. #
  1957. # Causes the given tab to be drawn as selected. 3d shadows are
  1958. # turned on and top line and top line shadow are drawn in sel
  1959. # bg color to hide them.
  1960. # ----------------------------------------------------------------------
  1961. body iwidgets::Tab::select {} {
  1962.     global tcl_platform
  1963.     $_canvas raise $this
  1964.  
  1965.     if {$tcl_platform(os) == "HP-UX"} {
  1966.     update idletasks
  1967.     }
  1968.  
  1969.     _selectNoRaise
  1970. }
  1971.  
  1972. # ----------------------------------------------------------------------
  1973. # METHOD: labelheight
  1974. #
  1975. # Returns the height of the tab's label in its current font.
  1976. # ----------------------------------------------------------------------
  1977. body iwidgets::Tab::labelheight {} {
  1978.     if {$_gLabel != 0} {
  1979.     set labelBBox [$_canvas bbox $_gLabel]
  1980.     set labelHeight [expr [lindex $labelBBox 3] - [lindex $labelBBox 1]]
  1981.     } else {
  1982.     set labelHeight 0
  1983.     }
  1984.     return $labelHeight
  1985. }
  1986.  
  1987. # ----------------------------------------------------------------------
  1988. # METHOD: labelwidth
  1989. #
  1990. # Returns the width of the tab's label in its current font.
  1991. # ----------------------------------------------------------------------
  1992. body iwidgets::Tab::labelwidth {} {
  1993.     if {$_gLabel != 0} {
  1994.     set labelBBox [$_canvas bbox $_gLabel]
  1995.     set labelWidth [expr [lindex $labelBBox 2] - [lindex $labelBBox 0]]
  1996.     } else {
  1997.     set labelWidth 0
  1998.     }
  1999.     return $labelWidth
  2000. }
  2001.  
  2002. # ----------------------------------------------------------------------
  2003. # PRIVATE METHOD: _selectNoRaise
  2004. #
  2005. # Draws tab as selected without raising it.
  2006. # ----------------------------------------------------------------------
  2007. body iwidgets::Tab::_selectNoRaise {} {
  2008.     if { ! [info exists _gRegion] } {
  2009.     return
  2010.     }
  2011.     
  2012.     $_canvas itemconfigure $_gRegion -fill $selectbackground
  2013.     $_canvas itemconfigure $_gTopLine -fill $selectbackground
  2014.     $_canvas itemconfigure $_gTopLineShadow -fill $selectbackground
  2015.     $_canvas itemconfigure $_gLightShadow -fill $_lightShadow
  2016.     $_canvas itemconfigure $_gDarkShadow -fill $_darkShadow
  2017.     
  2018.     if { $_gLightOutline != {} } {
  2019.     $_canvas itemconfigure $_gLightOutline -fill $_lightShadow
  2020.     }
  2021.     if { $_gBlackOutline != {} } {
  2022.     $_canvas itemconfigure $_gBlackOutline -fill black
  2023.     }
  2024.     
  2025.     if { $state == "normal" } {
  2026.     if { $image != {}} {
  2027.         # do nothing for now
  2028.     } elseif { $bitmap != {}} {
  2029.         $_canvas itemconfigure $_gLabel \
  2030.             -foreground $selectforeground \
  2031.             -background $selectbackground 
  2032.     } else {
  2033.         $_canvas itemconfigure $_gLabel -fill $selectforeground
  2034.     }
  2035.     } else {
  2036.     if { $image != {}} {
  2037.         # do nothing for now
  2038.     } elseif { $bitmap != {}} {
  2039.         $_canvas itemconfigure $_gLabel \
  2040.             -foreground $disabledforeground \
  2041.             -background $selectbackground 
  2042.     } else {
  2043.         $_canvas itemconfigure $_gLabel -fill $disabledforeground
  2044.     }
  2045.     }
  2046.     
  2047.     set _selected true
  2048. }
  2049.  
  2050. # ----------------------------------------------------------------------
  2051. # PRIVATE METHOD: _deselectNoLower
  2052. #
  2053. # Causes the given tab to be drawn as deselected. 3d shadows are
  2054. # removed and top line and top line shadow are drawn in visible
  2055. # colors to reveal them.
  2056. # ----------------------------------------------------------------------
  2057. body iwidgets::Tab::_deselectNoLower {} {
  2058.     if { ! [info exists _gRegion] } {
  2059.     return
  2060.     }
  2061.     
  2062.     $_canvas itemconfigure $_gRegion -fill $background
  2063.     $_canvas itemconfigure $_gTopLine -fill black
  2064.     $_canvas itemconfigure $_gTopLineShadow -fill $_darkShadow
  2065.     $_canvas itemconfigure $_gLightShadow -fill $background
  2066.     $_canvas itemconfigure $_gDarkShadow -fill $background
  2067.     
  2068.     if { $tabborders } {
  2069.     if { $_gLightOutline != {} } {
  2070.         $_canvas itemconfigure $_gLightOutline -fill $_lightShadow
  2071.     }
  2072.     if { $_gBlackOutline != {} } {
  2073.         $_canvas itemconfigure $_gBlackOutline -fill black
  2074.     }
  2075.     } else {
  2076.     if { $_gLightOutline != {} } {
  2077.         $_canvas itemconfigure $_gLightOutline -fill $background
  2078.     }
  2079.     if { $_gBlackOutline != {} } {
  2080.         $_canvas itemconfigure $_gBlackOutline -fill $background
  2081.     }
  2082.     }
  2083.     
  2084.     
  2085.     if { $state == "normal" } {
  2086.     if { $image != {}} {
  2087.         # do nothing for now
  2088.     } elseif { $bitmap != {}} {
  2089.         $_canvas itemconfigure $_gLabel \
  2090.             -foreground $foreground \
  2091.             -background $background 
  2092.     } else {
  2093.         $_canvas itemconfigure $_gLabel -fill $foreground
  2094.     }
  2095.     } else {
  2096.     if { $image != {}} {
  2097.         # do nothing for now
  2098.     } elseif { $bitmap != {}} {
  2099.         $_canvas itemconfigure $_gLabel \
  2100.             -foreground $disabledforeground \
  2101.             -background $background 
  2102.     } else {
  2103.         $_canvas itemconfigure $_gLabel -fill $disabledforeground
  2104.     }
  2105.     }
  2106.     
  2107.     set _selected false
  2108. }
  2109.  
  2110. # ----------------------------------------------------------------------
  2111. # PRIVATE METHOD: _makeTab
  2112. # ----------------------------------------------------------------------
  2113. body iwidgets::Tab::_makeTab {} {
  2114.     if { $orient == "horizontal" } {
  2115.     if { $invert } {
  2116.         _makeNorthTab $_canvas
  2117.     } else {
  2118.         _makeSouthTab $_canvas
  2119.     }
  2120.     } elseif { $orient == "vertical" } {
  2121.     if { $invert } {
  2122.         _makeEastTab $_canvas
  2123.     } else {
  2124.         _makeWestTab $_canvas
  2125.     }
  2126.     } else {
  2127.     error "bad value for option -orient"
  2128.     }
  2129. }
  2130.  
  2131. # ----------------------------------------------------------------------
  2132. # PRIVATE METHOD: _createLabel
  2133. #
  2134. # Creates the label for the tab. Can be either a text label
  2135. # or a bitmap label.
  2136. # ----------------------------------------------------------------------
  2137. body iwidgets::Tab::_createLabel {canvas tagList} {
  2138.     if { $image != {}} {
  2139.     set _gLabel [$canvas create image \
  2140.         0 0 \
  2141.         -image $image \
  2142.         -anchor nw \
  2143.         -tags $tagList \
  2144.         ]
  2145.     } elseif { $bitmap != {}} {
  2146.     set _gLabel [$canvas create bitmap \
  2147.         0 0 \
  2148.         -bitmap $bitmap \
  2149.         -anchor nw \
  2150.         -tags $tagList \
  2151.         ]
  2152.     } else {
  2153.     set _gLabel [$canvas create text \
  2154.         0 0 \
  2155.         -text $label \
  2156.         -font $font \
  2157.         -anchor nw \
  2158.         -tags $tagList \
  2159.         ]
  2160.     }
  2161. }
  2162.  
  2163. # ----------------------------------------------------------------------
  2164. # PRIVATE METHOD: _makeEastTab
  2165. #
  2166. # Makes a tab that hangs to the east and opens to the west.
  2167. # ----------------------------------------------------------------------
  2168. body iwidgets::Tab::_makeEastTab {canvas} {
  2169.     $canvas delete $this
  2170.     set _gLightOutline {}
  2171.     set _gBlackOutline {}
  2172.     
  2173.     lappend tagList $this TAB
  2174.     
  2175.     _createLabel $canvas $tagList
  2176.     
  2177.     _calcLabelDim $_gLabel
  2178.     
  2179.     
  2180.     set right  [expr $_left + $_labelWidth]
  2181.     # now have _left, _top, right...
  2182.     
  2183.     # Turn off calculating angle tabs on Vertical orientations
  2184.     #set angleOffset [expr $_labelHeight * $_tan($angle)]
  2185.     set angleOffset 0
  2186.     
  2187.     set outerTop $_top
  2188.     set outerBottom \
  2189.         [expr $outerTop + $angleOffset + $_labelHeight + $angleOffset]
  2190.     set innerTop [expr $outerTop + $angleOffset]
  2191.     set innerBottom [expr $outerTop + $angleOffset + $_labelHeight]
  2192.     
  2193.     # now have _left, _top, right, outerTop, innerTop,
  2194.     # innerBottom, outerBottom, width, height
  2195.     
  2196.     set bottom $innerBottom
  2197.     # tab area... gets filled either white or selected
  2198.     # done
  2199.     set _gRegion [$canvas create polygon \
  2200.         $_left $outerTop \
  2201.         [expr $right - $bevelamount] $innerTop \
  2202.         $right [expr $innerTop + $bevelamount] \
  2203.         $right [expr $innerBottom - $bevelamount] \
  2204.         [expr $right - $bevelamount] $innerBottom \
  2205.         $_left $outerBottom \
  2206.         $_left $outerTop \
  2207.         -tags $tagList  \
  2208.         ]
  2209.     
  2210.     # lighter shadow (left edge)
  2211.     set _gLightShadow [$canvas create line \
  2212.         [expr $_left - 3] [expr $outerTop + 1] \
  2213.         [expr $right - $bevelamount] [expr $innerTop + 1] \
  2214.         -tags $tagList \
  2215.         ]
  2216.     
  2217.     # darker shadow (bottom and right edges)
  2218.     set _gDarkShadow [$canvas create line \
  2219.         [expr $right - $bevelamount] [expr $innerTop + 1] \
  2220.         [expr $right - 1] [expr $innerTop + $bevelamount] \
  2221.         [expr $right - 1] [expr $innerBottom - $bevelamount] \
  2222.         [expr $right - $bevelamount] [expr $innerBottom - 1] \
  2223.         [expr $_left - 3] [expr $outerBottom - 1] \
  2224.         -tags $tagList \
  2225.         ]
  2226.     
  2227.     # outline of tab
  2228.     set _gLightOutline [$canvas create line \
  2229.         $_left $outerTop \
  2230.         [expr $right - $bevelamount] $innerTop \
  2231.         -tags $tagList \
  2232.         ]
  2233.     # outline of tab
  2234.     set _gBlackOutline [$canvas create line \
  2235.         [expr $right - $bevelamount] $innerTop \
  2236.         $right [expr $innerTop + $bevelamount] \
  2237.         $right [expr $innerBottom - $bevelamount] \
  2238.         [expr $right - $bevelamount] $innerBottom \
  2239.         $_left $outerBottom \
  2240.         $_left $outerTop \
  2241.         -tags $tagList \
  2242.         ]
  2243.     
  2244.     # line closest to the edge
  2245.     set _gTopLineShadow [$canvas create line \
  2246.         $_left $outerTop \
  2247.         $_left $outerBottom \
  2248.         -tags $tagList \
  2249.         ]
  2250.     
  2251.     # next line down
  2252.     set _gTopLine [$canvas create line \
  2253.         [expr $_left + 1] [expr $outerTop + 2] \
  2254.         [expr $_left + 1] [expr $outerBottom - 1] \
  2255.         -tags $tagList  \
  2256.         ]
  2257.     
  2258.     $canvas coords $_gLabel [expr $_left + $_labelXOrigin] \
  2259.         [expr $innerTop + $_labelYOrigin]
  2260.     
  2261.     if { $image != {} || $bitmap != {} } {
  2262.     $canvas itemconfigure $_gLabel -anchor $anchor
  2263.     } else {
  2264.     $canvas itemconfigure $_gLabel -anchor $anchor -justify $_just
  2265.     }
  2266.     
  2267.     $canvas raise $_gLabel $_gRegion
  2268.     
  2269.     
  2270.     set _offset    [expr $innerBottom - $outerTop]
  2271.     # height
  2272.     set _majorDim  [expr $outerBottom - $outerTop]
  2273.     # width
  2274.     set _minorDim [expr $right - $_left]
  2275.     
  2276.     set _right   $right 
  2277.     set _bottom  $outerBottom
  2278.     
  2279.     # draw in correct state...
  2280.     if { $_selected } {
  2281.     select
  2282.     } else {
  2283.     deselect
  2284.     }
  2285. }
  2286.  
  2287. # ----------------------------------------------------------------------
  2288. # PRIVATE METHOD: _makeWestTab
  2289. #
  2290. # Makes a tab that hangs to the west and opens to the east.
  2291. # ----------------------------------------------------------------------
  2292. body iwidgets::Tab::_makeWestTab {canvas} {
  2293.     $canvas delete $this
  2294.     set _gLightOutline {}
  2295.     set _gBlackOutline {}
  2296.     
  2297.     lappend tagList $this TAB
  2298.     
  2299.     _createLabel $canvas $tagList
  2300.     _calcLabelDim $_gLabel
  2301.     
  2302.     set right  [expr $_left + $_labelWidth]
  2303.     # now have _left, _top, right...
  2304.     
  2305.     # Turn off calculating angle tabs on Vertical orientations
  2306.     #set angleOffset [expr $_labelHeight * $_tan($angle)]
  2307.     set angleOffset 0
  2308.     
  2309.     set outerTop $_top
  2310.     set outerBottom \
  2311.         [expr $outerTop + $angleOffset + $_labelHeight + $angleOffset]
  2312.     set innerTop [expr $outerTop + $angleOffset]
  2313.     set innerBottom [expr $outerTop + $angleOffset + $_labelHeight]
  2314.     
  2315.     # now have _left, _top, right, outerTop, innerTop,
  2316.     # innerBottom, outerBottom, width, height
  2317.     
  2318.     # tab area... gets filled either white or selected
  2319.     # done
  2320.     set _gRegion [$canvas create polygon \
  2321.         $right $outerTop \
  2322.         [expr $_left + $bevelamount] $innerTop \
  2323.         $_left [expr $innerTop + $bevelamount] \
  2324.         $_left [expr $innerBottom - $bevelamount]\
  2325.         [expr $_left + $bevelamount] $innerBottom \
  2326.         $right $outerBottom \
  2327.         $right $outerTop \
  2328.         -tags $tagList  \
  2329.         ]
  2330.     # lighter shadow (left edge)
  2331.     set _gLightShadow [$canvas create line \
  2332.         $right [expr $outerTop+1] \
  2333.         [expr $_left + $bevelamount] [expr $innerTop + 1] \
  2334.         [expr $_left + 1] [expr $innerTop + $bevelamount] \
  2335.         [expr $_left + 1] [expr $innerBottom - $bevelamount] \
  2336.         -tags $tagList \
  2337.         ]
  2338.     
  2339.     # darker shadow (bottom and right edges)
  2340.     set _gDarkShadow [$canvas create line \
  2341.         [expr $_left + 1] [expr $innerBottom - $bevelamount] \
  2342.         [expr $_left + $bevelamount] [expr $innerBottom - 1] \
  2343.         $right [expr $outerBottom - 1] \
  2344.         -tags $tagList \
  2345.         ]
  2346.     
  2347.     # outline of tab -- lighter top left sides
  2348.     set _gLightOutline [$canvas create line \
  2349.         $right $outerTop \
  2350.         [expr $_left + $bevelamount] $innerTop \
  2351.         $_left [expr $innerTop + $bevelamount] \
  2352.         $_left [expr $innerBottom - $bevelamount]\
  2353.         -tags $tagList \
  2354.         ]
  2355.     # outline of tab -- darker bottom side
  2356.     set _gBlackOutline [$canvas create line \
  2357.         $_left [expr $innerBottom - $bevelamount]\
  2358.         [expr $_left + $bevelamount] $innerBottom \
  2359.         $right $outerBottom \
  2360.         $right $outerTop \
  2361.         -tags $tagList \
  2362.         ]
  2363.     
  2364.     # top of tab
  2365.     set _gTopLine [$canvas create line \
  2366.         [expr $right + 1] $outerTop \
  2367.         [expr $right + 1] $outerBottom \
  2368.         -tags $tagList  \
  2369.         ]
  2370.     
  2371.     # line below top of tab
  2372.     set _gTopLineShadow [$canvas create line \
  2373.         $right $outerTop \
  2374.         $right $outerBottom \
  2375.         -tags $tagList \
  2376.         ]
  2377.     
  2378.     $canvas coords $_gLabel [expr $_left + $_labelXOrigin] \
  2379.         [expr $innerTop + $_labelYOrigin]
  2380.     if { $image != {} || $bitmap != {} } {
  2381.     $canvas itemconfigure $_gLabel -anchor $anchor 
  2382.     } else {
  2383.     $canvas itemconfigure $_gLabel -anchor $anchor -justify $_just
  2384.     }
  2385.     
  2386.     $canvas raise $_gLabel $_gRegion
  2387.     
  2388.     
  2389.     set _offset    [expr $innerBottom - $outerTop]
  2390.     # height
  2391.     set _majorDim  [expr $outerBottom - $outerTop]
  2392.     # width
  2393.     set _minorDim [expr $right - $_left]
  2394.     
  2395.     set _right   $right 
  2396.     set _bottom  $outerBottom
  2397.     
  2398.     # draw in correct state...
  2399.     if { $_selected } {
  2400.     select
  2401.     } else {
  2402.     deselect
  2403.     }
  2404.     
  2405. }
  2406.  
  2407. # ----------------------------------------------------------------------
  2408. # PRIVATE METHOD: _makeNorthTab
  2409. #
  2410. # Makes a tab that hangs to the north and opens to the south.
  2411. # ----------------------------------------------------------------------
  2412. body iwidgets::Tab::_makeNorthTab {canvas} {
  2413.     $canvas delete $this
  2414.     set _gLightOutline {}
  2415.     set _gBlackOutline {}
  2416.     
  2417.     lappend tagList $this TAB
  2418.     
  2419.     _createLabel $canvas $tagList
  2420.     
  2421.     # first get the label width and height
  2422.     _calcLabelDim $_gLabel
  2423.     
  2424.     set bottom [expr $_top + $_labelHeight]
  2425.     
  2426.     set angleOffset [expr $_labelHeight * $_tan($angle)]
  2427.     
  2428.     set outerLeft $_left
  2429.     set outerRight \
  2430.         [expr $outerLeft + $angleOffset + $_labelWidth + $angleOffset]
  2431.     set innerLeft [expr $outerLeft + $angleOffset]
  2432.     set innerRight [expr $outerLeft + $angleOffset + $_labelWidth]
  2433.     
  2434.     # tab area... gets filled either white or selected
  2435.     set _gRegion [$canvas create polygon \
  2436.         $outerLeft [expr $bottom + 3]  \
  2437.         $innerLeft [expr $_top + $bevelamount] \
  2438.         [expr $innerLeft +  $bevelamount] $_top \
  2439.         [expr $innerRight - $bevelamount] $_top \
  2440.         $innerRight [expr $_top + $bevelamount]\
  2441.         $outerRight [expr $bottom + 3] \
  2442.         $outerLeft [expr $bottom + 3] \
  2443.         -tags $tagList  \
  2444.         ]
  2445.     
  2446.     # lighter shadow (left edge)
  2447.     set _gLightShadow [$canvas create line \
  2448.         [expr $outerLeft + 1] [expr $bottom + 3]  \
  2449.         [expr $innerLeft + 1] [expr $_top + $bevelamount] \
  2450.         [expr $innerLeft + $bevelamount] [expr $_top + 1]\
  2451.         [expr $innerRight - $bevelamount] [expr $_top + 1]\
  2452.         -tags $tagList \
  2453.         ]
  2454.     
  2455.     # darker shadow (bottom and right edges)
  2456.     set _gDarkShadow [$canvas create line \
  2457.         [expr $innerRight - $bevelamount] [expr $_top + 1]\
  2458.         [expr $innerRight - 1] [expr $_top + $bevelamount]\
  2459.         [expr $outerRight - 1] [expr $bottom + 3]\
  2460.         -tags $tagList \
  2461.         ]
  2462.     
  2463.     set _gLightOutline [$canvas create line \
  2464.         $outerLeft [expr $bottom + 3]  \
  2465.         $innerLeft [expr $_top + $bevelamount] \
  2466.         [expr $innerLeft +  $bevelamount] $_top \
  2467.         [expr $innerRight - $bevelamount] $_top \
  2468.         -tags $tagList \
  2469.         ]
  2470.     
  2471.     set _gBlackOutline [$canvas create line \
  2472.         [expr $innerRight - $bevelamount] $_top \
  2473.         $innerRight [expr $_top + $bevelamount]\
  2474.         $outerRight [expr $bottom + 3] \
  2475.         $outerLeft [expr $bottom + 3] \
  2476.         -tags $tagList \
  2477.         ]
  2478.     
  2479.     # top of tab... to make it closed off
  2480.     set _gTopLine [$canvas create line \
  2481.         0 0 0 0\
  2482.         -tags $tagList  \
  2483.         ]
  2484.     #[expr $outerLeft + 2] [expr $_top + 1] \
  2485.         [expr $outerRight - 2] [expr $_top + 1]
  2486.     
  2487.     # top of tab... to make it closed off
  2488.     set _gTopLineShadow [$canvas create line \
  2489.         0 0 0 0 \
  2490.         -tags $tagList \
  2491.         ]
  2492.     #$outerLeft $_top \
  2493.         $outerRight $_top 
  2494.     
  2495.     $canvas coords $_gLabel [expr $innerLeft + $_labelXOrigin] \
  2496.         [expr $_top + $_labelYOrigin]
  2497.     
  2498.     if { $image != {} || $bitmap != {} } {
  2499.     $canvas itemconfigure $_gLabel -anchor $anchor 
  2500.     } else {
  2501.     $canvas itemconfigure $_gLabel -anchor $anchor -justify $_just
  2502.     }
  2503.     
  2504.     $canvas raise $_gLabel $_gRegion
  2505.     
  2506.     
  2507.     set _offset    [expr $innerRight - $outerLeft]
  2508.     # width
  2509.     set _majorDim  [expr $outerRight - $outerLeft]
  2510.     # height
  2511.     set _minorDim [expr $bottom - $_top]
  2512.     
  2513.     set _right     $outerRight
  2514.     set _bottom    $bottom
  2515.     
  2516.     # draw in correct state...
  2517.     if { $_selected } {
  2518.     select
  2519.     } else {
  2520.     deselect
  2521.     }
  2522. }
  2523.  
  2524. # ----------------------------------------------------------------------
  2525. # PRIVATE METHOD: _makeSouthTab
  2526. #
  2527. # Makes a tab that hangs to the south and opens to the north.
  2528. # ----------------------------------------------------------------------
  2529. body iwidgets::Tab::_makeSouthTab {canvas} {
  2530.     $canvas delete $this
  2531.     set _gLightOutline {}
  2532.     set _gBlackOutline {}
  2533.     
  2534.     lappend tagList $this TAB
  2535.     
  2536.     _createLabel $canvas $tagList
  2537.     
  2538.     # first get the label width and height
  2539.     _calcLabelDim $_gLabel
  2540.     
  2541.     set bottom [expr $_top + $_labelHeight]
  2542.     
  2543.     set angleOffset [expr $_labelHeight * $_tan($angle)]
  2544.     
  2545.     set outerLeft $_left
  2546.     set outerRight \
  2547.         [expr $outerLeft + $angleOffset + $_labelWidth + $angleOffset]
  2548.     set innerLeft [expr $outerLeft + $angleOffset]
  2549.     set innerRight [expr $outerLeft + $angleOffset + $_labelWidth]
  2550.     
  2551.     # tab area... gets filled either white or selected
  2552.     set _gRegion [$canvas create polygon \
  2553.         $outerLeft [expr $_top + 1] \
  2554.         $innerLeft [expr $bottom  - $bevelamount]\
  2555.         [expr $innerLeft + $bevelamount] $bottom \
  2556.         [expr $innerRight - $bevelamount] $bottom \
  2557.         $innerRight [expr $bottom - $bevelamount]\
  2558.         $outerRight [expr $_top + 1] \
  2559.         $outerLeft [expr $_top + 1] \
  2560.         -tags $tagList  \
  2561.         ]
  2562.     
  2563.     
  2564.     # lighter shadow (left edge)
  2565.     set _gLightShadow [$canvas create line \
  2566.         [expr $outerLeft+1] $_top \
  2567.         [expr $innerLeft+1] [expr $bottom-$bevelamount] \
  2568.         -tags $tagList \
  2569.         ]
  2570.     
  2571.     # darker shadow (bottom and right edges)
  2572.     set _gDarkShadow [$canvas create line \
  2573.         [expr $innerLeft+1] [expr $bottom-$bevelamount] \
  2574.         [expr $innerLeft+$bevelamount] [expr $bottom-1] \
  2575.         [expr $innerRight-$bevelamount] [expr $bottom-1] \
  2576.         [expr $innerRight-1] [expr $bottom-$bevelamount] \
  2577.         [expr $outerRight-1] [expr $_top + 1] \
  2578.         -tags $tagList \
  2579.         ]
  2580.     # outline of tab
  2581.     set _gBlackOutline [$canvas create line \
  2582.         $outerLeft [expr $_top + 1] \
  2583.         $innerLeft [expr $bottom  -$bevelamount]\
  2584.         [expr $innerLeft + $bevelamount] $bottom \
  2585.         [expr $innerRight - $bevelamount] $bottom \
  2586.         $innerRight [expr $bottom - $bevelamount]\
  2587.         $outerRight [expr $_top + 1] \
  2588.         -tags $tagList \
  2589.         ]
  2590.     
  2591.     # top of tab... to make it closed off
  2592.     set _gTopLine [$canvas create line \
  2593.         $outerLeft [expr $_top + 1] \
  2594.         $outerRight [expr $_top + 1] \
  2595.         -tags $tagList  \
  2596.         ]
  2597.     
  2598.     # top of tab... to make it closed off
  2599.     set _gTopLineShadow [$canvas create line \
  2600.         $outerLeft $_top \
  2601.         $outerRight $_top \
  2602.         -tags $tagList \
  2603.         ]
  2604.     
  2605.     #$canvas coords $_gLabel [expr $innerLeft + $_padX + 2] \
  2606.         [expr $_top + $_padY]
  2607.     $canvas coords $_gLabel [expr $innerLeft + $_labelXOrigin] \
  2608.         [expr $_top + $_labelYOrigin]
  2609.     
  2610.     if { $image != {} || $bitmap != {} } {
  2611.     $canvas itemconfigure $_gLabel -anchor $anchor 
  2612.     } else {
  2613.     $canvas itemconfigure $_gLabel -anchor $anchor -justify $_just
  2614.     }
  2615.     $canvas raise $_gLabel $_gRegion
  2616.     
  2617.     
  2618.     set _offset    [expr $innerRight - $outerLeft]
  2619.     
  2620.     # width
  2621.     set _majorDim  [expr $outerRight - $outerLeft]
  2622.     
  2623.     # height
  2624.     set _minorDim [expr $bottom - $_top]
  2625.     
  2626.     set _right     $outerRight
  2627.     set _bottom    $bottom
  2628.     
  2629.     # draw in correct state...
  2630.     if { $_selected } {
  2631.     select
  2632.     } else {
  2633.     deselect
  2634.     }
  2635. }
  2636.  
  2637. # ----------------------------------------------------------------------
  2638. # PRIVATE METHOD: _calcLabelDim
  2639. #
  2640. # Calculate the width and height of the label bbox of labelItem
  2641. # can be either text or bitmap (in future also an image)
  2642. #
  2643. # There are two ways to calculate the label bbox.
  2644. #
  2645. # First, if the $_width and/or $_height is specified, we will use
  2646. # it to determine that dimension(s) width and/or height. For 
  2647. # a width/height of 0 we use the labels bbox to
  2648. # give us a base width/height.
  2649. # Then we add in the padx/pady to determine final bounds.
  2650. #
  2651. # Uses the following option or option derived variables:
  2652. #    -padx     ($_padX - converted to pixels)
  2653. #    -pady     ($_padY - converted to pixels)
  2654. #    -anchor   ($anchor)
  2655. #    -width    ($_width) This is the width for inside tab (label area)
  2656. #    -height   ($_height) This is the width for inside tab (label area)
  2657. #
  2658. # Side Effects:
  2659. #    _labelWidth will be set
  2660. #    _labelHeight will be set
  2661. #    _labelXOrigin will be set
  2662. #    _labelYOrigin will be set
  2663. # ----------------------------------------------------------------------
  2664. body iwidgets::Tab::_calcLabelDim {labelItem} {
  2665.     # ... calculate the label width and height
  2666.     set labelBBox [$_canvas bbox $labelItem]
  2667.     
  2668.     if { $_width > 0 } {
  2669.     set _labelWidth [expr $_width + ($_padX * 2)]
  2670.     } else {
  2671.     set _labelWidth [expr \
  2672.         ([lindex $labelBBox 2] - [lindex $labelBBox 0]) + ($_padX * 2)]
  2673.     }
  2674.     
  2675.     if { $_height > 0 } {
  2676.     set _labelHeight [expr $_height + ($_padY * 2)]
  2677.     } else {
  2678.     set _labelHeight [expr \
  2679.         ([lindex $labelBBox 3] - [lindex $labelBBox 1]) + ($_padY * 2)]
  2680.     }
  2681.     
  2682.     # ... calculate the label anchor point
  2683.     set centerX [expr $_labelWidth/2.0]
  2684.     set centerY [expr $_labelHeight/2.0 - 1]
  2685.     
  2686.     switch $anchor {
  2687.     n {
  2688.         set _labelXOrigin $centerX
  2689.         set _labelYOrigin $_padY
  2690.         set _just center
  2691.     }
  2692.     s {
  2693.         set _labelXOrigin $centerX
  2694.         set _labelYOrigin [expr $_labelHeight - $_padY]
  2695.         set _just center
  2696.     }
  2697.     e {
  2698.         set _labelXOrigin [expr $_labelWidth - $_padX - 1]
  2699.         set _labelYOrigin $centerY
  2700.         set _just right
  2701.     }
  2702.     w {
  2703.         set _labelXOrigin [expr $_padX + 2]
  2704.         set _labelYOrigin $centerY
  2705.         set _just left
  2706.     }
  2707.     c {
  2708.         set _labelXOrigin $centerX
  2709.         set _labelYOrigin $centerY
  2710.         set _just center
  2711.     }
  2712.     ne {
  2713.         set _labelXOrigin [expr $_labelWidth - $_padX - 1]
  2714.         set _labelYOrigin $_padY
  2715.         set _just right
  2716.     }
  2717.     nw {
  2718.         set _labelXOrigin [expr $_padX + 2]
  2719.         set _labelYOrigin $_padY
  2720.         set _just left
  2721.     }
  2722.     se {
  2723.         set _labelXOrigin [expr $_labelWidth - $_padX - 1]
  2724.         set _labelYOrigin [expr $_labelHeight - $_padY]
  2725.         set _just right
  2726.     }
  2727.     sw {
  2728.         set _labelXOrigin [expr $_padX + 2]
  2729.         set _labelYOrigin [expr $_labelHeight - $_padY]
  2730.         set _just left
  2731.     }
  2732.     default {
  2733.         error "bad anchor position: \
  2734.             \"$tabpos\" must be n, ne, nw, s, sw, se, e, w, or center"
  2735.     }
  2736.     }
  2737. }
  2738.