| /* |
| * 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.android.SdkConstants; |
| import com.intellij.android.designer.designSurface.layout.grid.GridOperation; |
| import com.intellij.android.designer.model.RadComponentOperations; |
| import com.intellij.android.designer.model.RadViewComponent; |
| import com.intellij.android.designer.model.ViewsMetaManager; |
| import com.intellij.android.designer.model.grid.GridInfo; |
| import com.intellij.android.designer.model.grid.GridInsertType; |
| import com.intellij.android.designer.model.layout.table.RadTableLayoutComponent; |
| import com.intellij.android.designer.model.layout.table.RadTableRowLayout; |
| import com.intellij.designer.designSurface.OperationContext; |
| import com.intellij.designer.model.MetaManager; |
| import com.intellij.designer.model.MetaModel; |
| import com.intellij.designer.model.RadComponent; |
| import com.intellij.designer.model.RadComponentVisitor; |
| import com.intellij.util.ArrayUtil; |
| import org.jetbrains.annotations.Nullable; |
| |
| import java.util.List; |
| |
| /** |
| * @author Alexander Lobas |
| */ |
| public class TableLayoutOperation extends GridOperation { |
| public TableLayoutOperation(RadComponent container, OperationContext context) { |
| super(container, context); |
| } |
| |
| @Override |
| protected boolean isMoveOperation() { |
| if (myContext.isPaste() || myContext.isCreate()) { |
| return false; |
| } |
| if (myContext.isMove()) { |
| return true; |
| } |
| |
| final RadComponent editComponent = myContext.getComponents().get(0); |
| final boolean[] move = new boolean[1]; |
| |
| myContainer.accept(new RadComponentVisitor() { |
| @Override |
| public boolean visit(RadComponent component) { |
| if (editComponent == component) { |
| move[0] = true; |
| return false; |
| } |
| |
| return true; |
| } |
| |
| @Override |
| public void endVisit(RadComponent component) { |
| } |
| }, true); |
| |
| return move[0]; |
| } |
| |
| @Override |
| protected int getMovedIndex(boolean row) { |
| RadComponent movedComponent = myContext.getComponents().get(0); |
| List<RadComponent> children = myContainer.getChildren(); |
| |
| if (row) { |
| if (movedComponent.getParent() == myContainer) { |
| return children.indexOf(movedComponent); |
| } |
| return children.indexOf(movedComponent.getParent()); |
| } |
| |
| if (movedComponent.getParent() == myContainer) { |
| return 0; |
| } |
| |
| int columnIndex = RadTableLayoutComponent.getCellIndex(movedComponent); |
| if (columnIndex != -1) { |
| return columnIndex; |
| } |
| |
| int rowIndex = children.indexOf(movedComponent.getParent()); |
| RadComponent[] components = getGridInfo().components[rowIndex]; |
| return ArrayUtil.indexOf(components, movedComponent); |
| } |
| |
| @Override |
| protected boolean isSingleMovedAxis(boolean row) { |
| RadComponent movedComponent = myContext.getComponents().get(0); |
| RadComponent[][] components = getGridInfo().components; |
| |
| if (row) { |
| if (movedComponent.getParent() == myContainer) { |
| return true; |
| } |
| int rowIndex = myContainer.getChildren().indexOf(movedComponent.getParent()); |
| return getSizeInRow(rowIndex, movedComponent) == 0; |
| } |
| else { |
| int columnCount = components[0].length; |
| |
| if (movedComponent.getParent() == myContainer) { |
| return getSizeInColumn(0, columnCount, movedComponent) == 0; |
| } |
| |
| int columnIndex = getMovedIndex(false); |
| int span = RadTableLayoutComponent.getCellSpan(movedComponent); |
| |
| for (int i = 0; i < span; i++) { |
| if (getSizeInColumn(columnIndex + i, columnCount, movedComponent) > 0) { |
| return false; |
| } |
| } |
| } |
| |
| return true; |
| } |
| |
| @Override |
| public boolean canExecute() { |
| RadComponent editComponent = myComponents.get(0); |
| boolean isTableRowElement = SdkConstants.TABLE_ROW.equals(editComponent.getMetaModel().getTag()); |
| |
| if (isTableRowElement && rowExists(getGridInfo().components, myRow)) { |
| // Avoid TableRow being dropped in an existing row. |
| return false; |
| } |
| |
| return super.canExecute(); |
| } |
| |
| @Override |
| public void execute() throws Exception { |
| GridInfo gridInfo = getGridInfo(); |
| |
| RadViewComponent container = (RadViewComponent)myContainer; |
| List<RadComponent> rows = myContainer.getChildren(); |
| RadComponent editComponent = myComponents.get(0); |
| |
| MetaManager metaManager = ViewsMetaManager.getInstance(container.getTag().getProject()); |
| MetaModel tableRowModel = metaManager.getModelByTag(SdkConstants.TABLE_ROW); |
| |
| if (myInsertType == GridInsertType.in_cell) { |
| if (gridInfo.components != null && myRow < gridInfo.components.length) { |
| RadViewComponent rowComponent = (RadViewComponent)rows.get(myRow); |
| if (RadTableRowLayout.is(rowComponent)) { |
| insertInRow(rowComponent, null, true, myColumn + 1, myColumn); |
| } |
| else { |
| convertToTableRowAndExecute(rowComponent, false, tableRowModel, myColumn); |
| } |
| } |
| else { |
| RadViewComponent newRowComponent = null; |
| for (int i = rows.size(); i <= myRow; i++) { |
| newRowComponent = RadComponentOperations.createComponent(null, tableRowModel); |
| RadComponentOperations.addComponent(container, newRowComponent, null); |
| } |
| |
| execute(myContext, newRowComponent, myComponents, null); |
| RadTableLayoutComponent.setCellIndex(editComponent, myColumn); |
| } |
| } |
| else if (myInsertType == GridInsertType.before_h_cell || myInsertType == GridInsertType.after_h_cell) { |
| insertInNewRow(tableRowModel, myInsertType == GridInsertType.before_h_cell, myRow, myColumn); |
| } |
| else if (myInsertType == GridInsertType.before_v_cell || myInsertType == GridInsertType.after_v_cell) { |
| int column = myColumn; |
| if (myInsertType == GridInsertType.after_v_cell) { |
| column++; |
| } |
| |
| shiftColumns(column); |
| |
| RadViewComponent rowComponent = (RadViewComponent)rows.get(myRow); |
| if (RadTableRowLayout.is(rowComponent)) { |
| insertInRow(rowComponent, |
| myInsertType == GridInsertType.before_v_cell ? gridInfo.components[myRow][column] : null, |
| myInsertType == GridInsertType.after_v_cell, |
| column, column); |
| } |
| else { |
| convertToTableRowAndExecute(rowComponent, |
| myInsertType == GridInsertType.before_v_cell, |
| tableRowModel, |
| column); |
| } |
| } |
| else { |
| int column = myColumn; |
| |
| if (myInsertType == GridInsertType.corner_top_right || myInsertType == GridInsertType.corner_bottom_right) { |
| column++; |
| } |
| |
| shiftColumns(column); |
| |
| insertInNewRow(tableRowModel, |
| myInsertType == GridInsertType.corner_top_left || myInsertType == GridInsertType.corner_top_right, |
| myRow, column); |
| } |
| } |
| |
| private void insertInRow(RadViewComponent rowComponent, |
| @Nullable RadComponent insertBefore, |
| boolean calculateInsert, |
| int startColumn, |
| int column) throws Exception { |
| if (calculateInsert) { |
| GridInfo gridInfo = getGridInfo(); |
| RadComponent[] rowComponents = gridInfo.components[myRow]; |
| |
| for (int i = startColumn; i < rowComponents.length; i++) { |
| insertBefore = rowComponents[i]; |
| if (insertBefore != null) { |
| break; |
| } |
| } |
| } |
| |
| RadComponent editComponent = myComponents.get(0); |
| if (editComponent != insertBefore) { |
| execute(myContext, rowComponent, myComponents, (RadViewComponent)insertBefore); |
| } |
| |
| RadTableLayoutComponent.setCellIndex(editComponent, column); |
| } |
| |
| private void insertInNewRow(MetaModel tableRowModel, boolean before, int row, int column) throws Exception { |
| List<RadComponent> rows = myContainer.getChildren(); |
| RadComponent insertBefore = null; |
| |
| if (before) { |
| insertBefore = rows.get(row); |
| } |
| else if (row + 1 < rows.size()) { |
| insertBefore = rows.get(row + 1); |
| } |
| |
| RadViewComponent newRowComponent = RadComponentOperations.createComponent(null, tableRowModel); |
| RadComponentOperations.addComponent((RadViewComponent)myContainer, newRowComponent, (RadViewComponent)insertBefore); |
| |
| execute(myContext, newRowComponent, myComponents, null); |
| RadTableLayoutComponent.setCellIndex(myComponents.get(0), column); |
| } |
| |
| private void convertToTableRowAndExecute(RadViewComponent rowComponent, |
| boolean insertBefore, |
| MetaModel tableRowModel, |
| int column) |
| throws Exception { |
| RadViewComponent newRowComponent = RadComponentOperations.createComponent(null, tableRowModel); |
| RadComponentOperations.addComponent((RadViewComponent)myContainer, newRowComponent, rowComponent); |
| RadComponentOperations.moveComponent(newRowComponent, rowComponent, null); |
| |
| RadComponent editComponent = myComponents.get(0); |
| if (!insertBefore || editComponent != rowComponent) { |
| execute(myContext, newRowComponent, myComponents, insertBefore ? rowComponent : null); |
| } |
| |
| if (column > 1) { |
| RadTableLayoutComponent.setCellIndex(editComponent, column); |
| } |
| } |
| |
| private void shiftColumns(int startColumn) { |
| List<RadComponent> rows = myContainer.getChildren(); |
| RadComponent[][] components = getGridInfo().components; |
| |
| for (int i = 0; i < components.length; i++) { |
| if (RadTableRowLayout.is(rows.get(i))) { |
| RadComponent[] rowComponents = components[i]; |
| |
| for (int j = startColumn; j < rowComponents.length; j++) { |
| RadComponent cellComponent = rowComponents[j]; |
| |
| if (cellComponent != null) { |
| if (j == startColumn && startColumn > 0 && cellComponent == rowComponents[j - 1]) { |
| RadTableLayoutComponent.setCellSpan(cellComponent, RadTableLayoutComponent.getCellSpan(cellComponent) + 1); |
| } |
| else { |
| RadTableLayoutComponent.setCellIndex(cellComponent, j + 1); |
| } |
| |
| while (j + 1 < rowComponents.length && cellComponent == rowComponents[j + 1]) { |
| j++; |
| } |
| } |
| } |
| } |
| } |
| } |
| } |