Author: sletellier Date: 2010-12-01 17:42:44 +0100 (Wed, 01 Dec 2010) New Revision: 315 Url: http://nuiton.org/repositories/revision/nuiton-widgets/315 Log: Allow to create a focusable tooltip with a specific component inside Added: trunk/src/test/java/org/nuiton/widget/toolTip/ trunk/src/test/java/org/nuiton/widget/toolTip/FocusableToolTipTest.java Modified: trunk/src/main/java/org/nuiton/widget/tooltip/FocusableTip.java trunk/src/main/java/org/nuiton/widget/tooltip/TipUtil.java trunk/src/main/java/org/nuiton/widget/tooltip/TipWindow.java Modified: trunk/src/main/java/org/nuiton/widget/tooltip/FocusableTip.java =================================================================== --- trunk/src/main/java/org/nuiton/widget/tooltip/FocusableTip.java 2010-11-21 14:30:46 UTC (rev 314) +++ trunk/src/main/java/org/nuiton/widget/tooltip/FocusableTip.java 2010-12-01 16:42:44 UTC (rev 315) @@ -57,12 +57,15 @@ */ public class FocusableTip { + public static final String DUMMY_TOOL_TIP = "DUMMY"; + protected JComponent attachedComponent; protected TipWindow tipWindow; protected URL imageBase; protected AttachedComponentListener attachedComponentListener; protected HyperlinkListener hyperlinkListener; protected String lastText; + protected Component lastComponent; protected boolean showCopyContextMenu; /** Width with default value. */ @@ -124,6 +127,8 @@ attachedComponentListener = new AttachedComponentListener(); tipVisibleBounds = new Rectangle(); this.showCopyContextMenu = showCopyContextMenu; + + attachedComponent.setToolTipText(" "); } /** @@ -162,12 +167,17 @@ } - protected void createAndShowTipWindow(final MouseEvent e, final String text) { + protected void createAndShowTipWindow(final MouseEvent e, final Component component, final String text) { Window owner = SwingUtilities.getWindowAncestor(attachedComponent); - tipWindow = new TipWindow(owner, this, text); - tipWindow.setHyperlinkListener(hyperlinkListener); + if (component == null) { + tipWindow = new TipWindow(owner, this, text); + } else { + tipWindow = new TipWindow(owner, this, component); + } + tipWindow.setHyperlinkListener(hyperlinkListener); + // TODO: Position tip window better (handle RTL, edges of screen, etc.). // Wrap in an invokeLater() to work around a JEditorPane issue where it // doesn't return its proper preferred size until after it is displayed. @@ -186,7 +196,7 @@ } // Add copy context menu - if (showCopyContextMenu) { + if (showCopyContextMenu && component == null) { TipUtil.addCopyContextMenu(tipWindow); } @@ -215,7 +225,7 @@ computeTipVisibleBounds(); // Do after tip is visible attachedComponentListener.install(attachedComponent); lastText = text; - + lastComponent = component; } }); @@ -254,6 +264,7 @@ attachedComponentListener.uninstall(); tipVisibleBounds.setBounds(-1, -1, 0, 0); lastText = null; + lastComponent = null; attachedComponent.requestFocus(); } } @@ -282,7 +293,6 @@ ToolTipManager.sharedInstance().registerComponent(attachedComponent); } - public void toolTipRequested(MouseEvent e, String text) { if (text==null || text.length()==0) { @@ -294,12 +304,32 @@ if (lastText==null || text.length()!=lastText.length() || !text.equals(lastText)) { possiblyDisposeOfTipWindow(); - createAndShowTipWindow(e, text); + createAndShowTipWindow(e, null, text); } } + /* + * To display specific component in toolTip + * + * Note : Be carfull, set toolTipText of attachedComponent.setToolTipText(FocusableTip.DUMMY_TOOL_TIP); + */ + public void toolTipRequested(MouseEvent e, Component component) { + if (component == null) { + possiblyDisposeOfTipWindow(); + lastComponent = component; + return; + } + + if (lastComponent==null || !lastComponent.equals(component)) { + possiblyDisposeOfTipWindow(); + createAndShowTipWindow(e, component, null); + } + + } + + protected class AttachedComponentListener extends MouseInputAdapter implements CaretListener, ComponentListener, FocusListener, KeyListener { Modified: trunk/src/main/java/org/nuiton/widget/tooltip/TipUtil.java =================================================================== --- trunk/src/main/java/org/nuiton/widget/tooltip/TipUtil.java 2010-11-21 14:30:46 UTC (rev 314) +++ trunk/src/main/java/org/nuiton/widget/tooltip/TipUtil.java 2010-12-01 16:42:44 UTC (rev 315) @@ -25,6 +25,7 @@ package org.nuiton.widget.tooltip; import java.awt.Color; +import java.awt.Component; import java.awt.Font; import java.awt.SystemColor; import java.awt.Toolkit; @@ -148,8 +149,8 @@ throw new NullPointerException("TipWindows must be non null"); } - JEditorPane textArea = tipWindows.getTextArea(); - textArea.addMouseListener(new MouseAdapter(){ + Component component = tipWindows.getComponent(); + component.addMouseListener(new MouseAdapter(){ @Override public void mouseClicked(MouseEvent e) { Modified: trunk/src/main/java/org/nuiton/widget/tooltip/TipWindow.java =================================================================== --- trunk/src/main/java/org/nuiton/widget/tooltip/TipWindow.java 2010-11-21 14:30:46 UTC (rev 314) +++ trunk/src/main/java/org/nuiton/widget/tooltip/TipWindow.java 2010-12-01 16:42:44 UTC (rev 315) @@ -69,34 +69,26 @@ public class TipWindow extends JWindow implements ActionListener { protected FocusableTip ft; - protected JEditorPane textArea; + protected Component component; protected String text; protected TipListener tipListener; protected HyperlinkListener userHyperlinkListener; protected static TipWindow visibleInstance; - /** - * Constructor. + * Constructor, by default, is JEditorPane will be used for toolTip. * * @param owner The parent window. * @param ft Focusable tip * @param msg The text of the tool tip. This can be HTML. */ public TipWindow(Window owner, FocusableTip ft, String msg) { - super(owner); this.ft = ft; - this.text = msg; tipListener = new TipListener(); - JPanel cp = new JPanel(new BorderLayout()); - cp.setBorder(BorderFactory.createCompoundBorder(BorderFactory - .createLineBorder(Color.BLACK), BorderFactory - .createEmptyBorder())); - cp.setBackground(TipUtil.getToolTipBackground()); - textArea = new JEditorPane("text/html", msg); + JEditorPane textArea = new JEditorPane("text/html", msg); TipUtil.tweakTipEditorPane(textArea); if (ft.getImageBase()!=null) { // Base URL for images ((HTMLDocument)textArea.getDocument()).setBase(ft.getImageBase()); @@ -109,8 +101,34 @@ } } }); - cp.add(textArea); + init(ft, textArea); + } + /** + * To specify component to display + * + * @param owner The parent window. + * @param ft Focusable tip + * @param component custom component to display + */ + public TipWindow(Window owner, FocusableTip ft, Component component) { + super(owner); + init(ft, component); + } + + protected void init(FocusableTip ft, Component component) { + this.ft = ft; + tipListener = new TipListener(); + this.component = component; + + JPanel cp = new JPanel(new BorderLayout()); + cp.setBorder(BorderFactory.createCompoundBorder(BorderFactory + .createLineBorder(Color.BLACK), BorderFactory + .createEmptyBorder())); + cp.setBackground(TipUtil.getToolTipBackground()); + component.addMouseListener(tipListener); + cp.add(component); + setFocusableWindowState(false); setContentPane(cp); setBottomPanel(); // Must do after setContentPane() @@ -126,7 +144,7 @@ } }; addKeyListener(ka); - textArea.addKeyListener(ka); + component.addKeyListener(ka); // Ensure only 1 TipWindow is ever visible. If the caller does what // they're supposed to and only creates these on the EDT, the @@ -137,16 +155,15 @@ } visibleInstance = this; } + } - } - /** * Return textArea of TipWindow * * @return textArea */ - public JEditorPane getTextArea() { - return textArea; + public Component getComponent() { + return component; } public void actionPerformed(ActionEvent e) { @@ -154,7 +171,7 @@ if (!getFocusableWindowState()) { setFocusableWindowState(true); setBottomPanel(); - textArea.removeMouseListener(tipListener); + component.removeMouseListener(tipListener); pack(); addWindowFocusListener(new WindowAdapter() { public void windowLostFocus(WindowEvent e) { @@ -196,26 +213,33 @@ */ public void fixSize(int width, int height) { - Dimension d = textArea.getPreferredSize(); - Rectangle r; - try { +// Dimension d = textArea.getPreferredSize(); +// Rectangle r; +// try { +// +// r = textArea.modelToView(textArea.getDocument().getLength()-1); +// d.height = r.y + r.height; +// +// // Ensure the text area doesn't start out too tall or wide. +// d = textArea.getPreferredSize(); +// d.width = Math.min(d.width+25, width); +// d.height = Math.min(d.height, height); +// +// textArea.setPreferredSize(d); +// +// } catch (BadLocationException ble) { // Never happens +// ble.printStackTrace(); +// } +// +// pack(); // Must re-pack to calculate proper size. - r = textArea.modelToView(textArea.getDocument().getLength()-1); - d.height = r.y + r.height; - - // Ensure the text area doesn't start out too tall or wide. - d = textArea.getPreferredSize(); - d.width = Math.min(d.width+25, width); - d.height = Math.min(d.height, height); - - textArea.setPreferredSize(d); - - } catch (BadLocationException ble) { // Never happens - ble.printStackTrace(); - } - - pack(); // Must re-pack to calculate proper size. - + // Use specified size + Dimension d = component.getPreferredSize(); + d.height = width; + d.width = height; + component.setPreferredSize(d); + component.setSize(d); + pack(); } @@ -262,7 +286,7 @@ panel.setOpaque(false); JLabel label = new JLabel(_("nuitonwidgets.tootilp.focushotkey")/*FocusableTip.getString("FocusHotkey")*/); Color fg = UIManager.getColor("Label.disabledForeground"); - Font font = textArea.getFont(); + Font font = component.getFont(); font = font.deriveFont(font.getSize2D() - 1.0f); label.setFont(font); if (fg==null) { // Non BasicLookAndFeel-derived Looks @@ -285,8 +309,8 @@ cp.remove(0); JScrollPane sp = new JScrollPane(comp); sp.setViewportBorder(BorderFactory.createEmptyBorder()); - sp.setBackground(textArea.getBackground()); - sp.getViewport().setBackground(textArea.getBackground()); + sp.setBackground(component.getBackground()); + sp.getViewport().setBackground(component.getBackground()); cp.add(sp); // What was component 1 is now 0. cp.getComponent(0).removeMouseListener(tipListener); @@ -305,14 +329,18 @@ * removed. A value of <code>null</code> means "no listener." */ public void setHyperlinkListener(HyperlinkListener listener) { - // We've added a separate listener, so remove only the user's. - if (userHyperlinkListener!=null) { - textArea.removeHyperlinkListener(userHyperlinkListener); - } - userHyperlinkListener = listener; - if (userHyperlinkListener!=null) { - textArea.addHyperlinkListener(userHyperlinkListener); - } + if (component instanceof JEditorPane) { + JEditorPane textArea = (JEditorPane)component; + + // We've added a separate listener, so remove only the user's. + if (userHyperlinkListener!=null) { + textArea.removeHyperlinkListener(userHyperlinkListener); + } + userHyperlinkListener = listener; + if (userHyperlinkListener!=null) { + textArea.addHyperlinkListener(userHyperlinkListener); + } + } } Added: trunk/src/test/java/org/nuiton/widget/toolTip/FocusableToolTipTest.java =================================================================== --- trunk/src/test/java/org/nuiton/widget/toolTip/FocusableToolTipTest.java (rev 0) +++ trunk/src/test/java/org/nuiton/widget/toolTip/FocusableToolTipTest.java 2010-12-01 16:42:44 UTC (rev 315) @@ -0,0 +1,68 @@ +package org.nuiton.widget.toolTip; + +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JTree; +import javax.swing.WindowConstants; +import org.nuiton.widget.tooltip.FocusableTip; + +import java.awt.BorderLayout; +import java.awt.event.MouseEvent; + +/** + * @author sletellier + */ +public class FocusableToolTipTest { + + public void testDummy() { + } + + public static void main(String[] args) throws Exception { + JFrame frame = new JFrame("FocusableToolTip"); + frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); + frame.getContentPane().setLayout(new BorderLayout()); + + JLabel simpleToolTipLabel = new JLabel("Simple tool tip text") { + protected FocusableTip focusableTip; + + @Override + public String getToolTipText(MouseEvent event) { + String toolTipText = super.getToolTipText(event); + + // display it into persistant tooltip + if (focusableTip == null) { + focusableTip = new FocusableTip(this, true); + focusableTip.setSize(600, 400); + } + focusableTip.toolTipRequested(event, toolTipText); + + return null; + } + }; + simpleToolTipLabel.setToolTipText("Simple tool tip text<p><b>is Working !</b>"); + frame.getContentPane().add(simpleToolTipLabel, BorderLayout.NORTH); + + JLabel complexeToolTipLabel = new JLabel("Complexe tool tip text") { + protected FocusableTip focusableTip; + + @Override + public String getToolTipText(MouseEvent event) { + super.getToolTipText(event); + + // display it into persistant tooltip + if (focusableTip == null) { + focusableTip = new FocusableTip(this, true); + focusableTip.setSize(600, 400); + } + focusableTip.toolTipRequested(event, new JTree()); + + return null; + } + }; + complexeToolTipLabel.setToolTipText(FocusableTip.DUMMY_TOOL_TIP); + frame.getContentPane().add(complexeToolTipLabel, BorderLayout.CENTER); + + frame.setVisible(true); + frame.pack(); + } +}