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

  1. #
  2. # Panedwindow
  3. # ----------------------------------------------------------------------
  4. # Implements a multiple paned window widget capable of orienting the panes
  5. # either vertically or horizontally.  Each pane is itself a frame acting
  6. # as a child site for other widgets.  The border separating each pane 
  7. # contains a sash which allows user positioning of the panes relative to
  8. # one another.  
  9. #
  10. # ----------------------------------------------------------------------
  11. #  AUTHOR: Mark L. Ulferts              EMAIL: mulferts@austin.dsccc.com
  12. #
  13. #  @(#) $Id: panedwindow.itk,v 1.1 1998/07/27 18:53:12 stanton Exp $
  14. # ----------------------------------------------------------------------
  15. #            Copyright (c) 1995 DSC Technologies Corporation
  16. # ======================================================================
  17. # Permission to use, copy, modify, distribute and license this software 
  18. # and its documentation for any purpose, and without fee or written 
  19. # agreement with DSC, is hereby granted, provided that the above copyright 
  20. # notice appears in all copies and that both the copyright notice and 
  21. # warranty disclaimer below appear in supporting documentation, and that 
  22. # the names of DSC Technologies Corporation or DSC Communications 
  23. # Corporation not be used in advertising or publicity pertaining to the 
  24. # software without specific, written prior permission.
  25. # DSC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
  26. # ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, AND NON-
  27. # INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND THE
  28. # AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE MAINTENANCE, 
  29. # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. IN NO EVENT SHALL 
  30. # DSC BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 
  31. # ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
  32. # WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTUOUS ACTION,
  33. # ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
  34. # SOFTWARE.
  35. # ======================================================================
  36.  
  37. #
  38. # Usual options.
  39. #
  40. itk::usual Panedwindow {
  41.     keep -background -cursor -sashcursor
  42. }
  43.  
  44. # ------------------------------------------------------------------
  45. #                            PANEDWINDOW
  46. # ------------------------------------------------------------------
  47. class iwidgets::Panedwindow {
  48.     inherit itk::Widget
  49.  
  50.     constructor {args} {}
  51.  
  52.     itk_option define -orient orient Orient horizontal 
  53.     itk_option define -sashborderwidth sashBorderWidth SashBorderWidth 2
  54.     itk_option define -sashcursor sashCursor SashCursor crosshair
  55.     itk_option define -sashwidth sashWidth SashWidth 10
  56.     itk_option define -sashheight sashHeight SashHeight 10
  57.     itk_option define -thickness thickness Thickness 3
  58.     itk_option define -sashindent sashIndent SashIndent -10
  59.  
  60.     public method index {index} 
  61.     public method childsite {args} 
  62.     public method fraction {percentage1 percentage2 args} 
  63.     public method add {tag args} 
  64.     public method insert {index tag args} 
  65.     public method delete {index} 
  66.     public method hide {index}    
  67.     public method show {index} 
  68.     public method paneconfigure {index args} 
  69.     public method reset {} 
  70.  
  71.     protected method _pwConfigureEventHandler {width height} 
  72.     protected method _startGrip {where num} 
  73.     protected method _endGrip {where num} 
  74.     protected method _configGrip {where num} 
  75.     protected method _handleGrip {where num} 
  76.     protected method _moveSash {where num} 
  77.  
  78.     private method _setFracArray {} 
  79.     private method _setActivePanes {} 
  80.     private method _calcFraction {where num} 
  81.     private method _makeSashes {} 
  82.     private method _placeSash {i} 
  83.     private method _placePanes {{start 0} {end end}} 
  84.     
  85.     private variable _initialized 0    ;# Denotes initialized state.
  86.     private variable _panes {}         ;# List of panes.
  87.     private variable _activePanes {}   ;# List of active panes.
  88.     private variable _sashes {}        ;# List of sashes.
  89.     private variable _separators {}    ;# List of separators.
  90.     private variable _frac             ;# Array of fraction percentages.
  91.     private variable _lowerlimit       ;# Margin distance above/left of sash.
  92.     private variable _upperlimit       ;# Margin distance below/right of sash.
  93.     private variable _dimension        ;# Width/Height at start of drag.
  94.     private variable _sashloc          ;# Array of dist of sash from above/left.
  95.     private variable _pixels           ;# Array of dist of sash from above/left.
  96.     private variable _minheight        ;# Array of min heights for panes.
  97.     private variable _minsashmoved     ;# Lowest sash moved during dragging.
  98.     private variable _maxsashmoved     ;# Highest sash moved during dragging.
  99.     private variable _dragging 0       ;# Boolean for dragging enabled.
  100.     private variable _movecount 0      ;# Kludge counter to get sashes to
  101.                                        ;# display without calling update 
  102.                                        ;# idletasks too often.
  103.     private variable _width 0          ;# hull's width.
  104.     private variable _height 0         ;# hull's height.
  105.     private variable _unique -1         ;# Unique number for pane names.
  106. }
  107.  
  108. #
  109. # Provide a lowercased access method for the Panedwindow class.
  110. proc ::iwidgets::panedwindow {pathName args} {
  111.     uplevel ::iwidgets::Panedwindow $pathName $args
  112. }
  113.  
  114. #
  115. # Use option database to override default resources of base classes.
  116. #
  117. option add *Panedwindow.width 10 widgetDefault
  118. option add *Panedwindow.height 10 widgetDefault
  119.  
  120. # ------------------------------------------------------------------
  121. #                        CONSTRUCTOR
  122. # ------------------------------------------------------------------
  123. body iwidgets::Panedwindow::constructor {args} {
  124.     itk_option add hull.width hull.height
  125.  
  126.     pack propagate $itk_component(hull) no
  127.     
  128.     #
  129.     # Add binding for the configure event.
  130.     #
  131.     bind pw-config-$this <Configure> [code $this _pwConfigureEventHandler %w %h]
  132.     bindtags $itk_component(hull) \
  133.         [linsert [bindtags $itk_component(hull)] 0 pw-config-$this]
  134.     
  135.     eval itk_initialize $args
  136. }
  137.  
  138. # ------------------------------------------------------------------
  139. #                             OPTIONS
  140. # ------------------------------------------------------------------
  141.  
  142. # ------------------------------------------------------------------
  143. # OPTION: -orient
  144. #
  145. # Specifies the orientation of the sashes.  Once the paned window
  146. # has been mapped, set the sash bindings and place the panes.
  147. # ------------------------------------------------------------------
  148. configbody iwidgets::Panedwindow::orient {
  149.     if {$_initialized} {
  150.     switch $itk_option(-orient) {
  151.         vertical {
  152.         for {set i 1} {$i < [llength $_panes]} {incr i} {
  153.             bind $itk_component(sash$i) <Button-1> \
  154.                 [code $this _startGrip %x $i]
  155.             bind $itk_component(sash$i) <B1-Motion> \
  156.                 [code $this _handleGrip %x $i]
  157.             bind $itk_component(sash$i) <B1-ButtonRelease-1> \
  158.                 [code $this _endGrip %x $i]
  159.             bind $itk_component(sash$i) <Configure> \
  160.                 [code $this _configGrip %x $i]
  161.         }
  162.         
  163.         _setFracArray
  164.         _makeSashes
  165.         _placePanes
  166.         }
  167.         
  168.         horizontal {
  169.         for {set i 1} {$i < [llength $_panes]} {incr i} {
  170.             bind $itk_component(sash$i) <Button-1> \
  171.                 [code $this _startGrip %y $i]
  172.             bind $itk_component(sash$i) <B1-Motion> \
  173.                 [code $this _handleGrip %y $i]
  174.             bind $itk_component(sash$i) <B1-ButtonRelease-1> \
  175.                 [code $this _endGrip %y $i]
  176.             bind $itk_component(sash$i) <Configure> \
  177.                 [code $this _configGrip %y $i]
  178.         }
  179.         
  180.         _setFracArray
  181.         _makeSashes
  182.         _placePanes
  183.         }
  184.         
  185.         default {
  186.         error "bad orientation option \"$itk_option(-orient)\":\
  187.             should be horizontal or vertical"
  188.         }
  189.     }
  190.     }
  191. }
  192.  
  193. # ------------------------------------------------------------------
  194. # OPTION: -sashborderwidth
  195. #
  196. # Specifies a non-negative value indicating the width of the 3-D
  197. # border to draw around the outside of the sash.
  198. # ------------------------------------------------------------------
  199. configbody iwidgets::Panedwindow::sashborderwidth {
  200.     set pixels [winfo pixels $itk_component(hull) \
  201.         $itk_option(-sashborderwidth)]
  202.     set itk_option(-sashborderwidth) $pixels
  203.     
  204.     if {$_initialized} {
  205.     for {set i 1} {$i < [llength $_panes]} {incr i} {
  206.         $itk_component(sash$i) configure \
  207.             -borderwidth $itk_option(-sashborderwidth)
  208.     }
  209.     }
  210. }
  211.  
  212. # ------------------------------------------------------------------
  213. # OPTION: -sashcursor
  214. #
  215. # Specifies the type of cursor to be used when over the sash.
  216. # ------------------------------------------------------------------
  217. configbody iwidgets::Panedwindow::sashcursor {
  218.     if {$_initialized} {
  219.     for {set i 1} {$i < [llength $_panes]} {incr i} {
  220.         $itk_component(sash$i) configure \
  221.             -cursor $itk_option(-sashcursor)
  222.     }
  223.     }
  224. }
  225.  
  226. # ------------------------------------------------------------------
  227. # OPTION: -sashwidth
  228. #
  229. # Specifies the width of the sash.
  230. # ------------------------------------------------------------------
  231. configbody iwidgets::Panedwindow::sashwidth {
  232.     set pixels [winfo pixels $itk_component(hull) \
  233.         $itk_option(-sashwidth)]
  234.     set itk_option(-sashwidth) $pixels
  235.     
  236.     if {$_initialized} {
  237.     for {set i 1} {$i < [llength $_panes]} {incr i} {
  238.         $itk_component(sash$i) configure \
  239.             -width $itk_option(-sashwidth)
  240.     }
  241.     }
  242. }
  243.  
  244. # ------------------------------------------------------------------
  245. # OPTION: -sashheight
  246. #
  247. # Specifies the height of the sash,
  248. # ------------------------------------------------------------------
  249. configbody iwidgets::Panedwindow::sashheight {
  250.     set pixels [winfo pixels $itk_component(hull) \
  251.         $itk_option(-sashheight)]
  252.     set itk_option(-sashheight) $pixels
  253.     
  254.     if {$_initialized} {
  255.     for {set i 1} {$i < [llength $_panes]} {incr i} {
  256.         $itk_component(sash$i) configure \
  257.             -height $itk_option(-sashheight)
  258.     }
  259.     }
  260. }
  261.  
  262. # ------------------------------------------------------------------
  263. # OPTION: -thickness
  264. #
  265. # Specifies the thickness of the separators.  It sets the width and
  266. # height of the separator to the thickness value and the borderwidth
  267. # to half the thickness.
  268. # ------------------------------------------------------------------
  269. configbody iwidgets::Panedwindow::thickness {
  270.     set pixels [winfo pixels $itk_component(hull) \
  271.         $itk_option(-thickness)]
  272.     set itk_option(-thickness) $pixels
  273.     
  274.     if {$_initialized} {
  275.     for {set i 1} {$i < [llength $_panes]} {incr i} {
  276.         $itk_component(separator$i) configure \
  277.             -height $itk_option(-thickness)
  278.         $itk_component(separator$i) configure \
  279.             -width $itk_option(-thickness)
  280.         $itk_component(separator$i) configure \
  281.             -borderwidth [expr $itk_option(-thickness) / 2]
  282.     }
  283.     
  284.     for {set i 1} {$i < [llength $_panes]} {incr i} {
  285.         _placeSash $i
  286.     }
  287.     }
  288. }
  289.  
  290. # ------------------------------------------------------------------
  291. # OPTION: -sashindent
  292. #
  293. # Specifies the placement of the sash along the panes.  A positive
  294. # value causes the sash to be offset from the near (left/top) side
  295. # of the pane, and a negative value causes the sash to be offset from
  296. # the far (right/bottom) side.  If the offset is greater than the 
  297. # width, then the sash is placed flush against the side.  
  298. # ------------------------------------------------------------------
  299. configbody iwidgets::Panedwindow::sashindent {
  300.     set pixels [winfo pixels $itk_component(hull) \
  301.         $itk_option(-sashindent)]
  302.     set itk_option(-sashindent) $pixels
  303.     
  304.     if {$_initialized} {
  305.     for {set i 1} {$i < [llength $_panes]} {incr i} {
  306.         _placeSash $i
  307.     }
  308.     }
  309. }
  310.  
  311. # ------------------------------------------------------------------
  312. #                            METHODS
  313. # ------------------------------------------------------------------
  314.  
  315. # ------------------------------------------------------------------
  316. # METHOD: index index
  317. #
  318. # Searches the panes in the paned window for the one with the 
  319. # requested tag, numerical index, or keyword "end".  Returns the pane's 
  320. # numerical index if found, otherwise error.
  321. # ------------------------------------------------------------------    
  322. body iwidgets::Panedwindow::index {index} {
  323.     if {[llength $_panes] > 0} {
  324.     if {[regexp {(^[0-9]+$)} $index]} {
  325.         if {$index < [llength $_panes]} {
  326.         return $index
  327.         } else {
  328.         error "Panedwindow index \"$index\" is out of range"
  329.         }
  330.         
  331.     } elseif {$index == "end"} {
  332.         return [expr [llength $_panes] - 1]
  333.         
  334.     } else {
  335.         if {[set idx [lsearch $_panes $index]] != -1} {
  336.         return $idx
  337.         }
  338.         
  339.         error "bad Panedwindow index \"$index\": must be number, end,\
  340.             or pattern"
  341.     }
  342.     
  343.     } else {
  344.     error "Panedwindow \"$itk_component(hull)\" has no panes"
  345.     }
  346. }
  347.  
  348. # ------------------------------------------------------------------
  349. # METHOD: childsite ?index?
  350. #
  351. # Given an index return the specifc childsite path name.  Invoked 
  352. # without an index return a list of all the child site panes.  The 
  353. # list is ordered from the near side (left/top).
  354. # ------------------------------------------------------------------
  355. body iwidgets::Panedwindow::childsite {args} {
  356.     if {! $_initialized} {
  357.     set _initialized 1
  358.     reset
  359.     }
  360.  
  361.     if {[llength $args] == 0} {
  362.     set children {}
  363.     
  364.     foreach pane $_panes {
  365.         lappend children [$itk_component($pane) childSite]
  366.     }
  367.     
  368.     return $children
  369.     
  370.     } else {
  371.     set index [index [lindex $args 0]]
  372.     return [$itk_component([lindex $_panes $index]) childSite]
  373.     }
  374. }
  375.  
  376. # ------------------------------------------------------------------
  377. # METHOD: fraction percentage percentage ?percentage ...?
  378. #
  379. # Sets the visible percentage of the panes.  Specifies a list of
  380. # percentages which are applied to the currently visible panes from 
  381. # the near side (left/top).  The number of percentages must be equal 
  382. # to the current number of visible (mapped) panes and add up to 100.
  383. # ------------------------------------------------------------------
  384. body iwidgets::Panedwindow::fraction {percentage1 percentage2 args} {
  385.     set args [linsert $args 0 $percentage1 $percentage2]
  386.     
  387.     if {[llength $args] == [llength $_activePanes]} {
  388.     set sum 0
  389.     
  390.     for {set i 0} {$i < [llength $args]} {incr i} {
  391.         set sum [expr $sum + [lindex $args $i]]
  392.     }
  393.     
  394.     if {$sum == 100} {
  395.         set perc 0.0
  396.         
  397.         for {set i 0} {$i < [llength $_activePanes]} {incr i} {
  398.         set _frac($i) $perc
  399.         set perc [expr $perc + [expr [lindex $args $i] / 100.0]]
  400.         }
  401.         
  402.         set _frac($i) 1.0
  403.         
  404.         if {[winfo ismapped $itk_component(hull)]} {
  405.         _placePanes
  406.         }
  407.         
  408.     } else {
  409.         error "bad fraction arguments \"$args\": they should add\
  410.             up to 100"
  411.     }
  412.     
  413.     } else {
  414.     error "wrong # args: should be \"$itk_component(hull)\
  415.         fraction percentage percentage ?percentage ...?\",\
  416.         where the number of percentages is\
  417.         [llength $_activePanes] and equal 100"
  418.     }
  419. }
  420.  
  421. # ------------------------------------------------------------------
  422. # METHOD: add tag ?option value option value ...?
  423. #
  424. # Add a new pane to the paned window to the far (right/bottom) side.
  425. # The method takes additional options which are passed on to the 
  426. # pane constructor.  These include -margin, and -minimum.  The path 
  427. # of the pane is returned.
  428. # ------------------------------------------------------------------
  429. body iwidgets::Panedwindow::add {tag args} {
  430.     #
  431.     # Create panes.
  432.     #
  433.     itk_component add $tag {
  434.     eval iwidgets::Pane $itk_interior.pane[incr _unique] $args
  435.     } {
  436.     keep -background -cursor
  437.     }
  438.     
  439.     lappend _panes $tag
  440.     lappend _activePanes $tag
  441.     
  442.     reset
  443.     
  444.     return $itk_component($tag)
  445. }
  446.  
  447. # ------------------------------------------------------------------
  448. # METHOD: insert index tag ?option value option value ...?
  449. #
  450. # Insert the specified pane in the paned window just before the one 
  451. # given by index.  Any additional options which are passed on to the 
  452. # pane constructor.  These include -margin, -minimum.  The path of 
  453. # the pane is returned.
  454. # ------------------------------------------------------------------
  455. body iwidgets::Panedwindow::insert {index tag args} {
  456.     #
  457.     # Create panes.
  458.     #
  459.     itk_component add $tag {
  460.     eval iwidgets::Pane $itk_interior.pane[incr _unique] $args
  461.     } {
  462.     keep -background -cursor
  463.     }
  464.     
  465.     set index [index $index]
  466.     set _panes [linsert $_panes $index $tag]
  467.     lappend _activePanes $tag
  468.     
  469.     reset
  470.     
  471.     return $itk_component($tag)
  472. }
  473.  
  474. # ------------------------------------------------------------------
  475. # METHOD: delete index
  476. #
  477. # Delete the specified pane.
  478. # ------------------------------------------------------------------
  479. body iwidgets::Panedwindow::delete {index} {
  480.     set index [index $index]
  481.     set tag [lindex $_panes $index]
  482.     
  483.     destroy $itk_component($tag)
  484.     
  485.     set _panes [lreplace $_panes $index $index]
  486.     
  487.     reset
  488. }
  489.  
  490. # ------------------------------------------------------------------
  491. # METHOD: hide index
  492. #
  493. # Remove the specified pane from the paned window. 
  494. # ------------------------------------------------------------------
  495. body iwidgets::Panedwindow::hide {index} {
  496.     set index [index $index]
  497.     set tag [lindex $_panes $index]
  498.     
  499.     if {[set idx [lsearch -exact $_activePanes $tag]] != -1} {
  500.     set _activePanes [lreplace $_activePanes $idx $idx]
  501.     }
  502.     
  503.     reset
  504. }   
  505.  
  506. # ------------------------------------------------------------------
  507. # METHOD: show index
  508. #
  509. # Display the specified pane in the paned window.
  510. # ------------------------------------------------------------------
  511. body iwidgets::Panedwindow::show {index} {
  512.     set index [index $index]
  513.     set tag [lindex $_panes $index]
  514.     
  515.     if {[lsearch -exact $_activePanes $tag] == -1} {
  516.     lappend _activePanes $tag
  517.     }
  518.     
  519.     reset
  520. }   
  521.  
  522. # ------------------------------------------------------------------
  523. # METHOD: paneconfigure index ?option? ?value option value ...?
  524. #
  525. # Configure a specified pane.  This method allows configuration of
  526. # panes from the Panedwindow level.  The options may have any of the 
  527. # values accepted by the add method.
  528. # ------------------------------------------------------------------
  529. body iwidgets::Panedwindow::paneconfigure {index args} {
  530.     set index [index $index]
  531.     set tag [lindex $_panes $index]
  532.     
  533.     return [uplevel $itk_component($tag) configure $args]
  534. }
  535.  
  536. # ------------------------------------------------------------------
  537. # METHOD: reset
  538. #
  539. # Redisplay the panes based on the default percentages of the panes.
  540. # ------------------------------------------------------------------
  541. body iwidgets::Panedwindow::reset {} {
  542.     if {$_initialized && [llength $_panes]} {
  543.     _setActivePanes
  544.     _setFracArray
  545.     
  546.     _makeSashes
  547.     _placePanes
  548.     }
  549. }
  550.  
  551. # ------------------------------------------------------------------
  552. # PROTECTED METHOD: _pwConfigureEventHandler
  553. #
  554. # Performs operations necessary following a configure event.  This
  555. # includes placing the panes.
  556. # ------------------------------------------------------------------
  557. body iwidgets::Panedwindow::_pwConfigureEventHandler {width height} {
  558.     set _width $width
  559.     set _height $height
  560.     if {$_initialized} {
  561.     _placePanes
  562.     } else {
  563.     set _initialized 1
  564.     reset
  565.     }
  566. }
  567.  
  568. # ------------------------------------------------------------------
  569. # PROTECTED METHOD: _startGrip where num
  570. #
  571. # Starts the sash drag and drop operation.  At the start of the drag
  572. # operation all the information is known as for the upper and lower
  573. # limits for sash movement.  The calculation is made at this time and
  574. # stored in protected variables for later access during the drag
  575. # handling routines.
  576. # ------------------------------------------------------------------
  577. body iwidgets::Panedwindow::_startGrip {where num} {
  578.     if {$itk_option(-orient) == "horizontal"} {
  579.       set _dimension $_height
  580.     } else {
  581.       set _dimension $_width
  582.     }
  583.     
  584.     set _minsashmoved $num
  585.     set _maxsashmoved $num
  586.     set totMinHeight 0
  587.     set cnt [llength $_activePanes]
  588.     set _sashloc(0) 0
  589.     set _pixels($cnt) [expr int($_dimension)]
  590.     for {set i 0} {$i < $cnt} {incr i} {
  591.       set _pixels($i) [expr int($_frac($i) * $_dimension)]
  592.       set margaft [$itk_component([lindex $_activePanes $i]) cget -margin]
  593.       set minaft [$itk_component([lindex $_activePanes $i]) cget -minimum]
  594.       set _minheight($i) [expr $minaft + (2 * $margaft)]
  595.       incr totMinHeight $_minheight($i)
  596.     }
  597.     set _dragging [expr $_dimension > $totMinHeight]
  598.  
  599.     grab  $itk_component(sash$num)
  600.     raise $itk_component(separator$num)
  601.     raise $itk_component(sash$num)
  602.     
  603.     $itk_component(sash$num) configure -relief sunken
  604. }
  605.  
  606. # ------------------------------------------------------------------
  607. # PROTECTED METHOD: _endGrip where num
  608. #
  609. # Ends the sash drag and drop operation.
  610. # ------------------------------------------------------------------
  611. body iwidgets::Panedwindow::_endGrip {where num} {
  612.     $itk_component(sash$num) configure -relief raised
  613.     grab release $itk_component(sash$num)
  614.     if {$_dragging} {
  615.       _calcFraction [expr $_sashloc($num) + $where] $num
  616.       _placePanes [expr $_minsashmoved - 1] $_maxsashmoved
  617.       set _dragging 0
  618.     }
  619. }
  620.  
  621. # ------------------------------------------------------------------
  622. # PROTECTED METHOD: _configGrip where num
  623. #
  624. # Configure  action for sash.
  625. # ------------------------------------------------------------------
  626. body iwidgets::Panedwindow::_configGrip {where num} {
  627.    set _sashloc($num) $where
  628. }
  629.  
  630. # ------------------------------------------------------------------
  631. # PROTECTED METHOD: _handleGrip where num
  632. #
  633. # Motion action for sash.
  634. # ------------------------------------------------------------------
  635. body iwidgets::Panedwindow::_handleGrip {where num} {
  636.  if {$_dragging} {
  637.   _moveSash [expr $where + $_sashloc($num)] $num
  638.   incr _movecount
  639.   if {$_movecount>4} {
  640.     set _movecount 0
  641.     update idletasks
  642.   }
  643.  }
  644. }
  645.  
  646. # ------------------------------------------------------------------
  647. # PROTECTED METHOD: _moveSash where num
  648. #
  649. # Move the sash to the absolute pixel location
  650. # ------------------------------------------------------------------
  651. body iwidgets::Panedwindow::_moveSash {where num} {
  652.   set _minsashmoved [expr ($_minsashmoved<$num)?$_minsashmoved:$num]
  653.   set _maxsashmoved [expr ($_maxsashmoved>$num)?$_maxsashmoved:$num]
  654.   set oldfrac $_frac($num)
  655.   _calcFraction $where $num
  656.   if {$_frac($num)!=$oldfrac} { _placeSash $num }
  657. }
  658.  
  659. # ------------------------------------------------------------------
  660. # PRIVATE METHOD: _setFracArray
  661. #
  662. # Calculates the percentages for the fraction array which lists the
  663. # percentages for each pane.
  664. # ------------------------------------------------------------------
  665. body iwidgets::Panedwindow::_setFracArray {} {
  666.     set perc 0.0
  667.     if {[llength $_activePanes] != 0} {
  668.     set percIncr [expr 1.0 / [llength $_activePanes]]
  669.     }
  670.     
  671.     for {set i 0} {$i < [llength $_activePanes]} {incr i} {
  672.     set _frac($i) $perc
  673.     set perc [expr $perc + $percIncr]
  674.     }
  675.     
  676.     set _frac($i) 1.0
  677. }
  678.  
  679. # ------------------------------------------------------------------
  680. # PRIVATE METHOD: _setActivePanes
  681. #
  682. # Resets the active pane list.
  683. # ------------------------------------------------------------------
  684. body iwidgets::Panedwindow::_setActivePanes {} {
  685.     set _prevActivePanes $_activePanes
  686.  
  687.     set _activePanes {}
  688.     
  689.     foreach pane $_panes {
  690.     if {[lsearch -exact $_prevActivePanes $pane] != -1} {
  691.         lappend _activePanes $pane
  692.     }
  693.     }
  694. }
  695.  
  696. # ------------------------------------------------------------------
  697. # PRIVATE METHOD: _calcFraction where num
  698. #
  699. # Determines the fraction for the sash.  Make sure the fraction does
  700. # not go past the minimum for the pane on each side of the separator.
  701. # ------------------------------------------------------------------
  702. body iwidgets::Panedwindow::_calcFraction {where num} {
  703.     
  704.     set _lowerlimit \
  705.         [expr $_pixels([expr $num - 1]) + $_minheight([expr $num - 1])]
  706.     set _upperlimit \
  707.         [expr $_pixels([expr $num + 1]) - $_minheight($num)]
  708.     
  709.     set dir [expr $where - $_pixels($num)]
  710.  
  711.     if {$where < $_lowerlimit && $dir <= 0} {
  712.      if {$num == 1} {
  713.       set _pixels($num) $_lowerlimit
  714.      } {
  715.       _moveSash [expr $where - $_minheight([expr $num - 1])] [expr $num -1]
  716.       set _pixels($num) \
  717.          [expr $_pixels([expr $num - 1]) + $_minheight([expr $num - 1])]
  718.      }
  719.     } elseif {$where > $_upperlimit && $dir >= 0} {
  720.      if {[expr $num + 1] == [llength $_activePanes]} {
  721.       set _pixels($num) $_upperlimit
  722.      } {
  723.       _moveSash [expr $where + $_minheight($num)] [expr $num +1]
  724.       set _pixels($num) \
  725.          [expr $_pixels([expr $num + 1]) - $_minheight($num)]
  726.      }
  727.     } else {
  728.       set _pixels($num) $where
  729.     }
  730.     set _frac($num) [expr $_pixels($num).0 / $_dimension]
  731. }
  732.  
  733. # ------------------------------------------------------------------
  734. # PRIVATE METHOD: _makeSashes
  735. #
  736. # Removes any previous sashes and separators and creates new one.
  737. # ------------------------------------------------------------------
  738. body iwidgets::Panedwindow::_makeSashes {} {
  739.     #
  740.     # Remove any existing sashes and separators.
  741.     #
  742.     foreach sash $_sashes {
  743.     destroy $itk_component($sash)
  744.     }
  745.     
  746.     foreach separator $_separators {
  747.     destroy $itk_component($separator)
  748.     }
  749.     
  750.     set _sashes {}
  751.     set _separators {}
  752.     
  753.     #
  754.     # Create one less separator and sash than the number of panes.  
  755.     #
  756.     for {set id 1} {$id < [llength $_activePanes]} {incr id} {
  757.     itk_component add sash$id {
  758.         frame $itk_interior.sash$id -relief raised \
  759.             -borderwidth $itk_option(-sashborderwidth) \
  760.             -cursor $itk_option(-sashcursor) \
  761.             -width $itk_option(-sashwidth) \
  762.             -height $itk_option(-sashheight)
  763.     } {
  764.         keep -background
  765.     }
  766.     
  767.     lappend _sashes sash$id
  768.     
  769.     switch $itk_option(-orient) {
  770.         vertical {
  771.         bind $itk_component(sash$id) <Button-1> \
  772.             [code $this _startGrip %x $id]
  773.         bind $itk_component(sash$id) <B1-Motion> \
  774.             [code $this _handleGrip %x $id]
  775.         bind $itk_component(sash$id) <B1-ButtonRelease-1> \
  776.             [code $this _endGrip %x $id]
  777.         bind $itk_component(sash$id) <Configure> \
  778.                 [code $this _configGrip %x $id]
  779.         }
  780.         
  781.         horizontal {
  782.         bind $itk_component(sash$id) <Button-1> \
  783.             [code $this _startGrip %y $id]
  784.         bind $itk_component(sash$id) <B1-Motion> \
  785.             [code $this _handleGrip %y $id]
  786.         bind $itk_component(sash$id) <B1-ButtonRelease-1> \
  787.             [code $this _endGrip %y $id]
  788.         bind $itk_component(sash$id) <Configure> \
  789.                 [code $this _configGrip %y $id]
  790.         }
  791.     }
  792.     
  793.     itk_component add separator$id {
  794.         frame $itk_interior.separator$id -relief sunken \
  795.             -height $itk_option(-thickness) \
  796.             -width $itk_option(-thickness) \
  797.             -borderwidth [expr $itk_option(-thickness) / 2]
  798.     } {
  799.         keep -background -cursor
  800.     }
  801.     
  802.     lappend _separators separator$id
  803.     }
  804. }
  805.  
  806. # ------------------------------------------------------------------
  807. # PRIVATE METHOD: _placeSash i
  808. #
  809. # Places the position of the sash and separator.
  810. # ------------------------------------------------------------------
  811. body iwidgets::Panedwindow::_placeSash {i} {
  812.     if {$itk_option(-orient) == "horizontal"} {
  813.     place $itk_component(separator$i) -in $itk_component(hull) \
  814.         -x 0 -relwidth 1 -rely $_frac($i) -anchor w \
  815.         -height $itk_option(-thickness)
  816.     
  817.     if {$itk_option(-sashindent) < 0} {
  818.         set sashPos [expr $_width + $itk_option(-sashindent)]
  819.         set sashAnchor e
  820.     } else {
  821.         set sashPos $itk_option(-sashindent)
  822.         set sashAnchor w
  823.     }
  824.     
  825.     place $itk_component(sash$i) -in $itk_component(hull) \
  826.         -x $sashPos -rely $_frac($i) -anchor $sashAnchor
  827.     
  828.     } else {
  829.     place $itk_component(separator$i) -in $itk_component(hull) \
  830.         -y 0 -relheight 1 -relx $_frac($i) -anchor n \
  831.         -width $itk_option(-thickness)
  832.     
  833.     if {$itk_option(-sashindent) < 0} {
  834.         set sashPos [expr $_height + $itk_option(-sashindent)]
  835.         set sashAnchor s
  836.     } else {
  837.         set sashPos $itk_option(-sashindent)
  838.         set sashAnchor n
  839.     }
  840.     
  841.     place $itk_component(sash$i) -in $itk_component(hull) \
  842.         -y $sashPos -relx $_frac($i) -anchor $sashAnchor
  843.     }
  844. }
  845.  
  846. # ------------------------------------------------------------------
  847. # PRIVATE METHOD: _placePanes
  848. #
  849. # Resets the panes of the window following movement of the sash.
  850. # ------------------------------------------------------------------
  851. body iwidgets::Panedwindow::_placePanes {{start 0} {end end}} {
  852.      if {$end=="end"} { set end [expr [llength $_activePanes] - 1] }
  853.      set _updatePanes [lrange $_activePanes $start $end]
  854.      if {$_updatePanes == $_activePanes} {
  855.        set _forgetPanes $_panes
  856.      } {
  857.        set _forgetPanes $_updatePanes
  858.      }
  859.     foreach pane $_forgetPanes {
  860.     place forget $itk_component($pane)
  861.     }
  862.    
  863.     
  864.     if {$itk_option(-orient) == "horizontal"} {
  865.     set i $start
  866.     foreach pane $_updatePanes {
  867.         place $itk_component($pane) -in $itk_component(hull) \
  868.             -x 0 -rely $_frac($i) -relwidth 1 \
  869.             -relheight [expr $_frac([expr $i + 1]) - $_frac($i)]
  870.         incr i
  871.     }
  872.     
  873.     } else {
  874.     set i $start
  875.     foreach pane $_updatePanes {
  876.         place $itk_component($pane) -in $itk_component(hull) \
  877.             -y 0 -relx $_frac($i) -relheight 1 \
  878.             -relwidth [expr $_frac([expr $i + 1]) - $_frac($i)]
  879.         incr i
  880.     }
  881.     
  882.     }
  883.  
  884.     for {set i [expr $start+1]} {$i <= $end} {incr i} {
  885.     if {[array names itk_component separator$i] != ""} {
  886.         _placeSash $i
  887.         raise $itk_component(separator$i)
  888.         raise $itk_component(sash$i)
  889.     }
  890.     }
  891. }
  892.