edu.kit.dama.ui.commons.util.UIUtils7.java Source code

Java tutorial

Introduction

Here is the source code for edu.kit.dama.ui.commons.util.UIUtils7.java

Source

/**
 * Copyright (C) 2014 Karlsruhe Institute of Technology 
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package edu.kit.dama.ui.commons.util;

import com.vaadin.data.Validator;
import com.vaadin.data.validator.StringLengthValidator;
import com.vaadin.server.FileResource;
import com.vaadin.server.UserError;
import com.vaadin.shared.ui.label.ContentMode;
import com.vaadin.ui.AbstractComponent;
import com.vaadin.ui.AbstractComponentContainer;
import com.vaadin.ui.AbstractField;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.Component;
import com.vaadin.ui.ComponentContainer;
import com.vaadin.ui.Embedded;
import com.vaadin.ui.GridLayout;
import com.vaadin.ui.Image;
import com.vaadin.ui.Label;
import com.vaadin.ui.Link;
import com.vaadin.ui.PasswordField;
import com.vaadin.ui.TextArea;
import com.vaadin.ui.TextField;
import com.vaadin.ui.UI;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.Window;
import java.io.File;
import java.io.PrintStream;
import java.util.Iterator;
import org.apache.commons.lang3.StringUtils;

/**
 * UIUtils7 containing several helper methods for working with Vaadin UIs. This
 * implementation is identical with
 * {@link edu.kit.dama.ui.commons.util.UIUtils7} but compatible with Vaadin
 * 7.
 *
 * @author jejkal
 */
public class UIUtils7 {

    /**
     * Set all components within pContainer to readOnly/notReadOnly. If pRecursive
     * is set true, containers withing the provided container are processed
     * recursively. If a contained component is a button, the button is
     * enabled/disabled instead of setting it to readOnly.
     *
     * @param pContainer The container to process
     * @param pRecursive Recurse into sub-containers
     * @param pValue TRUE = ReadOnly
     */
    public static void setReadOnly(ComponentContainer pContainer, boolean pRecursive, boolean pValue) {
        pContainer.setReadOnly(pValue);

        if (pRecursive) {
            Iterator<Component> com = pContainer.iterator();
            while (com.hasNext()) {
                Component next = com.next();
                if (next instanceof ComponentContainer) {
                    setReadOnly((ComponentContainer) next, pRecursive, pValue);
                } else if (next instanceof Button) {
                    ((Button) next).setEnabled(!pValue);
                } else {
                    next.setReadOnly(pValue);
                }
            }
        }
    }

    /**
     * Enable/disable all components within pContainer. If pRecursive is set true,
     * containers withing the provided container are processed recursively.
     *
     * @param pContainer The container to process
     * @param pRecursive Recurse into sub-containers
     * @param pValue TRUE = Enabled
     */
    public static void setEnabled(ComponentContainer pContainer, boolean pRecursive, boolean pValue) {
        pContainer.setReadOnly(pValue);

        if (pRecursive) {
            Iterator<Component> com = pContainer.iterator();
            while (com.hasNext()) {
                Component next = com.next();
                if (next instanceof ComponentContainer) {
                    setEnabled((ComponentContainer) next, pRecursive, pValue);
                } else {
                    next.setEnabled(pValue);
                }
            }
        }
    }

    /**
     * Create a text area with the provided properties. The size is set to
     * SizeFull and the text area is set to 'immediate' (show changed immediately
     * to the user).
     *
     * @param pCaption The caption
     * @param pInputPrompt The input prompt shown if no value is set
     * @param pMaxLength The max. string length of the text area. The content can
     * be checked during validation.
     *
     * @return The text area
     */
    public static TextArea factoryTextArea(String pCaption, String pInputPrompt, int pMaxLength) {
        return factoryTextArea(pCaption, pInputPrompt, -1, pMaxLength);
    }

    /**
     * Create a text area with the provided properties. The size is set to
     * SizeFull and the text area is set to 'immediate' (show changed immediately
     * to the user).
     *
     * @param pCaption The caption
     * @param pInputPrompt The input prompt shown if no value is set
     * @param pMinLength The min. string length of the text area. The content can
     * be checked during validation.
     * @param pMaxLength The max. string length of the text area. The content can
     * be checked during validation.
     *
     * @return The text area
     */
    public static TextArea factoryTextArea(String pCaption, String pInputPrompt, int pMinLength, int pMaxLength) {
        TextArea theArea = new TextArea();
        theArea.setCaption(pCaption);
        theArea.setImmediate(true);
        theArea.setSizeFull();
        theArea.setInputPrompt(pInputPrompt);
        theArea.setNullSettingAllowed(false);
        theArea.setNullRepresentation("");
        StringLengthValidator val;
        if (pMinLength > 0) {
            val = new StringLengthValidator("The content length of this text area must be between " + pMinLength
                    + " and " + pMaxLength + " characters.");
            val.setMinLength(pMinLength);
        } else {
            val = new StringLengthValidator(
                    "The maximum content length of this text area is " + pMaxLength + " characters.");
        }

        val.setMaxLength(pMaxLength);
        theArea.addValidator(val);
        return theArea;
    }

    /**
     * Create a text area with the provided properties. The size is set to
     * SizeFull and the text area is set to 'immediate' (show changed immediately
     * to the user). The max. string length for the returned area is 1024
     * characters.
     *
     * @param pCaption The caption
     * @param pInputPrompt The input prompt shown if no value is set
     *
     * @return The text area
     */
    public static TextArea factoryTextArea(String pCaption, String pInputPrompt) {
        return factoryTextArea(pCaption, pInputPrompt, 1024);
    }

    /**
     * Create a text field with the provided properties. The width is set to 100%
     * and the text field is set to 'immediate' (show changed immediately to the
     * user). The max. string length for the returned field is 255 characters.
     *
     * @param pCaption The field caption
     * @param pInputPrompt The input prompt shown if no value is set
     *
     * @return The text field
     *
     * @see factoryTextField(String pCaption, String pInputPrompt, String pWidth,
     * boolean pImmediate)
     */
    public static TextField factoryTextField(String pCaption, String pInputPrompt) {
        return factoryTextField(pCaption, pInputPrompt, "100%", true, -1, 255);
    }

    /**
     * Create a text field with the provided properties. The width is set to 100%
     * and the text field is set to 'immediate' (show changed immediately to the
     * user). The max. string length for the returned field is 255 characters.
     *
     * @param pCaption The field caption
     * @param pInputPrompt The input prompt shown if no value is set
     * @param pMinLength The min length.
     *
     * @return The text field
     *
     * @see factoryTextField(String pCaption, String pInputPrompt, String pWidth,
     * boolean pImmediate)
     */
    public static TextField factoryTextField(String pCaption, String pInputPrompt, int pMinLength) {
        return factoryTextField(pCaption, pInputPrompt, "100%", true, pMinLength, 255);
    }

    /**
     * Create a text field with the provided properties. The width is set to 100%
     * and the text field is set to 'immediate' (show changed immediately to the
     * user).
     *
     * @param pCaption The field caption
     * @param pInputPrompt The input prompt shown if no value is set
     * @param pMinLength The min length.
     * @param pMaxLength The max length.
     *
     * @return The text field
     *
     * @see factoryTextField(String pCaption, String pInputPrompt, String pWidth,
     * boolean pImmediate)
     */
    public static TextField factoryTextField(String pCaption, String pInputPrompt, int pMinLength, int pMaxLength) {
        return factoryTextField(pCaption, pInputPrompt, "100%", true, pMinLength, pMaxLength);
    }

    /**
     * Create a text field with the provided properties. In addition, the returned
     * text field won't allow to set 'null' values by the user and has no
     * null-representation. Therefore it shows the input prompt when no value is
     * provided. The height of the text field is left to the default value
     * ('undefined').
     *
     * @param pCaption The field caption
     * @param pInputPrompt The input prompt shown if no value is set
     * @param pWidth The field width (e.g. 100% or 60px)
     * @param pImmediate The value of the 'immediate' flag
     * @param pMaxLength The max. string length of the text field. The content can
     * be checked during validation.
     *
     * @return The text field
     */
    public static TextField factoryTextField(String pCaption, String pInputPrompt, String pWidth,
            boolean pImmediate, int pMaxLength) {
        return factoryTextField(pCaption, pInputPrompt, pWidth, pImmediate, -1, pMaxLength);
    }

    /**
     * Create a text field with the provided properties. In addition, the returned
     * text field won't allow to set 'null' values by the user and has no
     * null-representation. Therefore it shows the input prompt when no value is
     * provided. The height of the text field is left to the default value
     * ('undefined').
     *
     * @param pCaption The field caption.
     * @param pInputPrompt The input prompt shown if no value is set.
     * @param pWidth The field width (e.g. 100% or 60px).
     * @param pImmediate The value of the 'immediate' flag.
     * @param pMinLength The min. string length of the text field. The content can
     * be checked during validation.
     * @param pMaxLength The max. string length of the text field. The content can
     * be checked during validation.
     *
     * @return The text field
     */
    public static TextField factoryTextField(String pCaption, String pInputPrompt, String pWidth,
            boolean pImmediate, int pMinLength, int pMaxLength) {
        TextField theField = new TextField();
        theField.setCaption(pCaption);
        theField.setImmediate(pImmediate);
        theField.setWidth(pWidth);
        theField.setInputPrompt(pInputPrompt);
        theField.setNullSettingAllowed(false);
        theField.setNullRepresentation("");

        StringLengthValidator val;
        if (pMinLength > 0) {
            val = new StringLengthValidator("The content length of this text field must be between " + pMinLength
                    + " and " + pMaxLength + " characters.");
            val.setMinLength(pMinLength);
        } else {
            val = new StringLengthValidator(
                    "The maximum content length of this text field is " + pMaxLength + " characters.");
        }
        val.setMaxLength(pMaxLength);
        theField.addValidator(val);
        return theField;
    }

    /**
     * Create a password field with the provided properties. In addition, the
     * returned password field won't allow to set 'null' values by the user and
     * has no null-representation. As this is a password field, no input prompt is
     * shown. The height of the text field is left to the default value
     * ('undefined').
     *
     * @param pCaption The field caption.
     * @param pWidth The field width (e.g. 100% or 60px).
     * @param pImmediate The value of the 'immediate' flag.
     * @param pMinLength The min. string length of the text field. The content can
     * be checked during validation.
     * @param pMaxLength The max. string length of the text field. The content can
     * be checked during validation.
     *
     * @return The text field
     */
    public static PasswordField factoryPasswordField(String pCaption, String pWidth, boolean pImmediate,
            int pMinLength, int pMaxLength) {
        PasswordField theField = new PasswordField();
        theField.setCaption(pCaption);
        theField.setImmediate(pImmediate);
        theField.setWidth(pWidth);
        theField.setNullSettingAllowed(false);
        theField.setNullRepresentation("");

        StringLengthValidator val;
        if (pMinLength > 0) {
            val = new StringLengthValidator("The content length of this text field must be between " + pMinLength
                    + " and " + pMaxLength + " characters.");
            val.setMinLength(pMinLength);
        } else {
            val = new StringLengthValidator(
                    "The maximum content length of this text field is " + pMaxLength + " characters.");
        }
        val.setMaxLength(pMaxLength);
        theField.addValidator(val);
        return theField;
    }

    /**
     * Validate all components within the provided component container. If a
     * component is invalid, an appropriate component error will be set and the
     * method returns 'FALSE'. For valid components, the component error will be
     * removed. If all components are valid according to their setup, 'TRUE' will
     * be returned. A component can be invalid because:
     *
     * <ul>
     *
     * <li>A validator installed by <i>Component.addValidator()</i> fails</li>
     *
     * <li>The component is marked as 'required' and contains no value</li>
     *
     * </ul>
     *
     *
     * @param pContainer The component container to validate.
     *
     * @return TRUE if all components within pContainer are valid.
     */
    public static boolean validate(ComponentContainer pContainer) {
        boolean result = true;
        Iterator<Component> i = pContainer.iterator();
        while (i.hasNext()) {
            Component c = i.next();
            result = validate(c);
        }
        return result;
    }

    /**
     * Validate a single component. If a component is invalid, an appropriate
     * component error will be set and the method returns 'FALSE'. For valid
     * components, the component error will be removed. If the component is valid
     * according to their setup, 'TRUE' will be returned. A component can be
     * invalid because:
     *
     * <ul>
     *
     * <li>A validator installed by <i>Component.addValidator()</i> fails</li>
     *
     * <li>The component is marked as 'required' and contains no value</li>
     *
     * </ul>
     *
     * @param pComponent The component to validate.
     *
     * @return TRUE if the component is valid.
     */
    public static boolean validate(Component pComponent) {
        boolean result = true;
        if (pComponent instanceof AbstractField) {
            try {
                ((AbstractField) pComponent).validate();
                ((AbstractField) pComponent).setComponentError(null);
            } catch (Validator.InvalidValueException e) {
                ((AbstractComponent) pComponent)
                        .setComponentError(new UserError("The value of this field is invalid."));
                result = false;
            }
        } else if (pComponent instanceof AbstractComponentContainer) {
            if (!validate((AbstractComponentContainer) pComponent)) {
                result = false;
            }
        }
        return result;
    }

    public static void openResourceSubWindow(File sourceFile) {
        boolean fileAccessible = sourceFile != null && sourceFile.exists() && sourceFile.canRead();

        // Set subwindow for displaying file resource
        final Window window = new Window(fileAccessible ? sourceFile.getName() : "Information");
        window.center();
        // Set window layout
        VerticalLayout windowLayout = new VerticalLayout();
        windowLayout.setSizeFull();

        if (fileAccessible) {
            // Set resource that has to be embedded
            final Embedded resource = new Embedded(null, new FileResource(sourceFile));
            if ("application/octet-stream".equals(resource.getMimeType())) {
                window.setWidth("570px");
                window.setHeight("150px");
                windowLayout.setMargin(true);

                Label attentionNote = new Label(
                        "A file preview is not possible as the file type is not supported by your browser.");
                attentionNote.setContentMode(ContentMode.HTML);
                Link fileURL = new Link("Click here for downloading the file.", new FileResource(sourceFile));

                windowLayout.addComponent(attentionNote);
                windowLayout.addComponent(fileURL);
                windowLayout.setComponentAlignment(attentionNote, Alignment.MIDDLE_CENTER);
                windowLayout.setComponentAlignment(fileURL, Alignment.MIDDLE_CENTER);
            } else {
                window.setResizable(true);
                window.setWidth("800px");
                window.setHeight("500px");
                final Image image = new Image(null, new FileResource(sourceFile));
                image.setSizeFull();
                windowLayout.addComponent(image);
            }
        } else {
            //file is not accessible
            window.setWidth("570px");
            window.setHeight("150px");
            windowLayout.setMargin(true);
            Label attentionNote = new Label("Provided file cannot be accessed.");
            attentionNote.setContentMode(ContentMode.HTML);
            windowLayout.addComponent(attentionNote);
            windowLayout.setComponentAlignment(attentionNote, Alignment.MIDDLE_CENTER);
        }

        window.setContent(windowLayout);
        UI.getCurrent().addWindow(window);
    }

    public static class GridLayoutBuilder {

        /**
         * The default alignment of a component within a cell
         */
        private static final Alignment DEFAULT_ALIGNMENT = Alignment.TOP_LEFT;
        /**
         * A representation used for empty cells
         */
        private static final String EMPTY_CELL = "||||||||||";
        /**
         * The final layout
         */
        private final GridLayout layout;
        /**
         * The debugging representation of the layout
         */
        private final String[][] assignedFields;
        /**
         * The number of columns
         */
        private final int columns;
        /**
         * The number of rows
         */
        private final int rows;

        /**
         * The default constructor initializing a layout builder with the provided
         * dimensions.
         *
         * @param pColumns The number of columns
         * @param pRows The number of rows
         */
        public GridLayoutBuilder(int pColumns, int pRows) {
            columns = pColumns;
            rows = pRows;
            layout = new GridLayout(columns, rows);
            assignedFields = new String[columns][rows];

            for (int i = 0; i < columns; i++) {
                for (int j = 0; j < rows; j++) {
                    assignedFields[i][j] = EMPTY_CELL;
                }
            }
        }

        /**
         * The constructor taking an existing GridLayout. This layout is parsed and
         * may be filled (only for cells which are not assigned yet) or printed out
         * for debugging purposes.
         *
         * @param pLayout The existing layout
         */
        public GridLayoutBuilder(GridLayout pLayout) {
            columns = pLayout.getColumns();
            rows = pLayout.getRows();
            assignedFields = new String[columns][rows];

            for (int i = 0; i < columns; i++) {
                for (int j = 0; j < rows; j++) {
                    assignedFields[i][j] = EMPTY_CELL;
                }
            }
            for (int i = 0; i < columns; i++) {
                for (int j = 0; j < rows; j++) {
                    Component com = pLayout.getComponent(i, j);
                    if (com != null) {
                        assignedFields[i][j] = getComponentIdentifier(com);
                    }
                }
            }
            layout = pLayout;
        }

        /**
         * Add a component filling row and column defined by pColumn and pRow till
         * the end of the grid. The default default alignment is used.
         *
         * @param pComponent The component, which must not be 'null'
         * @param pColumn The target column
         * @param pRow The target row
         *
         * @return GridLayoutBuilder.this
         */
        public GridLayoutBuilder fill(Component pComponent, int pColumn, int pRow) {
            return addComponent(pComponent, null, pColumn, pRow, columns - pColumn, rows - pRow);
        }

        /**
         * Add a component filling row and column defined by pColumn and pRow till
         * the end of the grid.
         *
         * @param pComponent The component, which must not be 'null'
         * @param pAlignment The component alignment within the cell
         * @param pColumn The target column
         * @param pRow The target row
         *
         * @return GridLayoutBuilder.this
         */
        public GridLayoutBuilder fill(Component pComponent, Alignment pAlignment, int pColumn, int pRow) {
            return addComponent(pComponent, pAlignment, pColumn, pRow, columns - pColumn, rows - pRow);
        }

        /**
         * Add a component filling the column defined by pColumn till the end of the
         * grid. The default default alignment is used.
         *
         * @param pComponent The component, which must not be 'null'
         * @param pColumn The target column
         * @param pRow The target row
         * @param pWidth The width in cells
         *
         * @return GridLayoutBuilder.this
         */
        public GridLayoutBuilder fillColumn(Component pComponent, int pColumn, int pRow, int pWidth) {
            return addComponent(pComponent, null, pColumn, pRow, pWidth, rows - pRow);
        }

        /**
         * Add a component filling the column defined by pColumn till the end of the
         * grid.
         *
         * @param pComponent The component, which must not be 'null'
         * @param pAlignment The component alignment within the cell
         * @param pColumn The target column
         * @param pRow The target row
         * @param pWidth The width in cells
         *
         * @return GridLayoutBuilder.this
         */
        public GridLayoutBuilder fillColumn(Component pComponent, Alignment pAlignment, int pColumn, int pRow,
                int pWidth) {
            return addComponent(pComponent, pAlignment, pColumn, pRow, pWidth, rows - pRow);
        }

        /**
         * Add a component filling the row defined by pRow till the end of the grid.
         * The default default alignment is used.
         *
         * @param pComponent The component, which must not be 'null'
         * @param pColumn The target column
         * @param pRow The target row
         * @param pHeight The height in cells
         *
         * @return GridLayoutBuilder.this
         */
        public GridLayoutBuilder fillRow(Component pComponent, int pColumn, int pRow, int pHeight) {
            return addComponent(pComponent, null, pColumn, pRow, columns - pColumn, pHeight);
        }

        /**
         * Add a component filling the row defined by pRow till the end of the grid.
         *
         * @param pComponent The component, which must not be 'null'
         * @param pAlignment The component alignment within the cell
         * @param pColumn The target column
         * @param pRow The target row
         * @param pHeight The height in cells
         *
         * @return GridLayoutBuilder.this
         */
        public GridLayoutBuilder fillRow(Component pComponent, Alignment pAlignment, int pColumn, int pRow,
                int pHeight) {
            return addComponent(pComponent, pAlignment, pColumn, pRow, columns - pColumn, pHeight);
        }

        /**
         * Add a component with the size 1x1 using the default alignment.
         *
         * @param pComponent The component, which must not be 'null'
         * @param pColumn The target column
         * @param pRow The target row
         *
         * @return GridLayoutBuilder.this
         */
        public GridLayoutBuilder addComponent(Component pComponent, int pColumn, int pRow) {
            return addComponent(pComponent, null, pColumn, pRow, 1, 1);
        }

        /**
         * Add a component using the default alignment.
         *
         * @param pComponent The component, which must not be 'null'
         * @param pColumn The target column
         * @param pRow The target row
         * @param pWidth The width in cells
         * @param pHeight The height in cells
         *
         * @return GridLayoutBuilder.this
         */
        public GridLayoutBuilder addComponent(Component pComponent, int pColumn, int pRow, int pWidth,
                int pHeight) {
            return addComponent(pComponent, null, pColumn, pRow, pWidth, pHeight);
        }

        /**
         * Add a new component to the layout. This method may throw an
         * IllegalArgumentException if pComponent is null or an
         * IndexOutOfBoundsException if the component location exceeds the layout
         * grid. Furthermore it is checked, whether to component overlaps another
         * component added before. If this is the case, an IllegalArgumentException
         * is throws and the current layout is printed to StdErr. If everything
         * works fine, the component is added to the layout.
         *
         * @param pComponent The component, which must not be 'null'
         * @param pAlignment The component alignment within the cell. The default
         * alignment is MIDDLE_CENTER.
         * @param pColumn The target column
         * @param pRow The target row
         * @param pWidth The width in cells
         * @param pHeight The height in cells
         *
         * @return GridLayoutBuilder.this
         */
        public GridLayoutBuilder addComponent(Component pComponent, Alignment pAlignment, int pColumn, int pRow,
                int pWidth, int pHeight) {
            if (pComponent == null) {
                throw new IllegalArgumentException("Argument pComponent must not be null");
            }

            Alignment componentAlignment = pAlignment;
            if (componentAlignment == null) {
                componentAlignment = DEFAULT_ALIGNMENT;
            }

            if (pColumn + pWidth > columns || pRow + pHeight > rows) {
                printLayoutToStdErr();
                throw new IndexOutOfBoundsException(
                        "Failed to add component " + getComponentIdentifier(pComponent) + ", grid too small.");
            }
            for (int i = pColumn; i < pColumn + pWidth; i++) {
                for (int j = pRow; j < pRow + pHeight; j++) {
                    if (!assignedFields[i][j].equals(EMPTY_CELL)) {
                        printLayoutToStdErr();
                        throw new IllegalArgumentException(
                                "Failed to add component " + getComponentIdentifier(pComponent) + ", cell [" + i
                                        + "][" + j + "] already assigned.");
                    }
                    assignedFields[i][j] = getComponentIdentifier(pComponent);
                }
            }
            layout.addComponent(pComponent, pColumn, pRow, pColumn + pWidth - 1, pRow + pHeight - 1);
            layout.setComponentAlignment(pComponent, componentAlignment);
            return this;
        }

        /**
         * Get the component identifier. This might be the debug Id, the caption or
         * the item's toString() result, depending on which of these values is not
         * null. The identifier is used for the debug output via printLayout().
         *
         * @param The component
         *
         * @return The identifiert
         */
        private String getComponentIdentifier(Component pComponent) {
            //removed DebugId to support Vaadin 7
            String identifier = null;//pComponent.getId();
            if (identifier == null) {
                identifier = pComponent.getCaption();
                if (identifier == null) {
                    identifier = pComponent.toString();
                }
            }
            return identifier;
        }

        /**
         * Returns the final layout with all components
         *
         * @return GridLayoutBuilder.this
         */
        public GridLayout getLayout() {
            return layout;
        }

        /**
         * Print the current layout to StdErr. This method is for internal use only.
         */
        private void printLayoutToStdErr() {
            printLayout(System.err);
        }

        /**
         * Internal helper method to redirect to debug output to StdOut or StdErr.
         */
        private GridLayoutBuilder printLayout(PrintStream pOut) {
            StringBuilder b = new StringBuilder();

            StringBuilder hr = new StringBuilder();

            for (int i = 0; i < columns * 10 + 4; i++) {
                hr.append("-");
            }
            hr.append("\n");

            b.append(hr.toString());

            for (int j = 0; j < rows; j++) {
                b.append("|");
                for (int i = 0; i < columns; i++) {
                    b.append(StringUtils.center(StringUtils.substring(assignedFields[i][j], 0, 10), 10))
                            .append("|");
                }
                b.append("\n").append(hr.toString());
            }

            pOut.println(b.toString());
            return this;
        }

        /**
         * Print the current layout to StdOut. This method is intended to be used
         * for debugging purposes.
         *
         * @return GridLayoutBuilder.this
         */
        public GridLayoutBuilder printLayout() {
            return printLayout(System.out);
        }
    }
    /**
     * SAMPLE CODE
     */
    //    public static void main(String[] args) {
    //        GridLayout layout = new UIUtils7.GridLayoutBuilder(3, 5).addComponent(new Label("1"), 0, 0, 3, 1).addComponent(new Label("2"), 0, 1, 1, 1).
    //                addComponent(new Label("3"), 2, 1, 1, 1).fillRow(new Label("4"), 0, 2, 1).fillRow(new Label("5"), 0, 3, 1).
    //                addComponent(new Label("6"), 0, 4, 1, 1).addComponent(new Label("="), 1, 4, 1, 1).addComponent(new Label("7"), 2, 4, 1, 1).getLayout();
    //
    //        new UIUtils7.GridLayoutBuilder(layout).printLayout();
    //    }
}