Coverage Report - net.miginfocom.layout.UnitValue
 
Classes in this File Line Coverage Branch Coverage Complexity
UnitValue
N/A
N/A
5.719
UnitValue$1
N/A
N/A
5.719
 
 1  
 package net.miginfocom.layout;
 2  
 /*
 3  
  * License (BSD):
 4  
  * ==============
 5  
  *
 6  
  * Copyright (c) 2004, Mikael Grev, MiG InfoCom AB. (miglayout (at) miginfocom (dot) com)
 7  
  * All rights reserved.
 8  
  *
 9  
  * Redistribution and use in source and binary forms, with or without modification,
 10  
  * are permitted provided that the following conditions are met:
 11  
  * Redistributions of source code must retain the above copyright notice, this list
 12  
  * of conditions and the following disclaimer.
 13  
  * Redistributions in binary form must reproduce the above copyright notice, this
 14  
  * list of conditions and the following disclaimer in the documentation and/or other
 15  
  * materials provided with the distribution.
 16  
  * Neither the name of the MiG InfoCom AB nor the names of its contributors may be
 17  
  * used to endorse or promote products derived from this software without specific
 18  
  * prior written permission.
 19  
  *
 20  
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 21  
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 22  
  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 23  
  * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 24  
  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 25  
  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
 26  
  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 27  
  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 28  
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
 29  
  * OF SUCH DAMAGE.
 30  
  *
 31  
  * @version 1.0
 32  
  * @author Mikael Grev, MiG InfoCom AB
 33  
  *         Date: 2006-sep-08
 34  
  */
 35  
 
 36  
 import java.beans.Encoder;
 37  
 import java.beans.Expression;
 38  
 import java.beans.PersistenceDelegate;
 39  
 import java.io.*;
 40  
 import java.util.ArrayList;
 41  
 import java.util.HashMap;
 42  
 
 43  
 public final class UnitValue implements Serializable
 44  
 {
 45  
         private static final HashMap<String, Integer> UNIT_MAP = new HashMap<String, Integer>(32);
 46  
 
 47  
         private static final ArrayList<UnitConverter> CONVERTERS = new ArrayList<UnitConverter>();
 48  
 
 49  
         /** An operation indicating a static value.
 50  
          */
 51  
         public static final int STATIC = 100;
 52  
 
 53  
         /** An operation indicating a addition of two sub units.
 54  
          */
 55  
         public static final int ADD = 101; // Must have "sub-unit values"
 56  
 
 57  
         /** An operation indicating a subtraction of two sub units
 58  
          */
 59  
         public static final int SUB = 102; // Must have "sub-unit values"
 60  
 
 61  
         /** An operation indicating a multiplication of two sub units.
 62  
          */
 63  
         public static final int MUL = 103; // Must have "sub-unit values"
 64  
 
 65  
         /** An operation indicating a division of two sub units.
 66  
          */
 67  
         public static final int DIV = 104; // Must have "sub-unit values"
 68  
 
 69  
         /** An operation indicating the minimum of two sub units
 70  
          */
 71  
         public static final int MIN = 105; // Must have "sub-unit values"
 72  
 
 73  
         /** An operation indicating the maximum of two sub units
 74  
          */
 75  
         public static final int MAX = 106; // Must have "sub-unit values"
 76  
 
 77  
         /** An operation indicating the middle value of two sub units
 78  
          */
 79  
         public static final int MID = 107; // Must have "sub-unit values"
 80  
 
 81  
 
 82  
 
 83  
 
 84  
         /** A unit indicating pixels.
 85  
          */
 86  
         public static final int PIXEL = 0;
 87  
 
 88  
         /** A unit indicating logical horizontal pixels.
 89  
          */
 90  
         public static final int LPX = 1;
 91  
 
 92  
         /** A unit indicating logical vertical pixels.
 93  
          */
 94  
         public static final int LPY = 2;
 95  
 
 96  
         /** A unit indicating millimeters.
 97  
          */
 98  
         public static final int MM = 3;
 99  
 
 100  
         /** A unit indicating centimeters.
 101  
          */
 102  
         public static final int CM = 4;
 103  
 
 104  
         /** A unit indicating inches.
 105  
          */
 106  
         public static final int INCH = 5;
 107  
 
 108  
         /** A unit indicating percent.
 109  
          */
 110  
         public static final int PERCENT = 6;
 111  
 
 112  
         /** A unit indicating points.
 113  
          */
 114  
         public static final int PT = 7;
 115  
 
 116  
         /** A unit indicating screen percentage width.
 117  
          */
 118  
         public static final int SPX = 8;
 119  
 
 120  
         /** A unit indicating screen percentage height.
 121  
          */
 122  
         public static final int SPY = 9;
 123  
 
 124  
         /** A unit indicating alignment.
 125  
          */
 126  
         public static final int ALIGN = 12;
 127  
 
 128  
         /** A unit indicating minimum size.
 129  
          */
 130  
         public static final int MIN_SIZE = 13;
 131  
 
 132  
         /** A unit indicating preferred size.
 133  
          */
 134  
         public static final int PREF_SIZE = 14;
 135  
 
 136  
         /** A unit indicating maximum size.
 137  
          */
 138  
         public static final int MAX_SIZE = 15;
 139  
 
 140  
         /** A unit indicating botton size.
 141  
          */
 142  
         public static final int BUTTON = 16;
 143  
 
 144  
         /** A unit indicating linking to x.
 145  
          */
 146  
         public static final int LINK_X = 18;   // First link
 147  
 
 148  
         /** A unit indicating linking to y.
 149  
          */
 150  
         public static final int LINK_Y = 19;
 151  
 
 152  
         /** A unit indicating linking to width.
 153  
          */
 154  
         public static final int LINK_W = 20;
 155  
 
 156  
         /** A unit indicating linking to height.
 157  
          */
 158  
         public static final int LINK_H = 21;
 159  
 
 160  
         /** A unit indicating linking to x2.
 161  
          */
 162  
         public static final int LINK_X2 = 22;
 163  
 
 164  
         /** A unit indicating linking to y2.
 165  
          */
 166  
         public static final int LINK_Y2 = 23;
 167  
 
 168  
         /** A unit indicating linking to x position on screen.
 169  
          */
 170  
         public static final int LINK_XPOS = 24;
 171  
 
 172  
         /** A unit indicating linking to y position on screen.
 173  
          */
 174  
         public static final int LINK_YPOS = 25;    // Last link
 175  
 
 176  
         /** A unit indicating a lookup.
 177  
          */
 178  
         public static final int LOOKUP = 26;
 179  
 
 180  
         /** A unit indicating label alignment.
 181  
          */
 182  
         public static final int LABEL_ALIGN = 27;
 183  
 
 184  
         private static final int IDENTITY = -1;
 185  
 
 186  
         static {
 187  
                 UNIT_MAP.put("px", PIXEL);
 188  
                 UNIT_MAP.put("lpx", LPX);
 189  
                 UNIT_MAP.put("lpy", LPY);
 190  
                 UNIT_MAP.put("%", PERCENT);
 191  
                 UNIT_MAP.put("cm", CM);
 192  
                 UNIT_MAP.put("in", INCH);
 193  
                 UNIT_MAP.put("spx", SPX);
 194  
                 UNIT_MAP.put("spy", SPY);
 195  
                 UNIT_MAP.put("al", ALIGN);
 196  
                 UNIT_MAP.put("mm", MM);
 197  
                 UNIT_MAP.put("pt", PT);
 198  
                 UNIT_MAP.put("min", MIN_SIZE);
 199  
                 UNIT_MAP.put("minimum", MIN_SIZE);
 200  
                 UNIT_MAP.put("p", PREF_SIZE);
 201  
                 UNIT_MAP.put("pref", PREF_SIZE);
 202  
                 UNIT_MAP.put("max", MAX_SIZE);
 203  
                 UNIT_MAP.put("maximum", MAX_SIZE);
 204  
                 UNIT_MAP.put("button", BUTTON);
 205  
                 UNIT_MAP.put("label", LABEL_ALIGN);
 206  
         }
 207  
 
 208  
         static final UnitValue ZERO = new UnitValue(0, null, PIXEL, true, STATIC, null, null, "0px");
 209  
         static final UnitValue TOP = new UnitValue(0, null, PERCENT, false, STATIC, null, null, "top");
 210  
         static final UnitValue LEADING = new UnitValue(0, null, PERCENT, true, STATIC, null, null, "leading");
 211  
         static final UnitValue LEFT = new UnitValue(0, null, PERCENT, true, STATIC, null, null, "left");
 212  
         static final UnitValue CENTER = new UnitValue(50, null, PERCENT, true, STATIC, null, null, "center");
 213  
         static final UnitValue TRAILING = new UnitValue(100, null, PERCENT, true, STATIC, null, null, "trailing");
 214  
         static final UnitValue RIGHT = new UnitValue(100, null, PERCENT, true, STATIC, null, null, "right");
 215  
         static final UnitValue BOTTOM = new UnitValue(100, null, PERCENT, false, STATIC, null, null, "bottom");
 216  
         static final UnitValue LABEL = new UnitValue(0, null, LABEL_ALIGN, false, STATIC, null, null, "label");
 217  
 
 218  
         static final UnitValue INF = new UnitValue(LayoutUtil.INF, null, PIXEL, true, STATIC, null, null, "inf");
 219  
 
 220  
         static final UnitValue BASELINE_IDENTITY = new UnitValue(0, null, IDENTITY, false, STATIC, null, null, "baseline");
 221  
 
 222  
         private final transient float value;
 223  
         private final transient int unit;
 224  
         private final transient int oper;
 225  
         private final transient String unitStr;
 226  
         private transient String linkId = null; // Should be final, but initializes in a sub method.
 227  
         private final transient boolean isHor;
 228  
         private final transient UnitValue[] subUnits;
 229  
 
 230  
         // Pixel
 231  
         public UnitValue(float value)  // If hor/ver does not matter.
 232  
         {
 233  
                 this(value, null, PIXEL, true, STATIC, null, null, value + "px");
 234  
         }
 235  
 
 236  
         public UnitValue(float value, int unit, String createString)  // If hor/ver does not matter.
 237  
         {
 238  
                 this(value, null, unit, true, STATIC, null, null, createString);
 239  
         }
 240  
 
 241  
         UnitValue(float value, String unitStr, boolean isHor, int oper, String createString)
 242  
         {
 243  
                 this(value, unitStr, -1, isHor, oper, null, null, createString);
 244  
         }
 245  
 
 246  
         UnitValue(boolean isHor, int oper, UnitValue sub1, UnitValue sub2, String createString)
 247  
         {
 248  
                 this(0, "", -1, isHor, oper, sub1, sub2, createString);
 249  
                 if (sub1 == null || sub2 == null)
 250  
                         throw new IllegalArgumentException("Sub units is null!");
 251  
         }
 252  
 
 253  
         private UnitValue(float value, String unitStr, int unit, boolean isHor, int oper, UnitValue sub1, UnitValue sub2, String createString)
 254  
         {
 255  
                 if (oper < STATIC || oper > MID)
 256  
                         throw new IllegalArgumentException("Unknown Operation: " + oper);
 257  
 
 258  
                 if (oper >= ADD && oper <= MID && (sub1 == null || sub2 == null))
 259  
                         throw new IllegalArgumentException(oper + " Operation may not have null sub-UnitValues.");
 260  
 
 261  
                 this.value = value;
 262  
                 this.oper = oper;
 263  
                 this.isHor = isHor;
 264  
                 this.unitStr = unitStr;
 265  
                 this.unit = unitStr != null ? parseUnitString() : unit;
 266  
                 this.subUnits = sub1 != null && sub2 != null ? new UnitValue[] {sub1, sub2} : null;
 267  
 
 268  
                 LayoutUtil.putCCString(this, createString);    // "this" escapes!! Safe though.
 269  
         }
 270  
 
 271  
         /** Returns the size in pixels rounded.
 272  
          * @param refValue The reference value. Normally the size of the parent. For unit {@link #ALIGN} the current size of the component should be sent in.
 273  
          * @param parent The parent. May be <code>null</code> for testing the validity of the value, but should normally not and are not
 274  
          * required to return any usable value if <code>null</code>.
 275  
          * @param comp The component, if any, that the value is for. Might be <code>null</code> if the value is not
 276  
          * connected to any component.
 277  
          * @return The size in pixels.
 278  
          */
 279  
         public final int getPixels(float refValue, ContainerWrapper parent, ComponentWrapper comp)
 280  
         {
 281  
                 return Math.round(getPixelsExact(refValue, parent, comp));
 282  
         }
 283  
 
 284  
         private static final float[] SCALE = new float[] {25.4f, 2.54f, 1f, 0f, 72f};
 285  
         /** Returns the size in pixels.
 286  
          * @param refValue The reference value. Normally the size of the parent. For unit {@link #ALIGN} the current size of the component should be sent in.
 287  
          * @param parent The parent. May be <code>null</code> for testing the validity of the value, but should normally not and are not
 288  
          * required to return any usable value if <code>null</code>.
 289  
          * @param comp The component, if any, that the value is for. Might be <code>null</code> if the value is not
 290  
          * connected to any component.
 291  
          * @return The size in pixels.
 292  
          */
 293  
         public final float getPixelsExact(float refValue, ContainerWrapper parent, ComponentWrapper comp)
 294  
         {
 295  
                 if (parent == null)
 296  
                         return 1;
 297  
 
 298  
                 if (oper == STATIC) {
 299  
                         switch (unit) {
 300  
                                 case PIXEL:
 301  
                                         return value;
 302  
 
 303  
                                 case LPX:
 304  
                                 case LPY:
 305  
                                         return parent.getPixelUnitFactor(unit == LPX) * value;
 306  
 
 307  
                                 case MM:
 308  
                                 case CM:
 309  
                                 case INCH:
 310  
                                 case PT:
 311  
                                         float f = SCALE[unit - MM];
 312  
                                         Float s = isHor ? PlatformDefaults.getHorizontalScaleFactor() : PlatformDefaults.getVerticalScaleFactor();
 313  
                                         if (s != null)
 314  
                                                 f *= s;
 315  
                                         return (isHor ? parent.getHorizontalScreenDPI() : parent.getVerticalScreenDPI()) * value / f;
 316  
 
 317  
                                 case PERCENT:
 318  
                                         return value * refValue * 0.01f;
 319  
 
 320  
                                 case SPX:
 321  
                                 case SPY:
 322  
                                         return (unit == SPX ? parent.getScreenWidth() : parent.getScreenHeight()) * value * 0.01f;
 323  
 
 324  
                                 case ALIGN:
 325  
                                         Integer st = LinkHandler.getValue(parent.getLayout(), "visual", isHor ? LinkHandler.X : LinkHandler.Y);
 326  
                                         Integer sz = LinkHandler.getValue(parent.getLayout(), "visual", isHor ? LinkHandler.WIDTH : LinkHandler.HEIGHT);
 327  
                                         if (st == null || sz == null)
 328  
                                                 return 0;
 329  
                                         return value * (Math.max(0, sz.intValue()) - refValue) + st;
 330  
 
 331  
                                 case MIN_SIZE:
 332  
                                         if (comp == null)
 333  
                                                 return 0;
 334  
                                         return isHor ? comp.getMinimumWidth(comp.getHeight()) : comp.getMinimumHeight(comp.getWidth());
 335  
 
 336  
                                 case PREF_SIZE:
 337  
                                         if (comp == null)
 338  
                                                 return 0;
 339  
                                         return isHor ? comp.getPreferredWidth(comp.getHeight()) : comp.getPreferredHeight(comp.getWidth());
 340  
 
 341  
                                 case MAX_SIZE:
 342  
                                         if (comp == null)
 343  
                                                 return 0;
 344  
                                         return isHor ? comp.getMaximumWidth(comp.getHeight()) : comp.getMaximumHeight(comp.getWidth());
 345  
 
 346  
                                 case BUTTON:
 347  
                                         return PlatformDefaults.getMinimumButtonWidth().getPixels(refValue, parent, comp);
 348  
 
 349  
                                 case LINK_X:
 350  
                                 case LINK_Y:
 351  
                                 case LINK_W:
 352  
                                 case LINK_H:
 353  
                                 case LINK_X2:
 354  
                                 case LINK_Y2:
 355  
                                 case LINK_XPOS:
 356  
                                 case LINK_YPOS:
 357  
                                         Integer v = LinkHandler.getValue(parent.getLayout(), getLinkTargetId(), unit - (unit >= LINK_XPOS ? LINK_XPOS : LINK_X));
 358  
                                         if (v == null)
 359  
                                                 return 0;
 360  
 
 361  
                                         if (unit == LINK_XPOS)
 362  
                                                 return parent.getScreenLocationX() + v;
 363  
                                         if (unit == LINK_YPOS)
 364  
                                                 return parent.getScreenLocationY() + v;
 365  
 
 366  
                                         return v;
 367  
 
 368  
                                 case LOOKUP:
 369  
                                         float res = lookup(refValue, parent, comp);
 370  
                                         if (res != UnitConverter.UNABLE)
 371  
                                                 return res;
 372  
 
 373  
                                 case LABEL_ALIGN:
 374  
                                         return PlatformDefaults.getLabelAlignPercentage() * refValue;
 375  
 
 376  
                                 case IDENTITY:
 377  
                         }
 378  
                         throw new IllegalArgumentException("Unknown/illegal unit: " + unit + ", unitStr: " + unitStr);
 379  
                 }
 380  
 
 381  
                 if (subUnits != null && subUnits.length == 2) {
 382  
                         float r1 = subUnits[0].getPixelsExact(refValue, parent, comp);
 383  
                         float r2 = subUnits[1].getPixelsExact(refValue, parent, comp);
 384  
                         switch (oper) {
 385  
                                 case ADD:
 386  
                                         return r1 + r2;
 387  
                                 case SUB:
 388  
                                         return r1 - r2;
 389  
                                 case MUL:
 390  
                                         return r1 * r2;
 391  
                                 case DIV:
 392  
                                         return r1 / r2;
 393  
                                 case MIN:
 394  
                                         return r1 < r2 ? r1 : r2;
 395  
                                 case MAX:
 396  
                                         return r1 > r2 ? r1 : r2;
 397  
                                 case MID:
 398  
                                         return (r1 + r2) * 0.5f;
 399  
                         }
 400  
                 }
 401  
 
 402  
                 throw new IllegalArgumentException("Internal: Unknown Oper: " + oper);
 403  
         }
 404  
 
 405  
         private float lookup(float refValue, ContainerWrapper parent, ComponentWrapper comp)
 406  
         {
 407  
                 float res = UnitConverter.UNABLE;
 408  
                 for (int i = CONVERTERS.size() - 1; i >= 0; i--) {
 409  
                         res = CONVERTERS.get(i).convertToPixels(value, unitStr, isHor, refValue, parent, comp);
 410  
                         if (res != UnitConverter.UNABLE)
 411  
                                 return res;
 412  
                 }
 413  
                 return PlatformDefaults.convertToPixels(value, unitStr, isHor, refValue, parent, comp);
 414  
         }
 415  
 
 416  
         private int parseUnitString()
 417  
         {
 418  
                 int len = unitStr.length();
 419  
                 if (len == 0)
 420  
                         return isHor ? PlatformDefaults.getDefaultHorizontalUnit() : PlatformDefaults.getDefaultVerticalUnit();
 421  
 
 422  
                 Integer u = UNIT_MAP.get(unitStr);
 423  
                 if (u != null)
 424  
                         return u;
 425  
 
 426  
                 if (unitStr.equals("lp"))
 427  
                         return isHor ? LPX : LPY;
 428  
 
 429  
                 if (unitStr.equals("sp"))
 430  
                         return isHor ? SPX : SPY;
 431  
 
 432  
                 if (lookup(0, null, null) != UnitConverter.UNABLE)    // To test so we can fail fast
 433  
                         return LOOKUP;
 434  
 
 435  
                 // Only link left. E.g. "otherID.width"
 436  
 
 437  
                 int pIx = unitStr.indexOf('.');
 438  
                 if (pIx != -1) {
 439  
                         linkId = unitStr.substring(0, pIx);
 440  
                         String e = unitStr.substring(pIx + 1);
 441  
 
 442  
                         if (e.equals("x"))
 443  
                                 return LINK_X;
 444  
                         if (e.equals("y"))
 445  
                                 return LINK_Y;
 446  
                         if (e.equals("w") || e.equals("width"))
 447  
                                 return LINK_W;
 448  
                         if (e.equals("h") || e.equals("height"))
 449  
                                 return LINK_H;
 450  
                         if (e.equals("x2"))
 451  
                                 return LINK_X2;
 452  
                         if (e.equals("y2"))
 453  
                                 return LINK_Y2;
 454  
                         if (e.equals("xpos"))
 455  
                                 return LINK_XPOS;
 456  
                         if (e.equals("ypos"))
 457  
                                 return LINK_YPOS;
 458  
                 }
 459  
 
 460  
                 throw new IllegalArgumentException("Unknown keyword: " + unitStr);
 461  
         }
 462  
 
 463  
         final boolean isLinked()
 464  
         {
 465  
                 return linkId != null;
 466  
         }
 467  
 
 468  
         final boolean isLinkedDeep()
 469  
         {
 470  
                 if (subUnits == null)
 471  
                         return linkId != null;
 472  
 
 473  
                 for (UnitValue subUnit : subUnits) {
 474  
                         if (subUnit.isLinkedDeep())
 475  
                                 return true;
 476  
                 }
 477  
 
 478  
                 return false;
 479  
         }
 480  
 
 481  
         final String getLinkTargetId()
 482  
         {
 483  
                 return linkId;
 484  
         }
 485  
 
 486  
         final UnitValue getSubUnitValue(int i)
 487  
         {
 488  
                 return subUnits[i];
 489  
         }
 490  
 
 491  
         final int getSubUnitCount()
 492  
         {
 493  
                 return subUnits != null ? subUnits.length : 0;
 494  
         }
 495  
 
 496  
         public final UnitValue[] getSubUnits()
 497  
         {
 498  
                 return subUnits != null ? subUnits.clone() : null;
 499  
         }
 500  
 
 501  
         public final int getUnit()
 502  
         {
 503  
                 return unit;
 504  
         }
 505  
 
 506  
         public final String getUnitString()
 507  
         {
 508  
                 return unitStr;
 509  
         }
 510  
 
 511  
         public final int getOperation()
 512  
         {
 513  
                 return oper;
 514  
         }
 515  
 
 516  
         public final float getValue()
 517  
         {
 518  
                 return value;
 519  
         }
 520  
 
 521  
         public final boolean isHorizontal()
 522  
         {
 523  
                 return isHor;
 524  
         }
 525  
 
 526  
         final public String toString()
 527  
         {
 528  
                 return getClass().getName() + ". Value=" + value + ", unit=" + unit + ", unitString: " + unitStr + ", oper=" + oper + ", isHor: " + isHor;
 529  
         }
 530  
 
 531  
         /** Returns the creation string for this object. Note that {@link LayoutUtil#setDesignTime(ContainerWrapper, boolean)} must be
 532  
          * set to <code>true</code> for the creation strings to be stored.
 533  
          * @return The constraint string or <code>null</code> if none is registered.
 534  
          */
 535  
         public final String getConstraintString()
 536  
         {
 537  
                 return LayoutUtil.getCCString(this);
 538  
         }
 539  
 
 540  
         public final int hashCode()
 541  
         {
 542  
                 return (int) (value * 12345) + (oper >>> 5) + unit >>> 17;
 543  
         }
 544  
 
 545  
         /** Adds a global unit converter that can convert from some <code>unit</code> to pixels.
 546  
          * <p>
 547  
          * This converter will be asked before the platform converter so the values for it (e.g. "related" and "unrelated")
 548  
          * can be overridden. It is however not possible to override the built in ones (e.g. "mm", "pixel" or "lp").
 549  
          * @param conv The converter. Not <code>null</code>.
 550  
          */
 551  
         public synchronized static void addGlobalUnitConverter(UnitConverter conv)
 552  
         {
 553  
                 if (conv == null)
 554  
                         throw new NullPointerException();
 555  
                 CONVERTERS.add(conv);
 556  
         }
 557  
 
 558  
         /** Removed the converter.
 559  
          * @param unit The converter.
 560  
          * @return If there was a converter found and thus removed.
 561  
          */
 562  
         public synchronized static boolean removeGlobalUnitConverter(UnitConverter unit)
 563  
         {
 564  
                 return CONVERTERS.remove(unit);
 565  
         }
 566  
 
 567  
         /** Returns the global converters currently registered. The platform converter will not be in this list.
 568  
          * @return The converters. Never <code>null</code>.
 569  
          */
 570  
         public synchronized static UnitConverter[] getGlobalUnitConverters()
 571  
         {
 572  
                 return CONVERTERS.toArray(new UnitConverter[CONVERTERS.size()]);
 573  
         }
 574  
 
 575  
         /** Returns the current default unit. The default unit is the unit used if no unit is set. E.g. "width 10".
 576  
          * @return The current default unit.
 577  
          * @see #PIXEL
 578  
          * @see #LPX
 579  
          * @deprecated Use {@link PlatformDefaults#getDefaultHorizontalUnit()} and {@link PlatformDefaults#getDefaultVerticalUnit()} instead.
 580  
          */
 581  
         public static int getDefaultUnit()
 582  
         {
 583  
                 return PlatformDefaults.getDefaultHorizontalUnit();
 584  
         }
 585  
 
 586  
         /** Sets the default unit. The default unit is the unit used if no unit is set. E.g. "width 10".
 587  
          * @param unit The new default unit.
 588  
          * @see #PIXEL
 589  
          * @see #LPX
 590  
          * @deprecated Use {@link PlatformDefaults#setDefaultHorizontalUnit(int)} and {@link PlatformDefaults#setDefaultVerticalUnit(int)} instead.
 591  
          */
 592  
         public static void setDefaultUnit(int unit)
 593  
         {
 594  
                 PlatformDefaults.setDefaultHorizontalUnit(unit);
 595  
                 PlatformDefaults.setDefaultVerticalUnit(unit);
 596  
         }
 597  
 
 598  
         static {
 599  
         if(LayoutUtil.HAS_BEANS){
 600  
             LayoutUtil.setDelegate(UnitValue.class, new PersistenceDelegate() {
 601  
                 protected Expression instantiate(Object oldInstance, Encoder out)
 602  
                 {
 603  
                     UnitValue uv = (UnitValue) oldInstance;
 604  
                     String cs = uv.getConstraintString();
 605  
                     if (cs == null)
 606  
                         throw new IllegalStateException("Design time must be on to use XML persistence. See LayoutUtil.");
 607  
 
 608  
                     return new Expression(oldInstance, ConstraintParser.class, "parseUnitValueOrAlign", new Object[] {
 609  
                             uv.getConstraintString(), (uv.isHorizontal() ? Boolean.TRUE : Boolean.FALSE), null
 610  
                     });
 611  
                 }
 612  
             });
 613  
         }
 614  
         }
 615  
 
 616  
         // ************************************************
 617  
         // Persistence Delegate and Serializable combined.
 618  
         // ************************************************
 619  
 
 620  
         private static final long serialVersionUID = 1L;
 621  
 
 622  
         private Object readResolve() throws ObjectStreamException
 623  
         {
 624  
                 return LayoutUtil.getSerializedObject(this);
 625  
         }
 626  
 
 627  
         private void writeObject(ObjectOutputStream out) throws IOException
 628  
         {
 629  
                 if (getClass() == UnitValue.class)
 630  
                         LayoutUtil.writeAsXML(out, this);
 631  
         }
 632  
 
 633  
         private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException
 634  
         {
 635  
                 LayoutUtil.setSerializedObject(this, LayoutUtil.readAsXML(in));
 636  
         }
 637  
 }