diff options
author | Teemu Suo-Anttila <teemusa@vaadin.com> | 2014-09-03 11:48:47 +0300 |
---|---|---|
committer | Teemu Suo-Anttila <teemusa@vaadin.com> | 2014-09-03 15:33:01 +0300 |
commit | 927e424acc1e43a12bdbbcd971302d00717af540 (patch) | |
tree | a91f0486fb646f6d1de9a4d590e25100347cc7ec | |
parent | 600d5b436d7ca33840b1b697082d140a5040bdf3 (diff) | |
parent | f6282cbe0386d03b57a65450bc163b20bfecfb70 (diff) | |
download | vaadin-framework-927e424acc1e43a12bdbbcd971302d00717af540.tar.gz vaadin-framework-927e424acc1e43a12bdbbcd971302d00717af540.zip |
Merge remote-tracking branch 'origin/master' into grid
This merge needs Grid to use elemental.json instead of org.json
Change-Id: Ib3c387c7e282b2502f266bafbdaad8727f5dc6ef
141 files changed, 5159 insertions, 1867 deletions
diff --git a/.classpath b/.classpath index 62c06df6c8..847fe8f769 100644 --- a/.classpath +++ b/.classpath @@ -24,6 +24,6 @@ <classpathentry kind="con" path="org.eclipse.jst.j2ee.internal.web.container"/> <classpathentry kind="con" path="org.eclipse.jst.j2ee.internal.module.container"/> <classpathentry kind="con" path="org.apache.ivyde.eclipse.cpcontainer.IVYDE_CONTAINER/?project=vaadin&ivyXmlPath=buildhelpers%2Fivy.xml&confs=ide&ivySettingsPath=%24%7Bworkspace_loc%3Avaadin%2Fivysettings.xml%7D&loadSettingsOnDemand=false&propertyFiles=build.properties"/> - <classpathentry kind="con" path="org.apache.ivyde.eclipse.cpcontainer.IVYDE_CONTAINER/?project=vaadin&ivyXmlPath=gwt%2Fivy.xml&confs=ide&ivySettingsPath=%24%7Bworkspace_loc%3Avaadin%2Fivysettings.xml%7D&loadSettingsOnDemand=false&propertyFiles=%24%7Bworkspace_loc%3Avaadin%2Fbuild.properties%7D"/> + <classpathentry exported="true" kind="con" path="org.apache.ivyde.eclipse.cpcontainer.IVYDE_CONTAINER/?project=vaadin&ivyXmlPath=gwt%2Fivy.xml&confs=ide&ivySettingsPath=%24%7Bworkspace_loc%3Avaadin%2Fivysettings.xml%7D&loadSettingsOnDemand=false&propertyFiles=%24%7Bworkspace_loc%3Avaadin%2Fbuild.properties%7D"/> <classpathentry kind="output" path="build/classes"/> </classpath> diff --git a/WebContent/VAADIN/themes/valo/_valo.scss b/WebContent/VAADIN/themes/valo/_valo.scss index f7d0534da1..8a2da5b789 100644 --- a/WebContent/VAADIN/themes/valo/_valo.scss +++ b/WebContent/VAADIN/themes/valo/_valo.scss @@ -48,7 +48,11 @@ @include valo-global; -// The main theme mixin +/** + * The main Valo theme mixin, which outputs all the selectors and properties to produce + * the variation specified by global variables. Should not be included multiple times + * per compilation. + */ @mixin valo { @include valo-common; @include valo-components; diff --git a/WebContent/VAADIN/themes/valo/components/_accordion.scss b/WebContent/VAADIN/themes/valo/components/_accordion.scss index e5457a2331..91ce4efe33 100644 --- a/WebContent/VAADIN/themes/valo/components/_accordion.scss +++ b/WebContent/VAADIN/themes/valo/components/_accordion.scss @@ -1,3 +1,10 @@ +/** + * Outputs the selectors and properties for the Accordion component. + * + * @param {string} $primary-stylename (v-accordion) - the primary style name for the selectors + * @param {bool}Â $include-additional-styles - should the mixin output all the different style variations of the component + * @group accordion + */ @mixin valo-accordion ($primary-stylename: v-accordion, $include-additional-styles: contains($v-included-additional-styles, accordion)) { .#{$primary-stylename} { @include valo-accordion-style; @@ -22,7 +29,9 @@ border-radius: 0; @include box-shadow(none); - > .#{$primary-stylename}-item { + > .#{$primary-stylename}-item, + > .#{$primary-stylename}-item > div > .v-caption, + > .#{$primary-stylename}-item > .#{$primary-stylename}-item-content { border-radius: 0; } } @@ -31,7 +40,10 @@ } - +/** + * Outputs the styles for the Accordion component root element. + * @group accordion + */ @mixin valo-accordion-style { @include valo-panel-style; $grad-style: valo-gradient-style($v-gradient); @@ -41,50 +53,64 @@ } +/** + * Outputs the styles for an individual Accordion item root element. + * @group accordion + */ @mixin valo-accordion-item-style { + $_br: $v-border-radius - first-number($v-border); position: relative; - overflow: hidden; @if $v-border-radius > 0 { - $_br: $v-border-radius - first-number($v-border); - &:first-child { - border-radius: $_br $_br 0 0; - - .v-caption { - border-radius: inherit; - } + border-top-left-radius: $_br; + border-top-right-radius: $_br; } &:last-child { - border-radius: 0 0 $_br $_br; + border-bottom-left-radius: $_br; + border-bottom-right-radius: $_br; - .v-caption { - border-radius: 0; + [class*="item-content"] { + border-radius: inherit; } } } - &:last-child:not([class*="item-open"]) .v-caption { + &[class*="item-open"]:last-child > div > .v-caption { + border-radius: 0; + } + + &:not([class*="item-open"]):last-child > div > .v-caption { border-bottom: none; + margin-bottom: 0; } &[class*="item-open"] + [class*="item"] { - border-top: valo-border($color: $v-panel-background-color, $strength: 0.7); + border-top: valo-border($border: $v-panel-border, $color: $v-panel-background-color, $strength: 0.7); } } - +/** + * Outputs the styles for an individual Accordion item's caption element. + * + * @param {color} $background-color (null) - the background color of the caption. Other styles (such as font and border colors, gradients and bevels) adapt to the background color automatically. + * @group accordion + */ @mixin valo-accordion-item-caption-style ($background-color: null) { - .v-caption { + border-radius: inherit; + + > .v-caption { @include valo-panel-caption-style($background-color: $background-color or $v-background-color); display: block; @if $background-color == null { background: transparent; } border-bottom-color: first-color(valo-border($color: $v-panel-background-color)); + border-radius: inherit; cursor: pointer; + position: relative; &:hover:before, &:active:before { @@ -94,6 +120,7 @@ right: 0; bottom: 0; left: 0; + border-radius: inherit; } @if $v-hover-styles-enabled { @@ -110,11 +137,11 @@ } +/** + * Outputs the styles for an individual Accordion item's content element. + * @group accordion + */ @mixin valo-accordion-item-content-style { - position: absolute; - width: 100%; - bottom: 0; - right: 0; @include box-shadow(valo-bevel-and-shadow($shadow: join(inset, $v-shadow), $shadow-opacity: $v-shadow-opacity/2)); background-color: $v-panel-background-color; @include box-sizing(border-box); diff --git a/WebContent/VAADIN/themes/valo/components/_all.scss b/WebContent/VAADIN/themes/valo/components/_all.scss index b41a2f3308..0efc363a82 100644 --- a/WebContent/VAADIN/themes/valo/components/_all.scss +++ b/WebContent/VAADIN/themes/valo/components/_all.scss @@ -42,13 +42,33 @@ @import "valo-menu"; +/** + * Outputs all the selectors and properties for all individual components to produce + * the variation specified by global variables. + * + * This mixin can be called multiple times for a theme, if you for instance wish to + * generate alternative color versions of the components. + * + * @example scss + * .my-theme { + * // The default color variation + * @include valo; + * + * .sidebar { + * // For the sidebar context, we generate a darker variant of all components + * $v-background-color: #696969; + * background-color: $v-background-color; + * @include valo-components; + * } + * } + */ @mixin valo-components { @if v-is-included(absolutelayout) { @include valo-absolutelayout; } - @if v-is-included(orderedlayout) { + @if v-is-included(orderedlayout) or v-is-included(verticallayout) or v-is-included(horizontallayout) { @include valo-orderedlayout; } diff --git a/WebContent/VAADIN/themes/valo/components/_button.scss b/WebContent/VAADIN/themes/valo/components/_button.scss index 42953ea610..eb57e20d2a 100644 --- a/WebContent/VAADIN/themes/valo/components/_button.scss +++ b/WebContent/VAADIN/themes/valo/components/_button.scss @@ -1,3 +1,11 @@ +/** + * Outputs the selectors and properties for the Button component. + * + * @param {string} $primary-stylename (v-button) - the primary style name for the selectors + * @param {bool}Â $include-additional-styles - should the mixin output all the different style variations of the component + * + * @group button + */ @mixin valo-button ($primary-stylename: v-button, $include-additional-styles: contains($v-included-additional-styles, button)) { .#{$primary-stylename} { @include valo-button-static-style; @@ -97,9 +105,14 @@ } - - - +/** + * Outputs the static styles (i.e. styles which don't differ between button variants) for a button. + * + * @param {list} $states (normal hover focus active disabled) - The button states for which to output corresponding static styles + * @param {bool} $vertical-centering (true) - Should the output contain a vertical centering guide + * + * @group button + */ @mixin valo-button-static-style ($states: (normal, hover, focus, active, disabled), $vertical-centering: true) { @if contains($states, normal) { position: relative; @@ -148,14 +161,30 @@ } - - - +/** + * Outputs the styles for a button variant. + * + * @param {size}Â $unit-size ($v-unit-size) - The sizing of the button, which corresponds its height + * @param {size | list} $padding (null) - The padding of the button. Computed from other parameters by default. + * @param {color} $font-color (null) - The font color of the button. Computed from the $background-color by default. + * @param {number} $font-weight ($v-font-weight + 100) - The font weight of the button + * @param {size} $font-size (null) - The font size of the button. Inherited from the parent by default. + * @param {string} $cursor (null) - The mouse cursor of the button + * @param {color} $background-color ($v-background-color) - The background color of the button + * @param {list} $border ($v-border) - The border of the button + * @param {size} $border-radius ($v-border-radius) - The border-radius of the button + * @param {list} $gradient ($v-gradient) - Valo specific gradient value. See the documentation for $v-gradient. + * @param {list} $bevel ($v-bevel) - Box-shadow value according to $v-bevel documentation + * @param {list} $shadow ($v-shadow) - Box-shadow value according to $v-shadow documentation + * @param {list} $states (normal hover focus active disabled) - The button states for which to output corresponding styles + * + * @group button + */ @mixin valo-button-style ( $unit-size : $v-unit-size, - $padding : null, // Computed by default + $padding : null, - $font-color : null, // Computed by default + $font-color : null, $font-weight : $v-font-weight + 100, $font-size : null, // Inherited by default $cursor : null, @@ -207,7 +236,7 @@ } @if $bevel and type-of($_font-color) == color and type-of($background-color) == color { - text-shadow: valo-text-shadow($_font-color, $background-color, $bevel); + text-shadow: valo-text-shadow($_font-color, $background-color); } @if $bevel == none and $shadow == none { @@ -237,8 +266,14 @@ } - - +/** + * Outputs the hover state styles for a button. The styles are by default targeted + * for a pseudo element which is shown on top of the normal state button. + * + * @group button + * + * @param {color} $background-color ($v-background-color) - The background color of the normal state button + */ @mixin valo-button-hover-style ($background-color: $v-background-color) { $bg: darken($background-color, 25%); @if is-dark-color($background-color) { @@ -248,8 +283,16 @@ } - -@mixin valo-button-focus-style ($background-color: $v-background-color, $border-fallback: inherit, $include-box-shadow: true) { +/** + * Outputs the focus state styles for a button. The styles are by default targeted + * for a pseudo element which is shown on top of the normal state button. + * + * @group button + * + * @param {color} $background-color ($v-background-color) - The background color of the normal state button + * @param {list} $border-fallback (inherit) - If the luminance of $v-focus-color is less than the $background-color, the focus color is also used for the border color. If not, then $border-fallback is used for the focus element's border value. + */ +@mixin valo-button-focus-style ($background-color: $v-background-color, $border-fallback: inherit) { $focus-color: $v-focus-color; @if color-luminance($focus-color) + 50 < color-luminance($background-color) { @@ -258,22 +301,31 @@ border: $border-fallback or valo-border($color: $background-color); } - @include valo-focus-style($include-box-shadow: $include-box-shadow); + @include valo-focus-style; } - +/** + * Outputs the active state (pressed/down) styles for a button. The styles are by default targeted + * for a pseudo element which is shown on top of the normal state button. + * + * @group button + * + * @param {color} $background-color ($v-background-color) - The background color of the normal state button + */ @mixin valo-button-active-style ($background-color: $v-background-color) { $bg: scale-color($background-color, $lightness: -50%, $saturation: saturation($background-color)); background-color: rgba($bg, .2); } - - - +/** + * Outputs styles to allow vertical centering of the icon and the caption, independent of the + * height of the button. + * + * @group button + */ @mixin valo-button-vertical-centering { - // Vertical centering of icon and caption, independent of the height of the button @include valo-vertical-align-guide($to-align: div, $pseudo-element: before); // WebKit handles line-heights and vertical-alignments somewhat differently, so we need to adjust @@ -293,8 +345,14 @@ } - - +/** + * Output styles for a borderless button. Expects that the targeted element + * already has both valo-button-static-style and valo-button-style included. + * + * @param {color}Â $font-color (inherit) - The font color of the borderless button + * + * @group button + */ @mixin valo-button-borderless-style ($font-color: inherit) { border: none; @include box-shadow(none); @@ -321,7 +379,15 @@ } -@mixin valo-button-quiet-style ($primary-stylename: v-button) { +/** + * Output styles for a "quiet" button (a button whose outline is only shown + * once the user hovers over the button caption). Expects that the targeted + * element already has both valo-button-static-style and valo-button-style + * included. + * + * @group button + */ +@mixin valo-button-quiet-style { visibility: hidden; &:focus, @@ -329,19 +395,24 @@ visibility: visible; } - .#{$primary-stylename}-wrap { + [class*="wrap"] { visibility: visible; } - .#{$primary-stylename}-caption { + [class*="caption"] { // For IE8 display: inline-block; } } -@mixin valo-button-icon-align-right-style ($primary-stylename: v-button) { - .#{$primary-stylename}-wrap { +/** + * Output styles to align a button's icon on the right side of its caption. + * + * @group button + */ +@mixin valo-button-icon-align-right-style { + [class*="wrap"] { display: inline-block; } @@ -357,12 +428,17 @@ } -@mixin valo-button-icon-align-top-style ($primary-stylename: v-button) { +/** + * Output styles to align a button's icon on top of its caption. + * + * @group button + */ +@mixin valo-button-icon-align-top-style { height: auto; padding-top: ceil($v-unit-size/9); padding-bottom: ceil($v-unit-size/9); - .#{$primary-stylename}-wrap { + [class*="wrap"] { display: inline-block; } diff --git a/WebContent/VAADIN/themes/valo/components/_calendar.scss b/WebContent/VAADIN/themes/valo/components/_calendar.scss index 753291eea9..bf1dc1c3dc 100644 --- a/WebContent/VAADIN/themes/valo/components/_calendar.scss +++ b/WebContent/VAADIN/themes/valo/components/_calendar.scss @@ -1,6 +1,27 @@ +/** + * A list of colors for custom event colors. Can be an empty list of you don't + * need any custom event colors. + * + * @example javascript + * // Java code + * // 'event' is an instance of EditableCalendarEvent + * event.setStyleName("color1"); // 1st color in the list + * event.setStyleName("color2"); // 2nd color in the list + * // etc. + * + * @group calendar + */ $v-calendar-event-colors: #00ace0, #2d9f19, #d18100, #ce3812, #2d55cd !default; +/** + * Outputs the global selectors and properties for the Calendar component - styles which are + * considered mandatory for the component to work properly. + * + * @param {string} $primary-stylename (v-calendar) - the primary style name for the selectors + * + * @group calendar + */ @mixin valo-calendar-global ($primary-stylename: v-calendar) { .#{$primary-stylename}-month-day-scrollable { overflow-y: scroll; @@ -103,12 +124,13 @@ $v-calendar-event-colors: #00ace0, #2d9f19, #d18100, #ce3812, #2d55cd !default; } - - - - - - +/** + * Outputs the selectors and properties for the Calendar component. + * + * @param {string} $primary-stylename (v-calendar) - the primary style name for the selectors + * + * @group calendar + */ @mixin valo-calendar ($primary-stylename: v-calendar) { @@ -525,12 +547,23 @@ $v-calendar-event-colors: #00ace0, #2d9f19, #d18100, #ce3812, #2d55cd !default; } +/** + * Outputs the styles for the previous button. + * + * @group calendar + */ @mixin valo-calendar-prev-style { &:before { @include valo-tabsheet-scroller-prev-icon-style; } } + +/** + * Outputs the styles for the next button. + * + * @group calendar + */ @mixin valo-calendar-next-style { &:before { @include valo-tabsheet-scroller-next-icon-style; diff --git a/WebContent/VAADIN/themes/valo/components/_checkbox.scss b/WebContent/VAADIN/themes/valo/components/_checkbox.scss index 9fe360c6ed..7ad08ad74d 100644 --- a/WebContent/VAADIN/themes/valo/components/_checkbox.scss +++ b/WebContent/VAADIN/themes/valo/components/_checkbox.scss @@ -1,3 +1,11 @@ +/** + * Outputs the selectors and properties for the CheckBox component. + * + * @param {string} $primary-stylename (v-checkbox) - the primary style name for the selectors + * @param {bool}Â $include-additional-styles - should the mixin output all the different style variations of the component + * + * @group checkbox + */ @mixin valo-checkbox ($primary-stylename: v-checkbox, $include-additional-styles: contains($v-included-additional-styles, checkbox)) { .#{$primary-stylename} { @@ -20,12 +28,26 @@ } +/** + * Outputs the font icon to indicate the checked state. + * + * @group checkbox + */ @mixin valo-checkbox-icon-style { content: "\f00c"; font-family: FontAwesome; } +/** + * Outputs the styles for a checkbox variant. + * + * @param {color} $background-color ($v-background-color) - The background color of the checkbox + * @param {size}Â $unit-size ($v-unit-size) - The sizing of the checkbox. The width and height of the checkbox will be the unit-size divided by 2. + * @param {color}Â $selection-color ($v-selection-color) - The color of the checked state icon + * + * @group checkbox + */ @mixin valo-checkbox-style ($background-color: $v-background-color, $unit-size: $v-unit-size, $selection-color: $v-selection-color) { // So that we can use the same 'unit-size' for all component sizes @@ -57,7 +79,7 @@ margin: 0; &:focus ~ label:before { - @include valo-button-focus-style($background-color: $background-color, $border-fallback: null, $include-box-shadow: false); + @include valo-button-focus-style($background-color: $background-color, $border-fallback: null); @include box-shadow(valo-bevel-and-shadow($background-color: $background-color, $bevel: $v-bevel, $shadow: $v-shadow, $gradient: $v-gradient, $include-focus: true)); } diff --git a/WebContent/VAADIN/themes/valo/components/_colorpicker.scss b/WebContent/VAADIN/themes/valo/components/_colorpicker.scss index 4460aafb21..b859904e59 100644 --- a/WebContent/VAADIN/themes/valo/components/_colorpicker.scss +++ b/WebContent/VAADIN/themes/valo/components/_colorpicker.scss @@ -1,3 +1,11 @@ +/** + * Outputs the global selectors and properties for the ColorPicker component - styles which are + * considered mandatory for the component to work properly. + * + * @param {string} $primary-stylename (v-colorpicker) - the primary style name for the selectors + * + * @group colorpicker + */ @mixin valo-colorpicker-global ($primary-stylename: v-colorpicker) { $valo-colorpicker-pathPrefix: null; @if $v-relative-paths == false { @@ -73,10 +81,13 @@ } - - - - +/** + * Outputs the selectors and properties for the ColorPicker component. + * + * @param {string} $primary-stylename (v-colorpicker) - the primary style name for the selectors + * + * @group colorpicker + */ @mixin valo-colorpicker ($primary-stylename: v-colorpicker) { .#{$primary-stylename}-popup.v-window { diff --git a/WebContent/VAADIN/themes/valo/components/_combobox.scss b/WebContent/VAADIN/themes/valo/components/_combobox.scss index 93cb5393ee..0b756126ff 100644 --- a/WebContent/VAADIN/themes/valo/components/_combobox.scss +++ b/WebContent/VAADIN/themes/valo/components/_combobox.scss @@ -1,9 +1,17 @@ +/** + * Outputs the selectors and properties for the ComboBox component. + * + * @param {string} $primary-stylename (v-filterselect) - the primary style name for the selectors + * @param {bool}Â $include-additional-styles - should the mixin output all the different style variations of the component + * + * @group combobox + */ @mixin valo-combobox ($primary-stylename: v-filterselect, $include-additional-styles: contains($v-included-additional-styles, combobox)) { .#{$primary-stylename} { position: relative; width: $v-default-field-width; - @include valo-combobox-style($primary-stylename: $primary-stylename); + @include valo-combobox-style; white-space: nowrap; .v-icon { @@ -24,39 +32,11 @@ } .#{$primary-stylename}-suggestpopup { - @include valo-combobox-popup-style($primary-stylename: $primary-stylename); + @include valo-combobox-popup-style; } .#{$primary-stylename}-no-input { - cursor: pointer; - text-shadow: valo-text-shadow(); - - @if $v-border-radius != $v-textfield-border-radius { - border-radius: $v-border-radius; - } - - .#{$primary-stylename}-input { - @include user-select(none); - @include valo-gradient; - cursor: inherit; - @include box-shadow(valo-bevel-and-shadow($bevel: $v-bevel, $shadow: $v-shadow, $gradient: $v-gradient)); - @include valo-border-with-gradient($border: $v-border, $color: $v-background-color, $gradient: $v-gradient); - text-shadow: inherit; - text-overflow: ellipsis; - border-radius: inherit; - - &:focus { - @include valo-textfield-focus-style($bevel: $v-bevel, $shadow: $v-shadow, $gradient: $v-gradient, $background-color: $v-background-color); - } - } - - .#{$primary-stylename}-button { - border-left: none !important; - } - - &:hover .#{$primary-stylename}-button:before { - color: inherit; - } + @include valo-combobox-no-input-style; } @@ -110,16 +90,29 @@ } - - - - +/** + * Outputs the styles for a combobox variant. + * + * @param {size}Â $unit-size ($v-unit-size) - The sizing of the combobox, which corresponds its height + * @param {color} $font-color (null) - The font color of the combobox. Computed from the $background-color by default. + * @param {number} $font-weight (max(400, $v-font-weight)) - The font weight of the combobox + * @param {size} $font-size (null) - The font size of the combobox. Inherited from the parent by default. + * @param {color} $background-color ($v-textfield-background-color) - The background color of the combobox + * @param {list} $border ($v-textfield-border) - The border of the combobox + * @param {size} $border-radius ($v-textfield-border-radius) - The border-radius of the combobox + * @param {list} $gradient (none) - Valo specific gradient value. See the documentation for $v-gradient. + * @param {list} $bevel ($v-textfield-bevel) - Box-shadow value according to $v-bevel documentation + * @param {list} $shadow ($v-textfield-shadow) - Box-shadow value according to $v-shadow documentation + * @param {list} $states (normal focus disabled) - The combobox states for which to output corresponding styles + * + * @group combobox + */ @mixin valo-combobox-style ( $unit-size: $v-unit-size, - $font-color: null, // Computed by default + $font-color: null, $font-weight: max(400, $v-font-weight), - $font-size: null, // Inherited by default + $font-size: null, $background-color: $v-textfield-background-color, $border: $v-textfield-border, @@ -129,14 +122,13 @@ $bevel: $v-textfield-bevel, $shadow: $v-textfield-shadow, - $primary-stylename: v-filterselect, $states: normal focus disabled ) { height: $unit-size; border-radius: $border-radius; - .#{$primary-stylename}-input { + [class*="input"] { @include valo-combobox-input-style( $unit-size: $unit-size, $gradient: $gradient, @@ -151,7 +143,7 @@ $states: $states); } - .v-icon + .#{$primary-stylename}-input { + .v-icon + [class*="input"] { padding-left: $unit-size; } @@ -171,17 +163,17 @@ padding-top: .12em; } - &.#{$primary-stylename}-prompt > .#{$primary-stylename}-input { + &[class*="prompt"] > [class*="input"] { @include valo-textfield-prompt-style($background-color); } - .#{$primary-stylename}-button { - @include valo-combobox-button-style($unit-size: $unit-size, $bevel: $bevel, $background-color: $background-color); + [class$="button"] { + @include valo-combobox-button-style($unit-size: $unit-size, $bevel: $bevel, $background-color: $background-color, $border-radius: $border-radius, $border: $border); } &.v-disabled { @include opacity($v-textfield-disabled-opacity); - & .#{$primary-stylename}-button { + & [class$="button"] { cursor: default; pointer-events: none; &:active:after { @@ -191,11 +183,11 @@ } &.v-readonly { - .#{$primary-stylename}-input { + [class*="input"] { @include valo-textfield-readonly-style; } - .#{$primary-stylename}-button { + [class$="button"] { cursor: default; pointer-events: none; &:active:after { @@ -206,18 +198,34 @@ } - - +/** + * Outputs the styles for a combobox variant input element. + * + * @param {size}Â $unit-size ($v-unit-size) - The sizing of the input (affects the padding only, width and height are 100%) + * @param {size | list} $padding (null) - The padding of the input. Computed from other parameters by default. + * @param {color} $font-color (null) - The font color of the input. Computed from the $background-color by default. + * @param {number} $font-weight (null) - The font weight of the input. Inherited from the parent by default. + * @param {size} $font-size (null) - The font size of the combobox. Inherited from the parent by default. + * @param {color} $background-color ($v-textfield-background-color) - The background color of the input + * @param {list} $border ($v-textfield-border) - The border of the input + * @param {size} $border-radius ($v-textfield-border-radius) - The border-radius of the input + * @param {list} $gradient (none) - Valo specific gradient value. See the documentation for $v-gradient. + * @param {list} $bevel ($v-textfield-bevel) - Box-shadow value according to $v-bevel documentation + * @param {list} $shadow ($v-textfield-shadow) - Box-shadow value according to $v-shadow documentation + * @param {list} $states (normal focus disabled) - The combobox states for which to output corresponding styles + * + * @group combobox + */ @mixin valo-combobox-input-style ( $unit-size: $v-unit-size, - $padding: null, // Computed by default + $padding: null, - $font-color: null, // Computed by default - $font-weight: null, // Inherited by default - $font-size: null, // Inherited by default + $font-color: null, + $font-weight: null, + $font-size: null, $background-color: $v-textfield-background-color, - $border: $v-border, + $border: $v-textfield-border, $border-radius: $v-textfield-border-radius, $gradient: none, @@ -246,13 +254,19 @@ } - - - - - -@mixin valo-combobox-button-style ($unit-size: $v-unit-size, $bevel: $v-bevel, $background-color: $v-textfield-background-color) { - $border-width: first-number($v-textfield-border); +/** + * Outputs the styles for a combobox variant button element. + * + * @param {size}Â $unit-size ($v-unit-size) - The sizing of the button, which corresponds its width. + * @param {list} $bevel ($v-textfield-bevel) - Box-shadow value according to $v-bevel documentation + * @param {color} $background-color ($v-textfield-background-color) - The background color of the input, which affects the font color of the button + * @param {size} $border-radius ($v-textfield-border-radius) - The border-radius of the input, which affects the border-radius of the button + * @param {list} $border ($v-textfield-border) - The border of the input, which affects the border of the button + * + * @group combobox + */ +@mixin valo-combobox-button-style ($unit-size: $v-unit-size, $bevel: $v-bevel, $background-color: $v-textfield-background-color, $border-radius: $v-border-radius, $border: $v-textfield-border) { + $border-width: first-number($v-textfield-border) or 0; @include valo-tappable; position: absolute; top: $border-width; @@ -310,16 +324,23 @@ } - +/** + * Outputs the font icon styles for the combobox drop down button. + * + * @group combobox + */ @mixin valo-combobox-button-icon-style { font-family: FontAwesome; content: "\f078"; } - - -@mixin valo-combobox-popup-style ($primary-stylename: v-filterselect) { +/** + * Outputs the styles for a combobox popup. + * + * @group combobox + */ +@mixin valo-combobox-popup-style { @if $v-animations-enabled { @if $v-overlay-animate-in { @@ -331,11 +352,15 @@ // closing when the user selects an item } - .#{$primary-stylename}-suggestmenu { + [class$="suggestmenu"] { @include valo-selection-overlay-style($animate-in: false, $animate-out: false); - box-sizing: border-box; + @include box-sizing(border-box); position: relative; z-index: 1; + + &[style*="height"] { + @include box-sizing(content-box); + } } margin-top: ceil($v-unit-size/8) !important; @@ -355,7 +380,7 @@ @include valo-selection-item-selected-style; } - .#{$primary-stylename}-status { + [class$="status"] { position: absolute; right: $v-border-radius; $bg: scale-color($v-background-color, $lightness: -15%); @@ -371,7 +396,7 @@ pointer-events: none; @if $v-animations-enabled { - @include animation(valo-anim-slide-in-down 200ms 80ms backwards); + @include animation(valo-animate-in-slide-down 200ms 80ms backwards); } > * { @@ -396,9 +421,24 @@ color: valo-font-color($v-background-color); + &:after { + // Extend click target when hovering over (popup width might change between pages) + content: ""; + position: absolute; + display: block; + border-radius: 50%; + } + &:hover { @include opacity(1); background: rgba($v-background-color, .5); + + &:after { + top: -10px; + bottom: -10px; + left: -20px; + right: -20px; + } } span { @@ -434,3 +474,35 @@ display: none; } } + +@mixin valo-combobox-no-input-style { + cursor: pointer; + text-shadow: valo-text-shadow(); + + @if $v-border-radius != $v-textfield-border-radius { + border-radius: $v-border-radius; + } + + [class*="input"] { + @include user-select(none); + @include valo-gradient; + cursor: inherit; + @include box-shadow(valo-bevel-and-shadow($bevel: $v-bevel, $shadow: $v-shadow, $gradient: $v-gradient)); + @include valo-border-with-gradient($border: $v-border, $color: $v-background-color, $gradient: $v-gradient); + text-shadow: inherit; + text-overflow: ellipsis; + border-radius: inherit; + + &:focus { + @include valo-textfield-focus-style($bevel: $v-bevel, $shadow: $v-shadow, $gradient: $v-gradient, $background-color: $v-background-color); + } + } + + [class$="button"] { + border-left: none !important; + } + + &:hover [class$="button"]:before { + color: inherit; + } +} diff --git a/WebContent/VAADIN/themes/valo/components/_csslayout.scss b/WebContent/VAADIN/themes/valo/components/_csslayout.scss index b0fa4362e7..3525bcad5a 100644 --- a/WebContent/VAADIN/themes/valo/components/_csslayout.scss +++ b/WebContent/VAADIN/themes/valo/components/_csslayout.scss @@ -1,6 +1,20 @@ +/** + * The amount of spacing between different widgets in a component group. + * If null, a computed value is used ($v-border size * -1, or 1px if $v-border size is 0) + * + * @group csslayout + */ $v-component-group-spacing: null !default; +/** + * Outputs the additional styles for the CssLayout component. Does not produce any other output. + * + * @param {string} $primary-stylename (v-csslayout) - the primary style name for the selectors + * @param {bool}Â $include-additional-styles - should the mixin output all the different style variations of the component + * + * @group csslayout + */ @mixin valo-csslayout ($primary-stylename: v-csslayout, $include-additional-styles: contains($v-included-additional-styles, csslayout)){ @if $include-additional-styles { .#{$primary-stylename}-well { @@ -20,6 +34,18 @@ $v-component-group-spacing: null !default; } +/** + * Outputs the styles for a horizontal component group. The target component is + * expected to be a CssLayout, which is a single DIV element with child components + * directly inside. + * + * @group csslayout + * + * @example scss + * .my-csslayout { + * @include valo-component-group; + * } + */ @mixin valo-component-group { white-space: nowrap; position: relative; diff --git a/WebContent/VAADIN/themes/valo/components/_datefield.scss b/WebContent/VAADIN/themes/valo/components/_datefield.scss index 81c7fa0e5e..b1d5dcce5b 100644 --- a/WebContent/VAADIN/themes/valo/components/_datefield.scss +++ b/WebContent/VAADIN/themes/valo/components/_datefield.scss @@ -1,9 +1,17 @@ +/** + * Outputs the selectors and properties for the DateField component. + * + * @param {string} $primary-stylename (v-datefield) - the primary style name for the selectors + * @param {bool}Â $include-additional-styles - should the mixin output all the different style variations of the component + * + * @group datefield + */ @mixin valo-datefield ($primary-stylename: v-datefield, $include-additional-styles: contains($v-included-additional-styles, datefield)) { .#{$primary-stylename} { position: relative; width: $v-default-field-width; - @include valo-datefield-style($primary-stylename: $primary-stylename); + @include valo-datefield-style; } .#{$primary-stylename}-error { @@ -89,6 +97,13 @@ } +/** + * Outputs the selectors and properties for the InlineDateField component. + * + * @param {string} $primary-stylename (v-inline-datefield) - the primary style name for the selectors + * + * @group datefield + */ @mixin valo-inline-datefield ($primary-stylename: v-inline-datefield) { @include valo-datefield-calendarpanel-style(#{$primary-stylename}-calendarpanel); @@ -100,9 +115,19 @@ } - - - +/** + * Outputs the styles for a date field variant. + * + * @param {list} $bevel ($v-textfield-bevel) - Box-shadow value according to $v-bevel documentation + * @param {list} $shadow ($v-textfield-shadow) - Box-shadow value according to $v-shadow documentation + * @param {size}Â $unit-size ($v-unit-size) - The sizing of the datefield, which corresponds its height + * @param {list} $border ($v-textfield-border) - The border of the datefield + * @param {size} $border-radius ($v-textfield-border-radius) - The border-radius of the datefield + * @param {color} $background-color ($v-textfield-background-color) - The background color of the datefield + * @param {list} $states (normal focus disabled) - The datefield states for which to output corresponding styles + * + * @group datefield + */ @mixin valo-datefield-style ( $bevel : $v-textfield-bevel, $shadow : $v-textfield-shadow, @@ -110,14 +135,13 @@ $border : $v-textfield-border, $border-radius : $v-textfield-border-radius, $background-color : $v-textfield-background-color, - $primary-stylename : v-datefield, $states : normal focus disabled ) { height: $unit-size; border-radius: $border-radius; - .#{$primary-stylename}-textfield { + [class*="textfield"] { @include box-sizing(border-box); @include valo-textfield-style($bevel: $bevel, $shadow: $shadow, $unit-size: $unit-size, $border: $border, $border-radius: $border-radius, $background-color: $background-color, $states: $states) ; padding-left: $unit-size * 1.2; @@ -126,18 +150,18 @@ border-radius: inherit; } - &.#{$primary-stylename}-prompt > .#{$primary-stylename}-textfield { + &[class*="prompt"] > [class*="textfield"] { @include valo-textfield-prompt-style($background-color); } - .#{$primary-stylename}-button { + [class$="button"] { @include valo-datefield-button-style($unit-size: $unit-size, $bevel: $bevel, $background-color: $background-color, $border-radius: $border-radius, $border: $border); } &.v-disabled { @include opacity($v-disabled-opacity); - .#{$primary-stylename}-button { + [class$="button"] { cursor: default; pointer-events: none; &:active:after { @@ -147,11 +171,11 @@ } &.v-readonly { - .#{$primary-stylename}-textfield { + [class*="textfield"] { @include valo-textfield-readonly-style; } - .#{$primary-stylename}-button { + [class$="button"] { cursor: default; pointer-events: none; &:active:after { @@ -162,10 +186,19 @@ } - - +/** + * Outputs the styles for a date field variant button element. + * + * @param {size}Â $unit-size ($v-unit-size) - The sizing of the button, which corresponds its width. + * @param {list} $bevel ($v-textfield-bevel) - Box-shadow value according to $v-bevel documentation + * @param {color} $background-color ($v-textfield-background-color) - The background color of the input, which affects the font color of the button + * @param {size} $border-radius ($v-textfield-border-radius) - The border-radius of the input, which affects the border-radius of the button + * @param {list} $border ($v-textfield-border) - The border of the input, which affects the border of the button + * + * @group datefield + */ @mixin valo-datefield-button-style ($unit-size: $v-unit-size, $bevel: $v-bevel, $background-color: $v-textfield-background-color, $border-radius: $v-border-radius, $border: $v-textfield-border) { - $border-width: first-number($border) or first-number($v-textfield-border); + $border-width: first-number($border) or 0; @include valo-tappable; -webkit-appearance: none; background: transparent; @@ -223,16 +256,22 @@ } - - +/** + * Outputs the font icon styles for the date field drop down button. + * + * @group datefield + */ @mixin valo-datefield-button-icon-style { font-family: FontAwesome; content: "\f073"; } - - +/** + * Outputs the styles for a date field popup. + * + * @group datefield + */ @mixin valo-datefield-popup-style { @include valo-overlay-style; @@ -241,8 +280,9 @@ width: auto; table { - border-collapse: collapse; + border-collapse: collapse; border-spacing: 0; + margin: 0 auto; } td { @@ -253,6 +293,13 @@ } +/** + * Outputs the styles for calendar panel (i.e. month view). + * + * @param {string} $primary-stylename (v-datefield-calendarpanel) - the primary style name for the selectors + * + * @group datefield + */ @mixin valo-datefield-calendarpanel-style ($primary-stylename: v-datefield-calendarpanel) { .#{$primary-stylename} { font-size: $v-font-size; @@ -360,7 +407,7 @@ } td.#{$primary-stylename}-month { - width: round($v-unit-size * 3.5); + width: round($v-unit-size * 4); @include valo-datefield-calendarpanel-month-style; } @@ -409,8 +456,11 @@ } - - +/** + * Outputs the styles for an individual day element in a calendar panel. + * + * @group datefield + */ @mixin valo-datefield-calendarpanel-day-style { @include box-sizing(border-box); width: round($v-unit-size * 0.8); @@ -429,29 +479,60 @@ } } + +/** + * Outputs the hover state styles for an individual day element in a calendar panel. + * + * @group datefield + */ @mixin valo-datefield-calendarpanel-day-hover-style { color: $v-selection-color; } + +/** + * Outputs the styles for an individual day element, which are not part of the current month, in a calendar panel. + * + * @group datefield + */ @mixin valo-datefield-calendarpanel-day-offmonth-style { color: mix(valo-font-color($v-background-color), $v-background-color); background: transparent; } + +/** + * Outputs the styles for todays day element in a calendar panel. + * + * @group datefield + */ @mixin valo-datefield-calendarpanel-day-today-style { color: valo-font-color($v-background-color, 0.9); font-weight: max(600, $v-font-weight + 100); border-color: valo-font-color($v-background-color, 0.3); } + +/** + * Outputs the styles for the selected day element in a calendar panel. + * + * @group datefield + */ @mixin valo-datefield-calendarpanel-day-selected-style { color: valo-font-color($v-selection-color); @include valo-gradient($v-selection-color); border: none; + font-weight: max(600, $v-font-weight + 100); } + +/** + * Outputs the focus state styles for an individual day element in a calendar panel. + * + * @group datefield + */ @mixin valo-datefield-calendarpanel-day-focused-style { - @include valo-focus-style($include-box-shadow: true); + @include valo-focus-style; position: relative; // Show above other cells .v-ie8 & { @@ -460,26 +541,55 @@ } +/** + * Outputs the font icon styles for the next month button in a calendar panel. + * + * @group datefield + */ @mixin valo-datefield-calendarpanel-nextmonth-icon-style { font-family: FontAwesome; content: "\f105"; } + +/** + * Outputs the font icon styles for the previous month button in a calendar panel. + * + * @group datefield + */ @mixin valo-datefield-calendarpanel-prevmonth-icon-style { font-family: FontAwesome; content: "\f104"; } + +/** + * Outputs the font icon styles for the next year button in a calendar panel. + * + * @group datefield + */ @mixin valo-datefield-calendarpanel-nextyear-icon-style { font-family: FontAwesome; content: "\f101"; } + +/** + * Outputs the font icon styles for the previous year button in a calendar panel. + * + * @group datefield + */ @mixin valo-datefield-calendarpanel-prevyear-icon-style { font-family: FontAwesome; content: "\f100"; } + +/** + * Outputs the styles for the current month and year title element in a calendar panel. + * + * @group datefield + */ @mixin valo-datefield-calendarpanel-month-style { color: $v-selection-color; } diff --git a/WebContent/VAADIN/themes/valo/components/_dragwrapper.scss b/WebContent/VAADIN/themes/valo/components/_dragwrapper.scss index 1eaf078661..6e4859b82c 100644 --- a/WebContent/VAADIN/themes/valo/components/_dragwrapper.scss +++ b/WebContent/VAADIN/themes/valo/components/_dragwrapper.scss @@ -1,3 +1,10 @@ +/** + * Outputs the styles and selectors for the DragAndDropWrapper component. + * + * @param {string} $primary-stylename (v-ddwrapper) - the primary style name for the selectors + * + * @group drag-n-drop + */ @mixin valo-dragwrapper ($primary-stylename: v-ddwrapper) { [draggable=true] { @@ -103,8 +110,11 @@ } - - +/** + * Outputs the styles for a drop target when the drag is on top of it. + * + * @group drag-n-drop + */ @mixin valo-ddwrapper-box-hint-style { border-width: 2px; border-radius: $v-border-radius; diff --git a/WebContent/VAADIN/themes/valo/components/_formlayout.scss b/WebContent/VAADIN/themes/valo/components/_formlayout.scss index fc065cec3d..7a9e81b30a 100644 --- a/WebContent/VAADIN/themes/valo/components/_formlayout.scss +++ b/WebContent/VAADIN/themes/valo/components/_formlayout.scss @@ -1,7 +1,15 @@ +/** + * Outputs the selectors and properties for the FormLayout component. + * + * @param {string} $primary-stylename (v-formlayout) - the primary style name for the selectors + * @param {bool}Â $include-additional-styles - should the mixin output all the different style variations of the component + * + * @group formlayout + */ @mixin valo-formlayout ($primary-stylename: v-formlayout, $include-additional-styles: contains($v-included-additional-styles, formlayout)) { @include valo-formlayout-spacing; - @include valo-formlayout-margins; + @include valo-formlayout-margin; .#{$primary-stylename} > table { border-spacing: 0; @@ -53,91 +61,114 @@ @if $include-additional-styles { .#{$primary-stylename}.light { - @include valo-formlayout-light-style($primary-stylename); + @include valo-formlayout-light-style; } } } -@mixin valo-formlayout-margins ($primary-stylename: v-formlayout, $all: null, $top: $v-layout-margin-top, $right: $v-layout-margin-right, $bottom: $v-layout-margin-bottom, $left: $v-layout-margin-left) { - @if $all != null { - $top: $all; - $right: $all; - $bottom: $all; - $left: $all; - } - - .#{$primary-stylename}-margin-top > tbody > .#{$primary-stylename}-firstrow { - > .#{$primary-stylename}-captioncell, - > .#{$primary-stylename}-contentcell, - > .#{$primary-stylename}-errorcell { - padding-top: $top; - } - } - - .#{$primary-stylename}-margin-bottom > tbody > .#{$primary-stylename}-lastrow { - > .#{$primary-stylename}-captioncell, - > .#{$primary-stylename}-contentcell, - > .#{$primary-stylename}-errorcell { - padding-bottom: $bottom; - } - } - - .#{$primary-stylename}-margin-left > tbody > .#{$primary-stylename}-row > .#{$primary-stylename}-captioncell { +/** + * Outputs the styles for form layout margin. + * + * @param {list} $margin ($v-layout-margin-top $v-layout-margin-right $v-layout-margin-bottom $v-layout-margin-left) - The margin for the form layout (any valid CSS margin value) + * + * @group formlayout + */ +@mixin valo-formlayout-margin ($margin: $v-layout-margin-top $v-layout-margin-right $v-layout-margin-bottom $v-layout-margin-left) { + $top: 0; + $right: 0; + $bottom: 0; + $left: 0; + + @if length($margin) == 1 { + $top: $margin; + $right: $margin; + $bottom: $margin; + $left: $margin; + } @else if length($margin) == 2Â { + $top: nth($margin, 1); + $right: nth($margin, 2); + $bottom: nth($margin, 1); + $left: nth($margin, 2); + } @else if length($margin) == 3Â { + $top: nth($margin, 1); + $right: nth($margin, 2); + $bottom: nth($margin, 3); + $left: nth($margin, 2); + } @else if length($margin) == 4Â { + $top: nth($margin, 1); + $right: nth($margin, 2); + $bottom: nth($margin, 3); + $left: nth($margin, 4); + } + + [class*="margin-top"] > tbody > [class*="firstrow"] > td { + padding-top: $top; + } + + [class*="margin-bottom"] > tbody > [class*="lastrow"] > td { + padding-bottom: $bottom; + } + + [class*="margin-left"] > tbody > [class*="row"] > [class*="captioncell"] { padding-left: $left; } - .#{$primary-stylename}-margin-right > tbody > .#{$primary-stylename}-row > .#{$primary-stylename}-contentcell { + [class*="margin-right"] > tbody > [class*="row"] > [class*="contentcell"] { padding-right: $right; } } -@mixin valo-formlayout-spacing ($primary-stylename: v-formlayout, $vertical: $v-layout-spacing-vertical) { - .#{$primary-stylename}-spacing > tbody > .#{$primary-stylename}-row { - > .#{$primary-stylename}-captioncell, - > .#{$primary-stylename}-contentcell, - > .#{$primary-stylename}-errorcell { - padding-top: $vertical; - } +/** + * Outputs the styles for form layout spacing. + * + * @param {size} $vertical ($v-layout-spacing-vertical) - The vertical spacing between the rows in the form layout + * + * @group formlayout + */ +@mixin valo-formlayout-spacing ($vertical: $v-layout-spacing-vertical) { + [class*="spacing"] > tbody > [class*="row"] > td { + padding-top: $vertical; } -} - - + [class*="spacing"] > tbody > [class*="firstrow"] > td { + padding-top: 0; + } +} -@mixin valo-formlayout-light-style ($primary-stylename: v-formlayout, $row-height: $v-unit-size) { +/** + * Outputs the styles for a light style form layout. This mixin expects the target to have the normal styles of a form layout applied. + * + * @param {size}Â $row-height ($v-unit-size) - The height of an individual form layout row + * + * @group formlayout + */ +@mixin valo-formlayout-light-style ($row-height: $v-unit-size) { > table { padding: 0; } - > table > tbody > .#{$primary-stylename}-row { - > .#{$primary-stylename}-captioncell, - > .#{$primary-stylename}-contentcell, - > .#{$primary-stylename}-errorcell { - padding-top: 0; - height: $row-height; // Effectively min-height - } - } - - > table > tbody > .#{$primary-stylename}-row td { + > table > tbody > [class*="row"] > td { + padding-top: 0; + height: $row-height; // Effectively min-height border-bottom: valo-border($color: $v-app-background-color, $strength: 0.3); } - > table > tbody > .#{$primary-stylename}-lastrow td { + > table > tbody > [class*="lastrow"] > td { border-bottom: none; } - > table > tbody > .#{$primary-stylename}-row > .#{$primary-stylename}-captioncell { + > table > tbody > [class*="row"] > [class*="captioncell"] { color: valo-font-color($v-background-color, .5); text-align: right; padding-left: ceil($v-unit-size/3); line-height: $row-height; } - .#{$primary-stylename}-contentcell { + > table > tbody > [class*="row"] > [class*="contentcell"] { > .v-textfield, > .v-textarea, > .v-filterselect, @@ -156,6 +187,10 @@ background: transparent; border: none; color: inherit; + + &:focus { + box-shadow: none; + } } > .v-textfield-prompt, @@ -169,6 +204,17 @@ > .v-richtextarea { height: auto; } + + > .v-label-h2, + > .v-label-h3, + > .v-label-h4 { + border-bottom: none; + } + + > .v-label-h3, + > .v-label-h4 { + margin-top: 0; + } } .v-richtextarea { @@ -192,17 +238,4 @@ .v-checkbox { margin-left: ceil($v-unit-size/6); } - - > table > tbody > .#{$primary-stylename}-row > .#{$primary-stylename}-contentcell { - > .v-label-h2, - > .v-label-h3, - > .v-label-h4 { - border-bottom: none; - } - - > .v-label-h3, - > .v-label-h4 { - margin-top: 0; - } - } } diff --git a/WebContent/VAADIN/themes/valo/components/_label.scss b/WebContent/VAADIN/themes/valo/components/_label.scss index 7f4fef58d9..b59d3e0e21 100644 --- a/WebContent/VAADIN/themes/valo/components/_label.scss +++ b/WebContent/VAADIN/themes/valo/components/_label.scss @@ -1,24 +1,110 @@ -$v-font-weight--header: $v-font-weight - 100 !default; -$v-line-height--header: 1.1 !default; -$v-font-family--header: null !default; -$v-font-color--colored: $v-selection-color !default; - -$v-font-size--h1: 2.4em !default; -$v-font-size--h2: 1.6em !default; -$v-font-size--h3: 1.2em !default; -$v-font-size--large: 1.2em !default; -$v-font-size--small: 0.87em !default; - -$v-font-family--h1: $v-font-family--header !default; -$v-font-family--h2: $v-font-family--header !default; -$v-font-family--h3: $v-font-family--header !default; - -$v-letter-spacing--h1: -0.03em !default; -$v-letter-spacing--h2: -0.02em !default; -$v-letter-spacing--h3: 0 !default; -$v-letter-spacing--h4: 0 !default; - - +/** + * The font weight for headers. + * + * @group label + */ +$v-font-weight--header: $v-font-weight - 100 !default; + +/** + * The line height for headers. + * + * @group label + */ +$v-line-height--header: 1.1 !default; + +/** + * The font family for headers. + * + * @group label + */ +$v-font-family--header: null !default; + +/** + * The font color for colored style labels. + * + * @group label + */ +$v-font-color--colored: $v-selection-color !default; + +/** + * The font size for 1st level headers. + * + * @group label + */ +$v-font-size--h1: 2.4em !default; + +/** + * The font size for 2nd level headers. + * + * @group label + */ +$v-font-size--h2: 1.6em !default; + +/** + * The font size for 3rd level headers. + * + * @group label + */ +$v-font-size--h3: 1.2em !default; + +/** + * The font family for 1st level headers. + * + * @group label + */ +$v-font-family--h1: $v-font-family--header !default; + +/** + * The font family for 2nd level headers. + * + * @group label + */ +$v-font-family--h2: $v-font-family--header !default; + +/** + * The font family for 3rd level headers. + * + * @group label + */ +$v-font-family--h3: $v-font-family--header !default; + +/** + * The letter spacing for 1st level headers. + * + * @group label + */ +$v-letter-spacing--h1: -0.03em !default; + +/** + * The letter spacing for 2nd level headers. + * + * @group label + */ +$v-letter-spacing--h2: -0.02em !default; + +/** + * The letter spacing for 3rd level headers. + * + * @group label + */ +$v-letter-spacing--h3: 0 !default; + +/** + * The letter spacing for 4th level headers. + * + * @group label + */ +$v-letter-spacing--h4: 0 !default; + + +/** + * Outputs the selectors and styles for the Label component. + * + * @param {string} $primary-stylename (v-label) - the primary style name for the selectors + * @param {bool}Â $include-additional-styles - should the mixin output all the different style variations of the component + * + * @group label + */ @mixin valo-label ($primary-stylename: v-label, $include-additional-styles: contains($v-included-additional-styles, label)) { .#{$primary-stylename} { @@ -34,7 +120,7 @@ $v-letter-spacing--h4: 0 !default; h3, .#{$primary-stylename}-h3 { line-height: $v-line-height--header; font-weight: $v-font-weight--header; - color: valo-header-color($v-app-background-color); + color: valo-font-color($v-app-background-color, 0.92); } h1, .#{$primary-stylename}-h1 { @@ -65,7 +151,7 @@ $v-letter-spacing--h4: 0 !default; line-height: $v-line-height--header; font-weight: $v-font-weight + 200; font-size: $v-font-size--small; - color: valo-header-color($v-app-background-color, $contrast: 0.12); + color: valo-font-color($v-app-background-color, 0.74); text-transform: uppercase; letter-spacing: $v-letter-spacing--h4; margin-top: 2.4em; diff --git a/WebContent/VAADIN/themes/valo/components/_menubar.scss b/WebContent/VAADIN/themes/valo/components/_menubar.scss index 7368579d43..fee5b87e84 100644 --- a/WebContent/VAADIN/themes/valo/components/_menubar.scss +++ b/WebContent/VAADIN/themes/valo/components/_menubar.scss @@ -283,6 +283,7 @@ border-radius: 0; padding: first-number($v-border); @include box-shadow(none); + text-shadow: none; background: transparent; color: inherit; @@ -296,7 +297,6 @@ margin-right: max(1px, first-number($v-border)); border-radius: $v-border-radius; color: $v-selection-color; - text-shadow: valo-text-shadow($font-color: $v-selection-color, $offset: -1px); padding: 0 round($v-unit-size/3); @if $v-animations-enabled { diff --git a/WebContent/VAADIN/themes/valo/components/_nativeselect.scss b/WebContent/VAADIN/themes/valo/components/_nativeselect.scss index 1b7469ed2b..3f24d9293f 100644 --- a/WebContent/VAADIN/themes/valo/components/_nativeselect.scss +++ b/WebContent/VAADIN/themes/valo/components/_nativeselect.scss @@ -27,6 +27,6 @@ &:focus { outline: none; - @include valo-focus-style($include-box-shadow: true); + @include valo-focus-style; } } diff --git a/WebContent/VAADIN/themes/valo/components/_notification.scss b/WebContent/VAADIN/themes/valo/components/_notification.scss index 3cfa446f7d..ff5e2da8d6 100644 --- a/WebContent/VAADIN/themes/valo/components/_notification.scss +++ b/WebContent/VAADIN/themes/valo/components/_notification.scss @@ -33,23 +33,23 @@ $v-notification-title-color: $v-focus-color !default; @if $v-animations-enabled { .#{$primary-stylename}-animate-in { - @include animation(valo-placeholder-animate-in 100ms, valo-anim-fade-in 100ms); + @include animation(valo-animate-in-fade 180ms); - &.v-position-left { - @include animation(valo-placeholder-animate-in 200ms, valo-anim-slide-in-right 200ms); + &.v-position-top { + @include animation(valo-animate-in-slide-down 400ms); } - &.v-position-right { - @include animation(valo-placeholder-animate-in 200ms, valo-anim-slide-in-left 200ms); + &.v-position-bottom { + @include animation(valo-animate-in-slide-up 400ms); } } .#{$primary-stylename}-animate-out { - @include animation(valo-placeholder-animate-out 150ms, valo-anim-fade-out 150ms); + @include animation(valo-animate-out-fade 150ms); - &.v-position-left, - &.v-position-right { - @include animation(valo-placeholder-animate-out 120ms, valo-anim-drop-fade-out 120ms); + &.v-position-top, + &.v-position-bottom { + @include animation(valo-animate-out-slide-down-fade 200ms); } } } @@ -216,11 +216,12 @@ $v-notification-title-color: $v-focus-color !default; height: round($v-unit-size/1.5); line-height: round($v-unit-size/1.5) - 1px; cursor: pointer; - color: #000; + $color: if(is-dark-color($v-overlay-background-color), #fff, #000); + color: $color; @include opacity(.5); text-align: center; - border: first-number($v-border) solid #000; - border-color: rgba(0,0,0,.3); + border: first-number($v-border) solid $color; + border-color: rgba($color, .3); border-radius: 50%; @include transition(opacity 200ms); } @@ -230,8 +231,10 @@ $v-notification-title-color: $v-focus-color !default; } &:active:after { - background-color: #000; - color: #fff; + $color: if(is-dark-color($v-overlay-background-color), #000, #fff); + $bg: if(is-dark-color($v-overlay-background-color), #fff, #000); + background-color: $bg; + color: $color; @include opacity(.3); @include transition(none 200ms); } @@ -242,7 +245,7 @@ $v-notification-title-color: $v-focus-color !default; @mixin valo-notification-style { - background: valo-overlay-background-color(); + background: $v-overlay-background-color; @include box-shadow(0px 5px 15px 0px rgba(0,0,0,0.15)); padding: round($v-unit-size/2) round($v-unit-size/1.7); @@ -274,11 +277,11 @@ $v-notification-title-color: $v-focus-color !default; @if $v-animations-enabled { &[class*="animate-in"] { - @include animation(valo-placeholder-animate-in 200ms, valo-anim-slide-in-down 200ms); + @include animation(valo-animate-in-slide-down 300ms); } &[class*="animate-out"] { - @include animation(valo-placeholder-animate-out 200ms, valo-anim-slide-out-up 200ms); + @include animation(valo-animate-out-slide-up 200ms); } } } @@ -288,11 +291,11 @@ $v-notification-title-color: $v-focus-color !default; @if $v-animations-enabled { &[class*="animate-in"] { - @include animation(valo-placeholder-animate-in 200ms, valo-anim-slide-in-up 200ms); + @include animation(valo-animate-in-slide-up 300ms); } &[class*="animate-out"] { - @include animation(valo-placeholder-animate-out 200ms, valo-anim-slide-out-down 200ms); + @include animation(valo-animate-out-slide-down 200ms); } } } diff --git a/WebContent/VAADIN/themes/valo/components/_orderedlayout.scss b/WebContent/VAADIN/themes/valo/components/_orderedlayout.scss index dbe2490826..ae1347d0e3 100644 --- a/WebContent/VAADIN/themes/valo/components/_orderedlayout.scss +++ b/WebContent/VAADIN/themes/valo/components/_orderedlayout.scss @@ -140,7 +140,7 @@ -@mixin valo-orderedlayout ($include-additional-styles: contains($v-included-additional-styles, orderedlayout)) { +@mixin valo-orderedlayout ($include-additional-styles: contains($v-included-additional-styles, orderedlayout) or contains($v-included-additional-styles, verticallayout) or contains($v-included-additional-styles, horizontallayout)) { .v-margin-top { padding-top: $v-layout-margin-top; diff --git a/WebContent/VAADIN/themes/valo/components/_panel.scss b/WebContent/VAADIN/themes/valo/components/_panel.scss index 07e21cccbf..8a7cd72c7c 100644 --- a/WebContent/VAADIN/themes/valo/components/_panel.scss +++ b/WebContent/VAADIN/themes/valo/components/_panel.scss @@ -97,7 +97,7 @@ $v-panel-border: $v-border !default; font-weight: $v-caption-font-weight; font-size: $v-caption-font-size; @include box-shadow(valo-bevel-and-shadow($background-color: $bg, $bevel: $bevel, $shadow: $shadow, $gradient: $gradient)); - text-shadow: valo-text-shadow(valo-font-color($bg), $bg, $v-bevel); + text-shadow: valo-text-shadow(valo-font-color($bg), $bg); } diff --git a/WebContent/VAADIN/themes/valo/components/_popupview.scss b/WebContent/VAADIN/themes/valo/components/_popupview.scss index 794a6997de..12e294e8cc 100644 --- a/WebContent/VAADIN/themes/valo/components/_popupview.scss +++ b/WebContent/VAADIN/themes/valo/components/_popupview.scss @@ -8,9 +8,9 @@ .#{$primary-stylename} { @include valo-link-style; } - + .#{$primary-stylename}-popup { - @include valo-overlay-style($animate-in: v-popupview-animate-in 120ms, $animate-out: (valo-placeholder-animate-out 120ms, valo-anim-fade-out 120ms)); + @include valo-overlay-style($animate-in: v-popupview-animate-in 120ms, $animate-out: (valo-animate-out-fade 120ms)); .popupContent { @include valo-panel-adjust-content-margins; diff --git a/WebContent/VAADIN/themes/valo/components/_tabsheet.scss b/WebContent/VAADIN/themes/valo/components/_tabsheet.scss index ccd70c4328..7dafbe4624 100644 --- a/WebContent/VAADIN/themes/valo/components/_tabsheet.scss +++ b/WebContent/VAADIN/themes/valo/components/_tabsheet.scss @@ -1,8 +1,19 @@ +/** + * Should the tabsheet content changes be animated. + * + * @group tabsheet + */ $v-tabsheet-content-animation-enabled: $v-animations-enabled !default; - - +/** + * Outputs the global selectors and properties for the TabSheet component - styles which are + * considered mandatory for the component to work properly. + * + * @param {string} $primary-stylename (v-tabsheet) - the primary style name for the selectors + * + * @group tabsheet + */ @mixin valo-tabsheet-global ($primary-stylename: v-tabsheet) { .#{$primary-stylename}-hidetabs > .#{$primary-stylename}-tabcontainer, .#{$primary-stylename}-spacertd, @@ -48,9 +59,14 @@ $v-tabsheet-content-animation-enabled: $v-animations-enabled !default; } - - - +/** + * Outputs the selectors and properties for the TabSheet component. + * + * @param {string} $primary-stylename (v-tabsheet) - the primary style name for the selectors + * @param {bool}Â $include-additional-styles - should the mixin output all the different style variations of the component + * + * @group tabsheet + */ @mixin valo-tabsheet ($primary-stylename: v-tabsheet, $include-additional-styles: contains($v-included-additional-styles, tabsheet)) { .#{$primary-stylename} { &:not(.v-has-width) { @@ -77,7 +93,7 @@ $v-tabsheet-content-animation-enabled: $v-animations-enabled !default; @if $v-tabsheet-content-animation-enabled { .#{$primary-stylename}-tabsheetpanel > .v-scrollable > .v-widget { - @include valo-anim-fade-in(300ms); + @include valo-animate-in-fade(300ms); } $spinner-size: round($v-unit-size/2); @@ -85,37 +101,17 @@ $v-tabsheet-content-animation-enabled: $v-animations-enabled !default; .#{$primary-stylename}-deco { @include valo-spinner($size: $spinner-size); - height: 0 !important; - border-style: none; - display: block; + display: none; position: absolute; - z-index: -1; + z-index: 1; bottom: 50%; margin-bottom: round($v-unit-size/-2) - $spinner-size/2; left: 50%; margin-left: $spinner-size/-2; - opacity: 0; - - .v-ie8 & { - min-height: 0; - } } .#{$primary-stylename}-loading .#{$primary-stylename}-deco { - @include transition(opacity 200ms 200ms); - opacity: 1; - z-index: 1; - height: $spinner-size !important; - border-style: solid; - - .v-ie8 &, - .v-ie9 & { - border-style: none; - } - - .v-ie8 & { - min-height: 30px; - } + display: block; } } @@ -159,6 +155,11 @@ $v-tabsheet-content-animation-enabled: $v-animations-enabled !default; } +/** + * Outputs the styles for the tabcontainer element of a tabsheet. + * + * @group tabsheet + */ @mixin valo-tabsheet-tabcontainer-style ($primary-stylename: v-tabsheet) { position: relative; @include box-sizing(border-box); @@ -168,7 +169,7 @@ $v-tabsheet-content-animation-enabled: $v-animations-enabled !default; position: absolute; height: 0; // iOS panics with background color, creating black line artifacts - border-top: max(1px, first-number($v-border)) solid first-color(valo-border($strength: 0.5)); + border-top: max(1px, first-number($v-border)) solid first-color(valo-border($color: $v-app-background-color, $strength: 0.5)); bottom: 0; left: 0; right: 0; @@ -180,6 +181,11 @@ $v-tabsheet-content-animation-enabled: $v-animations-enabled !default; } +/** + * Outputs the styles for the tabitemcell element of a tabsheet. + * + * @group tabsheet + */ @mixin valo-tabsheet-tabitemcell-style ($primary-stylename: v-tabsheet) { vertical-align: bottom; @@ -269,6 +275,11 @@ $v-tabsheet-content-animation-enabled: $v-animations-enabled !default; } +/** + * Outputs the styles for the tab scroller element of a tabsheet. + * + * @group tabsheet + */ @mixin valo-tabsheet-scroller-style ($primary-stylename: v-tabsheet) { $border-color: first-color(valo-border($strength: 0.5)); @@ -352,24 +363,38 @@ $v-tabsheet-content-animation-enabled: $v-animations-enabled !default; } +/** + * Outputs the font icon styles for the previous button element of a tabsheet scroller. + * + * @group tabsheet + */ @mixin valo-tabsheet-scroller-prev-icon-style { font-family: FontAwesome; content: "\f053"; } +/** + * Outputs the font icon styles for the next button element of a tabsheet scroller. + * + * @group tabsheet + */ @mixin valo-tabsheet-scroller-next-icon-style { font-family: FontAwesome; content: "\f054"; } - - - - - - +/** + * Outputs the styles for the framed tabsheet style. + * + * @param {string}Â $primary-stylename (v-tabsheet) - The primary style name for the selectors + * @param {bool} $frame-inactive-tabs (true) - Should inactive tabs be framed as well (the active tab is always framed with this style) + * @param {bool} $outer-frame (true) - Should the frame contain the whole tabsheet (i.e. tabbar and tab content). If false, works like a "borderless" style. + * @param {size} $tab-spacing ($v-unit-size/10) - The spacing between tabs + * + * @group tabsheet + */ @mixin valo-tabsheet-framed-style ($primary-stylename: v-tabsheet, $frame-inactive-tabs: true, $outer-frame: true, $tab-spacing: round($v-unit-size/10)) { > .#{$primary-stylename}-tabcontainer { .v-caption { @@ -387,7 +412,7 @@ $v-tabsheet-content-animation-enabled: $v-animations-enabled !default; &:hover { background-color: darken($v-app-background-color, 3%); - border-bottom-color: first-color(valo-border($strength: 0.5)); + border-bottom-color: first-color(valo-border($color: $v-app-background-color, $strength: 0.5)); } } @@ -398,13 +423,13 @@ $v-tabsheet-content-animation-enabled: $v-animations-enabled !default; @if $frame-inactive-tabs { .#{$primary-stylename}-tabitem .v-caption { - border-color: first-color(valo-border($strength: 0.5)); + border-color: first-color(valo-border($color: $v-app-background-color, $strength: 0.5)); } } .#{$primary-stylename}-tabitem-selected .v-caption { background: $v-panel-background-color; - border-color: first-color(valo-border($strength: 0.5)); + border-color: first-color(valo-border($color: $v-app-background-color, $strength: 0.5)); border-bottom: none; padding-bottom: first-number($v-border); } @@ -429,7 +454,7 @@ $v-tabsheet-content-animation-enabled: $v-animations-enabled !default; } @if $outer-frame { - border: valo-border($strength: 0.5); + border: valo-border($color: $v-app-background-color, $strength: 0.5); border-top: none; } } @@ -437,7 +462,7 @@ $v-tabsheet-content-animation-enabled: $v-animations-enabled !default; &.padded-tabbar { > .#{$primary-stylename}-tabcontainer { @if $outer-frame { - border: valo-border($strength: 0.5); + border: valo-border($color: $v-app-background-color, $strength: 0.5); border-bottom: none; } @@ -452,19 +477,29 @@ $v-tabsheet-content-animation-enabled: $v-animations-enabled !default; } - - - - - - - +/** + * Outputs the styles for a tabsheet where the tabs are aligned to the position specified by the parameter in the tabbar. + * + * @param {string}Â $primary-stylename (v-tabsheet) - The primary style name for the selectors + * @param {string}Â $align (center) - The alignment of the tabs inside the tabbar. Possible values: left, right, center. + * + * @group tabsheet + */ @mixin valo-tabsheet-align-tabs-style ($primary-stylename: v-tabsheet, $align: center) { > .#{$primary-stylename}-tabcontainer { text-align: $align; } } + +/** + * Outputs the styles for a tabsheet where all tabs in the tabbar have equal width and span the entire width of the tabbar. + * + * @param {string}Â $primary-stylename (v-tabsheet) - The primary style name for the selectors + * @param {bool} $flex (false) - Should the size of the tabs be proportional to their content, i.e. should the available space in the tabbar be distributed to the tabs in relation to their content sizes. + * + * @group tabsheet + */ @mixin valo-tabsheet-equal-width-tabs-style ($primary-stylename: v-tabsheet, $flex: false) { > .#{$primary-stylename}-tabcontainer { table, @@ -491,6 +526,14 @@ $v-tabsheet-content-animation-enabled: $v-animations-enabled !default; } } + +/** + * Outputs the styles for a tabsheet where the icons of individual tabs are on top of the tab captions. + * + * @param {string}Â $primary-stylename (v-tabsheet) - The primary style name for the selectors + * + * @group tabsheet + */ @mixin valo-tabsheet-icons-on-top-style ($primary-stylename: v-tabsheet) { > div > .#{$primary-stylename}-tabs { .v-caption { @@ -514,6 +557,14 @@ $v-tabsheet-content-animation-enabled: $v-animations-enabled !default; } +/** + * Outputs the styles for a tabsheet where only the selected tab has the close button visible. + * Note that the other tabs can still be closed programmatically. + * + * @param {string}Â $primary-stylename (v-tabsheet) - The primary style name for the selectors + * + * @group tabsheet + */ @mixin valo-tabsheet-only-selected-closable-style ($primary-stylename: v-tabsheet) { > .#{$primary-stylename}-tabcontainer .#{$primary-stylename}-caption-close { visibility: hidden; @@ -525,6 +576,14 @@ $v-tabsheet-content-animation-enabled: $v-animations-enabled !default; } +/** + * Outputs the styles for a tabsheet where the tabbar has increased padding to separate the tabs + * inside it from their surrounding container. + * + * @param {string}Â $primary-stylename (v-tabsheet) - The primary style name for the selectors + * + * @group tabsheet + */ @mixin valo-tabsheet-padded-tabbar-style ($primary-stylename: v-tabsheet) { > .#{$primary-stylename}-tabcontainer .#{$primary-stylename}-tabs { padding: 0 round($v-unit-size/4); diff --git a/WebContent/VAADIN/themes/valo/components/_textarea.scss b/WebContent/VAADIN/themes/valo/components/_textarea.scss index 5e524bfb9e..ffd5ba855a 100644 --- a/WebContent/VAADIN/themes/valo/components/_textarea.scss +++ b/WebContent/VAADIN/themes/valo/components/_textarea.scss @@ -1,3 +1,11 @@ +/** + * Outputs the selectors and properties for the TextArea component. + * + * @param {string} $primary-stylename (v-textarea) - the primary style name for the selectors + * @param {bool}Â $include-additional-styles - should the mixin output all the different style variations of the component + * + * @group textarea + */ @mixin valo-textarea ($primary-stylename: v-textarea, $include-additional-styles: contains($v-included-additional-styles, textarea)) { .#{$primary-stylename} { @@ -51,13 +59,30 @@ } +/** + * Outputs the styles for a text area variant. + * + * @param {size}Â $unit-size ($v-unit-size) - The sizing of the text area, which corresponds its height + * @param {size | list} $padding (null) - The padding of the text area. Computed from other parameters by default. + * @param {color} $font-color (null) - The font color of the text area. Computed from the $background-color by default. + * @param {number} $font-weight (max(400, $v-font-weight)) - The font weight of the text area + * @param {size} $font-size (null) - The font size of the text area. Inherited from the parent by default. + * @param {color} $background-color ($v-textfield-background-color) - The background color of the text area + * @param {list} $border ($v-textfield-border) - The border of the text area + * @param {size} $border-radius ($v-textfield-border-radius) - The border-radius of the text area + * @param {list} $bevel ($v-textfield-bevel) - Box-shadow value according to $v-bevel documentation + * @param {list} $shadow ($v-textfield-shadow) - Box-shadow value according to $v-shadow documentation + * @param {list} $states (normal focus disabled) - The text area states for which to output corresponding styles + * + * @group textfield + */ @mixin valo-textarea-style ( $unit-size : $v-unit-size, - $padding : round($v-unit-size/6), // Computed by default + $padding : round($v-unit-size/6), - $font-color : null, // Computed by default - $font-weight : max(400, $v-font-weight), // Inherited by default - $font-size : null, // Inherited by default + $font-color : null, + $font-weight : max(400, $v-font-weight), + $font-size : null, $background-color : $v-textfield-background-color, $border : $v-textfield-border, @@ -71,8 +96,8 @@ @include valo-textfield-style($unit-size: $unit-size, $padding: $padding, $font-color: $font-color, - $font-weight: $font-weight, // Inherited by default - $font-size: $font-size, // Inherited by default + $font-weight: $font-weight, + $font-size: $font-size, $background-color: $background-color, $border: $border, diff --git a/WebContent/VAADIN/themes/valo/components/_textfield.scss b/WebContent/VAADIN/themes/valo/components/_textfield.scss index c194bd715f..f4ca3538bd 100644 --- a/WebContent/VAADIN/themes/valo/components/_textfield.scss +++ b/WebContent/VAADIN/themes/valo/components/_textfield.scss @@ -1,14 +1,60 @@ +/** + * The background color for text fields. + * @group textfield + */ $v-textfield-background-color: if(is-dark-color($v-app-background-color), darken($v-app-background-color, 4%), lighten($v-app-background-color, 8%)) !default; + +/** + * The background color for read-only text fields. + * @group textfield + */ $v-textfield-background-color--readonly: darkest-color($v-app-background-color, darken($v-textfield-background-color, 2%)); + +/** + * The bevel style for text fields. See the documentation for $v-bevel. + * @group textfield + */ $v-textfield-bevel: inset 0 1px 0 v-shade !default; + +/** + * The shadow style for text fields. See the documentation for $v-shadow. + * @group textfield + */ $v-textfield-shadow: 0 1px 0 (v-tint 2) !default; + +/** + * The font-weight for text fields. + * @group textfield + */ $v-textfield-font-weight: 400 !default; + +/** + * The border style for text fields. See the documentation for $v-border. + * @group textfield + */ $v-textfield-border: $v-border !default; + +/** + * The border-radius for text fields. See the documentation for $v-border-radius; + * @group textfield + */ $v-textfield-border-radius: $v-border-radius !default; -$v-textfield-disabled-opacity: $v-disabled-opacity !default; +/** + * The opacity for disabled text fields. + * @group textfield + */ +$v-textfield-disabled-opacity: $v-disabled-opacity !default; +/** + * Outputs the selectors and properties for the TextField component. + * + * @param {string} $primary-stylename (v-textfield) - the primary style name for the selectors + * @param {bool}Â $include-additional-styles - should the mixin output all the different style variations of the component + * + * @group textfield + */ @mixin valo-textfield ($primary-stylename: v-textfield, $include-additional-styles: contains($v-included-additional-styles, textfield)) { .#{$primary-stylename} { @@ -73,14 +119,30 @@ $v-textfield-disabled-opacity: $v-disabled-opacity !default; } - +/** + * Outputs the styles for a text field variant. + * + * @param {size}Â $unit-size ($v-unit-size) - The sizing of the text field, which corresponds its height + * @param {size | list} $padding (null) - The padding of the text field. Computed from other parameters by default. + * @param {color} $font-color (null) - The font color of the text field. Computed from the $background-color by default. + * @param {number} $font-weight (max(400, $v-font-weight)) - The font weight of the text field + * @param {size} $font-size (null) - The font size of the text field. Inherited from the parent by default. + * @param {color} $background-color ($v-textfield-background-color) - The background color of the text field + * @param {list} $border ($v-textfield-border) - The border of the text field + * @param {size} $border-radius ($v-textfield-border-radius) - The border-radius of the text field + * @param {list} $bevel ($v-textfield-bevel) - Box-shadow value according to $v-bevel documentation + * @param {list} $shadow ($v-textfield-shadow) - Box-shadow value according to $v-shadow documentation + * @param {list} $states (normal focus disabled) - The text field states for which to output corresponding styles + * + * @group textfield + */ @mixin valo-textfield-style ( $unit-size : $v-unit-size, - $padding : null, // Computed by default + $padding : null, - $font-color : null, // Computed by default + $font-color : null, $font-weight : max(400, $v-font-weight), - $font-size : null, // Inherited by default + $font-size : null, $background-color : $v-textfield-background-color, $border : $v-textfield-border, @@ -163,6 +225,13 @@ $v-textfield-disabled-opacity: $v-disabled-opacity !default; } +/** + * Outputs the styles for a text field input prompt. + * + * @param {color} $background-color ($v-textfield-background-color) - The background color of the text field + * + * @group textfield + */ @mixin valo-textfield-prompt-style ($background-color: $v-textfield-background-color) { @if $background-color == transparent { color: inherit; @@ -179,6 +248,16 @@ $v-textfield-disabled-opacity: $v-disabled-opacity !default; } +/** + * Outputs the styles for a text field focus state. + * + * @param {list} $bevel ($v-textfield-bevel) - Box-shadow value according to $v-bevel documentation + * @param {list} $shadow ($v-textfield-shadow) - Box-shadow value according to $v-shadow documentation + * @param {color} $background-color ($v-textfield-background-color) - The background color of the text field + * @param {list}Â $gradient (null) - Valo specific gradient value. See the documentation for $v-gradient. + * + * @group textfield + */ @mixin valo-textfield-focus-style ($bevel: $v-textfield-bevel, $shadow: $v-textfield-shadow, $background-color: $v-textfield-background-color, $gradient: null) { outline: none; @if $v-animations-enabled { @@ -197,6 +276,11 @@ $v-textfield-disabled-opacity: $v-disabled-opacity !default; } +/** + * Outputs the styles for a read-only text field. + * + * @group textfield + */ @mixin valo-textfield-readonly-style { background: $v-textfield-background-color--readonly; color: valo-font-color($v-textfield-background-color--readonly); @@ -208,7 +292,13 @@ $v-textfield-disabled-opacity: $v-disabled-opacity !default; } - +/** + * Outputs the styles for a borderless style text field. + * + * @param {color} $background-color (transparent) - The background color of the text field + * + * @group textfield + */ @mixin valo-textfield-borderless-style ($background-color: transparent) { border: none; border-radius: 0; @@ -231,8 +321,11 @@ $v-textfield-disabled-opacity: $v-disabled-opacity !default; } - - +/** + * Outputs the styles for a text field error state. + * + * @group textfield + */ @mixin valo-textfield-error-style { border-color: $v-error-indicator-color !important; $bg: scale-color($v-error-indicator-color, $lightness: 98%); @@ -241,11 +334,18 @@ $v-textfield-disabled-opacity: $v-disabled-opacity !default; } - - - - - +/** + * Outputs the selectors and styles for an inline-icon style for a text field. Included indipendently (i.e. not enclosed with a parent text field selector). + * + * @param {string} $primary-stylename (v-textfield) - The primary style name for the selectors + * @param {string | list} $stylenames (inline-icon) - The additional style names which will define the inline-icon style + * @param {string} $input-selector (null) - Additional selector for a nested input element which should be targeted + * @param {size} $unit-size ($v-unit-size) - The unit size which the resulting style will support + * @param {size}Â $font-size ($v-font-size) - The font size which the resulting style will support (needed for font icons) + * @param {size} $image-icon-size (16px) - The image icon height which the resulting style will support (needed to center the icon vertically inside the text field) + * + * @group text field + */ @mixin valo-textfield-inline-icon($primary-stylename: v-textfield, $stylenames: inline-icon, $input-selector: null, $unit-size: $v-unit-size, $font-size: $v-font-size, $image-icon-size: 16px) { $slot-selector: ""; $caption-selector: ""; diff --git a/WebContent/VAADIN/themes/valo/components/_valo-menu.scss b/WebContent/VAADIN/themes/valo/components/_valo-menu.scss index 9a9e597888..59d3ddca4b 100644 --- a/WebContent/VAADIN/themes/valo/components/_valo-menu.scss +++ b/WebContent/VAADIN/themes/valo/components/_valo-menu.scss @@ -75,6 +75,7 @@ $valo-menu-background-color: scale-color($v-app-background-color, $lightness: if @include valo-menubar-borderless-style; margin: round($v-unit-size/2) round($v-unit-size/5); display: block; + overflow: hidden; text-align: center; height: auto; color: inherit; @@ -83,6 +84,7 @@ $valo-menu-background-color: scale-color($v-app-background-color, $lightness: if color: inherit; white-space: normal; line-height: 1.4; + margin: 0; img.v-icon { width: round($v-unit-size * 1.5); @@ -93,6 +95,13 @@ $valo-menu-background-color: scale-color($v-app-background-color, $lightness: if margin: 0 auto .3em; border: valo-border(); } + + &:after { + top: 0; + right: 0; + bottom: 0; + left: 0; + } } .v-menubar-menuitem-selected { @@ -150,6 +159,10 @@ $valo-menu-background-color: scale-color($v-app-background-color, $lightness: if border-right: none; } + .valo-menu-part { + overflow: visible; + } + .valo-menu-toggle { display: inline-block; } @@ -271,7 +284,7 @@ $valo-menu-background-color: scale-color($v-app-background-color, $lightness: if padding: 0 round($v-unit-size) 0 round($v-unit-size/2); cursor: pointer; position: relative; - text-shadow: valo-text-shadow($font-color: $font-color, $background-color: $bg, $offset: -2px); + text-shadow: valo-text-shadow($font-color: $font-color, $background-color: $bg, $offset: 2px); @include transition(background-color 300ms, color 60ms); $diff: color-luminance($bg) - color-luminance($v-selection-color); @@ -297,7 +310,7 @@ $valo-menu-background-color: scale-color($v-app-background-color, $lightness: if color: $active-color; } } - + &.selected { background: if(is-dark-color($bg), darken($bg, 3%), lighten($bg, 5%)); diff --git a/WebContent/VAADIN/themes/valo/components/_window.scss b/WebContent/VAADIN/themes/valo/components/_window.scss index cdd2298499..574c14b3b6 100644 --- a/WebContent/VAADIN/themes/valo/components/_window.scss +++ b/WebContent/VAADIN/themes/valo/components/_window.scss @@ -1,8 +1,8 @@ $v-window-background-color: $v-panel-background-color !default; $v-window-border-radius: $v-border-radius !default; $v-window-shadow: 0 2px 10px (v-shade 2), 0 16px 80px -6px (v-shade 3), last($v-overlay-shadow) !default; -$v-window-animate-in: valo-placeholder-animate-in 140ms, valo-anim-fade-in 140ms !default; -$v-window-animate-out: valo-placeholder-animate-out 100ms, valo-anim-scale-down-fade-out 100ms !default; +$v-window-animate-in: valo-animate-in-fade 140ms !default; +$v-window-animate-out: valo-animate-out-scale-down-fade 100ms !default; $v-window-modality-curtain-background-color: #222 !default; @@ -12,7 +12,7 @@ $v-window-modality-curtain-background-color: #222 !default; 100% { opacity: 1; } } - @include keyframes(valo-anim-scale-down-fade-out) { + @include keyframes(valo-animate-out-scale-down-fade) { 100% { @include transform(scale(0.8)); opacity: 0; @@ -59,7 +59,7 @@ $v-window-modality-curtain-background-color: #222 !default; left: 0; @include radial-gradient(circle at 50% 50%, $v-window-modality-curtain-background-color, darken($v-window-modality-curtain-background-color, valo-gradient-opacity()), $fallback: $v-window-modality-curtain-background-color); @include opacity(max(0.2, 0.8 - valo-gradient-opacity()/100%)); - @include valo-anim-fade-in($duration: 400ms, $delay: 100ms); + @include valo-animate-in-fade($duration: 400ms, $delay: 100ms); .v-op12 & { // Opera 12 has a shitbreak with the fade-in (flickers) @@ -205,7 +205,7 @@ $v-window-modality-curtain-background-color: #222 !default; @include valo-panel-adjust-content-margins; > .v-formlayout { - @include valo-formlayout-margins($all: round($v-unit-size/3)); + @include valo-formlayout-margin(round($v-unit-size/3)); } position: relative; diff --git a/WebContent/VAADIN/themes/valo/shared/_contextmenu.scss b/WebContent/VAADIN/themes/valo/shared/_contextmenu.scss index 4b737416c2..7fd182b6cd 100644 --- a/WebContent/VAADIN/themes/valo/shared/_contextmenu.scss +++ b/WebContent/VAADIN/themes/valo/shared/_contextmenu.scss @@ -1,3 +1,9 @@ +/** + * Outputs the context menu selectors and styles, which is used by Table and Tree for instance. + * + * @requires {mixin} valo-selection-item-style + * @requires {mixin} valo-selection-item-selected-style + */ @mixin valo-contextmenu { .v-contextmenu { diff --git a/WebContent/VAADIN/themes/valo/shared/_global.scss b/WebContent/VAADIN/themes/valo/shared/_global.scss index 5c010c128d..049518af73 100644 --- a/WebContent/VAADIN/themes/valo/shared/_global.scss +++ b/WebContent/VAADIN/themes/valo/shared/_global.scss @@ -4,9 +4,22 @@ @import "tooltip"; -// Include global styles only once +/* + * A flag which is set to true when the global styles have been included in the compilation. + * Used to only include them once, if Valo is imported multiple times during the compilation + * (multiple theme support). + * + * @access private + * @type bool + */ $valo-global-included: false !default; +/* + * Global Valo related styles, containing styles which are necessary for the application + * and widgets to work correctly. + * + * @access private + */ @mixin valo-global { @if $valo-global-included == false { @@ -173,14 +186,16 @@ $valo-global-included: false !default; } - $valo-shared-pathPrefix: null; @if $v-relative-paths == false { $valo-shared-pathPrefix: "../valo/shared/"; } - +/** + * Styles for the application root element. Outputs font, font color, background color and default + * cursor styles. + */ @mixin valo-app-style { font: $v-font-weight #{$v-font-size}/#{$v-line-height} $v-font-family; color: $v-font-color; @@ -195,7 +210,13 @@ $valo-shared-pathPrefix: null; } } - +/** + * Common application styles, such as loading indicators, tooltip and context menu styles, + * caption and icon defaults, basic HTML element resets. + * Should only be included once (done automatically when including the main valo mixin). + * + * @requires {mixin} valo-app-style + */ @mixin valo-common { //@if & != null { @@ -351,7 +372,9 @@ $valo-shared-pathPrefix: null; - +/** + * Generic component caption styles (captions which are generated by layouts). + */ @mixin valo-caption-style { font-size: $v-caption-font-size; font-weight: $v-caption-font-weight; @@ -362,7 +385,11 @@ $valo-shared-pathPrefix: null; } - +/** + * Error indicator styles. The error indicator is by default a font character which you can style freely. + * + * @requires {mixin} valo-error-indicator-icon-style by default + */ @mixin valo-error-indicator-style { color: $v-error-indicator-color; font-weight: 600; @@ -374,18 +401,23 @@ $valo-shared-pathPrefix: null; } } +/** + * The error indicator icon style. Should be a font character or a font icon. + */ @mixin valo-error-indicator-icon-style { content: "!"; } - -// Make the BODY element scrollable instead of the .v-ui element. Scrolling the BODY works better on touch screens. -// NOTE: breaks percentage sized overlay elements -// @mixin valo-natural-page-scrolling -// @usage -// // Call without any parent selector somewhere in your theme -// =valo-natural-page-scrolling; +/** + * Make the BODY element scrollable instead of the .v-ui element. Scrolling the BODY usually + * works better on touch devices. You loose the ability to control the scroll position from + * the server side when using this. + * + * @example scss + * // Include without any parent selector + * @include valo-natural-page-scrolling; + */ @mixin valo-natural-page-scrolling { html { diff --git a/WebContent/VAADIN/themes/valo/shared/_loading-indicator.scss b/WebContent/VAADIN/themes/valo/shared/_loading-indicator.scss index 56aab30d2b..645e188b09 100644 --- a/WebContent/VAADIN/themes/valo/shared/_loading-indicator.scss +++ b/WebContent/VAADIN/themes/valo/shared/_loading-indicator.scss @@ -1,5 +1,3 @@ -// TODO make fallbacks for IE 8 & 9 - @-webkit-keyframes v-rotate-360 { to {-webkit-transform: rotate(360deg);} } @@ -13,9 +11,16 @@ to {transform: rotate(360deg);} } - -@mixin valo-spinner ($size: 24px, $thickness: 2px, $color: null, $speed: 500ms) { - $color: $color or $v-focus-color; +/** + * Creates a spinner to be used as a loading indicator. On browsers which do not + * support CSS animations, an animated GIF image is used as a fallback. + * + * @param {size} $size (24px) - the diameter of the spinner, in pixels. Should be divisible by 2, increased by 1px if not + * @param {size} $thickness (2px) - the thickness or width of the border of the spinner + * @param {color} $color ($v-focus-color) - the color of the border of the spinner + * @param {time} $speed (500ms) - the speed of the spinning animation + */ +@mixin valo-spinner ($size: 24px, $thickness: 2px, $color: $v-focus-color, $speed: 500ms) { // Make size divisible by 2, so that the rotation won't jiggle $size: round($size) + round($size) % 2; height: $size !important; @@ -59,9 +64,25 @@ - +/** + * The color of the main loading indicator bar. + * @type color + */ $v-loading-indicator-color: $v-focus-color !default; + +/** + * The height of the main loading indicator bar. + * + * @type size + */ $v-loading-indicator-bar-height: ceil($v-unit-size/10) !default; + +/** + * The height of the main loading indicator bar when the request to the server + * is taking longer than usual and the user is notified that they should wait. + * + * @type size + */ $v-loading-indicator-bar-height--wait: ceil($v-unit-size/6) !default; @@ -89,7 +110,11 @@ $v-loading-indicator-bar-height--wait: ceil($v-unit-size/6) !default; } - +/* + * Outputs the necessary styles to create the main loading indicator bar. + * + * @access private + */ @mixin valo-loading-bar { .v-loading-indicator { diff --git a/WebContent/VAADIN/themes/valo/shared/_overlay.scss b/WebContent/VAADIN/themes/valo/shared/_overlay.scss index dc54672cb6..926b00f529 100644 --- a/WebContent/VAADIN/themes/valo/shared/_overlay.scss +++ b/WebContent/VAADIN/themes/valo/shared/_overlay.scss @@ -1,40 +1,160 @@ -@function valo-overlay-background-color ($context: $v-background-color) { - @if is-dark-color($context) { - @return darken($context, 3%); - } - @return lighten($context, 2%); -} - - -$v-overlay-background-color: valo-overlay-background-color() !default; +/** + * The background color for overlay elements. + * + * @type color + * @group overlay + */ +$v-overlay-background-color: if(is-dark-color($v-background-color), darken($v-background-color, 3%), lighten($v-background-color, 2%)) !default; + +/** + * The corner radius for overlay elements. + * + * @type size (px) + * @group overlay + */ $v-overlay-border-radius: $v-border-radius !default; + +/** + * The border width for overlay elements. + * + * @type size (px) + * @group overlay + */ $v-overlay-border-width: first-number($v-border) !default; +/** + * The animation which is used when overlay elements are made visible. + * + * @type list + * @group overlay + */ $v-overlay-animate-in: valo-overlay-animate-in 120ms !default; -$v-overlay-animate-out: valo-placeholder-animate-out 120ms, valo-anim-fade-out 120ms !default; +/** + * The animation which is used when overlay elements are removed. + * + * @type list + * @group overlay + */ +$v-overlay-animate-out: valo-animate-out-fade 120ms !default; + +/** + * The padding on each size of overlay elements. + * + * @type size + * @group overlay + */ $v-overlay-padding: round($v-unit-size/9) !default; + +/** + * The padding on the top and bottom edges of overlay elements. + * + * @type size + * @group overlay + */ $v-overlay-padding-vertical: $v-overlay-padding !default; + +/** + * The padding on the left and right edges of overlay elements. + * + * @type size + * @group overlay + */ $v-overlay-padding-horizontal: $v-overlay-padding !default; +/** + * The shadow used for overlay elements. + * + * @type list + * @group overlay + */ $v-overlay-shadow: 0 4px 10px 0 (v-shade 2), 0 3px 5px 0 v-shade, 0 0 0 $v-overlay-border-width (v-shade (2.5 - color-luminance($v-background-color)/255 + $v-bevel-depth/100%)) !default; +/** + * The background color for selection overlays, i.e. overlays which present a + * list of options for the user to choose from, such as context menus and drop down + * menus. + * + * @type color + * @group overlay + */ $v-selection-overlay-background-color: $v-overlay-background-color !default; + +/** + * The padding on each size of selection overlay elements. + * + * @type size + * @group overlay + */ $v-selection-overlay-padding: $v-overlay-padding !default; + +/** + * The padding on the top and bottom edges of selection overlay elements. + * + * @type size + * @group overlay + */ $v-selection-overlay-padding-vertical: $v-selection-overlay-padding !default; + +/** + * The padding on the left and right edges of selection overlay elements. + * + * @type size + * @group overlay + */ $v-selection-overlay-padding-horizontal: $v-selection-overlay-padding !default; +/** + * The corner radius for selection overlay elements. + * + * @type size (px) + * @group overlay + */ $v-selection-item-border-radius: $v-border-radius - 1px !default; + +/** + * The height of individual selection overlay list items. + * + * @type size (px) + * @group overlay + */ $v-selection-item-height: ceil($v-unit-size/1.4) !default; + +/** + * The horizontal padding for individual selection overlay list items. + * + * @type size + * @group overlay + */ $v-selection-item-padding-horizontal: ceil($v-unit-size/4) !default; + +/** + * The font weight for individual selection overlay list items. + * + * @type number | identifier + * @group overlay + */ $v-selection-item-font-weight: max(400, $v-font-weight); -$v-selection-item-selection-color: $v-selection-color !default; +/** + * The font color for individual selection overlay list items. + * + * @type color + * @group overlay + */ +$v-selection-item-selection-color: $v-selection-color !default; +/* + * Simulates CSS box-shadow using the extraneous shadow elements in the DOM. + * + * @access private + * @deprecated The .v-shadow element is deprecated since 7.3.0 + * @group overlay + */ @mixin valo-ie8-shadow($shadow, $element: top) { .#{$element} { $shadow-offset-x: nth($shadow, 1); @@ -97,7 +217,16 @@ $v-selection-item-selection-color: $v-selection-color !default; - +/** + * Outputs styles for overlay elements + * + * @group overlay + * + * @param {color} $background-color ($v-overlay-background-color) - the background color for the overlay + * @param {list} $shadow ($v-overlay-shadow) - the shadow for the overlay + * @param {list} $animate-in ($v-overlay-animate-in) - the animation used when the overlay is made visible + * @param {list} $animate-out ($v-overlay-animate-out) - the animation used when the overlay is removed + */ @mixin valo-overlay-style ( $background-color: $v-overlay-background-color, $shadow: $v-overlay-shadow, @@ -135,7 +264,15 @@ $v-selection-item-selection-color: $v-selection-color !default; - +/** + * Outputs styles for selection overlay elements. + * + * @group overlay + * + * @param {color} $background-color ($v-selection-overlay-background-color) - the background color for the overlay + * @param {list} $animate-in ($v-overlay-animate-in) - the animation used when the selection overlay is made visible + * @param {list} $animate-out ($v-overlay-animate-out) - the animation used when the selection overlay is removed + */ @mixin valo-selection-overlay-style ($background-color: $v-selection-overlay-background-color, $animate-in: $v-overlay-animate-in, $animate-out: $v-overlay-animate-out) { @include valo-overlay-style($background-color: $background-color, $animate-in: $animate-in, $animate-out: $animate-out); padding: $v-selection-overlay-padding-vertical $v-selection-overlay-padding-horizontal; @@ -143,7 +280,11 @@ $v-selection-item-selection-color: $v-selection-color !default; - +/** + * Outputs the styles for selection item elements (i.e. individual items in context menus and drop down menus). + * + * @group overlay + */ @mixin valo-selection-item-style { cursor: pointer; line-height: $v-selection-item-height; @@ -178,7 +319,11 @@ $v-selection-item-selection-color: $v-selection-color !default; - +/** + * Outputs the styles for selected selection item elements. + * + * @group overlay + */ @mixin valo-selection-item-selected-style { @include valo-gradient($v-selection-item-selection-color); $font-color: valo-font-color($v-selection-item-selection-color, 0.9); @@ -192,13 +337,24 @@ $v-selection-item-selection-color: $v-selection-color !default; - +/** + * Outputs the selectors and styles for generic dragging ghost elements. + * + * @group drag-n-drop + */ @mixin valo-drag-element { .v-drag-element { @include valo-drag-element-style; } } +/** + * Outputs the styles for generic dragging ghost elements. + * + * @group drag-n-drop + * + * @param {color} $background-color ($v-app-background-color) - the background color for the ghost element + */ @mixin valo-drag-element-style ($background-color: $v-app-background-color) { background: $background-color; color: valo-font-color($background-color); diff --git a/WebContent/VAADIN/themes/valo/shared/_tooltip.scss b/WebContent/VAADIN/themes/valo/shared/_tooltip.scss index 7b7b83ff33..3c9c914499 100644 --- a/WebContent/VAADIN/themes/valo/shared/_tooltip.scss +++ b/WebContent/VAADIN/themes/valo/shared/_tooltip.scss @@ -1,16 +1,81 @@ -// @category Tooltip - +/** + * The backgound color for tooltips. + * + * @type color + * @group tooltip + */ $v-tooltip-background-color: rgba(if(is-dark-color($v-background-color), scale-color($v-background-color, $lightness: 80%), scale-color($v-background-color, $lightness: -80%)), .9) !default; + +/** + * The font color for tooltips. + * + * @type color + * @group tooltip + */ $v-tooltip-font-color: valo-font-color(opacify($v-tooltip-background-color, 1), 1) !default; + +/** + * The font size for tooltips. + * + * @type size + * @group tooltip + */ $v-tooltip-font-size: max(12px, round($v-font-size * 0.86)) !default; + +/** + * The CSS box shadow for tooltips. + * + * @type list + * @group tooltip + */ $v-tooltip-box-shadow: 0 2px 12px rgba(#000, .2) !default; + +/** + * The vertical padding for tooltips. + * + * @type size + * @group tooltip + */ $v-tooltip-padding-vertical: round($v-unit-size/8) !default; + +/** + * The horizontal padding for tooltips. + * + * @type size + * @group tooltip + */ $v-tooltip-padding-horizontal: round($v-unit-size/4) !default; + +/** + * The backgound color for error tooltips. + * + * @type color + * @group tooltip + */ $v-tooltip-error-message-background-color: #fff !default; + +/** + * The font color for error tooltips. + * + * @type color + * @group tooltip + */ $v-tooltip-error-message-font-color: $v-error-indicator-color !default; + +/** + * The corner radius for tooltips. + * + * @type size + * @group tooltip + */ $v-tooltip-border-radius: $v-border-radius - 1px !default; +/** + * Outputs the selectors and styles for tooltip elements. + * + * @group tooltip + */ @mixin valo-tooltip { .v-tooltip { @include valo-tooltip-style; @@ -54,7 +119,11 @@ $v-tooltip-border-radius: $v-border-radius - 1px !default; } } - +/** + * Outputs the main styles for tooltip elements. + * + * @group tooltip + */ @mixin valo-tooltip-style { background-color: opacify($v-tooltip-background-color, 1); // For IE8 background-color: $v-tooltip-background-color; diff --git a/WebContent/VAADIN/themes/valo/shared/_variables.scss b/WebContent/VAADIN/themes/valo/shared/_variables.scss index 7dd3827298..4634a71fea 100644 --- a/WebContent/VAADIN/themes/valo/shared/_variables.scss +++ b/WebContent/VAADIN/themes/valo/shared/_variables.scss @@ -1,88 +1,459 @@ // Color functions are used to calculate default font color @import "../util/color"; - - -// A static text that is shown while the application JavaScript is loaded and started -$v-app-loading-text : "" !default; - - -// Base line height used for all widgets -$v-line-height : 1.55 !default; - - -$v-background-color : hsl(210, 0%, 98%) !default; -$v-app-background-color : $v-background-color !default; - -$v-font-size : 16px !default; // Should be specified in pixels -$v-font-weight : 300 !default; // Must be specified as a numeric value (i.e. not 'normal' or 'bold') -$v-font-color : valo-font-color($v-app-background-color) !default; -$v-font-family : "Open Sans", sans-serif !default; - -$v-caption-font-size : round($v-font-size * 0.9) !default; // Should be a pixel value -$v-caption-font-weight : max(400, $v-font-weight) !default; - -$v-unit-size : round(2.3 * $v-font-size) !default; // Must be specified in pixels (suitable range 18-50) - -$v-layout-margin-top : round($v-unit-size) !default; -$v-layout-margin-right : round($v-unit-size) !default; -$v-layout-margin-bottom : round($v-unit-size) !default; -$v-layout-margin-left : round($v-unit-size) !default; - -$v-layout-spacing-vertical : round($v-unit-size/3) !default; -$v-layout-spacing-horizontal : round($v-unit-size/3) !default; - -$v-border : 1px solid (v-shade 0.7) !default; // Size must be specified in pixels -$v-border-radius : 4px !default; // Must be specified in pixels - -$v-gradient : v-linear 8% !default; - -$v-bevel : inset 0 1px 0 v-tint, inset 0 -1px 0 v-shade !default; -$v-bevel-depth : 30% !default; - -$v-shadow : 0 2px 3px v-shade !default; -$v-shadow-opacity : 5% !default; - -$v-focus-color : valo-focus-color() !default; -$v-focus-style : 0 0 0 2px rgba($v-focus-color, .5) !default; - -$v-animations-enabled : true !default; -$v-hover-styles-enabled : true !default; - -$v-disabled-opacity : 0.5 !default; - -$v-selection-color : $v-focus-color !default; - -$v-default-field-width : $v-unit-size * 5 !default; - -$v-error-indicator-color : #ed473b !default; -$v-required-field-indicator-color : $v-error-indicator-color !default; -$v-friendly-color : #2c9720 !default; - - -$v-scaling-factor--tiny : 0.75 !default; -$v-scaling-factor--small : 0.85 !default; -$v-scaling-factor--large : 1.2 !default; -$v-scaling-factor--huge : 1.6 !default; - -$v-unit-size--tiny : round($v-unit-size * $v-scaling-factor--tiny) !default; -$v-unit-size--small : round($v-unit-size * $v-scaling-factor--small) !default; -$v-unit-size--large : round($v-unit-size * $v-scaling-factor--large) !default; -$v-unit-size--huge : round($v-unit-size * $v-scaling-factor--huge) !default; - -$v-font-size--tiny : ceil($v-font-size * $v-scaling-factor--tiny) !default; -$v-font-size--small : ceil($v-font-size * $v-scaling-factor--small) !default; -$v-font-size--large : ceil($v-font-size * $v-scaling-factor--large) !default; -$v-font-size--huge : ceil($v-font-size * $v-scaling-factor--huge) !default; - - - -// List of components to include in the theme compilation. The list can be modified to make -// the compiled theme smaller by removing unused components from the list. -// -// @usage -// // Remove the Calendar component styles from the output -// $v-included-components: remove($v-included-components, calendar); +/** + * A static text that is shown under the loading spinned while the client-side + * engine is being loaded and started. The text must be given in quotes. The + * text can not be localized currently. + * + * @type string, quoted + */ +$v-app-loading-text: "" !default; + +/** + * Base line height for all widgets. It must be given a unitless number. + * + * @group typography + * @type number + */ +$v-line-height: 1.55 !default; + +/** + * Base font size for the theme. The font size defines the overall sizing of + * UI components by default. Must be specified in pixels. + * + * @group typography + * @type size (px) + */ +$v-font-size: 16px !default; + +/** + * Base font weight for plain text. + * Must be specified as a numeric value: 100, 200, 300 (light), 400 (regular), + * 500, 600, 700 (bold), 800 or 900. + * + * @group typography + * @type number + */ +$v-font-weight: 300 !default; + +/** + * Base font family for the theme. Can be any valid CSS font stack. + * + * @group typography + * @type list + */ +$v-font-family: "Open Sans", sans-serif !default; + +/** + * Font size for generic component captions. Can be any valid CSS font-size. A + * round pixel value is recommended. + * + * @group typography + * @type number + */ +$v-caption-font-size: round($v-font-size * 0.9) !default; + +/** + * Font weight for generic component captions. Can be any valid CSS font-weight. + * + * @group typography + * @type number | identifier + */ +$v-caption-font-weight: max(400, $v-font-weight) !default; + +/** + * Border specification for the components that have a border. The border width + * must be specified in pixels. For the border color, you can specify any CSS color + * or one of the v-tint, v-shade, and v-tone keywords. + * + * @group style + * @type list + */ +$v-border: 1px solid (v-shade 0.7) !default; + +/** + * Corner radius for components that have a border. The measure must be specified as a + * single pixel value (i.e. not as a list of values for each corner). + * + * @group style + * @type size (px) + */ +$v-border-radius: 4px !default; + +/** + * Color gradient style for components that have a gradient. The gradient style may use + * the following keywords: v-linear and v-linear-reverse. The opacity must be given + * as percentage between 0% and 100%. + * + * #### Gradient styles + * + * - __v-linear__ - The start of the gradient is a lighter shade of the base color and the end is a darker shade of the base color. A basic linear gradient. + * - __v-linear-reverse__ - Same as v-linear, but the color stops are reversed (darker at the start and lighter at the end) + * + * @group style + * @type list + */ +$v-gradient: v-linear 8% !default; + +/** + * Inset shadow style to define how some components are "raised" from the background. + * The value follows the syntax of CSS box-shadow, and should be a list of insets. + * For the bevel color, you can specify any CSS color or one of the v-tint, v-shade, + * and v-tone keywords. + * + * @group style + * @type list + */ +$v-bevel: inset 0 1px 0 v-tint, inset 0 -1px 0 v-shade !default; + +/** + * Specifies the "depth" of the bevel shadow, as applied to one of the color keywords for + * the bevel style. The actual amount of tint, shade, or tone is computed from the depth. + * + * @group style + * @type number (pct) + */ +$v-bevel-depth: 30% !default; + +/** + * Default shadow style for all components. As with $v-bevel, the value follows the syntax + * of CSS box-shadow, but without the inset. For the shadow color, you can specify any CSS + * color or one of the v-tint or v-shade keywords. + * + * @group style + * @type list + */ +$v-shadow: 0 2px 3px v-shade !default; + +/** + * Specifies the opacity of the shadow, as applied to one of the color keywords for the + * shadow style. The actual amount of tint or shade is computed from the depth. + * + * @group style + * @type number (pct) + */ +$v-shadow-opacity: 5% !default; + +/** + * The background color is the main control parameter for the Valo theme and + * it is used for computing all other colors in the theme. If the color is dark + * (has low luminance), * light foreground colors that give high contrast + * with the background are automatically used. + * + * Can be any valid CSS color. + * + * @group color + * @type color + */ +$v-background-color: hsl(210, 0%, 98%) !default; + +/** + * Background color of the UI's root element. You can specify the color in + * any way allowed in CSS. Used as the base for other default colors, such + * as panel and window content areas. + * + * Can be any valid CSS color. + * + * @group color + * @type color + */ +$v-app-background-color: $v-background-color !default; + +/** + * Base font color for the theme. Can be any valid CSS color. + * + * @group color + * @type color + */ +$v-font-color: valo-font-color($v-app-background-color) !default; + +/** + * Color for the field focus indicator. The valo-focus-color() function computes a + * high-contrast color from the context, which is usually the background color. The color + * can be any CSS color. + * + * @group color + * @type color + */ +$v-focus-color: valo-focus-color() !default; + +/** + * Box-shadow specification for the field focus indicator. The space-separated values + * are the horizontal shadow position in pixels, vertical shadow position in pixels, + * blur distance in pixels, spread distance in pixels, and the color. The color can be + * any CSS color. You can only specify the color, in which case defaults for the position + * are used. rgba() or hsla() can be used to enable transparency. + * + * @group style + * @type list | color + */ +$v-focus-style: 0 0 0 2px rgba($v-focus-color, .5) !default; + +/** + * Opacity of disabled components, from 0 to 1. Not all components have reduced opacity when disabled, such as Labels. + * + * @group style + * @type number + */ +$v-disabled-opacity: 0.5 !default; + +/** + * Color for indicating selection in selection components. + * + * @group color + * @type color + */ +$v-selection-color: $v-focus-color !default; + +/** + * Color of the component error indicator and other error indications, such as the + * error style notification. + * + * @group color + * @type color + */ +$v-error-indicator-color: #ed473b !default; + +/** + * Color of the required indicator in field components. + * + * @group color + * @type color + */ +$v-required-field-indicator-color: $v-error-indicator-color !default; + +/** + * Color used for success states and to indicate safe actions (i.e. actions that + * will not cause any data loss). + * + * @group color + * @type color + */ +$v-friendly-color: #2c9720 !default; + +/** + * Color specifications for $v-border, $v-bevel, and $v-shadow may use, in addition to CSS colors, the following keywords: + * + * - __v-tint__ - Lighter than the background color + * - __v-shade__ - Darker than the background color + * - __v-tone__ - Adaptive color specification: darker on light background and lighter on dark background. Not usable in $v-shadow. + * + * + * These keywords can be further adjusted by combining them with a strength multiplier, specified in parenthesis. + * + * Examples: + * + * (v-tint 2) + * (v-shade 0.6) + * (v-tone 1.1) + * + * @group color + */ +$v-color-keywords: v-tint, v-shade, v-tone; + +/** + * This is the base size for various layout measures. It is directly used in some + * measures, such as button height and layout margins, while other measures are + * derived from it. The value must be specified in pixels, with a suitable range + * of 18-50. + * + * @group layout + * @type size (px) + */ +$v-unit-size: round(2.3 * $v-font-size) !default; + +/** + * Scaling factor for tiny sizes. Must be a unitless number. + * + * @group layout + * @type number + */ +$v-scaling-factor--tiny: 0.75 !default; + +/** + * Scaling factor for small sizes. Must be a unitless number. + * + * @group layout + * @type number + */ +$v-scaling-factor--small: 0.85 !default; + +/** + * Scaling factor for large sizes. Must be a unitless number. + * + * @group layout + * @type number + */ +$v-scaling-factor--large: 1.2 !default; + +/** + * Scaling factor for huge sizes. Must be a unitless number. + * + * @group layout + * @type number + */ +$v-scaling-factor--huge: 1.6 !default; + +/** + * Unit size for tiny components. Must be a pixel value. + * + * @group layout + * @type size (px) + */ +$v-unit-size--tiny: round($v-unit-size * $v-scaling-factor--tiny) !default; + +/** + * Unit size for small components. Must be a pixel value. + * + * @group layout + * @type size (px) + */ +$v-unit-size--small: round($v-unit-size * $v-scaling-factor--small) !default; + +/** + * Unit size for large components. Must be a pixel value. + * + * @group layout + * @type size (px) + */ +$v-unit-size--large: round($v-unit-size * $v-scaling-factor--large) !default; + +/** + * Unit size for huge components. Must be a pixel value. + * + * @group layout + * @type size (px) + */ +$v-unit-size--huge: round($v-unit-size * $v-scaling-factor--huge) !default; + +/** + * The top margin size for all built-in layout components, when the margin is + * enabled with setMargin(). Can be any valid CSS size. + * + * @group layout + * @type size + */ +$v-layout-margin-top: round($v-unit-size) !default; + +/** + * The right margin size for all built-in layout components, when the margin is + * enabled with setMargin(). Can be any valid CSS size. + * + * @group layout + * @type size + */ +$v-layout-margin-right: round($v-unit-size) !default; + +/** + * The bottom margin size for all built-in layout components, when the margin is + * enabled with setMargin(). Can be any valid CSS size. + * + * @group layout + * @type size + */ +$v-layout-margin-bottom: round($v-unit-size) !default; + +/** + * The left margin size for all built-in layout components, when the margin is + * enabled with setMargin(). Can be any valid CSS size. + * + * @group layout + * @type size + */ +$v-layout-margin-left: round($v-unit-size) !default; + +/** + * Amount of vertical space when spacing is enabled for a layout with setSpacing(). + * Can be any valid CSS size. + * + * @group layout + * @type size + */ +$v-layout-spacing-vertical: round($v-unit-size/3) !default; + +/** + * Amount of horizontal space when spacing is enabled for a layout with setSpacing(). + * Can be any valid CSS size. + * + * @group layout + * @type size + */ +$v-layout-spacing-horizontal: round($v-unit-size/3) !default; + +/** + * Tiny font size. + * + * @group typography + * @type size (px) + */ +$v-font-size--tiny: ceil($v-font-size * $v-scaling-factor--tiny) !default; + +/** + * Small font size. + * + * @group typography + * @type size (px) + */ +$v-font-size--small: ceil($v-font-size * $v-scaling-factor--small) !default; + +/** + * Large font size. + * + * @group typography + * @type size (px) + */ +$v-font-size--large: ceil($v-font-size * $v-scaling-factor--large) !default; + +/** + * Huge font size. + * + * @group typography + * @type size (px) + */ +$v-font-size--huge: ceil($v-font-size * $v-scaling-factor--huge) !default; + +/** + * Default width of certain field components, unless overridden with setWidth(). + * + * @group layout + * @type size (px) + */ +$v-default-field-width: $v-unit-size * 5 !default; + +/** + * Specifies whether various CSS animations are used. Not all animations are disabled when + * set to false, such as the default loading indicator animations. + * + * @group optimization + * @type bool + */ +$v-animations-enabled: true !default; + +/** + * Specifies whether various :hover styles are used for indicating that mouse pointer + * hovers over an element. + * + * @group optimization + * @type bool + */ +$v-hover-styles-enabled: true !default; + +/** + * List of components to include in the theme compilation. The list can be modified to make + * the compiled theme smaller by removing unused components from the list. + * + * @group optimization + * @type list + * + * @example scss + * // Remove the Calendar component styles from the output (must be declared after importing Valo) + * $v-included-components: remove($v-included-components, calendar); + * + * @example scss + * // Only include the Label, Button and Vertical and Horizontal layouts in the compilation + * $v-included-components: label, button, orderedlayout; + */ $v-included-components: absolutelayout, accordion, @@ -125,23 +496,43 @@ $v-included-components: window, valo-menu !default; - +/** + * List of components whose additional styles should be included in the compilation. + * + * @group optimization + * @type list + */ $v-included-additional-styles: $v-included-components !default; - -// Checks if a given component is included in the compilation. Used by the collection mixins that -// include all components, like valo-components and valo-components. -// @param $component-name {String} the name of the component to check -// @param $is-included {list} (Optional) the list of components which is checked -// @return {Boolean} true if the component is included in the compilation, false if not +/** + * Checks if a given component is included in the compilation. Used by the collection mixins that + * include all components (i.e. valo-components). + * + * @requires $v-included-components + * + * @example scss + * @if v-is-included(button) { + * // The Button component is included in the compilation + * } + * + * @param {string} $component-name - the name of the component to check + * @param {list} $is-included ($v-included-components) - the list of components which is checked + * + * @return {bool} true if the component is included in the compilation, false if not + * + * @group optimization + */ @function v-is-included ($component-name, $is-included: $v-included-components) { @return contains($is-included, $component-name); } - -// A flag to note whether relative URL paths are relative to the currently parsed SCSS file or to the compilation root file. -// The Vaadin compiler parses URL paths differently than the regular Sass compiler (i.e. Vaadin modifies relative url paths). -// This boolean is used to flag which compiler is used, so that paths are correct for different resources. -// false == Ruby, true == Vaadin +/** + * A flag to note whether relative URL paths are relative to the currently parsed SCSS file or to the compilation root file. + * The Vaadin compiler parses URL paths differently than the regular Sass compiler (i.e. Vaadin modifies relative url paths). + * This boolean is used to flag which compiler is used, so that paths are correct for different resources. + * false == Ruby, true == Vaadin + * + * @type bool + */ $v-relative-paths: true !default; diff --git a/WebContent/VAADIN/themes/valo/util/_anim.scss b/WebContent/VAADIN/themes/valo/util/_anim.scss index 430a6e4722..0cb738d832 100644 --- a/WebContent/VAADIN/themes/valo/util/_anim.scss +++ b/WebContent/VAADIN/themes/valo/util/_anim.scss @@ -1,73 +1,62 @@ -@if $v-animations-enabled { +$valo-anim-keyframes-included: false !default; - // 'Placeholder' animation names to trigger VOverlay animation-in and animation-out - @include keyframes(valo-placeholder-animate-in) { - 0% { - visibility: visible; - } - } +@if $v-animations-enabled and $valo-anim-keyframes-included == false{ - @include keyframes(valo-placeholder-animate-out) { - 100% { - visibility: visible; - } - } - - @include keyframes(valo-anim-fade-in) { + @include keyframes(valo-animate-in-fade) { 0% { opacity: 0; } } - @include keyframes(valo-anim-fade-out) { + @include keyframes(valo-animate-out-fade) { 100% { opacity: 0; } } - @include keyframes(valo-anim-slide-in-down) { + @include keyframes(valo-animate-in-slide-down) { 0% { @include transform( translateY(-100%) ); } } - @include keyframes(valo-anim-slide-in-up) { + @include keyframes(valo-animate-in-slide-up) { 0% { @include transform( translateY(100%) ); } } - @include keyframes(valo-anim-slide-in-left) { + @include keyframes(valo-animate-in-slide-left) { 0% { @include transform( translateX(100%) ); } } - @include keyframes(valo-anim-slide-in-right) { + @include keyframes(valo-animate-in-slide-right) { 0% { @include transform( translateX(-100%) ); } } - @include keyframes(valo-anim-slide-out-down) { + @include keyframes(valo-animate-out-slide-down) { 100% { @include transform( translateY(100%) ); } } - @include keyframes(valo-anim-slide-out-up) { + @include keyframes(valo-animate-out-slide-up) { 100% { @include transform( translateY(-100%) ); } } - @include keyframes(valo-anim-slide-out-left) { + @include keyframes(valo-animate-out-slide-left) { 100% { @include transform( translateX(-100%) ); } } - @include keyframes(valo-anim-slide-out-right) { + @include keyframes(valo-animate-out-slide-right) { 100% { @include transform( translateX(100%) ); } @@ -80,36 +69,84 @@ } } - @include keyframes(valo-anim-drop-fade-out) { + @include keyframes(valo-animate-out-slide-down-fade) { 100% { opacity: 0; @include transform(translatey(30%)); } } - + + $valo-anim-keyframes-included: true; } - -@mixin valo-anim-fade-in ($duration: 120ms, $delay: null){ - @include animation(valo-anim-fade-in $duration $delay); +/** + * Add animate-in-fade animation to the targeted elements. + * + * @group animation + * + * @param {time} $duration (180ms) - the duration of the fade + * @param {time} $delay (null) - the delay of the fade + */ +@mixin valo-animate-in-fade ($duration: 180ms, $delay: null){ + @include animation(valo-animate-in-fade $duration $delay); } -@mixin valo-anim-fade-out ($duration: 120ms, $delay: null){ - @include animation(valo-anim-fade-out $duration $delay); +/** + * Add animate-out-fade animation to the targeted elements. + * + * @group animation + * + * @param {time} $duration (180ms) - the duration of the fade + * @param {time} $delay (null) - the delay of the fade + */ +@mixin valo-animate-out-fade ($duration: 180ms, $delay: null){ + @include animation(valo-animate-out-fade $duration $delay); } -@mixin valo-anim-slide-down ($duration: 260ms, $delay: null){ - @include animation(valo-anim-slide-down $duration $delay); +/** + * Add animate-in-slide-down animation to the targeted elements. + * + * @group animation + * + * @param {time} $duration (400ms) - the duration of the slide + * @param {time} $delay (null) - the delay of the slide + */ +@mixin valo-animate-in-slide-down ($duration: 400ms, $delay: null){ + @include animation(valo-animate-in-slide-down $duration $delay); } -@mixin valo-anim-slide-up ($duration: 260ms, $delay: null){ - @include animation(valo-anim-slide-up $duration $delay); +/** + * Add animate-in-slide-up animation to the targeted elements. + * + * @group animation + * + * @param {time} $duration (400ms) - the duration of the slide + * @param {time} $delay (null) - the delay of the slide + */ +@mixin valo-animate-in-slide-up ($duration: 400ms, $delay: null){ + @include animation(valo-animate-in-slide-up $duration $delay); } -@mixin valo-anim-slide-left ($duration: 260ms, $delay: null){ - @include animation(valo-anim-slide-left $duration $delay); +/** + * Add animate-in-slide-left animation to the targeted elements. + * + * @group animation + * + * @param {time} $duration (400ms) - the duration of the slide + * @param {time} $delay (null) - the delay of the slide + */ +@mixin valo-animate-in-slide-left ($duration: 400ms, $delay: null){ + @include animation(valo-animate-in-slide-left $duration $delay); } -@mixin valo-anim-slide-right ($duration: 260ms, $delay: null){ - @include animation(valo-anim-slide-right $duration $delay); +/** + * Add animate-in-slide-right animation to the targeted elements. + * + * @group animation + * + * @param {time} $duration (400ms) - the duration of the slide + * @param {time} $delay (null) - the delay of the slide + */ +@mixin valo-animate-in-slide-right ($duration: 400ms, $delay: null){ + @include animation(valo-animate-in-slide-right $duration $delay); } diff --git a/WebContent/VAADIN/themes/valo/util/_bevel-and-shadow.scss b/WebContent/VAADIN/themes/valo/util/_bevel-and-shadow.scss index bf5b9b78bd..346a50c9de 100644 --- a/WebContent/VAADIN/themes/valo/util/_bevel-and-shadow.scss +++ b/WebContent/VAADIN/themes/valo/util/_bevel-and-shadow.scss @@ -1,3 +1,15 @@ +/** + * Computes a CSS border property value for the given base color. + * + * @group style + * + * @param {list}Â $border ($v-border) - CSS border value which can contain any of the color keywords + * @param {color} $color ($v-background-color) - the base color to which the color keywords are applied to + * @param {color} $context (null) - context/surrounding color where the border is expected to appear. The color of the final border is the darker of the two parameters passed to this function. + * @param {number} $strength (1) - adjustment for the border contrast + * + * @return {list} The input $border value with any color keyword replaced with the corresponding actual color + */ @function valo-border($border: $v-border, $color: $v-background-color, $context: null, $strength: 1) { @if type-of($border) != list { @return $border; @@ -18,8 +30,8 @@ $adjust-type: first-string($part); $adjust-amount: first-number($part); - $tint: blend-screen(white($v-bevel-depth/100%*$adjust-amount*$strength), $color); - $shade: blend-linearburn(black($v-bevel-depth/100%*$adjust-amount*$strength), $color); + $tint: blend-screen(rgba(#fff, $v-bevel-depth/100%*$adjust-amount*$strength), $color); + $shade: blend-linearburn(rgba(#000, $v-bevel-depth/100%*$adjust-amount*$strength), $color); @if $adjust-type == v-tone { @if is-dark-color($color) { @@ -42,22 +54,46 @@ } -@mixin valo-border-with-gradient($border: $v-border, $color: $v-background-color, $gradient: $v-gradient) { - border: valo-border($border, $color); - - // Adjust border-colors for gradient +/** + * Similar to the valo-border function, but adjusts the top and bottom border colors to suit an element with a gradient background-color. + * + * @group style + * + * @param {list}Â $border ($v-border) - CSS border value which can contain any of the color keywords + * @param {color} $color ($v-background-color) - the base color to which the color keywords are applied to + * @param {color} $context (null) - context/surrounding color where the border is expected to appear. The color of the final border is the darker of the two parameters passed to this function. + * @param {number} $strength (1) - adjustment for the border contrast + * @param {list} $gradient ($v-gradient) - Valo specific gradient value. See the documentation for $v-gradient. + */ +@mixin valo-border-with-gradient($border: $v-border, $color: $v-background-color, $context: null, $strength: 1, $gradient: $v-gradient) { + border: valo-border($border, $color, $context, $strength); + + // Adjust border colors for gradient @if $gradient { $color-stops: valo-gradient-color-stops($color, $gradient); $top: first(first($color-stops)); $bottom: first(last($color-stops)); - border-top-color: first-color(valo-border($border, $top)); - border-bottom-color: first-color(valo-border($border, $bottom)); + border-top-color: first-color(valo-border($border, $top, $context, $strength)); + border-bottom-color: first-color(valo-border($border, $bottom, $context, $strength)); } } - - +/** + * Computes a CSS box-shadow value according to the specified style parameters. + * + * @group style + * + * @param {list} $bevel (null) - box-shadow value according to $v-bevel documentation + * @param {number} $bevel-depth ($v-bevel-depth) - percentage defining the depth/amount of the bevel effect. Affects the color keywords specified in the $bevel parameter. + * @param {list} $shadow (null) - box-shadow value according to $v-shadow documentation + * @param {number} $shadow-opacity ($v-shadow-opacity) - percentage defining the opacity/amount of the shadow effect. Affects the color keywords specified in the $shadow parameter. + * @param {color}Â $background-color ($v-background-color) - the base color to which the color keywords are applied to + * @param {list}Â $gradient (null) - Valo specific gradient value. See the documentation for $v-gradient. Affects the color keywords specified in the $bevel parameter. + * @param {bool} $include-focus (false) - should the box-shadow value include $v-focus-style as well (only added if $v-focus-style is a) + * + * @return {list} CSS box-shadow value, combined from $bevel and $shadow with all occurences of v-tint, v-shade and v-tone color keywords replaced with the corresponding actual color + */ @function valo-bevel-and-shadow ($bevel: null, $bevel-depth: $v-bevel-depth, $shadow: null, $shadow-opacity: $v-shadow-opacity, $background-color: $v-background-color, $gradient: null, $include-focus: false) { $box-shadow: null; @@ -117,9 +153,18 @@ } - -@function valo-replace-tones($list, $tint-color, $gradient: null, $shade-color: null) { - $shade-color: $shade-color or $tint-color; +/** + * Replaces color keywords in the given list. + * + * @group style + * + * @param {list} $list - any CSS list with possible color keywords + * @param {color} $color - The color to which color keywords are applied to + * @param {list}Â $gradient (null) - Valo specific gradient value. See the documentation for $v-gradient. Affects the replacement colors to accommodate the gradient. + * + * @return {list} The input $list parameter with all occurences of v-tint, v-shade and v-tone color keywords replaced with the corresponding actual color + */ +@function valo-replace-tones($list, $color, $gradient: null) { $ret: (); @each $part in $list { @@ -130,11 +175,11 @@ $adjust-type: first-string($part); $adjust-amount: first-number($part); - $top-color: $tint-color; - $bottom-color: $shade-color; + $top-color: $color; + $bottom-color: $color; @if $gradient { - $color-stops: valo-gradient-color-stops($tint-color, $gradient); + $color-stops: valo-gradient-color-stops($color, $gradient); $top-color: first(first($color-stops)); $bottom-color: first(last($color-stops)); } @@ -142,20 +187,20 @@ $tint: blend-lighten(adjust-color($top-color, $lightness: $v-bevel-depth/4*$adjust-amount, $saturation: -$v-bevel-depth/2), scale-color($top-color, $lightness: $v-bevel-depth/4*$adjust-amount)); $shade: blend-darken(rgba(scale-color($bottom-color, $lightness: max(-30%, -$v-bevel-depth/3*$adjust-amount), $saturation: -$v-bevel-depth/2), $v-bevel-depth/100%), $bottom-color); - $color: null; + $new-color: null; @if $adjust-type == v-tone { - @if is-dark-color($tint-color) { - $color: $tint; + @if is-dark-color($color) { + $new-color: $tint; } @else { - $color: $shade; + $new-color: $shade; } } @else if $adjust-type == v-tint { - $color: $tint; + $new-color: $tint; } @else if $adjust-type == v-shade { - $color: $shade; + $new-color: $shade; } - $ret: join($ret, $color); + $ret: join($ret, $new-color); } @else { $ret: join($ret, $part); @@ -166,6 +211,15 @@ } +/** + * Replace color keywords in the given box-shadow parameter. + * + * @group style + * + * @param {list} $shadow - CSS box-shadow value, or any other CSS list which might contain either the v-tint or the v-shade color keywords. + * + * @return {list} the input $shadow parameter with all occurences of v-tint and v-shade color keywords replaced with the corresponding actual color + */ @function valo-replace-shadow ($shadow) { $ret: (); @each $part in $shadow { @@ -196,36 +250,24 @@ } -@function valo-text-shadow($font-color: $v-font-color, $background-color: $v-background-color, $bevel: $v-bevel, $offset: 1px) { - @if type-of($bevel) != list or $v-bevel-depth == 0 { - @return null; - } - - $needle: null; +/** + * Return a CSS text-shadow property value according to the specified style parameters. + * + * @group style + * + * @param {color} $font-color ($v-font-color) - the color of the text to which the text-shadow is added + * @param {color} $background-color ($v-background-color) - the color of the background where the text is to which the text-shadow is added + * @param {size} $offset (-1px) - the size of the text shadow vertical offset + * @param {number (pct)} $opacity ($v-shadow-opacity) - the percentage amount of shadow which is applied + */ +@function valo-text-shadow($font-color: $v-font-color, $background-color: $v-background-color, $offset: -1px, $opacity: $v-shadow-opacity) { + $color: null; @if color-luminance($font-color) < color-luminance($background-color) { - // Text darker than bg, light shadow. Look for tint - $needle: v-tint; + $color: rgba(#fff, $opacity / 100%); + $offset: $offset * -1; } @else { - // Text lighter than bg, dark shadow. Look for shade - $needle: v-shade; - } - - // Use the first match from the bevel list - @while list-of-lists($bevel) { - $bevel: first($bevel); - } - - // Remove possible 'inset' - $bevel: remove($bevel, inset); - - $color: $background-color; - @each $b in $bevel { - $strength: 1; - @if type-of($b) == list { - $strength: first-number($b); - } - $color: if($needle==v-tint, rgba(#fff, $v-shadow-opacity/100%*$strength), rgba(#000, $v-shadow-opacity/100%*$strength)); + $color: rgba(#000, $opacity / 100%); } - @return 0 if($needle==v-tint, $offset, $offset*-1) 0 $color; + @return 0 $offset 0 $color; } diff --git a/WebContent/VAADIN/themes/valo/util/_blend-modes.scss b/WebContent/VAADIN/themes/valo/util/_blend-modes.scss index 3da575660d..40d4defbdb 100644 --- a/WebContent/VAADIN/themes/valo/util/_blend-modes.scss +++ b/WebContent/VAADIN/themes/valo/util/_blend-modes.scss @@ -1,6 +1,5 @@ // From https://github.com/heygrady/scss-blend-modes // MIT license -// Remember to add a license notice to Vaadin //-------------------------------- // Normal diff --git a/WebContent/VAADIN/themes/valo/util/_color.scss b/WebContent/VAADIN/themes/valo/util/_color.scss index 0c80d2f0d0..37612fd48d 100644 --- a/WebContent/VAADIN/themes/valo/util/_color.scss +++ b/WebContent/VAADIN/themes/valo/util/_color.scss @@ -1,37 +1,48 @@ // "Photoshop" blend modes @import "blend-modes"; -// Returns the luminance of a color (0-255) -// (perceived brightness, rather than absolute mathematical lightness value) -// -// "The luminance calculation is a weighted average of the color channels that approximates -// how humans perceive brightness, while lightness is just an average of the largest and -// smallest channels without regard to perception." -// -// Source for equation: http://en.wikipedia.org/wiki/Luminance_(relative) +/** + * Returns the luminance of a color (0-255), i.e. the perceived brightness, rather than + * the absolute mathematical lightness value. + * + * "The luminance calculation is a weighted average of the color channels that approximates + * how humans perceive brightness, while lightness is just an average of the largest and + * smallest channels without regard to perception." + * + * Source: http://en.wikipedia.org/wiki/Luminance_(relative) + * + * @group color + * + * @param {color} $color - the color whose luminance value to get + * + * @return {number} the luminance value of the color, in the range of 0-255 + * + */ @function color-luminance ($color) { @return 0.2126 * red($color) + 0.7152 * green($color) + 0.0722 * blue($color); } -// Arbitrary luminance threshold after which colors should be adjusted either darker or lighter +/** + * Luminance value after which colors will be considered light (i.e. not dark). + * + * @group color + */ $v-luminance-threshold: 150 !default; - -@function black($opacity: 1) { - @return transparentize(#000, 1 - $opacity); -} - -@function white($opacity: 1) { - @return transparentize(#fff, 1 - $opacity); -} - - - -@function is-dark-color($bg-color) { - $luminance: color-luminance($bg-color); - @if $luminance < $v-luminance-threshold or (saturation($bg-color) > 80% and ($luminance < $v-luminance-threshold + 20)) { +/** + * Checks whether the color is considered dark or light, according to it's luminance and saturation. + * + * @group color + * + * @param {color} $color - the color to check + * + * @return {bool} true if the color is considered dark, false if considered light + */ +@function is-dark-color($color) { + $luminance: color-luminance($color); + @if $luminance < $v-luminance-threshold or (saturation($color) > 80% and ($luminance < $v-luminance-threshold + 20)) { @return true; } @else { @return false; @@ -39,6 +50,15 @@ $v-luminance-threshold: 150 !default; } +/** + * Get the darkest color (by luminance) from a list of colors. + * + * @group color + * + * @param {list} $colors - a list of CSS colors + * + * @return {color} darkest color (by luminance) from a list of colors + */ @function darkest-color($colors...) { $darkest: first($colors); @each $color in $colors { @@ -49,31 +69,38 @@ $v-luminance-threshold: 150 !default; @return $darkest; } -// Returns a text color with enough contrast for the given background color -@function valo-font-color ($bg-color, $contrast: 0.8) { - @if $bg-color { + +/** + * Returns a font color with enough contrast for the given background color. + * + * @group color + * + * @param {color} $bg-color - the background color for which to compute a suitable font color + * @param {number} $contrast (0.8) - the contrast of the font color compared to the background color + * + * @return {color} a suitable font color for the given background color + */ +@function valo-font-color ($bg-color, $contrast: 0.72) { + @if type-of($bg-color) == color { @if is-dark-color($bg-color) { @return scale-color($bg-color, $lightness: min(100%, 100% * $contrast), $saturation: max(-100%, -50% * $contrast)); } @else { - @return scale-color($bg-color, $lightness: max(-100%, -100% * $contrast * 0.9), $saturation: max(-100%, -50% * $contrast)); + @return scale-color($bg-color, $lightness: max(-100%, -100% * $contrast), $saturation: max(-100%, -50% * $contrast)); } } @return null; } -@function valo-header-color ($bg-color, $contrast: 1) { - $font-color: valo-font-color($bg-color); - @if is-dark-color($bg-color) { - @return lighten($font-color, 30% * $contrast); - } @else { - @return darken($font-color, 20% * $contrast); - } -} - - - - +/** + * Returns a suitable focus color for the given background color. + * + * @group color + * + * @param {color} $context ($v-app-background-color) - the background color for which to compute a suitable focus color + * + * @return {color} a suitable focus color for the given background color + */ @function valo-focus-color ($context: $v-app-background-color) { $color: $context; @if is-dark-color($context) { @@ -85,9 +112,13 @@ $v-luminance-threshold: 150 !default; } - -@mixin valo-focus-style($include-box-shadow: false) { - @if $include-box-shadow and type-of($v-focus-style) == list { +/** + * Output the default focus styles (border-color and box-shadow). + * + * @group style + */ +@mixin valo-focus-style { + @if type-of($v-focus-style) == list { @include box-shadow($v-focus-style); } @else if type-of($v-focus-style) == color { border-color: $v-focus-style; diff --git a/WebContent/VAADIN/themes/valo/util/_css3.scss b/WebContent/VAADIN/themes/valo/util/_css3.scss index b1215d735f..dc2dc781a7 100644 --- a/WebContent/VAADIN/themes/valo/util/_css3.scss +++ b/WebContent/VAADIN/themes/valo/util/_css3.scss @@ -1,3 +1,11 @@ +/** + * Cross-browser opacity. + * + * @param {number} $value - opacity value from 0 to 1 + * @param {bool} $important (false) - should the property value be declared with !important + * + * @group util + */ @mixin opacity ($value, $important: false) { $importantValue: null; @if $important { @@ -14,7 +22,14 @@ } } -// -webkit-box-shadow still needed for Android 2.3 and 3.0, as well as iOS 5 +/** + * Cross-browser box-shadow. + * -webkit-box-shadow is still needed for Android 2.3 and 3.0, as well as iOS 5 + * + * @param {list} $shadows - Any valid CSS box-shadow value + * + * @group util + */ @mixin box-shadow ($shadows...) { @include prefixer(box-shadow, $shadows, webkit spec); } diff --git a/WebContent/VAADIN/themes/valo/util/_gradient.scss b/WebContent/VAADIN/themes/valo/util/_gradient.scss index df159ad611..99490046ba 100644 --- a/WebContent/VAADIN/themes/valo/util/_gradient.scss +++ b/WebContent/VAADIN/themes/valo/util/_gradient.scss @@ -1,3 +1,13 @@ +/** + * Outputs cross-browser Valo-specific linear gradient background-image declarations. + * + * @group style + * + * @param {color} $color ($v-background-color) - The base color for the gradient color stops + * @param {list} $gradient ($v-gradient) - Valo-specific gradient value. See the documentation for $v-gradient. + * @param {color}Â $fallback (null) - A fallback color for browser which do not support linear gradients (IE8 and IE9 in particular). If null, the base $color is used instead. + * @param {string} $direction (to bottom) - the direction of the linear gradient. The color stops are by default so that a lighter shade is at the start and a darker shade is at the end. + */ @mixin valo-gradient($color: $v-background-color, $gradient: $v-gradient, $fallback: null, $direction: to bottom) { @if $color { @if $gradient { @@ -9,6 +19,14 @@ } } +/** + * Returns a valid CSS, Valo-specific, color stop list to be used in a linear gradient. + * + * @group style + * + * @param {color} $color - the base color for the color stops + * @param {list} $gradient ($v-gradient) - Valo-specific gradient value. See the documentation for $v-gradient. + */ @function valo-gradient-color-stops($color, $gradient: $v-gradient) { $style: valo-gradient-style($gradient); $opacity: valo-gradient-opacity($gradient); @@ -31,6 +49,13 @@ } +/** + * Returns the style part of a Valo-specific gradient value. + * + * @param {list} $gradient ($v-gradient) - Valo-specific gradient value. See the documentation for $v-gradient. + * + * @return {string} One of the possible style values for $v-gradient + */ @function valo-gradient-style($gradient: $v-gradient) { @if type-of($gradient) != list { @return none; @@ -38,6 +63,13 @@ @return first-string($gradient); } +/** + * Returns the opacity part of a Valo-specific gradient value. + * + * @param {list} $gradient ($v-gradient) - Valo-specific gradient value. See the documentation for $v-gradient. + * + * @return {number} A percentage value from 0% to 100% + */ @function valo-gradient-opacity($gradient: $v-gradient) { @if type-of($gradient) != list { @return 0%; diff --git a/WebContent/VAADIN/themes/valo/util/_lists.scss b/WebContent/VAADIN/themes/valo/util/_lists.scss index 54471b1380..f82c4f0fe3 100644 --- a/WebContent/VAADIN/themes/valo/util/_lists.scss +++ b/WebContent/VAADIN/themes/valo/util/_lists.scss @@ -1,15 +1,26 @@ -@function contains($list, $var, $recursive: false) { +/** + * Checks if a list contains a certain value. + * + * @param {list} $list - the list to check + * @param {value} $var - the value to search for + * @param {bool} $recursive (false) - should any contained lists be checked for the value + * + * @return {bool}Â true if the value is found from the list, false otherwise + * + * @group lists + */ +@function contains($list, $value, $recursive: false) { @if $recursive == false { - @return (false != index($list, $var)); + @return (false != index($list, $value)); } $ret: false; @each $item in $list { @if type-of($item) == list and $recursive { - @if contains($item, $var, true) { + @if contains($item, $value, true) { @return true; } - } @else if $item == $var { + } @else if $item == $value { @return true; } } @@ -18,6 +29,15 @@ } +/** + * Check whether a list contains nested lists. + * + * @param {list} $list - the list to check + * + * @return {bool}Â true of the list contains other nested lists, false otherwise + * + * @group lists + */ @function list-of-lists($list) { @each $part in $list { @if type-of($part) != list { @@ -28,26 +48,72 @@ } +/** + * Get the first color value from a list. + * + * @param {list} $list - a list which should contain a color value + * + * @return {color} The first color encountered in the list + * + * @group lists + */ @function first-color($list) { @return first-of-type($list, color); } +/** + * Get the first number value from a list. + * + * @param {list} $list - a list which should contain a number value + * + * @return {number} The first number encountered in the list + * + * @group lists + */ @function first-number($list) { @return first-of-type($list, number); } +/** + * Get the first string value from a list. + * + * @param {list} $list - a list which should contain a string value + * + * @return {string} The first string encountered in the list + * + * @group lists + */ @function first-string($list) { @return first-of-type($list, string); } +/** + * Get the first contained list from the list passed as the parameter. + * + * @param {list} $list - a list which should contain a nested list + * + * @return {list} The first list encountered in the list passed as the parameter + * + * @group lists + */ @function first-list($list) { @return first-of-type($list, list); } +/** + * Get the first value of a certain type from a list. + * + * @param {list} $list - a list which should contain a value of the certain type + * @param {string} $type - the type of value to search for + * + * @return {value} The first item of the certain type encountered in the list + * + * @group lists + */ @function first-of-type($list, $type) { @each $item in $list { @if type-of($item) == $type { @@ -63,6 +129,15 @@ } +/** + * Flatten nested lists to one list, while maintaining the original list separators. + * + * @param {list}Â $list - the list to flatten + * + * @return {list} the same list with all nested lists flattened + * + * @group lists + */ @function flatten-list($list) { $ret: (); @each $item in $list { diff --git a/WebContent/VAADIN/themes/valo/util/_util.scss b/WebContent/VAADIN/themes/valo/util/_util.scss index 1f983c0dad..585504600d 100644 --- a/WebContent/VAADIN/themes/valo/util/_util.scss +++ b/WebContent/VAADIN/themes/valo/util/_util.scss @@ -1,4 +1,12 @@ -// Align element vertically inside +/** + * Ouput selectors and properties to vertically center elements inside their parent. + * + * @param {string} $to-align (()) - The selector to match the elements which you wish to align vertically. The targeted elements should be inline or inline-block elements. + * @param {string} $align (middle) - The vertical-align value, e.g. top, middle, bottom + * @param {string}Â $pseudo-element (after) - Which pseudo element to use for the vertical align guide + * + * @group util + */ @mixin valo-vertical-align-guide ($to-align: (), $align: middle, $pseudo-element: after) { &:#{$pseudo-element} { content: ""; @@ -18,7 +26,11 @@ } - +/** + * Indicate that an element is clickable/tappable + * + * @group util + */ @mixin valo-tappable { -webkit-tap-highlight-color: rgba(0,0,0,0); -webkit-touch-callout: none; @@ -26,13 +38,53 @@ } - +/** + * Output Vaadin Responsive extension specific width-range declaration. + * + * @param {size} $min (0) - The lower bound for the width-range + * @param {size} $max (null) - The upper bound for the width-range + * + * @group util + * + * @example scss + * .v-ui { + * font-size: 18px; + * + * // Make the font-size smaller for 481px-768px wide UIs + * @include width-range(481px, 768px) { + * font-size: 16px; + * } + * + * // Make it even smaller for UIs narrower than 480px + * @include width-range($max: 480px) { + * font-size: 14px; + * } + * } + */ @mixin width-range($min: 0, $max: null) { &[width-range~="#{$min}-#{$max}"] { @content; } } +/** + * Output Vaadin Responsive extension specific height-range declaration. + * + * @param {size} $min (0) - The lower bound for the height-range + * @param {size} $max (null) - The upper bound for the height-range + * + * @group util + * + * @example scss + * .v-csslayout { + * color: red; + * + * // Make the text color blue when the layout height is between 100px-300px + * @include height-range(100px, 300px) { + * color: blue; + * } + * } + */ @mixin height-range($min: 0, $max: null) { &[height-range~="#{$min}-#{$max}"] { @content; diff --git a/WebContent/license.html b/WebContent/license.html index f714e4d64d..0ce22da99c 100644 --- a/WebContent/license.html +++ b/WebContent/license.html @@ -160,6 +160,14 @@ <td title="Custom web font">Lora</td> <td><a href="licenses/OFL.txt">SIL OFL 1.1</a></td> </tr> + <tr> + <td><a href="https://github.com/heygrady/scss-blend-modes">SCSS Blend Modes</a></td> + <td><a href="licenses/the-mit-license.txt">The MIT License</a></td> + </tr> + <tr> + <td><a href="https://github.com/Team-Sass/Sass-list-functions">Sass list functions</a></td> + <td><a href="licenses/the-mit-license.txt">The MIT License</a></td> + </tr> <!-- The extracted vaadin-sass-compiler --> <tr> <td>Vaadin Sass Compiler</td> diff --git a/build.properties b/build.properties index 0a25dab4b9..a9ad640e53 100644 --- a/build.properties +++ b/build.properties @@ -5,6 +5,6 @@ vaadin.vendor=Vaadin Ltd vaadin.url=http://vaadin.com vaadin.java.version=1.6 vaadin.version=0.0.0.unversioned-development-build -vaadin.sass.version=0.9.9 +vaadin.sass.version=0.9.10 gwt.version=2.6.0.vaadin5 commons-io.version=2.4 diff --git a/build/ide.xml b/build/ide.xml index 1e586acc19..fff4ba911d 100755 --- a/build/ide.xml +++ b/build/ide.xml @@ -128,13 +128,17 @@ <target name="compile-widgetset" depends="resolve"> <property name="module" value="${widgetset}" /> <property name="module.output.dir" location="WebContent/VAADIN/widgetsets" /> + <property name="logLevel" value="TRACE" /> <property name="style" value="PRETTY" /> <property name="localWorkers" value="2" /> + <!-- Whether assertions should be compiled into the widgetset. + Either "-ea" to enable or "" to disable. --> + <property name="assertions" value="-ea" /> <property name="extraParams" value="" /> <mkdir dir="${module.output.dir}" /> - <echo>Compiling ${module} to ${module.output.dir} with parameters -logLevel TRACE -style ${style} -localWorkers ${localWorkers} -strict ${extraParams}</echo> + <echo>Compiling ${module} to ${module.output.dir} with parameters -logLevel ${logLevel} -style ${style} -localWorkers ${localWorkers} ${assertions} -strict ${extraParams}</echo> <!--<ivy:resolve log="download-only" inline="true" organisation="javax.validation" module="validation-api" revision="1.0.0.GA"/> --> @@ -144,14 +148,14 @@ <arg value="-workDir" /> <arg value="${work.dir}" /> <arg value="-logLevel" /> - <arg value="TRACE" /> + <arg value="${logLevel}" /> <arg value="-war" /> <arg value="${module.output.dir}" /> <arg value="-style" /> <arg value="${style}" /> - <arg value="-localWorkers" /> <arg value="${localWorkers}" /> + <arg line="${assertions}" /> <arg value="-strict" /> <arg line="${extraParams}" /> <arg value="${module}" /> diff --git a/buildhelpers/src/com/vaadin/buildhelpers/FetchReleaseNotesTickets.java b/buildhelpers/src/com/vaadin/buildhelpers/FetchReleaseNotesTickets.java index dc2a676ab8..5bb010a1d2 100644 --- a/buildhelpers/src/com/vaadin/buildhelpers/FetchReleaseNotesTickets.java +++ b/buildhelpers/src/com/vaadin/buildhelpers/FetchReleaseNotesTickets.java @@ -20,6 +20,7 @@ import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; +import java.util.ArrayList; import java.util.List; import org.apache.commons.io.IOUtils; @@ -33,12 +34,26 @@ public class FetchReleaseNotesTickets { + "</tr>"; // public static void main(String[] args) throws IOException { - String versions = System.getProperty("vaadin.version"); - if (versions == null || versions.equals("")) { + String versionsProperty = System.getProperty("vaadin.version"); + if (versionsProperty == null || versionsProperty.equals("")) { usage(); } String milestone = ""; - for (String version : versions.split(" ")) { + + List<String> versions = new ArrayList<String>(); + for (String version : versionsProperty.split(" ")) { + if (version.endsWith(".0") || version.matches(".*\\.rc\\d+")) { + // Find all prerelease versions for final or rc + + // Strip potential rc prefix + version = version.replaceAll("\\.rc\\d+$", ""); + versions.addAll(findPrereleaseVersions(version)); + } else { + versions.add(version); + } + } + + for (String version : versions) { if (!milestone.equals("")) { milestone += "&"; } @@ -48,6 +63,22 @@ public class FetchReleaseNotesTickets { printMilestone(milestone); } + private static List<String> findPrereleaseVersions(String baseVersion) { + List<String> versions = new ArrayList<String>(); + + for (int i = 0; i < 50; i++) { + versions.add(baseVersion + ".alpha" + i); + } + for (int i = 0; i < 10; i++) { + versions.add(baseVersion + ".beta" + i); + } + for (int i = 0; i < 10; i++) { + versions.add(baseVersion + ".rc" + i); + } + + return versions; + } + private static void printMilestone(String milestone) throws MalformedURLException, IOException { diff --git a/client-compiler/src/com/vaadin/tools/CvalChecker.java b/client-compiler/src/com/vaadin/tools/CvalChecker.java index e426c5c4e6..c48aa7d9db 100644 --- a/client-compiler/src/com/vaadin/tools/CvalChecker.java +++ b/client-compiler/src/com/vaadin/tools/CvalChecker.java @@ -31,9 +31,10 @@ import java.util.Locale; import java.util.ResourceBundle; import java.util.prefs.Preferences; +import elemental.json.JsonException; +import elemental.json.JsonObject; +import elemental.json.impl.JsonUtil; import org.apache.commons.io.IOUtils; -import org.json.JSONException; -import org.json.JSONObject; /** * This class is able to validate the vaadin CVAL license. @@ -58,9 +59,9 @@ public final class CvalChecker { public static class CvalInfo { public static class Product { - private JSONObject o; + private JsonObject o; - public Product(JSONObject o) { + public Product(JsonObject o) { this.o = o; } @@ -74,40 +75,32 @@ public final class CvalChecker { } @SuppressWarnings("unchecked") - private static <T> T get(JSONObject o, String k, Class<T> clz) { + private static <T> T get(JsonObject o, String k, Class<T> clz) { Object ret = null; try { if (clz == String.class) { ret = o.getString(k); - } else if (clz == JSONObject.class) { - ret = o.getJSONObject(k); + } else if (clz == JsonObject.class) { + ret = o.getObject(k); } else if (clz == Integer.class) { - ret = o.getInt(k); + ret = Integer.valueOf((int) o.getNumber(k)); } else if (clz == Date.class) { - ret = new Date(o.getLong(k)); + ret = new Date((long) o.getNumber(k)); } else if (clz == Boolean.class) { ret = o.getBoolean(k); } - } catch (JSONException e) { + } catch (JsonException e) { } return (T) ret; } - private static <T> T put(JSONObject o, String k, Object v) { - try { - o.put(k, v); - } catch (JSONException e) { - } - return null; - } - - private JSONObject o; + private JsonObject o; private Product product; - public CvalInfo(JSONObject o) { + public CvalInfo(JsonObject o) { this.o = o; - product = new Product(get(o, "product", JSONObject.class)); + product = new Product(get(o, "product", JsonObject.class)); } public Boolean getExpired() { @@ -139,11 +132,11 @@ public final class CvalChecker { } public void setExpiredEpoch(Date expiredEpoch) { - put(o, "expiredEpoch", expiredEpoch.getTime()); + o.put("expiredEpoch", expiredEpoch.getTime()); } public void setMessage(String msg) { - put(o, "message", msg); + o.put("message", msg); } @Override @@ -327,9 +320,9 @@ public final class CvalChecker { return null; } try { - JSONObject o = new JSONObject(json); + JsonObject o = JsonUtil.parse(json); return new CvalInfo(o); - } catch (JSONException e) { + } catch (JsonException e) { return null; } } diff --git a/client/src/com/vaadin/client/ApplicationConnection.java b/client/src/com/vaadin/client/ApplicationConnection.java index 90aa0a14d6..3e3ad033a7 100644 --- a/client/src/com/vaadin/client/ApplicationConnection.java +++ b/client/src/com/vaadin/client/ApplicationConnection.java @@ -110,14 +110,14 @@ import com.vaadin.shared.ui.ui.UIState.PushConfigurationState; * This is the client side communication "engine", managing client-server * communication with its server side counterpart * com.vaadin.server.VaadinService. - * + * * Client-side connectors receive updates from the corresponding server-side * connector (typically component) as state updates or RPC calls. The connector * has the possibility to communicate back with its server side counter part * through RPC calls. - * + * * TODO document better - * + * * Entry point classes (widgetsets) define <code>onModuleLoad()</code>. */ public class ApplicationConnection implements HasHandlers { @@ -149,12 +149,12 @@ public class ApplicationConnection implements HasHandlers { * A string that, if found in a non-JSON response to a UIDL request, will * cause the browser to refresh the page. If followed by a colon, optional * whitespace, and a URI, causes the browser to synchronously load the URI. - * + * * <p> * This allows, for instance, a servlet filter to redirect the application * to a custom login page when the session expires. For example: * </p> - * + * * <pre> * if (sessionExpired) { * response.setHeader("Content-Type", "text/html"); @@ -345,7 +345,7 @@ public class ApplicationConnection implements HasHandlers { /** * Event triggered when a XHR request has finished with the status code of * the response. - * + * * Useful for handlers observing network failures like online/off-line * monitors. */ @@ -401,12 +401,12 @@ public class ApplicationConnection implements HasHandlers { /** * Event triggered when a application is stopped by calling * {@link ApplicationConnection#setApplicationRunning(false)}. - * + * * To listen for the event add a {@link ApplicationStoppedHandler} by * invoking * {@link ApplicationConnection#addHandler(ApplicationConnection.ApplicationStoppedEvent.Type, ApplicationStoppedHandler)} * to the {@link ApplicationConnection} - * + * * @since 7.1.8 * @author Vaadin Ltd */ @@ -433,7 +433,7 @@ public class ApplicationConnection implements HasHandlers { /** * Called when a communication error has occurred. Returning * <code>true</code> from this method suppresses error handling. - * + * * @param details * A string describing the error. * @param statusCode @@ -448,7 +448,7 @@ public class ApplicationConnection implements HasHandlers { * A listener for listening to application stopped events. The listener can * be added to a {@link ApplicationConnection} by invoking * {@link ApplicationConnection#addHandler(ApplicationStoppedEvent.Type, ApplicationStoppedHandler)} - * + * * @since 7.1.8 * @author Vaadin Ltd */ @@ -458,7 +458,7 @@ public class ApplicationConnection implements HasHandlers { * Triggered when the {@link ApplicationConnection} marks a previously * running application as stopped by invoking * {@link ApplicationConnection#setApplicationRunning(false)} - * + * * @param event * the event triggered by the {@link ApplicationConnection} */ @@ -569,7 +569,7 @@ public class ApplicationConnection implements HasHandlers { * called once this application has started (first response received) or * failed to start. This ensures that the applications are started in order, * to avoid session-id problems. - * + * */ public void start() { String jsonText = configuration.getUIDL(); @@ -646,7 +646,7 @@ public class ApplicationConnection implements HasHandlers { return componentLocator.@com.vaadin.client.componentlocator.ComponentLocator::getElementsByPathStartingAt(Ljava/lang/String;Lcom/google/gwt/dom/client/Element;)(id, element); }); client.getPathForElement = $entry(function(element) { - return componentLocator.@com.vaadin.client.componentlocator.ComponentLocator::getPathForElement(Lcom/google/gwt/dom/client/Element;)(element); + return componentLocator.@com.vaadin.client.componentlocator.ComponentLocator::getLegacyPathForElement(Lcom/google/gwt/dom/client/Element;)(element); }); client.initializing = false; @@ -679,7 +679,7 @@ public class ApplicationConnection implements HasHandlers { * <li><code>vaadin.postRequestHooks</code> is a map of functions which gets * called after each XHR made by vaadin application. Note, that it is * attaching js functions responsibility to create the variable like this: - * + * * <code><pre> * if(!vaadin.postRequestHooks) {vaadin.postRequestHooks = new Object();} * postRequestHooks.myHook = function(appId) { @@ -690,7 +690,7 @@ public class ApplicationConnection implements HasHandlers { * </pre></code> First parameter passed to these functions is the identifier * of Vaadin application that made the request. * </ul> - * + * * TODO make this multi-app aware */ private native void initializeClientHooks() @@ -721,7 +721,7 @@ public class ApplicationConnection implements HasHandlers { /** * Runs possibly registered client side post request hooks. This is expected * to be run after each uidl request made by Vaadin application. - * + * * @param appId */ private static native void runPostRequestHooks(String appId) @@ -741,7 +741,7 @@ public class ApplicationConnection implements HasHandlers { /** * If on Liferay and logged in, ask the client side session management * JavaScript to extend the session duration. - * + * * Otherwise, Liferay client side JavaScript will explicitly expire the * session even though the server side considers the session to be active. * See ticket #8305 for more information. @@ -760,7 +760,7 @@ public class ApplicationConnection implements HasHandlers { /** * Indicates whether or not there are currently active UIDL requests. Used * internally to sequence requests properly, seldom needed in Widgets. - * + * * @return true if there are active requests */ public boolean hasActiveRequest() { @@ -780,7 +780,7 @@ public class ApplicationConnection implements HasHandlers { /** * Requests an analyze of layouts, to find inconsistencies. Exclusively used * for debugging during development. - * + * * @deprecated as of 7.1. Replaced by {@link UIConnector#analyzeLayouts()} */ @Deprecated @@ -792,7 +792,7 @@ public class ApplicationConnection implements HasHandlers { * Sends a request to the server to print details to console that will help * the developer to locate the corresponding server-side connector in the * source code. - * + * * @param serverConnector * @deprecated as of 7.1. Replaced by * {@link UIConnector#showServerDebugInfo(ServerConnector)} @@ -804,7 +804,7 @@ public class ApplicationConnection implements HasHandlers { /** * Makes an UIDL request to the server. - * + * * @param reqInvocations * Data containing RPC invocations and all related information. * @param extraParams @@ -844,7 +844,7 @@ public class ApplicationConnection implements HasHandlers { /** * Sends an asynchronous or synchronous UIDL request to the server using the * given URI. - * + * * @param uri * The URI to use for the request. May includes GET parameters * @param payload @@ -982,7 +982,7 @@ public class ApplicationConnection implements HasHandlers { /** * Handles received UIDL JSON text, parsing it, and passing it on to the * appropriate handlers, while logging timing information. - * + * * @param jsonText * @param statusCode */ @@ -1010,7 +1010,7 @@ public class ApplicationConnection implements HasHandlers { /** * Sends an asynchronous UIDL request to the server using the given URI. - * + * * @param uri * The URI to use for the request. May includes GET parameters * @param payload @@ -1135,17 +1135,17 @@ public class ApplicationConnection implements HasHandlers { } } else { cssLoaded = true; - handleReceivedJSONMessage(new Date(), jsonText, json); if (cssWaits >= MAX_CSS_WAITS) { - VConsole.error("CSS files may have not loaded properly."); + getLogger().severe("CSS files may have not loaded properly."); } + handleReceivedJSONMessage(new Date(), jsonText, json); } } /** * Checks whether or not the CSS is loaded. By default checks the size of * the loading indicator element. - * + * * @return */ protected boolean isCSSLoaded() { @@ -1155,12 +1155,12 @@ public class ApplicationConnection implements HasHandlers { /** * Shows the communication error notification. - * + * * @param details * Optional details for debugging. * @param statusCode * The status code returned for the request - * + * */ protected void showCommunicationError(String details, int statusCode) { VConsole.error("Communication error: " + details); @@ -1169,7 +1169,7 @@ public class ApplicationConnection implements HasHandlers { /** * Shows the authentication error notification. - * + * * @param details * Optional details for debugging. */ @@ -1180,7 +1180,7 @@ public class ApplicationConnection implements HasHandlers { /** * Shows the session expiration notification. - * + * * @param details * Optional details for debugging. */ @@ -1191,7 +1191,7 @@ public class ApplicationConnection implements HasHandlers { /** * Shows an error notification. - * + * * @param details * Optional details for debugging. * @param message @@ -1204,7 +1204,7 @@ public class ApplicationConnection implements HasHandlers { /** * Shows the error notification. - * + * * @param details * Optional details for debugging. */ @@ -1292,7 +1292,7 @@ public class ApplicationConnection implements HasHandlers { /** * This method is called after applying uidl change set to application. - * + * * It will clean current and queued variable change sets. And send next * change set if it exists. */ @@ -1311,7 +1311,7 @@ public class ApplicationConnection implements HasHandlers { /** * Cleans given queue of variable changes of such changes that came from * components that do not exist anymore. - * + * * @param variableBurst */ private void cleanVariableBurst( @@ -1360,7 +1360,7 @@ public class ApplicationConnection implements HasHandlers { * <p> * Used by the native "client.isActive" function. * </p> - * + * * @return true if deferred commands are (potentially) being executed, false * otherwise */ @@ -1375,7 +1375,7 @@ public class ApplicationConnection implements HasHandlers { /** * Returns the loading indicator used by this ApplicationConnection - * + * * @return The loading indicator for this ApplicationConnection */ public VLoadingIndicator getLoadingIndicator() { @@ -1384,7 +1384,7 @@ public class ApplicationConnection implements HasHandlers { /** * Determines whether or not the loading indicator is showing. - * + * * @return true if the loading indicator is visible * @deprecated As of 7.1. Use {@link #getLoadingIndicator()} and * {@link VLoadingIndicator#isVisible()}.isVisible() instead. @@ -1418,7 +1418,7 @@ public class ApplicationConnection implements HasHandlers { * server is received. * <p> * The initial id when no request has yet been processed is -1. - * + * * @return and id identifying the response */ public int getLastResponseId() { @@ -1843,13 +1843,13 @@ public class ApplicationConnection implements HasHandlers { /** * Sends the state change events created while updating the state * information. - * + * * This must be called after hierarchy change listeners have been * called. At least caption updates for the parent are strange if * fired from state change listeners and thus calls the parent * BEFORE the parent is aware of the child (through a * ConnectorHierarchyChangedEvent) - * + * * @param pendingStateChangeEvents * The events to send */ @@ -2164,7 +2164,7 @@ public class ApplicationConnection implements HasHandlers { * Updates the connector hierarchy and returns a list of events that * should be fired after update of the hierarchy and the state is * done. - * + * * @param json * The JSON containing the hierarchy information * @return A collection of events that should be fired when update @@ -2561,9 +2561,9 @@ public class ApplicationConnection implements HasHandlers { /** * Adds an explicit RPC method invocation to the send queue. - * + * * @since 7.0 - * + * * @param invocation * RPC method invocation * @param delayed @@ -2603,7 +2603,7 @@ public class ApplicationConnection implements HasHandlers { /** * Removes any pending invocation of the given method from the queue - * + * * @param invocation * The invocation to remove */ @@ -2621,12 +2621,12 @@ public class ApplicationConnection implements HasHandlers { /** * This method sends currently queued variable changes to server. It is * called when immediate variable update must happen. - * + * * To ensure correct order for variable changes (due servers multithreading * or network), we always wait for active request to be handler before * sending a new one. If there is an active request, we will put varible * "burst" to queue that will be purged after current request is handled. - * + * */ public void sendPendingVariableChanges() { if (!deferedSendPending) { @@ -2667,11 +2667,11 @@ public class ApplicationConnection implements HasHandlers { /** * Build the variable burst and send it to server. - * + * * When sync is forced, we also force sending of all pending variable-bursts * at the same time. This is ok as we can assume that DOM will never be * updated after this. - * + * * @param pendingInvocations * List of RPC method invocations to send */ @@ -2758,7 +2758,7 @@ public class ApplicationConnection implements HasHandlers { * is true, the update is sent as soon as possible. If immediate is false, * the update will be sent along with the next immediate update. * </p> - * + * * @param paintableId * the id of the paintable that owns the variable * @param variableName @@ -2780,7 +2780,7 @@ public class ApplicationConnection implements HasHandlers { * is true, the update is sent as soon as possible. If immediate is false, * the update will be sent along with the next immediate update. * </p> - * + * * @param paintableId * the id of the paintable that owns the variable * @param variableName @@ -2803,7 +2803,7 @@ public class ApplicationConnection implements HasHandlers { * is true, the update is sent as soon as possible. If immediate is false, * the update will be sent along with the next immediate update. * </p> - * + * * @param paintableId * the id of the paintable that owns the variable * @param variableName @@ -2826,7 +2826,7 @@ public class ApplicationConnection implements HasHandlers { * is true, the update is sent as soon as possible. If immediate is false, * the update will be sent along with the next immediate update. * </p> - * + * * @param paintableId * the id of the paintable that owns the variable * @param variableName @@ -2849,7 +2849,7 @@ public class ApplicationConnection implements HasHandlers { * is true, the update is sent as soon as possible. If immediate is false, * the update will be sent along with the next immediate update. * </p> - * + * * @param paintableId * the id of the paintable that owns the variable * @param variableName @@ -2872,7 +2872,7 @@ public class ApplicationConnection implements HasHandlers { * is true, the update is sent as soon as possible. If immediate is false, * the update will be sent along with the next immediate update. * </p> - * + * * @param paintableId * the id of the paintable that owns the variable * @param variableName @@ -2895,7 +2895,7 @@ public class ApplicationConnection implements HasHandlers { * is true, the update is sent as soon as possible. If immediate is false, * the update will be sent along with the next immediate update. * </p> - * + * * @param paintableId * the id of the paintable that owns the variable * @param variableName @@ -2918,7 +2918,7 @@ public class ApplicationConnection implements HasHandlers { * is true, the update is sent as soon as possible. If immediate is false, * the update will be sent along with the next immediate update. * </p> - * + * * @param paintableId * the id of the paintable that owns the variable * @param variableName @@ -2935,13 +2935,13 @@ public class ApplicationConnection implements HasHandlers { /** * Sends a new value for the given paintables given variable to the server. - * + * * The update is actually queued to be sent at a suitable time. If immediate * is true, the update is sent as soon as possible. If immediate is false, * the update will be sent along with the next immediate update. - * + * * A null array is sent as an empty array. - * + * * @param paintableId * the id of the paintable that owns the variable * @param variableName @@ -2958,14 +2958,14 @@ public class ApplicationConnection implements HasHandlers { /** * Sends a new value for the given paintables given variable to the server. - * + * * The update is actually queued to be sent at a suitable time. If immediate * is true, the update is sent as soon as possible. If immediate is false, * the update will be sent along with the next immediate update. </p> - * + * * A null array is sent as an empty array. - * - * + * + * * @param paintableId * the id of the paintable that owns the variable * @param variableName @@ -2982,7 +2982,7 @@ public class ApplicationConnection implements HasHandlers { /** * Does absolutely nothing. Replaced by {@link LayoutManager}. - * + * * @param container * @deprecated As of 7.0, serves no purpose */ @@ -3004,7 +3004,7 @@ public class ApplicationConnection implements HasHandlers { /** * Returns false - * + * * @param paintable * @return false, always * @deprecated As of 7.0, serves no purpose @@ -3016,7 +3016,7 @@ public class ApplicationConnection implements HasHandlers { /** * Returns false - * + * * @param paintable * @return false, always * @deprecated As of 7.0, serves no purpose @@ -3037,16 +3037,16 @@ public class ApplicationConnection implements HasHandlers { /** * Get either an existing ComponentConnector or create a new * ComponentConnector with the given type and id. - * + * * If a ComponentConnector with the given id already exists, returns it. * Otherwise creates and registers a new ComponentConnector of the given * type. - * + * * @param connectorId * Id of the paintable * @param connectorType * Type of the connector, as passed from the server side - * + * * @return Either an existing ComponentConnector or a new ComponentConnector * of the given type */ @@ -3059,15 +3059,15 @@ public class ApplicationConnection implements HasHandlers { /** * Creates a new ServerConnector with the given type and id. - * + * * Creates and registers a new ServerConnector of the given type. Should * never be called with the connector id of an existing connector. - * + * * @param connectorId * Id of the new connector * @param connectorType * Type of the connector, as passed from the server side - * + * * @return A new ServerConnector of the given type */ private ServerConnector createAndRegisterConnector(String connectorId, @@ -3087,7 +3087,7 @@ public class ApplicationConnection implements HasHandlers { /** * Gets a recource that has been pre-loaded via UIDL, such as custom * layouts. - * + * * @param name * identifier of the resource to get * @return the resource @@ -3098,7 +3098,7 @@ public class ApplicationConnection implements HasHandlers { /** * Singleton method to get instance of app's context menu. - * + * * @return VContextMenu object */ public VContextMenu getContextMenu() { @@ -3113,7 +3113,7 @@ public class ApplicationConnection implements HasHandlers { /** * Gets an {@link Icon} instance corresponding to a URI. - * + * * @since 7.2 * @param uri * @return Icon object @@ -3135,7 +3135,7 @@ public class ApplicationConnection implements HasHandlers { * Translates custom protocols in UIDL URI's to be recognizable by browser. * All uri's from UIDL should be routed via this method before giving them * to browser due URI's in UIDL may contain custom protocols like theme://. - * + * * @param uidlUri * Vaadin URI from uidl * @return translated URI ready for browser @@ -3207,7 +3207,7 @@ public class ApplicationConnection implements HasHandlers { /** * Gets the URI for the current theme. Can be used to reference theme * resources. - * + * * @return URI to the current theme */ public String getThemeUri() { @@ -3218,7 +3218,7 @@ public class ApplicationConnection implements HasHandlers { /** * Listens for Notification hide event, and redirects. Used for system * messages, such as session expired. - * + * */ private class NotificationRedirect implements VNotification.EventListener { String url; @@ -3247,7 +3247,7 @@ public class ApplicationConnection implements HasHandlers { /** * Gets the token (aka double submit cookie) that the server uses to protect * against Cross Site Request Forgery attacks. - * + * * @return the CSRF token string */ public String getCsrfToken() { @@ -3257,7 +3257,7 @@ public class ApplicationConnection implements HasHandlers { /** * Use to notify that the given component's caption has changed; layouts may * have to be recalculated. - * + * * @param component * the Paintable whose caption has changed * @deprecated As of 7.0.2, has not had any effect for a long time @@ -3269,7 +3269,7 @@ public class ApplicationConnection implements HasHandlers { /** * Gets the main view - * + * * @return the main view */ public UIConnector getUIConnector() { @@ -3278,7 +3278,7 @@ public class ApplicationConnection implements HasHandlers { /** * Gets the {@link ApplicationConfiguration} for the current application. - * + * * @see ApplicationConfiguration * @return the configuration for this application */ @@ -3291,7 +3291,7 @@ public class ApplicationConnection implements HasHandlers { * list of events which has server side listeners is updated automatically * before the component is updated so the value is correct if called from * updatedFromUIDL. - * + * * @param paintable * The connector to register event listeners for * @param eventIdentifier @@ -3311,7 +3311,7 @@ public class ApplicationConnection implements HasHandlers { /** * Adds the get parameters to the uri and returns the new uri that contains * the parameters. - * + * * @param uri * The uri to which the parameters should be added. * @param extraParams @@ -3364,7 +3364,7 @@ public class ApplicationConnection implements HasHandlers { /** * Get VTooltip instance related to application connection - * + * * @return VTooltip instance */ public VTooltip getVTooltip() { @@ -3376,7 +3376,7 @@ public class ApplicationConnection implements HasHandlers { * this method is now handled by the state change event handler in * AbstractComponentConnector. The only function this method has is to * return true if the UIDL is a "cached" update. - * + * * @param component * @param uidl * @param manageCaption @@ -3427,7 +3427,7 @@ public class ApplicationConnection implements HasHandlers { * Schedules a heartbeat request to occur after the configured heartbeat * interval elapses if the interval is a positive number. Otherwise, does * nothing. - * + * * @deprecated as of 7.2, use {@link Heartbeat#schedule()} instead */ @Deprecated @@ -3441,7 +3441,7 @@ public class ApplicationConnection implements HasHandlers { * Heartbeat requests are used to inform the server that the client-side is * still alive. If the client page is closed or the connection lost, the * server will eventually close the inactive UI. - * + * * @deprecated as of 7.2, use {@link Heartbeat#send()} instead */ @Deprecated @@ -3465,7 +3465,7 @@ public class ApplicationConnection implements HasHandlers { /** * This method can be used to postpone rendering of a response for a short * period of time (e.g. to avoid the rendering process during animation). - * + * * @param lock */ public void suspendReponseHandling(Object lock) { @@ -3474,7 +3474,7 @@ public class ApplicationConnection implements HasHandlers { /** * Resumes the rendering process once all locks have been removed. - * + * * @param lock */ public void resumeResponseHandling(Object lock) { @@ -3519,7 +3519,7 @@ public class ApplicationConnection implements HasHandlers { /** * Sets the delegate that is called whenever a communication error occurrs. - * + * * @param delegate * the delegate. */ @@ -3562,7 +3562,7 @@ public class ApplicationConnection implements HasHandlers { /** * Gets the active connector for focused element in browser. - * + * * @return Connector for focused element or null. */ private ComponentConnector getActiveConnector() { @@ -3576,7 +3576,7 @@ public class ApplicationConnection implements HasHandlers { /** * Sets the status for the push connection. - * + * * @param enabled * <code>true</code> to enable the push connection; * <code>false</code> to disable the push connection. @@ -3626,7 +3626,7 @@ public class ApplicationConnection implements HasHandlers { /** * Returns a human readable string representation of the method used to * communicate with the server. - * + * * @since 7.1 * @return A string representation of the current transport type */ diff --git a/client/src/com/vaadin/client/componentlocator/ComponentLocator.java b/client/src/com/vaadin/client/componentlocator/ComponentLocator.java index c1ddc02aae..52c7b57d1d 100644 --- a/client/src/com/vaadin/client/componentlocator/ComponentLocator.java +++ b/client/src/com/vaadin/client/componentlocator/ComponentLocator.java @@ -36,6 +36,7 @@ import com.vaadin.client.ApplicationConnection; public class ComponentLocator { private final List<LocatorStrategy> locatorStrategies; + private final LocatorStrategy legacyLocatorStrategy; /** * Reference to ApplicationConnection instance. @@ -51,8 +52,9 @@ public class ComponentLocator { */ public ComponentLocator(ApplicationConnection client) { this.client = client; + legacyLocatorStrategy = new LegacyLocatorStrategy(client); locatorStrategies = Arrays.asList(new VaadinFinderLocatorStrategy( - client), new LegacyLocatorStrategy(client)); + client), legacyLocatorStrategy); } /** @@ -106,7 +108,28 @@ public class ComponentLocator { * String locator could not be created. */ public String getPathForElement(Element targetElement) { - return getPathForElement(DOM.asOld(targetElement)); + if (targetElement != null) { + return getPathForElement(DOM.asOld(targetElement)); + } + return null; + } + + /** + * Returns a String locator which uniquely identifies the target element. + * The returned locator is in a legacy format that is suitable for Vaadin + * TestBench Recorder. For non-legacy format, use + * {@link #getPathForElement(com.google.gwt.user.client.Element)} instead. + * + * + * @since + * @param targetElement + * The element to generate a path for. + * @return A String locator that identifies the target element or null if a + * String locator could not be created. + */ + public String getLegacyPathForElement(Element targetElement) { + return legacyLocatorStrategy + .getPathForElement(DOM.asOld(targetElement)); } /** diff --git a/client/src/com/vaadin/client/componentlocator/VaadinFinderLocatorStrategy.java b/client/src/com/vaadin/client/componentlocator/VaadinFinderLocatorStrategy.java index 6075d1bf48..9ed071c38f 100644 --- a/client/src/com/vaadin/client/componentlocator/VaadinFinderLocatorStrategy.java +++ b/client/src/com/vaadin/client/componentlocator/VaadinFinderLocatorStrategy.java @@ -20,6 +20,7 @@ import java.util.Arrays; import java.util.List; import com.google.gwt.dom.client.Element; +import com.google.gwt.user.client.DOM; import com.google.gwt.user.client.ui.RootPanel; import com.google.gwt.user.client.ui.Widget; import com.vaadin.client.ApplicationConnection; @@ -72,8 +73,24 @@ public class VaadinFinderLocatorStrategy implements LocatorStrategy { */ @Override public String getPathForElement(Element targetElement) { - if (targetElement == null) { - return ""; + Element oldTarget = targetElement; + Widget targetWidget = Util.findPaintable(client, targetElement) + .getWidget(); + targetElement = targetWidget.getElement(); + + // Find SubPart name if needed. + String subPart = null; + boolean hasSubParts = targetWidget instanceof SubPartAware; + if (oldTarget != targetElement) { + if (hasSubParts) { + subPart = ((SubPartAware) targetWidget).getSubPartName(DOM + .asOld(oldTarget)); + } + + if (!hasSubParts || subPart == null) { + // Couldn't find SubPart name for element. + return null; + } } List<ConnectorPath> hierarchy = getConnectorHierarchyForElement(targetElement); @@ -102,7 +119,7 @@ public class VaadinFinderLocatorStrategy implements LocatorStrategy { return null; } - return getBestSelector(generateQueries(path), targetElement); + return getBestSelector(generateQueries(path), targetElement, subPart); } /** @@ -114,9 +131,12 @@ public class VaadinFinderLocatorStrategy implements LocatorStrategy { * List of selectors * @param target * Target element + * @param subPart + * sub part selector string for actual target * @return Best selector string formatted with a post filter */ - private String getBestSelector(List<String> selectors, Element target) { + private String getBestSelector(List<String> selectors, Element target, + String subPart) { // The last selector gives us smallest list index for target element. String bestSelector = selectors.get(selectors.size() - 1); int min = getElementsByPath(bestSelector).indexOf(target); @@ -141,7 +161,8 @@ public class VaadinFinderLocatorStrategy implements LocatorStrategy { } } - return "(" + bestSelector + ")[" + min + "]"; + return "(" + bestSelector + (subPart != null ? "#" + subPart : "") + + ")[" + min + "]"; } diff --git a/client/src/com/vaadin/client/debug/internal/SelectorPath.java b/client/src/com/vaadin/client/debug/internal/SelectorPath.java index 5627bf0250..3f21e46a96 100644 --- a/client/src/com/vaadin/client/debug/internal/SelectorPath.java +++ b/client/src/com/vaadin/client/debug/internal/SelectorPath.java @@ -82,6 +82,10 @@ public class SelectorPath { .extractPostFilterPredicates(path); if (postFilters.size() > 0) { tmpPath = tmpPath.substring(1, tmpPath.lastIndexOf(')')); + if (tmpPath.contains("#")) { + // FIXME: SubParts should be handled. + tmpPath = tmpPath.split("#")[0]; + } } // Generate an ElementQuery diff --git a/client/src/com/vaadin/client/ui/VFilterSelect.java b/client/src/com/vaadin/client/ui/VFilterSelect.java index b323812c8c..356e7291c4 100644 --- a/client/src/com/vaadin/client/ui/VFilterSelect.java +++ b/client/src/com/vaadin/client/ui/VFilterSelect.java @@ -250,6 +250,8 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler, addCloseHandler(this); Roles.getListRole().set(getElement()); + + setPreviewingAllNativeEvents(true); } /** diff --git a/client/src/com/vaadin/client/ui/VGridLayout.java b/client/src/com/vaadin/client/ui/VGridLayout.java index 4929b02c9a..90ae944322 100644 --- a/client/src/com/vaadin/client/ui/VGridLayout.java +++ b/client/src/com/vaadin/client/ui/VGridLayout.java @@ -360,7 +360,8 @@ public class VGridLayout extends ComplexPanel { cell.layoutVertically(y, reservedMargin); } - if (rowHasComponentsOrRowSpan(row) || rowHeights[row] > 0) { + if (!hideEmptyRowsAndColumns || rowHasComponentsOrRowSpan(row) + || rowHeights[row] > 0) { y += rowHeights[row] + verticalSpacing; } } @@ -398,7 +399,8 @@ public class VGridLayout extends ComplexPanel { cell.layoutHorizontally(x, reservedMargin); } } - if (colHasComponentsOrColSpan(i) || columnWidths[i] > 0) { + if (!hideEmptyRowsAndColumns || colHasComponentsOrColSpan(i) + || columnWidths[i] > 0) { x += columnWidths[i] + horizontalSpacing; } } diff --git a/client/src/com/vaadin/client/ui/VPopupView.java b/client/src/com/vaadin/client/ui/VPopupView.java index 931945e546..1a59501d38 100644 --- a/client/src/com/vaadin/client/ui/VPopupView.java +++ b/client/src/com/vaadin/client/ui/VPopupView.java @@ -20,6 +20,8 @@ import java.util.HashSet; import java.util.Iterator; import java.util.Set; +import com.google.gwt.core.client.Scheduler; +import com.google.gwt.core.client.Scheduler.ScheduledCommand; import com.google.gwt.dom.client.Element; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; @@ -40,6 +42,7 @@ import com.google.gwt.user.client.ui.RootPanel; import com.google.gwt.user.client.ui.Widget; import com.vaadin.client.ApplicationConnection; import com.vaadin.client.ComponentConnector; +import com.vaadin.client.DeferredWorker; import com.vaadin.client.Util; import com.vaadin.client.VCaptionWrapper; import com.vaadin.client.VConsole; @@ -48,7 +51,8 @@ import com.vaadin.client.ui.ShortcutActionHandler.ShortcutActionHandlerOwner; import com.vaadin.client.ui.popupview.VisibilityChangeEvent; import com.vaadin.client.ui.popupview.VisibilityChangeHandler; -public class VPopupView extends HTML implements Iterable<Widget> { +public class VPopupView extends HTML implements Iterable<Widget>, + DeferredWorker { public static final String CLASSNAME = "v-popupview"; @@ -73,6 +77,8 @@ public class VPopupView extends HTML implements Iterable<Widget> { public final CustomPopup popup; private final Label loading = new Label(); + private boolean popupShowInProgress; + /** * loading constructor */ @@ -280,19 +286,33 @@ public class VPopupView extends HTML implements Iterable<Widget> { @Override public void show() { + popupShowInProgress = true; // Find the shortcut action handler that should handle keyboard // events from the popup. The events do not propagate automatically // because the popup is directly attached to the RootPanel. - Widget widget = VPopupView.this; - while (shortcutActionHandler == null && widget != null) { - if (widget instanceof ShortcutActionHandlerOwner) { - shortcutActionHandler = ((ShortcutActionHandlerOwner) widget) - .getShortcutActionHandler(); - } - widget = widget.getParent(); - } super.show(); + + /* + * Shortcut actions could be set (and currently in 7.2 they ARE SET + * via old style "updateFromUIDL" method, see f.e. UIConnector) + * AFTER method show() has been invoked (which is called as a + * reaction on change in component hierarchy). As a result there + * could be no shortcutActionHandler set yet. So let's postpone + * search of shortcutActionHandler. + */ + Scheduler.get().scheduleDeferred(new ScheduledCommand() { + @Override + public void execute() { + try { + if (shortcutActionHandler == null) { + shortcutActionHandler = findShortcutActionHandler(); + } + } finally { + popupShowInProgress = false; + } + } + }); } /** @@ -378,6 +398,18 @@ public class VPopupView extends HTML implements Iterable<Widget> { positionOrSizeUpdated(); } + private ShortcutActionHandler findShortcutActionHandler() { + Widget widget = VPopupView.this; + ShortcutActionHandler handler = null; + while (handler == null && widget != null) { + if (widget instanceof ShortcutActionHandlerOwner) { + handler = ((ShortcutActionHandlerOwner) widget) + .getShortcutActionHandler(); + } + widget = widget.getParent(); + } + return handler; + } }// class CustomPopup public HandlerRegistration addVisibilityChangeHandler( @@ -391,4 +423,9 @@ public class VPopupView extends HTML implements Iterable<Widget> { return Collections.singleton((Widget) popup).iterator(); } + @Override + public boolean isWorkPending() { + return popupShowInProgress; + } + }// class VPopupView diff --git a/client/src/com/vaadin/client/ui/VScrollTable.java b/client/src/com/vaadin/client/ui/VScrollTable.java index cb90823a7f..2e3c110d43 100644 --- a/client/src/com/vaadin/client/ui/VScrollTable.java +++ b/client/src/com/vaadin/client/ui/VScrollTable.java @@ -25,6 +25,8 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; import com.google.gwt.core.client.JavaScriptObject; import com.google.gwt.core.client.Scheduler; @@ -66,6 +68,8 @@ import com.google.gwt.regexp.shared.RegExp; import com.google.gwt.user.client.Command; import com.google.gwt.user.client.DOM; import com.google.gwt.user.client.Event; +import com.google.gwt.user.client.Event.NativePreviewEvent; +import com.google.gwt.user.client.Event.NativePreviewHandler; import com.google.gwt.user.client.Timer; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.ui.FlowPanel; @@ -129,7 +133,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets, /** * Simple interface for parts of the table capable of owning a context menu. - * + * * @since 7.2 * @author Vaadin Ltd */ @@ -139,7 +143,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets, /** * Handles showing context menu on "long press" from a touch screen. - * + * * @since 7.2 * @author Vaadin Ltd */ @@ -155,7 +159,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets, /** * Initializes a handler for a certain context menu owner. - * + * * @param target * the owner of the context menu */ @@ -176,7 +180,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets, /** * A function to handle touch context events in a table. - * + * * @param event * browser event to handle */ @@ -230,7 +234,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets, * Calculates how many pixels away the user's finger has traveled. This * reduces the chance of small non-intentional movements from canceling * the long press detection. - * + * * @param event * the Event for which to check the move distance * @return true if this is considered an intentional move by the user @@ -522,11 +526,11 @@ public class VScrollTable extends FlowPanel implements HasWidgets, /** * For internal use only. May be removed or replaced in the future. - * + * * Overwrites onBrowserEvent function on FocusableScrollPanel to give event * access to touchContextProvider. Has to be public to give TableConnector * access to the scrollBodyPanel field. - * + * * @since 7.2 * @author Vaadin Ltd */ @@ -763,6 +767,51 @@ public class VScrollTable extends FlowPanel implements HasWidgets, private HandlerRegistration addCloseHandler; + /** + * Changes to manage mouseDown and mouseUp + */ + /** + * The element where the last mouse down event was registered. + */ + private Element lastMouseDownTarget; + + /** + * Set to true by {@link #mouseUpPreviewHandler} if it gets a mouseup at the + * same element as {@link #lastMouseDownTarget}. + */ + private boolean mouseUpPreviewMatched = false; + + private HandlerRegistration mouseUpEventPreviewRegistration; + + /** + * Previews events after a mousedown to detect where the following mouseup + * hits. + */ + private final NativePreviewHandler mouseUpPreviewHandler = new NativePreviewHandler() { + + @Override + public void onPreviewNativeEvent(NativePreviewEvent event) { + if (event.getTypeInt() == Event.ONMOUSEUP) { + mouseUpEventPreviewRegistration.removeHandler(); + + // Event's reported target not always correct if event + // capture is in use + Element elementUnderMouse = Util.getElementUnderMouse(event + .getNativeEvent()); + if (lastMouseDownTarget != null + && lastMouseDownTarget.isOrHasChild(elementUnderMouse)) { + mouseUpPreviewMatched = true; + } else { + getLogger().log( + Level.FINEST, + "Ignoring mouseup from " + elementUnderMouse + + " when mousedown was on " + + lastMouseDownTarget); + } + } + } + }; + public VScrollTable() { setMultiSelectMode(MULTISELECT_MODE_DEFAULT); @@ -847,7 +896,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets, /** * Handles a context menu event on table body. - * + * * @param left * left position of the context menu * @param top @@ -1253,19 +1302,14 @@ public class VScrollTable extends FlowPanel implements HasWidgets, selected = true; keyboardSelectionOverRowFetchInProgress = true; } - if (selected) { - - if (focusedRow == null - || !selectedRowKeys.contains(focusedRow - .getKey())) { - /* - * The focus is no longer on a selected row. Move - * focus to the selected row. (#10522) - */ - - setRowFocus(row); - } + if (selected && selectedKeys.size() == 1) { + /* + * If a single item is selected, move focus to the + * selected row. (#10522) + */ + setRowFocus(row); } + if (selected != row.isSelected()) { row.toggleSelection(); @@ -5922,114 +5966,134 @@ public class VScrollTable extends FlowPanel implements HasWidgets, } break; case Event.ONMOUSEUP: - if (targetCellOrRowFound) { - /* - * Queue here, send at the same time as the - * corresponding value change event - see #7127 - */ - boolean clickEventSent = handleClickEvent(event, - targetTdOrTr, false); - - if (event.getButton() == Event.BUTTON_LEFT - && isSelectable()) { - - // Ctrl+Shift click - if ((event.getCtrlKey() || event.getMetaKey()) - && event.getShiftKey() - && isMultiSelectModeDefault()) { - toggleShiftSelection(false); - setRowFocus(this); - - // Ctrl click - } else if ((event.getCtrlKey() || event - .getMetaKey()) - && isMultiSelectModeDefault()) { - boolean wasSelected = isSelected(); - toggleSelection(); - setRowFocus(this); - /* - * next possible range select must start on - * this row - */ - selectionRangeStart = this; - if (wasSelected) { - removeRowFromUnsentSelectionRanges(this); - } + /* + * Only fire a click if the mouseup hits the same + * element as the corresponding mousedown. This is first + * checked in the event preview but we can't fire the + * event there as the event might get canceled before it + * gets here. + */ + if (mouseUpPreviewMatched + && lastMouseDownTarget != null + && lastMouseDownTarget == getElementTdOrTr(Util + .getElementUnderMouse(event))) { + // "Click" with left, right or middle button + + if (targetCellOrRowFound) { + /* + * Queue here, send at the same time as the + * corresponding value change event - see #7127 + */ + boolean clickEventSent = handleClickEvent( + event, targetTdOrTr, false); + + if (event.getButton() == Event.BUTTON_LEFT + && isSelectable()) { + + // Ctrl+Shift click + if ((event.getCtrlKey() || event + .getMetaKey()) + && event.getShiftKey() + && isMultiSelectModeDefault()) { + toggleShiftSelection(false); + setRowFocus(this); + + // Ctrl click + } else if ((event.getCtrlKey() || event + .getMetaKey()) + && isMultiSelectModeDefault()) { + boolean wasSelected = isSelected(); + toggleSelection(); + setRowFocus(this); + /* + * next possible range select must start + * on this row + */ + selectionRangeStart = this; + if (wasSelected) { + removeRowFromUnsentSelectionRanges(this); + } - } else if ((event.getCtrlKey() || event - .getMetaKey()) && isSingleSelectMode()) { - // Ctrl (or meta) click (Single selection) - if (!isSelected() - || (isSelected() && nullSelectionAllowed)) { + } else if ((event.getCtrlKey() || event + .getMetaKey()) + && isSingleSelectMode()) { + // Ctrl (or meta) click (Single + // selection) + if (!isSelected() + || (isSelected() && nullSelectionAllowed)) { - if (!isSelected()) { - deselectAll(); + if (!isSelected()) { + deselectAll(); + } + + toggleSelection(); + setRowFocus(this); } - toggleSelection(); + } else if (event.getShiftKey() + && isMultiSelectModeDefault()) { + // Shift click + toggleShiftSelection(true); + + } else { + // click + boolean currentlyJustThisRowSelected = selectedRowKeys + .size() == 1 + && selectedRowKeys + .contains(getKey()); + + if (!currentlyJustThisRowSelected) { + if (isSingleSelectMode() + || isMultiSelectModeDefault()) { + /* + * For default multi select mode + * (ctrl/shift) and for single + * select mode we need to clear + * the previous selection before + * selecting a new one when the + * user clicks on a row. Only in + * multiselect/simple mode the + * old selection should remain + * after a normal click. + */ + deselectAll(); + } + toggleSelection(); + } else if ((isSingleSelectMode() || isMultiSelectModeSimple()) + && nullSelectionAllowed) { + toggleSelection(); + }/* + * else NOP to avoid excessive server + * visits (selection is removed with + * CTRL/META click) + */ + + selectionRangeStart = this; setRowFocus(this); } - } else if (event.getShiftKey() - && isMultiSelectModeDefault()) { - // Shift click - toggleShiftSelection(true); - - } else { - // click - boolean currentlyJustThisRowSelected = selectedRowKeys - .size() == 1 - && selectedRowKeys - .contains(getKey()); - - if (!currentlyJustThisRowSelected) { - if (isSingleSelectMode() - || isMultiSelectModeDefault()) { - /* - * For default multi select mode - * (ctrl/shift) and for single - * select mode we need to clear the - * previous selection before - * selecting a new one when the user - * clicks on a row. Only in - * multiselect/simple mode the old - * selection should remain after a - * normal click. - */ - deselectAll(); - } - toggleSelection(); - } else if ((isSingleSelectMode() || isMultiSelectModeSimple()) - && nullSelectionAllowed) { - toggleSelection(); - }/* - * else NOP to avoid excessive server - * visits (selection is removed with - * CTRL/META click) - */ - - selectionRangeStart = this; - setRowFocus(this); + // Remove IE text selection hack + if (BrowserInfo.get().isIE()) { + ((Element) event.getEventTarget() + .cast()).setPropertyJSO( + "onselectstart", null); + } + // Queue value change + sendSelectedRows(false); } - - // Remove IE text selection hack - if (BrowserInfo.get().isIE()) { - ((Element) event.getEventTarget().cast()) - .setPropertyJSO("onselectstart", - null); + /* + * Send queued click and value change events if + * any If a click event is sent, send value + * change with it regardless of the immediate + * flag, see #7127 + */ + if (immediate || clickEventSent) { + client.sendPendingVariableChanges(); } - // Queue value change - sendSelectedRows(false); - } - /* - * Send queued click and value change events if any - * If a click event is sent, send value change with - * it regardless of the immediate flag, see #7127 - */ - if (immediate || clickEventSent) { - client.sendPendingVariableChanges(); } } + mouseUpPreviewMatched = false; + lastMouseDownTarget = null; break; case Event.ONTOUCHEND: case Event.ONTOUCHCANCEL: @@ -6135,6 +6199,17 @@ public class VScrollTable extends FlowPanel implements HasWidgets, } break; case Event.ONMOUSEDOWN: + /* + * When getting a mousedown event, we must detect where + * the corresponding mouseup event if it's on a + * different part of the page. + */ + lastMouseDownTarget = getElementTdOrTr(Util + .getElementUnderMouse(event)); + mouseUpPreviewMatched = false; + mouseUpEventPreviewRegistration = Event + .addNativePreviewHandler(mouseUpPreviewHandler); + if (targetCellOrRowFound) { setRowFocus(this); ensureFocus(); @@ -6269,7 +6344,12 @@ public class VScrollTable extends FlowPanel implements HasWidgets, */ private Element getEventTargetTdOrTr(Event event) { final Element eventTarget = event.getEventTarget().cast(); - Widget widget = Util.findWidget(eventTarget, null); + return getElementTdOrTr(eventTarget); + } + + private Element getElementTdOrTr(Element element) { + + Widget widget = Util.findWidget(element, null); if (widget != this) { /* @@ -6289,7 +6369,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets, return null; } } - return getTdOrTr(eventTarget); + return getTdOrTr(element); } @Override @@ -7435,7 +7515,6 @@ public class VScrollTable extends FlowPanel implements HasWidgets, } if (row != null) { - // Apply focus style to new selection row.addStyleName(getStylePrimaryName() + "-focus"); @@ -7449,14 +7528,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets, // Set new focused row focusedRow = row; - /* - * Don't scroll to the focused row when in multiselect mode. - * (#13341) - */ - - if (isSingleSelectMode()) { - ensureRowIsVisible(row); - } + ensureRowIsVisible(row); return true; } @@ -7476,6 +7548,10 @@ public class VScrollTable extends FlowPanel implements HasWidgets, // get odd scrolling here. return; } + /* + * FIXME The next line doesn't always do what expected, because if the + * row is not in the DOM it won't scroll to it. + */ Util.scrollIntoViewVertically(row.getElement()); } @@ -7930,7 +8006,6 @@ public class VScrollTable extends FlowPanel implements HasWidgets, public void lazyRevertFocusToRow(final VScrollTableRow currentlyFocusedRow) { Scheduler.get().scheduleFinally(new ScheduledCommand() { - @Override public void execute() { if (currentlyFocusedRow != null) { @@ -8133,4 +8208,8 @@ public class VScrollTable extends FlowPanel implements HasWidgets, public boolean isWorkPending() { return lazyAdjustColumnWidths.isRunning(); } + + private static Logger getLogger() { + return Logger.getLogger(VScrollTable.class.getName()); + } } diff --git a/client/src/com/vaadin/client/ui/VSlider.java b/client/src/com/vaadin/client/ui/VSlider.java index 86e5ef129d..a6ff8fabb4 100644 --- a/client/src/com/vaadin/client/ui/VSlider.java +++ b/client/src/com/vaadin/client/ui/VSlider.java @@ -35,7 +35,6 @@ import com.google.gwt.user.client.ui.HasValue; import com.vaadin.client.ApplicationConnection; import com.vaadin.client.BrowserInfo; import com.vaadin.client.Util; -import com.vaadin.client.VConsole; import com.vaadin.shared.ui.slider.SliderOrientation; public class VSlider extends SimpleFocusablePanel implements Field, @@ -329,13 +328,11 @@ public class VSlider extends SimpleFocusablePanel implements Field, DOM.eventPreventDefault(event); // prevent selecting text DOM.eventCancelBubble(event, true); event.stopPropagation(); - VConsole.log("Slider move start"); } break; case Event.ONMOUSEMOVE: case Event.ONTOUCHMOVE: if (dragging) { - VConsole.log("Slider move"); setValueByEvent(event, false); updateFeedbackPosition(); event.stopPropagation(); @@ -345,7 +342,6 @@ public class VSlider extends SimpleFocusablePanel implements Field, feedbackPopup.hide(); case Event.ONMOUSEUP: // feedbackPopup.hide(); - VConsole.log("Slider move end"); dragging = false; handle.setClassName(getStylePrimaryName() + "-handle"); DOM.releaseCapture(getElement()); diff --git a/client/src/com/vaadin/client/ui/calendar/schedule/DateCell.java b/client/src/com/vaadin/client/ui/calendar/schedule/DateCell.java index ffa5f78071..bef03707ba 100644 --- a/client/src/com/vaadin/client/ui/calendar/schedule/DateCell.java +++ b/client/src/com/vaadin/client/ui/calendar/schedule/DateCell.java @@ -18,7 +18,6 @@ package com.vaadin.client.ui.calendar.schedule; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; -import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -203,6 +202,8 @@ public class DateCell extends FocusableComplexPanel implements width = getOffsetWidth() - Util.measureHorizontalBorder(getElement()); + // Update moveWidth for any DateCellDayEvent child + updateEventCellsWidth(); recalculateEventWidths(); } else { removeStyleDependentName("Hsized"); @@ -221,6 +222,8 @@ public class DateCell extends FocusableComplexPanel implements // recalc heights&size for events. all other height sizes come // from css startingSlotHeight = slotElements[0].getOffsetHeight(); + // Update slotHeight for each DateCellDayEvent child + updateEventCellsHeight(); recalculateEventPositions(); if (isToday()) { @@ -327,14 +330,7 @@ public class DateCell extends FocusableComplexPanel implements .setHeight(slotElementHeights[i], Unit.PX); } - Iterator<Widget> it = iterator(); - while (it.hasNext()) { - Widget child = it.next(); - if (child instanceof DateCellDayEvent) { - ((DateCellDayEvent) child).setSlotHeightInPX(getSlotHeight()); - } - - } + updateEventCellsHeight(); } public int getSlotHeight() { @@ -829,4 +825,20 @@ public class DateCell extends FocusableComplexPanel implements .contextMenu(event, DateCell.this); } } + + private void updateEventCellsWidth() { + for (Widget widget : getChildren()) { + if (widget instanceof DateCellDayEvent) { + ((DateCellDayEvent) widget).setMoveWidth(width); + } + } + } + + private void updateEventCellsHeight() { + for (Widget widget : getChildren()) { + if (widget instanceof DateCellDayEvent) { + ((DateCellDayEvent) widget).setSlotHeightInPX(getSlotHeight()); + } + } + } } diff --git a/client/src/com/vaadin/client/ui/ui/UIConnector.java b/client/src/com/vaadin/client/ui/ui/UIConnector.java index c88fd23eca..d6f14bf158 100644 --- a/client/src/com/vaadin/client/ui/ui/UIConnector.java +++ b/client/src/com/vaadin/client/ui/ui/UIConnector.java @@ -494,7 +494,11 @@ public class UIConnector extends AbstractSingleComponentContainerConnector // the user root.getElement().setInnerHTML(""); + // Activate the initial theme by only adding the class name. Not calling + // activateTheme here as it will also cause a full layout and updates to + // the overlay container which has not yet been created at this point activeTheme = applicationConnection.getConfiguration().getThemeName(); + root.addStyleName(activeTheme); root.add(getWidget()); diff --git a/eclipse/Development Mode (vaadin).launch b/eclipse/Development Mode (vaadin).launch index 8c828eca96..2b8ff23ce8 100644 --- a/eclipse/Development Mode (vaadin).launch +++ b/eclipse/Development Mode (vaadin).launch @@ -2,27 +2,22 @@ <launchConfiguration type="org.eclipse.jdt.launching.localJavaApplication"> <stringAttribute key="bad_container_name" value="\eclipse"/> <listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS"> -<listEntry value="/gwt-dev/core/src/com/google/gwt/dev/DevMode.java"/> +<listEntry value="/vaadin"/> </listAttribute> <listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES"> -<listEntry value="1"/> +<listEntry value="4"/> </listAttribute> +<booleanAttribute key="org.eclipse.jdt.launching.ATTR_USE_START_ON_FIRST_THREAD" value="true"/> <listAttribute key="org.eclipse.jdt.launching.CLASSPATH"> -<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry path="3" projectName="vaadin" type="1"/> "/> -<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/vaadin/shared/src" path="3" type="2"/> "/> -<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/vaadin/client/src" path="3" type="2"/> "/> -<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/vaadin/uitest/src" path="3" type="2"/> "/> -<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry containerPath="GWT_TOOLS/lib/apache/tapestry-util-text-4.0.2.jar" path="3" type="3"/> "/> -<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry containerPath="GWT_TOOLS/lib/junit/junit-4.8.2.jar" path="3" type="3"/> "/> -<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry containerPath="GWT_TOOLS/lib/tomcat/servlet-api-2.5.jar" path="3" type="3"/> "/> -<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry containerPath="GWT_TOOLS/lib/javax/validation/validation-api-1.0.0.GA.jar" path="3" type="3"/> "/> -<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry containerPath="GWT_TOOLS/lib/javax/validation/validation-api-1.0.0.GA-sources.jar" path="3" type="3"/> "/> -<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry containerPath="org.apache.ivyde.eclipse.cpcontainer.IVYDE_CONTAINER/?project=vaadin&amp;ivyXmlPath=client%2Fivy.xml&amp;confs=ide&amp;ivySettingsPath=%24%7Bworkspace_loc%3Avaadin%2Fivysettings.xml%7D&amp;loadSettingsOnDemand=false&amp;propertyFiles=" javaProject="vaadin" path="3" type="4"/> "/> -<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry containerPath="org.apache.ivyde.eclipse.cpcontainer.IVYDE_CONTAINER/?project=vaadin&amp;ivyXmlPath=server%2Fivy.xml&amp;confs=ide&amp;ivySettingsPath=%24%7Bworkspace_loc%3Avaadin%2Fivysettings.xml%7D&amp;loadSettingsOnDemand=false&amp;propertyFiles=" javaProject="vaadin" path="3" type="4"/> "/> -<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry containerPath="org.apache.ivyde.eclipse.cpcontainer.IVYDE_CONTAINER/?project=vaadin&amp;ivyXmlPath=shared%2Fivy.xml&amp;confs=ide&amp;ivySettingsPath=%24%7Bworkspace_loc%3Avaadin%2Fivysettings.xml%7D&amp;loadSettingsOnDemand=false&amp;propertyFiles=" javaProject="vaadin" path="3" type="4"/> "/> -<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry containerPath="org.apache.ivyde.eclipse.cpcontainer.IVYDE_CONTAINER/?project=vaadin&amp;ivyXmlPath=client-compiler%2Fivy.xml&amp;confs=ide&amp;ivySettingsPath=%24%7Bworkspace_loc%3Avaadin%2Fivysettings.xml%7D&amp;loadSettingsOnDemand=false&amp;propertyFiles=" javaProject="vaadin" path="3" type="4"/> "/> -<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry containerPath="org.apache.ivyde.eclipse.cpcontainer.IVYDE_CONTAINER/?project=vaadin&amp;ivyXmlPath=gwt%2Fivy.xml&amp;confs=ide&amp;ivySettingsPath=%24%7Bworkspace_loc%3Avaadin%2Fivysettings.xml%7D&amp;loadSettingsOnDemand=false&amp;propertyFiles=" javaProject="vaadin" path="3" type="4"/> "/> -<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry containerPath="org.apache.ivyde.eclipse.cpcontainer.IVYDE_CONTAINER/?project=vaadin&amp;ivyXmlPath=uitest%2Fivy.xml&amp;confs=ide&amp;ivySettingsPath=%24%7Bworkspace_loc%3Avaadin%2Fivysettings.xml%7D&amp;loadSettingsOnDemand=false&amp;propertyFiles=" javaProject="vaadin" path="3" type="4"/> "/> +<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/vaadin/shared/src" path="3" type="2"/> "/> +<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/vaadin/client/src" path="3" type="2"/> "/> +<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/vaadin/uitest/src" path="3" type="2"/> "/> +<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry path="3" projectName="vaadin" type="1"/> "/> +<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry containerPath="org.apache.ivyde.eclipse.cpcontainer.IVYDE_CONTAINER/?project=vaadin&amp;ivyXmlPath=client%2Fivy.xml&amp;confs=ide&amp;ivySettingsPath=%24%7Bworkspace_loc%3Avaadin%2Fivysettings.xml%7D&amp;loadSettingsOnDemand=false&amp;propertyFiles=" javaProject="vaadin" path="3" type="4"/> "/> +<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry containerPath="org.apache.ivyde.eclipse.cpcontainer.IVYDE_CONTAINER/?project=vaadin&amp;ivyXmlPath=shared%2Fivy.xml&amp;confs=ide&amp;ivySettingsPath=%24%7Bworkspace_loc%3Avaadin%2Fivysettings.xml%7D&amp;loadSettingsOnDemand=false&amp;propertyFiles=" javaProject="vaadin" path="3" type="4"/> "/> +<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry containerPath="org.apache.ivyde.eclipse.cpcontainer.IVYDE_CONTAINER/?project=vaadin&amp;ivyXmlPath=uitest%2Fivy.xml&amp;confs=ide&amp;ivySettingsPath=%24%7Bworkspace_loc%3Avaadin%2Fivysettings.xml%7D&amp;loadSettingsOnDemand=false&amp;propertyFiles=%24%7Bworkspace_loc%3Avaadin%2Fbuild.properties%7D" javaProject="vaadin" path="3" type="4"/> "/> +<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry containerPath="org.apache.ivyde.eclipse.cpcontainer.IVYDE_CONTAINER/?project=vaadin&amp;ivyXmlPath=push%2Fivy.xml&amp;confs=ide&amp;ivySettingsPath=%24%7Bworkspace_loc%3Avaadin%2Fivysettings.xml%7D&amp;loadSettingsOnDemand=false&amp;propertyFiles=" javaProject="vaadin" path="3" type="4"/> "/> +<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry containerPath="org.apache.ivyde.eclipse.cpcontainer.IVYDE_CONTAINER/?project=vaadin&amp;ivyXmlPath=gwt%2Fivy.xml&amp;confs=ide&amp;ivySettingsPath=%24%7Bworkspace_loc%3Avaadin%2Fivysettings.xml%7D&amp;loadSettingsOnDemand=false&amp;propertyFiles=%24%7Bworkspace_loc%3Avaadin%2Fbuild.properties%7D" javaProject="vaadin" path="3" type="4"/> "/> </listAttribute> <booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="false"/> <stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="com.google.gwt.dev.DevMode"/> diff --git a/eclipse/Super Development Mode (vaadin).launch b/eclipse/Super Development Mode (vaadin).launch index 147ec2ae13..ed243cba82 100644 --- a/eclipse/Super Development Mode (vaadin).launch +++ b/eclipse/Super Development Mode (vaadin).launch @@ -9,21 +9,15 @@ </listAttribute> <booleanAttribute key="org.eclipse.jdt.launching.ATTR_USE_START_ON_FIRST_THREAD" value="true"/> <listAttribute key="org.eclipse.jdt.launching.CLASSPATH"> -<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry path="3" projectName="vaadin" type="1"/> "/> -<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/vaadin/shared/src" path="3" type="2"/> "/> -<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/vaadin/client/src" path="3" type="2"/> "/> -<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/vaadin/uitest/src" path="3" type="2"/> "/> -<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry containerPath="GWT_TOOLS/lib/apache/tapestry-util-text-4.0.2.jar" path="3" type="3"/> "/> -<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry containerPath="GWT_TOOLS/lib/junit/junit-4.8.2.jar" path="3" type="3"/> "/> -<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry containerPath="GWT_TOOLS/lib/tomcat/servlet-api-2.5.jar" path="3" type="3"/> "/> -<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry containerPath="GWT_TOOLS/lib/javax/validation/validation-api-1.0.0.GA.jar" path="3" type="3"/> "/> -<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry containerPath="GWT_TOOLS/lib/javax/validation/validation-api-1.0.0.GA-sources.jar" path="3" type="3"/> "/> -<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry containerPath="org.apache.ivyde.eclipse.cpcontainer.IVYDE_CONTAINER/?project=vaadin&amp;ivyXmlPath=client%2Fivy.xml&amp;confs=ide&amp;ivySettingsPath=%24%7Bworkspace_loc%3Avaadin%2Fivysettings.xml%7D&amp;loadSettingsOnDemand=false&amp;propertyFiles=" javaProject="vaadin" path="3" type="4"/> "/> -<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry containerPath="org.apache.ivyde.eclipse.cpcontainer.IVYDE_CONTAINER/?project=vaadin&amp;ivyXmlPath=server%2Fivy.xml&amp;confs=ide&amp;ivySettingsPath=%24%7Bworkspace_loc%3Avaadin%2Fivysettings.xml%7D&amp;loadSettingsOnDemand=false&amp;propertyFiles=" javaProject="vaadin" path="3" type="4"/> "/> -<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry containerPath="org.apache.ivyde.eclipse.cpcontainer.IVYDE_CONTAINER/?project=vaadin&amp;ivyXmlPath=shared%2Fivy.xml&amp;confs=ide&amp;ivySettingsPath=%24%7Bworkspace_loc%3Avaadin%2Fivysettings.xml%7D&amp;loadSettingsOnDemand=false&amp;propertyFiles=" javaProject="vaadin" path="3" type="4"/> "/> -<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry containerPath="org.apache.ivyde.eclipse.cpcontainer.IVYDE_CONTAINER/?project=vaadin&amp;ivyXmlPath=client-compiler%2Fivy.xml&amp;confs=ide&amp;ivySettingsPath=%24%7Bworkspace_loc%3Avaadin%2Fivysettings.xml%7D&amp;loadSettingsOnDemand=false&amp;propertyFiles=" javaProject="vaadin" path="3" type="4"/> "/> -<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry containerPath="org.apache.ivyde.eclipse.cpcontainer.IVYDE_CONTAINER/?project=vaadin&amp;ivyXmlPath=gwt%2Fivy.xml&amp;confs=ide&amp;ivySettingsPath=%24%7Bworkspace_loc%3Avaadin%2Fivysettings.xml%7D&amp;loadSettingsOnDemand=false&amp;propertyFiles=" javaProject="vaadin" path="3" type="4"/> "/> -<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry containerPath="org.apache.ivyde.eclipse.cpcontainer.IVYDE_CONTAINER/?project=vaadin&amp;ivyXmlPath=uitest%2Fivy.xml&amp;confs=ide&amp;ivySettingsPath=%24%7Bworkspace_loc%3Avaadin%2Fivysettings.xml%7D&amp;loadSettingsOnDemand=false&amp;propertyFiles=" javaProject="vaadin" path="3" type="4"/> "/> +<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/vaadin/shared/src" path="3" type="2"/> "/> +<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/vaadin/client/src" path="3" type="2"/> "/> +<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/vaadin/uitest/src" path="3" type="2"/> "/> +<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry path="3" projectName="vaadin" type="1"/> "/> +<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry containerPath="org.apache.ivyde.eclipse.cpcontainer.IVYDE_CONTAINER/?project=vaadin&amp;ivyXmlPath=client%2Fivy.xml&amp;confs=ide&amp;ivySettingsPath=%24%7Bworkspace_loc%3Avaadin%2Fivysettings.xml%7D&amp;loadSettingsOnDemand=false&amp;propertyFiles=" javaProject="vaadin" path="3" type="4"/> "/> +<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry containerPath="org.apache.ivyde.eclipse.cpcontainer.IVYDE_CONTAINER/?project=vaadin&amp;ivyXmlPath=shared%2Fivy.xml&amp;confs=ide&amp;ivySettingsPath=%24%7Bworkspace_loc%3Avaadin%2Fivysettings.xml%7D&amp;loadSettingsOnDemand=false&amp;propertyFiles=" javaProject="vaadin" path="3" type="4"/> "/> +<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry containerPath="org.apache.ivyde.eclipse.cpcontainer.IVYDE_CONTAINER/?project=vaadin&amp;ivyXmlPath=uitest%2Fivy.xml&amp;confs=ide&amp;ivySettingsPath=%24%7Bworkspace_loc%3Avaadin%2Fivysettings.xml%7D&amp;loadSettingsOnDemand=false&amp;propertyFiles=%24%7Bworkspace_loc%3Avaadin%2Fbuild.properties%7D" javaProject="vaadin" path="3" type="4"/> "/> +<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry containerPath="org.apache.ivyde.eclipse.cpcontainer.IVYDE_CONTAINER/?project=vaadin&amp;ivyXmlPath=push%2Fivy.xml&amp;confs=ide&amp;ivySettingsPath=%24%7Bworkspace_loc%3Avaadin%2Fivysettings.xml%7D&amp;loadSettingsOnDemand=false&amp;propertyFiles=" javaProject="vaadin" path="3" type="4"/> "/> +<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry containerPath="org.apache.ivyde.eclipse.cpcontainer.IVYDE_CONTAINER/?project=vaadin&amp;ivyXmlPath=gwt%2Fivy.xml&amp;confs=ide&amp;ivySettingsPath=%24%7Bworkspace_loc%3Avaadin%2Fivysettings.xml%7D&amp;loadSettingsOnDemand=false&amp;propertyFiles=%24%7Bworkspace_loc%3Avaadin%2Fbuild.properties%7D" javaProject="vaadin" path="3" type="4"/> "/> </listAttribute> <booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="false"/> <stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="com.google.gwt.dev.codeserver.CodeServer"/> diff --git a/gwt-files.xml b/gwt-files.xml index 4a8486ab55..c0ef583177 100644 --- a/gwt-files.xml +++ b/gwt-files.xml @@ -182,6 +182,13 @@ <include name="com/google/gwt/user/client/rpc/IsSerializable.*" /> </fileset> + <!-- GWT Elemental --> + <fileset dir="${gwt.elemental.jar.files}"> + <include name="elemental/util/Array*" /> + <include name="elemental/util/Can*" /> + <include name="elemental/util/Map*" /> + <include name="elemental/json/**" /> + </fileset> </union> <union id="server.gwt.includes"> @@ -189,5 +196,10 @@ <!-- Server files from gwt-user --> <include name="com/google/gwt/*/server/**" /> </fileset> + <!-- GWT Elemental --> + <fileset dir="${gwt.elemental.jar.files}"> + <exclude name="META-INF/**" /> + <exclude name="super/**" /> + </fileset> </union> </project> diff --git a/gwt/ivy.xml b/gwt/ivy.xml index 52d8acea92..d34b7ccfcc 100644 --- a/gwt/ivy.xml +++ b/gwt/ivy.xml @@ -25,6 +25,6 @@ <dependency org="com.vaadin.external.gwt" name="gwt-dev" rev="${gwt.version}" conf="gwt-dev,ide->default" /> <dependency org="com.vaadin.external.gwt" name="gwt-user" rev="${gwt.version}" conf="gwt-user,ide->default" /> <dependency org="com.vaadin.external.gwt" name="gwt-codeserver" rev="${gwt.version}" conf="gwt-codeserver,ide->default" /> - <dependency org="com.vaadin.external.gwt" name="gwt-elemental" rev="${gwt.version}" conf="gwt-elemental->default" /> + <dependency org="com.vaadin.external.gwt" name="gwt-elemental" rev="${gwt.version}" conf="gwt-elemental,ide->default" /> </dependencies> </ivy-module> diff --git a/push/build.xml b/push/build.xml index dee5820efb..fb80cc7cbf 100644 --- a/push/build.xml +++ b/push/build.xml @@ -16,7 +16,7 @@ <property name="vaadinPush.debug.js" location="${result.dir}/js/VAADIN/vaadinPush.debug.js" /> <!-- Keep the version number in sync with ivy.xml, server/src/com/vaadin/server/Constants.java --> - <property name="atmosphere.runtime.version" value="2.1.2.vaadin3" /> + <property name="atmosphere.runtime.version" value="2.1.2.vaadin4" /> <property name="jquery.js" location="lib/jquery/jquery-1.11.0.js" /> <path id="classpath.compile.custom" /> diff --git a/push/ivy.xml b/push/ivy.xml index d3b4944353..b6bd1b06f7 100644 --- a/push/ivy.xml +++ b/push/ivy.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE ivy-module [ <!-- Keep the version number in sync with build.xml --> - <!ENTITY atmosphere.runtime.version "2.1.2.vaadin3"> + <!ENTITY atmosphere.runtime.version "2.1.2.vaadin4"> <!ENTITY atmosphere.js.version "2.1.5.vaadin4"> ]> diff --git a/server/src/com/vaadin/data/RpcDataProviderExtension.java b/server/src/com/vaadin/data/RpcDataProviderExtension.java index 3185300897..f0a9ca39fd 100644 --- a/server/src/com/vaadin/data/RpcDataProviderExtension.java +++ b/server/src/com/vaadin/data/RpcDataProviderExtension.java @@ -19,7 +19,6 @@ package com.vaadin.data; import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -27,10 +26,6 @@ import java.util.Locale; import java.util.Map; import java.util.Set; -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; - import com.google.gwt.thirdparty.guava.common.collect.BiMap; import com.google.gwt.thirdparty.guava.common.collect.HashBiMap; import com.vaadin.data.Container.Indexed; @@ -56,6 +51,11 @@ import com.vaadin.ui.components.grid.Renderer; import com.vaadin.ui.components.grid.selection.SelectionChangeEvent; import com.vaadin.ui.components.grid.selection.SelectionChangeListener; +import elemental.json.Json; +import elemental.json.JsonArray; +import elemental.json.JsonObject; +import elemental.json.JsonValue; + /** * Provides Vaadin server-side container data source to a * {@link com.vaadin.client.ui.grid.GridConnector}. This is currently @@ -704,43 +704,36 @@ public class RpcDataProviderExtension extends AbstractExtension { private void pushRows(int firstRow, List<?> itemIds) { Collection<?> propertyIds = container.getContainerPropertyIds(); - JSONArray rows = new JSONArray(); - for (Object itemId : itemIds) { - rows.put(getRowData(propertyIds, itemId)); + JsonArray rows = Json.createArray(); + for (int i = 0; i < itemIds.size(); ++i) { + rows.set(i, getRowData(propertyIds, itemIds.get(i))); } - String jsonString = rows.toString(); - getRpcProxy(DataProviderRpc.class).setRowData(firstRow, jsonString); + getRpcProxy(DataProviderRpc.class).setRowData(firstRow, rows.toJson()); } - private JSONObject getRowData(Collection<?> propertyIds, Object itemId) { + private JsonValue getRowData(Collection<?> propertyIds, Object itemId) { Item item = container.getItem(itemId); - String[] row = new String[propertyIds.size()]; - JSONArray rowData = new JSONArray(); + JsonArray rowData = Json.createArray(); Grid grid = getGrid(); - try { - for (Object propertyId : propertyIds) { - GridColumn column = grid.getColumn(propertyId); - Object propertyValue = item.getItemProperty(propertyId) - .getValue(); - Object encodedValue = encodeValue(propertyValue, - column.getRenderer(), column.getConverter(), - grid.getLocale()); + int i = 0; + for (Object propertyId : propertyIds) { + GridColumn column = grid.getColumn(propertyId); - rowData.put(encodedValue); - } + Object propertyValue = item.getItemProperty(propertyId).getValue(); + JsonValue encodedValue = encodeValue(propertyValue, + column.getRenderer(), column.getConverter(), + grid.getLocale()); - final JSONObject rowObject = new JSONObject(); - rowObject.put(GridState.JSONKEY_DATA, rowData); - rowObject.put(GridState.JSONKEY_ROWKEY, keyMapper.getKey(itemId)); - return rowObject; - } catch (final JSONException e) { - throw new RuntimeException("Grid was unable to serialize " - + "data for row (this should've been caught " - + "eariler by other Grid logic)", e); + rowData.set(i++, encodedValue); } + + final JsonObject rowObject = Json.createObject(); + rowObject.put(GridState.JSONKEY_DATA, rowData); + rowObject.put(GridState.JSONKEY_ROWKEY, keyMapper.getKey(itemId)); + return rowObject; } @Override @@ -809,10 +802,10 @@ public class RpcDataProviderExtension extends AbstractExtension { * roundtrip. */ Object itemId = container.getIdByIndex(index); - JSONObject row = getRowData(container.getContainerPropertyIds(), itemId); - JSONArray rowArray = new JSONArray(Collections.singleton(row)); - String jsonString = rowArray.toString(); - getRpcProxy(DataProviderRpc.class).setRowData(index, jsonString); + JsonValue row = getRowData(container.getContainerPropertyIds(), itemId); + JsonArray rowArray = Json.createArray(); + rowArray.set(0, row); + getRpcProxy(DataProviderRpc.class).setRowData(index, rowArray.toJson()); } @Override @@ -888,7 +881,7 @@ public class RpcDataProviderExtension extends AbstractExtension { * the locale to use in conversion * @return an encoded value ready to be sent to the client */ - public static <T> Object encodeValue(Object modelValue, + public static <T> JsonValue encodeValue(Object modelValue, Renderer<T> renderer, Converter<?, ?> converter, Locale locale) { Class<T> presentationType = renderer.getPresentationType(); T presentationValue; @@ -913,24 +906,8 @@ public class RpcDataProviderExtension extends AbstractExtension { safeConverter.getPresentationType(), locale); } - Object encodedValue = renderer.encode(presentationValue); + JsonValue encodedValue = renderer.encode(presentationValue); - /* - * because this is a relatively heavy operation, we'll hide this behind - * an assert so that the check will be removed in production mode - */ - assert jsonSupports(encodedValue) : "org.json.JSONObject does not know how to serialize objects of type " - + encodedValue.getClass().getName(); return encodedValue; } - - private static boolean jsonSupports(Object encodedValue) { - JSONObject jsonObject = new JSONObject(); - try { - jsonObject.accumulate("test", encodedValue); - } catch (JSONException e) { - return false; - } - return true; - } } diff --git a/server/src/com/vaadin/server/AbstractClientConnector.java b/server/src/com/vaadin/server/AbstractClientConnector.java index 03300b20e2..19796af48d 100644 --- a/server/src/com/vaadin/server/AbstractClientConnector.java +++ b/server/src/com/vaadin/server/AbstractClientConnector.java @@ -32,9 +32,6 @@ import java.util.Map; import java.util.NoSuchElementException; import java.util.logging.Logger; -import org.json.JSONException; -import org.json.JSONObject; - import com.vaadin.event.EventRouter; import com.vaadin.event.MethodEventSource; import com.vaadin.shared.communication.ClientRpc; @@ -46,6 +43,7 @@ import com.vaadin.ui.Component.Event; import com.vaadin.ui.HasComponents; import com.vaadin.ui.LegacyComponent; import com.vaadin.ui.UI; +import elemental.json.JsonObject; /** * An abstract base class for ClientConnector implementations. This class @@ -243,7 +241,7 @@ public abstract class AbstractClientConnector implements ClientConnector, } @Override - public JSONObject encodeState() throws JSONException { + public JsonObject encodeState() { return LegacyCommunicationManager.encodeState(this, getState(false)); } diff --git a/server/src/com/vaadin/server/BootstrapHandler.java b/server/src/com/vaadin/server/BootstrapHandler.java index 73bafcca25..0605d6a2b8 100644 --- a/server/src/com/vaadin/server/BootstrapHandler.java +++ b/server/src/com/vaadin/server/BootstrapHandler.java @@ -30,8 +30,6 @@ import java.util.Set; import javax.servlet.http.HttpServletResponse; -import org.json.JSONException; -import org.json.JSONObject; import org.jsoup.nodes.DataNode; import org.jsoup.nodes.Document; import org.jsoup.nodes.DocumentType; @@ -44,6 +42,11 @@ import com.vaadin.shared.Version; import com.vaadin.shared.communication.PushMode; import com.vaadin.ui.UI; +import elemental.json.Json; +import elemental.json.JsonException; +import elemental.json.JsonObject; +import elemental.json.impl.JsonUtil; + /** * * @author Vaadin Ltd @@ -191,7 +194,7 @@ public abstract class BootstrapHandler extends SynchronizedRequestHandler { String html = getBootstrapHtml(context); writeBootstrapPage(response, html); - } catch (JSONException e) { + } catch (JsonException e) { writeError(response, e); } @@ -340,10 +343,8 @@ public abstract class BootstrapHandler extends SynchronizedRequestHandler { * @param context * * @throws IOException - * @throws JSONException */ - private void setupMainDiv(BootstrapContext context) throws IOException, - JSONException { + private void setupMainDiv(BootstrapContext context) throws IOException { String style = getMainDivStyle(context); /*- Add classnames; @@ -375,14 +376,6 @@ public abstract class BootstrapHandler extends SynchronizedRequestHandler { String vaadinLocation = vaadinService.getStaticFileLocation(request) + "/VAADIN/"; - fragmentNodes - .add(new Element(Tag.valueOf("iframe"), "") - .attr("tabIndex", "-1") - .attr("id", "__gwt_historyFrame") - .attr("style", - "position:absolute;width:0;height:0;border:0;overflow:hidden") - .attr("src", "javascript:false")); - if (context.getPushMode().isEnabled()) { // Load client-side dependencies for push support String pushJS = vaadinLocation; @@ -407,8 +400,8 @@ public abstract class BootstrapHandler extends SynchronizedRequestHandler { StringBuilder builder = new StringBuilder(); builder.append("//<![CDATA[\n"); builder.append("if (!window.vaadin) alert(" - + JSONObject.quote("Failed to load the bootstrap javascript: " - + bootstrapLocation) + ");\n"); + + JsonUtil.quote("Failed to load the bootstrap javascript: " + + bootstrapLocation) + ");\n"); appendMainScriptTagContents(context, builder); @@ -420,8 +413,8 @@ public abstract class BootstrapHandler extends SynchronizedRequestHandler { } protected void appendMainScriptTagContents(BootstrapContext context, - StringBuilder builder) throws JSONException, IOException { - JSONObject appConfig = getApplicationParameters(context); + StringBuilder builder) throws IOException { + JsonObject appConfig = getApplicationParameters(context); boolean isDebug = !context.getSession().getConfiguration() .isProductionMode(); @@ -446,21 +439,21 @@ public abstract class BootstrapHandler extends SynchronizedRequestHandler { } private static void appendJsonObject(StringBuilder builder, - JSONObject jsonObject, boolean isDebug) throws JSONException { + JsonObject jsonObject, boolean isDebug) { if (isDebug) { - builder.append(jsonObject.toString(4)); + builder.append(JsonUtil.stringify(jsonObject, 4)); } else { - builder.append(jsonObject.toString()); + builder.append(JsonUtil.stringify(jsonObject)); } } - protected JSONObject getApplicationParameters(BootstrapContext context) - throws JSONException, PaintException { + protected JsonObject getApplicationParameters(BootstrapContext context) + throws PaintException { VaadinRequest request = context.getRequest(); VaadinSession session = context.getSession(); VaadinService vaadinService = request.getService(); - JSONObject appConfig = new JSONObject(); + JsonObject appConfig = Json.createObject(); String themeName = context.getThemeName(); if (themeName != null) { @@ -473,7 +466,7 @@ public abstract class BootstrapHandler extends SynchronizedRequestHandler { appConfig.put("extraParams", "&" + IGNORE_RESTART_PARAM + "=1"); } - JSONObject versionInfo = new JSONObject(); + JsonObject versionInfo = Json.createObject(); versionInfo.put("vaadinVersion", Version.getFullVersion()); appConfig.put("versionInfo", versionInfo); @@ -487,30 +480,42 @@ public abstract class BootstrapHandler extends SynchronizedRequestHandler { request); if (systemMessages != null) { // Write the CommunicationError -message to client - JSONObject comErrMsg = new JSONObject(); + JsonObject comErrMsg = Json.createObject(); comErrMsg.put("caption", systemMessages.getCommunicationErrorCaption()); comErrMsg.put("message", systemMessages.getCommunicationErrorMessage()); - comErrMsg.put("url", systemMessages.getCommunicationErrorURL()); + if (systemMessages.getCommunicationErrorURL() == null) { + comErrMsg.put("url", Json.createNull()); + } else { + comErrMsg.put("url", systemMessages.getCommunicationErrorURL()); + } appConfig.put("comErrMsg", comErrMsg); - JSONObject authErrMsg = new JSONObject(); + JsonObject authErrMsg = Json.createObject(); authErrMsg.put("caption", systemMessages.getAuthenticationErrorCaption()); authErrMsg.put("message", systemMessages.getAuthenticationErrorMessage()); - authErrMsg.put("url", systemMessages.getAuthenticationErrorURL()); + if (systemMessages.getAuthenticationErrorURL() == null) { + authErrMsg.put("url", Json.createNull()); + } else { + authErrMsg.put("url", systemMessages.getAuthenticationErrorURL()); + } appConfig.put("authErrMsg", authErrMsg); - JSONObject sessExpMsg = new JSONObject(); + JsonObject sessExpMsg = Json.createObject(); sessExpMsg .put("caption", systemMessages.getSessionExpiredCaption()); sessExpMsg .put("message", systemMessages.getSessionExpiredMessage()); - sessExpMsg.put("url", systemMessages.getSessionExpiredURL()); + if (systemMessages.getSessionExpiredURL() == null) { + sessExpMsg.put("url", Json.createNull()); + } else { + sessExpMsg.put("url", systemMessages.getSessionExpiredURL()); + } appConfig.put("sessExpMsg", sessExpMsg); } diff --git a/server/src/com/vaadin/server/ClientConnector.java b/server/src/com/vaadin/server/ClientConnector.java index e61ba50a3a..50ce2754cb 100644 --- a/server/src/com/vaadin/server/ClientConnector.java +++ b/server/src/com/vaadin/server/ClientConnector.java @@ -20,15 +20,13 @@ import java.lang.reflect.Method; import java.util.Collection; import java.util.List; -import org.json.JSONException; -import org.json.JSONObject; - import com.vaadin.event.ConnectorEvent; import com.vaadin.event.ConnectorEventListener; import com.vaadin.shared.Connector; import com.vaadin.shared.communication.SharedState; import com.vaadin.ui.UI; import com.vaadin.util.ReflectTools; +import elemental.json.JsonObject; /** * Interface implemented by all connectors that are capable of communicating @@ -279,10 +277,9 @@ public interface ClientConnector extends Connector { * . * * @return a JSON object with the encoded connector state - * @throws JSONException * if the state can not be encoded */ - public JSONObject encodeState() throws JSONException; + public JsonObject encodeState() ; /** * Handle a request directed to this connector. This can be used by diff --git a/server/src/com/vaadin/server/ClientMethodInvocation.java b/server/src/com/vaadin/server/ClientMethodInvocation.java index e51138d7bf..97caa7614a 100644 --- a/server/src/com/vaadin/server/ClientMethodInvocation.java +++ b/server/src/com/vaadin/server/ClientMethodInvocation.java @@ -23,8 +23,9 @@ import java.io.Serializable; import java.lang.reflect.Method; import java.lang.reflect.Type; -import org.json.JSONArray; -import org.json.JSONException; +import elemental.json.JsonArray; +import elemental.json.JsonException; +import elemental.json.impl.JsonUtil; /** * Internal class for keeping track of pending server to client method @@ -107,8 +108,8 @@ public class ClientMethodInvocation implements Serializable, Type type = parameterTypes[i]; if (type instanceof Class<?>) { Class<?> clazz = (Class<?>) type; - if (JSONArray.class.isAssignableFrom(clazz)) { - parameters[i] = ((JSONArray) parameters[i]).toString(); + if (JsonArray.class.isAssignableFrom(clazz)) { + parameters[i] = JsonUtil.stringify((JsonArray) parameters[i]); } } } @@ -124,10 +125,10 @@ public class ClientMethodInvocation implements Serializable, Type type = parameterTypes[i]; if (type instanceof Class<?>) { Class<?> clazz = (Class<?>) type; - if (JSONArray.class.isAssignableFrom(clazz)) { + if (JsonArray.class.isAssignableFrom(clazz)) { try { - parameters[i] = new JSONArray(((String) parameters[i])); - } catch (JSONException e) { + parameters[i] = JsonUtil.<JsonArray>parse((String) parameters[i]); + } catch (JsonException e) { throw new IOException(e); } } diff --git a/server/src/com/vaadin/server/Constants.java b/server/src/com/vaadin/server/Constants.java index 08b5b70f50..aa1e02a96e 100644 --- a/server/src/com/vaadin/server/Constants.java +++ b/server/src/com/vaadin/server/Constants.java @@ -67,7 +67,7 @@ public interface Constants { // Keep the version number in sync with push/build.xml and other locations // listed in that file - static final String REQUIRED_ATMOSPHERE_RUNTIME_VERSION = "2.1.2.vaadin3"; + static final String REQUIRED_ATMOSPHERE_RUNTIME_VERSION = "2.1.2.vaadin4"; static final String INVALID_ATMOSPHERE_VERSION_WARNING = "\n" + "=================================================================\n" diff --git a/server/src/com/vaadin/server/DragAndDropService.java b/server/src/com/vaadin/server/DragAndDropService.java index 087a670b5b..c21f27de97 100644 --- a/server/src/com/vaadin/server/DragAndDropService.java +++ b/server/src/com/vaadin/server/DragAndDropService.java @@ -24,9 +24,6 @@ import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; -import org.json.JSONException; -import org.json.JSONObject; - import com.vaadin.event.Transferable; import com.vaadin.event.TransferableImpl; import com.vaadin.event.dd.DragAndDropEvent; @@ -41,6 +38,7 @@ import com.vaadin.shared.communication.SharedState; import com.vaadin.shared.ui.dd.DragEventType; import com.vaadin.ui.Component; import com.vaadin.ui.UI; +import elemental.json.JsonObject; public class DragAndDropService implements VariableOwner, ClientConnector { @@ -352,7 +350,7 @@ public class DragAndDropService implements VariableOwner, ClientConnector { } @Override - public JSONObject encodeState() throws JSONException { + public JsonObject encodeState() { // TODO Auto-generated method stub return null; } diff --git a/server/src/com/vaadin/server/EncodeResult.java b/server/src/com/vaadin/server/EncodeResult.java index 55a97aa829..bf4fd48438 100644 --- a/server/src/com/vaadin/server/EncodeResult.java +++ b/server/src/com/vaadin/server/EncodeResult.java @@ -18,29 +18,31 @@ package com.vaadin.server; import java.io.Serializable; +import elemental.json.JsonValue; + public class EncodeResult implements Serializable { - private final Object encodedValue; - private final Object diff; + private final JsonValue encodedValue; + private final JsonValue diff; - public EncodeResult(Object encodedValue) { + public EncodeResult(JsonValue encodedValue) { this(encodedValue, null); } - public EncodeResult(Object encodedValue, Object diff) { + public EncodeResult(JsonValue encodedValue, JsonValue diff) { this.encodedValue = encodedValue; this.diff = diff; } - public Object getEncodedValue() { + public JsonValue getEncodedValue() { return encodedValue; } - public Object getDiff() { + public JsonValue getDiff() { return diff; } - public Object getDiffOrValue() { - Object diff = getDiff(); + public JsonValue getDiffOrValue() { + JsonValue diff = getDiff(); if (diff != null) { return diff; } else { diff --git a/server/src/com/vaadin/server/JavaScriptCallbackHelper.java b/server/src/com/vaadin/server/JavaScriptCallbackHelper.java index 53fb1f838b..2552db6d13 100644 --- a/server/src/com/vaadin/server/JavaScriptCallbackHelper.java +++ b/server/src/com/vaadin/server/JavaScriptCallbackHelper.java @@ -18,21 +18,20 @@ package com.vaadin.server; import java.io.Serializable; import java.lang.reflect.Method; -import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; -import org.json.JSONArray; -import org.json.JSONException; - import com.vaadin.shared.JavaScriptConnectorState; import com.vaadin.ui.AbstractJavaScriptComponent; import com.vaadin.ui.JavaScript.JavaScriptCallbackRpc; import com.vaadin.ui.JavaScriptFunction; import com.vaadin.util.ReflectTools; +import elemental.json.JsonArray; +import elemental.json.JsonException; + /** * Internal helper class used to implement functionality common to * {@link AbstractJavaScriptComponent} and {@link AbstractJavaScriptExtension}. @@ -47,7 +46,7 @@ import com.vaadin.util.ReflectTools; public class JavaScriptCallbackHelper implements Serializable { private static final Method CALL_METHOD = ReflectTools.findMethod( - JavaScriptCallbackRpc.class, "call", String.class, JSONArray.class); + JavaScriptCallbackRpc.class, "call", String.class, JsonArray.class); private AbstractClientConnector connector; private Map<String, JavaScriptFunction> callbacks = new HashMap<String, JavaScriptFunction>(); @@ -75,11 +74,11 @@ public class JavaScriptCallbackHelper implements Serializable { if (javascriptCallbackRpc == null) { javascriptCallbackRpc = new JavaScriptCallbackRpc() { @Override - public void call(String name, JSONArray arguments) { + public void call(String name, JsonArray arguments) { JavaScriptFunction callback = callbacks.get(name); try { callback.call(arguments); - } catch (JSONException e) { + } catch (JsonException e) { throw new IllegalArgumentException(e); } } @@ -95,7 +94,7 @@ public class JavaScriptCallbackHelper implements Serializable { + name + " on the client because a callback with the same name is registered on the server."); } - JSONArray args = new JSONArray(Arrays.asList(arguments)); + JsonArray args = (JsonArray) JsonCodec.encode(arguments, null, Object[].class, null).getEncodedValue(); connector.addMethodInvocationToQueue( JavaScriptCallbackRpc.class.getName(), CALL_METHOD, new Object[] { name, args }); diff --git a/server/src/com/vaadin/server/JsonCodec.java b/server/src/com/vaadin/server/JsonCodec.java index 34b05f73bf..1e9438453a 100644 --- a/server/src/com/vaadin/server/JsonCodec.java +++ b/server/src/com/vaadin/server/JsonCodec.java @@ -28,12 +28,10 @@ import java.lang.reflect.Modifier; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; import java.util.Date; import java.util.HashMap; import java.util.HashSet; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -41,10 +39,6 @@ import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; - import com.vaadin.server.communication.DateSerializer; import com.vaadin.server.communication.JSONSerializer; import com.vaadin.shared.Connector; @@ -53,6 +47,16 @@ import com.vaadin.shared.communication.UidlValue; import com.vaadin.ui.Component; import com.vaadin.ui.ConnectorTracker; +import elemental.json.Json; +import elemental.json.JsonArray; +import elemental.json.JsonException; +import elemental.json.JsonNull; +import elemental.json.JsonObject; +import elemental.json.JsonString; +import elemental.json.JsonType; +import elemental.json.JsonValue; +import elemental.json.impl.JreJsonArray; + /** * Decoder for converting RPC parameters and other values from JSON in transfer * between the client and the server and vice versa. @@ -62,21 +66,32 @@ import com.vaadin.ui.ConnectorTracker; public class JsonCodec implements Serializable { /* Immutable Encode Result representing null */ - private static final EncodeResult ENCODE_RESULT_NULL = new EncodeResult( - JSONObject.NULL); + private static final EncodeResult ENCODE_RESULT_NULL = new EncodeResult(Json.createNull()); /* Immutable empty JSONArray */ - private static final JSONArray EMPTY_JSON_ARRAY = new JSONArray() { + private static final JsonArray EMPTY_JSON_ARRAY = new JreJsonArray(Json.instance()) { @Override - public JSONArray put(Object value) { + public void set(int index, JsonValue value) { throw new UnsupportedOperationException( - "Immutable empty JSONArray."); + "Immutable empty JsonArray."); } @Override - public JSONArray put(int index, Object value) { + public void set(int index, String string) { throw new UnsupportedOperationException( - "Immutable empty JSONArray."); + "Immutable empty JsonArray."); + } + + @Override + public void set(int index, double number) { + throw new UnsupportedOperationException( + "Immutable empty JsonArray."); + } + + @Override + public void set(int index, boolean bool) { + throw new UnsupportedOperationException( + "Immutable empty JsonArray."); } }; @@ -266,8 +281,7 @@ public class JsonCodec implements Serializable { } public static Object decodeInternalOrCustomType(Type targetType, - Object value, ConnectorTracker connectorTracker) - throws JSONException { + JsonValue value, ConnectorTracker connectorTracker) { if (isInternalType(targetType)) { return decodeInternalType(targetType, false, value, connectorTracker); @@ -276,50 +290,49 @@ public class JsonCodec implements Serializable { } } - public static Object decodeCustomType(Type targetType, Object value, - ConnectorTracker connectorTracker) throws JSONException { + public static Object decodeCustomType(Type targetType, JsonValue value, + ConnectorTracker connectorTracker) { if (isInternalType(targetType)) { - throw new JSONException("decodeCustomType cannot be used for " + throw new JsonException("decodeCustomType cannot be used for " + targetType + ", which is an internal type"); } // Try to decode object using fields - if (value == JSONObject.NULL) { + if (value.getType() == JsonType.NULL) { return null; } else if (targetType == byte.class || targetType == Byte.class) { - return Byte.valueOf(String.valueOf(value)); + return Byte.valueOf((byte) value.asNumber()); } else if (targetType == char.class || targetType == Character.class) { - return Character.valueOf(String.valueOf(value).charAt(0)); + return Character.valueOf(value.asString().charAt(0)); } else if (targetType instanceof Class<?> && ((Class<?>) targetType).isArray()) { // Legacy Object[] and String[] handled elsewhere, this takes care // of generic arrays Class<?> componentType = ((Class<?>) targetType).getComponentType(); - return decodeArray(componentType, (JSONArray) value, + return decodeArray(componentType, (JsonArray) value, connectorTracker); } else if (targetType instanceof GenericArrayType) { Type componentType = ((GenericArrayType) targetType) .getGenericComponentType(); - return decodeArray(componentType, (JSONArray) value, + return decodeArray(componentType, (JsonArray) value, connectorTracker); - } else if (targetType == JSONObject.class - || targetType == JSONArray.class) { + } else if (JsonValue.class.isAssignableFrom(getClassForType(targetType))) { return value; } else if (Enum.class.isAssignableFrom(getClassForType(targetType))) { Class<?> classForType = getClassForType(targetType); return decodeEnum(classForType.asSubclass(Enum.class), - (String) value); + (JsonString) value); } else if (customSerializers.containsKey(getClassForType(targetType))) { return customSerializers.get(getClassForType(targetType)) .deserialize(targetType, value, connectorTracker); } else { - return decodeObject(targetType, (JSONObject) value, + return decodeObject(targetType, (JsonObject) value, connectorTracker); } } - private static Object decodeArray(Type componentType, JSONArray value, - ConnectorTracker connectorTracker) throws JSONException { + private static Object decodeArray(Type componentType, JsonArray value, + ConnectorTracker connectorTracker) { Class<?> componentClass = getClassForType(componentType); Object array = Array.newInstance(componentClass, value.length()); for (int i = 0; i < value.length(); i++) { @@ -352,37 +365,36 @@ public class JsonCodec implements Serializable { * true if generics should be enforce, false to only allow * internal types in collections * @return - * @throws JSONException */ public static Object decodeInternalType(Type targetType, - boolean restrictToInternalTypes, Object encodedJsonValue, - ConnectorTracker connectorTracker) throws JSONException { + boolean restrictToInternalTypes, JsonValue encodedJsonValue, + ConnectorTracker connectorTracker) { if (!isInternalType(targetType)) { - throw new JSONException("Type " + targetType + throw new JsonException("Type " + targetType + " is not a supported internal type."); } String transportType = getInternalTransportType(targetType); - if (encodedJsonValue == JSONObject.NULL) { + if (encodedJsonValue.getType() == JsonType.NULL) { return null; } else if (targetType == Void.class) { - throw new JSONException( + throw new JsonException( "Something other than null was encoded for a null type"); } // UidlValue if (targetType == UidlValue.class) { - return decodeUidlValue((JSONArray) encodedJsonValue, + return decodeUidlValue((JsonArray) encodedJsonValue, connectorTracker); } // Collections if (JsonConstants.VTYPE_LIST.equals(transportType)) { return decodeList(targetType, restrictToInternalTypes, - (JSONArray) encodedJsonValue, connectorTracker); + (JsonArray) encodedJsonValue, connectorTracker); } else if (JsonConstants.VTYPE_SET.equals(transportType)) { return decodeSet(targetType, restrictToInternalTypes, - (JSONArray) encodedJsonValue, connectorTracker); + (JsonArray) encodedJsonValue, connectorTracker); } else if (JsonConstants.VTYPE_MAP.equals(transportType)) { return decodeMap(targetType, restrictToInternalTypes, encodedJsonValue, connectorTracker); @@ -391,42 +403,40 @@ public class JsonCodec implements Serializable { // Arrays if (JsonConstants.VTYPE_ARRAY.equals(transportType)) { - return decodeObjectArray(targetType, (JSONArray) encodedJsonValue, + return decodeObjectArray(targetType, (JsonArray) encodedJsonValue, connectorTracker); } else if (JsonConstants.VTYPE_STRINGARRAY.equals(transportType)) { - return decodeStringArray((JSONArray) encodedJsonValue); + return decodeStringArray((JsonArray) encodedJsonValue); } // Special Vaadin types - String stringValue = String.valueOf(encodedJsonValue); - if (JsonConstants.VTYPE_CONNECTOR.equals(transportType)) { - return connectorTracker.getConnector(stringValue); + return connectorTracker.getConnector(encodedJsonValue.asString()); } // Legacy types if (JsonConstants.VTYPE_STRING.equals(transportType)) { - return stringValue; + return encodedJsonValue.asString(); } else if (JsonConstants.VTYPE_INTEGER.equals(transportType)) { - return Integer.valueOf(stringValue); + return (int) encodedJsonValue.asNumber(); } else if (JsonConstants.VTYPE_LONG.equals(transportType)) { - return Long.valueOf(stringValue); + return (long) encodedJsonValue.asNumber(); } else if (JsonConstants.VTYPE_FLOAT.equals(transportType)) { - return Float.valueOf(stringValue); + return (float) encodedJsonValue.asNumber(); } else if (JsonConstants.VTYPE_DOUBLE.equals(transportType)) { - return Double.valueOf(stringValue); + return encodedJsonValue.asNumber(); } else if (JsonConstants.VTYPE_BOOLEAN.equals(transportType)) { - return Boolean.valueOf(stringValue); + return encodedJsonValue.asBoolean(); } - throw new JSONException("Unknown type " + transportType); + throw new JsonException("Unknown type " + transportType); } - private static UidlValue decodeUidlValue(JSONArray encodedJsonValue, - ConnectorTracker connectorTracker) throws JSONException { + private static UidlValue decodeUidlValue(JsonArray encodedJsonValue, + ConnectorTracker connectorTracker) { String type = encodedJsonValue.getString(0); Object decodedValue = decodeInternalType(getType(type), true, @@ -435,13 +445,13 @@ public class JsonCodec implements Serializable { } private static Map<Object, Object> decodeMap(Type targetType, - boolean restrictToInternalTypes, Object jsonMap, - ConnectorTracker connectorTracker) throws JSONException { - if (jsonMap instanceof JSONArray) { + boolean restrictToInternalTypes, JsonValue jsonMap, + ConnectorTracker connectorTracker) { + if (jsonMap.getType() == JsonType.ARRAY) { // Client-side has no declared type information to determine // encoding method for empty maps, so these are handled separately. // See #8906. - JSONArray jsonArray = (JSONArray) jsonMap; + JsonArray jsonArray = (JsonArray) jsonMap; if (jsonArray.length() == 0) { return new HashMap<Object, Object>(); } @@ -453,27 +463,27 @@ public class JsonCodec implements Serializable { Type valueType = ((ParameterizedType) targetType) .getActualTypeArguments()[1]; if (keyType == String.class) { - return decodeStringMap(valueType, (JSONObject) jsonMap, + return decodeStringMap(valueType, (JsonObject) jsonMap, connectorTracker); } else if (keyType == Connector.class) { - return decodeConnectorMap(valueType, (JSONObject) jsonMap, + return decodeConnectorMap(valueType, (JsonObject) jsonMap, connectorTracker); } else { - return decodeObjectMap(keyType, valueType, (JSONArray) jsonMap, + return decodeObjectMap(keyType, valueType, (JsonArray) jsonMap, connectorTracker); } } else { - return decodeStringMap(UidlValue.class, (JSONObject) jsonMap, + return decodeStringMap(UidlValue.class, (JsonObject) jsonMap, connectorTracker); } } private static Map<Object, Object> decodeObjectMap(Type keyType, - Type valueType, JSONArray jsonMap, ConnectorTracker connectorTracker) - throws JSONException { + Type valueType, JsonArray jsonMap, ConnectorTracker connectorTracker) + { - JSONArray keys = jsonMap.getJSONArray(0); - JSONArray values = jsonMap.getJSONArray(1); + JsonArray keys = jsonMap.getArray(0); + JsonArray values = jsonMap.getArray(1); assert (keys.length() == values.length()); @@ -491,12 +501,10 @@ public class JsonCodec implements Serializable { } private static Map<Object, Object> decodeConnectorMap(Type valueType, - JSONObject jsonMap, ConnectorTracker connectorTracker) - throws JSONException { + JsonObject jsonMap, ConnectorTracker connectorTracker) { Map<Object, Object> map = new HashMap<Object, Object>(); - for (Iterator<?> iter = jsonMap.keys(); iter.hasNext();) { - String key = (String) iter.next(); + for (String key : jsonMap.keys()) { Object value = decodeInternalOrCustomType(valueType, jsonMap.get(key), connectorTracker); if (valueType == UidlValue.class) { @@ -509,12 +517,10 @@ public class JsonCodec implements Serializable { } private static Map<Object, Object> decodeStringMap(Type valueType, - JSONObject jsonMap, ConnectorTracker connectorTracker) - throws JSONException { + JsonObject jsonMap, ConnectorTracker connectorTracker) { Map<Object, Object> map = new HashMap<Object, Object>(); - for (Iterator<?> iter = jsonMap.keys(); iter.hasNext();) { - String key = (String) iter.next(); + for (String key : jsonMap.keys()) { Object value = decodeInternalOrCustomType(valueType, jsonMap.get(key), connectorTracker); if (valueType == UidlValue.class) { @@ -535,11 +541,10 @@ public class JsonCodec implements Serializable { * @param encodedValueAndType * @param application * @return - * @throws JSONException */ private static Object decodeParametrizedType(Type targetType, - boolean restrictToInternalTypes, int typeIndex, Object value, - ConnectorTracker connectorTracker) throws JSONException { + boolean restrictToInternalTypes, int typeIndex, JsonValue value, + ConnectorTracker connectorTracker) { if (!restrictToInternalTypes && targetType instanceof ParameterizedType) { Type childType = ((ParameterizedType) targetType) .getActualTypeArguments()[typeIndex]; @@ -555,12 +560,11 @@ public class JsonCodec implements Serializable { } } - private static Object decodeEnum(Class<? extends Enum> cls, String value) { - return Enum.valueOf(cls, value); + private static Object decodeEnum(Class<? extends Enum> cls, JsonString value) { + return Enum.valueOf(cls, value.getString()); } - private static String[] decodeStringArray(JSONArray jsonArray) - throws JSONException { + private static String[] decodeStringArray(JsonArray jsonArray) { int length = jsonArray.length(); List<String> tokens = new ArrayList<String>(length); for (int i = 0; i < length; ++i) { @@ -570,21 +574,20 @@ public class JsonCodec implements Serializable { } private static Object[] decodeObjectArray(Type targetType, - JSONArray jsonArray, ConnectorTracker connectorTracker) - throws JSONException { + JsonArray jsonArray, ConnectorTracker connectorTracker) { List<Object> list = decodeList(List.class, true, jsonArray, connectorTracker); return list.toArray(new Object[list.size()]); } private static List<Object> decodeList(Type targetType, - boolean restrictToInternalTypes, JSONArray jsonArray, - ConnectorTracker connectorTracker) throws JSONException { + boolean restrictToInternalTypes, JsonArray jsonArray, + ConnectorTracker connectorTracker) { int arrayLength = jsonArray.length(); List<Object> list = new ArrayList<Object>(arrayLength); for (int i = 0; i < arrayLength; ++i) { // each entry always has two elements: type and value - Object encodedValue = jsonArray.get(i); + JsonValue encodedValue = jsonArray.get(i); Object decodedChild = decodeParametrizedType(targetType, restrictToInternalTypes, 0, encodedValue, connectorTracker); list.add(decodedChild); @@ -593,8 +596,8 @@ public class JsonCodec implements Serializable { } private static Set<Object> decodeSet(Type targetType, - boolean restrictToInternalTypes, JSONArray jsonArray, - ConnectorTracker connectorTracker) throws JSONException { + boolean restrictToInternalTypes, JsonArray jsonArray, + ConnectorTracker connectorTracker) { HashSet<Object> set = new HashSet<Object>(); set.addAll(decodeList(targetType, restrictToInternalTypes, jsonArray, connectorTracker)); @@ -602,8 +605,7 @@ public class JsonCodec implements Serializable { } private static Object decodeObject(Type targetType, - JSONObject serializedObject, ConnectorTracker connectorTracker) - throws JSONException { + JsonObject serializedObject, ConnectorTracker connectorTracker) { Class<?> targetClass = getClassForType(targetType); @@ -612,7 +614,7 @@ public class JsonCodec implements Serializable { for (BeanProperty property : getProperties(targetClass)) { String fieldName = property.getName(); - Object encodedFieldValue = serializedObject.get(fieldName); + JsonValue encodedFieldValue = serializedObject.get(fieldName); Type fieldType = property.getType(); Object decodedFieldValue = decodeInternalOrCustomType( fieldType, encodedFieldValue, connectorTracker); @@ -622,13 +624,12 @@ public class JsonCodec implements Serializable { return decodedObject; } catch (Exception e) { - throw new JSONException(e.getMessage()); + throw new RuntimeException(e); } } - public static EncodeResult encode(Object value, Object diffState, - Type valueType, ConnectorTracker connectorTracker) - throws JSONException { + public static EncodeResult encode(Object value, JsonValue diffState, + Type valueType, ConnectorTracker connectorTracker) { if (null == value) { return ENCODE_RESULT_NULL; @@ -636,13 +637,19 @@ public class JsonCodec implements Serializable { // Storing a single reference and only returning the EncodeResult at the // end the method is much shorter in bytecode which allows inlining - Object toReturn; + JsonValue toReturn; - if (value instanceof String || value instanceof Boolean - || value instanceof Number || value instanceof Character - || value instanceof JSONArray || value instanceof JSONObject) { + if (value instanceof JsonValue) { // all JSON compatible types are returned as is. - toReturn = value; + toReturn = (JsonValue) value; + } else if (value instanceof String) { + toReturn = Json.create((String) value); + } else if (value instanceof Boolean) { + toReturn = Json.create((Boolean) value); + } else if (value instanceof Number) { + toReturn = Json.create(((Number) value).doubleValue()); + } else if (value instanceof Character) { + toReturn = Json.create(Character.toString((Character) value)); } else if (value instanceof String[]) { toReturn = toJsonArray((String[]) value); } else if (value instanceof Collection) { @@ -658,9 +665,9 @@ public class JsonCodec implements Serializable { return ENCODE_RESULT_NULL; } // Connectors are simply serialized as ID. - toReturn = ((Connector) value).getConnectorId(); + toReturn = Json.create(((Connector) value).getConnectorId()); } else if (value instanceof Enum) { - toReturn = ((Enum<?>) value).name(); + toReturn = Json.create(((Enum<?>) value).name()); } else if (customSerializers.containsKey(value.getClass())) { toReturn = serializeJson(value, connectorTracker); } else if (valueType instanceof GenericArrayType) { @@ -677,10 +684,10 @@ public class JsonCodec implements Serializable { // needs to return it directly rather than assigning it to // toReturn. return encodeObject(value, (Class<?>) valueType, - (JSONObject) diffState, connectorTracker); + (JsonObject) diffState, connectorTracker); } } else { - throw new JSONException("Can not encode type " + valueType); + throw new JsonException("Can not encode type " + valueType); } return new EncodeResult(toReturn); } @@ -706,10 +713,9 @@ public class JsonCodec implements Serializable { * Loops through the fields of value and encodes them. */ private static EncodeResult encodeObject(Object value, Class<?> valueType, - JSONObject referenceValue, ConnectorTracker connectorTracker) - throws JSONException { - JSONObject encoded = new JSONObject(); - JSONObject diff = new JSONObject(); + JsonObject referenceValue, ConnectorTracker connectorTracker) { + JsonObject encoded = Json.createObject(); + JsonObject diff = Json.createObject(); try { for (BeanProperty property : getProperties(valueType)) { @@ -719,7 +725,7 @@ public class JsonCodec implements Serializable { Type fieldType = property.getType(); Object fieldValue = property.getValue(value); - if (encoded.has(fieldName)) { + if (encoded.hasKey(fieldName)) { throw new RuntimeException( "Can't encode " + valueType.getName() @@ -728,10 +734,10 @@ public class JsonCodec implements Serializable { + ". This can happen if there are getters and setters for a public field (the framework can't know which to ignore) or if there are properties with only casing distinguishing between the names (e.g. getFoo() and getFOO())"); } - Object fieldReference; + JsonValue fieldReference; if (referenceValue != null) { fieldReference = referenceValue.get(fieldName); - if (JSONObject.NULL.equals(fieldReference)) { + if (fieldReference instanceof JsonNull) { fieldReference = null; } } else { @@ -748,7 +754,7 @@ public class JsonCodec implements Serializable { } } catch (Exception e) { // TODO: Should exceptions be handled in a different way? - throw new JSONException(e.getMessage()); + throw new RuntimeException(e); } return new EncodeResult(encoded, diff); } @@ -760,8 +766,8 @@ public class JsonCodec implements Serializable { * @param referenceValue * @return */ - private static boolean jsonEquals(Object fieldValue, Object referenceValue) { - if (fieldValue == JSONObject.NULL) { + private static boolean jsonEquals(JsonValue fieldValue, JsonValue referenceValue) { + if (fieldValue instanceof JsonNull) { fieldValue = null; } @@ -769,41 +775,33 @@ public class JsonCodec implements Serializable { return true; } else if (fieldValue == null || referenceValue == null) { return false; - } else if (fieldValue instanceof Integer - && referenceValue instanceof Integer) { - return ((Integer) fieldValue).equals(referenceValue); - } else if (fieldValue instanceof Boolean - && referenceValue instanceof Boolean) { - return ((Boolean) fieldValue).equals(referenceValue); } else { - return fieldValue.toString().equals(referenceValue.toString()); + return fieldValue.jsEquals(referenceValue); } } - private static JSONArray encodeArrayContents(Type componentType, - Object array, ConnectorTracker connectorTracker) - throws JSONException { - JSONArray jsonArray = new JSONArray(); + private static JsonArray encodeArrayContents(Type componentType, + Object array, ConnectorTracker connectorTracker) { + JsonArray jsonArray = Json.createArray(); for (int i = 0; i < Array.getLength(array); i++) { EncodeResult encodeResult = encode(Array.get(array, i), null, componentType, connectorTracker); - jsonArray.put(encodeResult.getEncodedValue()); + jsonArray.set(i, encodeResult.getEncodedValue()); } return jsonArray; } - private static JSONArray encodeCollection(Type targetType, - Collection<?> collection, ConnectorTracker connectorTracker) - throws JSONException { - JSONArray jsonArray = new JSONArray(); + private static JsonArray encodeCollection(Type targetType, + Collection<?> collection, ConnectorTracker connectorTracker) { + JsonArray jsonArray = Json.createArray(); for (Object o : collection) { - jsonArray.put(encodeChild(targetType, 0, o, connectorTracker)); + jsonArray.set(jsonArray.length(), encodeChild(targetType, 0, o, connectorTracker)); } return jsonArray; } - private static Object encodeChild(Type targetType, int typeIndex, Object o, - ConnectorTracker connectorTracker) throws JSONException { + private static JsonValue encodeChild(Type targetType, int typeIndex, Object o, + ConnectorTracker connectorTracker) { if (targetType instanceof ParameterizedType) { Type childType = ((ParameterizedType) targetType) .getActualTypeArguments()[typeIndex]; @@ -812,19 +810,19 @@ public class JsonCodec implements Serializable { connectorTracker); return encodeResult.getEncodedValue(); } else { - throw new JSONException("Collection is missing generics"); + throw new JsonException("Collection is missing generics"); } } - private static Object encodeMap(Type mapType, Map<?, ?> map, - ConnectorTracker connectorTracker) throws JSONException { + private static JsonValue encodeMap(Type mapType, Map<?, ?> map, + ConnectorTracker connectorTracker) { Type keyType, valueType; if (mapType instanceof ParameterizedType) { keyType = ((ParameterizedType) mapType).getActualTypeArguments()[0]; valueType = ((ParameterizedType) mapType).getActualTypeArguments()[1]; } else { - throw new JSONException("Map is missing generics"); + throw new JsonException("Map is missing generics"); } if (map.isEmpty()) { @@ -842,11 +840,10 @@ public class JsonCodec implements Serializable { } } - private static JSONArray encodeObjectMap(Type keyType, Type valueType, - Map<?, ?> map, ConnectorTracker connectorTracker) - throws JSONException { - JSONArray keys = new JSONArray(); - JSONArray values = new JSONArray(); + private static JsonArray encodeObjectMap(Type keyType, Type valueType, + Map<?, ?> map, ConnectorTracker connectorTracker) { + JsonArray keys = Json.createArray(); + JsonArray values = Json.createArray(); for (Entry<?, ?> entry : map.entrySet()) { EncodeResult encodedKey = encode(entry.getKey(), null, keyType, @@ -854,19 +851,23 @@ public class JsonCodec implements Serializable { EncodeResult encodedValue = encode(entry.getValue(), null, valueType, connectorTracker); - keys.put(encodedKey.getEncodedValue()); - values.put(encodedValue.getEncodedValue()); + keys.set(keys.length(), encodedKey.getEncodedValue()); + values.set(values.length(), encodedValue.getEncodedValue()); } - return new JSONArray(Arrays.asList(keys, values)); + JsonArray jsonMap = Json.createArray(); + jsonMap.set(0, keys); + jsonMap.set(1, values); + + return jsonMap; } /* * Encodes a connector map. Invisible connectors are skipped. */ - private static JSONObject encodeConnectorMap(Type valueType, Map<?, ?> map, - ConnectorTracker connectorTracker) throws JSONException { - JSONObject jsonMap = new JSONObject(); + private static JsonObject encodeConnectorMap(Type valueType, Map<?, ?> map, + ConnectorTracker connectorTracker) { + JsonObject jsonMap = Json.createObject(); for (Entry<?, ?> entry : map.entrySet()) { ClientConnector key = (ClientConnector) entry.getKey(); @@ -881,9 +882,9 @@ public class JsonCodec implements Serializable { return jsonMap; } - private static JSONObject encodeStringMap(Type valueType, Map<?, ?> map, - ConnectorTracker connectorTracker) throws JSONException { - JSONObject jsonMap = new JSONObject(); + private static JsonObject encodeStringMap(Type valueType, Map<?, ?> map, + ConnectorTracker connectorTracker) { + JsonObject jsonMap = Json.createObject(); for (Entry<?, ?> entry : map.entrySet()) { String key = (String) entry.getKey(); @@ -904,16 +905,16 @@ public class JsonCodec implements Serializable { return typeToTransportType.get(getClassForType(valueType)); } - private static Object serializeJson(Object value, + private static JsonValue serializeJson(Object value, ConnectorTracker connectorTracker) { JSONSerializer serializer = customSerializers.get(value.getClass()); return serializer.serialize(value, connectorTracker); } - private static JSONArray toJsonArray(String[] array) { - JSONArray jsonArray = new JSONArray(); + private static JsonArray toJsonArray(String[] array) { + JsonArray jsonArray = Json.createArray(); for (int i = 0; i < array.length; ++i) { - jsonArray.put(array[i]); + jsonArray.set(i, array[i]); } return jsonArray; } diff --git a/server/src/com/vaadin/server/LegacyCommunicationManager.java b/server/src/com/vaadin/server/LegacyCommunicationManager.java index 0dda5661bd..e1beb1153c 100644 --- a/server/src/com/vaadin/server/LegacyCommunicationManager.java +++ b/server/src/com/vaadin/server/LegacyCommunicationManager.java @@ -27,9 +27,6 @@ import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; -import org.json.JSONException; -import org.json.JSONObject; - import com.vaadin.server.ClientConnector.ConnectorErrorEvent; import com.vaadin.shared.ApplicationConstants; import com.vaadin.shared.JavaScriptConnectorState; @@ -40,6 +37,9 @@ import com.vaadin.ui.HasComponents; import com.vaadin.ui.SelectiveRenderer; import com.vaadin.ui.UI; +import elemental.json.JsonObject; +import elemental.json.JsonValue; + /** * This is a common base class for the server-side implementations of the * communication system between the client code (compiled with GWT into @@ -85,12 +85,11 @@ public class LegacyCommunicationManager implements Serializable { * @deprecated As of 7.1. See #11411. */ @Deprecated - public static JSONObject encodeState(ClientConnector connector, - SharedState state) throws JSONException { + public static JsonObject encodeState(ClientConnector connector, SharedState state) { UI uI = connector.getUI(); ConnectorTracker connectorTracker = uI.getConnectorTracker(); Class<? extends SharedState> stateType = connector.getStateType(); - Object diffState = connectorTracker.getDiffState(connector); + JsonValue diffState = connectorTracker.getDiffState(connector); boolean supportsDiffState = !JavaScriptConnectorState.class .isAssignableFrom(stateType); if (diffState == null && supportsDiffState) { @@ -113,9 +112,9 @@ public class LegacyCommunicationManager implements Serializable { stateType, uI.getConnectorTracker()); if (supportsDiffState) { connectorTracker.setDiffState(connector, - (JSONObject) encodeResult.getEncodedValue()); + (JsonObject) encodeResult.getEncodedValue()); } - return (JSONObject) encodeResult.getDiff(); + return (JsonObject) encodeResult.getDiff(); } /** diff --git a/server/src/com/vaadin/server/VaadinService.java b/server/src/com/vaadin/server/VaadinService.java index 8d44ff74ed..8fd6da8dee 100644 --- a/server/src/com/vaadin/server/VaadinService.java +++ b/server/src/com/vaadin/server/VaadinService.java @@ -48,9 +48,6 @@ import javax.servlet.Servlet; import javax.servlet.ServletContext; import javax.servlet.http.HttpServletResponse; -import org.json.JSONException; -import org.json.JSONObject; - import com.vaadin.annotations.PreserveOnRefresh; import com.vaadin.event.EventRouter; import com.vaadin.server.VaadinSession.FutureAccess; @@ -67,6 +64,11 @@ import com.vaadin.ui.UI; import com.vaadin.util.CurrentInstance; import com.vaadin.util.ReflectTools; +import elemental.json.Json; +import elemental.json.JsonException; +import elemental.json.JsonObject; +import elemental.json.impl.JsonUtil; + /** * Provide deployment specific settings that are required outside terminal * specific code. @@ -1574,22 +1576,26 @@ public abstract class VaadinService implements Serializable { message += "<br/><br/>" + details; } - JSONObject appError = new JSONObject(); + JsonObject appError = Json.createObject(); appError.put("caption", caption); appError.put("message", message); - appError.put("url", url); + if (url == null) { + appError.put("url", Json.createNull()); + } else { + appError.put("url", url); + } - JSONObject meta = new JSONObject(); + JsonObject meta = Json.createObject(); meta.put("appError", appError); - JSONObject json = new JSONObject(); - json.put("changes", new JSONObject()); - json.put("resources", new JSONObject()); - json.put("locales", new JSONObject()); + JsonObject json = Json.createObject(); + json.put("changes", Json.createObject()); + json.put("resources", Json.createObject()); + json.put("locales", Json.createObject()); json.put("meta", meta); json.put(ApplicationConstants.SERVER_SYNC_ID, -1); - returnString = json.toString(); - } catch (JSONException e) { + returnString = JsonUtil.stringify(json); + } catch (JsonException e) { getLogger().log(Level.WARNING, "Error creating critical notification JSON message", e); } diff --git a/server/src/com/vaadin/server/VaadinServlet.java b/server/src/com/vaadin/server/VaadinServlet.java index 09b8a22a46..4656f9a672 100644 --- a/server/src/com/vaadin/server/VaadinServlet.java +++ b/server/src/com/vaadin/server/VaadinServlet.java @@ -77,10 +77,20 @@ public class VaadinServlet extends HttpServlet implements Constants { long newest = 0; for (String uri : sourceUris) { File file = new File(uri); - if (!file.exists()) { - return -1; - } else { + if (file.exists()) { newest = Math.max(newest, file.lastModified()); + } else if (!uri.startsWith("VAADIN/")) { + /* + * Ignore missing files starting with VAADIN/ since those + * are fetched from the classpath, report problem and abort + * for other files. + */ + getLogger() + .log(Level.WARNING, + "Could not resolve timestamp for {0}, Scss on the fly caching will be disabled", + uri); + // -1 means this cache entry will never be valid + return -1; } } diff --git a/server/src/com/vaadin/server/communication/ClientRpcWriter.java b/server/src/com/vaadin/server/communication/ClientRpcWriter.java index 1090fdbab9..6631f6176d 100644 --- a/server/src/com/vaadin/server/communication/ClientRpcWriter.java +++ b/server/src/com/vaadin/server/communication/ClientRpcWriter.java @@ -24,9 +24,6 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; -import org.json.JSONArray; -import org.json.JSONException; - import com.vaadin.server.ClientConnector; import com.vaadin.server.ClientMethodInvocation; import com.vaadin.server.EncodeResult; @@ -35,6 +32,12 @@ import com.vaadin.server.PaintException; import com.vaadin.shared.communication.ClientRpc; import com.vaadin.ui.UI; +import elemental.json.Json; +import elemental.json.JsonArray; +import elemental.json.JsonException; +import elemental.json.JsonValue; +import elemental.json.impl.JsonUtil; + /** * Serializes {@link ClientRpc client RPC} invocations to JSON. * @@ -59,18 +62,18 @@ public class ClientRpcWriter implements Serializable { Collection<ClientMethodInvocation> pendingInvocations = collectPendingRpcCalls(ui .getConnectorTracker().getDirtyVisibleConnectors()); - JSONArray rpcCalls = new JSONArray(); + JsonArray rpcCalls = Json.createArray(); for (ClientMethodInvocation invocation : pendingInvocations) { // add invocation to rpcCalls try { - JSONArray invocationJson = new JSONArray(); - invocationJson.put(invocation.getConnector().getConnectorId()); - invocationJson.put(invocation.getInterfaceName()); - invocationJson.put(invocation.getMethodName()); - JSONArray paramJson = new JSONArray(); + JsonArray invocationJson = Json.createArray(); + invocationJson.set(0, invocation.getConnector().getConnectorId()); + invocationJson.set(1, invocation.getInterfaceName()); + invocationJson.set(2, invocation.getMethodName()); + JsonArray paramJson = Json.createArray(); for (int i = 0; i < invocation.getParameterTypes().length; ++i) { Type parameterType = invocation.getParameterTypes()[i]; - Object referenceParameter = null; + JsonValue referenceParameter = null; // TODO Use default values for RPC parameter types // if (!JsonCodec.isInternalType(parameterType)) { // try { @@ -84,11 +87,11 @@ public class ClientRpcWriter implements Serializable { EncodeResult encodeResult = JsonCodec.encode( invocation.getParameters()[i], referenceParameter, parameterType, ui.getConnectorTracker()); - paramJson.put(encodeResult.getEncodedValue()); + paramJson.set(i, encodeResult.getEncodedValue()); } - invocationJson.put(paramJson); - rpcCalls.put(invocationJson); - } catch (JSONException e) { + invocationJson.set(3, paramJson); + rpcCalls.set(rpcCalls.length(), invocationJson); + } catch (JsonException e) { throw new PaintException( "Failed to serialize RPC method call parameters for connector " + invocation.getConnector().getConnectorId() @@ -97,7 +100,7 @@ public class ClientRpcWriter implements Serializable { + e.getMessage(), e); } } - writer.write(rpcCalls.toString()); + writer.write(JsonUtil.stringify(rpcCalls)); } /** diff --git a/server/src/com/vaadin/server/communication/ConnectorHierarchyWriter.java b/server/src/com/vaadin/server/communication/ConnectorHierarchyWriter.java index 653048b930..1c1a220b5d 100644 --- a/server/src/com/vaadin/server/communication/ConnectorHierarchyWriter.java +++ b/server/src/com/vaadin/server/communication/ConnectorHierarchyWriter.java @@ -21,16 +21,18 @@ import java.io.Serializable; import java.io.Writer; import java.util.Collection; -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; - import com.vaadin.server.AbstractClientConnector; import com.vaadin.server.ClientConnector; import com.vaadin.server.LegacyCommunicationManager; import com.vaadin.server.PaintException; import com.vaadin.ui.UI; +import elemental.json.Json; +import elemental.json.JsonArray; +import elemental.json.JsonException; +import elemental.json.JsonObject; +import elemental.json.impl.JsonUtil; + /** * Serializes a connector hierarchy to JSON. * @@ -55,27 +57,27 @@ public class ConnectorHierarchyWriter implements Serializable { Collection<ClientConnector> dirtyVisibleConnectors = ui .getConnectorTracker().getDirtyVisibleConnectors(); - JSONObject hierarchyInfo = new JSONObject(); + JsonObject hierarchyInfo = Json.createObject(); for (ClientConnector connector : dirtyVisibleConnectors) { String connectorId = connector.getConnectorId(); - JSONArray children = new JSONArray(); + JsonArray children = Json.createArray(); for (ClientConnector child : AbstractClientConnector .getAllChildrenIterable(connector)) { if (LegacyCommunicationManager .isConnectorVisibleToClient(child)) { - children.put(child.getConnectorId()); + children.set(children.length(), child.getConnectorId()); } } try { hierarchyInfo.put(connectorId, children); - } catch (JSONException e) { + } catch (JsonException e) { throw new PaintException( "Failed to send hierarchy information about " + connectorId + " to the client: " + e.getMessage(), e); } } - writer.write(hierarchyInfo.toString()); + writer.write(JsonUtil.stringify(hierarchyInfo)); } } diff --git a/server/src/com/vaadin/server/communication/ConnectorTypeWriter.java b/server/src/com/vaadin/server/communication/ConnectorTypeWriter.java index 0bafd20a81..d534987061 100644 --- a/server/src/com/vaadin/server/communication/ConnectorTypeWriter.java +++ b/server/src/com/vaadin/server/communication/ConnectorTypeWriter.java @@ -21,14 +21,16 @@ import java.io.Serializable; import java.io.Writer; import java.util.Collection; -import org.json.JSONException; -import org.json.JSONObject; - import com.vaadin.server.ClientConnector; import com.vaadin.server.PaintException; import com.vaadin.server.PaintTarget; import com.vaadin.ui.UI; +import elemental.json.Json; +import elemental.json.JsonException; +import elemental.json.JsonObject; +import elemental.json.impl.JsonUtil; + /** * Serializes connector type mappings to JSON. * @@ -56,18 +58,18 @@ public class ConnectorTypeWriter implements Serializable { Collection<ClientConnector> dirtyVisibleConnectors = ui .getConnectorTracker().getDirtyVisibleConnectors(); - JSONObject connectorTypes = new JSONObject(); + JsonObject connectorTypes = Json.createObject(); for (ClientConnector connector : dirtyVisibleConnectors) { String connectorType = target.getTag(connector); try { connectorTypes.put(connector.getConnectorId(), connectorType); - } catch (JSONException e) { + } catch (JsonException e) { throw new PaintException( "Failed to send connector type for connector " + connector.getConnectorId() + ": " + e.getMessage(), e); } } - writer.write(connectorTypes.toString()); + writer.write(JsonUtil.stringify(connectorTypes)); } } diff --git a/server/src/com/vaadin/server/communication/DateSerializer.java b/server/src/com/vaadin/server/communication/DateSerializer.java index 429941abfd..593728bac7 100644 --- a/server/src/com/vaadin/server/communication/DateSerializer.java +++ b/server/src/com/vaadin/server/communication/DateSerializer.java @@ -19,6 +19,8 @@ import java.lang.reflect.Type; import java.util.Date; import com.vaadin.ui.ConnectorTracker; +import elemental.json.Json; +import elemental.json.JsonValue; /** * Server side serializer/deserializer for java.util.Date @@ -29,14 +31,14 @@ import com.vaadin.ui.ConnectorTracker; public class DateSerializer implements JSONSerializer<Date> { @Override - public Date deserialize(Type type, Object jsonValue, + public Date deserialize(Type type, JsonValue jsonValue, ConnectorTracker connectorTracker) { - return new Date(Long.valueOf(String.valueOf(jsonValue))); + return new Date((long) jsonValue.asNumber()); } @Override - public Object serialize(Date value, ConnectorTracker connectorTracker) { - return value.getTime(); + public JsonValue serialize(Date value, ConnectorTracker connectorTracker) { + return Json.create(value.getTime()); } } diff --git a/server/src/com/vaadin/server/communication/JSONSerializer.java b/server/src/com/vaadin/server/communication/JSONSerializer.java index 91105d6ffd..e318b6b145 100644 --- a/server/src/com/vaadin/server/communication/JSONSerializer.java +++ b/server/src/com/vaadin/server/communication/JSONSerializer.java @@ -18,13 +18,14 @@ package com.vaadin.server.communication; import java.lang.reflect.Type; import com.vaadin.ui.ConnectorTracker; +import elemental.json.JsonValue; /** * Implementors of this interface knows how to serialize an Object of a given * type to JSON and how to deserialize the JSON back into an object. * <p> * The {@link #serialize(Object, ConnectorTracker)} and - * {@link #deserialize(Type, Object, ConnectorTracker)} methods must be + * {@link #deserialize(Type, JsonValue, ConnectorTracker)} methods must be * symmetric so they can be chained and produce the original result (or an equal * result). * <p> @@ -42,10 +43,7 @@ public interface JSONSerializer<T> { * Creates and deserializes an object received from the client. Must be * compatible with {@link #serialize(Object, ConnectorTracker)} and also * with the client side com.vaadin.client.communication.JSONSerializer. - * <p> - * The json parameter is of type Object as org.json JSON classes have no - * other common super class - * + * * @param type * The expected return type * @param jsonValue @@ -54,11 +52,11 @@ public interface JSONSerializer<T> { * the connector tracker instance for the UI * @return A deserialized object */ - T deserialize(Type type, Object jsonValue, ConnectorTracker connectorTracker); + T deserialize(Type type, JsonValue jsonValue, ConnectorTracker connectorTracker); /** * Serialize the given object into JSON. Must be compatible with - * {@link #deserialize(Object, connectorTracker)} and the client side + * {@link #deserialize(Type, JsonValue, ConnectorTracker)} and the client side * com.vaadin.client.communication.JSONSerializer * * @param value @@ -67,6 +65,6 @@ public interface JSONSerializer<T> { * The connector tracker instance for the UI * @return A JSON serialized version of the object */ - Object serialize(T value, ConnectorTracker connectorTracker); + JsonValue serialize(T value, ConnectorTracker connectorTracker); } diff --git a/server/src/com/vaadin/server/communication/PortletBootstrapHandler.java b/server/src/com/vaadin/server/communication/PortletBootstrapHandler.java index 66b08fdadd..1d1a300cd1 100644 --- a/server/src/com/vaadin/server/communication/PortletBootstrapHandler.java +++ b/server/src/com/vaadin/server/communication/PortletBootstrapHandler.java @@ -25,9 +25,6 @@ import javax.portlet.RenderRequest; import javax.portlet.RenderResponse; import javax.portlet.ResourceURL; -import org.json.JSONException; -import org.json.JSONObject; - import com.vaadin.server.BootstrapHandler; import com.vaadin.server.PaintException; import com.vaadin.server.VaadinPortlet; @@ -39,6 +36,7 @@ import com.vaadin.server.VaadinResponse; import com.vaadin.server.VaadinService; import com.vaadin.server.VaadinSession; import com.vaadin.shared.ApplicationConstants; +import elemental.json.JsonObject; public class PortletBootstrapHandler extends BootstrapHandler { @Override @@ -71,7 +69,7 @@ public class PortletBootstrapHandler extends BootstrapHandler { @Override protected void appendMainScriptTagContents(BootstrapContext context, - StringBuilder builder) throws JSONException, IOException { + StringBuilder builder) throws IOException { // fixed base theme to use - all portal pages with Vaadin // applications will load this exactly once String portalTheme = ((VaadinPortletRequest) context.getRequest()) @@ -94,9 +92,9 @@ public class PortletBootstrapHandler extends BootstrapHandler { } @Override - protected JSONObject getApplicationParameters(BootstrapContext context) - throws JSONException, PaintException { - JSONObject parameters = super.getApplicationParameters(context); + protected JsonObject getApplicationParameters(BootstrapContext context) + throws PaintException { + JsonObject parameters = super.getApplicationParameters(context); VaadinPortletResponse response = (VaadinPortletResponse) context .getResponse(); VaadinPortletRequest request = (VaadinPortletRequest) context diff --git a/server/src/com/vaadin/server/communication/PushHandler.java b/server/src/com/vaadin/server/communication/PushHandler.java index 67e5f87153..6ee81270cd 100644 --- a/server/src/com/vaadin/server/communication/PushHandler.java +++ b/server/src/com/vaadin/server/communication/PushHandler.java @@ -29,7 +29,6 @@ import org.atmosphere.cpr.AtmosphereResource.TRANSPORT; import org.atmosphere.cpr.AtmosphereResourceEvent; import org.atmosphere.cpr.AtmosphereResourceEventListenerAdapter; import org.atmosphere.handler.AbstractReflectorAtmosphereHandler; -import org.json.JSONException; import com.vaadin.server.ErrorEvent; import com.vaadin.server.ErrorHandler; @@ -46,6 +45,7 @@ import com.vaadin.server.VaadinSession; import com.vaadin.shared.ApplicationConstants; import com.vaadin.shared.communication.PushMode; import com.vaadin.ui.UI; +import elemental.json.JsonException; /** * Establishes bidirectional ("push") communication channels @@ -173,7 +173,7 @@ public class PushHandler extends AtmosphereResourceEventListenerAdapter { try { new ServerRpcHandler().handleRpc(ui, reader, vaadinRequest); connection.push(false); - } catch (JSONException e) { + } catch (JsonException e) { getLogger().log(Level.SEVERE, "Error writing JSON to response", e); // Refresh on client side diff --git a/server/src/com/vaadin/server/communication/ServerRpcHandler.java b/server/src/com/vaadin/server/communication/ServerRpcHandler.java index ae076e0856..d1b1be6b97 100644 --- a/server/src/com/vaadin/server/communication/ServerRpcHandler.java +++ b/server/src/com/vaadin/server/communication/ServerRpcHandler.java @@ -28,10 +28,6 @@ import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; - import com.vaadin.server.ClientConnector; import com.vaadin.server.JsonCodec; import com.vaadin.server.LegacyCommunicationManager; @@ -52,6 +48,12 @@ import com.vaadin.ui.Component; import com.vaadin.ui.ConnectorTracker; import com.vaadin.ui.UI; +import elemental.json.JsonArray; +import elemental.json.JsonException; +import elemental.json.JsonObject; +import elemental.json.JsonValue; +import elemental.json.impl.JsonUtil; + /** * Handles a client-to-server message containing serialized {@link ServerRpc * server RPC} invocations. @@ -71,28 +73,31 @@ public class ServerRpcHandler implements Serializable { public static class RpcRequest implements Serializable { private final String csrfToken; - private final JSONArray invocations; + private final JsonArray invocations; private final int syncId; - private final JSONObject json; + private final JsonObject json; - public RpcRequest(String jsonString, VaadinRequest request) - throws JSONException { - json = new JSONObject(jsonString); + public RpcRequest(String jsonString, VaadinRequest request) { + json = JsonUtil.parse(jsonString); - String csrfToken = json.optString(ApplicationConstants.CSRF_TOKEN); - if (csrfToken.equals("")) { - csrfToken = ApplicationConstants.CSRF_TOKEN_DEFAULT_VALUE; + JsonValue token = json.get(ApplicationConstants.CSRF_TOKEN); + if (token == null) { + this.csrfToken = ApplicationConstants.CSRF_TOKEN_DEFAULT_VALUE; + } else { + String csrfToken = token.asString(); + if (csrfToken.equals("")) { + csrfToken = ApplicationConstants.CSRF_TOKEN_DEFAULT_VALUE; + } + this.csrfToken = csrfToken; } - this.csrfToken = csrfToken; if (request.getService().getDeploymentConfiguration() .isSyncIdCheckEnabled()) { - syncId = json.getInt(ApplicationConstants.SERVER_SYNC_ID); + syncId = (int) json.getNumber(ApplicationConstants.SERVER_SYNC_ID); } else { syncId = -1; } - invocations = json - .getJSONArray(ApplicationConstants.RPC_INVOCATIONS); + invocations = json.getArray(ApplicationConstants.RPC_INVOCATIONS); } /** @@ -110,7 +115,7 @@ public class ServerRpcHandler implements Serializable { * @return the data describing which RPC should be made, and all their * data */ - public JSONArray getRpcInvocationsData() { + public JsonArray getRpcInvocationsData() { return invocations; } @@ -134,7 +139,7 @@ public class ServerRpcHandler implements Serializable { * @return the raw JSON object that was received from the client * */ - public JSONObject getRawJson() { + public JsonObject getRawJson() { return json; } } @@ -155,11 +160,9 @@ public class ServerRpcHandler implements Serializable { * @throws InvalidUIDLSecurityKeyException * If the received security key does not match the one stored in * the session. - * @throws JSONException - * If deserializing the JSON fails. */ public void handleRpc(UI ui, Reader reader, VaadinRequest request) - throws IOException, InvalidUIDLSecurityKeyException, JSONException { + throws IOException, InvalidUIDLSecurityKeyException { ui.getSession().setLastRequestTimestamp(System.currentTimeMillis()); String changeMessage = getMessage(reader); @@ -205,7 +208,7 @@ public class ServerRpcHandler implements Serializable { * requested RPC calls. */ private void handleInvocations(UI uI, int lastSyncIdSeenByClient, - JSONArray invocationsData) { + JsonArray invocationsData) { // TODO PUSH Refactor so that this is not needed LegacyCommunicationManager manager = uI.getSession() .getCommunicationManager(); @@ -314,7 +317,7 @@ public class ServerRpcHandler implements Serializable { } } } - } catch (JSONException e) { + } catch (JsonException e) { getLogger().warning( "Unable to parse RPC call from the client: " + e.getMessage()); @@ -334,11 +337,10 @@ public class ServerRpcHandler implements Serializable { * the most recent sync id the client has seen at the time the * request was sent * @return list of MethodInvocation to perform - * @throws JSONException */ private List<MethodInvocation> parseInvocations( - ConnectorTracker connectorTracker, JSONArray invocationsJson, - int lastSyncIdSeenByClient) throws JSONException { + ConnectorTracker connectorTracker, JsonArray invocationsJson, + int lastSyncIdSeenByClient) { int invocationCount = invocationsJson.length(); ArrayList<MethodInvocation> invocations = new ArrayList<MethodInvocation>( invocationCount); @@ -347,7 +349,7 @@ public class ServerRpcHandler implements Serializable { // parse JSON to MethodInvocations for (int i = 0; i < invocationCount; ++i) { - JSONArray invocationJson = invocationsJson.getJSONArray(i); + JsonArray invocationJson = invocationsJson.getArray(i); MethodInvocation invocation = parseInvocation(invocationJson, previousInvocation, connectorTracker, @@ -363,17 +365,15 @@ public class ServerRpcHandler implements Serializable { return invocations; } - private MethodInvocation parseInvocation(JSONArray invocationJson, + private MethodInvocation parseInvocation(JsonArray invocationJson, MethodInvocation previousInvocation, - ConnectorTracker connectorTracker, long lastSyncIdSeenByClient) - throws JSONException { + ConnectorTracker connectorTracker, long lastSyncIdSeenByClient) { String connectorId = invocationJson.getString(0); String interfaceName = invocationJson.getString(1); String methodName = invocationJson.getString(2); if (connectorTracker.getConnector(connectorId) == null - && !connectorId - .equals(ApplicationConstants.DRAG_AND_DROP_CONNECTOR_ID)) { + && !connectorId.equals(ApplicationConstants.DRAG_AND_DROP_CONNECTOR_ID)) { if (!connectorTracker.connectorWasPresentAsRequestWasSent( connectorId, lastSyncIdSeenByClient)) { @@ -393,7 +393,7 @@ public class ServerRpcHandler implements Serializable { return null; } - JSONArray parametersJson = invocationJson.getJSONArray(3); + JsonArray parametersJson = invocationJson.getArray(3); if (LegacyChangeVariablesInvocation.isLegacyVariableChange( interfaceName, methodName)) { @@ -415,10 +415,9 @@ public class ServerRpcHandler implements Serializable { private LegacyChangeVariablesInvocation parseLegacyChangeVariablesInvocation( String connectorId, String interfaceName, String methodName, LegacyChangeVariablesInvocation previousInvocation, - JSONArray parametersJson, ConnectorTracker connectorTracker) - throws JSONException { + JsonArray parametersJson, ConnectorTracker connectorTracker) { if (parametersJson.length() != 2) { - throw new JSONException( + throw new JsonException( "Invalid parameters in legacy change variables call. Expected 2, was " + parametersJson.length()); } @@ -440,8 +439,8 @@ public class ServerRpcHandler implements Serializable { private ServerRpcMethodInvocation parseServerRpcInvocation( String connectorId, String interfaceName, String methodName, - JSONArray parametersJson, ConnectorTracker connectorTracker) - throws JSONException { + JsonArray parametersJson, ConnectorTracker connectorTracker) + throws JsonException { ClientConnector connector = connectorTracker.getConnector(connectorId); ServerRpcManager<?> rpcManager = connector.getRpcManager(interfaceName); @@ -471,7 +470,7 @@ public class ServerRpcHandler implements Serializable { .getGenericParameterTypes(); for (int j = 0; j < parametersJson.length(); ++j) { - Object parameterValue = parametersJson.get(j); + JsonValue parameterValue = parametersJson.get(j); Type parameterType = declaredRpcMethodParameterTypes[j]; parameters[j] = JsonCodec.decodeInternalOrCustomType(parameterType, parameterValue, connectorTracker); diff --git a/server/src/com/vaadin/server/communication/SharedStateWriter.java b/server/src/com/vaadin/server/communication/SharedStateWriter.java index 6a318f0758..6ef02955f7 100644 --- a/server/src/com/vaadin/server/communication/SharedStateWriter.java +++ b/server/src/com/vaadin/server/communication/SharedStateWriter.java @@ -21,14 +21,16 @@ import java.io.Serializable; import java.io.Writer; import java.util.Collection; -import org.json.JSONException; -import org.json.JSONObject; - import com.vaadin.server.ClientConnector; import com.vaadin.server.PaintException; import com.vaadin.shared.communication.SharedState; import com.vaadin.ui.UI; +import elemental.json.Json; +import elemental.json.JsonException; +import elemental.json.JsonObject; +import elemental.json.impl.JsonUtil; + /** * Serializes {@link SharedState shared state} changes to JSON. * @@ -53,16 +55,16 @@ public class SharedStateWriter implements Serializable { Collection<ClientConnector> dirtyVisibleConnectors = ui .getConnectorTracker().getDirtyVisibleConnectors(); - JSONObject sharedStates = new JSONObject(); + JsonObject sharedStates = Json.createObject(); for (ClientConnector connector : dirtyVisibleConnectors) { // encode and send shared state try { - JSONObject stateJson = connector.encodeState(); + JsonObject stateJson = connector.encodeState(); - if (stateJson != null && stateJson.length() != 0) { + if (stateJson != null && stateJson.keys().length != 0) { sharedStates.put(connector.getConnectorId(), stateJson); } - } catch (JSONException e) { + } catch (JsonException e) { throw new PaintException( "Failed to serialize shared state for connector " + connector.getClass().getName() + " (" @@ -70,6 +72,6 @@ public class SharedStateWriter implements Serializable { + e.getMessage(), e); } } - writer.write(sharedStates.toString()); + writer.write(JsonUtil.stringify(sharedStates)); } } diff --git a/server/src/com/vaadin/server/communication/UIInitHandler.java b/server/src/com/vaadin/server/communication/UIInitHandler.java index cf0de8e9ee..356ad25219 100644 --- a/server/src/com/vaadin/server/communication/UIInitHandler.java +++ b/server/src/com/vaadin/server/communication/UIInitHandler.java @@ -23,9 +23,6 @@ import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; -import org.json.JSONException; -import org.json.JSONObject; - import com.vaadin.annotations.PreserveOnRefresh; import com.vaadin.server.LegacyApplicationUIProvider; import com.vaadin.server.SynchronizedRequestHandler; @@ -43,6 +40,11 @@ import com.vaadin.shared.ui.ui.Transport; import com.vaadin.shared.ui.ui.UIConstants; import com.vaadin.ui.UI; +import elemental.json.Json; +import elemental.json.JsonException; +import elemental.json.JsonObject; +import elemental.json.impl.JsonUtil; + /** * Handles an initial request from the client to initialize a {@link UI}. * @@ -75,13 +77,13 @@ public abstract class UIInitHandler extends SynchronizedRequestHandler { session.getCommunicationManager().repaintAll(uI); - JSONObject params = new JSONObject(); + JsonObject params = Json.createObject(); params.put(UIConstants.UI_ID_PARAMETER, uI.getUIId()); String initialUIDL = getInitialUidl(request, uI); params.put("uidl", initialUIDL); - stringWriter.write(params.toString()); - } catch (JSONException e) { + stringWriter.write(JsonUtil.stringify(params)); + } catch (JsonException e) { throw new IOException("Error producing initial UIDL", e); } finally { stringWriter.close(); @@ -278,12 +280,10 @@ public abstract class UIInitHandler extends SynchronizedRequestHandler { * @param uI * the UI for which the UIDL should be generated * @return a string with the initial UIDL message - * @throws JSONException - * if an exception occurs while encoding output * @throws IOException */ protected String getInitialUidl(VaadinRequest request, UI uI) - throws JSONException, IOException { + throws IOException { StringWriter writer = new StringWriter(); try { writer.write("{"); diff --git a/server/src/com/vaadin/server/communication/UidlRequestHandler.java b/server/src/com/vaadin/server/communication/UidlRequestHandler.java index 0d8ddb7bc7..d28107e8f8 100644 --- a/server/src/com/vaadin/server/communication/UidlRequestHandler.java +++ b/server/src/com/vaadin/server/communication/UidlRequestHandler.java @@ -22,8 +22,6 @@ import java.io.Writer; import java.util.logging.Level; import java.util.logging.Logger; -import org.json.JSONException; - import com.vaadin.server.Constants; import com.vaadin.server.LegacyCommunicationManager.InvalidUIDLSecurityKeyException; import com.vaadin.server.ServletPortletHelper; @@ -38,6 +36,7 @@ import com.vaadin.shared.ApplicationConstants; import com.vaadin.shared.JsonConstants; import com.vaadin.shared.Version; import com.vaadin.ui.UI; +import elemental.json.JsonException; /** * Processes a UIDL request from the client. @@ -97,7 +96,7 @@ public class UidlRequestHandler extends SynchronizedRequestHandler implements } writeUidl(request, response, uI, stringWriter, repaintAll); - } catch (JSONException e) { + } catch (JsonException e) { getLogger().log(Level.SEVERE, "Error writing JSON to response", e); // Refresh on client side response.getWriter().write( @@ -144,8 +143,7 @@ public class UidlRequestHandler extends SynchronizedRequestHandler implements } private void writeUidl(VaadinRequest request, VaadinResponse response, - UI ui, Writer writer, boolean repaintAll) throws IOException, - JSONException { + UI ui, Writer writer, boolean repaintAll) throws IOException { openJsonMessage(writer, response); new UidlWriter().write(ui, writer, repaintAll, false); diff --git a/server/src/com/vaadin/server/communication/UidlWriter.java b/server/src/com/vaadin/server/communication/UidlWriter.java index 9d55f7e197..3b2caba55b 100644 --- a/server/src/com/vaadin/server/communication/UidlWriter.java +++ b/server/src/com/vaadin/server/communication/UidlWriter.java @@ -27,9 +27,6 @@ import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; -import org.json.JSONArray; -import org.json.JSONException; - import com.vaadin.annotations.JavaScript; import com.vaadin.annotations.StyleSheet; import com.vaadin.server.ClientConnector; @@ -43,6 +40,10 @@ import com.vaadin.shared.ApplicationConstants; import com.vaadin.ui.ConnectorTracker; import com.vaadin.ui.UI; +import elemental.json.Json; +import elemental.json.JsonArray; +import elemental.json.impl.JsonUtil; + /** * Serializes pending server-side changes to UI state to JSON. This includes * shared state, client RPC invocations, connector hierarchy changes, connector @@ -70,11 +71,9 @@ public class UidlWriter implements Serializable { * * @throws IOException * If the writing fails. - * @throws JSONException - * If the JSON serialization fails. */ public void write(UI ui, Writer writer, boolean repaintAll, boolean async) - throws IOException, JSONException { + throws IOException { VaadinSession session = ui.getSession(); VaadinService service = session.getService(); @@ -282,13 +281,13 @@ public class UidlWriter implements Serializable { // Include script dependencies in output if there are any if (!scriptDependencies.isEmpty()) { writer.write(", \"scriptDependencies\": " - + new JSONArray(scriptDependencies).toString()); + + JsonUtil.stringify(toJsonArray(scriptDependencies))); } // Include style dependencies in output if there are any if (!styleDependencies.isEmpty()) { writer.write(", \"styleDependencies\": " - + new JSONArray(styleDependencies).toString()); + + JsonUtil.stringify(toJsonArray(styleDependencies))); } session.getDragAndDropService().printJSONResponse(writer); @@ -306,6 +305,15 @@ public class UidlWriter implements Serializable { } } + private JsonArray toJsonArray(List<String> list) { + JsonArray result = Json.createArray(); + for (int i = 0; i < list.size(); i++) { + result.set(i, list.get(i)); + } + + return result; + } + /** * Adds the performance timing data (used by TestBench 3) to the UIDL * response. diff --git a/server/src/com/vaadin/ui/Button.java b/server/src/com/vaadin/ui/Button.java index 58b6f9de81..76b82aa034 100644 --- a/server/src/com/vaadin/ui/Button.java +++ b/server/src/com/vaadin/ui/Button.java @@ -19,8 +19,6 @@ package com.vaadin.ui; import java.io.Serializable; import java.lang.reflect.Method; -import org.json.JSONException; - import com.vaadin.event.Action; import com.vaadin.event.FieldEvents; import com.vaadin.event.FieldEvents.BlurEvent; @@ -63,12 +61,8 @@ public class Button extends AbstractComponent implements // Makes sure the enabled=false state is noticed at once - otherwise // a following setEnabled(true) call might have no effect. see // ticket #10030 - try { - getUI().getConnectorTracker().getDiffState(Button.this) - .put("enabled", false); - } catch (JSONException e) { - throw new RuntimeException(e); - } + getUI().getConnectorTracker().getDiffState(Button.this) + .put("enabled", false); } }; diff --git a/server/src/com/vaadin/ui/CheckBox.java b/server/src/com/vaadin/ui/CheckBox.java index 3c4ce1c528..7d9da30f29 100644 --- a/server/src/com/vaadin/ui/CheckBox.java +++ b/server/src/com/vaadin/ui/CheckBox.java @@ -16,8 +16,6 @@ package com.vaadin.ui; -import org.json.JSONException; - import com.vaadin.data.Property; import com.vaadin.event.FieldEvents.BlurEvent; import com.vaadin.event.FieldEvents.BlurListener; @@ -47,12 +45,8 @@ public class CheckBox extends AbstractField<Boolean> { * * See #11028, #10030. */ - try { - getUI().getConnectorTracker().getDiffState(CheckBox.this) - .put("checked", checked); - } catch (JSONException e) { - throw new RuntimeException(e); - } + getUI().getConnectorTracker().getDiffState(CheckBox.this) + .put("checked", checked); final Boolean oldValue = getValue(); final Boolean newValue = checked; diff --git a/server/src/com/vaadin/ui/ConnectorTracker.java b/server/src/com/vaadin/ui/ConnectorTracker.java index 9b8729f779..5386eb9d64 100644 --- a/server/src/com/vaadin/ui/ConnectorTracker.java +++ b/server/src/com/vaadin/ui/ConnectorTracker.java @@ -30,9 +30,6 @@ import java.util.UUID; import java.util.logging.Level; import java.util.logging.Logger; -import org.json.JSONException; -import org.json.JSONObject; - import com.vaadin.server.AbstractClientConnector; import com.vaadin.server.ClientConnector; import com.vaadin.server.DragAndDropService; @@ -40,6 +37,10 @@ import com.vaadin.server.GlobalResourceHandler; import com.vaadin.server.LegacyCommunicationManager; import com.vaadin.server.StreamVariable; +import elemental.json.Json; +import elemental.json.JsonException; +import elemental.json.JsonObject; + /** * A class which takes care of book keeping of {@link ClientConnector}s for a * UI. @@ -76,7 +77,7 @@ public class ConnectorTracker implements Serializable { private boolean writingResponse = false; private UI uI; - private transient Map<ClientConnector, JSONObject> diffStates = new HashMap<ClientConnector, JSONObject>(); + private transient Map<ClientConnector, JsonObject> diffStates = new HashMap<ClientConnector, JsonObject>(); /** Maps connectorIds to a map of named StreamVariables */ private Map<String, Map<String, StreamVariable>> pidToNameToStreamVariable; @@ -556,12 +557,12 @@ public class ConnectorTracker implements Serializable { return dirtyVisibleConnectors; } - public JSONObject getDiffState(ClientConnector connector) { + public JsonObject getDiffState(ClientConnector connector) { assert getConnector(connector.getConnectorId()) == connector; return diffStates.get(connector); } - public void setDiffState(ClientConnector connector, JSONObject diffState) { + public void setDiffState(ClientConnector connector, JsonObject diffState) { assert getConnector(connector.getConnectorId()) == connector; diffStates.put(connector, diffState); } @@ -621,11 +622,11 @@ public class ConnectorTracker implements Serializable { this.writingResponse = writingResponse; } - /* Special serialization to JSONObjects which are not serializable */ + /* Special serialization to JsonObjects which are not serializable */ private void writeObject(java.io.ObjectOutputStream out) throws IOException { out.defaultWriteObject(); - // Convert JSONObjects in diff state to String representation as - // JSONObject is not serializable + // Convert JsonObjects in diff state to String representation as + // JsonObject is not serializable HashMap<ClientConnector, String> stringDiffStates = new HashMap<ClientConnector, String>( diffStates.size() * 2); for (ClientConnector key : diffStates.keySet()) { @@ -634,23 +635,23 @@ public class ConnectorTracker implements Serializable { out.writeObject(stringDiffStates); } - /* Special serialization to JSONObjects which are not serializable */ + /* Special serialization to JsonObjects which are not serializable */ private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); - // Read String versions of JSONObjects and parse into JSONObjects as - // JSONObject is not serializable - diffStates = new HashMap<ClientConnector, JSONObject>(); + // Read String versions of JsonObjects and parse into JsonObjects as + // JsonObject is not serializable + diffStates = new HashMap<ClientConnector, JsonObject>(); @SuppressWarnings("unchecked") HashMap<ClientConnector, String> stringDiffStates = (HashMap<ClientConnector, String>) in .readObject(); - diffStates = new HashMap<ClientConnector, JSONObject>( + diffStates = new HashMap<ClientConnector, JsonObject>( stringDiffStates.size() * 2); for (ClientConnector key : stringDiffStates.keySet()) { try { - diffStates.put(key, new JSONObject(stringDiffStates.get(key))); - } catch (JSONException e) { + diffStates.put(key, Json.parse(stringDiffStates.get(key))); + } catch (JsonException e) { throw new IOException(e); } } diff --git a/server/src/com/vaadin/ui/JavaScript.java b/server/src/com/vaadin/ui/JavaScript.java index 68c8c9a6e4..668ae67056 100644 --- a/server/src/com/vaadin/ui/JavaScript.java +++ b/server/src/com/vaadin/ui/JavaScript.java @@ -19,15 +19,15 @@ package com.vaadin.ui; import java.util.HashMap; import java.util.Map; -import org.json.JSONArray; -import org.json.JSONException; - import com.vaadin.server.AbstractExtension; import com.vaadin.server.Page; import com.vaadin.shared.communication.ServerRpc; import com.vaadin.shared.extension.javascriptmanager.ExecuteJavaScriptRpc; import com.vaadin.shared.extension.javascriptmanager.JavaScriptManagerState; +import elemental.json.JsonArray; +import elemental.json.JsonException; + /** * Provides access to JavaScript functionality in the web browser. To get an * instance of JavaScript, either use Page.getJavaScript() or @@ -43,7 +43,7 @@ public class JavaScript extends AbstractExtension { // Can not be defined in client package as this JSONArray is not available // in GWT public interface JavaScriptCallbackRpc extends ServerRpc { - public void call(String name, JSONArray arguments); + public void call(String name, JsonArray arguments); } /** @@ -54,12 +54,12 @@ public class JavaScript extends AbstractExtension { public JavaScript() { registerRpc(new JavaScriptCallbackRpc() { @Override - public void call(String name, JSONArray arguments) { + public void call(String name, JsonArray arguments) { JavaScriptFunction function = functions.get(name); // TODO handle situation if name is not registered try { function.call(arguments); - } catch (JSONException e) { + } catch (JsonException e) { throw new IllegalArgumentException(e); } } diff --git a/server/src/com/vaadin/ui/JavaScriptFunction.java b/server/src/com/vaadin/ui/JavaScriptFunction.java index 2c026abd1a..c006a36d58 100644 --- a/server/src/com/vaadin/ui/JavaScriptFunction.java +++ b/server/src/com/vaadin/ui/JavaScriptFunction.java @@ -18,14 +18,12 @@ package com.vaadin.ui; import java.io.Serializable; -import org.json.JSONArray; -import org.json.JSONException; - import com.vaadin.server.AbstractJavaScriptExtension; +import elemental.json.JsonArray; /** * Defines a method that is called by a client-side JavaScript function. When - * the corresponding JavaScript function is called, the {@link #call(JSONArray)} + * the corresponding JavaScript function is called, the {@link #call(JsonArray)} * method is invoked. * * @see JavaScript#addFunction(String, JavaScriptCallback) @@ -46,8 +44,6 @@ public interface JavaScriptFunction extends Serializable { * @param arguments * an array with JSON representations of the arguments with which * the JavaScript function was called. - * @throws JSONException - * if the arguments can not be interpreted */ - public void call(JSONArray arguments) throws JSONException; + public void call(JsonArray arguments); } diff --git a/server/src/com/vaadin/ui/Slider.java b/server/src/com/vaadin/ui/Slider.java index ff6c955e47..66ed1a48f4 100644 --- a/server/src/com/vaadin/ui/Slider.java +++ b/server/src/com/vaadin/ui/Slider.java @@ -16,8 +16,6 @@ package com.vaadin.ui; -import org.json.JSONException; - import com.vaadin.shared.ui.slider.SliderOrientation; import com.vaadin.shared.ui.slider.SliderServerRpc; import com.vaadin.shared.ui.slider.SliderState; @@ -42,12 +40,8 @@ public class Slider extends AbstractField<Double> { * * See #12133. */ - try { - getUI().getConnectorTracker().getDiffState(Slider.this) - .put("value", value); - } catch (JSONException e) { - throw new RuntimeException(e); - } + getUI().getConnectorTracker().getDiffState(Slider.this) + .put("value", value); try { setValue(value, true); diff --git a/server/src/com/vaadin/ui/TabSheet.java b/server/src/com/vaadin/ui/TabSheet.java index 8b13ecf1a4..0e4ea0d034 100644 --- a/server/src/com/vaadin/ui/TabSheet.java +++ b/server/src/com/vaadin/ui/TabSheet.java @@ -193,6 +193,9 @@ public class TabSheet extends AbstractComponentContainer implements Focusable, @Override public void removeComponent(Component component) { if (component != null && components.contains(component)) { + + int componentIndex = components.indexOf(component); + super.removeComponent(component); keyMapper.remove(component); components.remove(component); @@ -206,6 +209,24 @@ public class TabSheet extends AbstractComponentContainer implements Focusable, if (components.isEmpty()) { setSelected(null); } else { + + int newSelectedIndex = selectedTabIndexAfterTabRemove(componentIndex); + + // Make sure the component actually exists, in case someone + // override it and provide a non existing component. + if (0 <= newSelectedIndex + && newSelectedIndex < components.size()) { + + Component newSelectedComponent = components + .get(newSelectedIndex); + + // Select only if the tab is enabled. + Tab newSelectedTab = tabs.get(newSelectedComponent); + if (newSelectedTab.isEnabled()) { + setSelected(newSelectedComponent); + } + } + // select the first enabled and visible tab, if any updateSelection(); fireSelectedTabChange(); @@ -216,6 +237,40 @@ public class TabSheet extends AbstractComponentContainer implements Focusable, } /** + * Called when a selected tab is removed to specify the new tab to select. + * Can be overridden to provide another algorithm that calculates the new + * selection. + * + * Current implementation will choose the first enabled tab to the right of + * the removed tab if it's not the last one, otherwise will choose the + * closer enabled tab to the left. + * + * @since + * @param removedTabIndex + * the index of the selected tab which was just remove. + * @return the index of the tab to be selected or -1 if there are no more + * enabled tabs to select. + */ + protected int selectedTabIndexAfterTabRemove(int removedTabIndex) { + + for (int i = removedTabIndex; i < components.size(); i++) { + Tab tab = getTab(i); + if (tab.isEnabled()) { + return i; + } + } + + for (int i = removedTabIndex - 1; i >= 0; i--) { + Tab tab = getTab(i); + if (tab.isEnabled()) { + return i; + } + } + + return -1; + } + + /** * Removes a {@link Tab} and the component associated with it, as previously * added with {@link #addTab(Component)}, * {@link #addTab(Component, String, Resource)} or diff --git a/server/src/com/vaadin/ui/components/grid/Grid.java b/server/src/com/vaadin/ui/components/grid/Grid.java index f6a1231f43..962ea8f499 100644 --- a/server/src/com/vaadin/ui/components/grid/Grid.java +++ b/server/src/com/vaadin/ui/components/grid/Grid.java @@ -27,9 +27,6 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; -import org.json.JSONArray; -import org.json.JSONException; - import com.google.gwt.thirdparty.guava.common.collect.Sets; import com.google.gwt.thirdparty.guava.common.collect.Sets.SetView; import com.vaadin.data.Container; @@ -68,6 +65,9 @@ import com.vaadin.ui.components.grid.sort.Sort; import com.vaadin.ui.components.grid.sort.SortOrder; import com.vaadin.util.ReflectTools; +import elemental.json.Json; +import elemental.json.JsonArray; + /** * A grid component for displaying tabular data. * <p> @@ -303,19 +303,18 @@ public class Grid extends AbstractComponent implements SelectionChangeNotifier, ignoreSelectionClientSync--; markAsDirty = false; - try { - - /* - * Make sure that the diffstate is aware of the - * "undirty" modification, so that the diffs are - * calculated correctly the next time we actually want - * to send the selection state to the client. - */ - getUI().getConnectorTracker().getDiffState(Grid.this) - .put("selectedKeys", new JSONArray(keys)); - } catch (JSONException e) { - throw new RuntimeException("Internal error", e); + /* + * Make sure that the diffstate is aware of the "undirty" + * modification, so that the diffs are calculated correctly + * the next time we actually want to send the selection + * state to the client. + */ + JsonArray jsonKeys = Json.createArray(); + for (int i = 0; i < keys.size(); ++i) { + jsonKeys.set(i, keys.get(i)); } + getUI().getConnectorTracker().getDiffState(Grid.this) + .put("selectedKeys", jsonKeys); } getState(markAsDirty).selectedKeys = keys; diff --git a/server/src/com/vaadin/ui/components/grid/Renderer.java b/server/src/com/vaadin/ui/components/grid/Renderer.java index b9074fb9f7..33bac2ccff 100644 --- a/server/src/com/vaadin/ui/components/grid/Renderer.java +++ b/server/src/com/vaadin/ui/components/grid/Renderer.java @@ -18,6 +18,8 @@ package com.vaadin.ui.components.grid; import com.vaadin.server.ClientConnector; import com.vaadin.server.Extension; +import elemental.json.JsonValue; + /** * A ClientConnector for controlling client-side * {@link com.vaadin.client.ui.grid.Renderer Grid renderers}. Renderers @@ -41,17 +43,13 @@ public interface Renderer<T> extends Extension { Class<T> getPresentationType(); /** - * Encodes the given value into a form that can be transferred to the - * client. The type of the returned value must be one of the types that are - * accepted by <a href= - * "http://www.json.org/javadoc/org/json/JSONObject.html#put%28java.lang.String,%20java.lang.Object%29" - * >{@code org.json.JSONObject#put(String, Object)}</a>. + * Encodes the given value into a {@link JsonValue}. * * @param value * the value to encode * @return an encoded form of the given value */ - Object encode(T value); + JsonValue encode(T value); /** * This method is inherited from Extension but should never be called diff --git a/server/src/com/vaadin/ui/components/grid/renderers/DateRenderer.java b/server/src/com/vaadin/ui/components/grid/renderers/DateRenderer.java index 736b61d9e2..aeb653ae27 100644 --- a/server/src/com/vaadin/ui/components/grid/renderers/DateRenderer.java +++ b/server/src/com/vaadin/ui/components/grid/renderers/DateRenderer.java @@ -21,6 +21,9 @@ import java.util.Locale; import com.vaadin.ui.components.grid.AbstractRenderer; +import elemental.json.Json; +import elemental.json.JsonValue; + /** * A renderer for presenting date values. * @@ -130,11 +133,11 @@ public class DateRenderer extends AbstractRenderer<Date> { } @Override - public String encode(Date value) { + public JsonValue encode(Date value) { if (dateFormat != null) { - return dateFormat.format(value); + return Json.create(dateFormat.format(value)); } else { - return String.format(locale, formatString, value); + return Json.create(String.format(locale, formatString, value)); } } diff --git a/server/src/com/vaadin/ui/components/grid/renderers/HtmlRenderer.java b/server/src/com/vaadin/ui/components/grid/renderers/HtmlRenderer.java index 6439608c20..acbe4a69e7 100644 --- a/server/src/com/vaadin/ui/components/grid/renderers/HtmlRenderer.java +++ b/server/src/com/vaadin/ui/components/grid/renderers/HtmlRenderer.java @@ -17,6 +17,9 @@ package com.vaadin.ui.components.grid.renderers; import com.vaadin.ui.components.grid.AbstractRenderer; +import elemental.json.Json; +import elemental.json.JsonValue; + /** * A renderer for presenting HTML content. * @@ -32,7 +35,7 @@ public class HtmlRenderer extends AbstractRenderer<String> { } @Override - public String encode(String value) { - return value; + public JsonValue encode(String value) { + return Json.create(value); } } diff --git a/server/src/com/vaadin/ui/components/grid/renderers/NumberRenderer.java b/server/src/com/vaadin/ui/components/grid/renderers/NumberRenderer.java index 12fcfc890a..0f4619c180 100644 --- a/server/src/com/vaadin/ui/components/grid/renderers/NumberRenderer.java +++ b/server/src/com/vaadin/ui/components/grid/renderers/NumberRenderer.java @@ -20,6 +20,9 @@ import java.util.Locale; import com.vaadin.ui.components.grid.AbstractRenderer; +import elemental.json.Json; +import elemental.json.JsonValue; + /** * A renderer for presenting number values. * @@ -131,11 +134,11 @@ public class NumberRenderer extends AbstractRenderer<Number> { } @Override - public String encode(Number value) { + public JsonValue encode(Number value) { if (formatString != null && locale != null) { - return String.format(locale, formatString, value); + return Json.create(String.format(locale, formatString, value)); } else if (numberFormat != null) { - return numberFormat.format(value); + return Json.create(numberFormat.format(value)); } else { throw new IllegalStateException(String.format("Internal bug: " + "%s is in an illegal state: " diff --git a/server/src/com/vaadin/ui/components/grid/renderers/TextRenderer.java b/server/src/com/vaadin/ui/components/grid/renderers/TextRenderer.java index 61348a9e49..26fc226cfa 100644 --- a/server/src/com/vaadin/ui/components/grid/renderers/TextRenderer.java +++ b/server/src/com/vaadin/ui/components/grid/renderers/TextRenderer.java @@ -17,6 +17,9 @@ package com.vaadin.ui.components.grid.renderers; import com.vaadin.ui.components.grid.AbstractRenderer; +import elemental.json.Json; +import elemental.json.JsonValue; + /** * A renderer for presenting simple plain-text string values. * @@ -33,7 +36,7 @@ public class TextRenderer extends AbstractRenderer<String> { } @Override - public Object encode(String value) { - return value; + public JsonValue encode(String value) { + return Json.create(value); } } diff --git a/server/src/com/vaadin/ui/themes/ValoTheme.java b/server/src/com/vaadin/ui/themes/ValoTheme.java index d6bd97ed72..da80375114 100644 --- a/server/src/com/vaadin/ui/themes/ValoTheme.java +++ b/server/src/com/vaadin/ui/themes/ValoTheme.java @@ -566,7 +566,7 @@ public class ValoTheme { * Make the progress bar indicator appear as a dot which progresses over the * progress bar track (instead of a growing bar). */ - public static final String PROBRESSBAR_POINT = "point"; + public static final String PROGRESSBAR_POINT = "point"; /*************************************************************************** * diff --git a/server/tests/src/com/vaadin/server/JSONSerializerTest.java b/server/tests/src/com/vaadin/server/JSONSerializerTest.java index 8c1967acb3..393cea1c4c 100644 --- a/server/tests/src/com/vaadin/server/JSONSerializerTest.java +++ b/server/tests/src/com/vaadin/server/JSONSerializerTest.java @@ -15,8 +15,8 @@ package com.vaadin.server; * License for the specific language governing permissions and limitations under * the License. */ + import java.lang.reflect.Type; -import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.Map; @@ -24,14 +24,15 @@ import java.util.Map; import junit.framework.AssertionFailedError; import junit.framework.TestCase; -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; - import com.vaadin.server.JsonCodec.BeanProperty; import com.vaadin.shared.communication.UidlValue; import com.vaadin.shared.ui.splitpanel.AbstractSplitPanelState; +import elemental.json.Json; +import elemental.json.JsonArray; +import elemental.json.JsonException; +import elemental.json.JsonValue; + /** * Tests for {@link JsonCodec} * @@ -56,7 +57,7 @@ public class JSONSerializerTest extends TestCase { stringToStateMap.put("string - state 1", s); stringToStateMap.put("String - state 2", s2); - Object encodedMap = JsonCodec.encode(stringToStateMap, null, mapType, + JsonValue encodedMap = JsonCodec.encode(stringToStateMap, null, mapType, null).getEncodedValue(); ensureDecodedCorrectly(stringToStateMap, encodedMap, mapType); @@ -73,15 +74,16 @@ public class JSONSerializerTest extends TestCase { stateToStringMap.put(s, "string - state 1"); stateToStringMap.put(s2, "String - state 2"); - Object encodedMap = JsonCodec.encode(stateToStringMap, null, mapType, + JsonValue encodedMap = JsonCodec.encode(stateToStringMap, null, mapType, null).getEncodedValue(); ensureDecodedCorrectly(stateToStringMap, encodedMap, mapType); } - public void testNullLegacyValue() throws JSONException { - JSONArray inputArray = new JSONArray( - Arrays.asList("n", JSONObject.NULL)); + public void testNullLegacyValue() throws JsonException { + JsonArray inputArray = Json.createArray(); + inputArray.set(0, "n"); + inputArray.set(1, Json.createNull()); UidlValue decodedObject = (UidlValue) JsonCodec.decodeInternalType( UidlValue.class, true, inputArray, null); assertNull(decodedObject.getValue()); @@ -89,17 +91,19 @@ public class JSONSerializerTest extends TestCase { public void testNullTypeOtherValue() { try { - JSONArray inputArray = new JSONArray(Arrays.asList("n", "a")); + JsonArray inputArray = Json.createArray(); + inputArray.set(0, "n"); + inputArray.set(1, "a"); UidlValue decodedObject = (UidlValue) JsonCodec.decodeInternalType( UidlValue.class, true, inputArray, null); - throw new AssertionFailedError("No JSONException thrown"); - } catch (JSONException e) { + throw new AssertionFailedError("No JsonException thrown"); + } catch (JsonException e) { // Should throw exception } } - private void ensureDecodedCorrectly(Object original, Object encoded, + private void ensureDecodedCorrectly(Object original, JsonValue encoded, Type type) throws Exception { Object serverSideDecoded = JsonCodec.decodeInternalOrCustomType(type, encoded, null); diff --git a/server/tests/src/com/vaadin/tests/server/CsrfTokenMissingTestServer.java b/server/tests/src/com/vaadin/tests/server/CsrfTokenMissingTestServer.java index 30f1c85fef..214341371a 100644 --- a/server/tests/src/com/vaadin/tests/server/CsrfTokenMissingTestServer.java +++ b/server/tests/src/com/vaadin/tests/server/CsrfTokenMissingTestServer.java @@ -22,7 +22,6 @@ import java.util.logging.Logger; import javax.servlet.http.HttpServletRequest; import org.easymock.EasyMock; -import org.json.JSONException; import org.junit.Assert; import org.junit.Before; import org.junit.Test; @@ -37,6 +36,7 @@ import com.vaadin.server.communication.ServerRpcHandler.RpcRequest; import com.vaadin.shared.ApplicationConstants; import com.vaadin.tests.util.AlwaysLockedVaadinSession; import com.vaadin.tests.util.MockDeploymentConfiguration; +import elemental.json.JsonException; /** * Test the actual csrf token validation by the server. @@ -141,7 +141,7 @@ public class CsrfTokenMissingTestServer { private RpcRequest createRequest() { try { return new RpcRequest(getPayload(), vaadinRequest); - } catch (JSONException e) { + } catch (JsonException e) { LOGGER.log(Level.SEVERE, "", e); Assert.assertTrue(false); diff --git a/server/tests/src/com/vaadin/tests/server/TestClientMethodSerialization.java b/server/tests/src/com/vaadin/tests/server/TestClientMethodSerialization.java index 41b71a37fa..ad70024af4 100644 --- a/server/tests/src/com/vaadin/tests/server/TestClientMethodSerialization.java +++ b/server/tests/src/com/vaadin/tests/server/TestClientMethodSerialization.java @@ -21,22 +21,23 @@ import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; import java.lang.reflect.Method; -import java.util.Arrays; import junit.framework.TestCase; -import org.json.JSONArray; - import com.vaadin.server.ClientMethodInvocation; import com.vaadin.server.JavaScriptCallbackHelper; import com.vaadin.ui.JavaScript.JavaScriptCallbackRpc; import com.vaadin.util.ReflectTools; +import elemental.json.Json; +import elemental.json.JsonArray; +import elemental.json.impl.JsonUtil; + public class TestClientMethodSerialization extends TestCase { private static final Method JAVASCRIPT_CALLBACK_METHOD = ReflectTools .findMethod(JavaScriptCallbackRpc.class, "call", String.class, - JSONArray.class); + JsonArray.class); private static final Method BASIC_PARAMS_CALL_METHOD = ReflectTools .findMethod(TestClientMethodSerialization.class, @@ -60,15 +61,17 @@ public class TestClientMethodSerialization extends TestCase { */ public void testClientMethodSerialization_WithJSONArray_ContentStaysSame() throws Exception { - JSONArray originalArray = new JSONArray(Arrays.asList( - "callbackParameter1", "callBackParameter2", "12345")); + JsonArray originalArray = Json.createArray(); + originalArray.set(0, "callbackParameter1"); + originalArray.set(1, "callBackParameter2"); + originalArray.set(2, "12345"); ClientMethodInvocation original = new ClientMethodInvocation(null, "interfaceName", JAVASCRIPT_CALLBACK_METHOD, new Object[] { "callBackMethodName", originalArray }); ClientMethodInvocation copy = (ClientMethodInvocation) serializeAndDeserialize(original); - JSONArray copyArray = (JSONArray) copy.getParameters()[1]; - assertEquals(originalArray.toString(), copyArray.toString()); + JsonArray copyArray = (JsonArray) copy.getParameters()[1]; + assertEquals(JsonUtil.stringify(originalArray), JsonUtil.stringify(copyArray)); } public void testClientMethodSerialization_WithBasicParams_NoChanges() diff --git a/server/tests/src/com/vaadin/tests/server/component/grid/RendererTest.java b/server/tests/src/com/vaadin/tests/server/component/grid/RendererTest.java index 5583fc02e8..54d15f15d8 100644 --- a/server/tests/src/com/vaadin/tests/server/component/grid/RendererTest.java +++ b/server/tests/src/com/vaadin/tests/server/component/grid/RendererTest.java @@ -36,6 +36,9 @@ import com.vaadin.ui.components.grid.Grid; import com.vaadin.ui.components.grid.GridColumn; import com.vaadin.ui.components.grid.renderers.TextRenderer; +import elemental.json.Json; +import elemental.json.JsonValue; + public class RendererTest { private static class TestBean { @@ -48,8 +51,9 @@ public class RendererTest { private static class TestRenderer extends TextRenderer { @Override - public Object encode(String value) { - return "renderer(" + super.encode(value) + ")"; + public JsonValue encode(String value) { + return Json.create("renderer(" + super.encode(value).asString() + + ")"); } } @@ -156,13 +160,13 @@ public class RendererTest { @Test public void testEncoding() throws Exception { - assertEquals("42", render(foo, 42)); + assertEquals("42", render(foo, 42).asString()); foo.setRenderer(renderer()); - assertEquals("renderer(42)", render(foo, 42)); + assertEquals("renderer(42)", render(foo, 42).asString()); - assertEquals("2.72", render(bar, "2.72")); + assertEquals("2.72", render(bar, "2.72").asString()); bar.setRenderer(new TestRenderer()); - assertEquals("renderer(2.72)", render(bar, "2.72")); + assertEquals("renderer(2.72)", render(bar, "2.72").asString()); } @Test(expected = ConversionException.class) @@ -175,12 +179,13 @@ public class RendererTest { baz.setRenderer(renderer(), converter()); bah.setRenderer(renderer(), converter()); - assertEquals("renderer(TestBean(42))", render(baz, new TestBean())); + assertEquals("renderer(TestBean(42))", render(baz, new TestBean()) + .asString()); assertEquals("renderer(ExtendedBean(42, 3.14))", - render(baz, new ExtendedBean())); + render(baz, new ExtendedBean()).asString()); assertEquals("renderer(ExtendedBean(42, 3.14))", - render(bah, new ExtendedBean())); + render(bah, new ExtendedBean()).asString()); } private TestConverter converter() { @@ -191,7 +196,7 @@ public class RendererTest { return new TestRenderer(); } - private Object render(GridColumn column, Object value) { + private JsonValue render(GridColumn column, Object value) { return RpcDataProviderExtension.encodeValue(value, column.getRenderer(), column.getConverter(), grid.getLocale()); } diff --git a/shared/ivy.xml b/shared/ivy.xml index 2dac7adbc2..dcb7390c04 100644 --- a/shared/ivy.xml +++ b/shared/ivy.xml @@ -27,8 +27,6 @@ conf="build,ide,test->default" /> <dependency org="com.vaadin.external.google" name="guava" rev="16.0.1.vaadin1" conf="build,ide,test->default" /> - <dependency org="com.vaadin.external.json" name="json" - rev="0.0.20080701" conf="build,ide,test->default" /> <dependency org="junit" name="junit" rev="4.11" conf="test,ide -> default" /> diff --git a/shared/src/com/vaadin/shared/ui/tabsheet/TabsheetState.java b/shared/src/com/vaadin/shared/ui/tabsheet/TabsheetState.java index b96a1c9b79..98a1d2b87f 100644 --- a/shared/src/com/vaadin/shared/ui/tabsheet/TabsheetState.java +++ b/shared/src/com/vaadin/shared/ui/tabsheet/TabsheetState.java @@ -16,6 +16,7 @@ package com.vaadin.shared.ui.tabsheet; import java.util.ArrayList; +import java.util.List; import com.vaadin.shared.AbstractComponentState; @@ -32,7 +33,7 @@ public class TabsheetState extends AbstractComponentState { */ public int tabIndex; - public ArrayList<TabState> tabs = new ArrayList<TabState>(); + public List<TabState> tabs = new ArrayList<TabState>(); /** true to show the tab bar, false to only show the contained component */ public boolean tabsVisible = true; diff --git a/uitest/src/com/vaadin/tests/components/LayoutAttachListenerInfo.java b/uitest/src/com/vaadin/tests/components/LayoutAttachListenerInfo.java index b815705883..e118558528 100644 --- a/uitest/src/com/vaadin/tests/components/LayoutAttachListenerInfo.java +++ b/uitest/src/com/vaadin/tests/components/LayoutAttachListenerInfo.java @@ -122,6 +122,7 @@ public class LayoutAttachListenerInfo extends TestBase { final GridLayout g = new GridLayout(4, 4); g.setWidth("300px"); g.setHeight("300px"); + g.setHideEmptyRowsAndColumns(true); g.addComponentAttachListener(new ComponentAttachListener() { @Override public void componentAttachedToContainer(ComponentAttachEvent event) { diff --git a/uitest/src/com/vaadin/tests/components/calendar/CalendarNotifications.html b/uitest/src/com/vaadin/tests/components/calendar/CalendarNotifications.html deleted file mode 100644 index 15bf29a0fd..0000000000 --- a/uitest/src/com/vaadin/tests/components/calendar/CalendarNotifications.html +++ /dev/null @@ -1,41 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> -<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> -<head profile="http://selenium-ide.openqa.org/profiles/test-case"> -<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> -<link rel="selenium.base" href="http://localhost:8080/" /> -<title>New Test</title> -</head> -<body> -<table cellpadding="1" cellspacing="1" border="1"> -<thead> -<tr><td rowspan="1" colspan="3">New Test</td></tr> -</thead><tbody> -<tr> - <td>open</td> - <td>/run/com.vaadin.tests.components.calendar.NotificationTestUI?restartApplication</td> - <td></td> -</tr> -<tr> - <td>mouseClick</td> - <td>vaadin=runcomvaadintestscomponentscalendarNotificationTestUI::/VGridLayout[0]/VCalendar[0]/domChild[0]/domChild[1]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[2]/domChild[0]/domChild[0]</td> - <td>83,11</td> -</tr> -<tr> - <td>mouseMove</td> - <td>vaadin=runcomvaadintestscomponentscalendarNotificationTestUI::/VGridLayout[0]/VCalendar[0]/domChild[0]/domChild[1]/domChild[1]/domChild[0]/domChild[1]/domChild[1]/domChild[3]/domChild[0]/domChild[3]</td> - <td>10,10</td> -</tr> -<tr> - <td>closeNotification</td> - <td>//div[@id='runcomvaadintestscomponentscalendarNotificationTestUI-1842310749-overlays']/div</td> - <td>0,0</td> -</tr> -<tr> - <td>screenCapture</td> - <td></td> - <td>no-notification</td> -</tr> -</tbody></table> -</body> -</html> diff --git a/uitest/src/com/vaadin/tests/components/calendar/CalendarNotifications.java b/uitest/src/com/vaadin/tests/components/calendar/CalendarNotifications.java new file mode 100644 index 0000000000..9b9a64624a --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/calendar/CalendarNotifications.java @@ -0,0 +1,116 @@ +/* + * 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.calendar; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Locale; + +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUIWithLog; +import com.vaadin.ui.Button; +import com.vaadin.ui.Button.ClickEvent; +import com.vaadin.ui.Calendar; +import com.vaadin.ui.GridLayout; +import com.vaadin.ui.Notification; +import com.vaadin.ui.components.calendar.CalendarComponentEvents.DateClickEvent; +import com.vaadin.ui.components.calendar.CalendarComponentEvents.DateClickHandler; +import com.vaadin.ui.components.calendar.event.BasicEvent; +import com.vaadin.ui.components.calendar.event.CalendarEvent; +import com.vaadin.ui.components.calendar.event.CalendarEventProvider; + +public class CalendarNotifications extends AbstractTestUIWithLog { + + private DummyEventProvider provider; + + private static class DummyEventProvider implements CalendarEventProvider { + + private int index; + private List<CalendarEvent> events = new ArrayList<CalendarEvent>(); + + public void addEvent(Date date) { + BasicEvent e = new BasicEvent(); + e.setAllDay(true); + e.setStart(date); + e.setEnd(date); + e.setCaption("Some event " + ++index); + events.add(e); + } + + @Override + public List<CalendarEvent> getEvents(Date startDate, Date endDate) { + return events; + } + + } + + @Override + protected void setup(VaadinRequest request) { + GridLayout content = new GridLayout(1, 2); + content.setSizeFull(); + content.setRowExpandRatio(1, 1.0f); + addComponent(content); + final Button btn = new Button("Show working notification", + new Button.ClickListener() { + @Override + public void buttonClick(ClickEvent event) { + Notification + .show("This will disappear when you move your mouse!"); + } + }); + content.addComponent(btn); + + provider = new DummyEventProvider(); + final Calendar cal = new Calendar(provider); + cal.setLocale(Locale.US); + cal.setSizeFull(); + cal.setHandler(new DateClickHandler() { + @Override + public void dateClick(DateClickEvent event) { + provider.addEvent(event.getDate()); + log("Opening a notification"); + Notification + .show("This should disappear when the mouse is moved."); + + // this requestRepaint call interferes with the notification + cal.markAsDirty(); + } + }); + content.addComponent(cal); + + java.util.Calendar javaCal = java.util.Calendar.getInstance(); + javaCal.set(java.util.Calendar.YEAR, 2000); + javaCal.set(java.util.Calendar.MONTH, 0); + javaCal.set(java.util.Calendar.DAY_OF_MONTH, 1); + Date start = javaCal.getTime(); + javaCal.set(java.util.Calendar.DAY_OF_MONTH, 31); + Date end = javaCal.getTime(); + + cal.setStartDate(start); + cal.setEndDate(end); + } + + @Override + protected String getTestDescription() { + return "Notifications should be opened and then closed after the user has moved the mouse."; + } + + @Override + protected Integer getTicketNumber() { + return 6769; + } +} diff --git a/uitest/src/com/vaadin/tests/components/calendar/CalendarNotificationsTest.java b/uitest/src/com/vaadin/tests/components/calendar/CalendarNotificationsTest.java new file mode 100644 index 0000000000..2431b2f4d0 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/calendar/CalendarNotificationsTest.java @@ -0,0 +1,82 @@ +/* + * 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.calendar; + +import java.util.List; + +import org.junit.Assert; +import org.junit.Test; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.interactions.Actions; +import org.openqa.selenium.remote.DesiredCapabilities; + +import com.vaadin.testbench.By; +import com.vaadin.testbench.elements.NotificationElement; +import com.vaadin.tests.tb3.MultiBrowserTest; + +/** + * Tests opening and closing of calendar notifications. + * + * @since + * @author Vaadin Ltd + */ +public class CalendarNotificationsTest extends MultiBrowserTest { + + @Override + protected Class<?> getUIClass() { + return NotificationTestUI.class; + } + + @Override + protected DesiredCapabilities getDesiredCapabilities() { + DesiredCapabilities desiredCapabilities = new DesiredCapabilities( + super.getDesiredCapabilities()); + desiredCapabilities.setCapability("enablePersistentHover", false); + desiredCapabilities.setCapability("requireWindowFocus", true); + + return desiredCapabilities; + } + + @Override + public List<DesiredCapabilities> getBrowsersToTest() { + // TODO: IE testing is pending on #14312. For now, IE testing is handled + // with a logger. + return getBrowsersExcludingIE(); + } + + @Test + public void notificationTest() throws Exception { + openTestURL(); + + WebElement day = findElements(By.className("v-calendar-day-number")) + .get(2); + // IE8 requires you to click on the text part to fire the event + new Actions(getDriver()).moveToElement(day, 83, 11).click().perform(); + + Assert.assertTrue("There should be a notification", + $(NotificationElement.class).exists()); + + // move the mouse around a bit + new Actions(getDriver()).moveByOffset(5, 5).moveByOffset(100, 100) + .perform(); + + // wait until the notification has animated out + sleep(1000); + + Assert.assertFalse("There should be no notification on the page", + $(NotificationElement.class).exists()); + } +} diff --git a/uitest/src/com/vaadin/tests/components/calendar/CalendarNotificationsTestIE.java b/uitest/src/com/vaadin/tests/components/calendar/CalendarNotificationsTestIE.java new file mode 100644 index 0000000000..7ab6f01113 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/calendar/CalendarNotificationsTestIE.java @@ -0,0 +1,91 @@ +/* + * 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.calendar; + +import java.util.List; + +import org.junit.Assert; +import org.junit.Test; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.interactions.Actions; +import org.openqa.selenium.remote.DesiredCapabilities; + +import com.vaadin.testbench.By; +import com.vaadin.testbench.elements.NotificationElement; +import com.vaadin.tests.tb3.MultiBrowserTest; + +/** + * Tests opening and closing of calendar notifications. + * + * @since + * @author Vaadin Ltd + */ +public class CalendarNotificationsTestIE extends MultiBrowserTest { + + @Override + protected Class<?> getUIClass() { + return CalendarNotifications.class; + } + + @Override + protected DesiredCapabilities getDesiredCapabilities() { + DesiredCapabilities desiredCapabilities = new DesiredCapabilities( + super.getDesiredCapabilities()); + desiredCapabilities.setCapability("enablePersistentHover", false); + desiredCapabilities.setCapability("requireWindowFocus", true); + + return desiredCapabilities; + } + + @Override + public List<DesiredCapabilities> getBrowsersToTest() { + List<DesiredCapabilities> browsers = super.getBrowsersToTest(); + browsers.remove(Browser.CHROME.getDesiredCapabilities()); + browsers.remove(Browser.FIREFOX.getDesiredCapabilities()); + browsers.remove(Browser.OPERA.getDesiredCapabilities()); + browsers.remove(Browser.PHANTOMJS.getDesiredCapabilities()); + browsers.remove(Browser.SAFARI.getDesiredCapabilities()); + return browsers; + } + + @Test + public void notificationTest() throws Exception { + openTestURL(); + + WebElement day = findElements(By.className("v-calendar-day-number")) + .get(2); + // IE8 requires you to click on the text part to fire the event + new Actions(getDriver()).moveToElement(day, 83, 11).click().perform(); + + // check that a notification was opened, this is done with a log instead + // of a screenshot or element presence check due to problems with IE + // webdriver + String text = findElement(By.id("Log")).findElement( + By.className("v-label")).getText(); + Assert.assertTrue("Notification should've opened", + "1. Opening a notification".equals(text)); + + // move the mouse around a bit + new Actions(getDriver()).moveByOffset(5, 5).moveByOffset(100, 100) + .perform(); + + // wait until the notification has animated out + sleep(1000); + + Assert.assertFalse("There should be no notification on the page", + $(NotificationElement.class).exists()); + } +} diff --git a/uitest/src/com/vaadin/tests/components/calendar/CalendarRescheduleEvent.java b/uitest/src/com/vaadin/tests/components/calendar/CalendarRescheduleEvent.java new file mode 100644 index 0000000000..824ad0941f --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/calendar/CalendarRescheduleEvent.java @@ -0,0 +1,105 @@ +/* + * 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.calendar; + +import java.util.Date; +import java.util.List; + +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.Calendar; +import com.vaadin.ui.HorizontalLayout; +import com.vaadin.ui.Label; +import com.vaadin.ui.components.calendar.event.BasicEvent; +import com.vaadin.ui.components.calendar.event.BasicEventProvider; +import com.vaadin.ui.components.calendar.event.CalendarEvent; +import com.vaadin.ui.components.calendar.event.CalendarEventProvider.EventSetChangeEvent; +import com.vaadin.ui.components.calendar.event.CalendarEventProvider.EventSetChangeListener; + +/** + * Test UI to check ability to reschedule events unlimited times. + * + * @author Vaadin Ltd + */ +public class CalendarRescheduleEvent extends AbstractTestUI { + + @Override + protected void setup(VaadinRequest request) { + final Calendar calendar = new Calendar("Test calendar"); + final java.util.Calendar cal = getAdjustedCalendar(1); + + Date from = cal.getTime(); + + cal.add(java.util.Calendar.HOUR, 1); + Date to = cal.getTime(); + + final BasicEvent basicEvent = new BasicEvent("event", "description", + from, to); + + HorizontalLayout info = new HorizontalLayout(); + info.setSpacing(true); + info.setMargin(true); + addComponent(info); + final Label startLbl = new Label(); + startLbl.addStyleName("start"); + info.addComponent(startLbl); + + final Label endLbl = new Label(); + endLbl.addStyleName("end"); + info.addComponent(endLbl); + + BasicEventProvider provider = new BasicEventProvider(); + provider.addEvent(basicEvent); + calendar.setEventProvider(provider); + provider.addEventSetChangeListener(new EventSetChangeListener() { + + @Override + public void eventSetChange(EventSetChangeEvent event) { + List<CalendarEvent> events = event.getProvider().getEvents( + new Date(0), new Date(Long.MAX_VALUE)); + CalendarEvent calEvent = events.get(0); + Date startEvent = calEvent.getStart(); + Date endEvent = calEvent.getEnd(); + + startLbl.setValue(String.valueOf(startEvent.getTime())); + endLbl.setValue(String.valueOf(endEvent.getTime())); + } + }); + + addComponent(calendar); + } + + @Override + protected String getTestDescription() { + return "It should be possible to reschedule events unlimited times."; + } + + @Override + protected Integer getTicketNumber() { + return 13233; + } + + private java.util.Calendar getAdjustedCalendar(int hour) { + final java.util.Calendar cal = java.util.Calendar.getInstance(); + + cal.set(java.util.Calendar.HOUR_OF_DAY, hour); + cal.set(java.util.Calendar.MINUTE, 0); + cal.set(java.util.Calendar.SECOND, 0); + cal.set(java.util.Calendar.MILLISECOND, 0); + return cal; + } + +} diff --git a/uitest/src/com/vaadin/tests/components/calendar/CalendarRescheduleEventTest.java b/uitest/src/com/vaadin/tests/components/calendar/CalendarRescheduleEventTest.java new file mode 100644 index 0000000000..fb8cce7d53 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/calendar/CalendarRescheduleEventTest.java @@ -0,0 +1,82 @@ +/* + * 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.calendar; + +import org.junit.Assert; +import org.junit.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.WebElement; + +import com.vaadin.tests.tb3.DndActionsTest; + +/** + * Test to check ability to reschedule events unlimited times. + * + * @author Vaadin Ltd + */ +public class CalendarRescheduleEventTest extends DndActionsTest { + + @Test + public void rescheduleEventSeveralTimes() { + openTestURL(); + + // Reschedule event for the first time + int y = rescheduleEvent(20); + + WebElement startElement = getDriver() + .findElement(By.className("start")); + WebElement endElement = getDriver().findElement(By.className("end")); + + long start = Long.parseLong(startElement.getText()); + long end = Long.parseLong(endElement.getText()); + + long duration = end - start; + + // Reschedule event for the second time + int yNew = rescheduleEvent(20); + + startElement = getDriver().findElement(By.className("start")); + endElement = getDriver().findElement(By.className("end")); + + long newStart = Long.parseLong(startElement.getText()); + long newEnd = Long.parseLong(endElement.getText()); + + Assert.assertTrue( + "Second rescheduling did not change the event start time", + newStart > start); + Assert.assertEquals( + "Duration of the event after second rescheduling has been changed", + duration, newEnd - newStart); + Assert.assertTrue( + "Second rescheduling did not change the event Y coordinate", + yNew > y); + } + + /* + * DnD event by Y axis + */ + private int rescheduleEvent(int yOffset) { + WebElement eventCaption = getDriver().findElement( + By.className("v-calendar-event-caption")); + + dragAndDrop(eventCaption, 0, yOffset); + + eventCaption = getDriver().findElement( + By.className("v-calendar-event-caption")); + return eventCaption.getLocation().getY(); + } + +} diff --git a/uitest/src/com/vaadin/tests/components/calendar/CalendarResizeOverlappingEventsTest.java b/uitest/src/com/vaadin/tests/components/calendar/CalendarResizeOverlappingEventsTest.java index f664149cce..e3e5606089 100644 --- a/uitest/src/com/vaadin/tests/components/calendar/CalendarResizeOverlappingEventsTest.java +++ b/uitest/src/com/vaadin/tests/components/calendar/CalendarResizeOverlappingEventsTest.java @@ -24,15 +24,14 @@ import org.junit.Assert; import org.junit.Test; import org.openqa.selenium.By; import org.openqa.selenium.WebElement; -import org.openqa.selenium.interactions.Actions; -import com.vaadin.tests.tb3.MultiBrowserTest; +import com.vaadin.tests.tb3.DndActionsTest; /** * * @author Vaadin Ltd */ -public class CalendarResizeOverlappingEventsTest extends MultiBrowserTest { +public class CalendarResizeOverlappingEventsTest extends DndActionsTest { private int noOverlapWidth; private int oneOverlapWidth; @@ -100,23 +99,7 @@ public class CalendarResizeOverlappingEventsTest extends MultiBrowserTest { } private void dragAndDrop(WebElement element, int yOffset) { - /* - * Selenium doesn't properly drag and drop items in IE8. It tries to - * start dragging an element from a position above the element itself. - */ - if (BrowserUtil.isIE8(getDesiredCapabilities())) { - Actions action = new Actions(getDriver()); - action.moveToElement(element); - action.moveByOffset(0, 1); - action.clickAndHold(); - action.moveByOffset(0, yOffset); - action.release(); - action.build().perform(); - } else { - Actions action = new Actions(getDriver()); - action.dragAndDropBy(element, 0, yOffset); - action.build().perform(); - } + dragAndDrop(element, 0, yOffset); } private void initParams() { diff --git a/uitest/src/com/vaadin/tests/components/combobox/ComboboxMenuBarAutoopen.java b/uitest/src/com/vaadin/tests/components/combobox/ComboboxMenuBarAutoopen.java new file mode 100644 index 0000000000..f65b020bd1 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/combobox/ComboboxMenuBarAutoopen.java @@ -0,0 +1,79 @@ +/* + * 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.combobox; + +import java.util.ArrayList; + +import com.vaadin.server.Page; +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.ComboBox; +import com.vaadin.ui.HorizontalLayout; +import com.vaadin.ui.MenuBar; +import com.vaadin.ui.MenuBar.MenuItem; +import com.vaadin.ui.Notification; +import com.vaadin.ui.Notification.Type; + +/** + * Test UI for combobox popup which should be closed on any click outside it. + * + * @author Vaadin Ltd + */ +public class ComboboxMenuBarAutoopen extends AbstractTestUI { + + @Override + protected void setup(VaadinRequest request) { + HorizontalLayout layout = new HorizontalLayout(); + layout.setSpacing(true); + ArrayList<String> options = new ArrayList<String>(); + options.add("1"); + options.add("2"); + options.add("3"); + ComboBox combo = new ComboBox(null, options); + layout.addComponent(combo); + + MenuBar menubar = getMenubar(); + layout.addComponent(menubar); + + addComponent(layout); + } + + @Override + protected String getTestDescription() { + return "Combobox popup should close on click to other popup or associated components."; + } + + @Override + protected Integer getTicketNumber() { + return 14321; + } + + private MenuBar getMenubar() { + MenuBar menubar = new MenuBar(); + menubar.setAutoOpen(true); + MenuItem item = menubar.addItem("auto-open", null); + item.addItem("sub-item 1", new MenuBar.Command() { + + @Override + public void menuSelected(MenuItem selectedItem) { + Notification notification = new Notification("Test", + Type.HUMANIZED_MESSAGE); + notification.show(Page.getCurrent()); + } + }); + return menubar; + } +} diff --git a/uitest/src/com/vaadin/tests/components/combobox/ComboboxMenuBarAutoopenTest.java b/uitest/src/com/vaadin/tests/components/combobox/ComboboxMenuBarAutoopenTest.java new file mode 100644 index 0000000000..5c8c971194 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/combobox/ComboboxMenuBarAutoopenTest.java @@ -0,0 +1,80 @@ +/* + * 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.combobox; + +import org.junit.Assert; +import org.junit.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.interactions.Actions; + +import com.vaadin.testbench.elements.ComboBoxElement; +import com.vaadin.testbench.elements.MenuBarElement; +import com.vaadin.tests.tb3.MultiBrowserTest; + +/** + * Test that checks whether Combobox popup is closed on click to autoopen + * menubar and its item. + * + * @author Vaadin Ltd + */ +public class ComboboxMenuBarAutoopenTest extends MultiBrowserTest { + + @Test + public void closeComboboxPopupOnClickToMenuBar() { + openTestURL(); + + openPopup(); + MenuBarElement menuBar = selectMenuBar(); + menuBar.click(); + Assert.assertFalse("Combobox popup items are visible", + isElementPresent(By.className("gwt-MenuItem"))); + + openPopup(); + menuBar = selectMenuBar(); + + WebElement menuBarItem = findElement(By + .className("v-menubar-menuitem-caption")); + Actions actions = new Actions(getDriver()); + actions.moveToElement(menuBarItem).build().perform(); + menuBar.click(); + Assert.assertFalse("Combobox popup items are visible", + isElementPresent(By.className("gwt-MenuItem"))); + } + + private void openPopup() { + ComboBoxElement combobox = $(ComboBoxElement.class).first(); + combobox.click(); + combobox.openPopup(); + combobox.focus(); + + Actions actions = new Actions(getDriver()); + actions.moveToElement( + getDriver().findElement(By.className("gwt-MenuItem"))).build() + .perform(); + } + + private MenuBarElement selectMenuBar() { + MenuBarElement menuBar = $(MenuBarElement.class).first(); + menuBar.focus(); + + Actions actions = new Actions(getDriver()); + actions.moveToElement(menuBar).build().perform(); + + return menuBar; + } + +} diff --git a/uitest/src/com/vaadin/tests/components/grid/IntArrayRenderer.java b/uitest/src/com/vaadin/tests/components/grid/IntArrayRenderer.java index 142c370e13..ccedcc908a 100644 --- a/uitest/src/com/vaadin/tests/components/grid/IntArrayRenderer.java +++ b/uitest/src/com/vaadin/tests/components/grid/IntArrayRenderer.java @@ -15,22 +15,23 @@ */ package com.vaadin.tests.components.grid; -import org.json.JSONArray; -import org.json.JSONException; - import com.vaadin.ui.components.grid.AbstractRenderer; +import elemental.json.Json; +import elemental.json.JsonArray; +import elemental.json.JsonValue; + public class IntArrayRenderer extends AbstractRenderer<int[]> { public IntArrayRenderer() { super(int[].class); } @Override - public Object encode(int[] value) { - try { - return new JSONArray(value); - } catch (JSONException e) { - throw new RuntimeException(e); + public JsonValue encode(int[] value) { + JsonArray valueArray = Json.createArray(); + for (int i = 0; i < value.length; ++i) { + valueArray.set(i, value[i]); } + return valueArray; } } diff --git a/uitest/src/com/vaadin/tests/components/grid/RowAwareRenderer.java b/uitest/src/com/vaadin/tests/components/grid/RowAwareRenderer.java index f55f5f064c..41ccddc2cf 100644 --- a/uitest/src/com/vaadin/tests/components/grid/RowAwareRenderer.java +++ b/uitest/src/com/vaadin/tests/components/grid/RowAwareRenderer.java @@ -15,12 +15,13 @@ */ package com.vaadin.tests.components.grid; -import org.json.JSONObject; - import com.vaadin.tests.widgetset.client.grid.RowAwareRendererConnector.RowAwareRendererRpc; import com.vaadin.ui.Label; import com.vaadin.ui.components.grid.AbstractRenderer; +import elemental.json.Json; +import elemental.json.JsonValue; + public class RowAwareRenderer extends AbstractRenderer<Void> { public RowAwareRenderer(final Label debugLabel) { super(Void.class); @@ -34,8 +35,8 @@ public class RowAwareRenderer extends AbstractRenderer<Void> { } @Override - public Object encode(Void value) { - return JSONObject.NULL; + public JsonValue encode(Void value) { + return Json.createNull(); } } diff --git a/uitest/src/com/vaadin/tests/components/gridlayout/GridLayoutExtraSpacing.java b/uitest/src/com/vaadin/tests/components/gridlayout/GridLayoutExtraSpacing.java new file mode 100644 index 0000000000..ce59f9c89f --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/gridlayout/GridLayoutExtraSpacing.java @@ -0,0 +1,91 @@ +/* + * 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.gridlayout; + +import com.vaadin.data.Property.ValueChangeEvent; +import com.vaadin.data.Property.ValueChangeListener; +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.CheckBox; +import com.vaadin.ui.CssLayout; +import com.vaadin.ui.GridLayout; + +public class GridLayoutExtraSpacing extends AbstractTestUI { + + @Override + protected void setup(VaadinRequest request) { + getUI().getPage() + .getStyles() + .add(".v-gridlayout {background: red;} .v-csslayout {background: white;}"); + + final GridLayout gl = new GridLayout(4, 4); + + final CheckBox cb = new CheckBox("spacing"); + cb.addValueChangeListener(new ValueChangeListener() { + + @Override + public void valueChange(ValueChangeEvent event) { + gl.setSpacing(cb.getValue()); + } + }); + cb.setValue(true); + addComponent(cb); + + final CheckBox cb2 = new CheckBox("hide empty rows/columns"); + cb2.addValueChangeListener(new ValueChangeListener() { + + @Override + public void valueChange(ValueChangeEvent event) { + gl.setHideEmptyRowsAndColumns(cb2.getValue()); + } + }); + addComponent(cb2); + gl.setWidth("1000px"); + gl.setHeight("500px"); + + CssLayout ta = new CssLayout(); + ta.setSizeFull(); + // Only on last row + gl.addComponent(ta, 0, 3, 3, 3); + + gl.setRowExpandRatio(3, 1); + addComponent(gl); + + } + + /* + * (non-Javadoc) + * + * @see com.vaadin.tests.components.AbstractTestUI#getTestDescription() + */ + @Override + protected String getTestDescription() { + // TODO Auto-generated method stub + return null; + } + + /* + * (non-Javadoc) + * + * @see com.vaadin.tests.components.AbstractTestUI#getTicketNumber() + */ + @Override + protected Integer getTicketNumber() { + // TODO Auto-generated method stub + return null; + } + +} diff --git a/uitest/src/com/vaadin/tests/components/gridlayout/GridLayoutExtraSpacingTest.java b/uitest/src/com/vaadin/tests/components/gridlayout/GridLayoutExtraSpacingTest.java new file mode 100644 index 0000000000..64b9997dcc --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/gridlayout/GridLayoutExtraSpacingTest.java @@ -0,0 +1,104 @@ +/* + * 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.gridlayout; + +import java.io.IOException; + +import org.junit.Assert; +import org.junit.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.WebElement; + +import com.vaadin.testbench.elements.CheckBoxElement; +import com.vaadin.testbench.elements.CssLayoutElement; +import com.vaadin.testbench.elements.GridLayoutElement; +import com.vaadin.tests.tb3.MultiBrowserTest; + +public class GridLayoutExtraSpacingTest extends MultiBrowserTest { + + @Test + public void componentRowFour() throws IOException, Exception { + openTestURL(); + CssLayoutElement component = $(CssLayoutElement.class).first(); + GridLayoutElement gridLayout = $(GridLayoutElement.class).first(); + + // Spacing on, not hiding empty rows/columns + // There should be 3 * 6px spacing (red) above the csslayout + verifySpacingAbove(3 * 6, gridLayout, component); + + CheckBoxElement spacingCheckbox = $(CheckBoxElement.class).caption( + "spacing").first(); + check(spacingCheckbox); + + // Spacing off, not hiding empty rows/columns + // There should not be any spacing (red) above the csslayout + verifySpacingAbove(0, gridLayout, component); + + CheckBoxElement hideRowsColumnsCheckbox = $(CheckBoxElement.class) + .caption("hide empty rows/columns").first(); + check(hideRowsColumnsCheckbox); + + // Spacing off, hiding empty rows/columns + // There should not be any spacing (red) above the csslayout + verifySpacingAbove(0, gridLayout, component); + + check(spacingCheckbox); + // Spacing on, hiding empty rows/columns + // There should not be any spacing (red) above or below the csslayout + + // Oh PhantomJs... + sleep(100); + // FIXME: This should be 0 but there is a bug somewhere + // verifySpacingAbove(0, gridLayout, component); + verifySpacingBelow(6, gridLayout, component); + + } + + /** + * workaround for http://dev.vaadin.com/ticket/13763 + */ + private void check(CheckBoxElement checkbox) { + WebElement cb = checkbox.findElement(By.xpath("input")); + if (BrowserUtil.isChrome(getDesiredCapabilities())) { + testBenchElement(cb).click(0, 0); + } else { + cb.click(); + } + } + + private void verifySpacingAbove(int spacing, GridLayoutElement gridLayout, + CssLayoutElement component) { + assertHeight(component, 500 - spacing, 1); + int offset = component.getLocation().getY() + - gridLayout.getLocation().getY(); + Assert.assertEquals(spacing, offset); + + } + + private void verifySpacingBelow(int spacing, GridLayoutElement gridLayout, + CssLayoutElement component) { + assertHeight(component, 500 - spacing, 1); + + int offset = component.getLocation().getY() + - gridLayout.getLocation().getY(); + Assert.assertEquals(0, offset); + + } + + private void assertHeight(WebElement component, int height, int tolerance) { + Assert.assertTrue(Math.abs(height - component.getSize().getHeight()) <= tolerance); + } +} diff --git a/uitest/src/com/vaadin/tests/components/javascriptcomponent/BasicJavaScriptComponent.java b/uitest/src/com/vaadin/tests/components/javascriptcomponent/BasicJavaScriptComponent.java index 5a64cb6a00..bd7522aab7 100644 --- a/uitest/src/com/vaadin/tests/components/javascriptcomponent/BasicJavaScriptComponent.java +++ b/uitest/src/com/vaadin/tests/components/javascriptcomponent/BasicJavaScriptComponent.java @@ -19,9 +19,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import org.json.JSONArray; -import org.json.JSONException; - import com.vaadin.annotations.JavaScript; import com.vaadin.server.ConnectorResource; import com.vaadin.server.DownloadStream; @@ -39,6 +36,7 @@ import com.vaadin.ui.Button; import com.vaadin.ui.Button.ClickEvent; import com.vaadin.ui.HasComponents; import com.vaadin.ui.JavaScriptFunction; +import elemental.json.JsonArray; public class BasicJavaScriptComponent extends AbstractTestUI { @@ -78,15 +76,15 @@ public class BasicJavaScriptComponent extends AbstractTestUI { }); addFunction("messageToServer", new JavaScriptFunction() { @Override - public void call(JSONArray arguments) throws JSONException { + public void call(JsonArray arguments) { log.log("Got callback message: " + arguments.getString(0)); } }); addFunction("reportParentIds", new JavaScriptFunction() { @Override - public void call(JSONArray arguments) throws JSONException { - JSONArray parentIds = arguments.getJSONArray(0); + public void call(JsonArray arguments) { + JsonArray parentIds = arguments.getArray(0); if (!parentIds.getString(0).equals(getConnectorId())) { log.log("Connector ids doesn't match"); } diff --git a/uitest/src/com/vaadin/tests/components/popupview/PopupViewShortcutActionHandler.java b/uitest/src/com/vaadin/tests/components/popupview/PopupViewShortcutActionHandler.java new file mode 100644 index 0000000000..ca91597aa2 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/popupview/PopupViewShortcutActionHandler.java @@ -0,0 +1,79 @@ +/* + * 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.popupview; + +import com.vaadin.event.ShortcutAction; +import com.vaadin.event.ShortcutListener; +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.Component; +import com.vaadin.ui.Label; +import com.vaadin.ui.PopupView; +import com.vaadin.ui.TextField; + +/** + * Test UI to check availability of shortcut action listener in the popup view + * oeverlay component. + * + * @author Vaadin Ltd + */ +public class PopupViewShortcutActionHandler extends AbstractTestUI { + + @Override + protected void setup(VaadinRequest request) { + addComponent(new PopupView(new DemoPoupView())); + } + + @Override + protected String getTestDescription() { + return "Shortcut listener search should be executed in the end " + + "of request (after legacy UIDL request handling)."; + } + + @Override + protected Integer getTicketNumber() { + return 14275; + } + + private class DemoPoupView implements PopupView.Content { + + @Override + public String getMinimizedValueAsHTML() { + return "Click Me"; + } + + @Override + public Component getPopupComponent() { + TextField field = new TextField("Enter text"); + field.setImmediate(true); + field.addShortcutListener(new ShortcutListener("SearchAction", + ShortcutAction.KeyCode.ENTER, null) { + private static final long serialVersionUID = 1L; + + @Override + public void handleAction(Object sender, Object target) { + Label label = new Label( + "shortcut addedEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE"); + label.addStyleName("shortcut-result"); + addComponent(label); + } + }); + return field; + } + + } + +} diff --git a/uitest/src/com/vaadin/tests/components/popupview/PopupViewShortcutActionHandlerTest.java b/uitest/src/com/vaadin/tests/components/popupview/PopupViewShortcutActionHandlerTest.java new file mode 100644 index 0000000000..f122e1a415 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/popupview/PopupViewShortcutActionHandlerTest.java @@ -0,0 +1,79 @@ +/* + * 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.popupview; + +import java.util.Collections; +import java.util.List; + +import org.junit.Assert; +import org.junit.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.Keys; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.phantomjs.PhantomJSDriver; +import org.openqa.selenium.remote.DesiredCapabilities; + +import com.vaadin.testbench.TestBench; +import com.vaadin.tests.tb3.MultiBrowserTest; + +/** + * Check availability of shortcut action listener in the popup view. + * + * @author Vaadin Ltd + */ +public class PopupViewShortcutActionHandlerTest extends MultiBrowserTest { + + @Test + public void testShortcutHandling() { + openTestURL(); + + getDriver().findElement(By.className("v-popupview")).click(); + WebElement textField = getDriver().findElement( + By.className("v-textfield")); + textField.sendKeys("a", Keys.ENTER); + + Assert.assertTrue( + "Unable to find label component which is the result of" + + " shortcut action handling.", + isElementPresent(By.className("shortcut-result"))); + } + + @Override + protected void setupDriver() throws Exception { + System.setProperty("phantomjs.binary.path", + "C:\\tmp\\phantom\\phantomjs.exe"); + WebDriver dr = TestBench.createDriver(new PhantomJSDriver()); + setDriver(dr); + } + + @Override + protected String getScreenshotDirectory() { + return "C:\\tmp\\a"; + } + + @Override + protected void openTestURL() { + driver.get("http://localhost:8080/vaadin/run/PopupViewShortcutActionHandler"); + } + + @Override + public List<DesiredCapabilities> getBrowsersToTest() { + return Collections.singletonList(Browser.FIREFOX + .getDesiredCapabilities()); + } + +} diff --git a/uitest/src/com/vaadin/tests/components/table/TableMatchesMouseDownMouseUpElement.java b/uitest/src/com/vaadin/tests/components/table/TableMatchesMouseDownMouseUpElement.java new file mode 100644 index 0000000000..1515589b4c --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/table/TableMatchesMouseDownMouseUpElement.java @@ -0,0 +1,76 @@ +package com.vaadin.tests.components.table; + +import com.vaadin.data.Item; +import com.vaadin.server.VaadinRequest; +import com.vaadin.shared.ui.label.ContentMode; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.Button; +import com.vaadin.ui.Button.ClickEvent; +import com.vaadin.ui.Button.ClickListener; +import com.vaadin.ui.Component; +import com.vaadin.ui.Label; +import com.vaadin.ui.Table; +import com.vaadin.ui.VerticalLayout; + +public class TableMatchesMouseDownMouseUpElement extends AbstractTestUI { + + static final String CLEAR_BUTTON_ID = "clear-button-id"; + + @Override + protected String getTestDescription() { + return "Both mouse down and mouse up should be done on same cell to be considered as a click."; + } + + @Override + protected Integer getTicketNumber() { + return 14347; + } + + @SuppressWarnings("unchecked") + @Override + protected void setup(VaadinRequest request) { + final Table table = new Table(); + table.setHeight("500px"); + table.setSelectable(true); + table.setNullSelectionAllowed(true); + table.addContainerProperty("Column 1", String.class, ""); + table.addContainerProperty("Column 2", Component.class, ""); + table.addContainerProperty("Column 3", Component.class, ""); + table.addContainerProperty("Column 4", Component.class, ""); + + Item item = table.addItem("Item 1 (row 1)"); + item.getItemProperty("Column 1").setValue("String A"); + item.getItemProperty("Column 2").setValue(new Label("Label A")); + item.getItemProperty("Column 3").setValue( + new Label("<b>Label A</b>", ContentMode.HTML)); + VerticalLayout l = new VerticalLayout(); + l.setId("row-1"); + l.setHeight(100, Unit.PIXELS); + item.getItemProperty("Column 4").setValue(l); + + item = table.addItem("Item 2 (row 2)"); + item.getItemProperty("Column 1").setValue("String B"); + item.getItemProperty("Column 2").setValue(new Label("Label B")); + item.getItemProperty("Column 3") + .setValue( + new Label( + "<a style=\"color: blue\" href=\"javascript:false\">Label B</a>", + ContentMode.HTML)); + l = new VerticalLayout(); + l.setId("row-2"); + l.setSizeFull(); + item.getItemProperty("Column 4").setValue(l); + + Button clear = new Button("Clear"); + clear.setId(CLEAR_BUTTON_ID); + clear.addClickListener(new ClickListener() { + + @Override + public void buttonClick(ClickEvent event) { + table.setValue(null); + } + }); + addComponent(table); + addComponent(clear); + } +} diff --git a/uitest/src/com/vaadin/tests/components/table/TableMatchesMouseDownMouseUpElementTest.java b/uitest/src/com/vaadin/tests/components/table/TableMatchesMouseDownMouseUpElementTest.java new file mode 100644 index 0000000000..ea730ea30e --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/table/TableMatchesMouseDownMouseUpElementTest.java @@ -0,0 +1,147 @@ +/* + * 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.table; + +import static com.vaadin.tests.components.table.TableMatchesMouseDownMouseUpElement.CLEAR_BUTTON_ID; +import static org.junit.Assert.assertEquals; + +import java.util.List; + +import org.junit.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.interactions.Actions; + +import com.vaadin.testbench.elements.TableElement; +import com.vaadin.tests.tb3.MultiBrowserTest; + +/** + * Regular click cases already covered by @LabelEmbeddedClickThroughForTableTest + * Testing cases when mouse down and mouse up positions are different + * + * @since + * @author Vaadin Ltd + */ +public class TableMatchesMouseDownMouseUpElementTest extends MultiBrowserTest { + + TableElement table; + + @Test + public void testClick() { + openTestURL(); + table = $(TableElement.class).first(); + + testMoveOut(getBoldTag(0, 2)); + testMoveIn(getBoldTag(0, 2)); + + testMoveOut(getLabel(0, 1)); + testMoveIn(getLabel(0, 1)); + + testClickOnDifferentRows(); + } + + /** + * MouseDown on element and mouseUp outside element but on same cell + */ + private void testMoveOut(WebElement element) { + clearSelection(); + clickAndMove(element, 5, 5, 0, 50); + checkSelectedRowCount(1); + checkRowSelected(0); + } + + /** + * MouseDown outside element but on same cell and mouseUp on element + */ + private void testMoveIn(WebElement element) { + clearSelection(); + clickAndMove(element, 5, 55, 0, -50); + checkSelectedRowCount(1); + checkRowSelected(0); + } + + /** + * Mouse down in cell of row1 holds and mouse up in cell of row 2 + */ + public void testClickOnDifferentRows() { + clearSelection(); + WebElement elementFrom = getCell(0, 1); + WebElement elementTo = getCell(0, 2); + clickAndMove(elementFrom, elementTo); + checkSelectedRowCount(0); + } + + private WebElement getBoldTag(int row, int column) { + return table.getCell(row, column).findElement(By.className("v-label")) + .findElement(By.tagName("b")); + } + + private WebElement getLabel(int row, int column) { + return table.getCell(row, column).findElement(By.className("v-label")); + } + + private WebElement getCell(int row, int column) { + return table.getCell(row, column); + } + + private void clearSelection() { + WebElement clearButton = vaadinElementById(CLEAR_BUTTON_ID); + clearButton.click(); + } + + /** + * Mouse down on element + initial offset -> Moves the "move offset" -> + * Mouse up + */ + private void clickAndMove(WebElement element, int initialX, int initialY, + int moveX, int moveY) { + new Actions(driver).moveToElement(element, initialX, initialY) + .clickAndHold().perform(); + new Actions(driver).moveByOffset(moveX, moveY).perform(); + new Actions(driver).release().perform(); + } + + /** + * Mouse down on elementFrom -> Moves to elementTo -> Mouse up + */ + private void clickAndMove(WebElement elementFrom, WebElement elementTo) { + new Actions(driver).moveToElement(elementFrom, 5, 5).clickAndHold() + .perform(); + new Actions(driver).moveToElement(elementTo, 5, 5).perform(); + new Actions(driver).release().perform(); + } + + private void checkRowSelected(int rowIndex) { + assertEquals( + "contents of the selected row don't match contents of the row #" + + rowIndex, + table.getCell(rowIndex, 0).getText(), + getSelectedRows().get(0) + .findElement(By.className("v-table-cell-wrapper")) + .getText()); + } + + private void checkSelectedRowCount(int expected) { + assertEquals("unexpected table selection size", expected, + getSelectedRows().size()); + } + + private List<WebElement> getSelectedRows() { + return table.findElement(By.className("v-table-body")).findElements( + By.className("v-selected")); + } + +} diff --git a/uitest/src/com/vaadin/tests/components/table/TableRemovedQuicklySendsInvalidRpcCalls.java b/uitest/src/com/vaadin/tests/components/table/TableRemovedQuicklySendsInvalidRpcCalls.java index c21a38a0ac..710a4f8fe3 100644 --- a/uitest/src/com/vaadin/tests/components/table/TableRemovedQuicklySendsInvalidRpcCalls.java +++ b/uitest/src/com/vaadin/tests/components/table/TableRemovedQuicklySendsInvalidRpcCalls.java @@ -19,8 +19,6 @@ package com.vaadin.tests.components.table; import java.util.ArrayList; import java.util.Collection; -import org.json.JSONObject; - import com.vaadin.annotations.Push; import com.vaadin.server.ClientConnector; import com.vaadin.server.StreamVariable; @@ -30,6 +28,7 @@ import com.vaadin.ui.Button; import com.vaadin.ui.Button.ClickEvent; import com.vaadin.ui.ConnectorTracker; import com.vaadin.ui.Table; +import elemental.json.JsonObject; @Push public class TableRemovedQuicklySendsInvalidRpcCalls extends AbstractTestUI { @@ -125,12 +124,12 @@ public class TableRemovedQuicklySendsInvalidRpcCalls extends AbstractTestUI { } @Override - public JSONObject getDiffState(ClientConnector connector) { + public JsonObject getDiffState(ClientConnector connector) { return tracker.getDiffState(connector); } @Override - public void setDiffState(ClientConnector connector, JSONObject diffState) { + public void setDiffState(ClientConnector connector, JsonObject diffState) { tracker.setDiffState(connector, diffState); } diff --git a/uitest/src/com/vaadin/tests/components/tabsheet/NewSelectionAfterTabRemove.java b/uitest/src/com/vaadin/tests/components/tabsheet/NewSelectionAfterTabRemove.java new file mode 100644 index 0000000000..939bd645ea --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/tabsheet/NewSelectionAfterTabRemove.java @@ -0,0 +1,61 @@ +/* + * 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.tabsheet; + +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.Label; +import com.vaadin.ui.TabSheet; +import com.vaadin.ui.TabSheet.Tab; + +/** + * In case a selected tab is removed the new selected one should be a neighbor. + * + * In case an unselected tab is removed and the selected one is not visible, the + * scroll should not jump to the selected one. + * + * @since + * @author Vaadin Ltd + */ +public class NewSelectionAfterTabRemove extends AbstractTestUI { + + @Override + protected void setup(VaadinRequest request) { + TabSheet tabSheet = new TabSheet(); + + for (int i = 0; i < 20; i++) { + + String caption = "Tab " + i; + Label label = new Label(caption); + + Tab tab = tabSheet.addTab(label, caption); + tab.setClosable(true); + } + + addComponent(tabSheet); + } + + @Override + protected String getTestDescription() { + return "When a selected tab is removed, its neighbor should become selected."; + } + + @Override + protected Integer getTicketNumber() { + return 6876; + } + +} diff --git a/uitest/src/com/vaadin/tests/components/tabsheet/NewSelectionAfterTabRemoveTest.java b/uitest/src/com/vaadin/tests/components/tabsheet/NewSelectionAfterTabRemoveTest.java new file mode 100644 index 0000000000..bffbc3ecdf --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/tabsheet/NewSelectionAfterTabRemoveTest.java @@ -0,0 +1,121 @@ +/* + * 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.tabsheet; + +import java.io.IOException; +import java.util.List; + +import org.junit.Assert; +import org.junit.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.WebElement; + +import com.vaadin.testbench.TestBenchElement; +import com.vaadin.tests.tb3.MultiBrowserTest; + +/** + * Automatic test of the default TabSheet selection algorithm when removing a + * selected tab. + * + * @since + * @author Vaadin Ltd + */ +public class NewSelectionAfterTabRemoveTest extends MultiBrowserTest { + + @Test + public void testSelection() throws IOException, InterruptedException { + openTestURL(); + + while (scrollRight()) { + } + + selectAndClose(tab(19)); + + Assert.assertTrue("Tab 18 selected", isTabSelected(tab(18))); + + selectAndClose(tab(16)); + + Assert.assertTrue("Tab 17 selected", isTabSelected(tab(17))); + } + + /* + * Select the specified tab and close it. + */ + private void selectAndClose(TestBenchElement tab) + throws InterruptedException { + tab.click(5, 5); + + sleep(10); + + tabClose(tab).click(2, 2); + + sleep(10); + } + + /* + * Gets the selected state of the specified tab. + */ + private boolean isTabSelected(TestBenchElement tab) { + return tab.getAttribute("class").contains( + "v-tabsheet-tabitemcell-selected") + && tab.getAttribute("class").contains( + "v-tabsheet-tabitemcell-focus"); + } + + /* + * Scroll the tabsheet bar to the right. + */ + private boolean scrollRight() { + List<WebElement> scrollElements = getDriver().findElements( + By.className("v-tabsheet-scrollerNext")); + if (!scrollElements.isEmpty()) { + TestBenchElement rightScrollElement = (TestBenchElement) scrollElements + .get(0); + rightScrollElement.click(5, 5); + return true; + } else { + return false; + } + } + + /* + * Provide the tab close button for the specified tab. + */ + private TestBenchElement tabClose(TestBenchElement tab) { + return (TestBenchElement) tab.findElement(By + .className("v-tabsheet-caption-close")); + } + + /* + * Provide the tab at specified index. + */ + private TestBenchElement tab(int index) { + By by = By.className("v-tabsheet-tabitemcell"); + + List<WebElement> tabs = getDriver().findElements(by); + + String expected = "Tab " + index; + + for (WebElement tab : tabs) { + if (tab.getText().startsWith(expected)) { + return (TestBenchElement) tab; + } + } + + return null; + } + +} diff --git a/uitest/src/com/vaadin/tests/extensions/JavascriptManagerTest.java b/uitest/src/com/vaadin/tests/extensions/JavascriptManagerTest.java index b89e16d755..4807bb9029 100644 --- a/uitest/src/com/vaadin/tests/extensions/JavascriptManagerTest.java +++ b/uitest/src/com/vaadin/tests/extensions/JavascriptManagerTest.java @@ -16,16 +16,15 @@ package com.vaadin.tests.extensions; -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; - import com.vaadin.server.VaadinRequest; import com.vaadin.tests.components.AbstractTestUI; import com.vaadin.tests.util.Log; import com.vaadin.ui.JavaScript; import com.vaadin.ui.JavaScriptFunction; +import elemental.json.JsonArray; +import elemental.json.JsonNull; + public class JavascriptManagerTest extends AbstractTestUI { private Log log = new Log(5); @@ -36,14 +35,14 @@ public class JavascriptManagerTest extends AbstractTestUI { final JavaScript js = JavaScript.getCurrent(); js.addFunction("testing.doTest", new JavaScriptFunction() { @Override - public void call(JSONArray arguments) throws JSONException { + public void call(JsonArray arguments) { log.log("Got " + arguments.length() + " arguments"); - log.log("Argument 1 as a number: " + arguments.getInt(0)); + log.log("Argument 1 as a number: " + (int) arguments.getNumber(0)); log.log("Argument 2 as a string: " + arguments.getString(1)); log.log("Argument 3.p as a boolean: " - + arguments.getJSONObject(2).getBoolean("p")); + + arguments.getObject(2).getBoolean("p")); log.log("Argument 4 is JSONObject.NULL: " - + (arguments.get(3) == JSONObject.NULL)); + + (arguments.get(3) instanceof JsonNull)); js.removeFunction("testing.doTest"); } }); diff --git a/uitest/src/com/vaadin/tests/extensions/SimpleJavaScriptExtensionTest.java b/uitest/src/com/vaadin/tests/extensions/SimpleJavaScriptExtensionTest.java index d3e0edf04c..6f14fb301c 100644 --- a/uitest/src/com/vaadin/tests/extensions/SimpleJavaScriptExtensionTest.java +++ b/uitest/src/com/vaadin/tests/extensions/SimpleJavaScriptExtensionTest.java @@ -16,9 +16,6 @@ package com.vaadin.tests.extensions; -import org.json.JSONArray; -import org.json.JSONException; - import com.vaadin.annotations.JavaScript; import com.vaadin.annotations.StyleSheet; import com.vaadin.server.AbstractJavaScriptExtension; @@ -31,6 +28,7 @@ import com.vaadin.ui.Button; import com.vaadin.ui.Button.ClickEvent; import com.vaadin.ui.JavaScriptFunction; import com.vaadin.ui.Notification; +import elemental.json.JsonArray; public class SimpleJavaScriptExtensionTest extends AbstractTestUI { @@ -71,7 +69,7 @@ public class SimpleJavaScriptExtensionTest extends AbstractTestUI { }); addFunction("greetToServer", new JavaScriptFunction() { @Override - public void call(JSONArray arguments) throws JSONException { + public void call(JsonArray arguments) { Notification.show(getState().getPrefix() + arguments.getString(0)); } diff --git a/uitest/src/com/vaadin/tests/layouts/TestLayoutClickListeners.html b/uitest/src/com/vaadin/tests/layouts/TestLayoutClickListeners.html deleted file mode 100644 index 496994a60c..0000000000 --- a/uitest/src/com/vaadin/tests/layouts/TestLayoutClickListeners.html +++ /dev/null @@ -1,239 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> -<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> -<head profile="http://selenium-ide.openqa.org/profiles/test-case"> -<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> -<link rel="selenium.base" href="" /> -<title>TestLayoutClickListeners</title> -</head> -<body> -<table cellpadding="1" cellspacing="1" border="1"> -<thead> -<tr><td rowspan="1" colspan="3">TestLayoutClickListeners</td></tr> -</thead><tbody> -<tr> - <td>open</td> - <td>/run/com.vaadin.tests.layouts.TestLayoutClickListeners?restartApplication</td> - <td></td> -</tr> -<tr> - <td>screenCapture</td> - <td></td> - <td>initial</td> -</tr> -<!--GridLayout--> -<tr> - <td>mouseClick</td> - <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[1]/VHorizontalLayout[0]/ChildComponentContainer[0]/VVerticalLayout[0]/ChildComponentContainer[1]/VGridLayout[0]/AbsolutePanel[0]/ChildComponentContainer[0]/VLabel[0]</td> - <td>43,11</td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[0]/VVerticalLayout[0]/ChildComponentContainer[0]/VLabel[0]</td> - <td>exact:GridLayout: left click on This is label 1</td> -</tr> -<tr> - <td>mouseClick</td> - <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[1]/VHorizontalLayout[0]/ChildComponentContainer[0]/VVerticalLayout[0]/ChildComponentContainer[1]/VGridLayout[0]/AbsolutePanel[0]/ChildComponentContainer[4]/VTextField[0]</td> - <td>82,14</td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[0]/VVerticalLayout[0]/ChildComponentContainer[0]/VLabel[0]</td> - <td>exact:GridLayout: left click on This is tf5</td> -</tr> -<tr> - <td>mouseClick</td> - <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/VOrderedLayout$Slot[1]/VHorizontalLayout[0]/VOrderedLayout$Slot[0]/VVerticalLayout[0]/VOrderedLayout$Slot[1]/VGridLayout[0]</td> - <td>130,41</td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[0]/VVerticalLayout[0]/ChildComponentContainer[0]/VLabel[0]</td> - <td>exact:GridLayout: left click on <none></td> -</tr> -<!--VerticalLayout--> -<tr> - <td>mouseClick</td> - <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[1]/VHorizontalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[5]/VTextField[0]</td> - <td>74,13</td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[0]/VVerticalLayout[0]/ChildComponentContainer[0]/VLabel[0]</td> - <td>exact:VerticalLayout: left click on This is tf6</td> -</tr> -<tr> - <td>mouseClick</td> - <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[1]/VHorizontalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[2]/VLabel[0]</td> - <td>53,13</td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[0]/VVerticalLayout[0]/ChildComponentContainer[0]/VLabel[0]</td> - <td>exact:VerticalLayout: left click on This is label 3</td> -</tr> -<!--AbsoluteLayout--> -<tr> - <td>click</td> - <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[1]/VHorizontalLayout[0]/ChildComponentContainer[2]/VAbsoluteLayout[0]/VAbsoluteLayout$AbsoluteWrapper[2]/VButton[0]/domChild[0]/domChild[0]</td> - <td></td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[0]/VVerticalLayout[0]/ChildComponentContainer[0]/VLabel[0]</td> - <td>exact:Button A button with its own click listener was clicked</td> -</tr> -<tr> - <td>mouseClick</td> - <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[1]/VHorizontalLayout[0]/ChildComponentContainer[2]/VAbsoluteLayout[0]/VAbsoluteLayout$AbsoluteWrapper[0]/VTextField[0]</td> - <td>101,14</td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[0]/VVerticalLayout[0]/ChildComponentContainer[0]/VLabel[0]</td> - <td>exact:AbsoluteLayout: left click on This is its caption</td> -</tr> -<!--CssLayout--> -<tr> - <td>mouseClick</td> - <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[1]/VHorizontalLayout[0]/ChildComponentContainer[3]/VCssLayout[0]/VCssLayout$FlowPane[0]/VTextField[0]</td> - <td>108,13</td> -</tr> -<tr> - <td>mouseClick</td> - <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/VOrderedLayout$Slot[1]/VHorizontalLayout[0]/VOrderedLayout$Slot[3]/VCssLayout[0]/domChild[0]/domChild[0]</td> - <td>41,7</td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::PID_SLog_row_1</td> - <td>exact:CSSLayout: left click on This is its caption</td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::PID_SLog_row_0</td> - <td>exact:CSSLayout: left click on This is its caption</td> -</tr> -<tr> - <td>click</td> - <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[1]/VHorizontalLayout[0]/ChildComponentContainer[3]/VCssLayout[0]/VCssLayout$FlowPane[0]/VButton[0]/domChild[0]/domChild[0]</td> - <td></td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::PID_SLog_row_0</td> - <td>exact:Button A button with its own click listener was clicked</td> -</tr> -<!--Drag in GridLayout--> -<tr> - <td>drag</td> - <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[1]/VHorizontalLayout[0]/ChildComponentContainer[0]/VVerticalLayout[0]/ChildComponentContainer[1]/VGridLayout[0]/AbsolutePanel[0]/ChildComponentContainer[0]/VLabel[0]</td> - <td>40,8</td> -</tr> -<tr> - <td>drop</td> - <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[1]/VHorizontalLayout[0]/ChildComponentContainer[0]/VVerticalLayout[0]/ChildComponentContainer[1]/VGridLayout[0]/AbsolutePanel[0]/ChildComponentContainer[0]/VLabel[0]</td> - <td>40,8</td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::PID_SLog_row_0</td> - <td>exact:GridLayout: left click on This is label 1</td> -</tr> -<tr> - <td>drag</td> - <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[1]/VHorizontalLayout[0]/ChildComponentContainer[0]/VVerticalLayout[0]/ChildComponentContainer[1]/VGridLayout[0]/AbsolutePanel[0]/ChildComponentContainer[0]/VLabel[0]</td> - <td>24,7</td> -</tr> -<tr> - <td>drop</td> - <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[1]/VHorizontalLayout[0]/ChildComponentContainer[0]/VVerticalLayout[0]/ChildComponentContainer[1]/VGridLayout[0]/AbsolutePanel[0]/ChildComponentContainer[4]/VTextField[0]</td> - <td>46,13</td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::PID_SLog_row_0</td> - <td>exact:GridLayout: left click on This is label 1</td> -</tr> -<!--Drag in VerticalLayout--> -<tr> - <td>drag</td> - <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[1]/VHorizontalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[4]/VTextField[0]</td> - <td>25,9</td> -</tr> -<tr> - <td>drop</td> - <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[1]/VHorizontalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[4]/VTextField[0]</td> - <td>25,9</td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::PID_SLog_row_0</td> - <td>exact:VerticalLayout: left click on This is tf5</td> -</tr> -<tr> - <td>drag</td> - <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[1]/VHorizontalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/domChild[8]/domChild[0]</td> - <td>28,11</td> -</tr> -<tr> - <td>drop</td> - <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[1]/VHorizontalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[8]/VTextField[0]</td> - <td>39,7</td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::PID_SLog_row_0</td> - <td>exact:VerticalLayout: left click on This is tf5</td> -</tr> -<!--Drag in AbsoluteLayout--> -<tr> - <td>drag</td> - <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/VOrderedLayout$Slot[1]/VHorizontalLayout[0]/VOrderedLayout$Slot[2]/VAbsoluteLayout[0]/domChild[0]/domChild[0]/domChild[3]/domChild[0]</td> - <td>21,9</td> -</tr> -<tr> - <td>drop</td> - <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/VOrderedLayout$Slot[1]/VHorizontalLayout[0]/VOrderedLayout$Slot[2]/VAbsoluteLayout[0]/domChild[0]/domChild[0]/domChild[3]/domChild[0]</td> - <td>21,9</td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::PID_SLog_row_0</td> - <td>exact:AbsoluteLayout: left click on This is its caption</td> -</tr> -<tr> - <td>drag</td> - <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[1]/VHorizontalLayout[0]/ChildComponentContainer[2]/VAbsoluteLayout[0]/VAbsoluteLayout$AbsoluteWrapper[0]/VTextField[0]</td> - <td>54,7</td> -</tr> -<tr> - <td>drop</td> - <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[1]/VHorizontalLayout[0]/ChildComponentContainer[2]/VAbsoluteLayout[0]/VAbsoluteLayout$AbsoluteWrapper[1]/VTextField[0]</td> - <td>52,10</td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::PID_SLog_row_0</td> - <td>exact:AbsoluteLayout: left click on This is its caption</td> -</tr> -<!--Drag in CSSLayout--> -<tr> - <td>drag</td> - <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[1]/VHorizontalLayout[0]/ChildComponentContainer[3]/VCssLayout[0]/VCssLayout$FlowPane[0]/VTextField[0]</td> - <td>51,7</td> -</tr> -<tr> - <td>drop</td> - <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[1]/VHorizontalLayout[0]/ChildComponentContainer[3]/VCssLayout[0]/VCssLayout$FlowPane[0]/VTextField[0]</td> - <td>51,7</td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::PID_SLog_row_0</td> - <td>exact:CSSLayout: left click on This is its caption</td> -</tr> -</tbody></table> -</body> -</html> diff --git a/uitest/src/com/vaadin/tests/layouts/TestLayoutClickListeners.java b/uitest/src/com/vaadin/tests/layouts/TestLayoutClickListeners.java index c29e7710b7..22a37022c2 100644 --- a/uitest/src/com/vaadin/tests/layouts/TestLayoutClickListeners.java +++ b/uitest/src/com/vaadin/tests/layouts/TestLayoutClickListeners.java @@ -2,8 +2,8 @@ package com.vaadin.tests.layouts; import com.vaadin.event.LayoutEvents.LayoutClickEvent; import com.vaadin.event.LayoutEvents.LayoutClickListener; -import com.vaadin.tests.components.AbstractTestCase; -import com.vaadin.tests.util.Log; +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUIWithLog; import com.vaadin.ui.AbsoluteLayout; import com.vaadin.ui.Button; import com.vaadin.ui.Component; @@ -12,36 +12,22 @@ import com.vaadin.ui.GridLayout; import com.vaadin.ui.HorizontalLayout; import com.vaadin.ui.Label; import com.vaadin.ui.Layout; -import com.vaadin.ui.LegacyWindow; import com.vaadin.ui.TextArea; import com.vaadin.ui.TextField; import com.vaadin.ui.VerticalLayout; -public class TestLayoutClickListeners extends AbstractTestCase { - - private Log log = new Log(5).setNumberLogRows(false); +public class TestLayoutClickListeners extends AbstractTestUIWithLog { @Override - public void init() { - LegacyWindow w = new LegacyWindow("main window"); - setMainWindow(w); - setTheme("tests-tickets"); - + protected void setup(VaadinRequest request) { HorizontalLayout layoutsLayout = new HorizontalLayout(); layoutsLayout.setSpacing(true); - w.setContent(layoutsLayout); + addComponent(layoutsLayout); layoutsLayout.addComponent(createClickableGridLayout()); layoutsLayout.addComponent(createClickableVerticalLayout()); layoutsLayout.addComponent(createClickableAbsoluteLayout()); layoutsLayout.addComponent(createClickableCSSLayout()); - - VerticalLayout mainLayout = new VerticalLayout(); - mainLayout.setMargin(true); - mainLayout.setSpacing(true); - w.setContent(mainLayout); - mainLayout.addComponent(log); - mainLayout.addComponent(layoutsLayout); } private Component createClickableAbsoluteLayout() { @@ -62,12 +48,12 @@ public class TestLayoutClickListeners extends AbstractTestCase { @Override public void buttonClick( com.vaadin.ui.Button.ClickEvent event) { - log.log("Button " + event.getButton().getCaption() + log("Button " + event.getButton().getCaption() + " was clicked"); } })); - al.addListener(new LayoutClickListener() { + al.addLayoutClickListener(new LayoutClickListener() { @Override public void layoutClick(LayoutClickEvent event) { @@ -96,12 +82,12 @@ public class TestLayoutClickListeners extends AbstractTestCase { @Override public void buttonClick( com.vaadin.ui.Button.ClickEvent event) { - log.log("Button " + event.getButton().getCaption() + log("Button " + event.getButton().getCaption() + " was clicked"); } })); - cl.addListener(new LayoutClickListener() { + cl.addLayoutClickListener(new LayoutClickListener() { @Override public void layoutClick(LayoutClickEvent event) { @@ -120,13 +106,14 @@ public class TestLayoutClickListeners extends AbstractTestCase { gl.setWidth("564px"); gl.setStyleName("borders"); gl.setSpacing(true); + gl.setHideEmptyRowsAndColumns(true); addContent(gl, 4); TextArea largeTextarea = new TextArea("Large textarea"); largeTextarea.setWidth("100%"); largeTextarea.setHeight("99%"); gl.addComponent(largeTextarea, 0, 3, 3, 3); - gl.addListener(new LayoutClickListener() { + gl.addLayoutClickListener(new LayoutClickListener() { @Override public void layoutClick(LayoutClickEvent event) { @@ -151,10 +138,7 @@ public class TestLayoutClickListeners extends AbstractTestCase { if (event.isDoubleClick()) { type = "double-click"; } - log.log(layout + ": " + button + " " + type + " on " + target); - // + ", coordinates relative to the layout (" - // + event.getRelativeX() + ", " + event.getRelativeY() + ")"); - + log(layout + ": " + button + " " + type + " on " + target); } private Layout createClickableVerticalLayout() { @@ -162,7 +146,7 @@ public class TestLayoutClickListeners extends AbstractTestCase { VerticalLayout gl = new VerticalLayout(); addContent(gl, 5); - gl.addListener(new LayoutClickListener() { + gl.addLayoutClickListener(new LayoutClickListener() { @Override public void layoutClick(LayoutClickEvent event) { @@ -196,7 +180,7 @@ public class TestLayoutClickListeners extends AbstractTestCase { } @Override - protected String getDescription() { + protected String getTestDescription() { return "All layouts have click listeners attached and the events are shown in the event log at the top"; } @@ -204,5 +188,4 @@ public class TestLayoutClickListeners extends AbstractTestCase { protected Integer getTicketNumber() { return 3541; } - } diff --git a/uitest/src/com/vaadin/tests/layouts/TestLayoutClickListenersTest.java b/uitest/src/com/vaadin/tests/layouts/TestLayoutClickListenersTest.java new file mode 100644 index 0000000000..0c6b5cbff4 --- /dev/null +++ b/uitest/src/com/vaadin/tests/layouts/TestLayoutClickListenersTest.java @@ -0,0 +1,200 @@ +/* + * 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.layouts; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.openqa.selenium.interactions.Actions; + +import com.vaadin.testbench.elements.AbsoluteLayoutElement; +import com.vaadin.testbench.elements.ButtonElement; +import com.vaadin.testbench.elements.CssLayoutElement; +import com.vaadin.testbench.elements.GridLayoutElement; +import com.vaadin.testbench.elements.LabelElement; +import com.vaadin.testbench.elements.TextFieldElement; +import com.vaadin.testbench.elements.VerticalLayoutElement; +import com.vaadin.tests.tb3.MultiBrowserTest; + +/** + * Tests LayoutClickListener on different layouts. + * + * @since + * @author Vaadin Ltd + */ +public class TestLayoutClickListenersTest extends MultiBrowserTest { + + @Before + public void before() { + openTestURL(); + } + + @Test + public void clickInGridLayout() { + GridLayoutElement layout = $(GridLayoutElement.class).first(); + + // click on a label + layout.$(LabelElement.class).first().click(); + assertLogText("GridLayout 1st child clicked", + "1. GridLayout: left click on This is label 1"); + + // click on a text field + layout.$(TextFieldElement.class).get(1).click(); + assertLogText("GridLayout 5th child clicked", + "2. GridLayout: left click on This is tf5"); + + // click on the layout body (not any component inside the layout) + layout.click(130, 41); + assertLogText("GridLayout body clicked", + "3. GridLayout: left click on <none>"); + } + + @Test + public void clickInVerticalLayout() { + VerticalLayoutElement layout = $(VerticalLayoutElement.class).get(4); + + // click on a text field + layout.$(TextFieldElement.class).get(1).click(); + assertLogText("VerticalLayout 6th child clicked", + "1. VerticalLayout: left click on This is tf6"); + + // click on a label + layout.$(LabelElement.class).get(3).click(); + assertLogText("VerticalLayout 4th child clicked", + "2. VerticalLayout: left click on This is label 3"); + } + + @Test + public void clickInAbsoluteLayout() { + AbsoluteLayoutElement layout = $(AbsoluteLayoutElement.class).first(); + + // click on a button that has its own ClickListener (should be ignored + // by the LayoutClickListener) + layout.$(ButtonElement.class).first().click(); + assertLogText("A button with a ClickListener clicked", + "1. Button A button with its own click listener was clicked"); + + // click on a text field's caption + layout.$(TextFieldElement.class).first().click(); + assertLogText("AbsoluteLayout 1st child was clicked", + "2. AbsoluteLayout: left click on This is its caption"); + } + + @Test + public void clickInCSSLayout() { + CssLayoutElement layout = $(CssLayoutElement.class).first(); + + // click on a text field's caption + layout.$(TextFieldElement.class).first().click(); + assertLogText("CSSLayout 1st child clicked", + "1. CSSLayout: left click on This is its caption"); + + // click on a button that has its own ClickListener (should be ignored + // by the LayoutClickListener) + layout.$(ButtonElement.class).first().click(); + assertLogText("Abutton with a ClickListener was clicked", + "2. Button A button with its own click listener was clicked"); + } + + @Test + public void dragInGridLayout() { + GridLayoutElement layout = $(GridLayoutElement.class).first(); + + // Drag inside the first label in this layout + new Actions(getDriver()) + .moveToElement(layout.$(LabelElement.class).first(), 40, 8) + .clickAndHold().moveByOffset(-20, 0).release().perform(); + assertLogText("Mouse dragged in GridLayout", + "1. GridLayout: left click on This is label 1"); + + // Drag from the third label to a text field in this layout + new Actions(getDriver()) + .moveToElement(layout.$(LabelElement.class).first(), 40, 8) + .clickAndHold() + .moveToElement(layout.$(TextFieldElement.class).get(3), 46, 33) + .release().perform(); + assertLogText("Expected the drag to be ignored between elements", + "1. GridLayout: left click on This is label 1"); + } + + @Test + public void dragInVerticalLayout() { + VerticalLayoutElement layout = $(VerticalLayoutElement.class).get(4); + + // Drag inside the first text field + new Actions(getDriver()) + .moveToElement(layout.$(TextFieldElement.class).first(), 25, 9) + .clickAndHold().moveByOffset(-20, 0).release().perform(); + assertLogText("Mouse dragged in VerticalLayout", + "1. VerticalLayout: left click on This is tf5"); + + // Drag from a caption to its text field + new Actions(getDriver()) + .moveToElement(layout.$(TextFieldElement.class).get(4), 28, 11) + .clickAndHold() + .moveToElement(layout.$(TextFieldElement.class).get(4), 39, 30) + .release().perform(); + assertLogText("Expected the drag to be ignored between elements", + "1. VerticalLayout: left click on This is tf5"); + } + + @Test + public void dragInAbsoluteLayout() { + AbsoluteLayoutElement layout = $(AbsoluteLayoutElement.class).first(); + + // Drag inside the first text field's caption + new Actions(getDriver()) + .moveToElement(layout.$(TextFieldElement.class).first(), 21, 9) + .clickAndHold().moveByOffset(-10, 0).release().perform(); + assertLogText("Mouse dragged in AbsoluteLayout", + "1. AbsoluteLayout: left click on This is its caption"); + + // Drag from a text field to another text field + new Actions(getDriver()) + .moveToElement(layout.$(TextFieldElement.class).get(1), 54, 7) + .clickAndHold() + .moveToElement(layout.$(TextFieldElement.class).first(), 52, 10) + .release().perform(); + assertLogText("Expected the drag to be ignored between elements", + "1. AbsoluteLayout: left click on This is its caption"); + } + + @Test + public void dragInCSSLayout() { + CssLayoutElement layout = $(CssLayoutElement.class).first(); + + // Drag inside the first text field's caption + new Actions(getDriver()) + .moveToElement(layout.$(TextFieldElement.class).first(), 51, 7) + .clickAndHold().moveByOffset(-20, 0).release().perform(); + assertLogText("Mouse dragged in CSSLayout", + "1. CSSLayout: left click on This is its caption"); + + // Drag from the first text field to the second text field + new Actions(getDriver()) + .moveToElement(layout.$(TextFieldElement.class).first(), 51, 27) + .clickAndHold() + .moveToElement(layout.$(TextFieldElement.class).get(1), 51, 27) + .release().perform(); + assertLogText("Expected the drag to be ignored between elements", + "1. CSSLayout: left click on This is its caption"); + } + + private void assertLogText(String message, String expected) { + String actual = $(LabelElement.class).first().getText(); + Assert.assertEquals(message, expected, actual); + } +} diff --git a/uitest/src/com/vaadin/tests/minitutorials/v7a3/Flot.java b/uitest/src/com/vaadin/tests/minitutorials/v7a3/Flot.java index f4aca81ffa..86666b12e8 100644 --- a/uitest/src/com/vaadin/tests/minitutorials/v7a3/Flot.java +++ b/uitest/src/com/vaadin/tests/minitutorials/v7a3/Flot.java @@ -20,13 +20,11 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import org.json.JSONArray; -import org.json.JSONException; - import com.vaadin.annotations.JavaScript; import com.vaadin.ui.AbstractJavaScriptComponent; import com.vaadin.ui.JavaScriptFunction; import com.vaadin.ui.Notification; +import elemental.json.JsonArray; @JavaScript({ "https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js", @@ -42,9 +40,9 @@ public class Flot extends AbstractJavaScriptComponent { }); addFunction("onPlotClick", new JavaScriptFunction() { @Override - public void call(JSONArray arguments) throws JSONException { - int seriesIndex = arguments.getInt(0); - int dataIndex = arguments.getInt(1); + public void call(JsonArray arguments) { + int seriesIndex = (int) arguments.getNumber(0); + int dataIndex = (int) arguments.getNumber(1); Notification.show("Clicked on [" + seriesIndex + ", " + dataIndex + "]"); } diff --git a/uitest/src/com/vaadin/tests/minitutorials/v7a3/JSAPIUI.java b/uitest/src/com/vaadin/tests/minitutorials/v7a3/JSAPIUI.java index 8f1eda6816..e98fe6d066 100644 --- a/uitest/src/com/vaadin/tests/minitutorials/v7a3/JSAPIUI.java +++ b/uitest/src/com/vaadin/tests/minitutorials/v7a3/JSAPIUI.java @@ -1,8 +1,5 @@ package com.vaadin.tests.minitutorials.v7a3; -import org.json.JSONArray; -import org.json.JSONException; - import com.vaadin.server.ExternalResource; import com.vaadin.server.VaadinRequest; import com.vaadin.ui.JavaScript; @@ -12,6 +9,9 @@ import com.vaadin.ui.Notification; import com.vaadin.ui.Notification.Type; import com.vaadin.ui.UI; +import elemental.json.JsonArray; +import elemental.json.JsonException; + public class JSAPIUI extends UI { @Override public void init(VaadinRequest request) { @@ -19,7 +19,7 @@ public class JSAPIUI extends UI { JavaScript.getCurrent().addFunction("com.example.api.notify", new JavaScriptFunction() { @Override - public void call(JSONArray arguments) throws JSONException { + public void call(JsonArray arguments) { try { String caption = arguments.getString(0); if (arguments.length() == 1) { @@ -28,10 +28,10 @@ public class JSAPIUI extends UI { } else { // type should be in [1] Notification.show(caption, - Type.values()[arguments.getInt(1)]); + Type.values()[((int) arguments.getNumber(1))]); } - } catch (JSONException e) { + } catch (JsonException e) { // We'll log in the console, you might not want to JavaScript.getCurrent().execute( "console.error('" + e.getMessage() + "')"); diff --git a/uitest/src/com/vaadin/tests/push/TrackMessageSizeUI.java b/uitest/src/com/vaadin/tests/push/TrackMessageSizeUI.java index 6e2784f21d..e7a74775bf 100644 --- a/uitest/src/com/vaadin/tests/push/TrackMessageSizeUI.java +++ b/uitest/src/com/vaadin/tests/push/TrackMessageSizeUI.java @@ -23,8 +23,6 @@ import java.net.URL; import javax.servlet.ServletContext; import org.apache.commons.io.IOUtils; -import org.json.JSONArray; -import org.json.JSONException; import com.vaadin.annotations.JavaScript; import com.vaadin.server.VaadinRequest; @@ -32,6 +30,7 @@ import com.vaadin.server.VaadinService; import com.vaadin.server.VaadinServletService; import com.vaadin.tests.components.AbstractTestUIWithLog; import com.vaadin.ui.JavaScriptFunction; +import elemental.json.JsonArray; // Load vaadinPush.js so that jQueryVaadin is defined @JavaScript("vaadin://vaadinPush.debug.js") @@ -58,7 +57,7 @@ public class TrackMessageSizeUI extends AbstractTestUIWithLog { getPage().getJavaScript().addFunction("logToServer", new JavaScriptFunction() { @Override - public void call(JSONArray arguments) throws JSONException { + public void call(JsonArray arguments) { String message = arguments.getString(0); log(message); } diff --git a/uitest/src/com/vaadin/tests/serialization/SerializerTestTest.java b/uitest/src/com/vaadin/tests/serialization/SerializerTestTest.java index 47bb212347..dcba561599 100644 --- a/uitest/src/com/vaadin/tests/serialization/SerializerTestTest.java +++ b/uitest/src/com/vaadin/tests/serialization/SerializerTestTest.java @@ -86,9 +86,8 @@ public class SerializerTestTest extends MultiBrowserTest { getLogRow(logRow++)); Assert.assertEquals("state.floatArray: [57, 0, -12]", getLogRow(logRow++)); - Assert.assertEquals("state.floatObjectValue: 1.0000001", - getLogRow(logRow++)); - Assert.assertEquals("state.floatValue: 3.14159", getLogRow(logRow++)); + Assert.assertTrue(getLogRow(logRow++).startsWith("state.floatObjectValue: 1.0000001")); + Assert.assertTrue(getLogRow(logRow++).startsWith("state.floatValue: 3.14159")); Assert.assertEquals("state.longArray: [-57841235865, 57]", getLogRow(logRow++)); Assert.assertEquals("state.longObjectValue: 577431841360", diff --git a/uitest/src/com/vaadin/tests/tb3/AbstractTB3Test.java b/uitest/src/com/vaadin/tests/tb3/AbstractTB3Test.java index d2313a0709..1e1cbedbd6 100644 --- a/uitest/src/com/vaadin/tests/tb3/AbstractTB3Test.java +++ b/uitest/src/com/vaadin/tests/tb3/AbstractTB3Test.java @@ -30,13 +30,13 @@ import java.net.URL; import java.util.Collections; import java.util.List; +import elemental.json.JsonObject; +import elemental.json.impl.JsonUtil; import org.apache.commons.io.IOUtils; import org.apache.http.HttpHost; import org.apache.http.HttpResponse; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.message.BasicHttpEntityEnclosingRequest; -import org.json.JSONException; -import org.json.JSONObject; import org.junit.After; import org.junit.Before; import org.junit.runner.RunWith; @@ -1247,7 +1247,7 @@ public abstract class AbstractTB3Test extends TestBenchTestCase { BasicHttpEntityEnclosingRequest r = new BasicHttpEntityEnclosingRequest( "POST", sessionURL.toExternalForm()); HttpResponse response = client.execute(host, r); - JSONObject object = extractObject(response); + JsonObject object = extractObject(response); URL myURL = new URL(object.getString("proxyId")); if ((myURL.getHost() != null) && (myURL.getPort() != -1)) { return myURL.getHost(); @@ -1258,13 +1258,11 @@ public abstract class AbstractTB3Test extends TestBenchTestCase { return null; } - private static JSONObject extractObject(HttpResponse resp) - throws IOException, JSONException { + private static JsonObject extractObject(HttpResponse resp) throws IOException { InputStream contents = resp.getEntity().getContent(); StringWriter writer = new StringWriter(); IOUtils.copy(contents, writer, "UTF8"); - JSONObject objToReturn = new JSONObject(writer.toString()); - return objToReturn; + return JsonUtil.parse(writer.toString()); } } diff --git a/uitest/src/com/vaadin/tests/tb3/DndActionsTest.java b/uitest/src/com/vaadin/tests/tb3/DndActionsTest.java new file mode 100644 index 0000000000..e755a00a0d --- /dev/null +++ b/uitest/src/com/vaadin/tests/tb3/DndActionsTest.java @@ -0,0 +1,50 @@ +/* + * 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.tb3; + +import org.junit.Ignore; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.interactions.Actions; + +/** + * Base class for TestBench 3+ tests that use DnD. This class contains utility + * methods for DnD operations. + * + * @author Vaadin Ltd + */ +@Ignore +public abstract class DndActionsTest extends MultiBrowserTest { + + public void dragAndDrop(WebElement element, int xOffset, int yOffset) { + /* + * Selenium doesn't properly drag and drop items in IE8. It tries to + * start dragging an element from a position above the element itself. + */ + if (BrowserUtil.isIE8(getDesiredCapabilities())) { + Actions action = new Actions(getDriver()); + action.moveToElement(element); + action.moveByOffset(0, 1); + action.clickAndHold(); + action.moveByOffset(xOffset, yOffset); + action.release(); + action.build().perform(); + } else { + Actions action = new Actions(getDriver()); + action.dragAndDropBy(element, xOffset, yOffset); + action.build().perform(); + } + } +} diff --git a/uitest/src/com/vaadin/tests/themes/valo/ValoThemeUI.java b/uitest/src/com/vaadin/tests/themes/valo/ValoThemeUI.java index 62d76569dd..f30cec76cc 100644 --- a/uitest/src/com/vaadin/tests/themes/valo/ValoThemeUI.java +++ b/uitest/src/com/vaadin/tests/themes/valo/ValoThemeUI.java @@ -175,6 +175,7 @@ public class ValoThemeUI extends UI { break; } } + menu.removeStyleName("valo-menu-visible"); } }); diff --git a/uitest/src/com/vaadin/tests/themes/valo/ValoThemeUITest.java b/uitest/src/com/vaadin/tests/themes/valo/ValoThemeUITest.java index b5b7e16b34..71f770ab8f 100644 --- a/uitest/src/com/vaadin/tests/themes/valo/ValoThemeUITest.java +++ b/uitest/src/com/vaadin/tests/themes/valo/ValoThemeUITest.java @@ -276,6 +276,9 @@ public class ValoThemeUITest extends MultiBrowserTest { + getRemoteControlName()); open(link, caption, tries - 1); + } else { + // Done opening, scroll left panel to the top again for consistency + scrollTo(0, 0); } } |