com.jidesoft.swing.PopupWindow Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jide-oss Show documentation
Show all versions of jide-oss Show documentation
JIDE Common Layer (Professional Swing Components)
/*
* @(#)PopupWindow.java
*
* Copyright 2002 - 2003 JIDE Software. All rights reserved.
*/
package com.jidesoft.swing;
import com.jidesoft.utils.PortingUtils;
import javax.swing.*;
import javax.swing.event.EventListenerList;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
import java.awt.*;
import java.awt.event.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.List;
import java.util.Vector;
/**
* PopupWindow class
*
* You can add another JPopupMenu or JComboxBox in this popup.
*
* This class is copied from http://forum.java.sun.com/thread.jsp?forum=57&thread=230866 with some minor modifications.
*/
public class PopupWindow {
/**
* A list of event listeners for this component.
*/
protected EventListenerList listenerList = new EventListenerList();
private JWindow _delegate;
private Container _container;
private List _grabbed = new Vector();
private List _excluded = new Vector();
private WindowListener _windowListener;
private ComponentListener _componentListener;
private ContainerListener _containerListener;
private MouseListener _mouseListener;
private Component _component;
// JDK 1.3 Porting Hint.
// Use AWTEventListener instead
// private AWTEventListener _keyEventDispatcher;
private KeyEventDispatcher _keyEventDispatcher;
private Component _parent;
public PopupWindow(Container container) {
_container = container;
createDelegate();
createListeners();
}
private void createDelegate() {
Window window = getWindow();
if (window != null) {
_delegate = new JWindow(window);
}
}
public void add(Component component) {
_component = component;
_component.addPropertyChangeListener("preferredSize", new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
if (_delegate != null) {
_delegate.pack();
}
}
});
if (_delegate != null) {
_delegate.getContentPane().add(component);
_delegate.pack();
// workaround for a problem. JWindow somehow offset the height by 1
// See http://developer.java.sun.com/developer/bugParade/bugs/4511106.html
// looks like call pack again solve the problem.
_delegate.pack();
// mDelegate.setSize(mDelegate.getSize().width, mDelegate.getSize().height + 1);
}
}
public void show(Component relative, int x, int y) {
_parent = relative;
if (_delegate == null) {
createDelegate();
if (_delegate == null) return;
add(_component);
}
Point p = new Point(x, y);
SwingUtilities.convertPointToScreen(p, relative);
Rectangle screenSize = PortingUtils.getScreenBounds(relative);
Dimension size = _component.getPreferredSize();
int left = p.x + size.width;
int bottom = p.y + size.height;
if (p.x < screenSize.x) {
p.x = screenSize.x;
}
if (left > screenSize.width) {
p.x = screenSize.width - size.width;
}
if (p.y < screenSize.y) {
p.y = screenSize.y;
}
if (bottom > screenSize.height) {
p.y = screenSize.height - size.height;
}
// Point location = relative.getLocationOnScreen();
_delegate.setLocation(p.x, p.y);
_delegate.setSize(_component.getPreferredSize());
firePopupMenuWillBecomeVisible();
_delegate.setVisible(true);
grabContainers();
// set popup window focus and register esc key
// _delegate.toFront();
// _delegate.requestFocus();
// JDK 1.3 Porting Hint
// Replace by AWTEventListener
// Following Block is for JDK 1.3
// _keyEventDispatcher = new AWTEventListener() {
// public void eventDispatched(AWTEvent e) {
// if (e instanceof KeyEvent) {
// if (((KeyEvent) e).getKeyCode() == KeyEvent.VK_ESCAPE) {
// hide();
// }
// }
// }
// };
// Toolkit.getDefaultToolkit().addAWTEventListener(_keyEventDispatcher, AWTEvent.KEY_EVENT_MASK);
// Following Block is for JDK 1.4
_keyEventDispatcher = new KeyEventDispatcher() {
public boolean dispatchKeyEvent(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
hide();
return true;
}
return false;
}
};
DefaultFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(_keyEventDispatcher);
}
public void hide() {
if (_parent != null) {
_parent.requestFocus();
}
firePopupMenuWillBecomeInvisible();
if (_delegate != null) {
_delegate.setVisible(false);
}
if (_keyEventDispatcher != null) {
// JDK 1.3 Porting Hint
// Replace by AWTEventListener
// Toolkit.getDefaultToolkit().removeAWTEventListener(_keyEventDispatcher);
DefaultFocusManager.getCurrentKeyboardFocusManager().removeKeyEventDispatcher(_keyEventDispatcher);
_keyEventDispatcher = null;
}
releaseContainers();
disposeDelegate();
}
private void createListeners() {
_windowListener = new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
hide();
}
@Override
public void windowClosed(WindowEvent e) {
hide();
}
@Override
public void windowIconified(WindowEvent e) {
hide();
}
};
_componentListener = new ComponentListener() {
public void componentResized(ComponentEvent e) {
hide();
}
public void componentMoved(ComponentEvent e) {
hide();
}
public void componentShown(ComponentEvent e) {
hide();
}
public void componentHidden(ComponentEvent e) {
hide();
}
};
_containerListener = new ContainerListener() {
public void componentAdded(ContainerEvent e) {
hide();
}
public void componentRemoved(ContainerEvent e) {
hide();
}
};
_mouseListener = new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
hide();
}
};
}
private void disposeDelegate() {
if (_delegate != null) {
_delegate.dispose();
_delegate = null;
}
}
private Window getWindow() {
Container c = _container;
if (c == null) {
return null;
}
while (!(c instanceof Window) && c.getParent() != null) c = c.getParent();
if (c instanceof Window) return (Window) c;
return null;
}
private void grabContainers() {
Container c = _container;
while (!(c instanceof Window) && c.getParent() != null)
c = c.getParent();
grabContainer(c);
}
private void grabContainer(Container c) {
if (c instanceof Window) {
((Window) c).addWindowListener(_windowListener);
c.addComponentListener(_componentListener);
_grabbed.add(c);
}
synchronized (c.getTreeLock()) {
int ncomponents = c.getComponentCount();
Component[] component = c.getComponents();
for (int i = 0; i < ncomponents; i++) {
Component comp = component[i];
if (!comp.isVisible()) continue;
if (isExcludedComponent(comp)) {
continue;
}
// // TODO: this is not the right way to do things. Leave it for future enhancement to popup panel
// // don't hide popup when button of abstract combobox is pressed so that that button can toggle visibility of popup panel
// if(comp instanceof AbstractButton && comp.getParent() instanceof AbstractComboBox) {
// if(_delegate.isAncestorOf(((AbstractComboBox) comp.getParent()).getPopupPanel())) {
// continue;
// }
// }
comp.addMouseListener(_mouseListener);
_grabbed.add(comp);
if (comp instanceof Container) {
Container cont = (Container) comp;
if (cont instanceof JLayeredPane) {
cont.addContainerListener(_containerListener);
}
grabContainer(cont);
}
}
}
}
void releaseContainers() {
for (Object o : _grabbed) {
Component c = (Component) o;
if (c instanceof Window) {
((Window) c).removeWindowListener(_windowListener);
c.removeComponentListener(_componentListener);
}
else {
c.removeMouseListener(_mouseListener);
}
if (c instanceof Container) {
if (c instanceof JLayeredPane) {
((Container) c).removeContainerListener(_containerListener);
}
}
}
_grabbed.clear();
}
/**
* Gets the visibility of this popup.
*
* @return true if popup is visible
*/
public boolean isVisible() {
return _delegate != null ? _delegate.isVisible() : false;
}
/**
* Adds a PopupMenu
listener which will listen to notification messages from the popup portion of the
* combo box.
*
* For all standard look and feels shipped with Java 2, the popup list portion of combo box is implemented as a
* JPopupMenu
. A custom look and feel may not implement it this way and will therefore not receive the
* notification.
*
* @param l the PopupMenuListener
to add
* @since 1.4
*/
public void addPopupMenuListener(PopupMenuListener l) {
listenerList.add(PopupMenuListener.class, l);
}
/**
* Removes a PopupMenuListener
.
*
* @param l the PopupMenuListener
to remove
* @see #addPopupMenuListener
* @since 1.4
*/
public void removePopupMenuListener(PopupMenuListener l) {
listenerList.remove(PopupMenuListener.class, l);
}
/**
* Returns an array of all the PopupMenuListener
s added to this JComboBox with addPopupMenuListener().
*
* @return all of the PopupMenuListener
s added or an empty array if no listeners have been added
*
* @since 1.4
*/
public PopupMenuListener[] getPopupMenuListeners() {
return listenerList.getListeners(PopupMenuListener.class);
}
/**
* Notifies PopupMenuListener
s that the popup portion of the combo box will become visible.
*
* This method is public but should not be called by anything other than the UI delegate.
*
* @see #addPopupMenuListener
* @since 1.4
*/
public void firePopupMenuWillBecomeVisible() {
Object[] listeners = listenerList.getListenerList();
PopupMenuEvent e = null;
for (int i = listeners.length - 2; i >= 0; i -= 2) {
if (listeners[i] == PopupMenuListener.class) {
if (e == null)
e = new PopupMenuEvent(this);
((PopupMenuListener) listeners[i + 1]).popupMenuWillBecomeVisible(e);
}
}
}
/**
* Notifies PopupMenuListener
s that the popup portion of the combo box has become invisible.
*
* This method is public but should not be called by anything other than the UI delegate.
*
* @see #addPopupMenuListener
* @since 1.4
*/
public void firePopupMenuWillBecomeInvisible() {
Object[] listeners = listenerList.getListenerList();
PopupMenuEvent e = null;
for (int i = listeners.length - 2; i >= 0; i -= 2) {
if (listeners[i] == PopupMenuListener.class) {
if (e == null)
e = new PopupMenuEvent(this);
((PopupMenuListener) listeners[i + 1]).popupMenuWillBecomeInvisible(e);
}
}
}
/**
* Notifies PopupMenuListener
s that the popup portion of the combo box has been canceled.
*
* This method is public but should not be called by anything other than the UI delegate.
*
* @see #addPopupMenuListener
* @since 1.4
*/
public void firePopupMenuCanceled() {
Object[] listeners = listenerList.getListenerList();
PopupMenuEvent e = null;
for (int i = listeners.length - 2; i >= 0; i -= 2) {
if (listeners[i] == PopupMenuListener.class) {
if (e == null)
e = new PopupMenuEvent(this);
((PopupMenuListener) listeners[i + 1]).popupMenuCanceled(e);
}
}
}
/**
* PopupWindow will add necessary listeners to some components so that mouse click etc can hide the popup window.
* However in certain case, you might not want this.
*
* @param comp component which will not hide popup when it is clicked.
*/
public void addAsExcludedComponents(Component comp) {
if (_excluded.contains(comp)) {
return;
}
_excluded.add(comp);
}
public void removeFromExcludedComponents(Component comp) {
if (!_excluded.contains(comp)) {
return;
}
_excluded.remove(comp);
}
public boolean isExcludedComponent(Component comp) {
return _excluded.contains(comp);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy