Java tutorial
/** * Squidy Interaction Library is free software: you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the License, * or (at your option) any later version. * * Squidy Interaction Library 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with Squidy Interaction Library. If not, see * <http://www.gnu.org/licenses/>. * * 2009 Human-Computer Interaction Group, University of Konstanz. * <http://hci.uni-konstanz.de> * * Please contact info@squidy-lib.de or visit our website * <http://www.squidy-lib.de> for further information. */ package org.squidy.designer.zoom; import java.awt.Color; import java.awt.Graphics2D; import java.awt.Polygon; import java.awt.Rectangle; import java.awt.geom.RectangularShape; import java.awt.geom.RoundRectangle2D; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.ArrayList; import java.util.List; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlIDREF; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.squidy.designer.component.TemporaryNotification; import org.squidy.designer.component.button.TitledButton; import org.squidy.designer.component.button.VisualButton; import org.squidy.designer.model.PipeShape; import org.squidy.designer.shape.VisualShape; import org.squidy.designer.util.ShapeUtils; import org.squidy.designer.util.StrokeUtils; import org.squidy.manager.ILaunchable; import org.squidy.manager.model.Pipe; import org.squidy.manager.model.Processable; import edu.umd.cs.piccolo.event.PBasicInputEventHandler; import edu.umd.cs.piccolo.event.PInputEvent; import edu.umd.cs.piccolo.util.PBounds; import edu.umd.cs.piccolo.util.PPaintContext; /** * <code>ActionShape</code>. * * <pre> * Date: Feb 2, 2009 * Time: 12:29:44 AM * </pre> * * @author Roman Rädle, <a * href="mailto:Roman.Raedle@uni-konstanz.de">Roman. * Raedle@uni-konstanz.de</a>, University of Konstanz * @version $Id: ActionShape.java 772 2011-09-16 15:39:44Z raedle $ * @since 2.0 */ public abstract class ActionShape<T extends VisualShape<?>, P extends Processable> extends NavigationShape<T> implements ILaunchable { /** * Generated serial version UID. */ private static final long serialVersionUID = 374617687692996886L; // Logger to log info, error, debug,... messages. private static final Log LOG = LogFactory.getLog(ActionShape.class); private boolean polygonRendering = false; // ############################################################################# // BEGIN JAXB // ############################################################################# /** * Default constructor required for JAXB. */ public ActionShape() { super(); initializeLayout(); } @XmlIDREF @XmlAttribute(name = "processable-ref") private P processable; /** * @return the processable */ public P getProcessable() { return processable; } /** * @param processable * the processable to set */ public void setProcessable(P processable) { this.processable = processable; } // ############################################################################# // END JAXB // ############################################################################# // ############################################################################# // BEGIN ILaunchable // ############################################################################# /* * (non-Javadoc) * * @see * org.squidy.manager.ILaunchable#publishFailure(java.lang.Throwable) */ public void publishFailure(Throwable e) { failure = true; invalidatePaint(); } /* * (non-Javadoc) * * @see org.squidy.manager.ILaunchable#resolveFailure() */ public void resolveFailure() { failure = false; invalidatePaint(); } /** * @return */ public boolean hasFailure() { return failure; } // ############################################################################# // END ILaunchable // ############################################################################# // ############################################################################# // BEGIN Initializable // ############################################################################# /* * (non-Javadoc) * * @see org.squidy.designer.shape.ZoomShape#initialize() */ @Override public void initialize() { super.initialize(); if (getProcessable() != null) { // Add property change listener that allows to start valve // processing this way. getProcessable().addStatusChangeListener(Processable.PROPERTY_PROCESSING, new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent evt) { firePropertyChange(0, Processable.PROPERTY_PROCESSING, evt.getOldValue(), evt.getNewValue()); } }); getProcessable().addStatusChangeListener(Processable.STATUS_PROCESSABLE_DELETED, new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent evt) { if (Pipe.class.isAssignableFrom(evt.getOldValue().getClass())) return; removeFromParent(); } }); getProcessable().addStatusChangeListener(Processable.PROPERTY_FAILURE_PUBLISH, new PropertyChangeListener() { /* * (non-Javadoc) * * @see * java.beans.PropertyChangeListener#propertyChange( * java.beans.PropertyChangeEvent) */ public void propertyChange(PropertyChangeEvent evt) { Throwable e = (Throwable) evt.getNewValue(); publishFailure(e); } }); getProcessable().addStatusChangeListener(Processable.PROPERTY_FAILURE_RESOLVE, new PropertyChangeListener() { /* * (non-Javadoc) * * @see * java.beans.PropertyChangeListener#propertyChange( * java.beans.PropertyChangeEvent) */ public void propertyChange(PropertyChangeEvent evt) { resolveFailure(); // for (Object o : getChildrenReference()) { // if (o instanceof ZoomActionShape) { // ((ZoomActionShape<?>) o).resolveFailure(); // } // } } }); getProcessable().addStatusChangeListener(Processable.PROPERTY_NOTIFICATION, new PropertyChangeListener() { /* * (non-Javadoc) * * @see * java.beans.PropertyChangeListener#propertyChange( * java.beans.PropertyChangeEvent) */ public void propertyChange(PropertyChangeEvent evt) { publishNotification(new TemporaryNotification(evt.getNewValue().toString())); } }); } } // ############################################################################# // END Initializable // ############################################################################# private boolean started = false; private boolean failure = false; private List<VisualButton> buttons = new ArrayList<VisualButton>(); /** * @param visualButton */ public void addAction(VisualButton visualButton) { addAction(visualButton, buttons.size()); } /** * @param visualButton * @param index */ public void addAction(VisualButton visualButton, int index) { buttons.add(index, visualButton); addChild(visualButton); } private boolean showActionsOnMouseOver = true; /** * @return the showActionsOnMouseOver */ public final boolean isShowActionsOnMouseOver() { return showActionsOnMouseOver; } /** * @param showActionsOnMouseOver * the showActionsOnMouseOver to set */ public final void setShowActionsOnMouseOver(boolean showActionsOnMouseOver) { this.showActionsOnMouseOver = showActionsOnMouseOver; } /** * */ public void initializeLayout() { addInputEventListener(new PBasicInputEventHandler() { // /* // * (non-Javadoc) // * // * @see // * edu.umd.cs.piccolo.event.PBasicInputEventHandler#mouseClicked // * (edu.umd.cs.piccolo.event.PInputEvent) // */ // @Override // public void mouseClicked(PInputEvent event) { // super.mouseClicked(event); // // // Set keyboard request to current path object. // // event.getInputManager().setKeyboardFocus(event.getPath()); // // if (event.isLeftMouseButton() && event.getClickCount() == 2) { // for (Object child : getChildrenReference()) { // if (child instanceof ActionShape<?, ?>) { // ((ActionShape<?, ?>) child).setActionsInvisible(); // } // } // } // } /* * (non-Javadoc) * * @see * edu.umd.cs.piccolo.event.PBasicInputEventHandler#mouseEntered * (edu.umd.cs.piccolo.event.PInputEvent) */ @Override public void mouseEntered(PInputEvent event) { super.mouseEntered(event); if (showActionsOnMouseOver && !event.isHandled()) { for (int i = 0; i < 4 && i < buttons.size(); i++) { VisualButton button = buttons.get(i); ShapeUtils.setApparent(button, true); } event.setHandled(true); } } /* * (non-Javadoc) * * @see * edu.umd.cs.piccolo.event.PBasicInputEventHandler#mouseEntered * (edu.umd.cs.piccolo.event.PInputEvent) */ @Override public void mouseMoved(PInputEvent event) { super.mouseMoved(event); if (showActionsOnMouseOver && !event.isHandled()) { for (int i = 0; i < 4 && i < buttons.size(); i++) { VisualButton button = buttons.get(i); ShapeUtils.setApparent(button, true); } event.setHandled(true); } } /* * (non-Javadoc) * * @see * edu.umd.cs.piccolo.event.PBasicInputEventHandler#mouseExited( * edu.umd.cs.piccolo.event.PInputEvent) */ @Override public void mouseExited(PInputEvent event) { super.mouseExited(event); if (!event.isHandled()) { if (currentZoomState == ZoomState.ZOOM_OUT) { for (VisualButton button : buttons) { ShapeUtils.setApparent(button, false); } } event.setHandled(true); } } /* * (non-Javadoc) * * @see * edu.umd.cs.piccolo.event.PBasicInputEventHandler#keyPressed(edu * .umd.cs.piccolo.event.PInputEvent) */ @Override public void keyPressed(PInputEvent event) { super.keyPressed(event); // if (!event.isHandled()) { // delete(); // event.setHandled(true); // } } }); // final ToggleImageButton startProcessing = new // ToggleImageButton(ActionShape.class // .getResource("/images/24x24/media_play_green.png"), ActionShape.class // .getResource("/images/24x24/delete2.png"), "Start"); // startProcessing.addZoomToggleActionListener(new // ZoomToggleActionListener() { // // /* // * (non-Javadoc) // * // * @see // * org.squidy.designer.event.ZoomActionListener#actionPerformed // * (org.squidy.designer.event.ZoomActionEvent) // */ // public void toggleActionPerformed(ZoomToggleActionEvent e) { // switch (e.getZoomToggle()) { // case PRESSED: // if (LOG.isDebugEnabled()) { // LOG.debug("Start has been pressed for " + getBreadcrumb()); // } // // start(); // doStart(); // // break; // // // case RELEASED: // // if (LOG.isDebugEnabled()) { // // LOG.debug("Stop has been pressed for " + getBreadcrumb()); // // } // // // // stop(); // // doStop(); // // // // break; // } // } // }); // // final ToggleImageButton stopProcessing = new // ToggleImageButton(ActionShape.class // .getResource("/images/24x24/media_stop_red.png"), ActionShape.class // .getResource("/images/24x24/delete2.png"), "Stop"); // stopProcessing.addZoomToggleActionListener(new // ZoomToggleActionListener() { // // /* // * (non-Javadoc) // * // * @see // * org.squidy.designer.event.ZoomActionListener#actionPerformed // * (org.squidy.designer.event.ZoomActionEvent) // */ // public void toggleActionPerformed(ZoomToggleActionEvent e) { // switch (e.getZoomToggle()) { // // case PRESSED: // // if (LOG.isDebugEnabled()) { // // LOG.debug("Start has been pressed for " + getBreadcrumb()); // // } // // // // start(); // // doStart(); // // // // break; // // case RELEASED: // if (LOG.isDebugEnabled()) { // LOG.debug("Stop has been pressed for " + getBreadcrumb()); // } // // stop(); // doStop(); // // break; // } // } // }); } /** * */ protected void doStart() { started = true; invalidatePaint(); for (Object node : getParent().getChildrenReference()) { if (node instanceof PipeShape && !this.equals(node)) { ((PipeShape) node).repaint(); } } } /** * */ protected void doStop() { started = false; invalidatePaint(); for (Object node : getParent().getChildrenReference()) { if (node instanceof PipeShape && !this.equals(node)) { ((PipeShape) node).repaint(); } } } // /** // * // */ // protected void setActionsInvisible() { // for (VisualButton button : buttons) { // ShapeUtils.setApparent(button, false); // } // } /* * (non-Javadoc) * * @see org.squidy.designer.zoom.ZoomShape#layoutSemanticsZoomedIn() */ @Override protected void layoutSemanticsZoomedIn() { super.layoutSemanticsZoomedIn(); PBounds bounds = getBounds(); int i = 0; for (VisualButton button : buttons) { button.setScale(1.0); button.setBorder(false); if (button instanceof TitledButton) { ((TitledButton) button).setTitleVisible(true); } button.setOffset(bounds.getX() + i * 50 + ((i + 1) * 20), bounds.getY() + 10); ShapeUtils.setApparent(button, true); i++; } } /* * (non-Javadoc) * * @see org.squidy.designer.zoom.ZoomShape#layoutSemanticsZoomedOut() */ protected void layoutSemanticsZoomedOut() { super.layoutSemanticsZoomedOut(); PBounds bounds = getBoundsReference(); for (int i = 0; i < buttons.size(); i++) { VisualButton button = buttons.get(i); button.setScale(8); button.setBorder(true); if (button instanceof TitledButton) { ((TitledButton) button).setTitleVisible(false); } double buttonWidth = button.getWidth() * button.getScale(); double buttonHeight = button.getHeight() * button.getScale(); // Calculate overlap of each button which is 1/6. double offsetX = buttonWidth / (double) 2; // System.out.println("OFFSET: " + offsetX + " | " + offsetY); switch (i) { case 0: button.setOffset(bounds.getX() - offsetX, bounds.getY() - offsetX); break; case 1: button.setOffset(bounds.getX() + bounds.getWidth() - offsetX, bounds.getY() - offsetX); break; case 2: button.setOffset(bounds.getX() - offsetX, bounds.getY() + bounds.getHeight() - offsetX); break; case 3: button.setOffset(bounds.getX() + bounds.getWidth() - offsetX, bounds.getY() + bounds.getHeight() - offsetX); break; default: // ShapeUtils.setApparent(button, false); break; } ShapeUtils.setApparent(button, false); } } private static final Color COLOR_STOPPED = new Color(0, 0, 0, 100); private static final Color COLOR_STARTED = new Color(0, 255, 0, 100); private static final Color COLOR_FAILURE = new Color(255, 0, 0, 100); // private static final Color COLOR_STOPPED = new Color(0, 0, 0); // private static final Color COLOR_STARTED = new Color(0, 255, 0); // private static final Color COLOR_FAILURE = new Color(255, 0, 0); // private static final Stroke STROKE_ZOOMED_IN = new BasicStroke(10f); // private static final Stroke STROKE_ZOOMED_OUT = new BasicStroke(30f); private RoundRectangle2D shapeZoomedIn = new RoundRectangle2D.Double(0., 0., 0., 0., 25., 25.); private RoundRectangle2D shapeZoomedOut = new RoundRectangle2D.Double(0., 0., 0., 0., 200., 200.); /* * (non-Javadoc) * * @see * org.squidy.designer.zoom.TitledZoomShape#paintShapeZoomedOut(edu * .umd.cs.piccolo.util.PPaintContext) */ @Override protected void paintShape(PPaintContext paintContext) { super.paintShape(paintContext); // Graphics2D g = paintContext.getGraphics(); // // RectangularShape r = (RectangularShape) getZoomedOutShape(); // if (r instanceof RoundRectangle2D) { // g.setStroke(new BasicStroke(15f)); // int step = 40; // for (double shift = 30; shift >= 1; shift -= 5) { // int test = (int) (shift * step); // // g.setColor(new Color(test, test, test)); // // g.setColor(new Color(hasFailure ? 255 : 0, !hasFailure && started ? // 255 : 0, 0, (int) (shift * step + 30) - test)); // // // g.fill(new RoundRectangle2D.Double(r.getMinX() - shift, // r.getMinY() - shift, r.getMaxX() + 2 * shift, r.getMaxY() + 2 * // shift, 20, 20)); // g.fill(new RoundRectangle2D.Double(r.getMinX() + shift, r.getMinY() + // shift, r.getMaxX() + shift, r.getMaxY() + shift, 200, 200)); // // g.draw(new RoundRectangle2D.Double(r.getMinX() + shift, // r.getMinY() + shift, r.getMaxX() + shift, r.getMaxY() + shift, 20, // 20)); // } // } // // g.setColor(Color.WHITE); // g.fill(getBoundsReference()); } /* * (non-Javadoc) * * @see * org.squidy.designer.zoom.NavigationShape#paintShapeZoomedIn(edu * .umd.cs.piccolo.util.PPaintContext) */ @Override protected void paintShapeZoomedIn(PPaintContext paintContext) { Graphics2D g = paintContext.getGraphics(); RectangularShape r = (RectangularShape) getZoomedOutShape(); if (r instanceof RoundRectangle2D) { // int width = (int)(r.getMaxX()-r.getMinX()); // int height = (int)(r.getMaxY()-r.getMinY()); // BufferedImage shadeStarted = new BufferedImage(width, height, // BufferedImage.TYPE_INT_RGB); // BufferedImage shadeStopped = new BufferedImage(width, height, // BufferedImage.TYPE_INT_RGB); // BufferedImage shadeFailure = new BufferedImage(width, height, // BufferedImage.TYPE_INT_RGB); // shadeStarted.getGraphics().setColor(COLOR_STARTED); // shadeStopped.getGraphics().setColor(COLOR_STOPPED); // shadeFailure.getGraphics().setColor(COLOR_FAILURE); // shadeStarted.getGraphics().fillRect(0, 0, width, height); // shadeStopped.getGraphics().fillRect(0, 0, width, height); // shadeFailure.getGraphics().fillRect(0, 0, width, height); // g.setStroke(STROKE_ZOOMED_IN); g.setStroke(StrokeUtils.getBasicStroke(7f)); g.setColor(failure ? COLOR_FAILURE : started ? COLOR_STARTED : COLOR_STOPPED); if (polygonRendering) { if (isRenderPrimitiveRect()) { if (!isHierarchicalZoomInProgress()) { Polygon shadeHorizontal = new Polygon(); Polygon shadeVertical = new Polygon(); double shift = 1; shapeZoomedIn.setFrame(r.getMinX() + shift, r.getMinY() + shift, r.getMaxX() + shift, r.getMaxY() + shift); Rectangle bounds = shapeZoomedIn.getBounds(); shadeHorizontal.addPoint(bounds.x, bounds.y + bounds.height); shadeHorizontal.addPoint(bounds.x + bounds.width, bounds.y + bounds.height); shadeVertical.addPoint(bounds.x + bounds.width, bounds.y); shadeVertical.addPoint(bounds.x + bounds.width, bounds.y + bounds.height); shift = 5; shapeZoomedIn.setFrame(r.getMinX() + shift, r.getMinY() + shift, r.getMaxX() + shift, r.getMaxY() + shift); bounds = shapeZoomedIn.getBounds(); shadeHorizontal.addPoint(bounds.x + bounds.width, bounds.y + bounds.height); shadeHorizontal.addPoint(bounds.x, bounds.y + bounds.height); shadeVertical.addPoint(bounds.x + bounds.width, bounds.y + bounds.height); shadeVertical.addPoint(bounds.x + bounds.width, bounds.y); g.fillPolygon(shadeHorizontal); g.fillPolygon(shadeVertical); } } else { g.draw(shapeZoomedIn); } } else { for (double shift = 6.; shift >= 1.; shift -= 1.) { shapeZoomedIn.setFrame(r.getMinX() + shift, r.getMinY() + shift, r.getMaxX() + shift, r.getMaxY() + shift); if (isRenderPrimitiveRect()) { if (!isHierarchicalZoomInProgress()) { Rectangle bounds = shapeZoomedIn.getBounds(); // g.drawImage(shadeStarted,null,bounds.x, // bounds.y); // g.fillRect(bounds.x, bounds.y, bounds.width, // bounds.height); g.drawLine(bounds.x + 1, bounds.y + bounds.height, bounds.x + bounds.width - 3, bounds.y + bounds.height); g.drawLine(bounds.x + bounds.width, bounds.y + 1, bounds.x + bounds.width, bounds.y + bounds.height - 3); } } else { g.draw(shapeZoomedIn); } } } } super.paintShapeZoomedIn(paintContext); } /* * (non-Javadoc) * * @see * org.squidy.designer.zoom.TitledZoomShape#paintShapeZoomedOut(edu * .umd.cs.piccolo.util.PPaintContext) */ @Override protected void paintShapeZoomedOut(PPaintContext paintContext) { Graphics2D g = paintContext.getGraphics(); RectangularShape r = (RectangularShape) getZoomedOutShape(); if (r instanceof RoundRectangle2D) { // g.setStroke(STROKE_ZOOMED_OUT); g.setColor(failure ? COLOR_FAILURE : started ? COLOR_STARTED : COLOR_STOPPED); g.setStroke(StrokeUtils.getBasicStroke(20f)); if (polygonRendering) { if (isRenderPrimitiveRect()) { if (!isHierarchicalZoomInProgress()) { Polygon shadeHorizontal = new Polygon(); Polygon shadeVertical = new Polygon(); double shift = 1; shapeZoomedOut.setFrame(r.getMinX() + shift, r.getMinY() + shift, r.getMaxX() + shift, r.getMaxY() + shift); Rectangle bounds = shapeZoomedOut.getBounds(); shadeHorizontal.addPoint(bounds.x, bounds.y + bounds.height); shadeHorizontal.addPoint(bounds.x + bounds.width, bounds.y + bounds.height); shadeVertical.addPoint(bounds.x + bounds.width, bounds.y); shadeVertical.addPoint(bounds.x + bounds.width, bounds.y + bounds.height); shift = 30; shapeZoomedOut.setFrame(r.getMinX() + shift, r.getMinY() + shift, r.getMaxX() + shift, r.getMaxY() + shift); bounds = shapeZoomedOut.getBounds(); shadeHorizontal.addPoint(bounds.x + bounds.width, bounds.y + bounds.height); shadeHorizontal.addPoint(bounds.x, bounds.y + bounds.height); shadeVertical.addPoint(bounds.x + bounds.width, bounds.y + bounds.height); shadeVertical.addPoint(bounds.x + bounds.width, bounds.y); g.fillPolygon(shadeHorizontal); g.fillPolygon(shadeVertical); } } else { g.draw(shapeZoomedOut); } } else { for (double shift = 30.; shift >= 1.; shift -= 5.) { shapeZoomedOut.setFrame(r.getMinX() + shift, r.getMinY() + shift, r.getMaxX() + shift, r.getMaxY() + shift); if (isRenderPrimitiveRect()) { if (!isHierarchicalZoomInProgress()) { Rectangle bounds = shapeZoomedOut.getBounds(); // g.fillRect(bounds.x, bounds.y, bounds.width, // bounds.height); g.drawLine(bounds.x + 1, bounds.y + bounds.height, bounds.x + bounds.width - 3, bounds.y + bounds.height); g.drawLine(bounds.x + bounds.width, bounds.y + 1, bounds.x + bounds.width, bounds.y + bounds.height - 3); } } else { g.draw(shapeZoomedOut); } } } } super.paintShapeZoomedOut(paintContext); } }