/**
* Copyright (c) 2009 Borland Software Corp.
*
* 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:
* Alexander Shatalin (Borland) - initial API and implementation
*/
package org.eclipse.gmf.graphdef.editor.edit.policies;
import java.util.Iterator;
import org.eclipse.draw2d.FocusEvent;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.ImageFigure;
import org.eclipse.draw2d.MouseEvent;
import org.eclipse.draw2d.MouseMotionListener;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.emf.transaction.util.TransactionUtil;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.EditPartListener;
import org.eclipse.gef.LayerConstants;
import org.eclipse.gmf.gmfgraph.Figure;
import org.eclipse.gmf.gmfgraph.GMFGraphPackage;
import org.eclipse.gmf.gmfgraph.RealFigure;
import org.eclipse.gmf.graphdef.editor.edit.parts.AbstractFigureEditPart;
import org.eclipse.gmf.graphdef.editor.edit.policies.assistant.AssistantFigureKeyListener;
import org.eclipse.gmf.graphdef.editor.edit.policies.assistant.BubbleFigure;
import org.eclipse.gmf.graphdef.editor.edit.policies.assistant.HeadlessDiagramGraphicalViewer;
import org.eclipse.gmf.graphdef.editor.edit.policies.assistant.PreviewFigure;
import org.eclipse.gmf.graphdef.editor.edit.policies.assistant.SelectEditPartDragTracker;
import org.eclipse.gmf.graphdef.editor.edit.policies.assistant.SelectableBubbleItemFigure;
import org.eclipse.gmf.graphdef.editor.edit.policies.keyhandler.KeyHandler;
import org.eclipse.gmf.graphdef.editor.edit.policies.keyhandler.KeyPressedRequest;
import org.eclipse.gmf.graphdef.editor.part.GMFGraphDiagramEditorPlugin;
import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart;
import org.eclipse.gmf.runtime.diagram.ui.editpolicies.DiagramAssistantEditPolicy;
import org.eclipse.gmf.runtime.notation.View;
import org.eclipse.swt.widgets.Display;
public class ChildFigureSelectionEditPolicy extends DiagramAssistantEditPolicy implements KeyHandlerEditPolicy {
private static final String PNG_EXTENSION = ".png";
private static final String ICONS_FOLDER = "icons/handles/";
private static final String UNKNOWN_FIGURE_ICON = ICONS_FOLDER + "Unknown" + PNG_EXTENSION;
private BubbleFigure myFeedbackFigure;
private static Figure getFigure(EditPart editPart) {
View view = ((IGraphicalEditPart) editPart).getNotationView();
if (view != null && view.getElement() instanceof Figure) {
return (Figure) view.getElement();
}
return null;
}
public void processRequest(KeyPressedRequest request) {
if (KeyHandler.ACTIVATE_CHILD_SELECTION.equals(request.getKeyStroke()) && !isDiagramAssistantShowing()) {
showDiagramAssistant(request.getLocation());
request.markPerformed();
}
}
public void activate() {
// TODO: copied from DiagramAssistantEditPolicy. M.b. use super
// implementation of this method?
getHost().addEditPartListener(new EditPartListener.Stub() {
public void selectedStateChanged(EditPart editpart) {
if (!editpart.hasFocus() || !shouldShowDiagramAssistant()) {
hideDiagramAssistant();
}
}
});
}
@Override
protected void hideDiagramAssistant() {
if (getHost() instanceof AbstractFigureEditPart) {
((AbstractFigureEditPart) getHost()).setDragAllowed(true);
}
if (getFeedbackFigure() == null) {
return;
}
disposeFeedbackFigure();
}
protected boolean isDiagramAssistant(Object object) {
return object instanceof BubbleFigure;
}
@Override
protected boolean isDiagramAssistantShowing() {
return getFeedbackFigure() != null;
}
@Override
protected void showDiagramAssistant(Point referencePoint) {
if (getFeedbackFigure() != null || getRealFigure() == null || getRealFigure().getChildren().size() == 0) {
return;
}
initFeedbackFigure();
setLocation(getFeedbackFigure(), referencePoint);
if (getHost() instanceof AbstractFigureEditPart) {
((AbstractFigureEditPart) getHost()).setDragAllowed(false);
}
}
private void setLocation(BubbleFigure feedbackFigure, Point referencePoint) {
Point point = referencePoint.getCopy();
getHostFigure().translateToAbsolute(point);
feedbackFigure.translateToRelative(point);
point.translate(0, -feedbackFigure.getSize().height);
feedbackFigure.setLocation(point);
}
private void initFeedbackFigure() {
IFigure layer = getLayer(LayerConstants.HANDLE_LAYER);
myFeedbackFigure = new BubbleFigure();
HeadlessDiagramGraphicalViewer viewer = new HeadlessDiagramGraphicalViewer(getHost().getViewer().getEditPartFactory(), layer.getFont(), TransactionUtil.getEditingDomain(getRealFigure()));
for (Iterator it = getHost().getChildren().iterator(); it.hasNext();) {
IGraphicalEditPart childEditPart = (IGraphicalEditPart) it.next();
Figure figure = getFigure(childEditPart);
if (figure != null) {
final SelectableBubbleItemFigure itemFigure = new SelectableBubbleItemFigure(new SelectEditPartDragTracker(childEditPart));
itemFigure.addMouseMotionListener(new MouseMotionListener.Stub() {
@Override
public void mouseEntered(MouseEvent me) {
myFeedbackFigure.selectChild(itemFigure);
}
});
myFeedbackFigure.add(itemFigure);
PreviewFigure previewFigure = new PreviewFigure(childEditPart.getNotationView(), viewer);
// TODO: Better check for figure instance here.
if (previewFigure.isPreviewValid()) {
previewFigure.setPreferredSize(15, 15);
itemFigure.setItemRepresentation(BubbleFigure.Mode.PREVIEW, previewFigure);
} else {
itemFigure.setItemRepresentation(BubbleFigure.Mode.PREVIEW, new ImageFigure(GMFGraphDiagramEditorPlugin.getInstance().getBundledImage(UNKNOWN_FIGURE_ICON)));
}
itemFigure.setItemRepresentation(BubbleFigure.Mode.ICON, getImageFigure(figure));
if (myFeedbackFigure.getChildren().size() == 1) {
myFeedbackFigure.selectChild(itemFigure);
}
}
}
myFeedbackFigure.setMode(BubbleFigure.Mode.PREVIEW);
myFeedbackFigure.setSize(myFeedbackFigure.getPreferredSize());
layer.add(myFeedbackFigure);
myFeedbackFigure.addKeyListener(new AssistantFigureKeyListener(myFeedbackFigure) {
@Override
protected void hideAssistant() {
hideDiagramAssistant();
}
});
myFeedbackFigure.addFocusListener(new org.eclipse.draw2d.FocusListener.Stub() {
@Override
public void focusLost(FocusEvent fe) {
Display.getCurrent().asyncExec(new Runnable() {
public void run() {
hideDiagramAssistant();
}
});
}
});
myFeedbackFigure.requestFocus();
}
private IFigure getImageFigure(Figure figure) {
switch (figure.eClass().getClassifierID()) {
case GMFGraphPackage.ELLIPSE:
case GMFGraphPackage.LABEL:
case GMFGraphPackage.POINT:
case GMFGraphPackage.POLYGON:
case GMFGraphPackage.POLYLINE:
case GMFGraphPackage.RECTANGLE:
case GMFGraphPackage.ROUNDED_RECTANGLE:
return new ImageFigure(GMFGraphDiagramEditorPlugin.getInstance().getBundledImage(ICONS_FOLDER + figure.eClass().getName() + PNG_EXTENSION));
default:
return new ImageFigure(GMFGraphDiagramEditorPlugin.getInstance().getBundledImage(UNKNOWN_FIGURE_ICON));
}
}
private void disposeFeedbackFigure() {
IFigure layer = getLayer(LayerConstants.HANDLE_LAYER);
layer.remove(getFeedbackFigure());
myFeedbackFigure = null;
}
private RealFigure getRealFigure() {
Figure figure = getFigure(getHost());
return figure instanceof RealFigure ? (RealFigure) figure : null;
}
private BubbleFigure getFeedbackFigure() {
return myFeedbackFigure;
}
}