svn changeset:20392/svn branch:6.7tags/6.7.0.beta1
@@ -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) { |
@@ -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); | |||
} | |||
} |
@@ -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; | |||
} | |||
} |
@@ -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; | |||
} | |||
} |
@@ -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> |