svn changeset:7271/svn branch:6.0tags/6.7.0.beta1
@@ -541,6 +541,7 @@ public class IScrollTable extends FlowPanel implements Table, ScrollListener { | |||
int i = 0; | |||
int totalExplicitColumnsWidths = 0; | |||
int total = 0; | |||
float expandRatioDivider = 0; | |||
final int[] widths = new int[tHead.visibleCells.size()]; | |||
@@ -553,11 +554,18 @@ public class IScrollTable extends FlowPanel implements Table, ScrollListener { | |||
// server has defined column width explicitly | |||
totalExplicitColumnsWidths += w; | |||
} else { | |||
// get and store greater of header width and column width, and | |||
// store it as a minimumn natural col width | |||
final int hw = hCell.getOffsetWidth(); | |||
final int cw = tBody.getColWidth(i); | |||
w = (hw > cw ? hw : cw) + IScrollTableBody.CELL_EXTRA_WIDTH; | |||
if (hCell.getExpandRatio() > 0) { | |||
expandRatioDivider += hCell.getExpandRatio(); | |||
w = IScrollTableBody.CELL_EXTRA_WIDTH | |||
+ IScrollTableBody.CELL_CONTENT_PADDING; | |||
} else { | |||
// get and store greater of header width and column width, | |||
// and | |||
// store it as a minimumn natural col width | |||
final int hw = hCell.getOffsetWidth(); | |||
final int cw = tBody.getColWidth(i); | |||
w = (hw > cw ? hw : cw) + IScrollTableBody.CELL_EXTRA_WIDTH; | |||
} | |||
hCell.setNaturalMinimumColumnWidth(w); | |||
} | |||
widths[i] = w; | |||
@@ -596,7 +604,6 @@ public class IScrollTable extends FlowPanel implements Table, ScrollListener { | |||
int totalWidthR = total - totalExplicitColumnsWidths; | |||
if (totalWidthR > 0) { | |||
needsReLayout = true; | |||
/* | |||
* If the table has a relative width and there is enough space | |||
* for a scrollbar we reserve this in the last column | |||
@@ -619,23 +626,40 @@ public class IScrollTable extends FlowPanel implements Table, ScrollListener { | |||
extraSpace -= scrollbarWidthReserved; | |||
scrollbarWidthReservedInColumn = columnindex; | |||
} | |||
// now we will share this sum relatively to those without | |||
// explicit width | |||
headCells = tHead.iterator(); | |||
i = 0; | |||
HeaderCell hCell; | |||
while (headCells.hasNext()) { | |||
hCell = (HeaderCell) headCells.next(); | |||
if (hCell.getWidth() == -1) { | |||
int w = widths[i]; | |||
final int newSpace = extraSpace * w / totalWidthR; | |||
w += newSpace; | |||
widths[i] = w; | |||
if (expandRatioDivider > 0) { | |||
// visible columns have some active expand ratios, excess | |||
// space is divided according to them | |||
headCells = tHead.iterator(); | |||
i = 0; | |||
while (headCells.hasNext()) { | |||
HeaderCell hCell = (HeaderCell) headCells.next(); | |||
if (hCell.getExpandRatio() > 0) { | |||
int w = widths[i]; | |||
final int newSpace = (int) (extraSpace * (hCell | |||
.getExpandRatio() / expandRatioDivider)); | |||
w += newSpace; | |||
widths[i] = w; | |||
} | |||
i++; | |||
} | |||
} else { | |||
// now we will share this sum relatively to those without | |||
// explicit width | |||
headCells = tHead.iterator(); | |||
i = 0; | |||
while (headCells.hasNext()) { | |||
HeaderCell hCell = (HeaderCell) headCells.next(); | |||
if (hCell.getWidth() == -1) { | |||
int w = widths[i]; | |||
final int newSpace = extraSpace * w / totalWidthR; | |||
w += newSpace; | |||
widths[i] = w; | |||
} | |||
i++; | |||
} | |||
i++; | |||
} | |||
} | |||
} else { | |||
// bodys size will be more than available and scrollbar will appear | |||
} | |||
@@ -1000,6 +1024,8 @@ public class IScrollTable extends FlowPanel implements Table, ScrollListener { | |||
boolean definedWidth = false; | |||
private float expandRatio = 0; | |||
public void setSortable(boolean b) { | |||
sortable = b; | |||
} | |||
@@ -1039,6 +1065,8 @@ public class IScrollTable extends FlowPanel implements Table, ScrollListener { | |||
public void setWidth(int w, boolean ensureDefinedWidth) { | |||
if (ensureDefinedWidth) { | |||
definedWidth = true; | |||
// on column resize expand ratio becomes zero | |||
expandRatio = 0; | |||
} | |||
if (width == w) { | |||
return; | |||
@@ -1327,6 +1355,14 @@ public class IScrollTable extends FlowPanel implements Table, ScrollListener { | |||
} | |||
} | |||
public void setExpandRatio(float floatAttribute) { | |||
expandRatio = floatAttribute; | |||
} | |||
public float getExpandRatio() { | |||
return expandRatio; | |||
} | |||
} | |||
/** | |||
@@ -1441,6 +1477,9 @@ public class IScrollTable extends FlowPanel implements Table, ScrollListener { | |||
} else if (recalcWidths) { | |||
c.setUndefinedWidth(); | |||
} | |||
if (col.hasAttribute("er")) { | |||
c.setExpandRatio(col.getFloatAttribute("er")); | |||
} | |||
} | |||
// check for orphaned header cells | |||
for (String cid : availableCells.keySet()) { | |||
@@ -2556,11 +2595,14 @@ public class IScrollTable extends FlowPanel implements Table, ScrollListener { | |||
Iterator<Widget> headCells = tHead.iterator(); | |||
int usedMinimumWidth = 0; | |||
int totalExplicitColumnsWidths = 0; | |||
float expandRatioDivider = 0; | |||
while (headCells.hasNext()) { | |||
final HeaderCell hCell = (HeaderCell) headCells.next(); | |||
usedMinimumWidth += hCell.getNaturalColumnWidth(); | |||
if (hCell.isDefinedWidth()) { | |||
totalExplicitColumnsWidths += hCell.getWidth(); | |||
} else { | |||
expandRatioDivider += hCell.getExpandRatio(); | |||
} | |||
} | |||
@@ -2585,7 +2627,15 @@ public class IScrollTable extends FlowPanel implements Table, ScrollListener { | |||
hCell = (HeaderCell) headCells.next(); | |||
if (!hCell.isDefinedWidth()) { | |||
int w = hCell.getNaturalColumnWidth(); | |||
final int newSpace = w + extraSpace * w / totalWidthR; | |||
int newSpace; | |||
if (expandRatioDivider > 0) { | |||
// divide excess space by expand ratios | |||
newSpace = (int) (w + extraSpace | |||
* hCell.getExpandRatio() / expandRatioDivider); | |||
} else { | |||
// divide relatively to natural column widths | |||
newSpace = w + extraSpace * w / totalWidthR; | |||
} | |||
setColWidth(i, newSpace, false); | |||
} | |||
i++; |
@@ -0,0 +1,70 @@ | |||
package com.itmill.toolkit.tests.components.table; | |||
import com.itmill.toolkit.data.Item; | |||
import com.itmill.toolkit.data.util.IndexedContainer; | |||
import com.itmill.toolkit.tests.components.TestBase; | |||
import com.itmill.toolkit.ui.Label; | |||
import com.itmill.toolkit.ui.Table; | |||
public class ColumnExpandRatio extends TestBase { | |||
@Override | |||
protected String getDescription() { | |||
return "Column expand ratios can be used to adjust the way " | |||
+ "how excess horizontal space is divided among columns."; | |||
} | |||
@Override | |||
protected Integer getTicketNumber() { | |||
return 2806; | |||
} | |||
private static final int ROWS = 100; | |||
@Override | |||
public void setup() { | |||
Table table1 = initTable(); | |||
addComponent(new Label("Plain table")); | |||
addComponent(table1); | |||
} | |||
private Table initTable() { | |||
Table table = new Table(); | |||
table.setWidth("100%"); | |||
IndexedContainer idx = new IndexedContainer(); | |||
idx.addContainerProperty("firstname", String.class, null); | |||
idx.addContainerProperty("lastname", String.class, null); | |||
Item i = idx.addItem(1); | |||
i.getItemProperty("firstname").setValue("John"); | |||
i.getItemProperty("lastname").setValue("Johnson"); | |||
i = idx.addItem(2); | |||
i.getItemProperty("firstname").setValue("Jane"); | |||
i.getItemProperty("lastname").setValue("Janeine"); | |||
for (int index = 3; index < ROWS; index++) { | |||
i = idx.addItem(index); | |||
i.getItemProperty("firstname").setValue("Jane"); | |||
i.getItemProperty("lastname").setValue("Janeine"); | |||
} | |||
idx.addContainerProperty("fixed 50px column", String.class, ""); | |||
idx.addContainerProperty("Expanded with 2", String.class, "foobar"); | |||
table.setContainerDataSource(idx); | |||
table.setColumnHeader("firstname", "FirstName"); | |||
table.setColumnHeader("lastname", "LastName (1)"); | |||
table.setColumnWidth("fixed 50px column", 50); | |||
table.setColumnExpandRatio("Expanded with 2", 2); | |||
table.setColumnExpandRatio("lastname", 1); | |||
return table; | |||
} | |||
} |
@@ -0,0 +1,68 @@ | |||
package com.itmill.toolkit.tests.components.table; | |||
import com.itmill.toolkit.data.Item; | |||
import com.itmill.toolkit.data.util.IndexedContainer; | |||
import com.itmill.toolkit.tests.components.TestBase; | |||
import com.itmill.toolkit.ui.Label; | |||
import com.itmill.toolkit.ui.Table; | |||
public class ColumnWidths extends TestBase { | |||
@Override | |||
protected String getDescription() { | |||
return "On window resize undefined " | |||
+ "columns (by server or user (dragged)) columns " | |||
+ "must consume the excess space. Space is divided " | |||
+ "by default according to natural widths of columns." | |||
+ " Lastname should get 1/3 of excess spsace, the las column 2/3."; | |||
} | |||
@Override | |||
protected Integer getTicketNumber() { | |||
return 2804; | |||
} | |||
private static final int ROWS = 100; | |||
@Override | |||
public void setup() { | |||
Table table1 = initTable(); | |||
addComponent(new Label("Plain table")); | |||
addComponent(table1); | |||
} | |||
private Table initTable() { | |||
Table table = new Table(); | |||
table.setWidth("100%"); | |||
IndexedContainer idx = new IndexedContainer(); | |||
idx.addContainerProperty("firstname", String.class, null); | |||
idx.addContainerProperty("lastname", String.class, null); | |||
Item i = idx.addItem(1); | |||
i.getItemProperty("firstname").setValue("John"); | |||
i.getItemProperty("lastname").setValue("Johnson"); | |||
i = idx.addItem(2); | |||
i.getItemProperty("firstname").setValue("Jane"); | |||
i.getItemProperty("lastname").setValue("Janeine"); | |||
for (int index = 3; index < ROWS; index++) { | |||
i = idx.addItem(index); | |||
i.getItemProperty("firstname").setValue("Jane"); | |||
i.getItemProperty("lastname").setValue("Janeine"); | |||
} | |||
idx.addContainerProperty("150pxfixedCol", String.class, "foobar"); | |||
table.setContainerDataSource(idx); | |||
table.setColumnHeader("firstname", "FirstName"); | |||
table.setColumnHeader("lastname", "LastName"); | |||
table.setColumnWidth("150pxfixedCol", 150); | |||
return table; | |||
} | |||
} |
@@ -189,9 +189,10 @@ public class Table extends AbstractSelect implements Action.Container, | |||
private HashMap<Object, String> columnAlignments = new HashMap<Object, String>(); | |||
/** | |||
* Holds column widths in pixels for visible columns (by propertyId). | |||
* Holds column widths in pixels (Integer) or expand ratios (Float) for | |||
* visible columns (by propertyId). | |||
*/ | |||
private final HashMap<Object, Integer> columnWidths = new HashMap<Object, Integer>(); | |||
private final HashMap<Object, Object> columnWidths = new HashMap<Object, Object>(); | |||
/** | |||
* Holds column generators | |||
@@ -648,6 +649,10 @@ public class Table extends AbstractSelect implements Action.Container, | |||
* small or very big values. Setting width to -1 (default) means that theme | |||
* will make decision of width. | |||
* | |||
*<p> | |||
* Column can either have a fixed width or expand ratio. The latter one set | |||
* is used. See @link {@link #setColumnExpandRatio(Object, float)}. | |||
* | |||
* @param columnId | |||
* colunmns property id | |||
* @param width | |||
@@ -655,20 +660,78 @@ public class Table extends AbstractSelect implements Action.Container, | |||
* @since 4.0.3 | |||
*/ | |||
public void setColumnWidth(Object columnId, int width) { | |||
columnWidths.put(columnId, new Integer(width)); | |||
if (width < 0) { | |||
columnWidths.remove(columnId); | |||
} else { | |||
columnWidths.put(columnId, new Integer(width)); | |||
} | |||
} | |||
/** | |||
* Gets the width of column | |||
* Sets the column expand ratio for given column. | |||
* <p> | |||
* Expand ratios can be defined to customize the way how excess space is | |||
* divided among columns. Table can have excess space if it has its width | |||
* defined and there is horizontally more space than columns consume | |||
* naturally. Excess space is the space that is not used by columns with | |||
* explicit width (see {@link #setColumnWidth(Object, int)}) or with natural | |||
* width (no width nor expand ratio). | |||
* | |||
* <p> | |||
* By default (without expand ratios) the excess space is divided | |||
* proportionally to columns natural widths. | |||
* | |||
* <p> | |||
* Only expand ratios of visible columns are used in final calculations. | |||
* | |||
* <p> | |||
* Column can either have a fixed width or expand ratio. The latter one set | |||
* is used. | |||
* | |||
* <p> | |||
* A column with expand ratio is considered to be minimum width by default | |||
* (if no excess space exists). The minimum width is defined by terminal | |||
* implementation. | |||
* | |||
* <p> | |||
* If terminal implementation supports re-sizeable columns the column | |||
* becomes fixed width column if users resizes the column. | |||
* | |||
* @param columnId | |||
* colunmns property id | |||
* @param expandRatio | |||
* the expandRatio used to divide excess space for this column | |||
*/ | |||
public void setColumnExpandRatio(Object columnId, float expandRatio) { | |||
if (expandRatio < 0) { | |||
columnWidths.remove(columnId); | |||
} else { | |||
columnWidths.put(columnId, new Float(expandRatio)); | |||
} | |||
} | |||
public float getColumnExpandRatio(Object propertyId) { | |||
final Object width = columnWidths.get(propertyId); | |||
if (width == null || !(width instanceof Float)) { | |||
return -1; | |||
} | |||
final Float value = (Float) width; | |||
return value.floatValue(); | |||
} | |||
/** | |||
* Gets the pixel width of column | |||
* | |||
* @param propertyId | |||
* @return width of colun or -1 when value not set | |||
*/ | |||
public int getColumnWidth(Object propertyId) { | |||
final Integer value = columnWidths.get(propertyId); | |||
if (value == null) { | |||
final Object width = columnWidths.get(propertyId); | |||
if (width == null || !(width instanceof Integer)) { | |||
return -1; | |||
} | |||
final Integer value = (Integer) width; | |||
return value.intValue(); | |||
} | |||
@@ -2157,11 +2220,15 @@ public class Table extends AbstractSelect implements Action.Container, | |||
if (!ALIGN_LEFT.equals(getColumnAlignment(columnId))) { | |||
target.addAttribute("align", getColumnAlignment(columnId)); | |||
} | |||
if (getColumnWidth(columnId) > -1) { | |||
target.addAttribute("width", String | |||
.valueOf(getColumnWidth(columnId))); | |||
if (columnWidths.containsKey(columnId)) { | |||
if (getColumnWidth(columnId) > -1) { | |||
target.addAttribute("width", String | |||
.valueOf(getColumnWidth(columnId))); | |||
} else { | |||
target.addAttribute("er", | |||
getColumnExpandRatio(columnId)); | |||
} | |||
} | |||
target.endTag("column"); | |||
} | |||
} |