source: trunk/gui/scripts/notebook.tcl @ 2606

Last change on this file since 2606 was 1929, checked in by gah, 14 years ago
File size: 8.2 KB
Line 
1# ----------------------------------------------------------------------
2#  COMPONENT: notebook - series of pages, but only one packed at a time
3#
4#  This widget acts as the core of a tabbed notebook, without the tabs.
5#  It allows you to create a series of pages, and display one page at
6#  time.  The overall widget is just big enough to accommodate all of
7#  the pages within it.
8# ======================================================================
9#  AUTHOR:  Michael McLennan, Purdue University
10#  Copyright (c) 2004-2005  Purdue Research Foundation
11#
12#  See the file "license.terms" for information on usage and
13#  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
14# ======================================================================
15package require Itk
16
17option add *Notebook.width 0 widgetDefault
18option add *Notebook.height 0 widgetDefault
19
20itcl::class Rappture::Notebook {
21    inherit itk::Widget
22
23    itk_option define -width width Width 0
24    itk_option define -height height Height 0
25
26    constructor {args} { # defined below }
27    destructor { # defined below }
28
29    public method insert {pos args}
30    public method delete {args}
31    public method index {name}
32    public method page {name}
33    public method current {args}
34
35    protected method _fixSize {}
36
37    private variable _count 0       ;# counter for unique names
38    private variable _dispatcher "" ;# dispatcher for !events
39    private variable _pages ""      ;# list of page frames
40    private variable _name2page     ;# maps name => frame for page
41    private variable _current ""    ;# page currently shown
42}
43                                                                               
44itk::usual Notebook {
45    keep -background -cursor
46}
47
48# ----------------------------------------------------------------------
49# CONSTRUCTOR
50# ----------------------------------------------------------------------
51itcl::body Rappture::Notebook::constructor {args} {
52    pack propagate $itk_component(hull) no
53
54    Rappture::dispatcher _dispatcher
55    $_dispatcher register !fixsize
56    $_dispatcher dispatch $this !fixsize "[itcl::code $this _fixSize]; list"
57
58    eval itk_initialize $args
59}
60
61# ----------------------------------------------------------------------
62# USAGE: insert <pos> ?<name> <name>...?
63#
64# Used to insert one or more pages in the notebook.  Each page is
65# identified by its <name>.  Returns the widget name for each
66# page created.
67# ----------------------------------------------------------------------
68itcl::body Rappture::Notebook::insert {pos args} {
69    set rlist ""
70    foreach name $args {
71        if {[lsearch $_pages $name] >= 0} {
72            error "page \"$name\" already exists"
73        }
74        set pname "page[incr _count]"
75        itk_component add $pname {
76            frame $itk_interior.$pname
77        }
78        set _pages [linsert $_pages $pos $name]
79        set _name2page($name) $itk_component($pname)
80
81        bind $itk_component($pname) <Configure> \
82            [itcl::code $_dispatcher event -after 100 !fixsize]
83
84        lappend rlist $itk_component($pname)
85    }
86    return $rlist
87}
88
89# ----------------------------------------------------------------------
90# USAGE: delete -all
91# USAGE: delete ?<name> <name>...?
92#
93# Used to delete one or more pages from the notebook.  With the -all
94# flag, it deletes all pages.  Otherwise, it deletes each page
95# by name.  You can also delete a page by using an index of the
96# form "@n".
97# ----------------------------------------------------------------------
98itcl::body Rappture::Notebook::delete {args} {
99    if {$args == "-all"} {
100        set args $_pages
101    }
102    foreach name $args {
103        set i [index $name]
104        set pname [lindex $_pages $i]
105        if {$pname != ""} {
106            set _pages [lreplace $_pages $i $i]
107            destroy $_name2page($pname)
108            unset _name2page($pname)
109        }
110    }
111}
112
113# ----------------------------------------------------------------------
114# USAGE: index <name>|@n
115#
116# Used to convert a page <name> to its corresponding integer index.
117# ----------------------------------------------------------------------
118itcl::body Rappture::Notebook::index {name} {
119    set i [lsearch $_pages $name]
120    if {$i >= 0} {
121        return $i
122    }
123    if {[regexp {^@([0-9]+)$} $name match i]} {
124        return $i
125    }
126    error "bad page name \"$name\": should be @int or one of [join [lsort $_pages] {, }]"
127}
128
129# ----------------------------------------------------------------------
130# USAGE: page <name>|@n
131#
132# Used to convert a page <name> to its corresponding frame.
133# ----------------------------------------------------------------------
134itcl::body Rappture::Notebook::page {name} {
135    set i [index $name]
136    set name [lindex $_pages $i]
137    return $_name2page($name)
138}
139
140# ----------------------------------------------------------------------
141# USAGE: current ?<name>|next>|<back?
142#
143# Used to query/set the current page in the notebook.  With no args,
144# it returns the name of the current page.  Otherwise, it sets the
145# current page.  The special token "next>" is used to set the notebook
146# to the next logical page, and "<back" sets to the previous.
147# ----------------------------------------------------------------------
148itcl::body Rappture::Notebook::current {args} {
149    switch -- [llength $args] {
150        0 {
151            return $_current
152        }
153        1 {
154            set name [lindex $args 0]
155            set index 0
156            if {$name == "next>"} {
157                if {$_current == ""} {
158                    set index 0
159                } else {
160                    set i [lsearch -exact $_pages $_current]
161                    set index [expr {$i+1}]
162                    if {$index >= [llength $_pages]} {
163                        set index [expr {[llength $_pages]-1}]
164                    }
165                }
166            } elseif {$name == "<back"} {
167                if {$_current == ""} {
168                    set index end
169                } else {
170                    set i [lsearch -exact $_pages $_current]
171                    set index [expr {$i-1}]
172                    if {$index < 0} {
173                        set index 0
174                    }
175                }
176            } else {
177                set index [lsearch -exact $_pages $name]
178                if {$index < 0} {
179                    error "can't move to page \"$name\""
180                }
181            }
182
183            set _current [lindex $_pages $index]
184
185            foreach w [pack slaves $itk_component(hull)] {
186                pack forget $w
187            }
188            pack $_name2page($_current) -expand yes -fill both
189        }
190        default {
191            error "wrong # args: should be \"current name|next>|<back\""
192        }
193    }
194}
195
196# ----------------------------------------------------------------------
197# USAGE: _fixSize
198#
199# Invoked automatically whenever a page changes size or the -width
200# or -height options change.  When the -width/-height are zero, this
201# method computes the minimum size needed to accommodate all pages.
202# Otherwise, it passes the size request onto the hull.
203# ----------------------------------------------------------------------
204itcl::body Rappture::Notebook::_fixSize {} {
205    if {$itk_option(-width) <= 0} {
206        set maxw 0
207        foreach name $_pages {
208            set w [winfo reqwidth $_name2page($name)]
209            if {$w > $maxw} { set maxw $w }
210        }
211        component hull configure -width $maxw
212    } else {
213        component hull configure -width $itk_option(-width)
214    }
215
216    if {$itk_option(-height) <= 0} {
217        set maxh 0
218        foreach name $_pages {
219            set h [winfo reqheight $_name2page($name)]
220            if {$h > $maxh} { set maxh $h }
221        }
222        component hull configure -height $maxh
223    } else {
224        component hull configure -height $itk_option(-height)
225    }
226}
227
228# ----------------------------------------------------------------------
229# OPTION: -width
230# ----------------------------------------------------------------------
231itcl::configbody Rappture::Notebook::width {
232    $_dispatcher event -idle !fixsize
233}
234
235# ----------------------------------------------------------------------
236# OPTION: -height
237# ----------------------------------------------------------------------
238itcl::configbody Rappture::Notebook::height {
239    $_dispatcher event -idle !fixsize
240}
Note: See TracBrowser for help on using the repository browser.