/* * Copyright (C) 2015 Jack Jiang(cngeeker.com) The Swing9patch Project. * All rights reserved. * Project URL:https://github.com/JackJiang2011/Swing9patch * Version 1.0 * * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. * * FloatableDialog.java at 2015-2-6 16:10:04, original version by Jack Jiang. * You can contact author with [email protected]. */ package org.jb2011.swing9patch.fixtip; import java.awt.BorderLayout; import java.awt.Dialog; import java.awt.Point; import java.awt.Window; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ComponentAdapter; import java.awt.event.ComponentEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import javax.swing.JComponent; import javax.swing.JDialog; import javax.swing.JPanel; import javax.swing.JRootPane; import javax.swing.SwingUtilities; import javax.swing.Timer; import com.sun.awt.AWTUtilities; /** * A floatable dialog, who can auto relocation to parent. * * @author Jack Jiang([email protected]), 2012-11-03 * @version 1.0 */ public class FloatableDialog extends JDialog implements ActionListener { /** The parent component, this dialog will relative to it */ private JComponent parentCom = null; /** The content component of this dialog */ private JComponent contentCom = null; /** Delta x to show this dialog(value it's vector) */ private int deltaX = 0; /** Delta y to show this dialog(value it's vector) */ private int deltaY = 0; /** false means dispose dialog on close, else just setVisible(false) */ private boolean invisibleOnDispose = false; /** Timing to dispose */ private Timer timer = null; /** * Default constructor. * * @param parent The parent window instance of this dialog, it should be not null */ public FloatableDialog(Window parent) { super(parent, Dialog.ModalityType.MODELESS); initGUI(); initListeners(parent); timer = new Timer(3000, this);// dispose in 3 second } protected void initGUI() { // set dialog full transparent setUndecorated(true); AWTUtilities.setWindowOpaque(this, false); this.getRootPane().setWindowDecorationStyle(JRootPane.NONE); // init gui JPanel contentPane = new JPanel(); contentPane.setLayout(new BorderLayout(0, 0)); contentPane.setOpaque(false); setContentPane(contentPane); // others setup this.setFocusable(false); this.setFocusableWindowState(false); // this.setAlwaysOnTop(true); this.setVisible(false); } protected void initListeners(Window parent) { // add listeners addMouseListener(new MouseAdapter(){ @Override public void mouseReleased(MouseEvent e) { exit(); } }); parent.addWindowListener(new WindowAdapter(){ @Override public void windowClosed(WindowEvent e) { exit(); } }); parent.addComponentListener(new ComponentAdapter() { @Override public void componentMoved(ComponentEvent e){ FloatableDialog.this.refreshLocation(); } }); } @Override public void actionPerformed(ActionEvent e) { exit(); timer.stop(); } /** * Show this dialog. * * <p> * This method invoke {@link #refreshLocation()} first, and then * set this.setVisible(true). * * @see #refreshLocation() */ public void display() { if(refreshLocation()) this.setVisible(true); timer.start(); } /** * Exit this dialog. * * <p> * If invisibleOnDispose == true then this.setVisible(false), * else this.dispose(). * * @see #isInvisibleOnDispose() */ public void exit() { if(invisibleOnDispose) this.setVisible(false); else this.dispose(); } /** * Reset location of this dialog and sync to its parent. * * @return true means refresh sucess, else failed * @exception IllegalArgumentException means parentCom or contentCom is null */ public boolean refreshLocation() { if(parentCom != null && contentCom != null) { Point location = SwingUtilities.convertPoint(parentCom, getLocation(), this); setBounds(location.x + deltaX, (location.y + deltaY) - getPreferredSize().height, getPreferredSize().width, getPreferredSize().height); validate(); return true; } else throw new IllegalArgumentException("parentCom or contentCom is null!"); } public void setContentCom(JComponent contentCom) { this.contentCom = contentCom; this.getContentPane().removeAll(); this.getContentPane().add(this.contentCom, BorderLayout.CENTER); } public JComponent getParentCom() { return parentCom; } public void setParentCom(JComponent parentCom) { this.parentCom = parentCom; } public int getDeltaX() { return deltaX; } public void setDeltaX(int deltaX) { this.deltaX = deltaX; } public int getDeltaY() { return deltaY; } public void setDeltaY(int deltaY) { this.deltaY = deltaY; } public boolean isInvisibleOnDispose() { return invisibleOnDispose; } public void setInvisibleOnDispose(boolean invisibleOnDispose) { this.invisibleOnDispose = invisibleOnDispose; } /** * A convenient method to create a new FloatableDialog instance. * * @param contentCom The content component of this dialog * @param parentWindow The parent window instance of this dialog, it should be not null * @param parentCom The parent component, this dialog will relative to it * @return A new FloatableDialog object */ public static FloatableDialog createDialog(JComponent contentCom , Window parentWindow, JComponent parentCom) { final FloatableDialog d = new FloatableDialog(parentWindow); d.setContentCom(contentCom); d.setParentCom(parentCom); return d; } }