All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.nuiton.jaxx.runtime.swing.SwingUtil Maven / Gradle / Ivy

The newest version!
/*
 * #%L
 * JAXX :: Runtime
 * %%
 * Copyright (C) 2008 - 2024 Code Lutin, Ultreia.io
 * %%
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details.
 *
 * You should have received a copy of the GNU General Lesser Public
 * License along with this program.  If not, see
 * .
 * #L%
 */
package org.nuiton.jaxx.runtime.swing;

import com.google.common.collect.ImmutableSet;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.jdesktop.jxlayer.JXLayer;
import org.jdesktop.jxlayer.plaf.LayerUI;
import org.jdesktop.swingx.JXTreeTable;
import org.nuiton.jaxx.runtime.JAXXObject;
import org.nuiton.jaxx.runtime.JAXXUtil;
import org.nuiton.jaxx.runtime.swing.editor.BooleanCellEditor;
import org.nuiton.jaxx.runtime.swing.model.JaxxDefaultComboBoxModel;
import org.nuiton.jaxx.runtime.swing.model.JaxxDefaultListModel;
import org.nuiton.jaxx.runtime.swing.renderer.BooleanCellRenderer;
import org.nuiton.jaxx.runtime.swing.renderer.EmptyNumberTableCellRenderer;
import org.nuiton.jaxx.runtime.swing.renderer.EnumTableCellRenderer;
import org.nuiton.jaxx.runtime.swing.renderer.I18nTableCellRenderer;

import javax.swing.ComboBoxModel;
import javax.swing.DefaultComboBoxModel;
import javax.swing.DefaultListModel;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JEditorPane;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JRootPane;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.JTree;
import javax.swing.KeyStroke;
import javax.swing.ListModel;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.HyperlinkEvent;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Desktop;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Frame;
import java.awt.Rectangle;
import java.awt.event.KeyEvent;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.EventObject;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.Properties;
import java.util.function.Consumer;
import java.util.function.Predicate;

/**
 * The runtime swing util class with some nice stuff.
 * 

* Note : Replace previous class jaxx.runtime.swing.Utils in previous versions. * * @author Tony Chemit - [email protected] * @since 1.2 */ public class SwingUtil extends JAXXUtil { public static final String DEFAULT_ICON_PATH = "/icons/"; public static final String DEFAULT_ICON_PATH_PROPERTY = "default.icon.path"; public static final String ICON_PREFIX = "icon."; public static final String COLOR_PREFIX = "color."; /** * Pattern to use for short numeric values in editors with max 3 digits. * * @since 4.0 */ public static final String INT_3_DIGITS_PATTERN = "\\d{0,3}"; /** * Pattern to use for short numeric values in editors with max 4 digits. * * @since 3.0 */ public static final String INT_4_DIGITS_PATTERN = "\\d{0,4}"; /** * Pattern to use for integer numeric values in editors with max 6 digits. * * @since 4.0 */ public static final String INT_6_DIGITS_PATTERN = "\\d{0,6}"; /** * Pattern to use for integer numeric values in editors with max 7 digits. * * @since 4.0 */ public static final String INT_7_DIGITS_PATTERN = "\\d{0,7}"; /** * Pattern to use for long numeric values in editors with max 10 digits. * * @since 4.0 */ public static final String LONG_10_DIGITS_PATTERN = "\\d{0,10}"; /** * Pattern to use for decimal numeric values with 1 decimal digits in editors. * * @since 4.0 */ public static final String DECIMAL1_PATTERN = "\\d{0,6}|\\d{1,6}\\.\\d{0,1}"; /** * Pattern to use for decimal numeric values with 2 decimal digits in editors. * * @since 4.0 */ public static final String DECIMAL2_PATTERN = "\\d{0,6}|\\d{1,6}\\.\\d{0,2}"; /** * Pattern to use for decimal numeric values with 3 decimal digits in editors. * * @since 4.0 */ public static final String DECIMAL3_PATTERN = "\\d{0,6}|\\d{1,6}\\.\\d{0,3}"; /** * Pattern to use for decimal numeric values with 4 decimal digits in editors. * * @since 4.0 */ public static final String DECIMAL4_PATTERN = "\\d{0,6}|\\d{1,6}\\.\\d{0,4}"; /** * Pattern to use for long numeric values in editors with max 3 digits. * * @since 4.0 */ public static final String LONG_3_DIGITS_PATTERN = "\\d{0,3}"; static private final Logger log = LogManager.getLogger(SwingUtil.class); private static final ImmutableSet OPEN_PROTOCOLS = ImmutableSet.of("mailto", "http", "https", "ftp", "file"); /** * A simple iterator on a {@link JTabbedPane}. *

* Implements the method {@link #get(int, Component)} to obtain * the data required given the component (or index). *

* You can also inverse the order by usin the method {@link #reverse()}. *

* Note: After the use of the method {@link #reverse()} the iterator returns * to the first element. * * @param the type of return elements. * @since 1.4 */ public static abstract class TabbedPaneIterator implements Iterator { final JTabbedPane tabs; boolean reverse; int index; int increment; public TabbedPaneIterator(boolean reverse, JTabbedPane tabs) { this.tabs = tabs; setReverse(reverse); } protected abstract O get(int index, Component comp); public void reset() { setReverse(reverse); } public int size() { return tabs.getTabCount(); } public TabbedPaneIterator reverse() { setReverse(!reverse); return this; } @Override public boolean hasNext() { return reverse ? index > 0 : index < tabs.getTabCount(); } public int getIndex() { return index; } @Override public O next() { if (!hasNext()) { throw new NoSuchElementException(); } Component next = tabs.getComponentAt(index); O result = get(index, next); index += increment; return result; } @Override public void remove() { throw new IllegalStateException("not implemented for " + this); } @Override public String toString() { return super.toString() + "< reverse:" + reverse + ", index:" + index + ", size:" + tabs.getTabCount() + " >"; } protected void setReverse(boolean reverse) { if (reverse) { index = tabs.getTabCount() - 1; increment = -1; } else { index = 0; increment = 1; } this.reverse = reverse; } } public static Dimension newMinDimension() { return new Dimension(0, 0); } public static Dimension newMaxXDimension() { return new Dimension(Short.MAX_VALUE, 0); } public static Dimension newMaxYDimension() { return new Dimension(0, Short.MAX_VALUE); } public static Dimension newMaxXYDimension() { return new Dimension(Short.MAX_VALUE, Short.MAX_VALUE); } /** * Fill a combo box model with some datas, and select after all the given object * * @param combo the combo to fill * @param data data ot inject in combo * @param select the object to select in combo after reflling his model */ public static void fillComboBox(JComboBox combo, Collection data, Object select) { ComboBoxModel comboBoxModel = combo.getModel(); if (comboBoxModel instanceof JaxxDefaultComboBoxModel) { JaxxDefaultComboBoxModel model = (JaxxDefaultComboBoxModel) comboBoxModel; // evince the model model.removeListDataListener(combo); // set data model.setAllElements(data); // attach the model model.addListDataListener(combo); model.setSelectedItem(select); } else if (comboBoxModel instanceof DefaultComboBoxModel) { DefaultComboBoxModel model = (DefaultComboBoxModel) combo.getModel(); // evince the model model.removeListDataListener(combo); model.removeAllElements(); if (data != null) { for (Object o : data) { model.addElement(o); } } // attach the model model.addListDataListener(combo); model.setSelectedItem(select); } else { throw new IllegalArgumentException( "this method need a DefaultComboBoxModel for " + "this model but was " + combo.getModel().getClass()); } } /** * Fill a list model with some datas, and select after all the given object * * @param list the list to fill * @param data data ot inject in combo * @param select the object to select in combo after reflling his model */ public static void fillList(JList list, Collection data, Object select) { ListModel listModel = list.getModel(); if (listModel instanceof JaxxDefaultListModel) { JaxxDefaultListModel model = (JaxxDefaultListModel) listModel; // evince the model // model.removeListDataListener(combo); model.setAllElements(data); // attach the model // model.addListDataListener(combo); list.setSelectedValue(select, true); } else if (listModel instanceof DefaultListModel) { DefaultListModel model = (DefaultListModel) listModel; // evince the model // model.removeListDataListener(combo); model.removeAllElements(); if (data != null) { for (Object o : data) { model.addElement(o); } } // attach the model // model.addListDataListener(combo); list.setSelectedValue(select, true); } else { throw new IllegalArgumentException( "this method need a DefaultListModel for this model " + "but was " + listModel.getClass()); } } /** * TODO move this to JAXXComboBox. *

* Fill a combo box model with some datas, and select after all the given object * * @param combo the combo to fill * @param data data ot inject in combo * @param select the object to select in combo after reflling his model * @param firstNull add a first null element * @deprecated since 1.7.XXX this code is moved to JAXXComboBox */ @Deprecated public static void fillComboBox(JAXXComboBox combo, Collection data, Object select, boolean firstNull) { List items = new ArrayList<>(); if (firstNull) { items.add(new Item("null", " ", null, false)); } if (data != null) { for (Object d : data) { Item item = new Item(d.toString(), d.toString(), d, d.equals(select)); items.add(item); } } combo.setItems(items); } /** * Return parent's container corresponding to the Class clazz * * @param type of container to obtain from context * @param top the top container * @param clazz desired * @return parent's container */ @SuppressWarnings({"unchecked"}) public static O getParentContainer(Object top, Class clazz) { return getParent(top, clazz); } /** * Find a parent of the given {@code top} object using the container api to get up. *

* Stop on parent when it is of the given{@code clazz} type. * * @param type of container to obtain from context * @param top the top container * @param clazz desired * @return parent's container * @since 2.5.14 */ public static O getParent(Object top, Class clazz) { if (top == null) { throw new IllegalArgumentException("top parameter can not be null"); } if (!Container.class.isAssignableFrom(top.getClass())) { throw new IllegalArgumentException("top parameter " + top + " is not a " + Container.class); } Container parent = ((Container) top).getParent(); if (parent != null && !clazz.isAssignableFrom(parent.getClass())) { parent = (Container) getParent(parent, clazz); } return (O) parent; } public static int computeTableColumnWidth(JTable table, Font font, int columnIndex, String suffix) { int width = 0; if (font == null) { font = table.getFont(); } // if (font == null) { // TableColumn column = table.getColumnModel().getColumn(columnIndex); // font = ((JComponent) column.getCellRenderer()).getFont(); // } FontMetrics fontMetrics = table.getFontMetrics(font); for (int i = 0, rowCount = table.getRowCount(); i < rowCount; i++) { String key = (String) table.getModel().getValueAt(i, 0); int w = fontMetrics.stringWidth(key + suffix); if (w > width) { width = w; } } return width; } public static void fixTableColumnWidth(JTable table, int columnIndex, int width) { TableColumn column = table.getColumnModel().getColumn(columnIndex); column.setMaxWidth(width); column.setMinWidth(width); column.setWidth(width); column.setPreferredWidth(width); } public static void setTableColumnEditor(JTable table, int columnIndex, TableCellEditor editor) { TableColumn column = table.getColumnModel().getColumn(columnIndex); column.setCellEditor(editor); } public static void setTableColumnRenderer(JTable table, int columnIndex, TableCellRenderer editor) { TableColumn column = table.getColumnModel().getColumn(columnIndex); column.setCellRenderer(editor); } public static void setI18nTableHeaderRenderer(JTable table, String... libelles) { I18nTableCellRenderer defaultRenderer = new I18nTableCellRenderer( table.getTableHeader().getDefaultRenderer(), libelles); table.getTableHeader().setDefaultRenderer(defaultRenderer); } public static TableCellRenderer newStringTableCellRenderer( final DefaultTableCellRenderer renderer, final int length, final boolean tooltip) { return new DefaultTableCellRenderer() { private static final long serialVersionUID = 1L; @Override public Component getTableCellRendererComponent( JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { renderer.getTableCellRendererComponent( table, value, isSelected, hasFocus, row, column ); String val = renderer.getText(); String val2 = val; if (val.length() > length) { val2 = val.substring(0, length - 3) + "..."; } JComponent comp = (JComponent) super.getTableCellRendererComponent( table, val2, isSelected, hasFocus, row, column ); if (tooltip) { comp.setToolTipText(val); } return comp; } }; } /** * Box a component in a {@link JXLayer}. * * @param component the component to box * @return the {@link JXLayer} boxing the component */ public static JXLayer boxComponentWithJxLayer(V component) { JXLayer layer = getLayer(component); if (layer != null) { return layer; } layer = new JXLayer<>(); layer.setView(component); return layer; } public static List getLayeredComponents(JAXXObject object) { List result = new ArrayList<>(); for (Entry child : object.get$objectMap().entrySet()) { if (child.getValue() == null) { log.warn("find a null object in $objectMap " + child.getKey()); continue; } if (JComponent.class.isAssignableFrom(child.getValue().getClass())) { JComponent comp = (JComponent) child.getValue(); if (isLayered(comp)) { result.add(comp); } } } return result; } public static JXLayer getLayer(V comp) { if (!isLayered(comp)) { return null; } return (JXLayer) comp.getParent(); } public static void setLayerUI(JComponent comp, LayerUI ui) { JXLayer layer = getLayer(comp); layer.setUI(ui); } public static boolean isLayered(JComponent comp) { Container parent = comp.getParent(); return parent != null && parent instanceof JXLayer; } /** * recherche les composants portant le meme nom que les champs de la classe * clazz. Cette methode est statique pour pouvoir eventuellement l'utiliser * dans un autre context (je pense par exemple a la generation jaxx). *

* Si la recherche echoue pour quelque raison que se soit, aucune exception * n'est leve, et la map retournee est tout simplement vide ou incomplete * * @param clazz la classe ou recherche les champs * @param container le container ou rechercher les composants d'edition * @return le dictionnaire des composants recherches. */ public static Map lookingForEditor( Class clazz, Container container) { Map result = new HashMap<>(); try { // looking for all component with name set Map allNamedComponent = new HashMap<>(); List todo = new LinkedList<>(); todo.add(container); while (todo.size() > 0) { for (ListIterator i = todo.listIterator(); i.hasNext(); ) { Container parent = i.next(); i.remove(); for (Component c : parent.getComponents()) { if (c instanceof Container) { i.add((Container) c); String name = c.getName(); if (c instanceof JComponent && name != null && !"".equals(name)) { allNamedComponent.put(name, (JComponent) c); } } } } } // looking for all properties on class BeanInfo info = Introspector.getBeanInfo(clazz); PropertyDescriptor[] props = info.getPropertyDescriptors(); // find if one properties have same name that component for (PropertyDescriptor prop : props) { String name = prop.getName(); if (allNamedComponent.containsKey(name)) { result.put(name, allNamedComponent.get(name)); } } } catch (IntrospectionException eee) { log.warn("Can't introspect bean", eee); } if (log.isDebugEnabled()) { log.debug("Result: " + result); } return result; } /** * Centrer un component graphique au center d'un autre component. *

* Note: si le parent est null, alors on ne fait rien. * * @param parent le component parent * @param component le component à centrer */ public static void center(Component parent, Component component) { if (parent == null) { return; } Rectangle r = parent.getBounds(); int x = r.x + (r.width - component.getSize().width) / 2; int y = r.y + (r.height - component.getSize().height) / 2; component.setLocation(x, y); } /** * Try to load the Nimbus look and feel. * * @throws UnsupportedLookAndFeelException if nimbus is not applicable * @throws ClassNotFoundException * @throws InstantiationException * @throws IllegalAccessException */ public static void initNimbusLoookAndFeel() throws UnsupportedLookAndFeelException, ClassNotFoundException, InstantiationException, IllegalAccessException { for (UIManager.LookAndFeelInfo laf : UIManager.getInstalledLookAndFeels()) { if ("Nimbus".equals(laf.getName())) { UIManager.setLookAndFeel(laf.getClassName()); } } } /** * Load the ui.properties file and set in {@link UIManager} colors and * icons found. * * @param defaultUIConfig le path vers le fichier de la config d'ui par * défaut (doit etre dansle class-path) * @param extraUIConfig le path vers une surcharge de la config d'ui * (doit etre dans le class-path) * @throws IOException if could not load the ui.properties file */ public static void loadUIConfig(String defaultUIConfig, String extraUIConfig) throws IOException { Properties p = new Properties(); log.info("loading default UI config " + defaultUIConfig); p.load(SwingUtil.class.getResourceAsStream(defaultUIConfig)); if (log.isDebugEnabled()) { log.debug(p.toString()); } if (extraUIConfig != null) { InputStream extraStream = SwingUtil.class.getResourceAsStream(extraUIConfig); if (extraStream == null) { log.warn("could not find extraUIConfig : " + extraUIConfig); } else { log.info("loading extra UI config " + extraUIConfig); Properties p2 = new Properties(p); p2.load(extraStream); if (log.isDebugEnabled()) { log.debug(p2.toString()); } p.putAll(p2); } } for (Entry entry : p.entrySet()) { String key = (String) entry.getKey(); if (key.startsWith(ICON_PREFIX)) { ImageIcon icon; try { icon = createImageIcon((String) entry.getValue()); UIManager.put(key.substring(ICON_PREFIX.length()), icon); } catch (Exception e) { log.warn("could not load icon " + entry.getValue()); } continue; } if (key.startsWith(COLOR_PREFIX)) { String value = (String) entry.getValue(); String[] rgb = value.split(","); UIManager.put( key.substring(COLOR_PREFIX.length()), new Color( Integer.parseInt(rgb[0]), Integer.parseInt(rgb[1]), Integer.parseInt(rgb[2]) ) ); } } } /** * Load the ui.properties file and set in {@link UIManager} colors and * icons found. * * @param incoming the ui resources to load. * @param extraEntryConsumer extra entry consumer. * @since 3.0.7 */ public static void loadUIConfig(Properties incoming, Consumer> extraEntryConsumer) { for (Entry entry : incoming.entrySet()) { String key = (String) entry.getKey(); if (key.startsWith(ICON_PREFIX)) { ImageIcon icon; try { icon = createImageIcon((String) entry.getValue()); UIManager.put(key.substring(ICON_PREFIX.length()), icon); } catch (Exception e) { log.warn("could not load icon " + entry.getValue()); } } else if (key.startsWith(COLOR_PREFIX)) { String value = (String) entry.getValue(); String[] rgb = value.split(","); UIManager.put( key.substring(COLOR_PREFIX.length()), new Color( Integer.parseInt(rgb[0]), Integer.parseInt(rgb[1]), Integer.parseInt(rgb[2]) ) ); } if (extraEntryConsumer!=null) { extraEntryConsumer.accept(entry); } } } /** * Load the ui.properties file and set in {@link UIManager} colors and * icons found. * * @param incoming the ui resources to load. * @since 2.1 */ public static void loadUIConfig(Properties incoming) { loadUIConfig(incoming, null); } /** * Iterate the components of a {@link JTabbedPane} in natural order. *

* Says using method {@link JTabbedPane#getComponent(int)} * * @param tabs the * @return the iterator * @since 1.4 */ public static TabbedPaneIterator newTabbedPaneIterator( JTabbedPane tabs) { return new TabbedPaneIterator(false, tabs) { @Override protected Component get(int index, Component comp) { return comp; } }; } /** * Return the selected rows of the table in the model coordinate or empty * array if selection is empty. * * @param table the table to seek * @return the selected rows of the table in the model coordinate or empty * array if selection is empty. * @since 2.5.29 */ public static int[] getSelectedModelRows(JTable table) { int[] selectedRows = table.getSelectedRows(); int length = selectedRows.length; int[] result = new int[length]; for (int i = 0; i < length; i++) { int selectedRow = selectedRows[i]; result[i] = table.convertRowIndexToModel(selectedRow); } return result; } /** * Return the selected row of the table in the model coordinate or * {@code -1} if selection is empty. * * @param table the table to seek * @return the selected row of the table in the model coordinate or * {@code -1} if selection is empty. * @since 2.5.29 */ public static int getSelectedModelRow(JTable table) { int result = table.getSelectedRow(); if (result != -1) { // can convert to model coordinate result = table.convertRowIndexToModel(result); } return result; } /** * Return the selected column of the table in the model coordinate or * {@code -1} if selection is empty. * * @param table the table to seek * @return the selected column of the table in the model coordinate or * {@code -1} if selection is empty. * @since 2.5.29 */ public static int getSelectedModelColumn(JTable table) { int result = table.getSelectedColumn(); if (result != -1) { // can convert to model coordinate result = table.convertColumnIndexToModel(result); } return result; } /** * Select the given row index {@code rowIndex} (from the model coordinate) * in the selection of the given table. * * @param table the table where to set the selection * @param rowIndex the row index in the model coordinate to set as selection * @since 2.5.29 */ public static void setSelectionInterval(JTable table, int rowIndex) { int rowViewIndex = table.convertRowIndexToView(rowIndex); table.getSelectionModel().setSelectionInterval(rowViewIndex, rowViewIndex); } /** * Add the given row index {@code rowIndex} (from the model coordinate) * in the selection of the given table. * * @param table the table where to set the selection * @param rowIndex the row index in the model coordinate to add to selection * @since 2.5.29 */ public static void addRowSelectionInterval(JTable table, int rowIndex) { int rowViewIndex = table.convertRowIndexToView(rowIndex); table.getSelectionModel().addSelectionInterval(rowViewIndex, rowViewIndex); } public static void displayInfo(Component ui, String title, String text) { JOptionPanes.displayInfo(ui, title, text); } public static void displayWarning(Component ui, String title, String text) { JOptionPanes.displayWarning(ui, title, text); } public static int askUser(Component ui, String title, String message, int typeMessage, Object[] options, int defaultOption) { return JOptionPanes.askUser(ui, title, message, typeMessage, options, defaultOption); } public static int askUser(Component ui, String title, Object message, int typeMessage, Object[] options, int defaultOption) { return JOptionPanes.askUser(ui, title, message, typeMessage, options, defaultOption); } public static int askUser(Frame ui, JOptionPane pane, String title, Object[] options) { return JOptionPanes.askUser(ui, pane, title, options); } public static KeyStroke findKeyStroke(String name, String defaultValue) { String keyStrokeStr = UIManager.getDefaults().getString(name); if (keyStrokeStr == null) { keyStrokeStr = defaultValue; } return KeyStroke.getKeyStroke(keyStrokeStr); } public static String keyStrokeToStr(KeyStroke actionKey) { String result = ""; if (actionKey != null) { result = " (" + getAccText(actionKey) + ")"; } return result; } public static String getAccText(KeyStroke actionKey) { String result = ""; Objects.requireNonNull(actionKey); int var4 = actionKey.getModifiers(); if (var4 > 0) { result = KeyEvent.getKeyModifiersText(var4) + " + "; } int var5 = actionKey.getKeyCode(); if (var5 != 0) { result = result + KeyEvent.getKeyText(var5); } else { result = result + actionKey.getKeyChar(); } return result; } public static JLabel newLabel(String text, Object iconKey, int aligment) { Icon icon = null; if (iconKey instanceof Icon) { icon = (Icon) iconKey; } else if (iconKey instanceof String) { icon = getUIManagerActionIcon((String) iconKey); } JLabel result; if (icon == null) { result = new JLabel(text, aligment); } else { result = new JLabel(text, icon, aligment); } return result; } /** * Gets the higest visible component in a ancestor hierarchy at * specific x,y coordinates * * @param parent * @param x * @param y * @return the deppest component */ public static Component getDeepestObjectAt(Component parent, int x, int y) { if (parent instanceof Container) { Container cont = (Container) parent; // use a copy of 1.3 Container.findComponentAt Component child = findComponentAt(cont, cont.getWidth(), cont.getHeight(), x, y); if (child != null && child != cont) { //log.info("child find : " + child.getName()); if (child instanceof JRootPane) { JLayeredPane lp = ((JRootPane) child).getLayeredPane(); Rectangle b = lp.getBounds(); child = getDeepestObjectAt(lp, x - b.x, y - b.y); } if (child != null) { return child; } } } // if the parent is not a Container then it might be a MenuItem. // But even if it isn't a MenuItem just return the parent because // that's a close as we can come. return parent; } public static Component findComponentAt(Container cont, int width, int height, int x, int y) { //log.info("container : " + cont.getName()); synchronized (cont.getTreeLock()) { if (!(x >= 0 && x < width && y >= 0 && y < height && cont.isVisible() && cont.isEnabled())) { return null; } Component[] component = cont.getComponents(); int ncomponents = cont.getComponentCount(); // Two passes: see comment in sun.awt.SunGraphicsCallback for (int i = 0; i < ncomponents; i++) { Component comp = component[i]; Rectangle rect = null; if (comp != null && !comp.isLightweight()) { if (rect == null || rect.width == 0 || rect.height == 0) { rect = comp.getBounds(); } if (comp instanceof JXLayer) { JXLayer layer = (JXLayer) comp; comp = layer.getView(); } if (comp instanceof Container) { comp = findComponentAt( (Container) comp, rect.width, rect.height, x - rect.x, y - rect.y ); } else { comp = comp.getComponentAt(x - rect.x, y - rect.y); } if (comp != null && comp.isVisible() && comp.isEnabled()) { return comp; } } } for (int i = 0; i < ncomponents; i++) { Component comp = component[i]; Rectangle rect = null; if (comp != null && comp.isLightweight()) { if (rect == null || rect.width == 0 || rect.height == 0) { rect = comp.getBounds(); } if (comp instanceof JXLayer) { JXLayer layer = (JXLayer) comp; comp = layer.getView(); } if (comp instanceof Container) { comp = findComponentAt( (Container) comp, rect.width, rect.height, x - rect.x, y - rect.y ); } else { comp = comp.getComponentAt(x - rect.x, y - rect.y); } if (comp != null && comp.isVisible() && comp.isEnabled()) { return comp; } } } return cont; } } public static TableCellRenderer newDeleteCellRenderer( DefaultTableCellRenderer renderer) { Icon icon = UIManager.getIcon("Table.removeIcon"); if (icon == null) { // try with default icon icon = createActionIcon("delete"); } return new BooleanCellEditor(renderer, icon); } public static TableCellRenderer newBooleanTableCellRenderer( TableCellRenderer renderer) { return new BooleanCellRenderer(renderer); } public static TableCellRenderer newBooleanTableCellRenderer( TableCellRenderer renderer, Predicate predicate) { return new BooleanCellRenderer(renderer, predicate); } public static TableCellRenderer newBooleanTableCellEditorAndRenderer( TableCellRenderer renderer) { return new BooleanCellEditor(renderer); } public static BooleanCellEditor newBooleanTableCellEditor( TableCellRenderer renderer) { return new BooleanCellEditor(renderer); } public static EmptyNumberTableCellRenderer newEmptyNumberTableCellRenderer( TableCellRenderer renderer) { return new EmptyNumberTableCellRenderer(renderer); } public static > EnumTableCellRenderer newEnumTableCellRenderer(TableCellRenderer renderer, Class enumClass) { return new EnumTableCellRenderer<>(renderer, enumClass); } /** * Open a link coming from a {@link HyperlinkEvent}. *

* And try to open the link if an url in a browser. * * @param he the event to treate * @since 1.6.0 */ public static void openLink(HyperlinkEvent he) { if (he.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { URL u = he.getURL(); if (u == null) { // may be follow an anchor String description = he.getDescription(); if (description != null && description.startsWith("#")) { Object source = he.getSource(); if (source instanceof JEditorPane) { String anchorName = description.substring(1); ((JEditorPane) source).scrollToReference(anchorName); } } return; } if (Desktop.isDesktopSupported()) { try { if (OPEN_PROTOCOLS.contains(u.getProtocol().toLowerCase())) { Desktop.getDesktop().browse(u.toURI()); } } catch (IOException | URISyntaxException e) { if (log.isErrorEnabled()) { log.error("Error while opening link", e); } } } } } public static void openLink(String url) { try { if (!Desktop.isDesktopSupported()) { throw new IllegalStateException("Desktop not accessible"); } Desktop desktop = Desktop.getDesktop(); if (!desktop.isSupported(Desktop.Action.BROWSE)) { throw new IllegalStateException("Action 'Go' not supported by desktop"); } URI uri = new URI(url); desktop.browse(uri); } catch (Exception e) { if (log.isErrorEnabled()) { log.error("Error while opening link", e); } } } /** * Expand all childs of a tree. * * @param tree the tree to expand */ public static void expandTree(final JTree tree) { SwingUtilities.invokeLater(() -> { int i = 0; while (i < tree.getRowCount()) { tree.expandRow(i++); } }); } /** * Expand all childs of a tree table. *

* FIXME : Voir pour enlever le copier coller * * @param treeTable the tree to expand */ public static void expandTreeTable(final JXTreeTable treeTable) { SwingUtilities.invokeLater(() -> { int i = 0; while (i < treeTable.getRowCount()) { treeTable.expandRow(i++); } }); } /** * Add a listener of tree selection model to expand a new selected node * when it is selected. * * @param tree the tree to treate */ public static void addExpandOnClickListener(final JTree tree) { tree.getSelectionModel().addTreeSelectionListener( e -> { TreeNode node = (TreeNode) e.getPath().getLastPathComponent(); if (node != null && !node.isLeaf()) { SwingUtilities.invokeLater(() -> { for (TreePath path : e.getPaths()) { if (e.isAddedPath(path) && !tree.isExpanded(path)) { log.info("expand node [" + path + "]"); // will expand the node tree.expandPath(path); } } }); } }); } /** * Add a listener of tree table selection model to expand a new selected * node when it is selected. *

* FIXME : Voir pour enlever le copier coller * * @param treeTable the tree to treate */ public static void addExpandOnClickListener(final JXTreeTable treeTable) { treeTable.addTreeSelectionListener(e -> { TreeNode node = (TreeNode) e.getPath().getLastPathComponent(); if (node != null && !node.isLeaf()) { SwingUtilities.invokeLater(() -> { for (TreePath path : e.getPaths()) { if (e.isAddedPath(path) && !treeTable.isExpanded(path)) { log.info("expand node [" + path + "]"); // will expand the node treeTable.expandPath(path); } } }); } }); } /** * Set the width of the given component * * @param component the component to resize * @param width the new width to apply */ public static void setComponentWidth(Component component, int width) { component.setSize(width, component.getHeight()); if (component instanceof JComponent) { JComponent jcomponent = (JComponent) component; jcomponent.setPreferredSize( new Dimension(width, jcomponent.getPreferredSize().height) ); jcomponent.setMinimumSize( new Dimension(width, jcomponent.getPreferredSize().height) ); if (jcomponent.isDisplayable()) { jcomponent.revalidate(); } } } /** * Set the height of a given component. * * @param component the component to resize * @param height the new height to apply */ public static void setComponentHeight(Component component, int height) { component.setSize(component.getWidth(), height); if (component instanceof JComponent) { JComponent jcomponent = (JComponent) component; jcomponent.setPreferredSize( new Dimension(jcomponent.getPreferredSize().width, height)); jcomponent.setMinimumSize( new Dimension(jcomponent.getPreferredSize().width, height)); if (jcomponent.isDisplayable()) { jcomponent.revalidate(); } } } public static ImageIcon createIcon(String path) { URL imgURL = JAXXUtil.class.getResource(path); if (imgURL != null) { return new ImageIcon(imgURL); } else { throw new IllegalArgumentException("could not find icon " + path); } } /** * @param path the location of icons in root directory icons * @return the icon at {@link #getIconPath()}+path */ public static ImageIcon createImageIcon(String path) { String iconPath = getIconPath(); return createIcon(iconPath + path); } /** * @param key the key of the icon to retreave from {@link UIManager} * @return the icon, or {@code null} if no icon found in {@link UIManager} */ public static Icon getUIManagerIcon(String key) { return UIManager.getIcon(key); } /** * retreave for the {@link UIManager} the icon prefixed by {@code action}. * * @param key the key of the action icon to retreave from {@link UIManager} * @return the icon, or {@code null} if no icon found in {@link UIManager} */ public static Icon getUIManagerActionIcon(String key) { return getUIManagerIcon("action." + key); } public static ImageIcon createActionIcon(String name) { String iconPath = getIconPath(); return createIcon("action", name); } public static ImageIcon createIcon(String classifier, String name) { String iconPath = getIconPath(); return createIcon(iconPath + classifier + "-" + name + ".png"); } public static ImageIcon createI18nIcon(String name) { String iconPath = getIconPath(); return createIcon(iconPath + "i18n/" + name + ".png"); } private static String getIconPath() { String iconPath = UIManager.getString(DEFAULT_ICON_PATH_PROPERTY); if (iconPath == null) { iconPath = DEFAULT_ICON_PATH; } else { if (!iconPath.endsWith("/")) { iconPath += "/"; } } return iconPath; } /** * Used to edit a cell of a given table. * * @param table the table to edit * @param row row index of cell to editing * @param colummn column index of cell to editing * @return {@code false} if for any reason the cell cannot be edited, * or if the indices are invalid */ public static boolean editCell(JTable table, int row, int colummn) { boolean result = false; if (table.isCellEditable(row, colummn)) { if (table.isEditing()) { int editingRow = table.getEditingRow(); int editingColumn = table.getEditingColumn(); // stop edition TableCellEditor cellEditor = table.getCellEditor(editingRow, editingColumn); cellEditor.stopCellEditing(); } // select row table.setColumnSelectionInterval(colummn, colummn); table.setRowSelectionInterval(row, row); // edit cell result = table.editCellAt(row, colummn, new EventObject(table)); log.debug(String.format("Select row[%d] column[%d] return : %s", row, colummn, result)); } return result; } public static void ensureRowIndex(TableModel model, int rowIndex) throws ArrayIndexOutOfBoundsException { if (rowIndex < -1 || rowIndex >= model.getRowCount()) { throw new ArrayIndexOutOfBoundsException( "the rowIndex was " + rowIndex + ", but should be int [0," + (model.getRowCount() - 1) + "]"); } } public static void ensureColumnIndex(TableModel model, int index) throws ArrayIndexOutOfBoundsException { if (index < -1 || index >= model.getColumnCount()) { throw new ArrayIndexOutOfBoundsException( "the columnIndex was " + index + ", but should be int [0," + (model.getColumnCount() - 1) + "]"); } } /** * Add to a given table a selec tion model listener to always scroll to * current cell selection. * * @param table the table * @since 2.5.3 */ public static void scrollToTableSelection(final JTable table) { table.getSelectionModel().addListSelectionListener(e -> { ListSelectionModel listSelectionModel = (ListSelectionModel) e.getSource(); int firstIndex = e.getFirstIndex(); int lastIndex = e.getLastIndex(); Integer newSelectedRow = null; if (listSelectionModel.isSelectionEmpty()) { // no selection } else if (listSelectionModel.isSelectedIndex(firstIndex)) { // use first index newSelectedRow = firstIndex; } else if (listSelectionModel.isSelectedIndex(lastIndex)) { // use last index newSelectedRow = lastIndex; } if (newSelectedRow != null) { Rectangle rect = table.getCellRect(newSelectedRow, 0, true); table.scrollRectToVisible(rect); } }); } /** * Get the first char of a String, or return default value. *

* Used for example by generated code (i18nMnemonic). * * @param text the text to cut * @param defaultValue default char value if text is null, or empty * @return the first char of the given text or the default value if text is null or empty. * @since 2.6.14 */ public static char getFirstCharAt(String text, char defaultValue) { return text == null || text.trim().length() == 0 ? defaultValue : text.charAt(0); } public static void openLink(URI uri) { Desktop desktop = getDesktopForBrowse(); try { desktop.browse(uri); } catch (Exception e) { throw new RuntimeException("Could not open link " + uri, e); } } public static Desktop getDesktopForBrowse() { if (!Desktop.isDesktopSupported()) { throw new RuntimeException("Desktop not accessible"); } Desktop desktop = Desktop.getDesktop(); if (!desktop.isSupported(Desktop.Action.BROWSE)) { throw new RuntimeException("Action 'Go' not supported by desktop"); } return desktop; } public static DefaultComboBoxModel newComboModel(Object... items) { return new DefaultComboBoxModel(items); } public static void changeFontSize(JComponent editor, float newSize) { editor.setFont(editor.getFont().deriveFont(newSize)); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy