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

Last change on this file since 4094 was 3330, checked in by gah, 11 years ago

merge (by hand) with Rappture1.2 branch

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