From 33809f43cd30f19c87c11db4bf8e9710aeac297e Mon Sep 17 00:00:00 2001 From: Aleksi Hietanen Date: Tue, 6 Sep 2016 11:25:50 +0300 Subject: [PATCH] Migrate ClickableRenderer and subclasses Change-Id: I233250d9b68052825b73bed0288fffeaf5bdd04b --- .../connectors/ButtonRendererConnector.java | 45 +++++ .../ClickableRendererConnector.java | 63 +++++++ .../connectors/ImageRendererConnector.java | 57 ++++++ .../grid/AbstractGridRendererConnector.java | 44 ++++- .../client/connectors/grid/GridConnector.java | 13 +- server/src/main/java/com/vaadin/ui/Grid.java | 33 +++- .../vaadin/ui/renderers/AbstractRenderer.java | 45 +++-- .../vaadin/ui/renderers/ButtonRenderer.java | 74 ++++++++ .../ui/renderers/ClickableRenderer.java | 166 ++++++++++++++++++ .../com/vaadin/ui/renderers/DateRenderer.java | 18 +- .../com/vaadin/ui/renderers/HtmlRenderer.java | 2 +- .../vaadin/ui/renderers/ImageRenderer.java | 71 ++++++++ .../vaadin/ui/renderers/NumberRenderer.java | 10 +- .../ui/renderers/ProgressBarRenderer.java | 2 +- .../com/vaadin/ui/renderers/TextRenderer.java | 2 +- .../ui/grid/renderers/RendererClickRpc.java | 35 ++++ .../grid/GridClickableRenderers.java | 37 ++++ .../grid/GridClickableRenderersTest.java | 52 ++++++ 18 files changed, 730 insertions(+), 39 deletions(-) create mode 100644 client/src/main/java/com/vaadin/client/connectors/ButtonRendererConnector.java create mode 100644 client/src/main/java/com/vaadin/client/connectors/ClickableRendererConnector.java create mode 100644 client/src/main/java/com/vaadin/client/connectors/ImageRendererConnector.java create mode 100644 server/src/main/java/com/vaadin/ui/renderers/ButtonRenderer.java create mode 100644 server/src/main/java/com/vaadin/ui/renderers/ClickableRenderer.java create mode 100644 server/src/main/java/com/vaadin/ui/renderers/ImageRenderer.java create mode 100644 shared/src/main/java/com/vaadin/shared/ui/grid/renderers/RendererClickRpc.java create mode 100644 uitest/src/main/java/com/vaadin/tests/components/grid/GridClickableRenderers.java create mode 100644 uitest/src/test/java/com/vaadin/tests/components/grid/GridClickableRenderersTest.java diff --git a/client/src/main/java/com/vaadin/client/connectors/ButtonRendererConnector.java b/client/src/main/java/com/vaadin/client/connectors/ButtonRendererConnector.java new file mode 100644 index 0000000000..fad8918c92 --- /dev/null +++ b/client/src/main/java/com/vaadin/client/connectors/ButtonRendererConnector.java @@ -0,0 +1,45 @@ +/* + * Copyright 2000-2016 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 com.google.web.bindery.event.shared.HandlerRegistration; +import com.vaadin.client.renderers.ButtonRenderer; +import com.vaadin.client.renderers.ClickableRenderer.RendererClickHandler; +import com.vaadin.shared.ui.Connect; + +import elemental.json.JsonObject; + +/** + * A connector for {@link ButtonRenderer}. + * + * @since 7.4 + * @author Vaadin Ltd + */ +@Connect(com.vaadin.ui.renderers.ButtonRenderer.class) +public class ButtonRendererConnector + extends ClickableRendererConnector { + + @Override + public ButtonRenderer getRenderer() { + return (ButtonRenderer) super.getRenderer(); + } + + @Override + protected HandlerRegistration addClickHandler( + RendererClickHandler handler) { + return getRenderer().addClickHandler(handler); + } +} diff --git a/client/src/main/java/com/vaadin/client/connectors/ClickableRendererConnector.java b/client/src/main/java/com/vaadin/client/connectors/ClickableRendererConnector.java new file mode 100644 index 0000000000..f6f6607683 --- /dev/null +++ b/client/src/main/java/com/vaadin/client/connectors/ClickableRendererConnector.java @@ -0,0 +1,63 @@ +/* + * Copyright 2000-2016 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 com.google.web.bindery.event.shared.HandlerRegistration; +import com.vaadin.client.MouseEventDetailsBuilder; +import com.vaadin.client.connectors.grid.AbstractGridRendererConnector; +import com.vaadin.client.renderers.ClickableRenderer.RendererClickEvent; +import com.vaadin.client.renderers.ClickableRenderer.RendererClickHandler; +import com.vaadin.shared.ui.grid.renderers.RendererClickRpc; + +import elemental.json.JsonObject; + +/** + * An abstract base class for {@link ClickableRenderer} connectors. + * + * @param + * the presentation type of the renderer + * + * @since 7.4 + * @author Vaadin Ltd + */ +public abstract class ClickableRendererConnector + extends AbstractGridRendererConnector { + + private HandlerRegistration clickRegistration; + + @Override + protected void init() { + clickRegistration = addClickHandler( + new RendererClickHandler() { + @Override + public void onClick(RendererClickEvent event) { + getRpcProxy(RendererClickRpc.class).click( + getRowKey(event.getCell().getRow()), + getColumnId(event.getCell().getColumn()), + MouseEventDetailsBuilder.buildMouseEventDetails( + event.getNativeEvent())); + } + }); + } + + @Override + public void onUnregister() { + clickRegistration.removeHandler(); + } + + protected abstract HandlerRegistration addClickHandler( + RendererClickHandler handler); +} diff --git a/client/src/main/java/com/vaadin/client/connectors/ImageRendererConnector.java b/client/src/main/java/com/vaadin/client/connectors/ImageRendererConnector.java new file mode 100644 index 0000000000..7949eeab3c --- /dev/null +++ b/client/src/main/java/com/vaadin/client/connectors/ImageRendererConnector.java @@ -0,0 +1,57 @@ +/* + * Copyright 2000-2016 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 com.google.web.bindery.event.shared.HandlerRegistration; +import com.vaadin.client.communication.JsonDecoder; +import com.vaadin.client.metadata.TypeDataStore; +import com.vaadin.client.renderers.ClickableRenderer.RendererClickHandler; +import com.vaadin.client.renderers.ImageRenderer; +import com.vaadin.shared.communication.URLReference; +import com.vaadin.shared.ui.Connect; + +import elemental.json.JsonObject; +import elemental.json.JsonValue; + +/** + * A connector for {@link ImageRenderer}. + * + * @since 7.4 + * @author Vaadin Ltd + */ +@Connect(com.vaadin.ui.renderers.ImageRenderer.class) +public class ImageRendererConnector extends ClickableRendererConnector { + + @Override + public ImageRenderer getRenderer() { + return (ImageRenderer) super.getRenderer(); + } + + @Override + public String decode(JsonValue value) { + URLReference reference = (URLReference) JsonDecoder.decodeValue( + TypeDataStore.getType(URLReference.class), value, null, + getConnection()); + + return reference != null ? reference.getURL() : null; + } + + @Override + protected HandlerRegistration addClickHandler( + RendererClickHandler handler) { + return getRenderer().addClickHandler(handler); + } +} diff --git a/client/src/main/java/com/vaadin/client/connectors/grid/AbstractGridRendererConnector.java b/client/src/main/java/com/vaadin/client/connectors/grid/AbstractGridRendererConnector.java index 96bfc3b26d..e448c5f2fe 100644 --- a/client/src/main/java/com/vaadin/client/connectors/grid/AbstractGridRendererConnector.java +++ b/client/src/main/java/com/vaadin/client/connectors/grid/AbstractGridRendererConnector.java @@ -16,7 +16,12 @@ package com.vaadin.client.connectors.grid; +import com.vaadin.client.ServerConnector; import com.vaadin.client.connectors.AbstractRendererConnector; +import com.vaadin.client.widgets.Grid.Column; +import com.vaadin.shared.data.DataCommunicatorConstants; + +import elemental.json.JsonObject; /** * An abstract base class for renderer connectors. A renderer connector is used @@ -35,5 +40,42 @@ import com.vaadin.client.connectors.AbstractRendererConnector; */ public abstract class AbstractGridRendererConnector extends AbstractRendererConnector { - // getRowKey and getColumnId will be needed here later on + + /** + * Gets the row key for a row object. + *

+ * In case this renderer wants be able to identify a row in such a way that + * the server also understands it, the row key is used for that. Rows are + * identified by unified keys between the client and the server. + * + * @param row + * the row object + * @return the row key for the given row + */ + protected String getRowKey(JsonObject row) { + return row.getString(DataCommunicatorConstants.KEY); + } + + /** + * Gets the column id for a column. + *

+ * In case this renderer wants be able to identify a column in such a way + * that the server also understands it, the column id is used for that. + * Columns are identified by unified ids between the client and the server. + * + * @param column + * the column object + * @return the column id for the given column + */ + protected String getColumnId(Column column) { + final ServerConnector parent = getParent(); + if (parent instanceof ColumnConnector) { + final ServerConnector parentGrid = parent.getParent(); + if (parentGrid instanceof GridConnector) { + return ((GridConnector) parentGrid).getColumnId(column); + } + } + throw new IllegalStateException( + "Renderers can only be used with a Grid."); + } } diff --git a/client/src/main/java/com/vaadin/client/connectors/grid/GridConnector.java b/client/src/main/java/com/vaadin/client/connectors/grid/GridConnector.java index 006aa65318..43be3f0623 100644 --- a/client/src/main/java/com/vaadin/client/connectors/grid/GridConnector.java +++ b/client/src/main/java/com/vaadin/client/connectors/grid/GridConnector.java @@ -66,6 +66,17 @@ public class GridConnector private SpaceSelectHandler spaceSelectHandler; private ClickSelectHandler clickSelectHandler; + /** + * Gets the string identifier of a {@link Column} in this grid. + * + * @param column + * the column for which the identifier is to be retrieved for + * @return the string identifying the given column in this grid + */ + public String getColumnId(Grid.Column column) { + return columnToIdMap.get(column); + } + @Override @SuppressWarnings("unchecked") public Grid getWidget() { @@ -216,7 +227,7 @@ public class GridConnector @Override public void setChildComponents(List children) { - this.childComponents = children; + childComponents = children; } diff --git a/server/src/main/java/com/vaadin/ui/Grid.java b/server/src/main/java/com/vaadin/ui/Grid.java index 4a12099977..2a4f473536 100644 --- a/server/src/main/java/com/vaadin/ui/Grid.java +++ b/server/src/main/java/com/vaadin/ui/Grid.java @@ -44,6 +44,7 @@ import com.vaadin.shared.ui.grid.GridConstants.Section; import com.vaadin.shared.ui.grid.GridServerRpc; import com.vaadin.shared.ui.grid.GridState; import com.vaadin.shared.ui.grid.HeightMode; +import com.vaadin.ui.renderers.AbstractRenderer; import com.vaadin.ui.renderers.Renderer; import com.vaadin.ui.renderers.TextRenderer; @@ -711,7 +712,7 @@ public class Grid extends AbstractListing> } /** - * Adds a new column to this {@link Grid} with given header caption, + * Adds a new column to this {@link Grid} with given header caption, typed * renderer and value provider. * * @param caption @@ -720,21 +721,26 @@ public class Grid extends AbstractListing> * the value provider * @param renderer * the column value class + * @param + * the type of this grid * @param * the column value type * * @return the new column + * + * @see {@link AbstractRenderer} */ public Column addColumn(String caption, - Function valueProvider, Renderer renderer) { - Column c = new Column<>(caption, valueProvider, renderer); + Function valueProvider, + AbstractRenderer renderer) { + Column column = new Column<>(caption, valueProvider, renderer); - c.extend(this); - c.setId(columnKeys.key(c)); - columnSet.add(c); - addDataGenerator(c); + column.extend(this); + column.setId(columnKeys.key(column)); + columnSet.add(column); + addDataGenerator(column); - return c; + return column; } /** @@ -813,6 +819,17 @@ public class Grid extends AbstractListing> return Collections.unmodifiableSet(columnSet); } + /** + * Gets a {@link Column} of this grid by its identifying string. + * + * @param columnId + * the identifier of the column to get + * @return the column corresponding to the given column id + */ + public Column getColumn(String columnId) { + return columnKeys.get(columnId); + } + @Override public Iterator iterator() { return Collections.unmodifiableSet(extensionComponents).iterator(); diff --git a/server/src/main/java/com/vaadin/ui/renderers/AbstractRenderer.java b/server/src/main/java/com/vaadin/ui/renderers/AbstractRenderer.java index 4dcf911515..43ab4108a9 100644 --- a/server/src/main/java/com/vaadin/ui/renderers/AbstractRenderer.java +++ b/server/src/main/java/com/vaadin/ui/renderers/AbstractRenderer.java @@ -20,23 +20,29 @@ import java.util.Objects; import com.vaadin.server.AbstractClientConnector; import com.vaadin.server.AbstractExtension; import com.vaadin.server.JsonCodec; +import com.vaadin.ui.Grid; import com.vaadin.ui.Grid.Column; +import com.vaadin.ui.renderers.ClickableRenderer.RendererClickEvent; import elemental.json.JsonValue; /** * An abstract base class for server-side - * {@link com.vaadin.ui.renderers.Renderer Grid renderers}. This class currently - * extends the AbstractExtension superclass, but this fact should be regarded as - * an implementation detail and subject to change in a future major or minor - * Vaadin version. + * {@link com.vaadin.ui.renderers.Renderer Grid renderers}. + * + *

+ * This class currently extends the AbstractExtension superclass, but this fact + * should be regarded as an implementation detail and subject to change in a + * future major or minor Vaadin version. * * @param + * the grid type this renderer can be attached to + * @param * the type this renderer knows how to present */ -public abstract class AbstractRenderer extends AbstractExtension - implements Renderer { - private final Class presentationType; +public abstract class AbstractRenderer extends AbstractExtension + implements Renderer { + private final Class presentationType; private final String nullRepresentation; @@ -52,7 +58,7 @@ public abstract class AbstractRenderer extends AbstractExtension * value in case the actual cell value is null. May * be null. */ - protected AbstractRenderer(Class presentationType, + protected AbstractRenderer(Class presentationType, String nullRepresentation) { Objects.requireNonNull(presentationType, "Presentation type cannot be null"); @@ -68,7 +74,7 @@ public abstract class AbstractRenderer extends AbstractExtension * the data type that this renderer displays, not * null */ - protected AbstractRenderer(Class presentationType) { + protected AbstractRenderer(Class presentationType) { this(presentationType, null); } @@ -94,12 +100,12 @@ public abstract class AbstractRenderer extends AbstractExtension } @Override - public Class getPresentationType() { + public Class getPresentationType() { return presentationType; } @Override - public JsonValue encode(T value) { + public JsonValue encode(V value) { if (value == null) { return encode(getNullRepresentation(), String.class); } else { @@ -136,4 +142,19 @@ public abstract class AbstractRenderer extends AbstractExtension .encode(value, null, type, getUI().getConnectorTracker()) .getEncodedValue(); } -} \ No newline at end of file + + /** + * Gets the {@link Grid} this renderer is attached to. Used internally for + * indicating the source grid of possible events emitted by this renderer, + * such as {@link RendererClickEvent}s. + * + * @return the grid this renderer is attached to or null if unattached + */ + @SuppressWarnings("unchecked") + protected Grid getParentGrid() { + if (super.getParent() == null) { + return null; + } + return (Grid) super.getParent().getParent(); + } +} diff --git a/server/src/main/java/com/vaadin/ui/renderers/ButtonRenderer.java b/server/src/main/java/com/vaadin/ui/renderers/ButtonRenderer.java new file mode 100644 index 0000000000..30e098492f --- /dev/null +++ b/server/src/main/java/com/vaadin/ui/renderers/ButtonRenderer.java @@ -0,0 +1,74 @@ +/* + * Copyright 2000-2016 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.renderers; + +/** + * A Renderer that displays a button with a textual caption. The value of the + * corresponding property is used as the caption. Click listeners can be added + * to the renderer, invoked when any of the rendered buttons is clicked. + * + * @since 7.4 + * @author Vaadin Ltd + */ +public class ButtonRenderer extends ClickableRenderer { + + /** + * Creates a new button renderer. + * + * @param nullRepresentation + * the textual representation of {@code null} value + */ + public ButtonRenderer(String nullRepresentation) { + super(String.class, nullRepresentation); + } + + /** + * Creates a new button renderer and adds the given click listener to it. + * + * @param listener + * the click listener to register + * @param nullRepresentation + * the textual representation of {@code null} value + */ + public ButtonRenderer(RendererClickListener listener, + String nullRepresentation) { + this(nullRepresentation); + addClickListener(listener); + } + + /** + * Creates a new button renderer. + */ + public ButtonRenderer() { + this(""); + } + + /** + * Creates a new button renderer and adds the given click listener to it. + * + * @param listener + * the click listener to register + */ + public ButtonRenderer(RendererClickListener listener) { + this(listener, ""); + } + + @Override + public String getNullRepresentation() { + return super.getNullRepresentation(); + } + +} diff --git a/server/src/main/java/com/vaadin/ui/renderers/ClickableRenderer.java b/server/src/main/java/com/vaadin/ui/renderers/ClickableRenderer.java new file mode 100644 index 0000000000..2617827b77 --- /dev/null +++ b/server/src/main/java/com/vaadin/ui/renderers/ClickableRenderer.java @@ -0,0 +1,166 @@ +/* + * Copyright 2000-2016 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.renderers; + +import java.lang.reflect.Method; + +import com.vaadin.event.ConnectorEventListener; +import com.vaadin.event.MouseEvents.ClickEvent; +import com.vaadin.shared.MouseEventDetails; +import com.vaadin.shared.ui.grid.renderers.RendererClickRpc; +import com.vaadin.ui.Grid; +import com.vaadin.ui.Grid.Column; +import com.vaadin.util.ReflectTools; + +/** + * An abstract superclass for {@link Renderer}s that render clickable items. + * Click listeners can be added to a renderer to be notified when any of the + * rendered items is clicked. + * + * @param + * the type of the parent {@link Grid} + * @param + * the type presented by the renderer + * + * @since 7.4 + * @author Vaadin Ltd + */ +public abstract class ClickableRenderer + extends AbstractRenderer { + + /** + * An interface for listening to {@link RendererClickEvent renderer click + * events}. + * + * @see {@link ButtonRenderer#addClickListener(RendererClickListener)} + */ + public interface RendererClickListener extends ConnectorEventListener { + + static final Method CLICK_METHOD = ReflectTools.findMethod( + RendererClickListener.class, "click", RendererClickEvent.class); + + /** + * Called when a rendered button is clicked. + * + * @param event + * the event representing the click + */ + void click(RendererClickEvent event); + } + + /** + * An event fired when a clickable widget rendered by a ClickableRenderer is + * clicked. + * + * @param + * the item type associated with this click event + */ + public static class RendererClickEvent extends ClickEvent { + + private T item; + private Column column; + + protected RendererClickEvent(Grid source, T item, Column column, + MouseEventDetails mouseEventDetails) { + super(source, mouseEventDetails); + this.item = item; + this.column = column; + } + + /** + * Returns the item of the row where the click event originated. + * + * @return the item of the clicked row + */ + public T getItem() { + return item; + } + + /** + * Returns the {@link Column} where the click event originated. + * + * @return the column of the click event + */ + public Column getColumn() { + return column; + } + } + + /** + * Creates a new clickable renderer with the given presentation type. No + * null representation will be used. + * + * @param presentationType + * the data type that this renderer displays, not + * null + */ + protected ClickableRenderer(Class presentationType) { + this(presentationType, null); + } + + /** + * Creates a new clickable renderer with the given presentation type and + * null representation. + * + * @param presentationType + * the data type that this renderer displays, not + * null + * @param nullRepresentation + * a string that will be sent to the client instead of a regular + * value in case the actual cell value is null. May + * be null. + */ + protected ClickableRenderer(Class presentationType, + String nullRepresentation) { + super(presentationType, nullRepresentation); + registerRpc(new RendererClickRpc() { + + @Override + public void click(String rowKey, String columnId, + MouseEventDetails mouseDetails) { + + Grid grid = getParentGrid(); + T item = grid.getDataCommunicator().getKeyMapper().get(rowKey); + Column column = grid.getColumn(columnId); + + fireEvent(new RendererClickEvent(grid, item, column, + mouseDetails)); + } + }); + } + + /** + * Adds a click listener to this button renderer. The listener is invoked + * every time one of the buttons rendered by this renderer is clicked. + * + * @param listener + * the click listener to be added + */ + public void addClickListener(RendererClickListener listener) { + addListener(RendererClickEvent.class, listener, + RendererClickListener.CLICK_METHOD); + } + + /** + * Removes the given click listener from this renderer. + * + * @param listener + * the click listener to be removed + */ + public void removeClickListener(RendererClickListener listener) { + removeListener(RendererClickEvent.class, listener); + } +} diff --git a/server/src/main/java/com/vaadin/ui/renderers/DateRenderer.java b/server/src/main/java/com/vaadin/ui/renderers/DateRenderer.java index dd33ce064c..85f06697f0 100644 --- a/server/src/main/java/com/vaadin/ui/renderers/DateRenderer.java +++ b/server/src/main/java/com/vaadin/ui/renderers/DateRenderer.java @@ -27,7 +27,7 @@ import elemental.json.JsonValue; * @since 7.4 * @author Vaadin Ltd */ -public class DateRenderer extends AbstractRenderer { +public class DateRenderer extends AbstractRenderer { private final Locale locale; private final String formatString; private final DateFormat dateFormat; @@ -86,8 +86,8 @@ public class DateRenderer extends AbstractRenderer { * @throws IllegalArgumentException * if {@code formatString} is {@code null} * @see Format - * String Syntax + * "http://docs.oracle.com/javase/7/docs/api/java/util/Formatter.html#syntax"> + * Format String Syntax */ public DateRenderer(String formatString) throws IllegalArgumentException { this(formatString, ""); @@ -106,8 +106,8 @@ public class DateRenderer extends AbstractRenderer { * @throws IllegalArgumentException * if {@code formatString} is {@code null} * @see Format - * String Syntax + * "http://docs.oracle.com/javase/7/docs/api/java/util/Formatter.html#syntax"> + * Format String Syntax */ public DateRenderer(String formatString, String nullRepresentation) throws IllegalArgumentException { @@ -127,8 +127,8 @@ public class DateRenderer extends AbstractRenderer { * @throws IllegalArgumentException * if either argument is {@code null} * @see Format - * String Syntax + * "http://docs.oracle.com/javase/7/docs/api/java/util/Formatter.html#syntax"> + * Format String Syntax */ public DateRenderer(String formatString, Locale locale) throws IllegalArgumentException { @@ -150,8 +150,8 @@ public class DateRenderer extends AbstractRenderer { * @throws IllegalArgumentException * if either argument is {@code null} * @see Format - * String Syntax + * "http://docs.oracle.com/javase/7/docs/api/java/util/Formatter.html#syntax"> + * Format String Syntax */ public DateRenderer(String formatString, Locale locale, String nullRepresentation) throws IllegalArgumentException { diff --git a/server/src/main/java/com/vaadin/ui/renderers/HtmlRenderer.java b/server/src/main/java/com/vaadin/ui/renderers/HtmlRenderer.java index 80fcdc18c4..c2571b5e3a 100644 --- a/server/src/main/java/com/vaadin/ui/renderers/HtmlRenderer.java +++ b/server/src/main/java/com/vaadin/ui/renderers/HtmlRenderer.java @@ -21,7 +21,7 @@ package com.vaadin.ui.renderers; * @author Vaadin Ltd * @since 7.4 */ -public class HtmlRenderer extends AbstractRenderer { +public class HtmlRenderer extends AbstractRenderer { /** * Creates a new HTML renderer. * diff --git a/server/src/main/java/com/vaadin/ui/renderers/ImageRenderer.java b/server/src/main/java/com/vaadin/ui/renderers/ImageRenderer.java new file mode 100644 index 0000000000..2969d516b8 --- /dev/null +++ b/server/src/main/java/com/vaadin/ui/renderers/ImageRenderer.java @@ -0,0 +1,71 @@ +/* + * Copyright 2000-2016 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.renderers; + +import com.vaadin.server.ExternalResource; +import com.vaadin.server.Resource; +import com.vaadin.server.ResourceReference; +import com.vaadin.server.ThemeResource; +import com.vaadin.shared.communication.URLReference; + +import elemental.json.JsonValue; + +/** + * A renderer for presenting images. + *

+ * The image for each rendered cell is read from a Resource-typed property in + * the data source. Only {@link ExternalResource}s and {@link ThemeResource}s + * are currently supported. + * + * @param + * the type of the grid this renderer can be attached to + * + * @since 7.4 + * @author Vaadin Ltd + */ +public class ImageRenderer extends ClickableRenderer { + + /** + * Creates a new image renderer. + */ + public ImageRenderer() { + super(Resource.class, null); + } + + /** + * Creates a new image renderer and adds the given click listener to it. + * + * @param listener + * the click listener to register + */ + public ImageRenderer(RendererClickListener listener) { + this(); + addClickListener(listener); + } + + @Override + public JsonValue encode(Resource resource) { + if (!(resource == null || resource instanceof ExternalResource + || resource instanceof ThemeResource)) { + throw new IllegalArgumentException( + "ImageRenderer only supports ExternalResource and ThemeResource (" + + resource.getClass().getSimpleName() + " given)"); + } + + return encode(ResourceReference.create(resource, this, null), + URLReference.class); + } +} diff --git a/server/src/main/java/com/vaadin/ui/renderers/NumberRenderer.java b/server/src/main/java/com/vaadin/ui/renderers/NumberRenderer.java index 02e6ce68fd..b5f64308bd 100644 --- a/server/src/main/java/com/vaadin/ui/renderers/NumberRenderer.java +++ b/server/src/main/java/com/vaadin/ui/renderers/NumberRenderer.java @@ -26,7 +26,7 @@ import elemental.json.JsonValue; * @since 7.4 * @author Vaadin Ltd */ -public class NumberRenderer extends AbstractRenderer { +public class NumberRenderer extends AbstractRenderer { private final Locale locale; private final NumberFormat numberFormat; private final String formatString; @@ -127,8 +127,8 @@ public class NumberRenderer extends AbstractRenderer { * @throws IllegalArgumentException * if {@code formatString} is {@code null} * @see Format - * String Syntax + * "http://docs.oracle.com/javase/7/docs/api/java/util/Formatter.html#syntax"> + * Format String Syntax */ public NumberRenderer(String formatString) throws IllegalArgumentException { this(formatString, Locale.getDefault(), ""); @@ -147,8 +147,8 @@ public class NumberRenderer extends AbstractRenderer { * @throws IllegalArgumentException * if either argument is {@code null} * @see Format - * String Syntax + * "http://docs.oracle.com/javase/7/docs/api/java/util/Formatter.html#syntax"> + * Format String Syntax */ public NumberRenderer(String formatString, Locale locale, String nullRepresentation) { diff --git a/server/src/main/java/com/vaadin/ui/renderers/ProgressBarRenderer.java b/server/src/main/java/com/vaadin/ui/renderers/ProgressBarRenderer.java index 7d05959484..e06f98865d 100644 --- a/server/src/main/java/com/vaadin/ui/renderers/ProgressBarRenderer.java +++ b/server/src/main/java/com/vaadin/ui/renderers/ProgressBarRenderer.java @@ -24,7 +24,7 @@ import elemental.json.JsonValue; * @author Vaadin Ltd * @since 7.4 */ -public class ProgressBarRenderer extends AbstractRenderer { +public class ProgressBarRenderer extends AbstractRenderer { /** * Creates a new text renderer diff --git a/server/src/main/java/com/vaadin/ui/renderers/TextRenderer.java b/server/src/main/java/com/vaadin/ui/renderers/TextRenderer.java index 07f09b88f2..d6cd527edf 100644 --- a/server/src/main/java/com/vaadin/ui/renderers/TextRenderer.java +++ b/server/src/main/java/com/vaadin/ui/renderers/TextRenderer.java @@ -21,7 +21,7 @@ package com.vaadin.ui.renderers; * @since 7.4 * @author Vaadin Ltd */ -public class TextRenderer extends AbstractRenderer { +public class TextRenderer extends AbstractRenderer { /** * Creates a new text renderer diff --git a/shared/src/main/java/com/vaadin/shared/ui/grid/renderers/RendererClickRpc.java b/shared/src/main/java/com/vaadin/shared/ui/grid/renderers/RendererClickRpc.java new file mode 100644 index 0000000000..a8820215ab --- /dev/null +++ b/shared/src/main/java/com/vaadin/shared/ui/grid/renderers/RendererClickRpc.java @@ -0,0 +1,35 @@ +/* + * Copyright 2000-2016 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.ui.grid.renderers; + +import com.vaadin.shared.MouseEventDetails; +import com.vaadin.shared.communication.ServerRpc; + +/** + * RPC interface implemented by server side {@link ClickableRenderer}s to + * receive click events from their client side counterparts. + */ +public interface RendererClickRpc extends ServerRpc { + /** + * Called when a click event has occurred and there are server side + * listeners for the event. + * + * @param mouseDetails + * Details about the mouse when the event took place + */ + public void click(String rowKey, String columnId, + MouseEventDetails mouseDetails); +} diff --git a/uitest/src/main/java/com/vaadin/tests/components/grid/GridClickableRenderers.java b/uitest/src/main/java/com/vaadin/tests/components/grid/GridClickableRenderers.java new file mode 100644 index 0000000000..bb37d1d765 --- /dev/null +++ b/uitest/src/main/java/com/vaadin/tests/components/grid/GridClickableRenderers.java @@ -0,0 +1,37 @@ +package com.vaadin.tests.components.grid; + +import com.vaadin.server.ExternalResource; +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.Grid; +import com.vaadin.ui.Label; +import com.vaadin.ui.renderers.ButtonRenderer; +import com.vaadin.ui.renderers.ImageRenderer; + +public class GridClickableRenderers extends AbstractTestUI { + + private static class TestPOJO { + String testText; + String imageUrl; + String buttonText; + + TestPOJO(String intValue, String imageUrl, String buttonText) { + testText = intValue; + this.imageUrl = imageUrl; + this.buttonText = buttonText; + } + } + + @Override + protected void setup(VaadinRequest request) { + Label valueDisplayLabel = new Label(); + Grid grid = new Grid<>(); + grid.addColumn("images", pojo -> new ExternalResource(pojo.imageUrl), + new ImageRenderer<>()); + grid.addColumn("buttons", pojo -> pojo.buttonText, new ButtonRenderer<>( + event -> valueDisplayLabel.setValue(event.getItem().testText))); + grid.setItems(new TestPOJO("first button clicked", "", "button 1 text"), + new TestPOJO("second button clicked", "", "button 2 text")); + addComponents(valueDisplayLabel, grid); + } +} diff --git a/uitest/src/test/java/com/vaadin/tests/components/grid/GridClickableRenderersTest.java b/uitest/src/test/java/com/vaadin/tests/components/grid/GridClickableRenderersTest.java new file mode 100644 index 0000000000..9fe2eb0047 --- /dev/null +++ b/uitest/src/test/java/com/vaadin/tests/components/grid/GridClickableRenderersTest.java @@ -0,0 +1,52 @@ +/* + * Copyright 2000-2016 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 org.openqa.selenium.By; +import org.openqa.selenium.WebElement; + +import com.vaadin.testbench.elements.LabelElement; +import com.vaadin.tests.tb3.MultiBrowserTest; + +public class GridClickableRenderersTest extends MultiBrowserTest { + + @Test + public void buttonAndImageRenderersPresent() { + openTestURL(); + + Assert.assertTrue(isElementPresent(By.className("v-nativebutton"))); + + Assert.assertTrue(isElementPresent(By.className("gwt-Image"))); + } + + @Test + public void buttonRendererReturnsCorrectItem() { + openTestURL(); + WebElement firstButton = findElements(By.className("v-nativebutton")) + .get(0); + WebElement secondButton = findElements(By.className("v-nativebutton")) + .get(1); + LabelElement label = $(LabelElement.class).get(1); + + firstButton.click(); + Assert.assertEquals("first button clicked", label.getText()); + + secondButton.click(); + Assert.assertEquals("second button clicked", label.getText()); + } +} -- 2.39.5