Back to index

wims  3.65+svn20090927
IntegralLayout.java
Go to the documentation of this file.
00001 /*
00002 $Id: IntegralLayout.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 fr.ove.openmath.jome.ctrlview.bidim.Display;
00033 import fr.ove.openmath.jome.ctrlview.bidim.DisplayLayout;
00034 import fr.ove.openmath.jome.ctrlview.bidim.HorizontalLayout;
00035 import fr.ove.openmath.jome.ctrlview.bidim.selection.events.SelectionEvent;
00036 import fr.ove.openmath.jome.model.*;
00037 
00052 public class IntegralLayout extends HorizontalLayout {
00061     public void initDisplay(Display displayToLay) {
00062         super.initDisplay(displayToLay);
00063 
00064         SymbolDisplay integral = new SymbolDisplay(this.displayToLay.getGraphicContext(), 
00065                                                 new ImageSymbol("Integrale", this.displayToLay));
00066         // Le display de l'intégrale est le display d'un opérateur (on peut le considérer comme tel)
00067         integral.setIsSymbolOperatorDisplay(true);
00068         this.displayToLay.add(integral);
00069         integral.addControlListener((FormulaTreeStructure) this.displayToLay.getListener());
00070     }
00071     
00076     public void updateLevel(int level) {
00077         Display tmp;
00078         StringDisplay varIntDisplay;
00079         VariableOrNumber varInt;
00080         
00081         // Pour éviter de refaire le calcul plusieurs fois....
00082         if (displayToLay.getUpdateLevel()) {
00083             // On met à jour le niveau du display géré par le LM.
00084             displayToLay.setLevel(level);
00085             displayToLay.setUpdateLevel(false);
00086             
00087             int i = 0;
00088             int count = displayToLay.getComponentCount();
00089             // Si le nombre de composant est au moins 4, alors on a affaire à une intégrale où au moins une
00090             // borne est spécifiée (la borne inférieure)
00091             // On fait en sorte qu'elle soit en première position dans display,
00092             // sinon, à l'affichage, elle va être en partie masquée par le display de l'intégrale.
00093             if (count > 3) {
00094                 // On regarde si le premier display est celui d'un opérateur (celui de l'intégrale en fait)
00095                 // Si c'est le cas, il faut déplacer le display de la borne inf.
00096                 if (((Display) displayToLay.getComponent(0)).isSymbolOperatorDisplay()) {
00097                     tmp = (Display) displayToLay.getComponent(3);
00098                     
00099                     // De part l'implémentation du add(tmp, tmp, 0), tmp va être enlevé de la liste
00100                     // des listeners qu'il écoute. Chose qu'on ne veut pas.
00101                     displayToLay.removeFromListListeners(false);
00102                     
00103                     displayToLay.add(tmp, tmp, 0);
00104                     
00105                     // On se remet dans la cas classique où la suppression de display entraînera sa suppression
00106                     // dans la liste des listeners qu'il écoute.
00107                     displayToLay.removeFromListListeners(true);
00108                     
00109                     displayToLay.adjustRank();
00110                 }
00111                 
00112                 // On réduit la taille de la borne inf. de 1
00113                 tmp = (Display) displayToLay.getComponent(0);
00114                 ((DisplayLayout) tmp.getLayout()).updateLevel(level+1);
00115                 tmp.setUpdateLevel(false);
00116                 
00117                 // On incrémente l'indice i, pour que dans la boucle qui suit, on parte bien du display
00118                 // du tick
00119                 i++;
00120                 
00121                 // Le display de la variable d'intégration est en 4-ième position
00122                 tmp = (Display) displayToLay.getComponent(3);
00123                 varIntDisplay = (StringDisplay) tmp.getComponent(0);
00124                 
00125                 if (count > 4) {
00126                     // C'est la borne supérieure. On réduit sa taille de 1
00127                     tmp = (Display) displayToLay.getComponent(4);
00128                     ((DisplayLayout) tmp.getLayout()).updateLevel(level+1);
00129                     tmp.setUpdateLevel(false);
00130                     
00131                     count--;
00132                 }
00133             }
00134             else {
00135                 // Le display de la variable d'intégration est en 3-ième position
00136                 tmp = (Display) displayToLay.getComponent(2);
00137                 varIntDisplay = (StringDisplay) tmp.getComponent(0);
00138             }
00139             
00140             // On récupère la fts de la variable d'intégration.
00141             // Si c'est un template, alors pas besoin de rajouter le d. Sinon, on le rajoute
00142             varInt = (VariableOrNumber) varIntDisplay.getListener();
00143             if (!varInt.isTemplate())
00144                 varIntDisplay.setString("d" + varInt.getValue());
00145             
00146             // le symbole de l'intégrale, l'intégrande et la variable d'intégration (en fait le d"x")
00147             // ont le niveau du display qui les contient
00148             for (; i < count; i++) {
00149                 tmp = (Display) displayToLay.getComponent(i);
00150                 ((DisplayLayout) tmp.getLayout()).updateLevel(level);
00151                 tmp.setUpdateLevel(false);
00152             }
00153         }
00154     }
00155 
00160     public void validateSelection() {
00161         int count = displayToLay.getComponentCount();
00162         Display symbol, expression, varInt;
00163         
00164         if (count > 3) {
00165             symbol = (Display) displayToLay.getComponent(1);
00166             expression = (Display) displayToLay.getComponent(2);
00167             varInt = (Display) displayToLay.getComponent(3);
00168         }
00169         else {
00170             symbol = (Display) displayToLay.getComponent(0);
00171             expression = (Display) displayToLay.getComponent(1);
00172             varInt = (Display) displayToLay.getComponent(2);
00173         }
00174         
00175         if ((symbol.isSelected()) || (varInt.isSelected()))
00176             displayToLay.select();
00177         else if (count > 3) {
00178             Display lower = (Display) displayToLay.getComponent(0);
00179             Display upper;
00180             
00181             if (lower.gotSelectedElements()) {
00182                 if (expression.gotSelectedElements())
00183                     displayToLay.select();
00184                 else if (count > 4) {
00185                     upper = (Display) displayToLay.getComponent(4);
00186                     if (upper.gotSelectedElements())
00187                         displayToLay.select();
00188                 }
00189             }
00190             else if (count > 4) {
00191                 upper = (Display) displayToLay.getComponent(4);
00192                 if (upper.gotSelectedElements()) {
00193                     if (expression.gotSelectedElements())
00194                         displayToLay.select();
00195                 }
00196             }
00197         }
00198             
00199         // Quand on est ici, si display est sélectionné, alors c'est qu'on a validé un des tests
00200         // ci-dessus. On doit alors mettre à jour le gestionnaire de sélections, et y ajouter display
00201         if (displayToLay.isSelected()) {
00202             SelectionEvent selEvt = new SelectionEvent(displayToLay);
00203             // On purge la liste des éléments sélectionnés.
00204             selEvt.setAction(SelectionEvent.PURGE, null);
00205             displayToLay.fireSelectionEvent(selEvt);
00206             // On y ajoute notre intégrale.
00207             selEvt.setAction(SelectionEvent.ADD, displayToLay);
00208             displayToLay.fireSelectionEvent(selEvt);
00209         }
00210 
00211         // On a vérifié la validité de la sélection de l'intégrale. On doit maitenant
00212         // la contrôler au niveau supérieur, au niveau du père.
00213         Display display = displayToLay;
00214         if (display.getParent() instanceof Display) {
00215             display = (Display) display.getParent();
00216             FormulaTreeStructure fts = (FormulaTreeStructure) display.getListener();
00217             if (fts.getFather() != null) // Si fts est la racine de la formule alors la sélection à déjà été validée
00218                 ((DisplayLayout) display.getLayout()).validateSelection();
00219         }
00220 
00221         // On met à jour l'affichage.
00222         display.repaint();
00223     }
00224     
00229     public void validateDeselection(Display display) {
00230         Display father = displayToLay;
00231         Display tmp;
00232         SelectionEvent selEvt = new SelectionEvent(father);
00233         
00234         if (father.isSelected()) {
00235             father.setNotSelected();
00236             // On enlève le display père de la liste des display sélectionnés.
00237             selEvt.setAction(SelectionEvent.REMOVE, father);
00238             father.fireSelectionEvent(selEvt);
00239             
00240             int count = father.getComponentCount();
00241             Display expression;
00242             
00243             if (count > 3)
00244                 expression = (Display) father.getComponent(2);
00245             else
00246                 expression = (Display) father.getComponent(1);
00247             
00248             if (display != expression) {
00249                 // quand on désélectionne un élément de l'intégrale, autre que l'expression, l'expression
00250                 // reste sélectionnée.
00251                 selEvt.setAction(SelectionEvent.ADD, expression);
00252                 father.fireSelectionEvent(selEvt);
00253             }
00254             
00255             if (count > 3) {
00256                 ((Display) father.getComponent(0)).deselect();
00257                 ((Display) father.getComponent(1)).setNotSelected();
00258                 ((Display) father.getComponent(3)).deselect();
00259                 if (count > 4) 
00260                     ((Display) father.getComponent(4)).deselect();
00261             }
00262             else {
00263                 ((Display) father.getComponent(0)).setNotSelected();
00264                 ((Display) father.getComponent(2)).deselect();
00265             }
00266             
00267             // Comme pour la sélection, on contrôle la validité de la désélection.
00268             if (father.getParent() instanceof Display) {
00269                 father = (Display) father.getParent();
00270                 FormulaTreeStructure fts = (FormulaTreeStructure) father.getListener();
00271                 if (fts.getFather() != null)
00272                     ((DisplayLayout) father.getLayout()).validateDeselection(displayToLay);
00273             }
00274             // Hé oui, on contrôle la validité de la sélection... dans une désélection.
00275             // Toujours le même pb, est-ce que le nouvel état de la sélection (après
00276             // désélection donc) est syntaxiquement cohérent ?
00277             validateSelection();
00278             
00279             // On met à jour l'affichage.
00280             father.repaint();
00281         }        
00282 
00283     }
00284 
00290     public Dimension computeAttributes() {
00291         int ascent = 0;
00292         int descent = 0;
00293 
00294         updateLevel(displayToLay.getLevel());
00295 
00296         int width = 0;
00297         int height = 0;
00298         
00299         SymbolDisplay symbol;
00300         Display expression, integrand;
00301         int gap = 4;
00302         
00303         int count = displayToLay.getComponentCount();
00304         if (count > 3) {
00305             symbol = (SymbolDisplay) displayToLay.getComponent(1);
00306             expression = (Display) displayToLay.getComponent(2);
00307             integrand = (Display) displayToLay.getComponent(3);
00308         }
00309         else {
00310             symbol = (SymbolDisplay) displayToLay.getComponent(0);
00311             expression = (Display) displayToLay.getComponent(1);
00312             integrand = (Display) displayToLay.getComponent(2);
00313         }
00314         
00315         symbol.setSize(symbol.getPreferredSize());
00316         expression.setSize(expression.getPreferredSize());
00317         integrand.setSize(integrand.getPreferredSize());
00318         
00319         int width1 = symbol.getWidth();
00320         width += expression.getWidth() + integrand.getWidth();
00321         
00322         ascent = Math.max(expression.getAscent(), symbol.getAscent());
00323         descent = Math.max(expression.getDescent(), symbol.getDescent());
00324         
00325         if (count > 3) {
00326             Display lower = (Display) displayToLay.getComponent(0);
00327             lower.setSize(lower.getPreferredSize());
00328             lower.setShiftY((int) Math.round(symbol.getDescent()*0.2f) + lower.getAscent());
00329             lower.setShiftX((int) Math.round(symbol.getWidth()*0.55f));
00330             
00331             //width1 += lower.getWidth();
00332             width1 = Math.max(symbol.getWidth(), lower.getShiftX() + lower.getWidth());
00333             
00334             descent = Math.max(lower.getShiftY() + lower.getDescent() + gap, descent);
00335             
00336             symbol.setShiftX(-lower.getWidth() - lower.getShiftX());
00337             
00338             if (count > 4) {
00339                 Display upper = (Display) displayToLay.getComponent(4);
00340                 upper.setSize(upper.getPreferredSize());
00341                 
00342                 width1 = Math.max(width1, symbol.getWidth() + upper.getWidth());
00343                 
00344                 int decalage = width1 - symbol.getWidth();
00345                 upper.setShiftX(-(decalage + width/* - gap*/));
00346                 upper.setShiftY((int) Math.round(-symbol.getAscent()*0.6f) - upper.getDescent());
00347             
00348                 ascent = Math.max(-upper.getShiftY() + upper.getAscent() + gap, ascent);
00349             }
00350         }
00351         
00352         expression.setShiftX(width1 - symbol.getWidth() + gap);
00353                     
00354         displayToLay.setAscent(ascent);
00355         displayToLay.setDescent(descent);
00356         
00357         width += width1/* + expression.getWidth()*/ + 2*gap;
00358         
00359         height += ascent + descent;
00360         displayToLay.setSize(width , height);
00361         
00362         displayToLay.setComputeAttributes(false);
00363         return new Dimension(width, height);
00364     }
00365     
00369     public void rebuildDisplay() {
00370         // La taille des displays est probablement différente de ceux qui étaient
00371         // précédemment. On demande alors le recalcul des display ancêtres.
00372         displayToLay.computeAncestorsAttributes();
00373     }
00374    
00375 }