source: trunk/gui/scripts/dropdown.tcl @ 1

Last change on this file since 1 was 1, checked in by mmc, 19 years ago

initial import

File size: 6.1 KB
Line 
1# ----------------------------------------------------------------------
2#  COMPONENT: dropdown - base class for drop-down panels
3#
4#  This is the base class for a family of drop-down widget panels.
5#  They might be used, for example, to build the drop-down list for
6#  a combobox.
7#
8# ======================================================================
9#  AUTHOR:  Michael McLennan, Purdue University
10#  Copyright (c) 2004  Purdue Research Foundation, West Lafayette, IN
11# ======================================================================
12package require Itk
13
14option add *Dropdown.textBackground white widgetDefault
15option add *Dropdown.outline black widgetDefault
16option add *Dropdown.borderwidth 1 widgetDefault
17option add *Dropdown.font -*-helvetica-medium-r-normal-*-*-120-* widgetDefault
18
19itcl::class Rappture::Dropdown {
20    inherit itk::Toplevel
21
22    itk_option define -outline outline Outline ""
23    itk_option define -postcommand postCommand PostCommand ""
24    itk_option define -unpostcommand unpostCommand UnpostCommand ""
25
26    constructor {args} { # defined below }
27
28    public method post {where args}
29    public method unpost {}
30
31    protected method _adjust {{widget ""}}
32
33    public proc outside {w x y}
34
35    bind RapptureDropdown <ButtonPress> \
36        {if {[Rappture::Dropdown::outside %W %X %Y]} {%W unpost}}
37}
38
39itk::usual Dropdown {
40    keep -background -outline -cursor -font
41}
42
43# ----------------------------------------------------------------------
44# CONSTRUCTOR
45# ----------------------------------------------------------------------
46itcl::body Rappture::Dropdown::constructor {args} {
47    wm overrideredirect $itk_component(hull) yes
48    wm withdraw $itk_component(hull)
49
50    component hull configure -borderwidth 1 -background black
51    itk_option remove hull.background hull.borderwidth
52
53    # add bindings to release the grab
54    set btags [bindtags $itk_component(hull)]
55    bindtags $itk_component(hull) [linsert $btags 1 RapptureDropdown]
56
57    eval itk_initialize $args
58}
59
60# ----------------------------------------------------------------------
61# USAGE: post @<x>,<y>
62# USAGE: post <widget> <justify>
63#
64# Clients use this to pop up the dropdown on the screen.  The position
65# should be either a specific location "@x,y", or a <widget> and its
66# justification.
67# ----------------------------------------------------------------------
68itcl::body Rappture::Dropdown::post {where args} {
69    set owner [expr {([winfo exists $where]) ? $where : ""}]
70    _adjust $owner    ;# make sure contents are up-to-date
71    update idletasks  ;# fix size info
72
73    if {[string length $itk_option(-postcommand)] > 0} {
74        set cmd [list uplevel #0 $itk_option(-postcommand)]
75        if {[catch $cmd result]} {
76            bgerror $result
77        }
78    }
79
80    set w [winfo width $itk_component(hull)]
81    set h [winfo height $itk_component(hull)]
82    set sw [winfo screenwidth $itk_component(hull)]
83    set sh [winfo screenwidth $itk_component(hull)]
84
85    if {[regexp {^@([0-9]+),([0-9]+)$} $where match x y]} {
86        set xpos $x
87        set ypos $y
88    } elseif {[winfo exists $where]} {
89        set x0 [winfo rootx $where]
90        switch -- $args {
91            left { set xpos $x0 }
92            right { set xpos [expr {$x0 + [winfo width $where] - $sw}] }
93            default {
94                error "bad option \"$args\": should be left, right"
95            }
96        }
97        set ypos [expr {[winfo rooty $where]+[winfo height $where]}]
98    } else {
99        error "bad position \"$where\": should be widget name or @x,y"
100    }
101
102    # make sure the dropdown doesn't go off screen
103    if {$xpos > 0} {
104        # left-justified positions
105        if {$xpos + $w > $sw} {
106            set xpos [expr {$sw-$w}]
107            if {$xpos < 0} { set xpos 0 }
108        }
109        set xpos "+$xpos"
110    } else {
111        # right-justified positions
112        if {$xpos - $w < -$sw} {
113            set xpos [expr {-$sw+$w}]
114            if {$xpos > 0} { set xpos -1 }
115        }
116    }
117    if {$ypos + $h > $sh} {
118        set ypos [expr {$sh-$h}]
119        if {$ypos < 0} { set ypos 0 }
120    }
121
122    # post the dropdown on the screen
123    wm geometry $itk_component(hull) "$xpos+$ypos"
124    update
125
126    wm deiconify $itk_component(hull)
127    raise $itk_component(hull)
128
129    # grab the mouse pointer
130    update
131    while {[catch {grab set -global $itk_component(hull)}]} {
132        after 100
133    }
134}
135
136# ----------------------------------------------------------------------
137# USAGE: unpost
138#
139# Takes down the dropdown, if it is showing on the screen.
140# ----------------------------------------------------------------------
141itcl::body Rappture::Dropdown::unpost {} {
142    grab release $itk_component(hull)
143    wm withdraw $itk_component(hull)
144
145    if {[string length $itk_option(-unpostcommand)] > 0} {
146        set cmd [list uplevel #0 $itk_option(-unpostcommand)]
147        if {[catch $cmd result]} {
148            bgerror $result
149        }
150    }
151}
152
153# ----------------------------------------------------------------------
154# USAGE: _adjust
155#
156# This method is invoked each time the dropdown is posted to adjust
157# its size and contents.
158# ----------------------------------------------------------------------
159itcl::body Rappture::Dropdown::_adjust {{widget ""}} {
160    # derived classes redefine this to do something useful
161}
162
163# ----------------------------------------------------------------------
164# USAGE: outside <widget> <x> <y>
165#
166# Checks to see if the root coordinate <x>,<y> is outside of the
167# area for the <widget>.  Returns 1 if so, and 0 otherwise.
168# ----------------------------------------------------------------------
169itcl::body Rappture::Dropdown::outside {widget x y} {
170    return [expr {$x < [winfo rootx $widget]
171             || $x > [winfo rootx $widget]+[winfo width $widget]
172             || $y < [winfo rooty $widget]
173             || $y > [winfo rooty $widget]+[winfo height $widget]}]
174}
175
176# ----------------------------------------------------------------------
177# CONFIGURATION OPTION: -outline
178# ----------------------------------------------------------------------
179itcl::configbody Rappture::Dropdown::outline {
180    component hull configure -background $itk_option(-outline)
181}
Note: See TracBrowser for help on using the repository browser.