Salome HOME
pour elts de structure
[tools/eficas.git] / Editeur / jdcdisplay.py
1 # -*- coding: utf-8 -*-
2 #            CONFIGURATION MANAGEMENT OF EDF VERSION
3 # ======================================================================
4 # COPYRIGHT (C) 1991 - 2002  EDF R&D                  WWW.CODE-ASTER.ORG
5 # THIS PROGRAM IS FREE SOFTWARE; YOU CAN REDISTRIBUTE IT AND/OR MODIFY
6 # IT UNDER THE TERMS OF THE GNU GENERAL PUBLIC LICENSE AS PUBLISHED BY
7 # THE FREE SOFTWARE FOUNDATION; EITHER VERSION 2 OF THE LICENSE, OR
8 # (AT YOUR OPTION) ANY LATER VERSION.
9 #
10 # THIS PROGRAM IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT
11 # WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF
12 # MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. SEE THE GNU
13 # GENERAL PUBLIC LICENSE FOR MORE DETAILS.
14 #
15 # YOU SHOULD HAVE RECEIVED A COPY OF THE GNU GENERAL PUBLIC LICENSE
16 # ALONG WITH THIS PROGRAM; IF NOT, WRITE TO EDF R&D CODE_ASTER,
17 #    1 AVENUE DU GENERAL DE GAULLE, 92141 CLAMART CEDEX, FRANCE.
18 #
19 #
20 # ======================================================================
21 """
22    Ce module contient la classe JDCDISPLAY qui réalise l'affichage
23    du jeu de commandes sous la forme d'un arbre et de panneaux qui portent
24    les informations attachées au noeud de l'arbre sélectionné
25 """
26 # Modules Python
27 import types
28 import traceback
29 import Tkinter
30 import Pmw
31
32 # Modules Eficas
33 import panels
34 from treeitemincanvas import TREEITEMINCANVAS
35 from widgets import showinfo,showerror
36
37 class CONFIG:
38    isdeveloppeur='NON'
39
40 class JDCDISPLAY:
41    """
42        Cette classe ajoute à la class TREEITEMINCANVAS l'affichage des infos
43        attachées au noeud sélectionné dans un notebook
44        L'objet item associé au jdc est créé par la classe TREEITEMINCANVAS
45    """
46    def __init__(self,jdc,nom_jdc,appli=None,parent=None):
47       self.jdc=jdc
48       self.nom_jdc=nom_jdc
49       self.fichier=None
50       self.panel_courant=None
51
52       if not appli:
53          class Appli:
54             def __init__(self):
55                self.CONFIGURATION=CONFIG()
56             def affiche_infos(self,message):
57                print message
58                return
59
60             def efface_aide(self,event):
61                return
62
63             def affiche_aide(self,event,aide):
64                print aide
65                return
66
67          appli=Appli()
68       self.appli=appli
69
70       if not parent:
71          parent=Tkinter.Tk()
72          Pmw.initialise(parent)
73       self.parent=parent
74       self.node_selected = None
75       self.modified='n'
76
77       self.pane=Pmw.PanedWidget(self.parent,orient='horizontal')
78       self.pane.add('treebrowser',min=0.4,size=0.5)
79       self.pane.add('selected',min=0.4)
80       self.pane.pack(expand=1,fill='both')
81       self.tree=TREEITEMINCANVAS(jdc,nom_jdc,self.pane.pane('treebrowser'),
82                  self.appli,self.select_node,self.make_rmenu)
83
84    def make_rmenu(self,node,event):
85       if hasattr(node.item,'rmenu_specs'):
86          rmenu = Tkinter.Menu(self.pane.pane('treebrowser'), tearoff=0)
87          #node.select()
88          self.cree_menu(rmenu,node.item.rmenu_specs,node)
89          rmenu.tk_popup(event.x_root,event.y_root)
90
91    def cree_menu(self,menu,itemlist,node):
92       """
93             Ajoute les items du tuple itemlist
94             dans le menu menu
95       """
96       number_item=0
97       radio=None
98       for item in itemlist:
99          number_item=number_item + 1
100          if not item :
101             menu.add_separator()
102          else:
103             label,method=item
104             if type(method) == types.TupleType:
105                  # On a un tuple => on cree une cascade
106                  menu_cascade=Tkinter.Menu(menu)
107                  menu.add_cascade(label=label,menu=menu_cascade)
108                  self.cree_menu(menu_cascade,method,node)
109             elif method[0] == '&':
110                  # On a une chaine avec & en tete => on cree un radiobouton
111                  try:
112                     command=getattr(node.item,method[1:])
113                     menu.add_radiobutton(label=label,command=lambda a=self.appli,c=command,n=node:c(a,n))
114                     if radio == None:radio=number_item
115                  except:pass
116             else:
117                  try:
118                     command=getattr(node.item,method)
119                     menu.add_command(label=label,command=lambda a=self.appli,c=command,n=node:c(a,n))
120                  except:pass
121       # Si au moins un radiobouton existe on invoke le premier
122       if radio:menu.invoke(radio)
123
124    def select(self):
125       return
126
127    def unselect(self):
128       return
129
130    def select_node(self,node):
131       """
132           Cette méthode est appelée à chaque fois qu'un noeud est sélectionné
133           dans l'arbre.
134           Elle permet l'affichage du panneau correspondant au noeud sélectionné
135       """
136       if node is not self.node_selected :
137          #ATTENTION: il faut affecter l'attribut node_selected avant d'appeler 
138          # create_panel pour eviter une recursion infinie entre create_panel, 
139          # Emit, onValid, select_node
140          self.node_selected = node
141          self.create_panel(node)
142       elif self.panel_courant:
143          self.panel_courant.update_panel()
144
145    def create_panel(self,node):
146       """
147          Lance la génération du panneau contextuel de l'objet sélectionné 
148          dans l'arbre
149       """
150       if self.panel_courant:
151           # On detruit le panneau
152           self.panel_courant.destroy()
153           o=self.panel_courant
154           self.panel_courant=None
155           # Mettre à 1 pour verifier les cycles entre objets
156           # pour les panneaux
157           withCyclops=0
158           if withCyclops:
159              from Misc import Cyclops
160              z = Cyclops.CycleFinder()
161              z.register(o)
162              del o
163              z.find_cycles()
164              z.show_stats()
165              z.show_cycles()
166
167       if node is None:
168           self.panel_courant=None
169           return self.panel_courant
170
171       if node.item.isactif():
172           if hasattr(node.item,"panel"):
173               self.panel_courant=node.item.panel(self,self.pane.pane('selected'),node)
174           else:
175               raise Exception("Le noeud sélectionné n'a pas de panel associé")
176       else:
177           self.panel_courant = panels.Panel_Inactif(self,self.pane.pane('selected'),node)
178       return self.panel_courant
179
180    def init_modif(self):
181       """
182           Met l'attribut modified à 'o' : utilisé par Eficas pour savoir 
183           si un JDC doit être sauvegardé avant destruction ou non
184       """
185       self.modified = 'o'
186
187    def stop_modif(self):
188       """
189           Met l'attribut modified à 'n' : utilisé par Eficas pour savoir 
190           si un JDC doit être sauvegardé avant destruction ou non
191       """
192       self.modified = 'n'
193
194    def mainloop(self):
195       self.parent.mainloop()
196
197    def ReplaceObjectNode(self,node,new_object,nom_sd=None):
198       """
199       Cette méthode sert à remplacer l'objet pointé par node par
200       new_object.
201       Si nom_sd : on remplace un OPER et on essaie de renommer la
202       nouvelle sd par nom_sd
203       """
204       child = node.append_brother(new_object,retour='oui')
205       if child == 0:
206           self.appli.affiche_infos("Impossible de remplacer l'objet du noeud courant")
207       else:
208           self.init_modif()
209           node.delete()
210           #if nom_sd:
211               #child.item.nomme_sd(nom_sd)
212           child.select()
213           #child.update()
214
215    def doCut(self):
216       """
217       Stocke dans Eficas.noeud_a_editer le noeud à couper
218       """
219       if not self.node_selected.item.iscopiable():
220           showinfo("Copie impossible",
221                    "Cette version d'EFICAS ne permet que la copie d'objets de type 'Commande' ou mot-clé facteur")
222           return
223       self.edit="couper"
224       self.appli.noeud_a_editer = self.node_selected
225
226    def doCopy(self):
227       """
228       Stocke dans Eficas.noeud_a_editer le noeud à copier
229       """
230       if not self.node_selected.item.iscopiable():
231           showinfo("Copie impossible",
232                    "La copie d'un tel objet n'est pas permise")
233           return
234       self.edit="copier"
235       self.appli.noeud_a_editer = self.node_selected
236
237    def doPaste(self):
238       """
239       Lance la copie de l'objet placé dans self.appli.noeud_a_editer
240       Ne permet que la copie d'objets de type Commande ou MCF
241       """
242       try:
243          child=self.appli.noeud_a_editer.doPaste(self.node_selected)
244       except:
245          traceback.print_exc()
246          showinfo("Action de coller impossible",
247                   "L'action de coller apres un tel objet n'est pas permise")
248          return
249
250       if child == 0:
251           if self.appli.message != '':
252              showerror("Copie refusée",self.appli.message)
253              self.appli.message = ''
254           self.appli.affiche_infos("Copie refusée")
255           return
256
257       # il faut déclarer le JDCDisplay_courant modifié
258       self.init_modif()
259       # suppression éventuelle du noeud sélectionné
260       # si possible on renomme l objet comme le noeud couper
261       if self.edit == "couper":
262          #nom = self.appli.noeud_a_editer.item.object.sd.nom
263          item=self.appli.noeud_a_editer.item
264          self.appli.noeud_a_editer.delete()
265          child.item.update(item)
266          #test,mess = child.item.nomme_sd(nom)
267          child.select()
268       # on rend la copie à nouveau possible en libérant le flag edit
269       self.edit="copier"
270
271    def update(self):
272       """Cette methode est utilisee par le JDC associe pour 
273          signaler des modifications globales du JDC
274       """
275       self.tree.update()
276