Back to index

wims  3.65+svn20090927
BetweenOperatorLayout.java
Go to the documentation of this file.
00001 /*
00002 $Id: BetweenOperatorLayout.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.*;
00033 import fr.ove.openmath.jome.ctrlview.bidim.selection.events.SelectionEvent;
00034 import fr.ove.openmath.jome.model.*;
00035 
00044 public abstract class BetweenOperatorLayout extends VerticalCenteredLayout implements OperatorDisplayCreator {
00053     public void initDisplay(Display displayToLay) {
00054         super.initDisplay(displayToLay);
00055         Display operatorDisplay = createOperatorDisplay();
00056 
00057         // On met un listener au display de l'opérateur
00058         // En fait, il n'y en a pas besoin, dans le sens où il n'y a pas spécifiquement de fts qui
00059         // écoute le comportement de ce display. Néanmoins, il s'avère nécessaire qu'il en ait
00060         // un, par exemple lors de l'iconification, car c'est le display qui reçoit la demande
00061         // d'iconification qui envoie l'événement correspondant à la FTS. Or si ce display n'a pas
00062         // d'écouteur, alors pb. Par cohérence, l'écouteur du display d'opérateur, est le fts qui
00063         // représente cette opération. Par contre, la fts en question, n'écoute pas le display
00064         // d'opérateur.
00065         operatorDisplay.addControlListener((FormulaTreeStructure) displayToLay.getListener());
00066         this.displayToLay.add(operatorDisplay);
00067     }
00068     
00072     public void validateSelection() {
00073         SelectionEvent selEvt = new SelectionEvent(displayToLay);
00074 
00075         // La validité de la sélection est triviale.
00076         // Si les 2 opérandes sont sélectionnés, ou si le symbole de l'opérateur est sélectionné,
00077         // alors on sélectionne tout.
00078         Display operatorDisplay = (Display) displayToLay.getComponent(0);
00079         Display operand1 = (Display) displayToLay.getComponent(1);
00080         Display operand2 = (Display) displayToLay.getComponent(2);
00081         if ((operand1.gotSelectedElements() && operand2.gotSelectedElements()) ||
00082             (operatorDisplay.isSelected())) {
00083             // Sélectionne le display.
00084             displayToLay.select();
00085             // On purge la liste des éléments sélectionnés.
00086             selEvt.setAction(SelectionEvent.PURGE, null);
00087             displayToLay.fireSelectionEvent(selEvt);
00088             // On y ajoute os parenthèses
00089             selEvt.setAction(SelectionEvent.ADD, displayToLay);
00090             displayToLay.fireSelectionEvent(selEvt);
00091         }
00092 
00093         // On a vérifié la validité de la sélection de la puissance. On doit maitenant
00094         // la contrôler au niveau supérieur, au niveau du père.
00095         Display display = displayToLay;
00096         if (display.getParent() instanceof Display) {
00097             display = (Display) display.getParent();
00098             FormulaTreeStructure fts = (FormulaTreeStructure) display.getListener();
00099             if (fts.getFather() != null)
00100                 ((DisplayLayout) display.getLayout()).validateSelection();
00101         }
00102 
00103         // On met à jour l'affichage.
00104         display.repaint();
00105     }
00106     
00111     public void validateDeselection(Display display) {
00112         Display father = displayToLay;
00113         SelectionEvent selEvt = new SelectionEvent(father);
00114         
00115         // Si la fraction est sélectionnée, alors il faut la déselectionner.
00116         if (father.isSelected()) {
00117             father.setNotSelected();
00118             // On enlève le display père de la liste des display sélectionnés.
00119             selEvt.setAction(SelectionEvent.REMOVE, father);
00120             father.fireSelectionEvent(selEvt);
00121             
00122             Display operatorDisplay = (Display) father.getComponent(0);
00123             Display operand1 = (Display) father.getComponent(1);
00124             Display operand2 = (Display) father.getComponent(2);
00125             
00126             if (display == operand1) {
00127                 operatorDisplay.setNotSelected();
00128                 selEvt.setAction(SelectionEvent.ADD, operand2);
00129                 father.fireSelectionEvent(selEvt);
00130             }
00131             else if (display == operand2) {
00132                 operatorDisplay.setNotSelected();
00133                 selEvt.setAction(SelectionEvent.ADD, operand1);
00134                 father.fireSelectionEvent(selEvt);
00135             }
00136             else {
00137                 operand1.deselect();
00138                 operatorDisplay.setNotSelected();
00139                 operand2.deselect();
00140             }
00141 
00142             // Comme pour la sélection, on contrôle la validité de la désélection.
00143             if (father.getParent() instanceof Display) {
00144                 father = (Display) father.getParent();
00145                 FormulaTreeStructure fts = (FormulaTreeStructure) father.getListener();
00146                 if (fts.getFather() != null)
00147                     ((DisplayLayout) father.getLayout()).validateDeselection(displayToLay);
00148             }
00149             
00150             // Hé oui, on contrôle la validité de la sélection... dans une désélection.
00151             // Toujours le même pb, est-ce que le nouvel état de la sélection (après
00152             // désélection donc) est syntaxiquement cohérent ?
00153             validateSelection();
00154             
00155             // On met à jour l'affichage.
00156             father.repaint();
00157         }        
00158     }
00159     
00165     public Dimension computeAttributes() {
00166         Display displayOperator = (Display) displayToLay.getComponent(0);
00167         Display topOperand = (Display) displayToLay.getComponent(1);
00168         Display bottomOperand = (Display) displayToLay.getComponent(2);
00169         // Initialisation de ces paramètres pour annuler les (éventuelles) précédentes valeurs prises.
00170         displayOperator.setShiftY(0);
00171         topOperand.setShiftY(0);
00172         bottomOperand.setShiftY(0);
00173 
00174         // On calcule les attributs des display enfants comme si on avait affaire à un VerticalCenteredLayout.
00175         // La différece réside dans le fait qu'il faut faire en sorte que le display de l'opérateur soit affiché
00176         // entre les opérandes
00177         Dimension dim = super.computeAttributes(); 
00178         
00179 
00180         // Cette taille là correspond au décalage qu'il faut appliquer à la barre de fraction
00181         displayOperator.setShiftY(topOperand.getHeight());
00182         // Mais il faut l'enlever au display du numérateur
00183         topOperand.setShiftY(-displayOperator.getShiftY() - displayOperator.getHeight());
00184         bottomOperand.setShiftY(displayOperator.getHeight());
00185         
00186         // On met la baseline de la fraction sur celle de la barre de fraction + qque broutilles qui
00187         // correspondent à où se trouve la barre horizontale du +
00188         int ascent = displayToLay.getFontMetrics(displayToLay.getFont()).getAscent();
00189         ascent = (int) Math.round(((float) ascent)*0.388f);
00190         
00191         ascent += topOperand.getShiftY() + topOperand.getHeight() + 
00192                  displayOperator.getShiftY() + displayOperator.getAscent();
00193         
00194         displayToLay.setAscent(ascent);
00195         displayToLay.setDescent(dim.height - ascent);
00196         
00197         displayToLay.setComputeAttributes(false);
00198         
00199         return dim;
00200     }
00201     
00205     public void rebuildDisplay() {
00206         Display tmp;
00207         Display listDisplay[] = new Display[2];
00208         
00209         for (int i = 1; i <= 2; i++) {
00210             tmp = (Display) displayToLay.getComponent(i);
00211             tmp.setLocation(0,0);
00212             listDisplay[((FormulaTreeStructure) tmp.getListener()).getRank()] = tmp;
00213         }
00214         
00215         // On garde un référence sur le display du symbole l'opérateur
00216         tmp = (Display) displayToLay.getComponent(0);
00217         // On fait en sorte que temporairement ce display ne soit pas considéré comme un
00218         // display d'opérateur, sinon il serait supprimé de la liste des listeners de la fts,
00219         // chose qu'on ne veut pas puisque qu'on va le remettre à sa place.
00220         tmp.setIsSymbolOperatorDisplay(false);
00221         
00222         // ATTENTION : ici, on enlève les displays fils de display, mais on ne les enlève pas de la liste
00223         // des listeners de la fts qu'il sont en train d'écouter.
00224         displayToLay.removeAllDisplays();
00225         
00226         // On remet tmp comme étant un display d'opérateur
00227         tmp.setIsSymbolOperatorDisplay(true);
00228         // On le rajoute dans displayToLay à sa position (la première)
00229         displayToLay.add(tmp);
00230                 
00231         for (int i = 0; i < 2; i++)
00232             displayToLay.add(listDisplay[i]);
00233         
00234         // La taille des displays est probablement différente de ceux qui étaient
00235         // précédemment. On demande alors le recalcul des display ancêtres.
00236         displayToLay.computeAncestorsAttributes();
00237     }
00238 }