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