org.openmicroscopy.shoola.util.ui.UIUtilities.java Source code

Java tutorial

Introduction

Here is the source code for org.openmicroscopy.shoola.util.ui.UIUtilities.java

Source

/*
 * org.openmicroscopy.shoola.util.ui.UIUtilities
 *
 *------------------------------------------------------------------------------
 *  Copyright (C) 2006 University of Dundee. All rights reserved.
 *
 *
 *    This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *  
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 *------------------------------------------------------------------------------
 */

package org.openmicroscopy.shoola.util.ui;

//Java imports
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dialog;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Frame;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.event.KeyEvent;
import java.io.File;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.prefs.Preferences;
import java.util.regex.Pattern;
import javax.swing.AbstractButton;
import javax.swing.BorderFactory;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JEditorPane;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JSeparator;
import javax.swing.JTextField;
import javax.swing.JTextPane;
import javax.swing.KeyStroke;
import javax.swing.SwingConstants;
import javax.swing.border.BevelBorder;
import javax.swing.border.EmptyBorder;
import javax.swing.border.TitledBorder;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultStyledDocument;
import javax.swing.text.JTextComponent;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyleContext;
import javax.swing.text.StyledDocument;
import javax.swing.text.TabSet;
import javax.swing.text.TabStop;

//Third-party libraries
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.SystemUtils;
import org.jdesktop.swingx.JXDatePicker;
import org.jdesktop.swingx.JXTaskPane;

//Application-internal dependencies
import org.openmicroscopy.shoola.util.ui.border.TitledLineBorder;

/** 
 * A collection of static methods to perform common UI tasks.
 *
 * @author  Jean-Marie Burel     
 *             <a href="mailto:j.burel@dundee.ac.uk">j.burel@dundee.ac.uk</a>
 * @author  <br>Andrea Falconi &nbsp;&nbsp;&nbsp;&nbsp;
 *             <a href="mailto:a.falconi@dundee.ac.uk">
 *                a.falconi@dundee.ac.uk</a>
 * @version 2.2
 * <small>
 * (<b>Internal version:</b> $Revision$ $Date$)
 * </small>
 * @since OME2.2
 */
public class UIUtilities {

    /** The default number of characters for the partial name.*/
    public static final int DEFAULT_NUMBER_OF_CHARACTERS = 30;

    /** Indicates that the image is predominantly <code>red</code>.*/
    public static final int RED_COLOR = 0;

    /** Indicates that the image is predominantly <code>green</code>.*/
    public static final int GREEN_COLOR = 1;

    /** Indicates that the image is predominantly <code>blue</code>.*/
    public static final int BLUE_COLOR = 2;

    /** The maximum number read at once. */
    public static final int BYTES = 1024;

    /** The value used to compare double and float. */
    public final static double EPSILON = 0.00001;

    /** The number of lines displayed for error. */
    public static final int MAX_LINES_EXCEPTION = 20;

    /** 
      * The size of the invisible components used to separate buttons
      * horizontally.
      */
    public static final Dimension H_SPACER_SIZE = new Dimension(5, 10);

    /** Letter corresponding to number. */
    public static final Map<Integer, String> LETTERS;

    /** The maximum number of characters in a line for the tool tip. */
    public static final int MAX_CHARACTER = 40;

    /** A light grey colour for line borders etc. */
    public static final Color LIGHT_GREY = new Color(200, 200, 200);

    /** The default width of an icon. */
    public static final int DEFAULT_ICON_WIDTH = 16;

    /** The default height of an icon. */
    public static final int DEFAULT_ICON_HEIGHT = 16;

    /** The default background color. */
    public static final Color HYPERLINK_COLOR = Color.BLUE;

    /** The default background color. */
    public static final Color BACKGROUND_COLOR = Color.WHITE;

    /** The color of the required fields. */
    public static final Color REQUIRED_FIELDS_COLOR = Color.RED;

    /** The default background color. */
    public static final Color WINDOW_BACKGROUND_COLOR = new Color(248, 248, 248);

    /** The color of the text when editing. */
    public static final Color EDITED_COLOR = Color.red;

    /** The default color of the description. */
    public static final Color DEFAULT_FONT_COLOR = Color.GRAY;

    /**
     * This property should be exposed but is NOT.
     */
    public static final String COLLAPSED_PROPERTY_JXTASKPANE = "collapsed";

    /** 
      * The highlight color to use for the inner border surrounding the
      * frame's contents.
      */
    public static final Color INNER_BORDER_HIGHLIGHT = new Color(240, 240, 240);

    /** 
     * The shadow color to use for the inner border surrounding the
     * frame's contents.
     */
    public static final Color INNER_BORDER_SHADOW = new Color(200, 200, 200);

    /** The selected date format. */
    public static final String DATE_FORMAT = "yy/MM/dd";

    /** Background color of an even row. */
    public final static Color BACKGROUND_COLOUR_EVEN = new Color(232, 242, 254);

    /** Background color of an odd row. */
    public final static Color BACKGROUND_COLOUR_ODD = new Color(255, 255, 255);

    /** Background color of the selected row */
    public final static Color SELECTED_BACKGROUND_COLOUR = new Color(180, 213, 255);

    /** Foreground color of a cell.*/
    public final static Color FOREGROUND_COLOUR = new Color(0, 0, 0);

    /** The starting color of the gradient used in the track. */
    public static final Color TRACK_GRADIENT_START = new Color(76, 76, 76);

    /** The final color of the gradient used in the track. */
    public static final Color TRACK_GRADIENT_END = new Color(176, 176, 176);

    /** The color of the line drawn on the knobs. */
    public static final Color LINE_COLOR = Color.BLACK;

    /** A day in milliseconds. */
    public static final long DAY = 86400000;

    /** Unicode for the degrees symbol. */
    public final static String DEGREES_SYMBOL = "\u00B0";

    /** Unicode for the microns symbol. */
    public final static String MICRONS_SYMBOL = "\u00B5m";

    /** Unicode for the squared symbol. */
    public final static String SQUARED_SYMBOL = "\u00B2";

    /** Unicode for the squared symbol. */
    public final static String DELTA_SYMBOL = "\u0394";

    /** Pixels string. */
    public final static String PIXELS_SYMBOL = "px";

    /** String to representing the nanometer symbol. */
    public static final String NANOMETER = " \u00B5m";

    /** String to represent the micron symbol. */
    public static final String MICRONS = "(in \u00B5)";

    /** Background color of the highlighted node. */
    public static final Color HIGHLIGHT = new Color(204, 255, 204);
    /** Background color of the even rows. */
    public static final Color BACKGROUND = Color.WHITE;

    /** Background color of the add rows. */
    public static final Color BACKGROUND_ONE = new Color(236, 243, 254);
    /** 
     * The string displayed before an item name if the name has been
     * truncated.
     */
    public static final String DOTS = "...";

    /** The Steelblue color. */
    public static final Color STEELBLUE = new Color(0x4682B4);

    /** The default text color. */
    public static final Color DEFAULT_TEXT = Color.WHITE;

    /** Width of the dialog window. */
    public static final int DIALOG_WIDTH = 500;

    /** Height of the dialog window. */
    public static final int DIALOG_HEIGHT = 500;

    /** Width of the separator. */
    public static final int SEPARATOR_WIDTH = 2;

    /** Maximum width of the table. */
    public static final int TABLE_WIDTH = 200;

    /** The value of the increment factor. */
    public static final int INCREMENT = 15;

    /** The number of bytes in megabyte, used when working with memory methods.*/
    public static final long MEGABYTE = 1048567;

    /** Key value for the default folder. */
    private static final String DEFAULT_FOLDER = "defaultFolder";

    /** The pattern to format date. */
    public static final String WDMY_FORMAT = "E dd MMM yyyy, HH:mm:ss";

    /** The pattern to format date. */
    public static final String D_M_Y_FORMAT = "dd-MM-yyyy";

    /** The text displayed in the tool tip of the calendar button. */
    private static final String DATE_TOOLTIP = "Bring up a calendar.";

    /** The maximum width of the text when wrapping up text. */
    private static final int WRAP_UP_MAX_WIDTH = 50;

    private static final List<String> CHARACTERS;

    /** The fonts used for ROI.*/
    private static final Map<String, String> FONTS;

    static {
        CHARACTERS = new ArrayList<String>();
        CHARACTERS.add("[");
        CHARACTERS.add("]");
        CHARACTERS.add("\"");
        LETTERS = new HashMap<Integer, String>();
        LETTERS.put(1, "A");
        LETTERS.put(2, "B");
        LETTERS.put(3, "C");
        LETTERS.put(4, "D");
        LETTERS.put(5, "E");
        LETTERS.put(6, "F");
        LETTERS.put(7, "G");
        LETTERS.put(8, "H");
        LETTERS.put(9, "I");
        LETTERS.put(10, "J");
        LETTERS.put(11, "K");
        LETTERS.put(12, "L");
        LETTERS.put(13, "M");
        LETTERS.put(14, "N");
        LETTERS.put(15, "O");
        LETTERS.put(16, "P");
        LETTERS.put(17, "Q");
        LETTERS.put(18, "R");
        LETTERS.put(19, "S");
        LETTERS.put(20, "T");
        LETTERS.put(21, "U");
        LETTERS.put(22, "V");
        LETTERS.put(23, "W");
        LETTERS.put(24, "X");
        LETTERS.put(25, "Y");
        LETTERS.put(26, "Z");
        LETTERS.put(27, "AA");
        LETTERS.put(28, "AB");
        LETTERS.put(29, "AC");
        LETTERS.put(30, "AD");
        LETTERS.put(31, "AE");
        LETTERS.put(32, "AF");
        LETTERS.put(33, "AG");
        LETTERS.put(34, "AH");
        LETTERS.put(35, "AI");
        LETTERS.put(36, "AJ");
        LETTERS.put(37, "AK");
        LETTERS.put(38, "AL");
        LETTERS.put(39, "AM");
        LETTERS.put(40, "AN");
        LETTERS.put(41, "AO");
        LETTERS.put(42, "AP");
        LETTERS.put(43, "AQ");
        LETTERS.put(44, "AR");
        LETTERS.put(45, "AS");
        LETTERS.put(46, "AT");
        LETTERS.put(47, "AU");
        LETTERS.put(48, "AV");
        LETTERS.put(49, "AW");
        LETTERS.put(50, "AX");
        LETTERS.put(51, "AY");
        LETTERS.put(52, "AZ");
        LETTERS.put(53, "BA");
        LETTERS.put(54, "BB");
        LETTERS.put(55, "BC");
        LETTERS.put(56, "BD");
        LETTERS.put(57, "BE");
        LETTERS.put(58, "BF");
        LETTERS.put(59, "BG");
        LETTERS.put(60, "BH");
        LETTERS.put(61, "BI");
        LETTERS.put(62, "BJ");
        LETTERS.put(63, "BK");
        LETTERS.put(64, "BL");
        LETTERS.put(65, "BM");
        LETTERS.put(66, "BN");
        LETTERS.put(67, "BO");
        LETTERS.put(68, "BP");
        LETTERS.put(69, "BQ");
        LETTERS.put(70, "BR");
        LETTERS.put(71, "BS");
        LETTERS.put(72, "BT");
        LETTERS.put(73, "BU");
        LETTERS.put(74, "BV");
        LETTERS.put(75, "BW");
        LETTERS.put(76, "BX");
        LETTERS.put(77, "BY");
        LETTERS.put(78, "BZ");

        FONTS = new HashMap<String, String>();
        FONTS.put("Arial", "sans-serif");
        FONTS.put("Arial Black", "sans-serif");
        FONTS.put("Book Antiqua", "serif");
        FONTS.put("Charcoal", "sans-serif");
        FONTS.put("Comic Sans", "cursive");
        FONTS.put("Comic Sans MS", "cursive");
        FONTS.put("Courier", "monospace");
        FONTS.put("Courier New", "monospace");
        FONTS.put("Gadget", "sans-serif");
        FONTS.put("Geneva", "sans-serif");
        FONTS.put("Georgia", "serif");
        FONTS.put("Helvetica", "sans-serif");
        FONTS.put("Impact", "sans-serif");
        FONTS.put("Lucida Console", "monospace");
        FONTS.put("Lucida Grande", "sans-serif");
        FONTS.put("Lucida Sans Unicode", "sans-serif");
        FONTS.put("Monaco", "monospace");
        FONTS.put("MS Sans Serif", "sans-serif");
        FONTS.put("MS Serif", "serif");
        FONTS.put("New York", "serif");
        FONTS.put("Palatino", "serif");
        FONTS.put("Palatino Linotype", "serif");
        FONTS.put("Tahoma", "sans-serif");
        FONTS.put("Times", "serif");
        FONTS.put("Times New Roman", "serif");
        FONTS.put("Trebuchet MS", "sans-serif");
        FONTS.put("Verdana", "sans-serif");
        FONTS.put("Roman", "serif");
        FONTS.put("Swis", "sans-serif");
        FONTS.put("Script", "cursive");
        FONTS.put("Decorative", "fantasy");
        FONTS.put("serif", "serif");
        FONTS.put("sans-serif", "sans-serif");
        FONTS.put("cursive", "cursive");
        FONTS.put("fantasy", "fantasy");
        FONTS.put("monospace", "monospace");
        FONTS.put("Andale Mono", "sans-serif");
        FONTS.put("Antiqua", "serif");
        FONTS.put("Avqest", "serif");
        FONTS.put("Blackletter", "serif");
        FONTS.put("Calibri", "sans-serif");
        FONTS.put("Fraktur", "serif");
        FONTS.put("Frosty", "serif");
        FONTS.put("Garamond", "serif");
        FONTS.put("Minion", "serif");
        FONTS.put("Monotype.com", "sans-serif");
        FONTS.put("Bitstream Vera Sans", "sans-serif");
        FONTS.put("Bitstream Vera Sans Mono", "monospace");
        FONTS.put("Bitstream Vera Serif", "serif");
        FONTS.put("Caslon Roman", "serif");
        FONTS.put("Charis SIL", "serif");
        FONTS.put("DejaVu Sans", "sans-serif");
        FONTS.put("DejaVu Sans Mono", "monospace");
        FONTS.put("DejaVu Serif", "serif");
        FONTS.put("Doulos SIL", "serif");
        FONTS.put("Droid Sans", "sans-serif");
        FONTS.put("Droid Sans Mono", "monospace");
        FONTS.put("Droid Serif", "serif");
        FONTS.put("FreeMono", "monospace");
        FONTS.put("FreeSans", "sans-serif");
        FONTS.put("FreeSerif", "serif");
        FONTS.put("Gentium", "serif");
        FONTS.put("GNU Unifont", "monospace");
        FONTS.put("Junicode", "serif");
        FONTS.put("Liberation Mono", "monospace");
        FONTS.put("Liberation Sans", "sans-serif");
        FONTS.put("Liberation Sans Narrow", "sans-serif");
        FONTS.put("Liberation Serif", "serif");
        FONTS.put("Linux Biolinum", "sans-serif");
        FONTS.put("Linux Libertine", "serif");
        FONTS.put("Luxi Mono", "monospace");
        FONTS.put("Luxi Sans", "sans-serif");
        FONTS.put("Luxi Serif", "serif");
        FONTS.put("American Typewriter", "serif");
        FONTS.put("Apple Casual", "cursive");
        FONTS.put("Apple Chancery", "cursive");
        FONTS.put("Apple Garamond", "serif");
        FONTS.put("Baskerville", "serif");
        FONTS.put("Big Caslon", "serif");
        FONTS.put("Brush Script", "cursive");
        FONTS.put("Chalkboard", "sans-serif");
        FONTS.put("Chicago", "sans-serif");
        FONTS.put("Cochin", "serif");
        FONTS.put("Cooper", "serif");
        FONTS.put("Copperplate", "serif");
        FONTS.put("Didot", "serif");
        FONTS.put("Futura", "sans-serif");
        FONTS.put("Gill Sans", "sans-serif");
        FONTS.put("Helvetica Neue", "sans-serif");
        FONTS.put("Herculanum", "cursive");
        FONTS.put("Hoefler Text", "serif");
        FONTS.put("LiSong Pro", "serif");
        FONTS.put("Marker Felt", "cursive");
        FONTS.put("Menlo", "sans-serif");
        FONTS.put("New York", "sans-serif");
        FONTS.put("Optima", "sans-serif");
        FONTS.put("Papyrus", "sans-serif");
        FONTS.put("Sand", "cursive");
        FONTS.put("Skia", "sans-serif");
        FONTS.put("Techno", "sans-serif");
        FONTS.put("Textile", "cursive");
        FONTS.put("Zapf Chancery", "cursive");
        FONTS.put("Zapfino", "cursive");
    }

    /**
      * Returns <code>true</code> if the passed value is textual,
      * <code>false</code> otherwise.
      * 
      * @param value See above.
      * @return See above.
      */
    private static boolean isTextOnly(String value) {
        Iterator<String> i = CHARACTERS.iterator();
        while (i.hasNext()) {
            if (value.contains(i.next()))
                return false;
        }
        return true;
    }

    /**
     * Centers the specified component on the screen.
     * The location of the specified component is set so that it will appear
     * in the middle of the screen when made visible.
     * This method is mainly useful for windows, frames and dialogs.
     * 
     * @param window   The component to center.
     */
    public static void centerOnScreen(Component window) {
        if (window == null)
            return;
        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        Rectangle ed = window.getBounds();
        window.setLocation((screenSize.width - ed.width) / 2, (screenSize.height - ed.height) / 2);
    }

    /**
     * Shows the specified window on the screen, It will appear at the specified
     * location. If the location is <code>null</code>, it will appear in the 
     * middle of the screen. 
     * 
     * @param window   The component to show.
     * @param location   The location of the specified component if 
     *                <code>null</code> it will appear in the middle of the 
     *                screen.
     */
    public static void showOnScreen(Component window, Point location) {
        if (window == null)
            return;
        if (location == null)
            centerOnScreen(window);
        else {
            window.setLocation(location);
            window.setVisible(true);
        }
    }

    /**
     * Centers the specified component on the screen and then makes it visible.
     * This method is mainly useful for windows, frames and dialogs. 
     * 
     * @param window   The component to center.
     * @see   #centerOnScreen(Component)
     */
    public static void centerAndShow(Component window) {
        centerOnScreen(window);
        window.setVisible(true);
    }

    /**
     * Centers the specified component on the parent and then makes it visible.
     * This method is mainly useful for windows, frames and dialogs. 
     * 
     * @param parent    The visible parent.
      * @param child     The child to display.
     */
    public static void centerAndShow(Component parent, Component child) {
        if (parent == null || child == null)
            return;
        Rectangle bounds = parent.getBounds();
        Rectangle ed = child.getBounds();
        child.setLocation(bounds.x + (bounds.width - ed.width) / 2, bounds.y + (bounds.height - ed.height) / 2);
        child.setVisible(true);
    }

    /**
     * Sets the location of the specified child relative to the location
     * of the specified parent and then makes it visible.
     * This method is mainly useful for windows, frames and dialogs. 
     * 
     * @param parent    The visible parent.
     * @param child     The child to display.
     */
    public static void setLocationRelativeToAndShow(Component parent, Component child) {
        setLocationRelativeTo(parent, child);
    }

    /**
     * Sets the location of the specified child relative to the location
     * of the specified parent and then makes it visible.
     * This method is mainly useful for windows, frames and dialogs. 
     * 
     * @param parent    The visible parent.
     * @param child     The child to display.
     */
    public static void setLocationRelativeTo(Component parent, Component child) {
        if (parent == null || child == null)
            return;
        int x = parent.getX() + parent.getWidth();
        int y = parent.getY();
        int childWidth = child.getWidth();
        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        if (x + childWidth > screenSize.getWidth()) {
            if (childWidth < parent.getX())
                x = parent.getX() - childWidth;
            else
                x = (int) (screenSize.getWidth() - childWidth);
        }
        child.setLocation(x, y);
        child.setVisible(true);
    }

    /**
     * Sets the location of the specified child relative to the location
     * of the specified parent and then makes it visible, and size to fill 
     * the window.
     * This method is mainly useful for windows, frames and dialogs. 
     * 
     * @param parent    The visible parent.
     * @param child     The child to display.
     * @param max      The maximum size of the window.
     */
    public static void setLocationRelativeToAndSizeToWindow(Component parent, Component child, Dimension max) {
        setLocationRelativeToAndSizeToWindow(parent.getBounds(), child, max);
    }

    /**
     * Sets the location of the specified child relative to the location
     * of the specified parent and then makes it visible, and size to fill window.
     * This method is mainly useful for windows, frames and dialogs. 
     * 
     * @param parentBounds    The bounds of the visible parent.
     * @param child     The child to display.
     * @param max      The maximum size of the window.
     */
    public static void setLocationRelativeToAndSizeToWindow(Rectangle parentBounds, Component child,
            Dimension max) {
        if (child == null)
            return;
        if (parentBounds == null)
            parentBounds = new Rectangle(0, 0, 5, 5);
        if (max == null)
            max = new Dimension(5, 5);
        int x = (int) (parentBounds.getX() + parentBounds.getWidth());
        int y = (int) parentBounds.getY();
        int childWidth = child.getWidth();
        int childHeight = child.getHeight();
        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        if (x + childWidth > screenSize.getWidth()) {
            if (childWidth < parentBounds.getX())
                x = (int) (parentBounds.getX()) - childWidth;
            else
                x = (int) (screenSize.getWidth() - childWidth);
        }
        child.setLocation(x, y);
        int newHeight = (int) screenSize.getHeight() - y - 10;
        int newWidth = (int) screenSize.getWidth() - x - 10;

        if (newWidth > childWidth)
            childWidth = newWidth;
        if (newHeight > childHeight)
            childHeight = newHeight;

        if (childWidth > max.getWidth())
            childWidth = (int) max.getWidth();
        if (childHeight > max.getHeight())
            childHeight = (int) max.getHeight();

        child.setSize(childWidth, childHeight);
        child.setVisible(true);
    }

    /**
     * Sets the location of the specified child relative to the passed 
     * bounds.
     * This method is mainly useful for windows, frames and dialogs. 
     * 
     * @param parentBounds  The bounds of the parent.
     * @param child        The child to display.
     */
    public static void setLocationRelativeTo(Rectangle parentBounds, Component child) {
        if (child == null)
            return;
        if (parentBounds == null)
            parentBounds = new Rectangle(0, 0, 5, 5);

        int x = parentBounds.x + parentBounds.width;
        int y = parentBounds.y;
        int childWidth = child.getWidth();
        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        if (x + childWidth > screenSize.getWidth()) {
            if (childWidth < parentBounds.x)
                x = parentBounds.x - childWidth;
            else
                x = (int) (screenSize.getWidth() - childWidth);
        }
        child.setLocation(x, y);
        child.setVisible(true);
    }

    /**
     * Sets the location of the passed component relative to the specified 
     * bounds.
     * 
     * @param bounds    The bounds of the main component.
     * @param child     The location of the child
     */
    public static void incrementRelativeToAndShow(Rectangle bounds, Component child) {
        if (bounds == null) {
            UIUtilities.centerAndShow(child);
            return;
        }
        child.setLocation(bounds.x + INCREMENT, bounds.y + INCREMENT);
        child.setVisible(true);
    }

    /**
      * Creates a modal JDialog containing the specified JComponent
      * for the specified parent.
      * The newly created dialog is then centered on the screen and made visible.
     *
      * @param parent The parent component.
      * @param title  The title of the dialog.
      * @param c      The component to display.
      * @see #centerAndShow(Component)
     */
    public static void makeForDialog(Component parent, String title, JComponent c) {
        if (c == null)
            return;
        JDialog dialog = null;
        if (parent instanceof Frame)
            dialog = new JDialog((Frame) parent);
        else if (parent instanceof Dialog)
            dialog = new JDialog((Dialog) parent);
        else if (dialog == null)
            dialog = new JDialog(); //no parent
        dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
        dialog.setModal(true);
        dialog.setTitle(title);
        dialog.setSize(DIALOG_WIDTH, DIALOG_HEIGHT);
        Container container = dialog.getContentPane();
        container.setLayout(new BorderLayout(0, 0));
        container.add(c, BorderLayout.CENTER);
        centerAndShow(dialog);
    }

    /** 
     * Creates a modal JDialog with no title. 
     * 
     * @param parent The parent component.
     * @param c      The component to display.
     * @see #makeForDialog(Component, JComponent)
     */
    public static void makeForDialog(Component parent, JComponent c) {
        makeForDialog(parent, "", c);
    }

    /** 
     * Builds a tool tip in a fixed font and color.
     * You pass the tool tip text and get back an <i>HTML</i> string to be
     * passed, in turn, to the <code>setToolTipText</code> method of a 
     * {@link javax.swing.JComponent}.
     *
     * @param toolTipText     The textual content of the tool tip.
     * @return An <i>HTML</i> formatted string to be passed to 
     *          <code>setToolTipText()</code>.
     */
    public static String formatToolTipText(String toolTipText) {
        if (toolTipText == null)
            toolTipText = "";
        StringBuffer buf = new StringBuffer(90 + toolTipText.length());
        //buf.
        buf.append("<html><body bgcolor=#FFFCB7 text=#AD5B00>");
        //TODO: change into platform independent font
        buf.append("<font face=Arial size=2>");
        buf.append(toolTipText);
        buf.append("</font></body></html>");
        return toolTipText;
    }

    /** 
     * Builds a tool tip in a fixed font and color.
     * You pass the tool tip text and get back an <i>HTML</i> string to be
     * passed, in turn, to the <code>setToolTipText</code> method of a 
     * {@link javax.swing.JComponent}.
     *
     * @param toolTipText     The textual content of the tool tip.
     * @return An <i>HTML</i> formatted string to be passed to 
     *          <code>setToolTipText()</code>.
     */
    public static String formatToolTipText(List<String> toolTipText) {
        if (toolTipText == null)
            return "";
        StringBuffer buf = new StringBuffer();
        //buf.
        //buf.append("<html><body bgcolor=#FFFCB7 text=#AD5B00>");
        buf.append("<html><body>");
        buf.append("<font face=Arial size=2>");
        Iterator<String> i = toolTipText.iterator();
        buf.append("<p>");
        while (i.hasNext()) {
            buf.append(i.next());
            buf.append("<br>");
        }
        buf.append("</p>");
        buf.append("</font></body></html>");
        return buf.toString();
    }

    /** 
     * Builds a tool tip in a fixed font and color.
     * You pass the tool tip text and get back an <i>HTML</i> string to be
     * passed, in turn, to the <code>setToolTipText</code> method of a 
     * {@link javax.swing.JComponent}.
     *
     * @param toolTipText     The textual content of the tool tip.
     * @return An <i>HTML</i> formatted string to be passed to 
     *          <code>setToolTipText()</code>.
     */
    public static String formatToolTipText(String[] toolTipText) {
        if (toolTipText == null)
            return "";
        StringBuffer buf = new StringBuffer();
        buf.append("<html><body>");
        buf.append("<font face=Arial size=2>");
        buf.append("<p>");
        for (int i = 0; i < toolTipText.length; i++) {
            buf.append(toolTipText[i]);
            buf.append("<br>");
        }
        buf.append("</p>");
        buf.append("</font></body></html>");
        return buf.toString();
    }

    /**
     * Builds a tool tip in a fixed font and color.
     * 
     * @param title     The title to format.
     * @param body      The body to format.
     * @param maxWidth  The maximum width of the <code>HTML</code> table.
     * @return See below.
     */
    public static String makeParagraph(String title, String body, int maxWidth) {
        if (title != null && body == null)
            return formatToolTipText(title);
        //title.
        StringBuffer buf = new StringBuffer();
        buf.append("<html><body bgcolor=#FFFCB7 text=#AD5B00>");
        //TODO: change into platform independent font
        if (title != null && body != null) {
            String s = "<table width=" + maxWidth + "><tr>";
            buf.append(s);
            buf.append("<td><b>");
            buf.append(title);
            buf.append("</b><hr size=1>");
            buf.append("<font face=Arial size=2>");
            buf.append(body);
            buf.append("</font>");
            buf.append("</td></tr></table>");
        } else if (title == null && body != null) {
            String s = "<table width=" + maxWidth + "><tr>";
            buf.append(s);
            buf.append("<td>");
            buf.append("<font face=Arial size=2>");
            buf.append(body);
            buf.append("</font>");
            buf.append("</td></tr></table>");
        }
        buf.append("</body></html>");
        return buf.toString();
    }

    /** 
     * Create a separator to add to a toolbar. The separator needs to be 
     * set when the layout of the toolbar is reset.
     * 
     * @param button   The button to add to the toolBar. The height of the 
     *                separator depends of the insets of the button.
     * @param icon     The icon to add to the button. The height of the 
      *                 separator depends of the height of the icon.
     * @return See below.
     */
    public static JSeparator toolBarSeparator(JButton button, Icon icon) {
        JSeparator separator = new JSeparator(SwingConstants.VERTICAL);
        if (button == null)
            return separator;
        Insets i = button.getInsets();
        int h = 0;
        if (icon != null)
            h = icon.getIconHeight();
        Dimension d = new Dimension(SEPARATOR_WIDTH, i.top + h + i.bottom);
        separator.setPreferredSize(d);
        separator.setSize(d);
        return separator;
    }

    /**
     * Displays the specified string into a {@link JLabel} and sets 
     * the font to <code>bold</code>.
     * 
     * @param s The string to display.
     * @return See above.
     */
    public static JLabel setTextFont(String s) {
        return UIUtilities.setTextFont(s, Font.BOLD);
    }

    /**
     * Displays the specified string into a {@link JLabel} and sets 
     * the font to <code>bold</code>.
     * 
     * @param s       The string to display.
     * @param fontStyle The style of the font.
     * @return See above.
     */
    public static JLabel setTextFont(String s, int fontStyle) {
        if (s == null)
            s = "";
        JLabel label = new JLabel(s);
        Font font = label.getFont();
        Font newFont = font.deriveFont(fontStyle);
        label.setFont(newFont);
        return label;
    }

    /**
     * Displays the specified string into a {@link JLabel} and sets 
     * the font to <code>bold</code>.
     * 
     * @param s       The string to display.
     * @param fontStyle The style of font.
     * @param fontSize   The size of the font.
     * @return See above.
     */
    public static JLabel setTextFont(String s, int fontStyle, int fontSize) {
        if (s == null)
            s = "";
        JLabel label = new JLabel(s);
        Font font = label.getFont();
        label.setFont(font.deriveFont(fontStyle, fontSize));
        return label;
    }

    /**
     * Adds the specified {@link JComponent} to a {@link JPanel} 
     * with a left flow layout.
     * 
     * @param component The component to add.
     * @return See below.
     */
    public static JPanel buildComponentPanel(JComponent component) {
        return buildComponentPanel(component, 5, 5, true);
    }

    /**
     * Adds the specified {@link JComponent} to a {@link JPanel} 
     * with a left flow layout.
     * 
     * @param component The component to add.
     * @param isOpaque  Pass <code>true</code> if this component should be 
     *                opaque, <code>false</code> otherwise.
     * @return See below.
     */
    public static JPanel buildComponentPanel(JComponent component, boolean isOpaque) {
        return buildComponentPanel(component, 5, 5, isOpaque);
    }

    /**
     * Adds the specified {@link JComponent} to a {@link JPanel} 
     * with a left flow layout.
     * 
     * @param component The component to add.
     * @param hgap       The horizontal gap between components and between the 
     *                components and the borders of the 
     *                <code>Container</code>.
     * @param   vgap    The vertical gap between components and between the 
     *                components and the borders of the 
     *                <code>Container</code>.
     * @return See below.
     */
    public static JPanel buildComponentPanel(JComponent component, int hgap, int vgap) {
        return buildComponentPanel(component, hgap, vgap, true);
    }

    /**
     * Adds the specified {@link JComponent} to a {@link JPanel} 
     * with a left flow layout.
     * 
     * @param component The component to add.
     * @param hgap       The horizontal gap between components and between the 
     *                components and the borders of the 
     *                <code>Container</code>.
     * @param vgap       The vertical gap between components and between the 
     *                components and the borders of the 
     *                <code>Container</code>.
     * @param isOpaque  Pass <code>true</code> if this component should be 
     *                opaque, <code>false</code> otherwise.
     * @return See below.
     */
    public static JPanel buildComponentPanel(JComponent component, int hgap, int vgap, boolean isOpaque) {
        JPanel p = new JPanel();
        if (component == null)
            return p;
        if (hgap < 0)
            hgap = 0;
        if (vgap < 0)
            vgap = 0;
        p.setLayout(new FlowLayout(FlowLayout.LEFT, hgap, vgap));
        p.add(component);
        p.setOpaque(isOpaque);
        return p;
    }

    /**
     * Adds the specified {@link JComponent} to a {@link JPanel} 
     * with a right flow layout.
     * 
     * @param component The component to add.
     * @return See below.
     */
    public static JPanel buildComponentPanelRight(JComponent component) {
        return buildComponentPanelRight(component, true);
    }

    /**
     * Adds the specified {@link JComponent} to a {@link JPanel} 
     * with a right flow layout.
     * 
     * @param component The component to add.
     * @param hgap       The horizontal gap between components and between the 
     *                components and the borders of the 
     *                <code>Container</code>.
     * @param vgap       The vertical gap between components and between the 
     *                components and the borders of the 
     *                <code>Container</code>.
     * @param isOpaque  Pass <code>true</code> if this component should be 
     *                opaque, <code>false</code> otherwise.
     * @return See below.
     */
    public static JPanel buildComponentPanelRight(JComponent component, int hgap, int vgap, boolean isOpaque) {
        JPanel p = new JPanel();
        if (component == null)
            return p;
        if (hgap < 0)
            hgap = 0;
        if (vgap < 0)
            vgap = 0;
        p.setLayout(new FlowLayout(FlowLayout.RIGHT, hgap, vgap));
        p.add(component);
        p.setOpaque(isOpaque);
        return p;
    }

    /**
     * Adds the specified {@link JComponent} to a {@link JPanel} 
     * with a right flow layout.
     * 
     * @param component The component to add.
     * @param isOpaque  Pass <code>true</code> if this component should be 
     *                opaque, <code>false</code> otherwise.
     * @return See below.
     */
    public static JPanel buildComponentPanelRight(JComponent component, boolean isOpaque) {
        return buildComponentPanelRight(component, 5, 5, isOpaque);
    }

    /**
     * Adds the specified {@link JComponent} to a {@link JPanel} 
     * with a right flow layout.
     * 
     * @param component The component to add.
     *  @param hgap       The horizontal gap between components and between the 
     *                components and the borders of the 
     *                <code>Container</code>.
     * @param vgap       The vertical gap between components and between the 
     *                components and the borders of the 
     *                <code>Container</code>.
     * @return See below.
     */
    public static JPanel buildComponentPanelCenter(JComponent component, int hgap, int vgap) {
        JPanel p = new JPanel();
        if (component == null)
            return p;
        if (hgap < 0)
            hgap = 0;
        if (vgap < 0)
            vgap = 0;
        p.setLayout(new FlowLayout(FlowLayout.CENTER, hgap, vgap));
        p.add(component);
        return p;
    }

    /**
     * Adds the specified {@link JComponent} to a {@link JPanel} 
     * with a right flow layout.
     * 
     * @param component The component to add.
     * @return See below.
     */
    public static JPanel buildComponentPanelCenter(JComponent component) {
        return buildComponentPanelCenter(component, 5, 5);
    }

    /**
     * Sets the UI properties of the button to unify the L&F.
     * 
     * @param b The button.
     */
    public static void unifiedButtonLookAndFeel(AbstractButton b) {
        if (b == null)
            return;
        //b.setMargin(new Insets(0, 2, 0, 3));
        //b.setBorderPainted(false);
        //b.setFocusPainted(false);
        b.setOpaque(false);
        b.setBorder(new EmptyBorder(2, 2, 2, 2));
    }

    /**
     * Sets the opacity of the specified button depending on the 
     * system look and Feel.
     * 
     * @param b The button to handle.
     */
    public static void opacityCheck(AbstractButton b) {
        if (b == null)
            return;
        //String laf = UIManager.getSystemLookAndFeelClassName();
        String osName = System.getProperty("os.name");
        b.setContentAreaFilled(!(osName.startsWith("Mac OS")));
        //b.setContentAreaFilled(!(MAC_L_AND_F.equals(laf)));
    }

    /**
     * Sets the defaults for the specified area.
     * 
     * @param area The text area.
     */
    public static void setTextAreaDefault(JComponent area) {
        if (area == null)
            return;
        area.setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED));
        //area.setForeground(STEELBLUE);
        area.setBackground(BACKGROUND);
        area.setOpaque(true);
        if (area instanceof JTextComponent)
            ((JTextComponent) area).setEditable(true);
    }

    /**
     * Formats a double to two decimal places and returns as a string. 
     * 
     * @param val The number to be formatted. 
     * @return The formatted string. 
     */
    public static String twoDecimalPlaces(double val) {
        double v = val;
        String value;
        double c = v;
        if (v < 0)
            return null;
        if ((c - Math.floor(c)) > 0)
            value = "" + Math.round(c * 100) / 100f;
        else
            value = "" + (int) c;
        if (value.equals("0"))
            return null;
        return value;
    }

    /**
     * Formats the text and displays it in a {@link JTextPane}.
     * 
     * @param text The text to display.
     * @return See above.
     */
    public static JTextPane buildTextPane(String text) {
        return buildTextPane(text, null);
    }

    /**
     * Formats the text and displays it in a {@link JEditorPane}.
     * 
     * @param text   The text to display.
     * @return See above.
     */
    public static JEditorPane buildTextEditorPane(String text) {
        if (text == null)
            text = "";
        JEditorPane textPane = new JEditorPane();
        textPane.setContentType("text/html");
        textPane.setText(text);
        textPane.setOpaque(false);
        textPane.setEditable(false);
        textPane.setFocusable(false);
        return textPane;
    }

    /**
     * Formats the text and displays it in a {@link JTextPane}.
     * 
     * @param text          The text to display.
     * @param foreground   The foreground color.
     * @return See above.
     */
    public static JTextPane buildTextPane(String text, Color foreground) {
        if (text == null)
            text = "";
        StyleContext context = new StyleContext();
        StyledDocument document = new DefaultStyledDocument(context);

        Style style = context.getStyle(StyleContext.DEFAULT_STYLE);
        StyleConstants.setAlignment(style, StyleConstants.ALIGN_LEFT);
        if (foreground != null)
            StyleConstants.setForeground(style, foreground);
        try {
            document.insertString(document.getLength(), text, style);
        } catch (BadLocationException e) {
        }

        JTextPane textPane = new JTextPane(document);
        textPane.setOpaque(false);
        textPane.setEditable(false);
        textPane.setFocusable(false);
        return textPane;
    }

    /** 
     * Sets the focus default for the specified button.
     * 
     * @param button The button to handle.
     */
    public static void enterPressesWhenFocused(JButton button) {
        if (button == null)
            return;
        button.registerKeyboardAction(
                button.getActionForKeyStroke(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0, false)),
                KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0, false), JComponent.WHEN_FOCUSED);

        button.registerKeyboardAction(
                button.getActionForKeyStroke(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0, true)),
                KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0, true), JComponent.WHEN_FOCUSED);
    }

    /**
     * Returns the pathname string of the default folder.
     * 
     * @return See above.
     */
    public static String getDefaultFolderAsString() {
        Preferences prefs = Preferences.userNodeForPackage(UIUtilities.class);
        if (prefs == null)
            return null;
        return prefs.get(DEFAULT_FOLDER, null);
    }

    /**
     * Sets the pathname string of the default folder.
     * 
     * @param f The value to set.
     */
    public static void setDefaultFolder(String f) {
        Preferences prefs = Preferences.userNodeForPackage(UIUtilities.class);
        if (prefs == null)
            return;
        if (f == null)
            f = "";
        prefs.put(DEFAULT_FOLDER, f);
    }

    /**
     * Returns the default folder.
     *  
     * @return See above.
     */
    public static File getDefaultFolder() {
        String f = UIUtilities.getDefaultFolderAsString();
        if (f == null || f == "")
            return null;
        return new File(f);
    }

    /**
     * Sets the preferred size, minimum and maximum size of the specified 
     * component.
     * 
     * @param component   The component to handle.
     * @param dim      The dimension to set.
     */
    public static void setDefaultSize(Component component, Dimension dim) {
        if (component == null)
            return;
        if (dim == null)
            dim = new Dimension(5, 5);
        component.setPreferredSize(dim);
        component.setMaximumSize(dim);
        component.setMinimumSize(dim);
    }

    /**
     * Finds the component identified by the specified class contained in the 
     * passed component. Returns the found component or <code>null</code> if 
     * none found.
     * 
     * @param comp   The component to visit. Mustn't be <code>null</code>.
     * @param c      The class identifying the component to find.
     * @return See above.
     */
    public static Component findComponent(Component comp, Class c) {
        if (c == null || comp == null)
            throw new IllegalArgumentException("The parameters cannot be " + "null");
        if (c.isAssignableFrom(comp.getClass()))
            return comp;

        if (comp instanceof Container) {
            Component[] comps = ((Container) comp).getComponents();
            Component child;
            for (int i = 0; i < comps.length; i++) {
                child = findComponent(comps[i], c);
                if (child != null)
                    return child;
            }
        }
        return null;
    }

    /**
     * Finds the components identified by the specified class contained in the 
     * passed component. Returns a collection of found component or 
     * <code>null</code> if none found.
     * 
     * @param comp   The component to visit. Mustn't be <code>null</code>.
     * @param c      The class identifying the component to find.
     * @return See above.
     */
    public static List<Component> findComponents(Component comp, Class c) {
        List<Component> l = null;
        if (c == null || comp == null)
            throw new IllegalArgumentException("The parameters cannot be " + "null");
        if (c.isAssignableFrom(comp.getClass())) {
            l = new ArrayList<Component>(1);
            l.add(comp);
            return l;
        }
        if (comp instanceof Container) {
            Component[] comps = ((Container) comp).getComponents();
            Component child;
            l = new ArrayList<Component>(comps.length);
            for (int i = 0; i < comps.length; i++) {
                child = findComponent(comps[i], c);
                if (child != null)
                    l.add(child);
            }
            return l;
        }
        return null;
    }

    /**
     * Returns <code>true</code> if the passed color is a dark color,
     * <code>false</code> otherwise.
     * 
     * @param c The color to handle. Mustn't be <code>null</code>.
     * @return See above.
     */
    public static boolean isDarkColor(Color c) {
        if (c == null)
            return false;
        return (c.getRed() + c.getGreen() + c.getBlue()) / 3 < 128;
    }

    /**
     * Creates a default timestamp.
     * 
     * @return See above.
     */
    public static Timestamp getDefaultTimestamp() {
        return new Timestamp(new Date().getTime());
    }

    /**
     * Formats as a <code>String</code> the specified time.
     * 
     * @param time The timestamp to format.
     * @return Returns the stringified version of the passed timestamp.
     */
    public static String formatTime(Timestamp time) {
        if (time == null)
            return "";
        return DateFormat.getDateInstance().format(time);
    }

    /**
     * Formats as a <code>String</code> the specified time.
     * 
     * @param time The timestamp to format.
     * @return Returns the stringified version of the passed timestamp.
     */
    public static String formatShortDateTime(Timestamp time) {
        if (time == null)
            time = getDefaultTimestamp();
        return DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT).format(time);
    }

    /**
     * Formats as a <code>String</code> the specified time.
     * format: E dd MMM yyyy, HH:mm:ss
     * 
     * @param time The timestamp to format.
     * @return Returns the stringified version of the passed timestamp.
     */
    public static String formatWDMYDate(Timestamp time) {
        return formatDate(time, WDMY_FORMAT);
    }

    /**
     * Formats as a <code>String</code> the specified time.
     * format: E dd MMM yyyy, HH:mm:ss
     * 
     * @param time The timestamp to format.
     * @param pattern The format pattern
     * @return Returns the stringified version of the passed timestamp.
     */
    public static String formatDate(Timestamp time, String pattern) {
        if (time == null)
            time = getDefaultTimestamp();
        if (pattern == null || pattern.length() == 0)
            pattern = WDMY_FORMAT;
        SimpleDateFormat formatter = new SimpleDateFormat(pattern);
        return formatter.format(time);
    }

    /**
     * Converts the time in seconds into hours, minutes and seconds.
     * 
     * @param timeInMilliSeconds The time in milliseconds to convert.
     * @return See above.
     */
    public static String calculateHMSFromMilliseconds(long timeInMilliSeconds) {
        return calculateHMS((int) (timeInMilliSeconds / 1000));
    }

    /**
     * Converts the time in seconds into hours, minutes and seconds.
     * 
     * @param timeInSeconds The time in seconds to convert.
     * @return See above.
     */
    public static String calculateHMS(int timeInSeconds) {
        int hours = timeInSeconds / 3600;
        timeInSeconds = timeInSeconds - (hours * 3600);
        int minutes = timeInSeconds / 60;
        timeInSeconds = timeInSeconds - (minutes * 60);
        int seconds = timeInSeconds;
        String text = "";
        if (hours > 0) {
            text += hours;
            text += " hour";
        }
        if (hours > 1)
            text += "s";
        if (minutes > 0) {
            text += " ";
            text += minutes;
            text += " minute";
            if (minutes > 1)
                text += "s";
        }
        if (seconds > 0) {
            text += " ";
            text += seconds;
            text += " second";
            if (seconds > 1)
                text += "s";
        }
        return text;
    }

    /**
     * Formats the string to be two decimal places. 
     * 
    * @param value The value to be formatted. 
     * @return See above.
     */
    public static String formatToDecimal(double value) {
        try {
            return String.format("%.2f", value);
        } catch (Exception e) {
            return "";
        }
    }

    /**
     * Rounds the passed value to two decimals after decimal point.
     * 
     * @param value    The value to round.
     * @return The rounded value.
     */
    public static double roundTwoDecimals(double value) {
        return round(value, 2);
    }

    /**
     * Returns the decimal value.
     * 
     * @param value The value to handle.
     * @return See above.
     */
    public static final int findDecimal(double value, int decimal) {
        double v = round(value, decimal);
        if (v > 0)
            return decimal;
        decimal++;
        return findDecimal(value, decimal);
    }

    /**
     * Rounds the passed value to the specified number of decimals.
     * 
     * @param value    The value to round.
     * @param decimal    The number of figures after decimal point.
     * @return The rounded value.
     */
    public static double ceil(double value, int decimal) {
        if (decimal <= 0)
            return value;
        double p = Math.pow(10, decimal);
        value = value * p;
        return Math.ceil(value) / p;
    }

    /**
     * Rounds the passed value to the specified number of decimals.
     * 
     * @param value    The value to round.
     * @param decimal    The number of figures after decimal point.
     * @return The rounded value.
     */
    public static double floor(double value, int decimal) {
        if (decimal <= 0)
            return value;
        double p = Math.pow(10, decimal);
        value = value * p;
        return Math.floor(value) / p;
    }

    /**
     * Rounds the passed value to the specified number of decimals.
     * 
     * @param value    The value to round.
     * @param decimal    The number of figures after decimal point.
     * @return The rounded value.
     */
    public static double round(double value, int decimal) {
        if (decimal <= 0)
            return value;
        double p = Math.pow(10, decimal);
        value = value * p;
        return Math.round(value) / p;
    }

    /**
     * Returns the partial name of the image's name
     * 
     * @param originalName The original name.
     * @return See above.
     */
    public static String[] splitString(String originalName) {
        String[] l = null;
        if (originalName == null)
            return l;
        if (Pattern.compile("/").matcher(originalName).find()) {
            l = originalName.split("/", 0);
        } else if (Pattern.compile("\\\\").matcher(originalName).find()) {
            l = originalName.split("\\\\", 0);
        }
        return l;
    }

    /** 
     * Returns the separator or <code>null</code>.
     * 
     * @param originalName The original name.
     * @return See above.
     */
    public static String getStringSeparator(String originalName) {
        if (originalName == null)
            return null;
        String[] l = null;
        if (Pattern.compile("/").matcher(originalName).find()) {
            l = originalName.split("/", 0);
            if (l.length > 0)
                return "/";
        } else if (Pattern.compile("\\\\").matcher(originalName).find()) {
            l = originalName.split("\\\\", 0);
            if (l.length > 0)
                return "\\";
        }
        return null;
    }

    /** 
     * Builds the collapse component.
     * 
     * @param title The title displayed in the border.
     * @return See above.
     */
    public static JPanel buildCollapsePanel(String title) {
        if (title == null)
            title = "";
        JPanel p = new JPanel();
        p.setBorder(new TitledLineBorder(title));
        return p;
    }

    /**
     * Formats and sets the title border of the passed component.
     * 
     * @param title The title.
     * @param p      The component to handle.
     */
    public static void setBoldTitledBorder(String title, JComponent p) {
        if (title == null)
            title = "";
        if (p == null)
            return;
        TitledBorder border = new TitledBorder(title);
        border.setTitleFont(p.getFont().deriveFont(Font.BOLD));
        p.setBorder(border);
    }

    /**
     * Formats the passed URL.
     * 
     * @param url The value to format.
     * @return See above.
     */
    public static String formatURL(String url) {
        if (url == null)
            url = "";
        StringBuffer buf = new StringBuffer();
        buf.append("<html><body>");
        buf.append("<a href=\"");
        buf.append(url);
        buf.append("\"");
        buf.append(">");
        buf.append(url);
        buf.append("</a>");
        buf.append("</body></html>");
        return buf.toString();
    }

    /**
     * Converts the passed value into a string in Mb and returns a string 
     * version of it.
     * 
     * @param v The value to convert.
     * @return See above.
     */
    public static String formatFileSize(long v) {
        if (v <= 0)
            return "";
        String s = "";
        if (v < FileUtils.ONE_KB)
            s = String.format("%.1f", (double) v) + " bytes";
        else if (v >= FileUtils.ONE_KB && v < FileUtils.ONE_MB)
            s = String.format("%.1f", ((double) v / FileUtils.ONE_KB)) + " Kb";
        else if (v >= FileUtils.ONE_MB && v < FileUtils.ONE_GB)
            s = String.format("%.1f", ((double) v / FileUtils.ONE_MB)) + " Mb";
        else if (v >= FileUtils.ONE_GB)
            s = String.format("%.1f", ((double) v / FileUtils.ONE_GB)) + " Gb";
        return s;
    }

    /**
     * Creates a date picker.
     * 
     * @param editable Pass <code>true</code> to allow users to modify the date
     *                from the editor, <code>false</code> otherwise. The
     *               default value is <code>true</code>.
     * @return See above.
     */
    public static JXDatePicker createDatePicker(boolean editable) {
        String[] dateFormats = new String[1];
        dateFormats[0] = UIUtilities.DATE_FORMAT;
        JXDatePicker picker = new JXDatePicker();
        picker.setToolTipText(DATE_TOOLTIP);
        picker.setFormats(dateFormats);
        picker.getEditor().setBackground(BACKGROUND);
        picker.getEditor().setColumns(6);
        picker.getEditor().setEditable(editable);
        return picker;
    }

    /**
     * Creates a date picker.
     * 
     * @return See above.
     */
    public static JXDatePicker createDatePicker() {
        return createDatePicker(true);
    }

    /**
     * Wraps up the passed text at at word boundaries (whitespace) if they are 
     * too long to fit within the allocated width i.e. 
     * {@link #WRAP_UP_MAX_WIDTH}.
     * Returns a collection of blocks of text.
     * 
     * @param text The text to handle.
     * @return See above.
     */
    public static List<String> wrapStyleWord(String text) {
        return wrapStyleWord(text, WRAP_UP_MAX_WIDTH);
    }

    /**
     * Wraps up the passed text at at word boundaries (whitespace) if they are 
     * too long to fit within the allocated width.
     * Returns a collection of blocks of text.
     * 
     * @param text       The text to handle.
     * @param maxWidth    The allocated width.
     * @return See above.
     */
    public static List<String> wrapStyleWord(String text, int maxWidth) {
        List<String> l = new ArrayList<String>();
        if (text == null)
            return l;
        text = text.trim();
        if (maxWidth <= 0)
            maxWidth = WRAP_UP_MAX_WIDTH;
        String sep = " ";
        String[] values = text.split(sep);
        String v = "";
        String value, tmp;
        for (int i = 0; i < values.length; i++) {
            value = values[i];
            tmp = v + sep + value;
            if (tmp.length() < maxWidth) {
                v += sep + value;
            } else {
                l.add(v);
                v = value;
            }
        }
        if (!v.equals(""))
            l.add(v);
        return l;
    }

    /**
     * Initializes a <code>JXTaskPane</code>.
     * 
     * @param title The title of the component.
     * @param background The background color.
     * @return See above.
     */
    public static JXTaskPane createTaskPane(String title, Color background) {
        JXTaskPane taskPane = new JXTaskPane();
        if (isLinuxOS())
            taskPane.setAnimated(false);

        Container c = taskPane.getContentPane();
        if (background != null) {
            c.setBackground(background);
            taskPane.setBackground(background);
        }
        if (c instanceof JComponent)
            ((JComponent) c).setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1));
        taskPane.setTitle(title);
        taskPane.setCollapsed(true);
        Font font = taskPane.getFont();
        taskPane.setFont(font.deriveFont(font.getSize2D() - 2));
        return taskPane;
    }

    /**
     * Creates a new label.
     * 
     * @param c    The foreground color if not <code>null</code>.
     * @return See above.
     */
    public static JLabel createComponent(Color c) {
        return (JLabel) createComponent(JLabel.class, c);
    }

    /**
     * Creates a new label.
     * 
     * @param type    The type of component to create. Default type is JLabel.
     * @param color The foreground color if not <code>null</code>.
     * @return See above.
     */
    public static JComponent createComponent(Class type, Color color) {
        if (type == null)
            type = JLabel.class;
        JComponent comp = null;
        if (JLabel.class.equals(type))
            comp = new JLabel();
        else if (OMETextField.class.equals(type))
            comp = new OMETextField();
        else if (OMETextArea.class.equals(type))
            comp = new OMETextArea();
        else if (NumericalTextField.class.equals(type)) {
            comp = new NumericalTextField();
            ((NumericalTextField) comp).setHorizontalAlignment(JTextField.LEFT);
            ((NumericalTextField) comp).setNegativeAccepted(true);
            comp.setBorder(null);
        }

        if (comp == null)
            comp = new JLabel();
        comp.setBackground(BACKGROUND_COLOR);
        Font font = comp.getFont();
        comp.setFont(font.deriveFont(font.getStyle(), font.getSize() - 2));
        if (color != null)
            comp.setForeground(color);
        return comp;
    }

    /**
     * Converts the passed string into a number.
     * 
     * @param value The value to parse.
     * @param type   The type of number.
     * @return See above.
     */
    public static Number extractNumber(String value, Class type) {
        if (value == null)
            return null;
        try {
            if (Integer.class.equals(type))
                return Integer.parseInt(value);
            else if (Float.class.equals(type))
                return Float.parseFloat(value);
            else if (Double.class.equals(type))
                return Double.parseDouble(value);
        } catch (Exception e) {
        }
        return null;
    }

    /**
     * Get the free memory available in the system.
     * @return see above.
     */
    public static long getFreeMemory() {
        Runtime r = Runtime.getRuntime();
        return r.freeMemory();
    }

    /**
     * Get the total memory available to the JVM.
     * @return see above.
     */
    public static long getTotalMemory() {
        Runtime r = Runtime.getRuntime();
        return r.totalMemory();
    }

    /**
     * Return the amount of memory used in JVM.
     * @return see above.
     */
    public static long getUsedMemory() {
        return getTotalMemory() - getFreeMemory();
    }

    /**
     * Creates a separator of the specified height.
     * 
     * @param h The desired height.
     * @return See above.
     */
    public static JSeparator createSeparator(int h) {
        if (h <= 0)
            h = DEFAULT_ICON_HEIGHT;
        JSeparator s = new JSeparator(JSeparator.VERTICAL);
        Dimension d = s.getPreferredSize();
        s.setMaximumSize(new Dimension(d.width, h));
        return s;
    }

    /**
     * Removes the extension if any of the passed image's name.
     * 
     * @param originalName The name to handle.
     * @return See above.
     */
    public static String removeFileExtension(String originalName) {
        String name = originalName;
        String[] l = UIUtilities.splitString(originalName);
        StringBuffer buffer;
        if (l != null) {
            int n = l.length;
            if (n >= 1)
                name = l[n - 1];
        } else {
            if (Pattern.compile("\\.").matcher(name).find()) {
                l = name.split("\\.");
                if (l.length >= 1) {
                    name = "";
                    int n = l.length - 1;
                    buffer = new StringBuffer();
                    for (int i = 0; i < n; i++) {
                        buffer.append(l[i]);
                        if (i < (n - 1))
                            buffer.append(".");
                    }
                    name = buffer.toString();
                }
            }
            if (name.length() == 0)
                name = originalName;
            return name;
        }

        if (Pattern.compile("\\.").matcher(name).find()) {
            l = name.split("\\.");
            if (l.length >= 1) {
                name = "";
                int n = l.length - 1;
                buffer = new StringBuffer();
                for (int i = 0; i < n; i++) {
                    buffer.append(l[i]);
                    if (i < (n - 1))
                        buffer.append(".");
                }
                name = buffer.toString();
            }
        }
        if (name.length() == 0)
            name = originalName;
        return name;
    }

    /**
     * Returns the name to display for a file.
     * 
     * @param fullPath The file's absolute path.
     * @param number The number of folder to set the name.
     * @return See above.
     */
    public static String getDisplayedFileName(String fullPath, Integer number) {
        if (fullPath == null)
            return fullPath;
        if (number == null || number.intValue() < 0)
            return fullPath;
        String[] l = UIUtilities.splitString(fullPath);
        String extension = null;
        if (fullPath.endsWith("\\"))
            extension = "\\";
        else if (fullPath.endsWith("/"))
            extension = "/";
        String start = null;
        if (fullPath.startsWith("\\"))
            start = "\\";
        else if (fullPath.startsWith("/"))
            start = "/";
        String sep = UIUtilities.getStringSeparator(fullPath);
        if (sep == null)
            sep = "";
        String text = "";
        int folder = -1;
        if (number != null && number >= 0)
            folder = (Integer) number;
        if (folder == -1)
            return null;
        if (l != null && l.length > 1) {
            int n = 0;
            if (folder < l.length)
                n = l.length - folder - 2;
            if (n < 0)
                n = 0;
            int m = l.length - 1;
            for (int i = l.length - 1; i > n; i--) {
                if (i == m)
                    text = l[i];
                else
                    text = l[i] + sep + text;
            }
            if (n == 0 && start != null)
                text = start + text;
            if (extension != null)
                text = text + extension;
            return text;
        }
        return null;
    }

    /**
     * Formats the passed string.
     * 
     * @param name The string to format.
     * @param max  The maximum number of characters per line.
     * @return See above.
     */
    public static String formatString(String name, int max) {
        if (name == null)
            return "";
        if (max <= 0)
            max = MAX_CHARACTER;
        StringBuffer buf = new StringBuffer();
        int index = 0;
        for (int i = 0; i < name.length(); i++) {
            if (index == max) {
                index = 0;
                buf.append("<br>");
            }
            buf.append(name.charAt(i));
            index++;
        }
        return buf.toString();
    }

    /**
     * Returns <code>true</code> if the OS is MAC, <code>false</code>
     * otherwise.
     * 
     * @return See above.
     */
    public static boolean isMacOS() {
        //String osName = System.getProperty("os.name").toLowerCase();
        //return osName.startsWith("mac os");
        return (SystemUtils.IS_OS_MAC || SystemUtils.IS_OS_MAC_OSX);
    }

    /**
     * Returns <code>true</code> if the OS is Windows, <code>false</code>
     * otherwise.
     * 
     * @return See above.
     */
    public static boolean isWindowsOS() {
        //String osName = System.getProperty("os.name").toLowerCase();
        //return osName.startsWith("windows");
        return (SystemUtils.IS_OS_WINDOWS || SystemUtils.IS_OS_WINDOWS_2000 || SystemUtils.IS_OS_WINDOWS_7
                || SystemUtils.IS_OS_WINDOWS_95 || SystemUtils.IS_OS_WINDOWS_98 || SystemUtils.IS_OS_WINDOWS_ME
                || SystemUtils.IS_OS_WINDOWS_NT || SystemUtils.IS_OS_WINDOWS_VISTA || SystemUtils.IS_OS_WINDOWS_XP);
    }

    /**
     * Returns <code>true</code> if the OS is MAC, <code>false</code>
     * otherwise.
     * 
     * @return See above.
     */
    public static boolean isLinuxOS() {
        return (!(isWindowsOS() || isMacOS()));
    }

    /**
      * Returns the partial name of the image's name
      * 
      * @param originalName The original name.
      * @return See above.
      */
    public static String getPartialName(String originalName) {
        if (originalName == null)
            return null;
        String[] l = UIUtilities.splitString(originalName);
        String extension = null;
        if (originalName.endsWith("\\"))
            extension = "\\";
        else if (originalName.endsWith("/"))
            extension = "/";
        String sep = UIUtilities.getStringSeparator(originalName);
        if (sep == null)
            sep = "";
        if (l != null) {
            int n = l.length;
            switch (n) {
            case 0:
                return originalName;
            case 1:
                if (extension != null)
                    return l[0] + extension;
                return l[0];
            case 2:
                if (extension != null)
                    return l[n - 2] + sep + l[n - 1] + extension;
                return l[n - 2] + sep + l[n - 1];
            default:
                //Check of this is actually a path.
                for (int i = 0; i < l.length; i++) {
                    if (!isTextOnly(l[i]))
                        return originalName;
                }
                if (extension != null)
                    return UIUtilities.DOTS + l[n - 2] + sep + l[n - 1] + extension;
                return UIUtilities.DOTS + l[n - 2] + sep + l[n - 1];
            }
        }
        return originalName;
    }

    /**
     * Converts the passed color.
     * 
     * @param c The color to handle.
     * @return See above.
     */
    public static int convertColor(Color c) {
        int alpha = c.getAlpha();
        if (alpha == 0)
            alpha = 255;
        return ((alpha & 0xFF) << 24) | ((c.getRed() & 0xFF) << 16) | ((c.getGreen() & 0xFF) << 8)
                | ((c.getBlue() & 0xFF) << 0);
    }

    /**
    * Converts a list to a CSV string.
    *
    * @param list The list to convert.
    * @return See above.
    */
    public static String listToCSV(List<String> list) {
        StringBuffer buffer = new StringBuffer();
        for (int i = 0; i < list.size(); i++) {
            buffer.append(list.get(i));
            if (i < list.size() - 1)
                buffer.append(",");
        }
        return buffer.toString();
    }

    /**
    * Converts a CSV string to a list of strings.
    *
    * @param str The CSV string to convert.
    * @return See above.
    */
    public static List<String> CSVToList(String str) {
        List<String> list = new ArrayList<String>();
        String[] valueString = str.split(",");
        for (String value : valueString)
            if (!value.equals("[]"))
                list.add(value);
        return list;
    }

    /**
     * Makes sure the paths for the script are platform agnostic.
     * 
     * @param path The path
     * @return The corrected path
     */
    public static String toUnix(String path) {
        return path.replace('\\', '/');
    }

    /**
     * Converting the passed value to make sure we can use it for OpenGL.
     * 
     * @param n The value to convert.
     * @return See above.
     */
    public static int ceilingPow2(int n) {
        int pow2 = 1;
        while (n > pow2)
            pow2 = pow2 << 1;
        return pow2;
    }

    /**
     * Utility method to print an error message
     * 
     * @param e The exception to handle.
     * @return  See above.
     */
    public static String printErrorText(Throwable e) {
        if (e == null)
            return "";
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        e.printStackTrace(pw);
        return sw.toString();
    }

    /**
     * Formats the exception to display in tool tip. Displays the first
     * {@link #MAX_LINES_EXCEPTION} lines.
     * 
     * @param ex The exception to handle.
     * @return See above.
     */
    public static String formatExceptionForToolTip(Throwable ex) {
        return formatExceptionForToolTip(ex, MAX_LINES_EXCEPTION);
    }

    /**
     * Formats the exception to display in tool tip. Displays the specified
     * number of lines.
     * 
     * @param ex The exception to handle.
     * @param n  The number of lines to display.
     * @return See above.
     */
    public static String formatExceptionForToolTip(Throwable ex, int n) {
        if (ex == null)
            return "";
        if (n <= 0)
            n = MAX_LINES_EXCEPTION;
        ex.printStackTrace();
        String s = UIUtilities.printErrorText(ex.getCause());
        String[] values = s.split("\n");
        //Display the first 20 lines
        String[] lines = values;
        if (values.length > MAX_LINES_EXCEPTION) {
            lines = new String[MAX_LINES_EXCEPTION + 1];
            for (int i = 0; i < lines.length - 1; i++) {
                lines[i] = values[i];
            }
            lines[lines.length - 1] = "... " + (values.length - MAX_LINES_EXCEPTION) + " more";
        }
        return formatToolTipText(lines);
    }

    /**
     * Returns <code>true</code> if the passed colors are the same, 
     * <code>false</code> otherwise.
     * 
     * @param c1 One of the colors to check.
     * @param c2 One of the colors to check.
     * @param alpha Pass <code>true</code> to take into account the 
     *             alpha component, <code>false</code> otherwise.
     * @return See above.
     */
    public static boolean isSameColors(Color c1, Color c2, boolean alpha) {
        if (c1 == null || c2 == null)
            return false;
        if (c1.getRed() != c2.getRed())
            return false;
        if (c1.getGreen() != c2.getGreen())
            return false;
        if (c1.getBlue() != c2.getBlue())
            return false;
        if (alpha) {
            if (c1.getAlpha() != c2.getAlpha())
                return false;
        }
        return true;
    }

    /**
     * Creates a button looking like an hyper-link.
     * 
     * @param text The text to display
     * @return See above.
     */
    public static JButton createHyperLinkButton(String text) {
        if (text == null || text.trim().length() == 0)
            text = "hyperlink";
        JButton b = new JButton(text);
        Font f = b.getFont();
        b.setFont(f.deriveFont(f.getStyle(), f.getSize() - 2));
        b.setOpaque(false);
        b.setForeground(UIUtilities.HYPERLINK_COLOR);
        unifiedButtonLookAndFeel(b);
        return b;
    }

    /**
     * Creates a button looking like an hyper-link.
     * 
     * @param text The text to display
     * @return See above.
     */
    public static JMenuItem createHyperLinkMenuItem(String text) {
        if (text == null || text.trim().length() == 0)
            text = "hyperlink";
        JMenuItem b = new JMenuItem(text);
        //Font f = b.getFont();
        //b.setFont(f.deriveFont(f.getStyle(), f.getSize()-2));
        b.setOpaque(false);
        b.setForeground(UIUtilities.HYPERLINK_COLOR);
        unifiedButtonLookAndFeel(b);
        return b;
    }

    /**
     * Converts the font.
     * 
     * @param family The value to convert.
     * @return See above.
     */
    public static String convertFont(String family) {
        if (family == null)
            return "";
        String value = FONTS.get(family);
        if (value == null || value.trim().length() == 0)
            return "";
        return value;
    }

    /** Builds the UI component displaying the exception.*/
    public static JTextPane buildExceptionArea() {
        StyleContext context = new StyleContext();
        StyledDocument document = new DefaultStyledDocument(context);

        JTextPane textPane = new JTextPane(document);
        textPane.setOpaque(false);
        textPane.setEditable(false);

        // Create one of each type of tab stop
        List<TabStop> list = new ArrayList<TabStop>();

        // Create a left-aligned tab stop at 100 pixels from the left margin
        float pos = 15;
        int align = TabStop.ALIGN_LEFT;
        int leader = TabStop.LEAD_NONE;
        TabStop tstop = new TabStop(pos, align, leader);
        list.add(tstop);

        // Create a right-aligned tab stop at 200 pixels from the left margin
        pos = 15;
        align = TabStop.ALIGN_RIGHT;
        leader = TabStop.LEAD_NONE;
        tstop = new TabStop(pos, align, leader);
        list.add(tstop);

        // Create a center-aligned tab stop at 300 pixels from the left margin
        pos = 15;
        align = TabStop.ALIGN_CENTER;
        leader = TabStop.LEAD_NONE;
        tstop = new TabStop(pos, align, leader);
        list.add(tstop);

        // Create a decimal-aligned tab stop at 400 pixels from the left margin
        pos = 15;
        align = TabStop.ALIGN_DECIMAL;
        leader = TabStop.LEAD_NONE;
        tstop = new TabStop(pos, align, leader);
        list.add(tstop);

        // Create a tab set from the tab stops
        TabSet tabs = new TabSet(list.toArray(new TabStop[0]));

        // Add the tab set to the logical style;
        // the logical style is inherited by all paragraphs
        Style style = textPane.getLogicalStyle();
        StyleConstants.setTabSet(style, tabs);
        textPane.setLogicalStyle(style);
        Style debugStyle = document.addStyle("StyleName", null);
        StyleConstants.setForeground(debugStyle, Color.BLACK);
        StyleConstants.setFontFamily(debugStyle, "SansSerif");
        StyleConstants.setFontSize(debugStyle, 12);
        StyleConstants.setBold(debugStyle, false);
        return textPane;
    }

    /**
     * Returns the converted value.
     * 
     * @param rgba The RGBA value to convert.
     * @return See above.
     */
    public static int convertRgbaToArgb(int rgba) {
        return (rgba >>> 8) | (rgba << (32 - 8));
    }

    /**
     * Returns the converted value.
     * 
     * @param argb The ARGB value to convert.
     * @return See above.
     */
    public static int convertArgbToRgba(int argb) {
        return (argb << 8) | (argb >>> (32 - 8));
    }

    /**
     * Returns {@link #RED}, {@link #RED} or {@link #RED} to indicate the
     * range of the color.
     * 
     * @param color The color to handle.
     * @return See above
     */
    public static int getColorRange(Color color) {
        if (color == null)
            return -1;
        int r = color.getRed();
        int g = color.getGreen();
        int b = color.getBlue();
        if (g < r / 2 && b < r / 2)
            return RED_COLOR;
        if (r < g / 2 && b < g / 2)
            return GREEN_COLOR;
        return BLUE_COLOR;
    }

    /**
     * Displays the end of the name if the name is longer that the number
     * of specified characters.
     * 
     * @param name The name of handle.
     * @param numberOfCharacters The number of characters.
     * @return See above.
     */
    public static String formatPartialName(String name, int numberOfCharacters) {
        if (name == null)
            return null;
        int n = DOTS.length() + numberOfCharacters;
        int m = name.length();
        if (m <= n)
            return name;
        return DOTS + name.substring(m - n, m);
    }

    /**
     * Displays the end of the name if the name is longer that the number
     * of specified characters.
     * 
     * @param name The name of handle.
     * @param numberOfCharacters The number of characters.
     * @return See above.
     */
    public static String formatPartialName(String name) {
        return formatPartialName(name, DEFAULT_NUMBER_OF_CHARACTERS);
    }

}