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