/* * org.openmicroscopy.shoola.util.ui.UIUtilities * *------------------------------------------------------------------------------ * Copyright (C) 2006-2016 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; 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.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.Point; import java.awt.Rectangle; import java.awt.Toolkit; import java.awt.Window; import java.awt.datatransfer.Clipboard; import java.awt.datatransfer.StringSelection; 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.Locale; import java.util.Map; import java.util.prefs.Preferences; import java.util.regex.Pattern; import javax.swing.AbstractButton; import javax.swing.Action; import javax.swing.BorderFactory; import javax.swing.Box; 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; import org.apache.commons.io.FileUtils; import org.apache.commons.io.FilenameUtils; import org.openmicroscopy.shoola.util.CommonsLangUtils; import org.jdesktop.swingx.JXDatePicker; import org.jdesktop.swingx.JXLabel; import org.jdesktop.swingx.JXTaskPane; import org.openmicroscopy.shoola.util.ui.border.TitledLineBorder; import omero.model.Length; import omero.model.LengthI; import omero.model.enums.UnitsLength; /** * 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      * <a href="mailto:a.falconi@dundee.ac.uk"> * a.falconi@dundee.ac.uk</a> * @author Blazej Pindelski, bpindelski at dundee.ac.uk * @version 2.2 * @since OME2.2 */ public class UIUtilities { /** Defines the format how the date is shown */ private static final DateFormat DEFAULT_DATE_FORMAT = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss"); //2013-04-20 18:13:43 /** Bound property indicating that the font changes.*/ public static final String HINTS_PROPERTY = "awt.font.desktophints"; /** The default background color.*/ public static final Color TOOLTIP_COLOR = new Color(255, 252, 180, 200); /** 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 color 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 squared symbol. */ public final static String SQUARED_SYMBOL = "²"; /** Unicode for the squared symbol. */ public final static String DELTA_SYMBOL = "Δ"; /** Pixels string. */ public final static String PIXELS_SYMBOL = "px"; /** Degree symbol */ public final static String DEGREE_SYMBOL = "°"; /** 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 = 1048576; /** 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"); } /** Flag indicating if desktop is GNOME **/ private static final boolean GNOME; static { String desktop = System.getenv("XDG_CURRENT_DESKTOP"); GNOME = desktop != null && desktop.toLowerCase().contains("gnome"); } /** * 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) centerAndShow(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); applyGnome3Workaround(window); } /** * 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 The String. */ public static String formatToolTipText(String toolTipText) { return toolTipText; } /** * Builds an HTML table from supplied arguments. * * Accepts a list of column names and a list of <code>String</code> arrays. * Each array forms the column values for a specific row in the table. * If the number of column names and elements in a row array won't match * the table will be rendered correctly nevertheless. * * @param columnNames A list of column names. * @param rows A list of arrays representing column data for each row. * @return See above. */ public static String formatStringListToTable(List<String> columnNames, List<String[]> rows) { if (columnNames == null || rows == null) { return ""; } StringBuilder sb = new StringBuilder(); sb.append("<table>"); sb.append("<tr>"); for (String column : columnNames) { sb.append("<th>" + column + "</th>"); } sb.append("</tr>"); for (String[] rowColumns : rows) { sb.append("<tr>"); for (int i = 0; i < rowColumns.length; ++i) { sb.append("<td>"); sb.append(rowColumns[i]); sb.append("</td>"); } sb.append("</tr>"); } sb.append("</table>"); return formatToolTipText(sb.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(List<String> toolTipText) { if (toolTipText == null) return ""; StringBuffer buf = new StringBuffer(); 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 style 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 JXLabel} and sets * the font style to <code>bold</code>. * * @param s The string to display. * @return See above. */ public static JLabel setTextFontX(String s) { return UIUtilities.setTextFontX(s, Font.BOLD); } /** * Displays the specified string into a {@link JLabel}. * * @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 JXLabel}. * * @param s The string to display. * @param fontStyle The style of the font. * @return See above. */ public static JLabel setTextFontX(String s, int fontStyle) { if (s == null) s = ""; JXLabel label = new JXLabel(s); label.setLineWrap(true); Font font = label.getFont(); Font newFont = font.deriveFont(fontStyle); label.setFont(newFont); return label; } /** * Displays the specified string into a {@link JXLabel}. * * @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 setTextFontX(String s, int fontStyle, int fontSize) { if (s == null) s = ""; JXLabel label = new JXLabel(s); label.setLineWrap(true); Font font = label.getFont(); label.setFont(font.deriveFont(fontStyle, fontSize)); return label; } /** * Displays the specified string into a {@link JLabel}. * * @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) { return buildComponentPanelCenter(component, hgap, vgap, 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>. * @return See below. */ public static JPanel buildComponentPanelCenter(JComponent component, int hgap, int vgap, boolean opaque) { 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); p.setOpaque(opaque); 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(JComponent 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(); b.setContentAreaFilled(!isMacOS()); //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 a double to two decimal places and returns as a number. * * @param val The number to be formatted. * @return See above. */ public static Number twoDecimalPlacesAsNumber(double val) { double v = val; Number 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; 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, Locale.getDefault()).format(time); } /** * Formats as a <code>String</code> the specified time, * using the default date format: yyyy-MM-dd HH:mm:ss * @param time The timestamp to format. * @return Returns the stringified version of the passed timestamp. */ public static String formatDefaultDate(Timestamp time) { if (time == null) time = getDefaultTimestamp(); return DEFAULT_DATE_FORMAT.format(time); } /** * Formats as a <code>String</code> the specified time, * using the default date format: yyyy-MM-dd HH:mm:ss * @param date The timestamp to format. * @return Returns the stringified version of the passed timestamp. */ public static String formatDefaultDate(Date date) { if (date == null) return formatDefaultDate((Timestamp)null); return DEFAULT_DATE_FORMAT.format(date); } /** * 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; DateFormat df; if (WDMY_FORMAT.equals(pattern)) df = DateFormat.getDateTimeInstance( DateFormat.FULL, DateFormat.LONG, Locale.getDefault()); else df = DateFormat.getDateInstance(DateFormat.SHORT, Locale.getDefault()); return df.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), false); } /** * Converts the time in seconds into hours, minutes and seconds. * * @param timeInMilliSeconds The time in milliseconds to convert. * @param shortUnit Pass <code>true</code> to use short units * e.g. s for second, <code>false</code> otherwise. * @return See above. */ public static String calculateHMSFromMilliseconds(long timeInMilliSeconds, boolean shortUnit) { return calculateHMS((int) (timeInMilliSeconds/1000), shortUnit); } /** * Converts the time in seconds into hours, minutes and seconds. * * @param timeInSeconds The time in seconds to convert. * @param shortUnit Pass <code>true</code> to use short units * e.g. s for second, <code>false</code> otherwise. * @return See above. */ public static String calculateHMS(int timeInSeconds, boolean shortUnit) { int hours = timeInSeconds/3600; timeInSeconds = timeInSeconds-(hours*3600); int minutes = timeInSeconds/60; timeInSeconds = timeInSeconds-(minutes*60); int seconds = timeInSeconds; StringBuffer text = new StringBuffer(); if (hours > 0) { text.append(hours); if (shortUnit) text.append("h"); else { text.append(" hour"); if (hours > 1) text.append("s"); } } if (minutes > 0) { text.append(" "); text.append(minutes); if (shortUnit) text.append("min"); else { text.append(" minute"); if (minutes > 1) text.append("s"); } } if (seconds > 0) { text.append(" "); text.append(seconds); if (shortUnit) text.append("s"); else { text.append(" second"); if (seconds > 1) text.append("s"); } } return text.toString(); } /** * 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) { return calculateHMS(timeInSeconds, false); } /** * 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 maximum number of decimal places which still result in a * non-zero rounded value. * * @param value The value to handle. * @param decimal The starting number of decimal places to test. * @return See above. */ public static final int findDecimal(double value, int decimal) { double testValue = Math.abs(value); double v = round(testValue, decimal); if (v > 0) return decimal; decimal++; return findDecimal(testValue, 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) { return FileUtils.byteCountToDisplaySize(v); } /** * 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>. * @param dateFormat The date format which is used for the text field * @return See above. */ public static JXDatePicker createDatePicker(boolean editable, String dateFormat) { String[] dateFormats = new String[1]; dateFormats[0] = dateFormat; 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 an editable date picker, with default * date format * * @return See above. */ public static JXDatePicker createDatePicker() { return createDatePicker(true); } /** * Creates a date picker. * * @param editable Makes the picker's text fields editable or not. * @return See above. */ public static JXDatePicker createDatePicker(boolean editable) { return createDatePicker(editable, UIUtilities.DATE_FORMAT); } /** * 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(); 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) { return FilenameUtils.removeExtension(originalName); } /** * 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"); } /** * 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"); } /** * Returns <code>true</code> if the OS is MAC, <code>false</code> * otherwise. * * @return See above. */ public static boolean isLinuxOS() { return !(isMacOS() || isWindowsOS()); } /** * 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; String s; if (ex.getCause() != null) { s = UIUtilities.printErrorText(ex.getCause()); } else s = UIUtilities.printErrorText(ex); 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]; } StringBuffer buffer = new StringBuffer(); buffer.append(DOTS); buffer.append(values.length-MAX_LINES_EXCEPTION); buffer.append(" more"); lines[lines.length-1] = buffer.toString(); } 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 (CommonsLangUtils.isBlank(value)) 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_COLOR}, {@link #GREEN_COLOR} or {@link #BLUE_COLOR} * 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; StringBuffer buffer = new StringBuffer(); buffer.append(DOTS); buffer.append(name.substring(m-n, m)); return buffer.toString(); } /** * Displays the end of the name if the name is longer that the number * of specified characters. * * @param name The name of handle. * @return See above. */ public static String formatPartialName(String name) { return formatPartialName(name, DEFAULT_NUMBER_OF_CHARACTERS); } /** * Creates a new button and formats it using settings from action. * * @param a The action to use. */ public static JButton formatButtonFromAction(Action a) { JButton button = new JButton(); button.setToolTipText((String) a.getValue(Action.SHORT_DESCRIPTION)); button.setIcon((Icon) a.getValue(Action.SMALL_ICON)); return button; } /** * Transforms the given value (it's assumed it's in microns) to * a more readable value * @param value The value to transform * @return The transformed value as unit object */ public static Length transformSize(double value) { return transformSize(new LengthI(value, UnitsLength.MICROMETER)); } /** * Transforms the given value to a more readable value * @param value The value to transform * @return The transformed value */ public static Length transformSize(Length value) { if(value.getUnit().equals(UnitsLength.MICROMETER)) { double v = value.getValue(); UnitsLength unit = UnitsLength.MICROMETER; if (v > 0.0 && v < 0.1) { unit = UnitsLength.NANOMETER; v *= 1000; if (v < 1) { unit = UnitsLength.ANGSTROM; v *= 10; } return new LengthI(v, unit); } if (v > 1000) { unit = UnitsLength.MILLIMETER; v /= 1000; } if (v > 1000) { unit = UnitsLength.CENTIMETER; v /= 1000; } if (v > 1000) { unit = UnitsLength.METER; v /= 1000; } return new LengthI(v, unit); } return value; } /** * Transforms the given (squared) value to a more readable value; * Only use with squared values (e. g. area), for plain values * use {@link #transformSize(Length)} * @param value The value to transform * @return The transformed value */ public static Length transformSquareSize(Length value) { if(value.getUnit().equals(UnitsLength.MICROMETER)) { double v = value.getValue(); double pow = Math.pow(10, 6); UnitsLength unit = UnitsLength.MICROMETER; if (v > 0.0 && v < 0.1) { unit = UnitsLength.NANOMETER; v *= pow; if (v < 100) { unit = UnitsLength.ANGSTROM; v *= 100; } return new LengthI(v, unit); } if (v > pow) { unit = UnitsLength.MILLIMETER; v /= pow; } if (v > pow) { unit = UnitsLength.CENTIMETER;; v /= pow; } if (v > pow) { unit = UnitsLength.METER; v /= pow; } return new LengthI(v, unit); } return value; } /** * Creates a readable String representation of the given value, i. e. * transformed into a suitable unit, with unit symbol attached * @param value The value to format * @return See above. */ public static String formatValue(Length value) { return formatValue(value, false); } /** * Creates a readable String representation of the given value * (assumed it's a value in Microns), i. e. * transformed into a suitable unit, with unit symbol attached * @param value The value to format * @return See above. */ public static String formatValue(double value) { return formatValue(new LengthI(value, UnitsLength.MICROMETER), false); } /** * Creates a readable String representation of the given value, i. e. * transformed into a suitable unit, with unit symbol attached and * if squared flag is set, also attaches the square symbol. * @param value The value to format * @param squared Pass <code>true</code> to attach the square symbol * @return See above. */ public static String formatValue(Length value, boolean squared) { Length converted = squared ? transformSquareSize(value) : transformSize(value); String v; if (value.getUnit().equals(UnitsLength.PIXEL)) v = value.getValue() == 0 ? null : ""+((int)value.getValue()); else v = UIUtilities.twoDecimalPlaces(converted.getValue()); if (v==null) return ""; v += ((LengthI)converted).getSymbol(); if (squared && !value.getUnit().equals(UnitsLength.PIXEL)) v += UIUtilities.SQUARED_SYMBOL; return v; } /** * Creates a readable String representation of the given value, i. e. * transformed into a suitable unit, with unit symbol attached and * if squared flag is set, also attaches the square symbol. * @param value The value to format * @param squared Pass <code>true</code> to attach the square symbol * @return See above. */ public static String formatValueNoUnit(Length value, boolean squared) { Length converted = squared ? transformSquareSize(value) : transformSize(value); String v; if (value.getUnit().equals(UnitsLength.PIXEL)) v = value.getValue() == 0 ? null : ""+((int) value.getValue()); else v = UIUtilities.twoDecimalPlaces(converted.getValue()); if (v == null) return ""; return v; } /** * Creates a readable String representation of the given value, i. e. * transformed into a suitable unit, with unit symbol attached and * if squared flag is set, also attaches the square symbol. * @param value The value to format * @param squared Pass <code>true</code> to attach the square symbol * @return See above. */ public static Number formatValueNoUnitAsNumber(Length value, boolean squared) { Length converted = squared ? transformSquareSize(value) : transformSize(value); if (value.getUnit().equals(UnitsLength.PIXEL)) { return value.getValue() == 0 ? null : value.getValue(); } Number n = UIUtilities.twoDecimalPlacesAsNumber(converted.getValue()); if (n.doubleValue() == 0) return null; return n; } /** * Formats the passed value in seconds. * * @param v The value to transform. * @return See above. */ public static String formatTimeInSeconds(int v) { if (v <= 0) return ""; int hours = v/3600; int remainder = v%3600; int minutes = remainder/60; int seconds = remainder%60; StringBuffer text = new StringBuffer(); if (hours > 0) { text.append(hours); text.append("h"); } if (minutes > 0) { text.append(minutes); text.append("min"); if (seconds > 0) { text.append(seconds); text.append("s"); } } else { text.append(seconds); text.append("s"); } return text.toString(); } /** * Returns the last characters of the name when the name is longer that the * specified value. * * @param name The name to truncate. * @param maxLength The maximum length. * @param start Pass <code>true</code> to truncate the start of the word, * <code>false</code> to truncate the end. * @return See above. */ public static String truncate(String name, int maxLength, boolean start) { if (name == null) return ""; int v = maxLength+UIUtilities.DOTS.length(); int n = name.length(); if (n > v) { n = n-1; if (start) return UIUtilities.DOTS+name.substring(n-maxLength, n); return name.substring(0, maxLength)+UIUtilities.DOTS; } return name; } /** * Generates an unique filename in form 'folder'/'name'(INCREMENT).'ext', whereas * INCREMENT is chosen in such a way, that the file does not exist yet. * * @param folder The folder where the file is intended to be stored * @param name The base name of the file * @param ext The extension of the file * @return The generated unique filename */ public static File generateFileName(File folder, String name, String ext) { int i = 0; File file = new File(folder, name+"."+ext); while(file.exists()) { i++; file = new File(folder, name+"("+i+")."+ext); } return file; } /** * Adds an empty JPanel to component which takes up excessive space, a bit * like {@link Box#createHorizontalGlue()} and {@link Box#createVerticalGlue()} * just for {@link GridBagLayout} * * @param component * The component to add the filler to * @param c * The last used GridBagConstraints (c.gridx, respectively c.gridy * will be incremented) * @param vertical * Add a vertical (<code>true</code>) or horizontal ( * <code>false</code>) filler */ public static void addFiller(JComponent component, GridBagConstraints c, boolean vertical) { if (!(component.getLayout() instanceof GridBagLayout)) { throw new IllegalArgumentException( "Component does not use GridBagLayout!"); } double weightx = c.weightx; double weighty = c.weighty; int fill = c.fill; c.weightx = vertical ? c.weightx : 1; c.weighty = vertical ? 1 : c.weighty; c.fill = GridBagConstraints.BOTH; JPanel filler = new JPanel(); filler.setBackground(BACKGROUND_COLOR); component.add(filler, c); c.weightx = weightx; c.weighty = weighty; c.fill = fill; if (vertical) c.gridy++; else c.gridx++; } /** * Finds the parent of the component identified by the specified class. * 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 findParent(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 parent = ((Container) comp).getParent(); if (parent == null) return null; if (parent.getClass().equals(c)) return parent; return findParent(parent, c); } return null; } /** * Copies the passed value to the System clipboard * @param value */ public static void copyToClipboard(String value) { Toolkit toolkit = Toolkit.getDefaultToolkit(); Clipboard clipboard = toolkit.getSystemClipboard(); StringSelection strSel = new StringSelection(value); clipboard.setContents(strSel, null); } /** * Replaces the Windows backslash path separator with a slash * * @param path The path * @return See above */ public static String replaceWindowsPathSeparator(String path) { return path.replaceAll("\\\\", "/"); } /** * Simply replaces all non word characters with underscores. * @param name The original name * @return See above. */ public static String replaceNonWordCharacters(String name) { return name.replaceAll("\\W", "_"); } /** * As workaround for https://bugzilla.gnome.org/show_bug.cgi?id=759492 an * internal repaint has to be triggered for undecorated frames in order to * get displayed correctly. This is done by changing the size of the frame * (making it one pixel bigger); a simple call to repaint() is not * sufficient. * * @param c * The {@link Component} */ public static void applyGnome3Workaround(Component c) { if (!GNOME) return; boolean undecorated = false; if (c instanceof Dialog) undecorated = ((Dialog) c).isUndecorated(); if (c instanceof Frame) undecorated = ((Frame) c).isUndecorated(); if (undecorated) { Dimension size = c.getSize(); c.setSize(new Dimension(size.width + 1, size.height + 1)); } } }