/** * */ package org.squidy.nodes.powerpointer; import java.awt.AlphaComposite; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Composite; import java.awt.Container; import java.awt.Font; import java.awt.GradientPaint; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Paint; import java.awt.Point; import java.awt.Shape; import java.awt.Stroke; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseMotionListener; import java.awt.geom.AffineTransform; import java.awt.geom.Ellipse2D; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import javax.imageio.ImageIO; import javax.swing.JComponent; import javax.swing.JWindow; import javax.swing.SwingUtilities; import javax.swing.event.EventListenerList; /** * @author raedle * */ public class PieMenuComponent extends JComponent { /** * Generated serial version UID. */ private static final long serialVersionUID = 7453217419590215948L; private final EventListenerList listeners = new EventListenerList(); private static final AlphaComposite COMPOSITE_ALPHA = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.85f); private static final AlphaComposite COMPOSITE_ALPHA_PIECES = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.35f); private AffineTransform translateTransform = AffineTransform.getTranslateInstance(0, 0); private Paint knopPaint; private Paint piePaint; private Stroke border = new BasicStroke(2f); private Stroke piecesBorder1 = new BasicStroke(1f); private Stroke piecesBorder2 = new BasicStroke(3f); private Stroke piecesBorder3 = new BasicStroke(5f); private Ellipse2D pieMenuInner; private Ellipse2D pieMenuOuter; private int diameter; private boolean openPieMenu = false; private double openRatio = 0.0; private Thread pieMenuOpener; public PieMenuComponent(final int diameter) { setBounds(0, 0, diameter, diameter); this.diameter = diameter; int oneThird = diameter / 3; knopPaint = new GradientPaint(oneThird + oneThird / 10, oneThird + oneThird / 10, Color.WHITE, oneThird * 2, oneThird * 2, Color.DARK_GRAY); piePaint = new GradientPaint(oneThird / 5, oneThird / 5, Color.LIGHT_GRAY, diameter, diameter, Color.GRAY); pieMenuInner = new Ellipse2D.Double(oneThird, oneThird, oneThird, oneThird); pieMenuOuter = new Ellipse2D.Double(0, 0, diameter, diameter); pieMenuOpener = new Thread() { @Override public void run() { super.run(); double sizeHalf = (double) diameter / (double) 2; double trans = 0; for (openRatio = 0.0; openRatio <= 1.0; openRatio += 0.05) { trans = sizeHalf - (sizeHalf * openRatio); translateTransform.setTransform(openRatio, 0, 0, openRatio, trans, trans); try { SwingUtilities.invokeAndWait(new Runnable() { /* (non-Javadoc) * @see java.lang.Runnable#run() */ public void run() { repaint(); } }); } catch (InterruptedException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } catch (InvocationTargetException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } try { Thread.sleep(5); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } // BufferedImage img = new BufferedImage(diameter, diameter, BufferedImage.TYPE_INT_RGB); // Graphics2D g2d = img.createGraphics(); // g2d.setColor(Color.WHITE); // g2d.fillRect(0, 0, diameter, diameter); // paintAll(g2d); // g2d.dispose(); // try { // ImageIO.write(img, "png", new File("/Users/raedle/Desktop/c5_pie-menu.png")); // } catch (IOException e) { // // TODO Auto-generated catch block // e.printStackTrace(); // } } }; addMouseMotionListener(new MouseMotionListener() { public void mouseMoved(MouseEvent e) { if (openRatio < 0.5) { return; } if (!contains(e.getPoint())) { Container parent = getParent(); while (!(parent instanceof JWindow) && parent != null) { parent = parent.getParent(); } if (parent instanceof JWindow) { ((JWindow) parent).setVisible(false); ((JWindow) parent).dispose(); } Point p = e.getPoint(); int x = getX(); int y = getY(); int width = getWidth(); int height = getHeight(); Point[] edges = new Point[4]; edges[EdgeListener.EDGE_TOP] = new Point(x + width / 2, y); edges[EdgeListener.EDGE_RIGHT] = new Point(x + width, y + height / 2); edges[EdgeListener.EDGE_BOTTOM] = new Point(x + width / 2, y + height); edges[EdgeListener.EDGE_LEFT] = new Point(x, y + height / 2); // Calculate distance from exit point to edge points and the minimal distance // indicates the leave point. double edgeDistances[] = new double[4]; edgeDistances[EdgeListener.EDGE_TOP] = edges[EdgeListener.EDGE_TOP].distance(p); edgeDistances[EdgeListener.EDGE_RIGHT] = edges[EdgeListener.EDGE_RIGHT].distance(p); edgeDistances[EdgeListener.EDGE_BOTTOM] = edges[EdgeListener.EDGE_BOTTOM].distance(p); edgeDistances[EdgeListener.EDGE_LEFT] = edges[EdgeListener.EDGE_LEFT].distance(p); int edge = 0; for (int i = 0; i < 4; i++) { if (edgeDistances[edge] > edgeDistances[i]) { edge = i; } } EdgeListener[] edgeListeners = listeners.getListeners(EdgeListener.class); for (EdgeListener listener : edgeListeners) { listener.exitOnEdge(edge); } } } public void mouseDragged(MouseEvent e) { // empty } }); addMouseListener(new MouseAdapter() { @Override public void mouseExited(MouseEvent e) { super.mouseExited(e); // System.out.println("Point: " + e.getPoint()); Container parent = getParent(); while (!(parent instanceof JWindow) && parent != null) { parent = parent.getParent(); } if (parent instanceof JWindow) { ((JWindow) parent).setVisible(false); ((JWindow) parent).dispose(); } Point p = e.getPoint(); int x = getX(); int y = getY(); int width = getWidth(); int height = getHeight(); Point[] edges = new Point[4]; edges[EdgeListener.EDGE_TOP] = new Point(x + width / 2, y); edges[EdgeListener.EDGE_RIGHT] = new Point(x + width, y + height / 2); edges[EdgeListener.EDGE_BOTTOM] = new Point(x + width / 2, y + height); edges[EdgeListener.EDGE_LEFT] = new Point(x, y + height / 2); // Calculate distance from exit point to edge points and the minimal distance // indicates the leave point. double edgeDistances[] = new double[4]; edgeDistances[EdgeListener.EDGE_TOP] = edges[EdgeListener.EDGE_TOP].distance(p); edgeDistances[EdgeListener.EDGE_RIGHT] = edges[EdgeListener.EDGE_RIGHT].distance(p); edgeDistances[EdgeListener.EDGE_BOTTOM] = edges[EdgeListener.EDGE_BOTTOM].distance(p); edgeDistances[EdgeListener.EDGE_LEFT] = edges[EdgeListener.EDGE_LEFT].distance(p); int edge = 0; for (int i = 0; i < 4; i++) { if (edgeDistances[edge] > edgeDistances[i]) { edge = i; } } EdgeListener[] edgeListeners = listeners.getListeners(EdgeListener.class); for (EdgeListener listener : edgeListeners) { listener.exitOnEdge(edge); } } }); } public void addEdgeListener(EdgeListener edgeListener) { listeners.add(EdgeListener.class, edgeListener); } /* (non-Javadoc) * @see javax.swing.JComponent#paintComponent(java.awt.Graphics) */ @Override protected void paintComponent(Graphics g) { super.paintComponent(g); if (!openPieMenu) { openPieMenu = true; pieMenuOpener.start(); return; } Graphics2D g2d = (Graphics2D) g; AffineTransform saveTransform = g2d.getTransform(); g2d.setTransform(translateTransform); Composite originalComposite = g2d.getComposite(); // g.setColor(Color.LIGHT_GRAY); // g2d.draw(pieMenu); // g2d.setComposite(COMPOSITE_ALPHA); // g.setColor(Color.LIGHT_GRAY); // g2d.fill(pieMenu); Shape defaultClip = g2d.getClip(); // g2d.clip(pieMenuInner); g2d.setComposite(COMPOSITE_ALPHA); g.setColor(Color.LIGHT_GRAY); Paint defaultPaint = g2d.getPaint(); g2d.setPaint(piePaint); g2d.fill(pieMenuOuter); Stroke defaultStroke = g2d.getStroke(); g.setColor(Color.GRAY); g2d.setStroke(border); g2d.draw(pieMenuOuter); g2d.setComposite(COMPOSITE_ALPHA_PIECES); g2d.clip(pieMenuOuter); g.setColor(Color.GRAY); g2d.setStroke(piecesBorder3); g2d.drawLine(0, 0, diameter, diameter); g2d.drawLine(diameter, 0, 0, diameter); g.setColor(Color.GRAY); g2d.setStroke(piecesBorder2); g2d.drawLine(0, 0, diameter, diameter); g2d.drawLine(diameter, 0, 0, diameter); g.setColor(Color.GRAY); g2d.setStroke(piecesBorder1); g2d.drawLine(0, 0, diameter, diameter); g2d.drawLine(diameter, 0, 0, diameter); g2d.setComposite(originalComposite); g2d.setColor(Color.GRAY); // g2d.setXORMode(Color.MAGENTA); g2d.setPaint(knopPaint); g2d.fill(pieMenuInner); g2d.setPaint(defaultPaint); // g2d.setColor(Color.GRAY); // g2d.draw(pieMenuInner); g2d.setClip(defaultClip); g2d.setStroke(defaultStroke); g2d.setColor(Color.BLACK); g2d.setFont(g2d.getFont().deriveFont((float) diameter / (float) 14).deriveFont(Font.BOLD)); int width1 = g2d.getFontMetrics().stringWidth("Slide Overview"); g.drawString("Slide Overview", diameter / 2 - width1 / 2, 115); // int width2 = g2d.getFontMetrics().stringWidth("Erase Drawings"); // g.drawString("Erase Drawings", SIZE / 2 - width2 / 2, SIZE - 80); int width3 = g2d.getFontMetrics().stringWidth("Erase Drawings"); g.drawString("Erase Drawings", diameter / 2 - width3 / 2, diameter - 80); // int width4 = g2d.getFontMetrics().stringWidth("Erase Drawings"); // g.drawString("Erase Drawings", SIZE / 2 - width4 / 2, SIZE - 80); g2d.setTransform(saveTransform); } }