summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--WebContent/VAADIN/themes/base/grid/grid.scss90
-rw-r--r--WebContent/VAADIN/themes/reindeer/grid/grid.scss31
-rw-r--r--WebContent/VAADIN/themes/runo/grid/grid.scss4
-rw-r--r--WebContent/VAADIN/themes/valo/components/_grid.scss105
-rw-r--r--WebContent/VAADIN/themes/valo/shared/_global.scss10
-rw-r--r--client/src/com/vaadin/client/widgets/Grid.java134
-rw-r--r--uitest/src/com/vaadin/testbench/elements/GridElement.java6
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridEditorClientTest.java5
8 files changed, 292 insertions, 93 deletions
diff --git a/WebContent/VAADIN/themes/base/grid/grid.scss b/WebContent/VAADIN/themes/base/grid/grid.scss
index ed068a5efc..a79420f7a9 100644
--- a/WebContent/VAADIN/themes/base/grid/grid.scss
+++ b/WebContent/VAADIN/themes/base/grid/grid.scss
@@ -85,7 +85,8 @@ $v-grid-editor-background-color: $v-grid-row-background-color !default;
// Rows
- .#{$primaryStyleName}-row > td {
+ .#{$primaryStyleName}-row > td,
+ .#{$primaryStyleName}-editor-cells > div {
border-left: $v-grid-cell-vertical-border;
border-bottom: $v-grid-cell-horizontal-border;
@@ -221,22 +222,35 @@ $v-grid-editor-background-color: $v-grid-row-background-color !default;
// Editor
.#{$primaryStyleName}-editor {
- // TODO should be fixed in offset calculations
- margin-top: -1px;
position: absolute;
- overflow-y: visible;
- background: $v-grid-editor-background-color;
- @include box-shadow(0 0 10px 1px rgba(0,0,0,.3));
+ z-index: 20;
+ overflow: hidden;
+ left: 0;
+ right: 0;
+ border: $v-grid-border;
+ margin-top: nth($v-grid-border, 1) * -1;
+ @include box-shadow(0 0 9px rgba(0,0,0,.2));
+ }
+
+ .#{$primaryStyleName}-editor-cells {
+ position: relative;
+ white-space: nowrap;
> div {
- position: absolute;
+ display: inline-block;
@include box-sizing(border-box);
- border-left: $v-grid-cell-vertical-border;
+ vertical-align: middle;
+ background: $v-grid-editor-background-color;
&:first-child {
border-left: none;
}
+ > * {
+ vertical-align: middle;
+ display: inline-block;
+ }
+
.v-textfield,
.v-datefield,
.v-filterselect {
@@ -244,24 +258,60 @@ $v-grid-editor-background-color: $v-grid-row-background-color !default;
max-width: 100%;
min-height: 100%;
max-height: 100%;
- border: none;
- border-radius: 0;
}
- .v-textfield-focus,
- .v-filterselect-focus input {
- position: relative;
- z-index: 1;
+ .v-select,
+ .v-select-select {
+ min-width: 100%;
+ max-width: 100%;
}
}
}
- .#{$primaryStyleName}-editor-save,
- .#{$primaryStyleName}-editor-cancel {
- position: absolute;
- // TODO remove the inline size from the widgets
- width: auto !important;
- height: auto !important;
+ .#{$primaryStyleName}-editor-footer {
+ display: table;
+ height: $v-grid-row-height;
+ border-top: $v-grid-cell-horizontal-border;
+ margin-top: nth($v-grid-cell-horizontal-border, 1) * -1;
+ background: $v-grid-row-background-color;
+ padding: 0 5px;
+
+ + .#{$primaryStyleName}-editor-cells > div {
+ border-bottom: none;
+ border-top: $v-grid-cell-horizontal-border;
+ }
+
+ &:first-child {
+ border-top: none;
+ margin-top: 0;
+ border-bottom: $v-grid-cell-horizontal-border;
+ margin-bottom: nth($v-grid-cell-horizontal-border, 1) * -1;
+ }
+ }
+
+ .#{$primaryStyleName}-editor-message,
+ .#{$primaryStyleName}-editor-buttons {
+ display: table-cell;
+ white-space: nowrap;
+ vertical-align: middle;
+ }
+
+ .#{$primaryStyleName}-editor-message {
+ width: 100%;
+ position: relative;
+
+ > div {
+ position: absolute;
+ width: 100%;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ line-height: $v-grid-row-height;
+ top: 0;
+ }
+ }
+
+ .#{$primaryStyleName}-editor-save {
+ margin-right: 4px;
}
// Renderers
diff --git a/WebContent/VAADIN/themes/reindeer/grid/grid.scss b/WebContent/VAADIN/themes/reindeer/grid/grid.scss
index 8dacb3ccce..28c5977fda 100644
--- a/WebContent/VAADIN/themes/reindeer/grid/grid.scss
+++ b/WebContent/VAADIN/themes/reindeer/grid/grid.scss
@@ -57,4 +57,35 @@
background-image: url(img/desc-light.png);
}
+ .#{$primaryStyleName}-editor-footer {
+ background: #dfe1e3;
+ }
+
+ .#{$primaryStyleName}-editor-cells > div {
+ .v-textfield,
+ .v-textfield-focus,
+ .v-datefield,
+ .v-datefield .v-textfield-focus,
+ .v-filterselect,
+ .v-filterselect-input,
+ .v-filterselect-input:focus {
+ border: none;
+ border-radius: 0;
+ background: transparent;
+ }
+
+ .v-filterselect {
+ overflow: hidden;
+ }
+
+ .v-filterselect-input {
+ height: 100%;
+ }
+
+ .v-filterselect-button {
+ // 24px is the height of v-filterselect
+ margin-top: round((24px - $v-grid-row-height) / -2)
+ }
+ }
+
}
diff --git a/WebContent/VAADIN/themes/runo/grid/grid.scss b/WebContent/VAADIN/themes/runo/grid/grid.scss
index a1081878cc..06a04ec626 100644
--- a/WebContent/VAADIN/themes/runo/grid/grid.scss
+++ b/WebContent/VAADIN/themes/runo/grid/grid.scss
@@ -50,4 +50,8 @@
background-image: url(img/sort-desc.png);
}
+ .#{$primaryStyleName}-editor-footer {
+ background: #e7e9ea;
+ }
+
}
diff --git a/WebContent/VAADIN/themes/valo/components/_grid.scss b/WebContent/VAADIN/themes/valo/components/_grid.scss
index 50c7169225..c481f127a8 100644
--- a/WebContent/VAADIN/themes/valo/components/_grid.scss
+++ b/WebContent/VAADIN/themes/valo/components/_grid.scss
@@ -3,7 +3,7 @@
$v-grid-row-background-color: valo-table-background-color() !default;
$v-grid-row-stripe-background-color: scale-color($v-grid-row-background-color, $lightness: if(color-luminance($v-grid-row-background-color) < 10, 4%, -4%)) !default;
-$v-grid-border: valo-border($color: $v-grid-row-background-color, $strength: 0.8) !default;
+$v-grid-border: flatten-list(valo-border($color: $v-grid-row-background-color, $strength: 0.8)) !default;
$v-grid-cell-focused-border: max(2px, first-number($v-border)) solid $v-selection-color !default;
$v-grid-row-height: $v-table-row-height !default;
@@ -14,6 +14,8 @@ $v-grid-header-background-color: $v-background-color !default;
$v-grid-cell-padding-horizontal: $v-table-cell-padding-horizontal !default;
+$v-grid-animations-enabled: $v-animations-enabled !default;
+
@import "../../base/grid/grid";
@@ -68,10 +70,91 @@ $v-grid-cell-padding-horizontal: $v-table-cell-padding-horizontal !default;
}
}
+ .#{$primary-stylename}-editor {
+ @include valo-focus-style;
+ border-color: $v-focus-color;
+ }
+
+ .#{$primary-stylename}-editor-footer {
+ font-size: $v-font-size--small;
+ padding: 0 round($v-layout-spacing-horizontal / 2);
+ background: $v-app-background-color;
+ @if $v-grid-animations-enabled {
+ @include animation(valo-grid-editor-footer-animate-in 200ms 120ms backwards);
+ }
+ }
+
+ @if $v-grid-animations-enabled {
+ .#{$primary-stylename}-editor-footer:first-child {
+ @include animation(valo-grid-editor-footer-animate-in-alt 200ms 120ms backwards);
+ }
+ }
+
+ .#{$primary-stylename}-editor-cells {
+ z-index: 1;
+ }
+
+ .#{$primary-stylename}-editor-cells > div {
+ // Vertical centering for widgets
+ &:before {
+ content: "";
+ display: inline-block;
+ height: 100%;
+ vertical-align: middle;
+ }
+
+ .v-textfield,
+ .v-textfield-focus,
+ .v-datefield,
+ .v-datefield .v-textfield-focus,
+ .v-filterselect-input,
+ .v-filterselect-input:focus {
+ border: none;
+ border-radius: 0;
+ background: transparent;
+
+ @if $v-textfield-bevel {
+ @include box-shadow(valo-bevel-and-shadow($bevel: $v-textfield-bevel));
+ } @else {
+ @include box-shadow(none);
+ }
+ }
+
+ .v-textfield-focus,
+ .v-datefield .v-textfield-focus,
+ .v-filterselect-input:focus {
+ position: relative;
+ }
+
+ .v-select {
+ padding-left: round($v-grid-cell-padding-horizontal / 2);
+ padding-right: round($v-grid-cell-padding-horizontal / 2);
+ }
+
+ .v-checkbox {
+ margin: 0 round($v-grid-cell-padding-horizontal / 2);
+
+ label {
+ white-space: nowrap;
+ }
+ }
+ }
+
+ .#{$primary-stylename}-editor-message > div:before {
+ display: inline-block;
+ @include valo-error-indicator-style($is-pseudo-element: true);
+ }
+
.#{$primary-stylename}-editor-save,
.#{$primary-stylename}-editor-cancel {
- @include valo-button-static-style;
- @include valo-button-style($unit-size: $v-unit-size--small, $font-size: $v-font-size--small);
+ @include valo-link-style;
+ font-weight: $v-font-weight + 100;
+ text-decoration: none;
+ border: none;
+ background: transparent;
+ padding: round($v-layout-spacing-vertical / 2) round($v-layout-spacing-horizontal / 2);
+ margin: 0;
+ outline: none;
}
// Customize scrollbars
@@ -98,3 +181,19 @@ $v-grid-cell-padding-horizontal: $v-table-cell-padding-horizontal !default;
}
}
+
+
+@include keyframes(valo-grid-editor-footer-animate-in) {
+ 0% {
+ margin-top: -$v-grid-row-height;
+ }
+}
+
+@include keyframes(valo-grid-editor-footer-animate-in-alt) {
+ 0% {
+ margin-bottom: -$v-grid-row-height - first-number($v-grid-cell-horizontal-border);
+ }
+ 100% {
+ margin-bottom: first-number($v-grid-cell-horizontal-border) * -1;
+ }
+}
diff --git a/WebContent/VAADIN/themes/valo/shared/_global.scss b/WebContent/VAADIN/themes/valo/shared/_global.scss
index 4ce294b06a..b4e8564119 100644
--- a/WebContent/VAADIN/themes/valo/shared/_global.scss
+++ b/WebContent/VAADIN/themes/valo/shared/_global.scss
@@ -394,16 +394,22 @@ $valo-shared-pathPrefix: null;
/**
* Error indicator styles. The error indicator is by default a font character which you can style freely.
*
+ * @param {boolean} $is-pseudo-element (false) - is the selector including this mixin targeting a pseudo element
+ *
* @requires {mixin} valo-error-indicator-icon-style by default
*/
-@mixin valo-error-indicator-style {
+@mixin valo-error-indicator-style ($is-pseudo-element: false) {
color: $v-error-indicator-color;
font-weight: 600;
width: ceil($v-unit-size/2);
text-align: center;
- &:before {
+ @if $is-pseudo-element {
@include valo-error-indicator-icon-style;
+ } @else {
+ &:before {
+ @include valo-error-indicator-icon-style;
+ }
}
}
diff --git a/client/src/com/vaadin/client/widgets/Grid.java b/client/src/com/vaadin/client/widgets/Grid.java
index 303b94763d..fb7ec3abb5 100644
--- a/client/src/com/vaadin/client/widgets/Grid.java
+++ b/client/src/com/vaadin/client/widgets/Grid.java
@@ -942,13 +942,6 @@ public class Grid<T> extends ResizeComposite implements
*/
protected static class Editor<T> {
- private static final double BUTTON_HEIGHT = 25;
- private static final double BUTTON_WIDTH = 50;
- private static final double BUTTON_MARGIN = 5;
- private static final double SAVE_BUTTON_LEFT_MARGIN_PX = 0;
- private static final double CANCEL_BUTTON_LEFT_MARGIN_PX = SAVE_BUTTON_LEFT_MARGIN_PX
- + BUTTON_WIDTH + BUTTON_MARGIN;
-
public static final int KEYCODE_SHOW = KeyCodes.KEY_ENTER;
public static final int KEYCODE_HIDE = KeyCodes.KEY_ESCAPE;
@@ -960,6 +953,16 @@ public class Grid<T> extends ResizeComposite implements
private EditorHandler<T> handler;
private DivElement editorOverlay = DivElement.as(DOM.createDiv());
+ private DivElement cellWrapper = DivElement.as(DOM.createDiv());
+ private DivElement messageAndButtonsWrapper = DivElement.as(DOM
+ .createDiv());
+
+ private DivElement messageWrapper = DivElement.as(DOM.createDiv());
+ private DivElement buttonsWrapper = DivElement.as(DOM.createDiv());
+
+ // Element which contains the error message for the editor
+ // Should only be added to the DOM when there's a message to show
+ private DivElement message = DivElement.as(DOM.createDiv());
private Map<Column<?, T>, Widget> columnToWidget = new HashMap<Column<?, T>, Widget>();
@@ -1055,7 +1058,6 @@ public class Grid<T> extends ResizeComposite implements
public Editor() {
saveButton = new Button();
saveButton.setText(GridConstants.DEFAULT_SAVE_CAPTION);
- saveButton.setStylePrimaryName("v-nativebutton");
saveButton.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
@@ -1065,7 +1067,6 @@ public class Grid<T> extends ResizeComposite implements
cancelButton = new Button();
cancelButton.setText(GridConstants.DEFAULT_CANCEL_CAPTION);
- cancelButton.setStylePrimaryName("v-nativebutton");
cancelButton.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
@@ -1274,23 +1275,7 @@ public class Grid<T> extends ResizeComposite implements
*/
protected void showOverlay(TableRowElement tr) {
- DivElement tableWrapper = DivElement.as(tr.getParentElement()
- .getParentElement().getParentElement());
-
- AbstractRowContainer body = (AbstractRowContainer) grid
- .getEscalator().getBody();
-
- double rowTop = body.getRowTop(tr);
- int bodyTop = body.getElement().getAbsoluteTop();
- int wrapperTop = tableWrapper.getAbsoluteTop();
-
- double width = WidgetUtil
- .getRequiredWidthBoundingClientRectDouble(tr);
- double height = WidgetUtil
- .getRequiredHeightBoundingClientRectDouble(tr);
- double overlayTop = rowTop + bodyTop - wrapperTop;
- setBounds(editorOverlay, tr.getOffsetLeft(), overlayTop, width,
- height);
+ DivElement gridElement = DivElement.as(grid.getElement());
scrollHandler = grid.addScrollHandler(new ScrollHandler() {
@Override
@@ -1299,12 +1284,14 @@ public class Grid<T> extends ResizeComposite implements
}
});
- tableWrapper.appendChild(editorOverlay);
+ gridElement.appendChild(editorOverlay);
+ editorOverlay.appendChild(cellWrapper);
+ editorOverlay.appendChild(messageAndButtonsWrapper);
for (int i = 0; i < tr.getCells().getLength(); i++) {
Element cell = createCell(tr.getCells().getItem(i));
- editorOverlay.appendChild(cell);
+ cellWrapper.appendChild(cell);
Column<?, T> column = grid.getColumn(i);
if (column.isEditable()) {
@@ -1316,43 +1303,58 @@ public class Grid<T> extends ResizeComposite implements
}
}
- attachWidget(saveButton, editorOverlay);
- attachWidget(cancelButton, editorOverlay);
+ // Only add these elements once
+ if (!messageAndButtonsWrapper.isOrHasChild(messageWrapper)) {
+ messageAndButtonsWrapper.appendChild(messageWrapper);
+ messageAndButtonsWrapper.appendChild(buttonsWrapper);
+ }
- /*
- * We can't use BUTTON_HEIGHT here, becuase it's ignored by at least
- * Chrome and Firefox. So we measure it.
- */
- double buttonTop = getButtonTop(tr, saveButton.getOffsetHeight());
- setBounds(saveButton.getElement(), SAVE_BUTTON_LEFT_MARGIN_PX,
- buttonTop, BUTTON_WIDTH, BUTTON_HEIGHT);
- setBounds(cancelButton.getElement(), CANCEL_BUTTON_LEFT_MARGIN_PX,
- buttonTop, BUTTON_WIDTH, BUTTON_HEIGHT);
+ attachWidget(saveButton, buttonsWrapper);
+ attachWidget(cancelButton, buttonsWrapper);
updateHorizontalScrollPosition();
- }
- private double getButtonTop(TableRowElement tr, int buttonHeight) {
- boolean buttonsShouldBeRenderedBelow = buttonsShouldBeRenderedBelow(
- tr, buttonHeight);
- final double buttonTop;
- if (buttonsShouldBeRenderedBelow) {
- buttonTop = tr.getOffsetHeight() + BUTTON_MARGIN;
+ AbstractRowContainer body = (AbstractRowContainer) grid
+ .getEscalator().getBody();
+ double rowTop = body.getRowTop(tr);
+
+ int bodyTop = body.getElement().getAbsoluteTop();
+ int gridTop = gridElement.getAbsoluteTop();
+ double overlayTop = rowTop + bodyTop - gridTop;
+
+ if (buttonsShouldBeRenderedBelow(tr)) {
+ // Default case, editor buttons are below the edited row
+ editorOverlay.getStyle().setTop(overlayTop, Unit.PX);
+ editorOverlay.getStyle().clearBottom();
} else {
- buttonTop = -(buttonHeight + BUTTON_MARGIN);
+ // Move message and buttons wrapper on top of cell wrapper if
+ // there is not enough space visible space under and fix the
+ // overlay from the bottom
+ editorOverlay.appendChild(cellWrapper);
+ int gridHeight = grid.getElement().getOffsetHeight();
+ editorOverlay.getStyle()
+ .setBottom(
+ gridHeight - overlayTop - tr.getOffsetHeight(),
+ Unit.PX);
+ editorOverlay.getStyle().clearTop();
+ }
+
+ // Do not render over the vertical scrollbar
+ int nativeScrollbarSize = WidgetUtil.getNativeScrollbarSize();
+ if (nativeScrollbarSize > 0) {
+ editorOverlay.getStyle().setRight(nativeScrollbarSize, Unit.PX);
}
- return buttonTop;
}
- private boolean buttonsShouldBeRenderedBelow(TableRowElement tr,
- int buttonHeight) {
+ private boolean buttonsShouldBeRenderedBelow(TableRowElement tr) {
TableSectionElement tfoot = grid.escalator.getFooter().getElement();
double tfootPageTop = WidgetUtil.getBoundingClientRect(tfoot)
.getTop();
double trPageBottom = WidgetUtil.getBoundingClientRect(tr)
.getBottom();
- double bottomOfButtons = trPageBottom + buttonHeight
- + BUTTON_MARGIN;
+ int messageAndButtonsHeight = messageAndButtonsWrapper
+ .getOffsetHeight();
+ double bottomOfButtons = trPageBottom + messageAndButtonsHeight;
return bottomOfButtons < tfootPageTop;
}
@@ -1366,6 +1368,7 @@ public class Grid<T> extends ResizeComposite implements
detachWidget(cancelButton);
editorOverlay.removeAllChildren();
+ cellWrapper.removeAllChildren();
editorOverlay.removeFromParent();
scrollHandler.removeHandler();
@@ -1374,14 +1377,27 @@ public class Grid<T> extends ResizeComposite implements
protected void setStylePrimaryName(String primaryName) {
if (styleName != null) {
editorOverlay.removeClassName(styleName);
+
+ cellWrapper.removeClassName(styleName + "-cells");
+ messageAndButtonsWrapper.removeClassName(styleName + "-footer");
+
+ messageWrapper.removeClassName(styleName + "-message");
+ buttonsWrapper.removeClassName(styleName + "-buttons");
+
saveButton.removeStyleName(styleName + "-save");
cancelButton.removeStyleName(styleName + "-cancel");
}
styleName = primaryName + "-editor";
- editorOverlay.addClassName(styleName);
+ editorOverlay.setClassName(styleName);
- saveButton.addStyleName(styleName + "-save");
- cancelButton.addStyleName(styleName + "-cancel");
+ cellWrapper.setClassName(styleName + "-cells");
+ messageAndButtonsWrapper.setClassName(styleName + "-footer");
+
+ messageWrapper.setClassName(styleName + "-message");
+ buttonsWrapper.setClassName(styleName + "-buttons");
+
+ saveButton.setStyleName(styleName + "-save");
+ cancelButton.setStyleName(styleName + "-cancel");
}
/**
@@ -1425,13 +1441,7 @@ public class Grid<T> extends ResizeComposite implements
private void updateHorizontalScrollPosition() {
double scrollLeft = grid.getScrollLeft();
-
- editorOverlay.getStyle().setLeft(-scrollLeft, Unit.PX);
-
- double saveLeftPx = scrollLeft + SAVE_BUTTON_LEFT_MARGIN_PX;
- double cancelLeftPx = scrollLeft + CANCEL_BUTTON_LEFT_MARGIN_PX;
- saveButton.getElement().getStyle().setLeft(saveLeftPx, Unit.PX);
- cancelButton.getElement().getStyle().setLeft(cancelLeftPx, Unit.PX);
+ cellWrapper.getStyle().setLeft(-scrollLeft, Unit.PX);
}
protected void setGridEnabled(boolean enabled) {
diff --git a/uitest/src/com/vaadin/testbench/elements/GridElement.java b/uitest/src/com/vaadin/testbench/elements/GridElement.java
index 5a27bc1444..6b1279d2c2 100644
--- a/uitest/src/com/vaadin/testbench/elements/GridElement.java
+++ b/uitest/src/com/vaadin/testbench/elements/GridElement.java
@@ -106,8 +106,7 @@ public class GridElement extends AbstractComponentElement {
* useless.
*/
public void save() {
- List<WebElement> buttons = findElements(By.xpath("./button"));
- buttons.get(0).click();
+ findElement(By.className("v-grid-editor-save")).click();
}
/**
@@ -117,8 +116,7 @@ public class GridElement extends AbstractComponentElement {
* useless.
*/
public void cancel() {
- List<WebElement> buttons = findElements(By.xpath("./button"));
- buttons.get(1).click();
+ findElement(By.className("v-grid-editor-cancel")).click();
}
}
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridEditorClientTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridEditorClientTest.java
index f6f2fac074..30481ebc65 100644
--- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridEditorClientTest.java
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridEditorClientTest.java
@@ -117,8 +117,9 @@ public class GridEditorClientTest extends GridBasicClientFeaturesTest {
selectMenuPath("Component", "State", "Selection mode", "multi");
selectMenuPath(EDIT_ROW_5);
- WebElement editor = getEditor();
- List<WebElement> selectorDivs = editor.findElements(By
+ WebElement editorCells = findElement(By
+ .className("v-grid-editor-cells"));
+ List<WebElement> selectorDivs = editorCells.findElements(By
.cssSelector("div"));
assertTrue("selector column cell should've been empty", selectorDivs