/* ****************************************************************************** * Copyright (c) 2006-2012 XMind Ltd. and others. * * This file is a part of XMind 3. XMind releases 3 and * above are dual-licensed under the Eclipse Public License (EPL), * which is available at http://www.eclipse.org/legal/epl-v10.html * and the GNU Lesser General Public License (LGPL), * which is available at http://www.gnu.org/licenses/lgpl.html * See http://www.xmind.net/license.html for details. * * Contributors: * XMind Ltd. - initial API and implementation *******************************************************************************/ package org.xmind.ui.internal.spreadsheet.structures; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.TreeSet; import org.eclipse.draw2d.geometry.Point; import org.xmind.gef.graphicalpolicy.IStyleSelector; import org.xmind.ui.branch.BranchStructureData; import org.xmind.ui.mindmap.IBranchPart; import org.xmind.ui.mindmap.IInfoPart; import org.xmind.ui.mindmap.ITopicPart; import org.xmind.ui.style.StyleUtils; import org.xmind.ui.style.Styles; public class Chart2 extends BranchStructureData { private List<Column2> cols = null; private List<Row2> rows = null; private int titleAreaHeight = -1; private int colHeadHeight = -1; private int rowHeadWidth = -1; private int lineWidth = -1; private RowOrder prefRowOrder = null; public Chart2(IBranchPart branch) { super(branch); } void setContent(Column2 col, Row2... row) { cols = Collections.singletonList(col); rows = Arrays.asList(row); } void setLineWidth(int lineWidth) { this.lineWidth = lineWidth; } public IBranchPart getTitle() { return super.getBranch(); } public List<Row2> getRows() { ensureBuilt(); return rows; } public List<Column2> getColumns() { ensureBuilt(); return cols; } public boolean hasRows() { return !getRows().isEmpty(); } public boolean hasColumns() { return !getColumns().isEmpty(); } public int getNumRows() { return getRows().size(); } public int getNumColumns() { return getColumns().size(); } public int getNumValidRows() { int num = 0; for (Row2 row : getRows()) { if (!RowHead.EMPTY.equals(row.getHead()) && !row.getCells().isEmpty()) num++; } return num; } public Row2 getFirstRow() { return getRow(0); } public Row2 getRow(int rowIndex) { if (rowIndex < 0 || rowIndex >= getRows().size()) return null; return getRows().get(rowIndex); } public Column2 getColumn(int colIndex) { if (colIndex < 0 || colIndex >= getColumns().size()) return null; return getColumns().get(colIndex); } private void ensureBuilt() { if (rows != null && cols != null) return; rows = null; cols = null; lazyBuild(); if (cols == null) cols = Collections.emptyList(); if (rows == null) { rows = Collections.emptyList(); } } private void lazyBuild() { if (getTitle() == null) return; Map<Column2, List<Item2>> colItems = null; Map<Row2, List<Item2>> rowItems = null; List<Row2> rows2 = new ArrayList<Row2>(); for (IBranchPart colHead : getTitle().getSubBranches()) { List<Item2> items = new ArrayList<Item2>(); Column2 col = buildCol(colHead, items); if (!items.isEmpty()) { if (colItems == null) colItems = new HashMap<Column2, List<Item2>>(); colItems.put(col, items); for (Item2 item : items) { RowHead prefHead = item.getPrefRowHead(); if (prefHead != null) { Row2 row = rowItems == null ? null : findRow( rowItems.keySet(), prefHead); if (row == null) { row = new Row2(this, prefHead); rows2.add(row); List<Item2> list = new ArrayList<Item2>(); list.add(item); if (rowItems == null) rowItems = new HashMap<Row2, List<Item2>>(); rowItems.put(row, list); } else { List<Item2> list = rowItems.get(row); if (list == null) { list = new ArrayList<Item2>(); rowItems.put(row, list); } list.add(item); } } } } } for (int i = 0; i < rows2.size(); i++) { rows2.get(i).getHead().setIndex(i); } if (rowItems != null) { rows = new ArrayList<Row2>(new TreeSet<Row2>(rowItems.keySet())); } buildCells(colItems, rowItems); } private void buildCells(Map<Column2, List<Item2>> colItems, Map<Row2, List<Item2>> rowItems) { if (rows == null || cols == null) return; for (Column2 col : cols) { for (Row2 row : rows) { buildCell(col, row, colItems, rowItems); } } } private void buildCell(Column2 col, Row2 row, Map<Column2, List<Item2>> colItems, Map<Row2, List<Item2>> rowItems) { Cell2 cell = new Cell2(this, col, row); col.addCell(cell); row.addCell(cell); List<Item2> cItems = colItems == null ? null : colItems.get(col); List<Item2> rItems = rowItems == null ? null : rowItems.get(row); if (cItems != null && rItems != null) { for (Item2 item : rItems) { if (cItems.contains(item)) { cell.addItem(item); } } } } private Row2 findRow(Collection<Row2> rows, RowHead rowHead) { for (Row2 row : rows) { if (rowHead.equals(row.getHead())) return row; } return null; } private Column2 buildCol(IBranchPart colHead, List<Item2> colItems) { Column2 col = new Column2(colHead, this); if (cols == null) cols = new ArrayList<Column2>(); cols.add(col); for (IBranchPart child : colHead.getSubBranches()) { Item2 item = new Item2(this, child); colItems.add(item); } return col; } public int getTitleAreaHeight() { if (titleAreaHeight < 0) { titleAreaHeight = calcTitleAreaHeight(); } return titleAreaHeight; } private int calcTitleAreaHeight() { int h = 0; int y = getBranch().getFigure().getBounds().y; IInfoPart info = getBranch().getInfoPart(); if (info != null && info.getFigure().isVisible()) { h = info.getFigure().getBounds().bottom() - y; } else { ITopicPart topicPart = getBranch().getTopicPart(); if (topicPart != null && topicPart.getFigure().isVisible()) { h = topicPart.getFigure().getBounds().bottom() - y; } } return h; } public int getColHeadHeight() { if (colHeadHeight < 0) { colHeadHeight = calcColHeadHeight(); } return colHeadHeight; } private int calcColHeadHeight() { int maxTopicHeight = 0; int maxInfoHeight = 0; for (Column2 col : getColumns()) { IBranchPart head = col.getHead(); ITopicPart topicPart = head.getTopicPart(); if (topicPart != null) maxTopicHeight = Math.max(maxTopicHeight, topicPart.getFigure() .getBounds().height); IInfoPart infoPart = head.getInfoPart(); if (infoPart != null) maxInfoHeight = Math.max(maxInfoHeight, infoPart.getFigure() .getBounds().height); } return maxTopicHeight + maxInfoHeight; } public int getRowHeadWidth() { if (rowHeadWidth < 0) { rowHeadWidth = calcRowHeadWidth(); } return rowHeadWidth; } private int calcRowHeadWidth() { int sum = 0; for (Row2 row : getRows()) sum = Math.max(sum, row.getHead().getPrefSize().width); return sum; } public int getLineWidth() { if (lineWidth < 0) { IStyleSelector ss = StyleUtils.getStyleSelector(getBranch()); String decorationId = StyleUtils.getString(getBranch(), ss, Styles.ShapeClass, null); lineWidth = StyleUtils.getInteger(getBranch(), ss, Styles.LineWidth, decorationId, 1); } return lineWidth; } public int getMajorSpacing() { if (getBranch() == null) return 5; return super.getMajorSpacing(); } public int getMinorSpacing() { if (getBranch() == null) return 1; return super.getMinorSpacing(); } public Column2 getPreviousColumn(Column2 col) { int index = getColumnIndex(col); if (index > 0) return getColumns().get(index - 1); return null; } public Column2 getNextColumn(Column2 col) { int index = getColumnIndex(col); if (index < getColumns().size() - 1) return getColumns().get(index + 1); return null; } public int getRowIndex(Row2 row) { return getRows().indexOf(row); } public Row2 getPreviousRow(Row2 row) { int index = getRowIndex(row); if (index > 0) return getRows().get(index - 1); return null; } public Row2 getNextRow(Row2 row) { int index = getRowIndex(row); if (index < getRows().size() - 1) return getRows().get(index + 1); return null; } public int getColumnIndex(Column2 col) { return getColumns().indexOf(col); } public Cell2 findCell(Point point) { //TODO for (Column2 col : getColumns()) { for (Cell2 cell : col.getCells()) { if (cell.getBounds().contains(point)) return cell; } } return null; } public RowHead findRowHead(Point point) { if (hasRows()) { int x = getTitle().getTopicPart().getFigure().getBounds().x - getMajorSpacing(); if (point.x > x && point.x < x + getRowHeadWidth() + getMajorSpacing() * 2) { for (Row2 row : getRows()) { int y = row.getTop(); if (point.y > y && point.y < y + row.getHeight()) { return row.getHead(); } } } } return null; } public Row2 findRow(RowHead colHead) { for (Row2 row : getRows()) { if (row.getHead().equals(colHead)) return row; } return null; } public RowOrder getPrefRowOrder() { if (prefRowOrder == null) { prefRowOrder = RowOrder.createFromTopic(getTitle().getTopic()); } return prefRowOrder; } }