c36d88cee44490ba3317fd6c419f3e092264e4d8
[jalview.git] / src2 / net / miginfocom / layout / DimConstraint.java
1 package net.miginfocom.layout;
2
3 import java.io.Externalizable;
4 import java.io.IOException;
5 import java.io.ObjectInput;
6 import java.io.ObjectOutput;
7 import java.io.ObjectStreamException;
8 /*
9  * License (BSD):
10  * ==============
11  *
12  * Copyright (c) 2004, Mikael Grev, MiG InfoCom AB. (miglayout (at) miginfocom (dot) com)
13  * All rights reserved.
14  *
15  * Redistribution and use in source and binary forms, with or without modification,
16  * are permitted provided that the following conditions are met:
17  * Redistributions of source code must retain the above copyright notice, this list
18  * of conditions and the following disclaimer.
19  * Redistributions in binary form must reproduce the above copyright notice, this
20  * list of conditions and the following disclaimer in the documentation and/or other
21  * materials provided with the distribution.
22  * Neither the name of the MiG InfoCom AB nor the names of its contributors may be
23  * used to endorse or promote products derived from this software without specific
24  * prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
27  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
28  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
29  * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
30  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
31  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
32  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
33  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
35  * OF SUCH DAMAGE.
36  *
37  * @version 1.0
38  * @author Mikael Grev, MiG InfoCom AB
39  *         Date: 2006-sep-08
40  */
41
42 /** A simple value holder for a constraint for one dimension.
43  */
44 public final class DimConstraint implements Externalizable
45 {
46         /** How this entity can be resized in the dimension that this constraint represents.
47          */
48         final ResizeConstraint resize = new ResizeConstraint();
49
50         // Look at the properties' getter/setter methods for explanation
51
52         private String sizeGroup = null;            // A "context" compared with equals.
53
54         private BoundSize size = BoundSize.NULL_SIZE;     // Min, pref, max. Never null, but sizes can be null.
55
56         private BoundSize gapBefore = null, gapAfter = null;
57
58         private UnitValue align = null;
59
60
61         // **************  Only applicable on components! *******************
62
63         private String endGroup = null;            // A "context" compared with equals.
64
65
66         // **************  Only applicable on rows/columns! *******************
67
68         private boolean fill = false;
69
70         private boolean noGrid = false;
71
72         /** Empty constructor.
73          */
74         public DimConstraint()
75         {
76         }
77
78         /** Returns the grow priority. Relative priority is used for determining which entities gets the extra space first.
79          * <p>
80          * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
81          * @return The grow priority.
82          */
83         public int getGrowPriority()
84         {
85                 return resize.growPrio;
86         }
87
88         /** Sets the grow priority. Relative priority is used for determining which entities gets the extra space first.
89          * <p>
90          * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
91          * @param p The new grow priority.
92          */
93         public void setGrowPriority(int p)
94         {
95                 resize.growPrio = p;
96         }
97
98         /** Returns the grow weight.<p>
99          * Grow weight is how flexible the entity should be, relative to other entities, when it comes to growing. <code>null</code> or
100          * zero mean it will never grow. An entity that has twice the grow weight compared to another entity will get twice
101          * as much of available space.
102          * <p>
103          * GrowWeight are only compared within the same GrowPrio.
104          * <p>
105          * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
106          * @return The current grow weight.
107          */
108         public Float getGrow()
109         {
110                 return resize.grow;
111         }
112
113         /** Sets the grow weight.<p>
114          * Grow weight is how flexible the entity should be, relative to other entities, when it comes to growing. <code>null</code> or
115          * zero mean it will never grow. An entity that has twice the grow weight compared to another entity will get twice
116          * as much of available space.
117          * <p>
118          * GrowWeight are only compared within the same GrowPrio.
119          * <p>
120          * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
121          * @param weight The new grow weight.
122          */
123         public void setGrow(Float weight)
124         {
125                 resize.grow = weight;
126         }
127
128         /** Returns the shrink priority. Relative priority is used for determining which entities gets smaller first when space is scarce.
129          * <p>
130          * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
131          * @return The shrink priority.
132          */
133         public int getShrinkPriority()
134         {
135                 return resize.shrinkPrio;
136         }
137
138         /** Sets the shrink priority. Relative priority is used for determining which entities gets smaller first when space is scarce.
139          * <p>
140          * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
141          * @param p The new shrink priority.
142          */
143         public void setShrinkPriority(int p)
144         {
145                 resize.shrinkPrio = p;
146         }
147
148         /** Returns the shrink priority. Relative priority is used for determining which entities gets smaller first when space is scarce.
149          * Shrink weight is how flexible the entity should be, relative to other entities, when it comes to shrinking. <code>null</code> or
150          * zero mean it will never shrink (default). An entity that has twice the shrink weight compared to another entity will get twice
151          * as much of available space.
152          * <p>
153          * Shrink(Weight) are only compared within the same ShrinkPrio.
154          * <p>
155          * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
156          * @return The current shrink weight.
157          */
158         public Float getShrink()
159         {
160                 return resize.shrink;
161         }
162
163         /** Sets the shrink priority. Relative priority is used for determining which entities gets smaller first when space is scarce.
164          * Shrink weight is how flexible the entity should be, relative to other entities, when it comes to shrinking. <code>null</code> or
165          * zero mean it will never shrink (default). An entity that has twice the shrink weight compared to another entity will get twice
166          * as much of available space.
167          * <p>
168          * Shrink(Weight) are only compared within the same ShrinkPrio.
169          * <p>
170          * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
171          * @param weight The new shrink weight.
172          */
173         public void setShrink(Float weight)
174         {
175                 resize.shrink = weight;
176         }
177
178         public UnitValue getAlignOrDefault(boolean isCols)
179         {
180                 if (align != null)
181                         return align;
182
183                 if (isCols)
184                         return UnitValue.LEADING;
185
186                 return fill || PlatformDefaults.getDefaultRowAlignmentBaseline() == false ? UnitValue.CENTER : UnitValue.BASELINE_IDENTITY;
187         }
188
189         /** Returns the alignment used either as a default value for sub-entities or for this entity.
190          * <p>
191          * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
192          * @return The alignment.
193          */
194         public UnitValue getAlign()
195         {
196                 return align;
197         }
198
199         /** Sets the alignment used wither as a default value for sub-entities or for this entity.
200          * <p>
201          * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
202          * @param uv The new shrink priority. E.g. {@link UnitValue#CENTER} or {@link net.miginfocom.layout.UnitValue#LEADING}.
203          */
204         public void setAlign(UnitValue uv)
205         {
206                 this.align = uv;
207         }
208
209         /** Returns the gap after this entity. The gap is an empty space and can have a min/preferred/maximum size so that it can shrink and
210          * grow depending on available space. Gaps are against other entities' edges and not against other entities' gaps.
211          * <p>
212          * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
213          * @return The gap after this entity
214          */
215         public BoundSize getGapAfter()
216         {
217                 return gapAfter;
218         }
219
220         /** Sets the gap after this entity. The gap is an empty space and can have a min/preferred/maximum size so that it can shrink and
221          * grow depending on available space. Gaps are against other entities' edges and not against other entities' gaps.
222          * <p>
223          * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
224          * @param size The new gap.
225          * @see net.miginfocom.layout.ConstraintParser#parseBoundSize(String, boolean, boolean) 
226          */
227         public void setGapAfter(BoundSize size)
228         {
229                 this.gapAfter = size;
230         }
231
232         boolean hasGapAfter()
233         {
234                 return gapAfter != null && gapAfter.isUnset() == false;
235         }
236
237         boolean isGapAfterPush()
238         {
239                 return gapAfter != null && gapAfter.getGapPush();
240         }
241
242         /** Returns the gap before this entity. The gap is an empty space and can have a min/preferred/maximum size so that it can shrink and
243          * grow depending on available space. Gaps are against other entities' edges and not against other entities' gaps.
244          * <p>
245          * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
246          * @return The gap before this entity
247          */
248         public BoundSize getGapBefore()
249         {
250                 return gapBefore;
251         }
252
253         /** Sets the gap before this entity. The gap is an empty space and can have a min/preferred/maximum size so that it can shrink and
254          * grow depending on available space. Gaps are against other entities' edges and not against other entities' gaps.
255          * <p>
256          * See also {@link net.miginfocom.layout.ConstraintParser#parseBoundSize(String, boolean, boolean)}.
257          * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
258          * @param size The new gap.
259          */
260         public void setGapBefore(BoundSize size)
261         {
262                 this.gapBefore = size;
263         }
264
265         boolean hasGapBefore()
266         {
267                 return gapBefore != null && gapBefore.isUnset() == false;
268         }
269
270         boolean isGapBeforePush()
271         {
272                 return gapBefore != null && gapBefore.getGapPush();
273         }
274
275         /** Returns the min/preferred/max size for the entity in the dimension that this object describes.
276          * <p>
277      * See also {@link net.miginfocom.layout.ConstraintParser#parseBoundSize(String, boolean, boolean)}.
278          * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
279          * @return The current size. Never <code>null</code> since v3.5.
280          */
281         public BoundSize getSize()
282         {
283                 return size;
284         }
285
286         /** Sets the min/preferred/max size for the entity in the dimension that this object describes.
287          * <p>
288          * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
289          * @param size The new size. May be <code>null</code>.
290          */
291         public void setSize(BoundSize size)
292         {
293                 if (size != null)
294                         size.checkNotLinked();
295                 this.size = size;
296         }
297
298         /** Returns the size group that this entity should be in for the dimension that this object is describing.
299          * If this constraint is in a size group that is specified here. <code>null</code> means no size group
300          * and all other values are legal. Comparison with .equals(). Components/columns/rows in the same size group
301          * will have the same min/preferred/max size; that of the largest in the group for the first two and the
302          * smallest for max.
303          * <p>
304          * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
305          * @return The current size group. May be <code>null</code>.
306          */
307         public String getSizeGroup()
308         {
309                 return sizeGroup;
310         }
311
312         /** Sets the size group that this entity should be in for the dimension that this object is describing.
313          * If this constraint is in a size group that is specified here. <code>null</code> means no size group
314          * and all other values are legal. Comparison with .equals(). Components/columns/rows in the same size group
315          * will have the same min/preferred/max size; that of the largest in the group for the first two and the
316          * smallest for max.
317          * <p>
318          * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
319          * @param s The new size group. <code>null</code> disables size grouping.
320          */
321         public void setSizeGroup(String s)
322         {
323                 sizeGroup = s;
324         }
325
326         // **************  Only applicable on components ! *******************
327
328         /** Returns the end group that this entity should be in for the dimension that this object is describing.
329          * If this constraint is in an end group that is specified here. <code>null</code> means no end group
330          * and all other values are legal. Comparison with .equals(). Components in the same end group
331          * will have the same end coordinate.
332          * <p>
333          * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
334          * @return The current end group. <code>null</code> may be returned.
335          */
336         public String getEndGroup()
337         {
338                 return endGroup;
339         }
340
341         /** Sets the end group that this entity should be in for the dimension that this object is describing.
342          * If this constraint is in an end group that is specified here. <code>null</code> means no end group
343          * and all other values are legal. Comparison with .equals(). Components in the same end group
344          * will have the same end coordinate.
345          * <p>
346          * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
347          * @param s The new end group. <code>null</code> disables end grouping.
348          */
349         public void setEndGroup(String s)
350         {
351                 endGroup = s;
352         }
353
354         // **************  Not applicable on components below ! *******************
355
356         /** Returns if the component in the row/column that this constraint should default be grown in the same dimension that
357          * this constraint represents (width for column and height for a row).
358          * <p>
359          * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
360          * @return <code>true</code> means that components should grow.
361          */
362         public boolean isFill()
363         {
364                 return fill;
365         }
366
367         /** Sets if the component in the row/column that this constraint should default be grown in the same dimension that
368          * this constraint represents (width for column and height for a row).
369          * <p>
370          * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
371          * @param b <code>true</code> means that components should grow.
372          */
373         public void setFill(boolean b)
374         {
375                 fill = b;
376         }
377
378         /** Returns if the row/column should default to flow and not to grid behaviour. This means that the whole row/column
379          * will be one cell and all components will end up in that cell.
380          * <p>
381          * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
382          * @return <code>true</code> means that the whole row/column should be one cell.
383          */
384         public boolean isNoGrid()
385         {
386                 return noGrid;
387         }
388
389         /** Sets if the row/column should default to flow and not to grid behaviour. This means that the whole row/column
390          * will be one cell and all components will end up in that cell.
391          * <p>
392          * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
393          * @param b <code>true</code> means that the whole row/column should be one cell.
394          */
395         public void setNoGrid(boolean b)
396         {
397                 this.noGrid = b;
398         }
399
400         /** Returns the gaps as pixel values.
401          * @param parent The parent. Used to get the pixel values.
402          * @param defGap The default gap to use if there is no gap set on this object (i.e. it is null).
403          * @param refSize The reference size used to get the pixel sizes.
404          * @param before IF it is the gap before rather than the gap after to return.
405          * @return The [min,preferred,max] sizes for the specified gap. Uses {@link net.miginfocom.layout.LayoutUtil#NOT_SET}
406          * for gap sizes that are <code>null</code>. Returns <code>null</code> if there was no gap specified. A new and free to use array.
407          */
408         int[] getRowGaps(ContainerWrapper parent, BoundSize defGap, int refSize, boolean before)
409         {
410                 BoundSize gap = before ? gapBefore : gapAfter;
411                 if (gap == null || gap.isUnset())
412                         gap = defGap;
413
414                 if (gap == null || gap.isUnset())
415                         return null;
416
417                 int[] ret = new int[3];
418                 for (int i = LayoutUtil.MIN; i <= LayoutUtil.MAX; i++) {
419                         UnitValue uv = gap.getSize(i);
420                         ret[i] = uv != null ? uv.getPixels(refSize, parent, null) : LayoutUtil.NOT_SET;
421                 }
422                 return ret;
423         }
424
425         /** Returns the gaps as pixel values.
426          * @param parent The parent. Used to get the pixel values.
427          * @param comp The component that the gap is for. If not for a component it is <code>null</code>.
428          * @param adjGap The gap that the adjacent component, if any, has towards <code>comp</code>.
429          * @param adjacentComp The adjacent component if any. May be <code>null</code>.
430          * @param refSize The reference size used to get the pixel sizes.
431          * @param adjacentSide What side the <code>adjacentComp</code> is on. 0 = top, 1 = left, 2 = bottom, 3 = right.
432          * @param tag The tag string that the component might be tagged with in the component constraints. May be <code>null</code>.
433          * @param isLTR If it is left-to-right.
434          * @return The [min,preferred,max] sizes for the specified gap. Uses {@link net.miginfocom.layout.LayoutUtil#NOT_SET}
435          * for gap sizes that are <code>null</code>. Returns <code>null</code> if there was no gap specified. A new and free to use array.
436          */
437         int[] getComponentGaps(ContainerWrapper parent, ComponentWrapper comp, BoundSize adjGap, ComponentWrapper adjacentComp, String tag, int refSize, int adjacentSide, boolean isLTR)
438         {
439                 BoundSize gap = adjacentSide < 2 ? gapBefore : gapAfter;
440
441                 boolean hasGap = gap != null && gap.getGapPush();
442                 if ((gap == null || gap.isUnset()) && (adjGap == null || adjGap.isUnset()) && comp != null)
443                         gap = PlatformDefaults.getDefaultComponentGap(comp, adjacentComp, adjacentSide + 1, tag, isLTR);
444
445                 if (gap == null)
446                         return hasGap ? new int[] {0, 0, LayoutUtil.NOT_SET} : null;
447
448                 int[] ret = new int[3];
449                 for (int i = LayoutUtil.MIN; i <= LayoutUtil.MAX; i++) {
450                         UnitValue uv = gap.getSize(i);
451                         ret[i] = uv != null ? uv.getPixels(refSize, parent, null) : LayoutUtil.NOT_SET;
452                 }
453                 return ret;
454         }
455
456         // ************************************************
457         // Persistence Delegate and Serializable combined.
458         // ************************************************
459
460         private Object readResolve() throws ObjectStreamException
461         {
462                 return LayoutUtil.getSerializedObject(this);
463         }
464
465         @Override
466         public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException
467         {
468                 LayoutUtil.setSerializedObject(this, LayoutUtil.readAsXML(in));
469         }
470
471         @Override
472         public void writeExternal(ObjectOutput out) throws IOException
473         {
474                 if (getClass() == DimConstraint.class)
475                         LayoutUtil.writeAsXML(out, this);
476         }
477 }