/*****************************************************************************
* Copyright (c) 2009 CEA LIST.
*
*
* 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:
* Patrick Tessier (CEA LIST) Patrick.tessier@cea.fr - Initial API and implementation
*
*****************************************************************************/
package org.eclipse.papyrus.uml.diagram.common.editpolicies;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.eclipse.draw2d.ColorConstants;
import org.eclipse.draw2d.FigureCanvas;
import org.eclipse.draw2d.Graphics;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.Label;
import org.eclipse.draw2d.MouseEvent;
import org.eclipse.draw2d.MouseListener;
import org.eclipse.draw2d.RoundedRectangle;
import org.eclipse.draw2d.Viewport;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.gef.DragTracker;
import org.eclipse.gef.EditPartViewer;
import org.eclipse.gef.Handle;
import org.eclipse.gef.LayerConstants;
import org.eclipse.gmf.runtime.diagram.ui.editparts.GraphicalEditPart;
import org.eclipse.gmf.runtime.diagram.ui.editpolicies.DiagramAssistantEditPolicy;
import org.eclipse.gmf.runtime.diagram.ui.internal.l10n.DiagramUIPluginImages;
import org.eclipse.gmf.runtime.diagram.ui.parts.DiagramGraphicalViewer;
import org.eclipse.gmf.runtime.notation.Diagram;
import org.eclipse.papyrus.infra.core.editorsfactory.IPageIconsRegistry;
import org.eclipse.papyrus.infra.core.editorsfactory.PageIconsRegistry;
import org.eclipse.papyrus.infra.core.sasheditor.contentprovider.IPageMngr;
import org.eclipse.papyrus.infra.core.services.ServiceException;
import org.eclipse.papyrus.infra.core.utils.EditorUtils;
import org.eclipse.papyrus.infra.hyperlink.helper.AbstractHyperLinkHelper;
import org.eclipse.papyrus.infra.hyperlink.helper.HyperLinkHelperFactory;
import org.eclipse.papyrus.infra.hyperlink.object.HyperLinkObject;
import org.eclipse.papyrus.infra.hyperlink.ui.HyperLinkManagerShell;
import org.eclipse.papyrus.infra.hyperlink.util.HyperLinkException;
import org.eclipse.papyrus.infra.hyperlink.util.HyperLinkHelpersRegistrationUtil;
import org.eclipse.papyrus.infra.hyperlink.util.HyperLinkLabelProvider;
import org.eclipse.papyrus.uml.diagram.common.ui.hyperlinkshell.AdvancedHLManager;
import org.eclipse.swt.graphics.Image;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.eclipse.uml2.uml.Element;
import org.eclipse.uml2.uml.Package;
/**
* The Class HyperLinkPopupBarEditPolicy can be applied on edit part to display
* shortcuts on sub-diagrams or to associate hyper-link of files
*/
public class HyperLinkPopupBarEditPolicy extends DiagramAssistantEditPolicy {
public static Package topPackage(Element element) {
if(element.getOwner() == null) {
return (Package)element;
} else {
return topPackage(element.getOwner());
}
}
/**
* Default tool placed on the popup bar.
*
* @author affrantz@us.ibm.com modified by Patrick Tessier
*/
private class PopupBarLabelHandle extends Label implements Handle {
/**
* flag to drawFocus rect around the handle when the mouse rolls over
* it.
*/
private boolean myMouseOver = false;
/** The dragTracker CreationTool associated with the handle *. */
private Object myObject = null;
/**
* constructor.
*
* @param theImage
* the image to display
* @param anObject
* the an object
*/
public PopupBarLabelHandle(Object anObject, Image theImage) {
super(theImage);
myObject = anObject;
this.setOpaque(true);
this.setBackgroundColor(ColorConstants.buttonLightest);
}
/**
* Dispose.
*/
public void dispose() {
if(this.getIcon() != null && (!this.getIcon().isDisposed())) {
this.getIcon().dispose();
}
}
/**
* Gets the accessible location.
*
* @return the accessible location
*
* @see org.eclipse.gef.Handle#getAccessibleLocation()
*/
public Point getAccessibleLocation() {
return null;
}
/**
* {@inheritedDoc}
*/
public DragTracker getDragTracker() {
// TODO Auto-generated method stub
return null;
}
/**
* Gets the referenced object.
*
* @return the referenced object
*
* @see org.eclipse.gef.Handle#getDragTracker()
*/
public Object getReferencedObject() {
return myObject;
}
/**
* Handle mouse entered.
*
* @param event
* the event
*
* @see org.eclipse.draw2d.IFigure#handleMouseEntered(org.eclipse.draw2d.MouseEvent)
* flip myMouseOver bit and repaint
*/
@Override
public void handleMouseEntered(MouseEvent event) {
super.handleMouseEntered(event);
this.setBackgroundColor(ColorConstants.button);
myMouseOver = true;
// repaint();
}
/**
* Handle mouse exited.
*
* @param event
* the event
*
* @see org.eclipse.draw2d.IFigure#handleMouseExited(org.eclipse.draw2d.MouseEvent)
* flip myMouseOver bit and repaint
*/
@Override
public void handleMouseExited(MouseEvent event) {
super.handleMouseExited(event);
this.setBackgroundColor(ColorConstants.white);
myMouseOver = false;
// repaint();
}
/**
* Handle mouse pressed.
*
* @param event
* the event
*
* @see org.eclipse.draw2d.IFigure#handleMousePressed(org.eclipse.draw2d.MouseEvent)
* set PopupBarEditPolicy.myActionMoveFigure bit so the popup bar
* is not dismissed after creating an item in the editpart
*/
@Override
public void handleMousePressed(MouseEvent event) {
if(1 == event.button) {
}
super.handleMousePressed(event);
}
/**
* Paint border.
*
* @param graphics
* the graphics
*
* @see org.eclipse.draw2d.Figure#paintBorder(org.eclipse.draw2d.Graphics)
* paint a focus rectangle for the label if the mouse is inside the
* label
*/
@Override
protected void paintBorder(Graphics graphics) {
super.paintBorder(graphics);
if(myMouseOver) {
Rectangle area = getClientArea();
graphics.setForegroundColor(ColorConstants.black);
graphics.setBackgroundColor(ColorConstants.white);
graphics.drawFocus(area.x, area.y, area.width - 1, area.height - 1);
}
}
/**
* Paint figure.
*
* @param graphics
* the graphics
*
* @see org.eclipse.draw2d.Figure#paintFigure(org.eclipse.draw2d.Graphics)
*/
@Override
protected void paintFigure(Graphics graphics) {
if(!isEnabled()) {
Image theImage = this.getIcon();
if(theImage != null) {
graphics.translate(bounds.x, bounds.y);
graphics.drawImage(theImage, getIconLocation());
graphics.translate(-bounds.x, -bounds.y);
return;
}
}
super.paintFigure(graphics);
}
}
/**
* The Class PopupBarLabelPlusHandle.
*/
private class PopupBarLabelPlusHandle extends PopupBarLabelHandle {
/**
* Instantiates a new popup bar label plus handle.
*/
public PopupBarLabelPlusHandle() {
super(null, AbstractUIPlugin.imageDescriptorFromPlugin("org.eclipse.papyrus.uml.diagram.common", "/icons/obj16/Plus.gif").createImage());
// TODO Auto-generated constructor stub
}
}
/**
* Listens for mouse key presses so the popup bar can be dismissed if the
* context menu is displayed.
*
* @author affrantz@us.ibm.com
*/
private class PopupBarMouseListener extends MouseListener.Stub {
/**
* Mouse pressed.
*
* @param me
* the me
*
* @see org.eclipse.draw2d.MouseListener#mousePressed(org.eclipse.draw2d.MouseEvent)
*/
@Override
public void mousePressed(MouseEvent me) {
if(3 == me.button) // context menu, hide the popup bar
{
hideDiagramAssistant();
}
if(1 == me.button) // context menu, hide the popup bar
{
if(me.getSource() instanceof PopupBarLabelPlusHandle) {
hyperLinkManagerShell = new AdvancedHLManager(getEditorRegistry(), ((GraphicalEditPart)getHost()).getEditingDomain(), (Element)((GraphicalEditPart)getHost()).getNotationView().getElement(), ((GraphicalEditPart)getHost()).getNotationView(), topPackage((Element)((GraphicalEditPart)getHost()).getNotationView().getElement()), hyperlinkHelperFactory);
hyperLinkManagerShell.setInput(hyperLinkObjectList);
hyperLinkManagerShell.open();
} else if(me.getSource() instanceof PopupBarLabelHandle) {
if((((PopupBarLabelHandle)me.getSource()).getReferencedObject()) instanceof HyperLinkObject) {
HyperLinkObject hyperLinkObject = (HyperLinkObject)(((PopupBarLabelHandle)me.getSource()).getReferencedObject());
hyperLinkObject.executeSelectPressed();
}
}
hideDiagramAssistant();
}
super.mousePressed(me);
// setPopupBarOnDiagramActivated(true);
}
/**
* {@inheritedDoc}
*/
@Override
public void mouseReleased(MouseEvent me) {
super.mouseReleased(me);
}
}
/**
* This is the figure that represents the ballon portion of the popup bar.
*
* @author affrantz@us.ibm.com
*/
private class RoundedRectangleWithTail extends RoundedRectangle {
/** The b is init. */
private boolean bIsInit = false;
/** The my corner dimension. */
// @unused
private final int myCornerDimension = 3;
/** The my tail image. */
private Image myTailImage = null;
/**
* constructor.
*/
public RoundedRectangleWithTail() {
// we do not make the myActionTailFigue opaque because it
// doesn't look good when magnification is set.
this.setFill(true);
this.setBackgroundColor(ColorConstants.yellow);
this.setForegroundColor(ColorConstants.orange);
this.setVisible(true);
this.setEnabled(true);
this.setOpaque(true);
}
/**
* Gets the tail.
*
* @return the tail
*/
// @unused
private Image getTail() {
if(!bIsInit) {
if(myTailImage == null) {
myTailImage = IMAGE_POPUPBAR_PLUS;
bIsInit = true;
}
}
return myTailImage;
}
}
/** The IMAG e_ popupba r_ plus. */
private static Image IMAGE_POPUPBAR_PLUS = DiagramUIPluginImages.get(DiagramUIPluginImages.IMG_POPUPBAR_PLUS);
/** The POPUPBA r_ mov e_ figure. */
// @unused
static private int POPUPBAR_MOVE_FIGURE = 0x02; /*
* Ignore the first
* figureMoved event when
* creating elements inside
* a shape via a popup bar
*/
/** The POPUPBA r_ ondiagramactivated. */
// @unused
static private int POPUPBAR_ONDIAGRAMACTIVATED = 0x10; /*
* For popup bars on
* diagram and
* machine edit
* parts, where we
* POPUPBAR_DISPLAYATMOUSEHOVERLOCATION
* , don't display
* popup bar until
* user clicks on
* surface
*/
/** The editor registry. */
private IPageIconsRegistry editorRegistry;
/** The figure bar. */
private IFigure figureBar;
/** The hyper link manager shell. */
private HyperLinkManagerShell hyperLinkManagerShell;
/** Images created that must be deleted when popup bar is removed. */
protected List<Image> imagesToBeDisposed = new ArrayList<Image>();
/** mouse keys listener for the owner shape. */
private final PopupBarMouseListener myMouseKeyListener = new PopupBarMouseListener();
protected ArrayList<HyperLinkObject> hyperLinkObjectList;
protected HyperLinkHelperFactory hyperlinkHelperFactory;
/**
* {@inheritedDoc}
*/
@Override
public void activate() {
super.activate();
}
public HyperLinkPopupBarEditPolicy() {
super();
ArrayList<AbstractHyperLinkHelper> hyperLinkHelpers = new ArrayList<AbstractHyperLinkHelper>();
//TODO
// hyperLinkHelpers.add(new DiagramHyperLinkHelper());
// hyperLinkHelpers.add(new DocumentHyperLinkHelper());
// hyperLinkHelpers.add(new WebHyperLinkHelper());
hyperLinkHelpers.addAll(HyperLinkHelpersRegistrationUtil.INSTANCE.getAllRegisteredHyperLinkHelper());
hyperlinkHelperFactory = new HyperLinkHelperFactory(hyperLinkHelpers);
}
/**
* Adds the object list in the popup bar.
*
* @param imageLocation
* the image location that will represent the object
* @param positonwidth
* the positonwidth to display the icon into the popup
* @param objectList
* the object list to add
*
* @return the int the new position after adding all objects in the list
*/
public int addObjectList(int positonwidth, List<?> objectList) {
for(int i = 0; i < objectList.size(); i++) {
PopupBarLabelHandle handle = null;
HyperLinkLabelProvider hyperLinkLabelProvider = new HyperLinkLabelProvider(getEditorRegistry());
handle = new PopupBarLabelHandle(hyperLinkObjectList.get(i), hyperLinkLabelProvider.getImage(objectList.get(i)));
Rectangle r1 = new Rectangle();
r1.setLocation(positonwidth, 5);
positonwidth += 20;
r1.setSize(16, 16);
Label l = new Label();
l.setText(hyperLinkLabelProvider.getTooltipText(hyperLinkObjectList.get(i)));
handle.setToolTip(l);
handle.setPreferredSize(16, 16);
handle.setBounds(r1);
handle.setBackgroundColor(ColorConstants.white);
getFigureBar().add(handle);
handle.addMouseListener(this.myMouseKeyListener);
handle.addMouseMotionListener(this);
}
return positonwidth;
}
/**
* Return the EditorRegistry for nested editor descriptors. Subclass should
* implements this method in order to return the registry associated to the
* extension point namespace.
*
* @return the EditorRegistry for nested editor descriptors
*
* @generated NOT
*/
protected IPageIconsRegistry createEditorRegistry() {
try {
return EditorUtils.getServiceRegistry().getService(IPageIconsRegistry.class);
} catch (ServiceException e) {
// Return an empty registry always providing null;
return new PageIconsRegistry();
}
}
/**
* Creates the popup bar figure.
*
* @return the i figure
*/
protected IFigure createPopupBarFigure() {
figureBar = new RoundedRectangleWithTail();
return figureBar;
}
/**
* Gets the editor registry.
*
* @return the singleton eINSTANCE of editor registry
*
* @generated NOT Get the EditorRegistry used to create editor instances.
* This default implementation return the singleton eINSTANCE.
* This method can be subclassed to return another registry.
*/
protected IPageIconsRegistry getEditorRegistry() {
if(editorRegistry == null) {
editorRegistry = createEditorRegistry();
}
return editorRegistry;
}
/**
* Gets the figure bar.
*
* @return the figure bar
*/
protected IFigure getFigureBar() {
return figureBar;
}
/**
* getAll diag in relation with this element or subelements.
*
* @return the sub diagrams
*/
// @unused
protected ArrayList<Diagram> getSubDiagrams() {
Element host = (Element)((GraphicalEditPart)getHost()).getNotationView().getElement();
ArrayList<Diagram> result = new ArrayList<Diagram>();
if(host != null) {
try {
IPageMngr iPageMngr = EditorUtils.getIPageMngr();
Iterator<Object> iterator = iPageMngr.allPages().iterator();
while(iterator.hasNext()) {
Object current = iterator.next();
if(current instanceof Diagram) {
Element diagElement = (Element)((Diagram)current).getElement();
if(host.equals(diagElement) || host.allOwnedElements().contains(diagElement)) {
result.add((Diagram)current);
}
}
}
} catch (Exception e) {
}
}
return result;
}
/**
* {@inheritedDoc}
*/
@Override
protected void hideDiagramAssistant() {
if(getFigureBar() != null) {
getFigureBar().removeMouseMotionListener(this);
getFigureBar().removeMouseListener(myMouseKeyListener);
IFigure layer = getLayer(LayerConstants.HANDLE_LAYER);
if(getFigureBar().getParent() != null) {
layer.remove(getFigureBar());
}
if(imagesToBeDisposed != null) {
for(Iterator iter = figureBar.getChildren().iterator(); iter.hasNext();) {
Object current = iter.next();
if(current instanceof PopupBarLabelHandle) {
((PopupBarLabelHandle)current).dispose();
}
}
imagesToBeDisposed.clear();
}
}
figureBar = null;
}
/**
* {@inheritedDoc}
*/
@Override
protected boolean isDiagramAssistant(Object object) {
return object instanceof RoundedRectangleWithTail || object instanceof PopupBarLabelHandle;
}
/**
* {@inheritedDoc}
*/
@Override
protected boolean isDiagramAssistantShowing() {
return true;
}
/**
* {@inheritedDoc}.
*
* @return true, if checks if is preference on
*/
@Override
protected boolean isPreferenceOn() {
return true;
}
/**
* fill the popup bar.
*
* @return the width of popup bar
*/
protected int populatePopup() {
int xLoc = 5;
if(getFigureBar() != null) {
// add all subdiagrams
try {
hyperLinkObjectList = (ArrayList<HyperLinkObject>)hyperlinkHelperFactory.getAllreferenced(((GraphicalEditPart)getHost()).getNotationView());
} catch (HyperLinkException e) {
e.printStackTrace();
}
xLoc = addObjectList(xLoc, hyperLinkObjectList);
// add the PLUS button
PopupBarLabelHandle handle = new PopupBarLabelPlusHandle();
Rectangle r1 = new Rectangle();
r1.setLocation(xLoc, 5);
xLoc += 20;
r1.setSize(16, 16);
Label l = new Label();
l.setText("Add hyperlink");
handle.setToolTip(l);
handle.setPreferredSize(16, 16);
handle.setBounds(r1);
handle.setBackgroundColor(ColorConstants.white);
getFigureBar().add(handle);
handle.addMouseListener(this.myMouseKeyListener);
handle.addMouseMotionListener(this);
}
return xLoc;
}
/**
* {@inheritedDoc}.
*
* @param referencePoint
* the reference point
*/
@Override
protected void showDiagramAssistant(Point referencePoint) {
if(getFigureBar() == null) {
createPopupBarFigure();
int width = populatePopup();
IFigure layer = getLayer(LayerConstants.HANDLE_LAYER);
layer.add(getFigureBar());
if(referencePoint == null) {
referencePoint = getHostFigure().getBounds().getCenter();
}
Point position = getHostFigure().getBounds().getBottomLeft();
getHostFigure().translateToAbsolute(position);
EditPartViewer viewer = getHost().getRoot().getViewer();
Viewport viewport = null;
if(viewer instanceof DiagramGraphicalViewer) {
viewport = ((FigureCanvas)((DiagramGraphicalViewer)viewer).getControl()).getViewport();
}
if(viewport != null) {
position.x = position.x + viewport.getClientArea().x;
position.y = position.y + viewport.getClientArea().y;
}
getFigureBar().setSize(width, 30);
getFigureBar().setLocation(position);
getFigureBar().setBackgroundColor(ColorConstants.white);
getFigureBar().setForegroundColor(ColorConstants.orange);
// dismiss the popup bar after a delay
if(!shouldAvoidHidingDiagramAssistant()) {
hideDiagramAssistantAfterDelay(getDisappearanceDelay());
}
}
}
}