2 messages in net.java.dev.jna.usersBalloon Tip Code
FromSent OnAttachments
Timothy WallMay 31, 2007 4:05 pm 
mdte...@aim.comJun 1, 2007 10:56 am.java
Actions with this message:
Paste this link in email or IM:
Paste this link in email or IM:
Atom feed for this thread
Paste this URL into your reader:
Subject:Balloon Tip CodeActions...
From:mdte...@aim.com (mdte@aim.com)
Date:Jun 1, 2007 10:56:58 am
List:net.java.dev.jna.users
Attachments:

I had been looking for a balloon tip object that I could use for input
validation on text fields when I came across the BalloonManager in the examples
package. I made a modification to the code, along with some input from the swing
ToolTipManager, to make it act more like standard Windows balloon tips.

---------------------------

import java.awt.Color; import java.awt.Component; import java.awt.Dimension; import java.awt.Font; import java.awt.Graphics; import java.awt.Point; import java.awt.Polygon; import java.awt.Rectangle; import java.awt.Shape; import java.awt.Window; import java.awt.event.ActionEvent; import java.awt.event.ComponentAdapter; import java.awt.event.ComponentEvent; import java.awt.event.FocusAdapter; import java.awt.event.FocusEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.geom.Area; import java.awt.geom.RoundRectangle2D;

import javax.swing.AbstractAction; import javax.swing.JLabel; import javax.swing.JWindow; import javax.swing.Popup; import javax.swing.SwingUtilities; import javax.swing.Timer;

import com.sun.jna.examples.WindowUtils;

/**  * The BalloonTipManager class handles creation and disposal of balloon style  * tips that are typically used to display warning/error information based on  * results from input validation.  The balloon tips can be displayed either  * above or below the owner component, and is only displayed for a limited  * amount of time.  The balloon tip is also disposed when the owner component  * loses focus or the mouse is pressed.  */ public class BalloonTipManager {   public static final Integer POSITION_ABOVE = 0;   public static final Integer POSITION_BELOW = 1;     private static final Color BORDER_COLOR = Color.BLACK;   private static final Color BACKGROUND_COLOR = new Color(255, 255, 225);   private static final Color TEXT_COLOR = Color.BLACK;     /*    * The BalloonTip class defines the look of the BalloonTip object.    */   @SuppressWarnings("serial")   private static final class BalloonTip extends JWindow {     private static final Integer HMARGIN = 10;     private static final Integer VMARGIN = 6;     private static final Integer VSPACER = 4;     private static final int ARC_D = 16;         private boolean below = true;     private Area mask = null;     private Dimension maskSize = null;     private String[] textList = null;         private Color backgroundColor = null;     private Color borderColor = null;     private Color textColor = null;         /**      * Create a BalloonTip object.      * @param owner the parent window for the components      * @param content the string for the balloon tip      * @param position the position for the balloon; either above or below the      * owner component      * @param origin the origin point for the balloon tip      * @param bordercolor the background color for the balloon tip      * @param backgroundcolor the border color for the balloon tip      * @param textcolor the text color for the balloon tip      */     public BalloonTip (         Window owner, String content, Integer position, Point origin,         Color bordercolor, Color backgroundcolor, Color textcolor)     {       super(owner);       textList = content.split("\n");       setPosition(position);       borderColor = bordercolor;       backgroundColor = backgroundcolor;       textColor = textcolor;       setFocusableWindowState(false);       setName("###overrideRedirect###");       setSize(getPreferredSize());       mask = new Area(getMask());       maskSize = getSize();       WindowUtils.setWindowMask(BalloonTip.this, mask);     }         /*      * Sets the position for the balloon tip to be either above or below the      * owner component.      */     private void setPosition (Integer position) {       if (position == POSITION_ABOVE) {         below = false;       }       else {         below = true;       }     }         /*      * (non-Javadoc)      * @see java.awt.Container#paint(java.awt.Graphics)      */     public void paint (Graphics g) {       super.paint(g);       Dimension d = getMinimumWindowSize();       int width = d.width + 2 * HMARGIN;       int height = d.height + 2 * VMARGIN;       int x = 0;       int y = 0;       if (below) {         y += 15;       }       // Draw the filled rounded rectangle and clean up the missed pixels.       g.setColor(backgroundColor);       g.fillRoundRect(x, y, width, height, ARC_D, ARC_D);       g.drawLine(x + 6, y + height - 1, x + 6, y + height - 1);       g.drawLine(x + width - 1, y + 6, x + width - 1, y + 6);       g.drawLine(x + width - 1, y + height - 6, x + width - 1, y + height - 7);       g.drawLine(x + width - 2, y + height - 4, x + width - 4, y + height - 2);       g.drawLine(x + width - 6, y + height - 1, x + width - 7, y + height - 1);       g.clearRect(x + 2, y + 2, 1, 1);       // Draw the border of the rounded rectangle.       g.setColor(borderColor);       g.drawRoundRect(x, y, width, height, ARC_D, ARC_D);       // Draw the external triangle for the balloon.       if (below) {         g.setColor(backgroundColor);         int[] xPts = {16, 16, 31};         int[] yPts = {0, 16, 16};         g.fillPolygon(xPts, yPts, 3);         g.setColor(borderColor);         g.drawLine(16, 0, 16, 15);         g.drawLine(16, 0, 31, 15);         g.drawLine(16, 1, 30, 15);       }       else {         g.setColor(backgroundColor);         int[] xPts = {16, 16, 31};         int[] yPts = {height, height + 16, height};         g.fillPolygon(xPts, yPts, 3);         g.setColor(borderColor);         g.drawLine(16, height, 16, height + 15);         g.drawLine(16, height + 15, 31, height);         g.drawLine(16, height + 14, 30, height);       }       // Draw the inner component for the balloon.       g.setColor(textColor);       g.setFont(new Font("Tahoma", Font.PLAIN, 11));       int stringY = y + VMARGIN / 2;       for (int i = 0; i < textList.length; i++) {         stringY += new JLabel(textList[i]).getPreferredSize().height;         if (i > 0) {           stringY += VSPACER;         }         g.drawString(textList[i], HMARGIN, stringY);       }     }         /*      * Returns the mask for the balloon tip window.      */     private Shape getMask () {       Dimension d = getMinimumWindowSize();       int width = d.width + 2 * HMARGIN;       int height = d.height + 2 * VMARGIN;       int x = 0;       int y = 0;       if (below) {         y += 15;       }       // Start by creating the area of the main rounded rectangle.       Area area = new Area(         new RoundRectangle2D.Float(x, y, width + 1, height + 1, ARC_D, ARC_D));       // Add in the remaining pixels that are not included by default due to       // the differences between Graphics drawing and Shape creation.       area.add(new Area(new Rectangle(0, y + 6, 1, 2)));       area.add(new Area(new Rectangle(0, y + height - 7, 1, 2)));       area.add(new Area(new Rectangle(1, y + 4, 1, 1)));       area.add(new Area(new Rectangle(1, y + height - 5, 1, 2)));       area.add(new Area(new Rectangle(4, y + 1, 1, 1)));       area.add(new Area(new Rectangle(6, y, 2, 1)));       area.add(new Area(new Rectangle(width - 7, y, 2, 1)));       // Subtract the extra pixels that are not included by default due to the       // differences between Graphics drawing and Shape creation.       area.subtract(new Area(new Rectangle(2, y + height - 2, 1, 1)));       area.subtract(new Area(new Rectangle(3, y + height - 1, 1, 1)));       area.subtract(new Area(new Rectangle(5, y + height, 1, 1)));       area.subtract(new Area(new Rectangle(width - 5, y + height, 2, 1)));       area.subtract(new Area(new Rectangle(width - 3, y + height - 1, 2, 1)));       area.subtract(new Area(new Rectangle(width - 2, y + 2, 1, 1)));       area.subtract(new Area(new Rectangle(width - 2, y + height - 2, 2, 1)));       area.subtract(new Area(new Rectangle(width - 1, y + 3, 1, 1)));       area.subtract(new Area(new Rectangle(width - 1, y + height - 3, 1, 1)));       area.subtract(new Area(new Rectangle(width, y + 5, 1, 1)));       area.subtract(new Area(new Rectangle(width, y + height - 5, 1, 2)));       // Add in the triangle piece for the balloon.       if (below) {         int[] xPts = {16, 16, 32};         int[] yPts = {-1, 16, 16};         area.add(new Area(new Polygon(xPts, yPts, 3)));       }       else {         int[] xPts = {16, 16, 31};         int[] yPts = {height, height + 16, height};         area.add(new Area(new Polygon(xPts, yPts, 3)));       }       return area;     }         /*      * Returns the dimension of the window based on the preferred component      * sizes.      */     private Dimension getMinimumWindowSize () {       int maxWidth = 0;       int textHeight = 0;       JLabel tempLabel = null;       for (int i = 0; i < textList.length; i++) {         tempLabel = new JLabel(textList[i]);         maxWidth = Math.max(maxWidth, tempLabel.getPreferredSize().width);         textHeight += tempLabel.getPreferredSize().height;       }       int w = Math.max(maxWidth, 32);       int h = Math.max(textHeight + (textList.length - 1) * VSPACER, 8);       return new Dimension(w, h);     }         /*      * (non-Javadoc)      * @see java.awt.Window#setBounds(int, int, int, int)      */     public void setBounds (int x, int y, int w, int h) {       super.setBounds(x, y, w, h);       Dimension size = new Dimension(w, h);       if (mask != null && !size.equals(maskSize)) {         mask.subtract(mask);         mask.add(new Area(getMask()));         maskSize = size;       }     }         /*      * (non-Javadoc)      * @see java.awt.Container#getPreferredSize()      */     public Dimension getPreferredSize () {       Dimension d = getMinimumWindowSize();       int w = d.width + 2 * HMARGIN + 1;       int h = d.height + 2 * VMARGIN + 16;       return new Dimension(w, h);     }

    /**      * Returns whether the balloon is displayed above or below the owner      * component.      * @return true if displayed below the owner component, else false      */     public boolean isBelow () {       return below;     }   }     /**    * Returns the popup window of the balloon tip.    * @param owner the owner component for the balloon tip    * @param content the text string to display in the balloon tip    * @param x the x coordinate for the origin for the balloon tip in relation    * to the owner component    * @param y the y coordinate for the origin for the balloon tip in relation    * to the owner component    * @param position the position for the balloon; either above or below the      * owner component    * @param duration the duration in milliseconds to display balloon tip    * @return the popup window of the balloon tip    */   public static Popup getBalloonTip (final Component owner,       final String content, int x, int y, final int position,       final int duration)   {     return getBalloonTip(owner, content, x, y, position, duration,       BORDER_COLOR, BACKGROUND_COLOR, TEXT_COLOR);   }     /**    * Returns the popup window of the balloon tip.    * @param owner the owner component for the balloon tip    * @param content the text string to display in the balloon tip    * @param x the x coordinate for the origin for the balloon tip in relation    * to the owner component    * @param y the y coordinate for the origin for the balloon tip in relation    * to the owner component    * @param position the position for the balloon; either above or below the      * owner component    * @param duration the duration in milliseconds to display balloon tip    * @param bordercolor the background color for the balloon tip    * @param backgroundcolor the border color for the balloon tip    * @param textcolor the text color for the balloon tip    * @return the popup window of the balloon tip    */   public static Popup getBalloonTip (final Component owner,       final String content, int x, int y, final int position,       final int duration, final Color bordercolor, final Color backgroundcolor,       final Color textcolor)   {     final Point origin =       owner == null ? new Point(0, 0) : owner.getLocationOnScreen();     final Window parent =       owner != null ? SwingUtilities.getWindowAncestor(owner) : null;     origin.translate(x, y);     return new Popup () {       private BalloonTip bt = null;       Timer hidePopupTimer = new Timer(duration, new TimerAction());       final ComponentEar componentEar = new ComponentEar();       final MouseEar mouseEar = new MouseEar();       final FocusEar focusEar = new FocusEar();             /*        * (non-Javadoc)        * @see javax.swing.Popup#show()        */       public void show () {         bt = new BalloonTip(parent, content, position, origin, bordercolor,           backgroundcolor, textcolor);         bt.pack();         Point pt = new Point(origin);         if (bt.isBelow()) {           pt.translate(10, owner.getHeight());         }         else {           pt.translate(10, -bt.getHeight());         }         bt.setLocation(pt);         bt.setVisible(true);         owner.addFocusListener(focusEar);         owner.addMouseListener(mouseEar);         parent.addMouseListener(mouseEar);         parent.addComponentListener(componentEar);         hidePopupTimer.start();       }             /*        * (non-Javadoc)        * @see javax.swing.Popup#hide()        */       public void hide () {         if (bt != null) {           hidePopupTimer.stop();           parent.removeComponentListener(componentEar);           parent.removeMouseListener(mouseEar);           owner.removeMouseListener(mouseEar);           owner.removeFocusListener(focusEar);           bt.setVisible(false);           bt.dispose();         }       }             /*        * This class handles actions from the balloon tip timer.        */       @SuppressWarnings("serial")       final class TimerAction extends AbstractAction {         /*          * (non-Javadoc)          * @see java.awt.event.ActionListener#actionPerformed(          * java.awt.event.ActionEvent)          */         public void actionPerformed (ActionEvent e) {           hide();         }       }             /*        * This class handles events spawned from moving the component.        */       @SuppressWarnings("serial")       final class ComponentEar extends ComponentAdapter {         /*          * (non-Javadoc)          * @see java.awt.event.ComponentAdapter#componentMoved(          * java.awt.event.ComponentEvent)          */         public void componentMoved (ComponentEvent e) {           hide();         }       }             /*        * This class handles events spawned when a mouse button is pressed.        */       @SuppressWarnings("serial")       final class MouseEar extends MouseAdapter {         /*          * (non-Javadoc)          * @see java.awt.event.MouseAdapter#mousePressed(          * java.awt.event.MouseEvent)          */         public void mousePressed (MouseEvent e) {           hide();         }       }

      /*        * This class handles events spawned when the component loses focus.        */       @SuppressWarnings("serial")       final class FocusEar extends FocusAdapter {         /*          * (non-Javadoc)          * @see java.awt.event.FocusAdapter#focusLost(          * java.awt.event.FocusEvent)          */         public void focusLost (FocusEvent e) {           hide();         }       }     };   } }