source: tol/tolbase/lib/byswidget/blistboxplus/blistboxplus.tcl @ f861956

1941-docker-image-to-testdevel
Last change on this file since f861956 was bdc524a, checked in by Jorge Pérez <josp.jorge@…>, 18 years ago

svn:eol-style native

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

  • Property mode set to 100644
File size: 40.7 KB
Line 
1#/////////////////////////////////////////////////////////////////////////////
2# FILE    : blistboxplus.tcl
3# PURPOSE : Bayes List Box. ListBox con opciones sobre su elementos y varias
4#           columnas
5#/////////////////////////////////////////////////////////////////////////////
6
7package require byscommon
8package require BLT
9package require bfunctions
10package require bfieldsdialog
11
12proc debug_init { } {
13  catch {
14    file delete "/tmp/debug_tcl.out"
15  }
16}
17
18proc debug_msg { msg } {
19  catch {
20    set fd [open "/tmp/debug_tcl.out" "a"]
21    puts $fd $msg
22    close $fd
23  }
24}
25
26#/////////////////////////////////////////////////////////////////////////////
27::snit::widget blistboxplus {
28#
29# PURPOSE: ListBox con columnas, menu contextual y caracteristicas adicionales
30#
31#/////////////////////////////////////////////////////////////////////////////
32# opciones especificas
33# readonly -> componente en modo de lectura o lectura/escritura
34# keypress -> Activa la busqueda de filas mediante la pulsacion de teclas
35# colkeypress -> Indica por que columna se busca al pulsar una tecla
36# parent -> indica el padre donde se ubica el blistbox
37# cols -> columnas del listbox
38# hiddencols -> columnas del listbox que no se mostraran
39# filtercols -> columnas del listbox que por las que puede realizarse filtrado
40# initialdir -> directorio inicial para los dialogos de lec/esc de archivos,...
41# orientation -> orientation for de add dialog
42# icon -> icono que se mostrará como primera columna, si no hay icono la
43#  columna no se mostrará
44# nomenu -> Si es 1, no se mostrará el menu contextual
45# titles -> Lista con los titulos a mostrar en cada una de las columnas.
46# values -> List of initial values to load in widget
47# valuesinsert -> List of values to selection element
48# iniconfig -> Nombre que se asigna al listboxplus para identificar sus
49#           opciones en el archivo de configuración .ini por defecto "" en
50#           ese caso no se guardaran las opciones
51#
52# variables
53# listbox -> el treeview que hace de listbox propiamente
54# menu -> el menu contextual del listbox
55# xbar -> horizontal scrollbar
56# ybar -> vertical scrollbar
57# afterTime -> tiempo desde que se pulso la ultima tecla
58# listKey -> lista de teclas pulsadas
59#/////////////////////////////////////////////////////////////////////////////
60  widgetclass Blistboxplus
61
62  option -readonly  0
63  option -keypress    true
64  option -colkeypress ""   
65  option -parent    {}
66  option -cols {}
67  option -hiddencols {}
68  option -filtercols {}
69  option -initialdir {}
70  option -orientation vertical
71  option -showtitles true
72  option -icon ""
73  option -nomenu 0
74  option -titles {}
75  option -values {}
76  option -valuesinsert {}
77  option -iniconfig ""
78 
79  variable _listbox
80  variable menu
81  variable xbar
82  variable ybar
83 
84  variable afterTime 0
85  variable listKey   ""
86  variable currentId 0
87  variable created   0
88
89  #///////////////////////////////////////////////////////////////////////////
90  constructor {args} {
91  #
92  # PURPOSE: Constructor de un blistboxplus. Crea una instancia de un Listbox
93  #
94  # PARAMETERS:
95  #   args -> opciones
96  #
97  #///////////////////////////////////////////////////////////////////////////
98
99    debug_init
100
101    debug_msg "install listbox ..."
102
103    if {0} {
104      install _listbox using ::blt::treeview $win.lb -hideroot yes \
105          -activeicons "" -icons {} -selectmode multiple \
106          -selectbackground grey -selectforeground white \
107          -highlightthickness 0 -borderwidth 1 -selectborderwidth 1 \
108          -nofocusselectbackground grey -font {Arial 9} -flat yes
109    } else {
110      set _listbox [::blt::treeview $win.lb -hideroot yes \
111                        -activeicons "" -icons {} -selectmode multiple \
112                        -selectbackground grey -selectforeground white \
113                        -highlightthickness 0 -borderwidth 1 \
114                        -selectborderwidth 1 \
115                        -nofocusselectbackground grey -font {Arial 9} -flat yes]
116    }
117
118    debug_msg "despues de install listbox"
119
120    install menu using menu $win.m -tearoff 0
121    install xbar using scrollbar $win.sbh -orient horizontal \
122                                           -command "$win xview"
123    install ybar using scrollbar $win.sbv -orient vertical \
124                                           -command "$win yview"
125
126    #bindtags is modified to make possible to associate binds to self
127    bindtags $_listbox [linsert [bindtags $_listbox] 2 $win]
128
129    $_listbox style  configure text     -bg white
130
131    $_listbox column configure treeView -bg white
132
133    $self configure -readonly [from args -readonly]
134    $self _CreateMenu 
135   
136    # Apply all arguments given:
137    $self configurelist $args
138
139    $_listbox configure -xscrollcommand "$xbar set"
140    $_listbox configure -yscrollcommand "$ybar set"
141    if { $options(-parent) eq "" } {
142      $self configure -parent [winfo parent $win]
143    }
144   
145    # bind
146    $_listbox bind all <KeyPress> +[list $self _OnKeyPress %A]
147   
148    $self configure -nomenu [from args -nomenu]
149    $self configure -filtercols [from args -filtercols]
150
151    #pack
152    grid $_listbox -row 0 -column 0 -sticky news
153    grid $ybar -row 0 -column 1 -sticky ns
154    grid $xbar -row 1 -column 0 -sticky ew
155    grid columnconfigure $self 0 -weight 1
156    grid rowconfigure    $self 0 -weight 1
157
158    ::autoscroll::autoscroll $ybar
159    ::autoscroll::autoscroll $xbar
160    debug_msg "voy a pillarte: antes de _ReadIni"
161    $self _ReadIni
162    debug_msg "pase?"
163    set created 1
164  }
165
166  #///////////////////////////////////////////////////////////////////////////
167  destructor {
168  #
169  # PURPOSE: Funciones a evaluar al eliminar la instancia de blistboxplus.
170  #
171  # PARAMETERS:
172  #   self: toplevel
173  #
174  #///////////////////////////////////////////////////////////////////////////
175    # Save .ini
176    catch [list $self _WriteIni ]
177  }
178   
179  #///////////////////////////////////////////////////////////////////////////
180  #
181  # PURPOSE: Metodos cget y configure
182  #
183  #///////////////////////////////////////////////////////////////////////////
184
185    onconfigure -cols { lst } {
186     set options(-cols) $lst
187       foreach col [$self column names] {
188         $_listbox column delete $col
189       }
190       foreach col $options(-cols) {
191         $_listbox column insert end $col -justify left
192         $_listbox column configure $col -command "$self _SortByColumn [list $col]" \
193            -titleborderwidth 1
194       }
195       if { $options(-icon) == "" } {
196         $_listbox column configure "BLT TreeView $_listbox" -hide 1
197       } else {
198         $_lisbox column configure "BLT TreeView $_listbox" -hide 0
199       }
200  }
201
202  onconfigure -hiddencols { lst } {
203    set options(-hiddencols) $lst
204    foreach col [$self column names] {
205      if { "-1" eq [lsearch $options(-hiddencols) $col] } {
206        $_listbox column configure $col -hide 0
207      } else {
208        $_listbox column configure $col -hide 1
209      }
210    }
211  }
212
213  onconfigure -showtitles { bool } {
214    set options(-showtitles) $bool
215    $_listbox configure -showtitles $bool
216    $_listbox show
217  }
218
219  onconfigure -icon { icon } {
220    set options(-icon) $icon
221    if { $icon != "" } {
222      $_listbox column configure "BLT TreeView $_listbox" -min 16 -max 16 \
223        -hide 0 -titleborderwidth 1
224      $_listbox configure -icons [list [Bitmap::get $icon] [Bitmap::get $icon]]
225    } else {
226      $_listbox column configure "BLT TreeView $_listbox" -hide 1
227    }
228  }
229
230  onconfigure -titles { titles } {
231    set options(-titles) $titles
232    set c 0
233    set cols [$self column names]
234    foreach col $cols {
235     $self column configure $col -title [mc [lindex $titles $c] ]
236     incr c 1     
237    }
238  }
239 
240  onconfigure -values { lst } {
241    $self clear
242    eval $self insert end $lst
243  }
244
245  onconfigure -nomenu { bool } {
246    set options(-nomenu) $bool
247    if {$bool} {
248      # no mostrar menu
249      bind $self  <Button-3>   ""
250    } else {
251      # mostrar menu
252      bind $self  <Button-3>   "tk_popup $menu %X %Y"
253    }
254  }
255 
256  onconfigure -readonly { bool } {
257    if {!($created)} {
258      set options(-readonly) $bool       
259    } else {
260      puts "Blistboxplus widget error: option -readonly only can be set on \
261            creation time"
262    }
263  }
264 
265  onconfigure -filtercols { lst } {
266    set cols [$self cget -cols]   
267    set hiddencols [$self cget -hiddencols]
268    if { [llength cols] && [llength hiddencols]} {
269      set filtercols {}
270      foreach col $cols {
271        if {([lsearch -exact $hiddencols  $col])} {
272          lappend filtercols $col
273        }
274      }
275      set options(-filtercols) $filtercols   
276    } else {
277      if { [llength cols] } {
278        set options(-filtercols) $options(-cols)
279      }
280    }
281  }
282 
283  #///////////////////////////////////////////////////////////////////////////
284  method _CreateMenu {args} {
285  #
286  # PURPOSE: Append menu to listbox.
287  #
288  #///////////////////////////////////////////////////////////////////////////
289    # read option
290    $menu add command -label [mc "Select all"] \
291      -command "$self _SelectAll"  -accelerator CTRL+E
292    $menu add command -label [mc "Unselect all"] \
293      -command "$self selection clearall" -accelerator CTRL+U
294    $menu add command -label [mc "Toggle selection"] \
295      -command "$self _ToggleSelection" -accelerator CTRL+I
296    # read/write option
297    if {!([$self cget -readonly])} {
298      # delete
299      $menu add separator
300      $menu add command -label [mc "Insert"] \
301                -command "$self _OpenWR" -accelerator Ins
302      $menu add command -label [mc "Delete all"]  \
303        -command "$self clear"  -accelerator CTRL+D
304      $menu add command -label [mc "Delete selected"] \
305        -command "lbDeleteSelection $self"
306    }
307    # read option
308    # copy
309    $menu add separator
310    $menu add command -label [mc "Filter"] -command "$self _OpenFD"
311    $menu add command -label [mc "Unfilter"] -command "$self _RemoveFilter"
312    $menu add separator
313    set mc [menu $menu.copy -tearoff 0]
314    $menu add cascade -label [mc "Copy"] -menu $mc
315    $mc add command -label [mc "Copy all"] \
316      -command "$self _CopyToClipBoard 1 1" -accelerator CTRL+A
317    $mc add command -label [mc "Copy selected"] \
318      -command "$self _CopyToClipBoard 1 0" -accelerator CTRL+C
319    $mc add command -label [mc "Copy unselect"] \
320      -command "$self _CopyToClipBoard 0 1"
321    # count
322    $menu add separator
323    $menu add command -label [mc "Count elements"] \
324      -command "$self _ShowCountItems" -accelerator CTRL+N
325    # file
326    $menu add separator
327    set mf [menu $menu.file -tearoff 0]
328    $menu add cascade -label [mc "File_lbp"] -menu $mf
329    $mf add command -label "[mc "Save to file"] ..." \
330      -command "$self _SaveToFile 1 1"
331    if {![$self cget -readonly]} {
332      $mf add command -label "[mc "Load form file"] ..." \
333        -command "$self _LoadFromFile"
334    }
335    # bindings   
336    $self bind all <Control-KeyRelease> +[list $self _OnControlKey $self %K %k]
337    $self bind all <Key-Delete>    "lbDeleteSelection $self"
338    $self bind all <Key-Insert>    "$self _OpenWR"   
339    $self bind all <Shift-Up>      "$self addPrevious"
340    $self bind all <Shift-Down>    "$self addNext"
341    $self bind all <Up>            "$self previous"
342    $self bind all <Down>          "$self next"
343    $self bind all <Home>          "$self first"
344    $self bind all <End>           "$self last"
345    $self bind all <Shift-Home>    "$self addAllPrevious"
346    $self bind all <Shift-End>     "$self addAllNext"
347    $self bind all <Button-1>      +[list focus -force %W]
348  }
349
350
351  #///////////////////////////////////////////////////////////////////////////
352  method getMenu { } {
353  #
354  # PURPOSE: Devuelve el menu del blistboxplus para poder modificarlo y
355  #          ampliarlo
356  #
357  # RETURN: La variable de instancia que apunta al menu
358  #
359  #/////////////////////////////////////////////////////////////////////////// 
360    return $menu
361  }
362
363
364  #///////////////////////////////////////////////////////////////////////////
365  method _OnKeyPress {key} {
366  #
367  # PURPOSE: Activa la fila que coincide con las teclas pulsadas. Distinge
368  #          entre muysuculas y minusculas
369  #
370  # PARAMETERS: key -> tecla pulsada
371  #
372  #///////////////////////////////////////////////////////////////////////////
373    if {[$self cget -keypress]} {
374      set diference 500
375      set result [lbOnKeyPress $self $key $listKey $afterTime $diference \
376        [$self cget -colkeypress]]
377      set listKey   [lindex $result 0]
378      set afterTime [lindex $result 1]
379    }
380  }
381
382
383  #///////////////////////////////////////////////////////////////////////////
384  method _OnControlKey {_lb keysym keycode} {
385  #
386  # PURPOSE: Controla es uso de teclas rápidas para le ejecución de funciones
387  #
388  # PARAMETERS: _lb -> self
389  #             keysym -> The keysym corresponding to the event,
390  #                       substituted as a textual string
391  #             keycode -> The keycode field from the event
392  #
393  #///////////////////////////////////////////////////////////////////////////
394    switch [string toupper $keysym] {
395      E { $_lb _SelectAll }
396      C { lbToClipBoard $_lb 1 0 }
397     
398      A { $self _CopyToClipBoard 1 1 }
399      D { $self clear }
400      I { $self _ToggleSelection }
401      U { $self selection clearall }
402      N { $self _ShowCountItems }
403    }
404  } 
405
406  #///////////////////////////////////////////////////////////////////////////
407  method _ShowCountItems {} {
408  #
409  # PURPOSE: Shows information on the selection of the elements
410  #
411  #///////////////////////////////////////////////////////////////////////////
412    set info [lbCountItems $self]
413    set msg "[mc "Total"]: [lindex $info 0] \n\
414             [mc "Selected"]: [lindex $info 1] \n\
415             [mc "Not Selected"]: [lindex $info 2]"
416    if {[string length [$self cget -parent]]} {
417      set par $self
418    } else {
419      set par [$self cget -parent]
420    }
421    tk_messageBox -default ok \
422                  -icon info  \
423                  -message $msg \
424                  -type ok \
425                  -parent $par \
426                  -title [mc "numero de elementos"]
427  }
428
429
430  #/////////////////////////////////////////////////////////////////////////////
431  method _ToggleSelection {} {
432  #
433  # PURPOSE: Toggle selection elements
434  #
435  #/////////////////////////////////////////////////////////////////////////////
436    foreach i [$self get] {
437      $self selection toggle $i
438    }
439  }
440
441
442  #///////////////////////////////////////////////////////////////////////////
443  method _SelectAll { } {
444  #
445  # PURPOSE: Selection all
446  #
447  #///////////////////////////////////////////////////////////////////////////
448    foreach i [$self get] {
449      $self selection set $i
450    }
451  }
452
453
454  #/////////////////////////////////////////////////////////////////////////////
455  method _CopyToClipBoard { sl unSe {pref ""} {suf ""} {sep "\n"}} {
456  #
457  # PURPOSE: copy the elements indicates in clipboard
458  #
459  # PARAMETERS:
460  #   sl   -> Copy items selections
461  #   unSe -> Copy items not selections
462  #   pref -> Text to concatenate in the beginning. Default ""
463  #   suf  -> Text to concatenate in the end. Default ""
464  #   sep  -> Separating text of elements. Default "\n"
465  #
466  #/////////////////////////////////////////////////////////////////////////////
467    # items to copy
468    set lst {}
469    if { $sl } {
470      foreach i [$self curselection] {
471        lappend lst [$self get $i]
472      }
473    }
474    if { $unSe } {
475      foreach i [$self selection get unselected] {
476        lappend lst [$self get $i]
477      }
478    }
479    # copy
480    set str [ListToStr $lst $sep $pref $suf]
481    clipboard clear
482    clipboard append $str
483  }
484
485
486  #/////////////////////////////////////////////////////////////////////////////
487  method _SaveToFile {se unSe {pref ""} {suf ""} {sep "\n"}} {
488  #
489  # PURPOSE: Save the content from listbox in a file
490  #
491  # PARAMETERS:
492  #    sl   -> Copy items selections
493  #   unSe -> Copy items not selections
494  #   pref -> Text to concatenate in the beginning. Default ""
495  #   suf  -> Text to concatenate in the end. Default ""
496  #   sep  -> Separating text of elements. Default "\n"
497  #
498  #/////////////////////////////////////////////////////////////////////////////
499    # select file
500    set filNam [tk_getSaveFile -parent $self -title [mc "File selector"] \
501                               -initialdir $options(-initialdir)]
502
503    if {$filNam != ""} {
504      set options(-initialdir) [file dirname $filNam]   
505      # open file to write
506      if { ![ catch { set fd [open $filNam w] } msgerr] } {
507        # text to save
508        set lst {}
509        if { $se } {
510          foreach i [$self selection get selected] {
511            lappend lst [$self get $i]
512          }
513        }
514        if { $unSe } {
515          foreach i [$self selection get unselected] {
516            lappend lst [$self get $i]
517          }
518        }
519        set str [ListToStr $lst $sep $pref $suf]
520        # write
521        puts -nonewline $fd $str
522        close $fd
523        return 1
524      }
525      error $msgerr
526    }
527  }
528
529  #/////////////////////////////////////////////////////////////////////////////
530  method  _LoadFromFile { } {
531  #
532  # PURPOSE: Load the content from listbox in a file
533  #
534  #/////////////////////////////////////////////////////////////////////////////
535    # select file   
536    set filNam [tk_getOpenFile -parent $self -title [mc "File selector"] \
537                               -initialdir $options(-initialdir)]   
538
539    if {$filNam != ""} {
540      set options(-initialdir) [file dirname $filNam]
541      # open file to read
542      if { ![ catch { set fd [open $filNam r] } msgerr] } {
543         while { [gets $fd line ] >= 0} {
544                   Tolcon_Trace "adding $line"
545           $self add $line
546         }
547         close $fd     
548         return 1
549      }
550      error $msgerr
551    }
552  }
553
554  #///////////////////////////////////////////////////////////////////////////
555  method _SortByColumn { col } {
556  #
557  # PURPOSE: Sorts the ListBox by the values of the given column
558  # PARAMETERS:
559  #  col -> the column which the sort is performed
560  #
561  #///////////////////////////////////////////////////////////////////////////
562
563        set numofel [$self size]
564        set lst [list]
565        set fulllst [$self get]
566
567        foreach i $fulllst {
568           lappend lst [$self get $i ]
569    }
570# lst:    contains a list of values
571        set coln 0
572        set cols [$self cget -cols]
573        set hidcols [$self cget -hiddencols]
574        for { set j 0 } { $j < [llength $cols] } { incr j } {
575                if {[lindex $cols $j] eq $col} {
576                        set coln $j
577                }
578        }
579# coln:   contains the index of the column to be ordered
580        set lst [lsort -index $coln $lst]
581        $self clear
582    for { set i 0 } { $i < $numofel } { incr i } {
583        set el [lindex $lst $i ]
584                $self insert end $el
585    }
586
587  }
588
589
590  #///////////////////////////////////////////////////////////////////////////
591  proc _AddWR { elem father } {
592  #
593  # PURPOSE: adds the item introduced in the dialog to the selected list
594  #
595  # PARAMETERS:
596  #  elem -> the element to insert from the add dialog
597  #  father -> The dialog's window pathname
598  #
599  #///////////////////////////////////////////////////////////////////////////
600    foreach ele $elem {
601      $father insert 0 $ele
602    }
603  }
604
605
606  #//////////////////////////////////////////////////////////////////////////
607  method _OpenWR {} {
608  #
609  # PURPOSE: Calls (and creates) an add dialog for insert by hand elements
610  #
611  #///////////////////////////////////////////////////////////////////////////
612    destroy $self.dw
613   
614    if {![catch {eval $options(-valuesinsert)} res]} {
615      set valuesinsert $res
616    } else {
617      set valuesinsert $options(-valuesinsert)
618    }
619   
620    if {$valuesinsert == ""} {
621      set dialog  [bfieldsdialog $self.dw -title [mc "Insert element"] \
622                  -parent $self -orientation $options(-orientation) \
623                  -fields $options(-cols) -procedure [codename _AddWR] \
624                  -buttons { add exit } -titles $options(-titles) \
625                  -list $valuesinsert]
626    } else {       
627      set dialog  [bfieldsdialog $self.dw -title [mc "Insert element"] \
628                  -parent $self -orientation $options(-orientation) \
629                  -fields $options(-cols) -procedure [codename _AddWR] \
630                  -buttons { add addall exit } -titles $options(-titles) \
631                  -list $valuesinsert]
632    }
633    $dialog draw
634  }
635 
636 
637  #///////////////////////////////////////////////////////////////////////////
638  proc _Filter { elem father } {
639  #
640  # PURPOSE: Filters the listbox with the filter suministred
641  #
642  # PARAMETERS:
643  #  elem -> the list with the filter fields
644  #  father -> The dialog's window pathname
645  #
646  #///////////////////////////////////////////////////////////////////////////
647    eval $father filter $elem
648  }
649
650
651  #//////////////////////////////////////////////////////////////////////////
652  method _OpenFD {} {
653  #
654  # PURPOSE: Calls (and creates) a add dialog for getting a filter
655  #
656  #///////////////////////////////////////////////////////////////////////////
657
658    destroy $self.fd
659    set dialog  [bfieldsdialog $self.fd -title [mc "Filter elements"] \
660                -parent $self -orientation $options(-orientation) \
661                -fields $options(-filtercols) -procedure [codename _Filter] \
662                -buttons { info apply accept cancel } \
663                -titles $options(-titles)]
664    $dialog configure -info \
665"Los filtros admiten expresiones regulares:
666
667  expresiones regulares básicas:
668    - literales: caracteres simples
669    - brackets:  conincide con cualquier caracter especificado dentro
670       tambien pueden expecificarse rangos pe \[a-d\] equivale a \[abcd\]
671       o indicar la no coincidencia colocando como primer caracter ^
672       rangos predefinidos:
673        \[:alnum:\] equivale a \[0-9a-zA-Z\]
674        \[:alpha:\] equivale a \[a-zA-Z\]
675        \[:digit:\] equivale a \[0-9\]
676        \\w equivale a \[:alnum:\]
677        \\W equivale a \[^:alnum:\]
678        para incluir el literal - ponerlo al final del braquet
679        para incluir el literal ^ ponerlo en cualquier lugar menos el primero
680    - punto . : coincide con cualquier caracter simple
681    - ^ y $ : coinciden respectivamente con el principio o final de linea
682    - caracteres especiales: los caracteres que tienen significado en las
683      expresiones regulares pueden escribirse precediendolos con \\
684   
685  operadores sobre las expresiones:
686    - <e1><e2>: concatenacion, la expresion resultante coincide si coinciden
687         secuencialmente las expresiones
688    - <e1>|<e2> : disyuncion, coincide si coincide alguna de las expresiones
689    - <e>? : opcionalidad, coincide si la expresion anterior coincide 0 o 1 vez
690    - <e>* : repeticion, coincide si la expresion anterior coincide 0 o mas veces
691    - <e>+ : repeticion, coincide si la expresion anterior coincide 1 o mas veces
692    - <e>{n} : repeticion, coincide si la expresion anterior coincide  n veces
693    - <e>{n,} : repeticion, coincide si la exp anterior coincide n o mas veces
694    - <e>{n,m} : repeticion, coincide si la exp anterior coincide por lo menos n
695         y no mas de m veces
696
697  precedencia de los operadores:
698    - los operadores de repeticion tienen preferencia sobre la concatenacion
699    - la concatenacion tiene preferencia sobre la disyuncion
700    - las reglas pueden alterarse con el uso de parentesis
701"
702       
703    $dialog draw
704  }
705 
706  #///////////////////////////////////////////////////////////////////////////
707  method _WriteIni { } {
708  #
709  # PURPOSE: Guarda en el .ini informacion referente al blistboxplus
710  #
711  #
712  #///////////////////////////////////////////////////////////////////////////
713    if { [$self cget -iniconfig] ne "" } {
714      # comprobamos cargado namespace y variable de .ini
715      if {[namespace exists ::iniFile]} {
716        set wini ::iniFile::Write
717        set nm [$self cget -iniconfig]
718        if {![string length $nm]} {
719          set nm $self
720        }
721        $wini $nm initialdir $options(-initialdir)
722      }
723    }
724  }
725
726  #///////////////////////////////////////////////////////////////////////////
727  method _ReadIni { } {
728  #
729  # PURPOSE: Recupera del .ini informacion referente al blistboxplus
730  #
731  #
732  #///////////////////////////////////////////////////////////////////////////
733    if { [$self cget -iniconfig] ne "" } {
734      # comprobamos cargado namespace y variable de .ini
735      if {[namespace exists ::iniFile]} {
736        set rini ::iniFile::Read
737        set nm [$self cget -iniconfig]
738        if {![string length $nm]} {
739          set nm $self
740        }
741        set stt [::iniFile::ReadWMState $rini $nm]
742        set inid [$rini $nm initialdir ""]       
743        if {[string length $inid]} {
744            set options(-initialdir) $inid
745        }
746      }
747    }
748  }
749
750
751  #///////////////////////////////////////////////////////////////////////////
752  method selection { args } {
753  #
754  # PURPOSE: extends the original command to extend capabilities
755  #
756  # PARAMETERS:
757  #   args: arguments
758  #
759  #///////////////////////////////////////////////////////////////////////////
760    if { [lindex $args 0] eq "get" } {
761     if { [lindex $args 1] eq "unselected" } {
762       set result {}
763       set selected [$self curselection]
764       foreach i [$self get] {
765         if { "-1" eq [lsearch $selected $i] } {
766           lappend result $i
767         }
768       }
769       return $result
770     } else {
771      return [eval $_listbox curselection]
772     }
773    }
774
775    eval $_listbox selection $args
776  }
777
778
779  #///////////////////////////////////////////////////////////////////////////
780  method insert { pos args } {
781  #
782  # PURPOSE: inserts an element into de listbox
783  #
784  # PARAMETERS:
785  #   args: a list of elements to insert, each element is a list with column
786  #   data
787  #
788  #///////////////////////////////////////////////////////////////////////////   
789    if { [lindex $args 0] eq "cols" } {
790      set cols [lindex $args 1]
791      set args [lrange $args 2 end]
792    } else {
793      set cols $options(-cols)
794    }
795   
796    switch [llength $cols] {
797      1 {
798        # mas de una columna
799        foreach dats $args {
800          set datos [list [lindex $cols 0] $dats]
801          $_listbox insert $pos $currentId -data $datos
802          incr currentId
803        }       
804      }
805      default {
806        # mas de una columna
807        foreach dats $args {
808          set i 0
809          set datos {}
810          foreach col $cols {
811            lappend datos $col [lindex $dats $i]
812            incr i
813          }
814          $_listbox insert $pos $currentId -data $datos
815          incr currentId
816        }
817      }
818    }
819  }
820
821
822  #///////////////////////////////////////////////////////////////////////////
823  method add { args } {
824  #
825  # PURPOSE: appends elements to dthe listbox
826  #
827  # PARAMETERS:
828  #   args: a list of elements to insert, each element is a list with column
829  #   data
830  #
831  #///////////////////////////////////////////////////////////////////////////
832    eval $self insert end $args
833  }
834 
835
836  #///////////////////////////////////////////////////////////////////////////
837  method delete { args } {
838  #
839  # PURPOSE: deletes elements from the listbox
840  #
841  # PARAMETERS:
842  #   args: the tags or ids of the items to be deleted
843  #   data
844  #
845  #///////////////////////////////////////////////////////////////////////////
846    if { "-1" eq [lsearch $args 0] } {
847      eval $_listbox delete $args
848    } else {
849      puts "Root node can't be deleted"
850    }
851  }
852 
853 
854  #/////////////////////////////////////////////////////////////////////////// 
855  method getlb {} {
856  #
857  # PURPOSE: Get path of blistboxplus
858  #
859  #/////////////////////////////////////////////////////////////////////////// 
860    return $_listbox
861  }
862
863
864  #///////////////////////////////////////////////////////////////////////////
865  method get { {ids ""} {cols ""}} {
866  #
867  # PURPOSE: retrieves data from an entry identified by id
868  #
869  # PARAMETERS:
870  #  id: id list of nodes
871  #  cols: name of the cols from which retrieve data
872  #
873  #///////////////////////////////////////////////////////////////////////////
874    if { $ids eq "" } { return [lrange [$self find] 1 end] }
875 
876    set result {}
877         
878        if { "$cols" eq "" } {
879          set cols [$self column names]
880        }
881
882    foreach id $ids {
883   
884      set elem {}
885   
886      set data [$_listbox entry cget $id -data]   
887   
888      foreach col $cols {
889        set inx [lsearch $data $col]
890        if { "-1" ne $inx } {
891          incr inx
892          lappend elem [lindex $data $inx]
893        }
894      }
895     
896      lappend result $elem
897    }
898    if { [llength $ids] eq 1 } { return [lindex $result 0] }
899    return $result
900  }
901
902
903  #///////////////////////////////////////////////////////////////////////////
904  method set { id data {cols ""}} {
905  #
906  # PURPOSE: inserts data to an entry identified by id
907  #
908  # PARAMETERS:
909  #  id: id of the node
910  #  data: data to insert
911  #  cols: name of the cols from which retrieve data
912  #
913  #///////////////////////////////////////////////////////////////////////////
914    if { "$cols" eq "" } {
915      set cols [$self column names]
916    }   
917    set datos {}
918    set i 0   
919    foreach col $cols {
920      lappend datos $col
921      lappend datos [lindex $data $i]
922      incr i
923    }
924    return [$_listbox entry configure $id -data $datos]
925  }
926
927
928  #///////////////////////////////////////////////////////////////////////////
929  method first {} {
930  #
931  # PURPOSE: Selects and returns the first row of blistboxplus
932  #
933  # RETURN: The index of first row
934  #
935  #///////////////////////////////////////////////////////////////////////////
936    set all [$self get]
937    set selected [$self selection get]
938    if {$selected != ""} {   
939      foreach item $selected { 
940        $self selection clear $item
941      }
942    }
943    if { !([llength [$self get]] eq 0)} {
944      $self selection set [lindex $all 0]
945    }
946    return [lindex $all 0]
947  }
948   
949   
950  #///////////////////////////////////////////////////////////////////////////
951  method last {} {
952  #
953  # PURPOSE: Selects and returns the last row of blistboxplus
954  #
955  # RETURN: The index of last row
956  #
957  #///////////////////////////////////////////////////////////////////////////
958    set all [$self get]
959    set selected [$self selection get]
960    if {$selected != ""} {
961      foreach item $selected {
962        $self selection clear $item
963      }             
964    }
965    if { !([llength [$self get]] eq 0)} {
966      $self selection set [lindex $all [expr [llength $all] - 1]]
967    }
968    return [lindex $all [expr [llength $all] - 1]]           
969  }
970
971
972  #///////////////////////////////////////////////////////////////////////////
973  method addPrevious {} {
974  #
975  # PURPOSE: adds the row previous to the present selection
976  #
977  # RETURN: The index of the row previous
978  #
979  #///////////////////////////////////////////////////////////////////////////
980    set all [$self get]
981    set selected [$self selection get]
982    if {$selected == ""} {
983      return -1
984    } else  {
985      set firstSelected [lindex $selected 0]
986      set first [lindex $all 0]
987      if { $first == $firstSelected } {
988        return [lindex $all 0]
989      } else  {
990        set allPosition [lsearch -exact $all $firstSelected]
991        set firstSelected [lindex $all [expr $allPosition - 1]]
992        #set firstSelected [expr $firstSelected - 1]
993        $self selection set $firstSelected
994        return $firstSelected
995      }
996    }
997  }
998 
999
1000  #///////////////////////////////////////////////////////////////////////////
1001  method addNext {} {
1002  #
1003  # PURPOSE: Adds the following row to the present selection
1004  #
1005  # RETURN: The index of the following row
1006  #
1007  #///////////////////////////////////////////////////////////////////////////
1008    set all [$self get]
1009    set selected [$self selection get]
1010    if {$selected == ""} {
1011      return -1     
1012    } else  {
1013      set lastSelected [lindex $selected [expr [llength $selected] - 1] ]
1014      set last [lindex $all [expr [llength $all] - 1]]
1015      if { $last == $lastSelected } {
1016        return [lindex $all [expr [llength $all] - 1]]
1017      } else  {
1018        set allPosition [lsearch -exact $all $lastSelected]
1019        set lastSelected [lindex $all [expr $allPosition + 1]]
1020        $self selection set $lastSelected
1021        return $lastSelected
1022      }
1023    }   
1024  }
1025
1026
1027  #///////////////////////////////////////////////////////////////////////////
1028  method previous {} {
1029  #
1030  # PURPOSE: selects the row previous to the present selection
1031  #
1032  # RETURN: The index of the row previous
1033  #
1034  #///////////////////////////////////////////////////////////////////////////
1035    set all [$self get]
1036    set selected [$self selection get]
1037    if {$selected == ""} {
1038      return -1
1039    } else  {
1040      foreach item $selected {
1041        $self selection clear $item
1042      }
1043      set firstSelected [lindex $selected 0]
1044      set first [lindex $all 0]
1045      if { $first == $firstSelected } {
1046        $self selection set $firstSelected
1047        return [lindex $all 0]
1048      } else  {
1049        set allPosition [lsearch -exact $all $firstSelected]
1050        set firstSelected [lindex $all [expr $allPosition - 1]]
1051        $self selection set $firstSelected
1052        return $firstSelected
1053      }
1054    }
1055  }
1056   
1057
1058  #///////////////////////////////////////////////////////////////////////////
1059  method next {} {
1060  #
1061  # PURPOSE: selects the following row to the present selection
1062  #
1063  # RETURN: The index of the following row
1064  #
1065  #///////////////////////////////////////////////////////////////////////////
1066    set all [$self get]
1067    set selected [$self selection get]
1068    if {$selected == ""} {
1069      return -1
1070    } else  {
1071      foreach item $selected {
1072        $self selection clear $item
1073      }
1074      set lastSelected [lindex $selected [expr [llength $selected] - 1] ]
1075      set last [lindex $all [expr [llength $all] - 1]]
1076      if { $last == $lastSelected } {
1077        $self selection set $lastSelected
1078        return [lindex $all [expr [llength $all] - 1]]
1079      } else  {
1080        set allPosition [lsearch -exact $all $lastSelected]
1081        set lastSelected [lindex $all [expr $allPosition + 1]]
1082        $self selection set $lastSelected
1083        return $lastSelected
1084      }
1085    }
1086  }
1087   
1088
1089  #///////////////////////////////////////////////////////////////////////////
1090  method addAllPrevious {} {
1091  #
1092  # PURPOSE: Selects all the previous rows
1093  #
1094  # RETURN: The index of the first row
1095  #
1096  #///////////////////////////////////////////////////////////////////////////
1097    set all [$self get]
1098    set selected [$self selection get]
1099    if {$selected == ""} {
1100      return -1
1101    } else  {
1102      set firstSelected [lindex $selected 0]
1103      set first [lindex $all 0]
1104      set allPosition [lsearch -exact $all $firstSelected]
1105      while { $allPosition != 0 } {
1106        $self addPrevious
1107        #$self selection set $firstSelected
1108        set selected [$self selection get]
1109        set allPosition [lsearch -exact $all $firstSelected]
1110        if { $allPosition != 0 } {
1111          set firstSelected [lindex $all [expr $allPosition - 1]]
1112        }
1113      } 
1114      return [lindex $firstSelected]
1115    }
1116  }
1117   
1118
1119  #///////////////////////////////////////////////////////////////////////////
1120  method addAllNext {} {
1121  #
1122  # PURPOSE: Selects all the following rows
1123  #
1124  # RETURN: The index of the last row
1125  #
1126  #///////////////////////////////////////////////////////////////////////////
1127    set all [$self get]
1128    set selected [$self selection get]
1129    if {$selected == ""} {
1130      return -1
1131    } else  {
1132      set lastSelected [lindex $selected [expr [llength $selected] - 1] ]
1133      set last [lindex $all [expr [llength $all] - 1]] 
1134      set allPosition [lsearch -exact $all $lastSelected]
1135      while {$allPosition != [expr [llength $all] -1]} {
1136        $self addNext
1137        set selected [$self selection get]
1138        set lastSelected [lindex $selected [expr [llength $selected] - 1] ]
1139        set allPosition [lsearch -exact $all $lastSelected]
1140      }
1141      return $lastSelected
1142    }
1143  }
1144   
1145
1146  #///////////////////////////////////////////////////////////////////////////
1147  method clear {} {
1148  #
1149  # PURPOSE: deletes all nodes
1150  #
1151  #///////////////////////////////////////////////////////////////////////////
1152    foreach i [$self get] {
1153      if { 0 eq $i } { continue }
1154      $self delete $i
1155    }
1156  }
1157
1158
1159  #///////////////////////////////////////////////////////////////////////////
1160  method size {} {
1161  #
1162  # PURPOSE: calculates the listbox size
1163  #
1164  #///////////////////////////////////////////////////////////////////////////
1165    return [$_listbox entry size root]
1166  }
1167
1168
1169  #///////////////////////////////////////////////////////////////////////////
1170  method column { args } {
1171  #
1172  # PURPOSE: modifies a particular case of column -> column names
1173  #
1174  #///////////////////////////////////////////////////////////////////////////
1175    if { [lindex $args 0] eq "names" } {
1176      return [lrange [$_listbox column names] 1 end]
1177    }
1178    return [eval $_listbox column $args]
1179  }
1180 
1181
1182  #///////////////////////////////////////////////////////////////////////////
1183  method filter { filters } {
1184  #
1185  # PURPOSE: filters the listbox elements matching filters for each col in cols
1186  #
1187  # PARAMETERS:
1188  #  filters: list of filters for the columns above
1189  #
1190  #///////////////////////////////////////////////////////////////////////////
1191    $self configure -flat no
1192    foreach inx [$self get] {
1193      set datos [$self get $inx $options(-filtercols)]
1194      set match 1
1195      for { set i 0 } { $i < [llength $filters] } { incr i } {
1196        set match [expr $match & [regexp [lindex $filters $i] [lindex $datos $i]]]
1197      }
1198      if { ! $match } {
1199        $_listbox hide $inx
1200      } else {
1201        $_listbox show $inx
1202      }
1203    }
1204    $self configure -flat yes
1205
1206  }
1207
1208  #///////////////////////////////////////////////////////////////////////////
1209  method _RemoveFilter { } {
1210  #
1211  # PURPOSE: filters the listbox elements matching filters for each col in cols
1212  #
1213  # PARAMETERS:
1214  #  filters: list of filters for the columns above
1215  #
1216  #///////////////////////////////////////////////////////////////////////////
1217    $_listbox configure -flat no
1218    $_listbox show all
1219    $_listbox configure -flat yes
1220  }
1221
1222  #///////////////////////////////////////////////////////////////////////////
1223  method icon { id icon } {
1224  #
1225  # PURPOSE: changes the icon for an entry identified by id
1226  #
1227  # PARAMETERS:
1228  #  id: the identificator of the entry
1229  #  icon: the icon image (must be 16x16
1230  #
1231  #///////////////////////////////////////////////////////////////////////////
1232    $_listbox entry configure $id \
1233      -icons [list [Bitmap::get $icon] [Bitmap::get $icon]]
1234  }
1235       
1236  # delegacion de metodos y opciones
1237  delegate method * to _listbox
1238  delegate option * to _listbox
1239}
1240
1241package provide blistboxplus 1.0
1242
1243# ------- TEST CODE ----
1244
1245#/////////////////////////////////////////////////////////////////////////////
1246proc test_blistboxplus {} {
1247#
1248# PURPOSE: Funcion de test de un blistcontrol
1249#
1250#///////////////////////////////////////////////////////////////////////////// 
1251  # defining the widgets
1252  variable data
1253  set data(-selected) 1
1254 
1255  destroy .top
1256  toplevel .top -width 200 -height 100
1257   
1258  TitleFrame .top.f1 -text "BListBoxPlus test"
1259  set f1 [ .top.f1 getframe ]
1260  blistboxplus $f1.blb -cols { col1 col2 col3 col4 } -parent $f1 \
1261                    -height 150 -width 500 -orientation vertical \
1262                    -hiddencols {col4}
1263  $f1.blb insert end {1 2 3 4} {one two three four} {uno dos tres cuatro} \
1264                     {k kk kkk kkkk} {0 0 0 0} {@ # $ %}
1265 
1266  TitleFrame .top.f2 -text "Configure"
1267  set f2 [ .top.f2 getframe ]
1268  LabelEntry $f2.lei -width 5 -label Index -text 1
1269  LabelEntry $f2.lee -width 5 -label End
1270  LabelEntry $f2.lec -width 50 -label Content -text "{hay que introducir cada} \
1271     {fila entre corchetes y} {entre estos los items}"
1272  checkbutton $f2.cb -text "Allow multiple selection" \
1273    -command { toggleSelectModeCmd }
1274  $f2.cb select
1275  button $f2.bi -text "Insert" -command { insertCmd }
1276  button $f2.bd -text "Delete" -command { deleteCmd }
1277  button $f2.br -text "Reset" -command { resetCmd }
1278  $f2.bi configure -width 20
1279  $f2.bd configure -width 20
1280  # packing all
1281 
1282  grid .top.f1 -row 0 -column 0 -sticky "new" -padx 10 -pady 10
1283  grid .top.f2 -row 1 -column 0 -sticky "new" -padx 10 -pady 10
1284  grid columnconfigure .top 0 -weight 1
1285  grid rowconfigure .top 0 -weight 0
1286  grid rowconfigure .top 1 -weight 1
1287 
1288  grid $f1.blb -row 0 -column 0 -sticky "new"
1289  grid columnconfigure $f1 0 -weight 1
1290  grid rowconfigure $f1 0 -weight 1
1291
1292  grid $f2.lec -row 0 -column 0 -sticky "new" -columnspan 3
1293  grid $f2.lei -row 1 -column 0 -sticky "new"
1294  grid $f2.lee -row 1 -column 1 -sticky "new"
1295   
1296  grid $f2.cb  -row 1 -column 2 -sticky "new"
1297  grid $f2.bi  -row 2 -column 0 -sticky "new"
1298  grid $f2.bd  -row 2 -column 1 -sticky "new"
1299  grid $f2.br  -row 2 -column 2 -sticky "new"
1300  grid columnconfigure $f2 0 -weight 0
1301  grid columnconfigure $f2 1 -weight 0
1302  grid columnconfigure $f2 2 -weight 1
1303  grid rowconfigure $f2 0 -weight 0
1304  grid rowconfigure $f2 1 -weight 0
1305  grid rowconfigure $f2 2 -weight 0
1306
1307  puts "WIDGET blistboxplus: $f1.blb"
1308 
1309  # commands attached to the widgets
1310  proc insertCmd {} {
1311    eval .top.f1.f.blb insert [.top.f2.f.lei cget -text] \
1312                              [.top.f2.f.lec cget -text]
1313  }
1314 
1315  proc deleteCmd {} {
1316    .top.f1.f.blb delete [.top.f2.f.lei cget -text] \
1317                         [.top.f2.f.lee cget -text]
1318  }
1319 
1320  proc resetCmd {} {
1321    .top.f1.f.blb clear
1322    .top.f1.f.blb insert end {1 2 3 4} {one two three four} \
1323          {uno dos tres cuatro} {k kk kkk kkkk} {0 0 0 0} {@ # $ %}
1324  }
1325 
1326  proc toggleSelectModeCmd {} {
1327    if { [.top.f1.f.blb cget -selectmode] eq "multiple" } {
1328          .top.f1.f.blb configure -selectmode single
1329    } else {
1330          .top.f1.f.blb configure -selectmode multiple
1331    }
1332  }
1333}
1334
Note: See TracBrowser for help on using the repository browser.