531235f039834416e126bccb71ed6c6f602b59a7
[jalview.git] / srcjar / net / miginfocom / layout / BoundSize.java
1 package net.miginfocom.layout;
2
3 import java.beans.Encoder;
4 import java.beans.Expression;
5 import java.beans.PersistenceDelegate;
6 import java.io.*;
7 /*
8  * License (BSD):
9  * ==============
10  *
11  * Copyright (c) 2004, Mikael Grev, MiG InfoCom AB. (miglayout (at) miginfocom (dot) com)
12  * All rights reserved.
13  *
14  * Redistribution and use in source and binary forms, with or without modification,
15  * are permitted provided that the following conditions are met:
16  * Redistributions of source code must retain the above copyright notice, this list
17  * of conditions and the following disclaimer.
18  * Redistributions in binary form must reproduce the above copyright notice, this
19  * list of conditions and the following disclaimer in the documentation and/or other
20  * materials provided with the distribution.
21  * Neither the name of the MiG InfoCom AB nor the names of its contributors may be
22  * used to endorse or promote products derived from this software without specific
23  * prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
27  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
28  * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
29  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
30  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
31  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
32  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
34  * OF SUCH DAMAGE.
35  *
36  * @version 1.0
37  * @author Mikael Grev, MiG InfoCom AB
38  *         Date: 2006-sep-08
39  */
40
41 /** A size that contains minimum, preferred and maximum size of type {@link UnitValue}.
42  * <p>
43  * This class is a simple value container and it is immutable.
44  * <p>
45  * If a size is missing (i.e., <code>null</code>) that boundary should be considered "not in use".
46  * <p>
47  * You can create a BoundSize from a String with the use of {@link ConstraintParser#parseBoundSize(String, boolean, boolean)}
48  */
49 public class BoundSize implements Serializable
50 {
51         public static final BoundSize NULL_SIZE = new BoundSize(null, null);
52         public static final BoundSize ZERO_PIXEL = new BoundSize(UnitValue.ZERO, "0px");
53
54         private final transient UnitValue min;
55         private final transient UnitValue pref;
56         private final transient UnitValue max;
57         private final transient boolean gapPush;
58
59         /** Constructor that use the same value for min/preferred/max size.
60          * @param minMaxPref The value to use for min/preferred/max size.
61          * @param createString The string used to create the BoundsSize.
62          */
63         public BoundSize(UnitValue minMaxPref, String createString)
64         {
65                 this(minMaxPref, minMaxPref, minMaxPref, createString);
66         }
67
68         /** Constructor. <b>This method is here for serialization only and should normally not be used.</b> Use
69          * {@link ConstraintParser#parseBoundSize(String, boolean, boolean)} instead.
70          * @param min The minimum size. May be <code>null</code>.
71          * @param preferred  The preferred size. May be <code>null</code>.
72          * @param max  The maximum size. May be <code>null</code>.
73          * @param createString The string used to create the BoundsSize.
74          */
75         public BoundSize(UnitValue min, UnitValue preferred, UnitValue max, String createString)    // Bound to old delegate!!!!!
76         {
77                 this(min, preferred, max, false, createString);
78         }
79
80         /** Constructor. <b>This method is here for serialization only and should normally not be used.</b> Use
81          * {@link ConstraintParser#parseBoundSize(String, boolean, boolean)} instead.
82          * @param min The minimum size. May be <code>null</code>.
83          * @param preferred  The preferred size. May be <code>null</code>.
84          * @param max  The maximum size. May be <code>null</code>.
85          * @param gapPush If the size should be hinted as "pushing" and thus want to occupy free space if no one else is claiming it.
86          * @param createString The string used to create the BoundsSize.
87          */
88         public BoundSize(UnitValue min, UnitValue preferred, UnitValue max, boolean gapPush, String createString)
89         {
90                 this.min = min;
91                 this.pref = preferred;
92                 this.max = max;
93                 this.gapPush = gapPush;
94
95                 LayoutUtil.putCCString(this, createString);    // this escapes!!
96         }
97
98         /** Returns the minimum size as sent into the constructor.
99          * @return The minimum size as sent into the constructor. May be <code>null</code>.
100          */
101         public final UnitValue getMin()
102         {
103                 return min;
104         }
105
106         /** Returns the preferred size as sent into the constructor.
107          * @return The preferred size as sent into the constructor. May be <code>null</code>.
108          */
109         public final UnitValue getPreferred()
110         {
111                 return pref;
112         }
113
114         /** Returns the maximum size as sent into the constructor.
115          * @return The maximum size as sent into the constructor. May be <code>null</code>.
116          */
117         public final UnitValue getMax()
118         {
119                 return max;
120         }
121
122         /** If the size should be hinted as "pushing" and thus want to occupy free space if no one else is claiming it.
123          * @return The value.
124          */
125         public boolean getGapPush()
126         {
127                 return gapPush;
128         }
129
130         /** Returns if this bound size has no min, preferred and maximum size set (they are all <code>null</code>)
131          * @return If unset.
132          */
133         public boolean isUnset()
134         {
135                 // Most common case by far is this == ZERO_PIXEL...
136                 return this == ZERO_PIXEL || (pref == null && min == null && max == null && gapPush == false);
137         }
138
139         /** Makes sure that <code>size</code> is within min and max of this size.
140          * @param size The size to constrain.
141          * @param refValue The reference to use for relative sizes.
142          * @param parent The parent container.
143          * @return The size, constrained within min and max.
144          */
145         public int constrain(int size, float refValue, ContainerWrapper parent)
146         {
147                 if (max != null)
148                         size = Math.min(size, max.getPixels(refValue, parent, parent));
149                 if (min != null)
150                         size = Math.max(size, min.getPixels(refValue, parent, parent));
151                 return size;
152         }
153
154         /** Returns the minimum, preferred or maximum size for this bounded size.
155          * @param sizeType The type. <code>LayoutUtil.MIN</code>, <code>LayoutUtil.PREF</code> or <code>LayoutUtil.MAX</code>.
156          * @return
157          */
158         final UnitValue getSize(int sizeType)
159         {
160                 switch(sizeType) {
161                         case LayoutUtil.MIN:
162                                 return min;
163                         case LayoutUtil.PREF:
164                                 return pref;
165                         case LayoutUtil.MAX:
166                                 return max;
167                         default:
168                                 throw new IllegalArgumentException("Unknown size: " + sizeType);
169                 }
170         }
171
172         /** Convert the bound sizes to pixels.
173          * <p>
174          * <code>null</code> bound sizes will be 0 for min and preferred and {@link net.miginfocom.layout.LayoutUtil#INF} for max.
175          * @param refSize The reference size.
176          * @param parent The parent. Not <code>null</code>.
177          * @param comp The component, if applicable, can be <code>null</code>.
178          * @return An array of length three (min,pref,max).
179          */
180         final int[] getPixelSizes(float refSize, ContainerWrapper parent, ComponentWrapper comp)
181         {
182                 return new int[] {
183                                 min != null ? min.getPixels(refSize, parent, comp) : 0,
184                                 pref != null ? pref.getPixels(refSize, parent, comp) : 0,
185                                 max != null ? max.getPixels(refSize, parent, comp) : LayoutUtil.INF
186                 };
187         }
188
189         /** Returns the a constraint string that can be re-parsed to be the exact same UnitValue.
190          * @return A String. Never <code>null</code>.
191          */
192         String getConstraintString()
193         {
194                 String cs = LayoutUtil.getCCString(this);
195                 if (cs != null)
196                         return cs;
197
198                 if (min == pref && pref == max)
199                         return min != null ? (min.getConstraintString() + "!") : "null";
200
201                 StringBuilder sb = new StringBuilder(16);
202
203                 if (min != null)
204                         sb.append(min.getConstraintString()).append(':');
205
206                 if (pref != null) {
207                         if (min == null && max != null)
208                                 sb.append(":");
209                         sb.append(pref.getConstraintString());
210                 } else if (min != null) {
211                         sb.append('n');
212                 }
213
214                 if (max != null)
215                         sb.append(sb.length() == 0 ? "::" : ":").append(max.getConstraintString());
216
217                 if (gapPush) {
218                         if (sb.length() > 0)
219                                 sb.append(':');
220                         sb.append("push");
221                 }
222
223                 return sb.toString();
224         }
225
226         void checkNotLinked()
227         {
228                 if (isLinked())
229                         throw new IllegalArgumentException("Size may not contain links");
230         }
231
232         boolean isLinked()
233         {
234                 return min != null && min.isLinkedDeep() || pref != null && pref.isLinkedDeep() || max != null && max.isLinkedDeep();
235         }
236
237         boolean isAbsolute()
238         {
239                 return (min == null || min.isAbsoluteDeep()) && (pref == null || pref.isAbsoluteDeep()) && (max == null || max.isAbsoluteDeep());
240         }
241
242         public String toString()
243         {
244                 return "BoundSize{" + "min=" + min + ", pref=" + pref + ", max=" + max + ", gapPush=" + gapPush +'}';
245         }
246
247         static {
248         if(LayoutUtil.HAS_BEANS){
249             LayoutUtil.setDelegate(BoundSize.class, new PersistenceDelegate() {
250                 @Override
251                 protected Expression instantiate(Object oldInstance, Encoder out)
252                 {
253                     BoundSize bs = (BoundSize) oldInstance;
254                     if (Grid.TEST_GAPS) {
255                         return new Expression(oldInstance, BoundSize.class, "new", new Object[] {
256                                 bs.getMin(), bs.getPreferred(), bs.getMax(), bs.getGapPush(), bs.getConstraintString()
257                         });
258                     } else {
259                         return new Expression(oldInstance, BoundSize.class, "new", new Object[] {
260                                 bs.getMin(), bs.getPreferred(), bs.getMax(), bs.getConstraintString()
261                         });
262                     }
263                 }
264             });
265         }
266         }
267
268         // ************************************************
269         // Persistence Delegate and Serializable combined.
270         // ************************************************
271
272         private static final long serialVersionUID = 1L;
273
274         protected Object readResolve() throws ObjectStreamException
275         {
276                 return LayoutUtil.getSerializedObject(this);
277         }
278
279         private void writeObject(ObjectOutputStream out) throws IOException
280         {
281                 if (getClass() == BoundSize.class)
282                         LayoutUtil.writeAsXML(out, this);
283         }
284
285         private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException
286         {
287                 LayoutUtil.setSerializedObject(this, LayoutUtil.readAsXML(in));
288         }
289 }