/*
Copyright 2008-2010 Gephi
Authors : Mathieu Bastian <mathieu.bastian@gephi.org>
Website : http://www.gephi.org
This file is part of Gephi.
Gephi is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
Gephi is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with Gephi. If not, see <http://www.gnu.org/licenses/>.
*/
package org.gephi.ui.components;
import java.awt.AWTEvent;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.event.AWTEventListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.MouseEvent;
import java.awt.event.WindowEvent;
import java.awt.event.WindowStateListener;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JWindow;
import javax.swing.SwingUtilities;
import javax.swing.border.Border;
import org.openide.util.Utilities;
import org.openide.windows.WindowManager;
//Copied from org.netbeans.modules.progress.ui
//Author Milos Kleint (mkleint@netbeans.org)
public class JPopupPane {
private HideAWTListener hideListener;
private JComponent ancestor;
private boolean showingPopup = false;
private JPopupPaneComponent pane;
private JWindow popupWindow;
private JPanel view;
public JPopupPane(JComponent ancestor, JPanel content) {
this.ancestor = ancestor;
this.view = content;
hideListener = new HideAWTListener();
}
private class JPopupPaneComponent extends JScrollPane {
public JPopupPaneComponent() {
setName("jpopuppane");
GridLayout grid = new GridLayout(0, 1);
grid.setHgap(0);
grid.setVgap(0);
setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
setViewportView(view);
setFocusable(true);
setRequestFocusEnabled(true);
setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
}
static final int ITEM_WIDTH = 400;
public Dimension getPreferredSize() {
int count = view.getComponentCount();
int height = count > 0 ? view.getComponent(0).getPreferredSize().height : 0;
int offset = count > 6 ? height * 6 + 5 : (count * height) + 5;
// 22 is the width of the additional scrollbar
return new Dimension(count > 3 ? ITEM_WIDTH + 22
: ITEM_WIDTH + 2, offset);
}
private int findIndex(Component comp) {
Component[] comps = view.getComponents();
for (int i = 0; i < comps.length; i++) {
if (comps[i] == comp) {
return i;
}
}
return -1;
}
}
private static class BottomLineBorder implements Border {
private Insets ins = new Insets(0, 0, 1, 0);
private Color col = new Color(221, 229, 248);
public BottomLineBorder() {
}
public Insets getBorderInsets(Component c) {
return ins;
}
public boolean isBorderOpaque() {
return false;
}
public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
Color old = g.getColor();
g.setColor(col);
g.drawRect(x, y + height - 2, width, 1);
g.setColor(old);
}
}
private class HideAWTListener extends ComponentAdapter implements AWTEventListener, WindowStateListener {
public void eventDispatched(java.awt.AWTEvent aWTEvent) {
if (aWTEvent instanceof MouseEvent) {
MouseEvent mv = (MouseEvent) aWTEvent;
if (mv.getClickCount() > 0) {
if (!(aWTEvent.getSource() instanceof Component)) {
return;
}
Component comp = (Component) aWTEvent.getSource();
Container par = SwingUtilities.getAncestorNamed("jpopuppane", comp); //NOI18N
Container barpar = SwingUtilities.getAncestorOfClass(ancestor.getClass(), comp);
if (par == null && barpar == null) {
hidePopup();
}
}
}
}
public void windowStateChanged(WindowEvent windowEvent) {
if (showingPopup) {
int oldState = windowEvent.getOldState();
int newState = windowEvent.getNewState();
if (((oldState & Frame.ICONIFIED) == 0) &&
((newState & Frame.ICONIFIED) == Frame.ICONIFIED)) {
hidePopup();
// } else if (((oldState & Frame.ICONIFIED) == Frame.ICONIFIED) &&
// ((newState & Frame.ICONIFIED) == 0 )) {
// //TODO remember we showed before and show again? I guess not worth the efford, not part of spec.
}
}
}
public void componentResized(ComponentEvent evt) {
if (showingPopup) {
resizePopup();
}
}
public void componentMoved(ComponentEvent evt) {
if (showingPopup) {
resizePopup();
}
}
}
public void showPopupPane() {
if (pane == null) {
pane = new JPopupPaneComponent();
}
if (popupWindow == null) {
popupWindow = new JWindow(WindowManager.getDefault().getMainWindow());
}
popupWindow.getContentPane().add(pane);
showingPopup = true;
Toolkit.getDefaultToolkit().addAWTEventListener(hideListener, AWTEvent.MOUSE_EVENT_MASK);
WindowManager.getDefault().getMainWindow().addWindowStateListener(hideListener);
WindowManager.getDefault().getMainWindow().addComponentListener(hideListener);
resizePopup();
popupWindow.setVisible(true);
pane.requestFocus();
}
private void resizePopup() {
popupWindow.pack();
Point point = new Point(0, 0);
SwingUtilities.convertPointToScreen(point, ancestor);
Dimension dim = popupWindow.getSize();
Rectangle usableRect = Utilities.getUsableScreenBounds();
int sepShift = 0;
Point loc = new Point(point.x + ancestor.getSize().width - dim.width - sepShift - 5 * 2, point.y - dim.height - 5);
if (!usableRect.contains(loc)) {
loc = new Point(loc.x, point.y + 5 + ancestor.getSize().height);
}
popupWindow.setLocation(loc);
}
public void hidePopup() {
if (popupWindow != null) {
// popupWindow.getContentPane().removeAll();
popupWindow.setVisible(false);
}
Toolkit.getDefaultToolkit().removeAWTEventListener(hideListener);
WindowManager.getDefault().getMainWindow().removeWindowStateListener(hideListener);
WindowManager.getDefault().getMainWindow().removeComponentListener(hideListener);
showingPopup = false;
}
public boolean isPopupShown() {
return showingPopup;
}
}