diff options
author | Teemu Suo-Anttila <teemusa@vaadin.com> | 2015-04-15 10:24:44 +0300 |
---|---|---|
committer | Teemu Suo-Anttila <teemusa@vaadin.com> | 2015-04-15 10:24:44 +0300 |
commit | 2c4e533c9f2aa68211329ea6ce4de0b577407863 (patch) | |
tree | 1d9c1cc8bb72678b0edb991947c6fc94112baf0f /client/src | |
parent | 93235f05c9dd4739cdccf87a4858a61904dbf4b5 (diff) | |
parent | 7cb23bc63f794a7549dd79c37da2f8bb8e88e20d (diff) | |
download | vaadin-framework-2c4e533c9f2aa68211329ea6ce4de0b577407863.tar.gz vaadin-framework-2c4e533c9f2aa68211329ea6ce4de0b577407863.zip |
Merge remote-tracking branch 'origin/master' into grid-7.5
Change-Id: I03fdd2014fd0393341db0f650c065f6d27905b73
Diffstat (limited to 'client/src')
28 files changed, 1109 insertions, 467 deletions
diff --git a/client/src/com/vaadin/client/ApplicationConfiguration.java b/client/src/com/vaadin/client/ApplicationConfiguration.java index 37d689c6d3..f4b2c93111 100644 --- a/client/src/com/vaadin/client/ApplicationConfiguration.java +++ b/client/src/com/vaadin/client/ApplicationConfiguration.java @@ -638,7 +638,8 @@ public class ApplicationConfiguration implements EntryPoint { @Override public void failed(Throwable reason) { - VConsole.error(reason); + getLogger().log(Level.SEVERE, + "Error loading deferred bundle", reason); } }); } diff --git a/client/src/com/vaadin/client/ApplicationConnection.java b/client/src/com/vaadin/client/ApplicationConnection.java index 1b3196e1c2..af86818fb3 100644 --- a/client/src/com/vaadin/client/ApplicationConnection.java +++ b/client/src/com/vaadin/client/ApplicationConnection.java @@ -26,6 +26,7 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.logging.Level; import java.util.logging.Logger; import com.google.gwt.aria.client.LiveValue; @@ -93,6 +94,7 @@ 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; @@ -518,7 +520,7 @@ public class ApplicationConnection implements HasHandlers { int currentTime = elapsedMillis(); int stepDuration = currentTime - previousStep; if (stepDuration >= minDuration) { - VConsole.log(message + ": " + stepDuration + " ms"); + getLogger().info(message + ": " + stepDuration + " ms"); } previousStep = currentTime; } @@ -540,16 +542,18 @@ public class ApplicationConnection implements HasHandlers { } public void init(WidgetSet widgetSet, ApplicationConfiguration cnf) { - VConsole.log("Starting application " + cnf.getRootPanelId()); - VConsole.log("Using theme: " + cnf.getThemeName()); + getLogger().info("Starting application " + cnf.getRootPanelId()); + getLogger().info("Using theme: " + cnf.getThemeName()); - VConsole.log("Vaadin application servlet version: " - + cnf.getServletVersion()); + getLogger().info( + "Vaadin application servlet version: " + + cnf.getServletVersion()); if (!cnf.getServletVersion().equals(Version.getFullVersion())) { - VConsole.error("Warning: your widget set seems to be built with a different " - + "version than the one used on server. Unexpected " - + "behavior may occur."); + getLogger() + .severe("Warning: your widget set seems to be built with a different " + + "version than the one used on server. Unexpected " + + "behavior may occur."); } this.widgetSet = widgetSet; @@ -853,7 +857,8 @@ public class ApplicationConnection implements HasHandlers { payload.put(ApplicationConstants.RPC_INVOCATIONS, reqInvocations); payload.put(ApplicationConstants.SERVER_SYNC_ID, lastSeenServerSyncId); - VConsole.log("Making UIDL Request with params: " + payload.toJson()); + getLogger() + .info("Making UIDL Request with params: " + payload.toJson()); String uri = translateVaadinUri(ApplicationConstants.APP_PROTOCOL_PREFIX + ApplicationConstants.UIDL_PATH + '/'); @@ -911,9 +916,10 @@ public class ApplicationConnection implements HasHandlers { @Override public void onResponseReceived(Request request, Response response) { - VConsole.log("Server visit took " - + String.valueOf((new Date()).getTime() - - requestStartTime.getTime()) + "ms"); + getLogger().info( + "Server visit took " + + String.valueOf((new Date()).getTime() + - requestStartTime.getTime()) + "ms"); int statusCode = response.getStatusCode(); // Notify network observers about response status @@ -937,7 +943,7 @@ public class ApplicationConnection implements HasHandlers { * Status code 0 does indicate that there was no server * side processing, so we can retry the request. */ - VConsole.log("Status code 0, retrying"); + getLogger().warning("Status code 0, retrying"); (new Timer() { @Override public void run() { @@ -968,7 +974,8 @@ public class ApplicationConnection implements HasHandlers { */ String delay = response.getHeader("Retry-After"); if (delay != null) { - VConsole.log("503, retrying in " + delay + "msec"); + getLogger().warning( + "503, retrying in " + delay + "msec"); (new Timer() { @Override public void run() { @@ -1026,7 +1033,7 @@ public class ApplicationConnection implements HasHandlers { try { doAjaxRequest(uri, payload, requestCallback); } catch (RequestException e) { - VConsole.error(e); + getLogger().log(Level.SEVERE, "Error in server request", e); endRequest(); fireEvent(new ConnectionStatusEvent(0)); } @@ -1052,8 +1059,9 @@ public class ApplicationConnection implements HasHandlers { return; } - VConsole.log("JSON parsing took " - + (new Date().getTime() - start.getTime()) + "ms"); + getLogger().info( + "JSON parsing took " + (new Date().getTime() - start.getTime()) + + "ms"); if (isApplicationRunning()) { handleReceivedJSONMessage(start, jsonText, json); } else { @@ -1192,9 +1200,10 @@ public class ApplicationConnection implements HasHandlers { // Show this message just once if (cssWaits++ == 0) { - VConsole.log("Assuming CSS loading is not complete, " - + "postponing render phase. " - + "(.v-loading-indicator height == 0)"); + getLogger().warning( + "Assuming CSS loading is not complete, " + + "postponing render phase. " + + "(.v-loading-indicator height == 0)"); } } else { cssLoaded = true; @@ -1226,7 +1235,7 @@ public class ApplicationConnection implements HasHandlers { * */ protected void showCommunicationError(String details, int statusCode) { - VConsole.error("Communication error: " + details); + getLogger().severe("Communication error: " + details); showError(details, configuration.getCommunicationError()); } @@ -1237,7 +1246,7 @@ public class ApplicationConnection implements HasHandlers { * Optional details for debugging. */ protected void showAuthenticationError(String details) { - VConsole.error("Authentication error: " + details); + getLogger().severe("Authentication error: " + details); showError(details, configuration.getAuthorizationError()); } @@ -1248,7 +1257,7 @@ public class ApplicationConnection implements HasHandlers { * Optional details for debugging. */ public void showSessionExpiredError(String details) { - VConsole.error("Session expired: " + details); + getLogger().severe("Session expired: " + details); showError(details, configuration.getSessionExpiredError()); } @@ -1307,7 +1316,8 @@ public class ApplicationConnection implements HasHandlers { protected void startRequest() { if (hasActiveRequest) { - VConsole.error("Trying to start a new request while another is active"); + getLogger().severe( + "Trying to start a new request while another is active"); } hasActiveRequest = true; requestStartTime = new Date(); @@ -1316,7 +1326,7 @@ public class ApplicationConnection implements HasHandlers { protected void endRequest() { if (!hasActiveRequest) { - VConsole.error("No active request"); + getLogger().severe("No active request"); } // After checkForPendingVariableBursts() there may be a new active // request, so we must set hasActiveRequest to false before, not after, @@ -1385,7 +1395,8 @@ public class ApplicationConnection implements HasHandlers { && !getConnectorMap().isDragAndDropPaintable(id)) { // variable owner does not exist anymore iterator.remove(); - VConsole.log("Removed variable from removed component: " + id); + getLogger().info( + "Removed variable from removed component: " + id); } } } @@ -1504,7 +1515,7 @@ public class ApplicationConnection implements HasHandlers { // Some component is doing something that can't be interrupted // (e.g. animation that should be smooth). Enqueue the UIDL // message for later processing. - VConsole.log("Postponing UIDL handling due to lock..."); + getLogger().info("Postponing UIDL handling due to lock..."); pendingUIDLMessages.add(new PendingUIDLMessage(start, jsonText, json)); if (!forceHandleMessage.isRunning()) { @@ -1521,7 +1532,7 @@ public class ApplicationConnection implements HasHandlers { final Object lock = new Object(); suspendReponseHandling(lock); - VConsole.log("Handling message from server"); + getLogger().info("Handling message from server"); eventBus.fireEvent(new ResponseHandlingStartedEvent(this)); final int syncId; @@ -1540,14 +1551,15 @@ public class ApplicationConnection implements HasHandlers { } } else { syncId = -1; - VConsole.error("Server response didn't contain a sync id. " - + "Please verify that the server is up-to-date and that the response data has not been modified in transmission."); + getLogger() + .severe("Server response didn't contain a sync id. " + + "Please verify that the server is up-to-date and that the response data has not been modified in transmission."); } // Handle redirect if (json.containsKey("redirect")) { String url = json.getValueMap("redirect").getString("url"); - VConsole.log("redirecting to " + url); + getLogger().info("redirecting to " + url); redirect(url); return; } @@ -1559,7 +1571,7 @@ public class ApplicationConnection implements HasHandlers { csrfToken = json .getString(ApplicationConstants.UIDL_SECURITY_TOKEN_ID); } - VConsole.log(" * Handling resources from server"); + getLogger().info(" * Handling resources from server"); if (json.containsKey("resources")) { ValueMap resources = json.getValueMap("resources"); @@ -1573,7 +1585,7 @@ public class ApplicationConnection implements HasHandlers { handleUIDLDuration.logDuration( " * Handling resources from server completed", 10); - VConsole.log(" * Handling type inheritance map from server"); + getLogger().info(" * Handling type inheritance map from server"); if (json.containsKey("typeInheritanceMap")) { configuration.addComponentInheritanceInfo(json @@ -1582,7 +1594,7 @@ public class ApplicationConnection implements HasHandlers { handleUIDLDuration.logDuration( " * Handling type inheritance map from server completed", 10); - VConsole.log("Handling type mappings from server"); + getLogger().info("Handling type mappings from server"); if (json.containsKey("typeMappings")) { configuration.addComponentMappings( @@ -1590,7 +1602,7 @@ public class ApplicationConnection implements HasHandlers { } - VConsole.log("Handling resource dependencies"); + getLogger().info("Handling resource dependencies"); if (json.containsKey("scriptDependencies")) { loadScriptDependencies(json.getJSStringArray("scriptDependencies")); } @@ -1620,7 +1632,7 @@ public class ApplicationConnection implements HasHandlers { Profiler.enter("Handling meta information"); ValueMap meta = null; if (json.containsKey("meta")) { - VConsole.log(" * Handling meta information"); + getLogger().info(" * Handling meta information"); meta = json.getValueMap("meta"); if (meta.containsKey("repaintAll")) { prepareRepaintAll(); @@ -1663,7 +1675,7 @@ public class ApplicationConnection implements HasHandlers { * connectors which get a state change event before the UI. */ Profiler.enter("Handling locales"); - VConsole.log(" * Handling locales"); + getLogger().info(" * Handling locales"); // Store locale data LocaleService .addLocales(getUIConnector().getState().localeServiceState.localeData); @@ -1697,9 +1709,10 @@ public class ApplicationConnection implements HasHandlers { unregisterRemovedConnectors(connectorHierarchyUpdateResult.detachedConnectorIds); - VConsole.log("handleUIDLMessage: " - + (Duration.currentTimeMillis() - processUidlStart) - + " ms"); + getLogger() + .info("handleUIDLMessage: " + + (Duration.currentTimeMillis() - processUidlStart) + + " ms"); updatingState = false; @@ -1710,14 +1723,15 @@ public class ApplicationConnection implements HasHandlers { layoutManager.setEverythingNeedsMeasure(); layoutManager.layoutNow(); } catch (final Throwable e) { - VConsole.error(e); + getLogger().log(Level.SEVERE, + "Error processing layouts", e); } Profiler.leave("Layout processing"); } if (ApplicationConfiguration.isDebugMode()) { Profiler.enter("Dumping state changes to the console"); - VConsole.log(" * Dumping state changes to the console"); + getLogger().info(" * Dumping state changes to the console"); VConsole.dirUIDL(json, ApplicationConnection.this); Profiler.leave("Dumping state changes to the console"); } @@ -1748,10 +1762,13 @@ public class ApplicationConnection implements HasHandlers { } } - VConsole.log(" Processing time was " - + String.valueOf(lastProcessingTime) + "ms for " - + jsonText.length() + " characters of JSON"); - VConsole.log("Referenced paintables: " + connectorMap.size()); + getLogger().info( + " Processing time was " + + String.valueOf(lastProcessingTime) + + "ms for " + jsonText.length() + + " characters of JSON"); + getLogger().info( + "Referenced paintables: " + connectorMap.size()); if (meta == null || !meta.containsKey("async")) { // End the request if the received message was a response, @@ -1854,7 +1871,7 @@ public class ApplicationConnection implements HasHandlers { JsArrayObject<StateChangeEvent> pendingStateChangeEvents) { Profiler.enter("@DelegateToWidget"); - VConsole.log(" * Running @DelegateToWidget"); + getLogger().info(" * Running @DelegateToWidget"); // Keep track of types that have no @DelegateToWidget in their // state to optimize performance @@ -1938,7 +1955,7 @@ public class ApplicationConnection implements HasHandlers { private void sendStateChangeEvents( JsArrayObject<StateChangeEvent> pendingStateChangeEvents) { Profiler.enter("sendStateChangeEvents"); - VConsole.log(" * Sending state change events"); + getLogger().info(" * Sending state change events"); int size = pendingStateChangeEvents.size(); for (int i = 0; i < size; i++) { @@ -1946,7 +1963,8 @@ public class ApplicationConnection implements HasHandlers { try { sce.getConnector().fireEvent(sce); } catch (final Throwable e) { - VConsole.error(e); + getLogger().log(Level.SEVERE, + "Error sending state change events", e); } } @@ -1963,11 +1981,12 @@ public class ApplicationConnection implements HasHandlers { ServerConnector c = currentConnectors.get(i); if (c.getParent() != null) { if (!c.getParent().getChildren().contains(c)) { - VConsole.error("ERROR: Connector " - + c.getConnectorId() - + " is connected to a parent but the parent (" - + c.getParent().getConnectorId() - + ") does not contain the connector"); + getLogger() + .severe("ERROR: Connector " + + c.getConnectorId() + + " is connected to a parent but the parent (" + + c.getParent().getConnectorId() + + ") does not contain the connector"); } } else if (c == getUIConnector()) { // UIConnector for this connection, ignore @@ -1978,9 +1997,10 @@ public class ApplicationConnection implements HasHandlers { } else { // The connector has been detached from the // hierarchy but was not unregistered. - VConsole.error("ERROR: Connector " - + c.getConnectorId() - + " is not attached to a parent but has not been unregistered"); + getLogger() + .severe("ERROR: Connector " + + c.getConnectorId() + + " is not attached to a parent but has not been unregistered"); } } @@ -2008,13 +2028,14 @@ public class ApplicationConnection implements HasHandlers { verifyConnectorHierarchy(); } - VConsole.log("* Unregistered " + detachedArray.length() - + " connectors"); + getLogger().info( + "* Unregistered " + detachedArray.length() + + " connectors"); Profiler.leave("unregisterRemovedConnectors"); } private JsArrayString createConnectorsIfNeeded(ValueMap json) { - VConsole.log(" * Creating connectors (if needed)"); + getLogger().info(" * Creating connectors (if needed)"); JsArrayString createdConnectors = JavaScriptObject .createArray().cast(); @@ -2065,7 +2086,8 @@ public class ApplicationConnection implements HasHandlers { createdConnectors.push(connectorId); } } catch (final Throwable e) { - VConsole.error(e); + getLogger().log(Level.SEVERE, + "Error handling type data", e); } } @@ -2085,7 +2107,8 @@ public class ApplicationConnection implements HasHandlers { onlyNoLayoutUpdates = false; } - VConsole.log(" * Passing UIDL to Vaadin 6 style connectors"); + getLogger() + .info(" * Passing UIDL to Vaadin 6 style connectors"); // update paintables for (int i = 0; i < length; i++) { try { @@ -2111,18 +2134,20 @@ public class ApplicationConnection implements HasHandlers { Profiler.leave(key); } } else if (legacyConnector == null) { - VConsole.error("Received update for " - + uidl.getTag() - + ", but there is no such paintable (" - + connectorId + ") rendered."); + getLogger() + .severe("Received update for " + + uidl.getTag() + + ", but there is no such paintable (" + + connectorId + ") rendered."); } else { - VConsole.error("Server sent Vaadin 6 style updates for " - + Util.getConnectorString(legacyConnector) - + " but this is not a Vaadin 6 Paintable"); + getLogger() + .severe("Server sent Vaadin 6 style updates for " + + Util.getConnectorString(legacyConnector) + + " but this is not a Vaadin 6 Paintable"); } } catch (final Throwable e) { - VConsole.error(e); + getLogger().log(Level.SEVERE, "Error handling UIDL", e); } } @@ -2137,14 +2162,15 @@ public class ApplicationConnection implements HasHandlers { } Profiler.enter("sendHierarchyChangeEvents"); - VConsole.log(" * Sending hierarchy change events"); + getLogger().info(" * Sending hierarchy change events"); for (int i = 0; i < eventCount; i++) { ConnectorHierarchyChangeEvent event = events.get(i); try { logHierarchyChange(event); event.getConnector().fireEvent(event); } catch (final Throwable e) { - VConsole.error(e); + getLogger().log(Level.SEVERE, + "Error sending hierarchy change events", e); } } @@ -2157,13 +2183,14 @@ public class ApplicationConnection implements HasHandlers { return; } - VConsole.log("Hierarchy changed for " - + Util.getConnectorString(event.getConnector())); + getLogger() + .info("Hierarchy changed for " + + Util.getConnectorString(event.getConnector())); String oldChildren = "* Old children: "; for (ComponentConnector child : event.getOldChildren()) { oldChildren += Util.getConnectorString(child) + " "; } - VConsole.log(oldChildren); + getLogger().info(oldChildren); String newChildren = "* New children: "; HasComponentsConnector parent = (HasComponentsConnector) event @@ -2171,14 +2198,14 @@ public class ApplicationConnection implements HasHandlers { for (ComponentConnector child : parent.getChildComponents()) { newChildren += Util.getConnectorString(child) + " "; } - VConsole.log(newChildren); + getLogger().info(newChildren); } private JsArrayObject<StateChangeEvent> updateConnectorState( ValueMap json, JsArrayString createdConnectorIds) { JsArrayObject<StateChangeEvent> events = JavaScriptObject .createArray().cast(); - VConsole.log(" * Updating connector states"); + getLogger().info(" * Updating connector states"); if (!json.containsKey("state")) { return events; } @@ -2256,7 +2283,8 @@ public class ApplicationConnection implements HasHandlers { Profiler.leave("updateConnectorState inner loop"); } } catch (final Throwable e) { - VConsole.error(e); + getLogger().log(Level.SEVERE, + "Error updating connector states", e); } } @@ -2298,7 +2326,7 @@ public class ApplicationConnection implements HasHandlers { ValueMap json) { ConnectorHierarchyUpdateResult result = new ConnectorHierarchyUpdateResult(); - VConsole.log(" * Updating connector hierarchy"); + getLogger().info(" * Updating connector hierarchy"); if (!json.containsKey("hierarchy")) { return result; } @@ -2330,16 +2358,18 @@ public class ApplicationConnection implements HasHandlers { ServerConnector childConnector = connectorMap .getConnector(childConnectorId); if (childConnector == null) { - VConsole.error("Hierarchy claims that " - + childConnectorId - + " is a child for " - + connectorId - + " (" - + parentConnector.getClass().getName() - + ") but no connector with id " - + childConnectorId - + " has been registered. " - + "More information might be available in the server-side log if assertions are enabled"); + getLogger() + .severe("Hierarchy claims that " + + childConnectorId + + " is a child for " + + connectorId + + " (" + + parentConnector.getClass() + .getName() + + ") but no connector with id " + + childConnectorId + + " has been registered. " + + "More information might be available in the server-side log if assertions are enabled"); continue; } newChildren.add(childConnector); @@ -2392,9 +2422,10 @@ public class ApplicationConnection implements HasHandlers { result.events.add(event); } } else if (!newComponents.isEmpty()) { - VConsole.error("Hierachy claims " - + Util.getConnectorString(parentConnector) - + " has component children even though it isn't a HasComponentsConnector"); + getLogger() + .severe("Hierachy claims " + + Util.getConnectorString(parentConnector) + + " has component children even though it isn't a HasComponentsConnector"); } Profiler.leave("updateConnectorHierarchy handle HasComponentsConnector"); @@ -2428,7 +2459,8 @@ public class ApplicationConnection implements HasHandlers { Profiler.leave("updateConnectorHierarchy find removed children"); } catch (final Throwable e) { - VConsole.error(e); + getLogger().log(Level.SEVERE, + "Error updating connector hierarchy", e); } finally { Profiler.leave("updateConnectorHierarchy hierarchy entry"); } @@ -2575,7 +2607,8 @@ public class ApplicationConnection implements HasHandlers { if (json.containsKey("rpc")) { Profiler.enter("handleRpcInvocations"); - VConsole.log(" * Performing server to client RPC calls"); + getLogger() + .info(" * Performing server to client RPC calls"); JsonArray rpcCalls = Util.jso2json(json .getJavaScriptObject("rpc")); @@ -2595,7 +2628,10 @@ public class ApplicationConnection implements HasHandlers { } } catch (final Throwable e) { - VConsole.error(e); + getLogger() + .log(Level.SEVERE, + "Error performing server to client RPC calls", + e); } } @@ -2617,8 +2653,9 @@ public class ApplicationConnection implements HasHandlers { @Override public void onError(ResourceLoadEvent event) { - VConsole.error(event.getResourceUrl() - + " could not be loaded, or the load detection failed because the stylesheet is empty."); + getLogger() + .severe(event.getResourceUrl() + + " could not be loaded, or the load detection failed because the stylesheet is empty."); // The show must go on onLoad(event); } @@ -2652,7 +2689,8 @@ public class ApplicationConnection implements HasHandlers { @Override public void onError(ResourceLoadEvent event) { - VConsole.error(event.getResourceUrl() + " could not be loaded."); + getLogger().severe( + event.getResourceUrl() + " could not be loaded."); // The show must go on onLoad(event); } @@ -3143,7 +3181,7 @@ public class ApplicationConnection implements HasHandlers { layoutManager.forceLayout(); - VConsole.log("forceLayout in " + duration.elapsedMillis() + " ms"); + getLogger().info("forceLayout in " + duration.elapsedMillis() + " ms"); } /** @@ -3419,8 +3457,9 @@ public class ApplicationConnection implements HasHandlers { */ @Deprecated public void unregisterPaintable(ServerConnector p) { - VConsole.log("unregisterPaintable (unnecessarily) called for " - + Util.getConnectorString(p)); + getLogger().info( + "unregisterPaintable (unnecessarily) called for " + + Util.getConnectorString(p)); } /** @@ -3454,8 +3493,10 @@ public class ApplicationConnection implements HasHandlers { } if (!manageCaption) { - VConsole.error(Util.getConnectorString(connector) - + " called updateComponent with manageCaption=false. The parameter was ignored - override delegateCaption() to return false instead. It is however not recommended to use caption this way at all."); + getLogger() + .warning( + Util.getConnectorString(connector) + + " called updateComponent with manageCaption=false. The parameter was ignored - override delegateCaption() to return false instead. It is however not recommended to use caption this way at all."); } return false; } @@ -3517,7 +3558,9 @@ public class ApplicationConnection implements HasHandlers { Timer forceHandleMessage = new Timer() { @Override public void run() { - VConsole.log("WARNING: reponse handling was never resumed, forcibly removing locks..."); + getLogger() + .warning( + "WARNING: reponse handling was never resumed, forcibly removing locks..."); responseHandlingLocks.clear(); handlePendingMessages(); } @@ -3545,7 +3588,8 @@ public class ApplicationConnection implements HasHandlers { forceHandleMessage.cancel(); if (!pendingUIDLMessages.isEmpty()) { - VConsole.log("No more response handling locks, handling pending requests."); + getLogger() + .info("No more response handling locks, handling pending requests."); handlePendingMessages(); } } diff --git a/client/src/com/vaadin/client/BrowserInfo.java b/client/src/com/vaadin/client/BrowserInfo.java index 3bc75a9a9b..01968a17a6 100644 --- a/client/src/com/vaadin/client/BrowserInfo.java +++ b/client/src/com/vaadin/client/BrowserInfo.java @@ -88,7 +88,8 @@ public class BrowserInfo { } else if (browserDetails.isIE()) { touchDevice = detectIETouchDevice(); } else { - touchDevice = detectTouchDevice(); + //PhantomJS pretends to be a touch device which breaks some UI tests + touchDevice = !browserDetails.isPhantomJS() && detectTouchDevice(); } } diff --git a/client/src/com/vaadin/client/ConnectorMap.java b/client/src/com/vaadin/client/ConnectorMap.java index 1211eb2684..3200dd6ab4 100644 --- a/client/src/com/vaadin/client/ConnectorMap.java +++ b/client/src/com/vaadin/client/ConnectorMap.java @@ -17,6 +17,7 @@ package com.vaadin.client; import java.util.ArrayList; import java.util.Collection; +import java.util.logging.Logger; import com.google.gwt.core.client.GWT; import com.google.gwt.core.client.JavaScriptObject; @@ -182,7 +183,7 @@ public class ConnectorMap { */ public void unregisterConnector(ServerConnector connector) { if (connector == null) { - VConsole.error("Trying to unregister null connector"); + getLogger().severe("Trying to unregister null connector"); return; } @@ -299,4 +300,7 @@ public class ConnectorMap { return getConnectorId(w.getElement()) != null; } + private static Logger getLogger() { + return Logger.getLogger(ConnectorMap.class.getName()); + } } diff --git a/client/src/com/vaadin/client/DateTimeService.java b/client/src/com/vaadin/client/DateTimeService.java index f4cfe7a278..56116377cf 100644 --- a/client/src/com/vaadin/client/DateTimeService.java +++ b/client/src/com/vaadin/client/DateTimeService.java @@ -17,6 +17,8 @@ package com.vaadin.client; import java.util.Date; +import java.util.logging.Level; +import java.util.logging.Logger; import com.google.gwt.i18n.client.DateTimeFormat; import com.google.gwt.i18n.client.LocaleInfo; @@ -71,7 +73,7 @@ public class DateTimeService { try { return LocaleService.getMonthNames(currentLocale)[month]; } catch (final LocaleNotLoadedException e) { - VConsole.error(e); + getLogger().log(Level.SEVERE, "Error in getMonth", e); return null; } } @@ -80,7 +82,7 @@ public class DateTimeService { try { return LocaleService.getShortMonthNames(currentLocale)[month]; } catch (final LocaleNotLoadedException e) { - VConsole.error(e); + getLogger().log(Level.SEVERE, "Error in getShortMonth", e); return null; } } @@ -89,7 +91,7 @@ public class DateTimeService { try { return LocaleService.getDayNames(currentLocale)[day]; } catch (final LocaleNotLoadedException e) { - VConsole.error(e); + getLogger().log(Level.SEVERE, "Error in getDay", e); return null; } } @@ -98,7 +100,7 @@ public class DateTimeService { try { return LocaleService.getShortDayNames(currentLocale)[day]; } catch (final LocaleNotLoadedException e) { - VConsole.error(e); + getLogger().log(Level.SEVERE, "Error in getShortDay", e); return null; } } @@ -107,7 +109,7 @@ public class DateTimeService { try { return LocaleService.getFirstDayOfWeek(currentLocale); } catch (final LocaleNotLoadedException e) { - VConsole.error(e); + getLogger().log(Level.SEVERE, "Error in getFirstDayOfWeek", e); return 0; } } @@ -116,7 +118,7 @@ public class DateTimeService { try { return LocaleService.isTwelveHourClock(currentLocale); } catch (final LocaleNotLoadedException e) { - VConsole.error(e); + getLogger().log(Level.SEVERE, "Error in isTwelveHourClock", e); return false; } } @@ -125,7 +127,7 @@ public class DateTimeService { try { return LocaleService.getClockDelimiter(currentLocale); } catch (final LocaleNotLoadedException e) { - VConsole.error(e); + getLogger().log(Level.SEVERE, "Error in getClockDelimiter", e); return ":"; } } @@ -137,8 +139,8 @@ public class DateTimeService { return LocaleService.getAmPmStrings(currentLocale); } catch (final LocaleNotLoadedException e) { // TODO can this practically even happen? Should die instead? - VConsole.error("Locale not loaded, using fallback : AM/PM"); - VConsole.error(e); + getLogger().log(Level.SEVERE, + "Locale not loaded, using fallback : AM/PM", e); return DEFAULT_AMPM_STRINGS; } } @@ -150,8 +152,8 @@ public class DateTimeService { try { firstDay = LocaleService.getFirstDayOfWeek(currentLocale); } catch (final LocaleNotLoadedException e) { - VConsole.error("Locale not loaded, using fallback 0"); - VConsole.error(e); + getLogger().log(Level.SEVERE, + "Locale not loaded, using fallback 0", e); firstDay = 0; } int start = dateForFirstOfThisMonth.getDay() - firstDay; @@ -496,4 +498,7 @@ public class DateTimeService { } + public static Logger getLogger() { + return Logger.getLogger(DateTimeService.class.getName()); + } } diff --git a/client/src/com/vaadin/client/JavaScriptConnectorHelper.java b/client/src/com/vaadin/client/JavaScriptConnectorHelper.java index 1eb326115e..d992acd8b8 100644 --- a/client/src/com/vaadin/client/JavaScriptConnectorHelper.java +++ b/client/src/com/vaadin/client/JavaScriptConnectorHelper.java @@ -22,6 +22,7 @@ import java.util.HashSet; import java.util.Map; import java.util.Map.Entry; import java.util.Set; +import java.util.logging.Logger; import com.google.gwt.core.client.JavaScriptObject; import com.google.gwt.core.client.JsArray; @@ -158,18 +159,21 @@ public class JavaScriptConnectorHelper { String initFunctionName = serverSideClassName .replaceAll("\\.", "_"); if (tryInitJs(initFunctionName, getConnectorWrapper())) { - VConsole.log("JavaScript connector initialized using " - + initFunctionName); + getLogger().info( + "JavaScript connector initialized using " + + initFunctionName); this.initFunctionName = initFunctionName; return true; } else { - VConsole.log("No JavaScript function " + initFunctionName - + " found"); + getLogger() + .warning( + "No JavaScript function " + initFunctionName + + " found"); attemptedNames.add(initFunctionName); tag = conf.getParentTag(tag.intValue()); } } - VConsole.log("No JavaScript init for connector not found"); + getLogger().info("No JavaScript init for connector found"); showInitProblem(attemptedNames); return false; } @@ -497,4 +501,8 @@ public class JavaScriptConnectorHelper { public String getInitFunctionName() { return initFunctionName; } + + public static Logger getLogger() { + return Logger.getLogger(JavaScriptConnectorHelper.class.getName()); + } } diff --git a/client/src/com/vaadin/client/LayoutManager.java b/client/src/com/vaadin/client/LayoutManager.java index 828f0942b7..3f189bcea8 100644 --- a/client/src/com/vaadin/client/LayoutManager.java +++ b/client/src/com/vaadin/client/LayoutManager.java @@ -20,6 +20,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; +import java.util.logging.Level; import java.util.logging.Logger; import com.google.gwt.core.client.Duration; @@ -232,8 +233,9 @@ public class LayoutManager { } layoutCounts.put(layout.getConnectorId(), count); if (count.intValue() > 2) { - VConsole.error(Util.getConnectorString(layout) - + " has been layouted " + count.intValue() + " times"); + getLogger().severe( + Util.getConnectorString(layout) + " has been layouted " + + count.intValue() + " times"); } } @@ -281,7 +283,7 @@ public class LayoutManager { } private void doLayout() { - VConsole.log("Starting layout phase"); + getLogger().info("Starting layout phase"); Profiler.enter("LayoutManager phase init"); FastStringMap<Integer> layoutCounts = FastStringMap.create(); @@ -335,7 +337,7 @@ public class LayoutManager { everythingNeedsMeasure = false; if (measuredConnectorCount == 0) { - VConsole.log("No more changes in pass " + passes); + getLogger().info("No more changes in pass " + passes); Profiler.leave("Layout pass"); break; } @@ -373,7 +375,8 @@ public class LayoutManager { Profiler.leave(key); } } catch (RuntimeException e) { - VConsole.error(e); + getLogger().log(Level.SEVERE, + "Error in resize listener", e); } } Profiler.leave("Layout fire resize events - listeners not null"); @@ -417,7 +420,8 @@ public class LayoutManager { Profiler.leave(key); } } catch (RuntimeException e) { - VConsole.error(e); + getLogger().log(Level.SEVERE, + "Error in ManagedLayout handling", e); } countLayout(layoutCounts, cl); } else { @@ -440,7 +444,11 @@ public class LayoutManager { Profiler.leave(key); } } catch (RuntimeException e) { - VConsole.error(e); + getLogger() + .log(Level.SEVERE, + "Error in SimpleManagedLayout (horizontal) handling", + e); + } countLayout(layoutCounts, rr); } @@ -473,7 +481,10 @@ public class LayoutManager { Profiler.leave(key); } } catch (RuntimeException e) { - VConsole.error(e); + getLogger() + .log(Level.SEVERE, + "Error in DirectionalManagedLayout handling", + e); } countLayout(layoutCounts, cl); } else { @@ -496,7 +507,10 @@ public class LayoutManager { Profiler.leave(key); } } catch (RuntimeException e) { - VConsole.error(e); + getLogger() + .log(Level.SEVERE, + "Error in SimpleManagedLayout (vertical) handling", + e); } countLayout(layoutCounts, rr); } @@ -531,18 +545,19 @@ public class LayoutManager { b.append(connectorString); } } - VConsole.log(b.toString()); + getLogger().info(b.toString()); } Profiler.leave("Layout pass"); - VConsole.log("Pass " + passes + " measured " - + measuredConnectorCount + " elements, fired " - + firedListeners + " listeners and did " + layoutCount - + " layouts."); + getLogger() + .info("Pass " + passes + " measured " + + measuredConnectorCount + " elements, fired " + + firedListeners + " listeners and did " + + layoutCount + " layouts."); if (passes > 100) { - VConsole.log(LOOP_ABORT_MESSAGE); + getLogger().severe(LOOP_ABORT_MESSAGE); if (ApplicationConfiguration.isDebugMode()) { VNotification.createNotification( VNotification.DELAY_FOREVER, @@ -579,8 +594,9 @@ public class LayoutManager { cleanMeasuredSizes(); - VConsole.log("Total layout phase time: " - + totalDuration.elapsedMillis() + "ms"); + getLogger().info( + "Total layout phase time: " + totalDuration.elapsedMillis() + + "ms"); } private void logConnectorStatus(int connectorId) { @@ -614,11 +630,12 @@ public class LayoutManager { } if (debugLogging) { - VConsole.log("Doing overflow fix for " - + Util.getConnectorString(componentConnector) - + " in " - + Util.getConnectorString(componentConnector - .getParent())); + getLogger() + .info("Doing overflow fix for " + + Util.getConnectorString(componentConnector) + + " in " + + Util.getConnectorString(componentConnector + .getParent())); } Profiler.enter("Overflow fix apply"); @@ -669,8 +686,8 @@ public class LayoutManager { Profiler.leave("Overflow fix restore"); if (!pendingOverflowFixes.isEmpty()) { - VConsole.log("Did overflow fix for " + remainingCount - + " elements"); + getLogger().info( + "Did overflow fix for " + remainingCount + " elements"); } pendingOverflowFixes = delayedOverflowFixes; } @@ -794,8 +811,9 @@ public class LayoutManager { measuredAndUpdate(element, getMeasuredSize(element, null)); } Profiler.leave("LayoutManager.measureNonConenctors"); - VConsole.log("Measured " + measuredNonConnectorElements.size() - + " non connector elements"); + getLogger().info( + "Measured " + measuredNonConnectorElements.size() + + " non connector elements"); } private MeasureResult measuredAndUpdate(Element element, diff --git a/client/src/com/vaadin/client/MeasuredSize.java b/client/src/com/vaadin/client/MeasuredSize.java index 8520635a4d..eeedff561f 100644 --- a/client/src/com/vaadin/client/MeasuredSize.java +++ b/client/src/com/vaadin/client/MeasuredSize.java @@ -15,6 +15,8 @@ */ package com.vaadin.client; +import java.util.logging.Logger; + import com.google.gwt.core.client.JsArrayString; import com.google.gwt.dom.client.Element; @@ -276,8 +278,9 @@ public class MeasuredSize { private void debugSizeChange(Element element, String sizeChangeType, String changedFrom, String changedTo) { if (debugSizeChanges) { - VConsole.log(sizeChangeType + " has changed from " + changedFrom - + " to " + changedTo + " for " + element.toString()); + getLogger() + .info(sizeChangeType + " has changed from " + changedFrom + + " to " + changedTo + " for " + element.toString()); } } @@ -289,4 +292,8 @@ public class MeasuredSize { return sizes1[0] != sizes2[0] || sizes1[2] != sizes2[2]; } + public static Logger getLogger() { + return Logger.getLogger(MeasuredSize.class.getName()); + } + } diff --git a/client/src/com/vaadin/client/SuperDevMode.java b/client/src/com/vaadin/client/SuperDevMode.java index 821af6075a..7bd759a490 100644 --- a/client/src/com/vaadin/client/SuperDevMode.java +++ b/client/src/com/vaadin/client/SuperDevMode.java @@ -15,6 +15,8 @@ */ package com.vaadin.client; +import java.util.logging.Logger; + import com.google.gwt.core.client.GWT; import com.google.gwt.core.client.JavaScriptObject; import com.google.gwt.http.client.UrlBuilder; @@ -51,8 +53,9 @@ public class SuperDevMode { private static void recompileWidgetsetAndStartInDevMode( final String serverUrl) { - VConsole.log("Recompiling widgetset using<br/>" + serverUrl - + "<br/>and then reloading in super dev mode"); + getLogger().info( + "Recompiling widgetset using<br/>" + serverUrl + + "<br/>and then reloading in super dev mode"); VNotification n = new VNotification(); n.show("<b>Recompiling widgetset, please wait</b>", VNotification.CENTERED, VNotification.STYLE_SYSTEM); @@ -66,10 +69,10 @@ public class SuperDevMode { @Override public void onSuccess(RecompileResult result) { - VConsole.log("JSONP compile call successful"); + getLogger().fine("JSONP compile call successful"); if (!result.ok()) { - VConsole.log("* result: " + result); + getLogger().fine("* result: " + result); failed(); return; } @@ -80,17 +83,18 @@ public class SuperDevMode { serverUrl)); setSession(SKIP_RECOMPILE, "1"); - VConsole.log("* result: OK. Reloading"); + getLogger().fine("* result: OK. Reloading"); Location.reload(); } @Override public void onFailure(Throwable caught) { - VConsole.error("JSONP compile call failed"); + getLogger().severe("JSONP compile call failed"); // Don't log exception as they are shown as // notifications - VConsole.error(caught.getClass().getSimpleName() + ": " - + caught.getMessage()); + getLogger().severe( + caught.getClass().getSimpleName() + ": " + + caught.getMessage()); failed(); } @@ -189,7 +193,7 @@ public class SuperDevMode { } if (hasSession(SKIP_RECOMPILE)) { - VConsole.log("Running in SuperDevMode"); + getLogger().info("Running in SuperDevMode"); // When we get here, we are running in super dev mode // Remove the flag so next reload will recompile @@ -260,4 +264,8 @@ public class SuperDevMode { VNotification n = new VNotification(); n.show(message, VNotification.CENTERED_TOP, VNotification.STYLE_SYSTEM); } + + public static Logger getLogger() { + return Logger.getLogger(SuperDevMode.class.getName()); + } } diff --git a/client/src/com/vaadin/client/Util.java b/client/src/com/vaadin/client/Util.java index 99e6507d81..e8fbd8855b 100644 --- a/client/src/com/vaadin/client/Util.java +++ b/client/src/com/vaadin/client/Util.java @@ -21,6 +21,8 @@ import java.util.Arrays; import java.util.Collection; import java.util.Iterator; import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; import com.google.gwt.core.client.GWT; import com.google.gwt.core.client.JavaScriptObject; @@ -593,10 +595,11 @@ public class Util { ApplicationConnection c) { ServerConnector connector = ConnectorMap.get(c).getConnector(id); if (connector != null) { - VConsole.log("\t" + id + " (" + connector.getClass() + ") :"); + getLogger().info("\t" + id + " (" + connector.getClass() + ") :"); } else { - VConsole.log("\t" + id - + ": Warning: no corresponding connector for id " + id); + getLogger().warning( + "\t" + id + ": Warning: no corresponding connector for id " + + id); } for (MethodInvocation invocation : invocations) { Object[] parameters = invocation.getParameters(); @@ -615,15 +618,17 @@ public class Util { formattedParams = (null != parameters) ? Arrays .toString(parameters) : null; } - VConsole.log("\t\t" + invocation.getInterfaceName() + "." - + invocation.getMethodName() + "(" + formattedParams + ")"); + getLogger().info( + "\t\t" + invocation.getInterfaceName() + "." + + invocation.getMethodName() + "(" + + formattedParams + ")"); } } static void logVariableBurst(ApplicationConnection c, Collection<MethodInvocation> loggedBurst) { try { - VConsole.log("Variable burst to be sent to server:"); + getLogger().info("Variable burst to be sent to server:"); String curId = null; ArrayList<MethodInvocation> invocations = new ArrayList<MethodInvocation>(); for (MethodInvocation methodInvocation : loggedBurst) { @@ -642,7 +647,7 @@ public class Util { printConnectorInvocations(invocations, curId, c); } } catch (Exception e) { - VConsole.error(e); + getLogger().log(Level.SEVERE, "Error sending variable burst", e); } } @@ -959,4 +964,7 @@ public class Util { return JSON.parse(jsonAsString); }-*/; + public static Logger getLogger() { + return Logger.getLogger(Util.class.getName()); + } } diff --git a/client/src/com/vaadin/client/VCaption.java b/client/src/com/vaadin/client/VCaption.java index 050edae8be..47c9309b39 100644 --- a/client/src/com/vaadin/client/VCaption.java +++ b/client/src/com/vaadin/client/VCaption.java @@ -16,6 +16,8 @@ package com.vaadin.client; +import java.util.logging.Logger; + import com.google.gwt.aria.client.Roles; import com.google.gwt.dom.client.Element; import com.google.gwt.dom.client.Style.Unit; @@ -445,7 +447,9 @@ public class VCaption extends HTML { if (owner != null) { Util.notifyParentOfSizeChange(owner.getWidget(), true); } else { - VConsole.log("Warning: Icon load event was not propagated because VCaption owner is unknown."); + getLogger() + .warning( + "Warning: Icon load event was not propagated because VCaption owner is unknown."); } } } @@ -766,4 +770,7 @@ public class VCaption extends HTML { } + public static Logger getLogger() { + return Logger.getLogger(VCaption.class.getName()); + } } diff --git a/client/src/com/vaadin/client/VTooltip.java b/client/src/com/vaadin/client/VTooltip.java index 453563370c..b9392e3941 100644 --- a/client/src/com/vaadin/client/VTooltip.java +++ b/client/src/com/vaadin/client/VTooltip.java @@ -20,17 +20,7 @@ import com.google.gwt.aria.client.RelevantValue; import com.google.gwt.aria.client.Roles; import com.google.gwt.dom.client.Element; 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.DomEvent; -import com.google.gwt.event.dom.client.FocusEvent; -import com.google.gwt.event.dom.client.FocusHandler; -import com.google.gwt.event.dom.client.KeyDownEvent; -import com.google.gwt.event.dom.client.KeyDownHandler; -import com.google.gwt.event.dom.client.MouseDownEvent; -import com.google.gwt.event.dom.client.MouseDownHandler; -import com.google.gwt.event.dom.client.MouseMoveEvent; -import com.google.gwt.event.dom.client.MouseMoveHandler; +import com.google.gwt.event.dom.client.*; import com.google.gwt.user.client.DOM; import com.google.gwt.user.client.Event; import com.google.gwt.user.client.Timer; @@ -70,6 +60,11 @@ public class VTooltip extends VOverlay { private int closeTimeout; /** + * Current element hovered + */ + private com.google.gwt.dom.client.Element currentElement = null; + + /** * Used to show tooltips; usually used via the singleton in * {@link ApplicationConnection}. NOTE that #setOwner(Widget)} should be * called after instantiating. @@ -179,8 +174,20 @@ public class VTooltip extends VOverlay { offsetWidth = getOffsetWidth(); offsetHeight = getOffsetHeight(); } - int x = getFinalX(offsetWidth); - int y = getFinalY(offsetHeight); + + int x = 0; + int y = 0; + if(BrowserInfo.get().isTouchDevice()) { + setMaxWidth(Window.getClientWidth()); + offsetWidth = getOffsetWidth(); + offsetHeight = getOffsetHeight(); + + x = getFinalTouchX(offsetWidth); + y = getFinalTouchY(offsetHeight); + } else { + x = getFinalX(offsetWidth); + y = getFinalY(offsetHeight); + } setPopupPosition(x, y); sinkEvents(Event.ONMOUSEOVER | Event.ONMOUSEOUT); @@ -222,6 +229,40 @@ public class VTooltip extends VOverlay { } /** + * Return the final X-coordinate of the tooltip based on cursor + * position, size of the tooltip, size of the page and necessary + * margins. + * + * @param offsetWidth + * @return The final X-coordinate + */ + private int getFinalTouchX(int offsetWidth) { + int x = 0; + int widthNeeded = 10 + offsetWidth; + int roomLeft = currentElement != null ? + currentElement.getAbsoluteLeft() : EVENT_XY_POSITION_OUTSIDE; + int viewPortWidth = Window.getClientWidth(); + int roomRight = viewPortWidth - roomLeft; + if (roomRight > widthNeeded) { + x = roomLeft; + } else { + x = roomLeft - offsetWidth; + } + if (x + offsetWidth - Window.getScrollLeft() > viewPortWidth) { + x = viewPortWidth - offsetWidth + Window.getScrollLeft(); + } + + if (roomLeft != EVENT_XY_POSITION_OUTSIDE) { + // Do not allow x to be zero, for otherwise the tooltip + // does not close when the mouse is moved (see + // isTooltipOpen()). #15129 + int minX = Window.getScrollLeft(); + x = Math.max(x, minX); + } + return x; + } + + /** * Return the final Y-coordinate of the tooltip based on cursor * position, size of the tooltip, size of the page and necessary * margins. @@ -232,7 +273,7 @@ public class VTooltip extends VOverlay { */ private int getFinalY(int offsetHeight) { int y = 0; - int heightNeeded = 10 + MARGIN + offsetHeight; + int heightNeeded = 10 + offsetHeight; int roomAbove = tooltipEventMouseY; int roomBelow = Window.getClientHeight() - roomAbove; @@ -263,12 +304,58 @@ public class VTooltip extends VOverlay { } return y; } + + /** + * Return the final Y-coordinate of the tooltip based on cursor + * position, size of the tooltip, size of the page and necessary + * margins. + * + * @param offsetHeight + * @return The final y-coordinate + * + */ + private int getFinalTouchY(int offsetHeight) { + int y = 0; + int heightNeeded = 10 + offsetHeight; + int roomAbove = currentElement != null ? + currentElement.getAbsoluteTop() + currentElement.getOffsetHeight() + : EVENT_XY_POSITION_OUTSIDE; + int roomBelow = Window.getClientHeight() - roomAbove; + + if (roomBelow > heightNeeded) { + y = roomAbove; + } else { + y = roomAbove - offsetHeight - + (currentElement != null ? currentElement.getOffsetHeight() : 0); + } + + if (y + offsetHeight - Window.getScrollTop() > Window + .getClientHeight()) { + y = roomAbove - 5 - offsetHeight + + Window.getScrollTop(); + if (y - Window.getScrollTop() < 0) { + // tooltip does not fit on top of the mouse either, + // put it at the top of the screen + y = Window.getScrollTop(); + } + } + + if (roomAbove != EVENT_XY_POSITION_OUTSIDE) { + // Do not allow y to be zero, for otherwise the tooltip + // does not close when the mouse is moved (see + // isTooltipOpen()). #15129 + int minY = Window.getScrollTop(); + y = Math.max(y, minY); + } + return y; + } }); } else { hide(); } } + /** * For assistive tooltips to work correctly we must have the tooltip visible * and attached to the DOM well in advance. For this reason both isShowing @@ -391,11 +478,6 @@ public class VTooltip extends VOverlay { KeyDownHandler, FocusHandler, BlurHandler, MouseDownHandler { /** - * Current element hovered - */ - private com.google.gwt.dom.client.Element currentElement = null; - - /** * Marker for handling of tooltip through focus */ private boolean handledByFocus; @@ -455,7 +537,7 @@ public class VTooltip extends VOverlay { @Override public void onMouseDown(MouseDownEvent event) { - handleHideEvent(); + handleHideEvent(); } @Override @@ -524,6 +606,11 @@ public class VTooltip extends VOverlay { updatePosition(event, isFocused); // Schedule timer for showing the tooltip according to if it // was recently closed or not. + + if (BrowserInfo.get().isIOS()) { + element.focus(); + } + int timeout = justClosed ? getQuickOpenDelay() : getOpenDelay(); if (timeout == 0) { showTooltip(); diff --git a/client/src/com/vaadin/client/WidgetSet.java b/client/src/com/vaadin/client/WidgetSet.java index eff98a146a..797047367f 100644 --- a/client/src/com/vaadin/client/WidgetSet.java +++ b/client/src/com/vaadin/client/WidgetSet.java @@ -16,6 +16,9 @@ package com.vaadin.client; +import java.util.logging.Level; +import java.util.logging.Logger; + import com.google.gwt.core.client.GWT; import com.vaadin.client.communication.HasJavaScriptConnectorHelper; import com.vaadin.client.metadata.BundleLoadCallback; @@ -132,11 +135,15 @@ public class WidgetSet { @Override public void failed(Throwable reason) { - VConsole.error(reason); + getLogger().log(Level.SEVERE, "Error loading bundle", + reason); ApplicationConfiguration.endDependencyLoading(); } }); } } + public static Logger getLogger() { + return Logger.getLogger(WidgetSet.class.getName()); + } } diff --git a/client/src/com/vaadin/client/communication/AtmospherePushConnection.java b/client/src/com/vaadin/client/communication/AtmospherePushConnection.java index cd989d7ea4..e453ee7fcf 100644 --- a/client/src/com/vaadin/client/communication/AtmospherePushConnection.java +++ b/client/src/com/vaadin/client/communication/AtmospherePushConnection.java @@ -17,6 +17,7 @@ package com.vaadin.client.communication; import java.util.ArrayList; +import java.util.logging.Logger; import com.google.gwt.core.client.JavaScriptObject; import com.google.gwt.core.client.Scheduler; @@ -30,7 +31,6 @@ import com.vaadin.client.ApplicationConnection.CommunicationErrorHandler; import com.vaadin.client.ResourceLoader; import com.vaadin.client.ResourceLoader.ResourceLoadEvent; import com.vaadin.client.ResourceLoader.ResourceLoadListener; -import com.vaadin.client.VConsole; import com.vaadin.shared.ApplicationConstants; import com.vaadin.shared.Version; import com.vaadin.shared.communication.PushConstants; @@ -210,7 +210,7 @@ public class AtmospherePushConnection implements PushConnection { // uri is needed to identify the right connection when closing uri = SharedUtil.addGetParameters(baseUrl, extraParams); - VConsole.log("Establishing push connection"); + getLogger().info("Establishing push connection"); socket = doConnect(uri, getConfig()); } @@ -230,12 +230,12 @@ public class AtmospherePushConnection implements PushConnection { switch (state) { case CONNECT_PENDING: assert isActive(); - VConsole.log("Queuing push message: " + message.toJson()); + getLogger().info("Queuing push message: " + message.toJson()); messageQueue.add(message); break; case CONNECTED: assert isActive(); - VConsole.log("Sending push message: " + message.toJson()); + getLogger().info("Sending push message: " + message.toJson()); if (transport.equals("websocket")) { FragmentedMessage fragmented = new FragmentedMessage( @@ -258,14 +258,15 @@ public class AtmospherePushConnection implements PushConnection { } protected void onReopen(AtmosphereResponse response) { - VConsole.log("Push connection re-established using " - + response.getTransport()); + getLogger().info( + "Push connection re-established using " + + response.getTransport()); onConnect(response); } protected void onOpen(AtmosphereResponse response) { - VConsole.log("Push connection established using " - + response.getTransport()); + getLogger().info( + "Push connection established using " + response.getTransport()); onConnect(response); } @@ -321,7 +322,7 @@ public class AtmospherePushConnection implements PushConnection { break; case CONNECTED: // Normal disconnect - VConsole.log("Closing push connection"); + getLogger().info("Closing push connection"); doDisconnect(uri); state = State.DISCONNECTED; command.execute(); @@ -335,7 +336,7 @@ public class AtmospherePushConnection implements PushConnection { protected void onMessage(AtmosphereResponse response) { String message = response.getResponseBody(); if (message.startsWith("for(;;);")) { - VConsole.log("Received push message: " + message); + getLogger().info("Received push message: " + message); // "for(;;);[{json}]" -> "{json}" message = message.substring(9, message.length() - 1); connection.handlePushMessage(message); @@ -347,9 +348,10 @@ public class AtmospherePushConnection implements PushConnection { * tried */ protected void onTransportFailure() { - VConsole.log("Push connection using primary method (" - + getConfig().getTransport() + ") failed. Trying with " - + getConfig().getFallbackTransport()); + getLogger().warning( + "Push connection using primary method (" + + getConfig().getTransport() + ") failed. Trying with " + + getConfig().getFallbackTransport()); } /** @@ -365,7 +367,7 @@ public class AtmospherePushConnection implements PushConnection { } protected void onClose(AtmosphereResponse response) { - VConsole.log("Push connection closed"); + getLogger().info("Push connection closed"); state = State.CONNECT_PENDING; } @@ -380,10 +382,11 @@ public class AtmospherePushConnection implements PushConnection { protected void onReconnect(JavaScriptObject request, final AtmosphereResponse response) { if (state == State.CONNECTED) { - VConsole.log("No onClose was received before reconnect. Forcing state to closed."); + getLogger() + .fine("No onClose was received before reconnect. Forcing state to closed."); state = State.CONNECT_PENDING; } - VConsole.log("Reopening push connection"); + getLogger().info("Reopening push connection"); } public static abstract class AbstractJSO extends JavaScriptObject { @@ -535,14 +538,14 @@ public class AtmospherePushConnection implements PushConnection { } else { final String pushJs = getVersionedPushJs(); - VConsole.log("Loading " + pushJs); + getLogger().info("Loading " + pushJs); ResourceLoader.get().loadScript( connection.getConfiguration().getVaadinDirUrl() + pushJs, new ResourceLoadListener() { @Override public void onLoad(ResourceLoadEvent event) { if (isAtmosphereLoaded()) { - VConsole.log(pushJs + " loaded"); + getLogger().info(pushJs + " loaded"); command.execute(); } else { // If bootstrap tried to load vaadinPush.js, @@ -584,4 +587,8 @@ public class AtmospherePushConnection implements PushConnection { public String getTransportType() { return transport; } + + public static Logger getLogger() { + return Logger.getLogger(AtmospherePushConnection.class.getName()); + } } diff --git a/client/src/com/vaadin/client/communication/RpcManager.java b/client/src/com/vaadin/client/communication/RpcManager.java index f5c3ca9ffb..83dd6b15bd 100644 --- a/client/src/com/vaadin/client/communication/RpcManager.java +++ b/client/src/com/vaadin/client/communication/RpcManager.java @@ -17,11 +17,11 @@ package com.vaadin.client.communication; import java.util.Collection; +import java.util.logging.Logger; import com.vaadin.client.ApplicationConnection; import com.vaadin.client.ConnectorMap; import com.vaadin.client.ServerConnector; -import com.vaadin.client.VConsole; import com.vaadin.client.metadata.Method; import com.vaadin.client.metadata.NoDataException; import com.vaadin.client.metadata.Type; @@ -122,7 +122,7 @@ public class RpcManager { } parseMethodParameters(invocation, parametersJson, connection); - VConsole.log("Server to client RPC call: " + invocation); + getLogger().info("Server to client RPC call: " + invocation); applyInvocation(invocation, connector); } @@ -142,4 +142,7 @@ public class RpcManager { methodInvocation.setParameters(parameters); } + public static Logger getLogger() { + return Logger.getLogger(RpcManager.class.getName()); + } } diff --git a/client/src/com/vaadin/client/debug/internal/ConnectorInfoPanel.java b/client/src/com/vaadin/client/debug/internal/ConnectorInfoPanel.java index 0856bb3575..d26a0ee076 100644 --- a/client/src/com/vaadin/client/debug/internal/ConnectorInfoPanel.java +++ b/client/src/com/vaadin/client/debug/internal/ConnectorInfoPanel.java @@ -18,13 +18,14 @@ package com.vaadin.client.debug.internal; import java.util.Arrays; import java.util.HashSet; import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.HTML; import com.vaadin.client.ComponentConnector; import com.vaadin.client.JsArrayObject; import com.vaadin.client.ServerConnector; -import com.vaadin.client.VConsole; import com.vaadin.client.WidgetUtil; import com.vaadin.client.metadata.NoDataException; import com.vaadin.client.metadata.Property; @@ -84,7 +85,7 @@ public class ConnectorInfoPanel extends FlowPanel { } } catch (NoDataException e) { html += "<div>Could not read state, error has been logged to the console</div>"; - VConsole.error(e); + getLogger().log(Level.SEVERE, "Could not read state", e); } clear(); @@ -105,4 +106,8 @@ public class ConnectorInfoPanel extends FlowPanel { public void clearContents() { clear(); } + + public static Logger getLogger() { + return Logger.getLogger(ConnectorInfoPanel.class.getName()); + } } diff --git a/client/src/com/vaadin/client/debug/internal/OptimizedWidgetsetPanel.java b/client/src/com/vaadin/client/debug/internal/OptimizedWidgetsetPanel.java index e2b1f928de..5134ed3b27 100644 --- a/client/src/com/vaadin/client/debug/internal/OptimizedWidgetsetPanel.java +++ b/client/src/com/vaadin/client/debug/internal/OptimizedWidgetsetPanel.java @@ -17,6 +17,7 @@ package com.vaadin.client.debug.internal; import java.util.HashSet; import java.util.Set; +import java.util.logging.Logger; import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.HTML; @@ -24,7 +25,6 @@ import com.vaadin.client.ApplicationConfiguration; import com.vaadin.client.ApplicationConnection; import com.vaadin.client.ServerConnector; import com.vaadin.client.Util; -import com.vaadin.client.VConsole; import com.vaadin.client.ui.UnknownComponentConnector; /** @@ -95,7 +95,8 @@ public class OptimizedWidgetsetPanel extends FlowPanel { tag++; if (tag > 10000) { // Sanity check - VConsole.error("Search for used connector classes was forcefully terminated"); + getLogger() + .severe("Search for used connector classes was forcefully terminated"); break; } } @@ -136,4 +137,7 @@ public class OptimizedWidgetsetPanel extends FlowPanel { return s; } + public static Logger getLogger() { + return Logger.getLogger(OptimizedWidgetsetPanel.class.getName()); + } } diff --git a/client/src/com/vaadin/client/ui/VFilterSelect.java b/client/src/com/vaadin/client/ui/VFilterSelect.java index c99ed49c91..d99779b7ec 100644 --- a/client/src/com/vaadin/client/ui/VFilterSelect.java +++ b/client/src/com/vaadin/client/ui/VFilterSelect.java @@ -454,7 +454,6 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler, // Set the text. setText(suggestion.getReplacementString()); - menu.updateKeyboardSelectedItem(); } /* @@ -739,13 +738,6 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler, public class SuggestionMenu extends MenuBar implements SubPartAware, LoadHandler { - /** - * Tracks the item that is currently selected using the keyboard. This - * is need only because mouseover changes the selection and we do not - * want to use that selection when pressing enter to select the item. - */ - private MenuItem keyboardSelectedItem; - private VLazyExecutor delayedImageLoadExecutioner = new VLazyExecutor( 100, new ScheduledCommand() { @@ -807,9 +799,6 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler, if (enableDebug) { debug("VFS.SM: setSuggestions(" + suggestions + ")"); } - // Reset keyboard selection when contents is updated to avoid - // reusing old, invalid data - setKeyboardSelectedItem(null); clearItems(); final Iterator<FilterSelectSuggestion> it = suggestions.iterator(); @@ -984,14 +973,6 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler, } - private MenuItem getKeyboardSelectedItem() { - return keyboardSelectedItem; - } - - public void setKeyboardSelectedItem(MenuItem menuItem) { - keyboardSelectedItem = menuItem; - } - /** * @deprecated use {@link SuggestionPopup#selectFirstItem()} instead. */ @@ -1014,13 +995,6 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler, } /* - * Sets the keyboard item as the current selected one. - */ - void updateKeyboardSelectedItem() { - setKeyboardSelectedItem(getSelectedItem()); - } - - /* * Gets the height of one menu item. */ int getItemOffsetHeight() { @@ -1787,25 +1761,13 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler, break; case KeyCodes.KEY_TAB: case KeyCodes.KEY_ENTER: - if (suggestionPopup.menu.getKeyboardSelectedItem() == null) { - /* - * Nothing selected using up/down. Happens e.g. when entering a - * text (causes popup to open) and then pressing enter. - */ - if (!allowNewItem) { - onSuggestionSelected(currentSuggestions - .get(suggestionPopup.menu.getSelectedIndex())); - } else { - // Handle addition of new items. - suggestionPopup.menu.doSelectedItemAction(); - } + + if (!allowNewItem) { + onSuggestionSelected(currentSuggestions + .get(suggestionPopup.menu.getSelectedIndex())); } else { - /* - * Get the suggestion that was navigated to using up/down. - */ - currentSuggestion = ((FilterSelectSuggestion) suggestionPopup.menu - .getKeyboardSelectedItem().getCommand()); - onSuggestionSelected(currentSuggestion); + // Handle addition of new items. + suggestionPopup.menu.doSelectedItemAction(); } event.stopPropagation(); diff --git a/client/src/com/vaadin/client/ui/VFormLayout.java b/client/src/com/vaadin/client/ui/VFormLayout.java index a2ea77d31c..3781305e52 100644 --- a/client/src/com/vaadin/client/ui/VFormLayout.java +++ b/client/src/com/vaadin/client/ui/VFormLayout.java @@ -361,7 +361,11 @@ public class VFormLayout extends SimplePanel { public ErrorFlag(ComponentConnector owner) { setStyleName(CLASSNAME); - sinkEvents(VTooltip.TOOLTIP_EVENTS); + + if(!BrowserInfo.get().isTouchDevice()) { + sinkEvents(VTooltip.TOOLTIP_EVENTS); + } + this.owner = owner; } diff --git a/client/src/com/vaadin/client/ui/VGridLayout.java b/client/src/com/vaadin/client/ui/VGridLayout.java index 90ae944322..d1e055eb5d 100644 --- a/client/src/com/vaadin/client/ui/VGridLayout.java +++ b/client/src/com/vaadin/client/ui/VGridLayout.java @@ -889,6 +889,10 @@ public class VGridLayout extends ComplexPanel { cell.slot.setCaption(null); cell.slot.getWrapperElement().removeFromParent(); cell.slot = null; + Style style = w.getElement().getStyle(); + style.clearTop(); + style.clearLeft(); + style.clearPosition(); if (cells.length < cell.col && cells.length != 0 && cells[0].length < cell.row diff --git a/client/src/com/vaadin/client/ui/VNotification.java b/client/src/com/vaadin/client/ui/VNotification.java index d7639b0022..eee0f459a6 100644 --- a/client/src/com/vaadin/client/ui/VNotification.java +++ b/client/src/com/vaadin/client/ui/VNotification.java @@ -257,12 +257,19 @@ public class VNotification extends VOverlay { /** * Android 4 fails to render notifications correctly without a little * nudge (#8551) + * Chrome 41 now requires this too (#17252) */ - if (BrowserInfo.get().isAndroid()) { + if (BrowserInfo.get().isAndroid() + || isChrome41OrHigher()) { WidgetUtil.setStyleTemporarily(getElement(), "display", "none"); } } + private boolean isChrome41OrHigher() { + return BrowserInfo.get().isChrome() + && BrowserInfo.get().getBrowserMajorVersion() >= 41; + } + protected void hideAfterDelay() { if (delay == null) { delay = new Timer() { diff --git a/client/src/com/vaadin/client/ui/VScrollTable.java b/client/src/com/vaadin/client/ui/VScrollTable.java index 13561dcd0f..6a8ce67678 100644 --- a/client/src/com/vaadin/client/ui/VScrollTable.java +++ b/client/src/com/vaadin/client/ui/VScrollTable.java @@ -5947,6 +5947,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets, } contextTouchTimeout .schedule(TOUCH_CONTEXT_MENU_TIMEOUT); + event.stopPropagation(); } break; case Event.ONTOUCHMOVE: @@ -5987,10 +5988,10 @@ public class VScrollTable extends FlowPanel implements HasWidgets, if (touchStart != null) { if (!BrowserInfo.get().isAndroid()) { event.preventDefault(); - event.stopPropagation(); WidgetUtil.simulateClickFromTouchEvent( touchStart, this); } + event.stopPropagation(); touchStart = null; } isDragging = false; diff --git a/client/src/com/vaadin/client/ui/VSlider.java b/client/src/com/vaadin/client/ui/VSlider.java index f5769ddf74..651880502c 100644 --- a/client/src/com/vaadin/client/ui/VSlider.java +++ b/client/src/com/vaadin/client/ui/VSlider.java @@ -201,7 +201,7 @@ public class VSlider extends SimpleFocusablePanel implements Field, * applied to call code for parentElement only in case it exists. */ if (getElement().hasParentElement()) { - final Element p = getElement().getParentElement(); + final Element p = getElement(); if (p.getPropertyInt(domProperty) > MIN_SIZE) { if (isVertical()) { setHeight(); @@ -216,8 +216,10 @@ public class VSlider extends SimpleFocusablePanel implements Field, @Override public void execute() { - final Element p = getElement().getParentElement(); - if (p.getPropertyInt(domProperty) > (MIN_SIZE + 5)) { + final Element p = getElement(); + if (p.getPropertyInt(domProperty) > (MIN_SIZE + 5) + || propertyNotNullOrEmpty(styleAttribute, + p)) { if (isVertical()) { setHeight(); } else { @@ -227,6 +229,14 @@ public class VSlider extends SimpleFocusablePanel implements Field, setValue(value, false); } } + + // Style has non empty property + private boolean propertyNotNullOrEmpty( + final String styleAttribute, final Element p) { + return p.getStyle().getProperty(styleAttribute) != null + && !p.getStyle().getProperty(styleAttribute) + .isEmpty(); + } }); } } diff --git a/client/src/com/vaadin/client/ui/colorpicker/AbstractColorPickerConnector.java b/client/src/com/vaadin/client/ui/colorpicker/AbstractColorPickerConnector.java index ac168d1f9a..cba2a667ca 100644 --- a/client/src/com/vaadin/client/ui/colorpicker/AbstractColorPickerConnector.java +++ b/client/src/com/vaadin/client/ui/colorpicker/AbstractColorPickerConnector.java @@ -30,6 +30,8 @@ import com.vaadin.shared.ui.colorpicker.ColorPickerState; public abstract class AbstractColorPickerConnector extends AbstractComponentConnector implements ClickHandler { + private static final String DEFAULT_WIDTH_STYLE = "v-default-caption-width"; + @Override public ColorPickerState getState() { return (ColorPickerState) super.getState(); @@ -59,6 +61,7 @@ public abstract class AbstractColorPickerConnector extends || stateChangeEvent.hasPropertyChanged("showDefaultCaption")) { setCaption(getCaption()); + refreshDefaultCaptionStyle(); } } @@ -84,6 +87,19 @@ public abstract class AbstractColorPickerConnector extends } /** + * Add/remove default caption style. + */ + protected void refreshDefaultCaptionStyle() { + if (getState().showDefaultCaption + && (getState().caption == null || getState().caption.isEmpty()) + && getState().width.isEmpty()) { + getWidget().addStyleName(DEFAULT_WIDTH_STYLE); + } else { + getWidget().removeStyleName(DEFAULT_WIDTH_STYLE); + } + } + + /** * Set caption of the color picker widget. * * @param caption diff --git a/client/src/com/vaadin/client/ui/dd/DDEventHandleStrategy.java b/client/src/com/vaadin/client/ui/dd/DDEventHandleStrategy.java new file mode 100644 index 0000000000..9f8714ceaa --- /dev/null +++ b/client/src/com/vaadin/client/ui/dd/DDEventHandleStrategy.java @@ -0,0 +1,417 @@ +/* + * 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.dd; + +import com.google.gwt.dom.client.Element; +import com.google.gwt.dom.client.NativeEvent; +import com.google.gwt.dom.client.Node; +import com.google.gwt.dom.client.Style.Display; +import com.google.gwt.event.dom.client.KeyCodes; +import com.google.gwt.user.client.Event; +import com.google.gwt.user.client.Event.NativePreviewEvent; +import com.vaadin.client.WidgetUtil; +import com.vaadin.client.ui.dd.VDragAndDropManager.DDManagerMediator; + +/** + * Strategy to handle native preview events for VDragAndDropManager. + * + * The strategy could be overridden via GWT Deferred Binding mechanism. + * + * @author Vaadin Ltd + */ +public class DDEventHandleStrategy { + + /** + * Returns {@code true} if {@code event} interrupts Drag and Drop. + * + * @param event + * GWT event to handle + * @param mediator + * VDragAndDropManager data accessor + * @return whether {@code true} interrupts DnD + */ + public boolean isDragInterrupted(NativePreviewEvent event, + DDManagerMediator mediator) { + int typeInt = event.getTypeInt(); + if (typeInt == Event.ONKEYDOWN) { + int keyCode = event.getNativeEvent().getKeyCode(); + if (keyCode == KeyCodes.KEY_ESCAPE) { + return true; + } + } + return false; + } + + /** + * Handles key down {@code event}. + * + * Default implementation doesn't do anything. + * + * @param event + * key down GWT event + * @param mediator + * VDragAndDropManager data accessor + */ + public void handleKeyDownEvent(NativePreviewEvent event, + DDManagerMediator mediator) { + // no use for handling for any key down event + } + + /** + * Get target element for {@code event}. + * + * @param event + * GWT event to find target + * @param mediator + * VDragAndDropManager data accessor + * @return target element for {@code event} + */ + public Element getTargetElement(NativePreviewEvent event, + DDManagerMediator mediator) { + NativeEvent gwtEvent = event.getNativeEvent(); + Element targetElement; + if (WidgetUtil.isTouchEvent(gwtEvent) + || mediator.getManager().getDragElement() != null) { + int x = WidgetUtil.getTouchOrMouseClientX(gwtEvent); + int y = WidgetUtil.getTouchOrMouseClientY(gwtEvent); + // Util.browserDebugger(); + targetElement = WidgetUtil.getElementFromPoint(x, y); + } else { + Node targetNode = Node.as(gwtEvent.getEventTarget()); + + if (Element.is(targetNode)) { + targetElement = Element.as(targetNode); + } else { + targetElement = targetNode.getParentElement(); + } + } + return targetElement; + } + + /** + * Updates drag image DOM element. This method updates drag image position + * and adds additional styles. Default implementation hides drag element to + * be able to get target element by the point (see + * {@link #getTargetElement(NativePreviewEvent, DDManagerMediator)}. Method + * {@link #restoreDragImage(String, DDManagerMediator, NativePreviewEvent)} + * is used later on to restore the drag element in its state before + * temporary update. Returns "display" CSS style property of the original + * drag image. This value will be passed to the + * {@link #restoreDragImage(String, DDManagerMediator, NativePreviewEvent)} + * method. + * + * @param event + * GWT event for active DnD operation + * @param mediator + * VDragAndDropManager data accessor + * @return "display" CSS style property of drag image element to restore it + * later on + */ + public String updateDragImage(NativePreviewEvent event, + DDManagerMediator mediator) { + VDragAndDropManager manager = mediator.getManager(); + manager.updateDragImagePosition(event.getNativeEvent(), + manager.getDragElement()); + String display = null; + if (manager.getDragElement() != null) { + // to detect the "real" target, hide dragelement temporary and + // use elementFromPoint + display = manager.getDragElement().getStyle().getDisplay(); + manager.getDragElement().getStyle().setDisplay(Display.NONE); + } + return display; + } + + /** + * Restores drag image after temporary update by + * {@link #updateDragImage(NativePreviewEvent, DDManagerMediator)}. + * + * @param originalImageDisplay + * original "display" CSS style property of drag image element + * @param mediator + * VDragAndDropManager data accessor + * @param event + * GWT event for active DnD operation + */ + public void restoreDragImage(String originalImageDisplay, + DDManagerMediator mediator, NativePreviewEvent event) { + VDragAndDropManager manager = mediator.getManager(); + if (manager.getDragElement() != null) { + manager.getDragElement().getStyle() + .setProperty("display", originalImageDisplay); + } + } + + /** + * Handles event when drag image element ( + * {@link VDragAndDropManager#getDragElement()} return value) is not null or + * {@code event} is touch event. + * + * If method returns {@code true} then event processing will be stoped. + * + * @param target + * target element over which DnD event has happened + * @param event + * GWT event for active DnD operation + * @param mediator + * VDragAndDropManager data accessor + * @return {@code true} is strategy handled the event and no further steps + * to handle required. + */ + public boolean handleDragImageEvent(Element target, + NativePreviewEvent event, DDManagerMediator mediator) { + VDragAndDropManager manager = mediator.getManager(); + + // ApplicationConnection.getConsole().log( + // "Event on dragImage, target changed"); + // special handling for events over dragImage + // pretty much all events are mousemove althout below + // kind of happens mouseover + switch (event.getTypeInt()) { + case Event.ONMOUSEOVER: + case Event.ONMOUSEOUT: + // ApplicationConnection + // .getConsole() + // .log( + // "IGNORING proxy image event, fired because of hack or not significant"); + return true; + case Event.ONMOUSEMOVE: + case Event.ONTOUCHMOVE: + VDropHandler findDragTarget = findDragTarget(target, mediator); + if (findDragTarget != manager.getCurrentDropHandler()) { + // dragleave on old + handleDragLeave(mediator, true); + // dragenter on new + manager.setCurrentDropHandler(findDragTarget); + + handleDragEnter(target, mediator); + } else if (findDragTarget != null) { + handleDragOver(target, mediator); + } + // prevent text selection on IE + event.getNativeEvent().preventDefault(); + return true; + } + return false; + } + + /** + * Handles drag enter on new element. + * + * @param mediator + * VDragAndDropManager data accessor + * @param target + * target element over which DnD event has happened + */ + protected void handleDragEnter(Element target, DDManagerMediator mediator) { + VDragAndDropManager manager = mediator.getManager(); + if (manager.getCurrentDropHandler() != null) { + mediator.getDragEvent().setElementOver(target); + manager.getCurrentDropHandler().dragEnter(mediator.getDragEvent()); + } + } + + /** + * Handles drag over on element. + * + * @param mediator + * VDragAndDropManager data accessor + * @param target + * target element over which DnD event has happened + */ + protected void handleDragOver(Element target, DDManagerMediator mediator) { + mediator.getDragEvent().setElementOver(target); + mediator.getManager().getCurrentDropHandler() + .dragOver(mediator.getDragEvent()); + } + + /** + * Final phase of event handling. + * + * @param targetElement + * target element over which DnD event has happened + * @param event + * GWT event for active DnD operation + * @param mediator + * VDragAndDropManager data accessor + */ + public void handleEvent(Element targetElement, NativePreviewEvent event, + DDManagerMediator mediator) { + switch (event.getTypeInt()) { + case Event.ONMOUSEOVER: + handleMouseOver(targetElement, event, mediator); + break; + case Event.ONMOUSEOUT: + handleMouseOut(targetElement, event, mediator); + break; + case Event.ONMOUSEMOVE: + case Event.ONTOUCHMOVE: + handleMouseMove(targetElement, event, mediator); + break; + case Event.ONTOUCHEND: + handleTouchEnd(targetElement, event, mediator); + break; + case Event.ONMOUSEUP: + handleMouseUp(targetElement, event, mediator); + break; + } + } + + /** + * Called to handle {@link Event#ONMOUSEMOVE} event. + * + * @param target + * target element over which DnD event has happened + * @param event + * ONMOUSEMOVE GWT event for active DnD operation + * @param mediator + * VDragAndDropManager data accessor + */ + protected void handleMouseMove(Element target, NativePreviewEvent event, + DDManagerMediator mediator) { + VDragAndDropManager manager = mediator.getManager(); + if (manager.getCurrentDropHandler() != null) { + handleDragOver(target, mediator); + } + event.getNativeEvent().preventDefault(); + } + + /** + * Called to handle {@link Event#ONTOUCHEND} event. + * + * @param target + * target element over which DnD event has happened + * @param event + * ONTOUCHEND GWT event for active DnD operation + * @param mediator + * VDragAndDropManager data accessor + */ + protected void handleTouchEnd(Element target, NativePreviewEvent event, + DDManagerMediator mediator) { + /* Avoid simulated event on drag end */ + event.getNativeEvent().preventDefault(); + handleMouseUp(target, event, mediator); + } + + /** + * Called to handle {@link Event#ONMOUSEUP} event. + * + * @param target + * target element over which DnD event has happened + * @param event + * ONMOUSEUP GWT event for active DnD operation + * @param mediator + * VDragAndDropManager data accessor + */ + protected void handleMouseUp(Element target, NativePreviewEvent event, + DDManagerMediator mediator) { + mediator.getManager().endDrag(); + } + + /** + * Called to handle {@link Event#ONMOUSEOUT} event. + * + * @param target + * target element over which DnD event has happened + * @param event + * ONMOUSEOUT GWT event for active DnD operation + * @param mediator + * VDragAndDropManager data accessor + */ + protected void handleMouseOut(Element target, NativePreviewEvent event, + DDManagerMediator mediator) { + VDragAndDropManager manager = mediator.getManager(); + Element relatedTarget = Element.as(event.getNativeEvent() + .getRelatedEventTarget()); + VDropHandler newDragHanler = findDragTarget(relatedTarget, mediator); + if (manager.getDragElement() != null + && manager.getDragElement().isOrHasChild(relatedTarget)) { + // ApplicationConnection.getConsole().log( + // "Mouse out of dragImage, ignored"); + return; + } + + if (manager.getCurrentDropHandler() != newDragHanler) { + handleDragLeave(mediator, true); + manager.setCurrentDropHandler(null); + } + } + + /** + * Handles drag leave on old element. + * + * @param mediator + * VDragAndDropManager data accessor + */ + protected void handleDragLeave(DDManagerMediator mediator, + boolean clearServerCallback) { + VDragAndDropManager manager = mediator.getManager(); + if (manager.getCurrentDropHandler() != null) { + manager.getCurrentDropHandler().dragLeave(mediator.getDragEvent()); + mediator.getDragEvent().getDropDetails().clear(); + if (clearServerCallback) { + mediator.clearServerCallback(); + } + } + } + + /** + * Called to handle {@link Event#ONMOUSEOVER} event. + * + * @param target + * target element over which DnD event has happened + * @param event + * ONMOUSEOVER GWT event for active DnD operation + * @param mediator + * VDragAndDropManager data accessor + */ + protected void handleMouseOver(Element target, NativePreviewEvent event, + DDManagerMediator mediator) { + VDragAndDropManager manager = mediator.getManager(); + VDropHandler dragHandler = findDragTarget(target, mediator); + + if (dragHandler != null + && dragHandler != manager.getCurrentDropHandler()) { + handleDragLeave(mediator, false); + + manager.setCurrentDropHandler(dragHandler); + // ApplicationConnection.getConsole().log( + // "DropHandler now" + // + currentDropHandler.getPaintable()); + handleDragEnter(target, mediator); + } else if (dragHandler == null + && manager.getCurrentDropHandler() != null) { + // ApplicationConnection.getConsole().log("Invalid state!?"); + handleDragLeave(mediator, false); + manager.setCurrentDropHandler(null); + } + } + + /** + * Find drag handler for the {@code target} element. + * + * @param target + * target element over which DnD event has happened + * @param mediator + * VDragAndDropManager data accessor + * @return drop handler of target element + */ + protected VDropHandler findDragTarget(Element target, + DDManagerMediator mediator) { + return mediator.getManager().findDragTarget(target); + } + +} diff --git a/client/src/com/vaadin/client/ui/dd/VDragAndDropManager.java b/client/src/com/vaadin/client/ui/dd/VDragAndDropManager.java index 47f8eb1b66..19004cfaa9 100644 --- a/client/src/com/vaadin/client/ui/dd/VDragAndDropManager.java +++ b/client/src/com/vaadin/client/ui/dd/VDragAndDropManager.java @@ -23,9 +23,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.event.dom.client.KeyCodes; import com.google.gwt.event.shared.HandlerRegistration; import com.google.gwt.user.client.Command; import com.google.gwt.user.client.Event; @@ -61,183 +59,98 @@ public class VDragAndDropManager { public static final String ACTIVE_DRAG_SOURCE_STYLENAME = "v-active-drag-source"; + /** + * Implementation if this interface is provided as a parameter to + * DDEventHandleStrategy methods. The mediator instance allows to manage + * DnD. + */ + public interface DDManagerMediator { + /** + * Returns DnD manager instance. + */ + VDragAndDropManager getManager(); + + /** + * Returns current drag event. + */ + VDragEvent getDragEvent(); + + /** + * Clean up server communication callback. + */ + void clearServerCallback(); + } + private final class DefaultDragAndDropEventHandler implements NativePreviewHandler { @Override public void onPreviewNativeEvent(NativePreviewEvent event) { - NativeEvent nativeEvent = event.getNativeEvent(); + if (getEventHandleStrategy().isDragInterrupted(event, + managerMediator)) { + // end drag if ESC is hit + interruptDrag(); + event.cancel(); + event.getNativeEvent().preventDefault(); + return; + } int typeInt = event.getTypeInt(); if (typeInt == Event.ONKEYDOWN) { - int keyCode = event.getNativeEvent().getKeyCode(); - if (keyCode == KeyCodes.KEY_ESCAPE) { - // end drag if ESC is hit - interruptDrag(); - event.cancel(); - event.getNativeEvent().preventDefault(); - } - // no use for handling for any key down event + getEventHandleStrategy().handleKeyDownEvent(event, + managerMediator); return; } + NativeEvent nativeEvent = event.getNativeEvent(); currentDrag.setCurrentGwtEvent(nativeEvent); - updateDragImagePosition(); - - Node targetNode = Node.as(nativeEvent.getEventTarget()); - Element targetElement; - if (Element.is(targetNode)) { - targetElement = Element.as(targetNode); - } else { - targetElement = targetNode.getParentElement(); - } - - if (WidgetUtil.isTouchEvent(nativeEvent) || dragElement != null) { - // to detect the "real" target, hide dragelement temporary and - // use elementFromPoint - String display = dragElement.getStyle().getDisplay(); - dragElement.getStyle().setDisplay(Display.NONE); - try { - int x = WidgetUtil.getTouchOrMouseClientX(nativeEvent); - int y = WidgetUtil.getTouchOrMouseClientY(nativeEvent); - // Util.browserDebugger(); - targetElement = WidgetUtil.getElementFromPoint(x, y); - if (targetElement == null) { - // ApplicationConnection.getConsole().log( - // "Event on dragImage, ignored"); - event.cancel(); - nativeEvent.stopPropagation(); - return; - - } else { - // ApplicationConnection.getConsole().log( - // "Event on dragImage, target changed"); - // special handling for events over dragImage - // pretty much all events are mousemove althout below - // kind of happens mouseover - switch (typeInt) { - case Event.ONMOUSEOVER: - case Event.ONMOUSEOUT: - // ApplicationConnection - // .getConsole() - // .log( - // "IGNORING proxy image event, fired because of hack or not significant"); - return; - case Event.ONMOUSEMOVE: - case Event.ONTOUCHMOVE: - VDropHandler findDragTarget = findDragTarget(targetElement); - if (findDragTarget != currentDropHandler) { - // dragleave on old - if (currentDropHandler != null) { - currentDropHandler.dragLeave(currentDrag); - currentDrag.getDropDetails().clear(); - serverCallback = null; - } - // dragenter on new - currentDropHandler = findDragTarget; - if (findDragTarget != null) { - // ApplicationConnection.getConsole().log( - // "DropHandler now" - // + currentDropHandler - // .getPaintable()); - } - - if (currentDropHandler != null) { - currentDrag.setElementOver(targetElement); - currentDropHandler.dragEnter(currentDrag); - } - } else if (findDragTarget != null) { - currentDrag.setElementOver(targetElement); - currentDropHandler.dragOver(currentDrag); - } - // prevent text selection on IE - nativeEvent.preventDefault(); - return; - default: - // just update element over and let the actual - // handling code do the thing - // ApplicationConnection.getConsole().log( - // "Target just modified on " - // + event.getType()); - currentDrag.setElementOver(targetElement); - break; - } - - } - } catch (RuntimeException e) { - // ApplicationConnection.getConsole().log( - // "ERROR during elementFromPoint hack."); - throw e; - } finally { - dragElement.getStyle().setProperty("display", display); - } - } - switch (typeInt) { - case Event.ONMOUSEOVER: - VDropHandler target = findDragTarget(targetElement); + String display = getEventHandleStrategy().updateDragImage(event, + managerMediator); - if (target != null && target != currentDropHandler) { - if (currentDropHandler != null) { - currentDropHandler.dragLeave(currentDrag); - currentDrag.getDropDetails().clear(); - } + Element targetElement = getEventHandleStrategy().getTargetElement( + event, managerMediator); - currentDropHandler = target; - // ApplicationConnection.getConsole().log( - // "DropHandler now" - // + currentDropHandler.getPaintable()); - currentDrag.setElementOver(targetElement); - target.dragEnter(currentDrag); - } else if (target == null && currentDropHandler != null) { - // ApplicationConnection.getConsole().log("Invalid state!?"); - currentDropHandler.dragLeave(currentDrag); - currentDrag.getDropDetails().clear(); - currentDropHandler = null; - } - break; - case Event.ONMOUSEOUT: - Element relatedTarget = Element.as(nativeEvent - .getRelatedEventTarget()); - VDropHandler newDragHanler = findDragTarget(relatedTarget); - if (dragElement != null - && dragElement.isOrHasChild(relatedTarget)) { - // ApplicationConnection.getConsole().log( - // "Mouse out of dragImage, ignored"); + try { + if (handleDragImage(targetElement, event)) { return; } - - if (currentDropHandler != null - && currentDropHandler != newDragHanler) { - currentDropHandler.dragLeave(currentDrag); - currentDrag.getDropDetails().clear(); - currentDropHandler = null; - serverCallback = null; - } - break; - case Event.ONMOUSEMOVE: - case Event.ONTOUCHMOVE: - if (currentDropHandler != null) { - currentDrag.setElementOver(targetElement); - currentDropHandler.dragOver(currentDrag); - } - nativeEvent.preventDefault(); - - break; - - case Event.ONTOUCHEND: - /* Avoid simulated event on drag end */ - event.getNativeEvent().preventDefault(); - case Event.ONMOUSEUP: - endDrag(); - break; - - default: - break; + } catch (RuntimeException e) { + // ApplicationConnection.getConsole().log( + // "ERROR during elementFromPoint hack."); + throw e; + } finally { + getEventHandleStrategy().restoreDragImage(display, + managerMediator, event); } + getEventHandleStrategy().handleEvent(targetElement, event, + managerMediator); } + private boolean handleDragImage(Element target, NativePreviewEvent event) { + if (!WidgetUtil.isTouchEvent(event.getNativeEvent()) + && getDragElement() == null) { + return false; + } else if (target == null) { + // ApplicationConnection.getConsole().log( + // "Event on dragImage, ignored"); + event.cancel(); + event.getNativeEvent().stopPropagation(); + return true; + } else if (getEventHandleStrategy().handleDragImageEvent(target, + event, managerMediator)) { + return true; + } else { + // just update element over and let the actual + // handling code do the thing + // ApplicationConnection.getConsole().log( + // "Target just modified on " + // + event.getType()); + currentDrag.setElementOver(target); + return false; + } + } } /* @@ -250,6 +163,26 @@ public class VDragAndDropManager { private HandlerRegistration handlerRegistration; private VDragEvent currentDrag; + private DDManagerMediator managerMediator = new DDManagerMediator() { + + @Override + public VDragAndDropManager getManager() { + return VDragAndDropManager.this; + } + + @Override + public VDragEvent getDragEvent() { + return currentDrag; + } + + @Override + public void clearServerCallback() { + serverCallback = null; + } + }; + + private DDEventHandleStrategy eventHandleStrategy; + /** * If dragging is currently on a drophandler, this field has reference to it */ @@ -456,13 +389,12 @@ public class VDragAndDropManager { return currentDrag; } - private void updateDragImagePosition() { - if (currentDrag.getCurrentGwtEvent() != null && dragElement != null) { - Style style = dragElement.getStyle(); - int clientY = WidgetUtil.getTouchOrMouseClientY(currentDrag - .getCurrentGwtEvent()); - int clientX = WidgetUtil.getTouchOrMouseClientX(currentDrag - .getCurrentGwtEvent()); + protected void updateDragImagePosition(NativeEvent gwtEvent, + Element dragImage) { + if (gwtEvent != null && dragImage != null) { + Style style = dragImage.getStyle(); + int clientY = WidgetUtil.getTouchOrMouseClientY(gwtEvent); + int clientX = WidgetUtil.getTouchOrMouseClientX(gwtEvent); style.setTop(clientY, Unit.PX); style.setLeft(clientX, Unit.PX); } @@ -475,7 +407,7 @@ public class VDragAndDropManager { * @param element * @return */ - private VDropHandler findDragTarget(Element element) { + protected VDropHandler findDragTarget(Element element) { try { Widget w = WidgetUtil.findWidget(element, null); if (w == null) { @@ -565,8 +497,8 @@ public class VDragAndDropManager { } } else { - currentDrag.setCurrentGwtEvent(null); currentDropHandler.dragLeave(currentDrag); + currentDrag.setCurrentGwtEvent(null); } currentDropHandler = null; serverCallback = null; @@ -711,6 +643,21 @@ public class VDragAndDropManager { Profiler.leave("VDragAndDropManager.handleServerResponse"); } + /** + * Returns DnD strategy to handle native preview events used by the manager. + * + * Subclasses can override this method to return custom strategy or use GWT + * deferred binding. + * + * @return internal DnD native preview event handler + */ + protected DDEventHandleStrategy getEventHandleStrategy() { + if (eventHandleStrategy == null) { + eventHandleStrategy = GWT.create(DDEventHandleStrategy.class); + } + return eventHandleStrategy; + } + private void runDeferredCommands() { if (deferredCommand != null) { Command command = deferredCommand; @@ -732,7 +679,8 @@ public class VDragAndDropManager { dragElement = node; dragElement.addClassName("v-drag-element"); - updateDragImagePosition(); + updateDragImagePosition(currentDrag.getCurrentGwtEvent(), + dragElement); if (isStarted) { attachDragElement(); diff --git a/client/src/com/vaadin/client/ui/layout/VLayoutSlot.java b/client/src/com/vaadin/client/ui/layout/VLayoutSlot.java index 50020e51fe..5d463712df 100644 --- a/client/src/com/vaadin/client/ui/layout/VLayoutSlot.java +++ b/client/src/com/vaadin/client/ui/layout/VLayoutSlot.java @@ -69,6 +69,11 @@ public abstract class VLayoutSlot { public void setAlignment(AlignmentInfo alignment) { this.alignment = alignment; + // if alignment is something other than topLeft then we need to align + // the component inside this slot + if (alignment != null && (!alignment.isLeft() || !alignment.isTop())) { + widget.getElement().getStyle().setPosition(Position.ABSOLUTE); + } } public void positionHorizontally(double currentLocation, @@ -109,11 +114,7 @@ public abstract class VLayoutSlot { style.clearMarginRight(); } - if (isRelativeWidth()) { - style.setPropertyPx("width", (int) availableWidth); - } else { - style.clearProperty("width"); - } + style.setPropertyPx("width", (int) availableWidth); double allocatedContentWidth = 0; if (isRelativeWidth()) { @@ -124,6 +125,8 @@ public abstract class VLayoutSlot { reportActualRelativeWidth(Math.round((float) allocatedContentWidth)); } + style.setLeft(Math.round(currentLocation), Unit.PX); + double padding = 0; AlignmentInfo alignment = getAlignment(); if (!alignment.isLeft()) { double usedWidth; @@ -133,25 +136,26 @@ public abstract class VLayoutSlot { usedWidth = getWidgetWidth(); } if (alignment.isHorizontalCenter()) { - currentLocation += (allocatedSpace - usedWidth) / 2d; + padding = (allocatedSpace - usedWidth) / 2d; if (captionAboveCompnent) { captionStyle.setLeft( Math.round(usedWidth - captionWidth) / 2, Unit.PX); } } else { - currentLocation += (allocatedSpace - usedWidth); + padding = (allocatedSpace - usedWidth); if (captionAboveCompnent) { captionStyle.setLeft(Math.round(usedWidth - captionWidth), Unit.PX); } } + widget.getElement().getStyle() + .setLeft(Math.round(padding), Unit.PX); } else { if (captionAboveCompnent) { captionStyle.setLeft(0, Unit.PX); } } - style.setLeft(Math.round(currentLocation), Unit.PX); } private double parsePercent(String size) { @@ -184,11 +188,7 @@ public abstract class VLayoutSlot { style.clearMarginBottom(); } - if (isRelativeHeight()) { - style.setHeight(contentHeight, Unit.PX); - } else { - style.clearHeight(); - } + style.setHeight(contentHeight, Unit.PX); double allocatedContentHeight = 0; if (isRelativeHeight()) { @@ -199,6 +199,8 @@ public abstract class VLayoutSlot { .round((float) allocatedContentHeight)); } + style.setTop(currentLocation, Unit.PX); + double padding = 0; AlignmentInfo alignment = getAlignment(); if (!alignment.isTop()) { double usedHeight; @@ -208,13 +210,14 @@ public abstract class VLayoutSlot { usedHeight = getUsedHeight(); } if (alignment.isVerticalCenter()) { - currentLocation += (allocatedSpace - usedHeight) / 2d; + padding = (allocatedSpace - usedHeight) / 2d; } else { - currentLocation += (allocatedSpace - usedHeight); + padding = (allocatedSpace - usedHeight); } - } + padding += captionHeight; - style.setTop(currentLocation, Unit.PX); + widget.getElement().getStyle().setTop(padding, Unit.PX); + } } protected void reportActualRelativeHeight(int allocatedHeight) { diff --git a/client/src/com/vaadin/client/widgets/Grid.java b/client/src/com/vaadin/client/widgets/Grid.java index 9efea31d02..77bddb281f 100644 --- a/client/src/com/vaadin/client/widgets/Grid.java +++ b/client/src/com/vaadin/client/widgets/Grid.java @@ -2246,14 +2246,33 @@ public class Grid<T> extends ResizeComposite implements public final class SelectionColumn extends Column<Boolean, T> { private boolean initDone = false; + private boolean selected = false; SelectionColumn(final Renderer<Boolean> selectColumnRenderer) { super(selectColumnRenderer); } void initDone() { + addSelectAllToDefaultHeader(); + + setWidth(-1); + + setEditable(false); + + initDone = true; + } + + protected void addSelectAllToDefaultHeader() { if (getSelectionModel() instanceof SelectionModel.Multi && header.getDefaultRow() != null) { + // If selection cell already contains a widget do not + // create a new CheckBox + HeaderCell selectionCell = header.getDefaultRow().getCell(this); + if (selectionCell.getType() + .equals(GridStaticCellType.WIDGET) + && selectionCell.getWidget() instanceof CheckBox) { + return; + } /* * TODO: Currently the select all check box is shown when multi * selection is in use. This might result in malfunctions if no @@ -2270,19 +2289,18 @@ public class Grid<T> extends ResizeComposite implements public void onValueChange(ValueChangeEvent<Boolean> event) { if (event.getValue()) { fireEvent(new SelectAllEvent<T>(model)); + selected = true; } else { model.deselectAll(); + selected = false; } } }); - header.getDefaultRow().getCell(this).setWidget(checkBox); - } + checkBox.setValue(selected); - setWidth(-1); - - setEditable(false); + selectionCell.setWidget(checkBox); - initDone = true; + } } @Override @@ -4834,27 +4852,34 @@ public class Grid<T> extends ResizeComposite implements final StaticSection.StaticCell metadata = staticRow .getCell(columns.get(cell.getColumn())); + boolean updateCellData = true; // Decorate default row with sorting indicators if (staticRow instanceof HeaderRow) { addSortingIndicatorsToHeaderRow((HeaderRow) staticRow, cell); + + if (isHeaderSelectionColumn(row, cell)) { + updateCellData = false; + } } // Assign colspan to cell before rendering cell.setColSpan(metadata.getColspan()); TableCellElement element = cell.getElement(); - switch (metadata.getType()) { - case TEXT: - element.setInnerText(metadata.getText()); - break; - case HTML: - element.setInnerHTML(metadata.getHtml()); - break; - case WIDGET: - preDetach(row, Arrays.asList(cell)); - element.setInnerHTML(""); - postAttach(row, Arrays.asList(cell)); - break; + if (updateCellData) { + switch (metadata.getType()) { + case TEXT: + element.setInnerText(metadata.getText()); + break; + case HTML: + element.setInnerHTML(metadata.getHtml()); + break; + case WIDGET: + preDetach(row, Arrays.asList(cell)); + element.setInnerHTML(""); + postAttach(row, Arrays.asList(cell)); + break; + } } setCustomStyleName(element, metadata.getStyleName()); @@ -4914,6 +4939,27 @@ public class Grid<T> extends ResizeComposite implements @Override public void preAttach(Row row, Iterable<FlyweightCell> cellsToAttach) { + // Add select all checkbox if needed on rebuild. + for (FlyweightCell cell : cellsToAttach) { + if (isHeaderSelectionColumn(row, cell)) { + selectionColumn.addSelectAllToDefaultHeader(); + } + } + } + + /** + * Check if selectionColumn in the default header row + */ + private boolean isHeaderSelectionColumn(Row row, FlyweightCell cell) { + return selectionColumn != null && isDefaultHeaderRow(row) + && getColumn(cell.getColumn()).equals(selectionColumn); + } + + /** + * Row is the default header row. + */ + private boolean isDefaultHeaderRow(Row row) { + return section.getRow(row.getRow()).equals(header.getDefaultRow()); } @Override |