package info.limpet.stackedcharts.ui.editor.parts; import info.limpet.stackedcharts.model.Chart; import info.limpet.stackedcharts.model.ChartSet; import info.limpet.stackedcharts.model.IndependentAxis; import info.limpet.stackedcharts.model.Orientation; import info.limpet.stackedcharts.model.ScatterSet; import info.limpet.stackedcharts.model.SelectiveAnnotation; import info.limpet.stackedcharts.model.StackedchartsPackage; import info.limpet.stackedcharts.ui.editor.commands.DeleteChartCommand; import info.limpet.stackedcharts.ui.editor.figures.ChartFigure; import info.limpet.stackedcharts.ui.editor.policies.ChartContainerEditPolicy; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.eclipse.draw2d.ActionEvent; import org.eclipse.draw2d.ActionListener; import org.eclipse.draw2d.GridData; import org.eclipse.draw2d.IFigure; import org.eclipse.emf.common.notify.Notification; import org.eclipse.emf.ecore.EAttribute; import org.eclipse.emf.ecore.EReference; import org.eclipse.emf.ecore.util.EContentAdapter; import org.eclipse.gef.EditPart; import org.eclipse.gef.EditPolicy; import org.eclipse.gef.GraphicalEditPart; import org.eclipse.gef.commands.Command; import org.eclipse.gef.commands.CommandStack; import org.eclipse.gef.editparts.AbstractGraphicalEditPart; import org.eclipse.gef.editpolicies.ComponentEditPolicy; import org.eclipse.gef.editpolicies.NonResizableEditPolicy; import org.eclipse.gef.requests.GroupRequest; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.widgets.Display; public class ChartEditPart extends AbstractGraphicalEditPart implements ActionListener { public static final Color BACKGROUND_COLOR = Display.getDefault() .getSystemColor(SWT.COLOR_WHITE); /** * Helper class to handle the container of {@link ScatterSet}s */ @SuppressWarnings("serial") public static class ScatterSetContainer extends ArrayList<ScatterSet> { } public enum ChartPanePosition { MIN, MAX } final private ChartAdapter adapter = new ChartAdapter(); final private SharedAxisAdapter sharedAxisAdapter = new SharedAxisAdapter(); public final ArrayList<EAttribute> _visualUpdates; public final ArrayList<EReference> _childrenUpdates; public ChartEditPart() { // get our model definition final StackedchartsPackage pckg = StackedchartsPackage.eINSTANCE; // collate a list of what features trigger a visual update _visualUpdates = new ArrayList<EAttribute>(); _visualUpdates.add(pckg.getChart_Name()); _visualUpdates.add(pckg.getStyling_LineStyle()); _visualUpdates.add(pckg.getStyling_LineThickness()); _visualUpdates.add(pckg.getStyling_MarkerSize()); _visualUpdates.add(pckg.getStyling_MarkerStyle()); _visualUpdates.add(pckg.getPlainStyling_Color()); // and now collate a list of which attributes trigger the // chidren to update _childrenUpdates = new ArrayList<EReference>(); _childrenUpdates.add(pckg.getChart_MaxAxes()); _childrenUpdates.add(pckg.getChart_MinAxes()); } @Override public void activate() { super.activate(); getModel().eAdapters().add(adapter); sharedAxisAdapter.attachTo(getSharedAxis()); } @Override public void deactivate() { getModel().eAdapters().remove(adapter); // effectively detach the adapter/listener sharedAxisAdapter.attachTo(null); super.deactivate(); } private IndependentAxis getSharedAxis() { return getModel().getParent().getSharedAxis(); } @Override protected IFigure createFigure() { return new ChartFigure(getModel(), this); } @Override public Chart getModel() { return (Chart) super.getModel(); } @Override protected void createEditPolicies() { installEditPolicy(EditPolicy.PRIMARY_DRAG_ROLE, new NonResizableEditPolicy()); installEditPolicy(EditPolicy.CONTAINER_ROLE, new ChartContainerEditPolicy()); installEditPolicy(EditPolicy.COMPONENT_ROLE, new ComponentEditPolicy() { protected Command createDeleteCommand(GroupRequest deleteRequest) { Chart chart = getModel(); ChartSet parent = chart.getParent(); DeleteChartCommand deleteChartCommand = new DeleteChartCommand(parent, chart); return deleteChartCommand; } }); } @SuppressWarnings( {"rawtypes", "unchecked"}) @Override protected List getModelChildren() { List modelChildren = new ArrayList(); modelChildren.addAll(Arrays.asList(ChartPanePosition.values())); ScatterSetContainer scatterSets = new ScatterSetContainer(); for (SelectiveAnnotation annotation : getSharedAxis().getAnnotations()) { if (annotation.getAnnotation() instanceof ScatterSet && annotation.getAppearsIn().contains(getModel())) { scatterSets.add((ScatterSet) annotation.getAnnotation()); } } modelChildren.add(scatterSets); return modelChildren; } @Override protected void refreshVisuals() { String name = getModel().getName(); ChartFigure chartFigure = (ChartFigure) getFigure(); chartFigure.setName(name); chartFigure .setVertical(getModel().getParent().getOrientation() == Orientation.VERTICAL); GridData gridData = new GridData(); gridData.grabExcessHorizontalSpace = true; gridData.grabExcessVerticalSpace = true; gridData.horizontalAlignment = SWT.FILL; gridData.verticalAlignment = SWT.FILL; ((GraphicalEditPart) getParent()).setLayoutConstraint(this, figure, gridData); } protected void refreshChildren() { // remove all Childs @SuppressWarnings("unchecked") List<EditPart> children = getChildren(); for (EditPart object : new ArrayList<EditPart>(children)) { removeChild(object); } // add back all model elements @SuppressWarnings("rawtypes") List modelObjects = getModelChildren(); for (int i = 0; i < modelObjects.size(); i++) { addChild(createChild(modelObjects.get(i)), i); } ((ChartFigure) getFigure()).getLayoutManager().layout(getFigure()); } @Override public void actionPerformed(ActionEvent event) { Command deleteCommand = getCommand(new GroupRequest(REQ_DELETE)); if (deleteCommand != null) { CommandStack commandStack = getViewer().getEditDomain().getCommandStack(); commandStack.execute(deleteCommand); } } public class ChartAdapter extends EContentAdapter { @Override public void notifyChanged(Notification notification) { Object feature = notification.getFeature(); // ok, now check if anything changed that causes a visual update for (final EAttribute thisA : _visualUpdates) { if (feature == thisA) { refreshVisuals(); break; } } // ok, now check for a children update for (final EReference thisA : _childrenUpdates) { if (feature == thisA) { refreshChildren(); break; } } } } /** * Update scatter sets in the scatter set container when model changes. Use an * {@link EContentAdapter}, since we'd like to be notified when multiple properties of different * objects in the shared axis get changed. */ public class SharedAxisAdapter extends EContentAdapter { private IndependentAxis independentAxis; public void notifyChanged(Notification notification) { super.notifyChanged(notification); int featureId = notification.getFeatureID(StackedchartsPackage.class); switch (featureId) { case StackedchartsPackage.INDEPENDENT_AXIS__ANNOTATIONS: case StackedchartsPackage.SELECTIVE_ANNOTATION__APPEARS_IN: refreshChildren(); break; } } void attachTo(IndependentAxis independentAxis) { if (this.independentAxis != null) { this.independentAxis.eAdapters().remove(this); } this.independentAxis = independentAxis; if (this.independentAxis != null) { this.independentAxis.eAdapters().add(this); } } } }