/** * MyMultiDimColHeaderModel.java * * Copyright 2000 Eliad Technologies, Inc. All Rights Reserved. * * This software is the proprietary information of Eliad Technologies, Inc. */ package MultiDimTable; import java.awt.*; import java.util.*; import java.beans.*; import javax.swing.*; import javax.swing.tree.DefaultMutableTreeNode; import com.eliad.model.*; import com.eliad.model.defaults.*; public class MyMultiDimColHeaderModel extends AbstractGridModel implements RulerModelListener { private MatrixCellModel[][] headerCacheMatrix_ = null; private MyGridHeaderDirectSpan headerDirectSpanModel_ = new MyGridHeaderDirectSpan(); private DirectColDragController dragController_; // little cache for getValue() method - to remove in final version private Object cacheCellValue_ = null; private int lastRow_ = -1; private int lastColumn_ = -1; public MyMultiDimColHeaderModel(DefaultMutableTreeNode root) { headerCacheMatrix_ = parseHeaderCellTree(root); } // returns the height of the column header tree public int getRowCount() { return headerCacheMatrix_.length; } // returns the width of the column header tree public int getColumnCount() { return headerCacheMatrix_[0].length; } public Object getValueAt(int row, int column) { if (row != lastRow_ || column != lastColumn_) { cacheCellValue_ = headerCacheMatrix_[row][column].getValue(); lastRow_ = row; lastColumn_ = column; } else { ;//MultiDimTable.traceln("Cache for GetValueAt(" + row + ", " + column + ") = " + cacheCellValue_); } return cacheCellValue_; } public void directColumnDragController(DirectColDragController dcdc) { dragController_ = dcdc; } // inner class for ColumnHeaderDirectSpan public class MyGridHeaderDirectSpan extends AbstractDirectSpanModel { // little cache for ExtentCell - to remove in final version private ExtentCell cacheExtentCell_ = null; private int lastRow_ = -1; private int lastColumn_ = -1; public ExtentCell getSpanOver(final int row, final int column) { if (row != lastRow_ || column != lastColumn_) { cacheExtentCell_ = headerCacheMatrix_[row][column].getExtentCell(); lastRow_ = row; lastColumn_ = column; } else { ;//MultiDimTable.traceln("Cache for Extent Cells(" + row + ", " + column + ")"); } return cacheExtentCell_; } public boolean isEmpty() { return false; } } public GridModel getColumnHeaderModel() { return this; } public DirectSpanModel getColumnHeaderSpanModel() { return this.headerDirectSpanModel_; } // TreeNodes parsing function public MatrixCellModel[][] parseHeaderCellTree(DefaultMutableTreeNode root) { MatrixCellModel[][] cacheMatrix; int treeHeight, treeWidth; int row, column, spanRowCount, spanColumnCount, firstLeafColumn; DefaultMutableTreeNode node = null; Enumeration allNodes = null; Hashtable leafNodesIndex = new Hashtable(20); treeWidth = 0; treeHeight = root.getDepth() + 1; // treeHeight of the tree node = root.getFirstLeaf(); // Buttom left child of the entre tree /** * we parse each leaf child from left to right of the tree, * then we have the treeWidth of the tree and we can find the column index of parent nodes */ while (node != null) { leafNodesIndex.put(node, new Integer(treeWidth)); treeWidth++; node = node.getNextLeaf(); } /** * cache matrix for quick acces to Cell Data and Spanned Area * [treeHeight][treeWidth] means => [maxRows][maxColumns] */ cacheMatrix = new MatrixCell[treeHeight][treeWidth]; allNodes = root.postorderEnumeration(); // this enumeration crosses the tree nodes in postorder /** * now we put usefull informations into our cache matrix by parsing the tree nodes */ while (allNodes.hasMoreElements()) { node = (DefaultMutableTreeNode) allNodes.nextElement(); row = node.getLevel(); if (node.isLeaf()) { column = ((Integer)leafNodesIndex.get(node)).intValue(); spanRowCount = treeHeight - row; spanColumnCount = 1; for (int j=row+1; j