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

Subversion Repositories or1k_old

[/] [or1k_old/] [tags/] [start/] [insight/] [itcl/] [iwidgets3.0.0/] [generic/] [optionmenu.itk] - Blame information for rev 1782

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
#
2
# Optionmenu
3
# ----------------------------------------------------------------------
4
# Implements an option menu widget with options to manage it.
5
# An option menu displays a frame containing a label and a button.
6
# A pop-up menu will allow for the value of the button to change.
7
#
8
# ----------------------------------------------------------------------
9
#  AUTHOR:  Alfredo Jahn             Phone: (214) 519-3545
10
#                                    Email: ajahn@spd.dsccc.com
11
#                                           alfredo@wn.com
12
#
13
#  @(#) $Id: optionmenu.itk,v 1.1.1.1 2002-01-16 10:24:50 markom Exp $
14
# ----------------------------------------------------------------------
15
#            Copyright (c) 1995 DSC Technologies Corporation
16
# ======================================================================
17
# Permission to use, copy, modify, distribute and license this software
18
# and its documentation for any purpose, and without fee or written
19
# agreement with DSC, is hereby granted, provided that the above copyright
20
# notice appears in all copies and that both the copyright notice and
21
# warranty disclaimer below appear in supporting documentation, and that
22
# the names of DSC Technologies Corporation or DSC Communications
23
# Corporation not be used in advertising or publicity pertaining to the
24
# software without specific, written prior permission.
25
#
26
# DSC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
27
# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, AND NON-
28
# INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND THE
29
# AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE MAINTENANCE,
30
# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. IN NO EVENT SHALL
31
# DSC BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
32
# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
33
# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTUOUS ACTION,
34
# ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
35
# SOFTWARE.
36
# ======================================================================
37
 
38
#
39
# Default resources.
40
#
41
 
42
option add *Optionmenu.highlightThickness       1       widgetDefault
43
option add *Optionmenu.borderWidth              2       widgetDefault
44
option add *Optionmenu.labelPos                 w       widgetDefault
45
option add *Optionmenu.labelMargin              2       widgetDefault
46
option add *Optionmenu.popupCursor              arrow   widgetDefault
47
 
48
#
49
# Usual options.
50
#
51
itk::usual Optionmenu {
52
    keep -activebackground -activeborderwidth -activeforeground \
53
         -background -borderwidth -cursor -disabledforeground -font \
54
         -foreground -highlightcolor -highlightthickness -labelfont \
55
         -popupcursor
56
}
57
 
58
# ------------------------------------------------------------------
59
#                            OPTONMENU
60
# ------------------------------------------------------------------
61
class iwidgets::Optionmenu {
62
    inherit iwidgets::Labeledwidget
63
 
64
    constructor {args} {}
65
    destructor {}
66
 
67
    itk_option define -clicktime clickTime ClickTime 150
68
    itk_option define -command command Command {}
69
    itk_option define -cyclicon cyclicOn CyclicOn true
70
    itk_option define -width width Width 0
71
    itk_option define -font font Font -Adobe-Helvetica-Bold-R-Normal--*-120-*
72
    itk_option define -borderwidth borderWidth BorderWidth 2
73
    itk_option define -highlightthickness highlightThickness HighlightThickness 1
74
    itk_option define -state state State normal
75
 
76
    public {
77
      method index {index}
78
      method delete {first {last {}}}
79
      method disable {index}
80
      method enable {args}
81
      method get {{first "current"} {last ""}}
82
      method insert {index string args}
83
      method popupMenu {args}
84
      method select {index}
85
      method sort {{mode "increasing"}}
86
    }
87
 
88
    protected {
89
      variable _calcSize ""  ;# non-null => _calcSize pending
90
    }
91
 
92
    private {
93
      method _buttonRelease {time}
94
      method _getNextItem {index}
95
      method _next {}
96
      method _postMenu {time}
97
      method _previous {}
98
      method _setItem {item}
99
      method _setSize {{when later}}
100
      method _setitems {items} ;# Set the list of menu entries
101
 
102
      variable _postTime 0
103
      variable _items {}       ;# List of popup menu entries
104
      variable _numitems 0     ;# List of popup menu entries
105
 
106
      variable _currentItem "" ;# Active menu selection
107
    }
108
}
109
 
110
#
111
# Provide a lowercased access method for the Optionmenu class.
112
#
113
proc ::iwidgets::optionmenu {pathName args} {
114
    uplevel ::iwidgets::Optionmenu $pathName $args
115
}
116
 
117
# ------------------------------------------------------------------
118
#                        CONSTRUCTOR
119
# ------------------------------------------------------------------
120
body iwidgets::Optionmenu::constructor {args} {
121
    global tcl_platform
122
 
123
    component hull configure -highlightthickness 0
124
 
125
    itk_component add menuBtn {
126
        menubutton $itk_interior.menuBtn -relief raised -indicator on \
127
            -textvariable [scope _currentItem] -takefocus 1 \
128
            -menu $itk_interior.menuBtn.menu
129
    } {
130
        usual
131
        keep -borderwidth
132
        if {$tcl_platform(platform) != "unix"} {
133
            ignore -activebackground -activeforeground
134
        }
135
    }
136
    pack $itk_interior.menuBtn -fill x
137
    pack propagate $itk_interior no
138
 
139
    itk_component add popupMenu {
140
        menu $itk_interior.menuBtn.menu -tearoff no
141
    } {
142
        usual
143
        ignore -tearoff
144
        keep -activeborderwidth -borderwidth
145
        rename -cursor -popupcursor popupCursor Cursor
146
    }
147
 
148
    #
149
    # Bind to button release for all components.
150
    #
151
    bind $itk_component(menuBtn)  \
152
            "[code $this _postMenu %t]; break"
153
    bind $itk_component(menuBtn)  \
154
            "[code $this _postMenu %t]; break"
155
    bind $itk_component(popupMenu)  \
156
            [code $this _buttonRelease %t]
157
 
158
    #
159
    # Initialize the widget based on the command line options.
160
    #
161
    eval itk_initialize $args
162
}
163
 
164
# ------------------------------------------------------------------
165
#                           DESTRUCTOR
166
# ------------------------------------------------------------------
167
body iwidgets::Optionmenu::destructor {} {
168
    if {$_calcSize != ""} {after cancel $_calcSize}
169
}
170
 
171
# ------------------------------------------------------------------
172
#                             OPTIONS
173
# ------------------------------------------------------------------
174
 
175
# ------------------------------------------------------------------
176
# OPTION -clicktime
177
#
178
# Interval time (in msec) used to determine that a single mouse
179
# click has occurred. Used to post menu on a quick mouse click.
180
# **WARNING** changing this value may cause the sigle-click
181
# functionality to not work properly!
182
# ------------------------------------------------------------------
183
configbody iwidgets::Optionmenu::clicktime {}
184
 
185
# ------------------------------------------------------------------
186
# OPTION -command
187
#
188
# Specifies a command to be evaluated upon change in option menu.
189
# ------------------------------------------------------------------
190
configbody iwidgets::Optionmenu::command {}
191
 
192
# ------------------------------------------------------------------
193
# OPTION -cyclicon
194
#
195
# Turns on/off the 3rd mouse button capability. This feature
196
# allows the right mouse button to cycle through the popup
197
# menu list without poping it up. M3 cycles through
198
# the menu in reverse order.
199
# ------------------------------------------------------------------
200
configbody iwidgets::Optionmenu::cyclicon {
201
    if {$itk_option(-cyclicon)} {
202
        bind $itk_component(menuBtn) <3> [code $this _next]
203
        bind $itk_component(menuBtn)  [code $this _previous]
204
        bind $itk_component(menuBtn)  [code $this _next]
205
        bind $itk_component(menuBtn)  [code $this _previous]
206
    } else {
207
        bind $itk_component(menuBtn) <3> break
208
        bind $itk_component(menuBtn)  break
209
        bind $itk_component(menuBtn)  break
210
        bind $itk_component(menuBtn)  break
211
    }
212
}
213
 
214
# ------------------------------------------------------------------
215
# OPTION -width
216
#
217
# Allows the menu label width to be set to a fixed size
218
# ------------------------------------------------------------------
219
configbody iwidgets::Optionmenu::width {
220
    _setSize
221
}
222
 
223
# ------------------------------------------------------------------
224
# OPTION -font
225
#
226
# Change all fonts for this widget. Also re-calculate height based
227
# on font size (used to line up menu items over menu button label).
228
# ------------------------------------------------------------------
229
configbody iwidgets::Optionmenu::font {
230
    _setSize
231
}
232
 
233
# ------------------------------------------------------------------
234
# OPTION -borderwidth
235
#
236
# Change borderwidth for this widget. Also re-calculate height based
237
# on font size (used to line up menu items over menu button label).
238
# ------------------------------------------------------------------
239
configbody iwidgets::Optionmenu::borderwidth {
240
    _setSize
241
}
242
 
243
# ------------------------------------------------------------------
244
# OPTION -highlightthickness
245
#
246
# Change highlightthickness for this widget. Also re-calculate
247
# height based on font size (used to line up menu items over
248
# menu button label).
249
# ------------------------------------------------------------------
250
configbody iwidgets::Optionmenu::highlightthickness {
251
    _setSize
252
}
253
 
254
# ------------------------------------------------------------------
255
# OPTION -state
256
#
257
# Specified one of two states for the Optionmenu: normal, or
258
# disabled.  If the Optionmenu is disabled, then option menu
259
# selection is ignored.
260
# ------------------------------------------------------------------
261
configbody iwidgets::Optionmenu::state {
262
    switch $itk_option(-state) {
263
        normal {
264
            $itk_component(menuBtn) config -state normal
265
            $itk_component(label) config -fg $itk_option(-foreground)
266
        }
267
        disabled {
268
            $itk_component(menuBtn) config -state disabled
269
            $itk_component(label) config -fg $itk_option(-disabledforeground)
270
        }
271
        default {
272
            error "bad state option \"$itk_option(-state)\":\
273
                    should be disabled or normal"
274
        }
275
    }
276
}
277
 
278
# ------------------------------------------------------------------
279
#                            METHODS
280
# ------------------------------------------------------------------
281
 
282
# ------------------------------------------------------------------
283
# METHOD: index index
284
#
285
# Return the numerical index corresponding to index.
286
# ------------------------------------------------------------------
287
body iwidgets::Optionmenu::index {index} {
288
 
289
    if {[regexp {(^[0-9]+$)} $index]} {
290
        set idx [$itk_component(popupMenu) index $index]
291
 
292
        if {$idx == "none"} {
293
            return 0
294
        }
295
        return [expr {$index > $idx ? $_numitems : $idx}]
296
 
297
    } elseif {$index == "end"} {
298
        return $_numitems
299
 
300
    } elseif {$index == "select"} {
301
        return [lsearch $_items $_currentItem]
302
 
303
    }
304
 
305
    set numValue [lsearch -glob $_items $index]
306
 
307
    if {$numValue == -1} {
308
        error "bad Optionmenu index \"$index\""
309
    }
310
    return $numValue
311
}
312
 
313
# ------------------------------------------------------------------
314
# METHOD: delete first ?last?
315
#
316
# Remove an item (or range of items) from the popup menu.
317
# ------------------------------------------------------------------
318
body iwidgets::Optionmenu::delete {first {last {}}} {
319
 
320
    set first [index $first]
321
    set last [expr {$last != {} ? [index $last] : $first}]
322
    set nextAvail $_currentItem
323
 
324
    #
325
    # If current item is in delete range point to next available.
326
    #
327
    if {$_numitems > 1 &&
328
        ([lsearch -exact [lrange $_items $first $last] [get]] != -1)} {
329
        set nextAvail [_getNextItem $last]
330
    }
331
 
332
    _setitems [lreplace $_items $first $last]
333
 
334
    #
335
    # Make sure "nextAvail" is still in the list.
336
    #
337
    set index [lsearch -exact $_items $nextAvail]
338
    _setItem [expr {$index != -1 ? $nextAvail : ""}]
339
}
340
 
341
# ------------------------------------------------------------------
342
# METHOD: disable index
343
#
344
# Disable a menu item in the option menu.  This will prevent the user
345
# from being able to select this item from the menu.  This only effects
346
# the state of the item in the menu, in other words, should the item
347
# be the currently selected item, the user is responsible for
348
# determining this condition and taking appropriate action.
349
# ------------------------------------------------------------------
350
body iwidgets::Optionmenu::disable {index} {
351
    set index [index $index]
352
    $itk_component(popupMenu) entryconfigure $index -state disabled
353
}
354
 
355
# ------------------------------------------------------------------
356
# METHOD: enable index
357
#
358
# Enable a menu item in the option menu.  This will allow the user
359
# to select this item from the menu.
360
# ------------------------------------------------------------------
361
body iwidgets::Optionmenu::enable {index} {
362
    set index [index $index]
363
    $itk_component(popupMenu) entryconfigure $index -state normal
364
}
365
 
366
# ------------------------------------------------------------------
367
# METHOD: get
368
#
369
# Returns the current menu item.
370
# ------------------------------------------------------------------
371
body iwidgets::Optionmenu::get {{first "current"} {last ""}} {
372
    if {"current" == $first} {
373
        return $_currentItem
374
    }
375
 
376
    set first [index $first]
377
    if {"" == $last} {
378
        return [$itk_component(popupMenu) entrycget $first -label]
379
    }
380
 
381
    if {"end" == $last} {
382
        set last [$itk_component(popupMenu) index end]
383
    } else {
384
        set last [index $last]
385
    }
386
    set rval ""
387
    while {$first <= $last} {
388
        lappend rval [$itk_component(popupMenu) entrycget $first -label]
389
        incr first
390
    }
391
    return $rval
392
}
393
 
394
# ------------------------------------------------------------------
395
# METHOD: insert index string ?string?
396
#
397
# Insert an item in the popup menu.
398
# ------------------------------------------------------------------
399
body iwidgets::Optionmenu::insert {index string args} {
400
    set index [index $index]
401
    set args [linsert $args 0 $string]
402
    _setitems [eval linsert {$_items} $index $args]
403
    return ""
404
}
405
 
406
# ------------------------------------------------------------------
407
# METHOD: select index
408
#
409
# Select an item from the popup menu to display on the menu label
410
# button.
411
# ------------------------------------------------------------------
412
body iwidgets::Optionmenu::select {index} {
413
    set index [index $index]
414
    _setItem [lindex $_items $index]
415
}
416
 
417
# ------------------------------------------------------------------
418
# METHOD: popupMenu
419
#
420
# Evaluates the specified args against the popup menu component
421
# and returns the result.
422
# ------------------------------------------------------------------
423
body iwidgets::Optionmenu::popupMenu {args} {
424
    return [eval $itk_component(popupMenu) $args]
425
}
426
 
427
# ------------------------------------------------------------------
428
# METHOD: sort mode
429
#
430
# Sort the current menu in either "ascending" or "descending" order.
431
# ------------------------------------------------------------------
432
body iwidgets::Optionmenu::sort {{mode "increasing"}} {
433
    switch $mode {
434
        ascending -
435
        increasing {
436
            _setitems [lsort -increasing $_items]
437
        }
438
        descending -
439
        decreasing {
440
            _setitems [lsort -decreasing $_items]
441
        }
442
        default {
443
            error "bad sort argument \"$mode\": should be ascending,\
444
                    descending, increasing, or decreasing"
445
        }
446
    }
447
}
448
 
449
# ------------------------------------------------------------------
450
# PRIVATE METHOD: _buttonRelease
451
#
452
# Display the popup menu. Menu position is calculated.
453
# ------------------------------------------------------------------
454
body iwidgets::Optionmenu::_buttonRelease {time} {
455
    if {[expr abs([expr $_postTime - $time])] <= $itk_option(-clicktime)} {
456
        return -code break
457
    }
458
}
459
 
460
# ------------------------------------------------------------------
461
# PRIVATE METHOD: _getNextItem index
462
#
463
# Allows either a string or index number to be passed in, and returns
464
# the next item in the list in string format. Wrap around is automatic.
465
# ------------------------------------------------------------------
466
body iwidgets::Optionmenu::_getNextItem {index} {
467
 
468
    if {[incr index] >= $_numitems} {
469
        set index 0   ;# wrap around
470
    }
471
    return [lindex $_items $index]
472
}
473
 
474
# ------------------------------------------------------------------
475
# PRIVATE METHOD: _next
476
#
477
# Sets the current option label to next item in list if that item is
478
# not disbaled.
479
# ------------------------------------------------------------------
480
body iwidgets::Optionmenu::_next {} {
481
    if {$itk_option(-state) != "normal"} {
482
        return
483
    }
484
    set i [lsearch -exact $_items $_currentItem]
485
 
486
    for {set cnt 0} {$cnt < $_numitems} {incr cnt} {
487
 
488
        if {[incr i] >= $_numitems} {
489
            set i 0
490
        }
491
 
492
        if {[$itk_component(popupMenu) entrycget $i -state] != "disabled"} {
493
            _setItem [lindex $_items $i]
494
            break
495
        }
496
    }
497
}
498
 
499
# ------------------------------------------------------------------
500
# PRIVATE METHOD: _previous
501
#
502
# Sets the current option label to previous item in list if that
503
# item is not disbaled.
504
# ------------------------------------------------------------------
505
body iwidgets::Optionmenu::_previous {} {
506
    if {$itk_option(-state) != "normal"} {
507
        return
508
    }
509
 
510
    set i [lsearch -exact $_items $_currentItem]
511
 
512
    for {set cnt 0} {$cnt < $_numitems} {incr cnt} {
513
        set i [expr $i - 1]
514
 
515
        if {$i < 0} {
516
            set i [expr $_numitems - 1]
517
        }
518
 
519
        if {[$itk_component(popupMenu) entrycget $i -state] != "disabled"} {
520
            _setItem [lindex $_items $i]
521
            break
522
        }
523
    }
524
}
525
 
526
# ------------------------------------------------------------------
527
# PRIVATE METHOD: _postMenu time
528
#
529
# Display the popup menu. Menu position is calculated.
530
# ------------------------------------------------------------------
531
body iwidgets::Optionmenu::_postMenu {time} {
532
    #
533
    # Don't bother to post if menu is empty.
534
    #
535
    if {[llength $_items] > 0 && $itk_option(-state) == "normal"} {
536
        set _postTime $time
537
        set itemIndex [lsearch -exact $_items $_currentItem]
538
 
539
        set margin [expr $itk_option(-borderwidth) \
540
            + $itk_option(-highlightthickness)]
541
 
542
        set x [expr [winfo rootx $itk_component(menuBtn)] + $margin]
543
        set y [expr [winfo rooty $itk_component(menuBtn)] \
544
            - [$itk_component(popupMenu) yposition $itemIndex] + $margin]
545
 
546
        tk_popup $itk_component(popupMenu) $x $y
547
    }
548
}
549
 
550
# ------------------------------------------------------------------
551
# PRIVATE METHOD: _setItem
552
#
553
# Set the menu button label to item, then dismiss the popup menu.
554
# Also check if item has been changed. If so, also call user-supplied
555
# command.
556
# ------------------------------------------------------------------
557
body iwidgets::Optionmenu::_setItem {item} {
558
    if {$_currentItem != $item} {
559
        set _currentItem $item
560
        if {[winfo ismapped $itk_component(hull)]} {
561
            uplevel #0 $itk_option(-command)
562
        }
563
    }
564
}
565
 
566
# ------------------------------------------------------------------
567
# PRIVATE METHOD: _setitems items
568
#
569
# Create a list of items available on the menu. Used to create the
570
# popup menu.
571
# ------------------------------------------------------------------
572
body iwidgets::Optionmenu::_setitems {items_} {
573
 
574
    #
575
    # Delete the old menu entries, and set the new list of
576
    # menu entries to those specified in "items_".
577
    #
578
    $itk_component(popupMenu) delete 0 last
579
    set _items ""
580
    set _numitems [llength $items_]
581
 
582
    #
583
    # Clear the menu button label.
584
    #
585
    if {$_numitems == 0} {
586
        _setItem ""
587
        return
588
    }
589
 
590
    set savedCurrentItem $_currentItem
591
 
592
    foreach opt $items_ {
593
        lappend _items $opt
594
        $itk_component(popupMenu) add command -label $opt \
595
            -command [code $this _setItem $opt]
596
    }
597
    set first [lindex $_items 0]
598
 
599
    #
600
    # Make sure "savedCurrentItem" is still in the list.
601
    #
602
    if {$first != ""} {
603
        set i [lsearch -exact $_items $savedCurrentItem]
604
        select [expr {$i != -1 ? $savedCurrentItem : $first}]
605
    } else {
606
        _setItem ""
607
    }
608
 
609
    _setSize
610
}
611
 
612
# ------------------------------------------------------------------
613
# PRIVATE METHOD: _setSize ?when?
614
#
615
# Set the size of the option menu.  If "when" is "now", the change
616
# is applied immediately.  If it is "later" or it is not specified,
617
# then the change is applied later, when the application is idle.
618
# ------------------------------------------------------------------
619
body iwidgets::Optionmenu::_setSize {{when later}} {
620
 
621
    if {$when == "later"} {
622
        if {$_calcSize == ""} {
623
            set _calcSize [after idle [code $this _setSize now]]
624
        }
625
        return
626
    }
627
 
628
    set margin [expr 2*($itk_option(-borderwidth) \
629
        + $itk_option(-highlightthickness))]
630
 
631
    if {"0" != $itk_option(-width)} {
632
        set width $itk_option(-width)
633
    } else {
634
        set width [expr [winfo reqwidth $itk_component(popupMenu)]+$margin+20]
635
    }
636
    set height [winfo reqheight $itk_component(menuBtn)]
637
    $itk_component(lwchildsite) configure -width $width -height $height
638
 
639
    set _calcSize ""
640
}

powered by: WebSVN 2.1.0

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