diff options
author | Artur Signell <artur@vaadin.com> | 2013-03-21 08:59:51 +0200 |
---|---|---|
committer | Artur Signell <artur@vaadin.com> | 2013-03-21 08:59:51 +0200 |
commit | bd3bb24a36a0ad02ffb9cee2e46afc445a354191 (patch) | |
tree | 00d9248c84f8b7b60768552c822279c9cf151f45 | |
parent | 320b4e3776976e5dad822f01542f338cf76140bb (diff) | |
parent | e4c9eda51082a443822b66864df2fe14be7dc6d7 (diff) | |
download | vaadin-framework-bd3bb24a36a0ad02ffb9cee2e46afc445a354191.tar.gz vaadin-framework-bd3bb24a36a0ad02ffb9cee2e46afc445a354191.zip |
Merge commit 'e4c9eda51082a443822b66864df2fe14be7dc6d7'
Conflicts:
uitest/test.xml
Change-Id: I2c82fa7117b21bddad313abdd2f3f43143317c12
46 files changed, 1798 insertions, 376 deletions
diff --git a/WebContent/VAADIN/vaadinBootstrap.js b/WebContent/VAADIN/vaadinBootstrap.js index f5c00a0b65..40f9ce470f 100644 --- a/WebContent/VAADIN/vaadinBootstrap.js +++ b/WebContent/VAADIN/vaadinBootstrap.js @@ -55,19 +55,45 @@ pendingApps: [] }; }; - + + var isInitializedInDom = function(appId) { + var appDiv = document.getElementById(appId); + if (!appDiv) { + return false; + } + for ( var i = 0; i < appDiv.childElementCount; i++) { + var className = appDiv.childNodes[i].className; + // If the app div contains a child with the class + // "v-app-loading" we have only received the HTML + // but not yet started the widget set + // (UIConnector removes the v-app-loading div). + if (className && className.contains("v-app-loading")) { + return false; + } + } + return true; + }; + window.vaadin = window.vaadin || { initApplication: function(appId, config) { + var testbenchId = appId.replace(/-\d+$/, ''); + if (apps[appId]) { - throw "Application " + appId + " already initialized"; + if (window.vaadin && window.vaadin.clients && window.vaadin.clients[testbenchId] && window.vaadin.clients[testbenchId].initializing) { + throw "Application " + appId + " is already being initialized"; + } + if (isInitializedInDom(appId)) { + throw "Application " + appId + " already initialized"; + } } + log("init application", appId, config); - var testbenchId = appId.replace(/-\d+$/, ''); window.vaadin.clients[testbenchId] = { isActive: function() { return true; - } + }, + initializing: true }; var getConfig = function(name) { diff --git a/WebContent/release-notes.html b/WebContent/release-notes.html index 39b6652532..0f49e819b0 100644 --- a/WebContent/release-notes.html +++ b/WebContent/release-notes.html @@ -658,12 +658,12 @@ </p> <ul> - <li>Mozilla Firefox 18</li> + <li>Mozilla Firefox 18-19</li> <li>Mozilla Firefox 17 ESR</li> <li>Internet Explorer 8-10</li> <li>Safari 6</li> <li>Opera 12</li> - <li>Google Chrome 23</li> + <li>Google Chrome 23-25</li> </ul> <p> diff --git a/client/src/com/vaadin/client/ApplicationConnection.java b/client/src/com/vaadin/client/ApplicationConnection.java index 62827feffb..4ddbd7c39b 100644 --- a/client/src/com/vaadin/client/ApplicationConnection.java +++ b/client/src/com/vaadin/client/ApplicationConnection.java @@ -510,6 +510,7 @@ public class ApplicationConnection { client.getPathForElement = $entry(function(element) { return componentLocator.@com.vaadin.client.ComponentLocator::getPathForElement(Lcom/google/gwt/user/client/Element;)(element); }); + client.initializing = false; $wnd.vaadin.clients[TTAppId] = client; }-*/; diff --git a/client/src/com/vaadin/client/ui/AbstractComponentConnector.java b/client/src/com/vaadin/client/ui/AbstractComponentConnector.java index 694db6f02c..ecd6abae08 100644 --- a/client/src/com/vaadin/client/ui/AbstractComponentConnector.java +++ b/client/src/com/vaadin/client/ui/AbstractComponentConnector.java @@ -137,10 +137,19 @@ public abstract class AbstractComponentConnector extends AbstractConnector * implementation). */ Profiler.enter("AbstractComponentConnector.onStateChanged update tab index"); - if (getState() instanceof TabIndexState - && getWidget() instanceof Focusable) { - ((Focusable) getWidget()) - .setTabIndex(((TabIndexState) getState()).tabIndex); + if (getState() instanceof TabIndexState) { + if (getWidget() instanceof Focusable) { + ((Focusable) getWidget()) + .setTabIndex(((TabIndexState) getState()).tabIndex); + } else { + /* + * TODO Enable this error when all widgets have been fixed to + * properly support tabIndex, i.e. implement Focusable + */ + // VConsole.error("Tab index received for " + // + Util.getSimpleName(getWidget()) + // + " which does not implement Focusable"); + } } Profiler.leave("AbstractComponentConnector.onStateChanged update tab index"); diff --git a/client/src/com/vaadin/client/ui/FocusUtil.java b/client/src/com/vaadin/client/ui/FocusUtil.java new file mode 100644 index 0000000000..8de3f767bd --- /dev/null +++ b/client/src/com/vaadin/client/ui/FocusUtil.java @@ -0,0 +1,94 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.client.ui; + +import com.google.gwt.user.client.ui.Focusable; +import com.google.gwt.user.client.ui.Widget; + +/** + * A helper class used to make it easier for {@link Widget}s to implement + * {@link Focusable}. + * + * @author Vaadin Ltd + * @version @VERSION@ + * @since 7.0.3 + * + */ +public class FocusUtil { + + /** + * Sets the access key property + * + * @param focusable + * The widget for which we want to set the access key. + * @param key + * The access key to set + */ + public static void setAccessKey(Widget focusable, char key) { + assert (focusable != null && focusable.getElement() != null) : "Can't setAccessKey for a widget without an element"; + focusable.getElement().setPropertyString("accessKey", "" + key); + } + + /** + * Explicitly focus/unfocus the given widget. Only one widget can have focus + * at a time, and the widget that does will receive all keyboard events. + * + * @param focusable + * the widget to focus/unfocus + * @param focused + * whether this widget should take focus or release it + */ + public static void setFocus(Widget focusable, boolean focus) { + assert (focusable != null && focusable.getElement() != null) : "Can't setFocus for a widget without an element"; + + if (focus) { + focusable.getElement().focus(); + } else { + focusable.getElement().blur(); + } + } + + /** + * Sets the widget's position in the tab index. If more than one widget has + * the same tab index, each such widget will receive focus in an arbitrary + * order. Setting the tab index to <code>-1</code> will cause the widget to + * be removed from the tab order. + * + * @param focusable + * The widget + * @param tabIndex + * the widget's tab index + */ + public static void setTabIndex(Widget focusable, int tabIndex) { + assert (focusable != null && focusable.getElement() != null) : "Can't setTabIndex for a widget without an element"; + + focusable.getElement().setTabIndex(tabIndex); + } + + /** + * Gets the widget's position in the tab index. + * + * @param focusable + * The widget + * + * @return the widget's tab index + */ + public static int getTabIndex(Widget focusable) { + assert (focusable != null && focusable.getElement() != null) : "Can't getTabIndex for a widget without an element"; + + return focusable.getElement().getTabIndex(); + } +} diff --git a/client/src/com/vaadin/client/ui/MediaBaseConnector.java b/client/src/com/vaadin/client/ui/MediaBaseConnector.java index 6824caff78..8614977be1 100644 --- a/client/src/com/vaadin/client/ui/MediaBaseConnector.java +++ b/client/src/com/vaadin/client/ui/MediaBaseConnector.java @@ -46,15 +46,26 @@ public abstract class MediaBaseConnector extends AbstractComponentConnector { } @Override - public void onStateChanged(StateChangeEvent stateChangeEvent) { - super.onStateChanged(stateChangeEvent); + public void onStateChanged(StateChangeEvent event) { + super.onStateChanged(event); - for (int i = 0; i < getState().sources.size(); i++) { - URLReference source = getState().sources.get(i); - String sourceType = getState().sourceTypes.get(i); - getWidget().addSource(source.getURL(), sourceType); + final VMediaBase widget = getWidget(); + final AbstractMediaState state = getState(); + + setAltText(state.altText); // must do before loading sources + widget.setAutoplay(state.autoplay); + widget.setMuted(state.muted); + widget.setControls(state.showControls); + + if (event.hasPropertyChanged("sources")) { + widget.removeAllSources(); + for (int i = 0; i < state.sources.size(); i++) { + URLReference source = state.sources.get(i); + String sourceType = state.sourceTypes.get(i); + widget.addSource(source.getURL(), sourceType); + } + widget.load(); } - setAltText(getState().altText); } @Override diff --git a/client/src/com/vaadin/client/ui/VMediaBase.java b/client/src/com/vaadin/client/ui/VMediaBase.java index 8d40775c8d..b77e8bb161 100644 --- a/client/src/com/vaadin/client/ui/VMediaBase.java +++ b/client/src/com/vaadin/client/ui/VMediaBase.java @@ -18,12 +18,16 @@ package com.vaadin.client.ui; import com.google.gwt.dom.client.Document; import com.google.gwt.dom.client.MediaElement; +import com.google.gwt.dom.client.NodeList; +import com.google.gwt.dom.client.SourceElement; +import com.google.gwt.dom.client.Text; import com.google.gwt.user.client.Element; import com.google.gwt.user.client.ui.Widget; public abstract class VMediaBase extends Widget { private MediaElement media; + private Text altText; /** * Sets the MediaElement that is to receive all commands and properties. @@ -44,7 +48,12 @@ public abstract class VMediaBase extends Widget { } public void setAltText(String alt) { - media.appendChild(Document.get().createTextNode(alt)); + if (altText == null) { + altText = Document.get().createTextNode(alt); + media.appendChild(altText); + } else { + altText.setNodeValue(alt); + } } public void setControls(boolean shouldShowControls) { @@ -59,8 +68,21 @@ public abstract class VMediaBase extends Widget { media.setMuted(mediaMuted); } + public void removeAllSources() { + NodeList<com.google.gwt.dom.client.Element> l = media + .getElementsByTagName(SourceElement.TAG); + for (int i = l.getLength() - 1; i >= 0; i--) { + media.removeChild(l.getItem(i)); + } + + } + + public void load() { + media.load(); + } + public void addSource(String sourceUrl, String sourceType) { - Element src = Document.get().createElement("source").cast(); + Element src = Document.get().createElement(SourceElement.TAG).cast(); src.setAttribute("src", sourceUrl); src.setAttribute("type", sourceType); media.appendChild(src); diff --git a/client/src/com/vaadin/client/ui/VScrollTable.java b/client/src/com/vaadin/client/ui/VScrollTable.java index 6f9fd6da88..4d61fba429 100644 --- a/client/src/com/vaadin/client/ui/VScrollTable.java +++ b/client/src/com/vaadin/client/ui/VScrollTable.java @@ -3056,7 +3056,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets, .hasNext(); columnIndex++) { if (it.next() == this) { break; - } + } } } final int cw = scrollBody.getColWidth(columnIndex); @@ -3266,10 +3266,9 @@ public class VScrollTable extends FlowPanel implements HasWidgets, } if (col.hasAttribute("width")) { - final String widthStr = col.getStringAttribute("width"); // Make sure to accomodate for the sort indicator if // necessary. - int width = Integer.parseInt(widthStr); + int width = col.getIntAttribute("width"); int widthWithoutAddedIndent = width; // get min width with indent, no padding @@ -3301,12 +3300,25 @@ public class VScrollTable extends FlowPanel implements HasWidgets, // save min width without indent c.setWidth(widthWithoutAddedIndent, true); } + } else if (col.hasAttribute("er")) { + c.setExpandRatio(col.getFloatAttribute("er")); + } else if (recalcWidths) { c.setUndefinedWidth(); + + } else { + boolean hadExpandRatio = c.getExpandRatio() > 0; + boolean hadDefinedWidth = c.isDefinedWidth(); + if (hadExpandRatio || hadDefinedWidth) { + // Someone has removed a expand width or the defined + // width on the server side (setting it to -1), make the + // column undefined again and measure columns again. + c.setUndefinedWidth(); + c.setExpandRatio(0); + refreshContentWidths = true; + } } - if (col.hasAttribute("er")) { - c.setExpandRatio(col.getFloatAttribute("er")); - } + if (col.hasAttribute("collapsed")) { // ensure header is properly removed from parent (case when // collapsing happens via servers side api) diff --git a/client/src/com/vaadin/client/ui/VTextArea.java b/client/src/com/vaadin/client/ui/VTextArea.java index 6e93a076d9..45e0532451 100644 --- a/client/src/com/vaadin/client/ui/VTextArea.java +++ b/client/src/com/vaadin/client/ui/VTextArea.java @@ -18,6 +18,7 @@ package com.vaadin.client.ui; import com.google.gwt.core.client.Scheduler; import com.google.gwt.dom.client.Style.Overflow; +import com.google.gwt.dom.client.Style.WhiteSpace; import com.google.gwt.dom.client.TextAreaElement; import com.google.gwt.event.dom.client.ChangeEvent; import com.google.gwt.event.dom.client.ChangeHandler; @@ -62,6 +63,120 @@ public class VTextArea extends VTextField { getTextAreaElement().setRows(rows); } + @Override + public void setSelectionRange(int pos, int length) { + super.setSelectionRange(pos, length); + final String value = getValue(); + /* + * Align position to index inside string value + */ + int index = pos; + if (index < 0) { + index = 0; + } + if (index > value.length()) { + index = value.length(); + } + // Get pixels count required to scroll textarea vertically + int scrollTop = getScrollTop(value, index); + int scrollLeft = -1; + /* + * Check if textarea has wrap attribute set to "off". In the latter case + * horizontal scroll is also required. + */ + if (!isWordwrap()) { + // Get pixels count required to scroll textarea horizontally + scrollLeft = getScrollLeft(value, index); + } + // Set back original text if previous methods calls changed it + if (!isWordwrap() || index < value.length()) { + setValue(value, false); + } + /* + * Call original method to set cursor position. In most browsers it + * doesn't lead to scrolling. + */ + super.setSelectionRange(pos, length); + /* + * Align vertical scroll to middle of textarea view (height) if + * scrolling is reqiured at all. + */ + if (scrollTop > 0) { + scrollTop += getElement().getClientHeight() / 2; + } + /* + * Align horizontal scroll to middle of textarea view (widht) if + * scrolling is reqiured at all. + */ + if (scrollLeft > 0) { + scrollLeft += getElement().getClientWidth() / 2; + } + /* + * Scroll if computed scrollTop is greater than scroll after cursor + * setting + */ + if (getElement().getScrollTop() < scrollTop) { + getElement().setScrollTop(scrollTop); + } + /* + * Scroll if computed scrollLeft is greater than scroll after cursor + * setting + */ + if (getElement().getScrollLeft() < scrollLeft) { + getElement().setScrollLeft(scrollLeft); + } + } + + /* + * Get horizontal scroll value required to get position visible. Method is + * called only when text wrapping is off. There is need to scroll + * horizontally in case words are wrapped. + */ + private int getScrollLeft(String value, int index) { + String beginning = value.substring(0, index); + // Compute beginning of the current line + int begin = beginning.lastIndexOf('\n'); + String line = value.substring(begin + 1); + index = index - begin - 1; + if (index < line.length()) { + index++; + } + line = line.substring(0, index); + /* + * Now <code>line</code> contains current line up to index position + */ + setValue(line.trim(), false); // Set this line to the textarea. + /* + * Scroll textarea up to the end of the line (maximum possible + * horizontal scrolling value). Now the end line becomes visible. + */ + getElement().setScrollLeft(getElement().getScrollWidth()); + // Return resulting horizontal scrolling value. + return getElement().getScrollLeft(); + } + + /* + * Get vertical scroll value required to get position visible + */ + private int getScrollTop(String value, int index) { + /* + * Trim text after position and set this trimmed text if index is not + * very end. + */ + if (index < value.length()) { + String beginning = value.substring(0, index); + setValue(beginning, false); + } + /* + * Now textarea contains trimmed text and could be scrolled up to the + * top. Scroll it to maximum possible value to get end of the text + * visible. + */ + getElement().setScrollTop(getElement().getScrollHeight()); + // Return resulting vertical scrolling value. + return getElement().getScrollTop(); + } + private class MaxLengthHandler implements KeyUpHandler, ChangeHandler { @Override @@ -154,13 +269,18 @@ public class VTextArea extends VTextField { if (wordwrap) { getElement().removeAttribute("wrap"); getElement().getStyle().clearOverflow(); + getElement().getStyle().clearWhiteSpace(); } else { getElement().setAttribute("wrap", "off"); getElement().getStyle().setOverflow(Overflow.AUTO); + getElement().getStyle().setWhiteSpace(WhiteSpace.PRE); } - if (BrowserInfo.get().isOpera()) { + if (BrowserInfo.get().isOpera() + || (BrowserInfo.get().isWebkit() && wordwrap)) { // Opera fails to dynamically update the wrap attribute so we detach // and reattach the whole TextArea. + // Webkit fails to properly reflow the text when enabling wrapping, + // same workaround Util.detachAttach(getElement()); } this.wordwrap = wordwrap; diff --git a/client/src/com/vaadin/client/ui/VTextField.java b/client/src/com/vaadin/client/ui/VTextField.java index 9b85dd22da..60dc5a8f2a 100644 --- a/client/src/com/vaadin/client/ui/VTextField.java +++ b/client/src/com/vaadin/client/ui/VTextField.java @@ -450,4 +450,8 @@ public class VTextField extends TextBoxBase implements Field, ChangeHandler, this.inputPrompt = inputPrompt; } + protected boolean isWordwrap() { + String wrap = getElement().getAttribute("wrap"); + return !"off".equals(wrap); + } } diff --git a/client/src/com/vaadin/client/ui/VTree.java b/client/src/com/vaadin/client/ui/VTree.java index 809ed9c82d..624dce4f13 100644 --- a/client/src/com/vaadin/client/ui/VTree.java +++ b/client/src/com/vaadin/client/ui/VTree.java @@ -189,7 +189,7 @@ public class VTree extends FocusElementPanel implements VHasDropHandler, * handler, other browsers handle it correctly when using a key down * handler */ - if (BrowserInfo.get().isGecko() || BrowserInfo.get().isOpera()) { + if (BrowserInfo.get().isGecko()) { addKeyPressHandler(this); } else { addKeyDownHandler(this); diff --git a/client/src/com/vaadin/client/ui/VUI.java b/client/src/com/vaadin/client/ui/VUI.java index b627d4a2a9..b07593896f 100644 --- a/client/src/com/vaadin/client/ui/VUI.java +++ b/client/src/com/vaadin/client/ui/VUI.java @@ -53,7 +53,8 @@ import com.vaadin.shared.ui.ui.UIConstants; */ public class VUI extends SimplePanel implements ResizeHandler, Window.ClosingHandler, ShortcutActionHandlerOwner, Focusable, - HasResizeHandlers, HasScrollHandlers { + com.google.gwt.user.client.ui.Focusable, HasResizeHandlers, + HasScrollHandlers { private static int MONITOR_PARENT_TIMER_INTERVAL = 1000; @@ -437,7 +438,7 @@ public class VUI extends SimplePanel implements ResizeHandler, @Override public void focus() { - getElement().focus(); + setFocus(true); } /** @@ -462,4 +463,24 @@ public class VUI extends SimplePanel implements ResizeHandler, return addHandler(scrollHandler, ScrollEvent.getType()); } + @Override + public int getTabIndex() { + return FocusUtil.getTabIndex(this); + } + + @Override + public void setAccessKey(char key) { + FocusUtil.setAccessKey(this, key); + } + + @Override + public void setFocus(boolean focused) { + FocusUtil.setFocus(this, focused); + } + + @Override + public void setTabIndex(int index) { + FocusUtil.setTabIndex(this, index); + } + } diff --git a/client/src/com/vaadin/client/ui/VWindow.java b/client/src/com/vaadin/client/ui/VWindow.java index bd9493c761..fd2a701334 100644 --- a/client/src/com/vaadin/client/ui/VWindow.java +++ b/client/src/com/vaadin/client/ui/VWindow.java @@ -22,6 +22,9 @@ import java.util.Comparator; import com.google.gwt.core.client.Scheduler; import com.google.gwt.core.client.Scheduler.ScheduledCommand; +import com.google.gwt.dom.client.Style; +import com.google.gwt.dom.client.Style.Position; +import com.google.gwt.dom.client.Style.Unit; import com.google.gwt.event.dom.client.BlurEvent; import com.google.gwt.event.dom.client.BlurHandler; import com.google.gwt.event.dom.client.FocusEvent; @@ -35,6 +38,7 @@ import com.google.gwt.user.client.DOM; import com.google.gwt.user.client.Element; import com.google.gwt.user.client.Event; import com.google.gwt.user.client.Window; +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.BrowserInfo; @@ -423,6 +427,36 @@ public class VWindow extends VOverlay implements ShortcutActionHandlerOwner, // Remove window from windowOrder to avoid references being left // hanging. windowOrder.remove(this); + + /* + * If the window has a RichTextArea and the RTA is focused at the time + * of hiding in IE8 only the window will have some problems returning + * the focus to the correct place. Curiously the focus will be returned + * correctly if clicking on the "close" button in the window header but + * closing the window from a button for example in the window will fail. + * Symptom described in #10776 + * + * The problematic part is that for the focus to be returned correctly + * an input element needs to be focused in the root panel. Focusing some + * other element apparently won't work. + */ + if (BrowserInfo.get().isIE8()) { + fixIE8FocusCaptureIssue(); + } + } + + private void fixIE8FocusCaptureIssue() { + Element e = DOM.createInputText(); + Style elemStyle = e.getStyle(); + elemStyle.setPosition(Position.ABSOLUTE); + elemStyle.setLeft(-10, Unit.PX); + elemStyle.setWidth(0, Unit.PX); + elemStyle.setHeight(0, Unit.PX); + + Element rootPanel = RootPanel.getBodyElement(); + rootPanel.appendChild(e); + e.focus(); + rootPanel.removeChild(e); } /** For internal use only. May be removed or replaced in the future. */ diff --git a/client/src/com/vaadin/client/ui/audio/AudioConnector.java b/client/src/com/vaadin/client/ui/audio/AudioConnector.java index c7d20ef585..5a90cab09d 100644 --- a/client/src/com/vaadin/client/ui/audio/AudioConnector.java +++ b/client/src/com/vaadin/client/ui/audio/AudioConnector.java @@ -30,23 +30,6 @@ import com.vaadin.ui.Audio; public class AudioConnector extends MediaBaseConnector { @Override - public void onStateChanged(StateChangeEvent stateChangeEvent) { - super.onStateChanged(stateChangeEvent); - - Style style = getWidget().getElement().getStyle(); - - // Make sure that the controls are not clipped if visible. - if (getState().showControls - && (style.getHeight() == null || "".equals(style.getHeight()))) { - if (BrowserInfo.get().isChrome()) { - style.setHeight(32, Unit.PX); - } else { - style.setHeight(25, Unit.PX); - } - } - } - - @Override protected Widget createWidget() { return GWT.create(VAudio.class); } @@ -55,4 +38,35 @@ public class AudioConnector extends MediaBaseConnector { protected String getDefaultAltHtml() { return "Your browser does not support the <code>audio</code> element."; } + + @Override + public void onStateChanged(StateChangeEvent stateChangeEvent) { + super.onStateChanged(stateChangeEvent); + + // Opera (12.14) has a bug where an audio element w/o controls is shown + // as 150x300px, which is not usually desired. However, in order to show + // the error/alt message, we only do this in the exact situation. + if (BrowserInfo.get().isOpera() + && stateChangeEvent.hasPropertyChanged("showControls")) { + Style style = getWidget().getElement().getStyle(); + if (!getState().showControls) { + if (isUndefinedHeight() && isUndefinedWidth() + && getWidget().getOffsetHeight() == 150 + && getWidget().getOffsetWidth() == 300) { + // only if no size set and 150x300 + style.setWidth(0, Unit.PX); + style.setHeight(0, Unit.PX); + } + } else { + // clear sizes if it's supposed to be undefined + if (isUndefinedHeight()) { + style.clearHeight(); + } + if (isUndefinedWidth()) { + style.clearWidth(); + } + } + } + } + } diff --git a/client/src/com/vaadin/client/ui/checkbox/CheckBoxConnector.java b/client/src/com/vaadin/client/ui/checkbox/CheckBoxConnector.java index 014ea849a2..772419e730 100644 --- a/client/src/com/vaadin/client/ui/checkbox/CheckBoxConnector.java +++ b/client/src/com/vaadin/client/ui/checkbox/CheckBoxConnector.java @@ -143,11 +143,13 @@ public class CheckBoxConnector extends AbstractFieldConnector implements return; } + getState().checked = getWidget().getValue(); + // Add mouse details MouseEventDetails details = MouseEventDetailsBuilder .buildMouseEventDetails(event.getNativeEvent(), getWidget() .getElement()); - getRpcProxy(CheckBoxServerRpc.class).setChecked(getWidget().getValue(), + getRpcProxy(CheckBoxServerRpc.class).setChecked(getState().checked, details); } diff --git a/client/src/com/vaadin/client/ui/ui/UIConnector.java b/client/src/com/vaadin/client/ui/ui/UIConnector.java index c8210e3a09..4f0ea2de37 100644 --- a/client/src/com/vaadin/client/ui/ui/UIConnector.java +++ b/client/src/com/vaadin/client/ui/ui/UIConnector.java @@ -421,10 +421,6 @@ public class UIConnector extends AbstractSingleComponentContainerConnector DOM.sinkEvents(getWidget().getElement(), Event.ONKEYDOWN | Event.ONSCROLL); - // iview is focused when created so element needs tabIndex - // 1 due 0 is at the end of natural tabbing order - DOM.setElementProperty(getWidget().getElement(), "tabIndex", "1"); - RootPanel root = RootPanel.get(rootPanelId); // Remove the v-app-loading or any splash screen added inside the div by @@ -437,6 +433,10 @@ public class UIConnector extends AbstractSingleComponentContainerConnector root.add(getWidget()); + // Set default tab index before focus call. State change handler + // will update this later if needed. + getWidget().setTabIndex(1); + if (applicationConnection.getConfiguration().isStandalone()) { // set focus to iview element by default to listen possible keyboard // shortcuts. For embedded applications this is unacceptable as we diff --git a/common.xml b/common.xml index f575c3606d..eceb0b9077 100644 --- a/common.xml +++ b/common.xml @@ -316,7 +316,7 @@ <exclude name="com/vaadin/tests/data/bean/*" /> <exclude name="com/vaadin/tests/util/*" /> <exclude name="**/VaadinClasses.java" /> - <exclude name="**TestRunner.java" /> + <exclude name="**/*TestRunner.java" /> <exclude name="**/SQLTestsConstants.java" /> </fileset> </batchtest> diff --git a/server/src/com/vaadin/data/util/sqlcontainer/query/AbstractTransactionalQuery.java b/server/src/com/vaadin/data/util/sqlcontainer/query/AbstractTransactionalQuery.java new file mode 100644 index 0000000000..3264118732 --- /dev/null +++ b/server/src/com/vaadin/data/util/sqlcontainer/query/AbstractTransactionalQuery.java @@ -0,0 +1,185 @@ +/* + * Copyright 2000-2013 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.data.util.sqlcontainer.query; + +import java.io.Serializable; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; + +import com.vaadin.data.util.sqlcontainer.connection.JDBCConnectionPool; + +/** + * Common base class for database query classes that handle connections and + * transactions. + * + * @author Vaadin Ltd + * @since 6.8.9 + */ +abstract class AbstractTransactionalQuery implements Serializable { + + private JDBCConnectionPool connectionPool; + private transient Connection activeConnection; + + AbstractTransactionalQuery() { + } + + AbstractTransactionalQuery(JDBCConnectionPool connectionPool) { + this.connectionPool = connectionPool; + } + + /** + * Reserves a connection with auto-commit off if no transaction is in + * progress. + * + * @throws IllegalStateException + * if a transaction is already open + * @throws SQLException + * if a connection could not be obtained or configured + */ + public void beginTransaction() throws UnsupportedOperationException, + SQLException { + if (isInTransaction()) { + throw new IllegalStateException("A transaction is already active!"); + } + activeConnection = connectionPool.reserveConnection(); + activeConnection.setAutoCommit(false); + } + + /** + * Commits (if not in auto-commit mode) and releases the active connection. + * + * @throws SQLException + * if not in a transaction managed by this query + */ + public void commit() throws UnsupportedOperationException, SQLException { + if (!isInTransaction()) { + throw new SQLException("No active transaction"); + } + if (!activeConnection.getAutoCommit()) { + activeConnection.commit(); + } + connectionPool.releaseConnection(activeConnection); + activeConnection = null; + } + + /** + * Rolls back and releases the active connection. + * + * @throws SQLException + * if not in a transaction managed by this query + */ + public void rollback() throws UnsupportedOperationException, SQLException { + if (!isInTransaction()) { + throw new SQLException("No active transaction"); + } + activeConnection.rollback(); + connectionPool.releaseConnection(activeConnection); + activeConnection = null; + } + + /** + * Check that a transaction is active. + * + * @throws SQLException + * if no active transaction + */ + protected void ensureTransaction() throws SQLException { + if (!isInTransaction()) { + throw new SQLException("No active transaction!"); + } + } + + /** + * Closes a statement and a resultset, then releases the connection if it is + * not part of an active transaction. A failure in closing one of the + * parameters does not prevent closing the rest. + * + * If the statement is a {@link PreparedStatement}, its parameters are + * cleared prior to closing the statement. + * + * Although JDBC specification does state that closing a statement closes + * its result set and closing a connection closes statements and result + * sets, this method does try to close the result set and statement + * explicitly whenever not null. This can guard against bugs in certain JDBC + * drivers and reduce leaks in case e.g. closing the result set succeeds but + * closing the statement or connection fails. + * + * @param conn + * the connection to release + * @param statement + * the statement to close, may be null to skip closing + * @param rs + * the result set to close, may be null to skip closing + * @throws SQLException + * if closing the result set or the statement fails + */ + protected void releaseConnection(Connection conn, Statement statement, + ResultSet rs) throws SQLException { + try { + try { + if (null != rs) { + rs.close(); + } + } finally { + if (null != statement) { + if (statement instanceof PreparedStatement) { + try { + ((PreparedStatement) statement).clearParameters(); + } catch (Exception e) { + // will be closed below anyway + } + } + statement.close(); + } + } + } finally { + releaseConnection(conn); + } + } + + /** + * Returns the currently active connection, reserves and returns a new + * connection if no active connection. + * + * @return previously active or newly reserved connection + * @throws SQLException + */ + protected Connection getConnection() throws SQLException { + if (activeConnection != null) { + return activeConnection; + } + return connectionPool.reserveConnection(); + } + + protected boolean isInTransaction() { + return activeConnection != null; + } + + /** + * Releases the connection if it is not part of an active transaction. + * + * @param conn + * the connection to release + */ + private void releaseConnection(Connection conn) { + if (conn != activeConnection && conn != null) { + connectionPool.releaseConnection(conn); + } + } +} diff --git a/server/src/com/vaadin/data/util/sqlcontainer/query/FreeformQuery.java b/server/src/com/vaadin/data/util/sqlcontainer/query/FreeformQuery.java index 299183f5e6..6895e02147 100644 --- a/server/src/com/vaadin/data/util/sqlcontainer/query/FreeformQuery.java +++ b/server/src/com/vaadin/data/util/sqlcontainer/query/FreeformQuery.java @@ -34,13 +34,12 @@ import com.vaadin.data.util.sqlcontainer.query.generator.StatementHelper; import com.vaadin.data.util.sqlcontainer.query.generator.filter.QueryBuilder; @SuppressWarnings("serial") -public class FreeformQuery implements QueryDelegate { +public class FreeformQuery extends AbstractTransactionalQuery implements + QueryDelegate { FreeformQueryDelegate delegate = null; private String queryString; private List<String> primaryKeyColumns; - private JDBCConnectionPool connectionPool; - private transient Connection activeConnection = null; /** * Prevent no-parameters instantiation of FreeformQuery @@ -67,6 +66,7 @@ public class FreeformQuery implements QueryDelegate { @Deprecated public FreeformQuery(String queryString, List<String> primaryKeyColumns, JDBCConnectionPool connectionPool) { + super(connectionPool); if (primaryKeyColumns == null) { primaryKeyColumns = new ArrayList<String>(); } @@ -83,7 +83,6 @@ public class FreeformQuery implements QueryDelegate { this.queryString = queryString; this.primaryKeyColumns = Collections .unmodifiableList(primaryKeyColumns); - this.connectionPool = connectionPool; } /** @@ -189,13 +188,6 @@ public class FreeformQuery implements QueryDelegate { return count; } - private Connection getConnection() throws SQLException { - if (activeConnection != null) { - return activeConnection; - } - return connectionPool.reserveConnection(); - } - /** * Fetches the results for the query. This implementation always fetches the * entire record set, ignoring the offset and page length parameters. In @@ -210,9 +202,7 @@ public class FreeformQuery implements QueryDelegate { @Override @SuppressWarnings({ "deprecation", "finally" }) public ResultSet getResults(int offset, int pagelength) throws SQLException { - if (activeConnection == null) { - throw new SQLException("No active transaction!"); - } + ensureTransaction(); String query = queryString; if (delegate != null) { /* First try using prepared statement */ @@ -220,8 +210,8 @@ public class FreeformQuery implements QueryDelegate { try { StatementHelper sh = ((FreeformStatementDelegate) delegate) .getQueryStatement(offset, pagelength); - PreparedStatement pstmt = activeConnection - .prepareStatement(sh.getQueryString()); + PreparedStatement pstmt = getConnection().prepareStatement( + sh.getQueryString()); sh.setParameterValuesToStatement(pstmt); return pstmt.executeQuery(); } catch (UnsupportedOperationException e) { @@ -234,7 +224,7 @@ public class FreeformQuery implements QueryDelegate { // This is fine, we'll just use the default queryString. } } - Statement statement = activeConnection.createStatement(); + Statement statement = getConnection().createStatement(); ResultSet rs; try { rs = statement.executeQuery(query); @@ -322,14 +312,14 @@ public class FreeformQuery implements QueryDelegate { */ @Override public int storeRow(RowItem row) throws SQLException { - if (activeConnection == null) { + if (!isInTransaction()) { throw new IllegalStateException("No transaction is active!"); } else if (primaryKeyColumns.isEmpty()) { throw new UnsupportedOperationException( "Cannot store items fetched with a read-only freeform query!"); } if (delegate != null) { - return delegate.storeRow(activeConnection, row); + return delegate.storeRow(getConnection(), row); } else { throw new UnsupportedOperationException( "FreeFormQueryDelegate not set!"); @@ -345,68 +335,36 @@ public class FreeformQuery implements QueryDelegate { */ @Override public boolean removeRow(RowItem row) throws SQLException { - if (activeConnection == null) { + if (!isInTransaction()) { throw new IllegalStateException("No transaction is active!"); } else if (primaryKeyColumns.isEmpty()) { throw new UnsupportedOperationException( "Cannot remove items fetched with a read-only freeform query!"); } if (delegate != null) { - return delegate.removeRow(activeConnection, row); + return delegate.removeRow(getConnection(), row); } else { throw new UnsupportedOperationException( "FreeFormQueryDelegate not set!"); } } - /* - * (non-Javadoc) - * - * @see - * com.vaadin.data.util.sqlcontainer.query.QueryDelegate#beginTransaction() - */ @Override public synchronized void beginTransaction() throws UnsupportedOperationException, SQLException { - if (activeConnection != null) { - throw new IllegalStateException("A transaction is already active!"); - } - activeConnection = connectionPool.reserveConnection(); - activeConnection.setAutoCommit(false); + super.beginTransaction(); } - /* - * (non-Javadoc) - * - * @see com.vaadin.data.util.sqlcontainer.query.QueryDelegate#commit() - */ @Override public synchronized void commit() throws UnsupportedOperationException, SQLException { - if (activeConnection == null) { - throw new SQLException("No active transaction"); - } - if (!activeConnection.getAutoCommit()) { - activeConnection.commit(); - } - connectionPool.releaseConnection(activeConnection); - activeConnection = null; + super.commit(); } - /* - * (non-Javadoc) - * - * @see com.vaadin.data.util.sqlcontainer.query.QueryDelegate#rollback() - */ @Override public synchronized void rollback() throws UnsupportedOperationException, SQLException { - if (activeConnection == null) { - throw new SQLException("No active transaction"); - } - activeConnection.rollback(); - connectionPool.releaseConnection(activeConnection); - activeConnection = null; + super.rollback(); } /* @@ -492,66 +450,6 @@ public class FreeformQuery implements QueryDelegate { return contains; } - /** - * Releases the connection if it is not part of an active transaction. - * - * @param conn - * the connection to release - */ - private void releaseConnection(Connection conn) { - if (conn != activeConnection) { - connectionPool.releaseConnection(conn); - } - } - - /** - * Closes a statement and a resultset, then releases the connection if it is - * not part of an active transaction. A failure in closing one of the - * parameters does not prevent closing the rest. - * - * If the statement is a {@link PreparedStatement}, its parameters are - * cleared prior to closing the statement. - * - * Although JDBC specification does state that closing a statement closes - * its result set and closing a connection closes statements and result - * sets, this method does try to close the result set and statement - * explicitly whenever not null. This can guard against bugs in certain JDBC - * drivers and reduce leaks in case e.g. closing the result set succeeds but - * closing the statement or connection fails. - * - * @param conn - * the connection to release - * @param statement - * the statement to close, may be null to skip closing - * @param rs - * the result set to close, may be null to skip closing - * @throws SQLException - * if closing the result set or the statement fails - */ - private void releaseConnection(Connection conn, Statement statement, - ResultSet rs) throws SQLException { - try { - try { - if (null != rs) { - rs.close(); - } - } finally { - if (null != statement) { - if (statement instanceof PreparedStatement) { - try { - ((PreparedStatement) statement).clearParameters(); - } catch (Exception e) { - // will be closed below anyway - } - } - statement.close(); - } - } - } finally { - releaseConnection(conn); - } - } - private String modifyWhereClause(Object... keys) { // Build the where rules for the provided keys StringBuffer where = new StringBuffer(); diff --git a/server/src/com/vaadin/data/util/sqlcontainer/query/TableQuery.java b/server/src/com/vaadin/data/util/sqlcontainer/query/TableQuery.java index 63e4b3362c..caed5526e3 100644 --- a/server/src/com/vaadin/data/util/sqlcontainer/query/TableQuery.java +++ b/server/src/com/vaadin/data/util/sqlcontainer/query/TableQuery.java @@ -47,8 +47,8 @@ import com.vaadin.data.util.sqlcontainer.query.generator.SQLGenerator; import com.vaadin.data.util.sqlcontainer.query.generator.StatementHelper; @SuppressWarnings("serial") -public class TableQuery implements QueryDelegate, - QueryDelegate.RowIdChangeNotifier { +public class TableQuery extends AbstractTransactionalQuery implements + QueryDelegate, QueryDelegate.RowIdChangeNotifier { /** Table name, primary key column name(s) and version column name */ private String tableName; @@ -62,18 +62,13 @@ public class TableQuery implements QueryDelegate, /** SQLGenerator instance to use for generating queries */ private SQLGenerator sqlGenerator; - /** Fields related to Connection and Transaction handling */ - private JDBCConnectionPool connectionPool; - private transient Connection activeConnection; - private boolean transactionOpen; - /** Row ID change listeners */ private LinkedList<RowIdChangeListener> rowIdChangeListeners; /** Row ID change events, stored until commit() is called */ private final List<RowIdChangeEvent> bufferedEvents = new ArrayList<RowIdChangeEvent>(); /** Set to true to output generated SQL Queries to System.out */ - private boolean debug = false; + private final boolean debug = false; /** Prevent no-parameters instantiation of TableQuery */ @SuppressWarnings("unused") @@ -93,6 +88,7 @@ public class TableQuery implements QueryDelegate, */ public TableQuery(String tableName, JDBCConnectionPool connectionPool, SQLGenerator sqlGenerator) { + super(connectionPool); if (tableName == null || tableName.trim().length() < 1 || connectionPool == null || sqlGenerator == null) { throw new IllegalArgumentException( @@ -100,7 +96,6 @@ public class TableQuery implements QueryDelegate, } this.tableName = tableName; this.sqlGenerator = sqlGenerator; - this.connectionPool = connectionPool; fetchMetaData(); } @@ -129,17 +124,27 @@ public class TableQuery implements QueryDelegate, StatementHelper sh = sqlGenerator.generateSelectQuery(tableName, filters, null, 0, 0, "COUNT(*)"); boolean shouldCloseTransaction = false; - if (!transactionOpen) { + if (!isInTransaction()) { shouldCloseTransaction = true; beginTransaction(); } - ResultSet r = executeQuery(sh); - r.next(); - int count = r.getInt(1); - r.getStatement().close(); - r.close(); - if (shouldCloseTransaction) { - commit(); + ResultSet r = null; + int count = -1; + try { + r = executeQuery(sh); + r.next(); + count = r.getInt(1); + } finally { + try { + if (r != null) { + releaseConnection(r.getStatement().getConnection(), + r.getStatement(), r); + } + } finally { + if (shouldCloseTransaction) { + commit(); + } + } } return count; } @@ -240,28 +245,30 @@ public class TableQuery implements QueryDelegate, setVersionColumnFlagInProperty(row); /* Generate query */ StatementHelper sh = sqlGenerator.generateInsertQuery(tableName, row); - PreparedStatement pstmt = activeConnection.prepareStatement( - sh.getQueryString(), primaryKeyColumns.toArray(new String[0])); - sh.setParameterValuesToStatement(pstmt); - getLogger().log(Level.FINE, "DB -> {0}", sh.getQueryString()); - int result = pstmt.executeUpdate(); - if (result > 0) { - /* - * If affected rows exist, we'll get the new RowId, commit the - * transaction and return the new RowId. - */ - ResultSet generatedKeys = pstmt.getGeneratedKeys(); - RowId newId = getNewRowId(row, generatedKeys); - generatedKeys.close(); - pstmt.clearParameters(); - pstmt.close(); + Connection connection = null; + PreparedStatement pstmt = null; + ResultSet generatedKeys = null; + connection = getConnection(); + try { + pstmt = connection.prepareStatement(sh.getQueryString(), + primaryKeyColumns.toArray(new String[0])); + sh.setParameterValuesToStatement(pstmt); + getLogger().log(Level.FINE, "DB -> {0}", sh.getQueryString()); + int result = pstmt.executeUpdate(); + RowId newId = null; + if (result > 0) { + /* + * If affected rows exist, we'll get the new RowId, commit the + * transaction and return the new RowId. + */ + generatedKeys = pstmt.getGeneratedKeys(); + newId = getNewRowId(row, generatedKeys); + } + // transaction has to be closed in any case commit(); return newId; - } else { - pstmt.clearParameters(); - pstmt.close(); - /* On failure return null */ - return null; + } finally { + releaseConnection(connection, pstmt, generatedKeys); } } @@ -307,14 +314,8 @@ public class TableQuery implements QueryDelegate, @Override public void beginTransaction() throws UnsupportedOperationException, SQLException { - if (transactionOpen && activeConnection != null) { - throw new IllegalStateException(); - } - getLogger().log(Level.FINE, "DB -> begin transaction"); - activeConnection = connectionPool.reserveConnection(); - activeConnection.setAutoCommit(false); - transactionOpen = true; + super.beginTransaction(); } /* @@ -324,14 +325,8 @@ public class TableQuery implements QueryDelegate, */ @Override public void commit() throws UnsupportedOperationException, SQLException { - if (transactionOpen && activeConnection != null) { - getLogger().log(Level.FINE, "DB -> commit"); - activeConnection.commit(); - connectionPool.releaseConnection(activeConnection); - } else { - throw new SQLException("No active transaction"); - } - transactionOpen = false; + getLogger().log(Level.FINE, "DB -> commit"); + super.commit(); /* Handle firing row ID change events */ RowIdChangeEvent[] unFiredEvents = bufferedEvents @@ -353,14 +348,8 @@ public class TableQuery implements QueryDelegate, */ @Override public void rollback() throws UnsupportedOperationException, SQLException { - if (transactionOpen && activeConnection != null) { - getLogger().log(Level.FINE, "DB -> rollback"); - activeConnection.rollback(); - connectionPool.releaseConnection(activeConnection); - } else { - throw new SQLException("No active transaction"); - } - transactionOpen = false; + getLogger().log(Level.FINE, "DB -> rollback"); + super.rollback(); } /* @@ -402,16 +391,18 @@ public class TableQuery implements QueryDelegate, * @throws SQLException */ private ResultSet executeQuery(StatementHelper sh) throws SQLException { - Connection c = null; - if (transactionOpen && activeConnection != null) { - c = activeConnection; - } else { - throw new SQLException("No active transaction!"); + ensureTransaction(); + Connection connection = getConnection(); + PreparedStatement pstmt = null; + try { + pstmt = connection.prepareStatement(sh.getQueryString()); + sh.setParameterValuesToStatement(pstmt); + getLogger().log(Level.FINE, "DB -> {0}", sh.getQueryString()); + return pstmt.executeQuery(); + } catch (SQLException e) { + releaseConnection(null, pstmt, null); + throw e; } - PreparedStatement pstmt = c.prepareStatement(sh.getQueryString()); - sh.setParameterValuesToStatement(pstmt); - getLogger().log(Level.FINE, "DB -> {0}", sh.getQueryString()); - return pstmt.executeQuery(); } /** @@ -426,27 +417,17 @@ public class TableQuery implements QueryDelegate, * @throws SQLException */ private int executeUpdate(StatementHelper sh) throws SQLException { - Connection c = null; PreparedStatement pstmt = null; + Connection connection = null; try { - if (transactionOpen && activeConnection != null) { - c = activeConnection; - } else { - c = connectionPool.reserveConnection(); - } - pstmt = c.prepareStatement(sh.getQueryString()); + connection = getConnection(); + pstmt = connection.prepareStatement(sh.getQueryString()); sh.setParameterValuesToStatement(pstmt); getLogger().log(Level.FINE, "DB -> {0}", sh.getQueryString()); int retval = pstmt.executeUpdate(); return retval; } finally { - if (pstmt != null) { - pstmt.clearParameters(); - pstmt.close(); - } - if (!transactionOpen) { - connectionPool.releaseConnection(c); - } + releaseConnection(connection, pstmt, null); } } @@ -467,16 +448,12 @@ public class TableQuery implements QueryDelegate, */ private int executeUpdateReturnKeys(StatementHelper sh, RowItem row) throws SQLException { - Connection c = null; PreparedStatement pstmt = null; ResultSet genKeys = null; + Connection connection = null; try { - if (transactionOpen && activeConnection != null) { - c = activeConnection; - } else { - c = connectionPool.reserveConnection(); - } - pstmt = c.prepareStatement(sh.getQueryString(), + connection = getConnection(); + pstmt = connection.prepareStatement(sh.getQueryString(), primaryKeyColumns.toArray(new String[0])); sh.setParameterValuesToStatement(pstmt); getLogger().log(Level.FINE, "DB -> {0}", sh.getQueryString()); @@ -486,16 +463,7 @@ public class TableQuery implements QueryDelegate, bufferedEvents.add(new RowIdChangeEvent(row.getId(), newId)); return result; } finally { - if (genKeys != null) { - genKeys.close(); - } - if (pstmt != null) { - pstmt.clearParameters(); - pstmt.close(); - } - if (!transactionOpen) { - connectionPool.releaseConnection(c); - } + releaseConnection(connection, pstmt, genKeys); } } @@ -505,13 +473,15 @@ public class TableQuery implements QueryDelegate, * Also tries to get the escape string to be used in search strings. */ private void fetchMetaData() { - Connection c = null; + Connection connection = null; + ResultSet rs = null; + ResultSet tables = null; try { - c = connectionPool.reserveConnection(); - DatabaseMetaData dbmd = c.getMetaData(); + connection = getConnection(); + DatabaseMetaData dbmd = connection.getMetaData(); if (dbmd != null) { tableName = SQLUtil.escapeSQL(tableName); - ResultSet tables = dbmd.getTables(null, null, tableName, null); + tables = dbmd.getTables(null, null, tableName, null); if (!tables.next()) { tables = dbmd.getTables(null, null, tableName.toUpperCase(), null); @@ -525,7 +495,7 @@ public class TableQuery implements QueryDelegate, } } tables.close(); - ResultSet rs = dbmd.getPrimaryKeys(null, null, tableName); + rs = dbmd.getPrimaryKeys(null, null, tableName); List<String> names = new ArrayList<String>(); while (rs.next()) { names.add(rs.getString("COLUMN_NAME")); @@ -554,7 +524,15 @@ public class TableQuery implements QueryDelegate, } catch (SQLException e) { throw new RuntimeException(e); } finally { - connectionPool.releaseConnection(c); + try { + releaseConnection(connection, null, rs); + } catch (SQLException ignore) { + } finally { + try { + tables.close(); + } catch (SQLException ignore) { + } + } } } @@ -648,7 +626,7 @@ public class TableQuery implements QueryDelegate, filtersAndKeys, orderBys, 0, 0, "*"); boolean shouldCloseTransaction = false; - if (!transactionOpen) { + if (!isInTransaction()) { shouldCloseTransaction = true; beginTransaction(); } @@ -658,14 +636,15 @@ public class TableQuery implements QueryDelegate, boolean contains = rs.next(); return contains; } finally { - if (rs != null) { - if (rs.getStatement() != null) { - rs.getStatement().close(); + try { + if (rs != null) { + releaseConnection(rs.getStatement().getConnection(), + rs.getStatement(), rs); + } + } finally { + if (shouldCloseTransaction) { + commit(); } - rs.close(); - } - if (shouldCloseTransaction) { - commit(); } } } diff --git a/server/src/com/vaadin/ui/AbstractComponentContainer.java b/server/src/com/vaadin/ui/AbstractComponentContainer.java index ca83286311..4aacad680f 100644 --- a/server/src/com/vaadin/ui/AbstractComponentContainer.java +++ b/server/src/com/vaadin/ui/AbstractComponentContainer.java @@ -339,6 +339,12 @@ public abstract class AbstractComponentContainer extends AbstractComponent true); } + /** + * {@inheritDoc} + * + * @deprecated As of 7.0, use {@link #iterator()} instead. + */ + @Deprecated @Override public Iterator<Component> getComponentIterator() { return iterator(); diff --git a/server/src/com/vaadin/ui/CheckBox.java b/server/src/com/vaadin/ui/CheckBox.java index 0ace0a4f26..ac33f5e410 100644 --- a/server/src/com/vaadin/ui/CheckBox.java +++ b/server/src/com/vaadin/ui/CheckBox.java @@ -16,6 +16,8 @@ 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; @@ -37,6 +39,21 @@ public class CheckBox extends AbstractField<Boolean> { return; } + /* + * Client side updates the state before sending the event so we need + * to make sure the cached state is updated to match the client. If + * we do not do this, a reverting setValue() call in a listener will + * not cause the new state to be sent to the client. + * + * See #11028, #10030. + */ + try { + getUI().getConnectorTracker().getDiffState(CheckBox.this) + .put("checked", checked); + } catch (JSONException e) { + throw new RuntimeException(e); + } + final Boolean oldValue = getValue(); final Boolean newValue = checked; diff --git a/server/src/com/vaadin/ui/Table.java b/server/src/com/vaadin/ui/Table.java index 641c0ff1f6..3d7cb42050 100644 --- a/server/src/com/vaadin/ui/Table.java +++ b/server/src/com/vaadin/ui/Table.java @@ -396,10 +396,14 @@ public class Table extends AbstractSelect implements Action.Container, private HashMap<Object, Align> columnAlignments = new HashMap<Object, Align>(); /** - * Holds column widths in pixels (Integer) or expand ratios (Float) for - * visible columns (by propertyId). + * Holds column widths in pixels for visible columns (by propertyId). */ - private final HashMap<Object, Object> columnWidths = new HashMap<Object, Object>(); + private final HashMap<Object, Integer> columnWidths = new HashMap<Object, Integer>(); + + /** + * Holds column expand rations for visible columns (by propertyId). + */ + private final HashMap<Object, Float> columnExpandRatios = new HashMap<Object, Float>(); /** * Holds column generators @@ -886,10 +890,14 @@ public class Table extends AbstractSelect implements Action.Container, // id to store the width of the row header. propertyId = ROW_HEADER_FAKE_PROPERTY_ID; } + + // Setting column width should remove any expand ratios as well + columnExpandRatios.remove(propertyId); + if (width < 0) { columnWidths.remove(propertyId); } else { - columnWidths.put(propertyId, Integer.valueOf(width)); + columnWidths.put(propertyId, width); } markAsDirty(); } @@ -930,21 +938,39 @@ public class Table extends AbstractSelect implements Action.Container, * the expandRatio used to divide excess space for this column */ public void setColumnExpandRatio(Object propertyId, float expandRatio) { + if (propertyId == null) { + // Since propertyId is null, this is the row header. Use the magic + // id to store the width of the row header. + propertyId = ROW_HEADER_FAKE_PROPERTY_ID; + } + + // Setting the column expand ratio should remove and defined column + // width + columnWidths.remove(propertyId); + if (expandRatio < 0) { - columnWidths.remove(propertyId); + columnExpandRatios.remove(propertyId); } else { - columnWidths.put(propertyId, new Float(expandRatio)); + columnExpandRatios.put(propertyId, expandRatio); } + + requestRepaint(); } + /** + * Gets the column expand ratio for a columnd. See + * {@link #setColumnExpandRatio(Object, float)} + * + * @param propertyId + * columns property id + * @return the expandRatio used to divide excess space for this column + */ public float getColumnExpandRatio(Object propertyId) { - final Object width = columnWidths.get(propertyId); - if (width == null || !(width instanceof Float)) { + final Float width = columnExpandRatios.get(propertyId); + if (width == null) { return -1; } - final Float value = (Float) width; - return value.floatValue(); - + return width.floatValue(); } /** @@ -959,12 +985,11 @@ public class Table extends AbstractSelect implements Action.Container, // id to retrieve the width of the row header. propertyId = ROW_HEADER_FAKE_PROPERTY_ID; } - final Object width = columnWidths.get(propertyId); - if (width == null || !(width instanceof Integer)) { + final Integer width = columnWidths.get(propertyId); + if (width == null) { return -1; } - final Integer value = (Integer) width; - return value.intValue(); + return width.intValue(); } /** @@ -3434,6 +3459,7 @@ public class Table extends AbstractSelect implements Action.Container, target.startTag("column"); target.addAttribute("cid", ROW_HEADER_COLUMN_KEY); paintColumnWidth(target, ROW_HEADER_FAKE_PROPERTY_ID); + paintColumnExpandRatio(target, ROW_HEADER_FAKE_PROPERTY_ID); target.endTag("column"); } final Collection<?> sortables = getSortableContainerPropertyIds(); @@ -3461,6 +3487,7 @@ public class Table extends AbstractSelect implements Action.Container, .toString()); } paintColumnWidth(target, colId); + paintColumnExpandRatio(target, colId); target.endTag("column"); } } @@ -3706,12 +3733,14 @@ public class Table extends AbstractSelect implements Action.Container, private void paintColumnWidth(PaintTarget target, final Object columnId) throws PaintException { if (columnWidths.containsKey(columnId)) { - if (getColumnWidth(columnId) > -1) { - target.addAttribute("width", - String.valueOf(getColumnWidth(columnId))); - } else { - target.addAttribute("er", getColumnExpandRatio(columnId)); - } + target.addAttribute("width", getColumnWidth(columnId)); + } + } + + private void paintColumnExpandRatio(PaintTarget target, + final Object columnId) throws PaintException { + if (columnExpandRatios.containsKey(columnId)) { + target.addAttribute("er", getColumnExpandRatio(columnId)); } } diff --git a/server/src/com/vaadin/ui/UI.java b/server/src/com/vaadin/ui/UI.java index d12c8d89c9..796d1f08ea 100644 --- a/server/src/com/vaadin/ui/UI.java +++ b/server/src/com/vaadin/ui/UI.java @@ -78,7 +78,7 @@ import com.vaadin.util.CurrentInstance; * @since 7.0 */ public abstract class UI extends AbstractSingleComponentContainer implements - Action.Container, Action.Notifier, LegacyComponent { + Action.Container, Action.Notifier, LegacyComponent, Focusable { /** * The application to which this UI belongs @@ -184,6 +184,11 @@ public abstract class UI extends AbstractSingleComponentContainer implements } @Override + protected UIState getState(boolean markAsDirty) { + return (UIState) super.getState(markAsDirty); + } + + @Override public Class<? extends UIState> getStateType() { // This is a workaround for a problem with creating the correct state // object during build @@ -1039,4 +1044,14 @@ public abstract class UI extends AbstractSingleComponentContainer implements } super.setContent(content); } + + @Override + public void setTabIndex(int tabIndex) { + getState().tabIndex = tabIndex; + } + + @Override + public int getTabIndex() { + return getState(false).tabIndex; + } } diff --git a/server/tests/src/com/vaadin/tests/server/component/tree/TreeTest.java b/server/tests/src/com/vaadin/tests/server/component/tree/TreeTest.java index c1d7653c01..634e6a86f3 100644 --- a/server/tests/src/com/vaadin/tests/server/component/tree/TreeTest.java +++ b/server/tests/src/com/vaadin/tests/server/component/tree/TreeTest.java @@ -1,24 +1,31 @@ package com.vaadin.tests.server.component.tree; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + import java.lang.reflect.Field; import java.util.HashSet; -import junit.framework.TestCase; +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; import com.vaadin.data.Container; import com.vaadin.data.util.HierarchicalContainer; import com.vaadin.data.util.IndexedContainer; import com.vaadin.ui.Tree; -public class TreeTest extends TestCase { +public class TreeTest { private Tree tree; private Tree tree2; private Tree tree3; private Tree tree4; - @Override - protected void setUp() { + @Before + public void setUp() { tree = new Tree(); tree.addItem("parent"); tree.addItem("child"); @@ -44,6 +51,7 @@ public class TreeTest extends TestCase { tree4.setParent("child", "parent"); } + @Test public void testRemoveChildren() { assertTrue(tree.hasChildren("parent")); tree.removeItem("child"); @@ -62,6 +70,7 @@ public class TreeTest extends TestCase { assertFalse(tree4.hasChildren("parent")); } + @Test public void testContainerTypeIsHierarchical() { assertTrue(HierarchicalContainer.class.isAssignableFrom(tree .getContainerDataSource().getClass())); @@ -75,6 +84,11 @@ public class TreeTest extends TestCase { .getContainerDataSource().getClass())); } + @Ignore("This test tests that item ids which are removed are also " + + "removed from the expand list to prevent a memory leak. " + + "Fixing the memory leak cannot be done without changing some API (see #11053) " + + "so ignoring this test for the 7.0.x series.") + @Test public void testRemoveExpandedItems() throws Exception { tree.expandItem("parent"); tree.expandItem("child"); @@ -113,6 +127,7 @@ public class TreeTest extends TestCase { assertNull(expandedItemId); } + @Test public void testRemoveExpandedItemsOnContainerChange() throws Exception { tree.expandItem("parent"); tree.expandItem("child"); diff --git a/shared/src/com/vaadin/shared/ui/ui/UIState.java b/shared/src/com/vaadin/shared/ui/ui/UIState.java index aa862ae31a..9abaf47f4b 100644 --- a/shared/src/com/vaadin/shared/ui/ui/UIState.java +++ b/shared/src/com/vaadin/shared/ui/ui/UIState.java @@ -15,10 +15,12 @@ */ package com.vaadin.shared.ui.ui; -import com.vaadin.shared.AbstractComponentState; +import com.vaadin.shared.ui.TabIndexState; -public class UIState extends AbstractComponentState { +public class UIState extends TabIndexState { { primaryStyleName = "v-ui"; + // Default is 1 for legacy reasons + tabIndex = 1; } }
\ No newline at end of file diff --git a/uitest/integration-testscripts/GateIn-3/integration-test-GateIn-3.1.0-portlet2.html b/uitest/integration-testscripts/GateIn-3/integration-test-GateIn-3.1.0-portlet2.html index 4bc3e6a2cf..5d2d4c3445 100644 --- a/uitest/integration-testscripts/GateIn-3/integration-test-GateIn-3.1.0-portlet2.html +++ b/uitest/integration-testscripts/GateIn-3/integration-test-GateIn-3.1.0-portlet2.html @@ -17,11 +17,6 @@ <td></td> </tr> <tr> - <td>setSpeed</td> - <td>100</td> - <td>100</td> -</tr> -<tr> <td>mouseClickAndWait</td> <td>link=Administrator</td> <td>27,7</td> @@ -32,24 +27,94 @@ <td>93,13</td> </tr> <tr> - <td>expectDialog</td> - <td>//div[2]/div[2]/div[1]/div[1]/div[2]</td> - <td>73,18</td> + <td>mouseClick</td> + <td>link=Portlet</td> + <td>33,11</td> +</tr> +<tr> + <td>waitForElementPresent</td> + <td>link=Vaadin Portlet 2.0 Test</td> + <td>59,9</td> </tr> <tr> - <td>assertConfirmation</td> - <td>This action will automatically create categories and import all the gadgets and portlets on it.</td> + <td>mouseClick</td> + <td>link=Vaadin Portlet 2.0 Test</td> + <td>59,9</td> +</tr> +<tr> + <td>waitForElementPresent</td> + <td>link=Click here to add into categories</td> <td></td> </tr> <tr> + <td>mouseClick</td> + <td>link=Click here to add into categories</td> + <td>48,3</td> +</tr> +<tr> <td>waitForElementPresent</td> - <td>link=demo</td> + <td>name=category_Gadgets</td> <td></td> </tr> <tr> - <td>mouseClickAndWait</td> - <td>link=Home</td> - <td>65,18</td> + <td>mouseClick</td> + <td>name=category_Gadgets</td> + <td>10,16</td> +</tr> +<tr> + <td>waitForElementPresent</td> + <td>link=Save</td> + <td></td> +</tr> +<tr> + <td>mouseClick</td> + <td>link=Save</td> + <td>4,6</td> +</tr> +<tr> + <td>waitForElementPresent</td> + <td>link=Vaadin Liferay Theme</td> + <td></td> +</tr> +<tr> + <td>mouseClick</td> + <td>link=Vaadin Liferay Theme</td> + <td>64,13</td> +</tr> +<tr> + <td>waitForElementPresent</td> + <td>link=Click here to add into categories</td> + <td></td> +</tr> +<tr> + <td>mouseClick</td> + <td>link=Click here to add into categories</td> + <td>96,9</td> +</tr> +<tr> + <td>waitForElementPresent</td> + <td>name=category_Gadgets</td> + <td>7,12</td> +</tr> +<tr> + <td>mouseClick</td> + <td>name=category_Gadgets</td> + <td>7,12</td> +</tr> +<tr> + <td>waitForElementPresent</td> + <td>link=Save</td> + <td>4,6</td> +</tr> +<tr> + <td>mouseClick</td> + <td>link=Save</td> + <td>4,6</td> +</tr> +<tr> + <td>waitForElementPresent</td> + <td>link=Add New Page</td> + <td>55,11</td> </tr> <tr> <td>mouseClick</td> @@ -86,24 +151,15 @@ <td>//div[@id='UIPageCreationWizard']/div/div[3]/div/div/div/div[2]/div/table/tbody/tr/td/div[2]/div/div/div</td> <td>21,13</td> </tr> +<!--Drag JSR286 test portlet to page--> <tr> <td>waitForElementPresent</td> - <td>//div[@id='UIPageEditor']/div[1]/div/div/div/div[2]</td> - <td></td> -</tr> -<tr> - <td>mouseClick</td> - <td>//div[@onclick="javascript:ajaxGet('/portal/private/classic/home?portal:componentId=UIApplicationList&portal:action=SelectCategory&objectId=demo&ajaxRequest=true')"]</td> - <td>51,11</td> -</tr> -<tr> - <td>pause</td> - <td>300</td> + <td>//div[@id='Gadgets/JSR286TestPortlet']/div/div/div/div</td> <td></td> </tr> <tr> <td>drag</td> - <td>//div[@id='demo/JSR286TestPortlet']/div/div/div[1]/div[2]</td> + <td>//div[@id='Gadgets/JSR286TestPortlet']/div/div/div/div</td> <td></td> </tr> <tr> @@ -112,49 +168,25 @@ <td>113,9</td> </tr> <tr> - <td>mouseClickAndWait</td> - <td>//a[@onclick='eXo.core.DOMUtil.disableOnClick(this);']</td> - <td>13,5</td> -</tr> -<tr> - <td>mouseClickAndWait</td> - <td>//div[@id='UIPage']/div/div/div[2]/div/div/div/div/div/div/div[2]/div[5]/div/a</td> - <td>10,10</td> -</tr> -<tr> - <td>closeNotification</td> - <td>//body/div[2]</td> - <td>0,0</td> -</tr> -<tr> - <td>pause</td> - <td>500</td> + <td>waitForTextPresent</td> + <td>Vaadin Portlet 2.0 Test</td> <td></td> </tr> -<tr> - <td>screenCapture</td> - <td></td> - <td>Edit_mode</td> -</tr> +<!--Switch to view mode--> <tr> <td>mouseClickAndWait</td> - <td>//div[@id='UIPage']/div/div/div[2]/div/div/div/div/div/div/div[2]/div[5]/div/a</td> - <td>15,8</td> -</tr> -<tr> - <td>closeNotification</td> - <td>//body/div[2]</td> - <td>0,0</td> + <td>//a[@onclick='eXo.core.DOMUtil.disableOnClick(this);']</td> + <td>13,5</td> </tr> <tr> - <td>pause</td> - <td>500</td> + <td>waitForElementPresent</td> + <td>//div[2]/div/div[2]/img</td> <td></td> </tr> <tr> <td>screenCapture</td> <td></td> - <td>done</td> + <td>view</td> </tr> </tbody></table> </body> diff --git a/uitest/integration-testscripts/Liferay-6/integration-test-liferay-6.0.5.html b/uitest/integration-testscripts/Liferay-6/integration-test-liferay-6.0.5.html index 88cac6cd74..037ce23865 100644 --- a/uitest/integration-testscripts/Liferay-6/integration-test-liferay-6.0.5.html +++ b/uitest/integration-testscripts/Liferay-6/integration-test-liferay-6.0.5.html @@ -36,8 +36,6 @@ <td>//input[@value='Sign In']</td> <td>43,18</td> </tr> - -<!-- --> <tr> <td>mouseClickAndWait</td> <td>//input[@type='submit']</td> @@ -144,19 +142,34 @@ <td>10,10</td> </tr> <tr> - <td>pause</td> - <td>5000</td> + <td>waitForTextPresent</td> + <td>Normal Label</td> <td></td> </tr> <tr> - <td>waitForVaadin</td> + <td>screenCapture</td> + <td></td> + <td>theme</td> +</tr> +<tr> + <td>mouseClick</td> + <td>//td[3]/div/div/div</td> + <td>22,7</td> +</tr> +<tr> + <td>assertTextPresent</td> + <td>Normal TextField</td> <td></td> +</tr> +<tr> + <td>assertTextPresent</td> + <td>Normal TextArea</td> <td></td> </tr> <tr> - <td>screenCapture</td> + <td>assertTextNotPresent</td> + <td>Normal Label</td> <td></td> - <td>theme</td> </tr> </tbody></table> </body> diff --git a/uitest/integration_base_files/base.xml b/uitest/integration_base_files/base.xml index f9c2ff3d6b..5196aecfa9 100644 --- a/uitest/integration_base_files/base.xml +++ b/uitest/integration_base_files/base.xml @@ -28,6 +28,20 @@ </target> <target name="deployStatic"> + <unzip src="${war}" dest="${staticDeployDir}/tmp-unpack-jar/"> + <patternset> + <include name="WEB-INF/lib/*.jar" /> + </patternset> + </unzip> + <unzip dest="${staticDeployDir}"> + <fileset dir="${staticDeployDir}/tmp-unpack-jar/WEB-INF/lib" includes="*.jar" /> + + <patternset> + <include name="VAADIN/**" /> + </patternset> + </unzip> + <delete dir="${staticDeployDir}/tmp-unpack-jar/" /> + <unzip src="${war}" dest="${staticDeployDir}"> <patternset> <include name="VAADIN/**" /> diff --git a/uitest/src/com/vaadin/tests/components/AbstractTestUIWithLog.java b/uitest/src/com/vaadin/tests/components/AbstractTestUIWithLog.java new file mode 100644 index 0000000000..cace7c3404 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/AbstractTestUIWithLog.java @@ -0,0 +1,36 @@ +/* + * Copyright 2000-2013 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; + +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.util.Log; +import com.vaadin.ui.VerticalLayout; + +public abstract class AbstractTestUIWithLog extends AbstractTestUI { + + protected Log log = new Log(5); + + @Override + public void init(VaadinRequest request) { + super.init(request); + ((VerticalLayout) getContent()).addComponent(log, 0); + } + + protected void log(String message) { + log.log(message); + } + +} diff --git a/uitest/src/com/vaadin/tests/components/TestBase.java b/uitest/src/com/vaadin/tests/components/TestBase.java index d267d80669..15f39f6e5d 100644 --- a/uitest/src/com/vaadin/tests/components/TestBase.java +++ b/uitest/src/com/vaadin/tests/components/TestBase.java @@ -6,6 +6,12 @@ import com.vaadin.ui.Label; import com.vaadin.ui.LegacyWindow; import com.vaadin.ui.VerticalLayout; +/** + * + * @deprecated Use {@link AbstractTestUI} or {@link AbstractTestUIWithLog} + * instead. TestBase is a LegacyApplication + */ +@Deprecated public abstract class TestBase extends AbstractTestCase { @Override diff --git a/uitest/src/com/vaadin/tests/components/checkbox/CheckBoxRevertValueChange.html b/uitest/src/com/vaadin/tests/components/checkbox/CheckBoxRevertValueChange.html new file mode 100644 index 0000000000..ea5849f99f --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/checkbox/CheckBoxRevertValueChange.html @@ -0,0 +1,82 @@ +<?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:8888/" /> +<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.checkbox.CheckBoxRevertValueChange?restartApplication</td> + <td></td> +</tr> +<tr> + <td>mouseClick</td> + <td>vaadin=runcomvaadintestscomponentscheckboxCheckBoxRevertValueChange::/VVerticalLayout[0]/Slot[2]/VVerticalLayout[0]/Slot[0]/VCheckBox[0]/domChild[0]</td> + <td>10,5</td> +</tr> +<tr> + <td>assertText</td> + <td>vaadin=runcomvaadintestscomponentscheckboxCheckBoxRevertValueChange::PID_SLog_row_0</td> + <td>1. I said no checking!</td> +</tr> +<tr> + <td>assertValue</td> + <td>vaadin=runcomvaadintestscomponentscheckboxCheckBoxRevertValueChange::/VVerticalLayout[0]/Slot[2]/VVerticalLayout[0]/Slot[0]/VCheckBox[0]/domChild[0]</td> + <td>off</td> +</tr> +<tr> + <td>mouseClick</td> + <td>vaadin=runcomvaadintestscomponentscheckboxCheckBoxRevertValueChange::/VVerticalLayout[0]/Slot[2]/VVerticalLayout[0]/Slot[0]/VCheckBox[0]/domChild[1]</td> + <td>93,10</td> +</tr> +<tr> + <td>assertText</td> + <td>vaadin=runcomvaadintestscomponentscheckboxCheckBoxRevertValueChange::PID_SLog_row_0</td> + <td>2. I said no checking!</td> +</tr> +<tr> + <td>assertValue</td> + <td>vaadin=runcomvaadintestscomponentscheckboxCheckBoxRevertValueChange::/VVerticalLayout[0]/Slot[2]/VVerticalLayout[0]/Slot[0]/VCheckBox[0]/domChild[0]</td> + <td>off</td> +</tr> +<tr> + <td>mouseClick</td> + <td>vaadin=runcomvaadintestscomponentscheckboxCheckBoxRevertValueChange::/VVerticalLayout[0]/Slot[2]/VVerticalLayout[0]/Slot[1]/VCheckBox[0]/domChild[0]</td> + <td>5,8</td> +</tr> +<tr> + <td>assertText</td> + <td>vaadin=runcomvaadintestscomponentscheckboxCheckBoxRevertValueChange::PID_SLog_row_0</td> + <td>3. I said no unchecking!</td> +</tr> +<tr> + <td>assertValue</td> + <td>vaadin=runcomvaadintestscomponentscheckboxCheckBoxRevertValueChange::/VVerticalLayout[0]/Slot[2]/VVerticalLayout[0]/Slot[1]/VCheckBox[0]/domChild[0]</td> + <td>on</td> +</tr> +<tr> + <td>mouseClick</td> + <td>vaadin=runcomvaadintestscomponentscheckboxCheckBoxRevertValueChange::/VVerticalLayout[0]/Slot[2]/VVerticalLayout[0]/Slot[1]/VCheckBox[0]/domChild[1]</td> + <td>78,12</td> +</tr> +<tr> + <td>assertText</td> + <td>vaadin=runcomvaadintestscomponentscheckboxCheckBoxRevertValueChange::PID_SLog_row_0</td> + <td>4. I said no unchecking!</td> +</tr> +<tr> + <td>assertValue</td> + <td>vaadin=runcomvaadintestscomponentscheckboxCheckBoxRevertValueChange::/VVerticalLayout[0]/Slot[2]/VVerticalLayout[0]/Slot[1]/VCheckBox[0]/domChild[0]</td> + <td>on</td> +</tr> + +</tbody></table> +</body> +</html> diff --git a/uitest/src/com/vaadin/tests/components/checkbox/CheckBoxRevertValueChange.java b/uitest/src/com/vaadin/tests/components/checkbox/CheckBoxRevertValueChange.java new file mode 100644 index 0000000000..5b086fb935 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/checkbox/CheckBoxRevertValueChange.java @@ -0,0 +1,65 @@ +/* + * Copyright 2000-2013 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.checkbox; + +import com.vaadin.annotations.PreserveOnRefresh; +import com.vaadin.data.Property; +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUIWithLog; +import com.vaadin.ui.CheckBox; + +@PreserveOnRefresh +public class CheckBoxRevertValueChange extends AbstractTestUIWithLog { + + @Override + protected void setup(VaadinRequest request) { + final CheckBox alwaysUnchecked = new CheckBox("You may not check me"); + alwaysUnchecked + .addValueChangeListener(new Property.ValueChangeListener() { + public void valueChange(Property.ValueChangeEvent event) { + if (alwaysUnchecked.getValue()) { + log("I said no checking!"); + alwaysUnchecked.setValue(false); + } + } + }); + final CheckBox alwaysChecked = new CheckBox("You may not uncheck me"); + alwaysChecked.setValue(true); + alwaysChecked + .addValueChangeListener(new Property.ValueChangeListener() { + public void valueChange(Property.ValueChangeEvent event) { + if (!alwaysChecked.getValue()) { + log("I said no unchecking!"); + alwaysChecked.setValue(true); + } + } + }); + + addComponent(alwaysUnchecked); + addComponent(alwaysChecked); + } + + @Override + protected String getTestDescription() { + return "Ensure checking of a checkbox can be reverted on the server side without making the client go out of sync"; + } + + @Override + protected Integer getTicketNumber() { + return 11028; + } + +} diff --git a/uitest/src/com/vaadin/tests/components/media/AudioTest.html b/uitest/src/com/vaadin/tests/components/media/AudioTest.html new file mode 100644 index 0000000000..8425cad38a --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/media/AudioTest.html @@ -0,0 +1,66 @@ +<?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>AudioTest</title> +</head> +<body> +<table cellpadding="1" cellspacing="1" border="1"> +<thead> +<tr><td rowspan="1" colspan="3">AudioTest</td></tr> +</thead><tbody> +<tr> + <td>open</td> + <td>/run/AudioTest?restartApplication</td> + <td></td> +</tr> +<tr> + <td>pause</td> + <td>3000</td> + <td></td> +</tr> +<tr> + <td>screenCapture</td> + <td></td> + <td>shortAtEndUnmuted</td> +</tr> +<tr> + <td>mouseClick</td> + <td>vaadin=runAudioTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[2]/VCheckBox[0]/domChild[0]</td> + <td>11,7</td> +</tr> +<tr> + <td>mouseClick</td> + <td>vaadin=runAudioTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[3]/VCheckBox[0]/domChild[0]</td> + <td>6,7</td> +</tr> +<tr> + <td>click</td> + <td>vaadin=runAudioTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[5]/VButton[0]/domChild[0]/domChild[0]</td> + <td></td> +</tr> +<tr> + <td>pause</td> + <td>5000</td> + <td></td> +</tr> +<tr> + <td>screenCapture</td> + <td></td> + <td>longerAtEndMuted</td> +</tr> +<tr> + <td>mouseClick</td> + <td>vaadin=runAudioTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[1]/VCheckBox[0]/domChild[0]</td> + <td>69,9</td> +</tr> +<tr> + <td>screenCapture</td> + <td></td> + <td>controlsHidden</td> +</tr> +</tbody></table> +</body> +</html> diff --git a/uitest/src/com/vaadin/tests/components/media/AudioTest.java b/uitest/src/com/vaadin/tests/components/media/AudioTest.java new file mode 100644 index 0000000000..28d1a7716f --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/media/AudioTest.java @@ -0,0 +1,86 @@ +/* + * Copyright 2000-2013 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.media; + +import com.vaadin.data.util.MethodProperty; +import com.vaadin.server.ClassResource; +import com.vaadin.server.Resource; +import com.vaadin.tests.components.TestBase; +import com.vaadin.ui.Audio; +import com.vaadin.ui.Button; +import com.vaadin.ui.Button.ClickEvent; +import com.vaadin.ui.CheckBox; + +public class AudioTest extends TestBase { + + @Override + protected void setup() { + + // Public domain sounds from pdsounds.org 27.2.2013 + + final Resource[] s1 = { new ClassResource(getClass(), "bip.mp3"), + new ClassResource(getClass(), "bip.ogg") }; + final Resource[] s2 = { + new ClassResource(getClass(), "toyphone_dialling.mp3"), + new ClassResource(getClass(), "toyphone_dialling.ogg") }; + + final Audio audio = new Audio(); + + audio.setSources(s1); + audio.setShowControls(true); + audio.setHtmlContentAllowed(true); + audio.setAltText("Can't <b>play</b> media"); + audio.setAutoplay(true); + + addComponent(audio); + + CheckBox checkBox = new CheckBox("Show controls", + new MethodProperty<Boolean>(audio, "showControls")); + addComponent(checkBox); + checkBox = new CheckBox("HtmlContentAllowed", + new MethodProperty<Boolean>(audio, "htmlContentAllowed")); + addComponent(checkBox); + checkBox = new CheckBox("muted", new MethodProperty<Boolean>(audio, + "muted")); + addComponent(checkBox); + checkBox = new CheckBox("autoplay", new MethodProperty<Boolean>(audio, + "autoplay")); + addComponent(checkBox); + + Button b = new Button("Change", new Button.ClickListener() { + + @Override + public void buttonClick(ClickEvent event) { + audio.setSources(s2); + } + }); + addComponent(b); + getLayout().setHeight("400px"); + getLayout().setExpandRatio(b, 1.0f); + } + + @Override + protected String getDescription() { + return "Should autoplay, manipulating checkboxes should do appropriate thing, button changes file."; + } + + @Override + protected Integer getTicketNumber() { + return 11160; + } + +} diff --git a/uitest/src/com/vaadin/tests/components/media/bip.mp3 b/uitest/src/com/vaadin/tests/components/media/bip.mp3 Binary files differnew file mode 100644 index 0000000000..2c7e790cf7 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/media/bip.mp3 diff --git a/uitest/src/com/vaadin/tests/components/media/bip.ogg b/uitest/src/com/vaadin/tests/components/media/bip.ogg Binary files differnew file mode 100644 index 0000000000..4e5014d92f --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/media/bip.ogg diff --git a/uitest/src/com/vaadin/tests/components/media/toyphone_dialling.mp3 b/uitest/src/com/vaadin/tests/components/media/toyphone_dialling.mp3 Binary files differnew file mode 100644 index 0000000000..1788026856 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/media/toyphone_dialling.mp3 diff --git a/uitest/src/com/vaadin/tests/components/media/toyphone_dialling.ogg b/uitest/src/com/vaadin/tests/components/media/toyphone_dialling.ogg Binary files differnew file mode 100644 index 0000000000..a042da5795 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/media/toyphone_dialling.ogg diff --git a/uitest/src/com/vaadin/tests/components/table/TableColumnWidthsAndExpandRatios.html b/uitest/src/com/vaadin/tests/components/table/TableColumnWidthsAndExpandRatios.html new file mode 100644 index 0000000000..75d98ce2e6 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/table/TableColumnWidthsAndExpandRatios.html @@ -0,0 +1,83 @@ +<?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:8888/" /> +<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.table.TableColumnWidthsAndExpandRatios?restartApplication</td> + <td></td> +</tr> +<tr> + <td>screenCapture</td> + <td></td> + <td>initial-all-columns-undefined</td> +</tr> +<!--Resize column 1 making it defined size--> +<tr> + <td>dragAndDrop</td> + <td>vaadin=runcomvaadintestscomponentstableTableColumnWidthsAndExpandRatios::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VScrollTable[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]</td> + <td>-300,0</td> +</tr> +<!--Resize column 2 making it defined size--> +<tr> + <td>dragAndDrop</td> + <td>vaadin=runcomvaadintestscomponentstableTableColumnWidthsAndExpandRatios::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VScrollTable[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[1]/domChild[0]</td> + <td>-300,0</td> +</tr> +<!--Resize column 3 making it defined size--> +<tr> + <td>dragAndDrop</td> + <td>vaadin=runcomvaadintestscomponentstableTableColumnWidthsAndExpandRatios::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VScrollTable[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[2]/domChild[0]</td> + <td>-300,0</td> +</tr> +<tr> + <td>screenCapture</td> + <td></td> + <td>columns-defined-width</td> +</tr> +<!--Reset column 1 width--> +<tr> + <td>mouseClick</td> + <td>vaadin=runcomvaadintestscomponentstableTableColumnWidthsAndExpandRatios::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VHorizontalLayout[0]/ChildComponentContainer[0]/VNativeButton[0]</td> + <td>114,4</td> +</tr> +<tr> + <td>screenCapture</td> + <td></td> + <td>column1-undefined</td> +</tr> +<!--Reset column2 width--> +<tr> + <td>mouseClick</td> + <td>vaadin=runcomvaadintestscomponentstableTableColumnWidthsAndExpandRatios::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VHorizontalLayout[0]/ChildComponentContainer[1]/VNativeButton[0]</td> + <td>98,13</td> +</tr> +<tr> + <td>screenCapture</td> + <td></td> + <td>column2-undefined</td> +</tr> +<!--Reset column 3 width--> +<tr> + <td>mouseClick</td> + <td>vaadin=runcomvaadintestscomponentstableTableColumnWidthsAndExpandRatios::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VHorizontalLayout[0]/ChildComponentContainer[2]/VNativeButton[0]</td> + <td>40,10</td> +</tr> +<tr> + <td>screenCapture</td> + <td></td> + <td>columns-undefined-width</td> +</tr> + +</tbody></table> +</body> +</html> diff --git a/uitest/src/com/vaadin/tests/components/table/TableColumnWidthsAndExpandRatios.java b/uitest/src/com/vaadin/tests/components/table/TableColumnWidthsAndExpandRatios.java new file mode 100644 index 0000000000..747c99468f --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/table/TableColumnWidthsAndExpandRatios.java @@ -0,0 +1,57 @@ +package com.vaadin.tests.components.table; + +import com.vaadin.tests.components.TestBase; +import com.vaadin.ui.Button; +import com.vaadin.ui.Button.ClickEvent; +import com.vaadin.ui.HorizontalLayout; +import com.vaadin.ui.NativeButton; +import com.vaadin.ui.Table; + +public class TableColumnWidthsAndExpandRatios extends TestBase { + + @Override + protected void setup() { + getLayout().setSizeFull(); + + final Table table = new Table(); + table.setSizeFull(); + + table.addContainerProperty("column1", String.class, "Humpty"); + table.addContainerProperty("column2", String.class, "Dumpty"); + table.addContainerProperty("column3", String.class, "Doe"); + + for (int row = 0; row < 100; row++) { + table.addItem(); + } + + HorizontalLayout buttons = new HorizontalLayout(); + for (Object col : table.getContainerPropertyIds()) { + buttons.addComponent(createResetButton(col, table)); + } + + addComponent(table); + addComponent(buttons); + } + + private NativeButton createResetButton(final Object property, + final Table table) { + return new NativeButton("Reset " + property + " width", + new Button.ClickListener() { + + public void buttonClick(ClickEvent event) { + table.setColumnWidth(property, -1); + } + }); + } + + @Override + protected String getDescription() { + return "Changing column width to -1 should remove any previous size measurements"; + } + + @Override + protected Integer getTicketNumber() { + return 7922; + } + +} diff --git a/uitest/src/com/vaadin/tests/components/textarea/ScrollCursor.html b/uitest/src/com/vaadin/tests/components/textarea/ScrollCursor.html new file mode 100644 index 0000000000..9eaa1ceada --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/textarea/ScrollCursor.html @@ -0,0 +1,169 @@ +<?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:8888/" /> +<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.textarea.ScrollCursor?restartApplication</td> + <td></td> +</tr> +<tr> + <td>mouseClick</td> + <td>vaadin=runcomvaadintestscomponentstextareaScrollCursor::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/domChild[0]/domChild[0]</td> + <td>191,94</td> +</tr> +<tr> +<!-- set begin position value --> + <td>click</td> + <td>vaadin=runcomvaadintestscomponentstextareaScrollCursor::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VButton[0]/domChild[0]/domChild[0]</td> + <td></td> +</tr> +<tr> +<!-- set cursor position--> + <td>click</td> + <td>vaadin=runcomvaadintestscomponentstextareaScrollCursor::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VButton[0]/domChild[0]/domChild[0]</td> + <td></td> +</tr> +<tr> + <td>screenCapture</td> + <td></td> + <td>wrap-start</td> +</tr> +<tr> +<!-- set middle position value --> + <td>click</td> + <td>vaadin=runcomvaadintestscomponentstextareaScrollCursor::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[4]/VButton[0]/domChild[0]/domChild[0]</td> + <td></td> +</tr> +<tr> +<!-- set cursor position--> + <td>click</td> + <td>vaadin=runcomvaadintestscomponentstextareaScrollCursor::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VButton[0]/domChild[0]/domChild[0]</td> + <td></td> +</tr> +<tr> + <td>screenCapture</td> + <td></td> + <td>wrap-middle</td> +</tr> +<tr> +<!-- set end position value --> + <td>click</td> + <td>vaadin=runcomvaadintestscomponentstextareaScrollCursor::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[5]/VButton[0]/domChild[0]/domChild[0]</td> + <td></td> +</tr> +<tr> +<!-- set cursor position--> + <td>click</td> + <td>vaadin=runcomvaadintestscomponentstextareaScrollCursor::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VButton[0]/domChild[0]/domChild[0]</td> + <td></td> +</tr> +<tr> + <td>screenCapture</td> + <td></td> + <td>wrap-end</td> +</tr> +<tr> +<!-- set start position value --> + <td>click</td> + <td>vaadin=runcomvaadintestscomponentstextareaScrollCursor::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VButton[0]/domChild[0]/domChild[0]</td> + <td></td> +</tr> +<tr> +<!-- set cursor position : check that scrolling works from the end to the beginning--> + <td>click</td> + <td>vaadin=runcomvaadintestscomponentstextareaScrollCursor::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VButton[0]/domChild[0]/domChild[0]</td> + <td></td> +</tr> +<tr> + <td>screenCapture</td> + <td></td> + <td>wrap-end-start</td> +</tr> +<tr> +<!-- set no wrap --> + <td>click</td> + <td>vaadin=runcomvaadintestscomponentstextareaScrollCursor::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[2]/VButton[0]/domChild[0]/domChild[0]</td> + <td></td> +</tr> +<tr> +<!-- set start position value --> + <td>click</td> + <td>vaadin=runcomvaadintestscomponentstextareaScrollCursor::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VButton[0]/domChild[0]/domChild[0]</td> + <td></td> +</tr> +<tr> +<!-- set cursor position --> + <td>click</td> + <td>vaadin=runcomvaadintestscomponentstextareaScrollCursor::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VButton[0]/domChild[0]/domChild[0]</td> + <td></td> +</tr> +<tr> + <td>screenCapture</td> + <td></td> + <td>nowrap-start</td> +</tr> +<tr> +<!-- set middle position value --> + <td>click</td> + <td>vaadin=runcomvaadintestscomponentstextareaScrollCursor::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[4]/VButton[0]/domChild[0]/domChild[0]</td> + <td></td> +</tr> +<tr> +<!-- set cursor position --> + <td>click</td> + <td>vaadin=runcomvaadintestscomponentstextareaScrollCursor::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VButton[0]/domChild[0]/domChild[0]</td> + <td></td> +</tr> +<tr> + <td>screenCapture</td> + <td></td> + <td>nowrap-middle</td> +</tr> +<tr> +<!-- set end position value --> + <td>click</td> + <td>vaadin=runcomvaadintestscomponentstextareaScrollCursor::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[5]/VButton[0]/domChild[0]/domChild[0]</td> + <td></td> +</tr> +<tr> +<!-- set cursor position --> + <td>click</td> + <td>vaadin=runcomvaadintestscomponentstextareaScrollCursor::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VButton[0]/domChild[0]/domChild[0]</td> + <td></td> +</tr> +<tr> + <td>screenCapture</td> + <td></td> + <td>nowrap-end</td> +</tr> +<tr> +<!-- set start position value --> + <td>click</td> + <td>vaadin=runcomvaadintestscomponentstextareaScrollCursor::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VButton[0]/domChild[0]/domChild[0]</td> + <td></td> +</tr> +<tr> +<!-- set cursor position : check scrolling from the end to the beginning--> + <td>click</td> + <td>vaadin=runcomvaadintestscomponentstextareaScrollCursor::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VButton[0]/domChild[0]</td> + <td></td> +</tr> +<tr> + <td>screenCapture</td> + <td></td> + <td>nowrap-end-start</td> +</tr> + +</tbody></table> +</body> +</html> diff --git a/uitest/src/com/vaadin/tests/components/textarea/ScrollCursor.java b/uitest/src/com/vaadin/tests/components/textarea/ScrollCursor.java new file mode 100644 index 0000000000..c95731d94f --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/textarea/ScrollCursor.java @@ -0,0 +1,89 @@ +package com.vaadin.tests.components.textarea; + +import com.vaadin.tests.components.TestBase; +import com.vaadin.ui.Button; +import com.vaadin.ui.Button.ClickEvent; +import com.vaadin.ui.Button.ClickListener; +import com.vaadin.ui.TextArea; + +/** + * @author denis + * + */ +public class ScrollCursor extends TestBase { + + private TextArea textArea; + private int position; + + @Override + protected void setup() { + textArea = new TextArea(); + textArea.setValue("saddddddddddd fdgdfgfdgfd\n" + + "aasddddddddddd\n" + "dsaffffffdsf\n" + "sdf\n" + + "dsfsdfsdfsdfsd\n\n" + "ffffffffffffffffffff\n" + + "sdfdsfdsfsdfsdfsd xxxxxxxxxxxxxxxx\n" + "sdgfsd\n" + + "dsf\n" + "ds\n" + "fds\n" + "fds\nfs"); + addComponent(textArea); + Button button = new Button("Scroll"); + button.addListener(new ClickListener() { + + public void buttonClick(ClickEvent event) { + textArea.setCursorPosition(getPosition()); + } + }); + Button wrap = new Button("Set wrap"); + wrap.addListener(new ClickListener() { + + public void buttonClick(ClickEvent event) { + textArea.setWordwrap(false); + } + }); + + Button toBegin = new Button("To begin"); + toBegin.addListener(new ClickListener() { + + public void buttonClick(ClickEvent event) { + position = 3; + } + }); + + Button toMiddle = new Button("To middle"); + toMiddle.addListener(new ClickListener() { + + public void buttonClick(ClickEvent event) { + position = 130; + } + }); + + Button toEnd = new Button("To end"); + toEnd.addListener(new ClickListener() { + + public void buttonClick(ClickEvent event) { + position = textArea.getValue().toString().length(); + } + }); + + addComponent(button); + addComponent(wrap); + addComponent(toBegin); + addComponent(toMiddle); + addComponent(toEnd); + } + + @Override + protected String getDescription() { + return "Tests scrolling for TextArea with different word wrapping settings. " + + "Sets cursor position at the beginning, middle and the end " + + "of text and checks textarea is scrolled."; + } + + @Override + protected Integer getTicketNumber() { + return 8769; + } + + private int getPosition() { + return position; + } + +} diff --git a/uitest/src/com/vaadin/tests/components/ui/UITabIndex.html b/uitest/src/com/vaadin/tests/components/ui/UITabIndex.html new file mode 100644 index 0000000000..fa083f1489 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/ui/UITabIndex.html @@ -0,0 +1,57 @@ +<?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:8888/" /> +<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.ui.UITabIndex?restartApplication</td> + <td></td> +</tr> +<tr> + <td>assertAttribute</td> + <td>vaadin=runcomvaadintestscomponentsuiUITabIndex::@tabIndex</td> + <td>1</td> +</tr> +<tr> + <td>click</td> + <td>vaadin=runcomvaadintestscomponentsuiUITabIndex::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VButton[0]/domChild[0]/domChild[0]</td> + <td></td> +</tr> +<tr> + <td>assertAttribute</td> + <td>vaadin=runcomvaadintestscomponentsuiUITabIndex::@tabIndex</td> + <td>-1</td> +</tr> +<tr> + <td>click</td> + <td>vaadin=runcomvaadintestscomponentsuiUITabIndex::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[1]/VButton[0]/domChild[0]/domChild[0]</td> + <td></td> +</tr> +<tr> + <td>assertAttribute</td> + <td>vaadin=runcomvaadintestscomponentsuiUITabIndex::@tabIndex</td> + <td>0</td> +</tr> +<tr> + <td>click</td> + <td>vaadin=runcomvaadintestscomponentsuiUITabIndex::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[2]/VButton[0]/domChild[0]/domChild[0]</td> + <td></td> +</tr> +<tr> + <td>assertAttribute</td> + <td>vaadin=runcomvaadintestscomponentsuiUITabIndex::@tabIndex</td> + <td>1</td> +</tr> + +</tbody></table> +</body> +</html> diff --git a/uitest/src/com/vaadin/tests/components/ui/UITabIndex.java b/uitest/src/com/vaadin/tests/components/ui/UITabIndex.java new file mode 100644 index 0000000000..083eaf3f7d --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/ui/UITabIndex.java @@ -0,0 +1,51 @@ +package com.vaadin.tests.components.ui; + +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.Button; +import com.vaadin.ui.Button.ClickEvent; +import com.vaadin.ui.Button.ClickListener; + +public class UITabIndex extends AbstractTestUI { + + @Override + protected void setup(VaadinRequest request) { + Button b; + + b = new Button("Set tabIndex to -1"); + b.addClickListener(new ClickListener() { + @Override + public void buttonClick(ClickEvent event) { + setTabIndex(-1); + } + }); + addComponent(b); + b = new Button("Set tabIndex to 0"); + b.addClickListener(new ClickListener() { + @Override + public void buttonClick(ClickEvent event) { + setTabIndex(0); + } + }); + addComponent(b); + b = new Button("Set tabIndex to 1"); + b.addClickListener(new ClickListener() { + @Override + public void buttonClick(ClickEvent event) { + setTabIndex(1); + } + }); + addComponent(b); + } + + @Override + protected String getTestDescription() { + return "Tests tab index handling for UI"; + } + + @Override + protected Integer getTicketNumber() { + return 11129; + } + +} diff --git a/uitest/test.xml b/uitest/test.xml index e2c14b53af..5ff39c425d 100644 --- a/uitest/test.xml +++ b/uitest/test.xml @@ -8,7 +8,7 @@ <!-- Configuration --> <!-- ================================================================== --> <!-- Browsers to use for testing --> - <property name="browsers-windows" value="winxp-ie8,win7-ie9,win7-ie10,winxp-firefox17-esr,winxp-safari5,winxp-googlechrome21,winxp-opera11" /> + <property name="browsers-windows" value="winxp-ie8,win7-ie9,win7-ie10,winxp-firefox17-esr,winxp-safari5,winxp-googlechrome21,winxp-opera12" /> <property name="browsers-linux" value="linux-firefox3,linux-opera10,linux-googlechrome8" /> <property name="browsers-mac" value="osx-firefox3,osx-opera10,osx-googlechrome8,osx-safari4,osx-safari5" /> |