001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041: package org.netbeans.modules.sql.framework.ui.graph.impl;
042:
043: import java.awt.Color;
044: import java.awt.Dimension;
045: import java.awt.Graphics2D;
046: import java.awt.Insets;
047: import java.awt.Rectangle;
048: import java.util.ArrayList;
049: import java.util.Iterator;
050:
051: import org.netbeans.modules.sql.framework.model.SQLDBColumn;
052: import org.netbeans.modules.sql.framework.ui.graph.IHighlightConfigurator;
053:
054: import com.nwoods.jgo.JGoBrush;
055: import com.nwoods.jgo.JGoDrawable;
056: import com.nwoods.jgo.JGoObject;
057: import com.nwoods.jgo.JGoPen;
058: import com.nwoods.jgo.JGoRectangle;
059: import com.nwoods.jgo.JGoText;
060: import com.nwoods.jgo.JGoView;
061:
062: /**
063: * @author Ritesh Adval
064: * @version $Revision$
065: */
066: public class ColumnArea extends CanvasArea {
067: protected ArrayList cells;
068: private JGoRectangle columnRect;
069: private int vSpacing = 1;
070: private JGoPen linePen = JGoPen.makeStockPen(Color.WHITE);
071:
072: // Constants for first, last visible row
073: private int firstVisibleRow = 0;
074: private int lastVisibleRow = 0;
075:
076: private int preferredWidth = -1;
077:
078: private int tableType = -1;
079:
080: private int textAlignment = JGoText.ALIGN_CENTER;
081:
082: /** Creates a new instance of ColumnArea.
083: * @param tableType
084: */
085: public ColumnArea(int tableType) {
086: super ();
087: cells = new ArrayList();
088:
089: columnRect = new JGoRectangle();
090: columnRect.setSelectable(false);
091: columnRect.setPen(JGoPen.makeStockPen(Color.WHITE));
092: this .tableType = tableType;
093: //columnRect.setBrush(JGoBrush.makeStockBrush(IHighlightConfigurator.DEFAULT_BASIC_COLOR));
094: if (tableType == TableConstants.OUTPUT_TABLE
095: || tableType == TableConstants.NO_PORT_TABLE) {
096: columnRect
097: .setBrush(JGoBrush
098: .makeStockBrush(IHighlightConfigurator.DEFAULT_TARGET_COLOR));
099: } else {
100: columnRect
101: .setBrush(JGoBrush
102: .makeStockBrush(IHighlightConfigurator.DEFAULT_BASIC_COLOR));
103: }
104: addObjectAtHead(columnRect);
105:
106: this .setSelectable(false);
107: this .setResizable(false);
108:
109: //set the insets around column
110: this .insets = TableConstants.COLUMN_INSETS;
111: }
112:
113: /**
114: * Gets the bounding graph rectangle.
115: *
116: * @return graph rectangle
117: */
118: public JGoObject getRect() {
119: return columnRect;
120: }
121:
122: /**
123: * Gets the number of rows in this column area.
124: *
125: * @return number of rows in this column
126: */
127: public int getRowCount() {
128: if (cells == null) {
129: return -1;
130: }
131: return cells.size();
132: }
133:
134: /**
135: * Adds a new cell in the column area with the given display name.
136: *
137: * @param row row in which to add a new cell
138: * @param val value for the cell at <code>row</code>
139: * @param toolTip tool tip to display for the cell
140: */
141: public void addItem(int row, String val, String toolTip) {
142: BasicCellArea cell = new BasicCellArea(val);
143: if (row == 0 || row == 1) {
144: cell = new BasicCellArea(val);
145: }
146:
147: cell.setToolTipText(toolTip);
148: add(row, cell);
149: }
150:
151: /**
152: * Adds a new cell in the column area, using the given SQLDBColumn as a data object
153: *
154: * @param row row in which to add a new cell
155: * @param data SQLDBColumn containing data for the cell at <code>row</code>
156: * @param toolTip tool tip to display for the cell
157: */
158: public void addItem(int row, SQLDBColumn data, String toolTip) {
159: BasicCellArea cell = new BasicCellArea(data.getName());
160: cell.setToolTipText(toolTip);
161: cell.setDataObject(data);
162:
163: add(row, cell);
164: }
165:
166: private void add(int row, BasicCellArea cell) {
167: cell.setTextAlignment(this .textAlignment);
168: cell.setLocation(this .getLeft(), this .getTop()
169: + this .getMaximumHeight());
170:
171: cell.setLinePen(JGoPen.makeStockPen(Color.WHITE));
172: if (tableType == TableConstants.OUTPUT_TABLE
173: || tableType == TableConstants.NO_PORT_TABLE) {
174: cell
175: .setBrush(JGoBrush
176: .makeStockBrush(IHighlightConfigurator.DEFAULT_TARGET_COLOR));
177: } else {
178: cell
179: .setBrush(JGoBrush
180: .makeStockBrush(IHighlightConfigurator.DEFAULT_BASIC_COLOR));
181: }
182: cells.add(row, cell);
183: this .addObjectAtTail(cell);
184: }
185:
186: /**
187: * Removes cell at given row.
188: *
189: * @param row row whose cell should be removed
190: */
191: public void removeItem(int row) {
192: if (row < 0 || row >= cells.size()) {
193: throw new IllegalArgumentException(
194: "Can not remove cell, specified row " + row
195: + " does not exist.");
196: }
197: BasicCellArea cell = (BasicCellArea) cells.get(row);
198: this .removeObject(cell);
199: cells.remove(row);
200: }
201:
202: /**
203: * Gets the cell at an index.
204: *
205: * @param row row to get cell from
206: * @return cell area
207: */
208: public BasicCellArea getCellAt(int row) {
209: if (row <= cells.size() - 1) {
210: return (BasicCellArea) cells.get(row);
211: }
212:
213: return null;
214: }
215:
216: /**
217: * Sets the flag if this area updates scrollbar of its parent.
218: *
219: * @param manageScrollBar boolean
220: */
221: public void setManageHorizontalScrollBar(boolean manageScrollBar) {
222: //this.manageHScrollBar = manageScrollBar;
223: }
224:
225: /**
226: * Sets the preferred width of this area.
227: *
228: * @param width preferred width
229: */
230: public void setPreferredWidth(int width) {
231: this .preferredWidth = width;
232: }
233:
234: /**
235: * Gets the preferred width of this area.
236: *
237: * @return preferred width
238: */
239: public int getPreferredWidth() {
240: return preferredWidth;
241: }
242:
243: /**
244: * Gets the index of first visible row index.
245: *
246: * @return index of first visible row index
247: */
248: public int getFirstVisibleRow() {
249: return firstVisibleRow;
250: }
251:
252: /**
253: * Sets the first visible row index.
254: *
255: * @param rowIdx first visible row index
256: */
257: public void setFirstVisibleRow(int rowIdx) {
258: int oldIndex = firstVisibleRow;
259:
260: if (rowIdx >= 0 && rowIdx <= getRowCount()
261: && oldIndex != rowIdx) {
262: firstVisibleRow = rowIdx;
263: layoutChildren();
264: }
265: }
266:
267: /**
268: * Gets the index of last visible row in this area.
269: *
270: * @return last visible row index
271: */
272: public int getLastVisibleRow() {
273: return lastVisibleRow;
274: }
275:
276: /**
277: * Gets the maximum cell width of a cell in this area.
278: *
279: * @return maximum cell width
280: */
281: public int getMaximizeCellWidth() {
282: Iterator it = cells.iterator();
283: //this is the width of widest cell
284: int w = 0;
285:
286: while (it.hasNext()) {
287: BasicCellArea cell = (BasicCellArea) it.next();
288: //need to include the insets of cell also in the width
289: int width = cell.getMaximumWidth();
290: if (width > w) {
291: w = width;
292: }
293: }
294:
295: return w;
296: }
297:
298: /**
299: * Gets the maximum cell height of a cell in this area.
300: *
301: * @return maximum cell height
302: */
303: public int getMaximizeCellHeight() {
304: Iterator it = cells.iterator();
305: //this is the height of widest cell
306: int h = 0;
307:
308: while (it.hasNext()) {
309: BasicCellArea cell = (BasicCellArea) it.next();
310:
311: int height = cell.getHeight();
312: if (height > h) {
313: h = height;
314: }
315: }
316:
317: return h;
318: }
319:
320: /**
321: * Gets the height of a cell at a given row index.
322: *
323: * @param row row
324: * @return cell height
325: */
326: public int getCellHeight(int row) {
327: int h = -1;
328: if (cells.size() > row) {
329: BasicCellArea cell = (BasicCellArea) cells.get(row);
330: return cell.getHeight();
331: }
332:
333: return h;
334: }
335:
336: /**
337: * Gets the height of all visible rows in this column.
338: *
339: * @return height of visible rows
340: */
341: public int getVisibleRowHeights() {
342: int rowHeights = 0;
343: //add insets
344: for (int i = this .getFirstVisibleRow(); i <= this
345: .getLastVisibleRow(); i++) {
346: rowHeights += getCellHeight(i) + getVerticalSpacing();
347: }
348: rowHeights += insets.top + insets.bottom - getVerticalSpacing();
349:
350: return rowHeights;
351: }
352:
353: /**
354: * Gets maximum height of this area.
355: *
356: * @return maximum height
357: */
358: public int getMaximumHeight() {
359: Iterator it = cells.iterator();
360: //this is the height of widest cell
361: int h = 0;
362:
363: while (it.hasNext()) {
364: BasicCellArea cell = (BasicCellArea) it.next();
365:
366: int height = cell.getHeight();
367: h += height + vSpacing;
368: }
369: // add insets
370: h += insets.top + insets.bottom - vSpacing;
371: return h;
372: }
373:
374: /**
375: * Gets minimum height of this area.
376: *
377: * @return minimum height
378: */
379: public int getMinimumHeight() {
380: // show at least one cell
381: return getMaximumHeight();
382: }
383:
384: /**
385: * Gets the maximum width of this area.
386: *
387: * @return maximum width
388: */
389: public int getMaximumWidth() {
390: return getMaximizeCellWidth() + insets.left + insets.right;
391: }
392:
393: /**
394: * Gets the minimum width of this area.
395: *
396: * @return minimum width
397: */
398: public int getMinimumWidth() {
399: int minWidth = getInsets().left + getInsets().right;
400:
401: //account for ... in each cell of this column
402: minWidth += 20;
403: return minWidth;
404: }
405:
406: /**
407: * Calculates the minimum size for the columnRect, as determined by the maximum item
408: * size plus insets.
409: *
410: * @return min size
411: */
412: public Dimension getMinimumRectSize() {
413: int maxW = getMaximizeCellWidth();
414: int maxH = getMaximizeCellHeight();
415:
416: // now account for insets on all sides
417: Insets insets1 = getInsets();
418:
419: int minw = maxW + insets1.left + insets1.right;
420: int minh = maxH + insets1.top + insets1.bottom;
421: return new Dimension(minw, minh);
422: }
423:
424: /**
425: * Gets the minimum size of this area.
426: *
427: * @return minimum size
428: */
429: public Dimension getMinimumSize() {
430: // first account for the minimum ListAreaRect size
431: Dimension minRect = getMinimumRectSize();
432: return minRect;
433: }
434:
435: /**
436: * Gets the vertical spacing between cells in this column area.
437: *
438: * @return vertical spacing
439: */
440: public int getVerticalSpacing() {
441: return vSpacing;
442: }
443:
444: /**
445: * Sets the vertical spacing between cells in this column area.
446: *
447: * @param newspace new space
448: */
449: public void setVerticalSpacing(int newspace) {
450: int oldSpacing = vSpacing;
451: if (oldSpacing != newspace) {
452: vSpacing = newspace;
453: layoutChildren();
454: }
455: }
456:
457: /**
458: * Gets the line pen.
459: *
460: * @return line pen
461: */
462: public JGoPen getLinePen() {
463: return linePen;
464: }
465:
466: /**
467: * Sets the line pen for border.
468: *
469: * @param pen pen
470: */
471: public void setLinePen(JGoPen pen) {
472: JGoPen oldPen = linePen;
473: if (oldPen != pen) {
474: linePen = pen;
475: layoutChildren();
476: }
477: }
478:
479: /**
480: * Paints this area.
481: *
482: * @param g Graphics2D
483: * @param view view
484: */
485: public void paint(Graphics2D g, JGoView view) {
486: super .paint(g, view);
487:
488: int penwidth = 0;
489: if (getLinePen() != null) {
490: penwidth = getLinePen().getWidth();
491: }
492: if (penwidth == 0) {
493: return;
494: }
495: JGoObject r = getRect();
496: if (r == null) {
497: return; // not yet initialized
498: }
499: Insets insets1 = getInsets();
500:
501: int rectleft = r.getLeft();
502: int recttop = r.getTop();
503: int rectwidth = r.getWidth();
504: int rectheight = r.getHeight();
505:
506: int top = recttop + insets1.top;
507: int height = rectheight - insets1.top - insets1.bottom;
508:
509: int limit = 0;
510:
511: limit = height;
512:
513: int s = 0; // height/width of visible items so far
514: for (int i = getFirstVisibleRow(); i < getLastVisibleRow(); i++) {
515: BasicCellArea cell = (BasicCellArea) cells.get(i);
516: int h = cell.getHeight();
517: s += h;
518: int sep = Math.max(penwidth, getVerticalSpacing());
519: if (s + sep <= limit) {
520: JGoDrawable.drawLine(g, getLinePen(), rectleft, top + s
521: + sep / 2, rectleft + rectwidth, top + s + sep
522: / 2);
523: }
524: s += sep;
525: }
526:
527: }
528:
529: /**
530: * Overrides parent to handle the changes in the geometry of this area. We will lay
531: * out all the cell again.
532: *
533: * @param prevRect previous rectangle bounds
534: */
535: protected void geometryChange(Rectangle prevRect) {
536: // handle any size changes by repositioning all the items
537: if (prevRect.width != getWidth()
538: || prevRect.height != getHeight()) {
539: // first set the new geometry for the rectangle
540: if (getRect() != null) {
541: Rectangle this Rect = getBoundingRect();
542: getRect().setBoundingRect(this Rect);
543: }
544:
545: // then we can lay out all the other parts
546: layoutChildren();
547:
548: } else {
549: super .geometryChange(prevRect);
550: }
551:
552: }
553:
554: /**
555: * Lays out all of this children of this column area.
556: */
557: public void layoutChildren() {
558: JGoObject r = getRect();
559: if (r == null) {
560: return;
561: } // not yet initialized
562:
563: //get the bounding rectangle of this column area
564: int x = r.getLeft() + insets.left;
565: int y = r.getTop() + insets.top;
566: int width = r.getWidth() - insets.left - insets.right;
567: int height = r.getHeight() - insets.top - insets.bottom;
568:
569: // remember last visible row index
570: lastVisibleRow = getFirstVisibleRow();
571:
572: int cellWidth = width;
573:
574: // calculate the top of next cell
575: int nextCellDeltaTop = 0;
576:
577: Iterator it = cells.iterator();
578:
579: // row count
580: int cnt = 0;
581:
582: while (it.hasNext()) {
583: BasicCellArea cell = (BasicCellArea) it.next();
584:
585: if (cnt < getFirstVisibleRow()) {
586: cell.setVisible(false);
587:
588: cnt++;
589: continue;
590: }
591:
592: //if cell is going out of the height of this area then we
593: //mark it invisible
594: if (nextCellDeltaTop + cell.getHeight() > height) {
595: cell.setVisible(false);
596:
597: } else {
598: cell.setVisible(true);
599: lastVisibleRow = cnt;
600: cell.setBoundingRect(x, y + nextCellDeltaTop,
601: cellWidth, cell.getHeight());
602: }
603:
604: //calcualte the top for next cell
605: nextCellDeltaTop += cell.getHeight() + getVerticalSpacing();
606:
607: cnt++;
608: }
609: }
610:
611: /**
612: * Sets the alignment of text in this column area to the given characteristic.
613: *
614: * @param align desired alignment characteristic; one of
615: * <UL>
616: * <LI>JGoText.ALIGN_LEFT
617: * <LI>JGoText.ALIGN_CENTER
618: * <LI>JGoText.ALIGN_RIGHT
619: * </UL>
620: */
621: public void setTextAlignment(int align) {
622: this .textAlignment = align;
623: if (cells != null) {
624: Iterator it = cells.iterator();
625: while (it.hasNext()) {
626: BasicCellArea cell = (BasicCellArea) it.next();
627: cell.setTextAlignment(align);
628: }
629: }
630: }
631: }
|