History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/javax/swing/text/TableView.java (1 of 18352 files). Show all

Unified · Split

java/pkg/javax/swing/text/TableView.java+907−0
@@ -0,0 +1,907 @@
1+/*
2+ * Copyright (c) 1997, 2011, Oracle and/or its affiliates. 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. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+package javax.swing.text;
26+
27+import java.awt.*;
28+import java.util.BitSet;
29+import java.util.Vector;
30+import javax.swing.SizeRequirements;
31+import javax.swing.event.DocumentEvent;
32+
33+import 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+ */
70+public 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<TableRow>();
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 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((TableRow) 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+ * {@link #layoutColumns layoutColumns} 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 (SizeRequirements req : columnRequirements) {
372+ min += req.minimum;
373+ pref += req.preferred;
374+ max += req.maximum;
375+ }
376+ r.minimum = (int) min;
377+ r.preferred = (int) pref;
378+ r.maximum = (int) max;
379+ r.alignment = 0;
380+ return r;
381+ }
382+
383+ /*
384+ boolean shouldTrace() {
385+ AttributeSet a = getElement().getAttributes();
386+ Object o = a.getAttribute(HTML.Attribute.ID);
387+ if ((o != null) && o.equals("debug")) {
388+ return true;
389+ }
390+ return false;
391+ }
392+ */
393+
394+ /**
395+ * Calculate the requirements for each column. The calculation
396+ * is done as two passes over the table. The table cells that
397+ * occupy a single column are scanned first to determine the
398+ * maximum of minimum, preferred, and maximum spans along the
399+ * give axis. Table cells that span multiple columns are excluded
400+ * from the first pass. A second pass is made to determine if
401+ * the cells that span multiple columns are satisfied. If the
402+ * column requirements are not satisified, the needs of the
403+ * multi-column cell is mixed into the existing column requirements.
404+ * The calculation of the multi-column distribution is based upon
405+ * the proportions of the existing column requirements and taking
406+ * into consideration any constraining maximums.
407+ */
408+ void calculateColumnRequirements(int axis) {
409+ // pass 1 - single column cells
410+ boolean hasMultiColumn = false;
411+ int nrows = getRowCount();
412+ for (int i = 0; i < nrows; i++) {
413+ TableRow row = getRow(i);
414+ int col = 0;
415+ int ncells = row.getViewCount();
416+ for (int cell = 0; cell < ncells; cell++, col++) {
417+ View cv = row.getView(cell);
418+ for (; row.isFilled(col); col++); // advance to a free column
419+ int rowSpan = getRowsOccupied(cv);
420+ int colSpan = getColumnsOccupied(cv);
421+ if (colSpan == 1) {
422+ checkSingleColumnCell(axis, col, cv);
423+ } else {
424+ hasMultiColumn = true;
425+ col += colSpan - 1;
426+ }
427+ }
428+ }
429+
430+ // pass 2 - multi-column cells
431+ if (hasMultiColumn) {
432+ for (int i = 0; i < nrows; i++) {
433+ TableRow row = getRow(i);
434+ int col = 0;
435+ int ncells = row.getViewCount();
436+ for (int cell = 0; cell < ncells; cell++, col++) {
437+ View cv = row.getView(cell);
438+ for (; row.isFilled(col); col++); // advance to a free column
439+ int colSpan = getColumnsOccupied(cv);
440+ if (colSpan > 1) {
441+ checkMultiColumnCell(axis, col, colSpan, cv);
442+ col += colSpan - 1;
443+ }
444+ }
445+ }
446+ }
447+
448+ /*
449+ if (shouldTrace()) {
450+ System.err.println("calc:");
451+ for (int i = 0; i < columnRequirements.length; i++) {
452+ System.err.println(" " + i + ": " + columnRequirements[i]);
453+ }
454+ }
455+ */
456+ }
457+
458+ /**
459+ * check the requirements of a table cell that spans a single column.
460+ */
461+ void checkSingleColumnCell(int axis, int col, View v) {
462+ SizeRequirements req = columnRequirements[col];
463+ req.minimum = Math.max((int) v.getMinimumSpan(axis), req.minimum);
464+ req.preferred = Math.max((int) v.getPreferredSpan(axis), req.preferred);
465+ req.maximum = Math.max((int) v.getMaximumSpan(axis), req.maximum);
466+ }
467+
468+ /**
469+ * check the requirements of a table cell that spans multiple
470+ * columns.
471+ */
472+ void checkMultiColumnCell(int axis, int col, int ncols, View v) {
473+ // calculate the totals
474+ long min = 0;
475+ long pref = 0;
476+ long max = 0;
477+ for (int i = 0; i < ncols; i++) {
478+ SizeRequirements req = columnRequirements[col + i];
479+ min += req.minimum;
480+ pref += req.preferred;
481+ max += req.maximum;
482+ }
483+
484+ // check if the minimum size needs adjustment.
485+ int cmin = (int) v.getMinimumSpan(axis);
486+ if (cmin > min) {
487+ /*
488+ * the columns that this cell spans need adjustment to fit
489+ * this table cell.... calculate the adjustments. The
490+ * maximum for each cell is the maximum of the existing
491+ * maximum or the amount needed by the cell.
492+ */
493+ SizeRequirements[] reqs = new SizeRequirements[ncols];
494+ for (int i = 0; i < ncols; i++) {
495+ SizeRequirements r = reqs[i] = columnRequirements[col + i];
496+ r.maximum = Math.max(r.maximum, (int) v.getMaximumSpan(axis));
497+ }
498+ int[] spans = new int[ncols];
499+ int[] offsets = new int[ncols];
500+ SizeRequirements.calculateTiledPositions(cmin, null, reqs,
501+ offsets, spans);
502+ // apply the adjustments
503+ for (int i = 0; i < ncols; i++) {
504+ SizeRequirements req = reqs[i];
505+ req.minimum = Math.max(spans[i], req.minimum);
506+ req.preferred = Math.max(req.minimum, req.preferred);
507+ req.maximum = Math.max(req.preferred, req.maximum);
508+ }
509+ }
510+
511+ // check if the preferred size needs adjustment.
512+ int cpref = (int) v.getPreferredSpan(axis);
513+ if (cpref > pref) {
514+ /*
515+ * the columns that this cell spans need adjustment to fit
516+ * this table cell.... calculate the adjustments. The
517+ * maximum for each cell is the maximum of the existing
518+ * maximum or the amount needed by the cell.
519+ */
520+ SizeRequirements[] reqs = new SizeRequirements[ncols];
521+ for (int i = 0; i < ncols; i++) {
522+ SizeRequirements r = reqs[i] = columnRequirements[col + i];
523+ }
524+ int[] spans = new int[ncols];
525+ int[] offsets = new int[ncols];
526+ SizeRequirements.calculateTiledPositions(cpref, null, reqs,
527+ offsets, spans);
528+ // apply the adjustments
529+ for (int i = 0; i < ncols; i++) {
530+ SizeRequirements req = reqs[i];
531+ req.preferred = Math.max(spans[i], req.preferred);
532+ req.maximum = Math.max(req.preferred, req.maximum);
533+ }
534+ }
535+
536+ }
537+
538+ /**
539+ * Fetches the child view that represents the given position in
540+ * the model. This is implemented to walk through the children
541+ * looking for a range that contains the given position. In this
542+ * view the children do not necessarily have a one to one mapping
543+ * with the child elements.
544+ *
545+ * @param pos the search position >= 0
546+ * @param a the allocation to the table on entry, and the
547+ * allocation of the view containing the position on exit
548+ * @return the view representing the given position, or
549+ * <code>null</code> if there isn't one
550+ */
551+ protected View getViewAtPosition(int pos, Rectangle a) {
552+ int n = getViewCount();
553+ for (int i = 0; i < n; i++) {
554+ View v = getView(i);
555+ int p0 = v.getStartOffset();
556+ int p1 = v.getEndOffset();
557+ if ((pos >= p0) && (pos < p1)) {
558+ // it's in this view.
559+ if (a != null) {
560+ childAllocation(i, a);
561+ }
562+ return v;
563+ }
564+ }
565+ if (pos == getEndOffset()) {
566+ View v = getView(n - 1);
567+ if (a != null) {
568+ this.childAllocation(n - 1, a);
569+ }
570+ return v;
571+ }
572+ return null;
573+ }
574+
575+ // ---- variables ----------------------------------------------------
576+
577+ int[] columnSpans;
578+ int[] columnOffsets;
579+ SizeRequirements[] columnRequirements;
580+ Vector<TableRow> rows;
581+ boolean gridValid;
582+ static final private BitSet EMPTY = new BitSet();
583+
584+ /**
585+ * View of a row in a row-centric table.
586+ */
587+ public class TableRow extends BoxView {
588+
589+ /**
590+ * Constructs a TableView for the given element.
591+ *
592+ * @param elem the element that this view is responsible for
593+ * @since 1.4
594+ */
595+ public TableRow(Element elem) {
596+ super(elem, View.X_AXIS);
597+ fillColumns = new BitSet();
598+ }
599+
600+ void clearFilledColumns() {
601+ fillColumns.and(EMPTY);
602+ }
603+
604+ void fillColumn(int col) {
605+ fillColumns.set(col);
606+ }
607+
608+ boolean isFilled(int col) {
609+ return fillColumns.get(col);
610+ }
611+
612+ /** get location in the overall set of rows */
613+ int getRow() {
614+ return row;
615+ }
616+
617+ /**
618+ * set location in the overall set of rows, this is
619+ * set by the TableView.updateGrid() method.
620+ */
621+ void setRow(int row) {
622+ this.row = row;
623+ }
624+
625+ /**
626+ * The number of columns present in this row.
627+ */
628+ int getColumnCount() {
629+ int nfill = 0;
630+ int n = fillColumns.size();
631+ for (int i = 0; i < n; i++) {
632+ if (fillColumns.get(i)) {
633+ nfill ++;
634+ }
635+ }
636+ return getViewCount() + nfill;
637+ }
638+
639+ /**
640+ * Change the child views. This is implemented to
641+ * provide the superclass behavior and invalidate the
642+ * grid so that rows and columns will be recalculated.
643+ */
644+ public void replace(int offset, int length, View[] views) {
645+ super.replace(offset, length, views);
646+ invalidateGrid();
647+ }
648+
649+ /**
650+ * Perform layout for the major axis of the box (i.e. the
651+ * axis that it represents). The results of the layout should
652+ * be placed in the given arrays which represent the allocations
653+ * to the children along the major axis.
654+ * <p>
655+ * This is re-implemented to give each child the span of the column
656+ * width for the table, and to give cells that span multiple columns
657+ * the multi-column span.
658+ *
659+ * @param targetSpan the total span given to the view, which
660+ * whould be used to layout the children.
661+ * @param axis the axis being layed out.
662+ * @param offsets the offsets from the origin of the view for
663+ * each of the child views. This is a return value and is
664+ * filled in by the implementation of this method.
665+ * @param spans the span of each child view. This is a return
666+ * value and is filled in by the implementation of this method.
667+ */
668+ protected void layoutMajorAxis(int targetSpan, int axis, int[] offsets, int[] spans) {
669+ int col = 0;
670+ int ncells = getViewCount();
671+ for (int cell = 0; cell < ncells; cell++, col++) {
672+ View cv = getView(cell);
673+ for (; isFilled(col); col++); // advance to a free column
674+ int colSpan = getColumnsOccupied(cv);
675+ spans[cell] = columnSpans[col];
676+ offsets[cell] = columnOffsets[col];
677+ if (colSpan > 1) {
678+ int n = columnSpans.length;
679+ for (int j = 1; j < colSpan; j++) {
680+ // Because the table may be only partially formed, some
681+ // of the columns may not yet exist. Therefore we check
682+ // the bounds.
683+ if ((col+j) < n) {
684+ spans[cell] += columnSpans[col+j];
685+ }
686+ }
687+ col += colSpan - 1;
688+ }
689+ }
690+ }
691+
692+ /**
693+ * Perform layout for the minor axis of the box (i.e. the
694+ * axis orthoginal to the axis that it represents). The results
695+ * of the layout should be placed in the given arrays which represent
696+ * the allocations to the children along the minor axis. This
697+ * is called by the superclass whenever the layout needs to be
698+ * updated along the minor axis.
699+ * <p>
700+ * This is implemented to delegate to the superclass, then adjust
701+ * the span for any cell that spans multiple rows.
702+ *
703+ * @param targetSpan the total span given to the view, which
704+ * whould be used to layout the children.
705+ * @param axis the axis being layed out.
706+ * @param offsets the offsets from the origin of the view for
707+ * each of the child views. This is a return value and is
708+ * filled in by the implementation of this method.
709+ * @param spans the span of each child view. This is a return
710+ * value and is filled in by the implementation of this method.
711+ */
712+ protected void layoutMinorAxis(int targetSpan, int axis, int[] offsets, int[] spans) {
713+ super.layoutMinorAxis(targetSpan, axis, offsets, spans);
714+ int col = 0;
715+ int ncells = getViewCount();
716+ for (int cell = 0; cell < ncells; cell++, col++) {
717+ View cv = getView(cell);
718+ for (; isFilled(col); col++); // advance to a free column
719+ int colSpan = getColumnsOccupied(cv);
720+ int rowSpan = getRowsOccupied(cv);
721+ if (rowSpan > 1) {
722+ for (int j = 1; j < rowSpan; j++) {
723+ // test bounds of each row because it may not exist
724+ // either because of error or because the table isn't
725+ // fully loaded yet.
726+ int row = getRow() + j;
727+ if (row < TableView.this.getViewCount()) {
728+ int span = TableView.this.getSpan(Y_AXIS, getRow()+j);
729+ spans[cell] += span;
730+ }
731+ }
732+ }
733+ if (colSpan > 1) {
734+ col += colSpan - 1;
735+ }
736+ }
737+ }
738+
739+ /**
740+ * Determines the resizability of the view along the
741+ * given axis. A value of 0 or less is not resizable.
742+ *
743+ * @param axis may be either View.X_AXIS or View.Y_AXIS
744+ * @return the resize weight
745+ * @exception IllegalArgumentException for an invalid axis
746+ */
747+ public int getResizeWeight(int axis) {
748+ return 1;
749+ }
750+
751+ /**
752+ * Fetches the child view that represents the given position in
753+ * the model. This is implemented to walk through the children
754+ * looking for a range that contains the given position. In this
755+ * view the children do not necessarily have a one to one mapping
756+ * with the child elements.
757+ *
758+ * @param pos the search position >= 0
759+ * @param a the allocation to the table on entry, and the
760+ * allocation of the view containing the position on exit
761+ * @return the view representing the given position, or
762+ * <code>null</code> if there isn't one
763+ */
764+ protected View getViewAtPosition(int pos, Rectangle a) {
765+ int n = getViewCount();
766+ for (int i = 0; i < n; i++) {
767+ View v = getView(i);
768+ int p0 = v.getStartOffset();
769+ int p1 = v.getEndOffset();
770+ if ((pos >= p0) && (pos < p1)) {
771+ // it's in this view.
772+ if (a != null) {
773+ childAllocation(i, a);
774+ }
775+ return v;
776+ }
777+ }
778+ if (pos == getEndOffset()) {
779+ View v = getView(n - 1);
780+ if (a != null) {
781+ this.childAllocation(n - 1, a);
782+ }
783+ return v;
784+ }
785+ return null;
786+ }
787+
788+ /** columns filled by multi-column or multi-row cells */
789+ BitSet fillColumns;
790+ /** the row within the overall grid */
791+ int row;
792+ }
793+
794+ /**
795+ * @deprecated A table cell can now be any View implementation.
796+ */
797+ @Deprecated
798+ public class TableCell extends BoxView implements GridCell {
799+
800+ /**
801+ * Constructs a TableCell for the given element.
802+ *
803+ * @param elem the element that this view is responsible for
804+ * @since 1.4
805+ */
806+ public TableCell(Element elem) {
807+ super(elem, View.Y_AXIS);
808+ }
809+
810+ // --- GridCell methods -------------------------------------
811+
812+ /**
813+ * Gets the number of columns this cell spans (e.g. the
814+ * grid width).
815+ *
816+ * @return the number of columns
817+ */
818+ public int getColumnCount() {
819+ return 1;
820+ }
821+
822+ /**
823+ * Gets the number of rows this cell spans (that is, the
824+ * grid height).
825+ *
826+ * @return the number of rows
827+ */
828+ public int getRowCount() {
829+ return 1;
830+ }
831+
832+
833+ /**
834+ * Sets the grid location.
835+ *
836+ * @param row the row >= 0
837+ * @param col the column >= 0
838+ */
839+ public void setGridLocation(int row, int col) {
840+ this.row = row;
841+ this.col = col;
842+ }
843+
844+ /**
845+ * Gets the row of the grid location
846+ */
847+ public int getGridRow() {
848+ return row;
849+ }
850+
851+ /**
852+ * Gets the column of the grid location
853+ */
854+ public int getGridColumn() {
855+ return col;
856+ }
857+
858+ int row;
859+ int col;
860+ }
861+
862+ /**
863+ * <em>
864+ * THIS IS NO LONGER USED, AND WILL BE REMOVED IN THE
865+ * NEXT RELEASE. THE JCK SIGNATURE TEST THINKS THIS INTERFACE
866+ * SHOULD EXIST
867+ * </em>
868+ */
869+ interface GridCell {
870+
871+ /**
872+ * Sets the grid location.
873+ *
874+ * @param row the row >= 0
875+ * @param col the column >= 0
876+ */
877+ public void setGridLocation(int row, int col);
878+
879+ /**
880+ * Gets the row of the grid location
881+ */
882+ public int getGridRow();
883+
884+ /**
885+ * Gets the column of the grid location
886+ */
887+ public int getGridColumn();
888+
889+ /**
890+ * Gets the number of columns this cell spans (e.g. the
891+ * grid width).
892+ *
893+ * @return the number of columns
894+ */
895+ public int getColumnCount();
896+
897+ /**
898+ * Gets the number of rows this cell spans (that is, the
899+ * grid height).
900+ *
901+ * @return the number of rows
902+ */
903+ public int getRowCount();
904+
905+ }
906+
907+}