Browse Source

Added tooltips to Table cells and rows (ItemDescriptionGenerator) + Testbench test for them #5414

svn changeset:20392/svn branch:6.7
tags/6.7.0.beta1
John Alhroos 13 years ago
parent
commit
5737ec8704

+ 70
- 4
src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java View File

@@ -63,9 +63,11 @@ import com.vaadin.terminal.gwt.client.Focusable;
import com.vaadin.terminal.gwt.client.MouseEventDetails;
import com.vaadin.terminal.gwt.client.Paintable;
import com.vaadin.terminal.gwt.client.RenderSpace;
import com.vaadin.terminal.gwt.client.TooltipInfo;
import com.vaadin.terminal.gwt.client.UIDL;
import com.vaadin.terminal.gwt.client.Util;
import com.vaadin.terminal.gwt.client.VConsole;
import com.vaadin.terminal.gwt.client.VTooltip;
import com.vaadin.terminal.gwt.client.ui.VScrollTable.VScrollTableBody.VScrollTableRow;
import com.vaadin.terminal.gwt.client.ui.dd.DDUtil;
import com.vaadin.terminal.gwt.client.ui.dd.VAbstractDropHandler;
@@ -4039,7 +4041,14 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,

private void unlinkRowAtIndex(int index) {
final VScrollTableRow toBeRemoved = (VScrollTableRow) renderedRows
.get(index);
.get(index);
// Unregister row tooltip
client.registerTooltip(VScrollTable.this, toBeRemoved.getElement(), null);
for(int i=0; i<toBeRemoved.getElement().getChildCount(); i++){
// Unregister cell tooltips
Element td = toBeRemoved.getElement().getChild(i).cast();
client.registerTooltip(VScrollTable.this, td, null);
}
lazyUnregistryBag.add(toBeRemoved);
tBodyElement.removeChild(toBeRemoved.getElement());
orphan(toBeRemoved);
@@ -4281,7 +4290,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
setElement(rowElement);
DOM.sinkEvents(getElement(), Event.MOUSEEVENTS
| Event.TOUCHEVENTS | Event.ONDBLCLICK
| Event.ONCONTEXTMENU);
| Event.ONCONTEXTMENU | VTooltip.TOOLTIP_EVENTS);
}

/**
@@ -4387,6 +4396,12 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
if (rowStyle != null) {
addStyleName(CLASSNAME + "-row-" + rowStyle);
}
String rowDescription = uidl.getStringAttribute("rowdescr");
if(rowDescription != null && !rowDescription.equals("")) {
TooltipInfo info = new TooltipInfo(rowDescription);
client.registerTooltip(VScrollTable.this, rowElement, info);
}

tHead.getColumnAlignments();
int col = 0;
@@ -4416,10 +4431,15 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
style = uidl.getStringAttribute("style-" + columnId);
}

String description = null;
if(uidl.hasAttribute("descr-" + columnId)) {
description = uidl.getStringAttribute("descr-"+columnId);
}
boolean sorted = tHead.getHeaderCell(col).isSorted();
if (cell instanceof String) {
addCell(uidl, cell.toString(), aligns[col++], style,
false, sorted);
false, sorted, description);
} else {
final Paintable cellContent = client
.getPaintable((UIDL) cell);
@@ -4444,7 +4464,12 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
}

public void addCell(UIDL rowUidl, String text, char align,
String style, boolean textIsHTML, boolean sorted) {
String style, boolean textIsHTML, boolean sorted){
addCell(rowUidl, text, align, style, textIsHTML, sorted, null);
}
public void addCell(UIDL rowUidl, String text, char align,
String style, boolean textIsHTML, boolean sorted, String description) {
// String only content is optimized by not using Label widget
final Element td = DOM.createTD();
final Element container = DOM.createDiv();
@@ -4473,6 +4498,12 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
break;
}
}
if(description != null && client != null){
TooltipInfo info = new TooltipInfo(description);
client.registerTooltip(VScrollTable.this, td, info);
}
td.appendChild(container);
getElement().appendChild(td);
}
@@ -4572,6 +4603,37 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
}
}

private void handleTooltips(final Event event, Element target){
if(target.hasTagName("TD")){
// Table cell (td)
Element container = target.getFirstChildElement().cast();
Element widget = container.getFirstChildElement().cast();
boolean containsWidget = false;
for(Widget w : childWidgets){
if(widget == w.getElement()){
containsWidget = true;
break;
}
}
if(!containsWidget){
// Only text nodes has tooltips
if(client.getTooltipTitleInfo(VScrollTable.this, target) != null){
// Cell has description, use it
client.handleTooltipEvent(event, VScrollTable.this, target);
} else {
// Cell might have row description, use row description
client.handleTooltipEvent(event, VScrollTable.this, target.getParentElement());
}
}
} else {
// Table row (tr)
client.handleTooltipEvent(event, VScrollTable.this, target);
}
}
/*
* React on click that occur on content cells only
*/
@@ -4596,6 +4658,10 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
}

boolean targetCellOrRowFound = targetTdOrTr != null;
if(targetCellOrRowFound){
handleTooltips(event, targetTdOrTr);
}
switch (type) {
case Event.ONDBLCLICK:
if (targetCellOrRowFound) {

+ 19
- 0
src/com/vaadin/ui/AbstractSelect.java View File

@@ -1931,4 +1931,23 @@ public abstract class AbstractSelect extends AbstractField implements
}
}

/**
* Implement this interface and pass it to Tree.setCellStyleGenerator or Table.setCellStyleGenerator to
* generate mouse over descriptions ("tooltips") for the rows and cells in Table or for the items in Tree.
*/
public interface ItemDescriptionGenerator {
/**
* Called by Table when a cell (and row) is painted or a item is painted in Tree
* @param source
* The source of the generator, the Tree or Table the generator is attached to
* @param itemId
* The itemId of the painted cell
* @param propertyId
* The propertyId of the cell, null when getting row description
* @return
* The description or "tooltip" of the item.
*/
public String generateDescription(Component source, Object itemId, Object propertyId);
}
}

+ 53
- 4
src/com/vaadin/ui/Table.java View File

@@ -46,6 +46,7 @@ import com.vaadin.terminal.Resource;
import com.vaadin.terminal.gwt.client.MouseEventDetails;
import com.vaadin.terminal.gwt.client.ui.VScrollTable;
import com.vaadin.terminal.gwt.client.ui.dd.VLazyInitItemIdentifiers;
import com.vaadin.ui.AbstractSelect.ItemDescriptionGenerator;

/**
* <p>
@@ -378,6 +379,11 @@ public class Table extends AbstractSelect implements Action.Container,
* Table cell specific style generator
*/
private CellStyleGenerator cellStyleGenerator = null;
/**
* Table cell specific tooltip generator
*/
private ItemDescriptionGenerator itemDescriptionGenerator;

/*
* EXPERIMENTAL feature: will tell the client to re-calculate column widths
@@ -2862,7 +2868,8 @@ public class Table extends AbstractSelect implements Action.Container,
target.addAttribute("style-" + columnIdMap.key(columnId),
cellStyle);
}
}
}
if ((iscomponent[currentColumn] || iseditable)
&& Component.class.isInstance(cells[CELL_FIRSTCOL
+ currentColumn][indexInRowbuffer])) {
@@ -2870,16 +2877,36 @@ public class Table extends AbstractSelect implements Action.Container,
+ currentColumn][indexInRowbuffer];
if (c == null) {
target.addText("");
paintCellTooltips(target, itemId, columnId);
} else {
c.paint(target);
}
} else {
target.addText((String) cells[CELL_FIRSTCOL + currentColumn][indexInRowbuffer]);
target.addText((String) cells[CELL_FIRSTCOL + currentColumn][indexInRowbuffer]);
paintCellTooltips(target, itemId, columnId);
}
}

target.endTag("tr");
}
private void paintCellTooltips(PaintTarget target, Object itemId, Object columnId) throws PaintException {
if(itemDescriptionGenerator != null) {
String itemDescription = itemDescriptionGenerator.generateDescription(this, itemId, columnId);
if(itemDescription != null && !itemDescription.equals("")) {
target.addAttribute("descr-" + columnIdMap.key(columnId), itemDescription);
}
}
}
private void paintRowTooltips(PaintTarget target, Object itemId ) throws PaintException {
if(itemDescriptionGenerator != null) {
String rowDescription = itemDescriptionGenerator.generateDescription(this, itemId, null);
if(rowDescription != null && !rowDescription.equals("")){
target.addAttribute("rowdescr", rowDescription);
}
}
}

private void paintRowAttributes(PaintTarget target, final Object[][] cells,
final Set<Action> actionSet, int indexInRowbuffer,
@@ -2921,8 +2948,11 @@ public class Table extends AbstractSelect implements Action.Container,
if (rowStyle != null && !rowStyle.equals("")) {
target.addAttribute("rowstyle", rowStyle);
}
}
paintRowAttributes(target, itemId);
}
paintRowTooltips(target, itemId);
paintRowAttributes(target, itemId);
}

protected void paintRowHeader(PaintTarget target, Object[][] cells,
@@ -4547,5 +4577,24 @@ public class Table extends AbstractSelect implements Action.Container,
removeListener(VScrollTable.COLUMN_REORDER_EVENT_ID,
ColumnReorderEvent.class, listener);
}
/**
* Set the item description generator which generates tooltips
* for cells and rows in the Table
*
* @param generator
* The generator to use or null to disable
*/
public void setItemDescriptionGenerator(ItemDescriptionGenerator generator){
itemDescriptionGenerator = generator;
}
/**
* Get the item description generator which generates tooltips
* for cells and rows in the Table.
*/
public ItemDescriptionGenerator getItemDescriptionGenerator(){
return itemDescriptionGenerator;
}

}

+ 75
- 0
tests/src/com/vaadin/tests/components/table/TableItemDescriptionGeneratorTest.java View File

@@ -0,0 +1,75 @@
package com.vaadin.tests.components.table;

import com.vaadin.data.Container;
import com.vaadin.data.Item;
import com.vaadin.data.util.IndexedContainer;
import com.vaadin.tests.components.TestBase;
import com.vaadin.ui.Button;
import com.vaadin.ui.Component;
import com.vaadin.ui.Label;
import com.vaadin.ui.Table;
import com.vaadin.ui.AbstractSelect.ItemDescriptionGenerator;
import com.vaadin.ui.TextField;

public class TableItemDescriptionGeneratorTest extends TestBase {

private final String COLUMN1_PROPERTY_ID = "Text - Cell description";
private final String COLUMN2_PROPERTY_ID = "Text - Row description";
private final String COLUMN3_PROPERTY_ID = "Widget";
@Override
protected void setup() {
final Table table = new Table();
table.setDebugId("table");
table.setContainerDataSource(createContainer());
addComponent(table);
table.setItemDescriptionGenerator(new ItemDescriptionGenerator() {
public String generateDescription(Component source, Object itemId,
Object propertyId) {
if(propertyId == null){
return "Row description "+ itemId;
} else if(propertyId == COLUMN1_PROPERTY_ID) {
return "Cell description " + itemId +","+propertyId;
}
return null;
}
});
table.addGeneratedColumn(COLUMN3_PROPERTY_ID, new Table.ColumnGenerator() {
public Component generateCell(Table source, Object itemId, Object columnId) {
TextField lbl = new TextField();
lbl.setDescription("Textfields own description");
return lbl;
}
});
}

@Override
protected String getDescription() {
return "Cells and rows should have tooltips";
}

@Override
protected Integer getTicketNumber() {
return 5414;
}
private Container createContainer() {
IndexedContainer container = new IndexedContainer();
container.addContainerProperty(COLUMN1_PROPERTY_ID, String.class, "");
container.addContainerProperty(COLUMN2_PROPERTY_ID, String.class, "");
// container.addContainerProperty(COLUMN3_PROPERTY_ID, String.class, "");

for (int i = 0; i < 5; i++) {
Item item = container.addItem("item " + i);
item.getItemProperty(COLUMN1_PROPERTY_ID).setValue("first" + i);
item.getItemProperty(COLUMN2_PROPERTY_ID).setValue("middle" + i);
// item.getItemProperty(COLUMN3_PROPERTY_ID).setValue("last" + i);
}

return container;
}

}

+ 77
- 0
tests/src/com/vaadin/tests/components/table/TableTooltips.html View File

@@ -0,0 +1,77 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head profile="http://selenium-ide.openqa.org/profiles/test-case">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link rel="selenium.base" href="" />
<title>New Test</title>
</head>
<body>
<table cellpadding="1" cellspacing="1" border="1">
<thead>
<tr><td rowspan="1" colspan="3">New Test</td></tr>
</thead><tbody>
<tr>
<td>open</td>
<td>/run/com.vaadin.tests.components.table.TableItemDescriptionGeneratorTest?restartApplication</td>
<td></td>
</tr>
<tr>
<td>showTooltip</td>
<td>vaadin=runcomvaadintestscomponentstableTableItemDescriptionGeneratorTest::PID_Stable/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[3]/domChild[0]/domChild[0]</td>
<td>57,5</td>
</tr>
<tr>
<td>pause</td>
<td>1000</td>
<td>1000</td>
</tr>
<tr>
<td>assertText</td>
<td>vaadin=runcomvaadintestscomponentstableTableItemDescriptionGeneratorTest::Root/VTooltip[0]/FlowPanel[0]/domChild[1]</td>
<td>Cell description item 3,Text - Cell description</td>
</tr>
<tr>
<td>mouseClick</td>
<td>vaadin=runcomvaadintestscomponentstableTableItemDescriptionGeneratorTest::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/domChild[0]/domChild[0]</td>
<td>810,153</td>
</tr>
<tr>
<td>showTooltip</td>
<td>vaadin=runcomvaadintestscomponentstableTableItemDescriptionGeneratorTest::PID_Stable/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[1]/domChild[1]/domChild[0]</td>
<td>57,12</td>
</tr>
<tr>
<td>pause</td>
<td>1000</td>
<td>1000</td>
</tr>
<tr>
<td>assertText</td>
<td>vaadin=runcomvaadintestscomponentstableTableItemDescriptionGeneratorTest::Root/VTooltip[0]/FlowPanel[0]/domChild[1]</td>
<td>Row description item 1</td>
</tr>
<tr>
<td>mouseClick</td>
<td>vaadin=runcomvaadintestscomponentstableTableItemDescriptionGeneratorTest::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/domChild[0]/domChild[0]</td>
<td>1011,283</td>
</tr>
<tr>
<td>showTooltip</td>
<td>vaadin=runcomvaadintestscomponentstableTableItemDescriptionGeneratorTest::PID_Stable/FocusableScrollPanel[0]/VScrollTable$VScrollTableBody[0]/VScrollTable$VScrollTableBody$VScrollTableRow[4]/VTextField[0]</td>
<td>58,10</td>
</tr>
<tr>
<td>pause</td>
<td>1000</td>
<td>1000</td>
</tr>
<tr>
<td>assertText</td>
<td>vaadin=runcomvaadintestscomponentstableTableItemDescriptionGeneratorTest::Root/VTooltip[0]/FlowPanel[0]/domChild[1]</td>
<td>Textfields own description</td>
</tr>

</tbody></table>
</body>
</html>

Loading…
Cancel
Save