35301c1fab4e9cb83fab4ebed2da4c0faf5facc9
[jalview.git] / src / 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.Serializable;
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 /**
42  * A size that contains minimum, preferred and maximum size of type
43  * {@link UnitValue}.
44  * <p>
45  * This class is a simple value container and it is immutable.
46  * <p>
47  * If a size is missing (i.e., <code>null</code>) that boundary should be
48  * considered "not in use".
49  * <p>
50  * You can create a BoundSize from a String with the use of
51  * {@link ConstraintParser#parseBoundSize(String, boolean, boolean)}
52  */
53 public class BoundSize implements Serializable
54 {
55   public static final BoundSize NULL_SIZE = new BoundSize(null, null);
56
57   public static final BoundSize ZERO_PIXEL = new BoundSize(UnitValue.ZERO,
58           "0px");
59
60   private final transient UnitValue min;
61
62   private final transient UnitValue pref;
63
64   private final transient UnitValue max;
65
66   private final transient boolean gapPush;
67
68   /**
69    * Constructor that use the same value for min/preferred/max size.
70    * 
71    * @param minMaxPref
72    *          The value to use for min/preferred/max size.
73    * @param createString
74    *          The string used to create the BoundsSize.
75    */
76   public BoundSize(UnitValue minMaxPref, String createString)
77   {
78     this(minMaxPref, minMaxPref, minMaxPref, createString);
79   }
80
81   /**
82    * Constructor. <b>This method is here for serialization only and should
83    * normally not be used.</b> Use
84    * {@link ConstraintParser#parseBoundSize(String, boolean, boolean)} instead.
85    * 
86    * @param min
87    *          The minimum size. May be <code>null</code>.
88    * @param preferred
89    *          The preferred size. May be <code>null</code>.
90    * @param max
91    *          The maximum size. May be <code>null</code>.
92    * @param createString
93    *          The string used to create the BoundsSize.
94    */
95   public BoundSize(UnitValue min, UnitValue preferred, UnitValue max,
96           String createString) // Bound to old delegate!!!!!
97   {
98     this(min, preferred, max, false, createString);
99   }
100
101   /**
102    * Constructor. <b>This method is here for serialization only and should
103    * normally not be used.</b> Use
104    * {@link ConstraintParser#parseBoundSize(String, boolean, boolean)} instead.
105    * 
106    * @param min
107    *          The minimum size. May be <code>null</code>.
108    * @param preferred
109    *          The preferred size. May be <code>null</code>.
110    * @param max
111    *          The maximum size. May be <code>null</code>.
112    * @param gapPush
113    *          If the size should be hinted as "pushing" and thus want to occupy
114    *          free space if no one else is claiming it.
115    * @param createString
116    *          The string used to create the BoundsSize.
117    */
118   public BoundSize(UnitValue min, UnitValue preferred, UnitValue max,
119           boolean gapPush, String createString)
120   {
121     this.min = min;
122     this.pref = preferred;
123     this.max = max;
124     this.gapPush = gapPush;
125
126     LayoutUtil.putCCString(this, createString); // this escapes!!
127   }
128
129   /**
130    * Returns the minimum size as sent into the constructor.
131    * 
132    * @return The minimum size as sent into the constructor. May be
133    *         <code>null</code>.
134    */
135   public final UnitValue getMin()
136   {
137     return min;
138   }
139
140   /**
141    * Returns the preferred size as sent into the constructor.
142    * 
143    * @return The preferred size as sent into the constructor. May be
144    *         <code>null</code>.
145    */
146   public final UnitValue getPreferred()
147   {
148     return pref;
149   }
150
151   /**
152    * Returns the maximum size as sent into the constructor.
153    * 
154    * @return The maximum size as sent into the constructor. May be
155    *         <code>null</code>.
156    */
157   public final UnitValue getMax()
158   {
159     return max;
160   }
161
162   /**
163    * If the size should be hinted as "pushing" and thus want to occupy free
164    * space if no one else is claiming it.
165    * 
166    * @return The value.
167    */
168   public boolean getGapPush()
169   {
170     return gapPush;
171   }
172
173   /**
174    * Returns if this bound size has no min, preferred and maximum size set (they
175    * are all <code>null</code>)
176    * 
177    * @return If unset.
178    */
179   public boolean isUnset()
180   {
181     // Most common case by far is this == ZERO_PIXEL...
182     return this == ZERO_PIXEL || (pref == null && min == null && max == null
183             && gapPush == false);
184   }
185
186   /**
187    * Makes sure that <code>size</code> is within min and max of this size.
188    * 
189    * @param size
190    *          The size to constrain.
191    * @param refValue
192    *          The reference to use for relative sizes.
193    * @param parent
194    *          The parent container.
195    * @return The size, constrained within min and max.
196    */
197   public int constrain(int size, float refValue, ContainerWrapper parent)
198   {
199     if (max != null)
200       size = Math.min(size, max.getPixels(refValue, parent, parent));
201     if (min != null)
202       size = Math.max(size, min.getPixels(refValue, parent, parent));
203     return size;
204   }
205
206   /**
207    * Returns the minimum, preferred or maximum size for this bounded size.
208    * 
209    * @param sizeType
210    *          The type. <code>LayoutUtil.MIN</code>,
211    *          <code>LayoutUtil.PREF</code> or <code>LayoutUtil.MAX</code>.
212    * @return
213    */
214   final UnitValue getSize(int sizeType)
215   {
216     switch (sizeType)
217     {
218     case LayoutUtil.MIN:
219       return min;
220     case LayoutUtil.PREF:
221       return pref;
222     case LayoutUtil.MAX:
223       return max;
224     default:
225       throw new IllegalArgumentException("Unknown size: " + sizeType);
226     }
227   }
228
229   /**
230    * Convert the bound sizes to pixels.
231    * <p>
232    * <code>null</code> bound sizes will be 0 for min and preferred and
233    * {@link net.miginfocom.layout.LayoutUtil#INF} for max.
234    * 
235    * @param refSize
236    *          The reference size.
237    * @param parent
238    *          The parent. Not <code>null</code>.
239    * @param comp
240    *          The component, if applicable, can be <code>null</code>.
241    * @return An array of length three (min,pref,max).
242    */
243   final int[] getPixelSizes(float refSize, ContainerWrapper parent,
244           ComponentWrapper comp)
245   {
246     return new int[] {
247         min != null ? min.getPixels(refSize, parent, comp) : 0,
248         pref != null ? pref.getPixels(refSize, parent, comp) : 0,
249         max != null ? max.getPixels(refSize, parent, comp)
250                 : LayoutUtil.INF };
251   }
252
253   /**
254    * Returns the a constraint string that can be re-parsed to be the exact same
255    * UnitValue.
256    * 
257    * @return A String. Never <code>null</code>.
258    */
259   String getConstraintString()
260   {
261     String cs = LayoutUtil.getCCString(this);
262     if (cs != null)
263       return cs;
264
265     if (min == pref && pref == max)
266       return min != null ? (min.getConstraintString() + "!") : "null";
267
268     StringBuilder sb = new StringBuilder(16);
269
270     if (min != null)
271       sb.append(min.getConstraintString()).append(':');
272
273     if (pref != null)
274     {
275       if (min == null && max != null)
276         sb.append(":");
277       sb.append(pref.getConstraintString());
278     }
279     else if (min != null)
280     {
281       sb.append('n');
282     }
283
284     if (max != null)
285       sb.append(sb.length() == 0 ? "::" : ":")
286               .append(max.getConstraintString());
287
288     if (gapPush)
289     {
290       if (sb.length() > 0)
291         sb.append(':');
292       sb.append("push");
293     }
294
295     return sb.toString();
296   }
297
298   void checkNotLinked()
299   {
300     if (isLinked())
301       throw new IllegalArgumentException("Size may not contain links");
302   }
303
304   boolean isLinked()
305   {
306     return min != null && min.isLinkedDeep()
307             || pref != null && pref.isLinkedDeep()
308             || max != null && max.isLinkedDeep();
309   }
310
311   boolean isAbsolute()
312   {
313     return (min == null || min.isAbsoluteDeep())
314             && (pref == null || pref.isAbsoluteDeep())
315             && (max == null || max.isAbsoluteDeep());
316   }
317
318   public String toString()
319   {
320     return "BoundSize{" + "min=" + min + ", pref=" + pref + ", max=" + max
321             + ", gapPush=" + gapPush + '}';
322   }
323
324 //  static
325 //  {
326 //    if (LayoutUtil.HAS_BEANS)
327 //    {
328 //      LayoutUtil.setDelegate(BoundSize.class, new PersistenceDelegate()
329 //      {
330 //        @Override
331 //        protected Expression instantiate(Object oldInstance, Encoder out)
332 //        {
333 //          BoundSize bs = (BoundSize) oldInstance;
334 //          if (Grid.TEST_GAPS)
335 //          {
336 //            return new Expression(oldInstance, BoundSize.class, "new",
337 //                    new Object[]
338 //                    { bs.getMin(), bs.getPreferred(), bs.getMax(),
339 //                        bs.getGapPush(), bs.getConstraintString() });
340 //          }
341 //          else
342 //          {
343 //            return new Expression(oldInstance, BoundSize.class, "new",
344 //                    new Object[]
345 //                    { bs.getMin(), bs.getPreferred(), bs.getMax(),
346 //                        bs.getConstraintString() });
347 //          }
348 //        }
349 //      });
350 //    }
351 //  }
352
353   // // ************************************************
354   // // Persistence Delegate and Serializable combined.
355   // // ************************************************
356   //
357   // private static final long serialVersionUID = 1L;
358   //
359   // protected Object readResolve() throws ObjectStreamException
360   // {
361   // return LayoutUtil.getSerializedObject(this);
362   // }
363   //
364   // private void writeObject(ObjectOutputStream out) throws IOException
365   // {
366   // if (getClass() == BoundSize.class)
367   // LayoutUtil.writeAsXML(out, this);
368   // }
369   //
370   // private void readObject(ObjectInputStream in) throws IOException,
371   // ClassNotFoundException
372   // {
373   // LayoutUtil.setSerializedObject(this, LayoutUtil.readAsXML(in));
374   // }
375 }