From eaffcb2f31b8be2b8738685a6e30607dadf58d41 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Leif=20=C3=85strand?= Date: Wed, 24 Oct 2012 11:31:55 +0300 Subject: [PATCH] Create UIProvider & Extension for easily opening popups. (#9513) MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit * Based on Pekka Hyvönen's patch Change-Id: Ib97fc77a9a116da2b5af0cb2233a81aaa829f763 --- .../BrowserPopupOpenerConnector.java | 58 ++++++ .../com/vaadin/server/BrowserPopupOpener.java | 168 ++++++++++++++++++ .../vaadin/server/BrowserPopupUIProvider.java | 50 ++++++ .../shared/ui/BrowserPopupExtensionState.java | 27 +++ .../extensions/BrowserPopupExtensionTest.java | 107 +++++++++++ 5 files changed, 410 insertions(+) create mode 100644 client/src/com/vaadin/client/extensions/BrowserPopupOpenerConnector.java create mode 100644 server/src/com/vaadin/server/BrowserPopupOpener.java create mode 100644 server/src/com/vaadin/server/BrowserPopupUIProvider.java create mode 100644 shared/src/com/vaadin/shared/ui/BrowserPopupExtensionState.java create mode 100644 uitest/src/com/vaadin/tests/extensions/BrowserPopupExtensionTest.java 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/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 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 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 + * null or "blank", 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 null 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 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 uiClass; + + public BrowserPopupUIProvider(Class 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 getUIClass(UIClassSelectionEvent event) { + String requestPathInfo = event.getRequest().getRequestPathInfo(); + if (path.equals(requestPathInfo)) { + return uiClass; + } else { + return null; + } + } +} 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/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> components = new ArrayList>(); + 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> components, + String URL) { + final HorizontalLayout hl = new HorizontalLayout(); + for (Class 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); + } + +} -- 2.39.5