I'm trying to implement an Excel like functionality where a cell may have a comment, so on hover I want a pop up to appear containing the desired text. All is well until the pop up appears. The problem I'm facing is that when the pop up appears all the background events are disabled. When hovering at any other part of the grid, nothing happens if the pop up is on display (e.g. the header is unreachable). Although I specifically state dialog.setGlassEnabled(false);
. As I've seen by chrome dev tools, the glass div
that acts as a background is indeed not present. So why is this strange behavior? Is there something else? Below is the whole test case (in order to reproduce easily) and on separate parts is the code that I believe is of importance.
I'm using GWT 2.6 and GXT 3.1, but the component I'm using is the native component DialogBox of GWT, so I believe GXT is irrelevant here.
mainGrid.addHandler(new GridHoverPopUpHandler()
{
@Override
public void onHover(Element element)
{
dialog.hide();
if(element == null) return;
Element cell = mainGrid.getView().findCell(element);
if(cell != null && cell.hasClassName("comment-indicator"))
{
Label label = new Label("mpazingka " + (String)cell.getInnerText());
dialog.setText("Title of comment");
dialog.setWidget(label);
dialog.setPopupPosition(absoluteX, absoluteY);
dialog.show();
}
}
}, MouseMoveEvent.getType());
abstract class GridHoverPopUpHandler implements MouseOutHandler, MouseMoveHandler
{
protected int absoluteX;
protected int absoluteY;
private Element lastHoveredElement = null;
protected DialogBox dialog;
public abstract void onHover(Element element);
GridHoverPopUpHandler()
{
dialog = new DialogBox();
dialog.setGlassEnabled(false);
}
@Override
public void onMouseMove(MouseMoveEvent event)
{
Element curHoveredElement = null;
NativeEvent natev = event.getNativeEvent();
if (Element.is(natev.getEventTarget()))
{
curHoveredElement = Element.as(natev.getEventTarget());
}
if(lastHoveredElement == curHoveredElement)
{
return;
}
absoluteX = event.getClientX();
absoluteY = event.getClientY();
lastHoveredElement = curHoveredElement;
onHover(curHoveredElement);
}
@Override
public void onMouseOut(MouseOutEvent event)
{
//TODO: Pendig implementation
}
}
package com.test.client;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import com.google.gwt.cell.client.DateCell;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.event.dom.client.MouseMoveEvent;
import com.google.gwt.event.dom.client.MouseMoveHandler;
import com.google.gwt.event.dom.client.MouseOutEvent;
import com.google.gwt.event.dom.client.MouseOutHandler;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.safehtml.shared.SafeHtmlUtils;
import com.google.gwt.user.client.ui.DialogBox;
import com.google.gwt.user.client.ui.IsWidget;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.Widget;
import com.sencha.gxt.core.client.ValueProvider;
import com.sencha.gxt.data.shared.ListStore;
import com.sencha.gxt.widget.core.client.ContentPanel;
import com.sencha.gxt.widget.core.client.grid.ColumnConfig;
import com.sencha.gxt.widget.core.client.grid.ColumnModel;
import com.sencha.gxt.widget.core.client.grid.Grid;
import com.sencha.gxt.widget.core.client.grid.GridView;
import com.sencha.gxt.widget.core.client.grid.GridViewConfig;
import com.sencha.gxt.widget.core.client.grid.GroupSummaryView;
import com.sencha.gxt.widget.core.client.grid.SummaryColumnConfig;
public class GridHoverExample implements IsWidget, EntryPoint {
private static final StockProperties props = GWT.create(StockProperties.class);
private ContentPanel root;
private ArrayList<String> comments;
private void rootInit() {
root = new ContentPanel();
root.setHeadingText("Locked Grid Sample");
root.setPixelSize(400, 300);
comments = new ArrayList();
comments.add("Stack_2");
}
@Override
public Widget asWidget() {
if (root == null) {
rootInit();
ColumnConfig<Stock, String> nameCol = new SummaryColumnConfig<Stock, String>(props.name(), 100, SafeHtmlUtils.fromTrustedString("<b>Company</b>"));
ColumnConfig<Stock, String> symbolCol = new SummaryColumnConfig<Stock, String>(props.symbol(), 100, "Symbol");
ColumnConfig<Stock, Double> changeCol = new SummaryColumnConfig<Stock, Double>(props.change(), 100, "Change");
ColumnConfig<Stock, String> industryCol = new SummaryColumnConfig<Stock, String>(props.industry(), 100, "Industry");
ColumnConfig<Stock, Date> dateCol = new SummaryColumnConfig<Stock, Date>(props.date(), 100, "Date");
dateCol.setCell(new DateCell(DateTimeFormat.getFormat("MM/dd/yyyy")));
List<ColumnConfig<Stock, ?>> ccFree = new ArrayList<ColumnConfig<Stock, ?>>();
ccFree.add(nameCol);
ccFree.add(symbolCol);
ccFree.add(changeCol);
ccFree.add(dateCol);
ccFree.add(industryCol);
ColumnModel<Stock> cm = new ColumnModel<Stock>(ccFree);
ListStore<Stock> store = new ListStore<Stock>(props.key());
for (int i = 1; i <= 100; i++)
store.add(new Stock("Stack_"+i, "S_"+i, 2, 2, new Date()));
final Grid<Stock> mainGrid = new Grid<Stock>(store, cm);
mainGrid.addHandler(new GridHoverPopUpHandler()
{
@Override
public void onHover(Element element)
{
dialog.hide();
if(element == null) return;
Element cell = mainGrid.getView().findCell(element);
if(cell != null && cell.hasClassName("comment-indicator"))
{
Label label = new Label("mpazingka " + (String)cell.getInnerText());
dialog.setText("Title of comment");
dialog.setWidget(label);
dialog.setPopupPosition(absoluteX, absoluteY);
dialog.show();
}
}
}, MouseMoveEvent.getType());
mainGrid.setView(createGridView());
root.setWidget(mainGrid);
}
return root;
}
@Override
public void onModuleLoad() {
RootPanel.get("nameFieldContainer").add(asWidget());
}
private GridView<Stock> createGridView()
{
final GroupSummaryView<Stock> view = new GroupSummaryView<Stock>();
view.setShowGroupedColumn(false);
view.setStripeRows(true);
view.setColumnLines(true);
view.setSortingEnabled(false);
view.setShowDirtyCells(false);
view.setViewConfig(new GridViewConfig<Stock>()
{
@Override
public String getRowStyle(Stock model, int rowIndex)
{
return "";
}
@Override
public String getColStyle(Stock model, ValueProvider<? super Stock, ?> valueProvider, int rowIndex, int colIndex)
{
String style = "";
if(model.getName().equals(comments.get(0)) && colIndex == 0)
{
style += "comment-indicator ";
}
style += "columnWidth";
return style;
}
});
return view;
}
}
abstract class GridHoverPopUpHandler implements MouseOutHandler, MouseMoveHandler
{
protected int absoluteX;
protected int absoluteY;
private Element lastHoveredElement = null;
protected DialogBox dialog;
public abstract void onHover(Element element);
GridHoverPopUpHandler()
{
dialog = new DialogBox();
dialog.setGlassEnabled(false);
}
@Override
public void onMouseMove(MouseMoveEvent event)
{
Element curHoveredElement = null;
NativeEvent natev = event.getNativeEvent();
if (Element.is(natev.getEventTarget()))
{
curHoveredElement = Element.as(natev.getEventTarget());
}
if(lastHoveredElement == curHoveredElement)
{
return;
}
absoluteX = event.getClientX();
absoluteY = event.getClientY();
lastHoveredElement = curHoveredElement;
onHover(curHoveredElement);
}
@Override
public void onMouseOut(MouseOutEvent event)
{
//TODO: Pendig implementation
}
}
Update
Ok I found it. This widget in order to manipulate the DOM for making the component dragable captures some events (mouse events). I didn't follow through because of time restrictions, so I used DecoratedPopupPanel
which is the parent class of DialogBox
and doesn't capture all those events that I need. I'll be waiting for a day or two, for an answer about the part that does this event capturing, and how I can disable it. If not provided I'm posting this as an answer to close the topic.
I think you may have done it overkill by using the dialog to done the functionality of tool tip. IMHO, What you should do was add a tooltip to the cell that you want to have the "excel comment" functionality. So whenever, user hover to that cell, it will show the tooltip loaded with data from your comment. Take a look at the Basic Grid example at here: http://www.sencha.com/examples/#ExamplePlace:basicgrid Try to hover your mouse to Change cell, it will pop you a tool tip. The key point was to create your own grid cell implementation, like this :
ColumnConfig<Stock, Double> changeCol = new ColumnConfig<Stock, Double>(props.change(), 100, "Change");
changeCol.setCell(new AbstractCell<Double>() {
@Override
public void render(Context context, Double value, SafeHtmlBuilder sb) {
String style = "style='color: " + (value < 0 ? "red" : "green") + "'";
String v = number.format(value);
sb.appendHtmlConstant("<span " + style + " qtitle='Change' qtip='" + v + "'>" + v + "</span>");
}
});
If you need to use different type of tooltip, take a look at the tooltips example at here: http://www.sencha.com/examples/#ExamplePlace:tooltips
Hope this could help you.