Project

General

Profile

Download (14.7 KB) Statistics
| Branch: | Tag: | Revision:
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2010 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.gef.editpolicies;
12

    
13
import java.util.List;
14

    
15
import org.eclipse.draw2d.geometry.Dimension;
16
import org.eclipse.draw2d.geometry.Point;
17
import org.eclipse.draw2d.geometry.PrecisionRectangle;
18
import org.eclipse.draw2d.geometry.Rectangle;
19
import org.eclipse.draw2d.geometry.Translatable;
20

    
21
import org.eclipse.gef.EditPart;
22
import org.eclipse.gef.EditPolicy;
23
import org.eclipse.gef.GraphicalEditPart;
24
import org.eclipse.gef.Request;
25
import org.eclipse.gef.RequestConstants;
26
import org.eclipse.gef.commands.Command;
27
import org.eclipse.gef.commands.CompoundCommand;
28
import org.eclipse.gef.requests.AlignmentRequest;
29
import org.eclipse.gef.requests.ChangeBoundsRequest;
30
import org.eclipse.gef.requests.CreateRequest;
31

    
32
/**
33
 * For use with <code>LayoutManager</code> that require a <i>constraint</i>.
34
 * ConstrainedLayoutEditPolicy understands
35
 * {@link RequestConstants#REQ_ALIGN_CHILDREN} in addition to the Requests
36
 * handled in the superclass.
37
 * 
38
 * @author hudsonr
39
 * @author anyssen
40
 * @since 2.0
41
 */
42
public abstract class ConstrainedLayoutEditPolicy extends LayoutEditPolicy {
43

    
44
	/**
45
	 * Constant being used to indicate that upon creation (or during move) a
46
	 * size was not specified.
47
	 * 
48
	 * @since 3.7
49
	 */
50
	protected static final Dimension UNSPECIFIED_SIZE = new Dimension();
51

    
52
	/**
53
	 * Returns the <code>Command</code> to perform an Add with the specified
54
	 * child and constraint. The constraint has been converted from a draw2d
55
	 * constraint to an object suitable for the model by calling
56
	 * {@link #translateToModelConstraint(Object)}.
57
	 * 
58
	 * @param request
59
	 *            the ChangeBoundsRequest
60
	 * @param child
61
	 *            the EditPart of the child being added
62
	 * @param constraint
63
	 *            the model constraint, after being
64
	 *            {@link #translateToModelConstraint(Object) translated}
65
	 * @return the Command to add the child
66
	 * 
67
	 * @since 3.7
68
	 */
69
	protected Command createAddCommand(ChangeBoundsRequest request,
70
			EditPart child, Object constraint) {
71
		return createAddCommand(child, constraint);
72
	}
73

    
74
	/**
75
	 * Returns the <code>Command</code> to perform an Add with the specified
76
	 * child and constraint. The constraint has been converted from a draw2d
77
	 * constraint to an object suitable for the model by calling
78
	 * {@link #translateToModelConstraint(Object)}.
79
	 * 
80
	 * @param child
81
	 *            the EditPart of the child being added
82
	 * @param constraint
83
	 *            the model constraint, after being
84
	 *            {@link #translateToModelConstraint(Object) translated}
85
	 * @return the Command to add the child
86
	 * @deprecated Use
87
	 *             {@link #createAddCommand(ChangeBoundsRequest, EditPart, Object)}
88
	 *             instead.
89
	 * @nooverride Overwrite
90
	 *             {@link #createAddCommand(ChangeBoundsRequest, EditPart, Object)}
91
	 *             instead.
92
	 * @noreference Use
93
	 *              {@link #createAddCommand(ChangeBoundsRequest, EditPart, Object)}
94
	 *              instead.
95
	 */
96
	protected Command createAddCommand(EditPart child, Object constraint) {
97
		return null;
98
	}
99

    
100
	/**
101
	 * The request is now made available when creating the change constraint
102
	 * command. By default, this method invokes the old
103
	 * {@link ConstrainedLayoutEditPolicy#createChangeConstraintCommand(EditPart, Object)
104
	 * method}.
105
	 * 
106
	 * @param request
107
	 *            the ChangeBoundsRequest
108
	 * @param child
109
	 *            the EditPart of the child being changed
110
	 * @param constraint
111
	 *            the new constraint, after being
112
	 *            {@link #translateToModelConstraint(Object) translated}
113
	 * @return A Command to change the constraints of the given child as
114
	 *         specified in the given request
115
	 * @see ConstrainedLayoutEditPolicy#createChangeConstraintCommand(EditPart,
116
	 *      Object)
117
	 * @since 3.0
118
	 */
119
	protected Command createChangeConstraintCommand(
120
			ChangeBoundsRequest request, EditPart child, Object constraint) {
121
		return createChangeConstraintCommand(child, constraint);
122
	}
123

    
124
	/**
125
	 * Returns the <code>Command</code> to change the specified child's
126
	 * constraint. The constraint has been converted from a draw2d constraint to
127
	 * an object suitable for the model. Clients should overwrite
128
	 * {@link #createChangeConstraintCommand(ChangeBoundsRequest, EditPart, Object)}
129
	 * instead.
130
	 * 
131
	 * @param child
132
	 *            the EditPart of the child being changed
133
	 * @param constraint
134
	 *            the new constraint, after being
135
	 *            {@link #translateToModelConstraint(Object) translated}
136
	 * @return Command
137
	 * @see #createChangeConstraintCommand(ChangeBoundsRequest, EditPart,
138
	 *      Object)
139
	 * @deprecated Use
140
	 *             {@link #createChangeConstraintCommand(ChangeBoundsRequest, EditPart, Object)}
141
	 *             instead.
142
	 * @nooverride Overwrite
143
	 *             {@link #createChangeConstraintCommand(ChangeBoundsRequest, EditPart, Object)}
144
	 *             instead.
145
	 * @noreference Use
146
	 *              {@link #createChangeConstraintCommand(ChangeBoundsRequest, EditPart, Object)}
147
	 *              instead.
148
	 */
149
	protected Command createChangeConstraintCommand(EditPart child,
150
			Object constraint) {
151
		return null;
152
	}
153

    
154
	/**
155
	 * A {@link ResizableEditPolicy} is used by default for children. Subclasses
156
	 * may override this method to supply a different EditPolicy.
157
	 * 
158
	 * @see org.eclipse.gef.editpolicies.LayoutEditPolicy#createChildEditPolicy(EditPart)
159
	 */
160
	protected EditPolicy createChildEditPolicy(EditPart child) {
161
		return new ResizableEditPolicy();
162
	}
163

    
164
	/**
165
	 * Overrides <code>getAddCommand()</code> to generate the proper constraint
166
	 * for each child being added. Once the constraint is calculated,
167
	 * {@link #createAddCommand(EditPart,Object)} is called. Subclasses must
168
	 * implement this method.
169
	 * 
170
	 * @see org.eclipse.gef.editpolicies.LayoutEditPolicy#getAddCommand(Request)
171
	 */
172
	protected Command getAddCommand(Request generic) {
173
		ChangeBoundsRequest request = (ChangeBoundsRequest) generic;
174
		List editParts = request.getEditParts();
175
		CompoundCommand command = new CompoundCommand();
176
		command.setDebugLabel("Add in ConstrainedLayoutEditPolicy");//$NON-NLS-1$
177
		GraphicalEditPart child;
178

    
179
		for (int i = 0; i < editParts.size(); i++) {
180
			child = (GraphicalEditPart) editParts.get(i);
181
			command.add(createAddCommand(
182
					request,
183
					child,
184
					translateToModelConstraint(getConstraintFor(request, child))));
185
		}
186
		return command.unwrap();
187
	}
188

    
189
	/**
190
	 * Returns the command to align a group of children. By default, this is
191
	 * treated the same as a resize, and
192
	 * {@link #getResizeChildrenCommand(ChangeBoundsRequest)} is returned.
193
	 * 
194
	 * @param request
195
	 *            the AligmentRequest
196
	 * @return the command to perform alignment
197
	 */
198
	protected Command getAlignChildrenCommand(AlignmentRequest request) {
199
		return getResizeChildrenCommand(request);
200
	}
201

    
202
	/**
203
	 * Factors out RESIZE and ALIGN requests, otherwise calls <code>super</code>
204
	 * .
205
	 * 
206
	 * @see org.eclipse.gef.EditPolicy#getCommand(Request)
207
	 */
208
	public Command getCommand(Request request) {
209
		if (REQ_RESIZE_CHILDREN.equals(request.getType()))
210
			return getResizeChildrenCommand((ChangeBoundsRequest) request);
211
		if (REQ_ALIGN_CHILDREN.equals(request.getType()))
212
			return getAlignChildrenCommand((AlignmentRequest) request);
213

    
214
		return super.getCommand(request);
215
	}
216

    
217
	/**
218
	 * Generates a draw2d constraint object for the given
219
	 * <code>ChangeBoundsRequest</code> and child EditPart by delegating to
220
	 * {@link #getConstraintFor(Request, GraphicalEditPart, Rectangle)}.
221
	 * 
222
	 * The rectangle being passed over to
223
	 * {@link #getConstraintFor(Request, GraphicalEditPart, Rectangle)} is
224
	 * calculated based on the child figure's current bounds and the
225
	 * ChangeBoundsRequest's move and resize deltas. It is made layout-relative
226
	 * by using {@link #translateFromAbsoluteToLayoutRelative(Translatable)}
227
	 * before calling
228
	 * {@link #getConstraintFor(Request, GraphicalEditPart, Rectangle)}.
229
	 * 
230
	 * @param request
231
	 *            the ChangeBoundsRequest
232
	 * @param child
233
	 *            the child EditPart for which the constraint should be
234
	 *            generated
235
	 * @return the draw2d constraint
236
	 */
237
	protected Object getConstraintFor(ChangeBoundsRequest request,
238
			GraphicalEditPart child) {
239
		Rectangle locationAndSize = new PrecisionRectangle(child.getFigure()
240
				.getBounds());
241
		child.getFigure().translateToAbsolute(locationAndSize);
242
		locationAndSize = request.getTransformedRectangle(locationAndSize);
243
		translateFromAbsoluteToLayoutRelative(locationAndSize);
244
		return getConstraintFor(request, child, locationAndSize);
245
	}
246

    
247
	/**
248
	 * Responsible of generating a draw2d constraint for the given Rectangle,
249
	 * which represents the already transformed (layout-relative) position and
250
	 * size of the given Request.
251
	 * 
252
	 * By default, this method delegates to {@link #getConstraintFor(Point)} or
253
	 * {@link #getConstraintFor(Rectangle)}, dependent on whether the size of
254
	 * the rectangle is an {@link #UNSPECIFIED_SIZE} or not.
255
	 * 
256
	 * Subclasses may overwrite this method in case they need the request or the
257
	 * edit part (which will of course not be set during creation) to calculate
258
	 * a layout constraint for the request.
259
	 * 
260
	 * @param rectangle
261
	 *            the Rectangle relative to the {@link #getLayoutOrigin() layout
262
	 *            origin}
263
	 * @return the constraint
264
	 * @since 3.7
265
	 */
266
	protected Object getConstraintFor(Request request, GraphicalEditPart child,
267
			Rectangle rectangle) {
268
		if (UNSPECIFIED_SIZE.equals(rectangle.getSize())) {
269
			return getConstraintFor(rectangle.getLocation());
270
		}
271
		return getConstraintFor(rectangle);
272
	}
273

    
274
	/**
275
	 * Generates a draw2d constraint given a <code>Point</code>. This method is
276
	 * called during creation, when only a mouse location is available, as well
277
	 * as during move, in case no resizing is involved.
278
	 * 
279
	 * @param point
280
	 *            the Point relative to the {@link #getLayoutOrigin() layout
281
	 *            origin}
282
	 * @return the constraint
283
	 */
284
	protected abstract Object getConstraintFor(Point point);
285

    
286
	/**
287
	 * Generates a draw2d constraint given a <code>Rectangle</code>. This method
288
	 * is called during most operations.
289
	 * 
290
	 * @param rect
291
	 *            the Rectangle relative to the {@link #getLayoutOrigin() layout
292
	 *            origin}
293
	 * @return the constraint
294
	 */
295
	protected abstract Object getConstraintFor(Rectangle rect);
296

    
297
	/**
298
	 * Generates a draw2d constraint for the given <code>CreateRequest</code> by
299
	 * delegating to
300
	 * {@link #getConstraintFor(Request, GraphicalEditPart, Rectangle)}.
301
	 * 
302
	 * If the CreateRequest has a size, is used during size-on-drop creation, a
303
	 * Rectangle of the request's location and size is passed with the
304
	 * delegation. Otherwise, a rectangle with the request's location and an
305
	 * empty size (0,0) is passed over.
306
	 * <P>
307
	 * The CreateRequest's location is relative to the Viewer. The location is
308
	 * made layout-relative by using
309
	 * {@link #translateFromAbsoluteToLayoutRelative(Translatable)} before
310
	 * calling {@link #getConstraintFor(Request, GraphicalEditPart, Rectangle)}.
311
	 * 
312
	 * @param request
313
	 *            the CreateRequest
314
	 * @return a draw2d constraint
315
	 */
316
	protected Object getConstraintFor(CreateRequest request) {
317
		Rectangle locationAndSize = null;
318
		if (request.getSize() == null || request.getSize().isEmpty()) {
319
			locationAndSize = new PrecisionRectangle(request.getLocation(),
320
					UNSPECIFIED_SIZE);
321
		} else {
322
			locationAndSize = new PrecisionRectangle(request.getLocation(),
323
					request.getSize());
324
		}
325
		translateFromAbsoluteToLayoutRelative(locationAndSize);
326
		return getConstraintFor(request, null, locationAndSize);
327
	}
328

    
329
	/**
330
	 * Returns the correct rectangle bounds for the new clone's location.
331
	 * 
332
	 * @param part
333
	 *            the graphical edit part representing the object to be cloned.
334
	 * @param request
335
	 *            the ChangeBoundsRequest that knows where to place the new
336
	 *            object.
337
	 * @return the bounds that will be used for the new object.
338
	 * @deprecated Use
339
	 *             {@link #getConstraintFor(ChangeBoundsRequest, GraphicalEditPart)}
340
	 *             instead.
341
	 * @nooverride This method is not intended to be re-implemented or extended
342
	 *             by clients.
343
	 * @noreference This method is not intended to be referenced by clients.
344
	 */
345
	protected Object getConstraintForClone(GraphicalEditPart part,
346
			ChangeBoundsRequest request) {
347
		// anyssen: The code executed herein was functionally the same
348
		// as that in getConstraintFor(ChangeBoundsRequest, GraphicalEditPart),
349
		// despite it was erroneously missing a call to
350
		// getLayoutContainer().translateFromParent(), which is needed
351
		// to translate the part's figure's bounds into a coordinate
352
		// local to the client area of the layout container.
353
		return getConstraintFor(request, part);
354
	}
355

    
356
	/**
357
	 * Converts a constraint from the format used by LayoutManagers, to the form
358
	 * stored in the model.
359
	 * 
360
	 * @param figureConstraint
361
	 *            the draw2d constraint
362
	 * @return the model constraint
363
	 */
364
	protected Object translateToModelConstraint(Object figureConstraint) {
365
		return figureConstraint;
366
	}
367

    
368
	/**
369
	 * Returns the <code>Command</code> to resize a group of children.
370
	 * 
371
	 * @param request
372
	 *            the ChangeBoundsRequest
373
	 * @return the Command
374
	 */
375
	protected Command getResizeChildrenCommand(ChangeBoundsRequest request) {
376
		return getChangeConstraintCommand(request);
377
	}
378

    
379
	/**
380
	 * Returns the <code>Command</code> for changing bounds for a group of
381
	 * children.
382
	 * 
383
	 * @param request
384
	 *            the ChangeBoundsRequest
385
	 * @return the Command
386
	 * 
387
	 * @since 3.7
388
	 */
389
	protected Command getChangeConstraintCommand(ChangeBoundsRequest request) {
390
		CompoundCommand resize = new CompoundCommand();
391
		Command c;
392
		GraphicalEditPart child;
393
		List children = request.getEditParts();
394

    
395
		for (int i = 0; i < children.size(); i++) {
396
			child = (GraphicalEditPart) children.get(i);
397
			c = createChangeConstraintCommand(
398
					request,
399
					child,
400
					translateToModelConstraint(getConstraintFor(request, child)));
401
			resize.add(c);
402
		}
403
		return resize.unwrap();
404
	}
405

    
406
	/**
407
	 * Returns the <code>Command</code> to move a group of children. By default,
408
	 * move is treated the same as a resize.
409
	 * 
410
	 * @see org.eclipse.gef.editpolicies.LayoutEditPolicy#getMoveChildrenCommand(Request)
411
	 */
412
	protected Command getMoveChildrenCommand(Request request) {
413
		// By default, move and resize are treated the same for constrained
414
		// layouts.
415
		return getResizeChildrenCommand((ChangeBoundsRequest) request);
416
	}
417
}
(7-7/26)