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

ch.randelshofer.quaqua.QuaquaUtilities Maven / Gradle / Ivy

Go to download

A Mavenisation of the Quaqua Mac OSX Swing Look and Feel (Java library) Quaqua Look and Feel (C) 2003-2010, Werner Randelshofer. Mavenisation by Matt Gumbley, DevZendo.org - for problems with Mavenisation, see Matt; for issues with Quaqua, see the Quaqua home page. For full license details, see http://randelshofer.ch/quaqua/license.html

The newest version!
/*
 * @(#)QuaquaUtilities.java  
 *
 * Copyright (c) 2003-2010 Werner Randelshofer, Immensee, Switzerland.
 * All rights reserved.
 *
 * You may not use, copy or modify this file, except in compliance with the
 * license agreement you entered into with Werner Randelshofer.
 * For details see accompanying license terms.
 */
package ch.randelshofer.quaqua;

import ch.randelshofer.quaqua.util.*;
import java.awt.*;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DragSource;
import java.awt.event.*;
import java.awt.image.*;
import java.lang.reflect.Method;
import java.net.*;
import javax.swing.*;
import javax.swing.text.*;
import javax.swing.border.*;
import javax.swing.plaf.*;
import javax.swing.plaf.basic.*;

/**
 * Utility class for the Quaqua LAF.
 *
 * @author Werner Randelshofer, Hausmatt 10, CH-6405 Immensee, Switzerland
 * @version $Id: QuaquaUtilities.java 361 2010-11-21 11:19:20Z wrandelshofer $
 */
public class QuaquaUtilities extends BasicGraphicsUtils implements SwingConstants {

    private final static boolean DEBUG = false;
    /** Holds the class name of SwingUtilities2 once it has been resolved. */
    private static String swingUtilities2;

    /** Prevent instance creation. */
    private QuaquaUtilities() {
    }

    /*
     * Convenience function for determining ComponentOrientation.  Helps us
     * avoid having Munge directives throughout the code.
     */
    public static boolean isLeftToRight(Component c) {
        return c.getComponentOrientation().isLeftToRight();
    }

    /**
     * Draw a string with the graphics g at location
     * (x, y)
     * just like g.drawString would.
     * The character at index underlinedIndex
     * in text will be underlined. If index is beyond the
     * bounds of text (including < 0), nothing will be
     * underlined.
     *
     * @param g Graphics to draw with
     * @param text String to draw
     * @param underlinedIndex Index of character in text to underline
     * @param x x coordinate to draw at
     * @param y y coordinate to draw at
     * @since 1.4
     */
    public static void drawStringUnderlineCharAt(Graphics g, String text,
            int underlinedIndex, int x, int y) {
        g.drawString(text, x, y);
        if (underlinedIndex >= 0 && underlinedIndex < text.length()) {
            FontMetrics fm = g.getFontMetrics();
            int underlineRectX = x + fm.stringWidth(text.substring(0, underlinedIndex));
            int underlineRectY = y;
            int underlineRectWidth = fm.charWidth(text.charAt(underlinedIndex));
            int underlineRectHeight = 1;
            g.fillRect(underlineRectX, underlineRectY + fm.getDescent() - 1,
                    underlineRectWidth, underlineRectHeight);
        }
    }

    /**
     * Returns index of the first occurrence of mnemonic
     * within string text. Matching algorithm is not
     * case-sensitive.
     *
     * @param text The text to search through, may be null
     * @param mnemonic The mnemonic to find the character for.
     * @return index into the string if exists, otherwise -1
     */
    static int findDisplayedMnemonicIndex(String text, int mnemonic) {
        if (text == null || mnemonic == '\0') {
            return -1;
        }

        char uc = Character.toUpperCase((char) mnemonic);
        char lc = Character.toLowerCase((char) mnemonic);

        int uci = text.indexOf(uc);
        int lci = text.indexOf(lc);

        if (uci == -1) {
            return lci;
        } else if (lci == -1) {
            return uci;
        } else {
            return (lci < uci) ? lci : uci;
        }
    }

    /**
     * Returns true if the component is on a Dialog or a Frame, which is active,
     * or if it is on a Window, which is focused.
     * Always returns true, if the component has no parent window.
     */
    public static boolean isOnActiveWindow(Component c) {
        return isOnActiveWindow(c, false);
    }

    /**
     * Returns true if the component is on a Dialog or a Frame, which is active,
     * or if it is on a Window, which is focused.
     * Always returns true, if the component has no parent window.
     * 

* @param c The component. * @param isActiveWhenSheetIsActive Set this to true, when the window should * be considered as active when its sheet dialog is active. */ public static boolean isOnActiveWindow(Component c, boolean isActiveWhenSheetIsActive) { // In the RootPaneUI, we set a client property on the whole component // tree, if the ancestor Frame gets activated or deactivated. if (c instanceof JComponent) { Boolean value = (Boolean) ((JComponent) c).getClientProperty("Frame.active"); // Unfortunately, the value is not always reliable. // Therefore we can only do a short circuit, if the value is true. if (value != null && value.booleanValue()) { return true; //return value.booleanValue(); } } Window window = SwingUtilities.getWindowAncestor(c); boolean isOnActiveWindow; if (window == null) { isOnActiveWindow = true; } else if (window instanceof JWindow) { isOnActiveWindow = window.isActive() || window.getName() == "###focusableSwingPopup###";// literal strings get interned } else if ((window instanceof Frame) || (window instanceof Dialog)) { isOnActiveWindow = window.isActive(); if (!isOnActiveWindow && isActiveWhenSheetIsActive) { Window focusedWindow = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusedWindow(); isOnActiveWindow = focusedWindow != null && focusedWindow.getOwner() == window; // we return here, because we don't want to change the "Frame.active" // property. return isOnActiveWindow; } } else { if (window.getFocusableWindowState()) { isOnActiveWindow = window.isFocused(); } else { isOnActiveWindow = true; } } // In case the activation property is true, we fix the value of the // client property, so that we can do a short circuit next time. if (isOnActiveWindow && (c instanceof JComponent)) { ((JComponent) c).putClientProperty("Frame.active", isOnActiveWindow); } return isOnActiveWindow; } /** * Returns a Mac OS X specific String describing the modifier key(s), * such as "Shift", or "Ctrl+Shift". * * @return string a text description of the combination of modifier * keys that were held down during the event */ public static String getKeyModifiersText(int modifiers, boolean leftToRight) { return getKeyModifiersUnicode(modifiers, leftToRight); } static String getKeyModifiersUnicode(int modifiers, boolean leftToRight) { char[] cs = new char[4]; int count = 0; if (leftToRight) { if ((modifiers & InputEvent.CTRL_MASK) != 0) { cs[count++] = '\u2303'; } // Unicode: UP ARROWHEAD if ((modifiers & (InputEvent.ALT_MASK | InputEvent.ALT_GRAPH_MASK)) != 0) { cs[count++] = '\u2325'; } // Unicode: OPTION KEY if ((modifiers & InputEvent.SHIFT_MASK) != 0) { cs[count++] = '\u21e7'; } // Unicode: UPWARDS WHITE ARROW if ((modifiers & InputEvent.META_MASK) != 0) { cs[count++] = '\u2318'; } // Unicode: PLACE OF INTEREST SIGN } else { if ((modifiers & InputEvent.META_MASK) != 0) { cs[count++] = '\u2318'; } // Unicode: PLACE OF INTEREST SIGN if ((modifiers & InputEvent.SHIFT_MASK) != 0) { cs[count++] = '\u21e7'; } // Unicode: UPWARDS WHITE ARROW if ((modifiers & (InputEvent.ALT_MASK | InputEvent.ALT_GRAPH_MASK)) != 0) { cs[count++] = '\u2325'; } // Unicode: OPTION KEY if ((modifiers & InputEvent.CTRL_MASK) != 0) { cs[count++] = '\u2303'; } // Unicode: UP ARROWHEAD } return new String(cs, 0, count); } public static void repaintBorder(JComponent component) { JComponent c = component; Border border = null; Container container = component.getParent(); if (container instanceof JViewport) { c = (JComponent) container.getParent(); if (c != null) { border = c.getBorder(); } } if (border == null) { border = component.getBorder(); c = component; } if (border != null && c != null) { int w = c.getWidth(); int h = c.getHeight(); Insets insets = c.getInsets(); c.repaint(0, 0, w, insets.top); c.repaint(0, insets.top, insets.left, h - insets.bottom - insets.top); c.repaint(0, h - insets.bottom, w, insets.bottom); c.repaint(w - insets.right, insets.top, insets.right, h - insets.bottom - insets.top); } } public static final Object beginGraphics(Graphics2D graphics2d) { Object object = graphics2d.getRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING); /* AffineTransform tx = graphics2d.getTransform(); AffineTransform savedTransform = (AffineTransform) tx.clone(); tx.scale(0.9,0.9); graphics2d.setTransform(tx); */ graphics2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); // graphics2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, // RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB); /*graphics2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);*/ //if (true) return savedTransform; return object; } public static final void endGraphics(Graphics2D graphics2d, Object oldHints) { /* if (true) { graphics2d.setTransform((AffineTransform) oldHints); return; }*/ if (oldHints != null) { graphics2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, oldHints); } } /** * Returns true, if the specified component is focus owner or permanent * focus owner and if the component is on an the active window. */ public static final boolean isFocused(Component component) { // When a component is used as a cell renderer, the focus can // not be determined from the component itself. if (component instanceof JComponent) { if (((JComponent) component).getClientProperty("Quaqua.Component.cellRendererFor") != null) { component = (Component) ((JComponent) component).getClientProperty("Quaqua.Component.cellRendererFor"); } } //--- try { boolean isFocusOwner = ((Boolean) Methods.invoke(component, "isFocusOwner")).booleanValue(); Window ancestor = SwingUtilities.getWindowAncestor(component); Object kfm = Methods.invokeStatic("java.awt.KeyboardFocusManager", "getCurrentKeyboardFocusManager"); return isFocusOwner || component == Methods.invoke(kfm, "getPermanentFocusOwner") && ancestor != null && Methods.invokeGetter(ancestor, "isFocused", false); } catch (NoSuchMethodException e) { return component.hasFocus(); } } static boolean isHeadless() { return Methods.invokeStaticGetter(GraphicsEnvironment.class, "isHeadless", false); } /** Returns the class name of SwingUtilities2. */ private static String getSwingUtilities2() { if (swingUtilities2 == null) { // Location of SwingUtilities2 in J2SE6: swingUtilities2 = "sun.swing.SwingUtilities2"; try { Class.forName(swingUtilities2); } catch (ClassNotFoundException ex) { // Location of SwingUtilities2 in J2SE5: swingUtilities2 = "com.sun.java.swing.SwingUtilities2"; try { Class.forName(swingUtilities2); } catch (ClassNotFoundException ex2) { System.err.println("Warning QuaquaUtilities: Couldn't locate class " + swingUtilities2); } } } return swingUtilities2; } public static int getLeftSideBearing(Font f, String string) { return ((Integer) Methods.invokeStatic( getSwingUtilities2(), "getLeftSideBearing", new Class[]{Font.class, String.class}, new Object[]{f, string}, 0)).intValue(); } /** * Invoked when the user attempts an invalid operation, * such as pasting into an uneditable JTextField * that has focus. The default implementation beeps. Subclasses * that wish different behavior should override this and provide * the additional feedback. * * @param component Component the error occured in, may be null * indicating the error condition is not directly * associated with a Component. */ static void provideErrorFeedback(Component component) { Toolkit toolkit = null; if (component != null) { toolkit = component.getToolkit(); } else { toolkit = Toolkit.getDefaultToolkit(); } toolkit.beep(); } // provideErrorFeedback() public static BufferedImage createBufferedImage(URL location) { Image image = Toolkit.getDefaultToolkit().createImage(location); BufferedImage buf; if (image instanceof BufferedImage) { buf = (BufferedImage) image; } else { loadImage(image); //buf = new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_RGB); buf = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration().createCompatibleImage(image.getWidth(null), image.getHeight(null), Transparency.OPAQUE); Graphics g = buf.getGraphics(); g.drawImage(image, 0, 0, null); g.dispose(); image.flush(); } return buf; } public static TexturePaint createTexturePaint(URL location) { BufferedImage texture = createBufferedImage(location); TexturePaint paint = new TexturePaint(texture, new Rectangle(0, 0, texture.getWidth(), texture.getHeight())); return paint; } /** * Loads the image, returning only when the image is loaded. * @param image the image */ private static void loadImage(Image image) { Component component = new Component() { }; MediaTracker tracker = new MediaTracker(component); synchronized (tracker) { int id = 0; tracker.addImage(image, id); try { tracker.waitForID(id, 0); } catch (InterruptedException e) { if (DEBUG) { System.out.println("INTERRUPTED while loading Image"); } } ///int loadStatus = tracker.statusID(id, false); tracker.removeImage(image, id); } } /** * Compute and return the location of the icons origin, the * location of origin of the text baseline, and a possibly clipped * version of the compound labels string. Locations are computed * relative to the viewR rectangle. * The JComponents orientation (LEADING/TRAILING) will also be taken * into account and translated into LEFT/RIGHT values accordingly. */ public static String layoutCompoundLabel(JComponent c, FontMetrics fm, String text, Icon icon, int verticalAlignment, int horizontalAlignment, int verticalTextPosition, int horizontalTextPosition, Rectangle viewR, Rectangle iconR, Rectangle textR, int textIconGap) { boolean orientationIsLeftToRight = true; int hAlign = horizontalAlignment; int hTextPos = horizontalTextPosition; if (c != null) { if (!(c.getComponentOrientation().isLeftToRight())) { orientationIsLeftToRight = false; } } // Translate LEADING/TRAILING values in horizontalAlignment // to LEFT/RIGHT values depending on the components orientation switch (horizontalAlignment) { case LEADING: hAlign = (orientationIsLeftToRight) ? LEFT : RIGHT; break; case TRAILING: hAlign = (orientationIsLeftToRight) ? RIGHT : LEFT; break; } // Translate LEADING/TRAILING values in horizontalTextPosition // to LEFT/RIGHT values depending on the components orientation switch (horizontalTextPosition) { case LEADING: hTextPos = (orientationIsLeftToRight) ? LEFT : RIGHT; break; case TRAILING: hTextPos = (orientationIsLeftToRight) ? RIGHT : LEFT; break; } return layoutCompoundLabelImpl(c, fm, text, icon, verticalAlignment, hAlign, verticalTextPosition, hTextPos, viewR, iconR, textR, textIconGap); } /** * Compute and return the location of the icons origin, the * location of origin of the text baseline, and a possibly clipped * version of the compound labels string. Locations are computed * relative to the viewR rectangle. * This layoutCompoundLabel() does not know how to handle LEADING/TRAILING * values in horizontalTextPosition (they will default to RIGHT) and in * horizontalAlignment (they will default to CENTER). * Use the other version of layoutCompoundLabel() instead. */ public static String layoutCompoundLabel( FontMetrics fm, String text, Icon icon, int verticalAlignment, int horizontalAlignment, int verticalTextPosition, int horizontalTextPosition, Rectangle viewR, Rectangle iconR, Rectangle textR, int textIconGap) { return layoutCompoundLabelImpl(null, fm, text, icon, verticalAlignment, horizontalAlignment, verticalTextPosition, horizontalTextPosition, viewR, iconR, textR, textIconGap); } /** * Compute and return the location of the icons origin, the * location of origin of the text baseline, and a possibly clipped * version of the compound labels string. Locations are computed * relative to the viewR rectangle. * This layoutCompoundLabel() does not know how to handle LEADING/TRAILING * values in horizontalTextPosition (they will default to RIGHT) and in * horizontalAlignment (they will default to CENTER). * Use the other version of layoutCompoundLabel() instead. * * This is the same as SwingUtilities.layoutCompoundLabelImpl, except for * the algorithm for clipping the text. If a text is too long, "..." are * inserted at the middle of the text instead of at the end. */ private static String layoutCompoundLabelImpl( JComponent c, FontMetrics fm, String text, Icon icon, int verticalAlignment, int horizontalAlignment, int verticalTextPosition, int horizontalTextPosition, Rectangle viewR, Rectangle iconR, Rectangle textR, int textIconGap) { /* Initialize the icon bounds rectangle iconR. */ if (icon != null) { iconR.width = icon.getIconWidth(); iconR.height = icon.getIconHeight(); } else { iconR.width = iconR.height = 0; } /* Initialize the text bounds rectangle textR. If a null * or and empty String was specified we substitute "" here * and use 0,0,0,0 for textR. */ boolean textIsEmpty = (text == null) || text.equals(""); int lsb = 0; View v = null; if (textIsEmpty) { textR.width = textR.height = 0; text = ""; } else { v = (c != null) ? (View) c.getClientProperty("html") : null; if (v != null) { textR.width = (int) v.getPreferredSpan(View.X_AXIS); textR.height = (int) v.getPreferredSpan(View.Y_AXIS); } else { textR.width = SwingUtilities.computeStringWidth(fm, text); lsb = getLeftSideBearing(fm.getFont(), text); if (lsb < 0) { // If lsb is negative, add it to the width, the // text bounds will later be adjusted accordingly. textR.width -= lsb; } textR.height = fm.getHeight(); } } /* Unless both text and icon are non-null, we effectively ignore * the value of textIconGap. The code that follows uses the * value of gap instead of textIconGap. */ int gap = (textIsEmpty || (icon == null)) ? 0 : textIconGap; if (!textIsEmpty) { /* If the label text string is too wide to fit within the available * space "..." and as many characters as will fit will be * displayed instead. */ int availTextWidth; if (horizontalTextPosition == CENTER) { availTextWidth = viewR.width; } else { availTextWidth = viewR.width - (iconR.width + gap); } if (textR.width > availTextWidth) { if (v != null) { textR.width = availTextWidth; } else { String clipString = "..."; int totalWidth = SwingUtilities.computeStringWidth(fm, clipString); int nChars; int len = text.length(); for (nChars = 0; nChars < len; nChars++) { int charIndex = (nChars % 2 == 0) ? nChars / 2 : len - 1 - nChars / 2; totalWidth += fm.charWidth(text.charAt(charIndex)); if (totalWidth > availTextWidth) { break; } } text = text.substring(0, nChars / 2) + clipString + text.substring(len - nChars / 2); textR.width = SwingUtilities.computeStringWidth(fm, text); } } } /* Compute textR.x,y given the verticalTextPosition and * horizontalTextPosition properties */ if (verticalTextPosition == TOP) { if (horizontalTextPosition != CENTER) { textR.y = 0; } else { textR.y = -(textR.height + gap); } } else if (verticalTextPosition == CENTER) { textR.y = (iconR.height / 2) - (textR.height / 2); } else { // (verticalTextPosition == BOTTOM) if (horizontalTextPosition != CENTER) { textR.y = iconR.height - textR.height; } else { textR.y = (iconR.height + gap); } } if (horizontalTextPosition == LEFT) { textR.x = -(textR.width + gap); } else if (horizontalTextPosition == CENTER) { textR.x = (iconR.width / 2) - (textR.width / 2); } else { // (horizontalTextPosition == RIGHT) textR.x = (iconR.width + gap); } /* labelR is the rectangle that contains iconR and textR. * Move it to its proper position given the labelAlignment * properties. * * To avoid actually allocating a Rectangle, Rectangle.union * has been inlined below. */ int labelR_x = Math.min(iconR.x, textR.x); int labelR_width = Math.max(iconR.x + iconR.width, textR.x + textR.width) - labelR_x; int labelR_y = Math.min(iconR.y, textR.y); int labelR_height = Math.max(iconR.y + iconR.height, textR.y + textR.height) - labelR_y; int dx, dy; if (verticalAlignment == TOP) { dy = viewR.y - labelR_y; } else if (verticalAlignment == CENTER) { dy = (viewR.y + (viewR.height / 2)) - (labelR_y + (labelR_height / 2)); } else { // (verticalAlignment == BOTTOM) dy = (viewR.y + viewR.height) - (labelR_y + labelR_height); } if (horizontalAlignment == LEFT) { dx = viewR.x - labelR_x; } else if (horizontalAlignment == RIGHT) { dx = (viewR.x + viewR.width) - (labelR_x + labelR_width); } else { // (horizontalAlignment == CENTER) dx = (viewR.x + (viewR.width / 2)) - (labelR_x + (labelR_width / 2)); } /* Translate textR and glypyR by dx,dy. */ textR.x += dx; textR.y += dy; iconR.x += dx; iconR.y += dy; if (lsb < 0) { // lsb is negative. We previously adjusted the bounds by lsb, // we now need to shift the x location so that the text is // drawn at the right location. The result is textR does not // line up with the actual bounds (on the left side), but we will // have provided enough space for the text. textR.width += lsb; textR.x -= lsb; } return text; } public static void configureGraphics(Graphics gr) { Graphics2D g = (Graphics2D) gr; g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); /*g.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);*/ } /** * Uses some unsupported (dangerous) API calls on the native peers to make * a window translucent. If the API is not found, this method leaves the * window opaque. * * @param w The Window. * @param value The alpha channel for the window. */ static final void setWindowAlpha(Window w, int value) { if (w == null) { return; } if (w instanceof RootPaneContainer) { JRootPane rp = ((RootPaneContainer) w).getRootPane(); // Window alpha is for J2SE 5 on Mac OS X 10.5 // See: http://developer.apple.com/technotes/tn2007/tn2196.html#WINDOW_ALPHA rp.putClientProperty("Window.alpha", new Float(value / 255f)); } } static final void setWindowAlphaOld(Window w, int value) { if (w == null) { return; } if (QuaquaManager.isOSX()) { // Try Mac API /* // Platform neutral API w.setBackground(new Color(0, 0, 0, value)); */ // Java 1.4.2_05 does not support window alpha. // Setting window alpha only sets the background color of the window // to white. if (w.getPeer() == null) { w.pack(); } java.awt.peer.ComponentPeer peer = w.getPeer(); try { // Alpha API for Apple's Java 1.4 + 1.5 on Mac OS X 10.4 Tiger. Methods.invoke(peer, "setAlpha", (float) (value / 255f)); // Platform neutral API w.setBackground(new Color(255, 255, 255, value)); if (w instanceof RootPaneContainer) { ((RootPaneContainer) w).getContentPane().setBackground(new Color(255, 255, 255, 0)); } } catch (Throwable e) { // Alpha API for Apple's Java 1.3. if (QuaquaManager.getProperty("java.version").startsWith("1.3")) { try { Methods.invoke(peer, "_setAlpha", value); } catch (Throwable e2) { // Platform neutral API w.setBackground(new Color(255, 255, 255, value)); if (w instanceof RootPaneContainer) { ((RootPaneContainer) w).getContentPane().setBackground(new Color(255, 255, 255, 0)); } } } } } else { // Try J2SE 6 Update 10 API on Windows try { Class clazz = Class.forName("com.sun.awt.AWTUtilities"); Method method = clazz.getMethod("setWindowOpaque", new Class[]{java.awt.Window.class, Boolean.TYPE}); method.invoke(clazz, new Object[]{w, Boolean.FALSE}); } catch (Throwable e2) { // silently ignore this exception. } } } /** Copied from BasicLookAndFeel. */ public static Component compositeRequestFocus(Component component) { try { if (component instanceof Container) { Container container = (Container) component; if (Methods.invokeGetter(container, "isFocusCycleRoot", false)) { Object policy = Methods.invokeGetter(container, "getFocusTraversalPolicy", null); Component comp = (Component) Methods.invoke(policy, "getDefaultComponent", Container.class, container); if (comp != null) { comp.requestFocus(); return comp; } } Container rootAncestor = (Container) Methods.invokeGetter(container, "getFocusCycleRootAncestor", null); if (rootAncestor != null) { Object policy = Methods.invokeGetter(rootAncestor, "getFocusTraversalPolicy", null); Component comp = (Component) Methods.invoke(policy, "getComponentAfter", new Class[]{Container.class, Component.class}, new Object[]{rootAncestor, container}); if (comp != null && SwingUtilities.isDescendingFrom(comp, container)) { comp.requestFocus(); return comp; } } } } catch (NoSuchMethodException e) { // ignore } if (Methods.invokeGetter(component, "isFocusable", true)) { component.requestFocus(); return component; } return null; } /** * Convenience method for installing a property with the specified name * and value on a component if that property has not already been set * by the client program. This method is intended to be used by * UI delegate instances that need to specify a default value for a * property of primitive type (boolean, int, ..), but do not wish * to override a value set by the client. Since primitive property * values cannot be wrapped with the UIResource marker, this method * uses private state to determine whether the property has been set * by the client. * @throws IllegalArgumentException if the specified property is not * one which can be set using this method * @throws ClassCastException may be thrown if the property value * specified does not match the property's type * @throws NullPointerException may be thrown if c or propertyValue is null * @param c the target component for installing the property * @param propertyName String containing the name of the property to be set */ public static void installProperty(JComponent c, String propertyName, Object value) { LookAndFeel.installProperty(c, propertyName, value); } /** * Returns the ui that is of type klass, or null if * one can not be found. */ public static Object getUIOfType(ComponentUI ui, Class klass) { if (klass.isInstance(ui)) { return ui; } return null; } public static void adjustFocus(JComponent tree) { try { Methods.invokeStatic(getSwingUtilities2(), "adjustFocus", JComponent.class, tree); } catch (NoSuchMethodException ex) { tree.requestFocusInWindow(); } } static boolean shouldIgnore(MouseEvent e, JComponent tree) { //return QuaquaUtilities2.shouldIgnore(e, tree); try { return ((Boolean) Methods.invokeStatic(getSwingUtilities2(), "shouldIgnore", new Class[]{MouseEvent.class, JComponent.class}, new Object[]{e, tree})).booleanValue(); } catch (NoSuchMethodException ex) { return false; } } /** * Returns true, if the component should use the small appearance. * @param c * @return true, , if the component should use the small appearance. */ public static boolean isSmallSizeVariant(JComponent c) { Font f = c.getFont(); if (f != null && f.getSize() <= 11) { return true; } String p = (String) c.getClientProperty("JComponent.sizeVariant"); return p != null && p.equals("small"); } public static void applySizeVariant(JComponent c) { String p = (String) c.getClientProperty("JComponent.sizeVariant"); if (p == null) { } else if (p.equals("regular")) { c.setFont(UIManager.getFont("SystemFont")); } else if (p.equals("small")) { c.setFont(UIManager.getFont("SmallSystemFont")); } else if (p.equals("mini")) { c.setFont(UIManager.getFont("MiniSystemFont")); } } public static int getDragThreshold() { try { Integer value = (Integer) Methods.invokeStatic(DragSource.class, "getDragThreshold"); return value.intValue(); } catch (Throwable ex) { //ex.printStackTrace(); return 5; } } public static int mapDragOperationFromModifiers(MouseEvent me, TransferHandler th) { return convertModifiersToDropAction(me.getModifiersEx(), th.getSourceActions((JComponent) me.getSource())); } public static int convertModifiersToDropAction(final int modifiers, final int supportedActions) { int dropAction = DnDConstants.ACTION_NONE; /* * Fix for 4285634. * Calculate the drop action to match Motif DnD behavior. * If the user selects an operation (by pressing a modifier key), * return the selected operation or ACTION_NONE if the selected * operation is not supported by the drag source. * If the user doesn't select an operation search the set of operations * supported by the drag source for ACTION_MOVE, then for * ACTION_COPY, then for ACTION_LINK and return the first operation * found. */ switch (modifiers & (InputEvent.SHIFT_DOWN_MASK | InputEvent.CTRL_DOWN_MASK)) { case InputEvent.SHIFT_DOWN_MASK | InputEvent.CTRL_DOWN_MASK: dropAction = DnDConstants.ACTION_LINK; break; case InputEvent.CTRL_DOWN_MASK: dropAction = DnDConstants.ACTION_COPY; break; case InputEvent.SHIFT_DOWN_MASK: dropAction = DnDConstants.ACTION_MOVE; break; default: if ((supportedActions & DnDConstants.ACTION_MOVE) != 0) { dropAction = DnDConstants.ACTION_MOVE; } else if ((supportedActions & DnDConstants.ACTION_COPY) != 0) { dropAction = DnDConstants.ACTION_COPY; } else if ((supportedActions & DnDConstants.ACTION_LINK) != 0) { dropAction = DnDConstants.ACTION_LINK; } } return dropAction & supportedActions; } /** * Return the child Component of the specified * Component that is the focus owner, if any. * * @param c the root of the Component hierarchy to * search for the focus owner * @return the focus owner, or null if there is no focus * owner, or if the focus owner is not comp, or a * descendant of comp * * @see java.awt.KeyboardFocusManager#getFocusOwner */ public static Component findFocusOwner(Component c) { Component focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner(); // verify focusOwner is a descendant of c for (Component temp = focusOwner; temp != null; temp = (temp instanceof Window) ? null : temp.getParent()) { if (temp == c) { return focusOwner; } } return null; } public static boolean isOnTexturedWindow(Component c) { boolean isTextured; JRootPane rootPane = SwingUtilities.getRootPane(c); if (rootPane != null) { isTextured = rootPane.getClientProperty("apple.awt.brushMetalLook") == Boolean.TRUE; } else { isTextured = false; } return isTextured; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy