Ext GWT (GXT) tooltip over a grid row - gwt

I'm developing a custom tooltip using Ext GWT (GXT) for a project of mine, and this tooltip has to appear over Grid rows when they're selected.
I can't use the default GXT tooltip or quicktip because I need be able to add Components (like buttons) to this tooltip.
The problem is that the GXT Grid component doesn't expose a event related to mousing over a row (although there's RowClick and RowMouseDown).
I tried adding a listener to the Grid with the OnMouseOver and OnMouseOut events anyway, but it doesn't work as expected. It fires these events up whenever
you mouse over any of the divs and spans that composes a row.
The only way I see to solve this is to subclass the GridView component and make each row become a Component itself,
but that would be a lot of work and would probably impact performance as well. I can't help but think there's a better way to do this.
Could someone more experienced with GXT give me a light?

try this
QuickTip quickTip = new QuickTip(grid);
grid.addListener(Events.OnMouseOver, new Listener<GridEvent<BeanModel>>(){
#Override
public void handleEvent(GridEvent<BeanModel> ge) {
com.google.gwt.dom.client.Element el= grid.getView().getCell(ge.getRowIndex(),ge.getColIndex());
String html = "<span qtip='" + el.getFirstChildElement().getInnerText() + "'>" + el.getFirstChildElement().getInnerText() + "</span>";
el.getFirstChildElement().setInnerHTML(html);
}
});

onComponentEvent() (defined in com.extjs.gxt.ui.client.widget.Component with an empty body and overridden in com.extjs.gxt.ui.client.widget.grid.Grid) also receives Events with type Event.ONMOUSEOVER and Event.ONMOUSEOUT
The default implementation in the Grid class doesn't handle those events, so you may want to override this function in a subclass.
Additionally, at the end of onComponentEvent(), the Grid calls the function handleComponentEvent() of the GridView.

I found 2 ways to do that:
1.For specific column of the grid describe renderer, e.g.:
{
width: 200,
dataIndex : 'invoice',
renderer:addTooltip
}
And your renderer function:
function addTooltip(value, metadata){
metadata.attr = 'ext:qtip="' + value + '"';
return value;
}
But this method will work only when your mouse pointer will be above that specific column.
2.For 'render' event of the grid apply/use this function:
var myGrid = grid;
myGrid.on('render', function() {
myGrid.tip = new Ext.ToolTip({
view: myGrid.getView(),
target: myGrid.getView().mainBody,
delegate: '.x-grid3-row',
trackMouse: true,
renderTo: document.body,
listeners: {
beforeshow: function updateTipBody(tip) {
tip.body.dom.innerHTML = "Over row " + tip.view.findRowIndex(tip.triggerElement);
}
}
});
});
I hope this will be helpful to you :)

I know this is old but there's no accepted answer and I think I found a better way:
grid.addListener(Events.OnMouseOver, new Listener<GridEvent<Model>>() {
#Override
public void handleEvent(GridEvent<Model> ge) {
if (grid.getToolTip() != null) {
grid.getToolTip().hide();
}
ModelData model = ge.getModel();
if (model != null) {
Object someValue = model.get("someProperty");
String label = someValue.toString();
grid.setToolTip(label);
}
if (grid.getToolTip() != null) {
grid.getToolTip().show();
}
}
});

I am using GWT 2.6 and GXT 3.1.0 and I managed to do this in this way ....
Here the class RowSet is analogous to a Map
GridView<RowSet> view = new GridView<RowSet>() {
private Element cell;
#Override
protected void handleComponentEvent(Event event) {
switch (event.getTypeInt()) {
case Event.ONMOUSEMOVE:
cell = Element.is(event.getEventTarget()) ? findCell((Element) event.getEventTarget().cast())
: null;
break;
}
super.handleComponentEvent(event);
}
#Override
protected void onRowOut(Element row) {
grid.hideToolTip();
grid.setToolTipConfig(null);
super.onRowOut(row);
}
#Override
protected void onRowOver(final Element row) {
super.onRowOver(row);
grid.hideToolTip();
grid.setToolTipConfig(null);
ToolTipConfig config = new ToolTipConfig();
int rowIndex = grid.getView().findRowIndex(row);
// Through "rowIndex" you can get the Row like this :
// grid.getStore().get(rowIndex)
config.setBodyHtml("Your tool tip text here");
config.setTitleHtml("Tool Tip Title");
config.setCloseable(true);
grid.setToolTipConfig(config);
int absoluteRight = (cell != null) ? cell.getAbsoluteRight() : row.getAbsoluteRight();
int absoluteTop = (cell != null) ? cell.getAbsoluteTop() : row.getAbsoluteTop();
Point point = new Point(absoluteRight, absoluteTop);
grid.getToolTip().showAt(point);
}
};
view.setAutoFill(true);
grid.setView(view);

Related

How can I hide row/column headers in a NatTable?

I want to be able to add options to a right click menu of the NatTable that when clicked will cause either the row or column headers to be hidden but can be brought back as well.
The common practice is to operate on the corresponding DataLayer and modify the row height. Modifying the IDataProvider is typically not a good practice, as the IDataProvider is responsible for providing the data, not how the data should be rendered. So the following is an example of how to toggle the visibility of the column header layer (supposed that hideHeader is the flag to store the current state).
Button hideButton = new Button(buttonPanel, SWT.PUSH);
hideButton.setText("Hide/Show");
hideButton.addSelectionListener(new SelectionAdapter() {
#Override
public void widgetSelected(SelectionEvent e) {
this.hideHeader = !this.hideHeader;
if (this.hideHeader) {
columnHeaderDataLayer.setDefaultRowHeight(0);
} else {
columnHeaderDataLayer.setDefaultRowHeight(20);
}
natTable.refresh(false);
}
});
I know users who even used that approach to implement some sort of transition by slowly reducing the height to 0.
Alternatively you could use the RowResizeCommand if the column header DataLayer is not known
Button hideButton = new Button(buttonPanel, SWT.PUSH);
hideButton.setText("Hide/Show");
hideButton.addSelectionListener(new SelectionAdapter() {
#Override
public void widgetSelected(SelectionEvent e) {
this.hideHeader = !this.hideHeader;
if (this.hideHeader) {
natTable.doCommand(new RowResizeCommand(natTable, 0, 0));
} else {
natTable.doCommand(new RowResizeCommand(natTable, 0, 20));
}
}
});
I ended up solving this by changing the logic in the getColumnCount() method in my RowHeaderDataProvider to return 0 when flagged to be hidden, or 1 when flagged to be not hidden. Same applies for the getRowCount() in my ColumnHeaderDataProvider.

Smart GWT List Grid - Setting a hilite to a list grid on record click

I'm trying to set a hilite inside the record click handler of the list grid. I have tired the following code,
My hilites are as follows,
public static Hilite[] getWayBillSetHilites() {
return new Hilite[]{
new Hilite() {
{
setFieldNames("RECORD_VIEWED_STATUS");
setCriteria(new Criterion("RECORD_VIEWED_STATUS", OperatorId.EQUALS, "TRUE"));
setCssText(Constant.Css.TEXT_ITALIC_GRAY_32);
setTextColor("font-style:italic;color:#525252;");
setId("0");
}
}
};
}
record click handler of the grid appears as follows,
grid.addRecordClickHandler(new RecordClickHandler() {
#Override
public void onRecordClick(RecordClickEvent recordClickEvent) {
//gridWayBillSetGrid.getHiliteState()
//make RECORD_VIEWED_STATUS value "true"
recordClickEvent.getRecord().setAttribute("RECORD_VIEWED_STATUS", true);
gridWayBillSetGrid.enableHilite("0", true);
}
});
But when I click on the record, the styles are not showing up.
Please be kind to advise on this.
I think it's the wrong use case for hilites. Use getCellCSSText instead.
Try this one (override getCellCSSText method of ListGrid class):
ListGrid grid = new ListGrid(...){
#Override
protected String getCellCSSText(ListGridRecord record, int rowNum, int colNum) {
if("true".equalsIgnoreCase(record.getAttribute("RECORD_VIEWED_STATUS"))){
return "font-style:italic;color:#525252;";
}
return super.getCellCSSText(record, rowNum, colNum);
}
};

GWT native drag and drop: how to identify the dragged object

I followed the instructions given here: Drag and Drop in GWT 2.4
It works well, but I now want to select between many objects which to transfer. How can it be determined which object is dragged?
Thank you in advance!
I would do the following:
1) Create a map with objects allowed for dragging (Labels in your example)
HashMap <String, Label> draggableWidgetsMap = new HashMap<String, Label>();
draggableWidgetsMap.add("key1", widget1);
...
draggableWidgetsMap.add("keyN", widgetN);
2) Then apply the dragStart event handler for each widget, e.g. for widget1 it would be:
widget1.addDomHandler(new DragStartHandler() {
#Override
public void onDragStart(DragStartEvent event) {
event.setData("widgetKey", "key1");
}
}, DragStartEvent.getType());
3) And then you can check what widget is dragged now in DragOver event handler:
widget1.addDomHandler(new DragOverHandler() {
#Override
public void onDragOver(DragOverEvent event) {
String widgetKey = event.getDataTransfer().getData("widgetKey");
if (widgetKey != null && widgetKey.length() > 0){
if (draggableWidgetsMap.containsKey(widgetKey)){
// Print out Label's text to see which one is dragged
System.out.println("Dragged label has text: \" " + draggableWidgetsMap.get(widgetKey).getText() + "\"")
// do something relevant with this Label
}
}
}
}, DragOverEvent.getType());
Certainly, I would loop through all the widgets to apply both handlers for the widgets you are going to make draggable.

GWT CellTable Custom Selection Model

I need a 'custom selection model' for GWT CellTable. One of the columns in CellTable is a Checkbox column.
Basic rquirements (both work in solution below):
- Row click (not on checkbox), selects that row and un-selects all other rows.
- Checkbox selection should select/un-select that row only.
Following is the code I am using, but its very very slow. Any guidance would be appreciated.
final SelectionModel<T> selectionModel = new MultiSelectionModel<T>();
dataTable.setSelectionModel(selectionModel,
DefaultSelectionEventManager.createCustomManager(
new DefaultSelectionEventManager.CheckboxEventTranslator<T>() {
#Override
public SelectAction translateSelectionEvent(CellPreviewEvent<T> event) {
SelectAction action = super.translateSelectionEvent(event);
if (action.equals(SelectAction.IGNORE)) {
selectionModel.clear();
return SelectAction.TOGGLE;
}
return action;
}
}
)
);
Following is the code snipped for CheckColumn callback.
Column<T, Boolean> checkColumn = new Column<T, Boolean>(
new CheckboxCell(true, false))
{
#Override
public Boolean getValue(T t)
{
// Get the value from the selection model.
return selectionModel.isSelected(t);
}
};
I have put in a KeyProvider for the CellTable and its not slow anymore. :)
ProvidesKey<T> keyProvider = new ProvidesKey<T>() {
public Object getKey(T t) {
return tip == null? null : tip.getId();
}
};
dataTable = new CellTable<T>(PAGE_SIZE, keyProvider);
You could just whitelist your checkbox
int checkboxColumn = 0;
DefaultSelectionEventManager.createCustomManager(new DefaultSelectionEventManager
.WhitelistEventTranslator(checkboxColumn));

Handling click events from CellTable, how to handle them back to default dispatcher?

I have a CellTable with one custom column where I render it manually and put a FlowPanel with a bunch of HTMLPanel/Anchor/FlowPanel widgets, and among them is DecoratorPanel.
DecoratorPanel renders as a table, of course.
Rendering happens like this:
public class MyExpandableCell extends AbstractCell<String> {
...
#Override
public void render(com.google.gwt.cell.client.Cell.Context context, String value, SafeHtmlBuilder sb) {
if (value != null) {
FlowPanel fp = createDetailsFlowPanel(value);
sb.appendHtmlConstant(fp.getElement().getString());
}
}
Now, I have added a handler for click events to my main CellTable. In my handler I traverse the tree to find a first TR belonging to my CellTable, by checking if it contains "even row" or "odd row" CSS classes.
However, when click happens inside of the DecoratorPanel (which is inside of my cell table's TD), my handler also gets triggered, since the click belongs to the cell table area.
I can detect this my seeing that parent TR does not have CellTable CSS classes.
QUESTION: how can I return processing of such click events to the DecoratorPanel - where it really belongs to? As it is now, my DecoratorPanel does not expand and I think because my click handler intercepts and suppresses all clicks on the CellTable level.
table = setupMyCellTable(PAGE_SIZE, CLIENT_BUNDLE, myCellTableResources);
mydataprovider.addDataDisplay(table);
table.sinkEvents(Event.ONCLICK);
table.addDomHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent e) {
boolean isClick = "click".equals(e.getNativeEvent().getType());
if (isClick) {
Element originalElement = e.getNativeEvent().getEventTarget().cast();
Element element = originalElement;
String ctTrClassEven = CLIENT_BUNDLE.mainCss().cellTableEvenRow();
String ctTrClassEven = CLIENT_BUNDLE.mainCss().cellTableOddRow();
// Looking for closest parent TR which has one
// of the two row class names (for this cellTable):
while (element != null
&& !"tr".equalsIgnoreCase(element.getTagName())
&& !(element.getClassName().contains(ctTrClassEven) ||
element.getClassName().contains(ctTrClassEven))) {
element = element.getParentElement();
}
if (element != null) {
if (element.getClassName().contains(ctTrClassEven)
|| element.getClassName().contains(ctTrClassEven)) {
// Found cell table's TR. Set new TR height.
} else {
// Found TR from DecoratorPanel inside of the celltable's cell.
// Do nothing. But how do I make sure
// that decorator panel processes this click and expands?
return;
// Did not work: NS_ERROR_ILLEGAL_VALUE javascript exception.
// if (originalElement != null) {
// originalElement.dispatchEvent(e.getNativeEvent());
// }
}
} else {
debugStr.setText("(did not find tr)");
}
}
}
}, ClickEvent.getType());
Looks like a bug in GWT, triggered because decorator panel uses table to render itself:
http://code.google.com/p/google-web-toolkit/issues/detail?id=5714
(another example http://code.google.com/p/google-web-toolkit/issues/detail?id=6750)
Fix is expected to be shipped with GWT 2.5.