/****************************************************************************** * Copyright (c) 2002, 2006 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.gmf.runtime.diagram.ui.editpolicies; import java.util.ArrayList; import java.util.List; import org.eclipse.draw2d.IFigure; import org.eclipse.draw2d.PositionConstants; import org.eclipse.draw2d.geometry.Dimension; import org.eclipse.draw2d.geometry.Point; import org.eclipse.gef.EditPart; import org.eclipse.gef.EditPartListener; import org.eclipse.gef.commands.Command; import org.eclipse.gef.requests.ChangeBoundsRequest; import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart; import org.eclipse.gmf.runtime.diagram.ui.editparts.ResizableCompartmentEditPart; import org.eclipse.gmf.runtime.diagram.ui.figures.BorderedNodeFigure; import org.eclipse.gmf.runtime.diagram.ui.figures.ResizableCompartmentFigure; import org.eclipse.gmf.runtime.diagram.ui.handles.CompartmentCollapseHandle; import org.eclipse.gmf.runtime.diagram.ui.internal.handles.CompartmentResizeHandle; /** * A resizable editpolicy for resizable compartments. The editpolicy could be * vertical or horizontal * * @author melaasar */ public class ResizableCompartmentEditPolicy extends ResizableEditPolicyEx { private boolean horizontal; /** * Creates a new vertical ResizableCompartmentEditPolicy */ public ResizableCompartmentEditPolicy() { this(false); } /** * creates a new ResizableCompartmentEditPolicy with the given orientation * * @param horizontal */ public ResizableCompartmentEditPolicy(boolean horizontal) { this.horizontal = horizontal; } /** * @return Whether the editpolicy is horizontal */ protected boolean isHorizontal() { return horizontal; } /** * This method is used to get the collapse handle(s). Subclasses can * override to provide different collapse handles * * @return a list of collapse handles */ protected List createCollapseHandles() { IGraphicalEditPart part = (IGraphicalEditPart) getHost(); List collapseHandles = new ArrayList(); collapseHandles.add(new CompartmentCollapseHandle(part)); return collapseHandles; } /** * @see org.eclipse.gef.editpolicies.SelectionHandlesEditPolicy#createSelectionHandles() */ protected List createSelectionHandles() { IGraphicalEditPart part = (IGraphicalEditPart) getHost(); int d1 = isHorizontal() ? PositionConstants.WEST : PositionConstants.NORTH; int d2 = isHorizontal() ? PositionConstants.EAST : PositionConstants.SOUTH; List selectionHandles = new ArrayList(); selectionHandles.addAll(createCollapseHandles()); selectionHandles.add(new CompartmentResizeHandle(part, d1)); selectionHandles.add(new CompartmentResizeHandle(part, d2)); return selectionHandles; } /** * @return the <code>ResizableCompartmentFigure</code> that is the * corresponding figure for the host edit part. */ private ResizableCompartmentFigure getCompartmentFigure() { ResizableCompartmentFigure compartmentFigure = null; if (getGraphicalEditPart() instanceof ResizableCompartmentEditPart) { compartmentFigure = ((ResizableCompartmentEditPart) getGraphicalEditPart()) .getCompartmentFigure(); } else if (getGraphicalEditPart().getFigure() instanceof ResizableCompartmentFigure) { compartmentFigure = (ResizableCompartmentFigure) getGraphicalEditPart() .getFigure(); } // TODO: remove later. this is a temporary fix for defect // RATLC00522565 // eventually we will put the BorderedNodeFigure inside the resizable // compartment else if (getGraphicalEditPart().getFigure() instanceof BorderedNodeFigure) { BorderedNodeFigure gpf = (BorderedNodeFigure) getGraphicalEditPart() .getFigure(); IFigure f = gpf.getMainFigure(); if (f instanceof ResizableCompartmentFigure) { compartmentFigure = (ResizableCompartmentFigure) f; } } return compartmentFigure; } /** * @see org.eclipse.gef.editpolicies.SelectionEditPolicy#showSelection() */ protected void showSelection() { super.showSelection(); if (getHost().getSelected() != EditPart.SELECTED_NONE) { ResizableCompartmentFigure compartmentFigure = getCompartmentFigure(); if (compartmentFigure != null) { compartmentFigure.setSelected(true); } } } /** * @see org.eclipse.gef.editpolicies.SelectionEditPolicy#hideSelection() */ protected void hideSelection() { super.hideSelection(); if (getHost().getSelected() == EditPart.SELECTED_NONE) { ResizableCompartmentFigure compartmentFigure = getCompartmentFigure(); if (compartmentFigure != null) { compartmentFigure.setSelected(false); } } } /* (non-Javadoc) * @see org.eclipse.gef.editpolicies.SelectionEditPolicy#activate() */ public void activate() { super.activate(); if (getHost().getParent().getSelected() != EditPart.SELECTED_NONE) setSelectedState(); } private EditPartListener hostListener; private EditPartListener parentListener; /** * @see org.eclipse.gef.editpolicies.SelectionEditPolicy#addSelectionListener() */ protected void addSelectionListener() { hostListener = new EditPartListener.Stub() { public void selectedStateChanged(EditPart part) { setSelectedState(); setFocus(part.hasFocus()); } }; getHost().addEditPartListener(hostListener); parentListener = new EditPartListener.Stub() { public void selectedStateChanged(EditPart part) { setSelectedState(); } }; getParentGraphicEditPart().addEditPartListener(parentListener); } /** * @see org.eclipse.gef.editpolicies.SelectionEditPolicy#removeSelectionListener() */ protected void removeSelectionListener() { getHost().removeEditPartListener(hostListener); getParentGraphicEditPart().removeEditPartListener(parentListener); } /** * Determine the select state of the policy based on: 1- The select state of * the compartment editpart 2- The select state of the parent graphic * editpart 3- The visibility state of the compartment editpart */ protected void setSelectedState() { int hostState = getHost().getSelected(); int topState = EditPart.SELECTED_NONE; if (getGraphicalEditPart().getTopGraphicEditPart() != null) { topState = getGraphicalEditPart().getTopGraphicEditPart().getSelected(); } boolean vis = getGraphicalEditPart().getNotationView().isVisible(); if (vis && ((hostState != EditPart.SELECTED_NONE || topState != EditPart.SELECTED_NONE))) setSelectedState(EditPart.SELECTED); else setSelectedState(EditPart.SELECTED_NONE); } private IGraphicalEditPart getParentGraphicEditPart() { return (IGraphicalEditPart) getGraphicalEditPart().getParent(); } private IGraphicalEditPart getGraphicalEditPart() { return (IGraphicalEditPart) getHost(); } /** * @see org.eclipse.gef.editpolicies.NonResizableEditPolicy#showChangeBoundsFeedback(org.eclipse.gef.requests.ChangeBoundsRequest) */ protected void showChangeBoundsFeedback(ChangeBoundsRequest request) { super.showChangeBoundsFeedback(getResizeChildrenRequest(request)); } /** * @see org.eclipse.gef.editpolicies.ResizableEditPolicy#getResizeCommand(org.eclipse.gef.requests.ChangeBoundsRequest) */ protected Command getResizeCommand(ChangeBoundsRequest request) { return getHost().getParent().getCommand( getResizeChildrenRequest(request)); } /** * Creates a new ChangeBoundsRequest that respects the min and max of the * resize deltas */ private ChangeBoundsRequest getResizeChildrenRequest(ChangeBoundsRequest r) { Dimension delta = r.getSizeDelta(); ResizableCompartmentFigure f = getCompartmentFigure(); Dimension fd = f.getSize().getExpanded(delta); fd.intersect(f.getMaximumSize()).union(f.getMinimumSize()); delta = fd.shrink(f.getSize().width, f.getSize().height); boolean moved = (r.getResizeDirection() & PositionConstants.NORTH_WEST) != 0; IFigure a = f.getAdjacentSibling(moved); if (a != null) { Dimension ad = a.getSize().getExpanded(delta.negate()); ad.intersect(a.getMaximumSize()).union(a.getMinimumSize()); delta = ad.shrink(a.getSize().width, a.getSize().height).negate(); } else { delta.shrink(delta.width, delta.height); } ChangeBoundsRequest req = new ChangeBoundsRequest(REQ_RESIZE_CHILDREN); req.setEditParts(getHost()); req.setLocation(r.getLocation()); req.setResizeDirection(r.getResizeDirection()); req.setSizeDelta(delta); if (moved) req.setMoveDelta(new Point(-delta.width, -delta.height)); return req; } }