Coverage Report - net.miginfocom.layout.IDEUtil
 
Classes in this File Line Coverage Branch Coverage Complexity
IDEUtil
N/A
N/A
19.846
 
 1  
 package net.miginfocom.layout;
 2  
 
 3  
 import java.util.HashMap;
 4  
 /*
 5  
  * License (BSD):
 6  
  * ==============
 7  
  *
 8  
  * Copyright (c) 2004, Mikael Grev, MiG InfoCom AB. (miglayout (at) miginfocom (dot) com)
 9  
  * All rights reserved.
 10  
  *
 11  
  * Redistribution and use in source and binary forms, with or without modification,
 12  
  * are permitted provided that the following conditions are met:
 13  
  * Redistributions of source code must retain the above copyright notice, this list
 14  
  * of conditions and the following disclaimer.
 15  
  * Redistributions in binary form must reproduce the above copyright notice, this
 16  
  * list of conditions and the following disclaimer in the documentation and/or other
 17  
  * materials provided with the distribution.
 18  
  * Neither the name of the MiG InfoCom AB nor the names of its contributors may be
 19  
  * used to endorse or promote products derived from this software without specific
 20  
  * prior written permission.
 21  
  *
 22  
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 23  
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 24  
  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 25  
  * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 26  
  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 27  
  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
 28  
  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 29  
  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 30  
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
 31  
  * OF SUCH DAMAGE.
 32  
  *
 33  
  * @version 1.0
 34  
  * @author Mikael Grev, MiG InfoCom AB
 35  
  *         Date: 2006-sep-08
 36  
  */
 37  
 
 38  
 /** This class contains static methods to be used by IDE vendors to convert to and from String/API constraints.
 39  
  * <p>
 40  
  * <b>Note that {@link LayoutUtil#setDesignTime(ContainerWrapper, boolean)} should be set to <code>true</code> for this class'
 41  
  * methods to work.</b>
 42  
  */
 43  
 public class IDEUtil
 44  
 {
 45  
         /** A direct reference to the corresponding value for predefined UnitValues in {@link UnitValue}.
 46  
          */
 47  
         public static final UnitValue ZERO = UnitValue.ZERO;
 48  
 
 49  
         /** A direct reference to the corresponding value for predefined UnitValues in {@link UnitValue}.
 50  
          */
 51  
         public static final UnitValue TOP = UnitValue.TOP;
 52  
 
 53  
         /** A direct reference to the corresponding value for predefined UnitValues in {@link UnitValue}.
 54  
          */
 55  
         public static final UnitValue LEADING = UnitValue.LEADING;
 56  
 
 57  
         /** A direct reference to the corresponding value for predefined UnitValues in {@link UnitValue}.
 58  
          */
 59  
         public static final UnitValue LEFT = UnitValue.LEFT;
 60  
 
 61  
         /** A direct reference to the corresponding value for predefined UnitValues in {@link UnitValue}.
 62  
          */
 63  
         public static final UnitValue CENTER = UnitValue.CENTER;
 64  
 
 65  
         /** A direct reference to the corresponding value for predefined UnitValues in {@link UnitValue}.
 66  
          */
 67  
         public static final UnitValue TRAILING = UnitValue.TRAILING;
 68  
 
 69  
         /** A direct reference to the corresponding value for predefined UnitValues in {@link UnitValue}.
 70  
          */
 71  
         public static final UnitValue RIGHT = UnitValue.RIGHT;
 72  
 
 73  
         /** A direct reference to the corresponding value for predefined UnitValues in {@link UnitValue}.
 74  
          */
 75  
         public static final UnitValue BOTTOM = UnitValue.BOTTOM;
 76  
 
 77  
         /** A direct reference to the corresponding value for predefined UnitValues in {@link UnitValue}.
 78  
          */
 79  
         public static final UnitValue LABEL = UnitValue.LABEL;
 80  
 
 81  
         /** A direct reference to the corresponding value for predefined UnitValues in {@link UnitValue}.
 82  
          */
 83  
         public static final UnitValue INF = UnitValue.INF;
 84  
 
 85  
         /** A direct reference to the corresponding value for predefined UnitValues in {@link UnitValue}.
 86  
          */
 87  
         public static final UnitValue BASELINE_IDENTITY = UnitValue.BASELINE_IDENTITY;
 88  
 
 89  
         private final static String[] X_Y_STRINGS = new String[] {"x", "y", "x2", "y2"};
 90  
 
 91  
         /** Returns the version of IDEUtil
 92  
          * @return The version.
 93  
          */
 94  
         public String getIDEUtilVersion()
 95  
         {
 96  
                 return "1.0";
 97  
         }
 98  
 
 99  
         /** Returns the grid cells that the components in <code>parentContainer</code> has.
 100  
          * @param parentContainer The parent container. It is an object since MigLayout is GUI toolkit
 101  
          * independent.
 102  
          * @return A new hashmap with the components mapped to an array [x, y, spanx, spany].
 103  
          * <p>
 104  
          * Dock components will always have x and y less than -30000 or more than 30000. This is since they
 105  
          * are actually part of the grid, but on the outer edges.
 106  
          * <p>
 107  
          * Components that span the "rest of the row/column" have really large span values. Actually 30000-x or
 108  
          * 30000-y.
 109  
          * <p>
 110  
          * Generally, the grid does not need to have the upper left at 0, 0. Though it normally does if you
 111  
          * don't set the cells explicitly to other values. Rows and columns that are completely empty and
 112  
          * that does not have an explicit row/column constraint will be totally disregarded.
 113  
          */
 114  
         public static HashMap<Object, int[]> getGridPositions(Object parentContainer)
 115  
         {
 116  
                 return Grid.getGridPositions(parentContainer);
 117  
         }
 118  
 
 119  
         /** Returns the sizes of the rows and gaps for a container.
 120  
          * There will be two arrays returned [0] and [1].
 121  
          * <p>
 122  
          * The first array will be the indexes of the rows where indexes that
 123  
          * are less than 30000 or larger than 30000 is docking rows. There might be extra docking rows that aren't
 124  
          * visible but they always have size 0. Non docking indexes will probably always be 0, 1, 2, 3, etc..
 125  
          * <p>
 126  
          * The second array is the sizes of the form:<br>
 127  
          * <code>[left inset][row size 1][gap 1][row size 2][gap 2][row size n][right inset]</code>.
 128  
          * <p>
 129  
          * The returned sizes will be the ones calculated in the last layout cycle.
 130  
          * @param parentContainer The container to retuern the row sizes and gaps for. In Swing it will be a {@link java.awt.Container} and
 131  
          * in SWT it will be a {@link org.eclipse.swt.widgets.Composite}.
 132  
          * @return The sizes or <code>null</code> if {@link LayoutUtil#isDesignTime(ContainerWrapper)} is <code>false</code> or
 133  
          * <code>parentContainer</code> does not have a MigLayout layout manager.
 134  
          * The returned sizes will be the ones calculated in the last layout cycle.
 135  
          * @see LayoutUtil#isDesignTime(ContainerWrapper)
 136  
          */
 137  
         public static int[][] getRowSizes(Object parentContainer)
 138  
         {
 139  
                 return Grid.getSizesAndIndexes(parentContainer, true);
 140  
         }
 141  
 
 142  
         /** Returns the sizes of the columns and gaps for a container.
 143  
          * There will be two arrays returned [0] and [1].
 144  
          * <p>
 145  
          * The first array will be the indexes of the columns where indexes that
 146  
          * are less than 30000 or larger than 30000 is docking columns. There might be extra docking columns that aren't
 147  
          * visible but they always have size 0. Non docking indexes will probably always be 0, 1, 2, 3, etc..
 148  
          * <p>
 149  
          * The second array is the sizes of the form:<br>
 150  
          * <code>[top inset][column size 1][gap 1][column size 2][gap 2][column size n][bottom inset]</code>.
 151  
          * <p>
 152  
          * The returned sizes will be the ones calculated in the last layout cycle.
 153  
          * @param parentContainer The container to retuern the column sizes and gaps for. In Swing it will be a {@link java.awt.Container} and
 154  
          * in SWT it will be a {@link org.eclipse.swt.widgets.Composite}.
 155  
          * @return The sizes and indexes or <code>null</code> if {@link LayoutUtil#isDesignTime(ContainerWrapper)} is <code>false</code> or
 156  
          * <code>parentContainer</code> does not have a MigLayout layout manager.
 157  
          * The returned sizes will be the ones calculated in the last layout cycle.
 158  
          * @see LayoutUtil#isDesignTime(ContainerWrapper)
 159  
          */
 160  
         public static int[][] getColumnSizes(Object parentContainer)
 161  
         {
 162  
                 return Grid.getSizesAndIndexes(parentContainer, false);
 163  
         }
 164  
 
 165  
         /** Returns the a constraint string that can be re-parsed to be the exact same AxisConstraint.
 166  
          * @param ac The axis constraint to return as a constraint string.
 167  
          * @param asAPI If the returned string should be of API type (e.g. .flowX().gap("rel").align("right")) or
 168  
          * as a String type (e.g. "flowx, gap rel, right").
 169  
          * @param isCols The the constraint should be returned for columns rather than rows.
 170  
          * @return A String. Never <code>null</code>.
 171  
          */
 172  
         public static String getConstraintString(AC ac, boolean asAPI, boolean isCols)
 173  
         {
 174  
                 StringBuffer sb = new StringBuffer(32);
 175  
 
 176  
                 DimConstraint[] dims = ac.getConstaints();
 177  
                 BoundSize defGap = isCols ? PlatformDefaults.getGridGapX() : PlatformDefaults.getGridGapY();
 178  
 
 179  
                 for (int i = 0; i < dims.length; i++) {
 180  
                         DimConstraint dc = dims[i];
 181  
 
 182  
                         addRowDimConstraintString(dc, sb, asAPI);
 183  
 
 184  
                         if (i < dims.length - 1) {
 185  
                                 BoundSize gap = dc.getGapAfter();
 186  
 
 187  
                                 if (gap == defGap || gap == null)
 188  
                                         gap = dims[i + 1].getGapBefore();
 189  
 
 190  
                                 if (gap != null) {
 191  
                                         String gapStr = getBS(gap);
 192  
                                         if (asAPI) {
 193  
                                                 sb.append(".gap(\"").append(gapStr).append("\")");
 194  
                                         } else {
 195  
                                                 sb.append(gapStr);
 196  
                                         }
 197  
                                 } else {
 198  
                                         if (asAPI)
 199  
                                                 sb.append(".gap()");
 200  
                                 }
 201  
                         }
 202  
                 }
 203  
 
 204  
                 return sb.toString();
 205  
         }
 206  
 
 207  
         /** Adds the a constraint string that can be re-parsed to be the exact same DimConstraint.
 208  
          * @param dc The layout constraint to return as a constraint string.
 209  
          * @param asAPI If the returned string should be of API type (e.g. .flowX().gap("rel").align("right")) or
 210  
          * as a String type (e.g. "flowx, gap rel, right").
 211  
          */
 212  
         private static void addRowDimConstraintString(DimConstraint dc, StringBuffer sb, boolean asAPI)
 213  
         {
 214  
                 int gp = dc.getGrowPriority();
 215  
 
 216  
                 int firstComma = sb.length();
 217  
 
 218  
                 BoundSize size = dc.getSize();
 219  
                 if (size.isUnset() == false) {
 220  
                         if (asAPI) {
 221  
                                 sb.append(".size(\"").append(getBS(size)).append("\")");
 222  
                         } else {
 223  
                                 sb.append(',').append(getBS(size));
 224  
                         }
 225  
                 }
 226  
 
 227  
                 if (gp != 100) {
 228  
                         if (asAPI) {
 229  
                                 sb.append(".growPrio(").append(gp).append("\")");
 230  
                         } else {
 231  
                                 sb.append(",growprio ").append(gp);
 232  
                         }
 233  
                 }
 234  
 
 235  
                 Float gw = dc.getGrow();
 236  
                 if (gw != null) {
 237  
                         String g = gw != 100f ? floatToString(gw, asAPI) : "";
 238  
                         if (asAPI) {
 239  
                                 if (g.length() == 0) {
 240  
                                         sb.append(".grow()");
 241  
                                 } else {
 242  
                                         sb.append(".grow(\"").append(g).append("\")");
 243  
                                 }
 244  
                         } else {
 245  
                                 sb.append(",grow").append(g.length() > 0 ? (" " + g) : "");
 246  
                         }
 247  
                 }
 248  
 
 249  
                 int sp = dc.getShrinkPriority();
 250  
                 if (sp != 100) {
 251  
                         if (asAPI) {
 252  
                                 sb.append(".shrinkPrio(").append(sp).append("\")");
 253  
                         } else {
 254  
                                 sb.append(",shrinkprio ").append(sp);
 255  
                         }
 256  
                 }
 257  
 
 258  
                 Float sw = dc.getShrink();
 259  
                 if (sw != null && sw.intValue() != 100) {
 260  
                         String s = floatToString(sw, asAPI);
 261  
                         if (asAPI) {
 262  
                                 sb.append(".shrink(\"").append(s).append("\")");
 263  
                         } else {
 264  
                                 sb.append(",shrink ").append(s);
 265  
                         }
 266  
                 }
 267  
 
 268  
                 String eg = dc.getEndGroup();
 269  
                 if (eg != null) {
 270  
                         if (asAPI) {
 271  
                                 sb.append(".endGroup(\"").append(eg).append("\")");
 272  
                         } else {
 273  
                                 sb.append(",endgroup ").append(eg);
 274  
                         }
 275  
                 }
 276  
 
 277  
                 String sg = dc.getSizeGroup();
 278  
                 if (sg != null) {
 279  
                         if (asAPI) {
 280  
                                 sb.append(".sizeGroup(\"").append(sg).append("\")");
 281  
                         } else {
 282  
                                 sb.append(",sizegroup ").append(sg);
 283  
                         }
 284  
                 }
 285  
 
 286  
                 UnitValue al = dc.getAlign();
 287  
                 if (al != null) {
 288  
                         if (asAPI) {
 289  
                                 sb.append(".align(\"").append(getUV(al)).append("\")");
 290  
                         } else {
 291  
                                 String s = getUV(al);
 292  
                                 String alKw = (s.equals("top") || s.equals("bottom") || s.equals("left") || s.equals("label") ||
 293  
                                                            s.equals("leading") || s.equals("center") || s.equals("trailing") ||
 294  
                                                            s.equals("right") || s.equals("baseline")) ? "" : "align ";
 295  
                                 sb.append(',').append(alKw).append(s);
 296  
                         }
 297  
                 }
 298  
 
 299  
                 if (dc.isNoGrid()) {
 300  
                         if (asAPI) {
 301  
                                 sb.append(".noGrid()");
 302  
                         } else {
 303  
                                 sb.append(",nogrid");
 304  
                         }
 305  
                 }
 306  
 
 307  
                 if (dc.isFill()) {
 308  
                         if (asAPI) {
 309  
                                 sb.append(".fill()");
 310  
                         } else {
 311  
                                 sb.append(",fill");
 312  
                         }
 313  
                 }
 314  
 
 315  
                 if (asAPI == false) {
 316  
                         if (sb.length() > firstComma) {
 317  
                                 sb.setCharAt(firstComma, '[');
 318  
                                 sb.append(']');
 319  
                         } else {
 320  
                                 sb.append("[]");
 321  
                         }
 322  
                 }
 323  
         }
 324  
 
 325  
         /** Returns the a constraint string that can be re-parsed to be the exact same DimConstraint.
 326  
          * @param dc The layout constraint to return as a constraint string.
 327  
          * @param asAPI If the returned string should be of API type (e.g. .flowX().gap("rel").align("right")) or
 328  
          * as a String type (e.g. "flowx, gap rel, right").
 329  
          * @param isHor The the DimConstraint is decoration something horizontal (column or x).
 330  
          * @param noGrowAdd If <code>true</code> no grow constraints will be added.
 331  
          * @return A constraint string. Never <code>null</code>.
 332  
          */
 333  
         private static void addComponentDimConstraintString(DimConstraint dc, StringBuffer sb, boolean asAPI, boolean isHor, boolean noGrowAdd)
 334  
         {
 335  
                 int gp = dc.getGrowPriority();
 336  
                 if (gp != 100) {
 337  
                         if (asAPI) {
 338  
                                 sb.append(isHor ? ".growPrioX(" : ".growPrioY(").append(gp).append(')');
 339  
                         } else {
 340  
                                 sb.append(isHor ? ",growpriox " : ",growprioy ").append(gp);
 341  
                         }
 342  
                 }
 343  
 
 344  
                 if (noGrowAdd == false) {
 345  
                         Float gw = dc.getGrow();
 346  
                         if (gw != null) {
 347  
                                 String g = gw != 100f ? floatToString(gw, asAPI) : "";
 348  
                                 if (asAPI) {
 349  
                                         sb.append(isHor ? ".growX(" : ".growY(").append(g).append(')');
 350  
                                 } else {
 351  
                                         sb.append(isHor ? ",growx" : ",growy").append(g.length() > 0 ? (" " + g) : "");
 352  
                                 }
 353  
                         }
 354  
                 }
 355  
 
 356  
                 int sp = dc.getShrinkPriority();
 357  
                 if (sp != 100) {
 358  
                         if (asAPI) {
 359  
                                 sb.append(isHor ? ".shrinkPrioX(" : ".shrinkPrioY(").append(sp).append(')');
 360  
                         } else {
 361  
                                 sb.append(isHor ? ",shrinkpriox " : ",shrinkprioy ").append(sp);
 362  
                         }
 363  
                 }
 364  
 
 365  
                 Float sw = dc.getShrink();
 366  
                 if (sw != null && sw.intValue() != 100) {
 367  
                         String s = floatToString(sw, asAPI);
 368  
                         if (asAPI) {
 369  
                                 sb.append(isHor ? ".shrinkX(" : ".shrinkY(").append(s).append(')');
 370  
                         } else {
 371  
                                 sb.append(isHor ? ",shrinkx " : ",shrinky ").append(s);
 372  
                         }
 373  
                 }
 374  
 
 375  
                 String eg = dc.getEndGroup();
 376  
                 if (eg != null) {
 377  
                         if (asAPI) {
 378  
                                 sb.append(isHor ? ".endGroupX(\"" : ".endGroupY(\"").append(eg).append("\")");
 379  
                         } else {
 380  
                                 sb.append(isHor ? ",endgroupx " : ",endgroupy ").append(eg);
 381  
                         }
 382  
                 }
 383  
 
 384  
                 String sg = dc.getSizeGroup();
 385  
                 if (sg != null) {
 386  
                         if (asAPI) {
 387  
                                 sb.append(isHor ? ".sizeGroupX(\"" : ".sizeGroupY(\"").append(sg).append("\")");
 388  
                         } else {
 389  
                                 sb.append(isHor ? ",sizegroupx " : ",sizegroupy ").append(sg);
 390  
                         }
 391  
                 }
 392  
 
 393  
                 appendBoundSize(dc.getSize(), sb, isHor, asAPI);
 394  
 
 395  
                 UnitValue al = dc.getAlign();
 396  
                 if (al != null) {
 397  
                         if (asAPI) {
 398  
                                 sb.append(isHor ? ".alignX(\"" : ".alignY(\"").append(getUV(al)).append("\")");
 399  
                         } else {
 400  
                                 sb.append(isHor ? ",alignx " : ",aligny ").append(getUV(al));
 401  
                         }
 402  
                 }
 403  
 
 404  
                 BoundSize gapBef = dc.getGapBefore();
 405  
                 BoundSize gapAft= dc.getGapAfter();
 406  
                 if (gapBef != null || gapAft != null) {
 407  
                         if (asAPI) {
 408  
                                 sb.append(isHor ? ".gapX(\"" : ".gapY(\"").append(getBS(gapBef)).append("\", \"").append(getBS(gapAft)).append("\")");
 409  
                         } else {
 410  
                                 sb.append(isHor ? ",gapx " : ",gapy ").append(getBS(gapBef));
 411  
                                 if (gapAft != null)
 412  
                                         sb.append(' ').append(getBS(gapAft));
 413  
                         }
 414  
                 }
 415  
         }
 416  
 
 417  
         private static void appendBoundSize(BoundSize size, StringBuffer sb, boolean isHor, boolean asAPI)
 418  
         {
 419  
                 if (size.isUnset() == false) {
 420  
                         if (size.getPreferred() == null) {
 421  
                                 if (size.getMin() == null) {
 422  
                                         if (asAPI) {
 423  
                                                 sb.append(isHor ? ".maxWidth(\"" : ".maxHeight(\"").append(getUV(size.getMax())).append("\")");
 424  
                                         } else {
 425  
                                                 sb.append(isHor ? ",wmax " : ",hmax ").append(getUV(size.getMax()));
 426  
                                         }
 427  
 
 428  
                                 } else if (size.getMax() == null) {
 429  
                                         if (asAPI) {
 430  
                                                 sb.append(isHor ? ".minWidth(\"" : ".minHeight(\"").append(getUV(size.getMin())).append("\")");
 431  
                                         } else {
 432  
                                                 sb.append(isHor ? ",wmin " : ",hmin ").append(getUV(size.getMin()));
 433  
                                         }
 434  
                                 } else { // None are null
 435  
                                         if (asAPI) {
 436  
                                                 sb.append(isHor ? ".width(\"" : ".height(\"").append(getUV(size.getMin())).append("::").append(getUV(size.getMax())).append("\")");
 437  
                                         } else {
 438  
                                                 sb.append(isHor ? ",width " : ",height ").append(getUV(size.getMin())).append("::").append(getUV(size.getMax()));
 439  
                                         }
 440  
                                 }
 441  
                         } else {
 442  
                                 if (asAPI) {
 443  
                                         sb.append(isHor ? ".width(\"" : ".height(\"").append(getBS(size)).append("\")");
 444  
                                 } else {
 445  
                                         sb.append(isHor ? ",width " : ",height ").append(getBS(size));
 446  
                                 }
 447  
                         }
 448  
                 }
 449  
         }
 450  
 
 451  
         /** Returns the a constraint string that can be re-parsed to be the exact same LayoutConstraint.
 452  
          * @param cc The component constraint to return as a constraint string.
 453  
          * @param asAPI If the returned string should be of API type (e.g. .flowX().gap("rel").align("right")) or
 454  
          * as a String type (e.g. "flowx, gap rel, right").
 455  
          * @return A String. Never <code>null</code>.
 456  
          */
 457  
         public static String getConstraintString(CC cc, boolean asAPI)
 458  
         {
 459  
                 StringBuffer sb = new StringBuffer(16);
 460  
 
 461  
                 if (cc.isNewline())
 462  
                         sb.append(asAPI ? ".newline()" : ",newline");
 463  
 
 464  
                 if (cc.isExternal())
 465  
                         sb.append(asAPI ? ".external()" : ",external");
 466  
 
 467  
                 Boolean flowX = cc.getFlowX();
 468  
                 if (flowX != null) {
 469  
                         if (asAPI) {
 470  
                                 sb.append(flowX ? ".flowX()" : ".flowY()");
 471  
                         } else {
 472  
                                 sb.append(flowX ? ",flowx" : ",flowy");
 473  
                         }
 474  
                 }
 475  
 
 476  
                 UnitValue[] pad = cc.getPadding();
 477  
                 if (pad != null) {
 478  
                         sb.append(asAPI ? ".pad(\"" : ",pad ");
 479  
                         for (int i = 0; i < pad.length; i++)
 480  
                                 sb.append(getUV(pad[i])).append(i < pad.length - 1 ? " " : "");
 481  
                         if (asAPI)
 482  
                                 sb.append("\")");
 483  
                 }
 484  
 
 485  
                 UnitValue[] pos = cc.getPos();
 486  
                 if (pos != null) {
 487  
                         if (cc.isBoundsInGrid()) {
 488  
                                 for (int i = 0; i < 4; i++) {
 489  
                                         if (pos[i] != null) {
 490  
                                                 if (asAPI) {
 491  
                                                         sb.append('.').append(X_Y_STRINGS[i]).append("(\"").append(getUV(pos[i])).append("\")");
 492  
                                                 } else {
 493  
                                                         sb.append(',').append(X_Y_STRINGS[i]).append(getUV(pos[i]));
 494  
                                                 }
 495  
                                         }
 496  
                                 }
 497  
                         } else {
 498  
                                 sb.append(asAPI ? ".pos(\"" : ",pos ");
 499  
                                 int iSz = (pos[2] != null || pos[3] != null) ? 4 : 2;  // "pos x y" vs "pos x1 y1 x2 y2".
 500  
                                 for (int i = 0; i < iSz; i++)
 501  
                                         sb.append(getUV(pos[i])).append(i < iSz - 1 ? " " : "");
 502  
 
 503  
                                 if (asAPI)
 504  
                                         sb.append("\")");
 505  
                         }
 506  
                 }
 507  
 
 508  
                 String id = cc.getId();
 509  
                 if (id != null) {
 510  
                         if (asAPI) {
 511  
                                 sb.append(".id(\"").append(id).append("\")");
 512  
                         } else {
 513  
                                 sb.append(",id ").append(id);
 514  
                         }
 515  
                 }
 516  
 
 517  
                 String tag = cc.getTag();
 518  
                 if (tag != null) {
 519  
                         if (asAPI) {
 520  
                                 sb.append(".tag(\"").append(tag).append("\")");
 521  
                         } else {
 522  
                                 sb.append(",tag ").append(tag);
 523  
                         }
 524  
                 }
 525  
 
 526  
                 int hideMode = cc.getHideMode();
 527  
                 if (hideMode >= 0) {
 528  
                         if (asAPI) {
 529  
                                 sb.append(".hidemode(").append(hideMode).append(')');
 530  
                         } else {
 531  
                                 sb.append(",hidemode ").append(hideMode);
 532  
                         }
 533  
                 }
 534  
 
 535  
                 int skip = cc.getSkip();
 536  
                 if (skip > 0) {
 537  
                         if (asAPI) {
 538  
                                 sb.append(".skip(").append(skip).append(')');
 539  
                         } else {
 540  
                                 sb.append(",skip ").append(skip);
 541  
                         }
 542  
                 }
 543  
 
 544  
                 int split = cc.getSplit();
 545  
                 if (split > 1) {
 546  
                         String s = split == LayoutUtil.INF ? "" : String.valueOf(split);
 547  
                         if (asAPI) {
 548  
                                 sb.append(".split(").append(s).append(')');
 549  
                         } else {
 550  
                                 sb.append(",split ").append(s);
 551  
                         }
 552  
                 }
 553  
 
 554  
                 int cx = cc.getCellX();
 555  
                 int cy = cc.getCellY();
 556  
                 int spanX = cc.getSpanX();
 557  
                 int spanY = cc.getSpanY();
 558  
                 if (cx >= 0 && cy >= 0) {
 559  
                         if (asAPI) {
 560  
                                 sb.append(".cell(").append(cx).append(", ").append(cy);
 561  
                                 if (spanX > 1 || spanY > 1)
 562  
                                         sb.append(", ").append(spanX).append(", ").append(spanY);
 563  
                                 sb.append(')');
 564  
                         } else {
 565  
                                 sb.append(",cell ").append(cx).append(' ').append(cy);
 566  
                                 if (spanX > 1 || spanY > 1)
 567  
                                         sb.append(' ').append(spanX).append(' ').append(spanY);
 568  
                         }
 569  
                 } else if (spanX > 1 || spanY > 1) {
 570  
                         if (spanX > 1 && spanY > 1) {
 571  
                                 sb.append(asAPI ? ".span(" : ",span ").append(spanX).append(asAPI ? ", " : " ").append(spanY);
 572  
                         } else if (spanX > 1) {
 573  
                                 sb.append(asAPI ? ".spanX(" : ",spanx ").append(spanX == LayoutUtil.INF ? "" : (String.valueOf(spanX)));
 574  
                         } else if (spanY > 1) {
 575  
                                 sb.append(asAPI ? ".spanY(" : ",spany ").append(spanY == LayoutUtil.INF ? "" : (String.valueOf(spanY)));
 576  
                         }
 577  
                         if (asAPI)
 578  
                                 sb.append(')');
 579  
                 }
 580  
 
 581  
                 Float pushX = cc.getPushX();
 582  
                 Float pushY = cc.getPushY();
 583  
                 if (pushX != null || pushY != null) {
 584  
                         if (pushX != null && pushY != null) {
 585  
                                 sb.append(asAPI ? ".push(" : ",push ");
 586  
                                 if (pushX != 100.0 || pushY != 100.0)
 587  
                                         sb.append(pushX).append(asAPI ? ", " : " ").append(pushY);
 588  
                         } else if (pushX != null) {
 589  
                                 sb.append(asAPI ? ".pushX(" : ",pushx ").append(pushX == 100 ? "" : (String.valueOf(pushX)));
 590  
                         } else if (pushY != null) {
 591  
                                 sb.append(asAPI ? ".pushY(" : ",pushy ").append(pushY == 100 ? "" : (String.valueOf(pushY)));
 592  
                         }
 593  
                         if (asAPI)
 594  
                                 sb.append(')');
 595  
                 }
 596  
 
 597  
                 int dock = cc.getDockSide();
 598  
                 if (dock >= 0) {
 599  
                         String ds = CC.DOCK_SIDES[dock];
 600  
                         if (asAPI) {
 601  
                                 sb.append(".dock").append(Character.toUpperCase(ds.charAt(0))).append(ds.substring(1)).append("()");
 602  
                         } else {
 603  
                                 sb.append(",").append(ds);
 604  
                         }
 605  
                 }
 606  
 
 607  
                 boolean noGrowAdd = cc.getHorizontal().getGrow() != null && cc.getHorizontal().getGrow().intValue() == 100 &&
 608  
                                     cc.getVertical().getGrow() != null && cc.getVertical().getGrow().intValue() == 100;
 609  
 
 610  
                 addComponentDimConstraintString(cc.getHorizontal(), sb, asAPI, true, noGrowAdd);
 611  
                 addComponentDimConstraintString(cc.getVertical(), sb, asAPI, false, noGrowAdd);
 612  
                 if (noGrowAdd)
 613  
                         sb.append(asAPI ? ".grow()" : ",grow");   // Combine ".growX().growY()" into ".grow()".
 614  
 
 615  
                 if (cc.isWrap())
 616  
                         sb.append(asAPI ? ".wrap()" : ",wrap");
 617  
 
 618  
                 String s = sb.toString();
 619  
                 return s.length() == 0 || s.charAt(0) != ',' ? s : s.substring(1);
 620  
         }
 621  
 
 622  
         /** Returns the a constraint string that can be re-parsed to be the exact same LayoutConstraint.
 623  
          * @param lc The layout constraint to return as a constraint string.
 624  
          * @param asAPI If the returned string should be of API type (e.g. .flowX().gap("rel").align("right")) or
 625  
          * as a String type (e.g. "flowx, gap rel, right").
 626  
          * @return A String. Never <code>null</code>.
 627  
          */
 628  
         public static String getConstraintString(LC lc, boolean asAPI)
 629  
         {
 630  
                 StringBuffer sb = new StringBuffer(16);
 631  
 
 632  
                 if (lc.isFlowX() == false)
 633  
                         sb.append(asAPI ? ".flowY()" : ",flowy");
 634  
 
 635  
                 boolean fillX = lc.isFillX();
 636  
                 boolean fillY = lc.isFillY();
 637  
                 if (fillX || fillY) {
 638  
                         if (fillX == fillY) {
 639  
                                 sb.append(asAPI ? ".fill()" : ",fill");
 640  
                         } else {
 641  
                                 sb.append(asAPI ? (fillX ? ".fillX()" : ".fillY()") : (fillX ? ",fillx" : ",filly"));
 642  
                         }
 643  
                 }
 644  
 
 645  
                 Boolean leftToRight = lc.getLeftToRight();
 646  
                 if (leftToRight != null) {
 647  
                         if (asAPI) {
 648  
                                 sb.append(".leftToRight(").append(leftToRight).append(')');
 649  
                         } else {
 650  
                                 sb.append(leftToRight ? ",ltr" : ",rtl");
 651  
                         }
 652  
                 }
 653  
 
 654  
                 if (!lc.getPackWidth().isUnset() || !lc.getPackHeight().isUnset()) {
 655  
                         if (asAPI) {
 656  
                                 String w = getBS(lc.getPackWidth());
 657  
                                 String h = getBS(lc.getPackHeight());
 658  
                                 sb.append(".pack(");
 659  
                                 if (w.equals("pref") && h.equals("pref")) {
 660  
                                         sb.append(')');
 661  
                                 } else {
 662  
                                         sb.append('\"').append(w).append("\", \"").append(h).append("\")");
 663  
                                 }
 664  
                         } else {
 665  
                                 sb.append(",pack");
 666  
                                 String size = getBS(lc.getPackWidth()) + " " + getBS(lc.getPackHeight());
 667  
                                 if (size.equals("pref pref") == false)
 668  
                                         sb.append(' ').append(size);
 669  
                         }
 670  
                 }
 671  
 
 672  
                 if (lc.getPackWidthAlign() != 0.5f || lc.getPackHeightAlign() != 1f) {
 673  
                         if (asAPI) {
 674  
                                 sb.append(".packAlign(").append(floatToString(lc.getPackWidthAlign(), asAPI)).append(", ").append(floatToString(lc.getPackHeightAlign(), asAPI)).append(')');
 675  
                         } else {
 676  
                                 sb.append(",packalign ").append(floatToString(lc.getPackWidthAlign(), asAPI)).append(' ').append(floatToString(lc.getPackHeightAlign(), asAPI));
 677  
                         }
 678  
                 }
 679  
 
 680  
                 if (lc.isTopToBottom() == false)
 681  
                         sb.append(asAPI ? ".bottomToTop()" : ",btt");
 682  
 
 683  
                 UnitValue[] insets = lc.getInsets();
 684  
                 if (insets != null) {
 685  
                         String cs = LayoutUtil.getCCString(insets);
 686  
                         if (cs != null) {
 687  
                                 if (asAPI) {
 688  
                                         sb.append(".insets(\"").append(cs).append("\")");
 689  
                                 } else {
 690  
                                         sb.append(",insets ").append(cs);
 691  
                                 }
 692  
                         } else {
 693  
                                 sb.append(asAPI ? ".insets(\"" : ",insets ");
 694  
                                 for (int i = 0; i < insets.length; i++)
 695  
                                         sb.append(getUV(insets[i])).append(i < insets.length - 1 ? " " : "");
 696  
                                 if (asAPI)
 697  
                                         sb.append("\")");
 698  
                         }
 699  
                 }
 700  
 
 701  
                 if (lc.isNoGrid())
 702  
                         sb.append(asAPI ? ".noGrid()" : ",nogrid");
 703  
 
 704  
                 if (lc.isVisualPadding() == false)
 705  
                         sb.append(asAPI ? ".noVisualPadding()" : ",novisualpadding");
 706  
 
 707  
                 int hideMode = lc.getHideMode();
 708  
                 if (hideMode > 0) {
 709  
                         if (asAPI) {
 710  
                                 sb.append(".hideMode(").append(hideMode).append(')');
 711  
                         } else {
 712  
                                 sb.append(",hideMode ").append(hideMode);
 713  
                         }
 714  
                 }
 715  
 
 716  
                 appendBoundSize(lc.getWidth(), sb, true, asAPI);
 717  
                 appendBoundSize(lc.getHeight(), sb, false, asAPI);
 718  
 
 719  
                 UnitValue alignX = lc.getAlignX();
 720  
                 UnitValue alignY = lc.getAlignY();
 721  
                 if (alignX != null || alignY != null) {
 722  
                         if (alignX != null && alignY != null) {
 723  
                                 sb.append(asAPI ? ".align(\"" : ",align ").append(getUV(alignX)).append(' ').append(getUV(alignY));
 724  
                         } else if (alignX != null) {
 725  
                                 sb.append(asAPI ? ".alignX(\"" : ",alignx ").append(getUV(alignX));
 726  
                         } else if (alignY != null) {
 727  
                                 sb.append(asAPI ? ".alignY(\"" : ",aligny ").append(getUV(alignY));
 728  
                         }
 729  
                         if (asAPI)
 730  
                                 sb.append("\")");
 731  
                 }
 732  
 
 733  
                 BoundSize gridGapX = lc.getGridGapX();
 734  
                 BoundSize gridGapY = lc.getGridGapY();
 735  
                 if (gridGapX != null || gridGapY != null) {
 736  
                         if (gridGapX != null && gridGapY != null) {
 737  
                                 sb.append(asAPI ? ".gridGap(\"" : ",gap ").append(getBS(gridGapX)).append(' ').append(getBS(gridGapY));
 738  
                         } else if (gridGapX != null) {
 739  
                                 sb.append(asAPI ? ".gridGapX(\"" : ",gapx ").append(getBS(gridGapX));
 740  
                         } else if (gridGapY != null) {
 741  
                                 sb.append(asAPI ? ".gridGapY(\"" : ",gapy ").append(getBS(gridGapY));
 742  
                         }
 743  
                         if (asAPI)
 744  
                                 sb.append("\")");
 745  
                 }
 746  
 
 747  
                 int wrapAfter = lc.getWrapAfter();
 748  
                 if (wrapAfter != LayoutUtil.INF) {
 749  
                         String ws = wrapAfter > 0 ? String.valueOf(wrapAfter) : "";
 750  
                         if (asAPI) {
 751  
                                 sb.append(".wrap(").append(ws).append(')');
 752  
                         } else {
 753  
                                 sb.append(",wrap ").append(ws);
 754  
                         }
 755  
                 }
 756  
 
 757  
                 int debugMillis = lc.getDebugMillis();
 758  
                 if (debugMillis > 0) {
 759  
                         if (asAPI) {
 760  
                                 sb.append(".debug(").append(debugMillis).append(')');
 761  
                         } else {
 762  
                                 sb.append(",debug ").append(debugMillis);
 763  
                         }
 764  
                 }
 765  
 
 766  
                 String s = sb.toString();
 767  
                 return s.length() == 0 || s.charAt(0) != ',' ? s : s.substring(1);
 768  
         }
 769  
 
 770  
         private static String getUV(UnitValue uv)
 771  
         {
 772  
                 return uv != null ? uv.getConstraintString() : "null";
 773  
         }
 774  
 
 775  
         private static String getBS(BoundSize bs)
 776  
         {
 777  
                 return bs != null ? bs.getConstraintString() : "null";
 778  
         }
 779  
 
 780  
         /** Converts a <code>float</code> to a string and is removing the ".0" if the float is an integer.
 781  
          * @param f the float.
 782  
          * @return <code>f</code> as a string. Never <code>null</code>.
 783  
          */
 784  
         private static String floatToString(float f, boolean asAPI)
 785  
         {
 786  
                 String valS = String.valueOf(f);
 787  
                 return valS.endsWith(".0") ? valS.substring(0, valS.length() - 2) : (valS + (asAPI ? "f" : ""));
 788  
         }
 789  
 }