source: tol/tolbase/lib/toltk/MenuManager.tcl @ 15ee97c

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

#refs 963, se sube una funcion ::MenuManager::addObservers para intersectar los eventos Before y After asociados a la invocacion de una opcion de menu

proc onDeleteVariable { when } {
  puts "estoy $when"
  return 1
}
::MenuManager::addObservers "MMS.Delete_Variable" "Before" onDeleteVariable
::MenuManager::addObservers "MMS.Delete_Variable" "after" onDeleteVariable

El script debe retornar como resultado 0 ó 1

El valor $when (Before o After) se concatena al script antes de ejecutarlo.

Si alguno de los observadores del "Before" retorna 0 la opcion de menu
no se invoca.

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

  • Property mode set to 100644
File size: 11.6 KB
Line 
1namespace eval ::MenuManager {
2  variable observers
3}
4
5proc ::MenuManager::addObserver { event when script } {
6  variable observers
7
8  if { $when ne "Before" || $when ne "After" } {
9    error "::MenuManager::addObserver -- valor invalido '$when' para el argumento when, debe ser Before o After"
10  }
11  lappend observers($event,$when) $script
12}
13
14proc ::MenuManager::invokeObservers { event when } {
15  variable observers
16
17  if { [ info exists observers($event,$when) ] } {
18    foreach script $observers($event,$when) {
19      set result [ eval uplevel \#0 $script $when ]
20      if { !$result } {
21        return 0
22      }
23    }
24  }
25  return 1
26}
27
28proc ::MenuManager::getTypeOfObject { addr } {
29  set rvar "__getTypeOfObject__"
30  set tolExpr [ string map [ list %A $addr %RV $rvar ] {
31    Text %RV = {
32      Anything obj = GetObjectFromAddress( "%A" );
33      Text theGrammar = Grammar( obj );
34      Text theType = If( theGrammar == "NameBlock", {
35        Text theClass = ClassOf( obj );
36        If( theClass == "", "NameBlock", theClass )
37      }, theGrammar ) 
38    }
39  } ]
40  tol::console eval $tolExpr
41  set info [ tol::info variable [ list Text $rvar ] ]
42  set value [ string trim [ lindex $info 2 ] \" ]
43  tol::console stack release $rvar
44  return $value
45}
46
47proc ::MenuManager::getLabelInfoForType { type } {
48  set rvar "__getLabelForType__"
49  set tolExpr [ string map [ list %RV $rvar %T $type ] {
50    Set %RV = {
51      Set aux = GuiTools::MenuManager::getTypeLabelInfo( "%T" );
52      Set If( Card( aux ),
53              aux, GuiTools::MenuManager::getDefaultTypeLabelInfo( "%T" ) )
54    }
55  } ]
56  tol::console eval $tolExpr
57  set value [ TolObj2TclObj [ list Set $rvar ] ]
58  tol::console stack release $rvar
59  return $value
60}
61
62proc ::MenuManager::getLabelInfoForEntry { entryName } {
63  set rvar "__getLabelInfoForEntry__"
64  set tolExpr [ string map [ list %RV $rvar %N $entryName ] {
65    Set %RV = {
66      Set aux = GuiTools::MenuManager::getEntryInfo( "%N" );
67      Set If( Card( aux ),
68              aux, GuiTools::MenuManager::getDefaultEntryInfo( "%N" ) )
69    }
70  } ]
71  tol::console eval $tolExpr
72  set value [ TolObj2TclObj [ list Set $rvar ] ]
73  tol::console stack release $rvar
74  return $value
75}
76
77proc ::MenuManager::getMenuOptionsForType { type } {
78  set rvar "__getMenuOptionsForType__"
79  set tolExpr [ string map [ list %RV $rvar %T $type ] {
80    Set %RV = GuiTools::MenuManager::getTypeOptionsInfo( "%T" );
81  } ]
82  tol::console eval $tolExpr
83  set value [ TolObj2TclObj [ list Set $rvar ] ]
84  tol::console stack release $rvar
85  return $value
86}
87
88proc ::MenuManager::checkEntryState { name objSelection group } {
89  variable typesSelected
90
91  set SOA [ TclList2SetOfText $objSelection ]
92  set rvar "__checkEntryState__"
93  set tolExpr [ string map [ list %RV $rvar %N $name %S $SOA %G $group ] {
94    Real %RV = {
95      Set objAddress = %S;
96      Anything target = If( %G, {
97        EvalSet( objAddress, Anything( Text addr ) {
98          GetObjectFromAddress( addr )
99        } )
100      }, GetObjectFromAddress( objAddress[ 1 ] ) );
101      Real GuiTools::MenuManager::checkStateEntry( "%N", target )
102    }
103  } ]
104  tol::console eval $tolExpr
105  set info [ tol::info variable [ list Real $rvar ] ]
106  set value [ lindex $info 2 ]
107  tol::console stack release $rvar
108  return $value
109}
110
111proc ::MenuManager::invokeCommand { name objSelection group } {
112  variable typesSelected
113
114  if { ![ invokeObservers $name "Before" ] } {
115    return 0
116  }
117  set SOA [ TclList2SetOfText $objSelection ]
118  set rvar "__invokeCommand__"
119  set tolExpr [ string map [ list %RV $rvar %N $name %S $SOA %G $group ] {
120    Real %RV = {
121      Set objAddress = %S;
122      Real GuiTools::MenuManager::invokeEntry( "%N", If( %G, {
123        EvalSet( objAddress, Anything( Text addr ) {
124          GetObjectFromAddress( addr )
125        } )
126      }, GetObjectFromAddress( objAddress[ 1 ] ) ) )
127    }
128  } ]
129  tol::console eval $tolExpr
130  set info [ tol::info variable [ list Real $rvar ] ]
131  set value [ lindex $info 2 ]
132  tol::console stack release $rvar
133  invokeObservers $name "After"
134  return $value
135}
136
137proc ::MenuManager::checkIfMenuManagerIsLoaded { } {
138  set rvar "__checkIfMenuManagerIsLoaded__"
139  set tolExpr [ string map [ list %RV $rvar  ] {
140    Real %RV = ObjectExist( "NameBlock", "GuiTools::MenuManager" )
141  } ]
142  tol::console eval $tolExpr
143  set info [ tol::info variable [ list Real $rvar ] ]
144  set value [ lindex $info 2 ]
145  tol::console stack release $rvar
146  return [ expr { $value!=0 } ]
147}
148
149proc ::MenuManager::initTypesInfoFromSelection { selection } {
150  variable typesSelected
151
152  array unset typesSelected
153  array set typesSelected {
154    types {}
155  }
156  if { ![ checkIfMenuManagerIsLoaded ] } return
157  foreach addr $selection {
158    set type [ getTypeOfObject $addr ]
159    set typeOptionInfo [ getMenuOptionsForType $type ]
160    # registro el tipo solo si tiene informacion de menu asociada
161    if { [ llength $typeOptionInfo ] } {
162      if { ![ info exists typesSelected(objects,$type) ] } {
163        lappend typesSelected(types) $type
164        set typesSelected(labelInfo,$type) [ getLabelInfoForType $type ]
165        set typesSelected(entriesInfo,$type) $typeOptionInfo
166        foreach option $typeOptionInfo {
167          set name [ lindex $option 0 ]
168          set typesSelected(optionInfo,$name) $option
169          if { [ catch { lsearch $typesSelected(types,$name) $type } idx ] } {
170            set typesSelected(types,$name) [ list $type ]
171          } elseif { $idx == -1 } {
172            lappend typesSelected(types,$name) $type
173          }
174        }
175      }
176      lappend typesSelected(objects) $addr
177      lappend typesSelected(objects,$type) $addr
178    }
179  }
180  # busco las opciones que se aplican a toda la seleccion
181  set numberOfTypes [ llength $typesSelected(types) ]
182  set typesSelected(globalOptions) [ list ]
183  foreach optionIndex [ array names typesSelected types,* ] {
184    set optionName [ string range $optionIndex 6 end ]
185    if { [ llength $typesSelected(types,$optionName) ] == $numberOfTypes } {
186      lappend typesSelected(globalOptions) $typesSelected(optionInfo,$optionName)
187    }
188  }
189  return $typesSelected(types)
190}
191
192proc ::MenuManager::createSubMenuIfNeeded { targetMenu name } {
193  variable typesSelected
194
195  set path0 [ split $name "/" ]
196  set mm $targetMenu
197  set nn ""
198  set mapdot [ list . - ]
199  foreach n [ lrange $path0 0 end-1 ] {
200    #puts "n = $n"
201    # evito el caracter . en el nombre de widget
202    set n0 [ string map $mapdot $n ]
203    set mm0 ${mm}.mm$n0
204    #puts "mm0 = $mm0"
205    if { ![ info exists typesSelected(subMenu,inserted,$mm0) ] } {
206      if { [ winfo exists $mm0 ] } {
207        #puts "$mm0 existe"
208        $mm0 delete 0 end
209      } else {
210        menu $mm0 -tearoff 0
211      }
212      set nn [ expr { $nn eq "" ? $n : "${nn}/${n}" } ]
213      set labelInfo [ getLabelInfoForEntry $nn ]
214      foreach { name label image translate } $labelInfo break
215      set image0 [ ::ImageManager::getImageResourceId $image ]
216      if { $image0 ne "" } {
217        set image $image0
218      }
219      #puts "insertando menu $mm0 en $mm"
220      $mm add cascade -menu $mm0 \
221          -label [ expr { $translate ? [ msgcat::mc $label ] : $label } ] \
222          -image $image -compound [ expr { $image eq "" ? "none" : "left" } ]
223      set typesSelected(subMenu,inserted,$mm0) 1
224    }
225    set mm $mm0
226  }
227  #puts "retornando con mm  = $mm"
228  return $mm
229}
230
231proc ::MenuManager::compareMenuEntries { entry1 entry2 } {
232  # cache del rank de las entries, se pide a TOL solo una vez por
233  # ordenamiento
234  variable entriesRank
235
236  set name1 [ lindex $entry1 0 ]
237  set name2 [ lindex $entry2 0 ]
238  set path1 [ lrange [ split $name1 "/" ] 0 end-1 ]
239  set path2 [ lrange [ split $name2 "/" ] 0 end-1 ]
240  set submenu1 ""
241  set submenu2 ""
242  foreach subm1 $path1 subm2 $path2 {
243    if { $subm1 eq "" } {
244      # path1 es mas corto que path2, la parte comun es igual, asumo
245      # que es <
246      return -1
247    }
248    if { $subm2 eq "" } {
249      # path2 es mas corto que path2, la parte comun es igual, asumo
250      # que es >
251      return 1
252    }
253    append submenu1 [ expr { $submenu1 eq "" ? "" : "/" } ] $subm1
254    append submenu2 [ expr { $submenu2 eq "" ? "" : "/" } ] $subm2
255    if { ![ info exist entriesRank($submenu1) ] } {
256      set submenuInfo [ getLabelInfoForEntry $submenu1 ]
257      set entriesRank($submenu1,rank) [ lindex $submenuInfo 4 ]
258    }
259    if { ![ info exist entriesRank($submenu2) ] } {
260      set submenuInfo [ getLabelInfoForEntry $submenu2 ]
261      set entriesRank($submenu2,rank) [ lindex $submenuInfo 4 ]
262    }
263    set cmp \
264        [ expr { $entriesRank($submenu1,rank) - $entriesRank($submenu2,rank) } ]
265    if { $cmp != 0 } {
266      return $cmp
267    }
268  }
269  # hasta este punto los caminos son iguales hay que usar el rank de la entry
270  return [ expr { [ lindex $entry1 4 ] - [ lindex $entry2 4 ] } ]
271}
272
273proc ::MenuManager::insertEntries { menuWidget objSelection entriesInfo } {
274  variable entriesRank
275
276  set multiple [ expr { [ llength $objSelection ] > 1 } ]
277  # inserto las entries segun el orden inducido por el campo rank
278  if { [ llength [ lindex $entriesInfo 0 ] ] > 4 } {
279    # rank aparecio en la version 2.2 de GuiTools
280    array unset entriesRank
281
282    #set sortedEntriesInfo [ lsort -real -index 4 $entriesInfo ]
283    set sortedEntriesInfo [ lsort \
284                                -command ::MenuManager::compareMenuEntries \
285                                $entriesInfo ]
286  } else {
287    # se asume rank 0 para todos, el orden no cambia
288    set sortedEntriesInfo $entriesInfo
289  }
290  foreach entryInfo $sortedEntriesInfo {
291    foreach {name label image translate rank group} $entryInfo break
292    if { $group eq "" } {
293      # rank aparecio en la version 2.2 de GuiTools
294      set group $rank
295    }
296    if { $group ^ $multiple } continue
297    set mm [ createSubMenuIfNeeded $menuWidget $name ]
298    set state [ checkEntryState $name $objSelection $group ]
299    set entryLabel [ expr { $translate ? [ msgcat::mc $label ] : $label } ]
300    set image0 [ ::ImageManager::getImageResourceId $image ]
301    if { $image0 ne "" } {
302      set image $image0
303    }
304    $mm add command -label $entryLabel \
305        -command [ list ::MenuManager::invokeCommand $name $objSelection $group ] \
306        -state [ expr { $state ? "normal" : "disabled" } ] \
307        -image $image -compound [ expr { $image eq "" ? "none" : "left" } ]
308  }
309}
310
311proc ::MenuManager::insertEntriesForSelection { menuWidget selection } {
312  variable typesSelected
313
314  if { ![ llength [ initTypesInfoFromSelection $selection ] ] } return
315  set lenghtValidSelection [ llength $typesSelected(objects) ]
316  set lengthSelection [ llength $selection ]
317  if { $lengthSelection == $lenghtValidSelection } {
318    insertEntries $menuWidget \
319        $typesSelected(objects) $typesSelected(globalOptions)
320  }
321  # inserto las opciones especificas de cada tipo si es que hay mas de
322  # un tipo
323  if { ( $lengthSelection != $lenghtValidSelection ) ||
324       [ llength $typesSelected(types) ] > 1 } {
325    set mapdot [ list . - ]
326    foreach type $typesSelected(types) {
327      # type puede contener . por eso hay que reemplazarlo
328      set type0 [ string map $mapdot $type ]
329      set menuType $menuWidget.mtype$type0
330      if { ![ winfo exists $menuType ] } {
331        menu $menuType -tearoff 0
332      } else {
333        $menuType delete 0 end
334      }
335      foreach {label image translate} $typesSelected(labelInfo,$type) break 
336      set labelCascade [ expr { $translate ? [ msgcat::mc $label ] : $label } ]
337      set image0 [ ::ImageManager::getImageResourceId $image ]
338      if { $image0 ne "" } {
339        set image $image0
340      }
341      $menuWidget add cascade -label $labelCascade -menu $menuType \
342          -image $image -compound [ expr { $image eq "" ? "none" : "left" } ]
343      insertEntries $menuType \
344          $typesSelected(objects,$type) $typesSelected(entriesInfo,$type)
345    }
346  }
347}
Note: See TracBrowser for help on using the repository browser.