/* * RapidMiner * * Copyright (C) 2001-2008 by Rapid-I and the contributors * * Complete list of developers available at our web site: * * http://rapid-i.com * * This program 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. * * This program 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 this program. If not, see http://www.gnu.org/licenses/. */ package com.rapidminer.gui.look; import java.awt.Component; import java.awt.Container; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Point; import java.awt.Rectangle; import java.awt.Robot; import java.awt.Window; import java.awt.image.BufferedImage; import java.util.ArrayList; import java.util.List; import javax.swing.JApplet; import javax.swing.JComponent; import javax.swing.JInternalFrame; import javax.swing.JMenu; import javax.swing.JRootPane; import javax.swing.Popup; import javax.swing.SwingUtilities; import com.rapidminer.gui.look.borders.Borders; import com.rapidminer.gui.look.borders.DummyBorder; import com.rapidminer.gui.look.borders.PopupBorder; import com.rapidminer.gui.look.borders.ShadowedPopupMenuBorder; /** * A popup object in form of a rounded rectangle. * * @author Ingo Mierswa * @version $Id: RoundedRectanglePopup.java,v 1.2 2008/05/09 19:23:17 ingomierswa Exp $ */ public final class RoundedRectanglePopup extends Popup { private static final Rectangle rectangle = new Rectangle(); private static List<RoundedRectanglePopup> allPopups; private BufferedImage topRight; private BufferedImage topLeft; private BufferedImage bottomRight; private BufferedImage bottomLeft; private BufferedImage bottom; private BufferedImage right; private Dimension size; private Component contents; private int x, y; private Popup popup; private Robot robot; private Component owner; private static final Point point = new Point(); private static Rectangle bufferRectangle = new Rectangle(); static Popup getInstance(Component owner, Component contents, int x, int y, Popup delegate) { RoundedRectanglePopup popup; synchronized (RoundedRectanglePopup.class) { if (allPopups == null) { allPopups = new ArrayList<RoundedRectanglePopup>(7); } if (allPopups.size() > 0) { popup = allPopups.remove(0); } else { popup = new RoundedRectanglePopup(); } } popup.initPopup(owner, contents, x, y, delegate); return popup; } private static void addPopupToList(RoundedRectanglePopup popup) { synchronized (RoundedRectanglePopup.class) { if (allPopups.size() < 7) { allPopups.add(popup); } } } @Override public void hide() { this.popup.hide(); ((JComponent) this.contents).putClientProperty(RoundedPopupFactory.BOTTOM_LEFT_PIC, null); ((JComponent) this.contents).putClientProperty(RoundedPopupFactory.BOTTOM_RIGHT_PIC, null); ((JComponent) this.contents).putClientProperty(RoundedPopupFactory.TOP_LEFT_PIC, null); ((JComponent) this.contents).putClientProperty(RoundedPopupFactory.TOP_RIGHT_PIC, null); ((JComponent) this.contents).putClientProperty(RoundedPopupFactory.RIGHT_PIC, null); ((JComponent) this.contents).putClientProperty(RoundedPopupFactory.BOTTOM_PIC, null); this.contents = null; this.popup = null; addPopupToList(this); } @Override public void show() { if ((((JComponent) this.contents).getBorder() instanceof PopupBorder) || (((JComponent) this.contents).getBorder() instanceof ShadowedPopupMenuBorder)) { updatePics(); } this.popup.show(); } private void initPopup(Component owner, Component contents, int x, int y, Popup popup) { this.owner = owner; this.contents = contents; this.popup = popup; this.x = x; this.y = y; boolean mac = false; try { mac = System.getProperty("os.name").toLowerCase().startsWith("mac"); } catch (SecurityException e) { // do nothing } if (mac) { ((JComponent) contents).setBorder(Borders.getPopupMenuBorder()); } else if (((JComponent) contents).getBorder() instanceof DummyBorder) { if (!((owner instanceof JMenu) && ((JMenu) owner).isTopLevelMenu()) && !((owner.getParent() != null) && (owner.getParent() instanceof javax.swing.JToolBar)) && !((owner != null) && (owner instanceof javax.swing.JComboBox))) { ((JComponent) contents).setBorder(Borders.getShadowedPopupMenuBorder()); } else { ((JComponent) contents).setBorder(Borders.getPopupBorder()); } } } private void updatePics() { try { this.contents.requestFocus(); this.robot = new Robot(); this.size = this.contents.getPreferredSize(); int w = this.size.width; int h = this.size.height; rectangle.setBounds(this.x, this.y, 5, 5); this.topLeft = this.robot.createScreenCapture(rectangle); rectangle.setBounds(this.x + w - 5, this.y, 5, 5); this.topRight = this.robot.createScreenCapture(rectangle); rectangle.setBounds(this.x, this.y + h - 5, 5, 5); this.bottomLeft = this.robot.createScreenCapture(rectangle); rectangle.setBounds(this.x + w - 5, this.y + h - 5, 5, 5); this.bottomRight = this.robot.createScreenCapture(rectangle); rectangle.setBounds(this.x + w - 1, this.y, 1, h - 5); this.right = this.robot.createScreenCapture(rectangle); rectangle.setBounds(this.x + 5, this.y + h - 1, w - 10, 1); this.bottom = this.robot.createScreenCapture(rectangle); Component layeredPane = getLayeredPane(); if (layeredPane == null) { return; } point.x = this.x; point.y = this.y; SwingUtilities.convertPointFromScreen(point, layeredPane); bufferRectangle = new Rectangle(point.x, point.y, 5, 5); drawRemaining(bufferRectangle, layeredPane, this.topLeft); bufferRectangle = new Rectangle(point.x + w - 5, point.y, 5, 5); drawRemaining(bufferRectangle, layeredPane, this.topRight); bufferRectangle = new Rectangle(point.x, point.y + h - 5, 5, 5); drawRemaining(bufferRectangle, layeredPane, this.bottomLeft); bufferRectangle = new Rectangle(point.x + w - 5, point.y + h - 5, 5, 5); drawRemaining(bufferRectangle, layeredPane, this.bottomRight); bufferRectangle = new Rectangle(point.x + w - 1, point.y, 1, h - 5); drawRemaining(bufferRectangle, layeredPane, this.right); bufferRectangle = new Rectangle(point.x + 5, point.y + h - 1, w - 10, 1); drawRemaining(bufferRectangle, layeredPane, this.bottom); ((JComponent) this.contents).putClientProperty(RoundedPopupFactory.BOTTOM_LEFT_PIC, this.bottomLeft); ((JComponent) this.contents).putClientProperty(RoundedPopupFactory.BOTTOM_RIGHT_PIC, this.bottomRight); ((JComponent) this.contents).putClientProperty(RoundedPopupFactory.TOP_LEFT_PIC, this.topLeft); ((JComponent) this.contents).putClientProperty(RoundedPopupFactory.TOP_RIGHT_PIC, this.topRight); ((JComponent) this.contents).putClientProperty(RoundedPopupFactory.RIGHT_PIC, this.right); ((JComponent) this.contents).putClientProperty(RoundedPopupFactory.BOTTOM_PIC, this.bottom); } catch (Exception e) { // do nothing } } private void drawRemaining(Rectangle rectangle, Component lp, BufferedImage pic) { if ((rectangle.x + rectangle.width) > lp.getWidth()) { rectangle.width = lp.getWidth() - rectangle.x; } if ((rectangle.y + rectangle.height) > lp.getHeight()) { rectangle.height = lp.getHeight() - rectangle.y; } if (!rectangle.isEmpty()) { Graphics g = pic.createGraphics(); g.translate(-rectangle.x, -rectangle.y); g.setClip(rectangle); boolean doubleBuffered = lp.isDoubleBuffered(); if (lp instanceof JComponent) { ((JComponent) lp).setDoubleBuffered(false); lp.paint(g); ((JComponent) lp).setDoubleBuffered(doubleBuffered); } else { lp.paint(g); } g.dispose(); } } private Component getLayeredPane() { Container parent = null; if (this.owner != null) { parent = this.owner instanceof Container ? (Container) this.owner : this.owner.getParent(); } for (Container p = parent; p != null; p = p.getParent()) { if (p instanceof JRootPane) { if (p.getParent() instanceof JInternalFrame) { continue; } parent = ((JRootPane) p).getLayeredPane(); } else if (p instanceof Window) { if (parent == null) { parent = p; } break; } else if (p instanceof JApplet) { break; } } return parent; } }