/* This file is part of Green. * * Copyright (C) 2005 The Research Foundation of State University of New York * All Rights Under Copyright Reserved, The Research Foundation of S.U.N.Y. * * Green is free software, licensed under the terms of the Eclipse * Public License, version 1.0. The license is available at * http://www.eclipse.org/legal/epl-v10.html */ package edu.buffalo.cse.green.editor.controller; import static edu.buffalo.cse.green.GreenException.GRERR_FIGURE_CONSTRUCTOR; import static edu.buffalo.cse.green.editor.controller.PropertyChange.Children; import static edu.buffalo.cse.green.editor.controller.PropertyChange.Location; import static edu.buffalo.cse.green.editor.controller.PropertyChange.Refresh; import static edu.buffalo.cse.green.editor.controller.PropertyChange.Size; import static edu.buffalo.cse.green.editor.controller.PropertyChange.Visibility; import static edu.buffalo.cse.green.preferences.PreferenceInitializer.P_COLOR_SELECTED; import java.beans.PropertyChangeEvent; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.List; import org.eclipse.draw2d.IFigure; import org.eclipse.draw2d.LayoutListener; import org.eclipse.gef.EditPolicy; import org.eclipse.gef.Request; import org.eclipse.gef.RequestConstants; import org.eclipse.gef.editparts.AbstractGraphicalEditPart; import org.eclipse.gef.editpolicies.ResizableEditPolicy; import org.eclipse.jface.action.Action; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.widgets.Display; import edu.buffalo.cse.green.GreenException; import edu.buffalo.cse.green.PlugIn; import edu.buffalo.cse.green.editor.DiagramEditor; import edu.buffalo.cse.green.editor.action.OpenElementAction; import edu.buffalo.cse.green.editor.controller.policies.DeleteEditPolicy; import edu.buffalo.cse.green.editor.model.AbstractModel; import edu.buffalo.cse.green.editor.model.RootModel; import edu.buffalo.cse.green.editor.model.commands.DeleteCommand; /** * Represents the corresponding controller part for a model part * * @author bcmartin * @author hk47 */ public abstract class AbstractPart extends AbstractGraphicalEditPart { /** * @see org.eclipse.gef.editparts.AbstractGraphicalEditPart#createFigure() */ protected final IFigure createFigure() { IFigure f = doCreateFigure(); setFigure(f); f.setVisible(model().isVisible()); updateColors(f); initialize(); f.addLayoutListener(new LayoutListener() { /** * @see org.eclipse.draw2d.LayoutListener#invalidate(org.eclipse.draw2d.IFigure) */ public void invalidate(IFigure container) {} /** * @see org.eclipse.draw2d.LayoutListener#layout(org.eclipse.draw2d.IFigure) */ public boolean layout(IFigure container) { return false; } /** * @see org.eclipse.draw2d.LayoutListener#postLayout(org.eclipse.draw2d.IFigure) */ public void postLayout(IFigure container) {} /** * @see org.eclipse.draw2d.LayoutListener#remove(org.eclipse.draw2d.IFigure) */ public void remove(IFigure child) {} /** * @see org.eclipse.draw2d.LayoutListener#setConstraint(org.eclipse.draw2d.IFigure, java.lang.Object) */ public void setConstraint(IFigure child, Object constraint) { model().setDrawnSize(child.getPreferredSize()); } }); return f; } /** * Auxiliary method; makes reading easier. */ private AbstractModel<?, ?, ?> model() { return (AbstractModel) getModel(); } /** * @see java.lang.Object#equals(java.lang.Object) */ public boolean equals(Object o) { if (o instanceof AbstractPart) { AbstractPart part = (AbstractPart) o; return model().equals(part.getModel()); } return false; } /** * @see org.eclipse.gef.EditPart#getChildren() */ public List<AbstractPart> getChildren() { List pChildren = super.getChildren(); if (pChildren == null || pChildren.isEmpty()) return new ArrayList<AbstractPart>(); return (ArrayList<AbstractPart>) pChildren; } /** * Retrieves the <code>AbstractPart</code> that corresponds to the given * <code>AbstractModel</code> * * @param model - The <code>AbstractModel</code> * @return The part corresponding to the given model */ public AbstractPart getPartFromModel(AbstractModel model) { return getRootPart().getPartFromModel(model); } /** * @see org.eclipse.gef.editparts.AbstractEditPart#getModelChildren() */ protected List getModelChildren() { return model().getChildren(); } public final void propertyChange(PropertyChangeEvent evt) { } /** * @see org.eclipse.gef.EditPart#activate() */ public void activate() { if (getParent() != null && getParent().isActive() && !this.isActive()) { super.activate(); addListener(Children, new ChildAndVisualsUpdater()); addListener(Location, new VisualsUpdater()); addListener(Refresh, new Refresher()); addListener(Size, new VisualsUpdater()); addListener(Visibility, new VisibilityUpdater()); addPropertyListeners(); } } /** * Adds the appropriate <code>PropertyChange</code> listeners. */ protected abstract void addPropertyListeners(); protected void addListener(PropertyChange kind, PropertyListener listener) { model().addListener(kind, listener); } /** * @see org.eclipse.gef.EditPart#deactivate() */ public void deactivate() { if (isActive()) { super.deactivate(); } } /** * Updates the visual components of this part */ protected final void updateVisuals() { if (Display.getCurrent() != null) { refreshVisuals(); updateColors(getFigure()); } else { Display.getDefault().asyncExec(new Runnable() { /** * @see java.lang.Runnable#run() */ public void run() { refreshVisuals(); updateColors(getFigure()); } }); } } /** * Updates the children of this part */ protected final void updateChildren() { if (Display.getCurrent() != null) { refreshChildren(); } else { Display.getDefault().asyncExec(new Runnable() { /** * @see java.lang.Runnable#run() */ public void run() { refreshChildren(); } }); } } /** * @see org.eclipse.gef.editparts.AbstractEditPart#createEditPolicies() */ protected void createEditPolicies() { installEditPolicy(EditPolicy.COMPONENT_ROLE, new DeleteEditPolicy(this)); } /** * @return A <code>Command</code> for deleting this object */ public abstract DeleteCommand getDeleteCommand(); /** * @return The diagram's root part */ public RootPart getRootPart() { return ((AbstractPart) getParent()).getRootPart(); } /** * @return The diagram's root model */ public RootModel getRootModel() { return (RootModel) getRootPart().getModel(); } /** * @see org.eclipse.gef.EditPart#performRequest(org.eclipse.gef.Request) */ public void performRequest(Request req) { if (req.getType().equals(RequestConstants.REQ_OPEN)) { onDoubleClick(); } } /** * Method implemented to handle double-click events. */ protected abstract void onDoubleClick(); /** * @return The editor that contains this part */ public DiagramEditor getEditor() { return getRootPart().getEditor(); } /** * @return a new <code>OpenElementAction</code> that refers to this editor */ protected Action getOpenElementAction() { OpenElementAction action = new OpenElementAction(); action.setSelectionProvider(getEditor()); return action; } /** * @return The figure that will represent this part. */ protected final IFigure generateFigure() { Constructor[] constructor = PlugIn.getViewPart(getClass()).getConstructors(); if (constructor.length != 1 || constructor[0].getParameterTypes().length != 0) { GreenException.illegalOperation(GRERR_FIGURE_CONSTRUCTOR + "\nClass: " + PlugIn.getViewPart(getClass())); } try { return (IFigure) constructor[0].newInstance(); } catch (IllegalAccessException e) { e.printStackTrace(); return null; } catch (InstantiationException e) { e.printStackTrace(); return null; } catch (InvocationTargetException e) { e.printStackTrace(); return null; } } /** * Updates the colors belonging to the figure. */ protected abstract void updateColors(IFigure f); /** * Creates the figure corresponding to the part. */ protected abstract IFigure doCreateFigure(); /** * @return An <code>EditPolicy</code> appropriate to this part. */ public EditPolicy generateResizableEditPolicy() { return new ResizableEditPolicy(); } /** * Sets the original background color of the figure. */ public abstract void setInitialBackgroundColor(); /** * Sets the background color of the figure when it is selected. */ public void setSelectedBackgroundColor() { Color selectedColor = PlugIn.getColorPreference(P_COLOR_SELECTED); getFigure().setBackgroundColor(selectedColor); } /** * Called after the constructor */ public void initialize() {} class ChildAndVisualsUpdater implements PropertyListener { public void notify(Object oValue, Object nValue) { updateChildren(); updateVisuals(); } } class Refresher implements PropertyListener { public void notify(Object oValue, Object nValue) { getFigure().validate(); updateVisuals(); } } class VisibilityUpdater implements PropertyListener { public void notify(Object oValue, Object nValue) { getFigure().setVisible(nValue.equals(true)); updateChildren(); updateVisuals(); } } class VisualsUpdater implements PropertyListener { public void notify(Object oValue, Object nValue) { updateVisuals(); } } }