diff options
5 files changed, 189 insertions, 4 deletions
diff --git a/WebContent/VAADIN/themes/base/escalator/escalator.scss b/WebContent/VAADIN/themes/base/escalator/escalator.scss index 6d146f3a74..7949b52882 100644 --- a/WebContent/VAADIN/themes/base/escalator/escalator.scss +++ b/WebContent/VAADIN/themes/base/escalator/escalator.scss @@ -137,9 +137,7 @@ position: absolute; display: block; - // debug - background-color: rgba(0,0,0,0.6); - color: white; + background-color: $background-color; > td { width: 100%; diff --git a/WebContent/VAADIN/themes/base/grid/grid.scss b/WebContent/VAADIN/themes/base/grid/grid.scss index e4a4a1d920..730bee8a6b 100644 --- a/WebContent/VAADIN/themes/base/grid/grid.scss +++ b/WebContent/VAADIN/themes/base/grid/grid.scss @@ -328,6 +328,10 @@ $v-grid-editor-background-color: $v-grid-row-background-color !default; .#{$primaryStyleName}-editor-save { margin-right: 4px; } + + .#{$primaryStyleName}-spacer { + border: $v-grid-border; + } // Renderers diff --git a/client/src/com/vaadin/client/widget/grid/DetailsGenerator.java b/client/src/com/vaadin/client/widget/grid/DetailsGenerator.java new file mode 100644 index 0000000000..665362ca8e --- /dev/null +++ b/client/src/com/vaadin/client/widget/grid/DetailsGenerator.java @@ -0,0 +1,45 @@ +/* + * Copyright 2000-2014 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.client.widget.grid; + +/** + * A callback interface for generating details for a particular row in Grid. + * + * @since + * @author Vaadin Ltd + */ +public interface DetailsGenerator { + + public static final DetailsGenerator NULL = new DetailsGenerator() { + @Override + public String getDetails(int rowIndex) { + return null; + } + }; + + /** + * This method is called for whenever a new details row needs to be + * generated. + * + * @param rowIndex + * the index of the row for which to generate details + * @return the details for the given row, or <code>null</code> to leave the + * details empty. + */ + // TODO: provide a row object instead of index (maybe, needs discussion?) + // TODO: return a Widget instead of a String + String getDetails(int rowIndex); +} diff --git a/client/src/com/vaadin/client/widgets/Grid.java b/client/src/com/vaadin/client/widgets/Grid.java index 71962d6953..31984f7d5b 100644 --- a/client/src/com/vaadin/client/widgets/Grid.java +++ b/client/src/com/vaadin/client/widgets/Grid.java @@ -36,6 +36,7 @@ import com.google.gwt.dom.client.BrowserEvents; import com.google.gwt.dom.client.DivElement; import com.google.gwt.dom.client.Element; import com.google.gwt.dom.client.EventTarget; +import com.google.gwt.dom.client.Node; import com.google.gwt.dom.client.Style; import com.google.gwt.dom.client.Style.Unit; import com.google.gwt.dom.client.TableCellElement; @@ -77,10 +78,13 @@ import com.vaadin.client.widget.escalator.RowContainer; import com.vaadin.client.widget.escalator.RowVisibilityChangeEvent; import com.vaadin.client.widget.escalator.RowVisibilityChangeHandler; import com.vaadin.client.widget.escalator.ScrollbarBundle.Direction; +import com.vaadin.client.widget.escalator.Spacer; +import com.vaadin.client.widget.escalator.SpacerUpdater; import com.vaadin.client.widget.grid.CellReference; import com.vaadin.client.widget.grid.CellStyleGenerator; import com.vaadin.client.widget.grid.DataAvailableEvent; import com.vaadin.client.widget.grid.DataAvailableHandler; +import com.vaadin.client.widget.grid.DetailsGenerator; import com.vaadin.client.widget.grid.EditorHandler; import com.vaadin.client.widget.grid.EditorHandler.EditorRequest; import com.vaadin.client.widget.grid.EventCellReference; @@ -1776,6 +1780,8 @@ public class Grid<T> extends ResizeComposite implements private static final String CUSTOM_STYLE_PROPERTY_NAME = "customStyle"; + private static final double DETAILS_ROW_INITIAL_HEIGHT = 50; + private EventCellReference<T> eventCell = new EventCellReference<T>(this); private GridKeyDownEvent keyDown = new GridKeyDownEvent(this, eventCell); private GridKeyUpEvent keyUp = new GridKeyUpEvent(this, eventCell); @@ -2768,6 +2774,38 @@ public class Grid<T> extends ResizeComposite implements } } + private class GridSpacerUpdater implements SpacerUpdater { + @Override + public void init(Spacer spacer) { + int rowIndex = spacer.getRow(); + + String string = detailsGenerator.getDetails(rowIndex); + if (string == null) { + destroy(spacer); + escalator.getBody().setSpacer(rowIndex, + DETAILS_ROW_INITIAL_HEIGHT); + return; + } + + spacer.getElement().setInnerText(string); + + /* + * Once we have the content properly inside the DOM, we should + * re-measure it to make sure that it's the correct height. + */ + double measuredHeight = WidgetUtil + .getRequiredHeightBoundingClientRectDouble(spacer + .getElement()); + assert getElement().isOrHasChild(spacer.getElement()) : "The spacer element wasn't in the DOM during measurement, but was assumed to be."; + escalator.getBody().setSpacer(rowIndex, measuredHeight); + } + + @Override + public void destroy(Spacer spacer) { + spacer.getElement().setInnerText(""); + } + } + /** * Escalator used internally by grid to render the rows */ @@ -2853,6 +2891,10 @@ public class Grid<T> extends ResizeComposite implements private boolean enabled = true; + private DetailsGenerator detailsGenerator = DetailsGenerator.NULL; + + private GridSpacerUpdater gridSpacerUpdater = new GridSpacerUpdater(); + /** * Enumeration for easy setting of selection mode. */ @@ -4902,7 +4944,7 @@ public class Grid<T> extends ResizeComposite implements EventTarget target = event.getEventTarget(); - if (!Element.is(target)) { + if (!Element.is(target) || isOrContainsInSpacer(Element.as(target))) { return; } @@ -4968,6 +5010,19 @@ public class Grid<T> extends ResizeComposite implements } } + private boolean isOrContainsInSpacer(Node node) { + Node n = node; + while (n != null && n != getElement()) { + if (Element.is(n) + && Element.as(n).getClassName() + .equals(getStylePrimaryName() + "-spacer")) { + return true; + } + n = n.getParentNode(); + } + return false; + } + private boolean isElementInChildWidget(Element e) { Widget w = WidgetUtil.findWidget(e, null); @@ -6279,4 +6334,47 @@ public class Grid<T> extends ResizeComposite implements public void resetSizesFromDom() { getEscalator().resetSizesFromDom(); } + + /** + * Sets a new details generator for row details. + * <p> + * The currently opened row details will be re-rendered. + * + * @since + * @param detailsGenerator + * the details generator to set + */ + public void setDetailsGenerator(DetailsGenerator detailsGenerator) + throws IllegalArgumentException { + + this.detailsGenerator = detailsGenerator; + + // this will refresh all visible spacers + escalator.getBody().setSpacerUpdater(gridSpacerUpdater); + } + + /** + * Gets the current details generator for row details. + * + * @since + * @return the detailsGenerator the current details generator + */ + public DetailsGenerator getDetailsGenerator() { + return detailsGenerator; + } + + /** + * Shows or hides the details for a specific row. + * + * @since + * @param row + * the index of the affected row + * @param visible + * <code>true</code> to show the details, or <code>false</code> + * to hide them + */ + public void setDetailsVisible(int rowIndex, boolean visible) { + double height = visible ? DETAILS_ROW_INITIAL_HEIGHT : -1; + escalator.getBody().setSpacer(rowIndex, height); + } } diff --git a/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeaturesWidget.java b/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeaturesWidget.java index 0452aa65d1..7c2ca3eedb 100644 --- a/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeaturesWidget.java +++ b/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeaturesWidget.java @@ -46,6 +46,7 @@ import com.vaadin.client.renderers.TextRenderer; import com.vaadin.client.ui.VLabel; import com.vaadin.client.widget.grid.CellReference; import com.vaadin.client.widget.grid.CellStyleGenerator; +import com.vaadin.client.widget.grid.DetailsGenerator; import com.vaadin.client.widget.grid.EditorHandler; import com.vaadin.client.widget.grid.RendererCellReference; import com.vaadin.client.widget.grid.RowReference; @@ -400,6 +401,7 @@ public class GridBasicClientFeaturesWidget extends createEditorMenu(); createInternalsMenu(); createDataSourceMenu(); + createDetailsMenu(); grid.getElement().getStyle().setZIndex(0); @@ -1214,4 +1216,42 @@ public class GridBasicClientFeaturesWidget extends String coords = "(" + object + ", " + column + ")"; label.setText(coords + " " + output); } + + private void createDetailsMenu() { + String[] menupath = new String[] { "Component", "Row details" }; + addMenuCommand("Set generator", new ScheduledCommand() { + @Override + public void execute() { + grid.setDetailsGenerator(new DetailsGenerator() { + @Override + public String getDetails(int rowIndex) { + return "Row: " + rowIndex + ". Lorem ipsum " + + "dolor sit amet, consectetur adipiscing " + + "elit. Morbi congue massa non augue " + + "pulvinar, nec consectetur justo efficitur. " + + "In nec arcu sit amet lorem hendrerit " + + "mollis."; + } + }); + } + }, menupath); + addMenuCommand("Toggle details for row 1", new ScheduledCommand() { + boolean visible = false; + + @Override + public void execute() { + visible = !visible; + grid.setDetailsVisible(1, visible); + } + }, menupath); + addMenuCommand("Toggle details for row 100", new ScheduledCommand() { + boolean visible = false; + + @Override + public void execute() { + visible = !visible; + grid.setDetailsVisible(100, visible); + } + }, menupath); + } } |