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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [itcl/] [iwidgets3.0.0/] [generic/] [combobox.itk] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
# Combobox
2
# ----------------------------------------------------------------------
3
# Implements a Combobox widget. A Combobox has 2 basic styles: simple and
4
# dropdown. Dropdowns display an entry field with an arrow button to the
5
# right of it. When the arrow button is pressed a selectable list of
6
# items is popped up. A simple Combobox displays an entry field and a listbox
7
# just beneath it which is always displayed. In both types, if the user
8
# selects an item in the listbox, the contents of the entry field are
9
# replaced with the text from the selected item. If the Combobox is
10
# editable, the user can type in the entry field and when  is
11
# pressed the item will be inserted into the list.
12
#
13
# WISH LIST:
14
#       This section lists possible future enhancements.
15
#
16
#         Combobox 1.x:
17
#                 - convert bindings to bindtags.
18
#
19
# ----------------------------------------------------------------------
20
#  ORIGINAL AUTHOR: John S. Sigler              EMAIL: jsigler@spd.dsccc.com
21
#                                                                                          sigler@onramp.net
22
# ----------------------------------------------------------------------
23
#  CURRENT MAINTAINER: Mitch Gorman                             EMAIL: logain@erols.com
24
#                                       Copyright (c) 1995      John S. Sigler
25
#                                       Copyright (c) 1997      Mitch Gorman
26
# ======================================================================
27
# Permission is hereby granted, without written agreement and without
28
# license or royalty fees, to use, copy, modify, and distribute this
29
# software and its documentation for any purpose, provided that the
30
# above copyright notice and the following two paragraphs appear in
31
# all copies of this software.
32
#
33
# IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
34
# DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
35
# ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
36
# IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
37
# DAMAGE.
38
#
39
# THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
40
# BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
41
# FITNESS FOR A PARTICULAR PURPOSE.      THE SOFTWARE PROVIDED HEREUNDER IS
42
# ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
43
# PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
44
# ======================================================================
45
 
46
#
47
# Default resources.
48
#
49
option add *Combobox.borderWidth 2 widgetDefault
50
option add *Combobox.labelPos wn widgetDefault
51
option add *Combobox.listHeight 150 widgetDefault
52
option add *Combobox.hscrollMode dynamic widgetDefault
53
option add *Combobox.vscrollMode dynamic widgetDefault
54
 
55
#
56
# Usual options.
57
#
58
itk::usual Combobox {
59
    keep -background -borderwidth -cursor -foreground -highlightcolor \
60
        -highlightthickness -insertbackground -insertborderwidth \
61
        -insertofftime -insertontime -insertwidth -labelfont -popupcursor \
62
        -selectbackground -selectborderwidth -selectforeground \
63
        -textbackground -textfont
64
}
65
 
66
# ------------------------------------------------------------------
67
#                                                        COMBOBOX
68
# ------------------------------------------------------------------
69
class iwidgets::Combobox {
70
    inherit iwidgets::Entryfield
71
 
72
    constructor {args} {}
73
    destructor {}
74
 
75
    itk_option define -arrowrelief arrowRelief Relief raised
76
    itk_option define -completion completion Completion true
77
    itk_option define -dropdown dropdown Dropdown true
78
    itk_option define -editable editable Editable true
79
    itk_option define -grab grab Grab local
80
    itk_option define -listheight listHeight Height 150
81
    itk_option define -margin margin Margin 1
82
    itk_option define -popupcursor popupCursor Cursor arrow
83
    itk_option define -selectioncommand selectionCommand SelectionCommand {}
84
    itk_option define -state state State normal
85
    itk_option define -unique unique Unique true
86
 
87
    public method clear {{component all}}
88
    public method curselection {}
89
    public method delete {component first {last {}}}
90
    public method get {{index {}}}
91
    public method getcurselection {}
92
    public method insert {component index args}
93
    public method invoke {}
94
    public method justify {direction}
95
    public method see {index}
96
    public method selection {option first {last {}}}
97
    public method size {}
98
    public method sort {{mode ascending}}
99
    public method xview {args}
100
    public method yview {args}
101
 
102
    protected method _addToList {}
103
    protected method _createComponents {}
104
    protected method _deleteList {first {last {}}}
105
    protected method _deleteText {first {last {}}}
106
    protected method _doLayout {{when later}}
107
    protected method _drawArrow {}
108
    protected method _dropdownBtnRelease {{window {}} {x 1} {y 1}}
109
    protected method _ignoreNextBtnRelease {ignore}
110
    protected method _next {}
111
    protected method _packComponents {{when later}}
112
    protected method _positionList {}
113
    protected method _postList {}
114
    protected method _previous {}
115
    protected method _resizeArrow {}
116
    protected method _selectCmd {}
117
    protected method _toggleList {}
118
    protected method _unpostList {}
119
    protected method _commonBindings {}
120
    protected method _dropdownBindings {}
121
    protected method _simpleBindings {}
122
    protected method _listShowing {{val ""}}
123
 
124
    private method _bs {}
125
    private method _lookup {key}
126
    private method _slbListbox {}
127
    private method _stateSelect {}
128
 
129
    private variable _doit 0;
130
    private variable _inbs 0;
131
    private variable _inlookup 0;
132
    private variable _currItem {};                       ;# current selected item.
133
    private variable _ignoreRelease false        ;# next button release ignored.
134
    private variable _isPosted false;            ;# is the dropdown popped up.
135
    private variable _repacking {}        ;# non-null => _packComponents pending.
136
    private common _listShowing
137
    private common count 0
138
}
139
 
140
#
141
# Provide a lowercase access method for the Combobox class.
142
#
143
proc ::iwidgets::combobox {pathName args} {
144
    uplevel ::iwidgets::Combobox $pathName $args
145
}
146
 
147
# ------------------------------------------------------------------
148
#                                               CONSTRUCTOR
149
# ------------------------------------------------------------------
150
body iwidgets::Combobox::constructor {args} {
151
    set _listShowing($this) 0
152
 
153
    # combobox is different as all components are created
154
    # after determining what the dropdown style is...
155
 
156
    # configure args
157
    eval itk_initialize $args
158
 
159
    # create components that are dependent on options
160
    # (Scrolledlistbox, arrow button) and pack them.
161
    if {$count == 0} {
162
        image create bitmap downarrow -data {
163
            #define down_width 16
164
            #define down_height 16
165
            static unsigned char down_bits[] = {
166
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
167
                0x00, 0x00, 0x00, 0x00, 0xfc, 0x7f, 0xf8, 0x3f,
168
                0xf0, 0x1f, 0xe0, 0x0f, 0xc0, 0x07, 0x80, 0x03,
169
                0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
170
            };
171
        }
172
        image create bitmap uparrow -data {
173
            #define up_width 16
174
            #define up_height 16
175
            static unsigned char up_bits[] = {
176
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00,
177
                0xc0, 0x01, 0xe0, 0x03, 0xf0, 0x07, 0xf8, 0x0f,
178
                0xfc, 0x1f, 0xfe, 0x3f, 0x00, 0x00, 0x00, 0x00,
179
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
180
            };
181
        }
182
    }
183
    incr count
184
    _doLayout
185
}
186
 
187
# ------------------------------------------------------------------
188
#                                                  DESTRUCTOR
189
# ------------------------------------------------------------------
190
body iwidgets::Combobox::destructor {} {
191
    # catch any repacking that may be waiting for idle time
192
    if {$_repacking != ""} {
193
        after cancel $_repacking
194
    }
195
    incr count -1
196
    if {$count == 0} {
197
        image delete uparrow
198
        image delete downarrow
199
    }
200
}
201
 
202
# ================================================================
203
#                                                       OPTIONS
204
# ================================================================
205
 
206
# --------------------------------------------------------------------
207
# OPTION:  -arrowrelief
208
#
209
# Relief style used on the arrow button.
210
# --------------------------------------------------------------------
211
configbody iwidgets::Combobox::arrowrelief {}
212
 
213
# --------------------------------------------------------------------
214
# OPTION:  -completion
215
#
216
# Relief style used on the arrow button.
217
# --------------------------------------------------------------------
218
configbody iwidgets::Combobox::completion {
219
    switch -- $itk_option(-completion) {
220
 
221
        1 - yes - true - on { }
222
        default {
223
            error "bad completion option \"$itk_option(-completion)\":\
224
                                           should be boolean"
225
        }
226
    }
227
}
228
 
229
# --------------------------------------------------------------------
230
# OPTION:  -dropdown
231
#
232
# Boolean which determines the Combobox style: dropdown or simple.
233
# Because the two style's lists reside in different toplevel widgets
234
# this is more complicated than it should be.
235
# --------------------------------------------------------------------
236
configbody iwidgets::Combobox::dropdown {
237
    switch -- $itk_option(-dropdown) {
238
        1 - yes - true - on {
239
            if {[winfo exists $itk_interior.list]} {
240
                set vals [$itk_component(list) get 0 end]
241
                destroy $itk_component(list)
242
                _doLayout
243
                if [llength $vals] {
244
                    eval insert list end $vals
245
                }
246
            }
247
        }
248
 
249
            if {[winfo exists $itk_interior.popup.list]} {
250
                set vals [$itk_component(list) get 0 end]
251
                catch {destroy $itk_component(arrowBtn)}
252
                destroy $itk_component(popup)  ;# this deletes the list too
253
                _doLayout
254
                if [llength $vals] {
255
                    eval insert list end $vals
256
                }
257
            }
258
        }
259
        default {
260
            error "bad dropdown option \"$itk_option(-dropdown)\":\
261
                                           should be boolean"
262
        }
263
    }
264
}
265
 
266
# --------------------------------------------------------------------
267
# OPTION: -editable
268
#
269
# Boolean which allows/disallows user input to the entry field area.
270
# --------------------------------------------------------------------
271
configbody iwidgets::Combobox::editable {
272
    switch -- $itk_option(-editable) {
273
        1 - true - yes - on {
274
            switch -- $itk_option(-state) {
275
                normal {
276
                    $itk_component(entry) configure -state normal
277
                }
278
            }
279
        }
280
 
281
            $itk_component(entry) configure -state disabled
282
        }
283
        default {
284
            error "bad editable option \"$itk_option(-editable)\":\
285
                                   should be boolean"
286
        }
287
    }
288
}
289
 
290
# --------------------------------------------------------------------
291
# OPTION:  -grab
292
#
293
# grab-state of megawidget
294
# --------------------------------------------------------------------
295
configbody iwidgets::Combobox::grab {
296
    switch -- $itk_option(-grab) {
297
        local { }
298
        global { }
299
        default {
300
            error "bad grab value \"$itk_option(-grab)\":\
301
                                   must be global or local"
302
        }
303
    }
304
}
305
 
306
# --------------------------------------------------------------------
307
# OPTION: -listheight
308
#
309
# Listbox height in pixels. (Need to integrate the scrolledlistbox
310
# -visibleitems option here - at least for simple listbox.)
311
# --------------------------------------------------------------------
312
configbody iwidgets::Combobox::listheight {}
313
 
314
# --------------------------------------------------------------------
315
# OPTION:  -margin
316
#
317
# Spacer between the entry field and arrow button of dropdown style
318
# Comboboxes.
319
# --------------------------------------------------------------------
320
configbody iwidgets::Combobox::margin {
321
    grid columnconfigure $itk_interior 0 -minsize $itk_option(-margin)
322
}
323
 
324
# --------------------------------------------------------------------
325
# OPTION:  -popupcursor
326
#
327
# Set the cursor for the popup list.
328
# --------------------------------------------------------------------
329
configbody iwidgets::Combobox::popupcursor {}
330
 
331
# --------------------------------------------------------------------
332
# OPTION:  -selectioncommand
333
#
334
# Defines the proc to be called when an item is selected in the list.
335
# --------------------------------------------------------------------
336
configbody iwidgets::Combobox::selectioncommand {}
337
 
338
# --------------------------------------------------------------------
339
# OPTION:  -state
340
#
341
# overall state of megawidget
342
# --------------------------------------------------------------------
343
configbody iwidgets::Combobox::state {
344
    switch -- $itk_option(-state) {
345
        disabled {
346
            $itk_component(entry) configure -state disabled
347
        }
348
        normal {
349
            switch -- $itk_option(-editable) {
350
                1 - true - yes - on {
351
                    $itk_component(entry) configure -state normal
352
                }
353
 
354
                    $itk_component(entry) configure -state disabled
355
                }
356
            }
357
        }
358
        default {
359
            error "bad state value \"$itk_option(-state)\":\
360
                                   must be normal  or disabled"
361
        }
362
    }
363
    if {[info exists itk_component(arrowBtn)]} {
364
        $itk_component(arrowBtn) configure -state $itk_option(-state)
365
    }
366
}
367
 
368
# --------------------------------------------------------------------
369
# OPTION: -unique
370
#
371
# Boolean which disallows/allows adding duplicate items to the listbox.
372
# --------------------------------------------------------------------
373
configbody iwidgets::Combobox::unique {
374
    # boolean error check
375
    switch -- $itk_option(-unique) {
376
        1 - true - yes - on { }
377
 
378
        default {
379
            error "bad unique value \"$itk_option(-unique)\":\
380
                                   should be boolean"
381
        }
382
    }
383
}
384
 
385
# =================================================================
386
#                                                        METHODS
387
# =================================================================
388
 
389
# ------------------------------------------------------
390
#  PUBLIC METHOD: clear ?component?
391
#
392
#  Remove all elements from the listbox, all contents
393
#  from the entry component, or both (if all).
394
#
395
# ------------------------------------------------------
396
body iwidgets::Combobox::clear {{component all}} {
397
    switch -- $component {
398
        entry {
399
            iwidgets::Entryfield::clear
400
        }
401
        list {
402
            delete list 0 end
403
        }
404
        all {
405
            delete list 0 end
406
            iwidgets::Entryfield::clear
407
        }
408
        default {
409
            error "bad Combobox component \"$component\":\
410
                                   must be entry, list, or all."
411
        }
412
    }
413
    return
414
}
415
 
416
# ------------------------------------------------------
417
# PUBLIC METHOD: curselection
418
#
419
# Return the current selection index.
420
#
421
# ------------------------------------------------------
422
body iwidgets::Combobox::curselection {} {
423
    return [$itk_component(list) curselection]
424
}
425
 
426
# ------------------------------------------------------
427
# PUBLIC METHOD: delete component first ?last?
428
#
429
# Delete an item or items from the listbox OR delete
430
# text from the entry field. First argument determines
431
# which component deletion occurs in - valid values are
432
# entry or list.
433
#
434
# ------------------------------------------------------
435
body iwidgets::Combobox::delete {component first {last {}}} {
436
    switch -- $component {
437
        entry {
438
            iwidgets::Entryfield::delete $first $last
439
        }
440
        list {
441
            _deleteList $first $last
442
        }
443
        default {
444
            error "bad Combobox component \"$component\":\
445
                                   must be entry or list."
446
        }
447
    }
448
}
449
 
450
# ------------------------------------------------------
451
# PUBLIC METHOD: get ?index?
452
#
453
#
454
# Retrieve entry contents if no args OR use args as list
455
# index and retrieve list item at index .
456
#
457
# ------------------------------------------------------
458
body iwidgets::Combobox::get {{index {}}} {
459
    # no args means to get the current text in the entry field area
460
    if {$index == {}} {
461
        iwidgets::Entryfield::get
462
    } else {
463
        eval $itk_component(list) get $index
464
    }
465
}
466
 
467
# ------------------------------------------------------
468
# PUBLIC METHOD: getcurselection
469
#
470
# Return currently selected item in the listbox. Shortcut
471
# version of get curselection command combination.
472
#
473
# ------------------------------------------------------
474
body iwidgets::Combobox::getcurselection {} {
475
    return [$itk_component(list) getcurselection]
476
}
477
 
478
# ------------------------------------------------------------------
479
# PUBLIC METHOD: ivoke
480
#
481
# Pops up or down a dropdown combobox.
482
#
483
# ------------------------------------------------------------------
484
body iwidgets::Combobox::invoke {} {
485
    if {$itk_option(-dropdown)} {
486
        return [_toggleList]
487
    }
488
    return
489
}
490
 
491
# ------------------------------------------------------------
492
# PUBLIC METHOD: insert comonent index string ?string ...?
493
#
494
# Insert an item into the listbox OR text into the entry area.
495
# Valid component names are entry or list.
496
#
497
# ------------------------------------------------------------
498
body iwidgets::Combobox::insert {component index args} {
499
    set nargs [llength $args]
500
 
501
    if {$nargs == 0} {
502
        error "no value given for parameter \"string\" in function\
503
                           \"Combobox::insert\""
504
    }
505
 
506
    switch -- $component {
507
        entry {
508
            if { $nargs > 1} {
509
                error "called function \"Combobox::insert entry\"\
510
                                           with too many arguments"
511
            } else {
512
                if {$itk_option(-state) == "normal"} {
513
                    eval iwidgets::Entryfield::insert $index $args
514
                    [code $this _lookup ""]
515
                }
516
            }
517
        }
518
        list {
519
            if {$itk_option(-state) == "normal"} {
520
                eval $itk_component(list) insert $index $args
521
            }
522
        }
523
        default {
524
            error "bad Combobox component \"$component\": must\
525
                                   be entry or list."
526
        }
527
    }
528
}
529
 
530
# ------------------------------------------------------
531
# PUBLIC METHOD: justify direction
532
#
533
# Wrapper for justifying the listbox items in one of
534
# 4 directions:  top, bottom, left, or right.
535
#
536
# ------------------------------------------------------
537
body iwidgets::Combobox::justify {direction} {
538
    return [$itk_component(list) justify $direction]
539
}
540
 
541
# ------------------------------------------------------------------
542
# PUBLIC METHOD: see index
543
#
544
# Adjusts the view such that the element given by index is visible.
545
# ------------------------------------------------------------------
546
body iwidgets::Combobox::see {index} {
547
    return [$itk_component(list) see $index]
548
}
549
 
550
# ------------------------------------------------------------------
551
# PUBLIC METHOD: selection option first ?last?
552
#
553
# Adjusts the selection within the listbox and changes the contents
554
# of the entry component to be the value of the selected list item.
555
# ------------------------------------------------------------------
556
body iwidgets::Combobox::selection {option first {last {}}} {
557
    # thin wrap
558
    if {$option == "set"} {
559
        $itk_component(list) selection clear 0 end
560
        $itk_component(list) selection set $first
561
        set rtn ""
562
    } else {
563
        set rtn [eval $itk_component(list) selection $option $first $last]
564
    }
565
    set _currItem $first
566
 
567
    # combobox additions
568
    set theText [getcurselection]
569
    if {$theText != [$itk_component(entry) get]} {
570
        clear entry
571
        if {$theText != ""} {
572
            insert entry 0 $theText
573
        }
574
    }
575
    return $rtn
576
}
577
 
578
# ------------------------------------------------------------------
579
# PUBLIC METHOD: size
580
#
581
# Returns a decimal string indicating the total number of elements
582
# in the listbox.
583
# ------------------------------------------------------------------
584
body iwidgets::Combobox::size {} {
585
    return [$itk_component(list) size]
586
}
587
 
588
# ------------------------------------------------------
589
# PUBLIC METHOD: sort ?mode?
590
#
591
# Sort the current list in either "ascending" or "descending" order.
592
#
593
#       jss: how should i handle selected items?
594
#
595
# ------------------------------------------------------
596
body iwidgets::Combobox::sort {{mode ascending}} {
597
    $itk_component(list) sort $mode
598
    #    return [$itk_component(list) sort $mode]
599
}
600
 
601
 
602
# ------------------------------------------------------------------
603
# PUBLIC METHOD: xview ?arg arg ...?
604
#
605
# Change or query the vertical position of the text in the list box.
606
# ------------------------------------------------------------------
607
body iwidgets::Combobox::xview {args} {
608
    return [eval $itk_component(list) xview $args]
609
}
610
 
611
# ------------------------------------------------------------------
612
# PUBLIC METHOD: yview ?arg arg ...?
613
#
614
# Change or query the horizontal position of the text in the list box.
615
# ------------------------------------------------------------------
616
body iwidgets::Combobox::yview {args} {
617
    return [eval $itk_component(list) yview $args]
618
}
619
 
620
# ------------------------------------------------------
621
# PROTECTED METHOD: _addToList
622
#
623
# Add the current item in the entry to the listbox.
624
#
625
# ------------------------------------------------------
626
body iwidgets::Combobox::_addToList {} {
627
    set input [get]
628
    if {$input != ""} {
629
        if {$itk_option(-unique)} {
630
            # if item is already in list, select it and exit
631
            set item [lsearch -exact [$itk_component(list) get 0 end] $input]
632
            if {$item != -1} {
633
                selection clear 0 end
634
                if {$item != {}} {
635
                    selection set $item $item
636
                    set _currItem $item
637
                }
638
                return
639
            }
640
        }
641
        # add the item to end of list
642
        selection clear 0 end
643
        insert list end $input
644
        selection set end end
645
    }
646
}
647
 
648
# ------------------------------------------------------
649
# PROTECTED METHOD:       _createComponents
650
#
651
# Create deferred combobox components and add bindings.
652
#
653
# ------------------------------------------------------
654
body iwidgets::Combobox::_createComponents {} {
655
    if {$itk_option(-dropdown)} {
656
        # --- build a dropdown combobox ---
657
 
658
        # make the arrow childsite be on the right hand side
659
        configure -childsitepos e -command [code $this _addToList]
660
 
661
        # arrow button to popup the list
662
        itk_component add arrowBtn {
663
            button $itk_interior.arrowBtn -borderwidth 2 \
664
                -width 15 -height 15 -image downarrow \
665
                -command [code $this _toggleList] -state $itk_option(-state)
666
        } {
667
            keep -background -borderwidth -cursor  -state \
668
                -highlightcolor -highlightthickness
669
            rename -relief -arrowrelief arrowRelief Relief
670
            rename -highlightbackground -background background Background
671
        }
672
 
673
        # popup list container
674
        itk_component add popup {
675
            toplevel $itk_interior.popup
676
        } {
677
            keep -background -cursor
678
        }
679
        wm withdraw $itk_interior.popup
680
 
681
        # the listbox
682
        itk_component add list {
683
            iwidgets::Scrolledlistbox $itk_interior.popup.list -exportselection no \
684
                -vscrollmode dynamic -hscrollmode dynamic -selectmode browse
685
        } {
686
            keep -background -borderwidth -cursor -foreground \
687
                -highlightcolor -highlightthickness \
688
                -hscrollmode -selectbackground \
689
                -selectborderwidth -selectforeground -textbackground \
690
                -textfont -vscrollmode
691
            rename -height -listheight listHeight Height
692
            rename -cursor -popupcursor popupCursor Cursor
693
        }
694
        # mode specific bindings
695
        _dropdownBindings
696
 
697
        # Ugly hack to avoid tk buglet revealed in _dropdownBtnRelease where
698
        # relief is used but not set in scrollbar.tcl.
699
        global tkPriv
700
        set tkPriv(relief) raise
701
 
702
    } else {
703
        # --- build a simple combobox ---
704
        configure -childsitepos s
705
        itk_component add list {
706
            iwidgets::Scrolledlistbox $itk_interior.list -exportselection no \
707
                -vscrollmode dynamic -hscrollmode dynamic
708
        } {
709
            keep -background -borderwidth -cursor -foreground \
710
                -highlightcolor -highlightthickness \
711
                -hscrollmode -selectbackground \
712
                -selectborderwidth -selectforeground -textbackground \
713
                -textfont -visibleitems -vscrollmode
714
            rename -height -listheight listHeight Height
715
        }
716
        # add mode specific bindings
717
        _simpleBindings
718
    }
719
 
720
    # popup cursor applies only to the list within the combobox
721
    configure -popupcursor $itk_option(-popupcursor)
722
 
723
    # add mode independent bindings
724
    _commonBindings
725
}
726
 
727
# ------------------------------------------------------
728
# PROTECTED METHOD: _deleteList first ?last?
729
#
730
# Delete an item or items from the listbox. Called via
731
# "delete list args".
732
#
733
# ------------------------------------------------------
734
body iwidgets::Combobox::_deleteList {first {last {}}} {
735
 
736
    if {$last == {}} {
737
        set last $first
738
    }
739
    $itk_component(list) delete $first $last
740
 
741
    # remove the item if it is no longer in the list
742
    set text [$this get]
743
    if {$text != ""} {
744
        set index [lsearch -exact [$itk_component(list) get 0 end] $text ]
745
        if {$index == -1} {
746
            clear entry
747
        }
748
    }
749
    return
750
}
751
 
752
# ------------------------------------------------------
753
# PROTECTED METHOD: _deleteText first ?last?
754
#
755
# Renamed Entryfield delete method. Called via "delete entry args".
756
#
757
# ------------------------------------------------------
758
body iwidgets::Combobox::_deleteText {first {last {}}} {
759
    $itk_component(entry) configure -state normal
760
    set rtrn [delete $first $last]
761
    switch -- $itk_option(-editable) {
762
 
763
            $itk_component(entry) configure -state disabled
764
        }
765
    }
766
    return $rtrn
767
}
768
 
769
# ------------------------------------------------------
770
# PROTECTED METHOD:       _doLayout ?when?
771
#
772
# Call methods to create and pack the Combobox components.
773
#
774
# ------------------------------------------------------
775
body iwidgets::Combobox::_doLayout {{when later}} {
776
    _createComponents
777
    _packComponents $when
778
}
779
 
780
 
781
# ------------------------------------------------------
782
# PROTECTED METHOD:       _drawArrow
783
#
784
# Draw the arrow button. Determines packing according to
785
# -labelpos.
786
#
787
# ------------------------------------------------------
788
body iwidgets::Combobox::_drawArrow {} {
789
    set flip false
790
    set relief ""
791
    set fg [cget -foreground]
792
    if {$_isPosted} {
793
        set flip true
794
        set relief "-relief sunken"
795
    } else {
796
        set relief "-relief $itk_option(-arrowrelief)"
797
    }
798
 
799
    if {$flip} {
800
        #
801
        #                               draw up arrow
802
        #
803
        eval $itk_component(arrowBtn) configure -image uparrow $relief
804
    } else {
805
        #
806
        #                               draw down arrow
807
        #
808
        eval $itk_component(arrowBtn) configure -image downarrow $relief
809
    }
810
}
811
 
812
# ------------------------------------------------------
813
# PROTECTED METHOD: _dropdownBtnRelease window x y
814
#
815
# Event handler for button releases while a dropdown list
816
# is posted.
817
#
818
# ------------------------------------------------------
819
body iwidgets::Combobox::_dropdownBtnRelease {{window {}} {x 1} {y 1}} {
820
 
821
    # if it's a scrollbar then ignore the release
822
    if {($window == [$itk_component(list) component vertsb]) ||
823
        ($window == [$itk_component(list) component horizsb])} {
824
        return
825
    }
826
 
827
    # 1st release allows list to stay up unless we are in listbox
828
    if {$_ignoreRelease} {
829
        _ignoreNextBtnRelease false
830
        return
831
    }
832
 
833
    # should I use just the listbox or also include the scrollbars
834
    if { ($x >= 0) && ($x < [winfo width [_slbListbox]])
835
         && ($y >= 0) && ($y < [winfo height [_slbListbox]])} {
836
        _stateSelect
837
    }
838
 
839
    _unpostList
840
}
841
 
842
# ------------------------------------------------------
843
# PROTECTED METHOD: _ignoreNextBtnRelease ignore
844
#
845
# Set private variable _ignoreRelease. If this variable
846
# is true then the next button release will not remove
847
# a dropdown list.
848
#
849
# ------------------------------------------------------
850
body iwidgets::Combobox::_ignoreNextBtnRelease {ignore} {
851
    set _ignoreRelease $ignore
852
}
853
 
854
# ------------------------------------------------------
855
# PROTECTED METHOD:       _next
856
#
857
# Select the next item in the list.
858
#
859
# ------------------------------------------------------
860
body iwidgets::Combobox::_next {} {
861
    if {[size] <= 1} {
862
        return
863
    }
864
    set i [curselection]
865
    if {($i == {}) || ($i == [expr [size]-1]) } {
866
        set i 0
867
    } else {
868
        incr i
869
    }
870
    selection clear 0 end
871
    selection set $i $i
872
    see $i
873
    set _currItem $i
874
}
875
 
876
# ------------------------------------------------------
877
# PROTECTED METHOD:       _packComponents ?when?
878
#
879
# Pack the components of the combobox and add bindings.
880
#
881
# ------------------------------------------------------
882
body iwidgets::Combobox::_packComponents {{when later}} {
883
    if {$when == "later"} {
884
        if {$_repacking == ""} {
885
            set _repacking [after idle [code $this _packComponents now]]
886
            return
887
        }
888
    } elseif {$when != "now"} {
889
        error "bad option \"$when\": should be now or later"
890
    }
891
 
892
    if {$itk_option(-dropdown)} {
893
        grid configure $itk_component(list) -row 1 -column 0 -sticky news
894
        _resizeArrow
895
        grid config $itk_component(arrowBtn) -row 0 -column 1 -sticky nsew
896
    } else {
897
        # size and pack list hack
898
        grid configure $itk_component(entry) -row 0 -column 0 -sticky ew
899
        grid configure $itk_component(efchildsite) -row 1 -column 0 -sticky nsew
900
        grid configure $itk_component(list) -row 0 -column 0 -sticky nsew
901
 
902
        grid rowconfigure $itk_component(efchildsite) 1 -weight 1
903
        grid columnconfigure $itk_component(efchildsite) 0 -weight 1
904
    }
905
    set _repacking ""
906
}
907
 
908
# ------------------------------------------------------
909
# PROTECTED METHOD:       _positionList
910
#
911
# Determine the position (geometry) for the popped up list
912
# and map it to the screen.
913
#
914
# ------------------------------------------------------
915
body iwidgets::Combobox::_positionList {} {
916
 
917
    set x [winfo rootx $itk_component(entry) ]
918
    set y [expr [winfo rooty $itk_component(entry) ] + \
919
               [winfo height $itk_component(entry) ]]
920
    set w [winfo width $itk_component(entry) ]
921
    set h [winfo height [_slbListbox] ]
922
    set sh [winfo screenheight .]
923
 
924
    if {([expr $y+$h] > $sh) && ($y > [expr $sh/2])} {
925
        set y [expr [winfo rooty $itk_component(entry) ] - $h]
926
    }
927
 
928
    $itk_component(list) configure -width $w
929
    wm overrideredirect $itk_component(popup) 0
930
    wm geometry $itk_component(popup) +$x+$y
931
    wm overrideredirect $itk_component(popup) 1
932
}
933
 
934
# ------------------------------------------------------
935
# PROTECTED METHOD:       _postList
936
#
937
# Pop up the list in a dropdown style Combobox.
938
#
939
# ------------------------------------------------------
940
body iwidgets::Combobox::_postList {} {
941
    if {[$itk_component(list) size] == ""} {
942
        return
943
    }
944
 
945
    set _isPosted true
946
    _positionList
947
 
948
    # map window and do a grab
949
    wm deiconify $itk_component(popup)
950
    _listShowing -wait
951
    if {$itk_option(-grab) == "global"} {
952
        grab -global $itk_component(popup)
953
    } else {
954
        grab $itk_component(popup)
955
    }
956
    raise $itk_component(popup)
957
    focus $itk_component(popup)
958
    _drawArrow
959
}
960
 
961
# ------------------------------------------------------
962
# PROTECTED METHOD:        _previous
963
#
964
# Select the previous item in the list. Wraps at front
965
# and end of list.
966
#
967
# ------------------------------------------------------
968
body iwidgets::Combobox::_previous {} {
969
    if {[size] <= 1} {
970
        return
971
    }
972
    set i [curselection]
973
    if {$i == "" || $i == 0} {
974
        set i [expr [size] - 1]
975
    } else {
976
        incr i -1
977
    }
978
    selection clear 0 end
979
    selection set $i $i
980
    see $i
981
    set _currItem $i
982
}
983
 
984
# ------------------------------------------------------
985
# PROTECTED METHOD:       _resizeArrow
986
#
987
# Recalculate the arrow button size and then redraw it.
988
#
989
# ------------------------------------------------------
990
body iwidgets::Combobox::_resizeArrow {} {
991
    set bw [expr [$itk_component(arrowBtn) cget -borderwidth]+ \
992
                [$itk_component(arrowBtn) cget -highlightthickness]]
993
    set newHeight [expr [winfo reqheight $itk_component(entry) ]-(2*$bw) - 2]
994
    $itk_component(arrowBtn) configure -width $newHeight -height $newHeight
995
    _drawArrow
996
}
997
 
998
# ------------------------------------------------------
999
# PROTECTED METHOD:       _selectCmd
1000
#
1001
# Called when list item is selected to insert new text
1002
# in entry, and call user -command callback if defined.
1003
#
1004
# ------------------------------------------------------
1005
body iwidgets::Combobox::_selectCmd {} {
1006
    $itk_component(entry) configure -state normal
1007
 
1008
    set _currItem [$itk_component(list) curselection]
1009
    set item [$itk_component(list) getcurselection]
1010
    clear entry
1011
    $itk_component(entry) insert 0 $item
1012
    switch -- $itk_option(-editable) {
1013
 
1014
            $itk_component(entry) configure -state disabled
1015
        }
1016
    }
1017
 
1018
    # execute user command
1019
    if {$itk_option(-selectioncommand) != ""} {
1020
        uplevel #0 $itk_option(-selectioncommand)
1021
    }
1022
}
1023
 
1024
# ------------------------------------------------------
1025
# PROTECTED METHOD:      _toggleList
1026
#
1027
# Post or unpost the dropdown listbox (toggle).
1028
#
1029
# ------------------------------------------------------
1030
body iwidgets::Combobox::_toggleList {} {
1031
    if {[winfo ismapped $itk_component(popup)] } {
1032
        _unpostList
1033
    } else {
1034
        _postList
1035
    }
1036
}
1037
 
1038
# ------------------------------------------------------
1039
# PROTECTED METHOD:       _unpostList
1040
#
1041
# Unmap the listbox (pop it down).
1042
#
1043
# ------------------------------------------------------
1044
body iwidgets::Combobox::_unpostList {} {
1045
    # Determine if event occured in the scrolledlistbox and, if it did,
1046
    # don't unpost it. (A selection in the list unposts it correctly and
1047
    # in the scrollbar we don't want to unpost it.)
1048
    set x [winfo x $itk_component(list)]
1049
    set y [winfo y $itk_component(list)]
1050
    set w [winfo width $itk_component(list)]
1051
    set h [winfo height $itk_component(list)]
1052
 
1053
    wm withdraw $itk_component(popup)
1054
    grab release $itk_component(popup)
1055
 
1056
    set _isPosted false
1057
 
1058
    $itk_component(list) selection clear 0 end
1059
    if {$_currItem != {}} {
1060
        $itk_component(list) selection set $_currItem $_currItem
1061
        $itk_component(list) activate $_currItem
1062
    }
1063
 
1064
    switch -- $itk_option(-editable) {
1065
        1 - true - yes - on {
1066
            $itk_component(entry) configure -state normal
1067
        }
1068
 
1069
            $itk_component(entry) configure -state disabled
1070
        }
1071
    }
1072
 
1073
    _drawArrow
1074
}
1075
 
1076
# ------------------------------------------------------
1077
# PROTECTED METHOD:       _commonBindings
1078
#
1079
# Bindings that are used by both simple and dropdown
1080
# style Comboboxes.
1081
#
1082
# ------------------------------------------------------
1083
body iwidgets::Combobox::_commonBindings {} {
1084
    bind $itk_component(entry)  [code $this _bs]
1085
    bind $itk_component(entry)  [code $this _lookup %K]
1086
    bind $itk_component(entry)        [code $this _next]
1087
    bind $itk_component(entry)          [code $this _previous]
1088
    bind $itk_component(entry)   [code $this _next]
1089
    bind $itk_component(entry)   [code $this _previous]
1090
    bind [_slbListbox]           [code $this _next]
1091
    bind [_slbListbox]           [code $this _previous]
1092
}
1093
 
1094
 
1095
# ------------------------------------------------------
1096
# PROTECTED METHOD: _dropdownBindings
1097
#
1098
# Bindings used only by the dropdown type Combobox.
1099
#
1100
# ------------------------------------------------------
1101
body iwidgets::Combobox::_dropdownBindings {} {
1102
    bind $itk_component(popup)   [code $this _unpostList]
1103
    bind $itk_component(popup)    \
1104
        "[code $this _stateSelect]; [code $this _unpostList]"
1105
    bind $itk_component(popup)   \
1106
        "[code $this _stateSelect]; [code $this _unpostList]"
1107
    bind $itk_component(popup)   \
1108
        [code $this _dropdownBtnRelease %W %x %y]
1109
 
1110
    bind $itk_component(list)   \
1111
        [code $this _listShowing 1]
1112
    bind $itk_component(list)   \
1113
        [code $this _listShowing 0]
1114
 
1115
    # once in the listbox, we drop on the next release (unless in scrollbar)
1116
    bind [_slbListbox]      \
1117
        [code $this _ignoreNextBtnRelease false]
1118
 
1119
    bind $itk_component(arrowBtn) <3>          [code $this _next]
1120
    bind $itk_component(arrowBtn)     [code $this _previous]
1121
    bind $itk_component(arrowBtn)        [code $this _next]
1122
    bind $itk_component(arrowBtn)          [code $this _previous]
1123
    bind $itk_component(arrowBtn)   [code $this _next]
1124
    bind $itk_component(arrowBtn)   [code $this _previous]
1125
    bind $itk_component(arrowBtn)  [code $this _toggleList]
1126
    bind $itk_component(arrowBtn)    [code $this _toggleList]
1127
    bind $itk_component(arrowBtn)      [code $this _toggleList]
1128
    bind $itk_component(arrowBtn)       [code $this _toggleList]
1129
 
1130
    bind $itk_component(entry)      [code $this _resizeArrow]
1131
    bind $itk_component(entry)     [code $this _toggleList]
1132
    bind $itk_component(entry)       [code $this _toggleList]
1133
}
1134
 
1135
# ------------------------------------------------------
1136
# PROTECTED METHOD: _simpleBindings
1137
#
1138
# Bindings used only by the simple type Comboboxes.
1139
#
1140
# ------------------------------------------------------
1141
body iwidgets::Combobox::_simpleBindings {} {
1142
    bind [_slbListbox]          [code $this _stateSelect]
1143
    #               "[code $this _stateselect]; [code $this _selectCmd]"
1144
 
1145
 
1146
    bind [_slbListbox]              [code $this _stateSelect]
1147
    bind [_slbListbox]             [code $this _stateSelect]
1148
    bind $itk_component(entry)      ""
1149
    bind $itk_component(entry)  ""
1150
    bind $itk_component(entry)    ""
1151
    bind $itk_component(entry)   ""
1152
}
1153
 
1154
# ------------------------------------------------------
1155
# PROTECTED METHOD: _listShowing ?val?
1156
#
1157
# Used instead of "tkwait visibility" to make sure that
1158
# the dropdown list is visible.  Whenever the list gets
1159
# mapped or unmapped, this method is called to keep
1160
# track of it.  When it is called with the value "-wait",
1161
# it waits for the list to be mapped.
1162
# ------------------------------------------------------
1163
body iwidgets::Combobox::_listShowing {{val ""}} {
1164
    if {$val == ""} {
1165
        return $_listShowing($this)
1166
    } elseif {$val == "-wait"} {
1167
        while {!$_listShowing($this)} {
1168
            tkwait variable [scope _listShowing($this)]
1169
        }
1170
        return
1171
    }
1172
    set _listShowing($this) $val
1173
}
1174
 
1175
# ------------------------------------------------------
1176
# PRIVATE METHOD:        _slbListbox
1177
#
1178
# Access the tk listbox window out of the scrolledlistbox.
1179
#
1180
# ------------------------------------------------------
1181
body iwidgets::Combobox::_slbListbox {} {
1182
    return [$itk_component(list) component listbox]
1183
}
1184
 
1185
# ------------------------------------------------------
1186
# PRIVATE METHOD:        _stateSelect
1187
#
1188
# only allows a B1 release in the listbox to have an effect if -state is
1189
#       normal.
1190
#
1191
# ------------------------------------------------------
1192
body iwidgets::Combobox::_stateSelect {} {
1193
    switch --  $itk_option(-state) {
1194
        normal {
1195
            [code $this _selectCmd]
1196
        }
1197
    }
1198
}
1199
 
1200
# ------------------------------------------------------
1201
# PRIVATE METHOD:        _bs
1202
#
1203
# A part of the auto-completion code, this function sets a flag when the
1204
#       Backspace key is hit and there is a selection in the entry field.
1205
# Note that it's probably buggy to assume that a selection being present
1206
#       means that that selection came from auto-completion.
1207
#
1208
# ------------------------------------------------------
1209
body iwidgets::Combobox::_bs {} {
1210
    #
1211
    #           exit if completion is turned off
1212
    #
1213
    switch -- $itk_option(-completion) {
1214
 
1215
            return
1216
        }
1217
    }
1218
    #
1219
    #           critical section flag.  it ain't perfect, but for most usage it'll
1220
    #           keep us from being in this code "twice" at the same time
1221
    #           (auto-repeated keystrokes are a pain!)
1222
    #
1223
    if {$_inbs} {
1224
        return
1225
    } else {
1226
        set _inbs 1
1227
    }
1228
 
1229
    #
1230
    #           set the _doit flag if there is a selection set in the entry field
1231
    #
1232
    set _doit 0
1233
    if [$itk_component(entry) selection present] {
1234
        set _doit 1
1235
    }
1236
 
1237
    #
1238
    #           clear the semaphore and return
1239
    #
1240
    set _inbs 0
1241
}
1242
 
1243
# ------------------------------------------------------
1244
# PRIVATE METHOD:        _lookup
1245
#
1246
# handles auto-completion of text typed (or insert'd) into the entry field.
1247
#
1248
# ------------------------------------------------------
1249
body iwidgets::Combobox::_lookup {key} {
1250
    #
1251
    #           exit if completion is turned off
1252
    #
1253
    switch -- $itk_option(-completion) {
1254
 
1255
            return
1256
        }
1257
    }
1258
 
1259
    #
1260
    #           critical section flag.  it ain't perfect, but for most usage it'll
1261
    #           keep us from being in this code "twice" at the same time
1262
    #           (auto-repeated keystrokes are a pain!)
1263
    #
1264
    if {$_inlookup} {
1265
        return
1266
    } else {
1267
        set _inlookup 1
1268
    }
1269
 
1270
    #
1271
    #           if state of megawidget is disabled, or the entry is not editable,
1272
    #           clear the semaphore and exit
1273
    #
1274
    if {$itk_option(-state) == "disabled" \
1275
            || [lsearch {on 1 true yes} $itk_option(-editable)] == -1} {
1276
        set _inlookup 0
1277
        return
1278
    }
1279
 
1280
    #
1281
    #           okay, *now* we can get to work
1282
    #           the _bs function is called on keyPRESS of BackSpace, and will set
1283
    #           the _doit flag if there's a selection set in the entryfield.  If
1284
    #           there is, we're assuming that it's generated by completion itself
1285
    #           (this is probably a Bad Assumption), so we'll want to whack the
1286
    #           selected text, as well as the character immediately preceding the
1287
    #           insertion cursor.
1288
    #
1289
    if {$key == "BackSpace"} {
1290
        if {$_doit} {
1291
            set first [expr [$itk_component(entry) index insert] -1]
1292
            $itk_component(entry) delete $first end
1293
            $itk_component(entry) icursor $first
1294
        }
1295
    }
1296
 
1297
    #
1298
    #           get the text left in the entry field, and its length.  if
1299
    #           zero-length, clear the selection in the listbox, clear the
1300
    #           semaphore, and boogie.
1301
    #
1302
    set text [get]
1303
    set len [string length $text]
1304
    if {$len == 0} {
1305
        $itk_component(list) selection clear 0 end
1306
        set _inlookup 0
1307
        return
1308
    }
1309
 
1310
    #
1311
    #           okay, so we have to do a lookup.  find the first match in the
1312
    #           listbox to the text we've got in the entry field (glob).
1313
    #           if one exists, clear the current listbox selection, and set it to
1314
    #           the one we just found, making that one visible in the listbox.
1315
    #           then, pick off the text from the listbox entry that hadn't yet been
1316
    #           entered into the entry field.  we need to tack that text onto the
1317
    #           end of the entry field, select it, and then set the insertion cursor
1318
    #           back to just before the point where we just added that text.
1319
    #           if one didn't exist, then just clear the listbox selection
1320
    #
1321
    set item [lsearch [$itk_component(list) get 0 end] "$text*" ]
1322
    if {$item != -1} {
1323
        $itk_component(list) selection clear 0 end
1324
        $itk_component(list) selection set $item $item
1325
        see $item
1326
        set remainder [string range [$itk_component(list) get $item] \
1327
                           $len end]
1328
        $itk_component(entry) insert end $remainder
1329
        $itk_component(entry) selection range $len end
1330
        $itk_component(entry) icursor $len
1331
    } else {
1332
        $itk_component(list) selection clear 0 end
1333
    }
1334
    #
1335
    #           clear the semaphore and return
1336
    #
1337
    set _inlookup 0
1338
    return
1339
}

powered by: WebSVN 2.1.0

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