All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.gef.editpolicies.LayoutEditPolicy Maven / Gradle / Ivy

The newest version!
/*******************************************************************************
 * Copyright (c) 2000, 2010, 2012 IBM Corporation, Gerhardt Informatics Kft. 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
 *     Gerhardt Informatics Kft. - GEFGWT port
 *******************************************************************************/
package org.eclipse.gef.editpolicies;

import java.util.List;

import org.eclipse.draw2d.ColorConstants;
import org.eclipse.draw2d.FigureUtilities;
import org.eclipse.draw2d.Graphics;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.RectangleFigure;
import org.eclipse.draw2d.Shape;
import org.eclipse.draw2d.geometry.Insets;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Translatable;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.EditPartListener;
import org.eclipse.gef.EditPolicy;
import org.eclipse.gef.GraphicalEditPart;
import org.eclipse.gef.Request;
import org.eclipse.gef.RequestConstants;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.requests.ChangeBoundsRequest;
import org.eclipse.gef.requests.CreateRequest;

/**
 * Provides support for interacting with children
 * GraphicalEditParts with the host figure's current
 * {@link org.eclipse.draw2d.LayoutManager}.
 * 

* LayoutEditPolicies are responsible for moving, resizing, re-parenting, and * creating children. The should provide Commands for all of these * operations. Feedback on the container can also be useful for some layouts * like grids. *

* LayoutEditPolicies will decorate the host's children with "satellite" * EditPolicies. These policies are installed using the * {@link EditPolicy#PRIMARY_DRAG_ROLE}. Simple layouts will use either * {@link ResizableEditPolicy} or {@link NonResizableEditPolicy}, depending on * how the LayoutManager works, and/or attributes of the child EditPart. * * @author rhudson * @author msorens * @author anyssen */ public abstract class LayoutEditPolicy extends GraphicalEditPolicy { private IFigure sizeOnDropFeedback; private EditPartListener listener; /** * Extends activate() to allow proper decoration of children. * * @see org.eclipse.gef.EditPolicy#activate() */ public void activate() { setListener(createListener()); decorateChildren(); super.activate(); } /** * Returns the "satellite" EditPolicy used to decorate the child. * * @param child * the child EditPart * @return an EditPolicy to be installed as the * {@link EditPolicy#PRIMARY_DRAG_ROLE} */ protected abstract EditPolicy createChildEditPolicy(EditPart child); /** * creates the EditPartListener for observing when children are added to the * host. * * @return EditPartListener */ protected EditPartListener createListener() { return new EditPartListener.Stub() { public void childAdded(EditPart child, int index) { decorateChild(child); } }; } /** * Override to provide custom feedback figure for the given create request. * * @param createRequest * the create request * @return custom feedback figure */ protected IFigure createSizeOnDropFeedback(CreateRequest createRequest) { return null; } /** * Overrides deactivate to remove the EditPartListener. * * @see org.eclipse.gef.EditPolicy#deactivate() */ public void deactivate() { if (sizeOnDropFeedback != null) { removeFeedback(sizeOnDropFeedback); sizeOnDropFeedback = null; } setListener(null); super.deactivate(); } /** * Decorates the child with a {@link EditPolicy#PRIMARY_DRAG_ROLE} such as * {@link ResizableEditPolicy}. * * @param child * the child EditPart being decorated */ protected void decorateChild(EditPart child) { EditPolicy policy = createChildEditPolicy(child); child.installEditPolicy(EditPolicy.PRIMARY_DRAG_ROLE, policy); } /** * Decorates all existing children. This method is called on activation. */ protected void decorateChildren() { List children = getHost().getChildren(); for (int i = 0; i < children.size(); i++) decorateChild((EditPart) children.get(i)); } /** * Erases target layout feedback. This method is the inverse of * {@link #showLayoutTargetFeedback(Request)}. * * @param request * the Request */ protected void eraseLayoutTargetFeedback(Request request) { } /** * Erases size-on-drop feedback used during creation. * * @param request * the Request */ protected void eraseSizeOnDropFeedback(Request request) { if (sizeOnDropFeedback != null) { removeFeedback(sizeOnDropFeedback); sizeOnDropFeedback = null; } } /** * Calls two more specific methods depending on the Request. * * @see org.eclipse.gef.EditPolicy#eraseTargetFeedback(Request) */ public void eraseTargetFeedback(Request request) { if (REQ_ADD.equals(request.getType()) || REQ_MOVE.equals(request.getType()) || REQ_RESIZE_CHILDREN.equals(request.getType()) || REQ_CREATE.equals(request.getType()) || REQ_CLONE.equals(request.getType())) eraseLayoutTargetFeedback(request); if (REQ_CREATE.equals(request.getType())) eraseSizeOnDropFeedback(request); } /** * Override to return the Command to perform an * {@link RequestConstants#REQ_ADD ADD}. By default, null is * returned. * * @param request * the ADD Request * @return A command to perform the ADD. */ protected Command getAddCommand(Request request) { return null; } /** * Override to contribute to clone requests. * * @param request * the clone request * @return the command contribution to the clone */ protected Command getCloneCommand(ChangeBoundsRequest request) { return null; } /** * Factors incoming requests into various specific methods. * * @see org.eclipse.gef.EditPolicy#getCommand(Request) */ public Command getCommand(Request request) { if (REQ_DELETE_DEPENDANT.equals(request.getType())) return getDeleteDependantCommand(request); if (REQ_ADD.equals(request.getType())) return getAddCommand(request); if (REQ_ORPHAN_CHILDREN.equals(request.getType())) return getOrphanChildrenCommand(request); if (REQ_MOVE_CHILDREN.equals(request.getType())) return getMoveChildrenCommand(request); if (REQ_CLONE.equals(request.getType())) return getCloneCommand((ChangeBoundsRequest) request); if (REQ_CREATE.equals(request.getType())) return getCreateCommand((CreateRequest) request); return null; } /** * Returns the Command to perform a create. * * @param request * the CreateRequest * @return a Command to perform a create */ protected abstract Command getCreateCommand(CreateRequest request); /** * Returns any insets that need to be applied to the creation feedback's * bounds. * * @param request * the create request * @return insets, if necessary */ protected Insets getCreationFeedbackOffset(CreateRequest request) { return new Insets(); } /** * Returns the Command to delete a child. This method does not * get called unless the child forwards an additional request to the * container editpart. * * @param request * the Request * @return the Command to delete the child */ protected Command getDeleteDependantCommand(Request request) { return null; } /** * Returns the host's {@link GraphicalEditPart#getContentPane() contentPane} * . The contentPane is the Figure which parents the childrens' figures. It * is also the figure which has the LayoutManager that corresponds to this * EditPolicy. All operations should be interpreted with respect to this * figure. * * @return the Figure that owns the corresponding LayoutManager */ protected IFigure getLayoutContainer() { return ((GraphicalEditPart) getHost()).getContentPane(); } /** * Returns the Command to move a group of children. * * @param request * the Request * @return the Command to perform the move */ protected abstract Command getMoveChildrenCommand(Request request); /** * Returns the Command to orphan a group of children. The * contribution to orphan might contain two parts, both of which are * optional. The first part is to actually remove the children from their * existing parent. Some application models will perform an orphan * implicitly when the children are added to their new parent. The second * part is to perform some adjustments on the remaining children. For * example, a Table layout might simplify itself by collapsing any unused * columns and rows. * * @param request * the Request * @return null or a Command to perform an orphan */ protected Command getOrphanChildrenCommand(Request request) { return null; } /** * Lazily creates and returns the Figure to use for size-on-drop feedback. * * @param createRequest * the createRequest * @return the size-on-drop feedback figure */ protected IFigure getSizeOnDropFeedback(CreateRequest createRequest) { if (sizeOnDropFeedback == null) sizeOnDropFeedback = createSizeOnDropFeedback(createRequest); return getSizeOnDropFeedback(); } /** * Lazily creates and returns the Figure to use for size-on-drop feedback. * * @return the size-on-drop feedback figure */ protected IFigure getSizeOnDropFeedback() { if (sizeOnDropFeedback == null) { sizeOnDropFeedback = new RectangleFigure(); FigureUtilities.makeGhostShape((Shape) sizeOnDropFeedback); ((Shape) sizeOnDropFeedback).setLineStyle(Graphics.LINE_DASHDOT); sizeOnDropFeedback.setForegroundColor(ColorConstants.white); addFeedback(sizeOnDropFeedback); } return sizeOnDropFeedback; } /** * Returns the host if the Request is an ADD, MOVE, or CREATE. * * @see org.eclipse.gef.EditPolicy#getTargetEditPart(Request) */ public EditPart getTargetEditPart(Request request) { if (REQ_ADD.equals(request.getType()) || REQ_MOVE.equals(request.getType()) || REQ_CREATE.equals(request.getType()) || REQ_CLONE.equals(request.getType())) return getHost(); return null; } /** * Sets the EditPartListener used to decorate new children. If the listener * is currently set, it will be unhooked. If the new value is not * null, it will be hooked. *

* The listener must be remembered in case this EditPolicy is removed from * the host and replaced with another LayoutEditPolicy. * * @param listener * null or the listener. */ protected void setListener(EditPartListener listener) { if (this.listener != null) getHost().removeEditPartListener(this.listener); this.listener = listener; if (this.listener != null) getHost().addEditPartListener(this.listener); } /** * Shows target layout feedback. During moves, reparents, and * creation, this method is called to allow the LayoutEditPolicy to * temporarily show features of its layout that will help the User * understand what will happen if the operation is performed in the current * location. *

* By default, no feedback is shown. * * @param request * the Request * @see #eraseLayoutTargetFeedback(Request) */ protected void showLayoutTargetFeedback(Request request) { } /** * Shows size-on-drop feedback during creation. * * @param request * the CreateRequest */ protected void showSizeOnDropFeedback(CreateRequest request) { } /** * Factors feedback requests into two more specific methods. * * @see org.eclipse.gef.EditPolicy#showTargetFeedback(Request) */ public void showTargetFeedback(Request request) { if (REQ_ADD.equals(request.getType()) || REQ_CLONE.equals(request.getType()) || REQ_MOVE.equals(request.getType()) || REQ_RESIZE_CHILDREN.equals(request.getType()) || REQ_CREATE.equals(request.getType())) showLayoutTargetFeedback(request); if (REQ_CREATE.equals(request.getType())) { CreateRequest createReq = (CreateRequest) request; if (createReq.getSize() != null) { showSizeOnDropFeedback(createReq); } } } /** * Removes the decoration added in {@link #decorateChild(EditPart)}. * * @param child * the child whose decoration is being removed. */ protected void undecorateChild(EditPart child) { child.removeEditPolicy(EditPolicy.PRIMARY_DRAG_ROLE); } /** * Removes all decorations added by {@link #decorateChildren()}. */ protected void undecorateChildren() { List children = getHost().getChildren(); for (int i = 0; i < children.size(); i++) undecorateChild((EditPart) children.get(i)); } /** * Returns the layout's origin relative to the * {@link LayoutEditPolicy#getLayoutContainer()}. In other words, what Point * on the parent Figure does the LayoutManager use a reference when * generating the child figure's bounds from the child's constraint. *

* By default, it is assumed that the layout manager positions children * relative to the client area of the layout container. Thus, when * processing Viewer-relative Points or Rectangles, the clientArea's * location (top-left corner) will be subtracted from the Point/Rectangle, * resulting in an offset from the LayoutOrigin. * * @return Point * @since 3.7 Moved up from ConstrainedLayoutEditPolicy */ protected Point getLayoutOrigin() { return getLayoutContainer().getClientArea().getLocation(); } /** * Translates a {@link Translatable} in absolute coordinates to be * layout-relative, i.e. relative to the {@link #getLayoutContainer()}'s * origin, which is obtained via {@link #getLayoutOrigin()}. * * @param t * the Translatable in absolute coordinates to be translated to * layout-relative coordinates. * @since 3.7 */ protected void translateFromAbsoluteToLayoutRelative(Translatable t) { IFigure figure = getLayoutContainer(); figure.translateToRelative(t); figure.translateFromParent(t); Point negatedLayoutOrigin = getLayoutOrigin().getNegated(); t.performTranslate(negatedLayoutOrigin.x, negatedLayoutOrigin.y); } /** * Translates a {@link Translatable} in layout-relative coordinates, i.e. * relative to {@link #getLayoutContainer()}'s origin which is obtained via * {@link #getLayoutOrigin()}, into absolute coordinates. * * @param t * the Translatable in layout-relative coordinates to be * translated into absolute coordinates. * @since 3.7 */ protected void translateFromLayoutRelativeToAbsolute(Translatable t) { IFigure figure = getLayoutContainer(); Point layoutOrigin = getLayoutOrigin(); t.performTranslate(layoutOrigin.x, layoutOrigin.y); figure.translateToParent(t); figure.translateToAbsolute(t); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy