Method from javax.swing.text.TableView Detail: |
void addFill(int row,
int col) {
TableRow rv = getRow(row);
if (rv != null) {
rv.fillColumn(col);
}
}
Mark a grid location as filled in for a cells overflow. |
void calculateColumnRequirements(int axis) {
// pass 1 - single column cells
boolean hasMultiColumn = false;
int nrows = getRowCount();
for (int i = 0; i < nrows; i++) {
TableRow row = getRow(i);
int col = 0;
int ncells = row.getViewCount();
for (int cell = 0; cell < ncells; cell++, col++) {
View cv = row.getView(cell);
for (; row.isFilled(col); col++); // advance to a free column
int rowSpan = getRowsOccupied(cv);
int colSpan = getColumnsOccupied(cv);
if (colSpan == 1) {
checkSingleColumnCell(axis, col, cv);
} else {
hasMultiColumn = true;
col += colSpan - 1;
}
}
}
// pass 2 - multi-column cells
if (hasMultiColumn) {
for (int i = 0; i < nrows; i++) {
TableRow row = getRow(i);
int col = 0;
int ncells = row.getViewCount();
for (int cell = 0; cell < ncells; cell++, col++) {
View cv = row.getView(cell);
for (; row.isFilled(col); col++); // advance to a free column
int colSpan = getColumnsOccupied(cv);
if (colSpan > 1) {
checkMultiColumnCell(axis, col, colSpan, cv);
col += colSpan - 1;
}
}
}
}
/*
if (shouldTrace()) {
System.err.println("calc:");
for (int i = 0; i < columnRequirements.length; i++) {
System.err.println(" " + i + ": " + columnRequirements[i]);
}
}
*/
}
Calculate the requirements for each column. The calculation
is done as two passes over the table. The table cells that
occupy a single column are scanned first to determine the
maximum of minimum, preferred, and maximum spans along the
give axis. Table cells that span multiple columns are excluded
from the first pass. A second pass is made to determine if
the cells that span multiple columns are satisfied. If the
column requirements are not satisified, the needs of the
multi-column cell is mixed into the existing column requirements.
The calculation of the multi-column distribution is based upon
the proportions of the existing column requirements and taking
into consideration any constraining maximums. |
protected SizeRequirements calculateMinorAxisRequirements(int axis,
SizeRequirements r) {
updateGrid();
// calculate column requirements for each column
calculateColumnRequirements(axis);
// the requirements are the sum of the columns.
if (r == null) {
r = new SizeRequirements();
}
long min = 0;
long pref = 0;
long max = 0;
for (SizeRequirements req : columnRequirements) {
min += req.minimum;
pref += req.preferred;
max += req.maximum;
}
r.minimum = (int) min;
r.preferred = (int) pref;
r.maximum = (int) max;
r.alignment = 0;
return r;
}
|
void checkMultiColumnCell(int axis,
int col,
int ncols,
View v) {
// calculate the totals
long min = 0;
long pref = 0;
long max = 0;
for (int i = 0; i < ncols; i++) {
SizeRequirements req = columnRequirements[col + i];
min += req.minimum;
pref += req.preferred;
max += req.maximum;
}
// check if the minimum size needs adjustment.
int cmin = (int) v.getMinimumSpan(axis);
if (cmin > min) {
/*
* the columns that this cell spans need adjustment to fit
* this table cell.... calculate the adjustments. The
* maximum for each cell is the maximum of the existing
* maximum or the amount needed by the cell.
*/
SizeRequirements[] reqs = new SizeRequirements[ncols];
for (int i = 0; i < ncols; i++) {
SizeRequirements r = reqs[i] = columnRequirements[col + i];
r.maximum = Math.max(r.maximum, (int) v.getMaximumSpan(axis));
}
int[] spans = new int[ncols];
int[] offsets = new int[ncols];
SizeRequirements.calculateTiledPositions(cmin, null, reqs,
offsets, spans);
// apply the adjustments
for (int i = 0; i < ncols; i++) {
SizeRequirements req = reqs[i];
req.minimum = Math.max(spans[i], req.minimum);
req.preferred = Math.max(req.minimum, req.preferred);
req.maximum = Math.max(req.preferred, req.maximum);
}
}
// check if the preferred size needs adjustment.
int cpref = (int) v.getPreferredSpan(axis);
if (cpref > pref) {
/*
* the columns that this cell spans need adjustment to fit
* this table cell.... calculate the adjustments. The
* maximum for each cell is the maximum of the existing
* maximum or the amount needed by the cell.
*/
SizeRequirements[] reqs = new SizeRequirements[ncols];
for (int i = 0; i < ncols; i++) {
SizeRequirements r = reqs[i] = columnRequirements[col + i];
}
int[] spans = new int[ncols];
int[] offsets = new int[ncols];
SizeRequirements.calculateTiledPositions(cpref, null, reqs,
offsets, spans);
// apply the adjustments
for (int i = 0; i < ncols; i++) {
SizeRequirements req = reqs[i];
req.preferred = Math.max(spans[i], req.preferred);
req.maximum = Math.max(req.preferred, req.maximum);
}
}
}
check the requirements of a table cell that spans multiple
columns. |
void checkSingleColumnCell(int axis,
int col,
View v) {
SizeRequirements req = columnRequirements[col];
req.minimum = Math.max((int) v.getMinimumSpan(axis), req.minimum);
req.preferred = Math.max((int) v.getPreferredSpan(axis), req.preferred);
req.maximum = Math.max((int) v.getMaximumSpan(axis), req.maximum);
}
check the requirements of a table cell that spans a single column. |
protected TableCell createTableCell(Element elem) {
return new TableCell(elem);
} Deprecated! Table - cells can now be any arbitrary
View implementation and should be produced by the
ViewFactory rather than the table.
|
protected TableRow createTableRow(Element elem) {
return new TableRow(elem);
}
|
protected void forwardUpdate(ElementChange ec,
DocumentEvent e,
Shape a,
ViewFactory f) {
super.forwardUpdate(ec, e, a, f);
// A change in any of the table cells usually effects the whole table,
// so redraw it all!
if (a != null) {
Component c = getContainer();
if (c != null) {
Rectangle alloc = (a instanceof Rectangle) ? (Rectangle)a :
a.getBounds();
c.repaint(alloc.x, alloc.y, alloc.width, alloc.height);
}
}
}
|
int getColumnCount() {
return columnSpans.length;
}
The number of columns in the table. |
int getColumnSpan(int col) {
return columnSpans[col];
}
Fetches the span (width) of the given column.
This is used by the nested cells to query the
sizes of grid locations outside of themselves. |
int getColumnsOccupied(View v) {
// PENDING(prinz) this code should be in the html
// paragraph, but we can't add api to enable it.
AttributeSet a = v.getElement().getAttributes();
String s = (String) a.getAttribute(HTML.Attribute.COLSPAN);
if (s != null) {
try {
return Integer.parseInt(s);
} catch (NumberFormatException nfe) {
// fall through to one column
}
}
return 1;
}
Determines the number of columns occupied by
the table cell represented by given element. |
TableRow getRow(int row) {
if (row < rows.size()) {
return rows.elementAt(row);
}
return null;
}
|
int getRowCount() {
return rows.size();
}
The number of rows in the table. |
int getRowSpan(int row) {
View rv = getRow(row);
if (rv != null) {
return (int) rv.getPreferredSpan(Y_AXIS);
}
return 0;
}
Fetches the span (height) of the given row. |
int getRowsOccupied(View v) {
// PENDING(prinz) this code should be in the html
// paragraph, but we can't add api to enable it.
AttributeSet a = v.getElement().getAttributes();
String s = (String) a.getAttribute(HTML.Attribute.ROWSPAN);
if (s != null) {
try {
return Integer.parseInt(s);
} catch (NumberFormatException nfe) {
// fall through to one row
}
}
return 1;
}
Determines the number of rows occupied by
the table cell represented by given element. |
protected View getViewAtPosition(int pos,
Rectangle a) {
int n = getViewCount();
for (int i = 0; i < n; i++) {
View v = getView(i);
int p0 = v.getStartOffset();
int p1 = v.getEndOffset();
if ((pos >= p0) && (pos < p1)) {
// it's in this view.
if (a != null) {
childAllocation(i, a);
}
return v;
}
}
if (pos == getEndOffset()) {
View v = getView(n - 1);
if (a != null) {
this.childAllocation(n - 1, a);
}
return v;
}
return null;
}
Fetches the child view that represents the given position in
the model. This is implemented to walk through the children
looking for a range that contains the given position. In this
view the children do not necessarily have a one to one mapping
with the child elements. |
void invalidateGrid() {
gridValid = false;
}
|
protected void layoutColumns(int targetSpan,
int[] offsets,
int[] spans,
SizeRequirements[] reqs) {
// allocate using the convenience method on SizeRequirements
SizeRequirements.calculateTiledPositions(targetSpan, null, reqs,
offsets, spans);
}
Lays out the columns to fit within the given target span.
Returns the results through {@code offsets} and {@code spans}. |
protected void layoutMinorAxis(int targetSpan,
int axis,
int[] offsets,
int[] spans) {
// make grid is properly represented
updateGrid();
// all of the row layouts are invalid, so mark them that way
int n = getRowCount();
for (int i = 0; i < n; i++) {
TableRow row = getRow(i);
row.layoutChanged(axis);
}
// calculate column spans
layoutColumns(targetSpan, columnOffsets, columnSpans, columnRequirements);
// continue normal layout
super.layoutMinorAxis(targetSpan, axis, offsets, spans);
}
Perform layout for the minor axis of the box (i.e. the
axis orthoginal to the axis that it represents). The results
of the layout should be placed in the given arrays which represent
the allocations to the children along the minor axis. This
is called by the superclass whenever the layout needs to be
updated along the minor axis.
This is implemented to call the
layoutColumns method, and then
forward to the superclass to actually carry out the layout
of the tables rows. |
public void replace(int offset,
int length,
View[] views) {
super.replace(offset, length, views);
invalidateGrid();
}
Change the child views. This is implemented to
provide the superclass behavior and invalidate the
grid so that rows and columns will be recalculated. |
void updateGrid() {
if (! gridValid) {
// determine which views are table rows and clear out
// grid points marked filled.
rows.removeAllElements();
int n = getViewCount();
for (int i = 0; i < n; i++) {
View v = getView(i);
if (v instanceof TableRow) {
rows.addElement((TableRow) v);
TableRow rv = (TableRow) v;
rv.clearFilledColumns();
rv.setRow(i);
}
}
int maxColumns = 0;
int nrows = rows.size();
for (int row = 0; row < nrows; row++) {
TableRow rv = getRow(row);
int col = 0;
for (int cell = 0; cell < rv.getViewCount(); cell++, col++) {
View cv = rv.getView(cell);
// advance to a free column
for (; rv.isFilled(col); col++);
int rowSpan = getRowsOccupied(cv);
int colSpan = getColumnsOccupied(cv);
if ((colSpan > 1) || (rowSpan > 1)) {
// fill in the overflow entries for this cell
int rowLimit = row + rowSpan;
int colLimit = col + colSpan;
for (int i = row; i < rowLimit; i++) {
for (int j = col; j < colLimit; j++) {
if (i != row || j != col) {
addFill(i, j);
}
}
}
if (colSpan > 1) {
col += colSpan - 1;
}
}
}
maxColumns = Math.max(maxColumns, col);
}
// setup the column layout/requirements
columnSpans = new int[maxColumns];
columnOffsets = new int[maxColumns];
columnRequirements = new SizeRequirements[maxColumns];
for (int i = 0; i < maxColumns; i++) {
columnRequirements[i] = new SizeRequirements();
}
gridValid = true;
}
}
Fill in the grid locations that are placeholders
for multi-column, multi-row, and missing grid
locations. |