UIW: fix bug in normalized position
[scilab.git] / scilab / modules / gui / src / java / org / scilab / modules / gui / uiwidget / components / NoLayout.java
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2012 - Scilab Enterprises - Calixte DENIZET
4  *
5  * This file must be used under the terms of the CeCILL.
6  * This source file is licensed as described in the file COPYING, which
7  * you should have received as part of this distribution.  The terms
8  * are also available at
9  * http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
10  *
11  */
12
13 package org.scilab.modules.gui.uiwidget.components;
14
15 import java.awt.Component;
16 import java.awt.Container;
17 import java.awt.Dimension;
18 import java.awt.LayoutManager2;
19 import java.awt.Rectangle;
20 import java.awt.Toolkit;
21 import java.awt.geom.Rectangle2D;
22 import java.util.IdentityHashMap;
23 import java.util.Map;
24 import javax.swing.JComponent;
25
26 /**
27  * NoLayout: Layout Manager to lay out a la Scilab
28  * When a component is added with a constraint NoLayoutConstraint this last one
29  * can be directly modified: it is linked with the component (via a Map).
30  */
31 public class NoLayout implements LayoutManager2 {
32
33     public static final int UNIT_PIXELS = 0;
34     public static final int UNIT_NORMALIZED = 1;
35     public static final int UNIT_POINTS = 2;
36
37     private Map<Component, NoLayoutConstraint> map;
38
39     /**
40      * Default constructor
41      */
42     public NoLayout() {
43         map = new IdentityHashMap<Component, NoLayoutConstraint>();
44     }
45
46     /**
47      * {@inheritDoc}
48      */
49     public void addLayoutComponent(Component comp, Object constraints) {
50         if (comp != null && constraints instanceof NoLayoutConstraint) {
51             map.put(comp, (NoLayoutConstraint) constraints);
52         }
53     }
54
55     /**
56      * Get the component constraints
57      * @param comp the component
58      * @return the constraints
59      */
60     public Object getConstraints(Component comp) {
61         return map.get(comp);
62     }
63
64     /**
65      * {@inheritDoc}
66      */
67     public float getLayoutAlignmentX(Container target) {
68         return 0.5f;
69     }
70
71     /**
72      * {@inheritDoc}
73      */
74     public float getLayoutAlignmentY(Container target) {
75         return 0.5f;
76     }
77
78     /**
79      * {@inheritDoc}
80      */
81     public void invalidateLayout(Container target) {
82
83     }
84
85     /**
86      * {@inheritDoc}
87      */
88     public Dimension maximumLayoutSize(Container target) {
89         return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
90     }
91
92     /**
93      * {@inheritDoc}
94      */
95     public void addLayoutComponent(String name, Component comp) {
96
97     }
98
99     private final double getResolutionScale() {
100         return ((double) Toolkit.getDefaultToolkit().getScreenResolution()) / 72.0d;
101     }
102
103     /**
104      * {@inheritDoc}
105      */
106     public void layoutContainer(Container parent) {
107         synchronized (parent.getTreeLock()) {
108             final int ncomponents = parent.getComponentCount();
109             if (ncomponents == 0) {
110                 return;
111             }
112
113             final Rectangle rp = parent.getBounds();
114             final Rectangle rr = new Rectangle();
115             final double scale = getResolutionScale();
116
117             for (int i = 0; i < ncomponents; i++) {
118                 final Component c = parent.getComponent(i);
119                 final NoLayoutConstraint constraint = map.get(c);
120                 if (constraint != null) {
121                     switch (constraint.unit[0]) {
122                         case UNIT_NORMALIZED: // normalized unit
123                             rr.x = (int) (correct(constraint.bounds.x) * rp.width);
124                             break;
125                         case UNIT_POINTS: // point unit
126                             rr.x = (int) (constraint.bounds.x * scale);
127                             break;
128                         default: // pixel unit
129                             rr.x = (int) constraint.bounds.x;
130                             break;
131                     }
132
133                     switch (constraint.unit[2]) {
134                         case UNIT_NORMALIZED:
135                             rr.width = (int) (correct(constraint.bounds.width) * rp.width);
136                             break;
137                         case UNIT_POINTS:
138                             rr.width = (int) (constraint.bounds.width * scale);
139                             break;
140                         default:
141                             rr.width = (int) constraint.bounds.width;
142                             break;
143                     }
144
145                     switch (constraint.unit[3]) {
146                         case UNIT_NORMALIZED:
147                             rr.height = (int) (correct(constraint.bounds.height) * rp.height);
148                             break;
149                         case UNIT_POINTS:
150                             rr.height = (int) (constraint.bounds.height * scale);
151                             break;
152                         default:
153                             rr.height = (int) constraint.bounds.height;
154                             break;
155                     }
156
157                     switch (constraint.unit[1]) {
158                         case UNIT_NORMALIZED:
159                             rr.y = (int) (rp.height * (1 - correct(constraint.bounds.y))) - rr.height;
160                             break;
161                         case UNIT_POINTS:
162                             rr.y = (int) (rp.height - constraint.bounds.y * scale) - rr.height;
163                             break;
164                         default:
165                             rr.y = (int) (rp.height - constraint.bounds.y) - rr.height;
166                             break;
167                     }
168
169                     if (!c.getBounds().equals(rr)) {
170                         c.setBounds(rr);
171                         /*if (bounds.width != rr.width || bounds .height != rr.height) {
172                             if (c instanceof JComponent) {
173                                 ((JComponent) c).revalidate();
174                             } else {
175                                 c.invalidate();
176                                 c.validate();
177                             }
178                             }*/
179                     }
180                 }
181             }
182         }
183     }
184
185     /**
186      * {@inheritDoc}
187      */
188     public Dimension minimumLayoutSize(Container parent) {
189         return new Dimension(0, 0);
190     }
191
192     /**
193      * {@inheritDoc}
194      */
195     public Dimension preferredLayoutSize(Container parent) {
196         synchronized (parent.getTreeLock()) {
197             return parent.getSize();
198         }
199     }
200
201     /**
202      * {@inheritDoc}
203      */
204     public void removeLayoutComponent(Component comp) {
205         map.remove(comp);
206     }
207
208     /**
209      * @return a value between 0 and 1
210      */
211     private static double correct(double x) {
212         return x >= 0 ? (x >= 1 ? 1 : x) : 0;
213     }
214
215     public static class NoLayoutConstraint {
216
217         public Rectangle2D.Double bounds = new Rectangle2D.Double();
218         public int[] unit = new int[4];
219
220         public NoLayoutConstraint() {
221         }
222
223         public NoLayoutConstraint(double x, double y, double w, double h, int unit) {
224             this(x, y, w, h, unit, unit, unit, unit);
225         }
226
227         public NoLayoutConstraint(double x, double y, double w, double h, int xUnit, int yUnit, int wUnit, int hUnit) {
228             this();
229             setPoint(x, y);
230             setDims(w, h);
231             setUnit(xUnit, yUnit, wUnit, hUnit);
232         }
233
234         public void setPoint(double x, double y) {
235             bounds.x = x;
236             bounds.y = y;
237         }
238
239         public void setDims(double w, double h) {
240             bounds.width = w;
241             bounds.height = h;
242         }
243
244         public void setUnit(int x, int y, int w, int h) {
245             unit[0] = x;
246             unit[1] = y;
247             unit[2] = w;
248             unit[3] = h;
249         }
250
251
252         public String toString() {
253             return "NoLayoutConstraint:" + bounds + " units:" + unit[0] + ";" + unit[1] + ";" + unit[2] + ";" + unit[3];
254         }
255     }
256 }