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

devel
Last change on this file was cc64b09, checked in by Pedro Gea <pgea@…>, 10 years ago

Refs #1933
Se revisan los binds respecto a wtree y su treectrl.
Se quitan los métodos específicos para la creación de columnas e inserción de nodos que quedaban en tolinspe.
Se añade un update del nodo de paquetes para que se actualice ante un "require".
Se revisan los métodos de botón derecho para que aparezcan sólo sobre los objetos seleccionados.
Se añade un método a wtree para gestionar el color de todas las columnas de un nodo.
Se añaden las columnas al root de wtree.

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

  • Property mode set to 100644
File size: 20.3 KB
Line 
1#/////////////////////////////////////////////////////////////////////////////
2# FILE    : bmultiselec.tcl
3# PURPOSE : Component for creating a multiple selector of items and
4#           managing its events. A multiple selector consist of two listboxes:
5#           unselected (left) and selected (right) with items which you can
6#           move from one listbox to the other.
7#/////////////////////////////////////////////////////////////////////////////
8
9package require byscommon
10package require blistbox
11package require blistboxplus
12
13
14#/////////////////////////////////////////////////////////////////////////////
15::snit::widget bmultiselect {
16#
17# PURPOSE: Selector de elementos multiple
18#
19# opciones especificas
20#  unsel -> valores no seleccionados
21#  sel -> valores seleccionados
22#  labelsel -> etiqueta para la lista de elementos seleccionados
23#  labelunsel -> etiqueta para la lista de elementos no seleccionados
24#  font -> font for the both listboxes
25#  onchanged -> comando a ejecutar cada vez que cambia algo en las listas
26#  unique -> si esta a true solamente se permite pasar un elemento a la lista
27#            de seleccionados
28#  cols -> lista con las columnas de cada ListBox
29#  hiddencols -> aquellas columnas del ListBox que queremos mantener ocultas
30#  width -> ancho total orientativo del widget
31#  height -> alto total orientativo del widget
32#  initialdir -> directory where to go when opening a save dialog
33#
34# variables
35#  lright -> the right label
36#  lleft -> the left label
37#  right -> the right blistbox or blistcontrol
38#  left -> the left blistbox or blistcontrol
39#  bbox -> the buttonbox
40#  plus -> indicates if the listbox is listbox+ (columns)
41#  created -> indicates if the widget has been fully created
42# 
43#/////////////////////////////////////////////////////////////////////////////
44  widgetclass Bmultiselect
45
46  option -sel {}
47  option -unsel {}
48  option -labelsel   "Selected"
49  option -labelunsel "Not Selected"
50  option -font {arial 10}
51  option -onchanged ""
52  option -unique false
53  option -width {}
54  option -height {}
55  option -cols {}
56  option -hiddencols {}
57  option -initialdir ""
58 
59  variable lright
60  variable lleft
61  variable right
62  variable left
63  variable bbox
64  variable bboxright
65
66  variable created 0
67  variable plus 0
68
69  #///////////////////////////////////////////////////////////////////////////
70  constructor { args } {
71  #
72  # PURPOSE: Constructor de un bmultiselect. Crea una instancia de un selector
73  #          multiple
74  #
75  # PARAMETERS:
76  #   args -> Lista de opciones para el bmultiselect
77  #
78  #///////////////////////////////////////////////////////////////////////////
79    $self configure -cols [from args -cols ""]
80    $self configure -sel [from args -sel ""]
81    $self configure -unsel [from args -unsel ""]
82    $self configure -unique [from args -unique 0]
83   
84    # Create the widget
85    $self createwidget $args
86
87    # Apply all arguments given:
88    $self configurelist $args
89  }
90
91
92  #///////////////////////////////////////////////////////////////////////////
93  #
94  # PURPOSE: Metodos cget y configure
95  #
96  #///////////////////////////////////////////////////////////////////////////
97
98  onconfigure -sel { lst } {
99    set options(-sel) $lst
100    if { $created } {
101      $self _FillLB
102    }
103  }
104 
105  onconfigure -unsel { lst } {
106    set options(-unsel) $lst
107    if { $created } {
108      $self _FillLB
109    }
110  }
111 
112  onconfigure -labelsel { value } {
113    if { $created } {
114      set options(-labelsel) $value
115      $lright configure -text $value
116    }
117  }
118 
119  onconfigure -labelunsel { value } {
120    if { $created } {
121          set options(-labelunsel) $value
122      $lleft configure -text $value
123    }
124  }
125 
126  onconfigure -cols { value } {
127    set options(-cols) $value
128    set plus [llength $options(-cols)]
129    if { $created && $plus } {
130      $right configure -cols $value
131      $left configure -cols $value
132    }
133  }
134
135  onconfigure -hiddencols { value } {
136    set options(-hiddencols) $value
137    set plus [llength $options(-cols)]
138    if { $created && $plus } {
139      $right configure -hiddencols $value
140      $left configure -hiddencols $value
141    }
142  }
143
144  onconfigure -width { value } {
145    set options(-width) $value
146    if { ! $plus } {
147      set value [expr $value / 2]
148    }
149    if { $created } {
150      $left configure -width $value
151      $right configure -width $value
152    }
153  }
154
155  onconfigure -height { value } {
156    set options(-height) $value
157    if { ! $plus } {
158      set value [expr $value / 2]
159    }
160    if { $created } {
161      $left configure -height $value
162      $right configure -height $value
163    }
164  }
165
166   onconfigure -initialdir { value } {
167     set options(-initialdir) $value
168     if { $created && $plus } {
169       $left configure -initialdir $options(-initialdir)
170       $right configure -initialdir $options(-initialdir)
171     }
172   }
173
174   onconfigure -font { f } {
175     set options(-font) $f
176     if { $created } {
177       $left configure -font $f
178       $right configure -font $f
179     }
180   }
181
182 
183  #///////////////////////////////////////////////////////////////////////////
184  method createwidget { args } {
185  #
186  # PURPOSE: Creacion de los objetos que componen el widget
187  #
188  # PARAMETERS:
189  #   args -> Lista de opciones para el bmultiselect
190  #
191  #///////////////////////////////////////////////////////////////////////////
192    set labelunsel [from args -labelunsel [mc "Not Selected"]]
193    set labelsel [from args -labelsel [mc "Selected"]]
194    set cols [from args -cols ""]
195    set initialdir [from args -initialdir ""]
196
197    # listbox 1
198    install lleft using label $self.l1 -text $labelunsel -bd 1 -relief raised
199    if { ! $plus } {
200      ScrolledWindow $self.sw1
201      install left using blistbox $self.sw1.lb -selectmode extended \
202        -breadonly true -bkeypress true -bparent $self
203      $self.sw1 setwidget $self.sw1.lb
204      bind $left <Button-1> +[list focus -force %W]
205      bind $left <Double-Button-1> +[list $self _LBLeftToRight]
206    } else {
207       install left using blistboxplus $self.lbl -cols $options(-cols) \
208         -hiddencols $options(-hiddencols) -initialdir $initialdir -readonly true
209       if { $options(-unique) } {
210         $left configure -selectmode single
211       } else {
212         $left configure -selectmode multiple
213       }
214       #@ anteriormente era una llamada a un método bind
215       bind $left <Double-Button-1> +[list $self _LBLeftToRight]
216    }
217
218    # buttons
219    install bbox using ButtonBox $self.bb -orient vertical -spacing 0 \
220                                          -padx 4 -pady 1
221    $bbox add -image [Bitmap::get play] -height 16 -width 16 \
222      -command [list $self _LBLeftToRight] -relief link \
223      -helptext [mc "Moves selection from left to right"]
224    $bbox add -image [Bitmap::get reverse] -height 16 -width 16 \
225      -command [list $self _LBRightToLeft] -relief link \
226      -helptext [mc "Moves selection from right to left"]
227        if { ! $options(-unique) } {
228    $bbox add -image [Bitmap::get end] -height 16 -width 16 \
229      -command [list $self _LBAllLeftToRight] -relief link \
230      -helptext [mc "Moves all from left to right"]
231    $bbox add -image [Bitmap::get begin] -height 16 -width 16 \
232      -command [list $self _LBAllRightToLeft] -relief link \
233      -helptext [mc "Moves all from right to left"]
234    }
235
236
237    install bboxright using ButtonBox $self.bbr -orient vertical -spacing 0 \
238                                          -padx 4 -pady 1
239    $bboxright add -image [Bitmap::get upNext] -height 16 -width 16 \
240      -command [list $self _LBDownToUp] -relief link \
241      -helptext [mc "Moves selection up"]
242    $bboxright add -image [Bitmap::get downNext] -height 16 -width 16 \
243      -command [list $self _LBUpToDown] -relief link \
244      -helptext [mc "Moves selection down"]
245 
246 
247    # listbox 2
248    install lright using label $self.l2 -text $labelsel -bd 1 -relief raised
249    if { ! $plus  } {
250      ScrolledWindow $self.sw2
251      install right using blistbox $self.sw2.lb -selectmode extended \
252        -breadonly true -bkeypress true -bparent $self
253      $self.sw2 setwidget $self.sw2.lb
254      bind $right <Button-1> +[list focus -force %W]
255      bind $right <Double-Button-1> +[list $self _LBRightToLeft]
256    } else {
257       install right using blistboxplus $self.lbr -cols $options(-cols) \
258                                   -initialdir $initialdir -readonly true
259       if { $options(-unique) } {
260         $right configure -selectmode single
261       } else {
262         $right configure -selectmode multiple
263       }
264       #@ anteriormente era una llamada a un método bind
265       bind $right <Double-Button-1> +[list $self _LBRightToLeft]
266    }
267 
268    # fill the listbox
269    $self _FillLB
270
271    grid $self.l1 $bbox $self.l2 $bboxright -sticky news
272    if { ! $plus } {
273      grid $self.sw1  ^      $self.sw2 ^ -sticky news
274    } else {
275          grid $left  ^      $right ^ -sticky news
276    }
277    grid rowconfigure    $self 1 -weight 1
278    grid columnconfigure $self 0 -weight 1
279    grid columnconfigure $self 1 -pad 5
280    grid columnconfigure $self 2 -weight 1
281    grid columnconfigure $self 3 -pad 5
282    update
283    bind <Destroy> $self [list $self KillData]
284   
285    set created 1
286   
287    return $self
288  }
289 
290
291  #///////////////////////////////////////////////////////////////////////////
292    method _EvalOnChanged {} {
293  #
294  # PURPOSE: Evaluates a procedure when any of the listboxes changes any of
295  #          its items and actualizes the -sel and -unsel options.
296  #
297  #///////////////////////////////////////////////////////////////////////////
298   
299    set options(-unsel) [$left get 0 end]
300    set options(-sel) [$right get 0 end]
301       
302    if { [string length $options(-onchanged)] } {
303      eval $options(-onchanged)
304    }
305  }
306
307
308  #///////////////////////////////////////////////////////////////////////////
309    method _FillLB {} {
310  #
311  # PURPOSE: Fill unselected and selected listboxes.
312  #
313  #///////////////////////////////////////////////////////////////////////////
314
315    if { "" eq $options(-cols) } {
316      $left delete 0 end
317      $right delete 0 end
318    } else {
319      $left clear
320      $right clear
321    }
322   
323    foreach it $options(-unsel) {
324      $left insert end $it
325    }
326    foreach it $options(-sel) {
327     
328      $right insert end $it
329      if { $options(-unique) } { break }
330    }
331    $self _EvalOnChanged
332  }
333
334
335  #///////////////////////////////////////////////////////////////////////////
336    method _ListTransferSel { src dst } {
337  #
338  # PURPOSE: Transfer selected items from scr listbox to dst listbox.
339  #
340  # PARAMETERS:
341  #    src -> source listbox path
342  #    dst -> destination listbox path
343  #
344  #///////////////////////////////////////////////////////////////////////////
345
346    if { "$dst" eq "$right" && $options(-unique) } {
347      if { [$right size] eq 0 } {
348        if { "" ne [$src curselection] } {
349          switch [llength $options(-cols)] {
350            1 {
351              eval $dst insert end [$src get [lindex [$src curselection] 0]]
352            }
353            default {
354              $dst insert end [$src get [lindex [$src curselection] 0]]
355            }
356          }
357        }
358      } else {
359        if { $plus } {
360          $src selection clearall
361        } else {
362          $src select clear 0 end
363        }
364      }
365    } else {
366      foreach i [$src curselection] {
367        switch [llength $options(-cols)] {
368          1       { eval $dst insert end [$src get $i] }
369          default { $dst insert end [$src get $i]      }
370        }
371      }
372    }
373  }
374
375
376  #///////////////////////////////////////////////////////////////////////////
377    method _ListDeleteSel { w } {
378  #
379  # PURPOSE: Deletes selected items of a listbox
380  #
381  # PARAMETERS:
382  #    w -> listbox's path
383  #
384  #///////////////////////////////////////////////////////////////////////////
385 
386    if { "$w" eq "$left" && $options(-unique) } {
387          set index [lindex [$w curselection] 0]
388          if { $index >= 0 } { $w delete $index }
389    } else {
390      foreach i [lsort -integer -decreasing [$w curselection]] {
391        $w delete $i
392      }
393    }
394  }
395
396
397  #///////////////////////////////////////////////////////////////////////////
398    method _LBLeftToRight {} {
399  #
400  # PURPOSE: Moves selected items from unselected listbox to selected listbox
401  #
402  #///////////////////////////////////////////////////////////////////////////
403    $self _ListTransferSel $left $right
404    $self _ListDeleteSel   $left
405    $self _EvalOnChanged
406  }
407
408
409  #///////////////////////////////////////////////////////////////////////////
410    method _LBRightToLeft {} {
411  #
412  # PURPOSE: Moves selected items from selectedu listbox to unselected listbox
413  #
414  #///////////////////////////////////////////////////////////////////////////
415    $self _ListTransferSel $right $left
416    $self _ListDeleteSel   $right
417    $self _EvalOnChanged
418  }
419
420
421  #///////////////////////////////////////////////////////////////////////////
422    method _LBAllLeftToRight {} {
423  #
424  # PURPOSE: Moves all items from unselected listbox to selected listbox
425  #
426  #///////////////////////////////////////////////////////////////////////////
427    if { $plus } {
428      foreach i [$left get] {
429        switch [llength $options(-cols)] {
430          1       { eval $right add [$left get $i] }
431          default {      $right add [$left get $i] }
432        }
433        $left delete $i
434      }
435    } else {
436      eval $right insert end [$left get 0 end]
437      $left delete 0 end
438    }
439    $self _EvalOnChanged
440  }
441
442
443  #///////////////////////////////////////////////////////////////////////////
444    method _LBAllRightToLeft {} {
445  #
446  # PURPOSE: Moves all items from selected listbox to unselected listbox
447  #
448  #///////////////////////////////////////////////////////////////////////////
449    if { $plus } {
450      foreach i [$right get] {
451        switch [llength $options(-cols)] {
452          1       { eval $left add [$right get $i] }
453          default {      $left add [$right get $i] }
454        }
455        $right delete $i
456      }
457    } else {
458      eval $left insert end [$right get 0 end]
459      $right delete 0 end
460    }
461    $self _EvalOnChanged
462  }
463
464
465  #///////////////////////////////////////////////////////////////////////////
466    method _LBDownToUp {} {
467  #
468  # PURPOSE: Moves selected items in listbox on the right side up
469  #
470  #///////////////////////////////////////////////////////////////////////////
471    set indexes [$right curselection]
472    if {$indexes != ""} {
473      set first [lindex $indexes 0]
474      set last [lindex $indexes end]     
475      if { $plus } {
476        # hacia arriba
477        if {$first eq [$right item firstchild root]} return
478        foreach index $indexes {
479          $right move $index before {}
480        }       
481      } else {
482        if { $first != 0 } {
483          set previous [$right get [expr {$first-1}]]
484          $right delete [expr {$first-1}]
485          $right insert $last $previous
486        }
487      }
488    }
489  }
490
491
492  #///////////////////////////////////////////////////////////////////////////
493    method _LBUpToDown {} {
494  #
495  # PURPOSE: Moves selected items in listbox on the right side down
496  #
497  #///////////////////////////////////////////////////////////////////////////
498    set indexes [$right curselection]
499    if {$indexes != ""} {
500      set first [lindex $indexes 0]
501      set last [lindex $indexes end]
502      if { $plus } {
503        # hacia abajo
504        if {$last eq [$right item lastchild root]} return
505        foreach index [lreverse $indexes] {
506          $right move $index after {}
507        }
508      } else {
509        set end [$right index end]
510        if { $last != [expr {$end-1}] } {
511          set next [$right get [expr {$last+1}]]
512          $right delete [expr {$last+1}]
513          $right insert $first $next
514        }
515      }
516    }
517  }
518
519 
520  #///////////////////////////////////////////////////////////////////////////
521    method get { {sel "selected"} } {
522  #
523  # PURPOSE: gets items selected or unselected
524  #
525  # PARAMETERS:
526  #  sel: selected or unselected, indicates which ones to return
527  #
528  #///////////////////////////////////////////////////////////////////////////
529    if { $sel eq "selected" } {
530      if { $plus } {
531        set result {}
532        foreach i [$right get] {
533          switch [llength $options(-cols)] {
534            1       { lappend result [lindex [$right get $i] 0] }
535            default { lappend result [$right get $i] }
536          }
537        }
538        return $result
539      } else {
540        return [$right get 0 end]
541      }
542    }
543   
544    if { $sel eq "unselected" } {
545      if { $plus } {
546        set result {}
547        foreach i [$left get] {
548          switch [llength $options(-cols)] {         
549            1       { lappend result [lindex [$left get $i] 0] }
550            default { lappend result [$left get $i] }
551          }
552        }
553        return $result
554      } else {
555        return [$left get 0 end]
556      }
557    }
558  }
559
560  #///////////////////////////////////////////////////////////////////////////
561    method GetSelected {} {
562  #
563  # PURPOSE: Gets item from selected listbox (rigth)
564  #
565  #///////////////////////////////////////////////////////////////////////////
566    puts "This function is deprecated use get selected instead"
567    $self get selected
568  }
569
570
571  #///////////////////////////////////////////////////////////////////////////
572    method GetUnselected {} {
573  #
574  # PURPOSE: Gets item from unselected listbox (left)
575  #
576  #///////////////////////////////////////////////////////////////////////////
577    puts "This function is deprecated use get unselected instead"
578    $self get unselected
579  }
580}
581
582
583# TEST CODE
584
585
586#/////////////////////////////////////////////////////////////////////////////
587proc closeBmultiselectDialog { w } {
588#
589# PURPOSE: closes the dialog and returns the result
590#
591# PARAMETERS:
592#  w -> The dialog's window pathname
593#
594#/////////////////////////////////////////////////////////////////////////////
595  set f [$w getframe]
596  set result [$f.bms get selected]
597  $w enddialog $result
598}
599
600
601#/////////////////////////////////////////////////////////////////////////////
602proc launchDialog { unique multicolumn le } {
603#
604# PURPOSE: Launches a Dialog with a bmultiselect widget
605#
606# PARAMETERS:
607#  w -> The dialog's window pathname
608#  unique -> This option tells the bmultiselect widget if it will admit only
609#            one selected item
610#
611#/////////////////////////////////////////////////////////////////////////////
612
613  # example of how to use in a dialog
614  destroy .top.d
615  set dialog [Dialog .top.d -title "Prueba de BMultiSelect" \
616    -modal local -parent .top]
617  set dialogframe [$dialog getframe]
618
619  if { $multicolumn } {
620    bmultiselect $dialogframe.bms -cols {una dos tres} -unique $unique \
621          -unsel { {un dos tres} {i ii iii} {x y z} {@ # &} } \
622          -sel   { {one two three} {a b c} {k kk kkk} } \
623          -labelunsel "no seleccionados" -labelsel "seleccionados" \
624          -height 200
625  } else {
626    bmultiselect $dialogframe.bms -unsel {uno 2 tres 4} -sel {cinco 5 siete} \
627      -labelunsel "no seleccionados" -labelsel "seleccionados" -unique $unique
628  }
629 
630  set dialogframe_bbox \
631          [ButtonBox $dialogframe.bb -orient horizontal -spacing 10 -padx 0 -pady 0 \
632          -homogeneous false]
633  $dialogframe_bbox add -text [mc "Accept"] -relief link \
634          -helptext [mc "Accept selection"] \
635          -image [::Bitmap::get accept] -compound left -padx 5 -pady 1 \
636          -command [list closeBmultiselectDialog $dialog]
637  $dialogframe_bbox add -text [mc "Cancel"] -relief link \
638          -helptext [mc "Cancel selection"]\
639          -image [::Bitmap::get cancelx] -compound left -padx 5 -pady 1 \
640          -command [list $dialog enddialog ""]   
641 
642  pack $dialogframe_bbox -fill x -expand false -side bottom
643  pack $dialogframe.bms -fill both -expand true
644 
645  set result [$dialog draw]
646  $le configure -text $result
647}
648
649
650#/////////////////////////////////////////////////////////////////////////////
651proc test_bmultiselect {} {
652#
653# PURPOSE: Test function of a bmultiselect
654#
655#/////////////////////////////////////////////////////////////////////////////
656  destroy .top
657  toplevel .top
658  variable multcols 0
659  variable uniq 0
660
661  radiobutton .top.rb1 -text "Multiple columns" -value 1 -variable multcols
662  radiobutton .top.rb2 -text "Only one column"  -value 0 -variable multcols
663  checkbutton .top.cb -text "Only one selected" -command toggleuniq
664  .top.cb deselect
665  button .top.b -text "Launch a MultiSelect Dialog" -command "preLaunchDialog"
666  LabelEntry .top.le -label Result
667
668
669  grid .top.rb1 -row 0 -column 0
670  grid .top.rb2 -row 1 -column 0
671  grid .top.cb -row 0 -column 1
672  grid .top.b -row 1 -column 1
673  grid .top.le -row 2 -column 0 -columnspan 2 -sticky "ew"
674
675  proc toggleunique {} {
676    variable uniq
677    set uniq [expr ! $uniq]
678  }
679 
680  proc preLaunchDialog {} {
681    variable uniq
682        variable multcols
683    launchDialog $uniq $multcols .top.le
684  }
685
686}
687
688package provide bmultiselect 1.0
Note: See TracBrowser for help on using the repository browser.