Source code: com/trapezium/chisel/Table.java
1 /* Table
2 *
3 * The Table organizes generic rows and columns and a header.
4 */
5
6 package com.trapezium.chisel;
7
8 import java.awt.*;
9 import java.awt.event.*;
10 import java.util.*;
11
12 //import com.trapezium.factory.*;
13 import com.trapezium.chisel.gui.ComponentFactory;
14 import com.trapezium.chisel.gui.FontPool;
15
16
17 /** Generic table component
18 */
19 public class Table extends ChiselPane {
20
21 public TableRow createRow(int row, int columns, Insets insets, Object data) {
22 return new TableRow(columns, insets);
23 }
24
25 public TableRow createHeader(int columns, Insets insets, Object data) {
26 return new TableRow(columns, insets, true);
27 }
28
29 public final static int HEADER = -1;
30
31 TableRow header;
32 Vector rows; // TableRow objects
33
34 int visibleCols; // number of columns visible
35 int visibleRows; // number of rows visible
36 int leftCol; // index of leftmost visible column
37 int topRow; // index of topmost visible row
38
39 int selectedRow; // the currently selected row
40
41 boolean collapsed = false; // show only the header if true
42
43 /** this ContainerListener implementation tracks content change (i.e.
44 Components added or removed) which occurs in any row.
45 */
46 RowTracker rowTracker = new RowTracker();
47
48 /** the width of vertical lines and height of horizontal lines between
49 columns and rows */
50 Dimension lineDim = new Dimension(1, 1);
51
52 /** remember the cell insets for when we have to create new rows */
53 private Insets cellInsets;
54
55 /** the default insets in each cell */
56 static final Insets defaultCellInsets = new Insets(0, 0, 0, 0);
57
58 public Table(int numcolumns, int numrows) {
59 this(numcolumns, numrows, defaultCellInsets, null);
60 }
61
62 public Table(int numcolumns, int numrows, Insets insets) {
63 this(numcolumns, numrows, insets, null);
64 }
65
66 public Table(int numcolumns, int numrows, Insets insets, Object data) {
67 super();
68
69 Container container = getContainer();
70 ComponentFactory.setPaneBorder(container, NO_BORDER);
71 container.setBackground(DEFAULT_TABLECOLOR);
72
73 visibleRows = numrows;
74 visibleCols = numcolumns;
75 leftCol = 0;
76 topRow = 0;
77 rows = new Vector();
78 selectedRow = -1;
79
80 cellInsets = (Insets) insets.clone();
81
82 header = createHeader(visibleCols, cellInsets, data);
83 if (header != null) {
84 container.add(header.getComponent());
85 header.getContainer().addContainerListener(rowTracker);
86 }
87
88 for (int i = 0; i < visibleRows; i++) {
89 TableRow row = createRow(i, visibleCols, cellInsets, data);
90 rows.addElement(row);
91 container.add(row.getComponent());
92 row.getContainer().addContainerListener(rowTracker);
93 }
94 }
95
96 class RowTracker implements ContainerListener {
97 public void componentAdded(ContainerEvent evt) {
98 headerHeight = -1;
99 rowHeight = -1;
100 getContainer().invalidate();
101 }
102 public void componentRemoved(ContainerEvent evt) {
103 headerHeight = -1;
104 rowHeight = -1;
105 getContainer().invalidate();
106 }
107 }
108
109
110 public boolean isCollapsed() {
111 return header != null && header.isCollapsed();
112 }
113
114 public void setCollapsed(boolean collapsed) {
115 if (isCollapsed() != collapsed) {
116 header.setCollapsed(collapsed);
117 Component component = getComponent();
118 component.invalidate();
119 component.validate();
120 }
121 }
122
123 public boolean isExpandible() {
124 return header != null && header.isExpandible();
125 }
126
127 public void setExpandible(boolean expandible) {
128 header.setExpandible(expandible);
129 }
130
131
132 public int getNumberRows() {
133 return rows.size();
134 }
135
136 public void setNumberRows(int n, Object data) {
137 if (rows.size() < n) {
138 rowHeight = -1;
139 int nrows = rows.size();
140 Container container = getContainer();
141 for (int r = nrows; r < n; r++) {
142 TableRow row = createRow(r, visibleCols, cellInsets, data);
143 rows.addElement(row);
144 container.add(row.getComponent());
145 row.getContainer().addContainerListener(rowTracker);
146 }
147 }
148 }
149
150 public TableRow getHeader() {
151 return header;
152 }
153
154 public TableRow getRow(int row) {
155 if (row >= 0 && row < rows.size()) {
156 return (TableRow) rows.elementAt(row);
157 } else {
158 return null;
159 }
160 }
161
162
163 protected Dimension getSizeForDims(int ncols, int nrows) {
164 Insets insets = getContainer().getInsets();
165 int width = ncols * getColumnWidth() + insets.left + insets.right;
166 int height = getRowHeight(HEADER) + insets.top + insets.bottom;
167 for (int i = 0; i < nrows; i++) {
168 height += getRowHeight(i);
169 }
170 return new Dimension(width, height);
171 }
172
173 private transient int colWidth = -1; // calculated width of column
174 private transient int rowHeight = -1; // calculated height of row
175 private transient int headerHeight = -1; // calculated height of header
176 protected int getColumnWidth() {
177 if (colWidth < 0) {
178 colWidth = 10 * getEmWidth(false) + cellInsets.left + cellInsets.right + lineDim.width;
179 }
180 return colWidth;
181 }
182 protected int getRowHeight(int row) {
183 if (row == HEADER) {
184 if (headerHeight <= 0) {
185 if (header != null) {
186 headerHeight = header.getComponent().getPreferredSize().height;
187 } else {
188 headerHeight = 0;
189 }
190 }
191 return headerHeight;
192
193 } else {
194 /*****
195 if (rowHeight <= 0) {
196 rowHeight = 0;
197 for (int i = 0; i < rows.size(); i++) {
198 TableRow row = (TableRow) rows.elementAt(i);
199 Dimension prefsize = row.getComponent().getPreferredSize();
200 if (rowHeight < prefsize.height) {
201 rowHeight = prefsize.height;
202 }
203 }
204 } ***/
205 int height;
206 if (row < rows.size()) {
207 height = ((TableRow) rows.elementAt(row)).getComponent().getPreferredSize().height;
208 if (rowHeight <= 0) {
209 rowHeight = height;
210 }
211 } else {
212 height = rowHeight;
213 }
214 return height;
215 }
216 }
217
218 public int getEmWidth(boolean header) {
219 return getComponent().getFontMetrics((header ? FontPool.getHeaderFont(0) : FontPool.getFont(0))).charWidth('M');
220 }
221
222 public Dimension preferredLayoutSize(Container target) {
223 int numrows = isCollapsed() ? 0 : getNumberRows();
224
225 while (numrows > 0) {
226 TableRow row = getRow(numrows - 1);
227 if (!row.isEmpty()) {
228 break;
229 }
230 numrows--;
231 }
232 return getSizeForDims(visibleCols, numrows);
233 }
234
235 public Dimension minimumLayoutSize(Container target) {
236 return getSizeForDims(1, 0);
237 }
238
239 public void layoutContainer(Container target) {
240 Dimension size = target.getSize();
241 Insets insets = target.getInsets();
242
243 int x = insets.left;
244 int y = insets.top;
245
246 int width = size.width - insets.left - insets.right;
247 int headerheight = getRowHeight(HEADER);
248 int yvisbottom = size.height - insets.bottom;
249
250 if (header != null) {
251 header.getComponent().reshape(x, y, width, headerheight);
252 }
253
254 int nrows = (collapsed ? 0 : rows.size());
255
256 y += headerheight;
257
258 for (int i = 0; i < nrows; i++) {
259 TableRow row = (TableRow) rows.elementAt(i);
260 int rowheight = getRowHeight(i);
261 row.getComponent().reshape(x, y, width, rowheight);
262 y += rowheight;
263 //if (y >= yvisbottom) {
264 // break;
265 //}
266 }
267
268 }
269
270
271 /** dump the current document to the console */
272 public void dump() {
273 }
274 }
275