Browse Source

Fix client-side memory leak caused by Grid events (#9103)

Refactors AbstractGridKeyEvent, AbstractGridMouseEvent and their
descendants to follow the pattern used in other GWT DomEvents.

Fixes #7633
tags/8.1.0.alpha6
Aleksi Hietanen 7 years ago
parent
commit
7d1b06cbc4
16 changed files with 401 additions and 146 deletions
  1. 0
    13
      client/src/main/java/com/vaadin/client/connectors/treegrid/TreeGridConnector.java
  2. 19
    1
      client/src/main/java/com/vaadin/client/widget/grid/events/GridClickEvent.java
  3. 19
    2
      client/src/main/java/com/vaadin/client/widget/grid/events/GridDoubleClickEvent.java
  4. 19
    1
      client/src/main/java/com/vaadin/client/widget/grid/events/GridKeyDownEvent.java
  5. 19
    1
      client/src/main/java/com/vaadin/client/widget/grid/events/GridKeyPressEvent.java
  6. 19
    1
      client/src/main/java/com/vaadin/client/widget/grid/events/GridKeyUpEvent.java
  7. 8
    0
      client/src/main/java/com/vaadin/client/widget/treegrid/TreeGrid.java
  8. 14
    4
      client/src/main/java/com/vaadin/client/widget/treegrid/events/TreeGridClickEvent.java
  9. 75
    59
      client/src/main/java/com/vaadin/client/widgets/Grid.java
  10. 19
    1
      compatibility-client/src/main/java/com/vaadin/v7/client/widget/grid/events/GridClickEvent.java
  11. 19
    2
      compatibility-client/src/main/java/com/vaadin/v7/client/widget/grid/events/GridDoubleClickEvent.java
  12. 19
    1
      compatibility-client/src/main/java/com/vaadin/v7/client/widget/grid/events/GridKeyDownEvent.java
  13. 19
    1
      compatibility-client/src/main/java/com/vaadin/v7/client/widget/grid/events/GridKeyPressEvent.java
  14. 19
    1
      compatibility-client/src/main/java/com/vaadin/v7/client/widget/grid/events/GridKeyUpEvent.java
  15. 74
    58
      compatibility-client/src/main/java/com/vaadin/v7/client/widgets/Grid.java
  16. 40
    0
      uitest/src/main/java/com/vaadin/tests/components/grid/GridClientMemoryLeak.java

+ 0
- 13
client/src/main/java/com/vaadin/client/connectors/treegrid/TreeGridConnector.java View File

@@ -33,9 +33,7 @@ import com.vaadin.client.data.DataSource;
import com.vaadin.client.renderers.HierarchyRenderer;
import com.vaadin.client.widget.grid.EventCellReference;
import com.vaadin.client.widget.grid.GridEventHandler;
import com.vaadin.client.widget.grid.events.GridClickEvent;
import com.vaadin.client.widget.treegrid.TreeGrid;
import com.vaadin.client.widget.treegrid.events.TreeGridClickEvent;
import com.vaadin.client.widgets.Grid;
import com.vaadin.shared.Range;
import com.vaadin.shared.data.DataCommunicatorConstants;
@@ -156,12 +154,6 @@ public class TreeGridConnector extends GridConnector {

getWidget().addBrowserEventHandler(5, new NavigationEventHandler());

// Swap Grid#clickEvent field
// The event is identical to the original one except for the child
// widget check
replaceClickEvent(getWidget(),
new TreeGridClickEvent(getWidget(), getEventCell(getWidget())));

registerRpc(TreeGridClientRpc.class, new TreeGridClientRpc() {

@Override
@@ -225,11 +217,6 @@ public class TreeGridConnector extends GridConnector {
browserEventHandlers.@java.util.List::set(*)(5, eventHandler);
}-*/;

private native void replaceClickEvent(Grid<?> grid, GridClickEvent event)
/*-{
grid.@com.vaadin.client.widgets.Grid::clickEvent = event;
}-*/;

private native EventCellReference<?> getEventCell(Grid<?> grid)
/*-{
return grid.@com.vaadin.client.widgets.Grid::eventCell;

+ 19
- 1
client/src/main/java/com/vaadin/client/widget/grid/events/GridClickEvent.java View File

@@ -30,8 +30,26 @@ import com.vaadin.shared.ui.grid.GridConstants.Section;
*/
public class GridClickEvent extends AbstractGridMouseEvent<GridClickHandler> {

public static final Type<GridClickHandler> TYPE = new Type<GridClickHandler>(
BrowserEvents.CLICK, new GridClickEvent());

/**
* @since 7.7.9
*/
public GridClickEvent() {
}

/**
* @deprecated This constructor's arguments are no longer used. Use the
* no-args constructor instead.
*/
@Deprecated
public GridClickEvent(Grid<?> grid, CellReference<?> targetCell) {
super(grid, targetCell);
}

@Override
public Type<GridClickHandler> getAssociatedType() {
return TYPE;
}

@Override

+ 19
- 2
client/src/main/java/com/vaadin/client/widget/grid/events/GridDoubleClickEvent.java View File

@@ -31,8 +31,26 @@ import com.vaadin.shared.ui.grid.GridConstants.Section;
public class GridDoubleClickEvent
extends AbstractGridMouseEvent<GridDoubleClickHandler> {

public static final Type<GridDoubleClickHandler> TYPE = new Type<GridDoubleClickHandler>(
BrowserEvents.DBLCLICK, new GridDoubleClickEvent());

/**
* @since 7.7.9
*/
public GridDoubleClickEvent() {
}

/**
* @deprecated This constructor's arguments are no longer used. Use the
* no-args constructor instead.
*/
@Deprecated
public GridDoubleClickEvent(Grid<?> grid, CellReference<?> targetCell) {
super(grid, targetCell);
}

@Override
public Type<GridDoubleClickHandler> getAssociatedType() {
return TYPE;
}

@Override
@@ -51,5 +69,4 @@ public class GridDoubleClickEvent
handler.onDoubleClick(this);
}
}

}

+ 19
- 1
client/src/main/java/com/vaadin/client/widget/grid/events/GridKeyDownEvent.java View File

@@ -31,8 +31,26 @@ import com.vaadin.shared.ui.grid.GridConstants.Section;
*/
public class GridKeyDownEvent extends AbstractGridKeyEvent<GridKeyDownHandler> {

public static final Type<GridKeyDownHandler> TYPE = new Type<GridKeyDownHandler>(
BrowserEvents.KEYDOWN, new GridKeyDownEvent());

/**
* @since 7.7.9
*/
public GridKeyDownEvent() {
}

/**
* @deprecated This constructor's arguments are no longer used. Use the
* no-args constructor instead.
*/
@Deprecated
public GridKeyDownEvent(Grid<?> grid, CellReference<?> targetCell) {
super(grid, targetCell);
}

@Override
public Type<GridKeyDownHandler> getAssociatedType() {
return TYPE;
}

@Override

+ 19
- 1
client/src/main/java/com/vaadin/client/widget/grid/events/GridKeyPressEvent.java View File

@@ -31,8 +31,26 @@ import com.vaadin.shared.ui.grid.GridConstants.Section;
public class GridKeyPressEvent
extends AbstractGridKeyEvent<GridKeyPressHandler> {

public static final Type<GridKeyPressHandler> TYPE = new Type<GridKeyPressHandler>(
BrowserEvents.KEYPRESS, new GridKeyPressEvent());

/**
* @since 7.7.9
*/
public GridKeyPressEvent() {
}

/**
* @deprecated This constructor's arguments are no longer used. Use the
* no-args constructor instead.
*/
@Deprecated
public GridKeyPressEvent(Grid<?> grid, CellReference<?> targetCell) {
super(grid, targetCell);
}

@Override
public Type<GridKeyPressHandler> getAssociatedType() {
return TYPE;
}

@Override

+ 19
- 1
client/src/main/java/com/vaadin/client/widget/grid/events/GridKeyUpEvent.java View File

@@ -31,8 +31,21 @@ import com.vaadin.shared.ui.grid.GridConstants.Section;
*/
public class GridKeyUpEvent extends AbstractGridKeyEvent<GridKeyUpHandler> {

public static final Type<GridKeyUpHandler> TYPE = new Type<GridKeyUpHandler>(
BrowserEvents.KEYUP, new GridKeyUpEvent());

/**
* @since 7.7.9
*/
public GridKeyUpEvent() {
}

/**
* @deprecated This constructor's arguments are no longer used. Use the
* no-args constructor instead.
*/
@Deprecated
public GridKeyUpEvent(Grid<?> grid, CellReference<?> targetCell) {
super(grid, targetCell);
}

@Override
@@ -46,6 +59,11 @@ public class GridKeyUpEvent extends AbstractGridKeyEvent<GridKeyUpHandler> {
}
}

@Override
public Type<GridKeyUpHandler> getAssociatedType() {
return TYPE;
}

@Override
protected String getBrowserEventType() {
return BrowserEvents.KEYUP;

+ 8
- 0
client/src/main/java/com/vaadin/client/widget/treegrid/TreeGrid.java View File

@@ -16,6 +16,9 @@
package com.vaadin.client.widget.treegrid;

import com.google.gwt.dom.client.Element;
import com.google.gwt.event.shared.HandlerRegistration;
import com.vaadin.client.widget.grid.events.BodyClickHandler;
import com.vaadin.client.widget.treegrid.events.TreeGridClickEvent;
import com.vaadin.client.widgets.Grid;

import elemental.json.JsonObject;
@@ -43,6 +46,11 @@ public class TreeGrid extends Grid<JsonObject> {
return this.@com.vaadin.client.widgets.Grid::isElementInChildWidget(*)(e);
}-*/;

@Override
public HandlerRegistration addBodyClickHandler(BodyClickHandler handler) {
return addHandler(handler, TreeGridClickEvent.TYPE);
}

@Override
protected String getFocusPrimaryStyleName() {
return super.getStylePrimaryName() + "-rowmode";

+ 14
- 4
client/src/main/java/com/vaadin/client/widget/treegrid/events/TreeGridClickEvent.java View File

@@ -15,12 +15,14 @@
*/
package com.vaadin.client.widget.treegrid.events;

import com.google.gwt.dom.client.BrowserEvents;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.EventTarget;
import com.vaadin.client.WidgetUtil;
import com.vaadin.client.renderers.HierarchyRenderer;
import com.vaadin.client.widget.escalator.RowContainer;
import com.vaadin.client.widget.grid.CellReference;
import com.vaadin.client.widget.grid.events.AbstractGridMouseEventHandler;
import com.vaadin.client.widget.grid.events.AbstractGridMouseEventHandler.GridClickHandler;
import com.vaadin.client.widget.grid.events.GridClickEvent;
import com.vaadin.client.widget.treegrid.TreeGrid;
import com.vaadin.shared.ui.grid.GridConstants;
@@ -36,13 +38,21 @@ import com.vaadin.shared.ui.grid.GridConstants;
*/
public class TreeGridClickEvent extends GridClickEvent {

public TreeGridClickEvent(TreeGrid grid, CellReference<?> targetCell) {
super(grid, targetCell);
public static final Type<GridClickHandler> TYPE = new Type<GridClickHandler>(
BrowserEvents.CLICK, new TreeGridClickEvent());

@Override
public Type<GridClickHandler> getAssociatedType() {
return TYPE;
}

@Override
public TreeGrid getGrid() {
return (TreeGrid) super.getGrid();
EventTarget target = getNativeEvent().getEventTarget();
if (!Element.is(target)) {
return null;
}
return WidgetUtil.findWidget(Element.as(target), TreeGrid.class);
}

@Override

+ 75
- 59
client/src/main/java/com/vaadin/client/widgets/Grid.java View File

@@ -2291,47 +2291,59 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
public static abstract class AbstractGridKeyEvent<HANDLER extends AbstractGridKeyEventHandler>
extends KeyEvent<HANDLER> {

private Grid<?> grid;
private final Type<HANDLER> associatedType = new Type<>(
getBrowserEventType(), this);
private final CellReference<?> targetCell;
/**
* @since 7.7.9
*/
public AbstractGridKeyEvent() {
}

/**
* @deprecated This constructor's arguments are no longer used. Use the
* no-args constructor instead.
*/
@Deprecated
public AbstractGridKeyEvent(Grid<?> grid, CellReference<?> targetCell) {
this.grid = grid;
this.targetCell = targetCell;
}

protected abstract String getBrowserEventType();

/**
* Gets the Grid instance for this event.
* Gets the Grid instance for this event, if it originated from a Grid.
*
* @return grid
* @return the grid this event originated from, or {@code null} if this
* event did not originate from a grid
*/
public Grid<?> getGrid() {
return grid;
EventTarget target = getNativeEvent().getEventTarget();
if (!Element.is(target)) {
return null;
}
return WidgetUtil.findWidget(Element.as(target), Grid.class);
}

/**
* Gets the focused cell for this event.
* Gets the reference of target cell for this event, if this event
* originated from a Grid.
*
* @return focused cell
* @return target cell, or {@code null} if this event did not originate
* from a grid
*/
public CellReference<?> getFocusedCell() {
return targetCell;
return getGrid().getEventCell();
}

@Override
protected void dispatch(HANDLER handler) {
EventTarget target = getNativeEvent().getEventTarget();
if (Element.is(target)
Grid<?> grid = getGrid();
if (Element.is(target) && grid != null
&& !grid.isElementInChildWidget(Element.as(target))) {

Section section = Section.FOOTER;
final RowContainer container = grid.cellFocusHandler.containerWithFocus;
if (container == grid.escalator.getHeader()) {
section = Section.HEADER;
} else if (container == grid.escalator.getBody()) {
} else if (container == getGrid().escalator.getBody()) {
section = Section.BODY;
}

@@ -2340,45 +2352,55 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
}

protected abstract void doDispatch(HANDLER handler, Section section);

@Override
public Type<HANDLER> getAssociatedType() {
return associatedType;
}
}

public static abstract class AbstractGridMouseEvent<HANDLER extends AbstractGridMouseEventHandler>
extends MouseEvent<HANDLER> {

private Grid<?> grid;
private final CellReference<?> targetCell;
private final Type<HANDLER> associatedType = new Type<>(
getBrowserEventType(), this);
/**
* @since 7.7.9
*/
public AbstractGridMouseEvent() {
}

/**
* @deprecated This constructor's arguments are no longer used. Use the
* no-args constructor instead.
*/
@Deprecated
public AbstractGridMouseEvent(Grid<?> grid,
CellReference<?> targetCell) {
this.grid = grid;
this.targetCell = targetCell;
}

protected abstract String getBrowserEventType();

/**
* Gets the Grid instance for this event.
* Gets the Grid instance for this event, if it originated from a Grid.
*
* @return grid
* @return the grid this event originated from, or {@code null} if this
* event did not originate from a grid
*/
public Grid<?> getGrid() {
return grid;
EventTarget target = getNativeEvent().getEventTarget();
if (!Element.is(target)) {
return null;
}
return WidgetUtil.findWidget(Element.as(target), Grid.class);
}

/**
* Gets the reference of target cell for this event.
* Gets the reference of target cell for this event, if this event
* originated from a Grid.
*
* @return target cell
* @return target cell, or {@code null} if this event did not originate
* from a grid
*/
public CellReference<?> getTargetCell() {
return targetCell;
Grid<?> grid = getGrid();
if (grid == null) {
return null;
}
return grid.getEventCell();
}

@Override
@@ -2389,6 +2411,12 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
return;
}

Grid<?> grid = getGrid();
if (grid == null) {
// Target is not an element of a grid
return;
}

Element targetElement = Element.as(target);
if (grid.isElementInChildWidget(targetElement)) {
// Target is some widget inside of Grid
@@ -2413,11 +2441,6 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
}

protected abstract void doDispatch(HANDLER handler, Section section);

@Override
public Type<HANDLER> getAssociatedType() {
return associatedType;
}
}

private static final String CUSTOM_STYLE_PROPERTY_NAME = "customStyle";
@@ -2430,13 +2453,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
*/
private static final double DETAILS_ROW_INITIAL_HEIGHT = 50;

private EventCellReference<T> eventCell = new EventCellReference<>(this);
private GridKeyDownEvent keyDown = new GridKeyDownEvent(this, eventCell);
private GridKeyUpEvent keyUp = new GridKeyUpEvent(this, eventCell);
private GridKeyPressEvent keyPress = new GridKeyPressEvent(this, eventCell);
private GridClickEvent clickEvent = new GridClickEvent(this, eventCell);
private GridDoubleClickEvent doubleClickEvent = new GridDoubleClickEvent(
this, eventCell);
private EventCellReference<T> eventCell = new EventCellReference<T>(this);

private class CellFocusHandler {

@@ -8094,7 +8111,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
*/
public HandlerRegistration addBodyKeyDownHandler(
BodyKeyDownHandler handler) {
return addHandler(handler, keyDown.getAssociatedType());
return addHandler(handler, GridKeyDownEvent.TYPE);
}

/**
@@ -8107,7 +8124,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
* @return the registration for the event
*/
public HandlerRegistration addBodyKeyUpHandler(BodyKeyUpHandler handler) {
return addHandler(handler, keyUp.getAssociatedType());
return addHandler(handler, GridKeyUpEvent.TYPE);
}

/**
@@ -8121,7 +8138,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
*/
public HandlerRegistration addBodyKeyPressHandler(
BodyKeyPressHandler handler) {
return addHandler(handler, keyPress.getAssociatedType());
return addHandler(handler, GridKeyPressEvent.TYPE);
}

/**
@@ -8135,7 +8152,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
*/
public HandlerRegistration addHeaderKeyDownHandler(
HeaderKeyDownHandler handler) {
return addHandler(handler, keyDown.getAssociatedType());
return addHandler(handler, GridKeyDownEvent.TYPE);
}

/**
@@ -8149,7 +8166,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
*/
public HandlerRegistration addHeaderKeyUpHandler(
HeaderKeyUpHandler handler) {
return addHandler(handler, keyUp.getAssociatedType());
return addHandler(handler, GridKeyUpEvent.TYPE);
}

/**
@@ -8163,7 +8180,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
*/
public HandlerRegistration addHeaderKeyPressHandler(
HeaderKeyPressHandler handler) {
return addHandler(handler, keyPress.getAssociatedType());
return addHandler(handler, GridKeyPressEvent.TYPE);
}

/**
@@ -8177,7 +8194,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
*/
public HandlerRegistration addFooterKeyDownHandler(
FooterKeyDownHandler handler) {
return addHandler(handler, keyDown.getAssociatedType());
return addHandler(handler, GridKeyDownEvent.TYPE);
}

/**
@@ -8191,7 +8208,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
*/
public HandlerRegistration addFooterKeyUpHandler(
FooterKeyUpHandler handler) {
return addHandler(handler, keyUp.getAssociatedType());
return addHandler(handler, GridKeyUpEvent.TYPE);
}

/**
@@ -8205,7 +8222,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
*/
public HandlerRegistration addFooterKeyPressHandler(
FooterKeyPressHandler handler) {
return addHandler(handler, keyPress.getAssociatedType());
return addHandler(handler, GridKeyPressEvent.TYPE);
}

/**
@@ -8217,7 +8234,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
* @return the registration for the event
*/
public HandlerRegistration addBodyClickHandler(BodyClickHandler handler) {
return addHandler(handler, clickEvent.getAssociatedType());
return addHandler(handler, GridClickEvent.TYPE);
}

/**
@@ -8230,7 +8247,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
*/
public HandlerRegistration addHeaderClickHandler(
HeaderClickHandler handler) {
return addHandler(handler, clickEvent.getAssociatedType());
return addHandler(handler, GridClickEvent.TYPE);
}

/**
@@ -8243,7 +8260,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
*/
public HandlerRegistration addFooterClickHandler(
FooterClickHandler handler) {
return addHandler(handler, clickEvent.getAssociatedType());
return addHandler(handler, GridClickEvent.TYPE);
}

/**
@@ -8257,7 +8274,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
*/
public HandlerRegistration addBodyDoubleClickHandler(
BodyDoubleClickHandler handler) {
return addHandler(handler, doubleClickEvent.getAssociatedType());
return addHandler(handler, GridDoubleClickEvent.TYPE);
}

/**
@@ -8271,7 +8288,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
*/
public HandlerRegistration addHeaderDoubleClickHandler(
HeaderDoubleClickHandler handler) {
return addHandler(handler, doubleClickEvent.getAssociatedType());
return addHandler(handler, GridDoubleClickEvent.TYPE);
}

/**
@@ -8285,7 +8302,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
*/
public HandlerRegistration addFooterDoubleClickHandler(
FooterDoubleClickHandler handler) {
return addHandler(handler, doubleClickEvent.getAssociatedType());
return addHandler(handler, GridDoubleClickEvent.TYPE);
}

/**
@@ -8762,7 +8779,6 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
for (int row : details) {
setDetailsVisible(row, false);
}

super.onDetach();
}


+ 19
- 1
compatibility-client/src/main/java/com/vaadin/v7/client/widget/grid/events/GridClickEvent.java View File

@@ -30,8 +30,26 @@ import com.vaadin.v7.shared.ui.grid.GridConstants.Section;
*/
public class GridClickEvent extends AbstractGridMouseEvent<GridClickHandler> {

public static final Type<GridClickHandler> TYPE = new Type<GridClickHandler>(
BrowserEvents.CLICK, new GridClickEvent());

/**
* @since 7.7.9
*/
public GridClickEvent() {
}

/**
* @deprecated This constructor's arguments are no longer used. Use the
* no-args constructor instead.
*/
@Deprecated
public GridClickEvent(Grid<?> grid, CellReference<?> targetCell) {
super(grid, targetCell);
}

@Override
public Type<GridClickHandler> getAssociatedType() {
return TYPE;
}

@Override

+ 19
- 2
compatibility-client/src/main/java/com/vaadin/v7/client/widget/grid/events/GridDoubleClickEvent.java View File

@@ -31,8 +31,26 @@ import com.vaadin.v7.shared.ui.grid.GridConstants.Section;
public class GridDoubleClickEvent
extends AbstractGridMouseEvent<GridDoubleClickHandler> {

public static final Type<GridDoubleClickHandler> TYPE = new Type<GridDoubleClickHandler>(
BrowserEvents.DBLCLICK, new GridDoubleClickEvent());

/**
* @since 7.7.9
*/
public GridDoubleClickEvent() {
}

/**
* @deprecated This constructor's arguments are no longer used. Use the
* no-args constructor instead.
*/
@Deprecated
public GridDoubleClickEvent(Grid<?> grid, CellReference<?> targetCell) {
super(grid, targetCell);
}

@Override
public Type<GridDoubleClickHandler> getAssociatedType() {
return TYPE;
}

@Override
@@ -51,5 +69,4 @@ public class GridDoubleClickEvent
handler.onDoubleClick(this);
}
}

}

+ 19
- 1
compatibility-client/src/main/java/com/vaadin/v7/client/widget/grid/events/GridKeyDownEvent.java View File

@@ -31,8 +31,26 @@ import com.vaadin.v7.shared.ui.grid.GridConstants.Section;
*/
public class GridKeyDownEvent extends AbstractGridKeyEvent<GridKeyDownHandler> {

public static final Type<GridKeyDownHandler> TYPE = new Type<GridKeyDownHandler>(
BrowserEvents.KEYDOWN, new GridKeyDownEvent());

/**
* @since 7.7.9
*/
public GridKeyDownEvent() {
}

/**
* @deprecated This constructor's arguments are no longer used. Use the
* no-args constructor instead.
*/
@Deprecated
public GridKeyDownEvent(Grid<?> grid, CellReference<?> targetCell) {
super(grid, targetCell);
}

@Override
public Type<GridKeyDownHandler> getAssociatedType() {
return TYPE;
}

@Override

+ 19
- 1
compatibility-client/src/main/java/com/vaadin/v7/client/widget/grid/events/GridKeyPressEvent.java View File

@@ -31,8 +31,26 @@ import com.vaadin.v7.shared.ui.grid.GridConstants.Section;
public class GridKeyPressEvent
extends AbstractGridKeyEvent<GridKeyPressHandler> {

public static final Type<GridKeyPressHandler> TYPE = new Type<GridKeyPressHandler>(
BrowserEvents.KEYPRESS, new GridKeyPressEvent());

/**
* @since 7.7.9
*/
public GridKeyPressEvent() {
}

/**
* @deprecated This constructor's arguments are no longer used. Use the
* no-args constructor instead.
*/
@Deprecated
public GridKeyPressEvent(Grid<?> grid, CellReference<?> targetCell) {
super(grid, targetCell);
}

@Override
public Type<GridKeyPressHandler> getAssociatedType() {
return TYPE;
}

@Override

+ 19
- 1
compatibility-client/src/main/java/com/vaadin/v7/client/widget/grid/events/GridKeyUpEvent.java View File

@@ -31,8 +31,21 @@ import com.vaadin.v7.shared.ui.grid.GridConstants.Section;
*/
public class GridKeyUpEvent extends AbstractGridKeyEvent<GridKeyUpHandler> {

public static final Type<GridKeyUpHandler> TYPE = new Type<GridKeyUpHandler>(
BrowserEvents.KEYUP, new GridKeyUpEvent());

/**
* @since 7.7.9
*/
public GridKeyUpEvent() {
}

/**
* @deprecated This constructor's arguments are no longer used. Use the
* no-args constructor instead.
*/
@Deprecated
public GridKeyUpEvent(Grid<?> grid, CellReference<?> targetCell) {
super(grid, targetCell);
}

@Override
@@ -46,6 +59,11 @@ public class GridKeyUpEvent extends AbstractGridKeyEvent<GridKeyUpHandler> {
}
}

@Override
public Type<GridKeyUpHandler> getAssociatedType() {
return TYPE;
}

@Override
protected String getBrowserEventType() {
return BrowserEvents.KEYUP;

+ 74
- 58
compatibility-client/src/main/java/com/vaadin/v7/client/widgets/Grid.java View File

@@ -2298,94 +2298,115 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
public static abstract class AbstractGridKeyEvent<HANDLER extends AbstractGridKeyEventHandler>
extends KeyEvent<HANDLER> {

private Grid<?> grid;
private final Type<HANDLER> associatedType = new Type<HANDLER>(
getBrowserEventType(), this);
private final CellReference<?> targetCell;
/**
* @since 7.7.9
*/
public AbstractGridKeyEvent() {
}

/**
* @deprecated This constructor's arguments are no longer used. Use the
* no-args constructor instead.
*/
@Deprecated
public AbstractGridKeyEvent(Grid<?> grid, CellReference<?> targetCell) {
this.grid = grid;
this.targetCell = targetCell;
}

protected abstract String getBrowserEventType();

/**
* Gets the Grid instance for this event.
* Gets the Grid instance for this event, if it originated from a Grid.
*
* @return grid
* @return the grid this event originated from, or {@code null} if this
* event did not originate from a grid
*/
public Grid<?> getGrid() {
return grid;
EventTarget target = getNativeEvent().getEventTarget();
if (!Element.is(target)) {
return null;
}
return WidgetUtil.findWidget(Element.as(target), Grid.class);
}

/**
* Gets the focused cell for this event.
* Gets the reference of target cell for this event, if this event
* originated from a Grid.
*
* @return focused cell
* @return target cell, or {@code null} if this event did not originate
* from a grid
*/
public CellReference<?> getFocusedCell() {
return targetCell;
return getGrid().getEventCell();
}

@Override
protected void dispatch(HANDLER handler) {
EventTarget target = getNativeEvent().getEventTarget();
if (Element.is(target)
Grid<?> grid = getGrid();
if (Element.is(target) && grid != null
&& !grid.isElementInChildWidget(Element.as(target))) {

Section section = Section.FOOTER;
final RowContainer container = grid.cellFocusHandler.containerWithFocus;
if (container == grid.escalator.getHeader()) {
section = Section.HEADER;
} else if (container == grid.escalator.getBody()) {
} else if (container == getGrid().escalator.getBody()) {
section = Section.BODY;
}

doDispatch(handler, section);
}
}

protected abstract void doDispatch(HANDLER handler, Section section);

@Override
public Type<HANDLER> getAssociatedType() {
return associatedType;
}
}

public static abstract class AbstractGridMouseEvent<HANDLER extends AbstractGridMouseEventHandler>
extends MouseEvent<HANDLER> {

private Grid<?> grid;
private final CellReference<?> targetCell;
private final Type<HANDLER> associatedType = new Type<HANDLER>(
getBrowserEventType(), this);
/**
* @since 7.7.9
*/
public AbstractGridMouseEvent() {
}

/**
* @deprecated This constructor's arguments are no longer used. Use the
* no-args constructor instead.
*/
@Deprecated
public AbstractGridMouseEvent(Grid<?> grid,
CellReference<?> targetCell) {
this.grid = grid;
this.targetCell = targetCell;
}

protected abstract String getBrowserEventType();

/**
* Gets the Grid instance for this event.
* Gets the Grid instance for this event, if it originated from a Grid.
*
* @return grid
* @return the grid this event originated from, or {@code null} if this
* event did not originate from a grid
*/
public Grid<?> getGrid() {
return grid;
EventTarget target = getNativeEvent().getEventTarget();
if (!Element.is(target)) {
return null;
}
return WidgetUtil.findWidget(Element.as(target), Grid.class);
}

/**
* Gets the reference of target cell for this event.
* Gets the reference of target cell for this event, if this event
* originated from a Grid.
*
* @return target cell
* @return target cell, or {@code null} if this event did not originate
* from a grid
*/
public CellReference<?> getTargetCell() {
return targetCell;
Grid<?> grid = getGrid();
if (grid == null) {
return null;
}
return grid.getEventCell();
}

@Override
@@ -2396,6 +2417,12 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
return;
}

Grid<?> grid = getGrid();
if (grid == null) {
// Target is not an element of a grid
return;
}

Element targetElement = Element.as(target);
if (grid.isElementInChildWidget(targetElement)) {
// Target is some widget inside of Grid
@@ -2420,11 +2447,6 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
}

protected abstract void doDispatch(HANDLER handler, Section section);

@Override
public Type<HANDLER> getAssociatedType() {
return associatedType;
}
}

private static final String CUSTOM_STYLE_PROPERTY_NAME = "customStyle";
@@ -2438,12 +2460,6 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
private static final double DETAILS_ROW_INITIAL_HEIGHT = 50;

private EventCellReference<T> eventCell = new EventCellReference<T>(this);
private GridKeyDownEvent keyDown = new GridKeyDownEvent(this, eventCell);
private GridKeyUpEvent keyUp = new GridKeyUpEvent(this, eventCell);
private GridKeyPressEvent keyPress = new GridKeyPressEvent(this, eventCell);
private GridClickEvent clickEvent = new GridClickEvent(this, eventCell);
private GridDoubleClickEvent doubleClickEvent = new GridDoubleClickEvent(
this, eventCell);

private class CellFocusHandler {

@@ -8176,7 +8192,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
*/
public HandlerRegistration addBodyKeyDownHandler(
BodyKeyDownHandler handler) {
return addHandler(handler, keyDown.getAssociatedType());
return addHandler(handler, GridKeyDownEvent.TYPE);
}

/**
@@ -8189,7 +8205,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
* @return the registration for the event
*/
public HandlerRegistration addBodyKeyUpHandler(BodyKeyUpHandler handler) {
return addHandler(handler, keyUp.getAssociatedType());
return addHandler(handler, GridKeyUpEvent.TYPE);
}

/**
@@ -8203,7 +8219,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
*/
public HandlerRegistration addBodyKeyPressHandler(
BodyKeyPressHandler handler) {
return addHandler(handler, keyPress.getAssociatedType());
return addHandler(handler, GridKeyPressEvent.TYPE);
}

/**
@@ -8217,7 +8233,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
*/
public HandlerRegistration addHeaderKeyDownHandler(
HeaderKeyDownHandler handler) {
return addHandler(handler, keyDown.getAssociatedType());
return addHandler(handler, GridKeyDownEvent.TYPE);
}

/**
@@ -8231,7 +8247,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
*/
public HandlerRegistration addHeaderKeyUpHandler(
HeaderKeyUpHandler handler) {
return addHandler(handler, keyUp.getAssociatedType());
return addHandler(handler, GridKeyUpEvent.TYPE);
}

/**
@@ -8245,7 +8261,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
*/
public HandlerRegistration addHeaderKeyPressHandler(
HeaderKeyPressHandler handler) {
return addHandler(handler, keyPress.getAssociatedType());
return addHandler(handler, GridKeyPressEvent.TYPE);
}

/**
@@ -8259,7 +8275,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
*/
public HandlerRegistration addFooterKeyDownHandler(
FooterKeyDownHandler handler) {
return addHandler(handler, keyDown.getAssociatedType());
return addHandler(handler, GridKeyDownEvent.TYPE);
}

/**
@@ -8273,7 +8289,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
*/
public HandlerRegistration addFooterKeyUpHandler(
FooterKeyUpHandler handler) {
return addHandler(handler, keyUp.getAssociatedType());
return addHandler(handler, GridKeyUpEvent.TYPE);
}

/**
@@ -8287,7 +8303,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
*/
public HandlerRegistration addFooterKeyPressHandler(
FooterKeyPressHandler handler) {
return addHandler(handler, keyPress.getAssociatedType());
return addHandler(handler, GridKeyPressEvent.TYPE);
}

/**
@@ -8299,7 +8315,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
* @return the registration for the event
*/
public HandlerRegistration addBodyClickHandler(BodyClickHandler handler) {
return addHandler(handler, clickEvent.getAssociatedType());
return addHandler(handler, GridClickEvent.TYPE);
}

/**
@@ -8312,7 +8328,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
*/
public HandlerRegistration addHeaderClickHandler(
HeaderClickHandler handler) {
return addHandler(handler, clickEvent.getAssociatedType());
return addHandler(handler, GridClickEvent.TYPE);
}

/**
@@ -8325,7 +8341,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
*/
public HandlerRegistration addFooterClickHandler(
FooterClickHandler handler) {
return addHandler(handler, clickEvent.getAssociatedType());
return addHandler(handler, GridClickEvent.TYPE);
}

/**
@@ -8339,7 +8355,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
*/
public HandlerRegistration addBodyDoubleClickHandler(
BodyDoubleClickHandler handler) {
return addHandler(handler, doubleClickEvent.getAssociatedType());
return addHandler(handler, GridDoubleClickEvent.TYPE);
}

/**
@@ -8353,7 +8369,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
*/
public HandlerRegistration addHeaderDoubleClickHandler(
HeaderDoubleClickHandler handler) {
return addHandler(handler, doubleClickEvent.getAssociatedType());
return addHandler(handler, GridDoubleClickEvent.TYPE);
}

/**
@@ -8367,7 +8383,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
*/
public HandlerRegistration addFooterDoubleClickHandler(
FooterDoubleClickHandler handler) {
return addHandler(handler, doubleClickEvent.getAssociatedType());
return addHandler(handler, GridDoubleClickEvent.TYPE);
}

/**

+ 40
- 0
uitest/src/main/java/com/vaadin/tests/components/grid/GridClientMemoryLeak.java View File

@@ -0,0 +1,40 @@
package com.vaadin.tests.components.grid;

import com.vaadin.server.VaadinRequest;
import com.vaadin.shared.ui.ContentMode;
import com.vaadin.tests.components.AbstractTestUI;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Grid;
import com.vaadin.ui.Label;
import com.vaadin.ui.VerticalLayout;

public class GridClientMemoryLeak extends AbstractTestUI {

private static final String INSTRUCTIONS = "This UI is for manually testing that the client side grid does not leak memory. "
+ "Steps to take:\n"
+ "\t1. Click the newGrid button 1-n times\n"
+ "\t2. Capture a JS heap dump in your browser\n"
+ "\t3. The heap dump should only contain 1 instance of each of the following:\n"
+ "\t\tGrid, GridKeyDownEvent, GridKeyPressEvent, GridKeyUpEvent, GridClickEvent, GridDoubleClickEvent";

@Override
protected void setup(VaadinRequest request) {
final Label instructionLabel = new Label(INSTRUCTIONS,
ContentMode.PREFORMATTED);
final VerticalLayout layout = new VerticalLayout();
final Button btn = new Button("newGrid");
btn.addClickListener(new Button.ClickListener() {

@Override
public void buttonClick(ClickEvent event) {
layout.removeComponent(layout.getComponent(1));
layout.addComponent(new Grid<String>());
}
});
layout.addComponent(instructionLabel);
layout.addComponent(btn);
layout.addComponent(new Grid<String>());
addComponent(layout);
}
}

Loading…
Cancel
Save