package net.miginfocom.layout;
import java.beans.Encoder;
import java.beans.Expression;
import java.beans.PersistenceDelegate;
import java.io.*;
/*
* License (BSD):
* ==============
*
* Copyright (c) 2004, Mikael Grev, MiG InfoCom AB. (miglayout (at) miginfocom (dot) com)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
* Neither the name of the MiG InfoCom AB nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* @version 1.0
* @author Mikael Grev, MiG InfoCom AB
* Date: 2006-sep-08
*/
/**
* A size that contains minimum, preferred and maximum size of type
* {@link UnitValue}.
* <p>
* This class is a simple value container and it is immutable.
* <p>
* If a size is missing (i.e., <code>null</code>) that boundary should be
* considered "not in use".
* <p>
* You can create a BoundSize from a String with the use of
* {@link ConstraintParser#parseBoundSize(String, boolean, boolean)}
*/
public class BoundSize implements Serializable {
public static final BoundSize NULL_SIZE = new BoundSize(null, null);
public static final BoundSize ZERO_PIXEL = new BoundSize(UnitValue.ZERO,
"0px");
private final transient UnitValue min;
private final transient UnitValue pref;
private final transient UnitValue max;
private final transient boolean gapPush;
/**
* Constructor that use the same value for min/preferred/max size.
*
* @param minMaxPref
* The value to use for min/preferred/max size.
* @param createString
* The string used to create the BoundsSize.
*/
public BoundSize(UnitValue minMaxPref, String createString) {
this(minMaxPref, minMaxPref, minMaxPref, createString);
}
/**
* Constructor. <b>This method is here for serilization only and should
* normally not be used. Use
* {@link ConstraintParser#parseBoundSize(String, boolean, boolean)}
* instead.
*
* @param min
* The minimum size. May be <code>null</code>.
* @param preferred
* The preferred size. May be <code>null</code>.
* @param max
* The maximum size. May be <code>null</code>.
* @param createString
* The string used to create the BoundsSize.
*/
public BoundSize(UnitValue min, UnitValue preferred, UnitValue max,
String createString) // Bound to old delegate!!!!!
{
this(min, preferred, max, false, createString);
}
/**
* Constructor. <b>This method is here for serilization only and should
* normally not be used. Use
* {@link ConstraintParser#parseBoundSize(String, boolean, boolean)}
* instead.
*
* @param min
* The minimum size. May be <code>null</code>.
* @param preferred
* The preferred size. May be <code>null</code>.
* @param max
* The maximum size. May be <code>null</code>.
* @param gapPush
* If the size should be hinted as "pushing" and thus want to
* occupy free space if no one else is claiming it.
* @param createString
* The string used to create the BoundsSize.
*/
public BoundSize(UnitValue min, UnitValue preferred, UnitValue max,
boolean gapPush, String createString) {
this.min = min;
this.pref = preferred;
this.max = max;
this.gapPush = gapPush;
LayoutUtil.putCCString(this, createString); // this escapes!!
}
/**
* Returns the minimum size as sent into the constructor.
*
* @return The minimum size as sent into the constructor. May be
* <code>null</code>.
*/
public final UnitValue getMin() {
return min;
}
/**
* Returns the preferred size as sent into the constructor.
*
* @return The preferred size as sent into the constructor. May be
* <code>null</code>.
*/
public final UnitValue getPreferred() {
return pref;
}
/**
* Returns the maximum size as sent into the constructor.
*
* @return The maximum size as sent into the constructor. May be
* <code>null</code>.
*/
public final UnitValue getMax() {
return max;
}
/**
* If the size should be hinted as "pushing" and thus want to occupy free
* space if noone else is claiming it.
*
* @return The value.
*/
public boolean getGapPush() {
return gapPush;
}
/**
* Returns if this bound size has no min, preferred and maximum size set
* (they are all <code>null</code>)
*
* @return If unset.
*/
public boolean isUnset() {
// Most common case by far is this == ZERO_PIXEL...
return this == ZERO_PIXEL
|| (pref == null && min == null && max == null && gapPush == false);
}
/**
* Makes sure that <code>size</code> is within min and max of this size.
*
* @param size
* The size to constrain.
* @param refValue
* The reference to use for relative sizes.
* @param parent
* The parent container.
* @return The size, constrained within min and max.
*/
public int constrain(int size, float refValue, ContainerWrapper parent) {
if (max != null)
size = Math.min(size, max.getPixels(refValue, parent, parent));
if (min != null)
size = Math.max(size, min.getPixels(refValue, parent, parent));
return size;
}
/**
* Returns the minimum, preferred or maximum size for this bounded size.
*
* @param sizeType
* The type. <code>LayoutUtil.MIN</code>,
* <code>LayoutUtil.PREF</code> or <code>LayoutUtil.MAX</code>.
* @return
*/
final UnitValue getSize(int sizeType) {
switch (sizeType) {
case LayoutUtil.MIN:
return min;
case LayoutUtil.PREF:
return pref;
case LayoutUtil.MAX:
return max;
default:
throw new IllegalArgumentException("Unknown size: " + sizeType);
}
}
/**
* Convert the bound sizes to pixels.
* <p>
* <code>null</code> bound sizes will be 0 for min and preferred and
* {@link net.miginfocom.layout.LayoutUtil#INF} for max.
*
* @param refSize
* The reference size.
* @param parent
* The parent. Not <code>null</code>.
* @param comp
* The component, if applicable, can be <code>null</code>.
* @return An array of lenth three (min,pref,max).
*/
final int[] getPixelSizes(float refSize, ContainerWrapper parent,
ComponentWrapper comp) {
return new int[] {
min != null ? min.getPixels(refSize, parent, comp) : 0,
pref != null ? pref.getPixels(refSize, parent, comp) : 0,
max != null ? max.getPixels(refSize, parent, comp)
: LayoutUtil.INF };
}
/**
* Returns the a constraint string that can be re-parsed to be the exact
* same UnitValue.
*
* @return A String. Never <code>null</code>.
*/
String getConstraintString() {
String cs = LayoutUtil.getCCString(this);
if (cs != null)
return cs;
if (min == pref && pref == max)
return min != null ? (min.getConstraintString() + "!") : "null";
StringBuilder sb = new StringBuilder(16);
if (min != null)
sb.append(min.getConstraintString()).append(':');
if (pref != null) {
if (min == null && max != null)
sb.append(":");
sb.append(pref.getConstraintString());
} else if (min != null) {
sb.append('n');
}
if (max != null)
sb.append(sb.length() == 0 ? "::" : ":").append(
max.getConstraintString());
if (gapPush) {
if (sb.length() > 0)
sb.append(':');
sb.append("push");
}
return sb.toString();
}
void checkNotLinked() {
if (min != null && min.isLinkedDeep() || pref != null
&& pref.isLinkedDeep() || max != null && max.isLinkedDeep())
throw new IllegalArgumentException("Size may not contain links");
}
static {
if (LayoutUtil.HAS_BEANS) {
LayoutUtil.setDelegate(BoundSize.class, new PersistenceDelegate() {
protected Expression instantiate(Object oldInstance, Encoder out) {
BoundSize bs = (BoundSize) oldInstance;
if (Grid.TEST_GAPS) {
return new Expression(oldInstance, BoundSize.class,
"new", new Object[] { bs.getMin(),
bs.getPreferred(), bs.getMax(),
bs.getGapPush(),
bs.getConstraintString() });
} else {
return new Expression(oldInstance, BoundSize.class,
"new", new Object[] { bs.getMin(),
bs.getPreferred(), bs.getMax(),
bs.getConstraintString() });
}
}
});
}
}
// ************************************************
// Persistence Delegate and Serializable combined.
// ************************************************
private static final long serialVersionUID = 1L;
protected Object readResolve() throws ObjectStreamException {
return LayoutUtil.getSerializedObject(this);
}
private void writeObject(ObjectOutputStream out) throws IOException {
if (getClass() == BoundSize.class)
LayoutUtil.writeAsXML(out, this);
}
private void readObject(ObjectInputStream in) throws IOException,
ClassNotFoundException {
LayoutUtil.setSerializedObject(this, LayoutUtil.readAsXML(in));
}
}