From 73f8549170d2db5c46439b4d113bf550d171a4ce Mon Sep 17 00:00:00 2001 From: Alexander Lobas Date: Sat, 28 Apr 2012 18:34:00 +0400 Subject: [PATCH] GridLayout --- .../actions/GridLayoutSpanOperation.java | 101 ++++++ .../layout/actions/LayoutSpanOperation.java | 304 +++++++++++++----- .../layout/actions/ResizeOperation.java | 8 +- .../actions/TableLayoutSpanOperation.java | 98 ++++++ .../layout/grid/GridSelectionDecorator.java | 48 +++ .../model/layout/grid/RadGridLayout.java | 23 +- .../model/layout/table/RadTableRowLayout.java | 36 ++- .../selection/DirectionResizePoint.java | 6 +- .../NonResizeSelectionDecorator.java | 8 +- 9 files changed, 527 insertions(+), 105 deletions(-) create mode 100644 plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/actions/GridLayoutSpanOperation.java create mode 100644 plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/actions/TableLayoutSpanOperation.java create mode 100644 plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/grid/GridSelectionDecorator.java diff --git a/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/actions/GridLayoutSpanOperation.java b/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/actions/GridLayoutSpanOperation.java new file mode 100644 index 000000000000..6d57587e6c7a --- /dev/null +++ b/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/actions/GridLayoutSpanOperation.java @@ -0,0 +1,101 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.android.designer.designSurface.layout.actions; + +import com.intellij.android.designer.designSurface.layout.grid.GridSelectionDecorator; +import com.intellij.android.designer.model.layout.grid.RadGridLayoutComponent; +import com.intellij.designer.designSurface.OperationContext; +import com.intellij.designer.model.RadComponent; +import com.intellij.designer.utils.Position; + +import java.awt.*; + +/** + * @author Alexander Lobas + */ +public class GridLayoutSpanOperation extends LayoutSpanOperation { + public GridLayoutSpanOperation(OperationContext context, GridSelectionDecorator decorator) { + super(context, decorator); + } + + @Override + public void setComponent(RadComponent component) { + super.setComponent(component); + int direction = myContext.getResizeDirection(); + mySpan = RadGridLayoutComponent.getSpan(myComponent, direction == Position.NORTH || direction == Position.SOUTH); + } + + @Override + protected String getColumnAttribute(boolean asName) { + return asName ? "layout:column" : "android:layout_column"; + } + + @Override + protected String getColumnSpanAttribute(boolean asName) { + return asName ? "layout:columnSpan" : "android:layout_columnSpan"; + } + + @Override + protected String getRowAttribute(boolean asName) { + return asName ? "layout:row" : "android:layout_row"; + } + + @Override + protected String getRowSpanAttribute(boolean asName) { + return asName ? "layout:rowSpan" : "android:layout_rowSpan"; + } + + @Override + protected Point getCellInfo() { + return RadGridLayoutComponent.getCellInfo(myComponent).getLocation(); + } + + ////////////////////////////////////////////////////////////////////////////////////////// + // + // ResizePoint + // + ////////////////////////////////////////////////////////////////////////////////////////// + + public static void points(GridSelectionDecorator decorator) { + decorator.addPoint(new SpanPoint(COLOR, + Color.black, + Position.WEST, + TYPE, + "Change layout:column x layout:columnSpan", + decorator)); // left + + decorator.addPoint(new SpanPoint(COLOR, + Color.black, + Position.EAST, + TYPE, + "Change layout:columnSpan", + decorator).move(1, 0.75)); // right + + decorator.addPoint(new SpanPoint(COLOR, + Color.black, + Position.NORTH, + TYPE, + "Change layout:row x layout:rowSpan", + decorator)); // top + + decorator.addPoint(new SpanPoint(COLOR, + Color.black, + Position.SOUTH, + TYPE, + "Change layout:rowSpan", + decorator).move(0.75, 1)); // bottom + } +} \ No newline at end of file diff --git a/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/actions/LayoutSpanOperation.java b/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/actions/LayoutSpanOperation.java index 280a594b5e54..bcdacb846d4b 100644 --- a/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/actions/LayoutSpanOperation.java +++ b/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/actions/LayoutSpanOperation.java @@ -15,10 +15,12 @@ */ package com.intellij.android.designer.designSurface.layout.actions; +import com.intellij.android.designer.designSurface.layout.grid.GridSelectionDecorator; import com.intellij.android.designer.model.ModelParser; import com.intellij.android.designer.model.RadViewComponent; import com.intellij.android.designer.model.grid.GridInfo; -import com.intellij.android.designer.model.layout.table.RadTableLayoutComponent; +import com.intellij.android.designer.model.grid.IGridProvider; +import com.intellij.designer.designSurface.DecorationLayer; import com.intellij.designer.designSurface.EditOperation; import com.intellij.designer.designSurface.FeedbackLayer; import com.intellij.designer.designSurface.OperationContext; @@ -26,13 +28,12 @@ import com.intellij.designer.designSurface.feedbacks.LineMarginBorder; import com.intellij.designer.designSurface.feedbacks.RectangleFeedback; import com.intellij.designer.designSurface.feedbacks.TextFeedback; import com.intellij.designer.designSurface.selection.DirectionResizePoint; -import com.intellij.designer.designSurface.selection.ResizeSelectionDecorator; import com.intellij.designer.model.RadComponent; import com.intellij.designer.utils.Position; import com.intellij.openapi.application.ApplicationManager; import com.intellij.psi.xml.XmlTag; -import com.intellij.util.ArrayUtil; import com.intellij.util.containers.IntArrayList; +import org.jetbrains.annotations.Nullable; import java.awt.*; import java.util.List; @@ -40,38 +41,40 @@ import java.util.List; /** * @author Alexander Lobas */ -public class LayoutSpanOperation implements EditOperation { +public abstract class LayoutSpanOperation implements EditOperation { public static final String TYPE = "layout_span"; - private static final Color COLOR = Color.green.darker(); + protected static final Color COLOR = Color.green.darker(); - private final OperationContext myContext; - private RadViewComponent myComponent; + protected final OperationContext myContext; + private final GridSelectionDecorator myDecorator; + protected RadViewComponent myComponent; private RectangleFeedback myFeedback; private TextFeedback myTextFeedback; private Rectangle myBounds; - private Rectangle myTableBounds; - private int mySpan; + private Rectangle myContainerBounds; + protected int mySpan; private int[] mySpans; private int[] myOffsets; - private int[] myColumns; + private int[] myCells; private int myIndex = -1; - public LayoutSpanOperation(OperationContext context) { + public LayoutSpanOperation(OperationContext context, GridSelectionDecorator decorator) { myContext = context; + myDecorator = decorator; } @Override public void setComponent(RadComponent component) { myComponent = (RadViewComponent)component; - myBounds = myComponent.getBounds(myContext.getArea().getFeedbackLayer()); + myBounds = myDecorator.getCellBounds(myContext.getArea().getFeedbackLayer(), myComponent); } @Override public void setComponents(List components) { } - private void createFeedback() { + protected void createFeedback() { if (myFeedback == null) { FeedbackLayer layer = myContext.getArea().getFeedbackLayer(); @@ -90,11 +93,87 @@ public class LayoutSpanOperation implements EditOperation { public void showFeedback() { createFeedback(); - Rectangle bounds = myContext.getTransformedRectangle(myBounds); - boolean right = myContext.getResizeDirection() == Position.EAST; + int direction = myContext.getResizeDirection(); + if (direction == Position.WEST || direction == Position.EAST) { + handleColumns(direction == Position.EAST); + } + else { + handleRows(direction == Position.SOUTH); + } + } + @Override + public void eraseFeedback() { + if (myFeedback != null) { + FeedbackLayer layer = myContext.getArea().getFeedbackLayer(); + layer.remove(myTextFeedback); + layer.remove(myFeedback); + layer.repaint(); + myTextFeedback = null; + myFeedback = null; + } + } + + protected abstract String getColumnAttribute(boolean asName); + + protected abstract String getColumnSpanAttribute(boolean asName); + + protected abstract String getRowAttribute(boolean asName); + + protected abstract String getRowSpanAttribute(boolean asName); + + private void handleRows(boolean bottom) { + calculateRows(bottom); + + Rectangle bounds = myContext.getTransformedRectangle(myBounds); + int location = bottom ? bounds.y + bounds.height : bounds.y; + + if (location < myOffsets[0]) { + myIndex = 0; + } + else { + myIndex = -1; + + for (int i = 0; i < myOffsets.length - 1; i++) { + if (myOffsets[i] <= location && location <= myOffsets[i + 1]) { + int delta1 = location - myOffsets[i]; + int delta2 = myOffsets[i + 1] - location; + myIndex = delta2 >= delta1 ? i : i + 1; + break; + } + } + + if (myIndex == -1) { + myIndex = myOffsets.length - 1; + } + } + + if (bottom) { + myFeedback.setBounds(myBounds.x, myBounds.y, myBounds.width, myOffsets[myIndex] - myBounds.y); + } + else { + myFeedback.setBounds(myBounds.x, myOffsets[myIndex], myBounds.width, myBounds.y + myBounds.height - myOffsets[myIndex]); + } + + myTextFeedback.clear(); + + if (!bottom) { + myTextFeedback.append(getRowAttribute(true)); + myTextFeedback.append(" "); + myTextFeedback.append(Integer.toString(myCells[myIndex])); + myTextFeedback.append(", "); + } + + myTextFeedback.append(getRowSpanAttribute(true)); + myTextFeedback.append(" "); + myTextFeedback.append(Integer.toString(mySpans[myIndex])); + myTextFeedback.centerTop(myContainerBounds); + } + + private void handleColumns(boolean right) { calculateColumns(right); + Rectangle bounds = myContext.getTransformedRectangle(myBounds); int location = right ? bounds.x + bounds.width : bounds.x; if (location < myOffsets[0]) { @@ -127,14 +206,86 @@ public class LayoutSpanOperation implements EditOperation { myTextFeedback.clear(); if (!right) { - myTextFeedback.append("layout:column "); - myTextFeedback.append(Integer.toString(myColumns[myIndex])); + myTextFeedback.append(getColumnAttribute(true)); + myTextFeedback.append(" "); + myTextFeedback.append(Integer.toString(myCells[myIndex])); myTextFeedback.append(", "); } - myTextFeedback.append("layout:span "); + myTextFeedback.append(getColumnSpanAttribute(true)); + myTextFeedback.append(" "); myTextFeedback.append(Integer.toString(mySpans[myIndex])); - myTextFeedback.centerTop(myTableBounds); + myTextFeedback.centerTop(myContainerBounds); + } + + protected RadComponent getContainer() { + return myComponent.getParent(); + } + + protected abstract Point getCellInfo(); + + private void calculateRows(boolean bottom) { + if (mySpans != null) { + return; + } + + RadComponent container = getContainer(); + GridInfo gridInfo = ((IGridProvider)container).getVirtualGridInfo(); + RadComponent[][] components = gridInfo.components; + Point cellInfo = getCellInfo(); + int row = cellInfo.y; + + myContainerBounds = container.getBounds(myContext.getArea().getFeedbackLayer()); + + IntArrayList spans = new IntArrayList(); + IntArrayList offsets = new IntArrayList(); + + if (bottom) { + int span = 1; + + for (int i = row; i < row + mySpan; i++) { + spans.add(span++); + offsets.add(myContainerBounds.y + gridInfo.hLines[i + 1]); + } + + for (int i = row + mySpan; i < components.length; i++) { + if (components[i][cellInfo.x] == null) { + spans.add(span++); + offsets.add(myContainerBounds.y + gridInfo.hLines[i + 1]); + } + else { + break; + } + } + } + else { + IntArrayList columns = new IntArrayList(); + int span = mySpan; + + for (int i = row; i < row + mySpan; i++) { + spans.add(span--); + offsets.add(myContainerBounds.y + gridInfo.hLines[i]); + columns.add(i); + } + + span = mySpan; + + for (int i = row - 1; i >= 0; i--) { + if (components[i][cellInfo.x] == null) { + spans.add(0, ++span); + offsets.add(0, myContainerBounds.y + gridInfo.hLines[i]); + columns.add(0, i); + } + else { + break; + } + } + + myCells = columns.toArray(); + } + + mySpans = spans.toArray(); + myOffsets = offsets.toArray(); } private void calculateColumns(boolean right) { @@ -142,13 +293,13 @@ public class LayoutSpanOperation implements EditOperation { return; } - RadTableLayoutComponent tableComponent = (RadTableLayoutComponent)myComponent.getParent().getParent(); - GridInfo gridInfo = tableComponent.getVirtualGridInfo(); - RadComponent[] rowComponents = gridInfo.components[tableComponent.getChildren().indexOf(myComponent.getParent())]; - int column = ArrayUtil.indexOf(rowComponents, myComponent); + RadComponent container = getContainer(); + GridInfo gridInfo = ((IGridProvider)container).getVirtualGridInfo(); + Point cellInfo = getCellInfo(); + RadComponent[] rowComponents = gridInfo.components[cellInfo.y]; + int column = cellInfo.x; - mySpan = RadTableLayoutComponent.getCellSpan(myComponent); - myTableBounds = tableComponent.getBounds(myContext.getArea().getFeedbackLayer()); + myContainerBounds = container.getBounds(myContext.getArea().getFeedbackLayer()); IntArrayList spans = new IntArrayList(); IntArrayList offsets = new IntArrayList(); @@ -158,13 +309,13 @@ public class LayoutSpanOperation implements EditOperation { for (int i = column; i < column + mySpan; i++) { spans.add(span++); - offsets.add(myTableBounds.x + gridInfo.vLines[i + 1]); + offsets.add(myContainerBounds.x + gridInfo.vLines[i + 1]); } for (int i = column + mySpan; i < rowComponents.length; i++) { if (rowComponents[i] == null) { spans.add(span++); - offsets.add(myTableBounds.x + gridInfo.vLines[i + 1]); + offsets.add(myContainerBounds.x + gridInfo.vLines[i + 1]); } else { break; @@ -177,7 +328,7 @@ public class LayoutSpanOperation implements EditOperation { for (int i = column; i < column + mySpan; i++) { spans.add(span--); - offsets.add(myTableBounds.x + gridInfo.vLines[i]); + offsets.add(myContainerBounds.x + gridInfo.vLines[i]); columns.add(i); } @@ -186,7 +337,7 @@ public class LayoutSpanOperation implements EditOperation { for (int i = column - 1; i >= 0; i--) { if (rowComponents[i] == null) { spans.add(0, ++span); - offsets.add(0, myTableBounds.x + gridInfo.vLines[i]); + offsets.add(0, myContainerBounds.x + gridInfo.vLines[i]); columns.add(0, i); } else { @@ -194,25 +345,13 @@ public class LayoutSpanOperation implements EditOperation { } } - myColumns = columns.toArray(); + myCells = columns.toArray(); } mySpans = spans.toArray(); myOffsets = offsets.toArray(); } - @Override - public void eraseFeedback() { - if (myFeedback != null) { - FeedbackLayer layer = myContext.getArea().getFeedbackLayer(); - layer.remove(myTextFeedback); - layer.remove(myFeedback); - layer.repaint(); - myTextFeedback = null; - myFeedback = null; - } - } - @Override public boolean canExecute() { return true; @@ -227,66 +366,55 @@ public class LayoutSpanOperation implements EditOperation { ApplicationManager.getApplication().runWriteAction(new Runnable() { @Override public void run() { - XmlTag tag = myComponent.getTag(); - - if (myContext.getResizeDirection() == Position.WEST) { - tag.setAttribute("android:layout_column", Integer.toString(myColumns[myIndex])); - } - - int span = mySpans[myIndex]; - if (span == 1) { - ModelParser.deleteAttribute(tag, "android:layout_span"); + int direction = myContext.getResizeDirection(); + if (direction == Position.WEST || direction == Position.EAST) { + execute(getColumnAttribute(false), getColumnSpanAttribute(false), direction == Position.WEST); } else { - tag.setAttribute("android:layout_span", Integer.toString(span)); + execute(getRowAttribute(false), getRowSpanAttribute(false), direction == Position.NORTH); } } }); } + private void execute(String cell, String span, boolean cellFix) { + XmlTag tag = myComponent.getTag(); + + if (cellFix) { + tag.setAttribute(cell, Integer.toString(myCells[myIndex])); + } + + int spanValue = mySpans[myIndex]; + if (spanValue == 1) { + ModelParser.deleteAttribute(tag, span); + } + else { + tag.setAttribute(span, Integer.toString(spanValue)); + } + } + ////////////////////////////////////////////////////////////////////////////////////////// // // ResizePoint // ////////////////////////////////////////////////////////////////////////////////////////// - public static void tablePoints(ResizeSelectionDecorator decorator) { - decorator.addPoint(new DirectionResizePoint(COLOR, - Color.black, - Position.WEST, - TYPE, - "Change layout:column x layout:span")); // left + protected static class SpanPoint extends DirectionResizePoint { + private final GridSelectionDecorator myDecorator; - decorator.addPoint(new DirectionResizePoint(COLOR, - Color.black, - Position.EAST, - TYPE, - "Change layout:span")); // right - } + public SpanPoint(Color color, + Color border, + int direction, + Object type, + @Nullable String description, + GridSelectionDecorator decorator) { + super(color, border, direction, type, description); + myDecorator = decorator; + } - public static void gridPoints(ResizeSelectionDecorator decorator) { - decorator.addPoint(new DirectionResizePoint(COLOR, - Color.black, - Position.WEST, - TYPE, - "Change layout:column x layout:columnSpan")); // left - - decorator.addPoint(new DirectionResizePoint(COLOR, - Color.black, - Position.EAST, - TYPE, - "Change layout:columnSpan").move(1, 0.25)); // right - - decorator.addPoint(new DirectionResizePoint(COLOR, - Color.black, - Position.NORTH, - TYPE, - "Change layout:row x layout:rowSpan")); // top - - decorator.addPoint(new DirectionResizePoint(COLOR, - Color.black, - Position.SOUTH, - TYPE, - "Change layout:rowSpan").move(0.25, 1)); // bottom + @Override + protected Rectangle getBounds(DecorationLayer layer, RadComponent component) { + return myDecorator.getCellBounds(layer, component); + } } } \ No newline at end of file diff --git a/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/actions/ResizeOperation.java b/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/actions/ResizeOperation.java index 32605ebb346c..ff7025ac434c 100644 --- a/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/actions/ResizeOperation.java +++ b/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/actions/ResizeOperation.java @@ -66,11 +66,15 @@ public class ResizeOperation implements EditOperation { } public static void points(ResizeSelectionDecorator decorator) { - decorator.addPoint(new DirectionResizePoint(blue, Color.black, Position.EAST, TYPE, "Change layout:width")); - decorator.addPoint(new DirectionResizePoint(blue, Color.black, Position.SOUTH, TYPE, "Change layout:height")); + width(decorator); + height(decorator); decorator.addPoint(new DirectionResizePoint(blue, Color.black, Position.SOUTH_EAST, TYPE, "Change layout:width x layout:height")); } + public static void width(ResizeSelectionDecorator decorator) { + decorator.addPoint(new DirectionResizePoint(blue, Color.black, Position.EAST, TYPE, "Change layout:width")); + } + public static void height(ResizeSelectionDecorator decorator) { decorator.addPoint(new DirectionResizePoint(blue, Color.black, Position.SOUTH, TYPE, "Change layout:height")); } diff --git a/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/actions/TableLayoutSpanOperation.java b/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/actions/TableLayoutSpanOperation.java new file mode 100644 index 000000000000..7a44d4c56ec3 --- /dev/null +++ b/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/actions/TableLayoutSpanOperation.java @@ -0,0 +1,98 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.android.designer.designSurface.layout.actions; + +import com.intellij.android.designer.designSurface.layout.grid.GridSelectionDecorator; +import com.intellij.android.designer.model.grid.GridInfo; +import com.intellij.android.designer.model.layout.table.RadTableLayoutComponent; +import com.intellij.designer.designSurface.OperationContext; +import com.intellij.designer.model.RadComponent; +import com.intellij.designer.utils.Position; +import com.intellij.util.ArrayUtil; + +import java.awt.*; + +/** + * @author Alexander Lobas + */ +public class TableLayoutSpanOperation extends LayoutSpanOperation { + public TableLayoutSpanOperation(OperationContext context, GridSelectionDecorator decorator) { + super(context, decorator); + } + + @Override + public void setComponent(RadComponent component) { + super.setComponent(component); + mySpan = RadTableLayoutComponent.getCellSpan(myComponent); + } + + @Override + protected String getColumnAttribute(boolean asName) { + return asName ? "layout:column" : "android:layout_column"; + } + + @Override + protected String getColumnSpanAttribute(boolean asName) { + return asName ? "layout:span" : "android:layout_span"; + } + + @Override + protected String getRowAttribute(boolean asName) { + throw new UnsupportedOperationException(); + } + + @Override + protected String getRowSpanAttribute(boolean asName) { + throw new UnsupportedOperationException(); + } + + @Override + protected RadComponent getContainer() { + return myComponent.getParent().getParent(); + } + + @Override + protected Point getCellInfo() { + RadTableLayoutComponent tableComponent = (RadTableLayoutComponent)myComponent.getParent().getParent(); + GridInfo gridInfo = tableComponent.getVirtualGridInfo(); + int row = tableComponent.getChildren().indexOf(myComponent.getParent()); + int column = ArrayUtil.indexOf(gridInfo.components[row], myComponent); + + return new Point(column, row); + } + + ////////////////////////////////////////////////////////////////////////////////////////// + // + // ResizePoint + // + ////////////////////////////////////////////////////////////////////////////////////////// + + public static void points(GridSelectionDecorator decorator) { + decorator.addPoint(new SpanPoint(COLOR, + Color.black, + Position.WEST, + TYPE, + "Change layout:column x layout:span", + decorator)); // left + + decorator.addPoint(new SpanPoint(COLOR, + Color.black, + Position.EAST, + TYPE, + "Change layout:span", + decorator)); // right + } +} \ No newline at end of file diff --git a/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/grid/GridSelectionDecorator.java b/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/grid/GridSelectionDecorator.java new file mode 100644 index 000000000000..f816ab6e51ed --- /dev/null +++ b/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/grid/GridSelectionDecorator.java @@ -0,0 +1,48 @@ +package com.intellij.android.designer.designSurface.layout.grid; + +import com.intellij.android.designer.model.grid.GridInfo; +import com.intellij.designer.designSurface.DecorationLayer; +import com.intellij.designer.designSurface.selection.ResizeSelectionDecorator; +import com.intellij.designer.model.RadComponent; + +import java.awt.*; + +/** + * @author Alexander Lobas + */ +public abstract class GridSelectionDecorator extends ResizeSelectionDecorator { + public GridSelectionDecorator(Color color, int lineWidth) { + super(color, lineWidth); + } + + @Override + protected Rectangle getBounds(DecorationLayer layer, RadComponent component) { + return getCellBounds(layer, component); + } + + public abstract Rectangle getCellBounds(Component layer, RadComponent component); + + public static Rectangle calculateBounds(Component layer, + GridInfo gridInfo, + RadComponent parent, + RadComponent component, + int row, + int column, + int rowSpan, + int columnSpan) { + Rectangle bounds = parent.getBounds(layer); + + bounds.x += gridInfo.vLines[column]; + bounds.width = gridInfo.vLines[column + columnSpan] - gridInfo.vLines[column]; + + bounds.y += gridInfo.hLines[row]; + bounds.height = gridInfo.hLines[row + rowSpan] - gridInfo.hLines[row]; + + Rectangle componentBounds = component.getBounds(layer); + if (!bounds.contains(componentBounds.x, componentBounds.y)) { + return componentBounds; + } + + return bounds; + } +} \ No newline at end of file diff --git a/plugins/android-designer/src/com/intellij/android/designer/model/layout/grid/RadGridLayout.java b/plugins/android-designer/src/com/intellij/android/designer/model/layout/grid/RadGridLayout.java index 929ea19cfb2c..0afcc41a4dd5 100644 --- a/plugins/android-designer/src/com/intellij/android/designer/model/layout/grid/RadGridLayout.java +++ b/plugins/android-designer/src/com/intellij/android/designer/model/layout/grid/RadGridLayout.java @@ -17,11 +17,13 @@ package com.intellij.android.designer.model.layout.grid; import com.intellij.android.designer.designSurface.TreeDropToOperation; import com.intellij.android.designer.designSurface.layout.GridLayoutOperation; +import com.intellij.android.designer.designSurface.layout.actions.GridLayoutSpanOperation; import com.intellij.android.designer.designSurface.layout.actions.LayoutSpanOperation; import com.intellij.android.designer.designSurface.layout.actions.ResizeOperation; import com.intellij.android.designer.designSurface.layout.caption.GridHorizontalCaptionOperation; import com.intellij.android.designer.designSurface.layout.caption.GridVerticalCaptionOperation; import com.intellij.android.designer.designSurface.layout.grid.GridDecorator; +import com.intellij.android.designer.designSurface.layout.grid.GridSelectionDecorator; import com.intellij.android.designer.model.RadViewLayout; import com.intellij.android.designer.model.RadViewLayoutWithData; import com.intellij.android.designer.model.grid.GridInfo; @@ -29,7 +31,6 @@ import com.intellij.android.designer.model.layout.actions.AllGravityAction; import com.intellij.android.designer.model.layout.actions.OrientationAction; import com.intellij.designer.componentTree.TreeEditOperation; import com.intellij.designer.designSurface.*; -import com.intellij.designer.designSurface.selection.ResizeSelectionDecorator; import com.intellij.designer.model.RadComponent; import com.intellij.designer.model.RadLayout; import com.intellij.openapi.actionSystem.DefaultActionGroup; @@ -49,7 +50,7 @@ public class RadGridLayout extends RadViewLayoutWithData implements ILayoutDecor private static final String[] LAYOUT_PARAMS = {"GridLayout_Layout", "ViewGroup_MarginLayout"}; private GridDecorator myGridDecorator; - private ResizeSelectionDecorator mySelectionDecorator; + private GridSelectionDecorator mySelectionDecorator; @NotNull @Override @@ -72,7 +73,7 @@ public class RadGridLayout extends RadViewLayoutWithData implements ILayoutDecor return new ResizeOperation(context); } if (context.is(LayoutSpanOperation.TYPE)) { - return new LayoutSpanOperation(context); + return new GridLayoutSpanOperation(context, mySelectionDecorator); } return null; } @@ -105,14 +106,24 @@ public class RadGridLayout extends RadViewLayoutWithData implements ILayoutDecor @Override public ComponentDecorator getChildSelectionDecorator(RadComponent component, List selection) { if (mySelectionDecorator == null) { - mySelectionDecorator = new ResizeSelectionDecorator(Color.red, 1); + mySelectionDecorator = new GridSelectionDecorator(Color.red, 1) { + @Override + public Rectangle getCellBounds(Component layer, RadComponent component) { + RadGridLayoutComponent parent = (RadGridLayoutComponent)component.getParent(); + GridInfo gridInfo = parent.getGridInfo(); + Rectangle cellInfo = RadGridLayoutComponent.getCellInfo(component); + + return calculateBounds(layer, gridInfo, parent, component, cellInfo.y, cellInfo.x, cellInfo.height, cellInfo.width); + } + }; } mySelectionDecorator.clear(); if (selection.size() == 1) { - LayoutSpanOperation.gridPoints(mySelectionDecorator); + GridLayoutSpanOperation.points(mySelectionDecorator); } - ResizeOperation.points(mySelectionDecorator); + ResizeOperation.width(mySelectionDecorator); + ResizeOperation.height(mySelectionDecorator); return mySelectionDecorator; } diff --git a/plugins/android-designer/src/com/intellij/android/designer/model/layout/table/RadTableRowLayout.java b/plugins/android-designer/src/com/intellij/android/designer/model/layout/table/RadTableRowLayout.java index 8c23795b6d6e..3b85798f1587 100644 --- a/plugins/android-designer/src/com/intellij/android/designer/model/layout/table/RadTableRowLayout.java +++ b/plugins/android-designer/src/com/intellij/android/designer/model/layout/table/RadTableRowLayout.java @@ -16,12 +16,15 @@ package com.intellij.android.designer.model.layout.table; import com.intellij.android.designer.designSurface.layout.actions.LayoutSpanOperation; -import com.intellij.android.designer.model.layout.actions.AllGravityAction; +import com.intellij.android.designer.designSurface.layout.actions.TableLayoutSpanOperation; +import com.intellij.android.designer.designSurface.layout.grid.GridSelectionDecorator; +import com.intellij.android.designer.model.grid.GridInfo; import com.intellij.android.designer.model.layout.RadLinearLayout; +import com.intellij.android.designer.model.layout.actions.AllGravityAction; import com.intellij.designer.designSurface.*; -import com.intellij.designer.designSurface.selection.ResizeSelectionDecorator; import com.intellij.designer.model.RadComponent; import com.intellij.openapi.actionSystem.DefaultActionGroup; +import com.intellij.util.ArrayUtil; import org.jetbrains.annotations.NotNull; import javax.swing.*; @@ -34,7 +37,7 @@ import java.util.List; public class RadTableRowLayout extends RadLinearLayout { private static final String[] LAYOUT_PARAMS = {"TableRow_Cell", "LinearLayout_Layout", "ViewGroup_MarginLayout"}; - private ResizeSelectionDecorator mySelectionDecorator; + private GridSelectionDecorator mySelectionDecorator; @Override @NotNull @@ -61,7 +64,7 @@ public class RadTableRowLayout extends RadLinearLayout { return super.processChildOperation(context); } if (context.is(LayoutSpanOperation.TYPE)) { - return new LayoutSpanOperation(context); + return new TableLayoutSpanOperation(context, mySelectionDecorator); } return null; } @@ -77,12 +80,33 @@ public class RadTableRowLayout extends RadLinearLayout { public ComponentDecorator getChildSelectionDecorator(RadComponent component, List selection) { if (isTableParent()) { if (mySelectionDecorator == null) { - mySelectionDecorator = new ResizeSelectionDecorator(Color.red, 1); + mySelectionDecorator = new GridSelectionDecorator(Color.red, 1) { + @Override + public Rectangle getCellBounds(Component layer, RadComponent component) { + RadTableLayoutComponent tableComponent = (RadTableLayoutComponent)component.getParent().getParent(); + GridInfo gridInfo = tableComponent.getVirtualGridInfo(); + int row = tableComponent.getChildren().indexOf(component.getParent()); + RadComponent[] rowComponents = gridInfo.components[row]; + int column = ArrayUtil.indexOf(rowComponents, component); + int columnSpan = 1; + + for (int i = column + 1; i < rowComponents.length; i++) { + if (rowComponents[i] == component) { + columnSpan++; + } + else { + break; + } + } + + return calculateBounds(layer, gridInfo, tableComponent, component, row, column, 1, columnSpan); + } + }; } mySelectionDecorator.clear(); if (selection.size() == 1) { - LayoutSpanOperation.tablePoints(mySelectionDecorator); + TableLayoutSpanOperation.points(mySelectionDecorator); } return mySelectionDecorator; } diff --git a/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/designSurface/selection/DirectionResizePoint.java b/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/designSurface/selection/DirectionResizePoint.java index a5c43bb1ee2d..68652083b873 100644 --- a/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/designSurface/selection/DirectionResizePoint.java +++ b/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/designSurface/selection/DirectionResizePoint.java @@ -95,11 +95,15 @@ public class DirectionResizePoint extends ResizePoint { @Override protected Point getLocation(DecorationLayer layer, RadComponent component) { - Rectangle bounds = component.getBounds(layer); + Rectangle bounds = getBounds(layer, component); int size = (getSize() + 1) / 2; int x = bounds.x + (int)(bounds.width * myXSeparator) - size; int y = bounds.y + (int)(bounds.height * myYSeparator) - size; return new Point(x, y); } + + protected Rectangle getBounds(DecorationLayer layer, RadComponent component) { + return component.getBounds(layer); + } } \ No newline at end of file diff --git a/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/designSurface/selection/NonResizeSelectionDecorator.java b/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/designSurface/selection/NonResizeSelectionDecorator.java index 64f6067d448c..2da90b4daf45 100644 --- a/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/designSurface/selection/NonResizeSelectionDecorator.java +++ b/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/designSurface/selection/NonResizeSelectionDecorator.java @@ -39,7 +39,7 @@ public class NonResizeSelectionDecorator extends ComponentDecorator { @Override public InputTool findTargetTool(DecorationLayer layer, RadComponent component, int x, int y) { - Rectangle bounds = component.getBounds(layer); + Rectangle bounds = getBounds(layer, component); int lineWidth = Math.max(myLineWidth, 2); Rectangle top = new Rectangle(bounds.x, bounds.y, bounds.width, lineWidth); @@ -61,7 +61,11 @@ public class NonResizeSelectionDecorator extends ComponentDecorator { g.setStroke(myStroke); } - Rectangle bounds = component.getBounds(layer); + Rectangle bounds = getBounds(layer, component); g.drawRect(bounds.x, bounds.y, bounds.width, bounds.height); } + + protected Rectangle getBounds(DecorationLayer layer, RadComponent component) { + return component.getBounds(layer); + } } \ No newline at end of file