classpath-patches
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[cp-patches] RFC: MetalToolTipUI and BasicToolTipUI


From: David Gilbert
Subject: [cp-patches] RFC: MetalToolTipUI and BasicToolTipUI
Date: Tue, 04 Oct 2005 12:39:18 +0000
User-agent: Mozilla Thunderbird 1.0.6 (X11/20050728)

I decided to implement the missing methods in MetalToolTipUI. As far as I can tell, tooltips for buttons and menu items under the MetalLookAndFeel display the accelerator text in the tooltip, but under the BasicLookAndFeel they do not. So the accelerator code in BasicToolTipUI needs moving to MetalToolTipUI.

This patch cleans up both classes - I'm asking for review and comments because it is a reasonably big change to BasicToolTipUI and it is possible that I've missed something. Here is the ChangeLog:

2005-10-04  David Gilbert  <address@hidden>

        * javax/swing/plaf/basic/BasicToolTipUI.java
        (accText): removed,
        (accDeliminator): removed,
        (accFont): removed,
        (accFore): removed,
        (getPreferredSize): removed accelerator code (now in MetalToolTipUI),
        (getAcceleratorText): removed (equivalent is now in MetalToolTipUI),
        (paint): removed accelerator painting,
        * javax/swing/plaf/metal/MetalToolTipUI.java
        (padSpaceBetweenStrings): new field,
        (MetalToolTipUI): initialise defaults,
        (getAcceleratorString): new method,
        (installUI): new method,
        (uninstallUI): new method,
        (isAcceleratorHidden): new method,
        (getPreferredSize): new method,
        (paint): new method,
        (fetchAcceleratorString): new private method,
        (acceleratorToString): new private method,
        * examples/gnu/classpath/examples/swing/Demo.java
        (mkButton): set tool tip.

Comments?

Regards,

Dave

Index: examples/gnu/classpath/examples/swing/Demo.java
===================================================================
RCS file: 
/cvsroot/classpath/classpath/examples/gnu/classpath/examples/swing/Demo.java,v
retrieving revision 1.21
diff -u -r1.21 Demo.java
--- examples/gnu/classpath/examples/swing/Demo.java     12 Sep 2005 23:04:55 
-0000      1.21
+++ examples/gnu/classpath/examples/swing/Demo.java     4 Oct 2005 11:21:02 
-0000
@@ -317,6 +317,7 @@
     else
       b = new JButton(title, icon);
     
+    b.setToolTipText(title);
     if (hAlign != -1) b.setHorizontalAlignment(hAlign);
     if (vAlign != -1) b.setVerticalAlignment(vAlign);
     if (hPos != -1) b.setHorizontalTextPosition(hPos);
Index: javax/swing/plaf/basic/BasicToolTipUI.java
===================================================================
RCS file: 
/cvsroot/classpath/classpath/javax/swing/plaf/basic/BasicToolTipUI.java,v
retrieving revision 1.8
diff -u -r1.8 BasicToolTipUI.java
--- javax/swing/plaf/basic/BasicToolTipUI.java  27 Sep 2005 18:50:58 -0000      
1.8
+++ javax/swing/plaf/basic/BasicToolTipUI.java  4 Oct 2005 11:21:10 -0000
@@ -1,5 +1,5 @@
 /* BasicToolTipUI.java --
-   Copyright (C) 2004 Free Software Foundation, Inc.
+   Copyright (C) 2004, 2005 Free Software Foundation, Inc.
 
 This file is part of GNU Classpath.
 
@@ -42,17 +42,12 @@
 import java.awt.Dimension;
 import java.awt.FontMetrics;
 import java.awt.Graphics;
-import java.awt.Font;
 import java.awt.Insets;
-import java.awt.event.KeyEvent;
 import java.awt.Rectangle;
 import java.awt.Toolkit;
-import java.awt.event.InputEvent;
 
 import javax.swing.JComponent;
 import javax.swing.JToolTip;
-import javax.swing.JMenuItem;
-import javax.swing.KeyStroke;
 import javax.swing.SwingConstants;
 import javax.swing.SwingUtilities;
 import javax.swing.UIDefaults;
@@ -72,19 +67,6 @@
   /** The tooltip's text */
   private String text;
 
-  /** The accelerator's text */
-  private String accText;
-
-  /** The accelerator's deliminator */
-  private String accDeliminator;
-
-  /** The accelerator's font */
-  private Font accFont;
-
-  /** The accelerator's foreground color */
-  private Color accFore;
-    
-
   /**
    * Creates a new BasicToolTipUI object.
    */
@@ -95,7 +77,7 @@
 
   /**
    * This method creates a new BasicToolTip UI for the given 
-        * JComponent.
+   * JComponent.
    *
    * @param c The JComponent to create a UI for.
    *
@@ -103,9 +85,9 @@
    */
   public static ComponentUI createUI(JComponent c)
   {
-               if (shared == null)
-                       shared = new BasicToolTipUI();
-               return shared;
+    if (shared == null)
+      shared = new BasicToolTipUI();
+    return shared;
   }
 
   /**
@@ -146,36 +128,6 @@
     Toolkit g = tip.getToolkit();
     text = tip.getTipText();
     
-    // accelerator
-    JComponent component = tip.getComponent();
-    if (component instanceof JMenuItem)
-      {
-        JMenuItem item = (JMenuItem) component;
-        KeyStroke acc = item.getAccelerator();
-        String tipText = item.getToolTipText();
-        int mne = item.getMnemonic();
-
-        if (acc == null && mne > 0)
-          acc = KeyStroke.getKeyStroke(Character.toUpperCase((char) mne), 
-                                       InputEvent.ALT_MASK, false);
-        if (tipText != null && acc != null)
-          {
-            UIDefaults defaults = UIManager.getLookAndFeelDefaults();
-            accFore = defaults.getColor("MenuItem.acceleratorForeground");
-            accDeliminator = 
defaults.getString("MenuItem.acceleratorDelimiter");
-            accFont = defaults.getFont("MenuItem.acceleratorFont");
-            accText = getAcceleratorText(acc);
-            text = tipText + "  " + accText;
-          }
-        else
-          {
-            accFore = null;
-            accDeliminator = null;
-            accFont = null;
-            accText = null;
-          }
-      }
-    
     Rectangle vr = new Rectangle();
     Rectangle ir = new Rectangle();
     Rectangle tr = new Rectangle();
@@ -189,32 +141,7 @@
     return new Dimension(insets.left + tr.width + insets.right,
                          insets.top + tr.height + insets.bottom);
   }
-  
-  /**
-   * Return text representation of the specified accelerator
-   * 
-   * @param accelerator
-   *          Accelerator for which to return string representation
-   * @return $String$ Text representation of the given accelerator
-   */
-  private String getAcceleratorText(KeyStroke accelerator)
-  {
-    // convert keystroke into string format
-    String modifiersText = "";
-    int modifiers = accelerator.getModifiers();
-    char keyChar = accelerator.getKeyChar();
-    int keyCode = accelerator.getKeyCode();
-    
-    if (modifiers != 0)
-      modifiersText = KeyEvent.getKeyModifiersText(modifiers)
-                      + accDeliminator;
-
-    if (keyCode == KeyEvent.VK_UNDEFINED)
-      return modifiersText + keyChar;
-    else
-      return modifiersText + KeyEvent.getKeyText(keyCode);
-  }
-  
+
   /**
    * This method installs the defaults for the given JComponent.
    *
@@ -280,17 +207,6 @@
     g.setColor(Color.BLACK);
 
     g.drawString(text, vr.x, vr.y + ascent); 
-    
-    // paint accelerator
-    if (accText != null)
-      {
-        g.setColor(accFore);
-        int textWidth = fm.stringWidth(text + "  ");
-        
-        fm = t.getFontMetrics(accFont);
-        int width = fm.stringWidth(accText);
-        g.drawString(accText, textWidth, vr.y + ascent);
-      }
 
     g.setColor(saved);   
   }
Index: javax/swing/plaf/metal/MetalToolTipUI.java
===================================================================
RCS file: 
/cvsroot/classpath/classpath/javax/swing/plaf/metal/MetalToolTipUI.java,v
retrieving revision 1.2
diff -u -r1.2 MetalToolTipUI.java
--- javax/swing/plaf/metal/MetalToolTipUI.java  2 Jul 2005 20:32:51 -0000       
1.2
+++ javax/swing/plaf/metal/MetalToolTipUI.java  4 Oct 2005 11:21:12 -0000
@@ -38,32 +38,92 @@
 
 package javax.swing.plaf.metal;
 
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.awt.Insets;
+import java.awt.Rectangle;
+import java.awt.Toolkit;
+import java.awt.event.InputEvent;
+import java.awt.event.KeyEvent;
+
+import javax.swing.AbstractButton;
 import javax.swing.JComponent;
+import javax.swing.JMenuItem;
+import javax.swing.JToolTip;
+import javax.swing.KeyStroke;
+import javax.swing.SwingConstants;
+import javax.swing.SwingUtilities;
+import javax.swing.UIDefaults;
+import javax.swing.UIManager;
+import javax.swing.border.Border;
 import javax.swing.plaf.ComponentUI;
+import javax.swing.plaf.UIResource;
 import javax.swing.plaf.basic.BasicToolTipUI;
 
+/**
+ * A UI delegate for the address@hidden JToolTip} class.
+ */
 public class MetalToolTipUI
   extends BasicToolTipUI
 {
+  /** 
+   * The amount of space between the tool tip text and the accelerator 
+   * description (if visible). 
+   */
+  public static final int padSpaceBetweenStrings = 12;
 
-  // FIXME: maybe replace by a Map of instances when this becomes stateful
-  /** The shared UI instance for MetalToolTipUIs */
+  /** The shared UI instance. */
   private static MetalToolTipUI instance = null;
-
+  
+  /** A flag controlling the visibility of the accelerator (if there is one). 
*/
+  private boolean isAcceleratorHidden;
+  
+  /** A string representing the accelerator key for the component. */
+  private String acceleratorString;
+  
+  /** 
+   * The delimiter for the accelerator string.
+   */
+  private String acceleratorDelimiter;
+  
+  /** The font for the accelerator string. */
+  private Font acceleratorFont;
+  
+  /** The color for the accelerator string. */
+  private Color acceleratorForeground;
+  
+  /** The active border. */
+  private Border activeBorder;
+  
+  /** The inactive border. */
+  private Border inactiveBorder;
+  
   /**
-   * Constructs a new instance of MetalToolTipUI.
+   * Constructs a new instance of <code>MetalToolTipUI</code>.
    */
   public MetalToolTipUI()
   {
     super();
+    UIDefaults defaults = UIManager.getLookAndFeelDefaults();
+    activeBorder = defaults.getBorder("ToolTip.border");
+    inactiveBorder = defaults.getBorder("ToolTip.borderInactive");
+    isAcceleratorHidden = defaults.getBoolean("ToolTip.hideAccelerator");
+    acceleratorFont = defaults.getFont("MenuItem.acceleratorFont");
+    acceleratorForeground = 
defaults.getColor("MenuItem.acceleratorForeground");
+    acceleratorDelimiter = defaults.getString("MenuItem.acceleratorDelimiter");
   }
 
   /**
-   * Returns an instance of MetalToolTipUI.
+   * Returns a shared instance of the <code>MetalToolTipUI</code> class.
+   * Although this UI delegate does maintain state information, there is never
+   * more than one tool tip visible, so it is OK to use a shared instance.
    *
-   * @param component the component for which we return an UI instance
+   * @param component  the component (a address@hidden JToolTip}).
    *
-   * @return an instance of MetalToolTipUI
+   * @return A shared instance of the <code>MetalToolTipUI</code> class.
    */
   public static ComponentUI createUI(JComponent component)
   {
@@ -71,4 +131,199 @@
       instance = new MetalToolTipUI();
     return instance;
   }
+  
+  /**
+   * Returns a string representing the accelerator key (if there is one) for 
+   * the component that the tool tip belongs to.
+   * 
+   * @return A string representing the accelerator key.
+   */
+  public String getAcceleratorString()
+  {
+    return acceleratorString;   
+  }
+  
+  /**
+   * Installs the UI for the specified component (a address@hidden JToolTip}).
+   * 
+   * @param c  the address@hidden JToolTip} component.
+   */
+  public void installUI(JComponent c)
+  {
+    super.installUI(c);
+    Border existingBorder = c.getBorder();
+    if (existingBorder == null || existingBorder instanceof UIResource)
+      {
+        if (c.isEnabled())
+          c.setBorder(activeBorder);
+        else
+          c.setBorder(inactiveBorder);
+      }   
+  }
+  
+  /**
+   * Clears the defaults set in address@hidden #installUI(JComponent)}.
+   * 
+   * @param c  the component.
+   */
+  public void uninstallUI(JComponent c)
+  {
+    super.uninstallUI(c);
+    if (c.getBorder() instanceof UIResource)
+      c.setBorder(null);
+  }
+  
+  /**
+   * Returns <code>true</code> if the accelerator string is hidden, and
+   * <code>false</code> otherwise.  This setting is controlled by the
+   * <code>ToolTip.hideAccelerator</code> entry in the UI defaults table.
+   *
+   * @return A boolean.
+   */
+  protected boolean isAcceleratorHidden()
+  {
+    return isAcceleratorHidden;
+  }
+  
+  /**
+   * Returns the preferred size for the address@hidden JToolTip} component.
+   * 
+   * @param c  the component (a address@hidden JToolTip}).
+   * 
+   * @return The preferred size.
+   */
+  public Dimension getPreferredSize(JComponent c)
+  {
+    if (isAcceleratorHidden())
+      return super.getPreferredSize(c);
+    else
+      {
+        Insets insets = c.getInsets();
+        JToolTip tt = (JToolTip) c;
+        String tipText = tt.getTipText();
+        if (tipText != null)
+          {
+            FontMetrics fm = c.getFontMetrics(c.getFont());
+            int prefH = fm.getHeight() + insets.top + insets.bottom;
+            int prefW = fm.stringWidth(tipText) + insets.left + insets.right;
+
+            // this seems to be the first opportunity we have to get the 
+            // accelerator string from the component (if it has one)
+            acceleratorString = fetchAcceleratorString(c);
+            if (acceleratorString != null)
+              {
+                prefW += padSpaceBetweenStrings;
+                fm = c.getFontMetrics(acceleratorFont);
+                prefW += fm.stringWidth(acceleratorString);                
+              }
+            return new Dimension(prefW, prefH);  
+          }
+        else return new Dimension(0, 0);
+      }
+  }
+  
+  /**
+   * Paints the tool tip.
+   * 
+   * @param g  the graphics context.
+   * @param c  the address@hidden JToolTip} component.
+   */
+  public void paint(Graphics g, JComponent c)
+  {
+    JToolTip tip = (JToolTip) c;
+
+    String text = tip.getTipText();
+    Toolkit t = tip.getToolkit();
+    if (text == null)
+      return;
+
+    Rectangle vr = new Rectangle();
+    vr = SwingUtilities.calculateInnerArea(tip, vr);
+    Rectangle ir = new Rectangle();
+    Rectangle tr = new Rectangle();
+    FontMetrics fm = t.getFontMetrics(tip.getFont());
+    int ascent = fm.getAscent();
+    SwingUtilities.layoutCompoundLabel(tip, fm, text, null, 
+            SwingConstants.CENTER, SwingConstants.LEFT,
+            SwingConstants.CENTER, SwingConstants.CENTER, vr, ir, tr, 0);
+    Color saved = g.getColor();
+    g.setColor(Color.BLACK);
+
+    g.drawString(text, vr.x, vr.y + ascent); 
+    
+    // paint accelerator
+    if (acceleratorString != null)
+      {
+        g.setFont(acceleratorFont);
+        g.setColor(acceleratorForeground);
+        fm = t.getFontMetrics(acceleratorFont);
+        int width = fm.stringWidth(acceleratorString);
+        g.drawString(acceleratorString, vr.x + vr.width - width, 
+                vr.y + vr.height - fm.getDescent());
+      }
+
+    g.setColor(saved);   
+  }
+  
+  /**
+   * Returns a string representing the accelerator for the component, or 
+   * <code>null</code> if the component has no accelerator.
+   * 
+   * @param c  the component.
+   * 
+   * @return A string representing the accelerator (possibly 
+   *         <code>null</code>).
+   */
+  private String fetchAcceleratorString(JComponent c)
+  {
+    String result = null;
+    if (c instanceof JToolTip)
+      {
+        JToolTip toolTip = (JToolTip) c;
+        JComponent component = toolTip.getComponent();
+        KeyStroke ks = null;
+        if (component instanceof JMenuItem)
+          {
+            JMenuItem item = (JMenuItem) component;
+            ks = item.getAccelerator();
+          }
+        else if (component instanceof AbstractButton)
+          {
+            AbstractButton button = (AbstractButton) component;
+            int mne = button.getMnemonic();
+            if (mne > 0)
+              ks = KeyStroke.getKeyStroke(Character.toUpperCase((char) mne), 
+                    InputEvent.ALT_MASK, false);
+          }
+        if (ks != null)
+          result = acceleratorToString(ks);
+      }
+    return result;
+  }
+  
+  /**
+   * Returns a string representing an accelerator.
+   * 
+   * @param accelerator  the accelerator (<code>null</code> not permitted).
+   * 
+   * @return A string representing an accelerator.
+   */
+  private String acceleratorToString(KeyStroke accelerator)
+  {
+    // convert keystroke into string format
+    String modifiersText = "";
+    int modifiers = accelerator.getModifiers();
+    char keyChar = accelerator.getKeyChar();
+    int keyCode = accelerator.getKeyCode();
+    
+    if (modifiers != 0)
+      modifiersText = KeyEvent.getKeyModifiersText(modifiers) 
+          + acceleratorDelimiter;
+
+    if (keyCode == KeyEvent.VK_UNDEFINED)
+      return modifiersText + keyChar;
+    else
+      return modifiersText + KeyEvent.getKeyText(keyCode);
+  }
+
 }

reply via email to

[Prev in Thread] Current Thread [Next in Thread]