package org.limewire.ui.swing.components;
import java.awt.AWTEvent;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.Toolkit;
import java.awt.event.AWTEventListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import javax.swing.SwingUtilities;
import net.miginfocom.swing.MigLayout;
import org.jdesktop.application.Resource;
import org.jdesktop.swingx.JXPanel;
import org.jdesktop.swingx.painter.Painter;
import org.jdesktop.swingx.painter.effects.ShadowPathEffect;
import org.limewire.ui.swing.util.GuiUtils;
public class ShapeDialog extends JXPanel implements Resizable {
private AWTEventListener eventListener;
private Component component;
private ComponentListener componentListener;
private Component owner;
private boolean isAutoClose;
private static final int SHADOW_INSETS = 5;
@Resource
private boolean isPositionedRelativeToOwner;
public ShapeDialog() {
super(new MigLayout("fill, ins 0 0 0 0 , gap 0! 0!, novisualpadding"));
GuiUtils.assignResources(this);
setOpaque(false);
setVisible(false);
setBackgroundPainter(new DialogShadowPainter());
addComponentListener(new ComponentAdapter() {
@Override
public void componentShown(ComponentEvent e) {
addListeners();
resize();
}
@Override
public void componentHidden(ComponentEvent e) {
removeListeners();
}
});
componentListener = new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent e) {
setSize(getPreferredSize());
repaint();
}
};
}
/**
* Shows c centered in the Frame with no autoclose.
*/
public void show(Component c){
show(c, null, false);
}
/**
*
* @param c the Component shown
* @param owner the dialog owner. Dialog will be centered in frame if this is null
* @param autoClose Dialog will have PopupMenu close behavior (clicking away or pressing ESC closes dialog)
*/
public void show(Component c, Component owner, boolean autoClose) {
removeAll();
int inset = (owner != null && isPositionedRelativeToOwner) ? 0 : SHADOW_INSETS;
add(c, "alignx 50%, aligny 50%, gapleft " + inset + ", gapright " + inset + ", gaptop " + inset + ", gapbottom " + inset);
this.component = c;
this.owner = owner;
this.isAutoClose = autoClose;
setVisible(true);
//make sure this actually gets shown in a timely manner
getParent().repaint();
}
@Override
public void setVisible(boolean visible){
super.setVisible(visible);
//prevent initial strange appearance when reshown
if (!visible){
setSize(0, 0);
}
}
private void positionRelativeToOwner(){
Point ownerLocation = SwingUtilities.convertPoint(owner.getParent(), owner.getLocation(), getParent());
setBounds(ownerLocation.x + owner.getWidth() - getWidth(), ownerLocation.y + owner.getHeight(), getPreferredSize().width, getPreferredSize().height);
}
private void addListeners() {
if (eventListener == null) {
initializeEventListener();
}
Toolkit.getDefaultToolkit().addAWTEventListener(eventListener, AWTEvent.MOUSE_EVENT_MASK);
Toolkit.getDefaultToolkit().addAWTEventListener(eventListener, AWTEvent.KEY_EVENT_MASK);
if (component != null) {
component.addComponentListener(componentListener);
}
}
private void removeListeners() {
Toolkit.getDefaultToolkit().removeAWTEventListener(eventListener);
if (component != null) {
component.removeComponentListener(componentListener);
}
}
private void initializeEventListener() {
// make sharePanel disappear when the user clicks elsewhere
eventListener = new AWTEventListener() {
@Override
public void eventDispatched(AWTEvent event) {
if (isVisible() && isAutoClose) {
if ((event.getID() == MouseEvent.MOUSE_PRESSED)) {
MouseEvent e = (MouseEvent) event;
if ((getMousePosition(true) == null || !contains(getMousePosition(true))) && component != e.getComponent()
&& (!component.contains(SwingUtilities.convertPoint(e.getComponent(), e.getPoint(), component)))) {
setVisible(false);
}
} else if (event.getID() == KeyEvent.KEY_PRESSED) {
KeyEvent e = (KeyEvent) event;
if (e.getKeyChar() == KeyEvent.VK_ESCAPE) {
setVisible(false);
}
}
}
}
};
}
@Override
public void resize() {
if (component != null) {
if (!isPositionedRelativeToOwner || owner == null) {
Rectangle parentBounds = getParent().getBounds();
Dimension preferredSize = getPreferredSize();
int w = preferredSize.width;
int h = preferredSize.height;
setBounds(parentBounds.width / 2 - w / 2, parentBounds.height / 2 - h / 2, w, h);
} else {
positionRelativeToOwner();
}
}
}
private class DialogShadowPainter implements Painter {
private ShadowPathEffect shadow;
public DialogShadowPainter(){
shadow = new ShadowPathEffect();
shadow.setEffectWidth(14);
shadow.setOffset(new Point(0, 0));
}
@Override
public void paint(Graphics2D g, Object object, int width, int height) {
if (component != null) {
Graphics2D g2 = (Graphics2D) g.create();
Shape shape;
if (component instanceof ShapeComponent) {
shape = ((ShapeComponent) component).getShape();
g2.translate(component.getLocation().x, component.getLocation().y);
} else {
shape = component.getBounds();
}
shadow.apply(g2, shape, width, height);
g2.dispose();
}
}
}
}