diff options
author | Leif Åstrand <leif@vaadin.com> | 2013-05-10 16:53:33 +0300 |
---|---|---|
committer | Leif Åstrand <leif@vaadin.com> | 2013-05-10 16:53:33 +0300 |
commit | 42d94768bfacb3d831e125ae33eeb4b9fa1d8a53 (patch) | |
tree | a09cd9d99d1be99dd6600a90db07fb08d15af28a | |
parent | 762c924a8bf05f57b8af7108d7bb6a9c59dcc6c6 (diff) | |
parent | 19e27a15ca765de477fbe929a1cb6a7412c523f7 (diff) | |
download | vaadin-framework-42d94768bfacb3d831e125ae33eeb4b9fa1d8a53.tar.gz vaadin-framework-42d94768bfacb3d831e125ae33eeb4b9fa1d8a53.zip |
Merge changes from origin/7.0
7d9f544 Test for #11396 (merged from 6.8 branch). Depends on a blur event so cannot be autotested with TB.
1b18807 Remove pre-loader element after pre-loading, fixes #10863
ce9c818 Instead of applying workaround to the root panel, apply it to the sub window content element instead to prevent scrolling of the document when a sub window is removed. #11713 (#10776)
3f5d022 Liferay 6.2 compatibility (#11751)
ffd1c1b Don't ignore child component margins in AbstractOrderedLayout (#11553)
62ae5e1 More verbose output from running Jetty
21d9b67 Add a large number of debug calls to VFilterSelect (disabled by default)
bdb7931 Merge test for #11623 to 7.0.
19e27a1 Move suggestion popup width calculation from connector to VFilterSelect
Change-Id: I2d980126599e55fa5e4f6ec523dca16ba54107b5
14 files changed, 592 insertions, 52 deletions
diff --git a/client/src/com/vaadin/client/ResourceLoader.java b/client/src/com/vaadin/client/ResourceLoader.java index b3b9ac7256..7fc8b4f9f3 100644 --- a/client/src/com/vaadin/client/ResourceLoader.java +++ b/client/src/com/vaadin/client/ResourceLoader.java @@ -50,8 +50,8 @@ public class ResourceLoader { * Event fired when a resource has been loaded. */ public static class ResourceLoadEvent { - private ResourceLoader loader; - private String resourceUrl; + private final ResourceLoader loader; + private final String resourceUrl; private final boolean preload; /** @@ -286,25 +286,35 @@ public class ResourceLoader { // Inject loader element if this is the first time this is preloaded // AND the resources isn't already being loaded in the normal way - Element element = getPreloadElement(url); + final Element element = getPreloadElement(url); addOnloadHandler(element, new ResourceLoadListener() { @Override public void onLoad(ResourceLoadEvent event) { fireLoad(event); + Document.get().getBody().removeChild(element); } @Override public void onError(ResourceLoadEvent event) { fireError(event); + Document.get().getBody().removeChild(element); } }, event); - // TODO Remove object when loaded (without causing spinner in FF) Document.get().getBody().appendChild(element); } } private static Element getPreloadElement(String url) { + /*- + * TODO + * In Chrome, FF: + * <object> does not fire event if resource is 404 -> eternal spinner. + * <img> always fires onerror -> no way to know if it loaded -> eternal spinner + * <script type="text/javascript> fires, but also executes -> not preloading + * <script type="text/cache"> does not fire events + * XHR not tested - should work, probably causes other issues + -*/ if (BrowserInfo.get().isIE()) { ScriptElement element = Document.get().createScriptElement(); element.setSrc(url); diff --git a/client/src/com/vaadin/client/ui/VFilterSelect.java b/client/src/com/vaadin/client/ui/VFilterSelect.java index 5ec7039462..05535686d5 100644 --- a/client/src/com/vaadin/client/ui/VFilterSelect.java +++ b/client/src/com/vaadin/client/ui/VFilterSelect.java @@ -205,6 +205,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler, */ SuggestionPopup() { super(true, false, true); + debug("VFS.SP: constructor()"); setOwner(VFilterSelect.this); menu = new SuggestionMenu(); setWidget(menu); @@ -243,6 +244,11 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler, final Collection<FilterSelectSuggestion> currentSuggestions, final int currentPage, final int totalSuggestions) { + if (enableDebug) { + debug("VFS.SP: showSuggestions(" + currentSuggestions + ", " + + currentPage + ", " + totalSuggestions + ")"); + } + /* * We need to defer the opening of the popup so that the parent DOM * has stabilized so we can calculate an absolute top and left @@ -310,6 +316,9 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler, * @param active */ private void setNextButtonActive(boolean active) { + if (enableDebug) { + debug("VFS.SP: setNextButtonActive(" + active + ")"); + } if (active) { DOM.sinkEvents(down, Event.ONCLICK); down.setClassName(VFilterSelect.this.getStylePrimaryName() @@ -327,6 +336,10 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler, * @param active */ private void setPrevButtonActive(boolean active) { + if (enableDebug) { + debug("VFS.SP: setPrevButtonActive(" + active + ")"); + } + if (active) { DOM.sinkEvents(up, Event.ONCLICK); up.setClassName(VFilterSelect.this.getStylePrimaryName() @@ -343,6 +356,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler, * Selects the next item in the filtered selections */ public void selectNextItem() { + debug("VFS.SP: selectNextItem()"); final MenuItem cur = menu.getSelectedItem(); final int index = 1 + menu.getItems().indexOf(cur); if (menu.getItems().size() > index) { @@ -362,6 +376,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler, * Selects the previous item in the filtered selections */ public void selectPrevItem() { + debug("VFS.SP: selectPrevItem()"); final MenuItem cur = menu.getSelectedItem(); final int index = -1 + menu.getItems().indexOf(cur); if (index > -1) { @@ -396,6 +411,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler, @Override public void run() { + debug("VFS.SP.LPS: run()"); if (pagesToScroll != 0) { if (!waitingForFilteringResponse) { /* @@ -416,6 +432,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler, } public void scrollUp() { + debug("VFS.SP.LPS: scrollUp()"); if (currentPage + pagesToScroll > 0) { pagesToScroll--; cancel(); @@ -424,6 +441,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler, } public void scrollDown() { + debug("VFS.SP.LPS: scrollDown()"); if (totalMatches > (currentPage + pagesToScroll + 1) * pageLength) { pagesToScroll++; @@ -443,6 +461,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler, @Override public void onBrowserEvent(Event event) { + debug("VFS.SP: onBrowserEvent()"); if (event.getTypeInt() == Event.ONCLICK) { final Element target = DOM.eventGetTarget(event); if (target == up || target == DOM.getChild(up, 0)) { @@ -476,6 +495,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler, * Should the paging be turned on? */ public void setPagingEnabled(boolean paging) { + debug("VFS.SP: setPagingEnabled(" + paging + ")"); if (isPagingEnabled == paging) { return; } @@ -501,6 +521,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler, @Override public void setPosition(int offsetWidth, int offsetHeight) { + debug("VFS.SP: setPosition()"); int top = -1; int left = -1; @@ -579,6 +600,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler, * @return true if popup was just closed */ public boolean isJustClosed() { + debug("VFS.SP: justClosed()"); final long now = (new Date()).getTime(); return (lastAutoClosed > 0 && (now - lastAutoClosed) < 200); } @@ -593,6 +615,9 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler, @Override public void onClose(CloseEvent<PopupPanel> event) { + if (enableDebug) { + debug("VFS.SP: onClose(" + event.isAutoClosed() + ")"); + } if (event.isAutoClosed()) { lastAutoClosed = (new Date()).getTime(); } @@ -608,6 +633,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler, */ public void updateStyleNames(UIDL uidl, AbstractComponentState componentState) { + debug("VFS.SP: updateStyleNames()"); setStyleName(VFilterSelect.this.getStylePrimaryName() + "-suggestpopup"); menu.setStyleName(VFilterSelect.this.getStylePrimaryName() @@ -643,6 +669,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler, @Override public void execute() { + debug("VFS.SM: delayedImageLoadExecutioner()"); if (suggestionPopup.isVisible() && suggestionPopup.isAttached()) { setWidth(""); @@ -660,6 +687,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler, */ SuggestionMenu() { super(true); + debug("VFS.SM: constructor()"); addDomHandler(this, LoadEvent.getType()); } @@ -683,6 +711,9 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler, */ public void setSuggestions( Collection<FilterSelectSuggestion> suggestions) { + if (enableDebug) { + debug("VFS.SM: setSuggestions(" + suggestions + ")"); + } // Reset keyboard selection when contents is updated to avoid // reusing old, invalid data setKeyboardSelectedItem(null); @@ -708,6 +739,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler, * is made or on a blur event. */ public void doSelectedItemAction() { + debug("VFS.SM: doSelectedItemAction()"); // do not send a value change event if null was and stays selected final String enteredItemValue = tb.getText(); if (nullSelectionAllowed && "".equals(enteredItemValue) @@ -737,6 +769,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler, * Triggered after a selection has been made */ public void doPostFilterSelectedItemAction() { + debug("VFS.SM: doPostFilterSelectedItemAction()"); final MenuItem item = getSelectedItem(); final String enteredItemValue = tb.getText(); @@ -833,6 +866,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler, @Override public void onLoad(LoadEvent event) { + debug("VFS.SM: onLoad()"); // Handle icon onload events to ensure shadow is resized // correctly delayedImageLoadExecutioner.trigger(); @@ -840,6 +874,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler, } public void selectFirstItem() { + debug("VFS.SM: selectFirstItem()"); MenuItem firstItem = getItems().get(0); selectItem(firstItem); } @@ -853,6 +888,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler, } public void selectLastItem() { + debug("VFS.SM: selectLastItem()"); List<MenuItem> items = getItems(); MenuItem lastItem = items.get(items.size() - 1); selectItem(lastItem); @@ -1145,6 +1181,10 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler, * Whether to send the options request immediately */ private void filterOptions(int page, String filter, boolean immediate) { + if (enableDebug) { + debug("VFS: filterOptions(" + page + ", " + filter + ", " + + immediate + ")"); + } if (filter.equals(lastFilter) && currentPage == page) { if (!suggestionPopup.isAttached()) { suggestionPopup.showSuggestions(currentSuggestions, @@ -1171,10 +1211,12 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler, /** For internal use only. May be removed or replaced in the future. */ public void updateReadOnly() { + debug("VFS: updateReadOnly()"); tb.setReadOnly(readonly || !textInputEnabled); } public void setTextInputEnabled(boolean textInputEnabled) { + debug("VFS: setTextInputEnabled()"); // Always update styles as they might have been overwritten if (textInputEnabled) { removeStyleDependentName(STYLE_NO_INPUT); @@ -1200,6 +1242,9 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler, * the text to set in the text box */ public void setTextboxText(final String text) { + if (enableDebug) { + debug("VFS: setTextboxText(" + text + ")"); + } tb.setText(text); } @@ -1208,6 +1253,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler, * in the text box if nothing has been entered. */ public void setPromptingOn() { + debug("VFS: setPromptingOn()"); if (!prompting) { prompting = true; addStyleDependentName(CLASSNAME_PROMPT); @@ -1225,6 +1271,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler, * The text the text box should contain. */ public void setPromptingOff(String text) { + debug("VFS: setPromptingOff()"); setTextboxText(text); if (prompting) { prompting = false; @@ -1239,6 +1286,10 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler, * The suggestion that just got selected. */ public void onSuggestionSelected(FilterSelectSuggestion suggestion) { + if (enableDebug) { + debug("VFS: onSuggestionSelected(" + suggestion.caption + ": " + + suggestion.key + ")"); + } updateSelectionWhenReponseIsReceived = false; currentSuggestion = suggestion; @@ -1334,7 +1385,9 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler, if (enabled && !readonly) { int keyCode = event.getNativeKeyCode(); - debug("key down: " + keyCode); + if (enableDebug) { + debug("VFS: key down: " + keyCode); + } if (waitingForFilteringResponse && navigationKeyCodes.contains(keyCode)) { /* @@ -1342,18 +1395,25 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler, * waiting for a response. This avoids flickering, disappearing * items, wrongly interpreted responses and more. */ - debug("Ignoring " + keyCode - + " because we are waiting for a filtering response"); + if (enableDebug) { + debug("Ignoring " + + keyCode + + " because we are waiting for a filtering response"); + } DOM.eventPreventDefault(DOM.eventGetCurrentEvent()); event.stopPropagation(); return; } if (suggestionPopup.isAttached()) { - debug("Keycode " + keyCode + " target is popup"); + if (enableDebug) { + debug("Keycode " + keyCode + " target is popup"); + } popupKeyDown(event); } else { - debug("Keycode " + keyCode + " target is text field"); + if (enableDebug) { + debug("Keycode " + keyCode + " target is text field"); + } inputFieldKeyDown(event); } } @@ -1372,6 +1432,9 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler, * The KeyDownEvent */ private void inputFieldKeyDown(KeyDownEvent event) { + if (enableDebug) { + debug("VFS: inputFieldKeyDown(" + event.getNativeKeyCode() + ")"); + } switch (event.getNativeKeyCode()) { case KeyCodes.KEY_DOWN: case KeyCodes.KEY_UP: @@ -1414,6 +1477,9 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler, * The KeyDownEvent of the key */ private void popupKeyDown(KeyDownEvent event) { + if (enableDebug) { + debug("VFS: popupKeyDown(" + event.getNativeKeyCode() + ")"); + } // Propagation of handled events is stopped so other handlers such as // shortcut key handlers do not also handle the same events. switch (event.getNativeKeyCode()) { @@ -1494,6 +1560,9 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler, @Override public void onKeyUp(KeyUpEvent event) { + if (enableDebug) { + debug("VFS: onKeyUp(" + event.getNativeKeyCode() + ")"); + } if (enabled && !readonly) { switch (event.getNativeKeyCode()) { case KeyCodes.KEY_ENTER: @@ -1521,6 +1590,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler, * Resets the Select to its initial state */ private void reset() { + debug("VFS: reset()"); if (currentSuggestion != null) { String text = currentSuggestion.getReplacementString(); setPromptingOff(text); @@ -1543,6 +1613,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler, @Override public void onClick(ClickEvent event) { + debug("VFS: onClick()"); if (textInputEnabled && event.getNativeEvent().getEventTarget().cast() == tb .getElement()) { @@ -1569,6 +1640,29 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler, } /** + * Update minimum width for FilterSelect textarea based on input prompt and + * suggestions. + * <p> + * For internal use only. May be removed or replaced in the future. + */ + public void updateSuggestionPopupMinWidth() { + // used only to calculate minimum width + String captions = Util.escapeHTML(inputPrompt); + + for (FilterSelectSuggestion suggestion : currentSuggestions) { + // Collect captions so we can calculate minimum width for + // textarea + if (captions.length() > 0) { + captions += "|"; + } + captions += Util.escapeHTML(suggestion.getReplacementString()); + } + + // Calculate minimum textarea width + suggestionPopupMinWidth = minWidth(captions); + } + + /** * Calculate minimum width for FilterSelect textarea. * <p> * For internal use only. May be removed or replaced in the future. @@ -1610,6 +1704,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler, @Override public void onFocus(FocusEvent event) { + debug("VFS: onFocus()"); /* * When we disable a blur event in ie we need to refocus the textfield. @@ -1648,6 +1743,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler, @Override public void onBlur(BlurEvent event) { + debug("VFS: onBlur()"); if (BrowserInfo.get().isIE() && preventNextBlurEventInIE) { /* @@ -1708,6 +1804,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler, @Override public void focus() { + debug("VFS: focus()"); focused = true; if (prompting && !readonly) { setPromptingOff(""); @@ -1807,6 +1904,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler, */ if (BrowserInfo.get().isIE() && focused) { preventNextBlurEventInIE = true; + debug("VFS: Going to prevent next blur event on IE"); } } } diff --git a/client/src/com/vaadin/client/ui/VWindow.java b/client/src/com/vaadin/client/ui/VWindow.java index 0ed5bd57bd..38dfdba1b8 100644 --- a/client/src/com/vaadin/client/ui/VWindow.java +++ b/client/src/com/vaadin/client/ui/VWindow.java @@ -415,14 +415,6 @@ public class VWindow extends VOverlay implements ShortcutActionHandlerOwner, @Override public void hide() { - if (vaadinModality) { - hideModalityCurtain(); - } - super.hide(); - - // 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 @@ -439,20 +431,28 @@ public class VWindow extends VOverlay implements ShortcutActionHandlerOwner, if (BrowserInfo.get().isIE8()) { fixIE8FocusCaptureIssue(); } + + if (vaadinModality) { + hideModalityCurtain(); + } + super.hide(); + + // Remove window from windowOrder to avoid references being left + // hanging. + windowOrder.remove(this); } private void fixIE8FocusCaptureIssue() { Element e = DOM.createInputText(); Style elemStyle = e.getStyle(); elemStyle.setPosition(Position.ABSOLUTE); - elemStyle.setLeft(-10, Unit.PX); + elemStyle.setTop(-10, Unit.PX); elemStyle.setWidth(0, Unit.PX); elemStyle.setHeight(0, Unit.PX); - Element rootPanel = RootPanel.getBodyElement(); - rootPanel.appendChild(e); + contentPanel.getElement().appendChild(e); e.focus(); - rootPanel.removeChild(e); + contentPanel.getElement().removeChild(e); } /** For internal use only. May be removed or replaced in the future. */ diff --git a/client/src/com/vaadin/client/ui/combobox/ComboBoxConnector.java b/client/src/com/vaadin/client/ui/combobox/ComboBoxConnector.java index 98d2651849..e96d27032b 100644 --- a/client/src/com/vaadin/client/ui/combobox/ComboBoxConnector.java +++ b/client/src/com/vaadin/client/ui/combobox/ComboBoxConnector.java @@ -20,7 +20,6 @@ import java.util.Iterator; import com.vaadin.client.ApplicationConnection; import com.vaadin.client.Paintable; import com.vaadin.client.UIDL; -import com.vaadin.client.Util; import com.vaadin.client.ui.AbstractFieldConnector; import com.vaadin.client.ui.SimpleManagedLayout; import com.vaadin.client.ui.VFilterSelect; @@ -124,9 +123,6 @@ public class ComboBoxConnector extends AbstractFieldConnector implements getWidget().totalMatches = 0; } - // used only to calculate minimum popup width - String captions = Util.escapeHTML(getWidget().inputPrompt); - for (final Iterator<?> i = options.getChildIterator(); i.hasNext();) { final UIDL optionUidl = (UIDL) i.next(); final FilterSelectSuggestion suggestion = getWidget().new FilterSelectSuggestion( @@ -152,12 +148,6 @@ public class ComboBoxConnector extends AbstractFieldConnector implements getWidget().currentSuggestion = suggestion; getWidget().setSelectedItemIcon(suggestion.getIconUri()); } - - // Collect captions so we can calculate minimum width for textarea - if (captions.length() > 0) { - captions += "|"; - } - captions += Util.escapeHTML(suggestion.getReplacementString()); } if ((!getWidget().waitingForFilteringResponse || getWidget().popupOpenerClicked) @@ -222,8 +212,8 @@ public class ComboBoxConnector extends AbstractFieldConnector implements } } - // Calculate minumum textarea width - getWidget().suggestionPopupMinWidth = getWidget().minWidth(captions); + // Calculate minimum textarea width + getWidget().updateSuggestionPopupMinWidth(); getWidget().popupOpenerClicked = false; diff --git a/client/src/com/vaadin/client/ui/orderedlayout/VAbstractOrderedLayout.java b/client/src/com/vaadin/client/ui/orderedlayout/VAbstractOrderedLayout.java index d8b0888936..b5a6262693 100644 --- a/client/src/com/vaadin/client/ui/orderedlayout/VAbstractOrderedLayout.java +++ b/client/src/com/vaadin/client/ui/orderedlayout/VAbstractOrderedLayout.java @@ -503,14 +503,10 @@ public class VAbstractOrderedLayout extends FlowPanel { // TODO check caption position if (vertical) { int size = layoutManager.getOuterHeight(slot - .getWidget().getElement()) - - layoutManager.getMarginHeight(slot - .getWidget().getElement()); + .getWidget().getElement()); if (slot.hasCaption()) { size += layoutManager.getOuterHeight(slot - .getCaptionElement()) - - layoutManager.getMarginHeight(slot - .getCaptionElement()); + .getCaptionElement()); } if (size > 0) { totalSize += size; @@ -518,14 +514,10 @@ public class VAbstractOrderedLayout extends FlowPanel { } else { int max = -1; max = layoutManager.getOuterWidth(slot.getWidget() - .getElement()) - - layoutManager.getMarginWidth(slot - .getWidget().getElement()); + .getElement()); if (slot.hasCaption()) { int max2 = layoutManager.getOuterWidth(slot - .getCaptionElement()) - - layoutManager.getMarginWidth(slot - .getCaptionElement()); + .getCaptionElement()); max = Math.max(max, max2); } if (max > 0) { diff --git a/server/src/com/vaadin/server/VaadinPortlet.java b/server/src/com/vaadin/server/VaadinPortlet.java index b383878f28..327ce78a6c 100644 --- a/server/src/com/vaadin/server/VaadinPortlet.java +++ b/server/src/com/vaadin/server/VaadinPortlet.java @@ -17,6 +17,7 @@ package com.vaadin.server; import java.io.IOException; import java.io.Serializable; +import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Enumeration; import java.util.Map; @@ -40,7 +41,7 @@ import javax.portlet.ResourceResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; -import com.liferay.portal.kernel.util.PortalClassInvoker; +import com.liferay.portal.kernel.util.PortalClassLoaderUtil; import com.liferay.portal.kernel.util.PropsUtil; import com.vaadin.server.communication.PortletDummyRequestHandler; import com.vaadin.server.communication.PortletUIInitHandler; @@ -171,19 +172,75 @@ public class VaadinPortlet extends GenericPortlet implements Constants, return PropsUtil.get(name); } + /** + * Simplified version of what Liferay PortalClassInvoker did. This is + * used because the API of PortalClassInvoker has changed in Liferay + * 6.2. + * + * This simply uses reflection with Liferay class loader. Parameters are + * Strings to avoid static dependencies and to load all classes with + * Liferay's own class loader. Only static utility methods are + * supported. + * + * This method is for internal use only and may change in future + * versions. + * + * @param className + * name of the Liferay class to call + * @param methodName + * name of the method to call + * @param parameterClassName + * name of the parameter class of the method + * @throws Exception + * @return return value of the invoked method + */ + private static Object invokeStaticLiferayMethod(String className, + String methodName, Object argument, String parameterClassName) + throws Exception { + Thread currentThread = Thread.currentThread(); + + ClassLoader contextClassLoader = currentThread + .getContextClassLoader(); + + try { + // this should be available across all Liferay versions with no + // problematic static dependencies + ClassLoader portalClassLoader = PortalClassLoaderUtil + .getClassLoader(); + // this is in case the class loading triggers code that + // explicitly + // uses current thread class loader + currentThread.setContextClassLoader(portalClassLoader); + + Class<?> targetClass = portalClassLoader.loadClass(className); + Class<?> parameterClass = portalClassLoader + .loadClass(parameterClassName); + Method method = targetClass.getMethod(methodName, + parameterClass); + + return method.invoke(null, new Object[] { argument }); + } catch (InvocationTargetException ite) { + throw (Exception) ite.getCause(); + } finally { + currentThread.setContextClassLoader(contextClassLoader); + } + } + private static HttpServletRequest getOriginalRequest( PortletRequest request) { try { // httpRequest = PortalUtil.getHttpServletRequest(request); - HttpServletRequest httpRequest = (HttpServletRequest) PortalClassInvoker - .invoke("com.liferay.portal.util.PortalUtil", - "getHttpServletRequest", request); + HttpServletRequest httpRequest = (HttpServletRequest) invokeStaticLiferayMethod( + "com.liferay.portal.util.PortalUtil", + "getHttpServletRequest", request, + "javax.portlet.PortletRequest"); // httpRequest = // PortalUtil.getOriginalServletRequest(httpRequest); - httpRequest = (HttpServletRequest) PortalClassInvoker.invoke( + httpRequest = (HttpServletRequest) invokeStaticLiferayMethod( "com.liferay.portal.util.PortalUtil", - "getOriginalServletRequest", httpRequest); + "getOriginalServletRequest", httpRequest, + "javax.servlet.http.HttpServletRequest"); return httpRequest; } catch (Exception e) { throw new IllegalStateException("Liferay request not detected", diff --git a/tests/testbench/com/vaadin/tests/components/textfield/TextChangeListenerLosesFocus.html b/tests/testbench/com/vaadin/tests/components/textfield/TextChangeListenerLosesFocus.html new file mode 100644 index 0000000000..d0dec8ce40 --- /dev/null +++ b/tests/testbench/com/vaadin/tests/components/textfield/TextChangeListenerLosesFocus.html @@ -0,0 +1,72 @@ +<?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:8068/" /> +<title>TextChangeListenerLosesFocus</title> +</head> +<body> +<table cellpadding="1" cellspacing="1" border="1"> +<thead> +<tr><td rowspan="1" colspan="3">TextChangeListenerLosesFocus</td></tr> +</thead><tbody> +<tr> + <td>open</td> + <td>/run/com.vaadin.tests.components.textfield.TextChangeListenerLosesFocus?restartApplication</td> + <td></td> +</tr> +<tr> + <td>focus</td> + <td>test-textfield</td> + <td></td> +</tr> +<tr> + <td>enterCharacter</td> + <td>test-textfield</td> + <td>123</td> +</tr> +<tr> + <td>pause</td> + <td>1000</td> + <td></td> +</tr> +<tr> + <td>assertValue</td> + <td>test-textfield</td> + <td>Updated by TextChangeListener</td> +</tr> +<tr> + <td>assertCSSClass</td> + <td>test-textfield</td> + <td>v-textfield-focus</td> +</tr> +<tr> + <td>focus</td> + <td>test-textarea</td> + <td></td> +</tr> +<tr> + <td>enterCharacter</td> + <td>test-textarea</td> + <td>123</td> +</tr> +<tr> + <td>pause</td> + <td>1000</td> + <td></td> +</tr> +<tr> + <td>assertValue</td> + <td>test-textarea</td> + <td>Updated by TextChangeListener</td> +</tr> +<tr> + <td>assertCSSClass</td> + <td>test-textarea</td> + <td>v-textarea-focus</td> +</tr> + +</tbody></table> +</body> +</html> diff --git a/uitest/src/com/vaadin/launcher/DevelopmentServerLauncher.java b/uitest/src/com/vaadin/launcher/DevelopmentServerLauncher.java index ad372bd5bc..070cd2834d 100644 --- a/uitest/src/com/vaadin/launcher/DevelopmentServerLauncher.java +++ b/uitest/src/com/vaadin/launcher/DevelopmentServerLauncher.java @@ -22,9 +22,20 @@ import java.io.OutputStream; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; +import java.text.SimpleDateFormat; +import java.util.Calendar; import java.util.HashMap; import java.util.Map; +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.nio.SelectChannelConnector; @@ -163,6 +174,25 @@ public class DevelopmentServerLauncher { webappcontext.setWar(serverArgs.get("webroot")); server.setHandler(webappcontext); + // --slowdown=/run/APP/PUBLISHED/*,/other/path/asd.jpg + // slows down specified paths + if (serverArgs.containsKey("slowdown")) { + String[] paths = serverArgs.get("slowdown").split(","); + for (String p : paths) { + System.out.println("Slowing down: " + p); + webappcontext.addFilter(SlowFilter.class, p, 1); + } + } + // --cache=/run/APP/PUBLISHED/*,/other/path/asd.jpg + // caches specified paths + if (serverArgs.containsKey("cache")) { + String[] paths = serverArgs.get("cache").split(","); + for (String p : paths) { + System.out.println("Enabling cache for: " + p); + webappcontext.addFilter(CacheFilter.class, p, 1); + } + } + try { server.start(); @@ -243,4 +273,83 @@ public class DevelopmentServerLauncher { return map; } + /** + * Sleeps for 2-5 seconds when serving resources that matches given + * pathSpec. --slowdown=/run/APP/PUBLISHED/*,/other/path/asd.jpg + */ + public static class SlowFilter implements Filter { + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + // TODO Auto-generated method stub + } + + @Override + public void doFilter(ServletRequest request, ServletResponse response, + FilterChain chain) throws IOException, ServletException { + + String path = ((HttpServletRequest) request).getPathInfo(); + long delay = Math.round(Math.random() * 3000) + 2000; + System.out.println("Delaying " + path + " for " + delay); + + try { + Thread.sleep(delay); + } catch (InterruptedException e) { + System.out.println("Delay interrupted for " + path); + } finally { + System.out.println("Resuming " + path); + } + + chain.doFilter(request, response); + } + + @Override + public void destroy() { + // TODO Auto-generated method stub + } + + } + + /** + * Adds "Expires" and "Cache-control" headers when serving resources that + * match given pathSpec, in order to cache resource for CACHE_MINUTES. + * --cache=/run/APP/PUBLISHED/*,/other/path/asd.jpg + */ + public static class CacheFilter implements Filter { + + private static final int CACHE_MINUTES = 1; + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + // TODO Auto-generated method stub + } + + @Override + public void doFilter(ServletRequest request, ServletResponse response, + FilterChain chain) throws IOException, ServletException { + + String path = ((HttpServletRequest) request).getPathInfo(); + System.out.println("Caching " + path + " for " + CACHE_MINUTES + + " minutes"); + + Calendar calendar = Calendar.getInstance(); + calendar.add(Calendar.MINUTE, CACHE_MINUTES); + + String expires = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z") + .format(calendar.getTime()); + + ((HttpServletResponse) response).setHeader("Expires", expires); + ((HttpServletResponse) response).setHeader("Cache-Control", + "max-age=" + (CACHE_MINUTES * 60)); + + chain.doFilter(request, response); + } + + @Override + public void destroy() { + // TODO Auto-generated method stub + } + + } + } diff --git a/uitest/src/com/vaadin/tests/components/textarea/TextDisappearsOnBlur.java b/uitest/src/com/vaadin/tests/components/textarea/TextDisappearsOnBlur.java new file mode 100644 index 0000000000..2d2cf29e9e --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/textarea/TextDisappearsOnBlur.java @@ -0,0 +1,29 @@ +package com.vaadin.tests.components.textarea; + +import com.vaadin.tests.components.TestBase; +import com.vaadin.ui.TextArea; + +public class TextDisappearsOnBlur extends TestBase { + + @Override + protected void setup() { + TextArea ta = new TextArea(); + addComponent(ta); + + // All three are required for the bug to manifest + ta.setMaxLength(50); + ta.setImmediate(true); + ta.setRequired(true); + } + + @Override + protected String getDescription() { + return "Text disappears from TextArea in IE 6-8 when focus changes"; + } + + @Override + protected Integer getTicketNumber() { + return 11396; + } + +} diff --git a/uitest/src/com/vaadin/tests/components/textfield/TextChangeListenerLosesFocus.java b/uitest/src/com/vaadin/tests/components/textfield/TextChangeListenerLosesFocus.java new file mode 100644 index 0000000000..25ca46333a --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/textfield/TextChangeListenerLosesFocus.java @@ -0,0 +1,69 @@ +/* + * Copyright 2012 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.textfield; + +import com.vaadin.event.FieldEvents.TextChangeEvent; +import com.vaadin.event.FieldEvents.TextChangeListener; +import com.vaadin.tests.components.TestBase; +import com.vaadin.tests.util.TestUtils; +import com.vaadin.ui.AbstractTextField; +import com.vaadin.ui.Field; +import com.vaadin.ui.TextArea; +import com.vaadin.ui.TextField; + +public class TextChangeListenerLosesFocus extends TestBase { + + private final TextChangeListener listener = new TextChangeListener() { + public void textChange(TextChangeEvent event) { + final String value = event.getText(); + if (value.length() > 2) { + ((Field) event.getComponent()) + .setValue("Updated by TextChangeListener"); + } + } + }; + + @Override + protected void setup() { + TestUtils.injectCSS(getMainWindow(), + ".v-textfield-focus, .v-textarea-focus { " + + " background: #E8F0FF !important }"); + + AbstractTextField field = new TextField(); + field.setDebugId("test-textfield"); + field.setInputPrompt("Enter at least 3 characters"); + field.addListener(listener); + addComponent(field); + + field = new TextArea(); + field.setDebugId("test-textarea"); + field.setInputPrompt("Enter at least 3 characters"); + field.addListener(listener); + addComponent(field); + + } + + @Override + protected String getDescription() { + return "Updating a focused TextField overwrites the focus stylename"; + } + + @Override + protected Integer getTicketNumber() { + return 11623; + } +} diff --git a/uitest/src/com/vaadin/tests/layouts/MarginWithExpandRatio.html b/uitest/src/com/vaadin/tests/layouts/MarginWithExpandRatio.html new file mode 100644 index 0000000000..3132bdd16d --- /dev/null +++ b/uitest/src/com/vaadin/tests/layouts/MarginWithExpandRatio.html @@ -0,0 +1,27 @@ +<?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:8070/" /> +<title>MarginWithExpandRatio</title> +</head> +<body> +<table cellpadding="1" cellspacing="1" border="1"> +<thead> +<tr><td rowspan="1" colspan="3">MarginWithExpandRatio</td></tr> +</thead><tbody> +<tr> + <td>open</td> + <td>/run/MarginWithExpandRatio?restartApplication</td> + <td></td> +</tr> +<tr> + <td>screenCapture</td> + <td></td> + <td>no-overflow</td> +</tr> + +</tbody></table> +</body> +</html> diff --git a/uitest/src/com/vaadin/tests/layouts/MarginWithExpandRatio.java b/uitest/src/com/vaadin/tests/layouts/MarginWithExpandRatio.java new file mode 100644 index 0000000000..f6ee26e86f --- /dev/null +++ b/uitest/src/com/vaadin/tests/layouts/MarginWithExpandRatio.java @@ -0,0 +1,85 @@ +/* + * 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.layouts; + +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.tests.util.TestUtils; +import com.vaadin.ui.GridLayout; +import com.vaadin.ui.HorizontalLayout; +import com.vaadin.ui.Label; +import com.vaadin.ui.Layout; +import com.vaadin.ui.Panel; +import com.vaadin.ui.VerticalLayout; + +public class MarginWithExpandRatio extends AbstractTestUI { + + @Override + protected void setup(VaadinRequest request) { + TestUtils.injectCSS(this, + ".hugemargin { margin: 10px 20px !important; }"); + + HorizontalLayout hl = new HorizontalLayout(); + addLayoutTest(hl); + hl.setExpandRatio(hl.getComponent(0), 1.0f); + hl.setExpandRatio(hl.getComponent(2), 0.5f); + VerticalLayout vl = new VerticalLayout(); + addLayoutTest(vl); + vl.setExpandRatio(vl.getComponent(0), 1.0f); + vl.setExpandRatio(vl.getComponent(2), 0.5f); + + GridLayout gl = new GridLayout(2, 1); + addLayoutTest(gl); + gl.setColumnExpandRatio(0, 1.0f); + gl.setRowExpandRatio(0, 1.0f); + gl.setColumnExpandRatio(1, 0.5f); + gl.setRowExpandRatio(1, 0.5f); + } + + @Override + protected String getTestDescription() { + return "Layout content overflows if CSS margin used with expand ratio"; + } + + @Override + protected Integer getTicketNumber() { + return 11553; + } + + private void addLayoutTest(Layout l) { + l.setSizeFull(); + + Label lbl = new Label("First (expand ratio 1)"); + lbl.setSizeUndefined(); + l.addComponent(lbl); + + lbl = new Label("Second (margin 10px)"); + lbl.setSizeUndefined(); + lbl.addStyleName("hugemargin"); + l.addComponent(lbl); + + lbl = new Label("Third (margin+xr)"); + lbl.setSizeUndefined(); + lbl.addStyleName("hugemargin"); + l.addComponent(lbl); + + Panel p = new Panel(l.getClass().getSimpleName(), l); + p.setWidth("600px"); + p.setHeight("200px"); + addComponent(p); + } +} diff --git a/uitest/test.xml b/uitest/test.xml index 5ff39c425d..8228bd9d70 100644 --- a/uitest/test.xml +++ b/uitest/test.xml @@ -182,6 +182,7 @@ <sequential> <ant antfile="${test.xml.dir}/vaadin-server.xml" target="wait-for-startup" /> <antcall inheritall="true" inheritrefs="true" target="run-and-clean-up" /> + <echo message="All TestBench tests have been run" /> </sequential> </parallel> </target> diff --git a/uitest/vaadin-server.xml b/uitest/vaadin-server.xml index e02fab8564..5741d78525 100644 --- a/uitest/vaadin-server.xml +++ b/uitest/vaadin-server.xml @@ -8,7 +8,7 @@ <ivy:resolve file="${dir}/ivy.xml" /> <ivy:cachepath pathid="classpath.jetty" conf="jetty-run" /> - <java classname="org.mortbay.jetty.runner.Runner" fork="yes"> + <java classname="org.mortbay.jetty.runner.Runner" fork="yes" output="${vaadin.basedir}/result/jetty.java.out" resultproperty="resultCode"> <arg value="--port" /> <arg value="8888" /> <arg value="--out" /> @@ -19,6 +19,7 @@ <classpath refid="classpath.jetty" /> <jvmarg value="-ea" /> </java> + <echo message="Jetty process ended with result code ${resultCode}" /> </target> |