Skip to main content
summaryrefslogtreecommitdiffstats
blob: 09a94f0024bc13ebd9115bdd71e402719a077b0c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
/*******************************************************************************
 * Copyright (c) 2006 Sybase, Inc. 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:
 *     Sybase, Inc. - initial API and implementation
 *******************************************************************************/
package org.eclipse.jst.pagedesigner.editpolicies;

import java.util.List;

import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.gef.GraphicalEditPart;
import org.eclipse.jst.pagedesigner.css2.layout.FlowBox;
import org.eclipse.jst.pagedesigner.css2.layout.ICSSFigure;
import org.eclipse.jst.pagedesigner.parts.DocumentEditPart;
import org.eclipse.jst.pagedesigner.parts.ElementEditPart;
import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery;
import org.eclipse.wst.xml.core.internal.modelquery.ModelQueryUtil;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

/**
 * @author mengbo
 */
public class LocationHelper {
	/**
	 * @param p
	 * @param result
	 * @param tagName
	 * @param skip
	 * @return
	 */
	public static boolean findInsertLocation(GraphicalEditPart host, Point p,
			GraphicalEditPart[] result, String tagName, Node skip) {
		if (isHostInsideSkip(host, skip))
			return false;

		while (isValidHost(host) && !canHostContainTag(host, tagName)) {
			if (host.getParent() instanceof GraphicalEditPart)
				host = (GraphicalEditPart) host.getParent();
			else
				host = null;
		}
		if (!isValidHost(host))
			return false;

		// ok, next we try to find a insertion point inside host
		result[0] = host;
		List children = host.getChildren();
		if (children.isEmpty()) {
			result[1] = null;
			return true;
		}
		GraphicalEditPart ref = null;
		for (int i = 0, size = children.size(); i < size; i++) {
			GraphicalEditPart child = (GraphicalEditPart) children.get(i);
			Rectangle rect = getAbsoluteBounds(child);

			if (rect.contains(p)) {
				IFigure figure = child.getFigure();
				if (figure instanceof ICSSFigure) {
					List frags = ((ICSSFigure) figure).getFragmentsForRead();
					if (frags.size() > 1) // more than one frags, so is a zig
					// zag.
					{
						// check whether is before the first box.
						FlowBox box = (FlowBox) frags.get(0);
						Rectangle rect1 = getAbsoluteBounds(figure, box);
						if (rect1.x > p.x && rect1.y + rect1.height > p.y) {
							// p is at left/above the first box. so we think p
							// is before this child
							result[1] = child;
							return true;
						}
						// check whether is after the last box
						box = (FlowBox) frags.get(frags.size() - 1);
						rect1 = getAbsoluteBounds(figure, box);
						if (rect1.x < p.x && rect1.y < p.y) {
							continue;
						}
					}
				}
				// ok, treat as the point in a rect figure, see which side is
				// closer.
				if (p.x > rect.x + rect.width / 2) {
					continue;
				} else {
					result[1] = child;
					return true;
				}
			} else if (rect.x + rect.width < p.x || rect.y + rect.height < p.y) {
				// p is at right or below rect. so the point is "after" the
				// rect.
				continue;
			} else {
				// ok, p is "before" rect.
				result[1] = child;
				return true;
			}
		}
		// we search through all.
		result[1] = null;
		return true;
	}

	/**
	 * @param figure
	 * @param box
	 * @return
	 */
	public static Rectangle getAbsoluteBounds(IFigure figure, FlowBox box) {
		Rectangle r = new Rectangle(box._x, box._y, box.getWidth(), box
				.getHeight());
		figure.translateToAbsolute(r);
		return r;
	}

	/**
	 * @param child
	 * @return
	 */
	public static Rectangle getAbsoluteBounds(GraphicalEditPart child) {
		Rectangle bounds = child.getFigure().getBounds().getCopy();
		child.getFigure().translateToAbsolute(bounds);
		return bounds;
	}

	/**
	 * @param host
	 * @param tagName
	 * @return
	 */
	private static boolean canHostContainTag(GraphicalEditPart host,
			String tagName) {
		if (host == null)
			return false;
		Node node = (Node) host.getModel();
		if (node.getNodeType() == Node.ELEMENT_NODE) {
			ModelQuery modelQuery = getModelQuery(node);
			if (modelQuery != null) {
				CMElementDeclaration elementDecl = modelQuery
						.getCMElementDeclaration((Element) node);
				if (elementDecl == null) {
					return true;
				}
				if (elementDecl.getContentType() == CMElementDeclaration.EMPTY)
					return false;
			}
		}
		return true;
	}

	/**
	 * @param host
	 * @return
	 */
	private static boolean isValidHost(GraphicalEditPart host) {
		return host != null
				&& (host instanceof ElementEditPart || host instanceof DocumentEditPart);
	}

	/**
	 * @param host
	 * @param skip
	 * @return
	 */
	private static boolean isHostInsideSkip(GraphicalEditPart host, Node skip) {
		if (skip == null)
			return false;

		// XXX: not done.
		return false;
	}

	protected static ModelQuery getModelQuery(Node node) {
		if (node.getNodeType() == Node.DOCUMENT_NODE) {
			return ModelQueryUtil.getModelQuery((Document) node);
		} else {
			return ModelQueryUtil.getModelQuery(node.getOwnerDocument());
		}
	}

}

Back to the top