source: tol/tolbase/lib/byswidget/beditselector/beditselector.tcl

devel
Last change on this file was 6d7779d, checked in by Jorge Pérez <josp.jorge@…>, 18 years ago

initial import

git-svn-id: ​https://www.tol-project.org/svn/tolp/trunk@1 be4846ae-f051-483a-831f-b64e7d08527f

  • Property mode set to 100644
File size: 21.1 KB
Line 
1#/////////////////////////////////////////////////////////////////////////////
2# FILE    : beditselector.tcl
3# PURPOSE : Bayes Edit Selector. Creates a widget that has an entry widget
4#           and a button that calls a multiple selector (a widget that allows
5#           selecting multiple items from a list, see bmultiselect.tcl).
6#/////////////////////////////////////////////////////////////////////////////
7
8package require byscommon
9package require bmultiselect
10package require bfieldsdialog
11
12
13#/////////////////////////////////////////////////////////////////////////////
14::snit::widget beditselector {
15#
16# PURPOSE: Beditselector widget class definition
17#
18#/////////////////////////////////////////////////////////////////////////////
19#/////////////////////////////////////////////////////////////////////////////
20# options:
21#  -list  : initial list values
22#  -sel : selected values list
23#  -label : label of the widget
24#  -labelsel : label for the selected list on the multiselect child
25#  -labelunsel : label for the unselected list on the multiselect child
26#  -font : font for the blistboxplus inthe bmultiselect component
27#  -readonly : if not true an icon appears to allow introduce items manually
28#  -cols : columns associated with the item fields
29#  -selcols : columns which are displayed in the selection
30#  -entcols : columns which are displayed in the entry
31#  -hlpcols : columns which are displayed in the helptext
32#  -unique : if true the multiple selector associated can only select one item
33#  -width : width of the entry component.
34#           If the size is zero, the component does not visualize
35#  -lwidth : width of the label component
36#  -msgeometry : geometry for the multiselect dialog component
37#  -procedure : procedure to execute before showing the list of available \
38#     values. It must return a the list of posible values.
39#  -editstate: normal, active -> enabled editselector,
40#              disabled -> disabled editselector
41#  -postcommand: Procedure to execute after select any element
42#  -iconopen: Icon to visualize in the button to open selection
43#  -iconwrite: Icon to visualize in the button to write item
44#
45# variables:
46#   label: label component
47#   entry: entry component
48#   menu: the contextual menu
49#   dialogWRentry: entry variable of the insert element dialog
50#   buttonMS: button that launches the Multiple Selector
51#   buttonWR: button that launches the insert element dialog
52#/////////////////////////////////////////////////////////////////////////////
53
54  option -list {}
55  option -sel {}
56  option -label ""
57  option -labelsel "Selected"
58  option -labelunsel "Not Selected"
59  option -font {arial 10}
60  option -readonly "true"
61  option -cols {}
62  option -selcols {}
63  option -entcols {}
64  option -hlpcols {}
65  option -unique false
66  option -width  20
67  option -lwidth 0
68  option -msgeometry ""
69  option -procedure ""
70  option -editstate normal
71  option -postcommand ""
72  option -iconopen  puntos
73  option -iconwrite lapiz
74 
75  variable label
76  variable entry
77  variable menu
78  variable dialogWRentry
79  variable buttonMS
80  variable buttonWR
81
82  variable created 0
83
84  delegate option * to entry
85
86  #///////////////////////////////////////////////////////////////////////////
87  constructor { args } {
88  #
89  # PURPOSE: beditselector constructor
90  #
91  # PARAMETERS:
92  #   args ->
93  #
94  #///////////////////////////////////////////////////////////////////////////
95    # Apply all options passed at creation time.
96    $self configurelist $args
97    # Create widget
98    $self _CreateWidget
99    $self configure -labelsel [mc $options(-labelsel)]
100    $self configure -labelunsel [mc $options(-labelunsel)]
101    if { "" eq $options(-selcols) } {
102      set options(-selcols) $options(-cols)
103    }
104    if { "" eq $options(-entcols) } {
105      set options(-entcols) $options(-cols)
106    }
107    if { "" eq $options(-hlpcols) } {
108      set options(-hlpcols) $options(-cols)
109    }
110    if { "" eq $options(-msgeometry) } {
111      set swidth [expr [winfo screenwidth .] / 3]
112      set sheight [expr [winfo screenwidth .] / 3]
113      set options(-msgeometry) "${swidth}x${sheight}+${swidth}+[expr ${sheight} / 2]"
114    }
115   
116    $self configure -postcommand  [from args -postcommand ""]
117  }
118 
119  #///////////////////////////////////////////////////////////////////////////
120  #
121  # PURPOSE: Metodos cget y configure
122  #
123  #///////////////////////////////////////////////////////////////////////////
124 
125  onconfigure -label { t } {
126    if { $created } {
127          $label configure -text $t
128      if { [llength $t] } {
129        grid $self.l
130      } else {
131        grid remove $self.l
132      }
133    }
134    set options(-label) $t
135  }
136 
137  oncget -label {
138    if { $created } {
139      return [$label cget -text]labe}
140  }
141
142  onconfigure -width { w } {
143    if { $created } {
144      if {[expr $w == 0]} {
145        grid remove $entry
146      }
147      $entry configure -width $w
148    }
149    set options(-width) $w
150  }
151 
152  oncget -width {
153    if { $created } {
154      return [$entry cget -width]
155    }
156  }
157 
158  onconfigure -editstate { stt } {
159    if { $created } {
160      $buttonMS configure -state $stt
161      $entry configure -state $stt
162      if {([info exists buttonWR]) && ([winfo exists $buttonWR])} {
163        $buttonWR configure -state $stt
164      }
165      if {([info exists label]) && ([winfo exists $label])} {
166        $label configure -state $stt
167      }
168    }
169    set options(-editstate) $stt
170  } 
171 
172  oncget -editstate {
173    if { $created } {
174      return [$buttonMS cget -state]
175    }
176  }
177
178  onconfigure -lwidth { w } {
179    if { $created } {
180      $label configure -width $w
181    }
182    set options(-lwidth) $w
183  }
184 
185  oncget -lwidth {
186    if { $created } {
187      return [$label cget -width]
188    }
189  }
190 
191  onconfigure -sel { list } {
192    set options(-sel) $list
193    set ent [$self selection get $options(-entcols)]
194    set hlp [$self selection get $options(-hlpcols)]
195    if { $created } {
196      $entry configure -text [$self _ListToStr $ent] \
197        -helptext [::ListToStr $hlp "\n" { } { }]
198    }
199  }
200
201  oncget -font {
202    if { [winfo exists $self.d] } {
203      set fr [$self.d getframe]
204      return [$fr.bms cget -font]
205    }
206  }
207
208  onconfigure -msgeometry { geom } {
209    set options(-msgeometry) $geom
210    if { [winfo exists $self.d] } {
211      $self.d configure -geometry $geom
212    }
213  }
214 
215  onconfigure -postcommand { lst } {
216    set options(-postcommand) $lst
217  }
218
219  oncget -msgeometry {
220    if { [winfo exists $self.d] } {
221      $self.d cget -geometry
222    }
223  }
224
225#/////////////////////////////////////////////////////////////////////////////
226# PRIVATE METHODS
227#/////////////////////////////////////////////////////////////////////////////
228
229  #///////////////////////////////////////////////////////////////////////////
230  method _CreateWidget { args } {
231  #
232  # PURPOSE: Creates an edit selector. It creates the widget composed by
233  #          a label, an entry and a button that shows a bmultiselect widget.
234  #          Also creates a procedure asociated.
235  #
236  # PARAMETERS:
237  #   args ->
238  #
239  #///////////////////////////////////////////////////////////////////////////
240   
241    set options(-labelsel) [mc $options(-labelsel)]
242    set options(-labelunsel) [mc $options(-labelunsel)]
243    set dialogWRentry ""
244    install label using label $self.l -text $options(-label) -anchor w \
245      -width $options(-lwidth)
246    install entry using Entry $self.e -state normal -editable false \
247      -width $options(-width)
248    install buttonMS using Button $self.b1 \
249      -image [Bitmap::get $options(-iconopen)] \
250      -relief link -helptext [mc "Multiple Selector"] \
251      -command [list  $self _OpenMS]
252    if {! $options(-readonly) } {
253      install buttonWR using Button $self.b2 \
254        -image [Bitmap::get $options(-iconwrite)] \
255        -relief link -helptext [mc "Introduce item"] \
256        -command [list  $self _OpenWR]
257    }
258 
259    $self _CreateMenu
260    set created 1
261
262    $self configure -width $options(-width) -editstate $options(-editstate)
263       
264    if {[expr $options(-width) == 0]} {
265      grid $self.l $self.b1 -sticky ew -padx 2     
266    } else {
267      grid $self.l $self.e $self.b1 -sticky ew -padx 2
268    }
269    if { ! [llength [$label cget -text]] } { grid remove $self.l }
270    if { ! $options(-readonly) } {
271      grid $self.b2 -row 0 -column 4 -sticky ew -padx 2
272    }
273    grid columnconfigure $self 1 -weight 1
274  }
275
276
277  #///////////////////////////////////////////////////////////////////////////
278  method _CreateMenu {args} {
279  #
280  # PURPOSE: Append menu to listbox.
281  #
282  #///////////////////////////////////////////////////////////////////////////
283    install menu using menu $self.m -tearoff 0
284
285    # read option
286    $menu add command -label [mc "Select from a List"] \
287                      -command "$self _OpenMS"
288    $menu add command -label [mc "Select all"] \
289                      -command "$self _SelectAll; $self _PostCommand" \
290                      -accelerator CTRL+E
291    $menu add command -label [mc "Unselect all"] \
292                      -command "$self selection clear; $self _PostCommand"
293    # read/write option
294    if {![$self cget -readonly]} {
295      $menu add separator
296      $menu add command -label [mc "Insert"] \
297                        -command "$self _OpenWR; $self _PostCommand" \
298                        -accelerator CTRL+I
299    }
300    # read option
301    $menu add command -label [mc "Copy"] \
302                      -command "$self _CopySelected" -accelerator CTRL+C
303
304    set comps "$label $entry $buttonMS"
305    if { ! $options(-readonly) } { lappend comps $buttonWR }
306    foreach comp $comps {
307      bind $comp <Control-e> "$self _SelectAll; $self _PostCommand"
308      bind $comp <Control-i> "$self _OpenWR; $self _PostCommand"
309      bind $comp <Control-c> "$self _CopySelected"
310      bind $comp <Button-1> +[list focus -force %W]
311      bind $comp <Button-3> "tk_popup $menu %X %Y"
312    }
313
314    bind $self <Button-1> +[list focus -force %W]
315    bind $self <Button-3> "tk_popup $menu %X %Y"
316  }
317
318  #///////////////////////////////////////////////////////////////////////////
319  method _SelectAll {} {
320  #
321  # PURPOSE: Sets the selected list to all posible values
322  #
323  # RETURN: The list
324  #
325  #///////////////////////////////////////////////////////////////////////////
326    if {$options(-unique)} {
327      tk_messageBox -icon warning -message \
328        [mc "The option to select to all the elements of the list this disabled"]\
329        -title [mc "Attention"] -type ok
330    } else {
331      $self configure -sel [$self get]
332    }
333  }
334
335
336  #///////////////////////////////////////////////////////////////////////////
337  method _CopySelected {} {
338  #
339  # PURPOSE: Copy the selected items to the clipboard
340  #
341  # RETURN: The list
342  #
343  #///////////////////////////////////////////////////////////////////////////
344    clipboard clear
345    clipboard append $options(-sel)
346  }
347
348  #///////////////////////////////////////////////////////////////////////////
349  proc _AddWR { elem father } {
350  #
351  # PURPOSE: adds the item introduced in the dialog to the selected list
352  #
353  # PARAMETERS:
354  #  elem -> the element to insert from the add dialog
355  #  father -> The dialog's window pathname
356  #
357  #///////////////////////////////////////////////////////////////////////////
358    # unique ?
359    if {[$father cget -unique]} {
360      set list {}
361    } else {
362      set list [$father curselection]     
363    }
364    # add new value
365    eval lappend list $elem
366    eval $father selection set $list
367  }
368
369
370  #//////////////////////////////////////////////////////////////////////////
371  method _OpenWR {} {
372  #
373  # PURPOSE: Calls (and creates) a dialog for adding elements manually.
374  #
375  #///////////////////////////////////////////////////////////////////////////
376    destroy $self.dw
377    set dialog  [bfieldsdialog $self.dw -title $options(-label) -parent $self \
378      -fields $options(-cols) -procedure [myproc _AddWR] \
379      -buttons { add exit} -parent $self]
380
381    $dialog draw
382  }
383
384
385  #///////////////////////////////////////////////////////////////////////////
386  method _CloseMS { w { onlyexit 0 } } {
387  #
388  # PURPOSE: closes the dialog and returns the result
389  #
390  # PARAMETERS:
391  #  w -> The dialog's window pathname
392  #  onlyexit -> the dialogs end without doing nothing
393  #
394  #///////////////////////////////////////////////////////////////////////////   
395    if { $onlyexit } {
396      $self configure -msgeometry [wm geometry $self.d]
397      $w enddialog ""
398    } else {
399      set f [$w getframe]
400      set result [$f.bms get selected]
401      $self configure -sel $result
402      $self configure -msgeometry [wm geometry $self.d]
403      $w enddialog $result
404    }
405   
406    $self _PostCommand
407  }
408 
409  #////////////////////////////////////////////////////////////////////////// 
410  method _PostCommand { } {
411  #
412  # PURPOSE: Execute postcommand
413  #
414  #///////////////////////////////////////////////////////////////////////////
415    set cmd [$self cget -postcommand]
416    if {[string length $cmd]} {
417      eval $cmd
418    } 
419  }
420
421
422  #//////////////////////////////////////////////////////////////////////////
423  method _OpenMS {} {
424  #
425  # PURPOSE: Calls (and creates) a multiple selector widget with the selected
426  #          and unselected items.
427  #
428  #///////////////////////////////////////////////////////////////////////////
429
430    destroy $self.d
431    set dialog [Dialog $self.d -title $options(-label) \
432                -modal local -parent $self]
433   
434    set dialogframe [$dialog getframe]
435    wm protocol $dialog WM_DELETE_WINDOW [list $self _CloseMS $dialog]
436    bmultiselect $dialogframe.bms -cols $options(-cols) \
437          -hiddencols [lsub $options(-cols) $options(-selcols)] \
438          -unsel [lsub [$self get] $options(-sel)] -sel $options(-sel) \
439          -unique $options(-unique) -font $options(-font) \
440          -labelunsel $options(-labelunsel) -labelsel $options(-labelsel)
441 
442    set dialogframe_bbox \
443          [ButtonBox $dialogframe.bb -orient horizontal -spacing 10 -padx 0 -pady 0 \
444          -homogeneous false]
445    $dialogframe_bbox add -text [mc "Accept"] -relief link \
446          -helptext [mc "Accept selection"] \
447          -image [::Bitmap::get accept] -compound left -padx 5 -pady 1 \
448           -command [list $self _CloseMS $dialog]
449    $dialogframe_bbox add -text [mc "Cancel"] -relief link \
450          -helptext [mc "Cancel selection"]\
451          -image [::Bitmap::get cancelx] -compound left -padx 5 -pady 1 \
452            -command [list $self _CloseMS $dialog 1]     
453   
454    pack $dialogframe_bbox -fill x -expand false -side bottom
455    pack $dialogframe.bms -fill both -expand true
456   
457    if { $options(-msgeometry) ne "" } {
458      $dialog configure -geometry $options(-msgeometry)
459    }
460    $dialog draw
461  }
462
463
464  #///////////////////////////////////////////////////////////////////////////
465  method _ListToStr { list } {
466  #
467  # PURPOSE: Concatenates list element names into a string for the label of the
468  #          edit selector widget. If list has more than one element the string
469  #          is first element name plus '...'.
470  #
471  # RETURN: The string created.
472  #
473  #///////////////////////////////////////////////////////////////////////////
474
475    switch -exact -- [llength $list] {
476      0       {
477        set result {}
478      }
479      1       {
480        set result [lindex $list 0]
481      }
482      default {
483        set result [lindex $list 0]...
484      }
485    }
486    return $result
487  }
488 
489
490#/////////////////////////////////////////////////////////////////////////////
491# PUBLIC METHODS
492#/////////////////////////////////////////////////////////////////////////////
493
494  #///////////////////////////////////////////////////////////////////////////
495  method get { {cols ""} } {
496  #
497  # PURPOSE: Gets the given list or obtains it from a process
498  #
499  # PARAMETERS:
500  #   cols: specifies only which column to return data for
501  #
502  # RETURN: The list
503  #
504  #///////////////////////////////////////////////////////////////////////////
505    if { $options(-procedure) ne "" } {
506      set result [eval $options(-procedure) $self]
507    } else {
508      set result $options(-list)
509    }
510
511                                             
512    if { "" ne $cols } {
513      set colsresult {}
514      foreach elem $result {
515        set elemres {}
516        foreach col $cols {
517          lappend elemres [lindex $elem [lsearch $options(-cols) $col]]
518        }
519        lappend colsresult $elemres
520      }
521      set result $colsresult
522    }
523
524    return $result
525  }
526 
527  #///////////////////////////////////////////////////////////////////////////
528  method selectAll {} {
529  #
530  # PURPOSE: Public method to set the selected list to all posible values
531  #
532  # RETURN: The list
533  #
534  #///////////////////////////////////////////////////////////////////////////
535    $self _SelectAll
536  }
537 
538
539  #///////////////////////////////////////////////////////////////////////////
540  method selection { args } {
541  #
542  # PURPOSE: selection command, performs various operations with selected items
543  #    like get, set or clear the selected items
544  # 
545  # PARAMETERS:
546  #   arg0: <none>, set, get or clear
547  #   arg1: <none>, selected or unselected (for set and get switches)
548  #   arg2: <none>, cols (for get selected and get unselected switches)
549  #
550  # RETURN: returns in the case the selected or unselected items
551  #
552  #///////////////////////////////////////////////////////////////////////////
553    switch -exact [lindex $args 0] {
554      get {
555        if { [lindex $args 1] eq "unselected" } {
556          set result [lsub [$self get] $options(-sel)]
557          set cols [lindex $args 2]
558        } else {
559          set result $options(-sel)
560          if { [lindex $args 1] eq "selected" } {
561            set cols [lindex $args 2]
562          } else {
563            set cols [lindex $args 1]
564          }
565        }
566        if { "" ne $cols } {
567          set colsresult {}
568          foreach elem $result {
569            set elemres {}
570            foreach col $cols {
571              lappend elemres [lindex $elem [lsearch $options(-cols) $col]]
572            }
573            lappend colsresult $elemres
574          }
575          set result $colsresult
576        }
577        return $result
578      }
579      set {
580        if { [lindex $args 1] eq "unselected" } {
581          set values [lsub [$self get] [lrange $args 2 end]]
582          $self configure -sel $values
583        } else { if { [lindex $args 1] eq "selected" } {
584            $self configure -sel [lrange $args 2 end]
585          } else {
586            $self configure -sel [lrange $args 1 end]
587          }
588        }
589      }
590      clear {
591        $self configure -sel {}
592      }
593      default {
594        return $options(-sel)
595      }
596    }
597  }
598
599
600  #///////////////////////////////////////////////////////////////////////////
601  method curselection {  } {
602  #
603  # RETURN: returns the selected items.
604  #
605  #///////////////////////////////////////////////////////////////////////////
606    $self selection get
607  }
608 
609  #///////////////////////////////////////////////////////////////////////////
610  method getButtonAccept {  } {
611  #
612  # RETURN: returns accept Button Path.
613  #
614  #///////////////////////////////////////////////////////////////////////////
615    return $buttonMS
616  }
617}
618
619
620 
621# TEST CODE
622
623proc __TbesElProc { w } {
624  # this proc should load a list of values from any source
625  return {{4 5 6} {cuatro cinco seis} {four five six}}
626}
627
628
629#/////////////////////////////////////////////////////////////////////////////
630proc test_beditselector {} {
631#
632# PURPOSE: Test function of a beditselector
633#
634#/////////////////////////////////////////////////////////////////////////////
635  destroy .top
636  toplevel .top
637  variable uniq
638  variable multicol
639  variable withproc
640
641  TitleFrame .top.f1 -text "BEditSelector test"
642  set f1 [.top.f1 getframe]
643  set bes [beditselector $f1.bes -label Selector -width 35 -readonly false]
644  puts "beditselector widget : $bes"
645  button $f1.b -text "View All" -command "cmdViewAll"
646  LabelEntry $f1.le -label "All values" -editable false -width 60
647 
648  TitleFrame .top.f2 -text "Configure"
649  set f2 [.top.f2 getframe]
650  LabelEntry $f2.le1 -label "Columns" -text "col1 col2 col3" -width 60
651  LabelEntry $f2.le2 -label "Value list" -width 60 \
652                     -text "{1 2 3} {un dos tres} {one two three}"
653  checkbutton $f2.cb1 -text "Multiple columns" -variable multicol
654  checkbutton $f2.cb2 -text "Only one selected" -variable uniq
655  checkbutton $f2.cb3 -text "With proc" -variable withproc
656  $f2.cb1 select
657  $f2.cb2 deselect
658  $f2.cb3 deselect
659  button $f2.b -text "Load config" -command "cmdLoad"
660  LabelEntry .top.le -label Result
661
662  grid $f1.bes -row 0 -column 0 -sticky "news"
663  grid $f1.b   -row 0 -column 1 -sticky "nes"
664  grid $f1.le  -row 1 -column 0 -sticky "news" -columnspan 2
665 
666  grid $f2.le1 -row 0 -column 0 -columnspan 4
667  grid $f2.le2 -row 1 -column 0 -columnspan 4
668  grid $f2.cb1 -row 2 -column 0
669  grid $f2.cb2 -row 2 -column 1
670  grid $f2.cb3 -row 2 -column 2
671  grid $f2.b   -row 2 -column 3
672 
673  grid .top.f1 -row 0 -column 0 -padx 5 -pady 5 -sticky "news"
674  grid .top.f2 -row 1 -column 0 -padx 5 -pady 5 -sticky "news"
675
676  proc cmdLoad {} {
677    variable uniq
678    variable multicol
679    variable withproc
680       
681    set bes .top.f1.f.bes
682    set lst .top.f2.f.le2
683    set cols .top.f2.f.le1
684
685    set entcols [lrange [$cols cget -text] 0 0]
686    set selcols [lrange [$cols cget -text] 1 end]
687    set hlpcols [lrange [$cols cget -text]  0 1]
688    $bes configure -list [$lst cget -text] -cols [$cols cget -text] \
689                   -unique $uniq
690    $bes configure -entcols $entcols -selcols $selcols -hlpcols $hlpcols
691    if { $withproc } { $bes configure -procedure "__TbesElProc"
692    } else { $bes configure -procedure "" }
693  }
694
695  proc cmdViewAll {} {
696    .top.f1.f.le configure -text [ .top.f1.f.bes cget -sel ]
697  }
698}
699
700package provide beditselector 1.0
Note: See TracBrowser for help on using the repository browser.