summaryrefslogtreecommitdiffstats
path: root/client/src
diff options
context:
space:
mode:
Diffstat (limited to 'client/src')
-rw-r--r--client/src/com/vaadin/client/ApplicationConnection.java10
-rw-r--r--client/src/com/vaadin/client/EventHelper.java17
-rw-r--r--client/src/com/vaadin/client/connectors/GridConnector.java107
-rw-r--r--client/src/com/vaadin/client/ui/ConnectorFocusAndBlurHandler.java87
-rw-r--r--client/src/com/vaadin/client/ui/VButton.java3
-rw-r--r--client/src/com/vaadin/client/ui/button/ButtonConnector.java38
-rw-r--r--client/src/com/vaadin/client/ui/checkbox/CheckBoxConnector.java34
-rw-r--r--client/src/com/vaadin/client/ui/nativebutton/NativeButtonConnector.java35
-rw-r--r--client/src/com/vaadin/client/ui/nativeselect/NativeSelectConnector.java44
-rw-r--r--client/src/com/vaadin/client/ui/ui/UIConnector.java18
-rw-r--r--client/src/com/vaadin/client/widget/grid/events/EditorCloseEvent.java34
-rw-r--r--client/src/com/vaadin/client/widget/grid/events/EditorEvent.java108
-rw-r--r--client/src/com/vaadin/client/widget/grid/events/EditorEventHandler.java49
-rw-r--r--client/src/com/vaadin/client/widget/grid/events/EditorMoveEvent.java34
-rw-r--r--client/src/com/vaadin/client/widget/grid/events/EditorOpenEvent.java34
-rw-r--r--client/src/com/vaadin/client/widgets/Grid.java388
16 files changed, 798 insertions, 242 deletions
diff --git a/client/src/com/vaadin/client/ApplicationConnection.java b/client/src/com/vaadin/client/ApplicationConnection.java
index 628559dd2a..d9e705426b 100644
--- a/client/src/com/vaadin/client/ApplicationConnection.java
+++ b/client/src/com/vaadin/client/ApplicationConnection.java
@@ -94,7 +94,6 @@ import com.vaadin.client.ui.VOverlay;
import com.vaadin.client.ui.dd.VDragAndDropManager;
import com.vaadin.client.ui.ui.UIConnector;
import com.vaadin.client.ui.window.WindowConnector;
-import com.vaadin.shared.AbstractComponentState;
import com.vaadin.shared.ApplicationConstants;
import com.vaadin.shared.JsonConstants;
import com.vaadin.shared.VaadinUriResolver;
@@ -3378,20 +3377,19 @@ public class ApplicationConnection implements HasHandlers {
* before the component is updated so the value is correct if called from
* updatedFromUIDL.
*
- * @param paintable
+ * @param connector
* The connector to register event listeners for
* @param eventIdentifier
* The identifier for the event
* @return true if at least one listener has been registered on server side
* for the event identified by eventIdentifier.
* @deprecated As of 7.0. Use
- * {@link AbstractComponentState#hasEventListener(String)}
- * instead
+ * {@link AbstractConnector#hasEventListener(String)} instead
*/
@Deprecated
- public boolean hasEventListeners(ComponentConnector paintable,
+ public boolean hasEventListeners(ComponentConnector connector,
String eventIdentifier) {
- return paintable.hasEventListener(eventIdentifier);
+ return connector.hasEventListener(eventIdentifier);
}
/**
diff --git a/client/src/com/vaadin/client/EventHelper.java b/client/src/com/vaadin/client/EventHelper.java
index f251215d41..1ee252af0f 100644
--- a/client/src/com/vaadin/client/EventHelper.java
+++ b/client/src/com/vaadin/client/EventHelper.java
@@ -51,7 +51,6 @@ import com.google.gwt.user.client.ui.Widget;
*
*
* </pre>
- *
*/
public class EventHelper {
@@ -69,7 +68,7 @@ public class EventHelper {
*/
public static <T extends ComponentConnector & FocusHandler> HandlerRegistration updateFocusHandler(
T connector, HandlerRegistration handlerRegistration) {
- return updateHandler(connector, FOCUS, handlerRegistration,
+ return updateHandler(connector, connector, FOCUS, handlerRegistration,
FocusEvent.getType(), connector.getWidget());
}
@@ -89,7 +88,7 @@ public class EventHelper {
*/
public static <T extends ComponentConnector & FocusHandler> HandlerRegistration updateFocusHandler(
T connector, HandlerRegistration handlerRegistration, Widget widget) {
- return updateHandler(connector, FOCUS, handlerRegistration,
+ return updateHandler(connector, connector, FOCUS, handlerRegistration,
FocusEvent.getType(), widget);
}
@@ -107,7 +106,7 @@ public class EventHelper {
*/
public static <T extends ComponentConnector & BlurHandler> HandlerRegistration updateBlurHandler(
T connector, HandlerRegistration handlerRegistration) {
- return updateHandler(connector, BLUR, handlerRegistration,
+ return updateHandler(connector, connector, BLUR, handlerRegistration,
BlurEvent.getType(), connector.getWidget());
}
@@ -128,23 +127,21 @@ public class EventHelper {
*/
public static <T extends ComponentConnector & BlurHandler> HandlerRegistration updateBlurHandler(
T connector, HandlerRegistration handlerRegistration, Widget widget) {
- return updateHandler(connector, BLUR, handlerRegistration,
+ return updateHandler(connector, connector, BLUR, handlerRegistration,
BlurEvent.getType(), widget);
}
- private static <H extends EventHandler> HandlerRegistration updateHandler(
- ComponentConnector connector, String eventIdentifier,
+ public static <H extends EventHandler> HandlerRegistration updateHandler(
+ ComponentConnector connector, H handler, String eventIdentifier,
HandlerRegistration handlerRegistration, Type<H> type, Widget widget) {
if (connector.hasEventListener(eventIdentifier)) {
if (handlerRegistration == null) {
- handlerRegistration = widget.addDomHandler((H) connector, type);
+ handlerRegistration = widget.addDomHandler(handler, type);
}
} else if (handlerRegistration != null) {
handlerRegistration.removeHandler();
handlerRegistration = null;
}
return handlerRegistration;
-
}
-
}
diff --git a/client/src/com/vaadin/client/connectors/GridConnector.java b/client/src/com/vaadin/client/connectors/GridConnector.java
index 4c2e8ab4e1..62326c4b07 100644
--- a/client/src/com/vaadin/client/connectors/GridConnector.java
+++ b/client/src/com/vaadin/client/connectors/GridConnector.java
@@ -31,6 +31,7 @@ import java.util.logging.Logger;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
+import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.ui.Widget;
@@ -38,8 +39,8 @@ import com.vaadin.client.ComponentConnector;
import com.vaadin.client.ConnectorHierarchyChangeEvent;
import com.vaadin.client.DeferredWorker;
import com.vaadin.client.MouseEventDetailsBuilder;
+import com.vaadin.client.TooltipInfo;
import com.vaadin.client.ServerConnector;
-import com.vaadin.client.annotations.OnStateChange;
import com.vaadin.client.communication.StateChangeEvent;
import com.vaadin.client.connectors.RpcDataSourceConnector.DetailsListener;
import com.vaadin.client.connectors.RpcDataSourceConnector.RpcDataSource;
@@ -47,6 +48,7 @@ import com.vaadin.client.data.DataSource.RowHandle;
import com.vaadin.client.renderers.Renderer;
import com.vaadin.client.ui.AbstractFieldConnector;
import com.vaadin.client.ui.AbstractHasComponentsConnector;
+import com.vaadin.client.ui.ConnectorFocusAndBlurHandler;
import com.vaadin.client.ui.SimpleManagedLayout;
import com.vaadin.client.widget.grid.CellReference;
import com.vaadin.client.widget.grid.CellStyleGenerator;
@@ -60,6 +62,10 @@ import com.vaadin.client.widget.grid.events.ColumnReorderEvent;
import com.vaadin.client.widget.grid.events.ColumnReorderHandler;
import com.vaadin.client.widget.grid.events.ColumnVisibilityChangeEvent;
import com.vaadin.client.widget.grid.events.ColumnVisibilityChangeHandler;
+import com.vaadin.client.widget.grid.events.EditorCloseEvent;
+import com.vaadin.client.widget.grid.events.EditorEventHandler;
+import com.vaadin.client.widget.grid.events.EditorMoveEvent;
+import com.vaadin.client.widget.grid.events.EditorOpenEvent;
import com.vaadin.client.widget.grid.events.GridClickEvent;
import com.vaadin.client.widget.grid.events.GridDoubleClickEvent;
import com.vaadin.client.widget.grid.events.SelectAllEvent;
@@ -113,8 +119,8 @@ import elemental.json.JsonValue;
public class GridConnector extends AbstractHasComponentsConnector implements
SimpleManagedLayout, DeferredWorker {
- private static final class CustomCellStyleGenerator implements
- CellStyleGenerator<JsonObject> {
+ private static final class CustomStyleGenerator implements
+ CellStyleGenerator<JsonObject>, RowStyleGenerator<JsonObject> {
@Override
public String getStyle(CellReference<JsonObject> cellReference) {
JsonObject row = cellReference.getRow();
@@ -140,10 +146,6 @@ public class GridConnector extends AbstractHasComponentsConnector implements
}
}
- }
-
- private static final class CustomRowStyleGenerator implements
- RowStyleGenerator<JsonObject> {
@Override
public String getStyle(RowReference<JsonObject> rowReference) {
JsonObject row = rowReference.getRow();
@@ -153,7 +155,6 @@ public class GridConnector extends AbstractHasComponentsConnector implements
return null;
}
}
-
}
/**
@@ -580,6 +581,7 @@ public class GridConnector extends AbstractHasComponentsConnector implements
private String lastKnownTheme = null;
private final CustomDetailsGenerator customDetailsGenerator = new CustomDetailsGenerator();
+ private final CustomStyleGenerator styleGenerator = new CustomStyleGenerator();
private final DetailsListener detailsListener = new DetailsListener() {
@Override
@@ -691,6 +693,10 @@ public class GridConnector extends AbstractHasComponentsConnector implements
getWidget().addBodyClickHandler(itemClickHandler);
getWidget().addBodyDoubleClickHandler(itemClickHandler);
+ /* Style Generators */
+ getWidget().setCellStyleGenerator(styleGenerator);
+ getWidget().setRowStyleGenerator(styleGenerator);
+
getWidget().addSortHandler(new SortHandler<JsonObject>() {
@Override
public void sort(SortEvent<JsonObject> event) {
@@ -728,9 +734,38 @@ public class GridConnector extends AbstractHasComponentsConnector implements
getWidget().addColumnReorderHandler(columnReorderHandler);
getWidget().addColumnVisibilityChangeHandler(
columnVisibilityChangeHandler);
+
+ ConnectorFocusAndBlurHandler.addHandlers(this);
+
getWidget().setDetailsGenerator(customDetailsGenerator);
getLayoutManager().registerDependency(this, getWidget().getElement());
+ getWidget().addEditorEventHandler(new EditorEventHandler() {
+ @Override
+ public void onEditorOpen(EditorOpenEvent e) {
+ if (hasEventListener(GridConstants.EDITOR_OPEN_EVENT_ID)) {
+ String rowKey = getRowKey((JsonObject) e.getRow());
+ getRpcProxy(GridServerRpc.class).editorOpen(rowKey);
+ }
+ }
+
+ @Override
+ public void onEditorMove(EditorMoveEvent e) {
+ if (hasEventListener(GridConstants.EDITOR_MOVE_EVENT_ID)) {
+ String rowKey = getRowKey((JsonObject) e.getRow());
+ getRpcProxy(GridServerRpc.class).editorMove(rowKey);
+ }
+ }
+
+ @Override
+ public void onEditorClose(EditorCloseEvent e) {
+ if (hasEventListener(GridConstants.EDITOR_CLOSE_EVENT_ID)) {
+ String rowKey = getRowKey((JsonObject) e.getRow());
+ getRpcProxy(GridServerRpc.class).editorClose(rowKey);
+ }
+ }
+ });
+
layout();
}
@@ -1080,24 +1115,6 @@ public class GridConnector extends AbstractHasComponentsConnector implements
}
}
- @OnStateChange("hasCellStyleGenerator")
- private void onCellStyleGeneratorChange() {
- if (getState().hasCellStyleGenerator) {
- getWidget().setCellStyleGenerator(new CustomCellStyleGenerator());
- } else {
- getWidget().setCellStyleGenerator(null);
- }
- }
-
- @OnStateChange("hasRowStyleGenerator")
- private void onRowStyleGeneratorChange() {
- if (getState().hasRowStyleGenerator) {
- getWidget().setRowStyleGenerator(new CustomRowStyleGenerator());
- } else {
- getWidget().setRowStyleGenerator(null);
- }
- }
-
private void updateSelectionFromState() {
boolean changed = false;
@@ -1252,4 +1269,42 @@ public class GridConnector extends AbstractHasComponentsConnector implements
public DetailsListener getDetailsListener() {
return detailsListener;
}
+
+ @Override
+ public boolean hasTooltip() {
+ return getState().hasDescriptions || super.hasTooltip();
+ }
+
+ @Override
+ public TooltipInfo getTooltipInfo(Element element) {
+ CellReference<JsonObject> cell = getWidget().getCellReference(element);
+
+ if (cell != null) {
+ JsonObject row = cell.getRow();
+ if (row == null) {
+ return null;
+ }
+
+ Column<?, JsonObject> column = cell.getColumn();
+ if (!(column instanceof CustomGridColumn)) {
+ // Selection checkbox column
+ return null;
+ }
+ CustomGridColumn c = (CustomGridColumn) column;
+
+ JsonObject cellDescriptions = row
+ .getObject(GridState.JSONKEY_CELLDESCRIPTION);
+
+ if (cellDescriptions != null && cellDescriptions.hasKey(c.id)) {
+ return new TooltipInfo(cellDescriptions.getString(c.id));
+ } else if (row.hasKey(GridState.JSONKEY_ROWDESCRIPTION)) {
+ return new TooltipInfo(
+ row.getString(GridState.JSONKEY_ROWDESCRIPTION));
+ } else {
+ return null;
+ }
+ }
+
+ return super.getTooltipInfo(element);
+ }
}
diff --git a/client/src/com/vaadin/client/ui/ConnectorFocusAndBlurHandler.java b/client/src/com/vaadin/client/ui/ConnectorFocusAndBlurHandler.java
new file mode 100644
index 0000000000..8272f99d25
--- /dev/null
+++ b/client/src/com/vaadin/client/ui/ConnectorFocusAndBlurHandler.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.client.ui;
+
+import com.google.gwt.event.dom.client.BlurEvent;
+import com.google.gwt.event.dom.client.BlurHandler;
+import com.google.gwt.event.dom.client.FocusEvent;
+import com.google.gwt.event.dom.client.FocusHandler;
+import com.google.gwt.event.shared.HandlerRegistration;
+import com.google.gwt.user.client.ui.Widget;
+import com.vaadin.client.EventHelper;
+import com.vaadin.client.communication.StateChangeEvent;
+import com.vaadin.client.communication.StateChangeEvent.StateChangeHandler;
+import com.vaadin.shared.EventId;
+import com.vaadin.shared.communication.FieldRpc.FocusAndBlurServerRpc;
+
+/**
+ * A handler for focus and blur events which uses {@link FocusAndBlurServerRpc}
+ * to transmit received events to the server. Events are only handled if there
+ * is a corresponding listener on the server side.
+ *
+ * @since 7.6
+ * @author Vaadin Ltd
+ */
+public class ConnectorFocusAndBlurHandler implements StateChangeHandler,
+ FocusHandler, BlurHandler {
+
+ private final AbstractComponentConnector connector;
+ private final Widget widget;
+ private HandlerRegistration focusRegistration = null;
+ private HandlerRegistration blurRegistration = null;
+
+ public static void addHandlers(AbstractComponentConnector connector) {
+ addHandlers(connector, connector.getWidget());
+ }
+
+ public static void addHandlers(AbstractComponentConnector connector,
+ Widget widget) {
+ connector.addStateChangeHandler("registeredEventListeners",
+ new ConnectorFocusAndBlurHandler(connector, widget));
+ }
+
+ private ConnectorFocusAndBlurHandler(AbstractComponentConnector connector,
+ Widget widget) {
+ this.connector = connector;
+ this.widget = widget;
+ }
+
+ @Override
+ public void onStateChanged(StateChangeEvent stateChangeEvent) {
+ focusRegistration = EventHelper.updateHandler(connector, this,
+ EventId.FOCUS, focusRegistration, FocusEvent.getType(), widget);
+ blurRegistration = EventHelper.updateHandler(connector, this,
+ EventId.BLUR, blurRegistration, BlurEvent.getType(), widget);
+ }
+
+ @Override
+ public void onFocus(FocusEvent event) {
+ // updateHandler ensures that this is called only when
+ // there is a listener on the server side
+ getRpc().focus();
+ }
+
+ @Override
+ public void onBlur(BlurEvent event) {
+ // updateHandler ensures that this is called only when
+ // there is a listener on the server side
+ getRpc().blur();
+ }
+
+ private FocusAndBlurServerRpc getRpc() {
+ return connector.getRpcProxy(FocusAndBlurServerRpc.class);
+ }
+}
diff --git a/client/src/com/vaadin/client/ui/VButton.java b/client/src/com/vaadin/client/ui/VButton.java
index bf321f7f00..2eb967c4fa 100644
--- a/client/src/com/vaadin/client/ui/VButton.java
+++ b/client/src/com/vaadin/client/ui/VButton.java
@@ -23,7 +23,6 @@ import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyCodes;
-import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.ui.FocusWidget;
@@ -94,8 +93,6 @@ public class VButton extends FocusWidget implements ClickHandler {
/** For internal use only. May be removed or replaced in the future. */
public int clickShortcut = 0;
- private HandlerRegistration focusHandlerRegistration;
- private HandlerRegistration blurHandlerRegistration;
private long lastClickTime = 0;
public VButton() {
diff --git a/client/src/com/vaadin/client/ui/button/ButtonConnector.java b/client/src/com/vaadin/client/ui/button/ButtonConnector.java
index 2d13d62a91..2c2006e19b 100644
--- a/client/src/com/vaadin/client/ui/button/ButtonConnector.java
+++ b/client/src/com/vaadin/client/ui/button/ButtonConnector.java
@@ -16,24 +16,17 @@
package com.vaadin.client.ui.button;
-import com.google.gwt.event.dom.client.BlurEvent;
-import com.google.gwt.event.dom.client.BlurHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.event.dom.client.FocusEvent;
-import com.google.gwt.event.dom.client.FocusHandler;
-import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.DOM;
-import com.vaadin.client.EventHelper;
import com.vaadin.client.MouseEventDetailsBuilder;
import com.vaadin.client.VCaption;
import com.vaadin.client.annotations.OnStateChange;
-import com.vaadin.client.communication.StateChangeEvent;
import com.vaadin.client.ui.AbstractComponentConnector;
+import com.vaadin.client.ui.ConnectorFocusAndBlurHandler;
import com.vaadin.client.ui.Icon;
import com.vaadin.client.ui.VButton;
import com.vaadin.shared.MouseEventDetails;
-import com.vaadin.shared.communication.FieldRpc.FocusAndBlurServerRpc;
import com.vaadin.shared.ui.Connect;
import com.vaadin.shared.ui.Connect.LoadStyle;
import com.vaadin.shared.ui.button.ButtonServerRpc;
@@ -42,10 +35,7 @@ import com.vaadin.ui.Button;
@Connect(value = Button.class, loadStyle = LoadStyle.EAGER)
public class ButtonConnector extends AbstractComponentConnector implements
- BlurHandler, FocusHandler, ClickHandler {
-
- private HandlerRegistration focusHandlerRegistration = null;
- private HandlerRegistration blurHandlerRegistration = null;
+ ClickHandler {
@Override
public boolean delegateCaptionHandling() {
@@ -57,6 +47,7 @@ public class ButtonConnector extends AbstractComponentConnector implements
super.init();
getWidget().addClickHandler(this);
getWidget().client = getConnection();
+ ConnectorFocusAndBlurHandler.addHandlers(this);
}
@OnStateChange("errorMessage")
@@ -90,15 +81,6 @@ public class ButtonConnector extends AbstractComponentConnector implements
}
}
- @Override
- public void onStateChanged(StateChangeEvent stateChangeEvent) {
- super.onStateChanged(stateChangeEvent);
- focusHandlerRegistration = EventHelper.updateFocusHandler(this,
- focusHandlerRegistration);
- blurHandlerRegistration = EventHelper.updateBlurHandler(this,
- blurHandlerRegistration);
- }
-
@OnStateChange({ "caption", "captionAsHtml" })
void setCaption() {
VCaption.setCaptionText(getWidget().captionElement, getState());
@@ -127,20 +109,6 @@ public class ButtonConnector extends AbstractComponentConnector implements
}
@Override
- public void onFocus(FocusEvent event) {
- // EventHelper.updateFocusHandler ensures that this is called only when
- // there is a listener on server side
- getRpcProxy(FocusAndBlurServerRpc.class).focus();
- }
-
- @Override
- public void onBlur(BlurEvent event) {
- // EventHelper.updateFocusHandler ensures that this is called only when
- // there is a listener on server side
- getRpcProxy(FocusAndBlurServerRpc.class).blur();
- }
-
- @Override
public void onClick(ClickEvent event) {
if (getState().disableOnClick) {
// Simulate getting disabled from the server without waiting for the
diff --git a/client/src/com/vaadin/client/ui/checkbox/CheckBoxConnector.java b/client/src/com/vaadin/client/ui/checkbox/CheckBoxConnector.java
index 9e689f3314..8cfcf7feb1 100644
--- a/client/src/com/vaadin/client/ui/checkbox/CheckBoxConnector.java
+++ b/client/src/com/vaadin/client/ui/checkbox/CheckBoxConnector.java
@@ -16,25 +16,19 @@
package com.vaadin.client.ui.checkbox;
import com.google.gwt.dom.client.Style.Display;
-import com.google.gwt.event.dom.client.BlurEvent;
-import com.google.gwt.event.dom.client.BlurHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.event.dom.client.FocusEvent;
-import com.google.gwt.event.dom.client.FocusHandler;
-import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event;
-import com.vaadin.client.EventHelper;
import com.vaadin.client.MouseEventDetailsBuilder;
import com.vaadin.client.VCaption;
import com.vaadin.client.VTooltip;
import com.vaadin.client.communication.StateChangeEvent;
import com.vaadin.client.ui.AbstractFieldConnector;
+import com.vaadin.client.ui.ConnectorFocusAndBlurHandler;
import com.vaadin.client.ui.Icon;
import com.vaadin.client.ui.VCheckBox;
import com.vaadin.shared.MouseEventDetails;
-import com.vaadin.shared.communication.FieldRpc.FocusAndBlurServerRpc;
import com.vaadin.shared.ui.Connect;
import com.vaadin.shared.ui.checkbox.CheckBoxServerRpc;
import com.vaadin.shared.ui.checkbox.CheckBoxState;
@@ -42,10 +36,7 @@ import com.vaadin.ui.CheckBox;
@Connect(CheckBox.class)
public class CheckBoxConnector extends AbstractFieldConnector implements
- FocusHandler, BlurHandler, ClickHandler {
-
- private HandlerRegistration focusHandlerRegistration;
- private HandlerRegistration blurHandlerRegistration;
+ ClickHandler {
@Override
public boolean delegateCaptionHandling() {
@@ -55,21 +46,18 @@ public class CheckBoxConnector extends AbstractFieldConnector implements
@Override
protected void init() {
super.init();
+
getWidget().addClickHandler(this);
getWidget().client = getConnection();
getWidget().id = getConnectorId();
+ ConnectorFocusAndBlurHandler.addHandlers(this);
}
@Override
public void onStateChanged(StateChangeEvent stateChangeEvent) {
super.onStateChanged(stateChangeEvent);
- focusHandlerRegistration = EventHelper.updateFocusHandler(this,
- focusHandlerRegistration);
- blurHandlerRegistration = EventHelper.updateBlurHandler(this,
- blurHandlerRegistration);
-
if (null != getState().errorMessage) {
getWidget().setAriaInvalid(true);
@@ -127,20 +115,6 @@ public class CheckBoxConnector extends AbstractFieldConnector implements
}
@Override
- public void onFocus(FocusEvent event) {
- // EventHelper.updateFocusHandler ensures that this is called only when
- // there is a listener on server side
- getRpcProxy(FocusAndBlurServerRpc.class).focus();
- }
-
- @Override
- public void onBlur(BlurEvent event) {
- // EventHelper.updateFocusHandler ensures that this is called only when
- // there is a listener on server side
- getRpcProxy(FocusAndBlurServerRpc.class).blur();
- }
-
- @Override
public void onClick(ClickEvent event) {
if (!isEnabled()) {
return;
diff --git a/client/src/com/vaadin/client/ui/nativebutton/NativeButtonConnector.java b/client/src/com/vaadin/client/ui/nativebutton/NativeButtonConnector.java
index 2aae9beae6..65d4a1eb9b 100644
--- a/client/src/com/vaadin/client/ui/nativebutton/NativeButtonConnector.java
+++ b/client/src/com/vaadin/client/ui/nativebutton/NativeButtonConnector.java
@@ -15,30 +15,20 @@
*/
package com.vaadin.client.ui.nativebutton;
-import com.google.gwt.event.dom.client.BlurEvent;
-import com.google.gwt.event.dom.client.BlurHandler;
-import com.google.gwt.event.dom.client.FocusEvent;
-import com.google.gwt.event.dom.client.FocusHandler;
-import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.DOM;
-import com.vaadin.client.EventHelper;
import com.vaadin.client.VCaption;
import com.vaadin.client.communication.StateChangeEvent;
import com.vaadin.client.ui.AbstractComponentConnector;
+import com.vaadin.client.ui.ConnectorFocusAndBlurHandler;
import com.vaadin.client.ui.Icon;
import com.vaadin.client.ui.VNativeButton;
-import com.vaadin.shared.communication.FieldRpc.FocusAndBlurServerRpc;
import com.vaadin.shared.ui.Connect;
import com.vaadin.shared.ui.button.ButtonServerRpc;
import com.vaadin.shared.ui.button.NativeButtonState;
import com.vaadin.ui.NativeButton;
@Connect(NativeButton.class)
-public class NativeButtonConnector extends AbstractComponentConnector implements
- BlurHandler, FocusHandler {
-
- private HandlerRegistration focusHandlerRegistration;
- private HandlerRegistration blurHandlerRegistration;
+public class NativeButtonConnector extends AbstractComponentConnector {
@Override
public void init() {
@@ -47,6 +37,8 @@ public class NativeButtonConnector extends AbstractComponentConnector implements
getWidget().buttonRpcProxy = getRpcProxy(ButtonServerRpc.class);
getWidget().client = getConnection();
getWidget().paintableId = getConnectorId();
+
+ ConnectorFocusAndBlurHandler.addHandlers(this);
}
@Override
@@ -59,10 +51,6 @@ public class NativeButtonConnector extends AbstractComponentConnector implements
super.onStateChanged(stateChangeEvent);
getWidget().disableOnClick = getState().disableOnClick;
- focusHandlerRegistration = EventHelper.updateFocusHandler(this,
- focusHandlerRegistration);
- blurHandlerRegistration = EventHelper.updateBlurHandler(this,
- blurHandlerRegistration);
// Set text
VCaption.setCaptionText(getWidget(), getState());
@@ -107,19 +95,4 @@ public class NativeButtonConnector extends AbstractComponentConnector implements
public NativeButtonState getState() {
return (NativeButtonState) super.getState();
}
-
- @Override
- public void onFocus(FocusEvent event) {
- // EventHelper.updateFocusHandler ensures that this is called only when
- // there is a listener on server side
- getRpcProxy(FocusAndBlurServerRpc.class).focus();
- }
-
- @Override
- public void onBlur(BlurEvent event) {
- // EventHelper.updateFocusHandler ensures that this is called only when
- // there is a listener on server side
- getRpcProxy(FocusAndBlurServerRpc.class).blur();
- }
-
}
diff --git a/client/src/com/vaadin/client/ui/nativeselect/NativeSelectConnector.java b/client/src/com/vaadin/client/ui/nativeselect/NativeSelectConnector.java
index 938903da9a..d6ff2015b4 100644
--- a/client/src/com/vaadin/client/ui/nativeselect/NativeSelectConnector.java
+++ b/client/src/com/vaadin/client/ui/nativeselect/NativeSelectConnector.java
@@ -16,55 +16,23 @@
package com.vaadin.client.ui.nativeselect;
-import com.google.gwt.event.dom.client.BlurEvent;
-import com.google.gwt.event.dom.client.BlurHandler;
-import com.google.gwt.event.dom.client.FocusEvent;
-import com.google.gwt.event.dom.client.FocusHandler;
-import com.google.gwt.event.shared.HandlerRegistration;
-import com.vaadin.client.EventHelper;
-import com.vaadin.client.annotations.OnStateChange;
+import com.vaadin.client.ui.ConnectorFocusAndBlurHandler;
import com.vaadin.client.ui.VNativeSelect;
import com.vaadin.client.ui.optiongroup.OptionGroupBaseConnector;
-import com.vaadin.shared.communication.FieldRpc.FocusAndBlurServerRpc;
import com.vaadin.shared.ui.Connect;
import com.vaadin.ui.NativeSelect;
@Connect(NativeSelect.class)
-public class NativeSelectConnector extends OptionGroupBaseConnector implements
- BlurHandler, FocusHandler {
+public class NativeSelectConnector extends OptionGroupBaseConnector {
- private HandlerRegistration focusHandlerRegistration = null;
- private HandlerRegistration blurHandlerRegistration = null;
-
- public NativeSelectConnector() {
- super();
- }
-
- @OnStateChange("registeredEventListeners")
- private void onServerEventListenerChanged() {
- focusHandlerRegistration = EventHelper.updateFocusHandler(this,
- focusHandlerRegistration, getWidget().getSelect());
- blurHandlerRegistration = EventHelper.updateBlurHandler(this,
- blurHandlerRegistration, getWidget().getSelect());
+ @Override
+ protected void init() {
+ super.init();
+ ConnectorFocusAndBlurHandler.addHandlers(this, getWidget().getSelect());
}
@Override
public VNativeSelect getWidget() {
return (VNativeSelect) super.getWidget();
}
-
- @Override
- public void onFocus(FocusEvent event) {
- // EventHelper.updateFocusHandler ensures that this is called only when
- // there is a listener on server side
- getRpcProxy(FocusAndBlurServerRpc.class).focus();
- }
-
- @Override
- public void onBlur(BlurEvent event) {
- // EventHelper.updateFocusHandler ensures that this is called only when
- // there is a listener on server side
- getRpcProxy(FocusAndBlurServerRpc.class).blur();
- }
-
}
diff --git a/client/src/com/vaadin/client/ui/ui/UIConnector.java b/client/src/com/vaadin/client/ui/ui/UIConnector.java
index cfb444ada6..9d8aa5b877 100644
--- a/client/src/com/vaadin/client/ui/ui/UIConnector.java
+++ b/client/src/com/vaadin/client/ui/ui/UIConnector.java
@@ -59,6 +59,7 @@ import com.vaadin.client.ResourceLoader.ResourceLoadEvent;
import com.vaadin.client.ResourceLoader.ResourceLoadListener;
import com.vaadin.client.ServerConnector;
import com.vaadin.client.UIDL;
+import com.vaadin.client.Util;
import com.vaadin.client.VConsole;
import com.vaadin.client.ValueMap;
import com.vaadin.client.annotations.OnStateChange;
@@ -319,19 +320,19 @@ public class UIConnector extends AbstractSingleComponentContainerConnector
Scheduler.get().scheduleDeferred(new Command() {
@Override
public void execute() {
- ComponentConnector paintable = (ComponentConnector) uidl
+ ComponentConnector connector = (ComponentConnector) uidl
.getPaintableAttribute("focused", getConnection());
- if (paintable == null) {
+ if (connector == null) {
// Do not try to focus invisible components which not
// present in UIDL
return;
}
- final Widget toBeFocused = paintable.getWidget();
+ final Widget toBeFocused = connector.getWidget();
/*
* Two types of Widgets can be focused, either implementing
- * GWT HasFocus of a thinner Vaadin specific Focusable
+ * GWT Focusable of a thinner Vaadin specific Focusable
* interface.
*/
if (toBeFocused instanceof com.google.gwt.user.client.ui.Focusable) {
@@ -340,7 +341,14 @@ public class UIConnector extends AbstractSingleComponentContainerConnector
} else if (toBeFocused instanceof Focusable) {
((Focusable) toBeFocused).focus();
} else {
- VConsole.log("Could not focus component");
+ getLogger()
+ .severe("Server is trying to set focus to the widget of connector "
+ + Util.getConnectorString(connector)
+ + " but it is not focusable. The widget should implement either "
+ + com.google.gwt.user.client.ui.Focusable.class
+ .getName()
+ + " or "
+ + Focusable.class.getName());
}
}
});
diff --git a/client/src/com/vaadin/client/widget/grid/events/EditorCloseEvent.java b/client/src/com/vaadin/client/widget/grid/events/EditorCloseEvent.java
new file mode 100644
index 0000000000..99f59aa82a
--- /dev/null
+++ b/client/src/com/vaadin/client/widget/grid/events/EditorCloseEvent.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.client.widget.grid.events;
+
+import com.vaadin.client.widget.grid.CellReference;
+
+/**
+ * Event that gets fired when an open editor is closed (and not reopened
+ * elsewhere)
+ */
+public class EditorCloseEvent extends EditorEvent {
+
+ public EditorCloseEvent(CellReference<?> cell) {
+ super(cell);
+ }
+
+ @Override
+ protected void dispatch(EditorEventHandler handler) {
+ handler.onEditorClose(this);
+ }
+} \ No newline at end of file
diff --git a/client/src/com/vaadin/client/widget/grid/events/EditorEvent.java b/client/src/com/vaadin/client/widget/grid/events/EditorEvent.java
new file mode 100644
index 0000000000..eb34033197
--- /dev/null
+++ b/client/src/com/vaadin/client/widget/grid/events/EditorEvent.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.client.widget.grid.events;
+
+import com.google.gwt.event.shared.GwtEvent;
+import com.vaadin.client.widget.grid.CellReference;
+import com.vaadin.client.widgets.Grid;
+import com.vaadin.client.widgets.Grid.Column;
+
+/**
+ * Base class for editor events.
+ */
+public abstract class EditorEvent extends GwtEvent<EditorEventHandler> {
+ public static final Type<EditorEventHandler> TYPE = new Type<EditorEventHandler>();
+
+ private CellReference<?> cell;
+
+ protected EditorEvent(CellReference<?> cell) {
+ this.cell = cell;
+ }
+
+ @Override
+ public Type<EditorEventHandler> getAssociatedType() {
+ return TYPE;
+ }
+
+ /**
+ * Get a reference to the Grid that fired this Event.
+ *
+ * @return a Grid reference
+ */
+ @SuppressWarnings("unchecked")
+ public <T> Grid<T> getGrid() {
+ return (Grid<T>) cell.getGrid();
+ }
+
+ /**
+ * Get a reference to the cell that was active when this Event was fired.
+ * NOTE: do <i>NOT</i> rely on this information remaining accurate after
+ * leaving the event handler.
+ *
+ * @return a cell reference
+ */
+ @SuppressWarnings("unchecked")
+ public <T> CellReference<T> getCell() {
+ return (CellReference<T>) cell;
+ }
+
+ /**
+ * Get a reference to the row that was active when this Event was fired.
+ * NOTE: do <i>NOT</i> rely on this information remaining accurate after
+ * leaving the event handler.
+ *
+ * @return a row data object
+ */
+ @SuppressWarnings("unchecked")
+ public <T> T getRow() {
+ return (T) cell.getRow();
+ }
+
+ /**
+ * Get the index of the row that was active when this Event was fired. NOTE:
+ * do <i>NOT</i> rely on this information remaining accurate after leaving
+ * the event handler.
+ *
+ * @return an integer value
+ */
+ public int getRowIndex() {
+ return cell.getRowIndex();
+ }
+
+ /**
+ * Get a reference to the column that was active when this Event was fired.
+ * NOTE: do <i>NOT</i> rely on this information remaining accurate after
+ * leaving the event handler.
+ *
+ * @return a column object
+ */
+ @SuppressWarnings("unchecked")
+ public <C, T> Column<C, T> getColumn() {
+ return (Column<C, T>) cell.getColumn();
+ }
+
+ /**
+ * Get the index of the column that was active when this Event was fired.
+ * NOTE: do <i>NOT</i> rely on this information remaining accurate after
+ * leaving the event handler.
+ *
+ * @return an integer value
+ */
+ public int getColumnIndex() {
+ return cell.getColumnIndex();
+ }
+
+} \ No newline at end of file
diff --git a/client/src/com/vaadin/client/widget/grid/events/EditorEventHandler.java b/client/src/com/vaadin/client/widget/grid/events/EditorEventHandler.java
new file mode 100644
index 0000000000..4f9396a9f1
--- /dev/null
+++ b/client/src/com/vaadin/client/widget/grid/events/EditorEventHandler.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.client.widget.grid.events;
+
+import com.google.gwt.event.shared.EventHandler;
+
+/**
+ * Common handler interface for editor events
+ */
+public interface EditorEventHandler extends EventHandler {
+
+ /**
+ * Action to perform when the editor has been opened
+ *
+ * @param e
+ * an editor open event object
+ */
+ public void onEditorOpen(EditorOpenEvent e);
+
+ /**
+ * Action to perform when the editor is re-opened on another row
+ *
+ * @param e
+ * an editor move event object
+ */
+ public void onEditorMove(EditorMoveEvent e);
+
+ /**
+ * Action to perform when the editor is closed
+ *
+ * @param e
+ * an editor close event object
+ */
+ public void onEditorClose(EditorCloseEvent e);
+
+} \ No newline at end of file
diff --git a/client/src/com/vaadin/client/widget/grid/events/EditorMoveEvent.java b/client/src/com/vaadin/client/widget/grid/events/EditorMoveEvent.java
new file mode 100644
index 0000000000..0e5e2dcd7b
--- /dev/null
+++ b/client/src/com/vaadin/client/widget/grid/events/EditorMoveEvent.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.client.widget.grid.events;
+
+import com.vaadin.client.widget.grid.CellReference;
+
+/**
+ * Event that gets fired when an already open editor is closed and re-opened on
+ * another row
+ */
+public class EditorMoveEvent extends EditorEvent {
+
+ public EditorMoveEvent(CellReference<?> cell) {
+ super(cell);
+ }
+
+ @Override
+ protected void dispatch(EditorEventHandler handler) {
+ handler.onEditorMove(this);
+ }
+} \ No newline at end of file
diff --git a/client/src/com/vaadin/client/widget/grid/events/EditorOpenEvent.java b/client/src/com/vaadin/client/widget/grid/events/EditorOpenEvent.java
new file mode 100644
index 0000000000..df0171945f
--- /dev/null
+++ b/client/src/com/vaadin/client/widget/grid/events/EditorOpenEvent.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.client.widget.grid.events;
+
+import com.vaadin.client.widget.grid.CellReference;
+
+/**
+ * Event that gets fired when the editor is opened
+ */
+public class EditorOpenEvent extends EditorEvent {
+
+ public EditorOpenEvent(CellReference<?> cell) {
+ super(cell);
+ }
+
+ @Override
+ protected void dispatch(EditorEventHandler handler) {
+ handler.onEditorOpen(this);
+ }
+
+} \ No newline at end of file
diff --git a/client/src/com/vaadin/client/widgets/Grid.java b/client/src/com/vaadin/client/widgets/Grid.java
index 377943ed61..a17c59c795 100644
--- a/client/src/com/vaadin/client/widgets/Grid.java
+++ b/client/src/com/vaadin/client/widgets/Grid.java
@@ -42,6 +42,7 @@ import com.google.gwt.dom.client.EventTarget;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.dom.client.Node;
import com.google.gwt.dom.client.Style;
+import com.google.gwt.dom.client.Style.Display;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.dom.client.TableCellElement;
import com.google.gwt.dom.client.TableRowElement;
@@ -79,6 +80,7 @@ import com.vaadin.client.Focusable;
import com.vaadin.client.WidgetUtil;
import com.vaadin.client.data.DataChangeHandler;
import com.vaadin.client.data.DataSource;
+import com.vaadin.client.data.DataSource.RowHandle;
import com.vaadin.client.renderers.ComplexRenderer;
import com.vaadin.client.renderers.Renderer;
import com.vaadin.client.renderers.WidgetRenderer;
@@ -121,6 +123,11 @@ import com.vaadin.client.widget.grid.events.ColumnReorderEvent;
import com.vaadin.client.widget.grid.events.ColumnReorderHandler;
import com.vaadin.client.widget.grid.events.ColumnVisibilityChangeEvent;
import com.vaadin.client.widget.grid.events.ColumnVisibilityChangeHandler;
+import com.vaadin.client.widget.grid.events.EditorCloseEvent;
+import com.vaadin.client.widget.grid.events.EditorEvent;
+import com.vaadin.client.widget.grid.events.EditorEventHandler;
+import com.vaadin.client.widget.grid.events.EditorMoveEvent;
+import com.vaadin.client.widget.grid.events.EditorOpenEvent;
import com.vaadin.client.widget.grid.events.FooterClickHandler;
import com.vaadin.client.widget.grid.events.FooterDoubleClickHandler;
import com.vaadin.client.widget.grid.events.FooterKeyDownHandler;
@@ -206,8 +213,8 @@ import com.vaadin.shared.util.SharedUtil;
* @author Vaadin Ltd
*/
public class Grid<T> extends ResizeComposite implements
- HasSelectionHandlers<T>, SubPartAware, DeferredWorker, HasWidgets,
- HasEnabled {
+ HasSelectionHandlers<T>, SubPartAware, DeferredWorker, Focusable,
+ com.google.gwt.user.client.ui.Focusable, HasWidgets, HasEnabled {
/**
* Enum describing different sections of Grid.
@@ -1155,8 +1162,17 @@ public class Grid<T> extends ResizeComposite implements
private int columnIndex = -1;
private String styleName = null;
+ /*
+ * Used to track Grid horizontal scrolling
+ */
private HandlerRegistration scrollHandler;
+ /*
+ * Used to open editor once Grid has vertically scrolled to the proper
+ * position and data is available
+ */
+ private HandlerRegistration dataAvailableHandler;
+
private final Button saveButton;
private final Button cancelButton;
@@ -1211,6 +1227,7 @@ public class Grid<T> extends ResizeComposite implements
+ " remember to call success() or fail()?");
}
};
+
private final EditorRequestImpl.RequestCallback<T> bindRequestCallback = new EditorRequestImpl.RequestCallback<T>() {
@Override
public void onSuccess(EditorRequest<T> request) {
@@ -1218,10 +1235,7 @@ public class Grid<T> extends ResizeComposite implements
state = State.ACTIVE;
bindTimeout.cancel();
- assert rowIndex == request.getRowIndex() : "Request row index "
- + request.getRowIndex()
- + " did not match the saved row index " + rowIndex;
-
+ rowIndex = request.getRowIndex();
showOverlay();
}
}
@@ -1229,22 +1243,30 @@ public class Grid<T> extends ResizeComposite implements
@Override
public void onError(EditorRequest<T> request) {
if (state == State.BINDING) {
- state = State.INACTIVE;
+ if (rowIndex == -1) {
+ doCancel();
+ } else {
+ state = State.ACTIVE;
+ }
bindTimeout.cancel();
// TODO show something in the DOM as well?
getLogger().warning(
"An error occurred while trying to show the "
+ "Grid editor");
- grid.getEscalator().setScrollLocked(Direction.VERTICAL,
- false);
- updateSelectionCheckboxesAsNeeded(true);
}
}
};
/** A set of all the columns that display an error flag. */
private final Set<Column<?, T>> columnErrors = new HashSet<Grid.Column<?, T>>();
+ private boolean buffered = true;
+
+ /** Original position of editor */
+ private double originalTop;
+ /** Original scroll position of grid when editor was opened */
+ private double originalScrollTop;
+ private RowHandle<T> pinnedRowHandle;
public Editor() {
saveButton = new Button();
@@ -1275,6 +1297,10 @@ public class Grid<T> extends ResizeComposite implements
messageWrapper.appendChild(message);
}
}
+ // In unbuffered mode only show message wrapper if there is an error
+ if (!isBuffered()) {
+ setMessageAndButtonsWrapperVisible(errorMessage != null);
+ }
}
public int getRow() {
@@ -1282,12 +1308,26 @@ public class Grid<T> extends ResizeComposite implements
}
/**
- * Equivalent to {@code editRow(rowIndex, -1)}.
+ * If a cell of this Grid had focus once this editRow call was
+ * triggered, the editor component at the previously focused column
+ * index will be focused.
+ *
+ * If a Grid cell was not focused prior to calling this method, it will
+ * be equivalent to {@code editRow(rowIndex, -1)}.
*
* @see #editRow(int, int)
*/
public void editRow(int rowIndex) {
- editRow(rowIndex, -1);
+ // Focus the last focused column in the editor iff grid or its child
+ // was focused before the edit request
+ Cell focusedCell = grid.cellFocusHandler.getFocusedCell();
+ Element focusedElement = WidgetUtil.getFocusedElement();
+ if (focusedCell != null && focusedElement != null
+ && grid.getElement().isOrHasChild(focusedElement)) {
+ editRow(rowIndex, focusedCell.getColumn());
+ } else {
+ editRow(rowIndex, -1);
+ }
}
/**
@@ -1304,28 +1344,40 @@ public class Grid<T> extends ResizeComposite implements
* @throws IllegalStateException
* if this editor is not enabled
* @throws IllegalStateException
- * if this editor is already in edit mode
+ * if this editor is already in edit mode and in buffered
+ * mode
*
* @since 7.5
*/
- public void editRow(int rowIndex, int columnIndex) {
+ public void editRow(final int rowIndex, int columnIndex) {
if (!enabled) {
throw new IllegalStateException(
"Cannot edit row: editor is not enabled");
}
if (state != State.INACTIVE) {
- throw new IllegalStateException(
- "Cannot edit row: editor already in edit mode");
+ if (isBuffered()) {
+ throw new IllegalStateException(
+ "Cannot edit row: editor already in edit mode");
+ }
}
- this.rowIndex = rowIndex;
this.columnIndex = columnIndex;
-
state = State.ACTIVATING;
if (grid.getEscalator().getVisibleRowRange().contains(rowIndex)) {
- show();
+ show(rowIndex);
} else {
+ hideOverlay();
+ dataAvailableHandler = grid
+ .addDataAvailableHandler(new DataAvailableHandler() {
+ @Override
+ public void onDataAvailable(DataAvailableEvent event) {
+ if (event.getAvailableRows().contains(rowIndex)) {
+ show(rowIndex);
+ dataAvailableHandler.removeHandler();
+ }
+ }
+ });
grid.scrollToRow(rowIndex, ScrollDestination.MIDDLE);
}
}
@@ -1348,14 +1400,18 @@ public class Grid<T> extends ResizeComposite implements
throw new IllegalStateException(
"Cannot cancel edit: editor is not in edit mode");
}
- hideOverlay();
- grid.getEscalator().setScrollLocked(Direction.VERTICAL, false);
+ handler.cancel(new EditorRequestImpl<T>(grid, rowIndex, null));
+ doCancel();
+ }
- EditorRequest<T> request = new EditorRequestImpl<T>(grid, rowIndex,
- null);
- handler.cancel(request);
+ private void doCancel() {
+ hideOverlay();
state = State.INACTIVE;
+ rowIndex = -1;
+ columnIndex = -1;
+ grid.getEscalator().setScrollLocked(Direction.VERTICAL, false);
updateSelectionCheckboxesAsNeeded(true);
+ grid.fireEvent(new EditorCloseEvent(grid.eventCell));
}
private void updateSelectionCheckboxesAsNeeded(boolean isEnabled) {
@@ -1448,14 +1504,15 @@ public class Grid<T> extends ResizeComposite implements
this.enabled = enabled;
}
- protected void show() {
+ protected void show(int rowIndex) {
if (state == State.ACTIVATING) {
state = State.BINDING;
bindTimeout.schedule(BIND_TIMEOUT_MS);
EditorRequest<T> request = new EditorRequestImpl<T>(grid,
rowIndex, bindRequestCallback);
handler.bind(request);
- grid.getEscalator().setScrollLocked(Direction.VERTICAL, true);
+ grid.getEscalator().setScrollLocked(Direction.VERTICAL,
+ isBuffered());
updateSelectionCheckboxesAsNeeded(false);
}
}
@@ -1465,15 +1522,6 @@ public class Grid<T> extends ResizeComposite implements
assert this.grid == null : "Can only attach editor to Grid once";
this.grid = grid;
-
- grid.addDataAvailableHandler(new DataAvailableHandler() {
- @Override
- public void onDataAvailable(DataAvailableEvent event) {
- if (event.getAvailableRows().contains(rowIndex)) {
- show();
- }
- }
- });
}
protected State getState() {
@@ -1518,6 +1566,8 @@ public class Grid<T> extends ResizeComposite implements
* @since 7.5
*/
protected void showOverlay() {
+ // Ensure overlay is hidden initially
+ hideOverlay();
DivElement gridElement = DivElement.as(grid.getElement());
@@ -1528,6 +1578,9 @@ public class Grid<T> extends ResizeComposite implements
@Override
public void onScroll(ScrollEvent event) {
updateHorizontalScrollPosition();
+ if (!isBuffered()) {
+ updateVerticalScrollPosition();
+ }
}
});
@@ -1575,6 +1628,50 @@ public class Grid<T> extends ResizeComposite implements
}
} else {
cell.addClassName(NOT_EDITABLE_CLASS_NAME);
+ cell.addClassName(tr.getCells().getItem(i).getClassName());
+ // If the focused stylename is present it should not be
+ // inherited by the editor cell as it is not useful in the
+ // editor and would look broken without additional style
+ // rules. This is a bit of a hack.
+ cell.removeClassName(grid.cellFocusStyleName);
+
+ if (column == grid.selectionColumn) {
+ // Duplicate selection column CheckBox
+
+ pinnedRowHandle = grid.getDataSource().getHandle(
+ grid.getDataSource().getRow(rowIndex));
+ pinnedRowHandle.pin();
+
+ // We need to duplicate the selection CheckBox for the
+ // editor overlay since the original one is hidden by
+ // the overlay
+ final CheckBox checkBox = GWT.create(CheckBox.class);
+ checkBox.setValue(grid.isSelected(pinnedRowHandle
+ .getRow()));
+ checkBox.sinkEvents(Event.ONCLICK);
+
+ checkBox.addClickHandler(new ClickHandler() {
+ @Override
+ public void onClick(ClickEvent event) {
+ T row = pinnedRowHandle.getRow();
+ if (grid.isSelected(row)) {
+ grid.deselect(row);
+ } else {
+ grid.select(row);
+ }
+ }
+ });
+ attachWidget(checkBox, cell);
+ columnToWidget.put(column, checkBox);
+
+ // Only enable CheckBox in non-buffered mode
+ checkBox.setEnabled(!isBuffered());
+
+ } else if (!(column.getRenderer() instanceof WidgetRenderer)) {
+ // Copy non-widget content directly
+ cell.setInnerHTML(tr.getCells().getItem(i)
+ .getInnerHTML());
+ }
}
}
@@ -1588,8 +1685,12 @@ public class Grid<T> extends ResizeComposite implements
messageAndButtonsWrapper.appendChild(buttonsWrapper);
}
- attachWidget(saveButton, buttonsWrapper);
- attachWidget(cancelButton, buttonsWrapper);
+ if (isBuffered()) {
+ attachWidget(saveButton, buttonsWrapper);
+ attachWidget(cancelButton, buttonsWrapper);
+ }
+
+ setMessageAndButtonsWrapperVisible(isBuffered());
updateHorizontalScrollPosition();
@@ -1601,9 +1702,11 @@ public class Grid<T> extends ResizeComposite implements
int gridTop = gridElement.getAbsoluteTop();
double overlayTop = rowTop + bodyTop - gridTop;
- if (buttonsShouldBeRenderedBelow(tr)) {
+ originalScrollTop = grid.getScrollTop();
+ if (!isBuffered() || buttonsShouldBeRenderedBelow(tr)) {
// Default case, editor buttons are below the edited row
editorOverlay.getStyle().setTop(overlayTop, Unit.PX);
+ originalTop = overlayTop;
editorOverlay.getStyle().clearBottom();
} else {
// Move message and buttons wrapper on top of cell wrapper if
@@ -1636,6 +1739,15 @@ public class Grid<T> extends ResizeComposite implements
}
protected void hideOverlay() {
+ if (editorOverlay.getParentElement() == null) {
+ return;
+ }
+
+ if (pinnedRowHandle != null) {
+ pinnedRowHandle.unpin();
+ pinnedRowHandle = null;
+ }
+
for (Widget w : columnToWidget.values()) {
setParent(w, null);
}
@@ -1727,6 +1839,35 @@ public class Grid<T> extends ResizeComposite implements
frozenCellWrapper.getOffsetWidth() - scrollLeft, Unit.PX);
}
+ /**
+ * Moves the editor overlay on scroll so that it stays on top of the
+ * edited row. This will also snap the editor to top or bottom of the
+ * row container if the edited row is scrolled out of the visible area.
+ */
+ private void updateVerticalScrollPosition() {
+ double newScrollTop = grid.getScrollTop();
+
+ int gridTop = grid.getElement().getAbsoluteTop();
+ int editorHeight = editorOverlay.getOffsetHeight();
+
+ Escalator escalator = grid.getEscalator();
+ TableSectionElement header = escalator.getHeader().getElement();
+ int footerTop = escalator.getFooter().getElement().getAbsoluteTop();
+ int headerBottom = header.getAbsoluteBottom();
+
+ double newTop = originalTop - (newScrollTop - originalScrollTop);
+
+ if (newTop + gridTop < headerBottom) {
+ // Snap editor to top of the row container
+ newTop = header.getOffsetHeight();
+ } else if (newTop + gridTop > footerTop - editorHeight) {
+ // Snap editor to the bottom of the row container
+ newTop = footerTop - editorHeight - gridTop;
+ }
+
+ editorOverlay.getStyle().setTop(newTop, Unit.PX);
+ }
+
protected void setGridEnabled(boolean enabled) {
// TODO: This should be informed to handler as well so possible
// fields can be disabled.
@@ -1803,6 +1944,23 @@ public class Grid<T> extends ResizeComposite implements
public boolean isEditorColumnError(Column<?, T> column) {
return columnErrors.contains(column);
}
+
+ public void setBuffered(boolean buffered) {
+ this.buffered = buffered;
+ setMessageAndButtonsWrapperVisible(buffered);
+ }
+
+ public boolean isBuffered() {
+ return buffered;
+ }
+
+ private void setMessageAndButtonsWrapperVisible(boolean visible) {
+ if (visible) {
+ messageAndButtonsWrapper.getStyle().clearDisplay();
+ } else {
+ messageAndButtonsWrapper.getStyle().setDisplay(Display.NONE);
+ }
+ }
}
public static abstract class AbstractGridKeyEvent<HANDLER extends AbstractGridKeyEventHandler>
@@ -5236,7 +5394,7 @@ public class Grid<T> extends ResizeComposite implements
sinkEvents(getHeader().getConsumedEvents());
sinkEvents(Arrays.asList(BrowserEvents.KEYDOWN, BrowserEvents.KEYUP,
BrowserEvents.KEYPRESS, BrowserEvents.DBLCLICK,
- BrowserEvents.MOUSEDOWN));
+ BrowserEvents.MOUSEDOWN, BrowserEvents.CLICK));
// Make ENTER and SHIFT+ENTER in the header perform sorting
addHeaderKeyUpHandler(new HeaderKeyUpHandler() {
@@ -5912,6 +6070,19 @@ public class Grid<T> extends ResizeComposite implements
return editor;
}
+ /**
+ * Add handler for editor open/move/close events
+ *
+ * @param handler
+ * editor handler object
+ * @return a {@link HandlerRegistration} object that can be used to remove
+ * the event handler
+ */
+ public HandlerRegistration addEditorEventHandler(EditorEventHandler handler) {
+ return addHandler(handler, EditorEvent.TYPE);
+
+ }
+
protected Escalator getEscalator() {
return escalator;
}
@@ -6375,6 +6546,14 @@ public class Grid<T> extends ResizeComposite implements
return;
}
+ String eventType = event.getType();
+
+ if (eventType.equals(BrowserEvents.FOCUS)
+ || eventType.equals(BrowserEvents.BLUR)) {
+ super.onBrowserEvent(event);
+ return;
+ }
+
EventTarget target = event.getEventTarget();
if (!Element.is(target) || isOrContainsInSpacer(Element.as(target))) {
@@ -6385,7 +6564,6 @@ public class Grid<T> extends ResizeComposite implements
RowContainer container = escalator.findRowContainer(e);
Cell cell;
- String eventType = event.getType();
if (container == null) {
if (eventType.equals(BrowserEvents.KEYDOWN)
|| eventType.equals(BrowserEvents.KEYUP)
@@ -6493,50 +6671,68 @@ public class Grid<T> extends ResizeComposite implements
}
private boolean handleEditorEvent(Event event, RowContainer container) {
-
- final boolean closeEvent = event.getTypeInt() == Event.ONKEYDOWN
- && event.getKeyCode() == Editor.KEYCODE_HIDE;
+ final int type = event.getTypeInt();
+ final int key = event.getKeyCode();
+ final boolean editorIsActive = editor.getState() != Editor.State.INACTIVE;
double now = Duration.currentTimeMillis();
int currentX = WidgetUtil.getTouchOrMouseClientX(event);
int currentY = WidgetUtil.getTouchOrMouseClientY(event);
- final boolean validTouchOpenEvent = event.getTypeInt() == Event.ONTOUCHEND
+ final boolean validTouchOpenEvent = type == Event.ONTOUCHEND
&& now - lastTouchEventTime < 500
&& lastTouchEventRow == eventCell.getRowIndex()
&& Math.abs(lastTouchEventX - currentX) < 20
&& Math.abs(lastTouchEventY - currentY) < 20;
- final boolean openEvent = event.getTypeInt() == Event.ONDBLCLICK
- || (event.getTypeInt() == Event.ONKEYDOWN && event.getKeyCode() == Editor.KEYCODE_SHOW)
- || validTouchOpenEvent;
+ final boolean openEvent = eventCell.isBody()
+ && (type == Event.ONDBLCLICK
+ || (type == Event.ONKEYDOWN && key == Editor.KEYCODE_SHOW) || validTouchOpenEvent);
- if (event.getTypeInt() == Event.ONTOUCHSTART) {
+ if (type == Event.ONTOUCHSTART) {
lastTouchEventX = currentX;
lastTouchEventY = currentY;
}
- if (event.getTypeInt() == Event.ONTOUCHEND) {
+ if (type == Event.ONTOUCHEND) {
lastTouchEventTime = now;
lastTouchEventRow = eventCell.getRowIndex();
}
- if (editor.getState() != Editor.State.INACTIVE) {
- if (closeEvent) {
- editor.cancel();
- FocusUtil.setFocus(this, true);
- }
- return true;
- }
+ // TODO: Move on touch events
+ final boolean moveEvent = eventCell.isBody() && type == Event.ONCLICK;
+
+ final boolean closeEvent = type == Event.ONKEYDOWN
+ && key == Editor.KEYCODE_HIDE;
+
+ if (!editorIsActive && editor.isEnabled() && openEvent) {
- if (container == escalator.getBody() && editor.isEnabled() && openEvent) {
editor.editRow(eventCell.getRowIndex(),
eventCell.getColumnIndexDOM());
+ fireEvent(new EditorOpenEvent(eventCell));
event.preventDefault();
+
+ return true;
+
+ } else if (editorIsActive && !editor.isBuffered() && moveEvent) {
+
+ cellFocusHandler.setCellFocus(eventCell);
+ editor.editRow(eventCell.getRowIndex(),
+ eventCell.getColumnIndexDOM());
+ fireEvent(new EditorMoveEvent(eventCell));
+
+ return true;
+
+ } else if (editorIsActive && closeEvent) {
+
+ editor.cancel();
+ FocusUtil.setFocus(this, true);
+
return true;
}
- return false;
+ // Swallow events if editor is open and buffered (modal)
+ return editor.isBuffered() && editorIsActive;
}
private boolean handleRendererEvent(Event event, RowContainer container) {
@@ -7698,6 +7894,12 @@ public class Grid<T> extends ResizeComposite implements
if (escalator.getInnerWidth() != autoColumnWidthsRecalculator.lastCalculatedInnerWidth) {
recalculateColumnWidths();
}
+
+ // Vertical resizing could make editor positioning invalid so it
+ // needs to be recalculated on resize
+ if (isEditorActive()) {
+ editor.updateVerticalScrollPosition();
+ }
}
});
}
@@ -7990,6 +8192,54 @@ public class Grid<T> extends ResizeComposite implements
}
}
+ @Override
+ public int getTabIndex() {
+ return FocusUtil.getTabIndex(this);
+ }
+
+ @Override
+ public void setAccessKey(char key) {
+ FocusUtil.setAccessKey(this, key);
+ }
+
+ @Override
+ public void setFocus(boolean focused) {
+ FocusUtil.setFocus(this, focused);
+ }
+
+ @Override
+ public void setTabIndex(int index) {
+ FocusUtil.setTabIndex(this, index);
+ }
+
+ @Override
+ public void focus() {
+ setFocus(true);
+ }
+
+ /**
+ * Sets the buffered editor mode.
+ *
+ * @since 7.6
+ * @param editorUnbuffered
+ * <code>true</code> to enable buffered editor,
+ * <code>false</code> to disable it
+ */
+ public void setEditorBuffered(boolean editorBuffered) {
+ editor.setBuffered(editorBuffered);
+ }
+
+ /**
+ * Gets the buffered editor mode.
+ *
+ * @since 7.6
+ * @return <code>true</code> if buffered editor is enabled,
+ * <code>false</code> otherwise
+ */
+ public boolean isEditorBuffered() {
+ return editor.isBuffered();
+ }
+
/**
* Returns the {@link EventCellReference} for the latest event fired from
* this Grid.
@@ -8002,4 +8252,26 @@ public class Grid<T> extends ResizeComposite implements
public EventCellReference<T> getEventCell() {
return eventCell;
}
+
+ /**
+ * Returns a CellReference for the cell to which the given element belongs
+ * to.
+ *
+ * @since
+ * @param element
+ * Element to find from the cell's content.
+ * @return CellReference or <code>null</code> if cell was not found.
+ */
+ public CellReference<T> getCellReference(Element element) {
+ RowContainer container = getEscalator().findRowContainer(element);
+ if (container != null) {
+ Cell cell = container.getCell(element);
+ if (cell != null) {
+ EventCellReference<T> cellRef = new EventCellReference<T>(this);
+ cellRef.set(cell, getSectionFromContainer(container));
+ return cellRef;
+ }
+ }
+ return null;
+ }
}