Back to index

wims  3.65+svn20090927
FormulaTreeStructure.java
Go to the documentation of this file.
00001 /*
00002 $Id: FormulaTreeStructure.java,v 1.4 2003/02/18 11:48:47 sander Exp $
00003 */
00004 
00005 
00006 /*
00007 Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
00008 
00009 This library is free software; you can redistribute it and/or
00010 modify it under the terms of the GNU Lesser General Public
00011 License as published by the Free Software Foundation; either
00012 version 2.1 of the License, or (at your option) any later version.
00013 
00014 This library is distributed in the hope that it will be useful,
00015 but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017 Lesser General Public License for more details.
00018 
00019 You should have received a copy of the GNU Lesser General Public
00020 License along with this library; if not, write to the Free Software
00021 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00022 
00023 For further information on the GNU Lesser General Public License,
00024 see: http://www.gnu.org/copyleft/lesser.html
00025 For further information on this library, contact: mainline@essi.fr
00026 */
00027 
00028 
00029 package fr.ove.openmath.jome.model;
00030 
00031 import java.util.*;
00032 import fr.ove.utils.*;
00033 import fr.ove.openmath.jome.behaviour.*;
00034 import fr.ove.openmath.jome.model.*;
00035 import fr.ove.openmath.jome.model.events.*;
00036 import fr.ove.openmath.jome.ctrlview.events.*;
00037 import fr.ove.openmath.jome.model.evaluation.*;
00038 
00043 public abstract class FormulaTreeStructure extends Node implements ControlListener, Iconifiable, fr.ove.utils.Comparable, Maskable, Modifiable {
00049     private boolean isTemplate = false;
00050     
00054     private int asOperatorPriority;
00055 
00059     private int asOperandPriority;
00060     
00064     private Vector listeners = new Vector();
00065     
00071     private boolean areOperandsMovable = false;
00072     
00076     static FormulaResourcesManager resourcesManager = new FormulaResourcesManager("fr.ove.openmath.jome.model.resources2");
00077     
00081     private String resourceIdentifier;
00082     
00083     // ***********************************
00084     // Gestion des listeners de l'instance
00085     
00090     public void addModelListener(ModelListener modelListener) {
00091         listeners.addElement(modelListener);
00092     }
00093 
00098     public void removeModelListener(ModelListener modelListener) {
00099         listeners.removeElement(modelListener);
00100     }
00101 
00105     public void removeAllModelListener() {
00106         listeners.setSize(0);
00107     }
00108 
00113     public void fireModelEvent(ModelEvent modelEvent) {
00114         for (int i = 0; i < listeners.size(); i++)
00115           ((ModelListener)listeners.elementAt(i)).consumeModelEvent(modelEvent);
00116     }
00117     
00121     public Vector getListeners() {
00122         return listeners;
00123     }
00124 
00125     // **** fin de la gestion des listeners ****
00126     // *****************************************
00127 
00128     
00133     public void setResourceIdentifier(String resourceIdentifier) {
00134         this.resourceIdentifier = resourceIdentifier;
00135     }
00136     
00140     public String getResourceIdentifier() {
00141         return resourceIdentifier;
00142     }
00143     
00148     public void setAsOperatorPriority(int asOperatorPriority) {
00149         this.asOperatorPriority = asOperatorPriority;
00150     }
00151     
00156     public int getAsOperatorPriority() {
00157         return asOperatorPriority;
00158     }
00159 
00164     public void setAsOperandPriority(int asOperandPriority) {
00165         this.asOperandPriority = asOperandPriority;
00166     }
00167     
00172     public int getAsOperandPriority() {
00173         return asOperandPriority;
00174     }
00175     
00180     public boolean isTemplate() {
00181         return isTemplate;
00182     }
00183 
00187     public void setIsTemplate(boolean isTemplate) {
00188         this.isTemplate = isTemplate;
00189     }
00190     
00198     public FormulaTreeStructure findLocation(FormulaTreeStructure current) {
00199         //while (this.asOperandPriority < current.asOperatorPriority)
00200         while (asOperandPriority < current.getAsOperatorPriority())
00201             current = (FormulaTreeStructure) current.getFather();
00202 
00203         return current;
00204     }
00205 
00213     public FormulaTreeStructure goTo(int priority) {
00214         FormulaTreeStructure current = this;
00215 
00216         // Si le test est vrai, c'est qu'on est déjà sur un tel noeud.
00217         // On retourne un noeud identique placé au-dessus dans l'arbre
00218         int prio = current.asOperatorPriority;
00219         if (current.asOperatorPriority == priority)
00220             current = (FormulaTreeStructure) current.getFather();
00221 
00222         while ((current.asOperatorPriority != priority) &&
00223                 (((FormulaTreeStructure)current.getFather()).asOperatorPriority != 0))
00224             current = (FormulaTreeStructure) current.getFather();
00225 
00226         return (FormulaTreeStructure) current.getFather();
00227     }
00228     
00229     /*
00230     * Sets if we allow the move of the children (so operands) of the instance.
00231     * @param areOperandsMovable <CODE>true</CODE> if the operands are movable.
00232     * <CODE>false</CODE> otherwise.
00233     */
00234     public void setAreOperandsMovable(boolean areOperandsMovable) {
00235         this.areOperandsMovable = areOperandsMovable;
00236     }
00237     
00238     /*
00239     * Returns if we allow the move of the children (so operands) of the instance.
00240     * @return <CODE>true</CODE> if the operands are movable. <CODE>false</CODE> otherwise.
00241     */
00242     public boolean getAreOperandsMovable() {
00243         return areOperandsMovable;
00244     }
00245     
00253     public void moveOperands(Vector list, int rank) {
00254         // On fait la permutation dans la FTS
00255         moveChildren(list, rank);
00256         
00257         ModelEvent modelEvent = new ModelEvent(this);
00258         // On a fait les déplacements nécéssaires, on reconstruit le display
00259         modelEvent.setAction(ModelEvent.REBUILD, null);
00260         // On envoie l'événement.
00261         fireModelEvent(modelEvent);
00262         // On envoie maintenant un événement comme quoi il faut mettre à
00263         // jour l'affichage.
00264         modelEvent.setAction(ModelEvent.UPDATE, null);
00265         // On envoie l'événement.
00266         fireModelEvent(modelEvent);
00267     }
00268     
00269     // #################################################
00270     // ### Implémentation des différentes interfaces ###
00271     // #################################################
00272     
00273     // ****************************************
00274     // Implémentation de l'interface Comparable
00275     
00280     public boolean isEqual(fr.ove.utils.Comparable toCompare) {
00281         // On verra plus tard
00282         return false;
00283     }
00284     
00289     public boolean isGreater(fr.ove.utils.Comparable toCompare) {
00290         // On s'en fout, seule l'égalité nous intéresse
00291         return false;
00292     }
00293     
00298     public boolean isGreaterOrEqual(fr.ove.utils.Comparable toCompare) {
00299         // On s'en fout, seule l'égalité nous intéresse
00300         return false;
00301     }
00302     
00307     public boolean isLesser(fr.ove.utils.Comparable toCompare) {
00308         // On s'en fout, seule l'égalité nous intéresse
00309         return false;
00310     }
00311     
00316     public boolean isLesserOrEqual(fr.ove.utils.Comparable toCompare) {
00317         // On s'en fout, seule l'égalité nous intéresse
00318         return false;
00319     }
00320     
00321     // *** Fin de l'interface Comparable ***
00322     // *************************************
00323     
00324     
00325     // *****************************************
00326     // Implémentation de l'interface Iconifiable
00327     
00332     public void setIconName(String iconName) {
00333         // On ne fait rien, c'est dans les classes dérivées qu'on va implémenter getIconName().
00334         // Ca évite de stocker une String pour pas grand chose.
00335     }
00336     
00343     public String getIconName() {
00344         return resourceIdentifier + "_Ico"; //resourcesManager.getIconName(resourceIdentifier);
00345     }
00346     
00350     public boolean isIcon() {
00351         return false;
00352     }
00353     
00357     public void iconify() {
00358         if (isIconifiable()) {
00359             Icon icon = new Icon(this);
00360             // On ajoute l'instance à iconifier dans Icon (<=> on iconfie l'instance)
00361             icon.addIconified(this);
00362             // On insère maintenant notre icon à la place de l'instance.
00363             icon.insert(this);
00364         }
00365     }
00366     
00370     public void uniconify() {
00371         // Par défaut on ne fait rien, on ne peut désiconifier qu'une icone
00372     }
00373     
00374     
00378     public void uniconifyAll() {
00379         if (getNbChildren() != 0) {
00380             boolean rebuildDisplay = false;
00381             // On parcourre tous les enfants de l'instance et si on trouve une icone, on la
00382             // désiconifie
00383             FormulaTreeStructure fts = null;
00384             
00385             /*
00386             for (Enumeration e = getChildren().elements(); e.hasMoreElements(); ) {
00387                 fts = (FormulaTreeStructure) e.nextElement();
00388                 if (fts.isIcon()) {
00389                     fts.uniconify();
00390                     rebuildDisplay = true;
00391                 }
00392             }
00393             */
00394             for (int i = 0; i < getNbChildren(); i++) {
00395                 fts = (FormulaTreeStructure) getChild(i);
00396                 if (fts.isIcon()) {
00397                     fts.uniconify();
00398                     rebuildDisplay = true;
00399                     i = -1; // On repart à zéro car la désiconification a pu en refaire apparaître.
00400                 }
00401             }
00402             
00403             // l'instance n'a plus de d'icone fille, on s'occupe de la descendance
00404             for (Enumeration e = getChildren().elements(); e.hasMoreElements(); )
00405                 ((FormulaTreeStructure) e.nextElement()).uniconifyAll();
00406         
00407             // Reconstruction du display que si y a eu désiconification
00408             if (rebuildDisplay) {
00409                 // On part du principe que si l'on a une icone, c'est que l'on a le display qui lui est
00410                 // associé, donc reconstruction du display.
00411                 // Faire gaffe à appeler le ModelEvent.UPDATE quand nécessaire
00412                 
00413                 // On envoie maintenant un événement comme quoi il faut reconstruire
00414                 // l'affichage.
00415                 ModelEvent modelEvent = new ModelEvent(this);
00416                 modelEvent.setAction(ModelEvent.REBUILD, null);
00417                 fireModelEvent(modelEvent);
00418             }
00419         }
00420     }
00421         
00427     public void setIsIconifiable(boolean isIconifiable) {
00428         // On ne fait rien, les classes héritières retourneront la valeur qui leur correspond.
00429         // On évite de stocker un booléen pour pas grand chose puisque peu ne seront pas iconifiables
00430     }
00431     
00436     public boolean isIconifiable() {
00437         return true;  // Très peu ne sont pas iconifiables. Les concernés surchargeront cette méthode.
00438     }
00439     
00440     // *** Fin de l'interface Iconifiable ***
00441     // **************************************
00442     
00443     
00444     // *********************************************
00445     // Implémentation de l'interface ControlListener
00446     
00447     
00452     public void consumeControlEvent(ControlEvent controlEvent) {
00453         ModelEvent modelEvent;
00454         int action = controlEvent.getAction();
00455         FormulaTreeStructure fts = null;
00456         
00457         switch (action) {
00458             case ControlEvent.ADD :
00459                 //System.out.println("ControlEvent.ADD : on ajoute un nouveau display");
00460                 break;
00461             case ControlEvent.REMOVE :
00462                 //System.out.println("ControlEvent.REMOVE : on enleve un display");
00463                 break;
00464             case ControlEvent.ICONIFY :
00465                 //System.out.println("ControlEvent.ICONIFY : on iconifie");
00466                 Vector toIconify = (Vector) controlEvent.getArgument();
00467                 Icon icon = null;
00468                 if (toIconify.size() == 1) {
00469                     fts = (FormulaTreeStructure) toIconify.elementAt(0);
00470                     // une seule fts à iconifier.
00471                     if (fts.isIconifiable()) {
00472                         // Ce n'est pas déjà une icone et fts est iconifiable, on peut en créer une.
00473                         icon = new Icon(fts);
00474                         // On ajoute notre fts à iconifier dans Icon (<=> on iconfie fts)
00475                         icon.addIconified(fts);
00476                         // On insère maintenant notre icon à la place de fts.
00477                         icon.insert(fts);
00478                     }
00479                     // fts = icon.father pour que l'on puisse ajouter le display de notre icone dans icon.father
00480                     fts = (FormulaTreeStructure) icon.getFather();
00481                 }
00482                 else {
00483                     // Plusieurs fts sont à iconifier. Il faut donc récupérer la fts
00484                     // dont elles sont les filles, pour pouvoir créer l'icone adéquate.
00485                     fts = (FormulaTreeStructure) ((FormulaTreeStructure) toIconify.elementAt(0)).getFather();
00486                     // On crée une nouvelle icone
00487                     icon = new Icon(fts);
00488                     // On ajoute maintenant tous les fts à iconifier.
00489                     int countToIconify = toIconify.size();
00490                     for (int i = 0; i < countToIconify; i++)
00491                         icon.addIconified((FormulaTreeStructure) toIconify.elementAt(i));
00492                     // On insère maintenant notre icon à la place de la 1-ère fts.
00493                     icon.insert(icon.getIconified(0));
00494                 }
00495                 
00496                 // On ajoute un display pour notre icon.
00497                 modelEvent = new ModelEvent(fts);
00498                 modelEvent.setAction(ModelEvent.ADD, icon);
00499                 fts.fireModelEvent(modelEvent);
00500                 
00501                 // On met à jour l'affichage de la fts.
00502                 modelEvent.setAction(ModelEvent.UPDATE, null);
00503                 fts.fireModelEvent(modelEvent);
00504                 
00505                 break;
00506                 
00507             case ControlEvent.UNICONIFY :
00508                 //System.out.println("ControlEvent.UNICONIFY : on desiconifie");
00509                 Icon anIcon = (Icon) controlEvent.getArgument();
00510                 fts = (FormulaTreeStructure) anIcon.getFather();
00511                 anIcon.uniconify();
00512                 
00513                 // On envoie maintenant un événement comme quoi il faut reconstruire
00514                 // l'affichage.
00515                 modelEvent = new ModelEvent(fts);
00516                 modelEvent.setAction(ModelEvent.REBUILD, null);
00517                 fts.fireModelEvent(modelEvent);
00518                 // On envoie maintenant un événement comme quoi il faut mettre à
00519                 // jour l'affichage.
00520                 modelEvent.setAction(ModelEvent.UPDATE, null);
00521                 // On envoie l'événement.
00522                 fts.fireModelEvent(modelEvent);
00523                 break;
00524                 
00525             case ControlEvent.UNICONIFY_ALL :
00526                 // On remonte dans la FTS jusqu'à tomber sur la racine de la formule.
00527                 fts = this;
00528                 while (fts.getFather() != null)
00529                     fts = (FormulaTreeStructure) getFather();
00530                     
00531                 // On est sur la racine de la formule.
00532                 // A partir de là, on demande de tout désiconifier
00533                 fts.uniconifyAll();
00534                 
00535                 // On envoie maintenant un événement comme quoi il faut mettre à
00536                 // jour l'affichage.
00537                 modelEvent = new ModelEvent(fts);
00538                 modelEvent.setAction(ModelEvent.UPDATE, null);
00539                 // On envoie l'événement.
00540                 fts.fireModelEvent(modelEvent);
00541                 break;
00542                 
00543             case ControlEvent.SUBSTITUTE :
00544                 //System.out.println("ControlEvent.ICONIFY : on iconifie");
00545                 // ### ATTENTION, le premier élément sera le nom pour la substitution
00546                 Vector toSubstitute = (Vector) controlEvent.getArgument();
00547                 fts = (FormulaTreeStructure) toSubstitute.elementAt(1);
00548                 // On crée une nouvelle icone
00549                 Icon substitution = new Icon((String) toSubstitute.elementAt(0));
00550                 // On ajoute maintenant tous les fts à iconifier.
00551                 int countToIconify = toSubstitute.size();
00552                 
00553                 if ((countToIconify == 2) && !fts.isIconifiable())
00554                     break;
00555                 
00556                 for (int i = 1; i < countToIconify; i++)
00557                     substitution.addIconified((FormulaTreeStructure) toSubstitute.elementAt(i));
00558 
00559                 // On insère maintenant notre icon à la place de la 1-ère fts.
00560                 substitution.insert(fts);
00561 
00562                 // fts = substitution.father pour que l'on puisse ajouter le display de notre icone
00563                 // dans substitution.father
00564                 fts = (FormulaTreeStructure) substitution.getFather();
00565 
00566                 // On ajoute un display pour notre icon.
00567                 modelEvent = new ModelEvent(fts);
00568                 modelEvent.setAction(ModelEvent.ADD, substitution);
00569                 fts.fireModelEvent(modelEvent);
00570                 // On met à jour l'affichage de la fts.
00571                 modelEvent.setAction(ModelEvent.UPDATE, null);
00572                 fts.fireModelEvent(modelEvent);
00573                 break;
00574         }
00575     }
00576 
00577     // *** Fin de l'interface ControlListener ***
00578     // ******************************************
00579     
00580     // **************************************
00581     // Implémentation de l'interface Maskable
00582     
00587     public void setIsVisble(boolean isVisible) {
00588         // Ne fait rien par défaut. Tout les opérateurs sont visibles à de rares exceptions près.
00589         // Ce sont ces exceptions qui maintiendront cette propriété correctement en la surchargeant
00590     }
00591 
00596     public boolean isVisible() {
00597         // Tout les opérateurs sont visibles à de rares exceptions près.
00598         // Ce sont ces exceptions qui maintiendront cette propriété correctement en la surchargeant
00599         return true;
00600     }
00601     
00602     // *** Fin de l'interface Maskable ***
00603     // ***********************************
00604     
00605     
00606     // *****************************************
00607     // Implémentation de l'interface Modifiable
00608     
00612     public void setValue(String value) {
00613     }
00614     
00618     public String getValue() {
00619         return null;
00620     }
00621     
00622     // *** Fin de l'interface Modifiable ***
00623     // *************************************
00624     
00625     // ############################################
00626     // ### Les différentes méthodes abstraites  ###
00627     // ############################################
00628     
00633     public abstract boolean isOperator();
00634     
00642     public abstract FormulaTreeStructure insert(FormulaTreeStructure current);
00643     
00647     public abstract String createLinear(String linear);
00648 
00652     public abstract String evaluate();
00653 }