/*
* Copyright (c) 2004, Mikael Grev, MiG InfoCom AB. (miglayout (at) miginfocom (dot) com),
* modifications by Nikolaus Moll
* 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
*/
package org.jowidgets.impl.layout.miglayout;
import java.beans.Encoder;
import java.beans.Expression;
import java.beans.PersistenceDelegate;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamException;
import java.io.Serializable;
/**
* A size that contains minimum, preferred and maximum size of type {@link UnitValueCommon}.
* <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 ConstraintParserCommon#parseBoundSize(String, boolean, boolean)}
*/
class BoundSizeCommon implements Serializable {
public static final BoundSizeCommon NULL_SIZE = new BoundSizeCommon(null, null);
public static final BoundSizeCommon ZERO_PIXEL = new BoundSizeCommon(
MigLayoutToolkitImpl.getMigUnitValueToolkit().ZERO,
"0px");
private static final long serialVersionUID = 1L;
private final transient UnitValueCommon min;
private final transient UnitValueCommon pref;
private final transient UnitValueCommon max;
private final transient boolean gapPush;
private final LayoutUtilCommon layoutUtil;
/**
* 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.
*/
BoundSizeCommon(final UnitValueCommon minMaxPref, final String createString) {
this(minMaxPref, minMaxPref, minMaxPref, createString);
}
/**
* Constructor. <b>This method is here for serilization only and should normally not be used. Use
* {@link ConstraintParserCommon#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.
*/
BoundSizeCommon(
final UnitValueCommon min,
final UnitValueCommon preferred,
final UnitValueCommon max,
final 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 ConstraintParserCommon#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.
*/
BoundSizeCommon(
final UnitValueCommon min,
final UnitValueCommon preferred,
final UnitValueCommon max,
final boolean gapPush,
final String createString) {
this.layoutUtil = MigLayoutToolkitImpl.getMigLayoutUtil();
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 UnitValueCommon 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 UnitValueCommon 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 UnitValueCommon 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, final float refValue, final IContainerWrapperCommon 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 UnitValueCommon getSize(final int sizeType) {
if (sizeType == LayoutUtilCommon.MIN) {
return min;
}
else if (sizeType == LayoutUtilCommon.PREF) {
return pref;
}
else if (sizeType == LayoutUtilCommon.MAX) {
return max;
}
else {
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 LayoutUtilCommon.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(final float refSize, final IContainerWrapperCommon parent, final IComponentWrapperCommon 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) : LayoutUtilCommon.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() {
final String cs = layoutUtil.getCCString(this);
if (cs != null) {
return cs;
}
if (min == pref && pref == max) {
return min != null ? (min.getConstraintString() + "!") : "null";
}
final 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 {
final LayoutUtilCommon lUtil = MigLayoutToolkitImpl.getMigLayoutUtil();
if (lUtil.hasBeans()) {
lUtil.setDelegate(BoundSizeCommon.class, new PersistenceDelegate() {
@Override
protected Expression instantiate(final Object oldInstance, final Encoder out) {
final BoundSizeCommon bs = (BoundSizeCommon) oldInstance;
if (GridCommon.TEST_GAPS) {
return new Expression(oldInstance, BoundSizeCommon.class, "new", new Object[] {
bs.getMin(), bs.getPreferred(), bs.getMax(), bs.getGapPush(), bs.getConstraintString()});
}
else {
return new Expression(oldInstance, BoundSizeCommon.class, "new", new Object[] {
bs.getMin(), bs.getPreferred(), bs.getMax(), bs.getConstraintString()});
}
}
});
}
}
// ************************************************
// Persistence Delegate and Serializable combined.
// ************************************************
protected Object readResolve() throws ObjectStreamException {
return layoutUtil.getSerializedObject(this);
}
private void writeObject(final ObjectOutputStream out) throws IOException {
if (getClass() == BoundSizeCommon.class) {
layoutUtil.writeAsXML(out, this);
}
}
private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException {
layoutUtil.setSerializedObject(this, layoutUtil.readAsXML(in));
}
}