FrameLayout

This commit is contained in:
Alexander Lobas
2012-04-01 16:41:20 +04:00
parent 50ef46f5ed
commit c49459b0c0
2 changed files with 168 additions and 40 deletions
@@ -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, Gravity> 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, Gravity> 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;
}
}
}
@@ -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, Gravity> gravity(RadComponent component) {
String value = ((RadViewComponent)component).getTag().getAttributeValue("android:layout_gravity");
int flags = Gravity.getFlags(value);