View Javadoc

1   /*
2   $Id: UnderOverLayout.java 711 2005-03-21 16:46:11Z guest $
3   */
4   
5   
6   /*
7   Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
8   
9   This library is free software; you can redistribute it and/or
10  modify it under the terms of the GNU Lesser General Public
11  License as published by the Free Software Foundation; either
12  version 2.1 of the License, or (at your option) any later version.
13  
14  This library is distributed in the hope that it will be useful,
15  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  Lesser General Public License for more details.
18  
19  You should have received a copy of the GNU Lesser General Public
20  License along with this library; if not, write to the Free Software
21  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  
23  For further information on the GNU Lesser General Public License,
24  see: http://www.gnu.org/copyleft/lesser.html
25  For further information on this library, contact: mainline@essi.fr
26  */
27  
28  
29  package fr.ove.openmath.jome.ctrlview.bidim;
30  
31  import java.awt.*;
32  import fr.ove.openmath.jome.ctrlview.bidim.Display;
33  import fr.ove.openmath.jome.ctrlview.bidim.DisplayLayout;
34  import fr.ove.openmath.jome.ctrlview.bidim.HorizontalLayout;
35  import fr.ove.openmath.jome.ctrlview.bidim.selection.events.SelectionEvent;
36  import fr.ove.openmath.jome.model.*;
37  
38  /***
39  * A layout manager that lays components to place them as the different elements like the operator
40  * sum does.<BR>
41  * The different elements are contained in the display in the following order :
42  * <UL>
43  * <LI>the symbol of the operator.</LI>
44  * <LI>the expression.</LI>
45  * <LI>the lower bound.</LI>
46  * <LI>the upper bound.</LI>
47  *</UL>
48  *
49  * Bounds are optional elements.
50  *
51  * @author © 1999 DIRAT Laurent
52  * @version 2.0 16/12/1999
53  */
54  public class UnderOverLayout extends HorizontalLayout{
55  	/***
56  	* According to the operator, the layout manager has to add some components (e.g. brackets, ...)
57  	* or has to perform some "re-oganisation" before rendering.<BR>
58  	* As soon as the layout manager is set to the display, this mehtod MUST be called with the display laid out
59  	* as parameter. This method serves as well as a registering method. So all sub-classes of the instance MUST
60  	* call super.initDisplay(displayToLay).
61  	* @param displayToLay the display laid by the instance
62  	*/
63  	public void initDisplay(Display displayToLay) {
64  		super.initDisplay(displayToLay);
65  	}
66      
67  	/***
68  	* Updates the level of the display that is layed out.<BR>
69  	* @param level the level put to the display
70  	*/
71  	public void updateLevel(int level) {
72  		Display tmp;
73          
74  		if (displayToLay.getUpdateLevel()) {            
75  			displayToLay.updateChildrenLevel();
76              
77  			// On met ? jour le niveau du display gÈrÈ par le LM.
78  			displayToLay.setLevel(level);
79  			displayToLay.setUpdateLevel(false);
80              
81  			// Le symbole a le mÍme niveau que le display
82  			tmp = (Display) displayToLay.getComponent(0);
83  			((DisplayLayout) tmp.getLayout()).updateLevel(level);
84  			tmp.setUpdateLevel(false);
85              
86  			int count = displayToLay.getComponentCount();
87              
88  			if (count > 1) {
89  				// La borne infÈrieure a le niveau du dispay +1
90  				tmp = (Display) displayToLay.getComponent(1);
91  				((DisplayLayout) tmp.getLayout()).updateLevel(level+1);
92  				tmp.setUpdateLevel(false);
93  
94  				if (count > 2) {
95  					// La borne supÈrieure a le niveau du dispay +1
96  					tmp = (Display) displayToLay.getComponent(2);
97  					((DisplayLayout) tmp.getLayout()).updateLevel(level+1);
98  					tmp.setUpdateLevel(false);
99  				}
100 			}
101 		}
102 	}
103 
104 	/***
105 	* Checks the validity of the selection.
106 	* @param display the display to select.
107 	*/
108 	public void validateSelection() {
109 		Display symbol = (Display) displayToLay.getComponent(0);
110 		Display expression = (Display) displayToLay.getComponent(1);
111         
112 		int count = displayToLay.getComponentCount();
113         
114 		// Si le symbole est sÈlectionnÈ, on sÈlectionne tout le display
115 		if (symbol.isSelected())
116 			displayToLay.select();
117 		else if (count > 2) {
118 			Display lower = (Display) displayToLay.getComponent(2);
119 			Display upper;
120             
121 			if (lower.gotSelectedElements()) {
122 				if (expression.gotSelectedElements())
123 					displayToLay.select();
124 				else if (count > 3) {
125 					upper = (Display) displayToLay.getComponent(3);
126 					if (upper.gotSelectedElements())
127 						displayToLay.select();
128 				}
129 			}
130 			else if (count > 3) {
131 				upper = (Display) displayToLay.getComponent(3);
132 				if (upper.gotSelectedElements()) {
133 					if (expression.gotSelectedElements())
134 						displayToLay.select();
135 				}
136 			}
137 		}
138         
139 		// Quand on est ici, si display est sÈlectionnÈ, alors c'est qu'on a validÈ un des tests
140 		// ci-dessus. On doit alors mettre ? jour le gestionnaire de sÈlections, et y ajouter display
141 		if (displayToLay.isSelected()) {
142 			SelectionEvent selEvt = new SelectionEvent(displayToLay);
143 			// On purge la liste des ÈlÈments sÈlectionnÈs.
144 			selEvt.setAction(SelectionEvent.PURGE, null);
145 			displayToLay.fireSelectionEvent(selEvt);
146 			// On y ajoute notre puissance.
147 			selEvt.setAction(SelectionEvent.ADD, displayToLay);
148 			displayToLay.fireSelectionEvent(selEvt);
149 		}
150 
151 		// On a vÈrifiÈ la validitÈ de la sÈlection de la puissance. On doit maitenant
152 		// la contrÙler au niveau supÈrieur, au niveau du pËre.
153 		Display display = displayToLay;
154 		if (display.getParent() instanceof Display) {
155 			display = (Display) display.getParent();
156 			//if (!(display.getListener() instanceof Formula))
157 			FormulaTreeStructure fts = (FormulaTreeStructure) display.getListener();
158 			if (fts.getFather() != null)
159 				((DisplayLayout) display.getLayout()).validateSelection();
160 		}
161 
162 		// On met ? jour l'affichage.
163 		display.repaint();
164 	}
165     
166 	/***
167 	* Checks the validity of the deselection.
168 	* @param display the display to deselect.
169 	*/
170 	public void validateDeselection(Display display) {
171 		Display father = displayToLay;
172 		SelectionEvent selEvt = new SelectionEvent(father);
173         
174 		if (father.isSelected()) {
175 			father.setNotSelected();
176 			// On enlËve le display pËre de la liste des display sÈlectionnÈs.
177 			selEvt.setAction(SelectionEvent.REMOVE, father);
178 			father.fireSelectionEvent(selEvt);
179             
180 			Display expression = (Display) father.getComponent(1);
181 			int count = father.getComponentCount();
182 			if (display != expression) {
183 				// quand on dÈsÈlectionne un ÈlÈment de la somme, autre que l'expression, l'expression
184 				// reste sÈlectionnÈe.
185 				selEvt.setAction(SelectionEvent.ADD, expression);
186 				father.fireSelectionEvent(selEvt);
187 			}
188             
189 			((Display) father.getComponent(0)).setNotSelected();// On dÈsÈlectionne le symbole.
190 			if (count > 2) {
191 				((Display) father.getComponent(2)).deselect();// On dÈsÈlectionne la borne inf.
192 				if (count > 3) 
193 					((Display) father.getComponent(3)).deselect();// On dÈsÈlectionne la borne sup.
194 			}
195             
196 			// Comme pour la sÈlection, on contrÙle la validitÈ de la dÈsÈlection.
197 			if (father.getParent() instanceof Display) {
198 				father = (Display) father.getParent();
199 				FormulaTreeStructure fts = (FormulaTreeStructure) father.getListener();
200 				if (fts.getFather() != null)
201 					((DisplayLayout) father.getLayout()).validateDeselection(displayToLay);
202 			}
203 			// HÈ oui, on contrÙle la validitÈ de la sÈlection... dans une dÈsÈlection.
204 			// Toujours le mÍme pb, est-ce que le nouvel Ètat de la sÈlection (aprËs
205 			// dÈsÈlection donc) est syntaxiquement cohÈrent ?
206 			validateSelection();
207             
208 			// On met ? jour l'affichage.
209 			father.repaint();
210 		}        
211 	}
212 
213 	/***
214 	* Computes the size of the display according to its children size (if any),
215 	* and its different attributes.
216 	* @return the size of the display.
217 	*/
218 	public Dimension computeAttributes() {
219 		int ascent = 0;
220 		int descent = 0;
221 
222 		updateLevel(displayToLay.getLevel());
223 
224 		int width = 0;
225 		int height = 0;
226         
227 		Display symbol, lower, upper;
228 		int gap = 2;
229         
230 		// On calcule la taille du symbole
231 		symbol = (Display) displayToLay.getComponent(0);
232 		symbol.setSize(symbol.getPreferredSize());
233         
234         
235 		int width1 = symbol.getWidth();
236         
237 		int count = displayToLay.getComponentCount();
238 		if (count > 1) {
239 			// On calcule la taille de la borne infÈrieure
240 			lower = (Display) displayToLay.getComponent(1);
241 			lower.setSize(lower.getPreferredSize());
242 			lower.setShiftY(symbol.getDescent() + lower.getAscent() + gap);
243             
244 			width1 = Math.max(lower.getWidth(), width1);
245             
246 			if (count > 2 ) {
247 				// On calcule la taille de la borne supÈrieure
248 				upper = (Display) displayToLay.getComponent(2);
249 				upper.setSize(upper.getPreferredSize());
250                 
251 				width1 = Math.max(upper.getWidth(), width1);
252             
253 				upper.setShiftX(-(lower.getWidth() + upper.getWidth()) / 2);
254 				upper.setShiftY(-(symbol.getAscent() + upper.getDescent() + gap));
255                 
256 				ascent = symbol.getAscent() + upper.getHeight() + gap;
257 			}
258 			else {
259 				ascent = symbol.getAscent();
260 			}
261             
262 			symbol.setShiftX((width1 - symbol.getWidth()) / 2);
263             
264 			lower.setShiftX(-(symbol.getWidth() + lower.getWidth())/2);
265             
266 			descent = symbol.getDescent() + lower.getHeight() + gap;
267 		}
268 		else {
269 			ascent = symbol.getAscent();
270 			descent = symbol.getDescent();
271 		}
272                 
273 		displayToLay.setAscent(ascent);
274 		displayToLay.setDescent(descent);
275         
276 		width += width1 + 4*gap; // 1 gap entre symbole et expression, et 3 aprËs expression  
277         
278 		height += ascent + descent;
279 		displayToLay.setSize(width , height);
280         
281 		displayToLay.setComputeAttributes(false);
282 		return new Dimension(width, height);
283 	}
284     
285 	/***
286 	* The display needs to be rebuilt. We do this.
287 	*/
288 	public void rebuildDisplay() {
289         
290 		//Faudra faire ce qui faut !!!!
291         
292 		// La taille des displays est probablement diffÈrente de ceux qui Ètaient
293 		// prÈcÈdemment. On demande alors le recalcul des display ancÍtres.
294 		displayToLay.computeAncestorsAttributes();
295 	}
296    
297 }