aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xeclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/api/DropFeedback.java17
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/AbsoluteLayoutRule.java17
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/LayoutConstants.java19
-rwxr-xr-xeclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/RelativeLayoutRule.java181
-rwxr-xr-xeclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/DynamicContextMenu.java16
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/GestureManager.java12
-rwxr-xr-xeclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/GlobalCanvasDragInfo.java29
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/GraphicalEditorPart.java12
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/MoveGesture.java23
-rwxr-xr-xeclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/PaletteComposite.java10
-rwxr-xr-xeclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/RulesEngine.java40
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/common/layout/AbsoluteLayoutRuleTest.java8
12 files changed, 277 insertions, 107 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/api/DropFeedback.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/api/DropFeedback.java
index 9926571..232ab5b 100755
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/api/DropFeedback.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/api/DropFeedback.java
@@ -87,6 +87,17 @@ public class DropFeedback {
public boolean isCopy;
/**
+ * The bounds of the drag, relative to the starting mouse position. For example, if
+ * you have a rectangular view of size 100x80, and you start dragging at position
+ * (15,20) from the top left corner of this rectangle, then the drag bounds would be
+ * (-15,-20, 100x80).
+ * <p>
+ * NOTE: The coordinate units will be in layout/view coordinates. In other words, they
+ * are unaffected by the canvas zoom.
+ */
+ public Rect dragBounds;
+
+ /**
* Set to true when the drag'n'drop starts and ends in the same canvas of the
* same Eclipse instance.
* <p/>
@@ -95,6 +106,12 @@ public class DropFeedback {
public boolean sameCanvas;
/**
+ * Density scale for pixels. To compute the dip (device independent pixel) in the
+ * view from a layout coordinate, apply this scale.
+ */
+ public double dipScale = 1.0;
+
+ /**
* Initializes the drop feedback with the given user data and paint
* callback. A paint is requested if the paint callback is non-null.
*
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/AbsoluteLayoutRule.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/AbsoluteLayoutRule.java
index ffa43d9..559c3bf 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/AbsoluteLayoutRule.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/AbsoluteLayoutRule.java
@@ -86,8 +86,8 @@ public class AbsoluteLayoutRule extends BaseLayoutRule {
// At least the first element has a bound. Draw rectangles
// for all dropped elements with valid bounds, offset at
// the drop point.
- int offsetX = x - be.x - be.w / 2;
- int offsetY = y - be.y - be.h / 2;
+ int offsetX = x - be.x + (feedback.dragBounds != null ? feedback.dragBounds.x : 0);
+ int offsetY = y - be.y + (feedback.dragBounds != null ? feedback.dragBounds.y : 0);
gc.useStyle(DrawingStyle.DROP_PREVIEW);
for (IDragElement element : elements) {
drawElement(gc, element, offsetX, offsetY);
@@ -152,8 +152,11 @@ public class AbsoluteLayoutRule extends BaseLayoutRule {
// Copy all the attributes, modifying them as needed.
addAttributes(newChild, element, idMap, DEFAULT_ATTR_FILTER);
- int x = p.x - b.x - (be.isValid() ? be.w / 2 : 0);
- int y = p.y - b.y - (be.isValid() ? be.h / 2 : 0);
+ int deltaX = (feedback.dragBounds != null ? feedback.dragBounds.x : 0);
+ int deltaY = (feedback.dragBounds != null ? feedback.dragBounds.y : 0);
+
+ int x = p.x - b.x + deltaX;
+ int y = p.y - b.y + deltaY;
if (first) {
first = false;
@@ -168,6 +171,12 @@ public class AbsoluteLayoutRule extends BaseLayoutRule {
y += be.isValid() ? be.h : 10;
}
+ double scale = feedback.dipScale;
+ if (scale != 1.0) {
+ x *= scale;
+ y *= scale;
+ }
+
newChild.setAttribute(ANDROID_URI, "layout_x", //$NON-NLS-1$
x + "dip"); //$NON-NLS-1$
newChild.setAttribute(ANDROID_URI, "layout_y", //$NON-NLS-1$
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/LayoutConstants.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/LayoutConstants.java
index 1bc511b..5b90c7f 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/LayoutConstants.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/LayoutConstants.java
@@ -68,6 +68,25 @@ public class LayoutConstants {
public static final String VALUE_TRUE = "true"; //$NON-NLS-1$
public static final String VALUE_N_DIP = "%ddip"; //$NON-NLS-1$
+ public static final String VALUE_CENTER_VERTICAL = "centerVertical"; //$NON-NLS-1$
+ public static final String VALUE_CENTER_IN_PARENT = "centerInParent"; //$NON-NLS-1$
+ public static final String VALUE_CENTER_HORIZONTAL = "centerHorizontal"; //$NON-NLS-1$
+ public static final String VALUE_ALIGN_PARENT_RIGHT = "alignParentRight"; //$NON-NLS-1$
+ public static final String VALUE_ALIGN_PARENT_LEFT = "alignParentLeft"; //$NON-NLS-1$
+ public static final String VALUE_ALIGN_PARENT_BOTTOM = "alignParentBottom"; //$NON-NLS-1$
+ public static final String VALUE_ALIGN_PARENT_TOP = "alignParentTop"; //$NON-NLS-1$
+ public static final String VALUE_ALIGN_RIGHT = "alignRight"; //$NON-NLS-1$
+ public static final String VALUE_ALIGN_LEFT = "alignLeft"; //$NON-NLS-1$
+ public static final String VALUE_ALIGN_BOTTOM = "alignBottom"; //$NON-NLS-1$
+ public static final String VALUE_ALIGN_TOP = "alignTop"; //$NON-NLS-1$
+ public static final String VALUE_ALIGN_BASELINE = "alignBaseline"; //$NON-NLS-1$
+ public static final String VAUE_TO_RIGHT_OF = "toRightOf"; //$NON-NLS-1$
+ public static final String VALUE_TO_LEFT_OF = "toLeftOf"; //$NON-NLS-1$
+ public static final String VALUE_BELOW = "below"; //$NON-NLS-1$
+ public static final String VALUE_ABOVE = "above"; //$NON-NLS-1$
+ public static final String VALUE_ALIGN_WITH_PARENT_MISSING =
+ "alignWithParentMissing"; //$NON-NLS-1$
+
/**
* Namespace for the Android resource XML, i.e.
* "http://schemas.android.com/apk/res/android"
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/RelativeLayoutRule.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/RelativeLayoutRule.java
index bf708a3..15d18fc 100755
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/RelativeLayoutRule.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/RelativeLayoutRule.java
@@ -18,20 +18,37 @@ package com.android.ide.common.layout;
import static com.android.ide.common.layout.LayoutConstants.ANDROID_URI;
import static com.android.ide.common.layout.LayoutConstants.ATTR_ID;
+import static com.android.ide.common.layout.LayoutConstants.VALUE_ABOVE;
+import static com.android.ide.common.layout.LayoutConstants.VALUE_ALIGN_BASELINE;
+import static com.android.ide.common.layout.LayoutConstants.VALUE_ALIGN_BOTTOM;
+import static com.android.ide.common.layout.LayoutConstants.VALUE_ALIGN_LEFT;
+import static com.android.ide.common.layout.LayoutConstants.VALUE_ALIGN_PARENT_BOTTOM;
+import static com.android.ide.common.layout.LayoutConstants.VALUE_ALIGN_PARENT_LEFT;
+import static com.android.ide.common.layout.LayoutConstants.VALUE_ALIGN_PARENT_RIGHT;
+import static com.android.ide.common.layout.LayoutConstants.VALUE_ALIGN_PARENT_TOP;
+import static com.android.ide.common.layout.LayoutConstants.VALUE_ALIGN_RIGHT;
+import static com.android.ide.common.layout.LayoutConstants.VALUE_ALIGN_TOP;
+import static com.android.ide.common.layout.LayoutConstants.VALUE_ALIGN_WITH_PARENT_MISSING;
+import static com.android.ide.common.layout.LayoutConstants.VALUE_BELOW;
+import static com.android.ide.common.layout.LayoutConstants.VALUE_CENTER_HORIZONTAL;
+import static com.android.ide.common.layout.LayoutConstants.VALUE_CENTER_IN_PARENT;
+import static com.android.ide.common.layout.LayoutConstants.VALUE_CENTER_VERTICAL;
+import static com.android.ide.common.layout.LayoutConstants.VALUE_TO_LEFT_OF;
+import static com.android.ide.common.layout.LayoutConstants.VAUE_TO_RIGHT_OF;
import com.android.ide.common.api.DrawingStyle;
import com.android.ide.common.api.DropFeedback;
import com.android.ide.common.api.IAttributeInfo;
-import com.android.ide.common.api.IAttributeInfo.Format;
import com.android.ide.common.api.IDragElement;
import com.android.ide.common.api.IFeedbackPainter;
import com.android.ide.common.api.IGraphics;
import com.android.ide.common.api.INode;
-import com.android.ide.common.api.INode.IAttribute;
import com.android.ide.common.api.INodeHandler;
import com.android.ide.common.api.IViewRule;
import com.android.ide.common.api.Point;
import com.android.ide.common.api.Rect;
+import com.android.ide.common.api.IAttributeInfo.Format;
+import com.android.ide.common.api.INode.IAttribute;
import java.util.ArrayList;
import java.util.Collections;
@@ -52,23 +69,23 @@ public class RelativeLayoutRule extends BaseLayoutRule {
@Override
public List<String> getSelectionHint(INode parentNode, INode childNode) {
List<String> infos = new ArrayList<String>(18);
- addAttr("above", childNode, infos); //$NON-NLS-1$
- addAttr("below", childNode, infos); //$NON-NLS-1$
- addAttr("toLeftOf", childNode, infos); //$NON-NLS-1$
- addAttr("toRightOf", childNode, infos); //$NON-NLS-1$
- addAttr("alignBaseline", childNode, infos); //$NON-NLS-1$
- addAttr("alignTop", childNode, infos); //$NON-NLS-1$
- addAttr("alignBottom", childNode, infos); //$NON-NLS-1$
- addAttr("alignLeft", childNode, infos); //$NON-NLS-1$
- addAttr("alignRight", childNode, infos); //$NON-NLS-1$
- addAttr("alignParentTop", childNode, infos); //$NON-NLS-1$
- addAttr("alignParentBottom", childNode, infos); //$NON-NLS-1$
- addAttr("alignParentLeft", childNode, infos); //$NON-NLS-1$
- addAttr("alignParentRight", childNode, infos); //$NON-NLS-1$
- addAttr("alignWithParentMissing", childNode, infos); //$NON-NLS-1$
- addAttr("centerHorizontal", childNode, infos); //$NON-NLS-1$
- addAttr("centerInParent", childNode, infos); //$NON-NLS-1$
- addAttr("centerVertical", childNode, infos); //$NON-NLS-1$
+ addAttr(VALUE_ABOVE, childNode, infos);
+ addAttr(VALUE_BELOW, childNode, infos);
+ addAttr(VALUE_TO_LEFT_OF, childNode, infos);
+ addAttr(VAUE_TO_RIGHT_OF, childNode, infos);
+ addAttr(VALUE_ALIGN_BASELINE, childNode, infos);
+ addAttr(VALUE_ALIGN_TOP, childNode, infos);
+ addAttr(VALUE_ALIGN_BOTTOM, childNode, infos);
+ addAttr(VALUE_ALIGN_LEFT, childNode, infos);
+ addAttr(VALUE_ALIGN_RIGHT, childNode, infos);
+ addAttr(VALUE_ALIGN_PARENT_TOP, childNode, infos);
+ addAttr(VALUE_ALIGN_PARENT_BOTTOM, childNode, infos);
+ addAttr(VALUE_ALIGN_PARENT_LEFT, childNode, infos);
+ addAttr(VALUE_ALIGN_PARENT_RIGHT, childNode, infos);
+ addAttr(VALUE_ALIGN_WITH_PARENT_MISSING, childNode, infos);
+ addAttr(VALUE_CENTER_HORIZONTAL, childNode, infos);
+ addAttr(VALUE_CENTER_IN_PARENT, childNode, infos);
+ addAttr(VALUE_CENTER_VERTICAL, childNode, infos);
return infos;
}
@@ -185,8 +202,7 @@ public class RelativeLayoutRule extends BaseLayoutRule {
data.setIndex(-1);
data.setCurr(null);
- DropZone zone = computeBorderDropZone(targetNode.getBounds(), p);
-
+ DropZone zone = computeBorderDropZone(targetNode, p, feedback);
if (zone == null) {
data.setZones(null);
} else {
@@ -207,6 +223,24 @@ public class RelativeLayoutRule extends BaseLayoutRule {
break;
}
}
+
+ // Look to see if there's a border match if we didn't find anything better;
+ // a border match isn't required to have the mouse cursor within it since we
+ // do edge matching in the code which -adds- the border zones.
+ if (currZone == null && feedback.dragBounds != null) {
+ for (DropZone zone : data.getZones()) {
+ if (zone.isBorderZone()) {
+ currZone = zone;
+ break;
+ }
+ }
+ }
+ }
+
+ // Look for border match when there are no children: always offer one in this case
+ if (currZone == null && targetNode.getChildren().length == 0 && data.getZones() != null
+ && data.getZones().size() > 0) {
+ currZone = data.getZones().get(0);
}
if (currZone != data.getCurr()) {
@@ -286,7 +320,8 @@ public class RelativeLayoutRule extends BaseLayoutRule {
return ids;
}
- private DropZone computeBorderDropZone(Rect bounds, Point p) {
+ private DropZone computeBorderDropZone(INode targetNode, Point p, DropFeedback feedback) {
+ Rect bounds = targetNode.getBounds();
int x = p.x;
int y = p.y;
@@ -297,34 +332,50 @@ public class RelativeLayoutRule extends BaseLayoutRule {
int x2 = x1 + w;
int y2 = y1 + h;
+ // Default border zone size
int n = 10;
- int n2 = n * 2;
+ int n2 = 2*n;
+
+ // Size of -matched- border zone (not painted, but we detect edge overlaps here)
+ int hn = 0;
+ int vn = 0;
+ if (feedback.dragBounds != null) {
+ hn = feedback.dragBounds.w / 2;
+ vn = feedback.dragBounds.h / 2;
+ }
boolean vertical = false;
Rect r = null;
String attr = null;
- if (x <= x1 + n && y >= y1 && y <= y2) {
+ if (x <= x1 + n + hn && y >= y1 && y <= y2) {
r = new Rect(x1 - n, y1, n2, h);
- attr = "alignParentLeft"; //$NON-NLS-1$
+ attr = VALUE_ALIGN_PARENT_LEFT;
vertical = true;
- } else if (x >= x2 - n && y >= y1 && y <= y2) {
+ } else if (x >= x2 - hn - n && y >= y1 && y <= y2) {
r = new Rect(x2 - n, y1, n2, h);
- attr = "alignParentRight"; //$NON-NLS-1$
+ attr = VALUE_ALIGN_PARENT_RIGHT;
vertical = true;
- } else if (y <= y1 + n && x >= x1 && x <= x2) {
+ } else if (y <= y1 + n + vn && x >= x1 && x <= x2) {
r = new Rect(x1, y1 - n, w, n2);
- attr = "alignParentTop"; //$NON-NLS-1$
+ attr = VALUE_ALIGN_PARENT_TOP;
- } else if (y >= y2 - n && x >= x1 && x <= x2) {
+ } else if (y >= y2 - vn - n && x >= x1 && x <= x2) {
r = new Rect(x1, y2 - n, w, n2);
- attr = "alignParentBottom"; //$NON-NLS-1$
+ attr = VALUE_ALIGN_PARENT_BOTTOM;
} else {
- // we're nowhere near a border
- return null;
+ // We're nowhere near a border.
+ // If there are no children, we will offer one anyway:
+ if (targetNode.getChildren().length == 0) {
+ r = new Rect(x1 - n, y1, n2, h);
+ attr = VALUE_ALIGN_PARENT_LEFT;
+ vertical = true;
+ } else {
+ return null;
+ }
}
return new DropZone(r, Collections.singletonList(attr), r.getCenter(), vertical);
@@ -371,41 +422,41 @@ public class RelativeLayoutRule extends BaseLayoutRule {
Rect bounds = new Rect(x1, y1, wt, ht);
List<DropZone> zones = new ArrayList<DropZone>(16);
- String a = "above"; //$NON-NLS-1$
+ String a = VALUE_ABOVE;
int x = x1;
int y = y1;
- x = addx(w1, a, x, y, h1, zones, "toLeftOf"); //$NON-NLS-1$
- x = addx(w2, a, x, y, h1, zones, "alignLeft"); //$NON-NLS-1$
- x = addx(w2, a, x, y, h1, zones, "alignLeft", "alignRight"); //$NON-NLS-1$ //$NON-NLS-2$
- x = addx(w2, a, x, y, h1, zones, "alignRight"); //$NON-NLS-1$
- x = addx(w1, a, x, y, h1, zones, "toRightOf"); //$NON-NLS-1$
+ x = addx(w1, a, x, y, h1, zones, VALUE_TO_LEFT_OF);
+ x = addx(w2, a, x, y, h1, zones, VALUE_ALIGN_LEFT);
+ x = addx(w2, a, x, y, h1, zones, VALUE_ALIGN_LEFT, VALUE_ALIGN_RIGHT);
+ x = addx(w2, a, x, y, h1, zones, VALUE_ALIGN_RIGHT);
+ x = addx(w1, a, x, y, h1, zones, VAUE_TO_RIGHT_OF);
- a = "below"; //$NON-NLS-1$
+ a = VALUE_BELOW;
x = x1;
y = y1 + ht - h1;
- x = addx(w1, a, x, y, h1, zones, "toLeftOf"); //$NON-NLS-1$
- x = addx(w2, a, x, y, h1, zones, "alignLeft"); //$NON-NLS-1$
- x = addx(w2, a, x, y, h1, zones, "alignLeft", "alignRight"); //$NON-NLS-1$ //$NON-NLS-2$
- x = addx(w2, a, x, y, h1, zones, "alignRight"); //$NON-NLS-1$
- x = addx(w1, a, x, y, h1, zones, "toRightOf"); //$NON-NLS-1$
+ x = addx(w1, a, x, y, h1, zones, VALUE_TO_LEFT_OF);
+ x = addx(w2, a, x, y, h1, zones, VALUE_ALIGN_LEFT);
+ x = addx(w2, a, x, y, h1, zones, VALUE_ALIGN_LEFT, VALUE_ALIGN_RIGHT);
+ x = addx(w2, a, x, y, h1, zones, VALUE_ALIGN_RIGHT);
+ x = addx(w1, a, x, y, h1, zones, VAUE_TO_RIGHT_OF);
- a = "toLeftOf"; //$NON-NLS-1$
+ a = VALUE_TO_LEFT_OF;
x = x1;
y = y1 + h1;
- y = addy(h2, a, x, y, w1, zones, "alignTop"); //$NON-NLS-1$
- y = addy(h2, a, x, y, w1, zones, "alignTop", "alignBottom"); //$NON-NLS-1$ //$NON-NLS-2$
- y = addy(h2, a, x, y, w1, zones, "alignBottom"); //$NON-NLS-1$
+ y = addy(h2, a, x, y, w1, zones, VALUE_ALIGN_TOP);
+ y = addy(h2, a, x, y, w1, zones, VALUE_ALIGN_TOP, VALUE_ALIGN_BOTTOM);
+ y = addy(h2, a, x, y, w1, zones, VALUE_ALIGN_BOTTOM);
- a = "toRightOf"; //$NON-NLS-1$
+ a = VAUE_TO_RIGHT_OF;
x = x1 + wt - w1;
y = y1 + h1;
- y = addy(h2, a, x, y, w1, zones, "alignTop"); //$NON-NLS-1$
- y = addy(h2, a, x, y, w1, zones, "alignTop", "alignBottom"); //$NON-NLS-1$ //$NON-NLS-2$
- y = addy(h2, a, x, y, w1, zones, "alignBottom"); //$NON-NLS-1$
+ y = addy(h2, a, x, y, w1, zones, VALUE_ALIGN_TOP);
+ y = addy(h2, a, x, y, w1, zones, VALUE_ALIGN_TOP, VALUE_ALIGN_BOTTOM);
+ y = addy(h2, a, x, y, w1, zones, VALUE_ALIGN_BOTTOM);
return Pair.of(bounds, zones);
}
@@ -511,20 +562,20 @@ public class RelativeLayoutRule extends BaseLayoutRule {
int offsetX = x - be.x;
int offsetY = y - be.y;
- if (data.getCurr().getAttr().contains("alignTop") //$NON-NLS-1$
- && data.getCurr().getAttr().contains("alignBottom")) { //$NON-NLS-1$
+ if (data.getCurr().getAttr().contains(VALUE_ALIGN_TOP)
+ && data.getCurr().getAttr().contains(VALUE_ALIGN_BOTTOM)) {
offsetY -= be.h / 2;
- } else if (data.getCurr().getAttr().contains("above") //$NON-NLS-1$
- || data.getCurr().getAttr().contains("alignTop") //$NON-NLS-1$
- || data.getCurr().getAttr().contains("alignParentBottom")) { //$NON-NLS-1$
+ } else if (data.getCurr().getAttr().contains(VALUE_ABOVE)
+ || data.getCurr().getAttr().contains(VALUE_ALIGN_TOP)
+ || data.getCurr().getAttr().contains(VALUE_ALIGN_PARENT_BOTTOM)) {
offsetY -= be.h;
}
- if (data.getCurr().getAttr().contains("alignRight") //$NON-NLS-1$
- && data.getCurr().getAttr().contains("alignLeft")) { //$NON-NLS-1$
+ if (data.getCurr().getAttr().contains(VALUE_ALIGN_RIGHT)
+ && data.getCurr().getAttr().contains(VALUE_ALIGN_LEFT)) {
offsetX -= be.w / 2;
- } else if (data.getCurr().getAttr().contains("toLeftOft") //$NON-NLS-1$
- || data.getCurr().getAttr().contains("alignLeft") //$NON-NLS-1$
- || data.getCurr().getAttr().contains("alignParentRight")) { //$NON-NLS-1$
+ } else if (data.getCurr().getAttr().contains(VALUE_TO_LEFT_OF)
+ || data.getCurr().getAttr().contains(VALUE_ALIGN_LEFT)
+ || data.getCurr().getAttr().contains(VALUE_ALIGN_PARENT_RIGHT)) {
offsetX -= be.w;
}
@@ -719,5 +770,9 @@ public class RelativeLayoutRule extends BaseLayoutRule {
private boolean isVertical() {
return mVertical;
}
+
+ private boolean isBorderZone() {
+ return mMark != null;
+ }
}
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/DynamicContextMenu.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/DynamicContextMenu.java
index d702255..0875642 100755
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/DynamicContextMenu.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/DynamicContextMenu.java
@@ -24,7 +24,6 @@ import com.android.ide.eclipse.adt.internal.editors.IconFactory;
import com.android.ide.eclipse.adt.internal.editors.layout.LayoutEditor;
import com.android.ide.eclipse.adt.internal.editors.layout.gle2.IncludeFinder.Reference;
import com.android.ide.eclipse.adt.internal.editors.layout.gre.NodeProxy;
-import com.android.ide.eclipse.adt.internal.editors.layout.gre.RulesEngine;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
@@ -425,10 +424,11 @@ import java.util.regex.Pattern;
IMenuCallback c = ((MenuAction.Action) a2).getCallback();
if (c != null) {
try {
- c.action(a2, null /* no valueId for a toggle */, !isChecked);
+ c.action(a2, null /* no valueId for a toggle */,
+ !isChecked);
} catch (Exception e) {
- RulesEngine gre = mCanvas.getRulesEngine();
- gre.logError("XML edit operation failed: %s", e.toString());
+ AdtPlugin.log(e, "XML edit operation failed: %s",
+ e.toString());
}
}
}
@@ -488,8 +488,8 @@ import java.util.regex.Pattern;
// Values do not apply for plain actions
c.action(a2, null /* valueId */, null /* newValue */);
} catch (Exception e) {
- RulesEngine gre = mCanvas.getRulesEngine();
- gre.logError("XML edit operation failed: %s", e.toString());
+ AdtPlugin.log(e, "XML edit operation failed: %s",
+ e.toString());
}
}
}
@@ -614,8 +614,8 @@ import java.util.regex.Pattern;
((MenuAction.Action) a2).getCallback().action(a2, key,
!isChecked);
} catch (Exception e) {
- RulesEngine gre = mCanvas.getRulesEngine();
- gre.logError("XML edit operation failed: %s", e.toString());
+ AdtPlugin.log(e, "XML edit operation failed: %s",
+ e.toString());
}
}
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/GestureManager.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/GestureManager.java
index d3a7820..314719a 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/GestureManager.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/GestureManager.java
@@ -16,6 +16,8 @@
package com.android.ide.eclipse.adt.internal.editors.layout.gle2;
+import com.android.ide.common.api.Rect;
+
import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.DragSource;
@@ -612,6 +614,16 @@ public class GestureManager {
int deltaX = (int) (scale * (boundingBox.x - p.x));
int deltaY = (int) (scale * (boundingBox.y - p.y));
SwtUtils.setDragImageOffsets(e, -deltaX, -deltaY);
+
+ // View rules may need to know it as well
+ GlobalCanvasDragInfo dragInfo = GlobalCanvasDragInfo.getInstance();
+ Rect dragBounds = null;
+ if (dragInfo != null) {
+ int width = (int) (scale * boundingBox.width);
+ int height = (int) (scale * boundingBox.height);
+ dragBounds = new Rect(deltaX, deltaY, width, height);
+ dragInfo.setDragBounds(dragBounds);
+ }
}
}
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/GlobalCanvasDragInfo.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/GlobalCanvasDragInfo.java
index 3fd98a3..9315967 100755
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/GlobalCanvasDragInfo.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/GlobalCanvasDragInfo.java
@@ -16,6 +16,8 @@
package com.android.ide.eclipse.adt.internal.editors.layout.gle2;
+import com.android.ide.common.api.Rect;
+
/**
* This singleton is used to keep track of drag'n'drops initiated within this
@@ -43,6 +45,7 @@ final class GlobalCanvasDragInfo {
private SelectionItem[] mCurrentSelection;
private Object mSourceCanvas = null;
private Runnable mRemoveSourceHandler;
+ private Rect mDragBounds;
/** Private constructor. Use {@link #getInstance()} to retrieve the singleton. */
private GlobalCanvasDragInfo() {
@@ -114,4 +117,30 @@ final class GlobalCanvasDragInfo {
mRemoveSourceHandler = null;
}
}
+
+ /**
+ * Get the bounds of the drag, relative to the starting mouse position. For example,
+ * if you have a rectangular view of size 100x80, and you start dragging at position
+ * (15,20) from the top left corner of this rectangle, then the drag bounds would be
+ * (-15,-20, 100x80).
+ * <p>
+ * NOTE: The coordinate units will be in SWT/control pixels, not Android view pixels.
+ * In other words, they are affected by the canvas zoom: If you zoom the view and the
+ * bounds of a view grow, the drag bounds will be larger.
+ *
+ * @return the drag bounds, or null if there are no bounds for the current drag
+ */
+ public Rect getDragBounds() {
+ return mDragBounds;
+ }
+
+ /**
+ * Set the bounds of the drag, relative to the starting mouse position. See
+ * {@link #getDragBounds()} for details on the semantics of the drag bounds.
+ *
+ * @param dragBounds the new drag bounds, or null if there are no drag bounds
+ */
+ public void setDragBounds(Rect dragBounds) {
+ mDragBounds = dragBounds;
+ }
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/GraphicalEditorPart.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/GraphicalEditorPart.java
index ede9115..cce6c2a 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/GraphicalEditorPart.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/GraphicalEditorPart.java
@@ -16,6 +16,8 @@
package com.android.ide.eclipse.adt.internal.editors.layout.gle2;
+import static com.android.sdklib.resources.Density.DEFAULT_DENSITY;
+
import com.android.ide.common.layoutlib.BasicLayoutScene;
import com.android.ide.common.layoutlib.LayoutLibrary;
import com.android.ide.common.sdk.LoadStatus;
@@ -1176,7 +1178,15 @@ public class GraphicalEditorPart extends EditorPart
return mConfigComposite.getScreenBounds();
}
-
+ /**
+ * Returns the scale to multiply pixels in the layout coordinate space with to obtain
+ * the corresponding dip (device independent pixel)
+ *
+ * @return the scale to multiple layout coordinates with to obtain the dip position
+ */
+ public float getDipScale() {
+ return DEFAULT_DENSITY / (float) mConfigComposite.getDensity().getDpiValue();
+ }
// --- private methods ---
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/MoveGesture.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/MoveGesture.java
index f047cbc..863b250 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/MoveGesture.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/MoveGesture.java
@@ -446,6 +446,28 @@ public class MoveGesture extends DropGesture {
}
df.sameCanvas = mCanvas == mGlobalDragInfo.getSourceCanvas();
df.invalidTarget = false;
+ df.dipScale = mCanvas.getLayoutEditor().getGraphicalEditor().getDipScale();
+
+ // Set the drag bounds, after converting it from control coordinates to
+ // layout coordinates
+ GlobalCanvasDragInfo dragInfo = GlobalCanvasDragInfo.getInstance();
+ Rect dragBounds = null;
+ if (dragInfo != null) {
+ Rect controlDragBounds = dragInfo.getDragBounds();
+ if (controlDragBounds != null) {
+ CanvasTransform ht = mCanvas.getHorizontalTransform();
+ CanvasTransform vt = mCanvas.getVerticalTransform();
+ double horizScale = ht.getScale();
+ double verticalScale = vt.getScale();
+ int x = (int) (controlDragBounds.x / horizScale);
+ int y = (int) (controlDragBounds.y / verticalScale);
+ int w = (int) (controlDragBounds.w / horizScale);
+ int h = (int) (controlDragBounds.h / verticalScale);
+
+ dragBounds = new Rect(x, y, w, h);
+ }
+ }
+ df.dragBounds = dragBounds;
}
/**
@@ -560,6 +582,7 @@ public class MoveGesture extends DropGesture {
// guideline computations in onDropMove (since only onDropMove is handed
// the -position- of the mouse), and we want this computation to happen
// before we ask the view to draw its feedback.
+ updateDropFeedback(df, event);
df = mCanvas.getRulesEngine().callOnDropMove(targetNode,
mCurrentDragElements, df, new Point(p.x, p.y));
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/PaletteComposite.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/PaletteComposite.java
index f5aaeed..e3bbd00 100755
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/PaletteComposite.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/PaletteComposite.java
@@ -510,12 +510,16 @@ public class PaletteComposite extends Composite {
Rect bounds = null;
DragSource dragSource = mItem.getDragSource();
DragSourceEffect dragSourceEffect = dragSource.getDragSourceEffect();
+ Rect dragBounds = null;
if (dragSourceEffect instanceof PreviewDragSourceEffect) {
PreviewDragSourceEffect preview = (PreviewDragSourceEffect) dragSourceEffect;
Image previewImage = preview.getPreviewImage();
if (previewImage != null && !preview.isPlaceholder()) {
ImageData data = previewImage.getImageData();
- bounds = new Rect(0, 0, data.width, data.height);
+ int width = data.width;
+ int height = data.height;
+ bounds = new Rect(0, 0, width, height);
+ dragBounds = new Rect(-width / 2, -height / 2, width, height);
}
}
@@ -527,11 +531,13 @@ public class PaletteComposite extends Composite {
mElements = new SimpleElement[] { se };
// Register this as the current dragged data
- GlobalCanvasDragInfo.getInstance().startDrag(
+ GlobalCanvasDragInfo dragInfo = GlobalCanvasDragInfo.getInstance();
+ dragInfo.startDrag(
mElements,
null /* selection */,
null /* canvas */,
null /* removeSource */);
+ dragInfo.setDragBounds(dragBounds);
}
public void dragSetData(DragSourceEvent e) {
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/RulesEngine.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/RulesEngine.java
index ff6cbfe..ae894e6 100755
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/RulesEngine.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/RulesEngine.java
@@ -192,7 +192,7 @@ public class RulesEngine {
return rule.getDisplayName();
} catch (Exception e) {
- logError("%s.getDisplayName() failed: %s",
+ AdtPlugin.log(e, "%s.getDisplayName() failed: %s",
rule.getClass().getSimpleName(),
e.toString());
}
@@ -218,7 +218,7 @@ public class RulesEngine {
return rule.getContextMenu(selectedNode);
} catch (Exception e) {
- logError("%s.getContextMenu() failed: %s",
+ AdtPlugin.log(e, "%s.getContextMenu() failed: %s",
rule.getClass().getSimpleName(),
e.toString());
}
@@ -244,7 +244,7 @@ public class RulesEngine {
return rule.getSelectionHint(parentNode, childNode);
} catch (Exception e) {
- logError("%getSelectionHint() failed: %s",
+ AdtPlugin.log(e, "%getSelectionHint() failed: %s",
rule.getClass().getSimpleName(),
e.toString());
}
@@ -269,7 +269,7 @@ public class RulesEngine {
return rule.onDropEnter(targetNode, elements);
} catch (Exception e) {
- logError("%s.onDropEnter() failed: %s",
+ AdtPlugin.log(e, "%s.onDropEnter() failed: %s",
rule.getClass().getSimpleName(),
e.toString());
}
@@ -295,7 +295,7 @@ public class RulesEngine {
return rule.onDropMove(targetNode, elements, feedback, where);
} catch (Exception e) {
- logError("%s.onDropMove() failed: %s",
+ AdtPlugin.log(e, "%s.onDropMove() failed: %s",
rule.getClass().getSimpleName(),
e.toString());
}
@@ -318,7 +318,7 @@ public class RulesEngine {
rule.onDropLeave(targetNode, elements, feedback);
} catch (Exception e) {
- logError("%s.onDropLeave() failed: %s",
+ AdtPlugin.log(e, "%s.onDropLeave() failed: %s",
rule.getClass().getSimpleName(),
e.toString());
}
@@ -342,7 +342,7 @@ public class RulesEngine {
rule.onDropped(targetNode, elements, feedback, where);
} catch (Exception e) {
- logError("%s.onDropped() failed: %s",
+ AdtPlugin.log(e, "%s.onDropped() failed: %s",
rule.getClass().getSimpleName(),
e.toString());
}
@@ -359,7 +359,7 @@ public class RulesEngine {
try {
feedback.painter.paint(gc, targetNode, feedback);
} catch (Exception e) {
- logError("DropFeedback.painter failed: %s",
+ AdtPlugin.log(e, "DropFeedback.painter failed: %s",
e.toString());
}
}
@@ -381,7 +381,7 @@ public class RulesEngine {
rule.onPaste(targetNode, pastedElements);
} catch (Exception e) {
- logError("%s.onPaste() failed: %s",
+ AdtPlugin.log(e, "%s.onPaste() failed: %s",
rule.getClass().getSimpleName(),
e.toString());
}
@@ -490,7 +490,7 @@ public class RulesEngine {
try {
rule.onDispose();
} catch (Exception e) {
- logError("%s.onDispose() failed: %s",
+ AdtPlugin.log(e, "%s.onDispose() failed: %s",
rule.getClass().getSimpleName(),
e.toString());
}
@@ -649,10 +649,10 @@ public class RulesEngine {
// class.
} catch (InstantiationException e) {
// This is NOT an expected error: fail.
- logError("load rule error (%s): %s", realFqcn, e.toString());
+ AdtPlugin.log(e, "load rule error (%s): %s", realFqcn, e.toString());
} catch (IllegalAccessException e) {
// This is NOT an expected error: fail.
- logError("load rule error (%s): %s", realFqcn, e.toString());
+ AdtPlugin.log(e, "load rule error (%s): %s", realFqcn, e.toString());
}
// Memorize in the cache that we couldn't find a rule for this real FQCN
@@ -687,7 +687,7 @@ public class RulesEngine {
rule.onDispose();
}
} catch (Exception e) {
- logError("%s.onInit() failed: %s",
+ AdtPlugin.log(e, "%s.onInit() failed: %s",
rule.getClass().getSimpleName(),
e.toString());
}
@@ -696,18 +696,6 @@ public class RulesEngine {
}
/**
- * Logs an error to the console.
- *
- * @param format A format string following the format specified by
- * {@link String#format}
- * @param params An optional set of parameters to the format string
- */
- public void logError(String format, Object...params) {
- String s = String.format(format, params);
- AdtPlugin.printErrorToConsole(mProject, s);
- }
-
- /**
* Implementation of {@link IClientRulesEngine}. This provide {@link IViewRule} clients
* with a few methods they can use to use functionality from this {@link RulesEngine}.
*/
@@ -750,7 +738,7 @@ public class RulesEngine {
try {
return filter.validate(newText);
} catch (Exception e) {
- logError("Custom validator failed: %s", e.toString());
+ AdtPlugin.log(e, "Custom validator failed: %s", e.toString());
return ""; //$NON-NLS-1$
}
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/common/layout/AbsoluteLayoutRuleTest.java b/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/common/layout/AbsoluteLayoutRuleTest.java
index a6d6384..f4092eb 100644
--- a/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/common/layout/AbsoluteLayoutRuleTest.java
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/common/layout/AbsoluteLayoutRuleTest.java
@@ -52,14 +52,16 @@ public class AbsoluteLayoutRuleTest extends LayoutTestBase {
4,
// Not dragging one of the existing children
-1,
+
+
// Bounds rectangle
"useStyle(DROP_RECIPIENT), drawRect(Rect[0,0,240,480])",
// Drop preview
- "useStyle(DROP_PREVIEW), drawRect(Rect[-22,-50,105,80])");
+ "useStyle(DROP_PREVIEW), drawRect(Rect[30,-10,105,80])");
- assertEquals("-22dip", inserted.getStringAttr(ANDROID_URI, "layout_x"));
- assertEquals("-50dip", inserted.getStringAttr(ANDROID_URI, "layout_y"));
+ assertEquals("30dip", inserted.getStringAttr(ANDROID_URI, "layout_x"));
+ assertEquals("-10dip", inserted.getStringAttr(ANDROID_URI, "layout_y"));
// Without drag bounds we should just draw guide lines instead
inserted = dragInto(new Rect(0, 0, 0, 0), new Point(30, -10), 4, -1,