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