/******************************************************************************* * Copyright (c) 2005, 2012 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.bpel.ui.editparts; import org.eclipse.bpel.model.EventHandler; import org.eclipse.bpel.model.FaultHandler; import org.eclipse.bpel.model.Process; import org.eclipse.bpel.ui.BPELUIPlugin; import org.eclipse.bpel.ui.IBPELUIConstants; import org.eclipse.bpel.ui.adapters.IEventHandlerHolder; import org.eclipse.bpel.ui.adapters.IFaultHandlerHolder; import org.eclipse.bpel.ui.adapters.ILabeledElement; import org.eclipse.bpel.ui.editparts.policies.BPELSelectionEditPolicy; import org.eclipse.bpel.ui.figures.CenteredConnectionAnchor; import org.eclipse.bpel.ui.figures.ILayoutAware; import org.eclipse.bpel.ui.uiextensionmodel.StartNode; import org.eclipse.bpel.ui.util.BPELDragEditPartsTracker; import org.eclipse.bpel.ui.util.BPELUtil; import org.eclipse.bpel.ui.util.ModelHelper; import org.eclipse.draw2d.ConnectionAnchor; import org.eclipse.draw2d.Graphics; import org.eclipse.draw2d.IFigure; import org.eclipse.draw2d.ImageFigure; import org.eclipse.draw2d.MarginBorder; import org.eclipse.draw2d.geometry.Insets; import org.eclipse.draw2d.geometry.Point; import org.eclipse.gef.ConnectionEditPart; import org.eclipse.gef.DragTracker; import org.eclipse.gef.EditPolicy; import org.eclipse.gef.NodeEditPart; import org.eclipse.gef.Request; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Rectangle; public class StartNodeEditPart extends BPELEditPart implements NodeEditPart, ILayoutAware{ protected Image image; protected int imageWidth; protected int imageHeight; //Determines the border which will be added to both sides (left/right) //As a result this value is the distance to any attached handlers. public static final int BORDER_WIDTH = 8; // Whether the process has a fault handler and event handler protected boolean hasFH, hasEH; // Whether to show each of the actual handlers. // TODO: Initialize these from the preferences store protected boolean showFH = false, showEH = false; // Fault handler, Compensation handler and Event handler support protected int faultImageWidth, faultImageHeight; protected int eventImageWidth, eventImageHeight; protected Image faultImage; protected Image eventImage; protected Rectangle rectFault; protected Rectangle rectEvent; private IFigure faultImageFigure; private IFigure eventImageFigure; private class StartNodeFigure extends ImageFigure { /** * */ public StartNodeFigure() { super(image); } /** * @see org.eclipse.draw2d.Figure#paint(org.eclipse.draw2d.Graphics) */ @Override public void paint(Graphics graphics) { super.paint(graphics); computeHandlerIconPositions(ModelHelper.isHorizontalLayout(getModel())); if (hasFH) { graphics.pushState(); graphics.setClip(faultImageFigure.getBounds().getCopy()); faultImageFigure.paint(graphics); graphics.popState(); } if (hasEH) { graphics.pushState(); graphics.setClip(eventImageFigure.getBounds().getCopy()); eventImageFigure.paint(graphics); graphics.popState(); } } } /** * Brand new shiny start edit part. */ public StartNodeEditPart() { // Initialize images for fault and event handler decorations this.faultImage = BPELUIPlugin.INSTANCE.getImage(IBPELUIConstants.ICON_FAULT_INDICATOR); org.eclipse.swt.graphics.Rectangle r = faultImage.getBounds(); this.faultImageWidth = r.width; this.faultImageHeight = r.height; this.eventImage = BPELUIPlugin.INSTANCE.getImage(IBPELUIConstants.ICON_EVENT_INDICATOR); r = eventImage.getBounds(); this.eventImageWidth = r.width; this.eventImageHeight = r.height; } @Override protected void addAllAdapters() { super.addAllAdapters(); adapter.addToObject(getProcess()); } @Override protected void removeAllAdapters() { adapter.removedFrom(getProcess()); super.removeAllAdapters(); } @Override protected IFigure createFigure() { if (image == null) { ILabeledElement element = BPELUtil.adapt(getStartNode(), ILabeledElement.class); image = element.getSmallImage(getStartNode()); Rectangle rect = image.getBounds(); imageWidth = rect.width; imageHeight = rect.height; } this.hasFH = getFaultHandler() != null; this.hasEH = getEventHandler() != null; // Cause the handlerIcons don't belong to the // bounds of the StartNodeFigure (as a result of // moving them a bit to the right in vertical layout and a bit to to the bottom // in horizontal layout) hit testing // doesn't reach the Startnode. So add an invisible // border StartNodeFigure snf = new StartNodeFigure(); if(!ModelHelper.isHorizontalLayout(getModel())) snf.setBorder(new MarginBorder(0,7+BORDER_WIDTH,0,7+BORDER_WIDTH)); else snf.setBorder(new MarginBorder(5,0,5,0)); faultImageFigure = new ImageFigure(faultImage); faultImageFigure.setParent(snf); eventImageFigure = new ImageFigure(eventImage); eventImageFigure.setParent(snf); return snf; } /** * @see org.eclipse.bpel.ui.editparts.BPELEditPart#refreshVisuals() */ @Override public void refreshVisuals() { super.refreshVisuals(); // Refresh any decorations on this edit part this.hasFH = getFaultHandler() != null; this.hasEH = getEventHandler() != null; // Force a repaint, as the decorations. getFigure().repaint(); } /** * Return the start node. * @return return the start node. */ public StartNode getStartNode() { return (StartNode)getModel(); } /** * Return the process. * @return the process */ public Process getProcess() { return getStartNode().getProcess(); } @Override protected void createEditPolicies() { // Don't call super because we don't want a component edit policy // or a direct edit policy. // Show the selection rectangle installEditPolicy(EditPolicy.SELECTION_FEEDBACK_ROLE, new BPELSelectionEditPolicy(false, false){ @Override protected int getWestInset() { Insets ins = ((StartNodeEditPart)getHost()).getFigure().getInsets(); if(ins != null){ return ins.left; } return super.getWestInset(); } @Override protected int getEastInset() { Insets ins = ((StartNodeEditPart)getHost()).getFigure().getInsets(); if(ins != null){ return ins.right; } return super.getEastInset(); } }); } public ConnectionAnchor getTargetConnectionAnchor(ConnectionEditPart connEditPart) { // Start nodes cannot be the target of a connection. return null; } public ConnectionAnchor getSourceConnectionAnchor(ConnectionEditPart connEditPart) { // Start nodes can be the source of an implicit connection // anchored at the bottom centre of the node. return new CenteredConnectionAnchor(getFigure(), CenteredConnectionAnchor.BOTTOM, 0); } public ConnectionAnchor getSourceConnectionAnchor(Request request) { // TODO: Translate point to figure, call other method return getSourceConnectionAnchor((ConnectionEditPart)null); } public ConnectionAnchor getTargetConnectionAnchor(Request request) { // TODO: Translate point to figure, call other method return getTargetConnectionAnchor((ConnectionEditPart)null); } public void setShowFaultHandler(boolean showFaultHandler) { this.showFH = showFaultHandler; // Notify the process too. ProcessEditPart processEditPart = (ProcessEditPart)getParent(); processEditPart.setShowFaultHandler(showFaultHandler); // Call refresh so that both refreshVisuals and refreshChildren will be called. refresh(); } public void setShowEventHandler(boolean showEventHandler) { this.showEH = showEventHandler; // Notify the process too. ProcessEditPart processEditPart = (ProcessEditPart)getParent(); processEditPart.setShowEventHandler(showEventHandler); // Call refresh so that both refreshVisuals and refreshChildren will be called. refresh(); } public boolean getShowFaultHandler() { return showFH; } public boolean getShowEventHandler() { return showEH; } public FaultHandler getFaultHandler() { IFaultHandlerHolder holder = BPELUtil.adapt(getProcess(), IFaultHandlerHolder.class); if (holder != null) { return holder.getFaultHandler(getProcess()); } return null; } public EventHandler getEventHandler() { IEventHandlerHolder holder = BPELUtil.adapt(getProcess(), IEventHandlerHolder.class); if (holder != null) { return holder.getEventHandler(getProcess()); } return null; } /** * Is point in fault image. * @param x * @param y * @return true if it is, false if its not. */ public boolean isPointInFaultImage(int x, int y) { if (hasFH) { Point p = new Point(x, y); getFigure().translateToRelative(p); return rectFault.contains(p.x, p.y); } return false; } /** * Is point in event image. * @param x * @param y * @return true if it is, false if its not. */ public boolean isPointInEventImage(int x, int y) { if (hasEH) { Point p = new Point(x, y); getFigure().translateToRelative(p); return rectEvent.contains(p.x, p.y); } return false; } /** * @see org.eclipse.bpel.ui.editparts.BPELEditPart#getDragTracker(org.eclipse.gef.Request) */ @Override public DragTracker getDragTracker(Request request) { return new BPELDragEditPartsTracker(this) { @Override protected boolean handleDoubleClick(int button) { return true; } @Override protected boolean handleButtonDown(int button) { Point point = getLocation(); if (isPointInFaultImage(point.x, point.y)) { setShowFaultHandler(!showFH); return true; } if (isPointInEventImage(point.x, point.y)) { setShowEventHandler(!showEH); return true; } return super.handleButtonDown(button); } }; } private void computeHandlerIconPositions(boolean horizontal){ org.eclipse.draw2d.geometry.Rectangle bounds = getFigure().getBounds(); if(horizontal){ rectFault = new Rectangle(bounds.x, bounds.y + bounds.height - faultImageHeight, faultImageWidth, faultImageHeight); rectEvent = new Rectangle(bounds.x +faultImageWidth, bounds.y + bounds.height - eventImageHeight, eventImageWidth, eventImageHeight); }else{ rectFault = new Rectangle(bounds.x + bounds.width - faultImageWidth - BORDER_WIDTH, bounds.y-1, faultImageWidth, faultImageHeight); rectEvent = new Rectangle(bounds.x + bounds.width - eventImageWidth - BORDER_WIDTH, bounds.y + bounds.height - eventImageHeight+1, eventImageWidth, eventImageHeight); } // Apply the bounds to the figures faultImageFigure.setBounds(new org.eclipse.draw2d.geometry.Rectangle(rectFault.x,rectFault.y,rectFault.width,rectFault.height)); eventImageFigure.setBounds(new org.eclipse.draw2d.geometry.Rectangle(rectEvent.x,rectEvent.y,rectEvent.width,rectEvent.height)); } public Rectangle getRectFault() { return rectFault; } public Rectangle getRectEvent() { return rectEvent; } public void switchLayout(boolean horizontal) { if(horizontal){ getFigure().setBorder(new MarginBorder(5,0,5,0)); }else{ getFigure().setBorder(new MarginBorder(0,7+BORDER_WIDTH,0,7+BORDER_WIDTH)); } } public IFigure getFaultImageFigure() { return faultImageFigure; } public IFigure getEventImageFigure() { return eventImageFigure; } }