diff --git a/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/FrameLayoutMarginOperation.java b/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/FrameLayoutMarginOperation.java index de16f10b98fe..58a3b2e73d4f 100644 --- a/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/FrameLayoutMarginOperation.java +++ b/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/FrameLayoutMarginOperation.java @@ -15,8 +15,10 @@ */ package com.intellij.android.designer.designSurface.layout; +import com.android.ide.common.rendering.api.ViewInfo; import com.intellij.android.designer.model.RadViewComponent; import com.intellij.android.designer.model.layout.RadFrameLayout; +import com.intellij.designer.designSurface.DecorationLayer; import com.intellij.designer.designSurface.EditOperation; import com.intellij.designer.designSurface.FeedbackLayer; import com.intellij.designer.designSurface.OperationContext; @@ -24,7 +26,9 @@ import com.intellij.designer.designSurface.feedbacks.LineMarginBorder; import com.intellij.designer.designSurface.feedbacks.RectangleComponent; import com.intellij.designer.designSurface.feedbacks.TextFeedback; import com.intellij.designer.designSurface.selection.DirectionResizePoint; +import com.intellij.designer.designSurface.selection.ResizePoint; import com.intellij.designer.designSurface.selection.ResizeSelectionDecorator; +import com.intellij.designer.designSurface.tools.InputTool; import com.intellij.designer.model.RadComponent; import com.intellij.designer.utils.Position; import com.intellij.openapi.application.ApplicationManager; @@ -46,40 +50,16 @@ public class FrameLayoutMarginOperation implements EditOperation { private RadViewComponent myComponent; private RectangleComponent myFeedback; private TextFeedback myTextFeedback; + private Rectangle myMargins; public FrameLayoutMarginOperation(OperationContext context) { myContext = context; } - public static void points(ResizeSelectionDecorator decorator) { - decorator.addPoint(new DirectionResizePoint(Color.orange, Color.black, Position.WEST, TYPE)); // left - decorator.addPoint(new DirectionResizePoint(Color.orange, Color.black, Position.EAST, TYPE).move(1, 0.25)); // right - decorator.addPoint(new DirectionResizePoint(Color.orange, Color.black, Position.NORTH, TYPE)); // top - decorator.addPoint(new DirectionResizePoint(Color.orange, Color.black, Position.SOUTH, TYPE).move(0.25, 1)); // bottom - } - - public static boolean visible(RadComponent component, DirectionResizePoint point) { - Pair gravity = RadFrameLayout.gravity(component); - int direction = point.getDirection(); - - if (direction == Position.WEST) { // left - return gravity.first == Gravity.left || gravity.first == Gravity.center; - } - else if (direction == Position.EAST) { // right - return gravity.first == Gravity.right || gravity.first == Gravity.center; - } - else if (direction == Position.NORTH) { // top - return gravity.second == Gravity.top || gravity.second == Gravity.center; - } - else if (direction == Position.SOUTH) { // bottom - return gravity.second == Gravity.bottom || gravity.second == Gravity.center; - } - return true; - } - @Override public void setComponent(RadComponent component) { myComponent = (RadViewComponent)component; + myMargins = getMargins(myComponent); } @Override @@ -105,7 +85,9 @@ public class FrameLayoutMarginOperation implements EditOperation { public void showFeedback() { createFeedback(); - myFeedback.setBounds(myContext.getTransformedRectangle(myComponent.getBounds(myContext.getArea().getFeedbackLayer()))); + Rectangle bounds = myContext.getTransformedRectangle(myComponent.getBounds(myContext.getArea().getFeedbackLayer())); + applyMargins(bounds, myMargins); + myFeedback.setBounds(bounds); Point moveDelta = myContext.getMoveDelta(); Dimension sizeDelta = myContext.getSizeDelta(); @@ -114,16 +96,17 @@ public class FrameLayoutMarginOperation implements EditOperation { myTextFeedback.clear(); if (direction == Position.WEST) { // left - myTextFeedback.append(Integer.toString(-moveDelta.x)); + myTextFeedback.append(Integer.toString(myMargins.x - moveDelta.x)); } else if (direction == Position.EAST) { // right - myTextFeedback.append(Integer.toString(sizeDelta.width)); + + myTextFeedback.append(Integer.toString(myMargins.width + sizeDelta.width)); } else if (direction == Position.NORTH) { // top - myTextFeedback.append(Integer.toString(-moveDelta.y)); + myTextFeedback.append(Integer.toString(myMargins.y - moveDelta.y)); } else if (direction == Position.SOUTH) { // bottom - myTextFeedback.append(Integer.toString(sizeDelta.height)); + myTextFeedback.append(Integer.toString(myMargins.height + sizeDelta.height)); } myTextFeedback.dimension("dp"); @@ -174,16 +157,16 @@ public class FrameLayoutMarginOperation implements EditOperation { int direction = myContext.getResizeDirection(); if (direction == Position.WEST) { // left - setValue(tag, "android:layout_marginLeft", -moveDelta.x); + setValue(tag, "android:layout_marginLeft", myMargins.x - moveDelta.x); } else if (direction == Position.EAST) { // right - setValue(tag, "android:layout_marginRight", sizeDelta.width); + setValue(tag, "android:layout_marginRight", myMargins.width + sizeDelta.width); } else if (direction == Position.NORTH) { // top - setValue(tag, "android:layout_marginTop", -moveDelta.y); + setValue(tag, "android:layout_marginTop", myMargins.y - moveDelta.y); } else if (direction == Position.SOUTH) { // bottom - setValue(tag, "android:layout_marginBottom", sizeDelta.height); + setValue(tag, "android:layout_marginBottom", myMargins.height + sizeDelta.height); } } }); @@ -200,4 +183,146 @@ public class FrameLayoutMarginOperation implements EditOperation { tag.setAttribute(name, Integer.toString(value) + "dp"); } } + + ////////////////////////////////////////////////////////////////////////////////////////// + // + // Handlers + // + ////////////////////////////////////////////////////////////////////////////////////////// + private static final float[] DASHES = new float[]{1, 2}; + + public static boolean visible(RadComponent component, DirectionResizePoint point) { + Pair gravity = RadFrameLayout.gravity(component); + int direction = point.getDirection(); + + if (direction == Position.WEST) { // left + return gravity.first == Gravity.left || gravity.first == Gravity.center; + } + else if (direction == Position.EAST) { // right + return gravity.first == Gravity.right || gravity.first == Gravity.center; + } + else if (direction == Position.NORTH) { // top + return gravity.second == Gravity.top || gravity.second == Gravity.center; + } + else if (direction == Position.SOUTH) { // bottom + return gravity.second == Gravity.bottom || gravity.second == Gravity.center; + } + return true; + } + + public static void points(ResizeSelectionDecorator decorator) { + decorator.addPoint(new ResizePoint() { + private final BasicStroke myStroke = new BasicStroke(1, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 1, DASHES, 0); + + @Override + protected void paint(DecorationLayer layer, Graphics2D g, RadComponent component) { + Rectangle bounds = component.getBounds(layer); + applyMargins(bounds, getMargins(component)); + + g.setStroke(myStroke); + g.setColor(Color.red); + g.drawRect(bounds.x, bounds.y, bounds.width, bounds.height); + } + + @Override + public InputTool findTargetTool(DecorationLayer layer, RadComponent component, int x, int y) { + return null; + } + + @Override + public Object getType() { + return null; + } + + @Override + protected InputTool createTool(RadComponent component) { + return null; + } + + @Override + protected Point getLocation(DecorationLayer layer, RadComponent component) { + return null; + } + }); + + decorator.addPoint(new DirectionResizePoint(Color.orange, Color.black, Position.WEST, FrameLayoutMarginOperation.TYPE) { // left + @Override + protected Point getLocation(DecorationLayer layer, RadComponent component) { + Point location = super.getLocation(layer, component); + location.x -= getMargin(component, "leftMargin"); + return location; + } + }); + + decorator + .addPoint(new DirectionResizePoint(Color.orange, Color.black, Position.EAST, FrameLayoutMarginOperation.TYPE) { // right + @Override + protected Point getLocation(DecorationLayer layer, RadComponent component) { + Point location = super.getLocation(layer, component); + location.x += getMargin(component, "rightMargin"); + return location; + } + }.move(1, 0.25)); + + decorator.addPoint(new DirectionResizePoint(Color.orange, Color.black, Position.NORTH, FrameLayoutMarginOperation.TYPE) { // top + @Override + protected Point getLocation(DecorationLayer layer, RadComponent component) { + Point location = super.getLocation(layer, component); + location.y -= getMargin(component, "topMargin"); + return location; + } + }); + + decorator.addPoint( + new DirectionResizePoint(Color.orange, Color.black, Position.SOUTH, FrameLayoutMarginOperation.TYPE) { // bottom + @Override + protected Point getLocation(DecorationLayer layer, RadComponent component) { + Point location = super.getLocation(layer, component); + location.y += getMargin(component, "bottomMargin"); + return location; + } + }.move(0.25, 1)); + } + + private static void applyMargins(Rectangle bounds, Rectangle margins) { + bounds.x -= margins.x; + bounds.width += margins.x; + + bounds.y -= margins.y; + bounds.height += margins.y; + + bounds.width += margins.width; + bounds.height += margins.height; + } + + private static Rectangle getMargins(RadComponent component) { + Rectangle margins = new Rectangle(); + + try { + ViewInfo viewInfo = ((RadViewComponent)component).getViewInfo(); + Object layoutParams = viewInfo.getLayoutParamsObject(); + Class layoutClass = layoutParams.getClass(); + + margins.x = layoutClass.getField("leftMargin").getInt(layoutParams); + margins.y = layoutClass.getField("topMargin").getInt(layoutParams); + margins.width = layoutClass.getField("rightMargin").getInt(layoutParams); + margins.height = layoutClass.getField("bottomMargin").getInt(layoutParams); + } + catch (Throwable e) { + } + + return margins; + } + + private static int getMargin(RadComponent component, String marginName) { + try { + ViewInfo viewInfo = ((RadViewComponent)component).getViewInfo(); + Object layoutParams = viewInfo.getLayoutParamsObject(); + + return layoutParams.getClass().getField(marginName).getInt(layoutParams); + } + catch (Throwable e) { + return 0; + } + } } \ No newline at end of file diff --git a/plugins/android-designer/src/com/intellij/android/designer/model/layout/RadFrameLayout.java b/plugins/android-designer/src/com/intellij/android/designer/model/layout/RadFrameLayout.java index d53778d4dd61..cdf679a36b9e 100644 --- a/plugins/android-designer/src/com/intellij/android/designer/model/layout/RadFrameLayout.java +++ b/plugins/android-designer/src/com/intellij/android/designer/model/layout/RadFrameLayout.java @@ -16,10 +16,7 @@ package com.intellij.android.designer.model.layout; import com.intellij.android.designer.designSurface.TreeDropToOperation; -import com.intellij.android.designer.designSurface.layout.FrameLayoutMarginOperation; -import com.intellij.android.designer.designSurface.layout.FrameLayoutOperation; -import com.intellij.android.designer.designSurface.layout.Gravity; -import com.intellij.android.designer.designSurface.layout.ResizeOperation; +import com.intellij.android.designer.designSurface.layout.*; import com.intellij.android.designer.model.RadViewComponent; import com.intellij.android.designer.model.RadViewLayoutWithData; import com.intellij.designer.designSurface.ComponentDecorator; @@ -76,10 +73,10 @@ public class RadFrameLayout extends RadViewLayoutWithData { return true; } }; - ResizeOperation.points(decorator); if (selection.size() == 1) { FrameLayoutMarginOperation.points(decorator); } + ResizeOperation.points(decorator); return decorator; } @@ -91,6 +88,12 @@ public class RadFrameLayout extends RadViewLayoutWithData { super.addSelectionActions(designer, actionGroup, shortcuts, selection); // TODO: Auto-generated method stub } + ////////////////////////////////////////////////////////////////////////////////////////// + // + // Utils + // + ////////////////////////////////////////////////////////////////////////////////////////// + public static Pair gravity(RadComponent component) { String value = ((RadViewComponent)component).getTag().getAttributeValue("android:layout_gravity"); int flags = Gravity.getFlags(value);