From 41df6e04bf00877f423eace568171ce02253c1b9 Mon Sep 17 00:00:00 2001 From: Alexander Lobas Date: Tue, 24 Apr 2012 15:47:50 +0400 Subject: [PATCH] GridLayout --- .../layout/GridLayoutOperation.java | 10 +- .../designSurface/layout/GridOperation.java | 348 ++++++++++++++++++ .../layout/LayoutSpanOperation.java | 13 - .../layout/TableLayoutOperation.java | 297 +-------------- .../designer/model/agrid/GridInfo.java | 28 ++ .../designer/model/agrid/IGridProvider.java | 2 + .../model/grid/RadGridLayoutComponent.java | 81 ++++ .../model/table/RadTableLayoutComponent.java | 36 +- 8 files changed, 466 insertions(+), 349 deletions(-) create mode 100644 plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/GridOperation.java diff --git a/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/GridLayoutOperation.java b/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/GridLayoutOperation.java index baa2bfe7b573..45c2cf373dfd 100644 --- a/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/GridLayoutOperation.java +++ b/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/GridLayoutOperation.java @@ -15,25 +15,19 @@ */ package com.intellij.android.designer.designSurface.layout; -import com.intellij.android.designer.designSurface.AbstractEditOperation; import com.intellij.designer.designSurface.OperationContext; import com.intellij.designer.model.RadComponent; /** * @author Alexander Lobas */ -public class GridLayoutOperation extends AbstractEditOperation { +public class GridLayoutOperation extends GridOperation { public GridLayoutOperation(RadComponent container, OperationContext context) { super(container, context); } @Override - public void showFeedback() { - // TODO: Auto-generated method stub - } - - @Override - public void eraseFeedback() { + public void execute() throws Exception { // TODO: Auto-generated method stub } } \ No newline at end of file diff --git a/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/GridOperation.java b/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/GridOperation.java new file mode 100644 index 000000000000..ea799d5d2f80 --- /dev/null +++ b/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/GridOperation.java @@ -0,0 +1,348 @@ +/* + * 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; + +import com.intellij.android.designer.designSurface.AbstractEditOperation; +import com.intellij.android.designer.model.agrid.GridInfo; +import com.intellij.android.designer.model.agrid.GridInsertType; +import com.intellij.android.designer.model.agrid.IGridProvider; +import com.intellij.designer.designSurface.FeedbackLayer; +import com.intellij.designer.designSurface.OperationContext; +import com.intellij.designer.designSurface.feedbacks.AlphaFeedback; +import com.intellij.designer.designSurface.feedbacks.InsertFeedback; +import com.intellij.designer.designSurface.feedbacks.TextFeedback; +import com.intellij.designer.model.RadComponent; +import com.intellij.ui.IdeBorderFactory; + +import javax.swing.*; +import java.awt.*; + +/** + * @author Alexander Lobas + */ +public abstract class GridOperation extends AbstractEditOperation { + private GridFeedback myFeedback; + private InsertFeedback myInsertFeedback; + private TextFeedback myTextFeedback; + private Rectangle myBounds; + protected int myColumn; + protected int myRow; + protected GridInsertType myInsertType; + protected boolean myExist; + + public GridOperation(RadComponent container, OperationContext context) { + super(container, context); + } + + protected final GridInfo getGridInfo() { + return ((IGridProvider)myContainer).getVirtualGridInfo(); + } + + private void createFeedback() { + if (myFeedback == null) { + FeedbackLayer layer = myContext.getArea().getFeedbackLayer(); + + myInsertFeedback = new InsertFeedback(Color.green); + layer.add(myInsertFeedback); + + myBounds = myContainer.getBounds(layer); + + myFeedback = new GridFeedback(); + myFeedback.setBounds(myBounds); + layer.add(myFeedback); + + myTextFeedback = new TextFeedback(); + myTextFeedback.setBorder(IdeBorderFactory.createEmptyBorder(0, 3, 2, 0)); + layer.add(myTextFeedback); + + layer.repaint(); + } + } + + @Override + public void showFeedback() { + createFeedback(); + calculateGridInfo(); + configureTextFeedback(); + myFeedback.repaint(); + } + + private void configureTextFeedback() { + myTextFeedback.clear(); + + int row = myRow; + int column = myColumn; + + myTextFeedback.append("["); + + if (myInsertType == GridInsertType.before_h_cell) { + myTextFeedback.append("before "); + } + else if (myInsertType == GridInsertType.after_h_cell) { + myTextFeedback.append("after "); + } + else if (myInsertType != GridInsertType.in_cell) { + myTextFeedback.append("insert: "); + + if (myInsertType == GridInsertType.corner_top_right) { + column++; + } + else if (myInsertType == GridInsertType.corner_bottom_left) { + row++; + } + else if (myInsertType == GridInsertType.corner_bottom_right) { + row++; + column++; + } + } + + myTextFeedback.append("row "); + myTextFeedback.bold(Integer.toString(row)); + myTextFeedback.append(", "); + + if (myInsertType == GridInsertType.before_v_cell) { + myTextFeedback.append("before "); + } + else if (myInsertType == GridInsertType.after_v_cell) { + myTextFeedback.append("after "); + } + + myTextFeedback.append("column "); + myTextFeedback.bold(Integer.toString(column)); + myTextFeedback.append("]"); + + myTextFeedback.centerTop(myBounds); + } + + @Override + public void eraseFeedback() { + if (myFeedback != null) { + FeedbackLayer layer = myContext.getArea().getFeedbackLayer(); + layer.remove(myInsertFeedback); + layer.remove(myFeedback); + layer.remove(myTextFeedback); + layer.repaint(); + myFeedback = null; + myInsertFeedback = null; + myTextFeedback = null; + } + } + + @Override + public boolean canExecute() { + return myComponents.size() == 1 && (myInsertType != GridInsertType.in_cell || !myExist); + } + + @Override + public abstract void execute() throws Exception; + + private static final int CROSS_SIZE = 10; + + private void calculateGridInfo() { + GridInfo gridInfo = getGridInfo(); + Point location = SwingUtilities.convertPoint(myContext.getArea().getFeedbackLayer(), myContext.getLocation(), myFeedback); + + myColumn = getLineIndex(gridInfo.vLines, location.x); + myRow = getLineIndex(gridInfo.hLines, location.y); + + if (gridInfo.components == null) { + myInsertType = GridInsertType.in_cell; + myExist = false; + } + else { + myExist = isExist(myRow, myColumn); + myInsertType = GridInsertType.in_cell; + + Rectangle cellRect = getInsertRect(myExist); + Rectangle inCellRect = getInsertInRect(cellRect); + boolean isExistCell = gridInfo.components != null && myRow < gridInfo.components.length && myColumn < gridInfo.components[0].length; + + if (!inCellRect.contains(location)) { + if (location.x <= inCellRect.x) { + if (location.y <= inCellRect.y) { + if (isExistCell) { + myInsertType = GridInsertType.corner_top_left; + myInsertFeedback.cross(myBounds.x + cellRect.x, myBounds.y + cellRect.y, CROSS_SIZE); + } + } + else if (inCellRect.y < location.y && location.y < inCellRect.getMaxY()) { + if (myExist && (myColumn == 0 || isExist(myRow, myColumn - 1))) { + myInsertType = GridInsertType.before_v_cell; + myInsertFeedback.vertical(myBounds.x + cellRect.x, myBounds.y + cellRect.y, cellRect.height); + } + } + else if (isExistCell) { + myInsertType = GridInsertType.corner_bottom_left; + myInsertFeedback.cross(myBounds.x + cellRect.x, myBounds.y + cellRect.y + cellRect.height, CROSS_SIZE); + } + } + else if (location.x >= inCellRect.getMaxX()) { + if (location.y <= inCellRect.y) { + if (isExistCell) { + myInsertType = GridInsertType.corner_top_right; + myInsertFeedback.cross(myBounds.x + cellRect.x + cellRect.width, myBounds.y + cellRect.y, CROSS_SIZE); + } + } + else if (inCellRect.y < location.y && location.y < inCellRect.getMaxY()) { + if (myExist && (myColumn == gridInfo.lastColumn || isExist(myRow, myColumn + 1))) { + myInsertType = GridInsertType.after_v_cell; + myInsertFeedback.vertical(myBounds.x + cellRect.x + cellRect.width, myBounds.y + cellRect.y, cellRect.height); + } + } + else if (isExistCell) { + myInsertType = GridInsertType.corner_bottom_right; + myInsertFeedback.cross(myBounds.x + cellRect.x + cellRect.width, myBounds.y + cellRect.y + cellRect.height, CROSS_SIZE); + } + } + else if (location.y <= inCellRect.y) { + if (myExist && (myRow == 0 || isExist(myRow - 1, myColumn))) { + myInsertType = GridInsertType.before_h_cell; + cellRect = getInsertRect(false); + myInsertFeedback.horizontal(myBounds.x + cellRect.x, myBounds.y + cellRect.y, cellRect.width); + } + } + else if (location.y >= inCellRect.getMaxY()) { + if (myExist && (myRow == gridInfo.lastRow || isExist(myRow + 1, myColumn))) { + myInsertType = GridInsertType.after_h_cell; + cellRect = getInsertRect(false); + myInsertFeedback.horizontal(myBounds.x + cellRect.x, myBounds.y + cellRect.y + cellRect.height, cellRect.width); + } + } + } + } + + if (myInsertType == GridInsertType.in_cell) { + myInsertFeedback.setVisible(false); + } + } + + private static int getLineIndex(int[] line, int location) { + for (int i = 0; i < line.length - 1; i++) { + if (line[i] <= location && location <= line[i + 1]) { + return i; + } + } + return Math.max(0, line.length - 1); + } + + private boolean isExist(int row, int column) { + RadComponent[][] components = getGridInfo().components; + if (components != null && + 0 <= row && row < components.length && + 0 <= column && column < components[0].length) { + return components[row][column] != null; + } + return false; + } + + private Rectangle getInsertRect(boolean includeSpans) { + GridInfo gridInfo = getGridInfo(); + int startColumn = myColumn; + int endColumn = myColumn + 1; + int startRow = myRow; + int endRow = myRow + 1; + + if (includeSpans) { + RadComponent[] columnComponents = gridInfo.components[myRow]; + RadComponent existComponent = columnComponents[startColumn]; + + while (startColumn > 0) { + if (columnComponents[startColumn - 1] == existComponent) { + startColumn--; + } + else { + break; + } + } + while (endColumn < columnComponents.length) { + if (columnComponents[endColumn] == existComponent) { + endColumn++; + } + else { + break; + } + } + + while (startRow > 0) { + if (gridInfo.components[startRow - 1][startColumn] == existComponent) { + startRow--; + } + else { + break; + } + } + while (endRow < gridInfo.components.length) { + if (gridInfo.components[endRow][startColumn] == existComponent) { + endRow++; + } + else { + break; + } + } + } + + int x1 = startColumn < gridInfo.vLines.length ? gridInfo.vLines[startColumn] : 0; + int x2 = endColumn < gridInfo.vLines.length ? gridInfo.vLines[endColumn] : gridInfo.width; + + int y1 = startRow < gridInfo.hLines.length ? gridInfo.hLines[startRow] : 0; + int y2 = endRow < gridInfo.hLines.length ? gridInfo.hLines[endRow] : gridInfo.height; + + return new Rectangle(x1, y1, x2 - x1, y2 - y1); + } + + private static Rectangle getInsertInRect(Rectangle cellRect) { + int borderWidth = Math.min(cellRect.width / 3, 10); + int borderHeight = Math.min(cellRect.height / 3, 10); + return new Rectangle(cellRect.x + borderWidth, cellRect.y + borderHeight, cellRect.width - 2 * borderWidth, + cellRect.height - 2 * borderHeight); + } + + ////////////////////////////////////////////////////////////////////////////////////////// + // + // Feedback + // + ////////////////////////////////////////////////////////////////////////////////////////// + + private class GridFeedback extends JComponent { + @Override + protected void paintComponent(Graphics g) { + super.paintComponent(g); + g.setColor(BorderStaticDecorator.COLOR); + + GridInfo gridInfo = getGridInfo(); + + for (int x : gridInfo.vLines) { + g.drawLine(x, 0, x, gridInfo.height); + } + for (int y : gridInfo.hLines) { + g.drawLine(0, y, gridInfo.width, y); + } + g.drawRect(0, 0, gridInfo.width - 1, gridInfo.height - 1); + g.drawRect(1, 1, gridInfo.width - 3, gridInfo.height - 3); + + if (myInsertType == GridInsertType.in_cell) { + Rectangle cellRect = getInsertRect(myExist); + + if (myExist) { + AlphaFeedback.fillRect2(g, cellRect.x, cellRect.y, cellRect.width, cellRect.height, Color.pink); + } + else { + AlphaFeedback.fillRect1(g, cellRect.x, cellRect.y, cellRect.width, cellRect.height, Color.green); + } + } + } + } +} \ No newline at end of file diff --git a/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/LayoutSpanOperation.java b/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/LayoutSpanOperation.java index 6595a295b589..1672f8528781 100644 --- a/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/LayoutSpanOperation.java +++ b/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/LayoutSpanOperation.java @@ -19,7 +19,6 @@ import com.intellij.android.designer.model.ModelParser; import com.intellij.android.designer.model.RadViewComponent; import com.intellij.android.designer.model.agrid.GridInfo; import com.intellij.android.designer.model.table.RadTableLayoutComponent; -import com.intellij.designer.designSurface.DecorationLayer; import com.intellij.designer.designSurface.EditOperation; import com.intellij.designer.designSurface.FeedbackLayer; import com.intellij.designer.designSurface.OperationContext; @@ -27,7 +26,6 @@ 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.EmptyPoint; import com.intellij.designer.designSurface.selection.ResizeSelectionDecorator; import com.intellij.designer.model.RadComponent; import com.intellij.designer.utils.Position; @@ -267,17 +265,6 @@ public class LayoutSpanOperation implements EditOperation { } public static void gridPoints(ResizeSelectionDecorator decorator) { - decorator.addPoint(new EmptyPoint() { - @Override - protected void paint(DecorationLayer layer, Graphics2D g, RadComponent component) { - Rectangle bounds = component.getBounds(layer); - - g.setStroke(LayoutMarginOperation.STROKE); - g.setColor(COLOR); - g.drawRect(bounds.x, bounds.y, bounds.width, bounds.height); - } - }); - decorator.addPoint(new DirectionResizePoint(COLOR, Color.black, Position.WEST, diff --git a/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/TableLayoutOperation.java b/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/TableLayoutOperation.java index da860f0edd0b..686bf2460137 100644 --- a/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/TableLayoutOperation.java +++ b/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/TableLayoutOperation.java @@ -15,7 +15,6 @@ */ package com.intellij.android.designer.designSurface.layout; -import com.intellij.android.designer.designSurface.AbstractEditOperation; import com.intellij.android.designer.model.ModelParser; import com.intellij.android.designer.model.RadViewComponent; import com.intellij.android.designer.model.ViewsMetaManager; @@ -23,280 +22,22 @@ import com.intellij.android.designer.model.agrid.GridInfo; import com.intellij.android.designer.model.agrid.GridInsertType; import com.intellij.android.designer.model.table.RadTableLayoutComponent; import com.intellij.android.designer.model.table.RadTableRowLayout; -import com.intellij.designer.designSurface.FeedbackLayer; import com.intellij.designer.designSurface.OperationContext; -import com.intellij.designer.designSurface.feedbacks.AlphaFeedback; -import com.intellij.designer.designSurface.feedbacks.InsertFeedback; -import com.intellij.designer.designSurface.feedbacks.TextFeedback; import com.intellij.designer.model.MetaManager; import com.intellij.designer.model.MetaModel; import com.intellij.designer.model.RadComponent; -import com.intellij.ui.IdeBorderFactory; import org.jetbrains.annotations.Nullable; -import javax.swing.*; -import java.awt.*; import java.util.List; /** * @author Alexander Lobas */ -public class TableLayoutOperation extends AbstractEditOperation { - private static final int CROSS_SIZE = 10; - - private GridFeedback myFeedback; - private InsertFeedback myInsertFeedback; - private TextFeedback myTextFeedback; - private Rectangle myBounds; - private int myColumn; - private int myRow; - private GridInsertType myInsertType; - private boolean myExist; - +public class TableLayoutOperation extends GridOperation { public TableLayoutOperation(RadComponent container, OperationContext context) { super(container, context); } - private GridInfo getGridInfo() { - return ((RadTableLayoutComponent)myContainer).getVirtualGridInfo(); - } - - private void createFeedback() { - if (myFeedback == null) { - FeedbackLayer layer = myContext.getArea().getFeedbackLayer(); - - myInsertFeedback = new InsertFeedback(Color.green); - layer.add(myInsertFeedback); - - myBounds = myContainer.getBounds(layer); - - myFeedback = new GridFeedback(); - myFeedback.setBounds(myBounds); - layer.add(myFeedback); - - myTextFeedback = new TextFeedback(); - myTextFeedback.setBorder(IdeBorderFactory.createEmptyBorder(0, 3, 2, 0)); - layer.add(myTextFeedback); - - layer.repaint(); - } - } - - @Override - public void showFeedback() { - createFeedback(); - calculateGridInfo(); - configureTextFeedback(); - myFeedback.repaint(); - } - - private void configureTextFeedback() { - myTextFeedback.clear(); - - int row = myRow; - int column = myColumn; - - myTextFeedback.append("["); - - if (myInsertType == GridInsertType.before_h_cell) { - myTextFeedback.append("before "); - } - else if (myInsertType == GridInsertType.after_h_cell) { - myTextFeedback.append("after "); - } - else if (myInsertType != GridInsertType.in_cell) { - myTextFeedback.append("insert: "); - - if (myInsertType == GridInsertType.corner_top_right) { - column++; - } - else if (myInsertType == GridInsertType.corner_bottom_left) { - row++; - } - else if (myInsertType == GridInsertType.corner_bottom_right) { - row++; - column++; - } - } - - myTextFeedback.append("row "); - myTextFeedback.bold(Integer.toString(row)); - myTextFeedback.append(", "); - - if (myInsertType == GridInsertType.before_v_cell) { - myTextFeedback.append("before "); - } - else if (myInsertType == GridInsertType.after_v_cell) { - myTextFeedback.append("after "); - } - - myTextFeedback.append("column "); - myTextFeedback.bold(Integer.toString(column)); - myTextFeedback.append("]"); - - myTextFeedback.centerTop(myBounds); - } - - @Override - public void eraseFeedback() { - if (myFeedback != null) { - FeedbackLayer layer = myContext.getArea().getFeedbackLayer(); - layer.remove(myInsertFeedback); - layer.remove(myFeedback); - layer.remove(myTextFeedback); - layer.repaint(); - myFeedback = null; - myInsertFeedback = null; - myTextFeedback = null; - } - } - - private void calculateGridInfo() { - GridInfo gridInfo = getGridInfo(); - Point location = SwingUtilities.convertPoint(myContext.getArea().getFeedbackLayer(), myContext.getLocation(), myFeedback); - - myColumn = getLineIndex(gridInfo.vLines, location.x); - myRow = getLineIndex(gridInfo.hLines, location.y); - - if (gridInfo.components == null) { - myInsertType = GridInsertType.in_cell; - myExist = false; - } - else { - myExist = isExist(myRow, myColumn); - myInsertType = GridInsertType.in_cell; - - Rectangle cellRect = getInsertRect(myExist); - Rectangle inCellRect = getInsertInRect(cellRect); - boolean isExistCell = gridInfo.components != null && myRow < gridInfo.components.length && myColumn < gridInfo.components[0].length; - - if (!inCellRect.contains(location)) { - if (location.x <= inCellRect.x) { - if (location.y <= inCellRect.y) { - if (isExistCell) { - myInsertType = GridInsertType.corner_top_left; - myInsertFeedback.cross(myBounds.x + cellRect.x, myBounds.y + cellRect.y, CROSS_SIZE); - } - } - else if (inCellRect.y < location.y && location.y < inCellRect.getMaxY()) { - if (myExist && (myColumn == 0 || isExist(myRow, myColumn - 1))) { - myInsertType = GridInsertType.before_v_cell; - myInsertFeedback.vertical(myBounds.x + cellRect.x, myBounds.y + cellRect.y, cellRect.height); - } - } - else if (isExistCell) { - myInsertType = GridInsertType.corner_bottom_left; - myInsertFeedback.cross(myBounds.x + cellRect.x, myBounds.y + cellRect.y + cellRect.height, CROSS_SIZE); - } - } - else if (location.x >= inCellRect.getMaxX()) { - if (location.y <= inCellRect.y) { - if (isExistCell) { - myInsertType = GridInsertType.corner_top_right; - myInsertFeedback.cross(myBounds.x + cellRect.x + cellRect.width, myBounds.y + cellRect.y, CROSS_SIZE); - } - } - else if (inCellRect.y < location.y && location.y < inCellRect.getMaxY()) { - if (myExist && (myColumn == gridInfo.lastColumn || isExist(myRow, myColumn + 1))) { - myInsertType = GridInsertType.after_v_cell; - myInsertFeedback.vertical(myBounds.x + cellRect.x + cellRect.width, myBounds.y + cellRect.y, cellRect.height); - } - } - else if (isExistCell) { - myInsertType = GridInsertType.corner_bottom_right; - myInsertFeedback.cross(myBounds.x + cellRect.x + cellRect.width, myBounds.y + cellRect.y + cellRect.height, CROSS_SIZE); - } - } - else if (location.y <= inCellRect.y) { - if (myExist && (myRow == 0 || isExist(myRow - 1, myColumn))) { - myInsertType = GridInsertType.before_h_cell; - cellRect = getInsertRect(false); - myInsertFeedback.horizontal(myBounds.x + cellRect.x, myBounds.y + cellRect.y, cellRect.width); - } - } - else if (location.y >= inCellRect.getMaxY()) { - if (myExist && (myRow == gridInfo.lastRow || isExist(myRow + 1, myColumn))) { - myInsertType = GridInsertType.after_h_cell; - cellRect = getInsertRect(false); - myInsertFeedback.horizontal(myBounds.x + cellRect.x, myBounds.y + cellRect.y + cellRect.height, cellRect.width); - } - } - } - } - - if (myInsertType == GridInsertType.in_cell) { - myInsertFeedback.setVisible(false); - } - } - - private static int getLineIndex(int[] line, int location) { - for (int i = 0; i < line.length - 1; i++) { - if (line[i] <= location && location <= line[i + 1]) { - return i; - } - } - return Math.max(0, line.length - 1); - } - - private boolean isExist(int row, int column) { - RadComponent[][] components = getGridInfo().components; - if (components != null && - 0 <= row && row < components.length && - 0 <= column && column < components[0].length) { - return components[row][column] != null; - } - return false; - } - - private Rectangle getInsertRect(boolean includeSpan) { - GridInfo gridInfo = getGridInfo(); - int startColumn = myColumn; - int endColumn = myColumn + 1; - - if (includeSpan) { - RadComponent[] columnComponents = gridInfo.components[myRow]; - RadComponent existComponent = columnComponents[startColumn]; - - while (startColumn > 0) { - if (columnComponents[startColumn - 1] == existComponent) { - startColumn--; - } - else { - break; - } - } - - while (endColumn < columnComponents.length) { - if (columnComponents[endColumn] == existComponent) { - endColumn++; - } - else { - break; - } - } - } - - int x1 = startColumn < gridInfo.vLines.length ? gridInfo.vLines[startColumn] : 0; - int x2 = endColumn < gridInfo.vLines.length ? gridInfo.vLines[endColumn] : gridInfo.width; - - int y1 = myRow < gridInfo.hLines.length ? gridInfo.hLines[myRow] : 0; - int y2 = myRow + 1 < gridInfo.hLines.length ? gridInfo.hLines[myRow + 1] : gridInfo.height; - - return new Rectangle(x1, y1, x2 - x1, y2 - y1); - } - - private static Rectangle getInsertInRect(Rectangle cellRect) { - int borderWidth = Math.min(cellRect.width / 3, 10); - int borderHeight = Math.min(cellRect.height / 3, 10); - return new Rectangle(cellRect.x + borderWidth, cellRect.y + borderHeight, cellRect.width - 2 * borderWidth, - cellRect.height - 2 * borderHeight); - } - - @Override - public boolean canExecute() { - return myComponents.size() == 1 && (myInsertType != GridInsertType.in_cell || !myExist); - } - @Override public void execute() throws Exception { GridInfo gridInfo = getGridInfo(); @@ -448,40 +189,4 @@ public class TableLayoutOperation extends AbstractEditOperation { } } } - - ////////////////////////////////////////////////////////////////////////////////////////// - // - // Feedback - // - ////////////////////////////////////////////////////////////////////////////////////////// - - private class GridFeedback extends JComponent { - @Override - protected void paintComponent(Graphics g) { - super.paintComponent(g); - g.setColor(BorderStaticDecorator.COLOR); - - GridInfo gridInfo = getGridInfo(); - - for (int x : gridInfo.vLines) { - g.drawLine(x, 0, x, gridInfo.height); - } - for (int y : gridInfo.hLines) { - g.drawLine(0, y, gridInfo.width, y); - } - g.drawRect(0, 0, gridInfo.width - 1, gridInfo.height - 1); - g.drawRect(1, 1, gridInfo.width - 3, gridInfo.height - 3); - - if (myInsertType == GridInsertType.in_cell) { - Rectangle cellRect = getInsertRect(myExist); - - if (myExist) { - AlphaFeedback.fillRect2(g, cellRect.x, cellRect.y, cellRect.width, cellRect.height, Color.pink); - } - else { - AlphaFeedback.fillRect1(g, cellRect.x, cellRect.y, cellRect.width, cellRect.height, Color.green); - } - } - } - } } \ No newline at end of file diff --git a/plugins/android-designer/src/com/intellij/android/designer/model/agrid/GridInfo.java b/plugins/android-designer/src/com/intellij/android/designer/model/agrid/GridInfo.java index a3e31a5541fe..4ac7bbc9f6cd 100644 --- a/plugins/android-designer/src/com/intellij/android/designer/model/agrid/GridInfo.java +++ b/plugins/android-designer/src/com/intellij/android/designer/model/agrid/GridInfo.java @@ -32,4 +32,32 @@ public class GridInfo { public RadComponent[][] components; public int lastRow = -1; public int lastColumn = -1; + + private static final int NEW_CELL_SIZE = 32; + + public static int[] addLineInfo(int[] oldLines, int delta) { + if (delta > 0) { + int newLength = oldLines.length + delta / NEW_CELL_SIZE; + + if (newLength > oldLines.length) { + int[] newLines = new int[newLength]; + int startIndex = oldLines.length; + + if (oldLines.length > 0) { + System.arraycopy(oldLines, 0, newLines, 0, oldLines.length); + } + else { + startIndex = 1; + } + + for (int i = startIndex; i < newLength; i++) { + newLines[i] = newLines[i - 1] + NEW_CELL_SIZE; + } + + return newLines; + } + return oldLines; + } + return oldLines; + } } \ No newline at end of file diff --git a/plugins/android-designer/src/com/intellij/android/designer/model/agrid/IGridProvider.java b/plugins/android-designer/src/com/intellij/android/designer/model/agrid/IGridProvider.java index c68d67fc5d67..cf1b97c00cea 100644 --- a/plugins/android-designer/src/com/intellij/android/designer/model/agrid/IGridProvider.java +++ b/plugins/android-designer/src/com/intellij/android/designer/model/agrid/IGridProvider.java @@ -20,4 +20,6 @@ package com.intellij.android.designer.model.agrid; */ public interface IGridProvider { GridInfo getGridInfo(); + + GridInfo getVirtualGridInfo(); } \ No newline at end of file diff --git a/plugins/android-designer/src/com/intellij/android/designer/model/grid/RadGridLayoutComponent.java b/plugins/android-designer/src/com/intellij/android/designer/model/grid/RadGridLayoutComponent.java index d42b79ac0a66..ecb598719528 100644 --- a/plugins/android-designer/src/com/intellij/android/designer/model/grid/RadGridLayoutComponent.java +++ b/plugins/android-designer/src/com/intellij/android/designer/model/grid/RadGridLayoutComponent.java @@ -16,6 +16,7 @@ package com.intellij.android.designer.model.grid; import com.android.ide.common.rendering.api.ViewInfo; +import com.intellij.android.designer.model.RadViewComponent; import com.intellij.android.designer.model.RadViewContainer; import com.intellij.android.designer.model.agrid.GridInfo; import com.intellij.android.designer.model.agrid.IGridProvider; @@ -30,11 +31,13 @@ import java.lang.reflect.Method; */ public class RadGridLayoutComponent extends RadViewContainer implements IGridProvider { private GridInfo myGridInfo; + private GridInfo myVirtualGridInfo; @Override public void setViewInfo(ViewInfo viewInfo) { super.setViewInfo(viewInfo); myGridInfo = null; + myVirtualGridInfo = null; } @Override @@ -89,4 +92,82 @@ public class RadGridLayoutComponent extends RadViewContainer implements IGridPro } return myGridInfo; } + + @Override + public GridInfo getVirtualGridInfo() { + if (myVirtualGridInfo == null) { + myVirtualGridInfo = new GridInfo(); + GridInfo gridInfo = getGridInfo(); + Rectangle bounds = getBounds(); + + myVirtualGridInfo.lastColumn = gridInfo.lastColumn; + myVirtualGridInfo.lastRow = gridInfo.lastRow; + + myVirtualGridInfo.width = bounds.width; + myVirtualGridInfo.height = bounds.height; + + myVirtualGridInfo.vLines = GridInfo.addLineInfo(gridInfo.vLines, bounds.width - gridInfo.width); + myVirtualGridInfo.hLines = GridInfo.addLineInfo(gridInfo.hLines, bounds.height - gridInfo.height); + + myVirtualGridInfo.components = getGridComponents(true); + } + + return myVirtualGridInfo; + } + + public RadComponent[][] getGridComponents(boolean fillSpans) { + GridInfo gridInfo = getGridInfo(); + RadComponent[][] components = new RadComponent[gridInfo.lastRow + 1][gridInfo.lastColumn + 1]; + + for (RadComponent child : getChildren()) { + Rectangle cellInfo = getCellInfo(child); + + if (fillSpans) { + for (int row = 0; row < cellInfo.height; row++) { + for (int column = 0; column < cellInfo.width; column++) { + components[cellInfo.y + row][cellInfo.x + column] = child; + } + } + } + else { + components[cellInfo.y][cellInfo.x] = child; + } + } + + return components; + } + + public static Rectangle getCellInfo(RadComponent component) { + Rectangle cellInfo = new Rectangle(); + + try { + Object layoutParams = ((RadViewComponent)component).getViewInfo().getLayoutParamsObject(); + Class layoutParamsClass = layoutParams.getClass(); + + Object columnSpec = layoutParamsClass.getField("columnSpec").get(layoutParams); + Object rowSpec = layoutParamsClass.getField("rowSpec").get(layoutParams); + + Class class_Spec = columnSpec.getClass(); + Field field_span = class_Spec.getDeclaredField("span"); + field_span.setAccessible(true); + + Object columnSpan = field_span.get(columnSpec); + Object rowSpan = field_span.get(rowSpec); + + Class class_Interval = columnSpan.getClass(); + Field field_min = class_Interval.getField("min"); + field_min.setAccessible(true); + Field field_max = class_Interval.getField("max"); + field_max.setAccessible(true); + + cellInfo.x = field_min.getInt(columnSpan); + cellInfo.y = field_min.getInt(rowSpan); + cellInfo.width = field_max.getInt(columnSpan) - cellInfo.x; + cellInfo.height = field_max.getInt(rowSpan) - cellInfo.y; + } + catch (Throwable e) { + } + + return cellInfo; + } } \ No newline at end of file diff --git a/plugins/android-designer/src/com/intellij/android/designer/model/table/RadTableLayoutComponent.java b/plugins/android-designer/src/com/intellij/android/designer/model/table/RadTableLayoutComponent.java index d6003b8b022e..96686eb9a271 100644 --- a/plugins/android-designer/src/com/intellij/android/designer/model/table/RadTableLayoutComponent.java +++ b/plugins/android-designer/src/com/intellij/android/designer/model/table/RadTableLayoutComponent.java @@ -111,10 +111,10 @@ public class RadTableLayoutComponent extends RadViewContainer implements IGridPr myVirtualGridInfo.height = bounds.height; int deltaWidth = bounds.width - (gridInfo.vLines.length == 0 ? 0 : gridInfo.width); - myVirtualGridInfo.vLines = addLineInfo(gridInfo.vLines, deltaWidth); + myVirtualGridInfo.vLines = GridInfo.addLineInfo(gridInfo.vLines, deltaWidth); int deltaHeight = bounds.height - gridInfo.height; - myVirtualGridInfo.hLines = addLineInfo(gridInfo.hLines, deltaHeight); + myVirtualGridInfo.hLines = GridInfo.addLineInfo(gridInfo.hLines, deltaHeight); List rows = getChildren(); if (!rows.isEmpty()) { @@ -132,7 +132,7 @@ public class RadTableLayoutComponent extends RadViewContainer implements IGridPr return myVirtualGridInfo; } - public RadComponent[][] getGridComponents(boolean useSpan) { + public RadComponent[][] getGridComponents(boolean fillSpans) { GridInfo gridInfo = getGridInfo(); List rows = getChildren(); int columnSize = Math.max(1, gridInfo.vLines.length - 1); @@ -150,7 +150,7 @@ public class RadTableLayoutComponent extends RadViewContainer implements IGridPr } int cellSpan = getCellSpan(column); - if (useSpan) { + if (fillSpans) { for (int j = 0; j < cellSpan; j++) { components[i][index++] = column; } @@ -169,34 +169,6 @@ public class RadTableLayoutComponent extends RadViewContainer implements IGridPr return components; } - private static final int NEW_CELL_SIZE = 32; - - private static int[] addLineInfo(int[] oldLines, int delta) { - if (delta > 0) { - int newLength = oldLines.length + delta / NEW_CELL_SIZE; - - if (newLength > oldLines.length) { - int[] newLines = new int[newLength]; - int startIndex = oldLines.length; - - if (oldLines.length > 0) { - System.arraycopy(oldLines, 0, newLines, 0, oldLines.length); - } - else { - startIndex = 1; - } - - for (int i = startIndex; i < newLength; i++) { - newLines[i] = newLines[i - 1] + NEW_CELL_SIZE; - } - - return newLines; - } - return oldLines; - } - return oldLines; - } - public static void setCellIndex(final RadComponent component, final int column) { ApplicationManager.getApplication().runWriteAction(new Runnable() { @Override