/** * Copyright (c) 2012, Lindsay Bradford and other Contributors. * All rights reserved. * * This program and the accompanying materials are made available * under the terms of the BSD 3-Clause licence which accompanies * this distribution, and is available at * http://opensource.org/licenses/BSD-3-Clause */ package blacksmyth.general; import java.awt.Dimension; import java.awt.FontMetrics; import java.awt.MouseInfo; import java.awt.Point; import java.awt.event.ActionEvent; import java.awt.event.KeyEvent; import java.util.List; import java.util.UUID; import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.ActionMap; import javax.swing.InputMap; import javax.swing.JComboBox; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.JTable; import javax.swing.KeyStroke; import javax.swing.table.TableColumn; /** * A library of generally reusabile utility functions for Swing. * Being a library, the class is not able to be instantiated. * @author linds * */ public final class BlacksmythSwingUtilities { /** * Locks the width of <tt>column</tt> to the <tt>width</tt> specified. * @param column * @param width */ public static void lockColumnWidth(TableColumn column, int width) { column.setMinWidth(width); column.setMaxWidth(width); } /** * Returns the width in pixels that the supplied <tt>text</tt> * would consume if rendered with a <tt>JLabel</tt> using its default font. * @param text * @return width as an integer. */ public static int getTextWidth(String text) { JLabel label = new JLabel(text); FontMetrics metrics = label.getFontMetrics(label.getFont()); return (int) metrics.getStringBounds( text, label.getGraphics() ).getWidth(); } /** * Returns the longest string set as an item in the supplied <tt>comboBox</tt> * @param comboBox * @return */ public static String getWidestTextInComboBox(JComboBox<String> comboBox) { String longestFoundString = ""; for(int i = 0; i < comboBox.getItemCount(); i++) { assert (comboBox.getItemAt(i).getClass().equals(String.class)); String item = comboBox.getItemAt(i); if (item.length() > longestFoundString.length()) { longestFoundString = item; } } return longestFoundString; } /** * Binds the supplied <code>actionToPerform</code> to the supplied <code>keyStroke</code> * for the given <code>component</code>. <p> * This is a convenience method that auto-generates the necessary <code>keyStrokeLabel</code> for the * caller when mapping the <code>keyStroke</code> to the <code>actionToPerform</code>. * @see #bindKeyStrokeToAction(JComponent, String, KeyStroke, AbstractAction) * @param component * @param keyStroke * @param actionToPerform */ public static void bindKeyStrokeToAction(JComponent component, KeyStroke keyStroke, Action actionToPerform) { bindKeyStrokeToAction( component, UUID.randomUUID().toString(), // just use a random (semi-)unique label we don't need to track keyStroke, actionToPerform ); } /** * Binds the supplied <code>actionToPerform</code> to the supplied * <code>keyStroke</code> for the given <code>component</code> * via the <code>keyStrokeLabel</code>. <p> * Note that the <code>keyStroke</code> will trigger <code>actionToPerform</code> * whenever the component is in a focused window. * @see JComponent#WHEN_IN_FOCUSED_WINDOW * @param component * @param keyStrokeLabel * @param keyStroke * @param actionToPerform */ public static void bindKeyStrokeToAction(JComponent component, String keyStrokeLabel, KeyStroke keyStroke, Action actionToPerform) { InputMap inputMap = component.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW); inputMap.put( keyStroke, keyStrokeLabel ); component.getActionMap().put( keyStrokeLabel, actionToPerform ); } /** * Returns whether the mouse is currently located within the on-screen bounds of component. * @param component * @return true if mouse is over component, false otherwise. */ public static boolean mouseIsOverComponent(JComponent component) { Point mousePoint = MouseInfo.getPointerInfo().getLocation(); Point componentPoint = component.getLocationOnScreen(); if (mousePoint.x < componentPoint.x) return false; if (mousePoint.x > componentPoint.x + component.getWidth()) return false; if (mousePoint.y < componentPoint.y) return false; if (mousePoint.y > componentPoint.y + component.getHeight()) return false; return true; } public static void scrollRowToVisible(JTable table, int row) { table.scrollRectToVisible( table.getCellRect( row, 0, true ) ); } public static void equalizeComponentSizes(List<JComponent> components) { Dimension maxComponentSize = new Dimension(0,0); for (int i = 0; i < components.size(); ++i) { setMaximumSize( maxComponentSize, components.get(i) ); } for (int i = 0; i < components.size(); ++i) { resize( components.get(i), maxComponentSize ); } } private static void setMaximumSize(Dimension maxComponentSize, JComponent component) { final Dimension componentSize = component.getPreferredSize(); maxComponentSize.width = Math.max(maxComponentSize.width, (int)componentSize.getWidth()); maxComponentSize.height = Math.max(maxComponentSize.height, (int)componentSize.getHeight()); } private static void resize(JComponent component, Dimension size) { component.setPreferredSize(size); component.setMaximumSize(size); component.setMinimumSize(size); } public static void enableEnterKeyEditsInJTable(final JTable theTable) { InputMap im = theTable.getInputMap(JTable.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); ActionMap am = theTable.getActionMap(); KeyStroke enterKey = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0); im.put(enterKey, "Action.enter"); am.put("Action.enter", new AbstractAction() { public void actionPerformed(ActionEvent evt) { int row = theTable.getSelectedRow(); int column = theTable.getSelectedColumn(); if (theTable.editCellAt(row, column)) { theTable.getEditorComponent().requestFocusInWindow(); } } }); } }