use of org.apache.pivot.wtk.TablePane in project pivot by apache.
the class TablePaneSkin method getPreferredColumnWidth.
/**
* Gets the preferred width of a table pane column, which is defined as the
* maximum preferred width of the column's visible components. <p> Because
* their preferred width relates to the preferred widths of other columns,
* components that span multiple columns will not be considered in this
* calculation (even if they live in the column directly). It is up to the
* caller to factor such components into the column widths calculation.
*
* @param columnIndex The index of the column whose preferred width we're
* calculating
*/
private int getPreferredColumnWidth(int columnIndex) {
TablePane tablePane = (TablePane) getComponent();
TablePane.RowSequence rows = tablePane.getRows();
int preferredWidth = 0;
for (int i = 0, n = rows.getLength(); i < n; i++) {
TablePane.Row row = rows.get(i);
if (row.getLength() > columnIndex) {
Component component = row.get(columnIndex);
if (component != null && component.isVisible() && TablePane.getColumnSpan(component) == 1) {
preferredWidth = Math.max(preferredWidth, component.getPreferredWidth(-1));
}
}
}
return preferredWidth;
}
use of org.apache.pivot.wtk.TablePane in project pivot by apache.
the class TablePaneSkin method getOccupiedCells.
/**
* Returns a grid indicating which cells are occupied. A component is said
* to occupy a cell if it is visible and either lives in the cell directly
* or spans the cell. Conversely, vacant cells do not have visible
* components within them or spanning them.
*
* @return A grid of booleans, where occupied cells are denoted by
* <tt>true</tt>, and vacant cells are denoted by <tt>false</tt>
*/
private boolean[][] getOccupiedCells() {
TablePane tablePane = (TablePane) getComponent();
TablePane.RowSequence rows = tablePane.getRows();
TablePane.ColumnSequence columns = tablePane.getColumns();
int rowCount = rows.getLength();
int columnCount = columns.getLength();
boolean[][] occupiedCells = new boolean[rowCount][columnCount];
for (int i = 0; i < rowCount; i++) {
TablePane.Row row = rows.get(i);
for (int j = 0, n = row.getLength(); j < n && j < columnCount; j++) {
Component component = row.get(j);
if (component != null && component.isVisible()) {
int rowSpan = TablePane.getRowSpan(component);
int columnSpan = TablePane.getColumnSpan(component);
for (int k = 0; k < rowSpan && i + k < rowCount; k++) {
for (int l = 0; l < columnSpan && j + l < columnCount; l++) {
occupiedCells[i + k][j + l] = true;
}
}
}
}
}
return occupiedCells;
}
use of org.apache.pivot.wtk.TablePane in project pivot by apache.
the class TablePaneSkin method layout.
@Override
public void layout() {
TablePane tablePane = (TablePane) getComponent();
TablePane.RowSequence rows = tablePane.getRows();
TablePane.ColumnSequence columns = tablePane.getColumns();
int rowCount = rows.getLength();
int columnCount = columns.getLength();
int width = getWidth();
int height = getHeight();
// NOTE We cache column widths and row heights to make getColumnAt()
// and getRowAt() more efficient
columnWidths = getColumnWidths(width);
rowHeights = getRowHeights(height, columnWidths);
// Determine which rows and column should be visible so we know which
// ones should be collapsed
boolean[] visibleRows = new boolean[rowCount];
boolean[] visibleColumns = new boolean[columnCount];
boolean[][] occupiedCells = getOccupiedCells();
for (int i = 0; i < rowCount; i++) {
for (int j = 0; j < columnCount; j++) {
if (occupiedCells[i][j]) {
visibleRows[i] = true;
visibleColumns[j] = true;
}
}
}
int componentY = padding.top;
for (int i = 0; i < rowCount; i++) {
TablePane.Row row = rows.get(i);
int componentX = padding.left;
for (int j = 0, n = row.getLength(); j < n && j < columnCount; j++) {
Component child = row.get(j);
if (child != null && child.isVisible()) {
child.setLocation(componentX, componentY);
int columnSpan = TablePane.getColumnSpan(child);
columnSpan = Math.min(columnSpan, columnCount - j);
int childWidth = (columnSpan - 1) * horizontalSpacing;
for (int k = 0; k < columnSpan && j + k < columnCount; k++) {
childWidth += columnWidths[j + k];
}
int rowSpan = TablePane.getRowSpan(child);
rowSpan = Math.min(rowSpan, rowCount - i);
int childHeight = (rowSpan - 1) * verticalSpacing;
for (int k = 0; k < rowSpan && i + k < rowCount; k++) {
childHeight += rowHeights[i + k];
}
// Set the component's size
child.setSize(Math.max(childWidth, 0), Math.max(childHeight, 0));
}
if (visibleColumns[j]) {
componentX += (columnWidths[j] + horizontalSpacing);
}
}
if (visibleRows[i]) {
componentY += (rowHeights[i] + verticalSpacing);
}
}
}
use of org.apache.pivot.wtk.TablePane in project pivot by apache.
the class TablePaneSkin method getColumnWidths.
/**
* Gets the width of each table pane column given the specified table pane
* width.
*
* @param width The width constraint of the table pane
* @return An array containing the width of each column in the table pane
* given the specified constraint
*/
private int[] getColumnWidths(int width) {
TablePane tablePane = (TablePane) getComponent();
TablePane.RowSequence rows = tablePane.getRows();
TablePane.ColumnSequence columns = tablePane.getColumns();
int rowCount = rows.getLength();
int columnCount = columns.getLength();
int[] columnWidthsLocal = new int[columnCount];
boolean[] defaultWidthColumns = new boolean[columnCount];
int totalRelativeWeight = 0;
int visibleColumnCount = 0;
int reservedWidth = padding.getWidth();
for (int j = 0; j < columnCount; j++) {
if (isColumnVisible(j)) {
TablePane.Column column = columns.get(j);
int columnWidth = column.getWidth();
if (column.isRelative()) {
columnWidthsLocal[j] = -columnWidth;
totalRelativeWeight += columnWidth;
} else {
if (columnWidth < 0) {
// Default width column; we must calculate the width
columnWidth = getPreferredColumnWidth(j);
defaultWidthColumns[j] = true;
}
columnWidthsLocal[j] = columnWidth;
reservedWidth += columnWidth;
}
visibleColumnCount++;
} else {
columnWidthsLocal[j] = 0;
}
}
if (visibleColumnCount > 1) {
reservedWidth += (visibleColumnCount - 1) * horizontalSpacing;
}
for (int i = 0; i < rowCount; i++) {
TablePane.Row row = rows.get(i);
for (int j = 0, n = row.getLength(); j < n && j < columnCount; j++) {
Component component = row.get(j);
if (component != null && component.isVisible()) {
int columnSpan = TablePane.getColumnSpan(component);
if (columnSpan > 1) {
// We might need to adjust column widths to accomodate
// this spanning cell. First, we find out if any of the
// spanned cells are default width and how much space
// we've allocated thus far for those cells
boolean adjustCells = true;
int spannedDefaultWidthCellCount = 0;
int spannedWidth = 0;
for (int k = 0; k < columnSpan && j + k < columnCount; k++) {
if (columnWidthsLocal[j + k] < 0) {
adjustCells = false;
break;
}
if (defaultWidthColumns[j + k]) {
spannedDefaultWidthCellCount++;
}
spannedWidth += columnWidthsLocal[j + k];
}
if (adjustCells && spannedDefaultWidthCellCount > 0) {
int componentPreferredWidth = component.getPreferredWidth(-1);
if (componentPreferredWidth > spannedWidth) {
// The component's preferred width is larger
// than the width we've allocated thus far, so
// an adjustment is necessary
int adjustment = componentPreferredWidth - spannedWidth;
// among the default-width columns
for (int k = 0; k < columnSpan && j + k < columnCount; k++) {
if (defaultWidthColumns[j + k]) {
int columnAdjustment = adjustment / spannedDefaultWidthCellCount;
columnWidthsLocal[j + k] += columnAdjustment;
reservedWidth += columnAdjustment;
// Adjust these to avoid rounding errors
adjustment -= columnAdjustment;
spannedDefaultWidthCellCount--;
}
}
}
}
}
}
}
}
// Finally, we allocate the widths of the relative columns by divvying
// up the remaining width
int remainingWidth = Math.max(width - reservedWidth, 0);
if (totalRelativeWeight > 0 && remainingWidth > 0) {
for (int j = 0; j < columnCount; j++) {
if (columnWidthsLocal[j] < 0) {
int relativeWeight = -columnWidthsLocal[j];
float weightPercentage = relativeWeight / (float) totalRelativeWeight;
int columnWidth = (int) (remainingWidth * weightPercentage);
columnWidthsLocal[j] = columnWidth;
// NOTE we adjust remainingWidth and totalRelativeWeight as
// we go
// to avoid potential rounding errors in the columnWidth
// calculation
remainingWidth -= columnWidth;
totalRelativeWeight -= relativeWeight;
}
}
}
return columnWidthsLocal;
}
use of org.apache.pivot.wtk.TablePane in project pivot by apache.
the class TablePaneSkin method getPreferredHeight.
@Override
public int getPreferredHeight(int width) {
TablePane tablePane = (TablePane) getComponent();
TablePane.RowSequence rows = tablePane.getRows();
TablePane.ColumnSequence columns = tablePane.getColumns();
int rowCount = rows.getLength();
int columnCount = columns.getLength();
int[] rowHeightsLocal = new int[rowCount];
int[] relativeWeights = new int[rowCount];
boolean[] defaultHeightRows = new boolean[rowCount];
int totalRelativeWeight = 0;
int widthUpdated = width;
if (widthUpdated < 0) {
widthUpdated = getPreferredWidth(-1);
}
int[] columnWidthsLocal = getColumnWidths(widthUpdated);
for (int i = 0; i < rowCount; i++) {
TablePane.Row row = rows.get(i);
int rowHeight = row.getHeight();
boolean isRelative = row.isRelative();
defaultHeightRows[i] = (rowHeight < 0);
if (isRelative) {
relativeWeights[i] = rowHeight;
totalRelativeWeight += rowHeight;
}
if (rowHeight < 0 || isRelative) {
rowHeight = getPreferredRowHeight(i, columnWidthsLocal);
}
rowHeightsLocal[i] = rowHeight;
}
if (totalRelativeWeight > 0) {
int totalRelativeHeight = 0;
for (int i = 0; i < rowCount; i++) {
int rowHeight = rowHeightsLocal[i];
int relativeWeight = relativeWeights[i];
if (relativeWeight > 0) {
float weightPercentage = relativeWeight / (float) totalRelativeWeight;
totalRelativeHeight = Math.max(totalRelativeHeight, (int) (rowHeight / weightPercentage));
}
}
for (int i = 0; i < rowCount; i++) {
int relativeWeight = relativeWeights[i];
if (relativeWeight > 0) {
float weightPercentage = relativeWeight / (float) totalRelativeWeight;
rowHeightsLocal[i] = (int) (weightPercentage * totalRelativeHeight);
}
}
}
for (int i = 0; i < rowCount; i++) {
TablePane.Row row = rows.get(i);
for (int j = 0, n = row.getLength(); j < n && j < columnCount; j++) {
Component component = row.get(j);
if (component != null && component.isVisible()) {
int rowSpan = TablePane.getRowSpan(component);
if (rowSpan > 1) {
// We might need to adjust row heights to accomodate
// this spanning cell. First, we find out if any of the
// spanned cells are default height and how much space
// we've allocated thus far for those cells
int spannedDefaultHeightCellCount = 0;
int spannedRelativeWeight = 0;
int spannedHeight = 0;
for (int k = 0; k < rowSpan && i + k < rowCount; k++) {
if (defaultHeightRows[i + k]) {
spannedDefaultHeightCellCount++;
}
spannedRelativeWeight += relativeWeights[i + k];
spannedHeight += rowHeightsLocal[i + k];
}
if (spannedRelativeWeight > 0 || spannedDefaultHeightCellCount > 0) {
int componentPreferredHeight = component.getPreferredHeight(columnWidthsLocal[j]);
if (componentPreferredHeight > spannedHeight) {
// The component's preferred height is larger
// than the height we've allocated thus far, so
// an adjustment is necessary
int adjustment = componentPreferredHeight - spannedHeight;
if (spannedRelativeWeight > 0) {
// We'll distribute the adjustment across
// the spanned relative rows and adjust
// other relative row heights to keep all
// relative row heights reconciled
float unitAdjustment = adjustment / (float) spannedRelativeWeight;
for (int k = 0; k < rowCount; k++) {
int relativeWeight = relativeWeights[k];
if (relativeWeight > 0) {
int rowAdjustment = Math.round(unitAdjustment * relativeWeight);
rowHeightsLocal[k] += rowAdjustment;
}
}
} else {
// among the default-height rows
for (int k = 0; k < rowSpan && i + k < rowCount; k++) {
if (defaultHeightRows[i + k]) {
int rowAdjustment = adjustment / spannedDefaultHeightCellCount;
rowHeightsLocal[i + k] += rowAdjustment;
// Adjust these to avoid rounding
// errors
adjustment -= rowAdjustment;
spannedDefaultHeightCellCount--;
}
}
}
}
}
}
}
}
}
// The preferred height of the table pane is the sum of the row
// heights, plus padding and spacing
boolean[][] occupiedCells = getOccupiedCells();
int visibleRowCount = 0;
int preferredHeight = padding.getHeight();
for (int i = 0; i < rowCount; i++) {
boolean rowVisible = false;
for (int j = 0; j < columnCount; j++) {
if (occupiedCells[i][j]) {
rowVisible = true;
break;
}
}
if (rowVisible) {
preferredHeight += rowHeightsLocal[i];
visibleRowCount++;
}
}
if (visibleRowCount > 1) {
preferredHeight += (visibleRowCount - 1) * verticalSpacing;
}
return preferredHeight;
}
Aggregations