1#
2# Tabnotebook Widget
3# ----------------------------------------------------------------------
4# The Tabnotebook command creates a new window (given by the pathName
5# argument) and makes it into a Tabnotebook widget. Additional options,
6# described above may be specified on the command line or in the option
7# database to configure aspects of the Tabnotebook such as its colors,
8# font, and text. The Tabnotebook command returns its pathName argument.
9# At the time this command is invoked, there must not exist a window
10# named pathName, but pathName's parent must exist.
11#
12# A Tabnotebook is a widget that contains a set of tabbed pages. It
13# displays one page from the set as the selected page. A Tab displays
14# the label for the page to which it is attached and serves as a page
15# selector.   When a page's tab is selected, the page's contents are
16# displayed in the page area. The selected tab has a three-dimensional
17# effect to make it appear to float above the other tabs. The tabs are
18# displayed as a group along either the left, top, right, or bottom
19# edge. When first created a Tabnotebook has no pages. Pages may be
20# added or deleted using widget commands described below.
21#
22# A special option may be provided to the Tabnotebook. The -auto
23# option specifies whether the Tabnotebook will automatically handle
24# the unpacking and packing of pages when pages are selected. A value
25# of true sig nifies that the notebook will automatically manage it. This
26# is the default value. A value of false signifies the notebook will not
27# perform automatic switching of pages.
28#
29# ----------------------------------------------------------------------
30#  AUTHOR: Bill W. Scott
31#
32#  CURRENT MAINTAINER: Chad Smith --> csmith@adc.com or itclguy@yahoo.com
33#
34#  @(#) $Id: tabnotebook.itk,v 1.7 2002/09/05 20:19:35 smithc Exp $
35# ----------------------------------------------------------------------
36#            Copyright (c) 1995 DSC Technologies Corporation
37# ======================================================================
38# Permission to use, copy, modify, distribute and license this software
39# and its documentation for any purpose, and without fee or written
40# agreement with DSC, is hereby granted, provided that the above copyright
41# notice appears in all copies and that both the copyright notice and
42# warranty disclaimer below appear in supporting documentation, and that
43# the names of DSC Technologies Corporation or DSC Communications
44# Corporation not be used in advertising or publicity pertaining to the
45# software without specific, written prior permission.
46#
47# DSC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
48# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, AND NON-
49# INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND THE
50# AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE MAINTENANCE,
51# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. IN NO EVENT SHALL
52# DSC BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
53# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
54# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTUOUS ACTION,
55# ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
56# SOFTWARE.
57# ======================================================================
58
59#
60# Default resources.
61#
62option add *Tabnotebook.borderWidth 2 widgetDefault
63option add *Tabnotebook.state normal widgetDefault
64option add *Tabnotebook.disabledForeground #a3a3a3 widgetDefault
65option add *Tabnotebook.scrollCommand {} widgetDefault
66option add *Tabnotebook.equalTabs true widgetDefault
67option add *Tabnotebook.font \
68	-Adobe-Helvetica-Bold-R-Normal--*-120-*-*-*-*-*-* widgetDefault
69option add *Tabnotebook.width 300 widgetDefault
70option add *Tabnotebook.height 150 widgetDefault
71option add *Tabnotebook.foreground Black widgetDefault
72option add *Tabnotebook.background #d9d9d9 widgetDefault
73option add *Tabnotebook.tabForeground Black widgetDefault
74option add *Tabnotebook.tabBackground #d9d9d9 widgetDefault
75option add *Tabnotebook.backdrop #d9d9d9 widgetDefault
76option add *Tabnotebook.margin 4 widgetDefault
77option add *Tabnotebook.tabBorders true widgetDefault
78option add *Tabnotebook.bevelAmount 0 widgetDefault
79option add *Tabnotebook.raiseSelect false widgetDefault
80option add *Tabnotebook.auto true widgetDefault
81option add *Tabnotebook.start 4 widgetDefault
82option add *Tabnotebook.padX 4 widgetDefault
83option add *Tabnotebook.padY 4 widgetDefault
84option add *Tabnotebook.gap overlap widgetDefault
85option add *Tabnotebook.angle 15 widgetDefault
86option add *Tabnotebook.tabPos s widgetDefault
87
88#
89# Usual options.
90#
91itk::usual Tabnotebook {
92    keep -backdrop -background -borderwidth -cursor -disabledforeground \
93	 -font -foreground -tabbackground -tabforeground
94}
95
96# ------------------------------------------------------------------
97#                            TABNOTEBOOK
98# ------------------------------------------------------------------
99itcl::class iwidgets::Tabnotebook {
100    inherit itk::Widget
101
102    constructor {args} {}
103    destructor {}
104
105    itk_option define -borderwidth borderWidth BorderWidth 2
106    itk_option define -state state State normal
107    itk_option define \
108	    -disabledforeground disabledForeground DisabledForeground #a3a3a3
109    itk_option define -scrollcommand scrollCommand ScrollCommand {}
110    itk_option define -equaltabs equalTabs EqualTabs true
111    itk_option define -font font Font \
112	    -Adobe-Helvetica-Bold-R-Normal--*-120-*-*-*-*-*-*
113    itk_option define -width width Width 300
114    itk_option define -height height Height 150
115    itk_option define -foreground foreground Foreground Black
116    itk_option define -background background Background  #d9d9d9
117    itk_option define -tabforeground tabForeground TabForeground Black
118    itk_option define -tabbackground tabBackground TabBackground #d9d9d9
119    itk_option define -backdrop backdrop Backdrop #d9d9d9
120    itk_option define -margin margin Margin 4
121    itk_option define -tabborders tabBorders TabBorders true
122    itk_option define -bevelamount bevelAmount BevelAmount 0
123    itk_option define -raiseselect raiseSelect RaiseSelect false
124    itk_option define -auto auto Auto true
125    itk_option define -start start Start 4
126    itk_option define -padx padX PadX 4
127    itk_option define -pady padY PadY 4
128    itk_option define -gap gap Gap overlap
129    itk_option define -angle angle Angle 15
130    itk_option define -tabpos tabPos TabPos s
131
132    public method add { args }
133    public method configure { args }
134    public method childsite { args }
135    public method delete { args }
136    public method index { args }
137    public method insert { index args }
138    public method prev { }
139    public method next { }
140    public method pageconfigure { index args }
141    public method select { index }
142    public method view { args }
143
144    protected method _reconfigureTabset { }
145    protected method _canvasReconfigure { wid hgt }
146    protected method _pageReconfigure { pageName page wid hgt }
147
148    private method _getArgs { optList args }
149    private method _redrawBorder { wid hgt }
150    private method _recomputeBorder { }
151    private method _pack { tabPos }
152    private method _resize {newWidth_ newHeight_}
153
154    private variable _canvasWidth 0       ;# currently tabnote canvas width
155    private variable _canvasHeight 0      ;# currently tabnote canvas height
156    private variable _nbOptList {}        ;# list of notebook options available
157    private variable _tsOptList {}        ;# list of tabset options available
158
159    private variable _tabPos s            ;# holds -tabPos, because of ordering
160
161    private variable _borderRecompute false   ;# did we dirty border after cfg?
162    private variable _tabsetReconfigure false ;# did we dirty tabsets after cfg?
163
164}
165
166
167# ----------------------------------------------------------------------
168#                              CONSTRUCTOR
169# ----------------------------------------------------------------------
170itcl::body iwidgets::Tabnotebook::constructor {args} {
171    # The following conditional added for SF ticket #514222.   csmith 9/5/02
172    if {$::tk_version > 8.3} {
173      component hull configure -borderwidth 0 -padx 0 -pady 0
174    } else {
175      component hull configure -borderwidth 0
176    }
177
178    #
179    # Create the outermost canvas to maintain geometry.
180    #
181    itk_component add canvas {
182	canvas $itk_interior.canvas -highlightthickness 0
183    } {
184	keep -cursor -background -width -height
185    }
186    bind $itk_component(canvas) <Configure> [itcl::code $this _resize %w %h]
187
188
189
190    # .......................
191    # Create the NOTEBOOK
192    #
193    itk_component add notebook {
194	iwidgets::Notebook $itk_interior.canvas.notebook
195    } {
196	keep -cursor -background
197    }
198
199    #
200    # Ouch, create a dummy page, go pageconfigure to get its options
201    # and munge them into a list for later doling by pageconfigure
202    #
203    $itk_component(notebook) add
204    set nbConfigList [$itk_component(notebook) pageconfigure 0]
205    foreach config $nbConfigList {
206	lappend _nbOptList [lindex $config 0]
207    }
208    $itk_component(notebook) delete 0
209
210    #
211    # Create the tabset.
212    #
213    itk_component add tabset {
214	iwidgets::Tabset $itk_interior.canvas.tabset \
215		-command [itcl::code $this component notebook select]
216    } {
217	keep -cursor
218    }
219
220    eval itk_initialize $args
221
222    #
223    # Ouch, create a dummy tab, go tabconfigure to get its options
224    # and munge them into a list for later doling by pageconfigure
225    #
226    $itk_component(tabset) add
227    set tsConfigList [$itk_component(tabset) tabconfigure 0]
228    foreach config $tsConfigList {
229	lappend _tsOptList [lindex $config 0]
230    }
231    $itk_component(tabset) delete 0
232
233    bind $itk_component(tabset) <Configure> \
234	    [itcl::code $this _reconfigureTabset]
235
236    _pack $_tabPos
237    $itk_component(hull) configure -width [cget -width] -height [cget -height]
238}
239
240proc ::iwidgets::tabnotebook {pathName args} {
241    uplevel ::iwidgets::Tabnotebook $pathName $args
242}
243
244
245# -------------------------------------------------------------
246# DESTRUCTOR: destroy the Tabnotebook
247# -------------------------------------------------------------
248itcl::body iwidgets::Tabnotebook::destructor {} {
249}
250
251# ----------------------------------------------------------------------
252# OPTION -borderwidth
253#
254# Thickness of Notebook Border
255# ----------------------------------------------------------------------
256itcl::configbody iwidgets::Tabnotebook::borderwidth {
257    if {$itk_option(-borderwidth) != {}} {
258	#_recomputeBorder
259	set _borderRecompute true
260    }
261}
262
263# ----------------------------------------------------------------------
264# OPTION -state
265#
266# State of the tabs in the tab notebook: normal or disabled
267# ----------------------------------------------------------------------
268itcl::configbody iwidgets::Tabnotebook::state {
269    if {$itk_option(-state) != {}} {
270	$itk_component(tabset) configure -state $itk_option(-state)
271	#_reconfigureTabset
272	set _tabsetReconfigure true
273
274    }
275}
276
277# ----------------------------------------------------------------------
278# OPTION -disabledforeground
279#
280# Specifies a foreground color to use for displaying a
281# tab's label when its state is disabled.
282# ----------------------------------------------------------------------
283itcl::configbody iwidgets::Tabnotebook::disabledforeground {
284
285    if {$itk_option(-disabledforeground) != {}} {
286	$itk_component(tabset) configure \
287		-disabledforeground $itk_option(-disabledforeground)
288	#_reconfigureTabset
289	set _tabsetReconfigure true
290    }
291}
292
293# ----------------------------------------------------------------------
294# OPTION -scrollcommand
295#
296# Standard option. See options man pages.
297# ----------------------------------------------------------------------
298itcl::configbody iwidgets::Tabnotebook::scrollcommand {
299
300    if {$itk_option(-scrollcommand) != {}} {
301	$itk_component(notebook) \
302		configure -scrollcommand $itk_option(-scrollcommand)
303    }
304}
305
306# ----------------------------------------------------------------------
307# OPTION -equaltabs
308#
309# Specifies whether to force tabs to be equal sized or not.
310# A value of true means constrain tabs to be equal sized.
311# A value of false allows each tab to size based on the text
312# label size. The value may have any of the forms accepted by
313# the Tcl_GetBoolean, such as true, false, 0, 1, yes, or no.
314# ----------------------------------------------------------------------
315itcl::configbody iwidgets::Tabnotebook::equaltabs {
316
317    if {$itk_option(-equaltabs) != {}} {
318	$itk_component(tabset) \
319		configure -equaltabs $itk_option(-equaltabs)
320	#_reconfigureTabset
321	set _tabsetReconfigure true
322    }
323}
324
325# ----------------------------------------------------------------------
326# OPTION -font
327#
328# Font for tab labels when they are set to text (-label set)
329# ----------------------------------------------------------------------
330itcl::configbody iwidgets::Tabnotebook::font {
331
332    if {$itk_option(-font) != {}} {
333	$itk_component(tabset) configure -font $itk_option(-font)
334	#_reconfigureTabset
335	set _tabsetReconfigure true
336    }
337}
338
339# ----------------------------------------------------------------------
340# OPTION -width
341#
342# Width of the Tabnotebook
343# ----------------------------------------------------------------------
344itcl::configbody iwidgets::Tabnotebook::width {
345    if {$itk_option(-width) != {}} {
346	$itk_component(canvas) configure -width $itk_option(-width)
347	#_recomputeBorder
348	set _borderRecompute true
349    }
350}
351
352# ----------------------------------------------------------------------
353# OPTION -height
354#
355# Height of the Tabnotebook
356# ----------------------------------------------------------------------
357itcl::configbody iwidgets::Tabnotebook::height {
358    if {$itk_option(-height) != {}} {
359	$itk_component(canvas) configure -height $itk_option(-height)
360	#_recomputeBorder
361	set _borderRecompute true
362    }
363}
364
365# ----------------------------------------------------------------------
366# OPTION -foreground
367#
368# Specifies a foreground color to use for displaying a page
369# and its associated tab label (this is the selected state).
370# ----------------------------------------------------------------------
371itcl::configbody iwidgets::Tabnotebook::foreground {
372
373    if {$itk_option(-foreground) != {}} {
374	$itk_component(tabset) configure \
375		-selectforeground $itk_option(-foreground)
376    }
377}
378
379# ----------------------------------------------------------------------
380# OPTION -background
381#
382# Specifies a background color to use for displaying a page
383# and its associated tab bg (this is the selected state).
384# ----------------------------------------------------------------------
385itcl::configbody iwidgets::Tabnotebook::background {
386
387    if {$itk_option(-background) != {}} {
388	$itk_component(tabset) configure \
389		-selectbackground $itk_option(-background)
390	#_recomputeBorder
391	set _borderRecompute true
392    }
393}
394
395# ----------------------------------------------------------------------
396# OPTION -tabforeground
397#
398# Specifies a foreground color to use for displaying tab labels
399# when they are in their unselected state.
400# ----------------------------------------------------------------------
401itcl::configbody iwidgets::Tabnotebook::tabforeground {
402
403    if {$itk_option(-tabforeground) != {}} {
404	$itk_component(tabset) configure \
405		-foreground $itk_option(-tabforeground)
406    }
407}
408
409# ----------------------------------------------------------------------
410# OPTION -tabbackground
411#
412# Specifies a background color to use for displaying tab backgrounds
413# when they are in their unselected state.
414# ----------------------------------------------------------------------
415itcl::configbody iwidgets::Tabnotebook::tabbackground {
416
417    if {$itk_option(-tabbackground) != {}} {
418	$itk_component(tabset) configure \
419		-background $itk_option(-tabbackground)
420    }
421}
422
423# ----------------------------------------------------------------------
424# OPTION -backdrop
425#
426# Specifies a background color to use when filling in the
427# area behind the tabs.
428# ----------------------------------------------------------------------
429itcl::configbody iwidgets::Tabnotebook::backdrop {
430
431    if {$itk_option(-backdrop) != {}} {
432	$itk_component(tabset) configure \
433		-backdrop $itk_option(-backdrop)
434    }
435}
436
437# ----------------------------------------------------------------------
438# OPTION -margin
439#
440# Sets the backdrop margin between tab edge and backdrop edge
441# ----------------------------------------------------------------------
442itcl::configbody iwidgets::Tabnotebook::margin {
443    if {$itk_option(-margin) != {}} {
444	$itk_component(tabset) configure -margin $itk_option(-margin)
445    }
446}
447
448# ----------------------------------------------------------------------
449# OPTION -tabborders
450#
451# Boolean that specifies whether to draw the borders of
452# the unselected tabs (tabs in background)
453# ----------------------------------------------------------------------
454itcl::configbody iwidgets::Tabnotebook::tabborders {
455    if {$itk_option(-tabborders) != {}} {
456	$itk_component(tabset) \
457		configure -tabborders $itk_option(-tabborders)
458	#_reconfigureTabset
459	set _tabsetReconfigure true
460    }
461}
462
463# ----------------------------------------------------------------------
464# OPTION -bevelamount
465#
466# Specifies pixel size of tab corners. 0 means no corners.
467# ----------------------------------------------------------------------
468itcl::configbody iwidgets::Tabnotebook::bevelamount {
469    if {$itk_option(-bevelamount) != {}} {
470	$itk_component(tabset) \
471		configure -bevelamount $itk_option(-bevelamount)
472	#_reconfigureTabset
473	set _tabsetReconfigure true
474    }
475}
476
477# ----------------------------------------------------------------------
478# OPTION -raiseselect
479#
480# Sets whether to raise selected tabs
481# ----------------------------------------------------------------------
482itcl::configbody iwidgets::Tabnotebook::raiseselect {
483    if {$itk_option(-raiseselect) != {}} {
484	$itk_component(tabset) \
485		configure -raiseselect $itk_option(-raiseselect)
486	#_reconfigureTabset
487	set _tabsetReconfigure true
488    }
489}
490
491# ----------------------------------------------------------------------
492# OPTION -auto
493#
494# Determines whether pages are automatically unpacked and
495# packed when pages get selected.
496# ----------------------------------------------------------------------
497itcl::configbody iwidgets::Tabnotebook::auto {
498    if {$itk_option(-auto) != {}} {
499	$itk_component(notebook) configure -auto $itk_option(-auto)
500    }
501}
502
503# ----------------------------------------------------------------------
504# OPTION -start
505# ----------------------------------------------------------------------
506itcl::configbody iwidgets::Tabnotebook::start {
507
508    if {$itk_option(-start) != {}} {
509	$itk_component(tabset) configure \
510		-start $itk_option(-start)
511	#_reconfigureTabset
512	set _tabsetReconfigure true
513    }
514}
515
516# ----------------------------------------------------------------------
517# OPTION -padx
518#
519# Specifies a non-negative value indicating how much extra space
520# to request for a tab around its label in the X-direction.
521# When computing how large a window it needs, the tab will add
522# this amount to the width it would normally need The tab will
523# end up with extra internal space to the left and right of its
524# text label. This value may have any of the forms acceptable
525# to Tk_GetPixels.
526# ----------------------------------------------------------------------
527itcl::configbody iwidgets::Tabnotebook::padx {
528
529    if {$itk_option(-padx) != {}} {
530	$itk_component(tabset) configure -padx $itk_option(-padx)
531	#_reconfigureTabset
532	set _tabsetReconfigure true
533    }
534}
535
536# ----------------------------------------------------------------------
537# OPTION -pady
538#
539# Specifies a non-negative value indicating how much extra space to
540# request for a tab around its label in the Y-direction. When computing
541# how large a window it needs, the tab will add this amount to the
542# height it would normally need The tab will end up with extra internal
543# space to the top and bot tom of its text label. This value may have
544# any of the forms acceptable to Tk_GetPixels.
545# ----------------------------------------------------------------------
546itcl::configbody iwidgets::Tabnotebook::pady {
547
548    if {$itk_option(-pady) != {}} {
549	$itk_component(tabset) configure -pady $itk_option(-pady)
550	#_reconfigureTabset
551	set _tabsetReconfigure true
552    }
553}
554
555# ----------------------------------------------------------------------
556# OPTION -gap
557#
558# Specifies the amount of pixel space to place between each tab.
559# Value may be any pixel offset value. In addition, a special keyword
560# 'overlap' can be used as the value to achieve a standard overlap of
561# tabs. This value may have any of the forms acceptable to Tk_GetPixels.
562# ----------------------------------------------------------------------
563itcl::configbody iwidgets::Tabnotebook::gap {
564
565    if {$itk_option(-gap) != {}} {
566	$itk_component(tabset) configure -gap $itk_option(-gap)
567	#_reconfigureTabset
568	set _tabsetReconfigure true
569    }
570}
571
572# ----------------------------------------------------------------------
573# OPTION -angle
574#
575# Specifes the angle of slope from the inner edge to the outer edge
576# of the tab. An angle of 0 specifies square tabs. Valid ranges are
577# 0 to 45 degrees inclusive. Default is 15 degrees. If tabPos is
578# e or w, this option is ignored.
579# ----------------------------------------------------------------------
580itcl::configbody iwidgets::Tabnotebook::angle {
581
582    if {$itk_option(-angle) != {}} {
583	$itk_component(tabset) configure -angle $itk_option(-angle)
584	#_reconfigureTabset
585	set _tabsetReconfigure true
586    }
587}
588
589# ----------------------------------------------------------------------
590# OPTION -tabpos
591#
592# Specifies the location of the set of tabs in relation to the
593# Notebook area. Must be n, s, e, or w.   Defaults to s.
594# ----------------------------------------------------------------------
595itcl::configbody iwidgets::Tabnotebook::tabpos {
596
597    if {$itk_option(-tabpos) != {}} {
598	set _tabPos $itk_option(-tabpos)
599	$itk_component(tabset) configure \
600		-tabpos $itk_option(-tabpos)
601	pack forget $itk_component(canvas)
602	pack forget $itk_component(tabset)
603	pack forget $itk_component(notebook)
604	_pack $_tabPos
605    }
606}
607
608# -------------------------------------------------------------
609# METHOD: configure ?<option>? ?<value> <option> <value>...?
610#
611# Acts as an addendum to the itk::Widget::configure method.
612#
613# Checks the _recomputeBorder flag and the _tabsetReconfigure to
614# determine what work has been batched to after the configure
615# -------------------------------------------------------------
616itcl::body iwidgets::Tabnotebook::configure { args } {
617    set result [eval itk::Archetype::configure $args]
618
619    # check for flags then do update...
620    if { $_borderRecompute == "true" } {
621	_recomputeBorder
622	set _borderRecompute false
623    }
624
625    if { $_tabsetReconfigure == "true" } {
626	_reconfigureTabset
627	set _tabsetReconfigure false
628    }
629
630    return $result
631
632}
633
634# -------------------------------------------------------------
635# METHOD: add ?<option> <value>...?
636#
637# Creates a page and appends it to the list of pages.
638# processes pageconfigure for the page added.
639#
640# Returns the page's childsite frame
641# -------------------------------------------------------------
642itcl::body iwidgets::Tabnotebook::add { args } {
643
644    # The args list should be an even # of params, if not then
645    # prob missing value for last item in args list. Signal error.
646    set len [llength $args]
647    if { [expr {$len % 2}] } {
648	error "value for \"[lindex $args [expr {$len - 1}]]\" missing"
649    }
650
651    # pick out the notebook args
652    set nbArgs [eval _getArgs [list $_nbOptList] $args]
653    set pageName [eval $itk_component(notebook) add $nbArgs]
654
655    # pick out the tabset args
656    set tsArgs [eval _getArgs [list $_tsOptList] $args]
657    eval $itk_component(tabset)   add $tsArgs
658
659    set page [index end]
660    bind $pageName <Configure> \
661	    [itcl::code $this _pageReconfigure $pageName $page %w %h]
662    return $pageName
663}
664
665# -------------------------------------------------------------
666# METHOD: childsite ?<index>?
667#
668# If index is supplied, returns the child site widget
669# corresponding to the page index.  If called with no arguments,
670# returns a list of all child sites
671# -------------------------------------------------------------
672itcl::body iwidgets::Tabnotebook::childsite { args } {
673    return [eval $itk_component(notebook) childsite $args]
674}
675
676# -------------------------------------------------------------
677# METHOD: delete <index1> ?<index2>?
678#
679# Deletes a page or range of pages from the notebook
680# -------------------------------------------------------------
681itcl::body iwidgets::Tabnotebook::delete { args } {
682    eval $itk_component(notebook) delete $args
683    eval $itk_component(tabset)   delete $args
684}
685
686
687# -------------------------------------------------------------
688# METHOD: index <index>
689#
690# Given an index identifier returns the numeric index of the page
691# -------------------------------------------------------------
692itcl::body iwidgets::Tabnotebook::index { args } {
693    return [eval $itk_component(notebook) index $args]
694}
695
696# -------------------------------------------------------------
697# METHOD: insert <index> ?<option> <value>...?
698#
699# Inserts a page before a index. The before page may
700# be specified as a label or a page position.
701#
702# Note that since we use eval to preserve the $args list,
703# we must use list around $index to keep it together as a unit
704#
705# Returns the name of the page's child site
706# -------------------------------------------------------------
707itcl::body iwidgets::Tabnotebook::insert { index args } {
708
709    # pick out the notebook args
710    set nbArgs [eval _getArgs [list $_nbOptList] $args]
711    set pageName [eval $itk_component(notebook) insert [list $index] $nbArgs]
712
713    # pick out the tabset args
714    set tsArgs [eval _getArgs [list $_tsOptList] $args]
715    eval $itk_component(tabset)   insert [list $index] $tsArgs
716
717    return $pageName
718
719}
720
721# -------------------------------------------------------------
722# METHOD: prev
723#
724# Selects the previous page. Wraps at first back to last page.
725# -------------------------------------------------------------
726itcl::body iwidgets::Tabnotebook::prev { } {
727    eval $itk_component(notebook) prev
728    eval $itk_component(tabset)   prev
729}
730
731# -------------------------------------------------------------
732# METHOD: next
733#
734# Selects the next page. Wraps at last back to first page.
735# -------------------------------------------------------------
736itcl::body iwidgets::Tabnotebook::next { } {
737    eval $itk_component(notebook) next
738    eval $itk_component(tabset)   next
739}
740
741# -------------------------------------------------------------
742# METHOD: pageconfigure <index> ?<option> <value>...?
743#
744# Performs configure on a given page denoted by index.
745# Index may be a page number or a pattern matching the label
746# associated with a page.
747# -------------------------------------------------------------
748itcl::body iwidgets::Tabnotebook::pageconfigure { index args } {
749
750    set nbArgs [eval _getArgs [list $_nbOptList] $args]
751    set tsArgs [eval _getArgs [list $_tsOptList] $args]
752
753    set len [llength $args]
754    switch $len {
755	0 {
756	    # Here is the case where they just want to query options
757	    set nbConfig \
758		    [eval $itk_component(notebook) pageconfigure $index $nbArgs]
759	    set tsConfig \
760		    [eval $itk_component(tabset)   tabconfigure $index $tsArgs]
761	    #
762	    # BUG: this currently just concatenates a page and a tab's
763	    # config lists together... We should bias to the Page
764	    # since this is what we are using as primary when both??
765	    #
766	    # a pageconfigure index -background will return something like:
767	    # -background background Background #9D008FF583C1 gray70 \
768		    # -background background background white gray 70
769	    #
770	    return [concat $nbConfig $tsConfig]
771	}
772	1 {
773	    # Here is the case where they are asking for only one
774	    # one options value... need to figure out which one
775	    # (page or tab) can service this. Then only return
776	    # that one's result.
777
778	    if { [llength $nbArgs] != 0 } {
779		return [eval $itk_component(notebook) \
780			pageconfigure $index $nbArgs]
781	    } elseif { [llength $tsArgs] != 0 } {
782		return [eval $itk_component(tabset) \
783			tabconfigure $index $tsArgs]
784	    } else {
785		error "unknown option \"$args\""
786	    }
787
788	}
789	default {
790
791	    # pick out the notebook args
792	    set nbConfig \
793		    [eval $itk_component(notebook) \
794		    pageconfigure [list $index] $nbArgs]
795
796	    # pick out the tabset args
797	    set tsConfig \
798		    [eval $itk_component(tabset)   \
799		    tabconfigure [list $index] $tsArgs]
800
801	    return ""
802	    #return [concat $nbConfig $tsConfig]
803
804	}
805    }
806}
807
808# -------------------------------------------------------------
809# METHOD: select index
810#
811# Select a page by index
812# -------------------------------------------------------------
813itcl::body iwidgets::Tabnotebook::select { index } {
814    $itk_component(notebook) select $index
815    $itk_component(tabset)   select $index
816}
817
818# -------------------------------------------------------------
819# METHOD: view
820#
821# Return the current page
822#
823#         view index
824#
825# Selects the page denoted by index to be current page
826#
827#	  view 'moveto' fraction
828#
829# Selects the page by using fraction amount
830#
831#	  view 'scroll' num what
832#
833# Selects the page by using num as indicator of next or
834# previous
835#
836# -------------------------------------------------------------
837itcl::body iwidgets::Tabnotebook::view { args } {
838    eval $itk_component(notebook) view $args
839    $itk_component(tabset) select [index select]
840}
841
842# -------------------------------------------------------------
843# PRIVATE METHOD: _getArgs
844#
845# Given an optList returned from a configure on an object and
846# given a candidate argument list, peruse throught the optList
847# and build a new argument list with only those options found
848# in optList.
849#
850# This is used by the add, insert, and pageconfigure methods.
851# It is useful for a container kind of class like Tabnotebook
852# to be smart about args it gets for its concept of a "page"
853# which is actually a Notebook Page and a Tabset Tab.
854#
855# -------------------------------------------------------------
856itcl::body iwidgets::Tabnotebook::_getArgs { optList args } {
857
858    set len [llength $args]
859
860    set retArgs {}
861
862    for {set i 0} {$i < $len} {incr i} {
863	# get the option for this pair
864	set opt [lindex $args $i]
865
866	# move ahead to the value
867	incr i
868
869	# option exists!
870	if { [lsearch -exact $optList $opt] != -1} {
871	    lappend retArgs $opt
872	    if {$i < [llength $args]} {
873		lappend retArgs [lindex $args $i]
874	    }
875	    # option does not exist
876	}
877    }
878
879    return $retArgs
880}
881
882# -------------------------------------------------------------
883# PROTECTED METHOD: _reconfigureTabset
884#
885# bound to the tabset reconfigure... We call our canvas
886# reconfigure as if the canvas resized, it then configures
887# the tabset correctly.
888# -------------------------------------------------------------
889itcl::body iwidgets::Tabnotebook::_reconfigureTabset { } {
890    _canvasReconfigure $_canvasWidth $_canvasHeight
891
892}
893
894# -------------------------------------------------------------
895# PROTECTED METHOD: _canvasReconfigure
896#
897# bound to window Reconfigure event of the canvas
898# keeps the tabset area stretched in its major dimension.
899# -------------------------------------------------------------
900itcl::body iwidgets::Tabnotebook::_canvasReconfigure { wid hgt } {
901
902    if { $_tabPos == "n" || $_tabPos == "s" } {
903	$itk_component(tabset) configure -width $wid
904    } else {
905	$itk_component(tabset) configure -height $hgt
906    }
907
908    set _canvasWidth $wid
909    set _canvasHeight $hgt
910
911    _redrawBorder $wid $hgt
912
913}
914
915# -------------------------------------------------------------
916# PRIVATE METHOD: _redrawBorder
917#
918# called by methods when the packing changes, borderwidths, etc.
919# and height
920# -------------------------------------------------------------
921itcl::body iwidgets::Tabnotebook::_redrawBorder { wid hgt } {
922
923    # Get the top of the Notebook area...
924
925    set nbTop [winfo y $itk_component(notebook)]
926    set canTop [expr {$nbTop - $itk_option(-borderwidth)}]
927
928    $itk_component(canvas) delete BORDER
929    if { $itk_option(-borderwidth) > 0 } {
930
931	# For south, east, and west -- draw the top/north edge
932	if { $_tabPos != "n" } {
933	    $itk_component(canvas) create line \
934		    [expr {floor(0 + ($itk_option(-borderwidth)/2.0))}] \
935		    [expr {floor(0 + ($itk_option(-borderwidth)/2.0))}] \
936		    $wid \
937		    [expr {floor(0 + ($itk_option(-borderwidth)/2.0))}] \
938		    -width $itk_option(-borderwidth) \
939		    -fill [iwidgets::colors::topShadow $itk_option(-background)] \
940		    -tags BORDER
941	}
942
943	# For north, east, and west -- draw the bottom/south edge
944	if { $_tabPos != "s" } {
945	    $itk_component(canvas) create line \
946		    [expr {floor(0 + ($itk_option(-borderwidth)/2.0))}] \
947		    [expr {floor($hgt - ($itk_option(-borderwidth)/2.0))}] \
948		    [expr {floor($wid - ($itk_option(-borderwidth)/2.0))}] \
949		    [expr {floor($hgt - ($itk_option(-borderwidth)/2.0))}] \
950		    -width $itk_option(-borderwidth) \
951		    -fill [iwidgets::colors::bottomShadow $itk_option(-background)] \
952		    -tags BORDER
953	}
954
955	# For north, south, and east -- draw the left/west edge
956	if { $_tabPos != "w" } {
957	    $itk_component(canvas) create line \
958		    [expr {floor(0 + ($itk_option(-borderwidth)/2.0))}] \
959		    0 \
960		    [expr {floor(0 + ($itk_option(-borderwidth)/2.0))}] \
961		    $hgt \
962		    -width $itk_option(-borderwidth) \
963		    -fill [iwidgets::colors::topShadow $itk_option(-background)] \
964		    -tags BORDER
965	}
966
967	# For north, south, and west -- draw the right/east edge
968	if { $_tabPos != "e" } {
969	    $itk_component(canvas) create line \
970		    [expr {floor($wid - ($itk_option(-borderwidth)/2.0))}] \
971		    [expr {floor(0 + ($itk_option(-borderwidth)/2.0))}] \
972		    [expr {floor($wid - ($itk_option(-borderwidth)/2.0))}] \
973		    $hgt \
974		    -width $itk_option(-borderwidth) \
975		    -fill [iwidgets::colors::bottomShadow $itk_option(-background)] \
976		    -tags BORDER
977	}
978    }
979
980}
981
982# -------------------------------------------------------------
983# PRIVATE METHOD: _recomputeBorder
984#
985# Based on current width and height of our canvas, repacks
986# the notebook with padding for borderwidth, and calls
987# redraw border method
988# -------------------------------------------------------------
989itcl::body iwidgets::Tabnotebook::_recomputeBorder { } {
990
991    set wid [winfo width $itk_component(canvas)]
992    set hgt [winfo height $itk_component(canvas)]
993
994    _pack $_tabPos
995    _redrawBorder $wid $hgt
996}
997
998# -------------------------------------------------------------
999# PROTECTED METHOD: _pageReconfigure
1000#
1001# This method will eventually reconfigure the tab notebook's
1002# notebook area to contain the resized child site
1003# -------------------------------------------------------------
1004itcl::body iwidgets::Tabnotebook::_pageReconfigure { pageName page wid hgt } {
1005}
1006
1007# -------------------------------------------------------------
1008# PRIVATE METHOD: _pack
1009#
1010# This method packs the notebook and tabset correctly according
1011# to the current $tabPos
1012# -------------------------------------------------------------
1013itcl::body iwidgets::Tabnotebook::_pack { tabPos } {
1014
1015    pack $itk_component(canvas) -fill both -expand yes
1016    pack propagate $itk_component(canvas) no
1017
1018    switch $tabPos {
1019	n {
1020	    # north
1021	    pack $itk_component(tabset) \
1022		    -anchor nw \
1023		    -fill x \
1024		    -expand no
1025	    pack $itk_component(notebook) \
1026		    -fill both \
1027		    -expand yes \
1028		    -padx $itk_option(-borderwidth) \
1029		    -pady $itk_option(-borderwidth) \
1030		    -side bottom
1031	}
1032	s {
1033	    # south
1034	    pack $itk_component(notebook) \
1035		    -anchor nw \
1036		    -fill both \
1037		    -expand yes \
1038		    -padx $itk_option(-borderwidth) \
1039		    -pady $itk_option(-borderwidth)
1040
1041	    pack $itk_component(tabset) \
1042		    -side left \
1043		    -fill x \
1044		    -expand yes
1045	}
1046	w {
1047	    # west
1048	    pack $itk_component(tabset) \
1049		    -anchor nw \
1050		    -side left \
1051		    -fill y \
1052		    -expand no
1053	    pack $itk_component(notebook) \
1054		    -anchor nw \
1055		    -side left \
1056		    -fill both \
1057		    -expand yes \
1058		    -padx $itk_option(-borderwidth) \
1059		    -pady $itk_option(-borderwidth)
1060
1061	}
1062	e {
1063	    # east
1064	    pack $itk_component(notebook) \
1065		    -side left \
1066		    -anchor nw \
1067		    -fill both \
1068		    -expand yes \
1069		    -padx $itk_option(-borderwidth) \
1070		    -pady $itk_option(-borderwidth)
1071
1072	    pack $itk_component(tabset) \
1073		    -fill y \
1074		    -expand yes
1075	}
1076    }
1077
1078    set wid [winfo width $itk_component(canvas)]
1079    set hgt [winfo height $itk_component(canvas)]
1080
1081    _redrawBorder $wid $hgt
1082}
1083
1084
1085
1086# -------------------------------------------------------------
1087# PRIVATE METHOD: _resize
1088#
1089# This method added by csmith, 5/1/01, to fix a bug with the
1090# geometry of the tabnotebook.  The hull component's geometry
1091# was not being updated properly on <Configure> events.
1092# -------------------------------------------------------------
1093itcl::body iwidgets::Tabnotebook::_resize {newWidth_ newHeight_} {
1094  _canvasReconfigure $newWidth_ $newHeight_
1095
1096  # csmith: 9/14/01 - Commenting out the following code due to
1097  # SF ticket 461471, which is a dup of the original 452803. Since I
1098  # can't remember the exact problem surrounding the need to add
1099  # the _resize method, I'm going to do an undo here, leaving the
1100  # code for future reference if needed.  Should the original problem
1101  # arise again I will reinvestigate the need for _resize.
1102  #
1103  #  after idle \
1104  #    "$this component hull configure -width $newWidth_ -height $newHeight_"
1105}
1106