diff options
author | Artur Signell <artur@vaadin.com> | 2015-01-13 22:47:47 +0200 |
---|---|---|
committer | Artur Signell <artur@vaadin.com> | 2015-01-13 22:47:47 +0200 |
commit | a264cdf59106360c250af73d93a25d7c7a3b1542 (patch) | |
tree | 9479177a1b36a432c4e90b994e3eb0139f4bec58 | |
parent | dd116c6495de1caab73fe350acae876bd9380e96 (diff) | |
parent | 8a544b5a6e78337b24a5e56bcde1a21ff6087fae (diff) | |
download | vaadin-framework-a264cdf59106360c250af73d93a25d7c7a3b1542.tar.gz vaadin-framework-a264cdf59106360c250af73d93a25d7c7a3b1542.zip |
Merge remote-tracking branch 'origin/grid' into 7.4
41 files changed, 1291 insertions, 181 deletions
diff --git a/WebContent/VAADIN/themes/reindeer/progressindicator/img/base-static.gif b/WebContent/VAADIN/themes/reindeer/progressindicator/img/base-static.gif Binary files differnew file mode 100644 index 0000000000..474b684196 --- /dev/null +++ b/WebContent/VAADIN/themes/reindeer/progressindicator/img/base-static.gif diff --git a/WebContent/VAADIN/themes/reindeer/progressindicator/progressindicator.scss b/WebContent/VAADIN/themes/reindeer/progressindicator/progressindicator.scss index 52e4239752..2417202828 100644 --- a/WebContent/VAADIN/themes/reindeer/progressindicator/progressindicator.scss +++ b/WebContent/VAADIN/themes/reindeer/progressindicator/progressindicator.scss @@ -11,4 +11,10 @@ background: #f7f9f9 url(img/progress.png); } -}
\ No newline at end of file +// Static style + +.#{$primaryStyleName}-static .#{$primaryStyleName}-wrapper { + background: #dfe2e4 url(img/base-static.gif) repeat-x; +} + +} diff --git a/WebContent/VAADIN/themes/runo/progressindicator/img/base-static.gif b/WebContent/VAADIN/themes/runo/progressindicator/img/base-static.gif Binary files differnew file mode 100644 index 0000000000..474b684196 --- /dev/null +++ b/WebContent/VAADIN/themes/runo/progressindicator/img/base-static.gif diff --git a/WebContent/VAADIN/themes/runo/progressindicator/progressindicator.scss b/WebContent/VAADIN/themes/runo/progressindicator/progressindicator.scss index 9664a473b2..432123cf1f 100644 --- a/WebContent/VAADIN/themes/runo/progressindicator/progressindicator.scss +++ b/WebContent/VAADIN/themes/runo/progressindicator/progressindicator.scss @@ -20,4 +20,10 @@ background: #dfe2e4; } -}
\ No newline at end of file +// Static style + +.#{$primaryStyleName}-static .#{$primaryStyleName}-wrapper { + background: #dfe2e4 url(img/base-static.gif) repeat-x; +} + +} diff --git a/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/ServerRpcVisitor.java b/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/ServerRpcVisitor.java index a1852d5b32..86ece28041 100644 --- a/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/ServerRpcVisitor.java +++ b/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/ServerRpcVisitor.java @@ -24,6 +24,7 @@ import com.google.gwt.core.ext.typeinfo.JClassType; import com.google.gwt.core.ext.typeinfo.JMethod; import com.google.gwt.core.ext.typeinfo.JType; import com.vaadin.client.metadata.TypeDataStore.MethodAttribute; +import com.vaadin.shared.annotations.NoLoadingIndicator; import com.vaadin.shared.annotations.Delayed; public class ServerRpcVisitor extends TypeVisitor { @@ -51,6 +52,11 @@ public class ServerRpcVisitor extends TypeVisitor { } } + if (method.getAnnotation(NoLoadingIndicator.class) != null) { + bundle.setMethodAttribute(type, method, + MethodAttribute.NO_LOADING_INDICATOR); + } + bundle.setNeedsParamTypes(type, method); JType[] parameterTypes = method.getParameterTypes(); diff --git a/client/src/com/vaadin/client/ApplicationConnection.java b/client/src/com/vaadin/client/ApplicationConnection.java index aa00516feb..6abaf28eda 100644 --- a/client/src/com/vaadin/client/ApplicationConnection.java +++ b/client/src/com/vaadin/client/ApplicationConnection.java @@ -81,6 +81,7 @@ import com.vaadin.client.metadata.NoDataException; import com.vaadin.client.metadata.Property; import com.vaadin.client.metadata.Type; import com.vaadin.client.metadata.TypeData; +import com.vaadin.client.metadata.TypeDataStore; import com.vaadin.client.ui.AbstractComponentConnector; import com.vaadin.client.ui.AbstractConnector; import com.vaadin.client.ui.FontIcon; @@ -1275,7 +1276,6 @@ public class ApplicationConnection implements HasHandlers { } hasActiveRequest = true; requestStartTime = new Date(); - loadingIndicator.trigger(); eventBus.fireEvent(new RequestStartingEvent(this)); } @@ -1300,7 +1300,8 @@ public class ApplicationConnection implements HasHandlers { Scheduler.get().scheduleDeferred(new Command() { @Override public void execute() { - if (!hasActiveRequest()) { + if (!isApplicationRunning() + || !(hasActiveRequest() || deferredSendPending)) { getLoadingIndicator().hide(); // If on Liferay and session expiration management is in @@ -2720,8 +2721,8 @@ public class ApplicationConnection implements HasHandlers { * */ public void sendPendingVariableChanges() { - if (!deferedSendPending) { - deferedSendPending = true; + if (!deferredSendPending) { + deferredSendPending = true; Scheduler.get().scheduleFinally(sendPendingCommand); } } @@ -2729,11 +2730,11 @@ public class ApplicationConnection implements HasHandlers { private final ScheduledCommand sendPendingCommand = new ScheduledCommand() { @Override public void execute() { - deferedSendPending = false; + deferredSendPending = false; doSendPendingVariableChanges(); } }; - private boolean deferedSendPending = false; + private boolean deferredSendPending = false; private void doSendPendingVariableChanges() { if (isApplicationRunning()) { @@ -2768,7 +2769,7 @@ public class ApplicationConnection implements HasHandlers { */ private void buildAndSendVariableBurst( LinkedHashMap<String, MethodInvocation> pendingInvocations) { - + boolean showLoadingIndicator = false; JsonArray reqJson = Json.createArray(); if (!pendingInvocations.isEmpty()) { if (ApplicationConfiguration.isDebugMode()) { @@ -2791,10 +2792,16 @@ public class ApplicationConnection implements HasHandlers { Method method = type.getMethod(invocation .getMethodName()); parameterTypes = method.getParameterTypes(); + + showLoadingIndicator |= !TypeDataStore + .isNoLoadingIndicator(method); } catch (NoDataException e) { throw new RuntimeException("No type data for " + invocation.toString(), e); } + } else { + // Always show loading indicator for legacy requests + showLoadingIndicator = true; } for (int i = 0; i < invocation.getParameters().length; ++i) { @@ -2826,6 +2833,9 @@ public class ApplicationConnection implements HasHandlers { getConfiguration().setWidgetsetVersionSent(); } + if (showLoadingIndicator) { + getLoadingIndicator().trigger(); + } makeUidlRequest(reqJson, extraParams); } diff --git a/client/src/com/vaadin/client/JavaScriptConnectorHelper.java b/client/src/com/vaadin/client/JavaScriptConnectorHelper.java index 11511f9c36..3a9a6198d3 100644 --- a/client/src/com/vaadin/client/JavaScriptConnectorHelper.java +++ b/client/src/com/vaadin/client/JavaScriptConnectorHelper.java @@ -50,7 +50,7 @@ public class JavaScriptConnectorHelper { private JavaScriptObject connectorWrapper; private int tag; - private boolean inited = false; + private String initFunctionName; public JavaScriptConnectorHelper(ServerConnector connector) { this.connector = connector; @@ -96,9 +96,8 @@ public class JavaScriptConnectorHelper { } // Init after setting up callbacks & rpc - if (!inited) { + if (initFunctionName == null) { initJavaScript(); - inited = true; } invokeIfPresent(wrapper, "onStateChange"); @@ -120,7 +119,7 @@ public class JavaScriptConnectorHelper { return object; } - private boolean initJavaScript() { + protected boolean initJavaScript() { ApplicationConfiguration conf = connector.getConnection() .getConfiguration(); ArrayList<String> attemptedNames = new ArrayList<String>(); @@ -132,6 +131,7 @@ public class JavaScriptConnectorHelper { if (tryInitJs(initFunctionName, getConnectorWrapper())) { VConsole.log("JavaScript connector initialized using " + initFunctionName); + this.initFunctionName = initFunctionName; return true; } else { VConsole.log("No JavaScript function " + initFunctionName @@ -160,7 +160,7 @@ public class JavaScriptConnectorHelper { } }-*/; - private JavaScriptObject getConnectorWrapper() { + public JavaScriptObject getConnectorWrapper() { if (connectorWrapper == null) { connectorWrapper = createConnectorWrapper(this, connector.getConnection(), nativeState, rpcMap, @@ -465,4 +465,7 @@ public class JavaScriptConnectorHelper { } }-*/; + public String getInitFunctionName() { + return initFunctionName; + } } diff --git a/client/src/com/vaadin/client/VLoadingIndicator.java b/client/src/com/vaadin/client/VLoadingIndicator.java index e873005d3a..7c7edeb04f 100644 --- a/client/src/com/vaadin/client/VLoadingIndicator.java +++ b/client/src/com/vaadin/client/VLoadingIndicator.java @@ -154,6 +154,18 @@ public class VLoadingIndicator { } /** + * Triggers displaying of this loading indicator unless it's already visible + * or scheduled to be shown after a delay. + * + * @since 7.4 + */ + public void ensureTriggered() { + if (!isVisible() && !firstTimer.isRunning()) { + trigger(); + } + } + + /** * Shows the loading indicator in its standard state and triggers timers for * transitioning into the "second" and "third" states. */ diff --git a/client/src/com/vaadin/client/connectors/GridConnector.java b/client/src/com/vaadin/client/connectors/GridConnector.java index 450df31b36..a2e63fc397 100644 --- a/client/src/com/vaadin/client/connectors/GridConnector.java +++ b/client/src/com/vaadin/client/connectors/GridConnector.java @@ -160,12 +160,13 @@ public class GridConnector extends AbstractHasComponentsConnector implements public Object getValue(final JsonObject obj) { final JsonObject rowData = obj.getObject(GridState.JSONKEY_DATA); - assert rowData.hasKey(id) : "Could not find data for column with id " - + id; + if (rowData.hasKey(id)) { + final JsonValue columnValue = rowData.get(id); - final JsonValue columnValue = rowData.get(id); + return rendererConnector.decode(columnValue); + } - return rendererConnector.decode(columnValue); + return null; } /* @@ -202,19 +203,8 @@ public class GridConnector extends AbstractHasComponentsConnector implements @Override public void bind(final int rowIndex) { - /* - * Because most shared state handling is deferred, we must - * defer this too to ensure the editorConnector references - * in shared state are up to date before opening the editor. - * Yes, this is a hack on top of a hack. - */ - Scheduler.get().scheduleDeferred(new ScheduledCommand() { - @Override - public void execute() { - serverInitiated = true; - GridConnector.this.getWidget().editRow(rowIndex); - } - }); + serverInitiated = true; + GridConnector.this.getWidget().editRow(rowIndex); } @Override @@ -225,15 +215,8 @@ public class GridConnector extends AbstractHasComponentsConnector implements @Override public void confirmBind() { - /* - * See comment in bind() - */ - Scheduler.get().scheduleDeferred(new ScheduledCommand() { - @Override - public void execute() { - endRequest(); - } - }); + endRequest(); + } @Override @@ -382,17 +365,33 @@ public class GridConnector extends AbstractHasComponentsConnector implements registerRpc(GridClientRpc.class, new GridClientRpc() { @Override public void scrollToStart() { - getWidget().scrollToStart(); + Scheduler.get().scheduleFinally(new ScheduledCommand() { + @Override + public void execute() { + getWidget().scrollToStart(); + } + }); } @Override public void scrollToEnd() { - getWidget().scrollToEnd(); + Scheduler.get().scheduleFinally(new ScheduledCommand() { + @Override + public void execute() { + getWidget().scrollToEnd(); + } + }); } @Override - public void scrollToRow(int row, ScrollDestination destination) { - getWidget().scrollToRow(row, destination); + public void scrollToRow(final int row, + final ScrollDestination destination) { + Scheduler.get().scheduleFinally(new ScheduledCommand() { + @Override + public void execute() { + getWidget().scrollToRow(row, destination); + } + }); } }); @@ -447,62 +446,42 @@ public class GridConnector extends AbstractHasComponentsConnector implements updateSelectionFromState(); } - /* - * The operations in here have been made deferred. - * - * The row data needed to react to column changes comes in the RPC - * calls. Since state is always updated before RPCs are called, we need - * to be sure that RPC is called before Grid reacts to state changes. - * - * Note that there are still some methods annotated with @OnStateChange - * that aren't deferred. That's okay, though. - */ - - Scheduler.get().scheduleDeferred(new ScheduledCommand() { - @Override - public void execute() { - // Column updates - if (stateChangeEvent.hasPropertyChanged("columns")) { - - // Remove old columns - purgeRemovedColumns(); - - // Add new columns - for (GridColumnState state : getState().columns) { - if (!columnIdToColumn.containsKey(state.id)) { - addColumnFromStateChangeEvent(state); - } - updateColumnFromState(columnIdToColumn.get(state.id), - state); - } - } + // Column updates + if (stateChangeEvent.hasPropertyChanged("columns")) { - if (stateChangeEvent.hasPropertyChanged("columnOrder")) { - if (orderNeedsUpdate(getState().columnOrder)) { - updateColumnOrderFromState(getState().columnOrder); - } - } + // Remove old columns + purgeRemovedColumns(); - if (stateChangeEvent.hasPropertyChanged("header")) { - updateHeaderFromState(getState().header); + // Add new columns + for (GridColumnState state : getState().columns) { + if (!columnIdToColumn.containsKey(state.id)) { + addColumnFromStateChangeEvent(state); } + updateColumnFromState(columnIdToColumn.get(state.id), state); + } + } - if (stateChangeEvent.hasPropertyChanged("footer")) { - updateFooterFromState(getState().footer); - } + if (stateChangeEvent.hasPropertyChanged("columnOrder")) { + if (orderNeedsUpdate(getState().columnOrder)) { + updateColumnOrderFromState(getState().columnOrder); + } + } - if (stateChangeEvent.hasPropertyChanged("editorEnabled")) { - getWidget().setEditorEnabled(getState().editorEnabled); - } + if (stateChangeEvent.hasPropertyChanged("header")) { + updateHeaderFromState(getState().header); + } - if (stateChangeEvent.hasPropertyChanged("frozenColumnCount")) { - getWidget().setFrozenColumnCount( - getState().frozenColumnCount); - } + if (stateChangeEvent.hasPropertyChanged("footer")) { + updateFooterFromState(getState().footer); + } - } - }); + if (stateChangeEvent.hasPropertyChanged("editorEnabled")) { + getWidget().setEditorEnabled(getState().editorEnabled); + } + if (stateChangeEvent.hasPropertyChanged("frozenColumnCount")) { + getWidget().setFrozenColumnCount(getState().frozenColumnCount); + } } private void updateColumnOrderFromState(List<String> stateColumnOrder) { diff --git a/client/src/com/vaadin/client/connectors/JavaScriptRendererConnector.java b/client/src/com/vaadin/client/connectors/JavaScriptRendererConnector.java new file mode 100644 index 0000000000..a7036342f0 --- /dev/null +++ b/client/src/com/vaadin/client/connectors/JavaScriptRendererConnector.java @@ -0,0 +1,278 @@ +/* + * 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.connectors; + +import java.util.ArrayList; +import java.util.Collection; + +import com.google.gwt.core.client.JavaScriptObject; +import com.google.gwt.core.client.JsArrayString; +import com.google.gwt.dom.client.NativeEvent; +import com.vaadin.client.BrowserInfo; +import com.vaadin.client.JavaScriptConnectorHelper; +import com.vaadin.client.Util; +import com.vaadin.client.communication.HasJavaScriptConnectorHelper; +import com.vaadin.client.renderers.ComplexRenderer; +import com.vaadin.client.renderers.Renderer; +import com.vaadin.client.widget.grid.CellReference; +import com.vaadin.client.widget.grid.RendererCellReference; +import com.vaadin.shared.JavaScriptExtensionState; +import com.vaadin.shared.ui.Connect; +import com.vaadin.ui.renderer.AbstractJavaScriptRenderer; + +import elemental.json.JsonObject; +import elemental.json.JsonValue; + +/** + * Connector for server-side renderer implemented using JavaScript. + * + * @since 7.4 + * @author Vaadin Ltd + */ +@Connect(AbstractJavaScriptRenderer.class) +public class JavaScriptRendererConnector extends + AbstractRendererConnector<JsonValue> implements + HasJavaScriptConnectorHelper { + private final JavaScriptConnectorHelper helper = new JavaScriptConnectorHelper( + this); + + private final JavaScriptObject cellReferenceWrapper = createCellReferenceWrapper(BrowserInfo + .get().isIE8()); + + @Override + protected void init() { + super.init(); + helper.init(); + + addGetRowKey(helper.getConnectorWrapper()); + } + + private static native JavaScriptObject createCellReferenceWrapper( + boolean isIE8) + /*-{ + var reference = {}; + if (isIE8) { + // IE8 only supports defineProperty for DOM objects + reference = $doc.createElement('div'); + } + + var setProperty = function(name, getter, setter) { + var descriptor = { + get: getter + } + if (setter) { + descriptor.set = setter; + } + Object.defineProperty(reference, name, descriptor); + }; + + setProperty("element", function() { + return reference.target.@CellReference::getElement()(); + }, null); + + setProperty("rowIndex", function() { + return reference.target.@CellReference::getRowIndex()(); + }, null); + + setProperty("columnIndex", function() { + return reference.target.@CellReference::getColumnIndex()(); + }, null); + + setProperty("colSpan", function() { + return reference.target.@RendererCellReference::getColSpan()(); + }, function(colSpan) { + reference.target.@RendererCellReference::setColSpan(*)(colSpan); + }); + + return reference; + }-*/; + + @Override + public JavaScriptExtensionState getState() { + return (JavaScriptExtensionState) super.getState(); + } + + private native void addGetRowKey(JavaScriptObject wrapper) + /*-{ + var self = this; + wrapper.getRowKey = $entry(function(rowIndex) { + return @JavaScriptRendererConnector::findRowKey(*)(self, rowIndex); + }); + }-*/; + + private static String findRowKey(JavaScriptRendererConnector connector, + int rowIndex) { + GridConnector gc = (GridConnector) connector.getParent(); + JsonObject row = gc.getWidget().getDataSource().getRow(rowIndex); + return connector.getRowKey(row); + } + + private boolean hasFunction(String name) { + return hasFunction(helper.getConnectorWrapper(), name); + } + + private static native boolean hasFunction(JavaScriptObject wrapper, + String name) + /*-{ + return typeof wrapper[name] === 'function'; + }-*/; + + @Override + protected Renderer<JsonValue> createRenderer() { + if (!hasFunction("render")) { + throw new RuntimeException("JavaScriptRenderer " + + helper.getInitFunctionName() + + " must have a function named 'render'"); + } + + final boolean hasInit = hasFunction("init"); + final boolean hasDestroy = hasFunction("destroy"); + final boolean hasOnActivate = hasFunction("onActivate"); + final boolean hasGetConsumedEvents = hasFunction("getConsumedEvents"); + final boolean hasOnBrowserEvent = hasFunction("onBrowserEvent"); + + return new ComplexRenderer<JsonValue>() { + @Override + public void render(RendererCellReference cell, JsonValue data) { + render(helper.getConnectorWrapper(), getJsCell(cell), + Util.json2jso(data)); + } + + private JavaScriptObject getJsCell(CellReference<?> cell) { + updateCellReference(cellReferenceWrapper, cell); + return cellReferenceWrapper; + } + + public native void render(JavaScriptObject wrapper, + JavaScriptObject cell, JavaScriptObject data) + /*-{ + wrapper.render(cell, data); + }-*/; + + @Override + public void init(RendererCellReference cell) { + if (hasInit) { + init(helper.getConnectorWrapper(), getJsCell(cell)); + } + } + + private native void init(JavaScriptObject wrapper, + JavaScriptObject cell) + /*-{ + wrapper.init(cell); + }-*/; + + private native void updateCellReference( + JavaScriptObject cellWrapper, CellReference<?> target) + /*-{ + cellWrapper.target = target; + }-*/; + + @Override + public void destroy(RendererCellReference cell) { + if (hasDestroy) { + destory(helper.getConnectorWrapper(), getJsCell(cell)); + } else { + super.destroy(cell); + } + } + + private native void destory(JavaScriptObject wrapper, + JavaScriptObject cell) + /*-{ + wrapper.destory(cell); + }-*/; + + @Override + public boolean onActivate(CellReference<?> cell) { + if (hasOnActivate) { + return onActivate(helper.getConnectorWrapper(), + getJsCell(cell)); + } else { + return super.onActivate(cell); + } + } + + private native boolean onActivate(JavaScriptObject wrapper, + JavaScriptObject cell) + /*-{ + return !!wrapper.onActivate(cell); + }-*/; + + @Override + public Collection<String> getConsumedEvents() { + if (hasGetConsumedEvents) { + JsArrayString events = getConsumedEvents(helper + .getConnectorWrapper()); + + ArrayList<String> list = new ArrayList<String>( + events.length()); + for (int i = 0; i < events.length(); i++) { + list.add(events.get(i)); + } + return list; + } else { + return super.getConsumedEvents(); + } + } + + private native JsArrayString getConsumedEvents( + JavaScriptObject wrapper) + /*-{ + var rawEvents = wrapper.getConsumedEvents(); + var events = []; + for(var i = 0; i < rawEvents.length; i++) { + events[i] = ""+rawEvents[i]; + } + return events; + }-*/; + + @Override + public boolean onBrowserEvent(CellReference<?> cell, + NativeEvent event) { + if (hasOnBrowserEvent) { + return onBrowserEvent(helper.getConnectorWrapper(), + getJsCell(cell), event); + } else { + return super.onBrowserEvent(cell, event); + } + } + + private native boolean onBrowserEvent(JavaScriptObject wrapper, + JavaScriptObject cell, NativeEvent event) + /*-{ + return !!wrapper.onBrowserEvent(cell, event); + }-*/; + }; + } + + @Override + public JsonValue decode(JsonValue value) { + // Let the js logic decode the raw json that the server sent + return value; + } + + @Override + public void onUnregister() { + super.onUnregister(); + helper.onUnregister(); + } + + @Override + public JavaScriptConnectorHelper getJavascriptConnectorHelper() { + return helper; + } +} diff --git a/client/src/com/vaadin/client/connectors/RpcDataSourceConnector.java b/client/src/com/vaadin/client/connectors/RpcDataSourceConnector.java index c46db08553..74c8dfb02f 100644 --- a/client/src/com/vaadin/client/connectors/RpcDataSourceConnector.java +++ b/client/src/com/vaadin/client/connectors/RpcDataSourceConnector.java @@ -104,6 +104,43 @@ public class RpcDataSourceConnector extends AbstractExtensionConnector { rpcProxy.requestRows(firstRowIndex, numberOfRows, cached.getStart(), cached.length()); + + /* + * Show the progress indicator if there is a pending data request + * and some of the visible rows are being requested. The RPC in + * itself will not trigger the indicator since it might just fetch + * some rows in the background to fill the cache. + * + * The indicator will be hidden by the framework when the response + * is received (unless another request is already on its way at that + * point). + */ + if (getRequestedAvailability().intersects( + Range.withLength(firstRowIndex, numberOfRows))) { + getConnection().getLoadingIndicator().ensureTriggered(); + } + } + + @Override + public void ensureAvailability(int firstRowIndex, int numberOfRows) { + super.ensureAvailability(firstRowIndex, numberOfRows); + + /* + * We trigger the indicator already at this point since the actual + * RPC will not be sent right away when waiting for the response to + * a previous request. + * + * Only triggering here would not be enough since the check that + * sets isWaitingForData is deferred. We don't want to trigger the + * loading indicator here if we don't know that there is actually a + * request going on since some other bug might then cause the + * loading indicator to not be hidden. + */ + if (isWaitingForData() + && !Range.withLength(firstRowIndex, numberOfRows) + .isSubsetOf(getCachedRange())) { + getConnection().getLoadingIndicator().ensureTriggered(); + } } @Override diff --git a/client/src/com/vaadin/client/data/AbstractRemoteDataSource.java b/client/src/com/vaadin/client/data/AbstractRemoteDataSource.java index ffd1d4d170..0ad1631e19 100644 --- a/client/src/com/vaadin/client/data/AbstractRemoteDataSource.java +++ b/client/src/com/vaadin/client/data/AbstractRemoteDataSource.java @@ -262,10 +262,19 @@ public abstract class AbstractRemoteDataSource<T> implements DataSource<T> { ensureCoverageCheck(); } + /** + * Gets the row index range that was requested by the previous call to + * {@link #ensureAvailability(int, int)}. + * + * @return the requested availability range + */ + public Range getRequestedAvailability() { + return requestedAvailability; + } + private void checkCacheCoverage() { - if (currentRequestCallback != null) { - // Anyone clearing currentRequestCallback should run this method - // again + if (isWaitingForData()) { + // Anyone clearing the waiting status should run this method again return; } @@ -301,6 +310,17 @@ public abstract class AbstractRemoteDataSource<T> implements DataSource<T> { Profiler.leave("AbstractRemoteDataSource.checkCacheCoverage"); } + /** + * Checks whether this data source is currently waiting for more rows to + * become available. + * + * @return <code>true</code> if waiting for data; otherwise + * <code>false</code> + */ + public boolean isWaitingForData() { + return currentRequestCallback != null; + } + private void discardStaleCacheEntries() { Range[] cacheParition = cached.partitionWith(getMaxCacheRange()); dropFromCache(cacheParition[0]); @@ -378,7 +398,7 @@ public abstract class AbstractRemoteDataSource<T> implements DataSource<T> { Range received = Range.withLength(firstRowIndex, rowData.size()); - if (currentRequestCallback != null) { + if (isWaitingForData()) { cacheStrategy.onDataArrive(Duration.currentTimeMillis() - currentRequestCallback.requestStart, received.length()); diff --git a/client/src/com/vaadin/client/metadata/TypeDataStore.java b/client/src/com/vaadin/client/metadata/TypeDataStore.java index e3db0ccded..46f26f1b25 100644 --- a/client/src/com/vaadin/client/metadata/TypeDataStore.java +++ b/client/src/com/vaadin/client/metadata/TypeDataStore.java @@ -29,7 +29,7 @@ import com.vaadin.shared.annotations.NoLayout; public class TypeDataStore { public static enum MethodAttribute { - DELAYED, LAST_ONLY, NO_LAYOUT; + DELAYED, LAST_ONLY, NO_LAYOUT, NO_LOADING_INDICATOR; } private static final String CONSTRUCTOR_NAME = "!new"; @@ -219,6 +219,10 @@ public class TypeDataStore { return hasMethodAttribute(method, MethodAttribute.DELAYED); } + public static boolean isNoLoadingIndicator(Method method) { + return hasMethodAttribute(method, MethodAttribute.NO_LOADING_INDICATOR); + } + private static boolean hasMethodAttribute(Method method, MethodAttribute attribute) { FastStringSet attributes = get().methodAttributes.get(method diff --git a/client/src/com/vaadin/client/renderers/ProgressBarRenderer.java b/client/src/com/vaadin/client/renderers/ProgressBarRenderer.java index 8e09641cfc..5b2c70d274 100644 --- a/client/src/com/vaadin/client/renderers/ProgressBarRenderer.java +++ b/client/src/com/vaadin/client/renderers/ProgressBarRenderer.java @@ -29,7 +29,9 @@ public class ProgressBarRenderer extends WidgetRenderer<Double, VProgressBar> { @Override public VProgressBar createWidget() { - return GWT.create(VProgressBar.class); + VProgressBar progressBar = GWT.create(VProgressBar.class); + progressBar.addStyleDependentName("static"); + return progressBar; } @Override diff --git a/client/src/com/vaadin/client/widget/grid/RendererCellReference.java b/client/src/com/vaadin/client/widget/grid/RendererCellReference.java index 07ca462293..533eafded6 100644 --- a/client/src/com/vaadin/client/widget/grid/RendererCellReference.java +++ b/client/src/com/vaadin/client/widget/grid/RendererCellReference.java @@ -83,7 +83,7 @@ public class RendererCellReference extends CellReference<Object> { * * @return the number of columns that the cell should span */ - public int getColspan() { + public int getColSpan() { return cell.getColSpan(); } } diff --git a/client/src/com/vaadin/client/widgets/Escalator.java b/client/src/com/vaadin/client/widgets/Escalator.java index deaa9005c3..a4e3846196 100644 --- a/client/src/com/vaadin/client/widgets/Escalator.java +++ b/client/src/com/vaadin/client/widgets/Escalator.java @@ -64,7 +64,6 @@ import com.vaadin.client.widget.escalator.PositionFunction.AbsolutePosition; import com.vaadin.client.widget.escalator.PositionFunction.Translate3DPosition; import com.vaadin.client.widget.escalator.PositionFunction.TranslatePosition; import com.vaadin.client.widget.escalator.PositionFunction.WebkitTranslate3DPosition; -import com.vaadin.client.widget.escalator.Row; import com.vaadin.client.widget.escalator.RowContainer; import com.vaadin.client.widget.escalator.RowVisibilityChangeEvent; import com.vaadin.client.widget.escalator.RowVisibilityChangeHandler; @@ -2184,6 +2183,7 @@ public class Escalator extends Widget implements RequiresResize, DeferredWorker bodyElem.getStyle().setMarginTop(heightOfSection, Unit.PX); verticalScrollbar.getElement().getStyle() .setTop(heightOfSection, Unit.PX); + headerDeco.getStyle().setHeight(heightOfSection, Unit.PX); } @Override @@ -2225,6 +2225,8 @@ public class Escalator extends Widget implements RequiresResize, DeferredWorker vscrollHeight -= horizontalScrollbar.getScrollbarThickness(); } + footerDeco.getStyle().setHeight(footer.heightOfSection, Unit.PX); + verticalScrollbar.setOffsetSize(vscrollHeight); } } @@ -4730,9 +4732,6 @@ public class Escalator extends Widget implements RequiresResize, DeferredWorker body.recalculateSectionHeight(); footer.recalculateSectionHeight(); - headerDeco.getStyle().setHeight(header.heightOfSection, Unit.PX); - footerDeco.getStyle().setHeight(footer.heightOfSection, Unit.PX); - scroller.recalculateScrollbarsForVirtualViewport(); body.verifyEscalatorCount(); Profiler.leave("Escalator.recalculateElementSizes"); diff --git a/server/src/com/vaadin/data/RpcDataProviderExtension.java b/server/src/com/vaadin/data/RpcDataProviderExtension.java index 10857f8d6a..2e10ccfef1 100644 --- a/server/src/com/vaadin/data/RpcDataProviderExtension.java +++ b/server/src/com/vaadin/data/RpcDataProviderExtension.java @@ -404,9 +404,9 @@ public class RpcDataProviderExtension extends AbstractExtension { itemId); valueChangeListeners.put(itemId, listener); - for (final Object propertyId : item.getItemPropertyIds()) { - final Property<?> property = item - .getItemProperty(propertyId); + for (final Column column : getGrid().getColumns()) { + final Property<?> property = item.getItemProperty(column + .getPropertyId()); if (property instanceof ValueChangeNotifier) { ((ValueChangeNotifier) property) .addValueChangeListener(listener); @@ -423,9 +423,9 @@ public class RpcDataProviderExtension extends AbstractExtension { .remove(itemId); if (listener != null) { - for (final Object propertyId : item.getItemPropertyIds()) { + for (final Column column : getGrid().getColumns()) { final Property<?> property = item - .getItemProperty(propertyId); + .getItemProperty(column.getPropertyId()); if (property instanceof ValueChangeNotifier) { ((ValueChangeNotifier) property) .removeValueChangeListener(listener); @@ -436,30 +436,46 @@ public class RpcDataProviderExtension extends AbstractExtension { } /** - * Manages removed properties in active rows. + * Manages removed columns in active rows. + * <p> + * This method does <em>not</em> send data again to the client. * - * @param removedPropertyIds - * the property ids that have been removed from the container + * @param removedColumns + * the columns that have been removed from the grid */ - public void propertiesRemoved( - @SuppressWarnings("unused") Collection<Object> removedPropertyIds) { - /* - * no-op, for now. - * - * The Container should be responsible for cleaning out any - * ValueChangeListeners from removed Properties. Components will - * benefit from this, however. - */ + public void columnsRemoved(Collection<Column> removedColumns) { + if (removedColumns.isEmpty()) { + return; + } + + for (int i = activeRange.getStart(); i < activeRange.getEnd(); i++) { + final Object itemId = container.getIdByIndex(i); + final Item item = container.getItem(itemId); + final GridValueChangeListener listener = valueChangeListeners + .get(itemId); + assert (listener != null) : "a listener should've been pre-made by addValueChangeListeners"; + + for (final Column column : removedColumns) { + final Property<?> property = item.getItemProperty(column + .getPropertyId()); + if (property instanceof ValueChangeNotifier) { + ((ValueChangeNotifier) property) + .removeValueChangeListener(listener); + } + } + } } /** - * Manages added properties in active rows. + * Manages added columns in active rows. + * <p> + * This method sends the data for the changed rows to client side. * - * @param addedPropertyIds - * the property ids that have been added to the container + * @param addedColumns + * the columns that have been added to the grid */ - public void propertiesAdded(Collection<Object> addedPropertyIds) { - if (addedPropertyIds.isEmpty()) { + public void columnsAdded(Collection<Column> addedColumns) { + if (addedColumns.isEmpty()) { return; } @@ -470,9 +486,9 @@ public class RpcDataProviderExtension extends AbstractExtension { .get(itemId); assert (listener != null) : "a listener should've been pre-made by addValueChangeListeners"; - for (final Object propertyId : addedPropertyIds) { - final Property<?> property = item - .getItemProperty(propertyId); + for (final Column column : addedColumns) { + final Property<?> property = item.getItemProperty(column + .getPropertyId()); if (property instanceof ValueChangeNotifier) { ((ValueChangeNotifier) property) .addValueChangeListener(listener); @@ -924,37 +940,24 @@ public class RpcDataProviderExtension extends AbstractExtension { } /** - * Informs this data provider that some of the properties have been removed - * from the container. - * <p> - * Please note that we could add our own - * {@link com.vaadin.data.Container.PropertySetChangeListener - * PropertySetChangeListener} to the container, but then we'd need to - * implement the same bookeeping for finding what's added and removed that - * Grid already does in its own listener. + * Informs this data provider that given columns have been removed from + * grid. * * @param removedColumns - * a list of property ids for the removed columns + * a list of removed columns */ - public void propertiesRemoved(List<Object> removedColumns) { - activeRowHandler.propertiesRemoved(removedColumns); + public void columnsRemoved(List<Column> removedColumns) { + activeRowHandler.columnsRemoved(removedColumns); } /** - * Informs this data provider that some of the properties have been added to - * the container. - * <p> - * Please note that we could add our own - * {@link com.vaadin.data.Container.PropertySetChangeListener - * PropertySetChangeListener} to the container, but then we'd need to - * implement the same bookeeping for finding what's added and removed that - * Grid already does in its own listener. + * Informs this data provider that given columns have been added to grid. * - * @param addedPropertyIds - * a list of property ids for the added columns + * @param addedColumns + * a list of added columns */ - public void propertiesAdded(HashSet<Object> addedPropertyIds) { - activeRowHandler.propertiesAdded(addedPropertyIds); + public void columnsAdded(List<Column> addedColumns) { + activeRowHandler.columnsAdded(addedColumns); } public DataProviderKeyMapper getKeyMapper() { diff --git a/server/src/com/vaadin/server/AbstractJavaScriptExtension.java b/server/src/com/vaadin/server/AbstractJavaScriptExtension.java index e182319c85..e9cf2c5e33 100644 --- a/server/src/com/vaadin/server/AbstractJavaScriptExtension.java +++ b/server/src/com/vaadin/server/AbstractJavaScriptExtension.java @@ -106,8 +106,8 @@ import com.vaadin.ui.JavaScriptFunction; * <li>Java Dates are represented by JavaScript numbers containing the timestamp * </li> * <li>List, Set and all arrays in Java are represented by JavaScript arrays.</li> - * <li>Map<String, ?> in Java is represented by JavaScript object with fields - * corresponding to the map keys.</li> + * <li>Map<String, ?> in Java is represented by JavaScript object with + * fields corresponding to the map keys.</li> * <li>Any other Java Map is represented by a JavaScript array containing two * arrays, the first contains the keys and the second contains the values in the * same order.</li> diff --git a/server/src/com/vaadin/ui/AbstractJavaScriptComponent.java b/server/src/com/vaadin/ui/AbstractJavaScriptComponent.java index f3cbf47b62..84023555bb 100644 --- a/server/src/com/vaadin/ui/AbstractJavaScriptComponent.java +++ b/server/src/com/vaadin/ui/AbstractJavaScriptComponent.java @@ -119,8 +119,8 @@ import com.vaadin.shared.ui.JavaScriptComponentState; * <li>Java Dates are represented by JavaScript numbers containing the timestamp * </li> * <li>List, Set and all arrays in Java are represented by JavaScript arrays.</li> - * <li>Map<String, ?> in Java is represented by JavaScript object with fields - * corresponding to the map keys.</li> + * <li>Map<String, ?> in Java is represented by JavaScript object with + * fields corresponding to the map keys.</li> * <li>Any other Java Map is represented by a JavaScript array containing two * arrays, the first contains the keys and the second contains the values in the * same order.</li> diff --git a/server/src/com/vaadin/ui/Grid.java b/server/src/com/vaadin/ui/Grid.java index 316f7682de..0843fb6ec1 100644 --- a/server/src/com/vaadin/ui/Grid.java +++ b/server/src/com/vaadin/ui/Grid.java @@ -2447,28 +2447,30 @@ public class Grid extends AbstractComponent implements SelectionNotifier, Collection<?> properties = new HashSet<Object>(event.getContainer() .getContainerPropertyIds()); - // Cleanup columns that are no longer in grid - List<Object> removedColumns = new LinkedList<Object>(); - for (Object columnId : columns.keySet()) { - if (!properties.contains(columnId)) { - removedColumns.add(columnId); + // Find columns that need to be removed. + List<Column> removedColumns = new LinkedList<Column>(); + for (Object propertyId : columns.keySet()) { + if (!properties.contains(propertyId)) { + removedColumns.add(getColumn(propertyId)); } } - for (Object columnId : removedColumns) { - removeColumn(columnId); - columnKeys.remove(columnId); + + // Actually remove columns. + for (Column column : removedColumns) { + Object propertyId = column.getPropertyId(); + internalRemoveColumn(propertyId); + columnKeys.remove(propertyId); } - datasourceExtension.propertiesRemoved(removedColumns); + datasourceExtension.columnsRemoved(removedColumns); // Add new columns - HashSet<Object> addedPropertyIds = new HashSet<Object>(); + List<Column> addedColumns = new LinkedList<Column>(); for (Object propertyId : properties) { if (!columns.containsKey(propertyId)) { - appendColumn(propertyId); - addedPropertyIds.add(propertyId); + addedColumns.add(appendColumn(propertyId)); } } - datasourceExtension.propertiesAdded(addedPropertyIds); + datasourceExtension.columnsAdded(addedColumns); if (getFrozenColumnCount() > columns.size()) { setFrozenColumnCount(columns.size()); @@ -2950,7 +2952,14 @@ public class Grid extends AbstractComponent implements SelectionNotifier, } else { addColumnProperty(propertyId, String.class, ""); } - return getColumn(propertyId); + + // Inform the data provider of this new column. + Column column = getColumn(propertyId); + List<Column> addedColumns = new ArrayList<Column>(); + addedColumns.add(column); + datasourceExtension.columnsAdded(addedColumns); + + return column; } /** @@ -3012,10 +3021,12 @@ public class Grid extends AbstractComponent implements SelectionNotifier, * Removes all columns from this Grid. */ public void removeAllColumns() { + List<Column> removed = new ArrayList<Column>(columns.values()); Set<Object> properties = new HashSet<Object>(columns.keySet()); for (Object propertyId : properties) { removeColumn(propertyId); } + datasourceExtension.columnsRemoved(removed); } /** @@ -3093,6 +3104,13 @@ public class Grid extends AbstractComponent implements SelectionNotifier, * The property id of column to be removed */ public void removeColumn(Object propertyId) { + List<Column> removed = new ArrayList<Column>(); + removed.add(getColumn(propertyId)); + internalRemoveColumn(propertyId); + datasourceExtension.columnsRemoved(removed); + } + + private void internalRemoveColumn(Object propertyId) { setEditorField(propertyId, null); header.removeColumn(propertyId); footer.removeColumn(propertyId); @@ -4439,7 +4457,8 @@ public class Grid extends AbstractComponent implements SelectionNotifier, } /** - * Cancels the currently active edit if any. + * Cancels the currently active edit if any. Hides the editor and discards + * possible unsaved changes in the editor fields. */ public void cancelEditor() { if (isEditorActive()) { @@ -4451,6 +4470,7 @@ public class Grid extends AbstractComponent implements SelectionNotifier, protected void doCancelEditor() { editedItemId = null; + editorFieldGroup.discard(); } void resetEditor() { diff --git a/server/src/com/vaadin/ui/renderer/AbstractJavaScriptRenderer.java b/server/src/com/vaadin/ui/renderer/AbstractJavaScriptRenderer.java new file mode 100644 index 0000000000..8fabded536 --- /dev/null +++ b/server/src/com/vaadin/ui/renderer/AbstractJavaScriptRenderer.java @@ -0,0 +1,157 @@ +/* + * 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.ui.renderer; + +import com.vaadin.server.AbstractJavaScriptExtension; +import com.vaadin.server.JavaScriptCallbackHelper; +import com.vaadin.shared.JavaScriptExtensionState; +import com.vaadin.shared.communication.ServerRpc; +import com.vaadin.ui.Grid.AbstractRenderer; +import com.vaadin.ui.JavaScriptFunction; + +/** + * Base class for Renderers with all client-side logic implemented using + * JavaScript. + * <p> + * When a new JavaScript renderer is initialized in the browser, the framework + * will look for a globally defined JavaScript function that will initialize the + * renderer. The name of the initialization function is formed by replacing . + * with _ in the name of the server-side class. If no such function is defined, + * each super class is used in turn until a match is found. The framework will + * thus first attempt with <code>com_example_MyRenderer</code> for the + * server-side + * <code>com.example.MyRenderer extends AbstractJavaScriptRenderer</code> class. + * If MyRenderer instead extends <code>com.example.SuperRenderer</code> , then + * <code>com_example_SuperRenderer</code> will also be attempted if + * <code>com_example_MyRenderer</code> has not been defined. + * <p> + * + * In addition to the general JavaScript extension functionality explained in + * {@link AbstractJavaScriptExtension}, this class also provides some + * functionality specific for renderers. + * <p> + * The initialization function will be called with <code>this</code> pointing to + * a connector wrapper object providing integration to Vaadin with the following + * functions: + * <ul> + * <li><code>getRowKey(rowIndex)</code> - Gets a unique identifier for the row + * at the given index. This identifier can be used on the server to retrieve the + * corresponding ItemId using {@link #getItemId(String)}.</li> + * </ul> + * The connector wrapper also supports these special functions that can be + * implemented by the connector: + * <ul> + * <li><code>render(cell, data)</code> - Callback for rendering the given data + * into the given cell. The structure of cell and data are described in separate + * sections below. The renderer is required to implement this function. + * Corresponds to + * {@link com.vaadin.client.renderers.Renderer#render(com.vaadin.client.widget.grid.RendererCellReference, Object)} + * .</li> + * <li><code>init(cell)</code> - Prepares a cell for rendering. Corresponds to + * {@link com.vaadin.client.renderers.ComplexRenderer#init(com.vaadin.client.widget.grid.RendererCellReference)} + * .</li> + * <li><code>destory(cell)</code> - Allows the renderer to release resources + * allocate for a cell that will no longer be used. Corresponds to + * {@link com.vaadin.client.renderers.ComplexRenderer#destroy(com.vaadin.client.widget.grid.RendererCellReference)} + * .</li> + * <li><code>onActivate(cell)</code> - Called when the cell is activated by the + * user e.g. by double clicking on the cell or pressing enter with the cell + * focused. Corresponds to + * {@link com.vaadin.client.renderers.ComplexRenderer#onActivate(com.vaadin.client.widget.grid.CellReference)} + * .</li> + * <li><code>getConsumedEvents()</code> - Returns a JavaScript array of event + * names that should cause onBrowserEvent to be invoked whenever an event is + * fired for a cell managed by this renderer. Corresponds to + * {@link com.vaadin.client.renderers.ComplexRenderer#getConsumedEvents()}.</li> + * <li><code>onBrowserEvent(cell, event)</code> - Called by Grid when an event + * of a type returned by getConsumedEvents is fired for a cell managed by this + * renderer. Corresponds to + * {@link com.vaadin.client.renderers.ComplexRenderer#onBrowserEvent(com.vaadin.client.widget.grid.CellReference, com.google.gwt.dom.client.NativeEvent)} + * .</li> + * </ul> + * + * <p> + * The cell object passed to functions defined by the renderer has these + * properties: + * <ul> + * <li><code>element</code> - The DOM element corresponding to this cell. + * Readonly.</li> + * <li><code>rowIndex</code> - The current index of the row of this cell. + * Readonly.</li> + * <li><code>columnIndex</code> - The current index of the column of this cell. + * Readonly.</li> + * <li><code>colSpan</code> - The number of columns spanned by this cell. Only + * supported in the object passed to the <code>render</code> function - other + * functions should not use the property. Readable and writable. + * </ul> + * + * @author Vaadin Ltd + * @since 7.4 + */ +public abstract class AbstractJavaScriptRenderer<T> extends AbstractRenderer<T> { + private JavaScriptCallbackHelper callbackHelper = new JavaScriptCallbackHelper( + this); + + protected AbstractJavaScriptRenderer(Class<T> presentationType) { + super(presentationType); + } + + @Override + protected <R extends ServerRpc> void registerRpc(R implementation, + Class<R> rpcInterfaceType) { + super.registerRpc(implementation, rpcInterfaceType); + callbackHelper.registerRpc(rpcInterfaceType); + } + + /** + * Register a {@link JavaScriptFunction} that can be called from the + * JavaScript using the provided name. A JavaScript function with the + * provided name will be added to the connector wrapper object (initially + * available as <code>this</code>). Calling that JavaScript function will + * cause the call method in the registered {@link JavaScriptFunction} to be + * invoked with the same arguments. + * + * @param functionName + * the name that should be used for client-side callback + * @param function + * the {@link JavaScriptFunction} object that will be invoked + * when the JavaScript function is called + */ + protected void addFunction(String functionName, JavaScriptFunction function) { + callbackHelper.registerCallback(functionName, function); + } + + /** + * Invoke a named function that the connector JavaScript has added to the + * JavaScript connector wrapper object. The arguments should only contain + * data types that can be represented in JavaScript including primitives, + * their boxed types, arrays, String, List, Set, Map, Connector and + * JavaBeans. + * + * @param name + * the name of the function + * @param arguments + * function arguments + */ + protected void callFunction(String name, Object... arguments) { + callbackHelper.invokeCallback(name, arguments); + } + + @Override + protected JavaScriptExtensionState getState() { + return (JavaScriptExtensionState) super.getState(); + } +} diff --git a/server/src/com/vaadin/ui/themes/Reindeer.java b/server/src/com/vaadin/ui/themes/Reindeer.java index 6eeebd8a03..e0ab792a15 100644 --- a/server/src/com/vaadin/ui/themes/Reindeer.java +++ b/server/src/com/vaadin/ui/themes/Reindeer.java @@ -15,14 +15,6 @@ */ package com.vaadin.ui.themes; -import com.vaadin.ui.CssLayout; -import com.vaadin.ui.FormLayout; -import com.vaadin.ui.GridLayout; -import com.vaadin.ui.HorizontalLayout; -import com.vaadin.ui.HorizontalSplitPanel; -import com.vaadin.ui.VerticalLayout; -import com.vaadin.ui.VerticalSplitPanel; - public class Reindeer extends BaseTheme { public static final String THEME_NAME = "reindeer"; @@ -90,6 +82,18 @@ public class Reindeer extends BaseTheme { /*************************************************************************** * + * ProgressBar Styles + * + **************************************************************************/ + + /** + * Displays the progress bar with a static background, instead of an + * animated one. + */ + public static final String PROGRESSBAR_STATIC = "static"; + + /*************************************************************************** + * * SplitPanel styles * **************************************************************************/ diff --git a/server/src/com/vaadin/ui/themes/Runo.java b/server/src/com/vaadin/ui/themes/Runo.java index 11f1bae682..6f8d5f37d9 100644 --- a/server/src/com/vaadin/ui/themes/Runo.java +++ b/server/src/com/vaadin/ui/themes/Runo.java @@ -59,6 +59,18 @@ public class Runo extends BaseTheme { /*************************************************************************** * + * ProgressBar Styles + * + **************************************************************************/ + + /** + * Displays the progress bar with a static background, instead of an + * animated one. + */ + public static final String PROGRESSBAR_STATIC = "static"; + + /*************************************************************************** + * * TabSheet styles * **************************************************************************/ diff --git a/server/tests/src/com/vaadin/tests/server/component/grid/GridEditorTest.java b/server/tests/src/com/vaadin/tests/server/component/grid/GridEditorTest.java index c3817efc3f..3e52314fbc 100644 --- a/server/tests/src/com/vaadin/tests/server/component/grid/GridEditorTest.java +++ b/server/tests/src/com/vaadin/tests/server/component/grid/GridEditorTest.java @@ -24,11 +24,14 @@ import static org.junit.Assert.assertTrue; import org.easymock.EasyMock; import org.junit.After; +import org.junit.Assert; import org.junit.Before; import org.junit.Test; import com.vaadin.data.Item; +import com.vaadin.data.Property; import com.vaadin.data.fieldgroup.FieldGroup; +import com.vaadin.data.fieldgroup.FieldGroup.CommitException; import com.vaadin.data.util.IndexedContainer; import com.vaadin.server.MockVaadinSession; import com.vaadin.server.VaadinService; @@ -41,6 +44,8 @@ public class GridEditorTest { private static final Object PROPERTY_NAME = "name"; private static final Object PROPERTY_AGE = "age"; + private static final String DEFAULT_NAME = "Some Valid Name"; + private static final Integer DEFAULT_AGE = 25; private static final Object ITEM_ID = new Object(); private Grid grid; @@ -57,8 +62,8 @@ public class GridEditorTest { Integer.valueOf(-1)); Item item = container.addItem(ITEM_ID); - item.getItemProperty(PROPERTY_NAME).setValue("Some Valid Name"); - item.getItemProperty(PROPERTY_AGE).setValue(Integer.valueOf(25)); + item.getItemProperty(PROPERTY_NAME).setValue(DEFAULT_NAME); + item.getItemProperty(PROPERTY_AGE).setValue(DEFAULT_AGE); grid = new Grid(container); @@ -125,6 +130,57 @@ public class GridEditorTest { public void editItem() throws Exception { startEdit(); assertEquals(ITEM_ID, grid.getEditedItemId()); + assertEquals(getEditedItem(), grid.getEditorFieldGroup() + .getItemDataSource()); + + assertEquals(DEFAULT_NAME, grid.getEditorField(PROPERTY_NAME) + .getValue()); + assertEquals(String.valueOf(DEFAULT_AGE), + grid.getEditorField(PROPERTY_AGE).getValue()); + } + + @Test + public void saveEditor() throws Exception { + startEdit(); + TextField field = (TextField) grid.getEditorField(PROPERTY_NAME); + + field.setValue("New Name"); + assertEquals(DEFAULT_NAME, field.getPropertyDataSource().getValue()); + + grid.saveEditor(); + assertTrue(grid.isEditorActive()); + assertFalse(field.isModified()); + assertEquals("New Name", field.getValue()); + assertEquals("New Name", getEditedProperty(PROPERTY_NAME).getValue()); + } + + @Test + public void saveEditorCommitFail() throws Exception { + startEdit(); + + ((TextField) grid.getEditorField(PROPERTY_AGE)).setValue("Invalid"); + try { + // Manual fail instead of @Test(expected=...) to check it is + // saveEditor that fails and not setValue + grid.saveEditor(); + Assert.fail("CommitException expected when saving an invalid field value"); + } catch (CommitException e) { + // expected + } + } + + @Test + public void cancelEditor() throws Exception { + startEdit(); + TextField field = (TextField) grid.getEditorField(PROPERTY_NAME); + field.setValue("New Name"); + + grid.cancelEditor(); + assertFalse(grid.isEditorActive()); + assertNull(grid.getEditedItemId()); + assertFalse(field.isModified()); + assertEquals(DEFAULT_NAME, field.getValue()); + assertEquals(DEFAULT_NAME, field.getPropertyDataSource().getValue()); } @Test(expected = IllegalArgumentException.class) @@ -206,4 +262,13 @@ public class GridEditorTest { grid.setEditorEnabled(true); grid.editItem(ITEM_ID); } + + private Item getEditedItem() { + assertNotNull(grid.getEditedItemId()); + return grid.getContainerDataSource().getItem(grid.getEditedItemId()); + } + + private Property<?> getEditedProperty(Object propertyId) { + return getEditedItem().getItemProperty(PROPERTY_NAME); + } } diff --git a/shared/src/com/vaadin/shared/annotations/NoLoadingIndicator.java b/shared/src/com/vaadin/shared/annotations/NoLoadingIndicator.java new file mode 100644 index 0000000000..2e519b69e8 --- /dev/null +++ b/shared/src/com/vaadin/shared/annotations/NoLoadingIndicator.java @@ -0,0 +1,35 @@ +/* + * 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.shared.annotations; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Target; + +/** + * Annotation used to mark server RPC methods for which it isn't necessary to + * show the loading indicator. The framework will show a loading indicator when + * sending requests for RPC methods that are not marked with this annotation. + * The loading indicator is hidden once a response is received. + * + * @since 7.4 + * @author Vaadin Ltd + */ +@Target(ElementType.METHOD) +@Documented +public @interface NoLoadingIndicator { + // Just an empty marker annotation +} diff --git a/shared/src/com/vaadin/shared/data/DataRequestRpc.java b/shared/src/com/vaadin/shared/data/DataRequestRpc.java index 773a82fa9a..0d9b919a4e 100644 --- a/shared/src/com/vaadin/shared/data/DataRequestRpc.java +++ b/shared/src/com/vaadin/shared/data/DataRequestRpc.java @@ -16,6 +16,7 @@ package com.vaadin.shared.data; +import com.vaadin.shared.annotations.NoLoadingIndicator; import com.vaadin.shared.annotations.Delayed; import com.vaadin.shared.communication.ServerRpc; @@ -39,6 +40,7 @@ public interface DataRequestRpc extends ServerRpc { * @param cacheSize * the number of cached rows */ + @NoLoadingIndicator public void requestRows(int firstRowIndex, int numberOfRows, int firstCachedRowIndex, int cacheSize); diff --git a/shared/src/com/vaadin/shared/ui/progressindicator/ProgressIndicatorServerRpc.java b/shared/src/com/vaadin/shared/ui/progressindicator/ProgressIndicatorServerRpc.java index dd437094c7..f541395cef 100644 --- a/shared/src/com/vaadin/shared/ui/progressindicator/ProgressIndicatorServerRpc.java +++ b/shared/src/com/vaadin/shared/ui/progressindicator/ProgressIndicatorServerRpc.java @@ -15,8 +15,10 @@ */ package com.vaadin.shared.ui.progressindicator; +import com.vaadin.shared.annotations.NoLoadingIndicator; import com.vaadin.shared.communication.ServerRpc; public interface ProgressIndicatorServerRpc extends ServerRpc { + @NoLoadingIndicator public void poll(); } diff --git a/shared/src/com/vaadin/shared/ui/ui/UIServerRpc.java b/shared/src/com/vaadin/shared/ui/ui/UIServerRpc.java index 8227415e58..887ea760b3 100644 --- a/shared/src/com/vaadin/shared/ui/ui/UIServerRpc.java +++ b/shared/src/com/vaadin/shared/ui/ui/UIServerRpc.java @@ -15,6 +15,7 @@ */ package com.vaadin.shared.ui.ui; +import com.vaadin.shared.annotations.NoLoadingIndicator; import com.vaadin.shared.annotations.Delayed; import com.vaadin.shared.communication.ServerRpc; import com.vaadin.shared.ui.ClickRpc; @@ -27,6 +28,7 @@ public interface UIServerRpc extends ClickRpc, ServerRpc { @Delayed(lastOnly = true) public void scroll(int scrollTop, int scrollLeft); + @NoLoadingIndicator @Delayed(lastOnly = true) /* * @Delayed just to get lastOnly semantics, sendPendingVariableChanges() diff --git a/uitest/src/com/vaadin/tests/components/grid/GridSingleColumn.java b/uitest/src/com/vaadin/tests/components/grid/GridSingleColumn.java index e9987db1a8..2ab0282102 100644 --- a/uitest/src/com/vaadin/tests/components/grid/GridSingleColumn.java +++ b/uitest/src/com/vaadin/tests/components/grid/GridSingleColumn.java @@ -44,6 +44,7 @@ public class GridSingleColumn extends AbstractTestUI { column.setHeaderCaption("Header"); addComponent(grid); + grid.scrollTo(grid.getContainerDataSource().getIdByIndex(50)); } @Override diff --git a/uitest/src/com/vaadin/tests/components/grid/GridSingleColumnTest.java b/uitest/src/com/vaadin/tests/components/grid/GridSingleColumnTest.java index 05f6b4b9f7..42eb2197bf 100644 --- a/uitest/src/com/vaadin/tests/components/grid/GridSingleColumnTest.java +++ b/uitest/src/com/vaadin/tests/components/grid/GridSingleColumnTest.java @@ -20,6 +20,7 @@ import org.junit.Test; import com.vaadin.testbench.elements.GridElement; import com.vaadin.testbench.elements.GridElement.GridCellElement; +import com.vaadin.testbench.elements.NotificationElement; import com.vaadin.tests.annotations.TestCategory; import com.vaadin.tests.tb3.MultiBrowserTest; @@ -27,11 +28,20 @@ import com.vaadin.tests.tb3.MultiBrowserTest; public class GridSingleColumnTest extends MultiBrowserTest { @Test - public void headerIsVisible() { + public void testHeaderIsVisible() { openTestURL(); GridCellElement cell = $(GridElement.class).first().getHeaderCell(0, 0); Assert.assertTrue("No header available", cell.getText() .equalsIgnoreCase("header")); } + + @Test + public void testScrollDidNotThrow() { + setDebug(true); + openTestURL(); + + Assert.assertFalse("Exception when scrolling on init", + isElementPresent(NotificationElement.class)); + } } diff --git a/uitest/src/com/vaadin/tests/components/grid/JavaScriptRenderers.java b/uitest/src/com/vaadin/tests/components/grid/JavaScriptRenderers.java new file mode 100644 index 0000000000..4bfa244c22 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/JavaScriptRenderers.java @@ -0,0 +1,75 @@ +/* + * 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.tests.components.grid; + +import com.vaadin.data.Item; +import com.vaadin.data.util.IndexedContainer; +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.Grid; + +public class JavaScriptRenderers extends AbstractTestUI { + + public static class MyBean { + private int integer; + private String string; + + public MyBean(int integer, String string) { + super(); + this.integer = integer; + this.string = string; + } + + public int getInteger() { + return integer; + } + + public void setInteger(int integer) { + this.integer = integer; + } + + public String getString() { + return string; + } + + public void setString(String string) { + this.string = string; + } + } + + @Override + protected void setup(VaadinRequest request) { + IndexedContainer container = new IndexedContainer(); + container.addContainerProperty("id", Integer.class, Integer.valueOf(0)); + container.addContainerProperty("bean", MyBean.class, null); + + for (int i = 0; i < 1000; i++) { + Integer itemId = Integer.valueOf(i); + Item item = container.addItem(itemId); + item.getItemProperty("id").setValue(itemId); + item.getItemProperty("bean").setValue( + new MyBean(i + 1, Integer.toString(i - 1))); + } + + Grid grid = new Grid(container); + + grid.getColumn("bean").setRenderer(new MyBeanJSRenderer()); + grid.getColumn("bean").setWidth(250); + + addComponent(grid); + } + +} diff --git a/uitest/src/com/vaadin/tests/components/grid/JavaScriptRenderersTest.java b/uitest/src/com/vaadin/tests/components/grid/JavaScriptRenderersTest.java new file mode 100644 index 0000000000..a3bb736086 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/JavaScriptRenderersTest.java @@ -0,0 +1,46 @@ +/* + * 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.tests.components.grid; + +import org.junit.Assert; +import org.junit.Test; + +import com.vaadin.testbench.elements.GridElement; +import com.vaadin.testbench.elements.GridElement.GridCellElement; +import com.vaadin.tests.tb3.MultiBrowserTest; + +public class JavaScriptRenderersTest extends MultiBrowserTest { + + @Test + public void testJavaScriptRenderer() { + setDebug(true); + openTestURL(); + + GridElement grid = $(GridElement.class).first(); + GridCellElement cell_1_2 = grid.getCell(1, 2); + + // Verify render functionality + Assert.assertEquals("Bean(2, 0)", cell_1_2.getText()); + + // Verify init functionality + Assert.assertEquals("2", cell_1_2.getAttribute("column")); + + // Verify onbrowserevent + cell_1_2.click(); + Assert.assertTrue(cell_1_2.getText().startsWith( + "Clicked 1 with key 1 at")); + } +} diff --git a/uitest/src/com/vaadin/tests/components/grid/MyBeanJSRenderer.java b/uitest/src/com/vaadin/tests/components/grid/MyBeanJSRenderer.java new file mode 100644 index 0000000000..ccb94f5d2d --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/MyBeanJSRenderer.java @@ -0,0 +1,34 @@ +/* + * Copyright 2000-2014 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.tests.components.grid; + +import com.vaadin.annotations.JavaScript; +import com.vaadin.tests.components.grid.JavaScriptRenderers.MyBean; +import com.vaadin.ui.renderer.AbstractJavaScriptRenderer; + +/** + * + * @since + * @author Vaadin Ltd + */ +@JavaScript("myBeanJsRenderer.js") +public class MyBeanJSRenderer extends AbstractJavaScriptRenderer<MyBean> { + + public MyBeanJSRenderer() { + super(MyBean.class); + } + +} diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java index 20b6a3c418..5912f2b5a5 100644 --- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java @@ -77,6 +77,8 @@ public class GridBasicFeatures extends AbstractComponentTest<Grid> { public static final int COLUMNS = 12; public static final int ROWS = 1000; + private int containerDelay = 0; + private IndexedContainer ds; private Grid grid; private SelectionListener selectionListener = new SelectionListener() { @@ -101,6 +103,13 @@ public class GridBasicFeatures extends AbstractComponentTest<Grid> { public List<Object> getItemIds(int startIndex, int numberOfIds) { log("Requested items " + startIndex + " - " + (startIndex + numberOfIds)); + if (containerDelay > 0) { + try { + Thread.sleep(containerDelay); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } return super.getItemIds(startIndex, numberOfIds); } }; @@ -437,6 +446,19 @@ public class GridBasicFeatures extends AbstractComponentTest<Grid> { c.setFrozenColumnCount(value.intValue()); } }); + + LinkedHashMap<String, Integer> containerDelayValues = new LinkedHashMap<String, Integer>(); + for (int delay : new int[] { 0, 500, 2000, 10000 }) { + containerDelayValues.put(String.valueOf(delay), + Integer.valueOf(delay)); + } + createSelectAction("Container delay", "State", containerDelayValues, + "0", new Command<Grid, Integer>() { + @Override + public void execute(Grid grid, Integer delay, Object data) { + containerDelay = delay.intValue(); + } + }); } protected void createHeaderActions() { diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientStructureTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientStructureTest.java new file mode 100644 index 0000000000..74cf368da9 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientStructureTest.java @@ -0,0 +1,37 @@ +/* + * 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.tests.components.grid.basicfeatures.client; + +import org.junit.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.WebElement; + +import com.vaadin.tests.components.grid.basicfeatures.GridBasicClientFeaturesTest; + +@SuppressWarnings("all") +public class GridClientStructureTest extends GridBasicClientFeaturesTest { + @Test + public void haederDecoSizeShouldBeRecalculated() { + // it's easier to notice with valo + openTestURL("theme=valo"); + + WebElement topDeco = getGridElement().findElement( + By.className("v-grid-header-deco")); + assertGreater( + "The header deco in Valo hasn't been recalculated after initial rendering", + topDeco.getSize().getHeight(), 20); + } +} diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/LoadingIndicatorTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/LoadingIndicatorTest.java new file mode 100644 index 0000000000..1f16efdd39 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/LoadingIndicatorTest.java @@ -0,0 +1,85 @@ +/* + * 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.tests.components.grid.basicfeatures.server; + +import org.junit.Assert; +import org.junit.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.support.ui.ExpectedConditions; + +import com.vaadin.testbench.elements.GridElement; +import com.vaadin.tests.components.grid.basicfeatures.GridBasicFeaturesTest; + +public class LoadingIndicatorTest extends GridBasicFeaturesTest { + @Test + public void testLoadingIndicator() throws InterruptedException { + setDebug(true); + openTestURL(); + + selectMenuPath("Component", "State", "Container delay", "2000"); + + GridElement gridElement = $(GridElement.class).first(); + + Assert.assertFalse( + "Loading indicator should not be visible before disabling waitForVaadin", + isLoadingIndicatorVisible()); + + testBench().disableWaitForVaadin(); + + // Scroll to a completely new location + gridElement.getCell(200, 1); + + // Wait for loading indicator delay + Thread.sleep(500); + + Assert.assertTrue( + "Loading indicator should be visible when fetching rows that are visible", + isLoadingIndicatorVisible()); + + waitUntilNot(ExpectedConditions.visibilityOfElementLocated(By + .className("v-loading-indicator"))); + + // Scroll so much that more data gets fetched, but not so much that + // missing rows are shown + gridElement.getCell(230, 1); + + // Wait for potentially triggered loading indicator to become visible + Thread.sleep(500); + + Assert.assertFalse( + "Loading indicator should not be visible when fetching rows that are not visible", + isLoadingIndicatorVisible()); + + // Finally verify that there was actually a request going on + Thread.sleep(2000); + + String firstLogRow = getLogRow(0); + Assert.assertTrue("Last log message was not the fourth message: " + + firstLogRow, firstLogRow.startsWith("4. Requested items")); + } + + private boolean isLoadingIndicatorVisible() { + WebElement loadingIndicator = findElement(By + .className("v-loading-indicator")); + if (loadingIndicator == null) { + return false; + } else { + return loadingIndicator.isDisplayed(); + } + + } +} diff --git a/uitest/src/com/vaadin/tests/components/grid/myBeanJsRenderer.js b/uitest/src/com/vaadin/tests/components/grid/myBeanJsRenderer.js new file mode 100644 index 0000000000..5e7bde5ec7 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/myBeanJsRenderer.js @@ -0,0 +1,16 @@ +window.com_vaadin_tests_components_grid_MyBeanJSRenderer = function() { + this.init = function(cell) { + cell.element.setAttribute("column", cell.columnIndex); + } + + this.render = function(cell, data) { + cell.element.innerHTML = 'Bean(' + data.integer + ', ' + data.string + ')' + } + + this.getConsumedEvents = function() { return ["click"] }; + + this.onBrowserEvent = function(cell, event) { + cell.element.innerHTML = "Clicked " + cell.rowIndex + " with key " + this.getRowKey(cell.rowIndex) +" at " + event.clientX; + return true; + } +}
\ No newline at end of file diff --git a/uitest/src/com/vaadin/tests/components/progressindicator/ProgressBarStaticReindeer.java b/uitest/src/com/vaadin/tests/components/progressindicator/ProgressBarStaticReindeer.java new file mode 100644 index 0000000000..6cf7fb0ded --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/progressindicator/ProgressBarStaticReindeer.java @@ -0,0 +1,32 @@ +/* + * 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.tests.components.progressindicator; + +import com.vaadin.annotations.Theme; +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.ProgressBar; +import com.vaadin.ui.themes.Reindeer; + +@Theme(Reindeer.THEME_NAME) +public class ProgressBarStaticReindeer extends AbstractTestUI { + @Override + protected void setup(VaadinRequest request) { + ProgressBar progressBar = new ProgressBar(); + progressBar.addStyleName(Reindeer.PROGRESSBAR_STATIC); + addComponent(progressBar); + } +} diff --git a/uitest/src/com/vaadin/tests/components/progressindicator/ProgressBarStaticReindeerTest.java b/uitest/src/com/vaadin/tests/components/progressindicator/ProgressBarStaticReindeerTest.java new file mode 100644 index 0000000000..f1056a640d --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/progressindicator/ProgressBarStaticReindeerTest.java @@ -0,0 +1,28 @@ +/* + * 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.tests.components.progressindicator; + +import org.junit.Test; + +import com.vaadin.tests.tb3.MultiBrowserTest; + +public class ProgressBarStaticReindeerTest extends MultiBrowserTest { + @Test + public void compareScreenshot() throws Exception { + openTestURL(); + compareScreen("screen"); + } +} diff --git a/uitest/src/com/vaadin/tests/components/progressindicator/ProgressBarStaticRuno.java b/uitest/src/com/vaadin/tests/components/progressindicator/ProgressBarStaticRuno.java new file mode 100644 index 0000000000..4e1ff7c886 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/progressindicator/ProgressBarStaticRuno.java @@ -0,0 +1,32 @@ +/* + * 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.tests.components.progressindicator; + +import com.vaadin.annotations.Theme; +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.ProgressBar; +import com.vaadin.ui.themes.Runo; + +@Theme(Runo.THEME_NAME) +public class ProgressBarStaticRuno extends AbstractTestUI { + @Override + protected void setup(VaadinRequest request) { + ProgressBar progressBar = new ProgressBar(); + progressBar.addStyleName(Runo.PROGRESSBAR_STATIC); + addComponent(progressBar); + } +} diff --git a/uitest/src/com/vaadin/tests/components/progressindicator/ProgressBarStaticRunoTest.java b/uitest/src/com/vaadin/tests/components/progressindicator/ProgressBarStaticRunoTest.java new file mode 100644 index 0000000000..751e048694 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/progressindicator/ProgressBarStaticRunoTest.java @@ -0,0 +1,28 @@ +/* + * 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.tests.components.progressindicator; + +import org.junit.Test; + +import com.vaadin.tests.tb3.MultiBrowserTest; + +public class ProgressBarStaticRunoTest extends MultiBrowserTest { + @Test + public void compareScreenshot() throws Exception { + openTestURL(); + compareScreen("screen"); + } +} |