OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [libgui/] [library/] [panedwindow.tcl] - Blame information for rev 1780

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
#
2
# Panedwindow  
3
# ----------------------------------------------------------------------
4
# Implements a very general panedwindow which allows for mixing resizable
5
# and non-resizable panes.  It also allows limits to be set on individual
6
# pane sizes, both minimum and maximum.
7
#
8
# The look of this widget is much like Window, instead of the Motif-like
9
# iwidget panedwindow.
10
# ----------------------------------------------------------------------
11
 
12
# Portions of this code are originally from the iwidget panedwindow which
13
# is Copyright (c) 1995 DSC Technologies Corporation 
14
 
15
itk::usual PanedWindow {
16
  keep -background -cursor
17
}
18
 
19
# ------------------------------------------------------------------
20
#                            PANEDWINDOW
21
# ------------------------------------------------------------------
22
class cyg::PanedWindow {
23
  inherit itk::Widget
24
 
25
  constructor {args} {}
26
 
27
  itk_option define -orient orient Orient horizontal
28
  itk_option define -sashwidth sashWidth SashWidth 10
29
  itk_option define -sashcolor sashColor SashColor gray
30
 
31
  public {
32
    method index {index}
33
    method childsite {args}
34
    method fraction {percentage1 percentage2 args}
35
    method add {tag args}
36
    method insert {index tag args}
37
    method delete {index}
38
    method hide {index}
39
    method replace {pane1 pane2}
40
    method show {index}
41
    method paneconfigure {index args}
42
    method reset {}
43
  }
44
 
45
  private {
46
    method _eventHandler {width height}
47
    method _startDrag {num}
48
    method _endDrag {where num}
49
    method _configDrag {where num}
50
    method _handleDrag {where num}
51
    method _moveSash {where num}
52
 
53
    method _resizeArray {}
54
    method _setActivePanes {}
55
    method _caclPos {where num}
56
    method _makeSashes {}
57
    method _placeSash {i}
58
    method _placePanes {{start 0} {end end} {forget 0}}
59
 
60
    variable _initialized 0      ;# flag set when widget is first configured
61
    variable _sashes {}         ;# List of sashes.
62
 
63
    # Pane information
64
    variable _panes {}          ;# List of panes.
65
    variable _activePanes {}    ;# List of active panes.
66
    variable _where             ;# Array of relative positions
67
    variable _ploc              ;# Array of pixel positions
68
    variable _frac              ;# Array of relative pane sizes
69
    variable _pixels            ;# Array of sizes in pixels for non-resizable panes
70
    variable _max               ;# Array of pane maximum locations
71
    variable _min               ;# Array of pane minimum locations
72
    variable _pmin              ;# Array of pane minimum size
73
    variable _pmax              ;# Array of pane maximum size
74
 
75
    variable _dimension 0        ;# width or height of window
76
    variable _dir "height"      ;# resizable direction, "height" or "width"
77
    variable _rPixels
78
 
79
    variable _sashloc          ;# Array of dist of sash from above/left.
80
 
81
    variable _minsashmoved     ;# Lowest sash moved during dragging.
82
    variable _maxsashmoved     ;# Highest sash moved during dragging.
83
 
84
    variable _width 0            ;# hull's width.
85
    variable _height 0           ;# hull's height.
86
    variable _unique -1         ;# Unique number for pane names.
87
  }
88
}
89
 
90
#
91
# Provide a lowercased access method for the PanedWindow class.
92
# 
93
proc ::cyg::panedwindow {pathName args} {
94
  uplevel ::cyg::PanedWindow $pathName $args
95
}
96
 
97
#
98
# Use option database to override default resources of base classes.
99
#
100
option add *PanedWindow.width 10 widgetDefault
101
option add *PanedWindow.height 10 widgetDefault
102
 
103
# ------------------------------------------------------------------
104
#                        CONSTRUCTOR
105
# ------------------------------------------------------------------
106
body cyg::PanedWindow::constructor {args} {
107
  itk_option add hull.width hull.height
108
 
109
  pack propagate $itk_component(hull) no
110
 
111
  bind pw-config-$this <Configure> [code $this _eventHandler %w %h]
112
  bindtags $itk_component(hull) \
113
    [linsert [bindtags $itk_component(hull)] 0 pw-config-$this]
114
 
115
  eval itk_initialize $args
116
}
117
 
118
# ------------------------------------------------------------------
119
#                             OPTIONS
120
# ------------------------------------------------------------------
121
 
122
# ------------------------------------------------------------------
123
# OPTION: -orient
124
#
125
# Specifies the orientation of the sashes.  Once the paned window
126
# has been mapped, set the sash bindings and place the panes.
127
# ------------------------------------------------------------------
128
configbody cyg::PanedWindow::orient {
129
  #puts "orient $_initialized"
130
  if {$_initialized} {
131
    set orient $itk_option(-orient)
132
    if {$orient != "vertical" && $orient != "horizontal"} {
133
      error "bad orientation option \"$itk_option(-orient)\":\
134
                should be horizontal or vertical"
135
    }
136
    if {[string compare $orient "vertical"]} {
137
      set _dimension $_height
138
      set _dir "height"
139
    } else {
140
      set _dimension $_width
141
      set _dir "width"
142
    }
143
    _resizeArray
144
    _makeSashes
145
    _placePanes 0 end 1
146
  }
147
}
148
 
149
# ------------------------------------------------------------------
150
# OPTION: -sashwidth
151
#
152
# Specifies the width of the sash.
153
# ------------------------------------------------------------------
154
configbody cyg::PanedWindow::sashwidth {
155
  set pixels [winfo pixels $itk_component(hull) $itk_option(-sashwidth)]
156
  set itk_option(-sashwidth) $pixels
157
 
158
  if {$_initialized} {
159
    # FIXME
160
    for {set i 1} {$i < [llength $_panes]} {incr i} {
161
      $itk_component(sash$i) configure \
162
        -width $itk_option(-sashwidth) -height $itk_option(-sashwidth) \
163
        -borderwidth 2
164
    }
165
    for {set i 1} {$i < [llength $_panes]} {incr i} {
166
      _placeSash $i
167
    }
168
  }
169
}
170
 
171
# ------------------------------------------------------------------
172
# OPTION: -sashcolor
173
#
174
# Specifies the color of the sash.
175
# ------------------------------------------------------------------
176
configbody cyg::PanedWindow::sashcolor {
177
  if {$_initialized} {
178
    for {set i 1} {$i < [llength $_panes]} {incr i} {
179
      $itk_component(sash$i) configure -background $itk_option(-sashcolor)
180
    }
181
  }
182
}
183
 
184
# ------------------------------------------------------------------
185
#                            METHODS
186
# ------------------------------------------------------------------
187
 
188
# ------------------------------------------------------------------
189
# METHOD: index index
190
#
191
# Searches the panes in the paned window for the one with the 
192
# requested tag, numerical index, or keyword "end".  Returns the pane's 
193
# numerical index if found, otherwise error.
194
# ------------------------------------------------------------------    
195
body cyg::PanedWindow::index {index} {
196
  if {[llength $_panes] > 0} {
197
    if {[regexp {(^[0-9]+$)} $index]} {
198
      if {$index < [llength $_panes]} {
199
        return $index
200
      } else {
201
        error "PanedWindow index \"$index\" is out of range"
202
      }
203
    } elseif {$index == "end"} {
204
      return [expr [llength $_panes] - 1]
205
    } else {
206
      if {[set idx [lsearch $_panes $index]] != -1} {
207
        return $idx
208
      }
209
      error "bad PanedWindow index \"$index\": must be number, end,\
210
                    or pattern"
211
    }
212
  } else {
213
    error "PanedWindow \"$itk_component(hull)\" has no panes"
214
  }
215
}
216
 
217
# ------------------------------------------------------------------
218
# METHOD: childsite ?index?
219
#
220
# Given an index return the specifc childsite path name.  Invoked 
221
# without an index return a list of all the child site panes.  The 
222
# list is ordered from the near side (left/top).
223
# ------------------------------------------------------------------
224
body cyg::PanedWindow::childsite {args} {
225
  #puts "childsite $args ($_initialized)"
226
 
227
  if {[llength $args] == 0} {
228
    set children {}
229
    foreach pane $_panes {
230
      lappend children [$itk_component($pane) childSite]
231
    }
232
    return $children
233
  } else {
234
    set index [index [lindex $args 0]]
235
    return [$itk_component([lindex $_panes $index]) childSite]
236
  }
237
}
238
 
239
 
240
# ------------------------------------------------------------------
241
# METHOD: add tag ?option value option value ...?
242
#
243
# Add a new pane to the paned window to the far (right/bottom) side.
244
# The method takes additional options which are passed on to the 
245
# pane constructor.  These include -margin, and -minimum.  The path 
246
# of the pane is returned.
247
# ------------------------------------------------------------------
248
body cyg::PanedWindow::add {tag args} {
249
  itk_component add $tag {
250
    eval cyg::Pane $itk_interior.pane[incr _unique] $args
251
  } {
252
    keep -background -cursor
253
  }
254
 
255
  lappend _panes $tag
256
  lappend _activePanes $tag
257
  reset
258
  return $itk_component($tag)
259
}
260
 
261
# ------------------------------------------------------------------
262
# METHOD: insert index tag ?option value option value ...?
263
#
264
# Insert the specified pane in the paned window just before the one 
265
# given by index.  Any additional options which are passed on to the 
266
# pane constructor.  These include -margin, -minimum.  The path of 
267
# the pane is returned.
268
# ------------------------------------------------------------------
269
body cyg::PanedWindow::insert {index tag args} {
270
  itk_component add $tag {
271
    eval cyg::Pane $itk_interior.pane[incr _unique] $args
272
  } {
273
    keep -background -cursor
274
  }
275
 
276
  set index [index $index]
277
  set _panes [linsert $_panes $index $tag]
278
  lappend _activePanes $tag
279
  reset
280
  return $itk_component($tag)
281
}
282
 
283
# ------------------------------------------------------------------
284
# METHOD: delete index
285
#
286
# Delete the specified pane.
287
# ------------------------------------------------------------------
288
body cyg::PanedWindow::delete {index} {
289
  set index [index $index]
290
  set tag [lindex $_panes $index]
291
 
292
  # remove the itk component
293
  destroy $itk_component($tag)
294
  # remove it from panes list
295
  set _panes [lreplace $_panes $index $index]
296
 
297
  # remove its _frac value
298
  set ind [lsearch -exact $_activePanes $tag]
299
  if {$ind != -1 && [info exists _frac($ind)]} {
300
    unset _frac($ind)
301
  }
302
 
303
  # this will reset _activePane and resize things
304
  reset
305
}
306
 
307
# ------------------------------------------------------------------
308
# METHOD: hide index
309
#
310
# Remove the specified pane from the paned window. 
311
# ------------------------------------------------------------------
312
body cyg::PanedWindow::hide {index} {
313
  set index [index $index]
314
  set tag [lindex $_panes $index]
315
 
316
  if {[set idx [lsearch -exact $_activePanes $tag]] != -1} {
317
    set _activePanes [lreplace $_activePanes $idx $idx]
318
    if {[info exists _frac($idx)]} {unset _frac($idx)}
319
  }
320
 
321
  reset
322
}
323
 
324
body cyg::PanedWindow::replace {pane1 pane2} {
325
  set ind1 [lsearch -exact $_activePanes $pane1]
326
  if {$ind1 == -1} {
327
    error "$pane1 is not an active pane name."
328
  }
329
  set ind2 [lsearch -exact $_panes $pane2]
330
  if {$ind2 == -1} {
331
    error "Pane $pane2 does not exist."
332
  }
333
  set _activePanes [lreplace $_activePanes $ind1 $ind1 $pane2]
334
  _placePanes 0 $ind1 1
335
}
336
 
337
# ------------------------------------------------------------------
338
# METHOD: show index
339
#
340
# Display the specified pane in the paned window.
341
# ------------------------------------------------------------------
342
body cyg::PanedWindow::show {index} {
343
  set index [index $index]
344
  set tag [lindex $_panes $index]
345
 
346
  if {[lsearch -exact $_activePanes $tag] == -1} {
347
    lappend _activePanes $tag
348
  }
349
 
350
  reset
351
}
352
 
353
# ------------------------------------------------------------------
354
# METHOD: paneconfigure index ?option? ?value option value ...?
355
#
356
# Configure a specified pane.  This method allows configuration of
357
# panes from the PanedWindow level.  The options may have any of the 
358
# values accepted by the add method.
359
# ------------------------------------------------------------------
360
body cyg::PanedWindow::paneconfigure {index args} {
361
  set index [index $index]
362
  set tag [lindex $_panes $index]
363
  return [uplevel $itk_component($tag) configure $args]
364
}
365
 
366
# ------------------------------------------------------------------
367
# METHOD: reset
368
#
369
# Redisplay the panes based on the default percentages of the panes.
370
# ------------------------------------------------------------------
371
body cyg::PanedWindow::reset {} {
372
  if {$_initialized && [llength $_panes]} {
373
    #puts RESET
374
    _setActivePanes
375
    _resizeArray
376
    _makeSashes
377
    _placePanes 0 end 1
378
  }
379
}
380
 
381
# ------------------------------------------------------------------
382
# PRIVATE METHOD: _setActivePanes
383
#
384
# Resets the active pane list.
385
# ------------------------------------------------------------------
386
body cyg::PanedWindow::_setActivePanes {} {
387
  set _prevActivePanes $_activePanes
388
  set _activePanes {}
389
 
390
  foreach pane $_panes {
391
    if {[lsearch -exact $_prevActivePanes $pane] != -1} {
392
      lappend _activePanes $pane
393
    }
394
  }
395
}
396
 
397
# ------------------------------------------------------------------
398
# PROTECTED METHOD: _eventHandler
399
#
400
# Performs operations necessary following a configure event.  This
401
# includes placing the panes.
402
# ------------------------------------------------------------------
403
body cyg::PanedWindow::_eventHandler {width height} {
404
  #puts "Event $width $height"
405
  set _width $width
406
  set _height $height
407
  if {[string compare $itk_option(-orient) "vertical"]} {
408
    set _dimension $_height
409
    set _dir "height"
410
  } else {
411
    set _dimension $_width
412
    set _dir "width"
413
  }
414
 
415
  if {$_initialized} {
416
    _resizeArray
417
    _placePanes
418
  } else {
419
    set _initialized 1
420
    reset
421
  }
422
}
423
 
424
# ------------------------------------------------------------------
425
# PRIVATE METHOD: _resizeArray
426
#
427
# Recalculates the sizes and positions of all the panes.
428
# This is only done at startup, when the window size changes, when
429
# a new pane is added, or the orientation is changed.
430
#
431
# _frac($i) contains:
432
#               % of resizable space when pane$i is resizable
433
# _pixels($i) contains
434
#               pixels when pane$i is not resizable
435
#
436
# _where($i) contains the relative position of the top of pane$i
437
# ------------------------------------------------------------------
438
body cyg::PanedWindow::_resizeArray {} {
439
  set numpanes 0
440
  set _rPixels 0
441
  set totalFrac 0.0
442
  set numfreepanes 0
443
 
444
  #puts "sresizeArray dim=$_dimension dir=$_dir"
445
 
446
  # first pass. Count the number of resizable panes and
447
  # the pixels reserved for non-resizable panes.
448
  set i 0
449
  foreach p $_activePanes {
450
    set _resizable($i) [$itk_component($p) cget -resizable]
451
    if {$_resizable($i)} {
452
      # remember pane min and max
453
      set _pmin($i) [$itk_component($p) cget -minimum]
454
      set _pmax($i) [$itk_component($p) cget -maximum]
455
 
456
      incr numpanes
457
      if {[info exists _frac($i)]} {
458
        # sum up all the percents
459
        set totalFrac [expr $totalFrac + $_frac($i)]
460
      } else {
461
        # number of new windows not yet sized
462
        incr numfreepanes
463
      }
464
    } else {
465
      set _pixels($i) [winfo req$_dir $itk_component($p)]
466
      set _pmin($i) $_pixels($i)
467
      set _pmax($i) $_pixels($i)
468
      incr _rPixels $_pixels($i)
469
    }
470
    incr i
471
  }
472
  set totalpanes $i
473
 
474
  #puts "numpanes=$numpanes nfp=$numfreepanes _rPixels=$_rPixels  totalFrac=$totalFrac"
475
 
476
  if {$numfreepanes} {
477
    # set size for the new window(s) to average size
478
    if {$totalFrac > 0.0} {
479
      set freepanesize [expr $totalFrac / ($numpanes - $numfreepanes)]
480
    } else {
481
      set freepanesize [expr 1.0 / $numpanes.0]
482
    }
483
    for {set i 0} {$i < $totalpanes} {incr i} {
484
      if {$_resizable($i) && ![info exists _frac($i)]} {
485
        set _frac($i) $freepanesize
486
        set totalFrac [expr $totalFrac + $_frac($i)]
487
      }
488
    }
489
  }
490
 
491
  set done 0
492
 
493
  while {!$done} {
494
    # force to a reasonable value
495
    if {$totalFrac <= 0.0} { set totalFrac 1.0 }
496
 
497
    # scale the _frac array
498
    if {$totalFrac > 1.01 || $totalFrac < 0.99} {
499
      set cor [expr 1.0 / $totalFrac]
500
      set totalFrac 0.0
501
      for {set i 0} {$i < $totalpanes} {incr i} {
502
        if {$_resizable($i)} {
503
          set _frac($i) [expr $_frac($i) * $cor]
504
          set totalFrac [expr $totalFrac + $_frac($i)]
505
        }
506
      }
507
    }
508
 
509
    # bounds checking; look for panes that are too small or too large
510
    # if one is found, fix its size at the min or max and mark the
511
    # window non-resizable. Adjust percents and try again.
512
    set done 1
513
    for {set i 0} {$i < $totalpanes} {incr i} {
514
      if {$_resizable($i)} {
515
        set _pixels($i) [expr int($_frac($i) * ($_dimension - $_rPixels.0))]
516
        if {$_pixels($i) < $_pmin($i)} {
517
          set _resizable($i) 0
518
          set totalFrac [expr $totalFrac - $_frac($i)]
519
          set _pixels($i) $_pmin($i)
520
          incr  _rPixels $_pixels($i)
521
          set done 0
522
          break
523
        } elseif {$_pmax($i) && $_pixels($i) > $_pmax($i)} {
524
          set _resizable($i) 0
525
          set totalFrac [expr $totalFrac - $_frac($i)]
526
          set _pixels($i) $_pmax($i)
527
          incr  _rPixels $_pixels($i)
528
          set done 0
529
          break
530
        }
531
      }
532
    }
533
  }
534
 
535
  # Done adjusting. Now build pane position arrays.  These are designed
536
  # to minimize calculations while resizing.
537
  # Note: position of sash $i = position of top of pane $i
538
  # _where($i): relative (0.0 - 1.0) position of sash $i
539
  # _ploc($i): position in pixels of sash $i
540
  # _max($i): maximum position in pixels of sash $i (0 = no max)
541
  set _where(0) 0.0
542
  set _ploc(0) 0
543
  set _max(0) 0
544
  set _min(0) 0
545
  # calculate the percentage of resizable space
546
  set resizePerc [expr 1.0 - ($_rPixels.0 / $_dimension)]
547
  for {set i 1; set n 0} {$i < $totalpanes} {incr i; incr n} {
548
    if {$_resizable($n)} {
549
      set _where($i) [expr $_where($n) + ($_frac($n) * $resizePerc)]
550
    } else {
551
      set _where($i) [expr $_where($n) + [expr $_pixels($n).0 / $_dimension]]
552
    }
553
    set _ploc($i) [expr $_ploc($n) + $_pixels($n)]
554
    if {$_pmax($n)} {
555
      set _max($i) [expr $_max($n) + $_pmax($n)]
556
    } else {
557
      set _max($i) 0
558
    }
559
    set _min($i) [expr $_min($n) + $_pmin($n)]
560
    #puts "where($i)=$_where($i)"
561
    #puts "ploc($i)=$_ploc($i)"
562
    #puts "max($i)=$_max($i)"
563
    #puts "min($i)=$_min($i)"
564
  }
565
  set _ploc($i) $_dimension
566
  set _where($i) 1.0
567
}
568
 
569
# ------------------------------------------------------------------
570
# PROTECTED METHOD: _startDrag num
571
#
572
# Starts the sash drag and drop operation.  At the start of the drag
573
# operation all the information is known as for the upper and lower
574
# limits for sash movement.  The calculation is made at this time and
575
# stored in protected variables for later access during the drag
576
# handling routines.
577
# ------------------------------------------------------------------
578
body cyg::PanedWindow::_startDrag {num} {
579
  #puts "startDrag $num"
580
 
581
  set _minsashmoved $num
582
  set _maxsashmoved $num
583
 
584
  grab  $itk_component(sash$num)
585
}
586
 
587
# ------------------------------------------------------------------
588
# PROTECTED METHOD: _endDrag where num
589
#
590
# Ends the sash drag and drop operation.
591
# ------------------------------------------------------------------
592
body cyg::PanedWindow::_endDrag {where num} {
593
  #puts "endDrag $where $num"
594
 
595
  grab release $itk_component(sash$num)
596
 
597
  # set new _frac values
598
  for {set i [expr $_minsashmoved-1]} {$i <= $_maxsashmoved} {incr i} {
599
    set _frac($i) \
600
      [expr ($_ploc([expr $i+1]).0 - $_ploc($i)) / ($_dimension - $_rPixels)]
601
  }
602
}
603
 
604
# ------------------------------------------------------------------
605
# PROTECTED METHOD: _configDrag where num
606
#
607
# Configure  action for sash.
608
# ------------------------------------------------------------------
609
body cyg::PanedWindow::_configDrag {where num} {
610
  set _sashloc($num) $where
611
}
612
 
613
# ------------------------------------------------------------------
614
# PROTECTED METHOD: _handleDrag where num
615
#
616
# Motion action for sash.
617
# ------------------------------------------------------------------
618
body cyg::PanedWindow::_handleDrag {where num} {
619
  #puts "handleDrag $where $num"
620
  _moveSash [expr $where + $_sashloc($num)] $num
621
  _placePanes [expr $_minsashmoved - 1] $_maxsashmoved
622
}
623
 
624
# ------------------------------------------------------------------
625
# PROTECTED METHOD: _moveSash where num
626
#
627
# Move the sash to the absolute pixel location
628
# ------------------------------------------------------------------
629
body cyg::PanedWindow::_moveSash {where num} {
630
  #puts "moveSash $where $num"
631
  set _minsashmoved [expr ($_minsashmoved<$num)?$_minsashmoved:$num]
632
  set _maxsashmoved [expr ($_maxsashmoved>$num)?$_maxsashmoved:$num]
633
  _caclPos $where $num
634
}
635
 
636
 
637
# ------------------------------------------------------------------
638
# PRIVATE METHOD: _caclPos where num
639
#
640
# Determines the new position for the sash.  Make sure theposition does
641
# not go past the minimum for the pane on each side of the sash.
642
# ------------------------------------------------------------------
643
body cyg::PanedWindow::_caclPos {where num} {
644
  #puts "calcPos $num $where"
645
  set dir [expr $where - $_ploc($num)]
646
  if {$dir == 0} { return }
647
 
648
  # simplify expressions by computing these now
649
  set m [expr $num-1]
650
  set p [expr $num+1]
651
 
652
  # we have squeezed the pane below us to the limit
653
  set lower1 [expr $_ploc($m) + $_pmin($m)]
654
  set lower2 0
655
  if {$_pmax($num)} {
656
    # we have stretched the pane above us to the limit
657
    set lower2 [expr $_ploc($p) - $_pmax($num)]
658
  }
659
 
660
  set upper1 9999 ;# just a large number
661
  if {$_pmax($m)} {
662
    # we have stretched the pane above us to the limit
663
    set upper1 [expr $_ploc($m) + $_pmax($m)]
664
  }
665
  # we have squeezed the pane below us to the limit
666
  set upper2 [expr $_ploc($p) - $_pmin($num)]
667
 
668
  set done 0
669
 
670
  #puts "lower1=$lower1 lower2=$lower2 _min($num)=$_min($num)"
671
  #puts "upper1=$upper1 upper2=$upper2 _max($num)=$_max($num)"
672
  if {$dir < 0 && $where > $_min($num)} {
673
    if {$where < $lower2} {
674
      set done 1
675
      if {$p == [llength $_activePanes]} {
676
        set _ploc($num) $upper2
677
      } else {
678
        _moveSash [expr $where + $_pmax($num)] $p
679
        set _ploc($num) [expr $_ploc($p) - $_pmax($num)]
680
      }
681
    }
682
    if {$where < $lower1} {
683
      set done 1
684
      if {$num == 1} {
685
        set _ploc($num) $lower1
686
      } else {
687
        _moveSash [expr $where - $_pmin($m)] $m
688
        set _ploc($num) [expr $_ploc($m) + $_pmin($m)]
689
      }
690
    }
691
  } elseif {$dir > 0 && ($_max($num) == 0 || $where < $_max($num))} {
692
    if {$where > $upper1} {
693
      set done 1
694
      if {$num == 1} {
695
        set _ploc($num) $upper1
696
      } else {
697
        _moveSash [expr $where - $_pmax($m)] $m
698
        set _ploc($num) [expr $_ploc($m) + $_pmax($m)]
699
      }
700
    }
701
    if {$where > $upper2} {
702
      set done 1
703
      if {$p == [llength $_activePanes]} {
704
        set _ploc($num) $upper2
705
      } else {
706
        _moveSash [expr $where + $_pmin($num)] $p
707
        set _ploc($num) [expr $_ploc($p) - $_pmin($num)]
708
      }
709
    }
710
  }
711
 
712
  if {!$done} {
713
    if {!($_max($num) > 0 && $where > $_max($num)) && $where >= $_min($num)} {
714
      #puts "ploc($num)=$where"
715
      set _ploc($num) $where
716
    }
717
  }
718
  set _where($num) [expr $_ploc($num).0 / $_dimension]
719
}
720
 
721
# ------------------------------------------------------------------
722
# PRIVATE METHOD: _makeSashes
723
#
724
# Removes any previous sashes and creates new ones.
725
# ------------------------------------------------------------------
726
body cyg::PanedWindow::_makeSashes {} {
727
  #
728
  # Remove any existing sashes.
729
  #
730
  foreach sash $_sashes {
731
    destroy $itk_component($sash)
732
  }
733
 
734
  set _sashes {}
735
  set skipped_first 0
736
  #
737
  # Create necessary number of sashes
738
  #
739
  for {set id 0} {$id < [llength $_activePanes]} {incr id} {
740
    set p [lindex $_activePanes $id]
741
    if {[$itk_component($p) cget -resizable]} {
742
      if {$skipped_first == 0} {
743
        # create the first sash when we see the 2nd resizable pane
744
        incr skipped_first
745
      } else {
746
        # create sash
747
 
748
        itk_component add sash$id {
749
          frame $itk_interior.sash$id -relief raised \
750
            -height $itk_option(-sashwidth) \
751
            -width $itk_option(-sashwidth) \
752
            -borderwidth 2
753
        } {
754
          keep -background
755
        }
756
        lappend _sashes sash$id
757
 
758
        set com $itk_component(sash$id)
759
        $com configure -background $itk_option(-sashcolor)
760
        bind $com <Button-1> [code $this _startDrag $id]
761
 
762
        switch $itk_option(-orient) {
763
          vertical {
764
            bind $com <B1-Motion> \
765
              [code $this _handleDrag %x $id]
766
            bind $com <B1-ButtonRelease-1> \
767
              [code $this _endDrag %x $id]
768
            bind $com <Configure> \
769
              [code $this _configDrag %x $id]
770
            # FIXME Windows should have a different cirsor
771
            $com configure -cursor sb_h_double_arrow
772
          }
773
 
774
          horizontal {
775
            bind $com <B1-Motion> \
776
              [code $this _handleDrag %y $id]
777
            bind $com <B1-ButtonRelease-1> \
778
              [code $this _endDrag %y $id]
779
            bind $com <Configure> \
780
              [code $this _configDrag %y $id]
781
            # FIXME Windows should have a different cirsor
782
            $com configure -cursor sb_v_double_arrow
783
          }
784
        }
785
      }
786
    }
787
  }
788
}
789
 
790
# ------------------------------------------------------------------
791
# PRIVATE METHOD: _placeSash i
792
#
793
# Places the position of the sash
794
# ------------------------------------------------------------------
795
body cyg::PanedWindow::_placeSash {i} {
796
  if {[string compare $itk_option(-orient) "vertical"]} {
797
    place $itk_component(sash$i) -in $itk_component(hull) \
798
      -x 0 -relwidth 1 -rely $_where($i) -anchor w \
799
      -height $itk_option(-sashwidth)
800
  } else {
801
    place $itk_component(sash$i) -in $itk_component(hull) \
802
      -y 0 -relheight 1 -relx $_where($i) -anchor n \
803
      -width $itk_option(-sashwidth)
804
  }
805
}
806
 
807
# ------------------------------------------------------------------
808
# PRIVATE METHOD: _placePanes
809
#
810
# Resets the panes of the window following movement of the sash.
811
# ------------------------------------------------------------------
812
body cyg::PanedWindow::_placePanes {{start 0} {end end} {forget 0}} {
813
  #puts "placeplanes $start $end"
814
  if {$end=="end"} { set end [expr [llength $_activePanes] - 1] }
815
  set _updatePanes [lrange $_activePanes $start $end]
816
 
817
  if {$forget} {
818
    if {$_updatePanes == $_activePanes} {
819
      set _forgetPanes $_panes
820
    } else {
821
      set _forgetPanes $_updatePanes
822
    }
823
    foreach pane $_forgetPanes {
824
      place forget $itk_component($pane)
825
    }
826
  }
827
 
828
  if {[string compare $itk_option(-orient) "vertical"]} {
829
    set i $start
830
    foreach pane $_updatePanes {
831
      place $itk_component($pane) -in $itk_component(hull) \
832
        -x 0 -rely $_where($i) -relwidth 1 \
833
        -relheight [expr $_where([expr $i + 1]) - $_where($i)]
834
      incr i
835
    }
836
  } else {
837
    set i $start
838
    foreach pane $_updatePanes {
839
      place $itk_component($pane) -in $itk_component(hull) \
840
        -y 0 -relx $_where($i) -relheight 1 \
841
        -relwidth [expr $_where([expr $i + 1]) - $_where($i)]
842
      incr i
843
    }
844
  }
845
 
846
  for {set i [expr $start+1]} {$i <= $end} {incr i} {
847
    if {[lsearch -exact $_sashes sash$i] != -1} {
848
      _placeSash $i
849
    }
850
  }
851
}

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.