0001: /*
0002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
0003: *
0004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
0005: *
0006: * The contents of this file are subject to the terms of either the GNU
0007: * General Public License Version 2 only ("GPL") or the Common
0008: * Development and Distribution License("CDDL") (collectively, the
0009: * "License"). You may not use this file except in compliance with the
0010: * License. You can obtain a copy of the License at
0011: * http://www.netbeans.org/cddl-gplv2.html
0012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
0013: * specific language governing permissions and limitations under the
0014: * License. When distributing the software, include this License Header
0015: * Notice in each file and include the License file at
0016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
0017: * particular file as subject to the "Classpath" exception as provided
0018: * by Sun in the GPL Version 2 section of the License file that
0019: * accompanied this code. If applicable, add the following below the
0020: * License Header, with the fields enclosed by brackets [] replaced by
0021: * your own identifying information:
0022: * "Portions Copyrighted [year] [name of copyright owner]"
0023: *
0024: * Contributor(s):
0025: *
0026: * The Original Software is NetBeans. The Initial Developer of the Original
0027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
0028: * Microsystems, Inc. All Rights Reserved.
0029: *
0030: * If you wish your version of this file to be governed by only the CDDL
0031: * or only the GPL Version 2, indicate your decision by adding
0032: * "[Contributor] elects to include this software in this distribution
0033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
0034: * single choice of license, a recipient has the option to distribute
0035: * your version of this file under either the CDDL, the GPL Version 2 or
0036: * to extend the choice of license to its licensees as provided above.
0037: * However, if you add GPL Version 2 code and therefore, elected the GPL
0038: * Version 2 license, then the option applies only if the new code is
0039: * made subject to such option by the copyright holder.
0040: */
0041: package org.netbeans.modules.sql.framework.ui.graph.impl;
0042:
0043: import java.awt.Color;
0044: import java.awt.Insets;
0045: import java.awt.Rectangle;
0046: import java.util.ArrayList;
0047: import java.util.Iterator;
0048:
0049: import org.netbeans.modules.sql.framework.model.SQLDBColumn;
0050: import org.netbeans.modules.sql.framework.ui.graph.ICanvasInterface;
0051: import org.netbeans.modules.sql.framework.ui.graph.IGraphInterface;
0052: import org.netbeans.modules.sql.framework.ui.graph.IGraphPort;
0053:
0054: import com.nwoods.jgo.JGoBrush;
0055: import com.nwoods.jgo.JGoDocumentChangedEdit;
0056: import com.nwoods.jgo.JGoDocumentEvent;
0057: import com.nwoods.jgo.JGoObject;
0058: import com.nwoods.jgo.JGoPen;
0059: import com.nwoods.jgo.JGoRectangle;
0060: import com.nwoods.jgo.JGoScrollBar;
0061:
0062: /**
0063: * @author Ritesh Adval
0064: * @version $Revision$
0065: */
0066: public class TableArea extends CanvasArea implements IGraphInterface,
0067: ICanvasInterface {
0068:
0069: /**
0070: * Table header for this table.
0071: */
0072: protected TableHeaderArea headerArea;
0073:
0074: /**
0075: * Left port area.
0076: */
0077: protected ColumnPortArea leftPortArea;
0078:
0079: /**
0080: * Right port area.
0081: */
0082: protected ColumnPortArea rightPortArea;
0083:
0084: /**
0085: * Table type.
0086: */
0087: protected int tableType = TableConstants.INPUT_OUTPUT_TABLE;
0088:
0089: /**
0090: * Represents number of columns in the table
0091: */
0092: protected ArrayList columnAreas;
0093:
0094: // this is the column being resized.
0095: private ColumnArea resizeColumn;
0096:
0097: // these are for what is visible in this table area
0098: private int firstVisibleRow = 0;
0099: private int firstVisibleColumn = 0;
0100: private int lastVisibleColumn = -1;
0101:
0102: // some constant for gaps
0103: private int portAreaColumnAreaGap = 0;
0104: private int headerColumnGap = 0;
0105:
0106: // vertical scrollbar
0107: private BasicScrollBar vScrollBar;
0108:
0109: // horizontal scrollbar
0110: private BasicScrollBar hScrollBar;
0111:
0112: // this is the size of the scrollbar
0113:
0114: private JGoRectangle topLeftCornerRect;
0115:
0116: private JGoRectangle topRightCornerRect;
0117:
0118: private JGoRectangle rect;
0119:
0120: private boolean expanded = true;
0121:
0122: private ColumnArea lastColumn;
0123:
0124: private boolean showHeader = true;
0125:
0126: private boolean disableLayout = false;
0127:
0128: // EventHints
0129: /**
0130: * Event fired when first visible row in the table is changed.
0131: */
0132: public static final int FIRST_VISIBLE_ROW_CHANGED = JGoDocumentEvent.LAST + 40001;
0133:
0134: /**
0135: * Event fired when last visible row in the table is changed.
0136: */
0137: public static final int LAST_VISIBLE_ROW_CHANGED = JGoDocumentEvent.LAST + 40002;
0138:
0139: /**
0140: * Event fired when first visible column in the table is changed.
0141: */
0142: public static final int FIRST_VISIBLE_COLUMN_CHANGED = JGoDocumentEvent.LAST + 40003;
0143:
0144: /**
0145: * Event fired when last visible column in the table is changed.
0146: */
0147: public static final int LAST_VISIBLE_COLUMN_CHANGED = JGoDocumentEvent.LAST + 40004;
0148:
0149: // AutoResizeMode
0150: /**
0151: * When a column is adjusted in the UI, adjust the next column the opposite way.
0152: */
0153: public static final int AUTO_RESIZE_NEXT_COLUMN = 1;
0154:
0155: /**
0156: * During UI adjustment, change subsequent columns to preserve the total width; this
0157: * is the default behavior.
0158: */
0159: public static final int AUTO_RESIZE_SUBSEQUENT_COLUMNS = 2;
0160:
0161: /**
0162: * During all resize operations, apply adjustments to the last column only.
0163: */
0164: public static final int AUTO_RESIZE_LAST_COLUMN = 3;
0165:
0166: /** During all resize operations, proportionately resize all columns. */
0167: public static final int AUTO_RESIZE_ALL_COLUMNS = 4;
0168:
0169: /** Creates a new instance of TableArea */
0170: public TableArea() {
0171: super ();
0172: initGui();
0173: }
0174:
0175: /**
0176: * Initializes GUI components.
0177: */
0178: protected void initGui() {
0179: headerArea = new TableHeaderArea();
0180: this .addObjectAtTail(headerArea);
0181: columnAreas = new ArrayList();
0182:
0183: this .setDraggable(true);
0184: // for now do not allow it to be resizeable
0185: this .setResizable(false);
0186:
0187: // initialize top left and right corner display rectangle
0188: topLeftCornerRect = new JGoRectangle();
0189: topLeftCornerRect.setSelectable(false);
0190: topLeftCornerRect.setResizable(false);
0191: topLeftCornerRect.set4ResizeHandles(false);
0192: topLeftCornerRect.setPen(JGoPen.makeStockPen(Color.lightGray));
0193: topLeftCornerRect.setBrush(JGoBrush.makeStockBrush(new Color(
0194: 221, 235, 246)));
0195: addObjectAtHead(topLeftCornerRect);
0196:
0197: topRightCornerRect = new JGoRectangle();
0198: topRightCornerRect.setSelectable(false);
0199: topRightCornerRect.setResizable(false);
0200: topRightCornerRect.set4ResizeHandles(false);
0201: topRightCornerRect.setPen(JGoPen.makeStockPen(Color.lightGray));
0202: topRightCornerRect.setBrush(JGoBrush.makeStockBrush(new Color(
0203: 221, 235, 246)));//(254,253,235)
0204: addObjectAtHead(topRightCornerRect);
0205:
0206: rect = new JGoRectangle();
0207: rect.setSelectable(false);
0208: rect.setResizable(false);
0209: rect.set4ResizeHandles(false);
0210: rect.setPen(JGoPen.makeStockPen(Color.lightGray));
0211: addObjectAtHead(rect);
0212: }
0213:
0214: /**
0215: * Creates new instance of table.
0216: *
0217: * @param tType the table type
0218: */
0219: protected TableArea(int tType) {
0220: this ();
0221: this .tableType = tType;
0222: }
0223:
0224: /**
0225: * Creates an instance of table area based on row data and column name.
0226: *
0227: * @param rowData the row data to be displayed in the table
0228: * @param columnNames the name of the column headers
0229: */
0230: public TableArea(String[][] rowData, String[] columnNames) {
0231: this ();
0232: setHeaders(columnNames);
0233: addItems(rowData);
0234: initialize(getTableType());
0235: }
0236:
0237: /**
0238: * Creates an instance of table area based on row data and column name and table type.
0239: *
0240: * @param rowData the row data to be displayed in the table
0241: * @param columnNames the name of the column headers
0242: * @param tType the table type
0243: */
0244: public TableArea(String[][] rowData, String[] columnNames, int tType) {
0245: this (tType);
0246: setHeaders(columnNames);
0247: addItems(rowData);
0248:
0249: initialize(tType);
0250: }
0251:
0252: /**
0253: * Initialize the table.
0254: *
0255: * @param tType the table type
0256: */
0257: public void initialize(int tType) {
0258: this .tableType = tType;
0259:
0260: // if table is out we only need to provide port on left side
0261: // if it is both input and output , then we need ports on both sides
0262: if (tType == TableConstants.OUTPUT_TABLE) {
0263: leftPortArea = new ColumnPortArea(
0264: ColumnPortArea.LEFT_PORT_AREA, getRowCount());
0265: this .addObjectAtTail(leftPortArea);
0266: } else if (tType == TableConstants.INPUT_TABLE) {
0267: // if it is input we need to provide port on the right side
0268: rightPortArea = new ColumnPortArea(
0269: ColumnPortArea.RIGHT_PORT_AREA, getRowCount());
0270: this .addObjectAtTail(rightPortArea);
0271: } else if (tType == TableConstants.INPUT_OUTPUT_TABLE) {
0272: leftPortArea = new ColumnPortArea(
0273: ColumnPortArea.LEFT_PORT_AREA, getRowCount());
0274: this .addObjectAtTail(leftPortArea);
0275: rightPortArea = new ColumnPortArea(
0276: ColumnPortArea.RIGHT_PORT_AREA, getRowCount());
0277: this .addObjectAtTail(rightPortArea);
0278: } else if (tType == TableConstants.NO_PORT_TABLE) {
0279: // do nothing
0280: }
0281:
0282: }
0283:
0284: /**
0285: * Removes all of the child objects in this area.
0286: */
0287: public void removeAll() {
0288: super .removeAll();
0289: columnAreas.clear();
0290: }
0291:
0292: /**
0293: * Gets table type.
0294: *
0295: * @return current table type
0296: */
0297: public int getTableType() {
0298: return this .tableType;
0299: }
0300:
0301: /**
0302: * Sets table type.
0303: *
0304: * @param tType new table type
0305: */
0306: public void setTableType(int tType) {
0307: this .tableType = tType;
0308: }
0309:
0310: /**
0311: * Indicates whether table is expanded.
0312: *
0313: * @return true if table is expanded; false otherwise
0314: */
0315: public boolean isExpanded() {
0316: return expanded;
0317: }
0318:
0319: /**
0320: * Sets table mode as expanded.
0321: *
0322: * @param sExpanded true to expand the table, false otherwise.
0323: */
0324: public void setExpanded(boolean sExpanded) {
0325: this .expanded = sExpanded;
0326: }
0327:
0328: /**
0329: * Gets the left port area of the table.
0330: *
0331: * @return left port area
0332: */
0333: public ColumnPortArea getLeftPortArea() {
0334: return leftPortArea;
0335: }
0336:
0337: /**
0338: * Gets the right port area of the table.
0339: *
0340: * @return right port area
0341: */
0342: public ColumnPortArea getRightPortArea() {
0343: return rightPortArea;
0344: }
0345:
0346: /**
0347: * Gets the row count in this table area.
0348: *
0349: * @return number of rows in this table area
0350: */
0351: public int getRowCount() {
0352: if (columnAreas == null) {
0353: return -1;
0354: }
0355: Iterator it = columnAreas.iterator();
0356: if (it.hasNext()) {
0357: ColumnArea column = (ColumnArea) it.next();
0358: return column.getRowCount();
0359: }
0360:
0361: return -1;
0362: }
0363:
0364: /**
0365: * Gets column count in this area.
0366: *
0367: * @return number of column in this area
0368: */
0369: public int getColumnCount() {
0370: return headerArea.getHeaderCount();
0371: }
0372:
0373: // build the table with the provided set of row data
0374: private void addItems(String[][] rowData) {
0375: for (int i = 0; i < rowData.length; i++) {
0376: String[] columns = rowData[i];
0377:
0378: for (int j = 0; j < columns.length; j++) {
0379: String cellVal = columns[j];
0380: addItem(i, j, cellVal, "");
0381: }
0382: }
0383: }
0384:
0385: /**
0386: * Sets the header on this table.
0387: *
0388: * @param columnNames names of the headers
0389: */
0390: public void setHeaders(String[] columnNames) {
0391: headerArea.setHeaders(columnNames);
0392: }
0393:
0394: /**
0395: * Adds the column cell in the table header.
0396: *
0397: * @param columnName name of table column
0398: */
0399: public void addColumn(String columnName) {
0400: headerArea.addHeaderCell(columnName);
0401: }
0402:
0403: /**
0404: * Adds item to this table.
0405: *
0406: * @param row row where item needs to be added
0407: * @param col column in row row where item needs to be added
0408: * @param val the string value of the item
0409: */
0410: public void addItem(int row, int col, String val, String toolTip) {
0411: ColumnArea column = null;
0412:
0413: if (columnAreas.size() != 0 && col < columnAreas.size()) {
0414: column = (ColumnArea) columnAreas.get(col);
0415: }
0416: if (column == null) {
0417: column = new ColumnArea(getTableType());
0418:
0419: columnAreas.add(col, column);
0420: this .addObjectAtTail(column);
0421: }
0422: column.addItem(row, val, toolTip);
0423: addPort(row);
0424: // remember the last column added in the table
0425: lastColumn = column;
0426:
0427: this .setHeight(this .getMaximumHeight());
0428: }
0429:
0430: /**
0431: * Adds item to this table.
0432: *
0433: * @param row row where item needs to be added
0434: * @param col column in row row where item needs to be added
0435: * @param val the string value of the item
0436: */
0437: public void addItem(int row, int col, SQLDBColumn data,
0438: String toolTip) {
0439: ColumnArea column = null;
0440:
0441: if (columnAreas.size() != 0 && col < columnAreas.size()) {
0442: column = (ColumnArea) columnAreas.get(col);
0443: }
0444: if (column == null) {
0445: column = new ColumnArea(getTableType());
0446:
0447: columnAreas.add(col, column);
0448: this .addObjectAtTail(column);
0449: }
0450: column.addItem(row, data, toolTip);
0451: addPort(row);
0452: // remember the last column added in the table
0453: lastColumn = column;
0454:
0455: this .setHeight(this .getMaximumHeight());
0456: }
0457:
0458: private void addPort(int row) {
0459: // if table is out we only need to provide port on left side
0460: // if it is both input and output , then we need ports on both sides
0461: if (this .tableType == TableConstants.OUTPUT_TABLE) {
0462: leftPortArea = this .getLeftPortArea();
0463: if (leftPortArea != null
0464: && leftPortArea.getRowCount() != this .getRowCount()) {
0465: leftPortArea.addPort(row);
0466: }
0467: }
0468: // if it is input we need to provide port on the right side
0469: if (this .tableType == TableConstants.INPUT_TABLE) {
0470: rightPortArea = this .getRightPortArea();
0471: if (rightPortArea != null
0472: && rightPortArea.getRowCount() != this
0473: .getRowCount()) {
0474: rightPortArea.addPort(row);
0475: }
0476: }
0477: if (this .tableType == TableConstants.INPUT_OUTPUT_TABLE) {
0478:
0479: leftPortArea = this .getLeftPortArea();
0480: if (leftPortArea != null
0481: && leftPortArea.getRowCount() != this .getRowCount()) {
0482: leftPortArea.addPort();
0483: }
0484:
0485: rightPortArea = this .getRightPortArea();
0486: if (rightPortArea != null
0487: && rightPortArea.getRowCount() != this
0488: .getRowCount()) {
0489: rightPortArea.addPort();
0490: }
0491: }
0492: }
0493:
0494: public void removeItem(int row, int col) {
0495: ColumnArea column = null;
0496:
0497: if (columnAreas.size() != 0 && col < columnAreas.size()) {
0498: column = (ColumnArea) columnAreas.get(col);
0499: }
0500:
0501: if (column == null) {
0502: throw new IllegalArgumentException(
0503: "Cannot delete table item for row " + row
0504: + ", column " + col);
0505: }
0506:
0507: column.removeItem(row);
0508:
0509: if (leftPortArea != null) {
0510: leftPortArea.removePort(row);
0511: }
0512:
0513: if (rightPortArea != null) {
0514: rightPortArea.removePort(row);
0515: }
0516:
0517: this .setHeight(this .getMaximumHeight());
0518: }
0519:
0520: public IGraphPort getLeftGraphPort(int row) {
0521: if (leftPortArea != null) {
0522: PortArea pArea = leftPortArea.getPortAreaAt(row);
0523: if (pArea != null) {
0524: return pArea.getGraphPort();
0525: }
0526: }
0527:
0528: return null;
0529: }
0530:
0531: public IGraphPort getRightGraphPort(int row) {
0532: if (rightPortArea != null) {
0533: PortArea pArea = rightPortArea.getPortAreaAt(row);
0534: if (pArea != null) {
0535: return pArea.getGraphPort();
0536: }
0537: }
0538:
0539: return null;
0540: }
0541:
0542: /**
0543: * Gets the vertical scrollbar.
0544: *
0545: * @return vertical scrollbar
0546: */
0547: public JGoScrollBar getVerticalScrollBar() {
0548: return vScrollBar;
0549: }
0550:
0551: /**
0552: * Gets the horizontal scrollbar.
0553: *
0554: * @return horizontal scrollbar
0555: */
0556: public JGoScrollBar getHorizontalScrollBar() {
0557: return hScrollBar;
0558: }
0559:
0560: /**
0561: * Gets the first visible row of this table.
0562: *
0563: * @return first visible row
0564: */
0565: public int getFirstVisibleRow() {
0566: return lastColumn != null ? lastColumn.getFirstVisibleRow()
0567: : -1;
0568: }
0569:
0570: /**
0571: * Sets the first visible row of the table.
0572: *
0573: * @param rowIdx the first visible row of this table
0574: */
0575: public void setFirstVisibleRow(int rowIdx) {
0576: int oldIndex = firstVisibleRow;
0577:
0578: if (rowIdx >= 0 && rowIdx <= getRowCount()
0579: && oldIndex != rowIdx) {
0580: firstVisibleRow = rowIdx;
0581: layoutAllColumns(rowIdx);
0582: update(FIRST_VISIBLE_ROW_CHANGED, oldIndex, null);
0583: }
0584: }
0585:
0586: /**
0587: * Gets the last visible row in this table.
0588: *
0589: * @return last visible row
0590: */
0591: public int getLastVisibleRow() {
0592: // return lastVisibleRow;
0593: return lastColumn != null ? lastColumn.getLastVisibleRow() : -1;
0594: }
0595:
0596: /**
0597: * Gets the first visible column of the table.
0598: *
0599: * @return first visible column
0600: */
0601: public int getFirstVisibleColumn() {
0602: return firstVisibleColumn;
0603: }
0604:
0605: /**
0606: * Sets the first visible column in this table.
0607: *
0608: * @param colIdx the column to set as the first visible column
0609: */
0610: public void setFirstVisibleColumn(int colIdx) {
0611: int oldIndex = firstVisibleColumn;
0612:
0613: if (colIdx >= 0 && colIdx <= getColumnCount()
0614: && oldIndex != colIdx) {
0615: firstVisibleRow = colIdx;
0616: layoutChildren();
0617: update(FIRST_VISIBLE_COLUMN_CHANGED, oldIndex, null);
0618: }
0619: }
0620:
0621: /**
0622: * Gets the last visible column in this table.
0623: *
0624: * @return the last visible column in this table
0625: */
0626: public int getLastVisibleColumn() {
0627: return lastVisibleColumn;
0628: }
0629:
0630: private void layoutAllColumns(int rowIdx) {
0631: if (leftPortArea != null) {
0632: leftPortArea.setFirstVisibleRow(rowIdx);
0633: }
0634:
0635: if (rightPortArea != null) {
0636: rightPortArea.setFirstVisibleRow(rowIdx);
0637: }
0638:
0639: Iterator it = columnAreas.iterator();
0640: while (it.hasNext()) {
0641: ColumnArea columnArea = (ColumnArea) it.next();
0642: columnArea.setFirstVisibleRow(rowIdx);
0643: }
0644:
0645: }
0646:
0647: /**
0648: * Sets the value of a particular cell.
0649: *
0650: * @param row row to look the cell
0651: * @param col column to look for
0652: * @param val new value of the cell
0653: */
0654: public void setValueAt(int row, int col, String val) {
0655: }
0656:
0657: /**
0658: * Gets the maximum width which will allow us to show all the columns properly with no
0659: * excess whitespace surrounding the column with the longest name.
0660: *
0661: * @return maximum width of this table
0662: */
0663: public int getMaximumWidth() {
0664: Iterator it = columnAreas.iterator();
0665: int maxWidth = 0;
0666:
0667: // take the largest maximum width of all column areas into account
0668: while (it.hasNext()) {
0669: ColumnArea column = (ColumnArea) it.next();
0670: maxWidth = Math.max(maxWidth, column.getMaximumWidth());
0671: }
0672:
0673: maxWidth += getPortAreaWidth();
0674:
0675: // Always account for horizontal insets.
0676: maxWidth += getInsets().left + getInsets().right;
0677: return maxWidth;
0678: }
0679:
0680: /**
0681: * Gets the minimum width of this tables
0682: *
0683: * @return minimum width of this table
0684: */
0685: public int getMinimumWidth() {
0686: int minWidth = 0;
0687:
0688: // take the largest maximum width of all columns into account
0689: Iterator it = columnAreas.iterator();
0690: while (it.hasNext()) {
0691: ColumnArea column = (ColumnArea) it.next();
0692: minWidth = Math.max(minWidth, column.getMaximumWidth());
0693: }
0694:
0695: minWidth += getPortAreaWidth();
0696:
0697: // Always account for horizontal insets.
0698: minWidth += getInsets().left + getInsets().right;
0699: return minWidth;
0700: }
0701:
0702: /**
0703: * @return
0704: */
0705: private int getPortAreaWidth() {
0706: int portAreaWidth = 0;
0707:
0708: // we at least want to show port areas
0709: // now take the width of port areas into account
0710: if (getTableType() == TableConstants.INPUT_TABLE
0711: || getTableType() == TableConstants.INPUT_OUTPUT_TABLE) {
0712: portAreaWidth += leftPortArea != null ? leftPortArea
0713: .getMaximizePortAreaWidth() : 0;
0714: // account for gap between PortArea and ColumnArea
0715: portAreaWidth += portAreaColumnAreaGap;
0716: }
0717:
0718: if (getTableType() == TableConstants.OUTPUT_TABLE
0719: || getTableType() == TableConstants.INPUT_OUTPUT_TABLE) {
0720: portAreaWidth += rightPortArea != null ? rightPortArea
0721: .getMaximizePortAreaWidth() : 0;
0722: // account for gap between PortArea and ColumnArea
0723: portAreaWidth += portAreaColumnAreaGap;
0724: }
0725:
0726: return portAreaWidth;
0727: }
0728:
0729: /**
0730: * Gets the maximum height of this table.
0731: *
0732: * @return maximum height of table
0733: */
0734: public int getMaximumHeight() {
0735: Iterator it = columnAreas.iterator();
0736: // int maxWidth = 0;
0737: int maxHeight = 0;
0738:
0739: while (it.hasNext()) {
0740: ColumnArea column = (ColumnArea) it.next();
0741: int height = column.getMaximumHeight();
0742: if (height > maxHeight) {
0743: maxHeight = height;
0744: }
0745: }
0746:
0747: if (showHeader && getRowCount() != 0) {
0748: // accounts for height of header
0749: maxHeight += headerArea.getMaximumHeight();
0750: // account for gap between header and column
0751: maxHeight += headerColumnGap;
0752: }
0753:
0754: // account for insets
0755: maxHeight += getInsets().top + getInsets().bottom;
0756:
0757: return maxHeight;
0758: }
0759:
0760: /**
0761: * Gets the minimum height of this table.
0762: *
0763: * @return minimum height of table
0764: */
0765: public int getMinimumHeight() {
0766: // account for insets
0767: int minHeight = getInsets().top + getInsets().bottom;
0768:
0769: // account for header. we atleast want to show title always
0770: if (showHeader && getRowCount() != 0) {
0771: minHeight += headerArea.getMaximumHeight();
0772: }
0773:
0774: // account for first cell in a column we atleast want show first cell
0775: // we should add vertical spacing also + ;
0776: minHeight += getMaximumCellHeight(0);
0777: return minHeight;
0778: }
0779:
0780: /**
0781: * Gets height of the tallest column cell for a given row.
0782: *
0783: * @param row the row to look cell
0784: * @return maximum cell height in a row
0785: */
0786: public int getMaximumCellHeight(int row) {
0787: Iterator it = columnAreas.iterator();
0788: int maxHeight = 0;
0789:
0790: while (it.hasNext()) {
0791: ColumnArea column = (ColumnArea) it.next();
0792: int height = column.getCellHeight(row);
0793: if (height > maxHeight) {
0794: maxHeight = height;
0795: }
0796: }
0797: return maxHeight;
0798: }
0799:
0800: /**
0801: * Gets the height of all visible rows in this table.
0802: *
0803: * @return height of visible rows
0804: */
0805: public int getVisibleRowTableHeights() {
0806: int height = lastColumn != null ? lastColumn
0807: .getVisibleRowHeights()
0808: : 0
0809: + insets.top
0810: + insets.bottom
0811: + ((headerArea != null && showHeader && getRowCount() != 0) ? headerArea
0812: .getMaximumHeight()
0813: : 0) + headerColumnGap;
0814:
0815: return height;
0816: }
0817:
0818: private void adjustPortAreaHeight(ColumnPortArea cPortArea) {
0819: // go through the column and find out the maximum height of each row
0820: for (int i = 0; i < columnAreas.size(); i++) {
0821: int cellHeight = getMaximumCellHeight(i);
0822: cPortArea.setPortAreaHeight(i, cellHeight);
0823: }
0824: }
0825:
0826: /**
0827: * Overrides parent method to handle the changes in the geometry of this area. We will
0828: * lay out all the columns and headers again.
0829: *
0830: * @param prevRect previous bound rectangle
0831: */
0832: protected void geometryChange(Rectangle prevRect) {
0833: // handle any size changes by repositioning all the items
0834: if (!disableLayout && prevRect.width != getWidth()
0835: || prevRect.height != getHeight()) {
0836: layoutChildren();
0837: } else {
0838: super .geometryChange(prevRect);
0839: }
0840:
0841: }
0842:
0843: /**
0844: * Lays out all the children of this table area.
0845: */
0846: public void layoutChildren() {
0847: // rect.setBoundingRect(this.getBoundingRect());
0848: Insets insets1 = getInsets();
0849:
0850: // get the bounding rectangle of this table area
0851: int x = getLeft() + insets1.left;
0852: int y = getTop() + insets1.top;
0853: int width = getWidth() - insets1.left - insets1.right;
0854: int height = getHeight() - insets1.top - insets1.bottom;
0855:
0856: // calcualte the left for next column
0857: int nextColumnLeft = x;
0858:
0859: int headerHeight = 0;
0860:
0861: if (showHeader && getRowCount() != 0) {
0862: headerHeight = headerArea.getMaximumHeight();
0863: }
0864:
0865: int leftPortAreaWidth = 0;
0866: int rightPortAreaWidth = 0;
0867:
0868: // position leftportarea if it is available
0869: if (leftPortArea != null) {
0870: // this adjustment can be done in the following while loop also
0871: // do that if we see performance issues
0872: adjustPortAreaHeight(leftPortArea);
0873:
0874: // if (isExpanded()) {
0875: if (height - headerHeight - headerColumnGap > 0) {
0876: leftPortArea.setVisible(true);
0877: leftPortArea.setBoundingRect(x, y + headerHeight
0878: + headerColumnGap, leftPortArea.getWidth(),
0879: height - headerHeight - headerColumnGap);
0880:
0881: // set the top left and right corner rect bounds
0882: if (showHeader && getRowCount() != 0) {
0883: topLeftCornerRect.setVisible(true);
0884: topLeftCornerRect.setBoundingRect(x, y,
0885: leftPortArea.getWidth(), headerHeight);
0886: } else {
0887: topLeftCornerRect.setVisible(false);
0888: }
0889: } else {
0890: leftPortArea.setVisible(false);
0891: leftPortArea.setBoundingRect(x, y, leftPortArea
0892: .getWidth(), headerHeight);
0893: }
0894:
0895: leftPortAreaWidth = leftPortArea.getWidth();
0896: nextColumnLeft += leftPortAreaWidth + portAreaColumnAreaGap;
0897: }
0898:
0899: // position rightportarea if it is available
0900: if (rightPortArea != null) {
0901: adjustPortAreaHeight(rightPortArea);
0902: if (height - headerHeight - headerColumnGap > 0) {
0903: rightPortArea.setVisible(true);
0904: Rectangle rPortRect = new Rectangle(getLeft()
0905: + getWidth() - rightPortArea.getWidth()
0906: - portAreaColumnAreaGap, y + headerHeight
0907: + headerColumnGap, rightPortArea.getWidth(),
0908: height - headerHeight - headerColumnGap);
0909: rightPortArea.setBoundingRect(rPortRect);
0910: } else {
0911: rightPortArea.setVisible(false);
0912: rightPortArea.setBoundingRect(getLeft() + getWidth()
0913: - rightPortArea.getWidth()
0914: - portAreaColumnAreaGap, y, rightPortArea
0915: .getWidth(), headerHeight);
0916: }
0917:
0918: rightPortAreaWidth = rightPortArea.getWidth();
0919: }
0920:
0921: int columnWidth = 0;
0922:
0923: // divide the width among all the column equally when resizing
0924: // table externally
0925: if (resizeColumn == null && columnAreas.size() != 0) {
0926: int allColumnWidth = width - leftPortAreaWidth
0927: - rightPortAreaWidth;
0928: columnWidth = allColumnWidth / columnAreas.size();
0929: }
0930:
0931: // what is old last visible row
0932: // int oldLastVisibleRow = this.getLastVisibleRow();
0933:
0934: // go through the column and find out the maximum width of
0935: // each one of them
0936: Iterator it = columnAreas.iterator();
0937:
0938: int cumulativeWidth = getCumulativeColumnPreferredWidth();
0939:
0940: int cnt = 0;
0941: while (it.hasNext()) {
0942: ColumnArea column = (ColumnArea) it.next();
0943: columnWidth = getColumnWidth(cnt, cumulativeWidth);
0944: headerArea.setHeaderCellWidth(cnt, columnWidth);
0945:
0946: // set the column position and height, width will be column width
0947: column.setBoundingRect(nextColumnLeft, y + headerHeight
0948: + headerColumnGap, columnWidth, height
0949: - headerHeight - headerColumnGap);
0950: nextColumnLeft += columnWidth;
0951: cnt++;
0952: }
0953:
0954: if (showHeader && getRowCount() != 0) {
0955: headerArea.setBoundingRect(x + leftPortAreaWidth
0956: + portAreaColumnAreaGap, y, width
0957: - leftPortAreaWidth - rightPortAreaWidth - cnt
0958: * portAreaColumnAreaGap, headerHeight);
0959: }
0960:
0961: if (topRightCornerRect != null && showHeader
0962: && getRowCount() != 0) {
0963: topRightCornerRect.setVisible(true);
0964: topRightCornerRect.setBoundingRect(getLeft() + getWidth()
0965: - rightPortAreaWidth - portAreaColumnAreaGap, y,
0966: rightPortAreaWidth, headerHeight);
0967: } else {
0968: topRightCornerRect.setVisible(false);
0969: }
0970: }
0971:
0972: private int getColumnWidth(int columnIndex, int cumulativeWidth) {
0973: Insets insets1 = getInsets();
0974:
0975: // get the bounding rectangle of this table area
0976: int width = getWidth()
0977: - insets1.left
0978: - insets1.right
0979: - (leftPortArea != null ? leftPortArea.getWidth() : 0)
0980: - (rightPortArea != null ? rightPortArea.getWidth() : 0)
0981: - 2 * portAreaColumnAreaGap;
0982:
0983: ColumnArea column = (ColumnArea) columnAreas.get(columnIndex);
0984:
0985: // if column has preferred width then return it
0986: int preferredWidth = column.getPreferredWidth();
0987:
0988: // if we have more than one column with preffered width
0989: // we want to make sure we have enough width to accomodate
0990: // all preffered width if not we will ignore preffered width
0991: // and divide it equally among all the columns.
0992: // also if all column have preffered size set then we will
0993: // ignore it
0994: if (preferredWidth != -1
0995: && cumulativeWidth < width
0996: && getColumnCountWithPreferredWidth() != columnAreas
0997: .size()) {
0998: return preferredWidth;
0999: }
1000:
1001: int columnWidth = 0;
1002: // divide the width among all the column equally when resizing
1003: // table externally
1004: if (resizeColumn == null) {
1005: int preferredWidthColumnCount = getColumnCountWithPreferredWidth();
1006: int columnCount = columnAreas.size()
1007: - preferredWidthColumnCount;
1008: int allColumnWidth = width - cumulativeWidth;
1009:
1010: // check for divide by zero error
1011: // also if all column have preffered size set then we will ignore it
1012: if (columnCount == 0) {
1013: columnCount = columnAreas.size();
1014: allColumnWidth = width;
1015: }
1016:
1017: columnWidth = allColumnWidth / columnCount;
1018: // is there a 1 pixel excess width that needs to be allocated
1019: int excessWidth = allColumnWidth - columnWidth
1020: * columnCount;
1021: // if last column allocate any 1 pixel excess width also this
1022: // will manage scroll bar
1023: // updates
1024: if (columnIndex == columnAreas.size() - 1) {
1025: column.setManageHorizontalScrollBar(true);
1026: columnWidth += excessWidth;
1027: }
1028: }
1029:
1030: return columnWidth;
1031: }
1032:
1033: private int getCumulativeColumnPreferredWidth() {
1034: int width = 0;
1035:
1036: Iterator it = columnAreas.iterator();
1037:
1038: while (it.hasNext()) {
1039: ColumnArea column = (ColumnArea) it.next();
1040: // if column has preffered width then add it
1041: int preferredWidth = column.getPreferredWidth();
1042: if (preferredWidth != -1) {
1043: width += preferredWidth;
1044: }
1045: }
1046:
1047: return width;
1048: }
1049:
1050: /**
1051: * get the column area for this table at a particular index
1052: *
1053: * @param index column area at index
1054: * @return column area
1055: */
1056: public ColumnArea getColumnArea(int index) {
1057: if (index <= columnAreas.size() - 1) {
1058: return (ColumnArea) columnAreas.get(index);
1059: }
1060:
1061: return null;
1062: }
1063:
1064: /**
1065: * get the input port area
1066: *
1067: * @return column port area
1068: */
1069: public ColumnPortArea getInputPortArea() {
1070: return leftPortArea;
1071: }
1072:
1073: /**
1074: * get the output port area
1075: *
1076: * @return column port area
1077: */
1078: public ColumnPortArea getOutputPortArea() {
1079: return rightPortArea;
1080: }
1081:
1082: private int getColumnCountWithPreferredWidth() {
1083: int count = 0;
1084:
1085: Iterator it = columnAreas.iterator();
1086:
1087: while (it.hasNext()) {
1088: ColumnArea column = (ColumnArea) it.next();
1089: // if column has preffered width then add it
1090: int preferredWidth = column.getPreferredWidth();
1091: if (preferredWidth != -1) {
1092: count++;
1093: }
1094: }
1095: return count;
1096: }
1097:
1098: /**
1099: * get the bounds of title area this table contains
1100: *
1101: * @return the rectangle bounds of title area
1102: */
1103: public Rectangle getTitleAreaBounds() {
1104: JGoObject parent = this .getParent();
1105: if (parent != null && parent instanceof IGraphInterface) {
1106: return ((IGraphInterface) parent).getTitleAreaBounds();
1107: }
1108:
1109: return headerArea.getBoundingRect();
1110: }
1111:
1112: /**
1113: * copy new values when redo occurs
1114: *
1115: * @param e JGoDocumentChangedEdit
1116: */
1117: public void copyNewValueForRedo(JGoDocumentChangedEdit e) {
1118: switch (e.getFlags()) {
1119: case FIRST_VISIBLE_ROW_CHANGED:
1120: e.setNewValueInt(this .getFirstVisibleRow());
1121: return;
1122: default:
1123: super .copyNewValueForRedo(e);
1124: return;
1125: }
1126: }
1127:
1128: public void setShowHeader(boolean show) {
1129: this .showHeader = show;
1130: this .headerArea.setVisible(show);
1131: }
1132:
1133: /**
1134: * Updates the vertical scrollbar.
1135: */
1136: public void updateVerticalScrollBar() {
1137: // Empty as we no longer support a vertical scroll bar for TableAreas.
1138: }
1139:
1140: public void setBackgroundColor(Color c) {
1141: if (this.leftPortArea != null) {
1142: this.leftPortArea.setBackgroundColor(c);
1143: }
1144:
1145: if (this.rightPortArea != null) {
1146: this.rightPortArea.setBackgroundColor(c);
1147: }
1148:
1149: if (this.topLeftCornerRect != null) {
1150: this.topLeftCornerRect.setBrush(JGoBrush.makeStockBrush(c));
1151: }
1152:
1153: if (this.topRightCornerRect != null) {
1154: this.topRightCornerRect
1155: .setBrush(JGoBrush.makeStockBrush(c));
1156: }
1157: }
1158:
1159: }
|