#::source [::file join $::qw_library system qw_iwidgets.qw_tcl] # ------------------------------------------------------------ # Copyright (c) 2003, 2004, 2005 # Q.W.Page Associates Inc. # www.qwpage.com # All rights reserved. # ------------------------------------------------------------ # # ::iwidgets::qw_Disjointlistbox # #// ------------------------------------------------------------ #// # NOTICE #// #// This is based on the Iwidgets 4.0.2 disjointlistbox source from: \iwidgets4.0.2\scripts\disjointlistbox.itk #// #// I had to do this for a few reasons: #// #// - KitTen contains an older version of Iwidgets; 3.0.1 #// disjointlistbox in 3.0.1 did not have the options -lhssortoption & -rhssortoption #// These options were needed for the PRTACCTS column selection dialog where we #// didn't want the selected columns sorted, which is the only behaviour in 3.0.1. #// #// - QWFIX_1 - Remove the "item count" labels below the list boxes (who cares how many items?) #// #// - QWFIX_2 - Transferring items betweeen the list boxes had a bad bug. If an item #// contained whitespace, then it was split and added as separate items to the #// destination lstbox. #// #// - more to come ... #// #// ------------------------------------------------------------ # # ::iwidgets::qw_Disjointlistbox # ---------------------------------------------------------------------- # Implements a widget which maintains a disjoint relationship between # the items displayed by two listboxes. The disjointlistbox is composed # of 2 Scrolledlistboxes, 2 Pushbuttons, and 2 labels. # # The disjoint behavior of this widget exists between the two Listboxes, # That is, a given instance of a ::iwidgets::Disjointlistbox will never # exist which has Listbox widgets with items in common. # # Users may transfer items between the two Listbox widgets using the # the two Pushbuttons. # # The options include the ability to configure the "items" displayed by # either of the two Listboxes and to control the placement of the insertion # and removal buttons. # # The following depicts the allowable "-buttonplacement" option values # and their associated layout: # # "-buttonplacement" => center # # -------------------------- # |listbox| |listbox| # | |________| | # | (LHS) | button | (RHS) | # | |========| | # | | button | | # |_______|--------|_______| # | count | | count | # -------------------------- # # "-buttonplacement" => bottom # # --------------------- # | listbox | listbox | # | (LHS) | (RHS) | # |_________|_________| # | button | button | # |---------|---------| # | count | count | # --------------------- # # ---------------------------------------------------------------------- # AUTHOR: John A. Tucker EMAIL: jatucker@spd.dsccc.com # # ====================================================================== # # Default resources. # option add *Disjointlistbox.lhsLabelText Available widgetDefault option add *Disjointlistbox.rhsLabelText Current widgetDefault option add *Disjointlistbox.lhsButtonLabel {Insert >>} widgetDefault option add *Disjointlistbox.rhsButtonLabel {<< Remove} widgetDefault option add *Disjointlistbox.vscrollMode static widgetDefault option add *Disjointlistbox.hscrollMode static widgetDefault option add *Disjointlistbox.selectMode multiple widgetDefault option add *Disjointlistbox.labelPos nw widgetDefault option add *Disjointlistbox.buttonPlacement bottom widgetDefault option add *Disjointlistbox.lhsSortOption increasing widgetDefault option add *Disjointlistbox.rhsSortOption increasing widgetDefault # # Usual options. # itk::usual Disjointlistbox { keep -background -textbackground -cursor \ -foreground -textfont -labelfont } # ---------------------------------------------------------------------- # ::iwidgets::qw_Disjointlistbox # ---------------------------------------------------------------------- ::itcl::class ::iwidgets::qw_Disjointlistbox { inherit itk::Widget # # options # itk_option define -buttonplacement buttonPlacement ButtonPlacement bottom itk_option define -lhsbuttonlabel lhsButtonLabel LabelText {Insert >>} itk_option define -rhsbuttonlabel rhsButtonLabel LabelText {<< Remove} itk_option define -lhssortoption lhsSortOption LhsSortOption increasing itk_option define -rhssortoption rhsSortOption RhsSortOption increasing constructor {args} {} destructor { # ::puts "20050201 qw_Disjointlistbox destructor"; } # # PUBLIC # public { method clear {} method getlhs {{first 0} {last end}} method getrhs {{first 0} {last end}} method lhs {args} method insertlhs {items} method insertrhs {items} method setlhs {items} method setrhs {items} method rhs {args} } #QWFIX_3 method move_up {args} method move_down {args} # # PROTECTED # protected { method insert {theListbox items} method listboxClick {clickSide otherSide} method listboxDblClick {clickSide otherSide} method remove {theListbox items} #QWFIX_1 #// method showCount {} method transfer {} variable sourceListbox {} variable destinationListbox {} } } # # Provide a lowercased access method for the ::iwidgets::qw_Disjointlistbox class. # proc ::iwidgets::qw_disjointlistbox {pathName args} { uplevel ::iwidgets::qw_Disjointlistbox $pathName $args } # ------------------------------------------------------------------ # # Method: Constructor # # Purpose: # itcl::body ::iwidgets::qw_Disjointlistbox::constructor {args} { # # Create the left-most Listbox # itk_component add lhs { iwidgets::Scrolledlistbox $itk_interior.lhs \ -selectioncommand [::itcl::code $this listboxClick lhs rhs] \ -dblclickcommand [::itcl::code $this listboxDblClick lhs rhs] } { usual keep -selectmode -vscrollmode -hscrollmode rename -labeltext -lhslabeltext lhsLabelText LabelText } # # Create the right-most Listbox # itk_component add rhs { iwidgets::Scrolledlistbox $itk_interior.rhs \ -selectioncommand [::itcl::code $this listboxClick rhs lhs] \ -dblclickcommand [::itcl::code $this listboxDblClick rhs lhs] } { usual keep -selectmode -vscrollmode -hscrollmode rename -labeltext -rhslabeltext rhsLabelText LabelText } #QWFIX_1 /* { # # Create the left-most item count Label # itk_component add lhsCount { label $itk_interior.lhscount } { usual rename -font -labelfont labelFont Font } # # Create the right-most item count Label # itk_component add rhsCount { label $itk_interior.rhscount } { usual rename -font -labelfont labelFont Font } */} set sourceListbox $itk_component(lhs) set destinationListbox $itk_component(rhs) #QWFIX_1 /* { # # Bind the "showCount" method to the Map event of one of the labels # to keep the diplayed item count current. # bind $itk_component(lhsCount) [::itcl::code $this showCount] */} grid $itk_component(lhs) -row 0 -column 0 -sticky nsew grid $itk_component(rhs) -row 0 -column 2 -sticky nsew #QWFIX_3 # # Create the move buttons # itk_component add move_box { frame $itk_interior.move_box } itk_component add up_button { ::ArrowButton $itk_component(move_box).up_button -dir top -command [::itcl::code $this move_up] -height 20 -width 20 #button $itk_component(move_box).up_button -text "^" -command [::itcl::code $this move_up] } {} itk_component add down_button { ArrowButton $itk_component(move_box).down_button -dir bottom -command [::itcl::code $this move_down] -height 20 -width 20 #button $itk_component(move_box).down_button -text "v" -command [::itcl::code $this move_down] } {} grid configure $itk_component(move_box) -in $itk_interior -row 0 -column 3 -columnspan 1 -sticky nsew grid configure $itk_component(up_button) -in $itk_component(move_box) -row 0 -column 0 -sticky ew grid configure $itk_component(down_button) -in $itk_component(move_box) -row 1 -column 0 -sticky ew grid rowconfigure $itk_interior 0 -weight 1 grid columnconfigure $itk_interior 0 -weight 1 grid columnconfigure $itk_interior 1 -weight 1 grid columnconfigure $itk_interior 2 -weight 1 eval itk_initialize $args } # ------------------------------------------------------------------ # Method: listboxClick # # Purpose: Evaluate a single click make in the specified Listbox. # itcl::body ::iwidgets::qw_Disjointlistbox::listboxClick {clickSide otherSide} { set button "button" $itk_component($clickSide$button) configure -state active $itk_component($otherSide$button) configure -state disabled set sourceListbox $clickSide set destinationListbox $otherSide } # ------------------------------------------------------------------ # Method: listboxDblClick # # Purpose: Evaluate a double click in the specified Listbox. # itcl::body ::iwidgets::qw_Disjointlistbox::listboxDblClick {clickSide otherSide} { listboxClick $clickSide $otherSide transfer } # ------------------------------------------------------------------ # Method: transfer # # Purpose: Transfer source Listbox items to destination Listbox # itcl::body ::iwidgets::qw_Disjointlistbox::transfer {} { if {[$sourceListbox selecteditemcount] == 0} { return } set selectedindices [lsort -integer -decreasing [$sourceListbox curselection]] #QWFIX_2 # set selecteditems [$sourceListbox getcurselection] set selecteditems ""; foreach index $selectedindices { ::lappend selecteditems [$sourceListbox get $index] } foreach index $selectedindices { $sourceListbox delete $index } foreach item $selecteditems { $destinationListbox insert end $item } if {![string equal $itk_option(-${destinationListbox}sortoption) "none"]} { $destinationListbox sort $itk_option(-${destinationListbox}sortoption) } #QWFIX_1 #// showCount } # ------------------------------------------------------------------ # Method: getlhs # # Purpose: Retrieve the items of the left Listbox widget # itcl::body ::iwidgets::qw_Disjointlistbox::getlhs {{first 0} {last end}} { return [lhs get $first $last] } # ------------------------------------------------------------------ # Method: getrhs # # Purpose: Retrieve the items of the right Listbox widget # itcl::body ::iwidgets::qw_Disjointlistbox::getrhs {{first 0} {last end}} { return [rhs get $first $last] } # ------------------------------------------------------------------ # Method: insertrhs # # Purpose: Insert items into the right Listbox widget # itcl::body ::iwidgets::qw_Disjointlistbox::insertrhs {items} { remove $itk_component(lhs) $items insert rhs $items } # ------------------------------------------------------------------ # Method: insertlhs # # Purpose: Insert items into the left Listbox widget # itcl::body ::iwidgets::qw_Disjointlistbox::insertlhs {items} { remove $itk_component(rhs) $items insert lhs $items } # ------------------------------------------------------------------ # Method: clear # # Purpose: Remove the items from the Listbox widgets and set the item count # Labels text to 0 # itcl::body ::iwidgets::qw_Disjointlistbox::clear {} { lhs clear rhs clear #QWFIX_1 #// showCount } # ------------------------------------------------------------------ # Method: insert # # Purpose: Insert the input items into the input Listbox widget while # maintaining the disjoint property between them. # itcl::body ::iwidgets::qw_Disjointlistbox::insert {theListbox items} { set curritems [$theListbox get 0 end] foreach item $items { # # if the item is not already present in the Listbox then insert it # if {[lsearch -exact $curritems $item] == -1} { $theListbox insert end $item } } if {![string equal $itk_option(-${theListbox}sortoption) "none"]} { $theListbox sort $itk_option(-${theListbox}sortoption) } #QWFIX_1 #// showCount } # ------------------------------------------------------------------ # Method: remove # # Purpose: Remove the input items from the input Listbox widget while # maintaining the disjoint property between them. # itcl::body ::iwidgets::qw_Disjointlistbox::remove {theListbox items} { set indexes {} set curritems [$theListbox get 0 end] foreach item $items { # # if the item is in the listbox then add its index to the index list # if {[set index [lsearch -exact $curritems $item]] != -1} { lappend indexes $index } } foreach index [lsort -integer -decreasing $indexes] { $theListbox delete $index } #QWFIX_1 #// showCount } /* { # ------------------------------------------------------------------ # Method: showCount # # Purpose: Set the text of the item count Labels. # itcl::body ::iwidgets::qw_Disjointlistbox::showCount {} { $itk_component(lhsCount) config -text "item count: [lhs size]" $itk_component(rhsCount) config -text "item count: [rhs size]" } */} # ------------------------------------------------------------------ # METHOD: setlhs # # Set the items of the left-most Listbox with the input list # option. Remove all (if any) items from the right-most Listbox # which exist in the input list option to maintain the disjoint # property between the two # itcl::body ::iwidgets::qw_Disjointlistbox::setlhs {items} { lhs clear insertlhs $items } # ------------------------------------------------------------------ # METHOD: setrhs # # Set the items of the right-most Listbox with the input list # option. Remove all (if any) items from the left-most Listbox # which exist in the input list option to maintain the disjoint # property between the two # itcl::body ::iwidgets::qw_Disjointlistbox::setrhs {items} { rhs clear insertrhs $items } # ------------------------------------------------------------------ # Method: lhs # # Purpose: Evaluates the specified arguments against the lhs Listbox # itcl::body ::iwidgets::qw_Disjointlistbox::lhs {args} { return [eval $itk_component(lhs) $args] } # ------------------------------------------------------------------ # Method: rhs # # Purpose: Evaluates the specified arguments against the rhs Listbox # itcl::body ::iwidgets::qw_Disjointlistbox::rhs {args} { return [eval $itk_component(rhs) $args] } #QWFIX_3 # ------------------------------------------------------------------ # Method: move_up # # Purpose: Move selected item in right list up one # itcl::body ::iwidgets::qw_Disjointlistbox::move_up {args} { ::if {[rhs selecteditemcount] == 0} {::return;} ::set selectedindex [rhs curselection]; ::if {$selectedindex==0} {::return;} ::set values [rhs get 0 end]; ::set value [::lindex $values $selectedindex]; ::set values [::lreplace $values $selectedindex $selectedindex]; ::incr selectedindex -1; ::set values [::linsert $values $selectedindex $value]; setrhs $values; rhs selection set $selectedindex; } #QWFIX_3 # ------------------------------------------------------------------ # Method: move_down # # Purpose: Move selected item in right list up one # itcl::body ::iwidgets::qw_Disjointlistbox::move_down {args} { ::if {[rhs selecteditemcount] == 0} {::return;} ::set selectedindex [rhs curselection]; ::set Last [::expr [rhs size]-1]; ::if {$selectedindex==$Last} {::return;} ::set values [rhs get 0 end]; ::set value [::lindex $values $selectedindex]; ::set values [::lreplace $values $selectedindex $selectedindex]; ::incr selectedindex 1; ::set values [::linsert $values $selectedindex $value]; setrhs $values; rhs selection set $selectedindex; } # ------------------------------------------------------------------ # OPTION: buttonplacement # # Configure the placement of the buttons to be either between or below # the two list boxes. # ::if {$::rwb1_debug} {::puts "rwb1_debug,qw.qw_tcl,global,1000.14";} itcl::configbody ::iwidgets::qw_Disjointlistbox::buttonplacement { if {$itk_option(-buttonplacement) != ""} { if { [lsearch [component] lhsbutton] != -1 } { eval destroy $itk_component(rhsbutton) $itk_component(lhsbutton) } if { [lsearch [component] bbox] != -1 } { destroy $itk_component(bbox) } set where $itk_option(-buttonplacement) ::switch -- $where { center { # # Create the button box frame # itk_component add bbox { frame $itk_interior.bbox } itk_component add lhsbutton { button $itk_component(bbox).lhsbutton -command [::itcl::code \ $this transfer] } { usual rename -text -lhsbuttonlabel lhsButtonLabel LabelText rename -font -labelfont labelFont Font } itk_component add rhsbutton { button $itk_component(bbox).rhsbutton -command [::itcl::code \ $this transfer] } { usual rename -text -rhsbuttonlabel rhsButtonLabel LabelText rename -font -labelfont labelFont Font } #QWFIX_1 /* { grid configure $itk_component(lhsCount) -row 1 -column 0 \ -sticky ew grid configure $itk_component(rhsCount) -row 1 -column 2 \ -sticky ew */} grid configure $itk_component(bbox) \ -in $itk_interior -row 0 -column 1 -columnspan 1 \ -sticky nsew grid configure $itk_component(rhsbutton) \ -in $itk_component(bbox) -row 0 -column 0 -sticky ew grid configure $itk_component(lhsbutton) \ -in $itk_component(bbox) -row 1 -column 0 -sticky ew } bottom { itk_component add lhsbutton { button $itk_interior.lhsbutton -command [::itcl::code $this \ transfer] } { usual rename -text -lhsbuttonlabel lhsButtonLabel LabelText rename -font -labelfont labelFont Font } itk_component add rhsbutton { button $itk_interior.rhsbutton -command [::itcl::code $this \ transfer] } { usual rename -text -rhsbuttonlabel rhsButtonLabel LabelText rename -font -labelfont labelFont Font } #QWFIX_1 #// grid $itk_component(lhsCount) -row 2 -column 0 -sticky ew #// grid $itk_component(rhsCount) -row 2 -column 2 -sticky ew grid $itk_component(lhsbutton) -row 1 -column 0 -sticky ew grid $itk_component(rhsbutton) -row 1 -column 2 -sticky ew /* { #QWFIX_3 if { [lsearch [component] move_up_button] != -1 } { eval destroy $itk_component(move_up_button) $itk_component(move_up_button) } if { [lsearch [component] move_down_button] != -1 } { eval destroy $itk_component(move_down_button) $itk_component(move_down_button) } if { [lsearch [component] moveframe] != -1 } { eval destroy $itk_component(moveframe) $itk_component(moveframe) } itk_component add moveframe { frame $itk_interior.moveframe } { usual } itk_component add move_up_button { ArrowButton $itk_component(moveframe).move_up_button -dir top -command [::itcl::code $this move_up] } { usual } itk_component add move_down_button { ArrowButton $itk_component(moveframe).move_down_button -dir bottom -command [::itcl::code $this move_down] } { usual } grid configure $itk_component(movebox) -in $itk_interior -row 0 -column 2 -columnspan 1 -sticky nsew grid configure $itk_component(move_up_button) -in $itk_component(movebox) -row 0 -column 0 -sticky ew grid configure $itk_component(move_down_button) -in $itk_component(movebox) -row 1 -column 0 -sticky ew */} } default { error "bad buttonplacement option\"$where\": should be center\ or bottom" } } } } # ------------------------------------------------------------------ # OPTION: lhssortoption # # Configure the sort option to use for the left side # itcl::configbody ::iwidgets::qw_Disjointlistbox::lhssortoption { if {![string equal $itk_option(-lhssortoption) "none"]} { $itk_component(lhs) sort $itk_option(-lhssortoption) } } # ------------------------------------------------------------------ # OPTION: rhssortoption # # Configure the sort option to use for the right side # itcl::configbody ::iwidgets::qw_Disjointlistbox::rhssortoption { if {![string equal $itk_option(-rhssortoption) "none"]} { $itk_component(rhs) sort $itk_option(-rhssortoption) } } # ------------------------------------------------------------ # ::qw::dialog::disjointlist # ------------------------------------------------------------ ::sargs::var::+= ::qw::options { .window { .dialog { .disjointlist { .title "Select" .class "Disjoint List" .buttonplacement "bottom" .textfont "" .labelfont "" .left { .list {} .title "Choices" .buttontext "Add >" .sort "increasing" } .right { .list {} .title "Selected" .buttontext "Add >" .sort "none" } .sound "" .bbox "" .default "" /button { .text "Text not specified." .command {} /ok { .text OK .command {} } /cancel { .text Cancel .command {::set ::qw::dialog::result ""} } /help { .text Help .command {} } } } } } }; ::proc ::qw::dialog::disjointlist {args} { ::qw::s_args_marshal; ::qw::try { #dialog ::set Toplevel ""; ::set Args [::sargs::get $::qw::options .window]; ::sargs::var::+= Args [::sargs::get $::qw::options .window.dialog.disjointlist]; ::sargs::var::+= Args $s_args; ::set Toplevel [::qw::dialog::create $Args]; ::set Info ${Toplevel}.info; ::set ListBox [::eval ::QW::WIDGET::DISJOINTLIST $Info.list $s_args]; ::pack $Info.list -expand 1 -fill both; ::sargs::var::set Args /button/ok.command [::format {::set ::qw::dialog::result [%s selected];} $ListBox]; ::set Help [::sargs::get $Args .help]; ::sargs::var::set Args /button/help.command [::list ::qw::dialog::list_help $Help]; ::bind $Toplevel [::list ::qw::dialog::list_help $Help]; ::set Controls ${Toplevel}.controls; ::foreach {Column Button} {0 ok 1 cancel 2 help} { ::button $Controls.${Button} \ -text [::sargs::get_poly $Args /button/${Button}.text] \ -command [::sargs::get_poly $Args /button/${Button}.command] \ -font [::sargs::get_poly $Args /button/${Button}.font] \ -borderwidth [::sargs::get_poly $Args /button.border.width] \ ; ::grid $Controls.${Button} -row 0 -column $Column -sticky nesw \ -padx [::sargs::get_poly $Args /button/${Button}.pad.external.x] \ -pady [::sargs::get_poly $Args /button/${Button}.pad.external.y] \ ; ::grid columnconfigure $Controls $Column -weight 1; } #nv2.32.0 () #//::puts "pgq,debug::qw::dialog::disjointlist Args==(\n[::sargs::format .structure $Args]\n)"; #//::puts "pgq,debug::qw::dialog::disjointlist s_args==(\n[::sargs::format .structure $s_args]\n)"; ::wm geometry $Toplevel [::sargs::get $s_args .geometry]; ::raise $Toplevel; ::focus $Controls.ok; ::wm protocol $Toplevel WM_DELETE_WINDOW [::subst -nocommands {::if {[::winfo exists $Controls.cancel]} {$Controls.cancel invoke}}]; ::bind $Toplevel "$Controls.cancel invoke"; #::bind $Controls.ok "$Controls.ok invoke"; #::bind $Controls.cancel "$Controls.cancel invoke"; #::bind $Controls.help $HelpCommand; #::bind $Toplevel $HelpCommand; #::bind $Toplevel "$Controls.ok invoke"; ::qw::dialog::wait .toplevel $Toplevel .variable ::qw::dialog::result; ::destroy $Toplevel ::return $::qw::dialog::result; } catch Exception { ::if {$Toplevel ne ""&&[::winfo exists $Toplevel]} { ::qw::try { ::destroy $Toplevel; } catch Dummy {} } ::qw::throw [::qw::exception::nest .sub $Exception .super "Could not create a disjointlist dialog with arguments \"$s_args\"."]; } } # ------------------------------------------------------------ # ::QW::WIDGET::DISJOINTLIST class # ------------------------------------------------------------ ::if {$::rwb1_debug} {::puts "rwb1_debug,qw.qw_tcl,global,1000.15";} ::itcl::class ::QW::WIDGET::DISJOINTLIST { inherit ::itk::Widget #// # NOTICE #// #// There is a lot of 'green' (commented) code here. #// Some is not needed at all, some we might come back and implement. #// protected variable _selectionbox ""; # protected variable _scrolledlistbox ""; # protected variable _listbox ""; # protected variable _entryfield ""; # protected variable _current ""; protected variable _options ""; # method select {Date} { # ::qw::bug 314120030918120155; # return $this; # } # method selected {} {::return [$_scrolledlistbox getcurselection];} method selected {} {::return [$_selectionbox getrhs];} # method select_index {Index} {::return [select $_table($Index-date)];} method option_get {Path} {::return [::sargs::get_poly $_options $Path];} method constructor {args} { ::set _options $::qw::widget::options; ::sargs::var::+= _options [::subst { .default {} }]; ::sargs::var::+= _options $args; ::set _selectionbox [::iwidgets::qw_Disjointlistbox $itk_interior.selectionbox]; #::set _scrolledlistbox [$_selectionbox component items]; #::set _listbox [$_scrolledlistbox component listbox]; #::set _entryfield [$_selectionbox component selection]; # # # Cannot set this command until we have the scrolled list box widget. ## ::set Args [::sargs::set $Args /button/select.command [::format {::set ::qw::dialog::result [%s getcurselection]} $ScrolledListBox]]; ::pack $_selectionbox -expand 1 -fill both; ::foreach {QW_Option Widget_Option} { background background buttonplacement buttonplacement textfont textfont labelfont labelfont left.sort lhssortoption left.buttontext lhsbuttonlabel left.title lhslabeltext right.sort rhssortoption right.buttontext rhsbuttonlabel right.title rhslabeltext } { $_selectionbox configure -$Widget_Option [option_get .$QW_Option]; } ::set Items ""; ::foreach Item [option_get .left.list] { ::if {[::lsearch -exact -dictionary $Items $Item]<0} { ::lappend Items $Item; } } $_selectionbox setlhs $Items; ::set Items ""; ::foreach Item [option_get .right.list] { ::if {[::lsearch -exact -dictionary $Items $Item]<0} { ::lappend Items $Item; } } $_selectionbox setrhs $Items; /* { $_scrolledlistbox configure \ -vscrollmode [option_get /scroll/vertical.mode] \ -hscrollmode [option_get /scroll/horizontal.mode] \ -selectbackground [option_get /selection.background] \ -selectforeground [option_get /selection.foreground] \ ; $_selectionbox configure \ -selectionon 0 -itemslabel "" \ ; ::set Items ""; ::foreach Item [option_get .list] { ::if {[::lsearch -exact -dictionary $Items $Item]<0} { ::lappend Items $Item; } } ::set Height 10; ::if {[::llength $Items]<$Height} {::set Height [::llength $Items];} ::set Width 0; ::foreach Item $Items { ::if {[::string length $Item]>$Width} { ::set Width [::string length $Item]; } $_selectionbox insert items end $Item; } $_scrolledlistbox configure -visibleitems ${Width}x${Height}; $_listbox configure -font [option_get .font]; ::if {[option_get .default] ne ""} { ::set Index [::lsearch -exact -dictionary $Items [option_get .default]]; ::if {$Index<0} {::set Index 0;} $_entryfield insert 0 [::lindex $Items $Index]; $_scrolledlistbox selection set $Index; $_listbox activate $Index; $_listbox see $Index; } else { ::if {[::llength $Items]>0} { $_scrolledlistbox selection set 0; } } # $_selectionbox configure -dblclickcommand "$Controls.select invoke"; ::set Toplevel [::lindex [bindtags $itk_component(hull)] end-1]; ::foreach {Sequence Method} { cursor_up cursor_down cursor_left cursor_right page_down page_up cursor_up cursor_down cursor_left cursor_right page_down page_up end_page_down end_page_up } { ::bind $Toplevel $Sequence [::itcl::code $this $Method]; } */} ::eval itk_initialize; } method cursor_up {} { ::set Index [$_listbox index active]; $_listbox selection clear $Index; tk::ListboxUpDown $_listbox -1 ::set Index [$_listbox index active]; $_listbox selection set $Index; $_listbox see $Index; } method cursor_down {} { ::set Index [$_listbox index active]; $_listbox selection clear $Index; tk::ListboxUpDown $_listbox 1 ::set Index [$_listbox index active]; $_listbox selection set $Index; $_listbox see $Index; } method cursor_left {} {::return;} method cursor_right {} {::return;} method page_up {} { ::set Index [$_listbox index active]; $_listbox selection clear $Index; $_listbox yview scroll -1 pages $_listbox activate @0,0 ::set Index [$_listbox index active]; $_listbox selection set $Index; $_listbox see $Index; } method page_down {} { # This does not work yet. At least not on small windows. ::set Index [$_listbox index active]; $_listbox selection clear $Index; $_listbox yview scroll 1 pages $_listbox activate @0,0 ::set Index [$_listbox index active]; $_listbox selection set $Index; $_listbox see $Index; } method end_page_up {} { ::return; ::set Index [$_listbox index active]; $_listbox selection clear $Index; $_listbox yview scroll -1 pages $_listbox activate @0,0 ::set Index [$_listbox index active]; $_listbox selection set $Index; $_listbox see $Index; } method end_page_down {} { ::return; # This does not work yet. At least not on small windows. ::set Index [$_listbox index active]; $_listbox selection clear $Index; $_listbox yview scroll 1 pages $_listbox activate @0,0 ::set Index [$_listbox index active]; $_listbox selection set $Index; $_listbox see $Index; } } itcl::body iwidgets::Timeentry::_getDefaultIcon {} { #// # NOTICE #// #// 20050504 RTH #// #// Using the IWidget timeentry alway's caused a "Fatal error in Wish, #// unable to free bitmap. pallette still in use" error. #// Digging on the net I saw someone suggest that it may be a bug in #// the Img package. "Stock" Wish does not support pixmap images, but #// in our environment they are (I guess the Img package is included #// in TclKit/KitTen.) This method from the source for the timeentry #// IWidget will use a pixmap image if available. I tried overriding/ #// redefining the method to use bitmaps instead, and the fatal #// error went away. #// #// if {[lsearch [image types] pixmap] != -1} { #// set _defaultIcon [image create pixmap -data { #// /* XPM */ #// static char *watch1a[] = { #// /* width height num_colors chars_per_pixel */ #// " 20 20 8 1", #// /* colors */ #// ". c #//000000", #// "# c #000099", #// "a c #009999", #// "b c #999999", #// "c c #cccccc", #// "d c #ffff00", #// "e c #d9d9d9", #// "f c #ffffff", #// /* pixels */ #// "eeeeebbbcccccbbbeeee", #// "eeeee...#####..beeee", #// "eeeee#aacccccaabeeee", #// "eeee#accccccccc##eee", #// "eee#ccc#cc#ccdcff#ee", #// "ee#accccccccccfcca#e", #// "eeaccccccc.cccfcccae", #// "eeac#cccfc.cccc##cae", #// "e#cccccffc.cccccccc#", #// "e#ccccfffc.cccccccc#", #// "e#cc#ffcc......c#cc#", #// "e#ccfffccc.cccccccc#", #// "e#cffccfcc.cccccccc#", #// "eeafdccfcccccccd#cae", #// "eeafcffcccccccccccae", #// "eee#fcc#cccccdccc#ee", #// "eee#fcc#cc#cc#ccc#ee", #// "eeee#accccccccc##eee", #// "eeeee#aacccccaabeeee", #// "eeeee...#####..beeee" #// }; #// }] #// } else { #// set _defaultIcon [image create bitmap -data { #// #define watch1a_width 20 #// #define watch1a_height 20 #// static char watch1a_bits[] = { #// 0x40,0x40,0xf0,0xe0,0x7f,0xf0,0xe0,0xe0,0xf0,0x30, #// 0x80,0xf1,0x88,0x04,0xf2,0x0c,0x00,0xf6,0x04,0x04, #// 0xf4,0x94,0x84,0xf5,0x02,0x06,0xf8,0x02,0x0c,0xf8, #// 0x12,0x7e,0xf9,0x02,0x04,0xf8,0x02,0x24,0xf8,0x04, #// 0x00,0xf5,0x04,0x00,0xf4,0x88,0x02,0xf2,0x88,0x64, #// 0xf2,0x30,0x80,0xf1,0xe0,0x60,0xf0,0xe0,0xff,0xf0}; #// }] #// } #// #//::puts "20050504 - forcing bitmap image"; set _defaultIcon [image create bitmap -data { #define watch1a_width 20 #define watch1a_height 20 static char watch1a_bits[] = { 0x40,0x40,0xf0,0xe0,0x7f,0xf0,0xe0,0xe0,0xf0,0x30, 0x80,0xf1,0x88,0x04,0xf2,0x0c,0x00,0xf6,0x04,0x04, 0xf4,0x94,0x84,0xf5,0x02,0x06,0xf8,0x02,0x0c,0xf8, 0x12,0x7e,0xf9,0x02,0x04,0xf8,0x02,0x24,0xf8,0x04, 0x00,0xf5,0x04,0x00,0xf4,0x88,0x02,0xf2,0x88,0x64, 0xf2,0x30,0x80,0xf1,0xe0,0x60,0xf0,0xe0,0xff,0xf0}; }] # # Since this image will only need to be created once, we redefine # this method to just return the image name for subsequent calls. # itcl::body ::iwidgets::Timeentry::_getDefaultIcon {} { ::return $_defaultIcon } ::return $_defaultIcon }