/* * 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.model.layout.table; import com.android.SdkConstants; import com.android.ide.common.rendering.api.ViewInfo; import com.intellij.android.designer.model.RadComponentOperations; import com.intellij.android.designer.model.RadViewComponent; import com.intellij.android.designer.model.RadViewContainer; import com.intellij.android.designer.model.grid.GridInfo; import com.intellij.android.designer.model.grid.IGridProvider; import com.intellij.designer.model.RadComponent; import com.intellij.openapi.application.ApplicationManager; import com.intellij.psi.xml.XmlTag; import com.intellij.util.ArrayUtil; import java.awt.*; import java.lang.reflect.Field; import java.util.List; /** * @author Alexander Lobas */ public class RadTableLayoutComponent extends RadViewContainer implements IGridProvider { private GridInfo myGridInfo; private GridInfo myVirtualGridInfo; @Override public void setViewInfo(ViewInfo viewInfo) { super.setViewInfo(viewInfo); myGridInfo = null; myVirtualGridInfo = null; } private int[] getColumnWidths() { try { Object viewObject = myViewInfo.getViewObject(); Class<?> viewClass = viewObject.getClass(); Field maxWidths = viewClass.getDeclaredField("mMaxWidths"); maxWidths.setAccessible(true); int[] columnWidths = (int[])maxWidths.get(viewObject); return columnWidths == null ? ArrayUtil.EMPTY_INT_ARRAY : columnWidths; } catch (Throwable e) { return ArrayUtil.EMPTY_INT_ARRAY; } } @Override public GridInfo getGridInfo() { if (myGridInfo == null) { myGridInfo = new GridInfo(this); int[] columnWidths = getColumnWidths(); if (columnWidths.length > 0) { myGridInfo.emptyColumns = new boolean[columnWidths.length]; myGridInfo.vLines = new int[columnWidths.length + 1]; for (int i = 0; i < columnWidths.length; i++) { int width = Math.max(columnWidths[i], 0); myGridInfo.emptyColumns[i] = width == 0; if (width == 0) { width = 2; if (i + 1 < columnWidths.length) { columnWidths[i + 1] -= width; } } myGridInfo.width += width; myGridInfo.vLines[i + 1] = myGridInfo.width; } } List<RadComponent> rows = getChildren(); if (!rows.isEmpty()) { Rectangle bounds = getBounds(); if (columnWidths.length == 0) { myGridInfo.width = bounds.width; } myGridInfo.hLines = new int[rows.size() + 1]; int index = 1; for (RadComponent row : rows) { Rectangle rowBounds = row.getBounds(); myGridInfo.hLines[index++] = myGridInfo.height = rowBounds.y - bounds.y + rowBounds.height; } } } return myGridInfo; } @Override public GridInfo getVirtualGridInfo() { if (myVirtualGridInfo == null) { myVirtualGridInfo = new GridInfo(this); GridInfo gridInfo = getGridInfo(); Rectangle bounds = getBounds(); myVirtualGridInfo.width = bounds.width; myVirtualGridInfo.height = bounds.height; int deltaWidth = bounds.width - (gridInfo.vLines.length == 0 ? 0 : gridInfo.width); myVirtualGridInfo.vLines = GridInfo.addLineInfo(gridInfo.vLines, deltaWidth); int deltaHeight = bounds.height - gridInfo.height; myVirtualGridInfo.hLines = GridInfo.addLineInfo(gridInfo.hLines, deltaHeight); List<RadComponent> rows = getChildren(); if (!rows.isEmpty()) { int columnSize = Math.max(1, gridInfo.vLines.length - 1); if (deltaWidth < 2) { myVirtualGridInfo.lastInsertColumn = columnSize - 1; } if (deltaHeight < 2) { myVirtualGridInfo.lastInsertRow = rows.size() - 1; } myVirtualGridInfo.components = getGridComponents(true); } } return myVirtualGridInfo; } public RadComponent[][] getGridComponents(boolean fillSpans) { GridInfo gridInfo = getGridInfo(); List<RadComponent> rows = getChildren(); int columnSize = Math.max(1, gridInfo.vLines.length - 1); RadComponent[][] components = new RadComponent[rows.size()][columnSize]; for (int i = 0; i < components.length; i++) { RadComponent row = rows.get(i); if (RadTableRowLayout.is(row)) { int index = 0; for (RadComponent column : row.getChildren()) { int cellIndex = getCellIndex(column); if (cellIndex > index) { index = cellIndex; } int cellSpan = getCellSpan(column); if (fillSpans) { for (int j = 0; j < cellSpan; j++) { components[i][index++] = column; } } else { components[i][index] = column; index += cellSpan; } } } else { components[i][0] = row; } } return components; } public static int getCellIndex(RadComponent component) { try { String column = ((RadViewComponent)component).getTag().getAttributeValue("layout_column", SdkConstants.NS_RESOURCES); return Integer.parseInt(column); } catch (Throwable e) { return -1; } } public static int getCellSpan(RadComponent component) { try { String span = ((RadViewComponent)component).getTag().getAttributeValue("layout_span", SdkConstants.NS_RESOURCES); return Integer.parseInt(span); } catch (Throwable e) { return 1; } } public static void setCellIndex(final RadComponent component, final int column) { ApplicationManager.getApplication().runWriteAction(new Runnable() { @Override public void run() { XmlTag tag = ((RadViewComponent)component).getTag(); tag.setAttribute("layout_column", SdkConstants.NS_RESOURCES, Integer.toString(column)); RadComponentOperations.deleteAttribute(tag, "layout_span"); } }); } public static void setCellSpan(final RadComponent component, final int span) { ApplicationManager.getApplication().runWriteAction(new Runnable() { @Override public void run() { XmlTag tag = ((RadViewComponent)component).getTag(); tag.setAttribute("layout_span", SdkConstants.NS_RESOURCES, Integer.toString(span)); } }); } }