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