--- /dev/null
+
+-------------------------------------------------------------------------------------------------------------
+ FAQs et Limitations d'EFICAS
+-------------------------------------------------------------------------------------------------------------
+
+
+1. Mots réservés :
+
+ Tous les mots du langage Python sont des mots réservés.
+ On ne peut donc pas appeler une variable ou un concept 'fin' ou 'dir'
+ Pour la liste complète de ces mots-clés, veuillez vous référer à la
+ documentation Python
+
+2. Concepts réentrants :
+
+ Ne pas indiquer par un '&' devant son nom qu'un concept est utilisé comme
+ concept réentrant. En effet EFICAS le sait !
+
+3. Carte commentaire :
+
+ La carte commentaire est désormais le '#' (dièse) au lieu du '%' (pourcent)
+ Les commentaires sont gérés comme des objets de même niveau que les
+ commandes ; il n'est plus possible de placer des commentaires "dans"
+ une commande. Attention, lors de la traduction d'un fichier de version 5
+ en 6, les commentaires "dans" les commandes seront perdus.
+
+4. Nommer le concept produit par un opérateur :
+
+ Vous ne pouvez nommer le concept produit d'un opérateur que lorsque
+ celui-ci aura été entièrement et correctement rempli.
+
+5. Règle de rémanence dans les mots-clés facteurs répétés :
+
+ La règle de rémanence qui permettait pour certains mots-clés facteurs
+ et pour certains de leurs mots-clés simples de ne pas répeter la valeur
+ de ces derniers dans toutes les occurrences du mot-clé facteur n'est pas
+ connue d'EFICAS.
+ En conséquence, vous devez répéter les mots-clés simples concernés dans
+ toutes les occurrences des mots-clés facteurs.
+
+6. Besoin d'aide ?
+
+ La documentation d'utilisation d'EFICAS a pris un peu de retard sur le produit ...
+ Néanmoins, vous disposez sur la plupart des panneaux contextuels ( les panneaux à
+ droite de l'arbre) d'une aide en ligne que vous pouvez activer en maintenant le
+ bouton droit de votre souris enfoncé.
--- /dev/null
+Les macros INCLUDE, INCLUDE_MATERIAU et POURSUITE ont un fonctionnement spécial.
+Les concepts produits par ces macros sont obtenus par interpretation d'un fichier
+de commandes. Il n'est pas possible d'avoir une mise à jour complètement
+automatique d'un jeu de commandes qui contient une de ces macros.
+
+Les principes retenus sont les suivants :
+
+1- Un fichier invalide n'est pas du tout pris en compte meme si quelques
+commandes de ce fichier sont valides
+
+2- Il est possible de visualiser (bouton droit de la souris sur l'icone de
+la macro -> menu View) le contenu de ces types de macros. Cette visualisation
+n'est pas mise à jour en cas de reactualisation de cette macro. Le bouton (icone
+loupe) permet de visualiser le source du fichier inclus.
+
+3- Il est possible de reactualiser la validite du jeu de commandes en demandant
+un rapport de validation. Ceci declenche une reevaluation systematique des
+fichiers inclus. Les fichiers inclus sont mémorisés en fonction de leur UNITE
+pour les INCLUDE, du nom de matériau pour les INCLUDE_MATERIAU et comme poursuite
+pour une POURSUITE (il n'est pas possible d'avoir plus d'une POURSUITE par fichier).
+ATTENTION : comme on s'appuie sur l'UNITE pour memoriser les fichers inclus il est
+conseillé d'utiliser des numéros d'UNITE différents sinon la reactualisation sera
+faite avec le meme fichier pour des INCLUDE différents.
+
+4- Pour changer les fichiers inclus, il faut passer par l'onglet FICHIER, modifier
+le nom du fichier et appuyer sur le bouton Valider. Tous les fichiers inclus par
+ce premier fichier seront systématiquement redemandés à l'utilisateur.
+
+5- Le nom d'un fichier INCLUDE_MATERIAU est construit à partir des valeurs des mots-clés
+de la commande, il n'est donc jamais demandé explicitement à l'utilisateur.
+
--- /dev/null
+import os
+import Tkinter
+import ScrolledText
+import formatter
+import htmllib
+
+class TkWriter(formatter.DumbWriter):
+ def __init__(self, text,viewer):
+ formatter.DumbWriter.__init__(self, self)
+ self.text=text
+ self.viewer=viewer
+
+ def write(self,data):
+ self.text.insert("insert", data)
+
+ def anchor_bgn(self, href, name, type):
+ if href:
+ self.anchor = (href, name, type)
+ self.anchor_mark = self.text.index("insert")
+
+ def anchor_end(self):
+ if self.anchor:
+ url = self.anchor[0]
+ tag = "href_" + url
+ self.text.tag_add(tag, self.anchor_mark, "insert")
+ def displayurl(event,v=self.viewer,u=url):
+ v.display(u)
+ self.text.tag_bind(tag, "<ButtonPress>", displayurl)
+ self.text.tag_config(tag, foreground="blue", underline=1)
+ self.anchor = None
+
+class HTMLParser(htmllib.HTMLParser):
+ def anchor_bgn(self, href, name, type):
+ htmllib.HTMLParser.anchor_bgn(self, href, name, type)
+ # On signale directement au writer le debut d'une reference
+ self.formatter.writer.anchor_bgn(href, name, type)
+
+ def anchor_end(self):
+ if self.anchor:
+ self.formatter.writer.anchor_end()
+ self.anchor = None
+
+import string
+
+class DumbParser:
+ def __init__(self,fmt):
+ self.formatter=fmt
+
+ def feed(self,data):
+ self.formatter.writer.write(data)
+
+ def close(self):
+ pass
+
+class Historique:
+ def __init__(self):
+ self.liste=[]
+ self.index=0
+
+ def add(self,url):
+ if self.index > 0:
+ old=self.liste[self.index-1]
+ if url == old :return
+ del self.liste[self.index:]
+ self.liste.append(url)
+ self.index=self.index+1
+
+ def getback(self):
+ if self.index > 1:
+ self.index=self.index-1
+ return self.liste[self.index-1]
+ else:
+ return None
+
+ def getforward(self):
+ if self.index < len(self.liste):
+ url=self.liste[self.index]
+ self.index=self.index+1
+ return url
+ else:
+ return None
+
+class HTMLViewer:
+ def __init__(self,parent):
+ self.init_window(parent)
+ self.url=None
+ self.home=None
+ self.historique=Historique()
+ self.createWidgets()
+ self.init()
+
+ def init_window(self,parent):
+ self.parent=parent
+ self.fenetre=Tkinter.Toplevel()
+ self.fenetre.title("AIDE EFICAS")
+ if self.fenetre.winfo_screenwidth() < 800 or self.fenetre.winfo_screenheight() < 600:
+ self.fenetre.wm_minsize(300, 150)
+ else:
+ self.fenetre.wm_minsize(400, 200)
+ self.fenetre.protocol("WM_DELETE_WINDOW",self.destroy)
+
+ def createWidgets(self):
+ frame = self.frame = Tkinter.Frame(self.fenetre)
+ frame.pack(side="bottom", fill="x")
+ self.homeButton = Tkinter.Button(frame, text="Index",font="Helvetica 12 bold",
+ command=self.goHome)
+ self.homeButton.pack(side="left")
+ self.b_retour = Tkinter.Button(frame, text="Back",font="Helvetica 12 bold",
+ command=self.goBack)
+ self.b_retour.pack(side="left")
+ self.b_avance = Tkinter.Button(frame, text="Forward",font="Helvetica 12 bold",
+ command=self.goForward)
+ self.b_avance.pack(side="left")
+
+ self.b_close = Tkinter.Button(frame, text="Close",font="Helvetica 12 bold",
+ command=self.destroy)
+ self.b_close.pack(side="right")
+ self.config_boutons()
+
+ self.text=ScrolledText.ScrolledText(self.fenetre,bg='white',relief='sunken',font="Helvetica 12 bold")
+ self.text.pack(side="top", fill="both", expand=1)
+ self.text.bind("<Key-Prior>", self.page_up)
+ self.text.bind("<Key-Next>", self.page_down)
+ self.text.bind("<Key-Up>", self.unit_up)
+ self.text.bind("<Key-Down>", self.unit_down)
+ self.text.bind("<1>", self.clicked)
+
+ def clicked(self,event):
+ self.text.focus_set()
+
+ def page_up(self,event):
+ event.widget.yview_scroll(-1, "page")
+ def page_down(self,event):
+ event.widget.yview_scroll(1, "page")
+ def unit_up(self,event):
+ event.widget.yview_scroll(-1, "unit")
+ def unit_down(self,event):
+ event.widget.yview_scroll(1, "unit")
+
+ def config_boutons(self):
+ """
+ Activation du bouton précédent s'il y a lieu
+ """
+ if self.historique.index > 1 :
+ self.b_retour.config(state='normal')
+ else :
+ self.b_retour.config(state='disabled')
+ if self.historique.index < len(self.historique.liste) :
+ self.b_avance.config(state='normal')
+ else :
+ self.b_avance.config(state='disabled')
+
+ def openurl(self,url):
+ url=os.path.normpath(url)
+ if self.url and not os.path.isabs(url):
+ rep1,fich1=os.path.split(self.url)
+ rep2,fich2=os.path.split(url)
+ if rep1 != rep2 :
+ url=os.path.join(rep1,rep2,fich2)
+ url=os.path.normpath(url)
+ try:
+ f=open(url,'r')
+ data=f.read()
+ f.close()
+ except:
+ data="Impossible de trouver: "+url
+ self.url=url
+ if self.home is None:
+ self.home=self.url
+ return data
+
+ def display(self,url):
+ data=self.openurl(url)
+ ext=os.path.splitext(url)[1]
+ self.text.config(state="normal")
+ self.text.delete("1.0", "end")
+ writer=TkWriter(self.text,self)
+ fmt=formatter.AbstractFormatter(writer)
+ if ext == ".html":
+ parser=HTMLParser(fmt)
+ else:
+ parser=DumbParser(fmt)
+ parser.feed(data)
+ parser.close()
+ self.text.config(state="disabled")
+ self.historique.add(url)
+ self.config_boutons()
+
+ def init(self):
+ self.fenetre.bind("<KeyPress-BackSpace>", self.goBack)
+
+ def goHome(self,event=None):
+ if self.home and self.home != self.url:
+ self.display(self.home)
+
+ def goBack(self,event=None):
+ url=self.historique.getback()
+ if url:self.display(url)
+
+ def goForward(self,event=None):
+ url=self.historique.getforward()
+ if url:self.display(url)
+
+ def destroy(self):
+ try:
+ self.fenetre.destroy()
+ except:
+ pass
+
+if __name__ == "__main__":
+ v=HTMLViewer(None)
+ v.display("fichiers/index.html")
+ v.fenetre.mainloop()
+