/* ******************************************************************************
* 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 Chart extends BranchStructureData {
private List<Row> rows = null;
private List<Column> cols = null;
private int titleAreaHeight = -1;
private int columnHeadHeight = -1;
private int rowHeadWidth = -1;
private int lineWidth = -1;
private ColumnOrder prefColumnOrder = null;
public Chart(IBranchPart branch) {
super(branch);
}
void setContent(Row row, Column... col) {
rows = Collections.singletonList(row);
cols = Arrays.asList(col);
}
void setLineWidth(int lineWidth) {
this.lineWidth = lineWidth;
}
public IBranchPart getTitle() {
return super.getBranch();
}
public List<Row> getRows() {
ensureBuilt();
return rows;
}
public List<Column> 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 getNumValidColumns() {
int num = 0;
for (Column col : getColumns()) {
if (!ColumnHead.EMPTY.equals(col.getHead())
&& !col.getCells().isEmpty()) {
num++;
}
}
return num;
}
public Row getRow(int rowIndex) {
if (rowIndex < 0 || rowIndex >= getRows().size())
return null;
return getRows().get(rowIndex);
}
public Column 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 (rows == null)
rows = Collections.emptyList();
if (cols == null) {
cols = new ArrayList<Column>(1);
cols.add(new Column(this, ColumnHead.EMPTY));
}
}
private void lazyBuild() {
if (getTitle() == null)
return;
Map<Row, List<Item>> rowItems = null;
Map<Column, List<Item>> colItems = null;
List<Column> cols2 = new ArrayList<Column>();
for (IBranchPart rowHead : getTitle().getSubBranches()) {
List<Item> items = new ArrayList<Item>();
Row row = buildRow(rowHead, items);
if (!items.isEmpty()) {
if (rowItems == null)
rowItems = new HashMap<Row, List<Item>>();
rowItems.put(row, items);
for (Item item : items) {
ColumnHead prefHead = item.getPrefColumnHead();
if (prefHead != null) {
Column col = colItems == null ? null
: findColumn(colItems.keySet(), prefHead);
if (col == null) {
col = new Column(this, prefHead);
cols2.add(col);
List<Item> list = new ArrayList<Item>();
list.add(item);
if (colItems == null)
colItems = new HashMap<Column, List<Item>>();
colItems.put(col, list);
} else {
List<Item> list = colItems.get(col);
if (list == null) {
list = new ArrayList<Item>();
colItems.put(col, list);
}
list.add(item);
}
}
}
}
}
for (int i = 0; i < cols2.size(); i++) {
cols2.get(i).getHead().setIndex(i);
}
if (colItems != null) {
cols = new ArrayList<Column>(
new TreeSet<Column>(colItems.keySet()));
}
if (cols == null)
cols = new ArrayList<Column>(1);
if (cols.isEmpty()) {
cols.add(new Column(this, ColumnHead.EMPTY));
}
buildCells(rowItems, colItems);
}
private void buildCells(Map<Row, List<Item>> rowItems,
Map<Column, List<Item>> colItems) {
if (rows == null || cols == null)
return;
for (Row row : rows) {
for (Column col : cols) {
buildCell(row, col, rowItems, colItems);
}
}
}
private void buildCell(Row row, Column col, Map<Row, List<Item>> rowItems,
Map<Column, List<Item>> colItems) {
Cell cell = new Cell(this, row, col);
row.addCell(cell);
col.addCell(cell);
List<Item> rItems = rowItems == null ? null : rowItems.get(row);
List<Item> cItems = colItems == null ? null : colItems.get(col);
if (rItems != null && cItems != null) {
for (Item item : rItems) {
if (cItems.contains(item)) {
cell.addItem(item);
}
}
}
}
private Column findColumn(Collection<Column> columns, ColumnHead colHead) {
for (Column col : columns) {
if (colHead.equals(col.getHead()))
return col;
}
return null;
}
private Row buildRow(IBranchPart rowHead, List<Item> rowItems) {
Row row = new Row(rowHead, this);
if (rows == null)
rows = new ArrayList<Row>();
rows.add(row);
for (IBranchPart child : rowHead.getSubBranches()) {
Item item = new Item(this, child);
rowItems.add(item);
}
return row;
}
public int getTitleAreaHeight() {
if (titleAreaHeight < 0) {
titleAreaHeight = calcTitleAreaHeight();
}
return titleAreaHeight;
}
private int calcTitleAreaHeight() {
int h = 0;
int y = getBranch().getFigure().getBounds().y;
// ILabelPart label = getBranch().getLabel();
// if (label != null && label.getFigure().isVisible()) {
// h = label.getFigure().getBounds().bottom() - y;
// } else {
// ITopicPart topicPart = getBranch().getTopicPart();
// if (topicPart != null && topicPart.getFigure().isVisible()) {
// h = topicPart.getFigure().getBounds().bottom() - 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 getColumnHeadHeight() {
if (columnHeadHeight < 0) {
columnHeadHeight = calcColumnHeadHeight();
}
return columnHeadHeight;
}
private int calcColumnHeadHeight() {
int sum = 0;
for (Column c : getColumns()) {
sum = Math.max(sum, c.getHead().getPrefSize().height);
}
return sum;
}
public int getRowHeadWidth() {
if (rowHeadWidth < 0) {
rowHeadWidth = calcRowHeadWidth();
}
return rowHeadWidth;
}
private int calcRowHeadWidth() {
int sum = 0;
for (Row row : getRows()) {
IBranchPart head = row.getHead();
ITopicPart topicPart = head.getTopicPart();
if (topicPart != null) {
sum = Math.max(sum, topicPart.getFigure().getBounds().width);
}
IInfoPart infoPart = head.getInfoPart();
if (infoPart != null) {
sum = Math.max(sum, infoPart.getFigure().getBounds().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 Row getPreviousRow(Row row) {
int index = getRowIndex(row);
if (index > 0)
return getRows().get(index - 1);
return null;
}
public Row getNextRow(Row row) {
int index = getRowIndex(row);
if (index < getRows().size() - 1)
return getRows().get(index + 1);
return null;
}
public int getRowIndex(Row row) {
return getRows().indexOf(row);
}
public Column getPreviousColumn(Column col) {
int index = getColumnIndex(col);
if (index > 0)
return getColumns().get(index - 1);
return null;
}
public Column getNextColumn(Column col) {
int index = getColumnIndex(col);
if (index < getColumns().size() - 1)
return getColumns().get(index + 1);
return null;
}
public int getColumnIndex(Column col) {
return getColumns().indexOf(col);
}
public Cell findCell(Point point) {
for (Row row : getRows()) {
for (Cell cell : row.getCells()) {
if (cell.getBounds().contains(point))
return cell;
}
}
return null;
}
public ColumnHead findColumnHead(Point point) {
if (hasRows()) {
int y = getTitle().getTopicPart().getFigure().getBounds().bottom()
+ getLineWidth();
if (getTitle().getInfoPart() != null) {
y += getTitle().getInfoPart().getFigure().getBounds().height;
}
if (point.y > y && point.y < y + getColumnHeadHeight()
+ getMajorSpacing()) {
for (Column col : getColumns()) {
int x = col.getLeft();
if (point.x > x && point.x < x + col.getWidth()) {
return col.getHead();
}
}
}
}
return null;
}
public Column findColumn(ColumnHead colHead) {
for (Column col : getColumns()) {
if (col.getHead().equals(colHead))
return col;
}
return null;
}
public ColumnOrder getPrefColumnOrder() {
if (prefColumnOrder == null) {
prefColumnOrder = ColumnOrder
.createFromTopic(getTitle().getTopic());
}
return prefColumnOrder;
}
}