GridLayout

This commit is contained in:
Alexander Lobas
2012-04-24 15:47:50 +04:00
parent 594dae3709
commit 41df6e04bf
8 changed files with 466 additions and 349 deletions
@@ -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
}
}
@@ -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);
}
}
}
}
}
@@ -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,
@@ -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);
}
}
}
}
}
@@ -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;
}
}
@@ -20,4 +20,6 @@ package com.intellij.android.designer.model.agrid;
*/
public interface IGridProvider {
GridInfo getGridInfo();
GridInfo getVirtualGridInfo();
}
@@ -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;
}
}
@@ -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<RadComponent> 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<RadComponent> 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