//----------------------------------------------------------------------------// // // // U I U t i l // // // //----------------------------------------------------------------------------// // <editor-fold defaultstate="collapsed" desc="hdr"> // // Copyright (C) Hervé Bitteur and Brenton Partridge 2000-2013. // // This software is released under the GNU General Public License. // // Goto http://kenai.com/projects/audiveris to report bugs or suggestions. // //----------------------------------------------------------------------------// // </editor-fold> package omr.ui.util; import omr.WellKnowns; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.awt.BasicStroke; import java.awt.Component; import java.awt.Container; import java.awt.FileDialog; import java.awt.Frame; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Stroke; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.awt.event.WindowListener; import java.awt.geom.AffineTransform; import java.io.File; import java.util.Collection; import java.util.Iterator; import javax.swing.AbstractAction; import javax.swing.AbstractButton; import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JFileChooser; import javax.swing.JToggleButton; import javax.swing.border.Border; /** * Class {@code UIUtil} gathers utilities related to User Interface * * @author Hervé Bitteur and Brenton Partridge */ public class UIUtil { //~ Static fields/initializers --------------------------------------------- /** Usual logger utility */ private static final Logger logger = LoggerFactory.getLogger( UIUtil.class); /** * Customized border for tool buttons, to use consistently in all UI * components. */ private static Border toolBorder; public static final WindowListener closeWindow = new WindowAdapter() { @Override public void windowClosing (WindowEvent e) { e.getWindow() .dispose(); } }; //~ Constructors ----------------------------------------------------------- private UIUtil () { } //~ Methods ---------------------------------------------------------------- //------------------// // directoryChooser // //------------------// /** * Let the user select a directory. * * @param parent the parent component for the dialog * @param startDir the default directory * @return the chosen directory, or null */ public static File directoryChooser (Component parent, File startDir) { String oldMacProperty = System.getProperty( "apple.awt.fileDialogForDirectories", "false"); System.setProperty("apple.awt.fileDialogForDirectories", "true"); OmrFileFilter directoryFilter = new OmrFileFilter( "directory", new String[]{}) { @Override public boolean accept (File f) { return (f.isDirectory()); } }; File file = fileChooser(false, parent, startDir, directoryFilter); System.setProperty( "apple.awt.fileDialogForDirectories", oldMacProperty); return file; } //---------------// // enableActions // //---------------// /** * Given a list of actions, set all these actions (whether they * derive from AbstractAction or AbstractButton) enabled or not, * according to the bool parameter provided. * * @param actions list of actions to enable/disable as a whole * @param bool true for enable, false for disable */ public static void enableActions (Collection<?> actions, boolean bool) { for (Iterator<?> it = actions.iterator(); it.hasNext();) { Object next = it.next(); if (next instanceof AbstractAction) { ((AbstractAction) next).setEnabled(bool); } else if (next instanceof AbstractButton) { ((AbstractButton) next).setEnabled(bool); } else { logger.warn("Neither Button nor Action : {}", next); } } } //-------------// // fileChooser // //-------------// /** * A replacement for standard JFileChooser, to allow better * look & feel on the Mac platform. * * @param save true for a SAVE dialog, false for a LOAD dialog * @param parent the parent component for the dialog * @param startFile default file, or just default directory, or null * @param filter a filter to by applied on files * @return the selected file, or null */ public static File fileChooser (boolean save, Component parent, File startFile, OmrFileFilter filter) { File file = null; if (WellKnowns.MAC_OS_X) { if ((parent == null) && (omr.Main.getGui() != null)) { parent = omr.Main.getGui() .getFrame(); } Component parentFrame = parent; while (!(parentFrame instanceof Frame) && (parentFrame.getParent() != null)) { parentFrame = parentFrame.getParent(); } try { final FileDialog fd = new FileDialog((Frame) parentFrame); if (startFile != null) { fd.setDirectory( startFile.isDirectory() ? startFile.getPath() : startFile.getParent()); } fd.setMode(save ? FileDialog.SAVE : FileDialog.LOAD); fd.setFilenameFilter(filter); String title = save ? "Saving: " : "Loading: "; title += filter.getDescription(); fd.setTitle(title); fd.setVisible(true); String fileName = fd.getFile(); String dir = fd.getDirectory(); if ((dir != null) && (fileName != null)) { String fullName = dir + WellKnowns.FILE_SEPARATOR + fileName; file = new File(fullName); } } catch (ClassCastException e) { logger.warn("no ancestor is Frame"); } } else { ///final JFileChooser fc = new JFileChooser(); // see http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6317789 final JFileChooser fc = new JFileChooser() { @Override public void updateUI () { putClientProperty("FileChooser.useShellFolder", false); super.updateUI(); } }; // Pre-select the directory, and potentially the file to save to if (startFile != null) { if (startFile.isDirectory()) { fc.setCurrentDirectory(startFile); } else { File parentFile = startFile.getParentFile(); fc.setCurrentDirectory(parentFile); fc.setSelectedFile(startFile); } } fc.addChoosableFileFilter(filter); int result = save ? fc.showSaveDialog(parent) : fc.showOpenDialog(parent); if (result == JFileChooser.APPROVE_OPTION) { file = fc.getSelectedFile(); } } return file; } //---------------// // getToolBorder // //---------------// /** * Report a standard tool border entity, which is a blank border. * * @return the standard tool border */ public static Border getToolBorder () { if (toolBorder == null) { toolBorder = BorderFactory.createEmptyBorder(1, 2, 1, 2); } return toolBorder; } //-------------------// // setAbsoluteStroke // //-------------------// /** * Whatever the current scaling of a graphic context, set the stroke * to theesired absolute width, and return the saved stroke for * later restore. * * @param g the current graphics context * @param width the absolute stroke width desired * @return the previous stroke */ public static Stroke setAbsoluteStroke (Graphics g, float width) { Graphics2D g2 = (Graphics2D) g; AffineTransform AT = g2.getTransform(); double ratio = AT.getScaleX(); Stroke oldStroke = g2.getStroke(); Stroke stroke = new BasicStroke(width / (float) ratio); g2.setStroke(stroke); return oldStroke; } //-----------------// // suppressBorders // //-----------------// /** * Browse the whole hierarchy of components and nullify their * borders. */ public static void suppressBorders (Container container) { for (Component comp : container.getComponents()) { if (comp instanceof JComponent) { suppressBorders((JComponent) comp); } else if (comp instanceof Container) { suppressBorders((Container) comp); } } } //-----------------// // suppressBorders // //-----------------// /** * Nullify the border of this JComponent, as well as its * subcomponents. */ public static void suppressBorders (JComponent comp) { if (!(comp instanceof JButton) && !(comp instanceof JToggleButton)) { comp.setBorder(null); } suppressBorders((Container) comp); } }