diff options
13 files changed, 502 insertions, 21 deletions
diff --git a/client/src/com/vaadin/client/extensions/BrowserPopupOpenerConnector.java b/client/src/com/vaadin/client/extensions/BrowserPopupOpenerConnector.java new file mode 100644 index 0000000000..2615444832 --- /dev/null +++ b/client/src/com/vaadin/client/extensions/BrowserPopupOpenerConnector.java @@ -0,0 +1,58 @@ +/* + * 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.client.extensions; + +import com.google.gwt.event.dom.client.ClickEvent; +import com.google.gwt.event.dom.client.ClickHandler; +import com.google.gwt.user.client.Window; +import com.google.gwt.user.client.ui.Widget; +import com.vaadin.client.ComponentConnector; +import com.vaadin.client.ServerConnector; +import com.vaadin.server.BrowserPopupOpener; +import com.vaadin.shared.ui.BrowserPopupExtensionState; +import com.vaadin.shared.ui.Connect; + +/** + * Client-side code for {@link BrowserPopupOpener} + * + * @author Vaadin Ltd + * @since 7.0.0 + */ +@Connect(BrowserPopupOpener.class) +public class BrowserPopupOpenerConnector extends AbstractExtensionConnector + implements ClickHandler { + + @Override + protected void extend(ServerConnector target) { + final Widget targetWidget = ((ComponentConnector) target).getWidget(); + + targetWidget.addDomHandler(this, ClickEvent.getType()); + } + + @Override + public BrowserPopupExtensionState getState() { + return (BrowserPopupExtensionState) super.getState(); + } + + @Override + public void onClick(ClickEvent event) { + String url = getResourceUrl("popup"); + if (url != null) { + Window.open(url, getState().target, getState().features); + } + } +} diff --git a/client/src/com/vaadin/client/extensions/FileDownloaderConnector.java b/client/src/com/vaadin/client/extensions/FileDownloaderConnector.java index d76efcc046..6308de9c05 100644 --- a/client/src/com/vaadin/client/extensions/FileDownloaderConnector.java +++ b/client/src/com/vaadin/client/extensions/FileDownloaderConnector.java @@ -1,3 +1,19 @@ +/* + * 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.client.extensions; import com.google.gwt.dom.client.Document; diff --git a/server/src/com/vaadin/server/BrowserPopupOpener.java b/server/src/com/vaadin/server/BrowserPopupOpener.java new file mode 100644 index 0000000000..c55fa65931 --- /dev/null +++ b/server/src/com/vaadin/server/BrowserPopupOpener.java @@ -0,0 +1,168 @@ +/* + * 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.server; + +import com.vaadin.shared.ApplicationConstants; +import com.vaadin.shared.ui.BrowserPopupExtensionState; +import com.vaadin.ui.AbstractComponent; +import com.vaadin.ui.UI; + +/** + * Component extension that opens a browser popup window when the extended + * component is clicked. + * + * @author Vaadin Ltd + * @since 7.0.0 + */ +public class BrowserPopupOpener extends AbstractExtension { + + private final BrowserPopupUIProvider uiProvider; + + /** + * Creates a popup opener that will open popups containing the provided UI + * class + * + * @param uiClass + * the UI class that should be opened when the extended component + * is clicked + */ + public BrowserPopupOpener(Class<? extends UI> uiClass) { + this(uiClass, generateUIClassUrl(uiClass)); + } + + /** + * Creates a popup opener that will open popups containing the provided UI + * using the provided path + * + * @param uiClass + * the UI class that should be opened when the extended component + * is clicked + * @param path + * the path that the UI should be bound to + */ + public BrowserPopupOpener(Class<? extends UI> uiClass, String path) { + // Create a Resource with a translated URL going to the VaadinService + this(new ExternalResource(ApplicationConstants.APP_PROTOCOL_PREFIX + + path), new BrowserPopupUIProvider(uiClass, path)); + } + + /** + * Creates a popup opener that will open popups to the provided URL + * + * @param url + * the URL to open in the popup + */ + public BrowserPopupOpener(String url) { + this(new ExternalResource(url)); + } + + /** + * Creates a popup opener that will open popups to the provided resource + * + * @param resource + * the resource to open in the popup + */ + public BrowserPopupOpener(Resource resource) { + this(resource, null); + } + + private BrowserPopupOpener(Resource resource, + BrowserPopupUIProvider uiProvider) { + this.uiProvider = uiProvider; + setResource("popup", resource); + } + + public void extend(AbstractComponent target) { + super.extend(target); + } + + /** + * Sets the target window name that will be used when opening the popup. If + * a popup has already been opened with the same name, the contents of that + * window will be replaced instead of opening a new window. If the name is + * <code>null</code> or <code>"blank"</code>, the popup will always be + * opened in a new window. + * + * @param popupName + * the target name for the popups + */ + public void setPopupName(String popupName) { + getState().target = popupName; + } + + /** + * Gets the popup target name. + * + * @see #setPopupName(String) + * + * @return the popup target string + */ + public String getPopupName() { + return getState().target; + } + + // Avoid breaking url to multiple lines + // @formatter:off + /** + * Sets the features for opening the popup. See e.g. + * {@link https://developer.mozilla.org/en-US/docs/DOM/window.open#Position_and_size_features} + * for a description of the commonly supported features. + * + * @param features a string with popup features, or <code>null</code> to use the default features. + */ + // @formatter:on + public void setFeatures(String features) { + getState().features = features; + } + + /** + * Gets the popup features. + * + * @see #setFeatures(String) + * @return + */ + public String getFeatures() { + return getState().features; + } + + @Override + protected BrowserPopupExtensionState getState() { + return (BrowserPopupExtensionState) super.getState(); + } + + @Override + public void attach() { + super.attach(); + if (uiProvider != null + && !getSession().getUIProviders().contains(uiProvider)) { + getSession().addUIProvider(uiProvider); + } + } + + @Override + public void detach() { + if (uiProvider != null) { + getSession().removeUIProvider(uiProvider); + } + super.detach(); + } + + private static String generateUIClassUrl(Class<? extends UI> uiClass) { + return "popup/" + uiClass.getSimpleName(); + } + +} diff --git a/server/src/com/vaadin/server/BrowserPopupUIProvider.java b/server/src/com/vaadin/server/BrowserPopupUIProvider.java new file mode 100644 index 0000000000..23036dabed --- /dev/null +++ b/server/src/com/vaadin/server/BrowserPopupUIProvider.java @@ -0,0 +1,50 @@ +/* + * 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.server; + +import com.vaadin.ui.UI; + +public class BrowserPopupUIProvider extends UIProvider { + + private final String path; + private final Class<? extends UI> uiClass; + + public BrowserPopupUIProvider(Class<? extends UI> uiClass, String path) { + this.path = ensureInitialSlash(path); + this.uiClass = uiClass; + } + + private static String ensureInitialSlash(String path) { + if (path == null) { + return null; + } else if (!path.startsWith("/")) { + return '/' + path; + } else { + return path; + } + } + + @Override + public Class<? extends UI> getUIClass(UIClassSelectionEvent event) { + String requestPathInfo = event.getRequest().getRequestPathInfo(); + if (path.equals(requestPathInfo)) { + return uiClass; + } else { + return null; + } + } +} diff --git a/server/src/com/vaadin/server/FileDownloader.java b/server/src/com/vaadin/server/FileDownloader.java index a07c0d3ed1..a5f450c28b 100644 --- a/server/src/com/vaadin/server/FileDownloader.java +++ b/server/src/com/vaadin/server/FileDownloader.java @@ -1,3 +1,19 @@ +/* + * 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.server; import java.io.IOException; diff --git a/server/src/com/vaadin/ui/AbstractField.java b/server/src/com/vaadin/ui/AbstractField.java index 59f730f275..53301f093a 100644 --- a/server/src/com/vaadin/ui/AbstractField.java +++ b/server/src/com/vaadin/ui/AbstractField.java @@ -687,19 +687,18 @@ public abstract class AbstractField<T> extends AbstractComponent implements */ private Object convertToModel(T fieldValue) throws Converter.ConversionException { + Class<?> modelType = null; + Property pd = getPropertyDataSource(); + if (pd != null) { + modelType = pd.getType(); + } else if (getConverter() != null) { + modelType = getConverter().getModelType(); + } try { - Class<?> modelType = null; - Property pd = getPropertyDataSource(); - if (pd != null) { - modelType = pd.getType(); - } else if (getConverter() != null) { - modelType = getConverter().getModelType(); - } return ConverterUtil.convertToModel(fieldValue, (Class<Object>) modelType, getConverter(), getLocale()); } catch (ConversionException e) { - throw new ConversionException( - getConversionError(converter.getModelType()), e); + throw new ConversionException(getConversionError(modelType), e); } } diff --git a/server/tests/src/com/vaadin/tests/server/component/abstractfield/AbstractFieldValueConversions.java b/server/tests/src/com/vaadin/tests/server/component/abstractfield/AbstractFieldValueConversions.java index 73f6063fdd..83224861b6 100644 --- a/server/tests/src/com/vaadin/tests/server/component/abstractfield/AbstractFieldValueConversions.java +++ b/server/tests/src/com/vaadin/tests/server/component/abstractfield/AbstractFieldValueConversions.java @@ -2,10 +2,15 @@ package com.vaadin.tests.server.component.abstractfield; import java.util.Locale; +import junit.framework.Assert; import junit.framework.TestCase; +import org.junit.Test; + import com.vaadin.data.util.MethodProperty; +import com.vaadin.data.util.ObjectProperty; import com.vaadin.data.util.converter.Converter; +import com.vaadin.data.util.converter.Converter.ConversionException; import com.vaadin.data.util.converter.StringToIntegerConverter; import com.vaadin.server.VaadinServiceSession; import com.vaadin.tests.data.bean.Address; @@ -179,4 +184,19 @@ public class AbstractFieldValueConversions extends TestCase { } + @Test + public void testNullConverter() { + TextField tf = new TextField("foo"); + tf.setPropertyDataSource(new ObjectProperty<Integer>(12)); + tf.setConverter((Converter) null); + try { + Object v = tf.getConvertedValue(); + System.out.println(v); + Assert.fail("Trying to convert String -> Integer should fail when there is no converter"); + } catch (ConversionException e) { + // ok, should happen when there is no converter but conversion is + // needed + } + } + } diff --git a/shared/src/com/vaadin/shared/ui/BrowserPopupExtensionState.java b/shared/src/com/vaadin/shared/ui/BrowserPopupExtensionState.java new file mode 100644 index 0000000000..a9ca6841d8 --- /dev/null +++ b/shared/src/com/vaadin/shared/ui/BrowserPopupExtensionState.java @@ -0,0 +1,27 @@ +/* + * 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.shared.ui; + +import com.vaadin.shared.ComponentState; + +public class BrowserPopupExtensionState extends ComponentState { + + public String target = "_blank"; + + public String features; + +} diff --git a/uitest/src/com/vaadin/tests/applicationcontext/CloseSession.html b/uitest/src/com/vaadin/tests/applicationcontext/CloseSession.html index f5313c7bec..93f102097a 100644 --- a/uitest/src/com/vaadin/tests/applicationcontext/CloseSession.html +++ b/uitest/src/com/vaadin/tests/applicationcontext/CloseSession.html @@ -60,9 +60,9 @@ <td></td> </tr> <tr> - <td>assertLocation</td> - <td>https://www.google.*/</td> - <td>https://www.google.*/</td> + <td>assertText</td> + <td>//h1</td> + <td>Index of /download/nightly</td> </tr> <!--Open again and verify we get a Session Expired error if doing something after closing the session--> <tr> diff --git a/uitest/src/com/vaadin/tests/applicationcontext/CloseSession.java b/uitest/src/com/vaadin/tests/applicationcontext/CloseSession.java index 0278190084..6f1c05b9c8 100644 --- a/uitest/src/com/vaadin/tests/applicationcontext/CloseSession.java +++ b/uitest/src/com/vaadin/tests/applicationcontext/CloseSession.java @@ -62,7 +62,8 @@ public class CloseSession extends AbstractTestUI { new Button.ClickListener() { @Override public void buttonClick(ClickEvent event) { - getPage().setLocation("https://www.google.com"); + getPage().setLocation( + "http://vaadin.com/download/nightly/"); getSession().close(); } })); diff --git a/uitest/src/com/vaadin/tests/components/FileDownloaderTest.java b/uitest/src/com/vaadin/tests/components/FileDownloaderTest.java index d5f447c7c3..e773c8c75b 100644 --- a/uitest/src/com/vaadin/tests/components/FileDownloaderTest.java +++ b/uitest/src/com/vaadin/tests/components/FileDownloaderTest.java @@ -1,3 +1,19 @@ +/* + * 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; import java.awt.image.BufferedImage; diff --git a/uitest/src/com/vaadin/tests/components/image/ImageClicks.java b/uitest/src/com/vaadin/tests/components/image/ImageClicks.java index e50b8c3a4f..397e31c39c 100644 --- a/uitest/src/com/vaadin/tests/components/image/ImageClicks.java +++ b/uitest/src/com/vaadin/tests/components/image/ImageClicks.java @@ -7,7 +7,7 @@ import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; -import java.util.Random; +import java.util.Date; import javax.imageio.ImageIO; @@ -20,8 +20,6 @@ import com.vaadin.ui.Label; public class ImageClicks extends TestBase { - private final Random rng = new Random(0); - private int clickCounter = 0; @Override @@ -30,7 +28,7 @@ public class ImageClicks extends TestBase { final Label label = new Label(labelText()); addComponent(label); - Image image = new Image(); + final Image image = new Image(); final MyImageSource imageSource = new MyImageSource(); final StreamResource imageResource = new StreamResource(imageSource, "testimage.png"); @@ -40,6 +38,9 @@ public class ImageClicks extends TestBase { @Override public void click(ClickEvent event) { ++clickCounter; + imageResource.setFilename("testimage.png?" + + new Date().getTime()); + image.markAsDirty(); label.setValue(labelText()); } @@ -58,7 +59,7 @@ public class ImageClicks extends TestBase { @Override protected String getDescription() { - return "Test click event handling of images"; + return "Each click on the dynamically generated image should update the image and add another black square"; } @Override @@ -110,11 +111,13 @@ public class ImageClicks extends TestBase { } // Cell - if (rng.nextFloat() < 0.5f) { - drawable.setColor(Color.white); - } else { + int cellIndex = col + row * cols; + if (clickCounter > cellIndex) { drawable.setColor(Color.black); + } else { + drawable.setColor(Color.white); } + drawable.fillRect(gridx + 1, gridy + 1, gridxnext - gridx - 1, gridynext - gridy - 1); } diff --git a/uitest/src/com/vaadin/tests/extensions/BrowserPopupExtensionTest.java b/uitest/src/com/vaadin/tests/extensions/BrowserPopupExtensionTest.java new file mode 100644 index 0000000000..d69ebfab56 --- /dev/null +++ b/uitest/src/com/vaadin/tests/extensions/BrowserPopupExtensionTest.java @@ -0,0 +1,107 @@ +/* + * 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.extensions; + +import java.util.ArrayList; +import java.util.List; + +import com.vaadin.server.BrowserPopupOpener; +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.tests.components.popupview.ReopenPopupView; +import com.vaadin.ui.AbstractComponent; +import com.vaadin.ui.Button; +import com.vaadin.ui.Button.ClickEvent; +import com.vaadin.ui.Button.ClickListener; +import com.vaadin.ui.Component; +import com.vaadin.ui.CssLayout; +import com.vaadin.ui.HorizontalLayout; +import com.vaadin.ui.Label; +import com.vaadin.ui.Link; +import com.vaadin.ui.NativeButton; + +public class BrowserPopupExtensionTest extends AbstractTestUI { + + @Override + protected void setup(VaadinRequest request) { + List<Class<? extends Component>> components = new ArrayList<Class<? extends Component>>(); + components.add(Button.class); + components.add(NativeButton.class); + components.add(Link.class); + components.add(CssLayout.class); + components.add(Label.class); + addComponents(components, "http://vaadin.com/download/nightly/"); + + Button uiClassButton = new Button("Open UI class"); + new BrowserPopupOpener(ReopenPopupView.class).extend(uiClassButton); + addComponent(uiClassButton); + + Button uiWithPath = new Button("Open UI class with path"); + new BrowserPopupOpener(ReopenPopupView.class, "foobar") + .extend(uiWithPath); + addComponent(uiWithPath); + + Button withPopupFeaturesButton = new Button("Open with features"); + BrowserPopupOpener featuresPopup = new BrowserPopupOpener( + "http://vaadin.com/download/nightly/"); + featuresPopup.setFeatures("width=400,height=400"); + featuresPopup.extend(withPopupFeaturesButton); + addComponent(withPopupFeaturesButton); + } + + public void addComponents(List<Class<? extends Component>> components, + String URL) { + final HorizontalLayout hl = new HorizontalLayout(); + for (Class<? extends Component> cls : components) { + try { + AbstractComponent c = (AbstractComponent) cls.newInstance(); + c.setId(cls.getName()); + c.setCaption(cls.getName()); + c.setDescription(URL); + c.setWidth("100px"); + c.setHeight("100px"); + hl.addComponent(c); + + new BrowserPopupOpener(URL).extend(c); + + if (c instanceof Button) { + ((Button) c).addClickListener(new ClickListener() { + + @Override + public void buttonClick(ClickEvent event) { + } + }); + } + } catch (Exception e) { + System.err.println("Could not instatiate " + cls.getName()); + } + } + addComponent(hl); + } + + @Override + protected String getTestDescription() { + return "Test for " + BrowserPopupOpener.class.getSimpleName() + + " features"; + } + + @Override + protected Integer getTicketNumber() { + return Integer.valueOf(9513); + } + +} |