blob: b2d8ee05799116e89cc6798018c83b8854c2b948 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25package javax.swing.text;
26
27import java.awt.*;
28import java.util.BitSet;
29import java.util.Vector;
30import javax.swing.SizeRequirements;
31import javax.swing.event.DocumentEvent;
32
33import javax.swing.text.html.HTML;
34
35/**
36 * <p>
37 * Implements View interface for a table, that is composed of an
38 * element structure where the child elements of the element
39 * this view is responsible for represent rows and the child
40 * elements of the row elements are cells. The cell elements can
41 * have an arbitrary element structure under them, which will
42 * be built with the ViewFactory returned by the getViewFactory
43 * method.
44 * <pre>
45 *
46 * &nbsp; TABLE
47 * &nbsp; ROW
48 * &nbsp; CELL
49 * &nbsp; CELL
50 * &nbsp; ROW
51 * &nbsp; CELL
52 * &nbsp; CELL
53 *
54 * </pre>
55 * <p>
56 * This is implemented as a hierarchy of boxes, the table itself
57 * is a vertical box, the rows are horizontal boxes, and the cells
58 * are vertical boxes. The cells are allowed to span multiple
59 * columns and rows. By default, the table can be thought of as
60 * being formed over a grid (i.e. somewhat like one would find in
61 * gridbag layout), where table cells can request to span more
62 * than one grid cell. The default horizontal span of table cells
63 * will be based upon this grid, but can be changed by reimplementing
64 * the requested span of the cell (i.e. table cells can have independant
65 * spans if desired).
66 *
67 * @author Timothy Prinzing
68 * @see View
69 */
70public abstract class TableView extends BoxView {
71
72 /**
73 * Constructs a TableView for the given element.
74 *
75 * @param elem the element that this view is responsible for
76 */
77 public TableView(Element elem) {
78 super(elem, View.Y_AXIS);
79 rows = new Vector();
80 gridValid = false;
81 }
82
83 /**
84 * Creates a new table row.
85 *
86 * @param elem an element
87 * @return the row
88 */
89 protected TableRow createTableRow(Element elem) {
90 return new TableRow(elem);
91 }
92
93 /**
94 * @deprecated Table cells can now be any arbitrary
95 * View implementation and should be produced by the
96 * ViewFactory rather than the table.
97 *
98 * @param elem an element
99 * @return the cell
100 */
101 @Deprecated
102 protected TableCell createTableCell(Element elem) {
103 return new TableCell(elem);
104 }
105
106 /**
107 * The number of columns in the table.
108 */
109 int getColumnCount() {
110 return columnSpans.length;
111 }
112
113 /**
114 * Fetches the span (width) of the given column.
115 * This is used by the nested cells to query the
116 * sizes of grid locations outside of themselves.
117 */
118 int getColumnSpan(int col) {
119 return columnSpans[col];
120 }
121
122 /**
123 * The number of rows in the table.
124 */
125 int getRowCount() {
126 return rows.size();
127 }
128
129 /**
130 * Fetches the span (height) of the given row.
131 */
132 int getRowSpan(int row) {
133 View rv = getRow(row);
134 if (rv != null) {
135 return (int) rv.getPreferredSpan(Y_AXIS);
136 }
137 return 0;
138 }
139
140 TableRow getRow(int row) {
141 if (row < rows.size()) {
142 return (TableRow) rows.elementAt(row);
143 }
144 return null;
145 }
146
147 /**
148 * Determines the number of columns occupied by
149 * the table cell represented by given element.
150 */
151 /*protected*/ int getColumnsOccupied(View v) {
152 // PENDING(prinz) this code should be in the html
153 // paragraph, but we can't add api to enable it.
154 AttributeSet a = v.getElement().getAttributes();
155 String s = (String) a.getAttribute(HTML.Attribute.COLSPAN);
156 if (s != null) {
157 try {
158 return Integer.parseInt(s);
159 } catch (NumberFormatException nfe) {
160 // fall through to one column
161 }
162 }
163
164 return 1;
165 }
166
167 /**
168 * Determines the number of rows occupied by
169 * the table cell represented by given element.
170 */
171 /*protected*/ int getRowsOccupied(View v) {
172 // PENDING(prinz) this code should be in the html
173 // paragraph, but we can't add api to enable it.
174 AttributeSet a = v.getElement().getAttributes();
175 String s = (String) a.getAttribute(HTML.Attribute.ROWSPAN);
176 if (s != null) {
177 try {
178 return Integer.parseInt(s);
179 } catch (NumberFormatException nfe) {
180 // fall through to one row
181 }
182 }
183
184 return 1;
185 }
186
187 /*protected*/ void invalidateGrid() {
188 gridValid = false;
189 }
190
191 protected void forwardUpdate(DocumentEvent.ElementChange ec,
192 DocumentEvent e, Shape a, ViewFactory f) {
193 super.forwardUpdate(ec, e, a, f);
194 // A change in any of the table cells usually effects the whole table,
195 // so redraw it all!
196 if (a != null) {
197 Component c = getContainer();
198 if (c != null) {
199 Rectangle alloc = (a instanceof Rectangle) ? (Rectangle)a :
200 a.getBounds();
201 c.repaint(alloc.x, alloc.y, alloc.width, alloc.height);
202 }
203 }
204 }
205
206 /**
207 * Change the child views. This is implemented to
208 * provide the superclass behavior and invalidate the
209 * grid so that rows and columns will be recalculated.
210 */
211 public void replace(int offset, int length, View[] views) {
212 super.replace(offset, length, views);
213 invalidateGrid();
214 }
215
216 /**
217 * Fill in the grid locations that are placeholders
218 * for multi-column, multi-row, and missing grid
219 * locations.
220 */
221 void updateGrid() {
222 if (! gridValid) {
223 // determine which views are table rows and clear out
224 // grid points marked filled.
225 rows.removeAllElements();
226 int n = getViewCount();
227 for (int i = 0; i < n; i++) {
228 View v = getView(i);
229 if (v instanceof TableRow) {
230 rows.addElement(v);
231 TableRow rv = (TableRow) v;
232 rv.clearFilledColumns();
233 rv.setRow(i);
234 }
235 }
236
237 int maxColumns = 0;
238 int nrows = rows.size();
239 for (int row = 0; row < nrows; row++) {
240 TableRow rv = getRow(row);
241 int col = 0;
242 for (int cell = 0; cell < rv.getViewCount(); cell++, col++) {
243 View cv = rv.getView(cell);
244 // advance to a free column
245 for (; rv.isFilled(col); col++);
246 int rowSpan = getRowsOccupied(cv);
247 int colSpan = getColumnsOccupied(cv);
248 if ((colSpan > 1) || (rowSpan > 1)) {
249 // fill in the overflow entries for this cell
250 int rowLimit = row + rowSpan;
251 int colLimit = col + colSpan;
252 for (int i = row; i < rowLimit; i++) {
253 for (int j = col; j < colLimit; j++) {
254 if (i != row || j != col) {
255 addFill(i, j);
256 }
257 }
258 }
259 if (colSpan > 1) {
260 col += colSpan - 1;
261 }
262 }
263 }
264 maxColumns = Math.max(maxColumns, col);
265 }
266
267 // setup the column layout/requirements
268 columnSpans = new int[maxColumns];
269 columnOffsets = new int[maxColumns];
270 columnRequirements = new SizeRequirements[maxColumns];
271 for (int i = 0; i < maxColumns; i++) {
272 columnRequirements[i] = new SizeRequirements();
273 }
274 gridValid = true;
275 }
276 }
277
278 /**
279 * Mark a grid location as filled in for a cells overflow.
280 */
281 void addFill(int row, int col) {
282 TableRow rv = getRow(row);
283 if (rv != null) {
284 rv.fillColumn(col);
285 }
286 }
287
288 /**
289 * Lays out the columns to fit within the given target span.
290 * Returns the results through {@code offsets} and {@code spans}.
291 *
292 * @param targetSpan the given span for total of all the table
293 * columns
294 * @param reqs the requirements desired for each column. This
295 * is the column maximum of the cells minimum, preferred, and
296 * maximum requested span
297 * @param spans the return value of how much to allocated to
298 * each column
299 * @param offsets the return value of the offset from the
300 * origin for each column
301 */
302 protected void layoutColumns(int targetSpan, int[] offsets, int[] spans,
303 SizeRequirements[] reqs) {
304 // allocate using the convenience method on SizeRequirements
305 SizeRequirements.calculateTiledPositions(targetSpan, null, reqs,
306 offsets, spans);
307 }
308
309 /**
310 * Perform layout for the minor axis of the box (i.e. the
311 * axis orthoginal to the axis that it represents). The results
312 * of the layout should be placed in the given arrays which represent
313 * the allocations to the children along the minor axis. This
314 * is called by the superclass whenever the layout needs to be
315 * updated along the minor axis.
316 * <p>
317 * This is implemented to call the
318 * <a href="#layoutColumns">layoutColumns</a> method, and then
319 * forward to the superclass to actually carry out the layout
320 * of the tables rows.
321 *
322 * @param targetSpan the total span given to the view, which
323 * whould be used to layout the children.
324 * @param axis the axis being layed out.
325 * @param offsets the offsets from the origin of the view for
326 * each of the child views. This is a return value and is
327 * filled in by the implementation of this method.
328 * @param spans the span of each child view. This is a return
329 * value and is filled in by the implementation of this method.
330 */
331 protected void layoutMinorAxis(int targetSpan, int axis, int[] offsets, int[] spans) {
332 // make grid is properly represented
333 updateGrid();
334
335 // all of the row layouts are invalid, so mark them that way
336 int n = getRowCount();
337 for (int i = 0; i < n; i++) {
338 TableRow row = getRow(i);
339 row.layoutChanged(axis);
340 }
341
342 // calculate column spans
343 layoutColumns(targetSpan, columnOffsets, columnSpans, columnRequirements);
344
345 // continue normal layout
346 super.layoutMinorAxis(targetSpan, axis, offsets, spans);
347 }
348
349 /**
350 * Calculate the requirements for the minor axis. This is called by
351 * the superclass whenever the requirements need to be updated (i.e.
352 * a preferenceChanged was messaged through this view).
353 * <p>
354 * This is implemented to calculate the requirements as the sum of the
355 * requirements of the columns.
356 */
357 protected SizeRequirements calculateMinorAxisRequirements(int axis, SizeRequirements r) {
358 updateGrid();
359
360 // calculate column requirements for each column
361 calculateColumnRequirements(axis);
362
363
364 // the requirements are the sum of the columns.
365 if (r == null) {
366 r = new SizeRequirements();
367 }
368 long min = 0;
369 long pref = 0;
370 long max = 0;
371 for (int i = 0; i < columnRequirements.length; i++) {
372 SizeRequirements req = columnRequirements[i];
373 min += req.minimum;
374 pref += req.preferred;
375 max += req.maximum;
376 }
377 r.minimum = (int) min;
378 r.preferred = (int) pref;
379 r.maximum = (int) max;
380 r.alignment = 0;
381 return r;
382 }
383
384 /*
385 boolean shouldTrace() {
386 AttributeSet a = getElement().getAttributes();
387 Object o = a.getAttribute(HTML.Attribute.ID);
388 if ((o != null) && o.equals("debug")) {
389 return true;
390 }
391 return false;
392 }
393 */
394
395 /**
396 * Calculate the requirements for each column. The calculation
397 * is done as two passes over the table. The table cells that
398 * occupy a single column are scanned first to determine the
399 * maximum of minimum, preferred, and maximum spans along the
400 * give axis. Table cells that span multiple columns are excluded
401 * from the first pass. A second pass is made to determine if
402 * the cells that span multiple columns are satisfied. If the
403 * column requirements are not satisified, the needs of the
404 * multi-column cell is mixed into the existing column requirements.
405 * The calculation of the multi-column distribution is based upon
406 * the proportions of the existing column requirements and taking
407 * into consideration any constraining maximums.
408 */
409 void calculateColumnRequirements(int axis) {
410 // pass 1 - single column cells
411 boolean hasMultiColumn = false;
412 int nrows = getRowCount();
413 for (int i = 0; i < nrows; i++) {
414 TableRow row = getRow(i);
415 int col = 0;
416 int ncells = row.getViewCount();
417 for (int cell = 0; cell < ncells; cell++, col++) {
418 View cv = row.getView(cell);
419 for (; row.isFilled(col); col++); // advance to a free column
420 int rowSpan = getRowsOccupied(cv);
421 int colSpan = getColumnsOccupied(cv);
422 if (colSpan == 1) {
423 checkSingleColumnCell(axis, col, cv);
424 } else {
425 hasMultiColumn = true;
426 col += colSpan - 1;
427 }
428 }
429 }
430
431 // pass 2 - multi-column cells
432 if (hasMultiColumn) {
433 for (int i = 0; i < nrows; i++) {
434 TableRow row = getRow(i);
435 int col = 0;
436 int ncells = row.getViewCount();
437 for (int cell = 0; cell < ncells; cell++, col++) {
438 View cv = row.getView(cell);
439 for (; row.isFilled(col); col++); // advance to a free column
440 int colSpan = getColumnsOccupied(cv);
441 if (colSpan > 1) {
442 checkMultiColumnCell(axis, col, colSpan, cv);
443 col += colSpan - 1;
444 }
445 }
446 }
447 }
448
449 /*
450 if (shouldTrace()) {
451 System.err.println("calc:");
452 for (int i = 0; i < columnRequirements.length; i++) {
453 System.err.println(" " + i + ": " + columnRequirements[i]);
454 }
455 }
456 */
457 }
458
459 /**
460 * check the requirements of a table cell that spans a single column.
461 */
462 void checkSingleColumnCell(int axis, int col, View v) {
463 SizeRequirements req = columnRequirements[col];
464 req.minimum = Math.max((int) v.getMinimumSpan(axis), req.minimum);
465 req.preferred = Math.max((int) v.getPreferredSpan(axis), req.preferred);
466 req.maximum = Math.max((int) v.getMaximumSpan(axis), req.maximum);
467 }
468
469 /**
470 * check the requirements of a table cell that spans multiple
471 * columns.
472 */
473 void checkMultiColumnCell(int axis, int col, int ncols, View v) {
474 // calculate the totals
475 long min = 0;
476 long pref = 0;
477 long max = 0;
478 for (int i = 0; i < ncols; i++) {
479 SizeRequirements req = columnRequirements[col + i];
480 min += req.minimum;
481 pref += req.preferred;
482 max += req.maximum;
483 }
484
485 // check if the minimum size needs adjustment.
486 int cmin = (int) v.getMinimumSpan(axis);
487 if (cmin > min) {
488 /*
489 * the columns that this cell spans need adjustment to fit
490 * this table cell.... calculate the adjustments. The
491 * maximum for each cell is the maximum of the existing
492 * maximum or the amount needed by the cell.
493 */
494 SizeRequirements[] reqs = new SizeRequirements[ncols];
495 for (int i = 0; i < ncols; i++) {
496 SizeRequirements r = reqs[i] = columnRequirements[col + i];
497 r.maximum = Math.max(r.maximum, (int) v.getMaximumSpan(axis));
498 }
499 int[] spans = new int[ncols];
500 int[] offsets = new int[ncols];
501 SizeRequirements.calculateTiledPositions(cmin, null, reqs,
502 offsets, spans);
503 // apply the adjustments
504 for (int i = 0; i < ncols; i++) {
505 SizeRequirements req = reqs[i];
506 req.minimum = Math.max(spans[i], req.minimum);
507 req.preferred = Math.max(req.minimum, req.preferred);
508 req.maximum = Math.max(req.preferred, req.maximum);
509 }
510 }
511
512 // check if the preferred size needs adjustment.
513 int cpref = (int) v.getPreferredSpan(axis);
514 if (cpref > pref) {
515 /*
516 * the columns that this cell spans need adjustment to fit
517 * this table cell.... calculate the adjustments. The
518 * maximum for each cell is the maximum of the existing
519 * maximum or the amount needed by the cell.
520 */
521 SizeRequirements[] reqs = new SizeRequirements[ncols];
522 for (int i = 0; i < ncols; i++) {
523 SizeRequirements r = reqs[i] = columnRequirements[col + i];
524 }
525 int[] spans = new int[ncols];
526 int[] offsets = new int[ncols];
527 SizeRequirements.calculateTiledPositions(cpref, null, reqs,
528 offsets, spans);
529 // apply the adjustments
530 for (int i = 0; i < ncols; i++) {
531 SizeRequirements req = reqs[i];
532 req.preferred = Math.max(spans[i], req.preferred);
533 req.maximum = Math.max(req.preferred, req.maximum);
534 }
535 }
536
537 }
538
539 /**
540 * Fetches the child view that represents the given position in
541 * the model. This is implemented to walk through the children
542 * looking for a range that contains the given position. In this
543 * view the children do not necessarily have a one to one mapping
544 * with the child elements.
545 *
546 * @param pos the search position >= 0
547 * @param a the allocation to the table on entry, and the
548 * allocation of the view containing the position on exit
549 * @return the view representing the given position, or
550 * <code>null</code> if there isn't one
551 */
552 protected View getViewAtPosition(int pos, Rectangle a) {
553 int n = getViewCount();
554 for (int i = 0; i < n; i++) {
555 View v = getView(i);
556 int p0 = v.getStartOffset();
557 int p1 = v.getEndOffset();
558 if ((pos >= p0) && (pos < p1)) {
559 // it's in this view.
560 if (a != null) {
561 childAllocation(i, a);
562 }
563 return v;
564 }
565 }
566 if (pos == getEndOffset()) {
567 View v = getView(n - 1);
568 if (a != null) {
569 this.childAllocation(n - 1, a);
570 }
571 return v;
572 }
573 return null;
574 }
575
576 // ---- variables ----------------------------------------------------
577
578 int[] columnSpans;
579 int[] columnOffsets;
580 SizeRequirements[] columnRequirements;
581 Vector rows;
582 boolean gridValid;
583 static final private BitSet EMPTY = new BitSet();
584
585 /**
586 * View of a row in a row-centric table.
587 */
588 public class TableRow extends BoxView {
589
590 /**
591 * Constructs a TableView for the given element.
592 *
593 * @param elem the element that this view is responsible for
594 * @since 1.4
595 */
596 public TableRow(Element elem) {
597 super(elem, View.X_AXIS);
598 fillColumns = new BitSet();
599 }
600
601 void clearFilledColumns() {
602 fillColumns.and(EMPTY);
603 }
604
605 void fillColumn(int col) {
606 fillColumns.set(col);
607 }
608
609 boolean isFilled(int col) {
610 return fillColumns.get(col);
611 }
612
613 /** get location in the overall set of rows */
614 int getRow() {
615 return row;
616 }
617
618 /**
619 * set location in the overall set of rows, this is
620 * set by the TableView.updateGrid() method.
621 */
622 void setRow(int row) {
623 this.row = row;
624 }
625
626 /**
627 * The number of columns present in this row.
628 */
629 int getColumnCount() {
630 int nfill = 0;
631 int n = fillColumns.size();
632 for (int i = 0; i < n; i++) {
633 if (fillColumns.get(i)) {
634 nfill ++;
635 }
636 }
637 return getViewCount() + nfill;
638 }
639
640 /**
641 * Change the child views. This is implemented to
642 * provide the superclass behavior and invalidate the
643 * grid so that rows and columns will be recalculated.
644 */
645 public void replace(int offset, int length, View[] views) {
646 super.replace(offset, length, views);
647 invalidateGrid();
648 }
649
650 /**
651 * Perform layout for the major axis of the box (i.e. the
652 * axis that it represents). The results of the layout should
653 * be placed in the given arrays which represent the allocations
654 * to the children along the major axis.
655 * <p>
656 * This is re-implemented to give each child the span of the column
657 * width for the table, and to give cells that span multiple columns
658 * the multi-column span.
659 *
660 * @param targetSpan the total span given to the view, which
661 * whould be used to layout the children.
662 * @param axis the axis being layed out.
663 * @param offsets the offsets from the origin of the view for
664 * each of the child views. This is a return value and is
665 * filled in by the implementation of this method.
666 * @param spans the span of each child view. This is a return
667 * value and is filled in by the implementation of this method.
668 */
669 protected void layoutMajorAxis(int targetSpan, int axis, int[] offsets, int[] spans) {
670 int col = 0;
671 int ncells = getViewCount();
672 for (int cell = 0; cell < ncells; cell++, col++) {
673 View cv = getView(cell);
674 for (; isFilled(col); col++); // advance to a free column
675 int colSpan = getColumnsOccupied(cv);
676 spans[cell] = columnSpans[col];
677 offsets[cell] = columnOffsets[col];
678 if (colSpan > 1) {
679 int n = columnSpans.length;
680 for (int j = 1; j < colSpan; j++) {
681 // Because the table may be only partially formed, some
682 // of the columns may not yet exist. Therefore we check
683 // the bounds.
684 if ((col+j) < n) {
685 spans[cell] += columnSpans[col+j];
686 }
687 }
688 col += colSpan - 1;
689 }
690 }
691 }
692
693 /**
694 * Perform layout for the minor axis of the box (i.e. the
695 * axis orthoginal to the axis that it represents). The results
696 * of the layout should be placed in the given arrays which represent
697 * the allocations to the children along the minor axis. This
698 * is called by the superclass whenever the layout needs to be
699 * updated along the minor axis.
700 * <p>
701 * This is implemented to delegate to the superclass, then adjust
702 * the span for any cell that spans multiple rows.
703 *
704 * @param targetSpan the total span given to the view, which
705 * whould be used to layout the children.
706 * @param axis the axis being layed out.
707 * @param offsets the offsets from the origin of the view for
708 * each of the child views. This is a return value and is
709 * filled in by the implementation of this method.
710 * @param spans the span of each child view. This is a return
711 * value and is filled in by the implementation of this method.
712 */
713 protected void layoutMinorAxis(int targetSpan, int axis, int[] offsets, int[] spans) {
714 super.layoutMinorAxis(targetSpan, axis, offsets, spans);
715 int col = 0;
716 int ncells = getViewCount();
717 for (int cell = 0; cell < ncells; cell++, col++) {
718 View cv = getView(cell);
719 for (; isFilled(col); col++); // advance to a free column
720 int colSpan = getColumnsOccupied(cv);
721 int rowSpan = getRowsOccupied(cv);
722 if (rowSpan > 1) {
723 for (int j = 1; j < rowSpan; j++) {
724 // test bounds of each row because it may not exist
725 // either because of error or because the table isn't
726 // fully loaded yet.
727 int row = getRow() + j;
728 if (row < TableView.this.getViewCount()) {
729 int span = TableView.this.getSpan(Y_AXIS, getRow()+j);
730 spans[cell] += span;
731 }
732 }
733 }
734 if (colSpan > 1) {
735 col += colSpan - 1;
736 }
737 }
738 }
739
740 /**
741 * Determines the resizability of the view along the
742 * given axis. A value of 0 or less is not resizable.
743 *
744 * @param axis may be either View.X_AXIS or View.Y_AXIS
745 * @return the resize weight
746 * @exception IllegalArgumentException for an invalid axis
747 */
748 public int getResizeWeight(int axis) {
749 return 1;
750 }
751
752 /**
753 * Fetches the child view that represents the given position in
754 * the model. This is implemented to walk through the children
755 * looking for a range that contains the given position. In this
756 * view the children do not necessarily have a one to one mapping
757 * with the child elements.
758 *
759 * @param pos the search position >= 0
760 * @param a the allocation to the table on entry, and the
761 * allocation of the view containing the position on exit
762 * @return the view representing the given position, or
763 * <code>null</code> if there isn't one
764 */
765 protected View getViewAtPosition(int pos, Rectangle a) {
766 int n = getViewCount();
767 for (int i = 0; i < n; i++) {
768 View v = getView(i);
769 int p0 = v.getStartOffset();
770 int p1 = v.getEndOffset();
771 if ((pos >= p0) && (pos < p1)) {
772 // it's in this view.
773 if (a != null) {
774 childAllocation(i, a);
775 }
776 return v;
777 }
778 }
779 if (pos == getEndOffset()) {
780 View v = getView(n - 1);
781 if (a != null) {
782 this.childAllocation(n - 1, a);
783 }
784 return v;
785 }
786 return null;
787 }
788
789 /** columns filled by multi-column or multi-row cells */
790 BitSet fillColumns;
791 /** the row within the overall grid */
792 int row;
793 }
794
795 /**
796 * @deprecated A table cell can now be any View implementation.
797 */
798 @Deprecated
799 public class TableCell extends BoxView implements GridCell {
800
801 /**
802 * Constructs a TableCell for the given element.
803 *
804 * @param elem the element that this view is responsible for
805 * @since 1.4
806 */
807 public TableCell(Element elem) {
808 super(elem, View.Y_AXIS);
809 }
810
811 // --- GridCell methods -------------------------------------
812
813 /**
814 * Gets the number of columns this cell spans (e.g. the
815 * grid width).
816 *
817 * @return the number of columns
818 */
819 public int getColumnCount() {
820 return 1;
821 }
822
823 /**
824 * Gets the number of rows this cell spans (that is, the
825 * grid height).
826 *
827 * @return the number of rows
828 */
829 public int getRowCount() {
830 return 1;
831 }
832
833
834 /**
835 * Sets the grid location.
836 *
837 * @param row the row >= 0
838 * @param col the column >= 0
839 */
840 public void setGridLocation(int row, int col) {
841 this.row = row;
842 this.col = col;
843 }
844
845 /**
846 * Gets the row of the grid location
847 */
848 public int getGridRow() {
849 return row;
850 }
851
852 /**
853 * Gets the column of the grid location
854 */
855 public int getGridColumn() {
856 return col;
857 }
858
859 int row;
860 int col;
861 }
862
863 /**
864 * <em>
865 * THIS IS NO LONGER USED, AND WILL BE REMOVED IN THE
866 * NEXT RELEASE. THE JCK SIGNATURE TEST THINKS THIS INTERFACE
867 * SHOULD EXIST
868 * </em>
869 */
870 interface GridCell {
871
872 /**
873 * Sets the grid location.
874 *
875 * @param row the row >= 0
876 * @param col the column >= 0
877 */
878 public void setGridLocation(int row, int col);
879
880 /**
881 * Gets the row of the grid location
882 */
883 public int getGridRow();
884
885 /**
886 * Gets the column of the grid location
887 */
888 public int getGridColumn();
889
890 /**
891 * Gets the number of columns this cell spans (e.g. the
892 * grid width).
893 *
894 * @return the number of columns
895 */
896 public int getColumnCount();
897
898 /**
899 * Gets the number of rows this cell spans (that is, the
900 * grid height).
901 *
902 * @return the number of rows
903 */
904 public int getRowCount();
905
906 }
907
908}