Back to index

wims  3.65+svn20090927
BasicStringInfixOperatorLayout.java
Go to the documentation of this file.
00001 /*
00002 $Id: BasicStringInfixOperatorLayout.java,v 1.3 2003/02/18 11:48:46 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.ctrlview.bidim;
00030 
00031 import java.awt.*;
00032 import java.util.*;
00033 import fr.ove.openmath.jome.ctrlview.bidim.*;
00034 import fr.ove.openmath.jome.ctrlview.bidim.selection.events.*;
00035 import fr.ove.openmath.jome.model.*;
00036 
00043 public class BasicStringInfixOperatorLayout extends StringInfixOperatorLayout {    
00048     protected void insertOperatorDisplay() {
00049         Display current, next, displayOperator;
00050         FormulaTreeStructure fatherFts = (FormulaTreeStructure) displayToLay.getListener();
00051         FormulaTreeStructure fts;
00052         int nbComponent = displayToLay.getComponentCount();
00053         
00054         // On parcourre tous les components présents dans le display.
00055         for (int i = 1; i < nbComponent; i++) {
00056             // la référence sur le component courant
00057             current = (Display) displayToLay.getComponent(i - 1);
00058             // la référence sur le suivant
00059             next = (Display) displayToLay.getComponent(i);
00060             
00061             // Si le courant est un display d'opérateur alors on continue
00062             if (current.isSymbolOperatorDisplay())
00063                 continue;
00064                 
00065             // Si le suivant n'est pas un display d'opérateur alors 2 cas
00066             if (!next.isSymbolOperatorDisplay()) {
00067                 // La seule distinction qu'il faut faire à ce stade là, c'est le cas où next
00068                 // est le diplay d'un - unaire. Si c'est le cas, on n'insère pas de display.
00069                 fts = (FormulaTreeStructure) next.getListener();
00070                 if (fts.isOperator()) {
00071                     String ope = ((Operator) fts).getTheOperator();
00072                     if (ope.equals("-"))
00073                         continue;
00074                 }
00075                     
00076                 // On ajoute un display d'opérateur.
00077                 displayOperator = createOperatorDisplay();
00078                 displayToLay.add(displayOperator, displayOperator, i);
00079                 
00080                 // On met un listener à l'opérateur.
00081                 // En fait, il n'y en a pas besoin, dans le sens où il n'y a pas spécifiquement de fts qui
00082                 // écoute le comportement de ce display. Néanmoins, il s'avère nécessaire qu'il en ait
00083                 // un, par exemple lors de l'iconification, car c'est le display qui reçoit la demande
00084                 // d'iconification qui envoie l'événement correspondant à la FTS. Or si ce display n'a pas
00085                 // d'écouteur, alors pb. Par cohérence, l'écouteur du display d'opérateur, est le fts qui
00086                 // représente cette opération. Par contre, la fts en question, n'écoute pas le display
00087                 // d'opérateur.
00088                 displayOperator.addControlListener(fatherFts);
00089                 i++;
00090                 nbComponent++;
00091             }
00092         }
00093         
00094         // Mise à jour des rangs des displays
00095         displayToLay.adjustRank();
00096         // Mise à jour du nombre de components présents dans le display.
00097         prevNbComponent = displayToLay.getComponentCount();
00098         // On n'a plus besoin d'insérer des displays d'opérateur.
00099         insertOperatorDisplay = false;
00100         // On fait en sorte que la mise à niveau des displays (opérateurs) soit faite.
00101         displayToLay.setUpdateLevel(true);
00102         // On a rajouté un display, on demande le recalcul de tous les ancêtres
00103         // de l'instance.
00104         displayToLay.computeAncestorsAttributes();
00105     }
00106     
00110     public void validateSelection() {
00111         Display childDisplay;
00112         DisplayLayout childLayout;
00113         SelectionEvent selEvt = new SelectionEvent(displayToLay);
00114         
00115         int nbChild = displayToLay.getComponentCount();
00116         
00117         // On parcourre la liste des displays, et on regarde sur chacun des dispays s'il faut sélectionner
00118         // un de ses voisins.
00119         for (int i = 0; i < nbChild; i++) {
00120             childDisplay = (Display) displayToLay.getComponent(i);
00121             childLayout = (DisplayLayout) childDisplay.getLayout();
00122             
00123             // On regarde ici s'il faut sélectionner le display à gauche de childLayout
00124             // Si ledit display n'est pas sélectionner, on le sélectionne.
00125             if (childLayout.selectLeftDisplay() && (i > 0)) {
00126                 childDisplay = (Display) displayToLay.getComponent(i-1);
00127                 if (!childDisplay.isSelected())
00128                     childDisplay.select();
00129             }
00130 
00131             // On regarde ici s'il faut sélectionner le display à droite de childLayout
00132             // Si ledit display n'est pas sélectionner, on le sélectionne.
00133             if (childLayout.selectRightDisplay() && (i < (nbChild - 1))) {
00134                 childDisplay = (Display) displayToLay.getComponent(i+1);
00135                 if (!childDisplay.isSelected())
00136                     childDisplay.select();
00137                 // On a sélectionné le display à la position i+1, donc on incrémente ici i,
00138                 // pour que dans le for, le i soit encore incrémenté et que l'on se positionne
00139                 // ainsi sur un display suivant, non sélectionné
00140                 i++;
00141             }
00142         }
00143         
00144         // On parcourre la liste des displays et on regarde si les displays à gauche et à droite du display
00145         // courant ont des éléments sélectionnés. Si c'est le cas et que le display courant est un display
00146         // d'opérateur et qu'il n'est pas sélectionné, alors on sélectionne le display à gauche, le displa
00147         // d'opérateur et le display à droite.
00148         // Ex: (...) + (...), dans chacune des parenthèses, un élément est sélectionné, on sélectionne tout
00149         Display prev;
00150         Display next;
00151         for (int i = 1; i < (nbChild - 1); i++) {
00152             prev = (Display) displayToLay.getComponent(i-1);
00153             childDisplay = (Display) displayToLay.getComponent(i);
00154             next = (Display) displayToLay.getComponent(i+1);
00155             if (prev.gotSelectedElements() && next.gotSelectedElements()) {
00156                 //if ((childDisplay instanceof StringDisplay) && !childDisplay.isSelected()) {
00157                 if (childDisplay.isSymbolOperatorDisplay() && !childDisplay.isSelected()) {
00158                     if (!prev.isSelected())
00159                         prev.select();
00160                     childDisplay.select();
00161                     if (!next.isSelected())
00162                         next.select();
00163                 }
00164             }
00165         }
00166         
00167         // On créé maintenant une liste contenant tous les displays qui ont été sélectionnés au cours des
00168         // opérations précédentes.
00169         Vector list = new Vector();
00170         for (int i = 0; i < nbChild; i++) {
00171             childDisplay = (Display) displayToLay.getComponent(i);
00172             if (childDisplay.gotSelectedElements())
00173                 list.addElement(childDisplay);
00174         }
00175 
00176         if (list.size() > 0) {
00177             if ((list.size() == nbChild) && !(displayToLay.getListener() instanceof Formula) && !(displayToLay.getListener() instanceof Slot)) {
00178                 selEvt.setAction(SelectionEvent.PURGE, null);
00179                 displayToLay.fireSelectionEvent(selEvt);
00180 
00181                 displayToLay.setSelected();
00182                 selEvt.setAction(SelectionEvent.ADD, displayToLay);
00183                 displayToLay.fireSelectionEvent(selEvt);
00184             }
00185             else if (list.size() != 1) {
00186                 selEvt.setAction(SelectionEvent.PURGE, null);
00187                 displayToLay.fireSelectionEvent(selEvt);
00188 
00189                 for (Enumeration e = list.elements(); e.hasMoreElements(); ) {
00190                     childDisplay = (Display) e.nextElement();
00191                     if (!childDisplay.isSelected())
00192                         childDisplay.select();
00193                     selEvt.setAction(SelectionEvent.ADD, childDisplay);
00194                     displayToLay.fireSelectionEvent(selEvt);
00195                 }
00196             }
00197         }
00198         
00199         // On a une sélection valide dans le display layed.
00200         // On demande la validation au niveau de son père.
00201         // En principe, à cause du test sur le fait d'avoir une Formula, pas besoin
00202         // d'avoir le test juste suivant. A surveiller.
00203         Display display = displayToLay;
00204         if (display.getParent() instanceof Display) {
00205             display = (Display) display.getParent();
00206             //if (!(display.getListener() instanceof Formula))
00207             FormulaTreeStructure fts = (FormulaTreeStructure) display.getListener();
00208             if (fts.getFather() != null)
00209                 ((DisplayLayout) display.getLayout()).validateSelection();
00210         }
00211         
00212         display.repaint(); // faut voir, parce que autant de repaint que de display ?????????
00213     }
00214 
00215 
00220     public void validateDeselection(Display display) {
00221         Display father = displayToLay;
00222         Display tmp;
00223         SelectionEvent selEvt = new SelectionEvent(father);
00224         int rank = display.getRank();
00225 
00226         // Premier cas: father (i.e. le display géré par l'instance) est sélectionné.
00227         if (father.isSelected()) {
00228             // On l'enlève de la liste des displays sélectionnés.
00229             father.setNotSelected();
00230             selEvt.setAction(SelectionEvent.REMOVE, father);
00231             father.fireSelectionEvent(selEvt);
00232 
00233             // Comme on arrive dans cette méthode par display, display a été déjà désélectionné.
00234             // De plus, ce LM gère principalement (voire que) des displays N-aires dont il s'agit
00235             // la plupart du temps d'une succession de displays opérandes entre lesquels se trouvent
00236             // des displays opérateur (ex: + ou *).
00237             // Donc, s'ils existent, on doit alors désélectionner le display précédent et le display
00238             // suivant... display. (d'où récupération du rang de display au début)
00239 
00240             // On s'occupe du display précédant... display.
00241             if (rank > 0) {
00242                 if (!(display.getListener() instanceof UnaryMinus)) {
00243                     // Il existe un display avant... display, donc on prend garde de le désélectionner,
00244                     // s'il était sélectionné.
00245                     tmp = ((Display) father.getComponent(rank-1));
00246                     if (tmp.isSelected()) {
00247                         // On désélectionne donc ledit display.
00248                         tmp.deselect();
00249 
00250                         // Maintenant, on regarde s'il existe un display précédent celui que l'on vient
00251                         // de désélectionner, qui est un display d'opérateur et qui est sélectionné.
00252                         // Si c'est le cas, on le désélectionne.
00253                         if (rank > 1) {
00254                             tmp = ((Display) father.getComponent(rank-2));
00255                             if (tmp.isSymbolOperatorDisplay() && tmp.isSelected())
00256                                 tmp.deselect();
00257                         }
00258                     }
00259                 }
00260             }
00261 
00262             // On s'occupe du display suivant... display.
00263             if (rank < (father.getComponentCount()-1)) {
00264                 // Il existe un display après... display, donc on prend garde de le désélectionner,
00265                 // s'il était sélectionné.
00266                 tmp = ((Display) father.getComponent(rank+1));
00267                 // Il faut faire attention dans le cas d'une addition où il y aurait un opérateur unaire.
00268                 // (Normalement seulement un UnaryMinus). Dans le cas le plus simple, une soustraction: a-b
00269                 // Si a-b est sélectionné et que l'on arrive ici parce on a désélectionné a, alors -b doit rester
00270                 // sélectionné. D'où ce cas particulier supplémentaire.
00271                 if (!(tmp.getListener() instanceof UnaryMinus)) {
00272                     if (tmp.isSelected()) {
00273                         tmp.deselect();
00274 
00275                         // Maintenant, on regarde s'il existe un display suivant celui que l'on vient
00276                         // de désélectionner, qui est un display d'opérateur et qui est sélectionné.
00277                         // Si c'est le cas, on le désélectionne.
00278                         if (rank < (father.getComponentCount()-2)) {
00279                             tmp = ((Display) father.getComponent(rank+2));
00280                             if (tmp.isSymbolOperatorDisplay() && tmp.isSelected())
00281                                 tmp.deselect();
00282                         }
00283                     }
00284                 }
00285                 else
00286                     ((LeftAssocPrefixedUnaryOperatorLayout) tmp.getLayout()).setSelectLeftDisplay(false);
00287             }
00288             
00289             // On parcourre la liste des display de father et on ajoute dans la liste des sélectionnés,
00290             // ... les sélectionnés.
00291             for (int i = 0; i < father.getComponentCount(); i++) {
00292                 tmp = (Display) father.getComponent(i);
00293                 if (tmp.isSelected()) {
00294                     selEvt.setAction(SelectionEvent.ADD, tmp);
00295                     father.fireSelectionEvent(selEvt);
00296                 }
00297             }
00298             
00299             // On regarde maintenant au niveau supérieur, si la désélection de father génère
00300             // une désélection qui est valide.
00301             if (father.getParent() instanceof Display) {
00302                 father = (Display) father.getParent();
00303                 FormulaTreeStructure fts = (FormulaTreeStructure) father.getListener();
00304                 if (fts.getFather() != null)
00305                     ((DisplayLayout) father.getLayout()).validateDeselection(displayToLay);
00306             }
00307         }
00308         // Deuxième cas: father (i.e. le display géré par l'instance) n'est pas sélectionné.
00309         // Mais, il en a des sélectionnés, puisque display fait partie de sa descendance.
00310         else {
00311             // Et bien, on fait exactement la même chose que précédemment, à la différence importante
00312             // que là, les displays sélectionnés font partie de la liste des displays sélectionnés.
00313             // Il faut donc les y enlever.
00314             if (rank > 0) {
00315                 if (!(display.getListener() instanceof UnaryMinus)) {
00316                     tmp = ((Display) father.getComponent(rank-1));
00317                     if (tmp.isSelected()) {
00318                         tmp.deselect();
00319                         selEvt.setAction(SelectionEvent.REMOVE, tmp);
00320                         father.fireSelectionEvent(selEvt);
00321 
00322                         if (rank > 1) {
00323                             tmp = ((Display) father.getComponent(rank-2));
00324                             if (tmp.isSymbolOperatorDisplay() && tmp.isSelected()) {
00325                                 tmp.deselect();
00326                                 selEvt.setAction(SelectionEvent.REMOVE, tmp);
00327                                 father.fireSelectionEvent(selEvt);
00328                             }
00329                         }
00330                     }
00331                 }
00332             }
00333 
00334             if (rank < (father.getComponentCount()-1)) {
00335                 tmp = ((Display) father.getComponent(rank+1));
00336                 // Il faut faire attention dans le cas d'une addition où il y aurait un opérateur unaire.
00337                 // (Normalement seulement un UnaryMinus). Dans le cas le plus simple, une soustraction: a-b
00338                 // Si a-b est sélectionné et que l'on arrive ici parce on a désélectionné a, alors -b doit rester
00339                 // sélectionné. D'où ce cas particulier supplémentaire.
00340                 if (!(tmp.getListener() instanceof UnaryMinus)) {
00341                     if (tmp.isSelected()) {
00342                         tmp.deselect();
00343 
00344                         // Maintenant, on regarde s'il existe un display suivant celui que l'on vient
00345                         // de désélectionner, qui est un display d'opérateur et qui est sélectionné.
00346                         // Si c'est le cas, on le désélectionne.
00347                         if (rank < (father.getComponentCount()-2)) {
00348                             tmp = ((Display) father.getComponent(rank+2));
00349                             if (tmp.isSymbolOperatorDisplay() && tmp.isSelected())
00350                                 tmp.deselect();
00351                         }
00352                     }
00353                 }
00354                 else
00355                     ((LeftAssocPrefixedUnaryOperatorLayout) tmp.getLayout()).setSelectLeftDisplay(false);
00356             }
00357         }
00358 
00359         // Comme toujours, on contrôle maintenant, avec les éventuels displays sélectionnés restant,
00360         // si la sélection est valide.
00361         validateSelection();
00362         // On met à jour le display.
00363         father.repaint();
00364     }
00365 }