package com.revolsys.swing; import java.awt.Color; import java.awt.Component; import java.awt.Container; import java.awt.Dimension; import java.awt.Font; import java.awt.Frame; import java.awt.Graphics2D; import java.awt.GraphicsConfiguration; import java.awt.GraphicsDevice; import java.awt.GraphicsEnvironment; import java.awt.Insets; import java.awt.KeyboardFocusManager; import java.awt.LayoutManager; import java.awt.MenuContainer; import java.awt.MenuItem; import java.awt.Point; import java.awt.Rectangle; import java.awt.SplashScreen; import java.awt.Toolkit; import java.awt.Window; import java.awt.datatransfer.DataFlavor; import java.awt.event.InputEvent; import java.awt.event.MouseEvent; import java.io.BufferedReader; import java.io.File; import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Map.Entry; import javax.swing.ActionMap; import javax.swing.ComboBoxEditor; import javax.swing.InputMap; import javax.swing.JCheckBox; import javax.swing.JComboBox; import javax.swing.JComponent; import javax.swing.JFileChooser; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JLayeredPane; import javax.swing.JList; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JPopupMenu; import javax.swing.JScrollPane; import javax.swing.JTabbedPane; import javax.swing.JTextArea; import javax.swing.JTextField; import javax.swing.KeyStroke; import javax.swing.SwingUtilities; import javax.swing.text.JTextComponent; import com.revolsys.awt.WebColors; import com.revolsys.datatype.DataType; import com.revolsys.datatype.DataTypes; import com.revolsys.geometry.model.Geometry; import com.revolsys.identifier.Identifier; import com.revolsys.io.FileUtil; import com.revolsys.logging.Logs; import com.revolsys.record.code.CodeTable; import com.revolsys.record.schema.FieldDefinition; import com.revolsys.record.schema.RecordDefinition; import com.revolsys.swing.action.RunnableAction; import com.revolsys.swing.border.TitledBorder; import com.revolsys.swing.field.CheckBox; import com.revolsys.swing.field.CodeTableComboBoxModel; import com.revolsys.swing.field.ColorChooserField; import com.revolsys.swing.field.ComboBox; import com.revolsys.swing.field.DateField; import com.revolsys.swing.field.Field; import com.revolsys.swing.field.NumberTextField; import com.revolsys.swing.field.ObjectLabelField; import com.revolsys.swing.field.TextArea; import com.revolsys.swing.field.TextField; import com.revolsys.swing.menu.MenuFactory; import com.revolsys.swing.parallel.Invoke; import com.revolsys.util.CaseConverter; import com.revolsys.util.OS; import com.revolsys.util.PreferencesUtil; import com.revolsys.util.Property; import com.revolsys.util.Strings; public interface SwingUtil { static final Font BOLD_FONT = new Font(Font.SANS_SERIF, Font.BOLD, 11); static final Font FONT = new Font(Font.SANS_SERIF, Font.PLAIN, 11); static void addAction(final JComponent component, final KeyStroke keyStroke, final String actionKey, final Runnable runnable) { final InputMap inputMap = component.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); inputMap.put(keyStroke, actionKey); final ActionMap actionMap = component.getActionMap(); final RunnableAction action = new RunnableAction(actionKey, runnable); actionMap.put(actionKey, action); if (component instanceof JComboBox) { final JComboBox comboBox = (JComboBox)component; final JComponent editorComponent = (JComponent)comboBox.getEditor().getEditorComponent(); addAction(editorComponent, keyStroke, actionKey, runnable); } } static JComponent addField(final Container panel, final String fieldName, final Object fieldValue) { return addField(panel, fieldName, fieldName, fieldValue); } static JComponent addField(final Container panel, final String fieldName, final String label, final Object fieldValue) { addLabel(panel, label); final JComponent field = SwingUtil.newField(fieldValue.getClass(), fieldName, fieldValue); panel.add(field); return field; } static JLabel addLabel(final Container container, final String text) { final String labelText = CaseConverter.toCapitalizedWords(text) + " "; final JLabel label = newLabel(labelText); container.add(label); return label; } static void addLabelledReadOnlyTextField(final JPanel container, final String fieldName, final Object value) { final String string = DataTypes.toString(value); final int length = Math.max(1, string.length()); addLabelledReadOnlyTextField(container, fieldName, value, length); } static void addLabelledReadOnlyTextField(final JPanel container, final String fieldName, final Object value, final int length) { addLabel(container, fieldName); addReadOnlyTextField(container, fieldName, value, length); } static void addLayer(final JLayeredPane layeredPane, final JComponent component, final Integer layerIndex) { layeredPane.add(component, layerIndex); } static JComponent addObjectField(final Container container, final Object object, final String fieldName) { return addObjectField(container, object, fieldName, fieldName); } static JComponent addObjectField(final Container panel, final Object object, final String fieldName, final String label) { final Object fieldValue = Property.get(object, fieldName); return addField(panel, fieldName, label, fieldValue); } static void addReadOnlyTextField(final JPanel container, final String fieldName, final Object value, final int length) { final TextField field = new TextField(fieldName, value, length); field.setEditable(false); container.add(field); } static Rectangle applyInsets(final Rectangle bounds, final Insets insets) { final int x = bounds.x + insets.left; final int y = bounds.y + insets.top; final int width = bounds.width - insets.left - insets.right; final int height = bounds.height - insets.top - insets.bottom; return new Rectangle(x, y, width, height); } static void autoAdjustPosition(final Window window) { window.pack(); final Rectangle bounds = getScreenBounds(); final int width = Math.min(window.getWidth(), bounds.width - 100); final int height = Math.min(window.getHeight(), bounds.height - 100); window.setSize(width, height); setLocationCentre(bounds, window); } static void autoAdjustSize(final Window window) { window.pack(); final Rectangle bounds = getScreenBounds(); final int width = Math.min(window.getWidth(), bounds.width - 20 - window.getX()); final int height = Math.min(window.getHeight(), bounds.height - 20 - window.getY()); window.setSize(width, height); } static void dispose(final Window window) { if (window != null) { Invoke.later(() -> { window.setVisible(false); try { window.dispose(); } catch (final Throwable e) { Logs.debug(window, "Unable to dispose", e); } }); } } static void dndCopy(final Component component) { final JTextComponent textComponent = getTextComponent(component); if (textComponent != null) { textComponent.copy(); } } static void dndCut(final Component component) { final JTextComponent textComponent = getTextComponent(component); if (textComponent != null) { textComponent.cut(); } } static void dndPaste(final Component component) { final JTextComponent textComponent = getTextComponent(component); if (textComponent != null) { textComponent.paste(); } } static Window getActiveWindow() { final KeyboardFocusManager keyboardFocusManager = KeyboardFocusManager .getCurrentKeyboardFocusManager(); final Window activeWindow = keyboardFocusManager.getActiveWindow(); if (activeWindow == null) { final Window[] windows = Window.getOwnerlessWindows(); for (final Window window : windows) { if (window.isVisible()) { return window; } } } return activeWindow; } static Component getInvoker(final JMenuItem menuItem) { MenuContainer menuContainer = menuItem.getParent(); while (menuContainer != null && !(menuContainer instanceof JPopupMenu)) { if (menuContainer instanceof MenuItem) { menuContainer = ((MenuItem)menuContainer).getParent(); } else { menuContainer = null; } } if (menuContainer != null) { final JPopupMenu menu = (JPopupMenu)menuContainer; final Component invoker = menu.getInvoker(); return invoker; } else { return null; } } static Rectangle getScreenBounds() { return getScreenBounds((Component)null); } static Rectangle getScreenBounds(Component component) { if (component == null) { component = SwingUtil.getActiveWindow(); } final Point mousePosition; if (component == null) { mousePosition = null; } else { mousePosition = component.getMousePosition(); if (mousePosition != null) { SwingUtilities.convertPointToScreen(mousePosition, component); } } return getScreenBounds(mousePosition); } static Rectangle getScreenBounds(final int x, final int y) { return getScreenBounds(new Point(x, y)); } /** * Get the screen rectangle in which the mouse is in. If the mouse is outside all bounds return the current screen. * * @param point * @return */ static Rectangle getScreenBounds(final Point point) { Rectangle firstBounds = null; final GraphicsEnvironment graphicsEnvironment = GraphicsEnvironment .getLocalGraphicsEnvironment(); for (final GraphicsDevice device : graphicsEnvironment.getScreenDevices()) { for (final GraphicsConfiguration config : device.getConfigurations()) { final Rectangle bounds = config.getBounds(); if (point != null && bounds.contains(point)) { final Insets insets = Toolkit.getDefaultToolkit().getScreenInsets(config); return applyInsets(bounds, insets); } else if (firstBounds == null) { firstBounds = bounds; } } } final GraphicsDevice defaultScreenDevice = graphicsEnvironment.getDefaultScreenDevice(); for (final GraphicsConfiguration config : defaultScreenDevice.getConfigurations()) { final Rectangle bounds = config.getBounds(); final Insets insets = Toolkit.getDefaultToolkit().getScreenInsets(config); return applyInsets(bounds, insets); } return firstBounds; } static int getTabIndex(final JTabbedPane tabs, final String title) { for (int i = 0; i < tabs.getTabCount(); i++) { if (tabs.getTitleAt(i).equals(title)) { return i; } } return -1; } static JTextComponent getTextComponent(final Component component) { if (component instanceof JTextComponent) { return (JTextComponent)component; } else if (component instanceof JComboBox) { final JComboBox<?> comboBox = (JComboBox<?>)component; final ComboBoxEditor editor = comboBox.getEditor(); final Component editorComponent = editor.getEditorComponent(); return getTextComponent(editorComponent); } else { return null; } } @SuppressWarnings({ "unchecked" }) static <V> V getValue(final JComponent component) { if (component instanceof Field) { final Field field = (Field)component; return (V)field.getFieldValue(); } else if (component instanceof JTextComponent) { final JTextComponent textComponent = (JTextComponent)component; final String text = textComponent.getText(); if (Property.hasValue(text)) { return (V)text; } else { return null; } } else if (component instanceof JList) { final JList list = (JList)component; return (V)list.getSelectedValue(); } else if (component instanceof JCheckBox) { final JCheckBox checkBox = (JCheckBox)component; return (V)(Object)checkBox.isSelected(); } else { return null; } } static Window getWindowAncestor(final Component component) { if (component == null) { return null; } else { return SwingUtilities.getWindowAncestor(component); } } static int getX(final Component component) { final int x = component.getX(); final Component parent = component.getParent(); if (parent == null) { return x; } else { return x + getX(parent); } } static int getY(final Component component) { final int y = component.getY(); final Component parent = component.getParent(); if (parent == null) { return y; } else { return y + getY(parent); } } static boolean isAltDown(final InputEvent event) { final int modifiersEx = event.getModifiersEx(); final int flag = modifiersEx & InputEvent.ALT_DOWN_MASK; return flag != 0; } static boolean isControlDown(final InputEvent event) { final int modifiersEx = event.getModifiersEx(); final int flag = modifiersEx & InputEvent.CTRL_DOWN_MASK; return flag != 0; } static boolean isControlOrMetaDown(final InputEvent event) { final int modifiersEx = event.getModifiersEx(); final int flag = modifiersEx & (InputEvent.CTRL_DOWN_MASK | InputEvent.META_DOWN_MASK); return flag != 0; } static boolean isEventDispatchThread() { try { return SwingUtilities.isEventDispatchThread(); } catch (final NullPointerException e) { return false; } } /** * Check to see if the event is for the left mouse button and the Alt key is pressed. * Also allows the right mouse button with the control key down. This is so it can * work via Citrix Receiver. * * @param event * @return */ static boolean isLeftButtonAndAltDown(final MouseEvent event) { if (event.getButton() == MouseEvent.BUTTON1) { return isAltDown(event); } else if (event.getButton() == MouseEvent.BUTTON3) { return isControlDown(event); } else { return false; } } static boolean isLeftButtonAndNoModifiers(final MouseEvent event) { final boolean leftMouseButton = SwingUtilities.isLeftMouseButton(event); if (leftMouseButton) { final int modifiers = event.getModifiers(); if (InputEvent.BUTTON1_MASK == modifiers) { return true; } } return false; } static boolean isLeftButtonOnly(final MouseEvent event) { final int modifiers = event.getModifiersEx(); if ((modifiers & InputEvent.BUTTON1_DOWN_MASK) == InputEvent.BUTTON1_DOWN_MASK) { for (int button = 11; button <= 30; button++) { final int mask = 1 << button; if ((modifiers & mask) == mask) { return false; } } return true; } return false; } static boolean isMetaDown(final InputEvent event) { final int modifiersEx = event.getModifiersEx(); final int flag = modifiersEx & InputEvent.META_DOWN_MASK; return flag != 0; } static boolean isMiddleDown(final InputEvent event) { final int modifiersEx = event.getModifiersEx(); final int flag = modifiersEx & InputEvent.BUTTON2_DOWN_MASK; return flag != 0; } static boolean isModifierKeyDown(final InputEvent event) { final int modifiersEx = event.getModifiersEx(); final int flag = modifiersEx & (InputEvent.SHIFT_DOWN_MASK | InputEvent.ALT_DOWN_MASK | InputEvent.ALT_GRAPH_DOWN_MASK | InputEvent.CTRL_DOWN_MASK | InputEvent.META_DOWN_MASK); return flag != 0; } static boolean isRightDown(final InputEvent event) { final int modifiersEx = event.getModifiersEx(); final int flag = modifiersEx & InputEvent.BUTTON3_DOWN_MASK; return flag != 0; } static boolean isScrollReversed() { if (OS.isMac()) { final String[] cmdAttribs = new String[] { "/usr/bin/defaults", "read", System.getProperty("user.home") + "/Library/Preferences/.GlobalPreferences.plist", "com.apple.swipescrolldirection" }; Process process = null; InputStream in = null; OutputStream out = null; InputStream err = null; BufferedReader inr = null; final List<String> lines = new ArrayList<>(); try { process = Runtime.getRuntime().exec(cmdAttribs); in = process.getInputStream(); out = process.getOutputStream(); err = process.getErrorStream(); inr = new BufferedReader(FileUtil.newUtf8Reader(in)); String line = inr.readLine(); while (line != null) { line = line.toLowerCase().trim(); lines.add(line); line = inr.readLine(); } process.waitFor(); if (process.exitValue() == 0) { if (lines.size() == 1) { final String result = lines.get(0); return "1".equals(result); } } } catch (final Throwable e) { } finally { FileUtil.closeSilent(in); FileUtil.closeSilent(out); FileUtil.closeSilent(err); FileUtil.closeSilent(inr); if (process != null) { process.destroy(); } } return true; } return false; } static boolean isShiftDown(final InputEvent event) { final int modifiersEx = event.getModifiersEx(); final int flag = modifiersEx & InputEvent.SHIFT_DOWN_MASK; return flag != 0; } static ComboBox<Identifier> newComboBox(final CodeTable codeTable, final boolean required, final int maxLength) { return newComboBox("fieldValue", codeTable, required, maxLength, false); } static ComboBox<Identifier> newComboBox(final String fieldName, final CodeTable codeTable, final boolean required, final int maxLength, final boolean idSuffix) { if (codeTable == null) { return null; } else { final ComboBox<Identifier> comboBox = CodeTableComboBoxModel.newComboBox(fieldName, codeTable, !required, idSuffix); if (comboBox.getModel().getSize() > 0) { comboBox.setSelectedIndex(0); } int longestLength = -1; for (final Entry<Identifier, List<Object>> codes : codeTable.getCodes().entrySet()) { int length = 0; if (idSuffix) { final Identifier identifier = codes.getKey(); length += identifier.toString().length() + 3; } final List<Object> values = codes.getValue(); if (values != null && !values.isEmpty()) { final String text = Strings.toString(values); length += text.length(); } if (length > longestLength) { longestLength = length; } } if (longestLength == -1) { longestLength = 10; } if (maxLength > 0 && longestLength > maxLength) { longestLength = maxLength; } final StringBuilder value = new StringBuilder(); for (int i = 0; i < longestLength; i++) { value.append("W"); } comboBox.setPrototypeDisplayValue(Identifier.newIdentifier(value)); final ComboBoxEditor editor = comboBox.getEditor(); final Component editorComponent = editor.getEditorComponent(); if (editorComponent instanceof JTextComponent) { final JTextField textComponent = (JTextField)editorComponent; textComponent.setColumns((int)(longestLength * 0.8)); final MenuFactory menu = MenuFactory.getPopupMenuFactory(textComponent); MenuFactory.addToComponent(comboBox, menu); } else { MenuFactory.getPopupMenuFactory(comboBox); } return comboBox; } } static DataFlavor newDataFlavor(final String mimeType) { try { return new DataFlavor(mimeType); } catch (final ClassNotFoundException e) { throw new IllegalArgumentException("Cannot create data flavor for " + mimeType, e); } } static DateField newDateField(final String fieldName) { final DateField dateField = new DateField(fieldName); dateField.setFormats("yyyy-MM-dd", "yyyy/MM/dd", "yyyy-MMM-dd", "yyyy/MMM/dd"); MenuFactory.getPopupMenuFactory(dateField.getEditor()); return dateField; } @SuppressWarnings("unchecked") static <T extends JComponent> T newField(final Class<?> fieldClass, final String fieldName, final Object fieldValue) { JComponent field; if (Number.class.isAssignableFrom(fieldClass)) { final NumberTextField numberTextField = new NumberTextField(fieldName, DataTypes.DOUBLE, 10, 2); if (fieldValue instanceof Number) { final Number number = (Number)fieldValue; numberTextField.setFieldValue(number); } field = numberTextField; } else if (Date.class.isAssignableFrom(fieldClass)) { final DateField dateField = newDateField(fieldName); if (fieldValue instanceof Date) { final Date date = (Date)fieldValue; dateField.setDate(date); } field = dateField; } else if (Geometry.class.isAssignableFrom(fieldClass)) { final ObjectLabelField objectField = new ObjectLabelField(fieldName); objectField.setFieldValue(fieldValue); field = objectField; } else if (Color.class.isAssignableFrom(fieldClass)) { field = new ColorChooserField(fieldName, (Color)fieldValue); } else if (Boolean.class.isAssignableFrom(fieldClass)) { field = new CheckBox(fieldName, fieldValue); } else { final TextField textField = new TextField(fieldName, fieldValue); textField.setColumns(50); MenuFactory.getPopupMenuFactory(textField); field = textField; } if (field instanceof JTextField) { final JTextField textField = (JTextField)field; final int preferedWidth = textField.getPreferredSize().width; textField.setMinimumSize(new Dimension(preferedWidth, 0)); textField.setMaximumSize(new Dimension(preferedWidth, Integer.MAX_VALUE)); textField.setText(DataTypes.toString(fieldValue)); } field.setFont(FONT); return (T)field; } static <T extends JComponent> T newField(final DataType dataType, final String fieldName, final Object fieldValue) { return newField(dataType.getJavaClass(), fieldName, fieldValue); } @SuppressWarnings("unchecked") static <T extends Field> T newField(final RecordDefinition recordDefinition, final String fieldName, final boolean editable) { Field field; final FieldDefinition fieldDefinition = recordDefinition.getField(fieldName); if (fieldDefinition == null) { throw new IllegalArgumentException("Cannot find field " + fieldName); } else { final boolean required = fieldDefinition.isRequired(); final int length = fieldDefinition.getLength(); CodeTable codeTable; if (recordDefinition.getIdFieldNames().contains(fieldName)) { codeTable = null; } else { codeTable = recordDefinition.getCodeTableByFieldName(fieldName); } final DataType type = fieldDefinition.getDataType(); int columns = length; if (columns <= 0) { columns = 10; } else if (columns > 50) { columns = 50; } final Class<?> javaClass = type.getJavaClass(); if (codeTable != null) { if (editable) { final JComponent component = codeTable.getSwingEditor(); if (component == null) { field = newComboBox(fieldName, codeTable, required, -1, false); } else { field = ((Field)component).clone(); } } else { field = new ObjectLabelField(fieldName, columns, codeTable); } } else if (!editable) { final TextField textField = newTextField(fieldName, columns); textField.setEditable(false); field = textField; } else if (Number.class.isAssignableFrom(javaClass)) { final int scale = fieldDefinition.getScale(); final Number minValue = fieldDefinition.getMinValue(); final Number maxValue = fieldDefinition.getMaxValue(); final NumberTextField numberTextField = new NumberTextField(fieldName, type, length, scale, minValue, maxValue); field = numberTextField; } else if (Date.class.isAssignableFrom(javaClass)) { field = newDateField(fieldName); } else if (Geometry.class.isAssignableFrom(javaClass)) { field = new ObjectLabelField(fieldName); } else { field = newTextField(fieldName, columns); } } if (field instanceof JTextField) { final JTextField textField = (JTextField)field; final int preferedWidth = textField.getPreferredSize().width; textField.setMinimumSize(new Dimension(preferedWidth, 0)); textField.setMaximumSize(new Dimension(preferedWidth, Integer.MAX_VALUE)); } ((JComponent)field).setFont(FONT); return (T)field; } static JFileChooser newFileChooser(final Class<?> preferencesClass, final String preferenceName) { final JFileChooser fileChooser = new JFileChooser(); fileChooser.setDialogTitle("Open File"); final String currentDirectoryName = PreferencesUtil.getString(preferencesClass, preferenceName); if (Property.hasValue(currentDirectoryName)) { File directory = new File(currentDirectoryName); while (directory != null && (!directory.exists() || !directory.canRead())) { directory = directory.getParentFile(); } if (directory != null && directory.exists() && directory.canRead()) { fileChooser.setCurrentDirectory(directory); } } return fileChooser; } static JFileChooser newFileChooser(final String title, final String preferencesGroup, final String preferenceName) { final JFileChooser fileChooser = new JFileChooser(); fileChooser.setDialogTitle(title); final String currentDirectoryName = PreferencesUtil.getUserString(preferencesGroup, preferenceName); if (Property.hasValue(currentDirectoryName)) { final File directory = new File(currentDirectoryName); if (directory.exists() && directory.canRead()) { fileChooser.setCurrentDirectory(directory); } } return fileChooser; } static JLabel newLabel(final String text) { final JLabel label = new JLabel(text); label.setFont(BOLD_FONT); return label; } static TextArea newTextArea(final int rows, final int columns) { final TextArea textField = new TextArea(rows, columns); return textField; } static TextArea newTextArea(final String fieldName, final int rows, final int columns) { final TextArea textField = new TextArea(fieldName, rows, columns); return textField; } static TextField newTextField(final int columns) { final TextField textField = new TextField(columns); return textField; } static TextField newTextField(final String fieldName, final int columns) { final TextField textField = new TextField(fieldName, columns); return textField; } static void saveFileChooserDirectory(final Class<?> preferencesClass, final String preferenceName, final JFileChooser fileChooser) { final File currentDirectory = fileChooser.getCurrentDirectory(); final String path = FileUtil.getCanonicalPath(currentDirectory); PreferencesUtil.setString(preferencesClass, preferenceName, path); } static void setDescendantsEnabled(final Component component, final boolean enabled) { if (component != null) { component.setEnabled(enabled); if (component instanceof Container) { final Container container = (Container)component; for (final Component child : container.getComponents()) { setDescendantsEnabled(child, enabled); } } } } static void setFieldValue(final JComponent field, final Object value) { Invoke.later(() -> { if (field instanceof Field) { final Field fieldObject = (Field)field; fieldObject.setFieldValue(value); } else if (field instanceof JLabel) { final JLabel label = (JLabel)field; String string; if (value == null) { string = ""; } else { string = DataTypes.toString(value); } label.setText(string); } else if (field instanceof JTextField) { final JTextField textField = (JTextField)field; String string; if (value == null) { string = ""; } else { string = DataTypes.toString(value); } textField.setText(string); } else if (field instanceof JTextArea) { final JTextArea textField = (JTextArea)field; String string; if (value == null) { string = ""; } else { string = DataTypes.toString(value); } textField.setText(string); } final Container parent = field.getParent(); if (parent != null) { final LayoutManager layout = parent.getLayout(); if (layout != null) { layout.layoutContainer(parent); } field.revalidate(); } }); } static void setLocationCentre(final Rectangle bounds, final Window window) { final int width = window.getWidth(); final int height = window.getHeight(); final int x = bounds.x + (bounds.width - width) / 2; final int y = bounds.y + (bounds.height - height) / 2; window.setLocation(x, y); } static void setLocationCentre(final Window window) { final Rectangle bounds = getScreenBounds(); setLocationCentre(bounds, window); } /** * Set the location of the window in relation to the top left of the screen the current window is on * * @param window * @param x * @param y */ static void setLocationOffset(final Window window, int x, int y) { final Rectangle bounds = getScreenBounds(); x += bounds.x; y += bounds.y; window.setLocation(x, y); } static void setMaximumWidth(final JComponent component, final int width) { final Dimension preferredSize = component.getPreferredSize(); final Dimension size = new Dimension(width, preferredSize.height); component.setMaximumSize(size); } static void setSize(final Window window, final int minusX, final int minusY) { final Toolkit toolkit = Toolkit.getDefaultToolkit(); final Dimension screenSize = toolkit.getScreenSize(); final double screenWidth = screenSize.getWidth(); final double screenHeight = screenSize.getHeight(); final Dimension size = new Dimension((int)(screenWidth - minusX), (int)(screenHeight - minusY)); window.setBounds(minusX / 2, minusY / 2, size.width, size.height); window.setPreferredSize(size); } static void setSizeAndMaximize(final JFrame frame, final int minusX, final int minusY) { final Rectangle bounds = getScreenBounds((Point)null); final Dimension size = new Dimension(bounds.width - minusX, bounds.height - minusY); frame.setPreferredSize(size); frame.pack(); frame.setExtendedState(Frame.MAXIMIZED_BOTH); frame.setState(Frame.MAXIMIZED_BOTH); setLocationCentre(bounds, frame); } static void setSplashTitle(final String title) { final SplashScreen splash = SplashScreen.getSplashScreen(); if (splash != null) { final Graphics2D graphics = splash.createGraphics(); if (graphics != null) { graphics.setColor(WebColors.Black); graphics.setFont(new Font("sans-serif", Font.BOLD, 14)); graphics.drawString("Starting application: ", 100, 100); graphics.setFont(new Font("sans-serif", Font.PLAIN, 12)); graphics.drawString(title, 100, 130); splash.update(); } } } static void setTitledBorder(final JComponent component, final String title) { if (component != null) { final TitledBorder border = new TitledBorder(title); component.setBorder(border); component.setBackground(WebColors.White); } } static void setVisible(final Component component, final boolean visible) { if (component != null) { Invoke.later(() -> { component.setVisible(visible); }); } } static void showErrorDialog(final Window window, final String title, final String message, final Throwable e) { final String exceptionMessage = e.getMessage().replaceAll("\n", "<br />"); final String errorMessage = "<html><body><p style=\"margin-bottom: 10px\"><strong>" + message + "</strong></p><pre>" + exceptionMessage + "</pre></body></p>"; final JScrollPane scrollPane = new JScrollPane(new JLabel(errorMessage)); final Dimension preferredSize = scrollPane.getPreferredSize(); final Rectangle bounds = SwingUtil.getScreenBounds(window); final int width = Math.min(bounds.width - 200, preferredSize.width + 20); final int height = Math.min(bounds.height - 100, preferredSize.height + 20); scrollPane.setPreferredSize(new Dimension(width, height)); JOptionPane.showMessageDialog(window, scrollPane, title, JOptionPane.ERROR_MESSAGE); } }