@@ -103,6 +103,7 @@ | |||
<h2 id="incompatible">Incompatible or Behavior-altering Changes in @version-minor@</h2> | |||
<li><tt>BrowserWindowOpenerConnector</tt> and <tt>FileDownloaderConnector</tt> now are subclasses of <tt>AbstractEventTriggerExtensionConnector</tt> | |||
<li>Date range limits in <tt>AbstractDateFieldState</tt> are now <tt>String</tt>s instead of <tt>Date</tt>s, some client-side method signatures were changed</li> | |||
<li><tt>BrowserResizeListener</tt> is only called once resizing ends.</li> | |||
<li><tt>ItemClickEvent</tt> for <tt>Grid</tt> now takes and additional row index parameter.</li> |
@@ -0,0 +1,73 @@ | |||
/* | |||
* Copyright 2000-2018 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.user.client.ui.Widget; | |||
import com.google.web.bindery.event.shared.HandlerRegistration; | |||
import com.vaadin.client.ComponentConnector; | |||
import com.vaadin.client.ServerConnector; | |||
import com.vaadin.shared.extension.PartInformationState; | |||
/** | |||
* An abstract extension connector with trigger support. Implementor's | |||
* {@link #trigger} method call may be initiated by another {@code Component} | |||
* without server round-trip. The class is used to overcome browser security | |||
* limitations. For instance, window may not be open with the round-trip. | |||
* | |||
* @author Vaadin Ltd. | |||
* @since | |||
*/ | |||
public abstract class AbstractEventTriggerExtensionConnector | |||
extends AbstractExtensionConnector { | |||
private HandlerRegistration eventHandlerRegistration; | |||
/** | |||
* Called whenever a click occurs on the widget (if widget does not | |||
* implement {@link EventTrigger}) or when the {@link EventTrigger} fires. | |||
* | |||
*/ | |||
protected abstract void trigger(); | |||
@Override | |||
public PartInformationState getState() { | |||
return (PartInformationState) super.getState(); | |||
} | |||
@Override | |||
protected void extend(ServerConnector target) { | |||
Widget targetWidget = ((ComponentConnector) target).getWidget(); | |||
if (targetWidget instanceof EventTrigger) { | |||
String partInformation = getState().partInformation; | |||
eventHandlerRegistration = ((EventTrigger) targetWidget) | |||
.addTrigger(this::trigger, partInformation); | |||
} else { | |||
eventHandlerRegistration = targetWidget | |||
.addDomHandler(e -> trigger(), ClickEvent.getType()); | |||
} | |||
} | |||
@Override | |||
public void onUnregister() { | |||
super.onUnregister(); | |||
if (eventHandlerRegistration != null) { | |||
eventHandlerRegistration.removeHandler(); | |||
eventHandlerRegistration = null; | |||
} | |||
} | |||
} |
@@ -18,13 +18,8 @@ package com.vaadin.client.extensions; | |||
import java.util.Map.Entry; | |||
import com.google.gwt.event.dom.client.ClickEvent; | |||
import com.google.gwt.event.dom.client.ClickHandler; | |||
import com.google.gwt.http.client.URL; | |||
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.BrowserWindowOpener; | |||
import com.vaadin.shared.ui.BrowserWindowOpenerState; | |||
import com.vaadin.shared.ui.Connect; | |||
@@ -37,15 +32,8 @@ import com.vaadin.shared.util.SharedUtil; | |||
* @since 7.0.0 | |||
*/ | |||
@Connect(BrowserWindowOpener.class) | |||
public class BrowserWindowOpenerConnector extends AbstractExtensionConnector | |||
implements ClickHandler { | |||
@Override | |||
protected void extend(ServerConnector target) { | |||
final Widget targetWidget = ((ComponentConnector) target).getWidget(); | |||
targetWidget.addDomHandler(this, ClickEvent.getType()); | |||
} | |||
public class BrowserWindowOpenerConnector | |||
extends AbstractEventTriggerExtensionConnector { | |||
@Override | |||
public BrowserWindowOpenerState getState() { | |||
@@ -53,7 +41,7 @@ public class BrowserWindowOpenerConnector extends AbstractExtensionConnector | |||
} | |||
@Override | |||
public void onClick(ClickEvent event) { | |||
protected void trigger() { | |||
String url = getResourceUrl(BrowserWindowOpenerState.locationResource); | |||
url = addParametersAndFragment(url); | |||
if (url != null) { |
@@ -0,0 +1,55 @@ | |||
/* | |||
* Copyright 2000-2018 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.user.client.Command; | |||
import com.google.gwt.user.client.ui.Widget; | |||
import com.google.web.bindery.event.shared.HandlerRegistration; | |||
/** | |||
* Provides support for triggering an event from a given parts of a component or | |||
* using various events. | |||
* <p> | |||
* Used by features such as {@link FileDownloaderConnector} and | |||
* {@link BrowserWindowOpenerConnector} to listen to a given event on a given | |||
* element. The component is the one responsible for deciding the element and | |||
* the event to listen to. | |||
* <p> | |||
* This is the client side interface. | |||
* <p> | |||
* If the component on the server side implements | |||
* {@code com.vaadin.server.EventTrigger} then this interface should be | |||
* implemented by the {@link Widget} used by the client side connector. | |||
* | |||
* @since | |||
*/ | |||
public interface EventTrigger { | |||
/** | |||
* Adds an appropriate event handler on the correct element inside the | |||
* widget and invokes the given file downloader when the event occurs. | |||
* | |||
* @param command | |||
* The command to execute when the event occurs | |||
* @param partInformation | |||
* Information passed from the server, typically telling which | |||
* element to attach the DOM handler to | |||
* @return a registration handler which can be used to remove the handler | |||
*/ | |||
public HandlerRegistration addTrigger(Command command, | |||
String partInformation); | |||
} |
@@ -21,33 +21,27 @@ import com.google.gwt.dom.client.IFrameElement; | |||
import com.google.gwt.dom.client.Style; | |||
import com.google.gwt.dom.client.Style.Unit; | |||
import com.google.gwt.dom.client.Style.Visibility; | |||
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.RootPanel; | |||
import com.google.gwt.user.client.ui.Widget; | |||
import com.vaadin.client.BrowserInfo; | |||
import com.vaadin.client.ComponentConnector; | |||
import com.vaadin.client.ServerConnector; | |||
import com.vaadin.server.FileDownloader; | |||
import com.vaadin.shared.extension.filedownloader.FileDownloaderState; | |||
import com.vaadin.shared.ui.Connect; | |||
@Connect(FileDownloader.class) | |||
public class FileDownloaderConnector extends AbstractExtensionConnector | |||
implements ClickHandler { | |||
public class FileDownloaderConnector | |||
extends AbstractEventTriggerExtensionConnector { | |||
private IFrameElement iframe; | |||
/** | |||
* Called when the download should start. | |||
* | |||
* @since | |||
*/ | |||
@Override | |||
protected void extend(ServerConnector target) { | |||
final Widget downloadWidget = ((ComponentConnector) target).getWidget(); | |||
downloadWidget.addDomHandler(this, ClickEvent.getType()); | |||
} | |||
@Override | |||
public void onClick(ClickEvent event) { | |||
protected void trigger() { | |||
final String url = getResourceUrl("dl"); | |||
if (url != null && !url.isEmpty()) { | |||
BrowserInfo browser = BrowserInfo.get(); |
@@ -16,8 +16,10 @@ | |||
package com.vaadin.client.ui; | |||
import java.util.ArrayList; | |||
import java.util.HashMap; | |||
import java.util.LinkedList; | |||
import java.util.List; | |||
import java.util.Map; | |||
import java.util.Queue; | |||
import com.google.gwt.core.client.GWT; | |||
@@ -46,6 +48,7 @@ import com.google.gwt.user.client.ui.HasHTML; | |||
import com.google.gwt.user.client.ui.PopupPanel; | |||
import com.google.gwt.user.client.ui.RootPanel; | |||
import com.google.gwt.user.client.ui.Widget; | |||
import com.google.web.bindery.event.shared.HandlerRegistration; | |||
import com.vaadin.client.ApplicationConnection; | |||
import com.vaadin.client.BrowserInfo; | |||
import com.vaadin.client.LayoutManager; | |||
@@ -53,12 +56,13 @@ import com.vaadin.client.TooltipInfo; | |||
import com.vaadin.client.UIDL; | |||
import com.vaadin.client.Util; | |||
import com.vaadin.client.WidgetUtil; | |||
import com.vaadin.client.extensions.EventTrigger; | |||
import com.vaadin.shared.ui.ContentMode; | |||
import com.vaadin.shared.ui.menubar.MenuBarConstants; | |||
public class VMenuBar extends FocusableFlowPanel | |||
implements CloseHandler<PopupPanel>, KeyPressHandler, KeyDownHandler, | |||
FocusHandler, SubPartAware, MouseOutHandler, MouseOverHandler { | |||
implements CloseHandler<PopupPanel>, KeyPressHandler, KeyDownHandler, | |||
FocusHandler, SubPartAware, MouseOutHandler, MouseOverHandler, EventTrigger { | |||
// The hierarchy of VMenuBar is a bit weird as VMenuBar is the Paintable, | |||
// used for the root menu but also used for the sub menus. | |||
@@ -117,6 +121,8 @@ FocusHandler, SubPartAware, MouseOutHandler, MouseOverHandler { | |||
/** For internal use only. May be removed or replaced in the future. */ | |||
public boolean htmlContentAllowed; | |||
private Map<String, List<Command>> triggers = new HashMap<>(); | |||
public VMenuBar() { | |||
// Create an empty horizontal menubar | |||
this(false, null); | |||
@@ -414,9 +420,12 @@ FocusHandler, SubPartAware, MouseOutHandler, MouseOverHandler { | |||
* @param item | |||
*/ | |||
public void itemClick(CustomMenuItem item) { | |||
if (item.getCommand() != null) { | |||
boolean triggered = triggerEventIfNeeded(item); | |||
if (item.getCommand() != null || triggered) { | |||
try { | |||
item.getCommand().execute(); | |||
if (item.getCommand() != null) { | |||
item.getCommand().execute(); | |||
} | |||
} finally { | |||
setSelected(null); | |||
if (visibleChildMenu != null) { | |||
@@ -808,6 +817,7 @@ FocusHandler, SubPartAware, MouseOutHandler, MouseOverHandler { | |||
protected ContentMode descriptionContentMode = null; | |||
private String styleName; | |||
private String id; | |||
/** | |||
* Default menu item {@link Widget} constructor for GWT.create(). | |||
@@ -1166,6 +1176,14 @@ FocusHandler, SubPartAware, MouseOutHandler, MouseOverHandler { | |||
return null; | |||
} | |||
public String getId() { | |||
return id; | |||
} | |||
public void setId(String id) { | |||
this.id = id; | |||
} | |||
} | |||
/** | |||
@@ -1642,6 +1660,7 @@ FocusHandler, SubPartAware, MouseOutHandler, MouseOverHandler { | |||
openMenuAndFocusFirstIfPossible(getSelected()); | |||
} else { | |||
try { | |||
triggerEventIfNeeded(getSelected()); | |||
final Command command = getSelected().getCommand(); | |||
if (command != null) { | |||
command.execute(); | |||
@@ -1654,10 +1673,7 @@ FocusHandler, SubPartAware, MouseOutHandler, MouseOverHandler { | |||
// not leave menu to visible ("hover open") mode | |||
menuVisible = false; | |||
VMenuBar root = this; | |||
while (root.getParentMenu() != null) { | |||
root = root.getParentMenu(); | |||
} | |||
VMenuBar root = getRoot(); | |||
root.ignoreFocus = true; | |||
root.getElement().focus(); | |||
root.ignoreFocus = false; | |||
@@ -1669,6 +1685,17 @@ FocusHandler, SubPartAware, MouseOutHandler, MouseOverHandler { | |||
return false; | |||
} | |||
private boolean triggerEventIfNeeded(CustomMenuItem item) { | |||
List<Command> commands = getTriggers().get(item.getId()); | |||
if (commands != null) { | |||
for (Command command : commands) { | |||
command.execute(); | |||
} | |||
return true; | |||
} | |||
return false; | |||
} | |||
private void selectFirstItem() { | |||
for (int i = 0; i < items.size(); i++) { | |||
CustomMenuItem item = items.get(i); | |||
@@ -1877,4 +1904,36 @@ FocusHandler, SubPartAware, MouseOutHandler, MouseOverHandler { | |||
public void onMouseOut(MouseOutEvent event) { | |||
LazyCloser.schedule(); | |||
} | |||
private VMenuBar getRoot() { | |||
VMenuBar root = this; | |||
while (root.getParentMenu() != null) { | |||
root = root.getParentMenu(); | |||
} | |||
return root; | |||
} | |||
@Override | |||
public HandlerRegistration addTrigger(Command command, | |||
String partInformation) { | |||
if (partInformation == null || partInformation.isEmpty()) { | |||
throw new IllegalArgumentException( | |||
"The 'partInformation' parameter must contain the menu item id"); | |||
} | |||
getTriggers().computeIfAbsent(partInformation, s-> new ArrayList<>()).add(command); | |||
return () -> { | |||
List<Command> commands = getTriggers().get(partInformation); | |||
if (commands != null) { | |||
commands.remove(command); | |||
} | |||
}; | |||
} | |||
private Map<String, List<Command>> getTriggers() { | |||
return getRoot().triggers; | |||
} | |||
} |
@@ -129,6 +129,7 @@ public class MenuBarConnector extends AbstractComponentConnector | |||
} | |||
currentItem = currentMenu.addItem(itemHTML, cmd); | |||
currentItem.setId("" + itemId); | |||
currentItem.updateFromUIDL(item, client); | |||
if (item.getChildCount() > 0) { |
@@ -56,7 +56,7 @@ public class LettingUserDownladFile extends UI { | |||
.... | |||
To use `FileDownloader`, you just create an instance of the extension | |||
and use it to extend the component that should start the download. You | |||
and use it to extend the component or `MenuItem` that should start the download. You | |||
should also note that `FileDownloader` works best with resources that | |||
are served by Vaadin as it relies on sending some special HTTP headers | |||
along with the file to ensure the browser doesn't try to open the file |
@@ -122,10 +122,29 @@ public class BrowserWindowOpener extends AbstractExtension { | |||
setResource(BrowserWindowOpenerState.locationResource, resource); | |||
} | |||
/** | |||
* Add this extension to the target component. | |||
* | |||
* @param target | |||
* the component to attach this extension to | |||
*/ | |||
public void extend(AbstractComponent target) { | |||
super.extend(target); | |||
} | |||
/** | |||
* Add this extension to the {@code EventTrigger}. | |||
* | |||
* @param eventTrigger | |||
* the trigger to attach this extension to | |||
* | |||
* @since | |||
*/ | |||
public void extend(EventTrigger eventTrigger) { | |||
super.extend(eventTrigger.getConnector()); | |||
getState().partInformation = eventTrigger.getPartInformation(); | |||
} | |||
/** | |||
* Sets the provided URL {@code url} for this instance. The {@code url} will | |||
* be opened in a new browser window/tab when the extended component is |
@@ -0,0 +1,65 @@ | |||
/* | |||
* Copyright 2000-2018 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.Serializable; | |||
import com.vaadin.ui.Component; | |||
import com.vaadin.ui.MenuBar; | |||
/** | |||
* Provides support for triggering an event from a given parts of a component or | |||
* using various events. | |||
* <p> | |||
* Used by features such as {@link FileDownloader} and | |||
* {@link BrowserWindowOpener} to listen to a given event on a given element on | |||
* the client side. The component is the one responsible for deciding the | |||
* element and the event to listen to and can communicate this to the client | |||
* using {@link #getPartInformation()}. | |||
* <p> | |||
* This is the server side interface. | |||
* <p> | |||
* If a {@link Component} implements this interface, then the corresponding | |||
* connector on the client side must implement | |||
* {@code com.vaadin.client.extensions.EventTrigger}. | |||
* | |||
* @since | |||
*/ | |||
public interface EventTrigger extends Serializable { | |||
/** | |||
* Gets the connector who will be used to offer the file download. Typically | |||
* a component containing a certain DOM element, which in turn triggers the | |||
* download. | |||
* | |||
* @return the connector for the file download | |||
*/ | |||
AbstractClientConnector getConnector(); | |||
/** | |||
* Gets a free form string which identifies which part of the connector that | |||
* should trigger the download. The string is passed to the connector | |||
* (FileDownloaderHandler implementor) on the client side. | |||
* <p> | |||
* For example, {@link MenuBar} passes the id of a menu item through this | |||
* method so that the client side can listen to events for that particular | |||
* item only. | |||
* | |||
* @return a free form string which makes sense to the client side connector | |||
*/ | |||
String getPartInformation(); | |||
} |
@@ -66,10 +66,29 @@ public class FileDownloader extends AbstractExtension { | |||
setResource("dl", resource); | |||
} | |||
/** | |||
* Add this extension to the target component. | |||
* | |||
* @param target | |||
* the component to attach this extension to | |||
*/ | |||
public void extend(AbstractComponent target) { | |||
super.extend(target); | |||
} | |||
/** | |||
* Add this extension to the {@code EventTrigger}. | |||
* | |||
* @param eventTrigger | |||
* the trigger to attach this extension to | |||
* | |||
* @since | |||
*/ | |||
public void extend(EventTrigger eventTrigger) { | |||
super.extend(eventTrigger.getConnector()); | |||
getState().partInformation = eventTrigger.getPartInformation(); | |||
} | |||
/** | |||
* Gets the resource set for download. | |||
* |
@@ -28,6 +28,8 @@ import org.jsoup.nodes.Element; | |||
import org.jsoup.nodes.Node; | |||
import org.jsoup.parser.Tag; | |||
import com.vaadin.server.AbstractClientConnector; | |||
import com.vaadin.server.EventTrigger; | |||
import com.vaadin.server.PaintException; | |||
import com.vaadin.server.PaintTarget; | |||
import com.vaadin.server.Resource; | |||
@@ -217,6 +219,23 @@ implements LegacyComponent, Focusable { | |||
setMoreMenuItem(null); | |||
} | |||
/** | |||
* Adds a new menu item to the menu bar | |||
* <p> | |||
* Clicking on this menu item has no effect. Use | |||
* {@link #addItem(String, Command)} or {@link MenuItem#setCommand(Command)} | |||
* to assign an action to the menu item. | |||
* | |||
* @param caption | |||
* the text for the menu item | |||
* @throws IllegalArgumentException | |||
* | |||
* @since | |||
*/ | |||
public MenuBar.MenuItem addItem(String caption) { | |||
return addItem(caption, null, null); | |||
} | |||
/** | |||
* Add a new item to the menu bar. Command can be null, but a caption must | |||
* be given. | |||
@@ -453,7 +472,7 @@ implements LegacyComponent, Focusable { | |||
* multiple MenuItems to a MenuItem and create a sub-menu. | |||
* | |||
*/ | |||
public class MenuItem implements Serializable { | |||
public class MenuItem implements Serializable, EventTrigger { | |||
/** Private members * */ | |||
private final int itsId; | |||
@@ -522,6 +541,22 @@ implements LegacyComponent, Focusable { | |||
return item; | |||
} | |||
/** | |||
* Add a new menu item inside this menu item, creating a sub-menu. | |||
* <p> | |||
* Clicking on the new item has no effect. Use | |||
* {@link #addItem(String, Command)} or {@link #setCommand(Command)} to | |||
* assign an action to the menu item. | |||
* | |||
* @param caption | |||
* the text for the menu item | |||
* | |||
* @since | |||
*/ | |||
public MenuBar.MenuItem addItem(String caption) { | |||
return addItem(caption, null, null); | |||
} | |||
/** | |||
* Add a new item inside this item, thus creating a sub-menu. Command | |||
* can be null, but a caption must be given. | |||
@@ -992,6 +1027,26 @@ implements LegacyComponent, Focusable { | |||
this.checked = checked; | |||
markAsDirty(); | |||
} | |||
/** | |||
* Gets the menu bar this item is part of. | |||
* | |||
* @return the menu bar this item is attached to | |||
* @since | |||
*/ | |||
public MenuBar getMenuBar() { | |||
return MenuBar.this; | |||
} | |||
@Override | |||
public AbstractClientConnector getConnector() { | |||
return getMenuBar(); | |||
} | |||
@Override | |||
public String getPartInformation() { | |||
return String.valueOf(getId()); | |||
} | |||
} | |||
@Override |
@@ -0,0 +1,33 @@ | |||
/* | |||
* Copyright 2000-2018 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.extension; | |||
import com.vaadin.shared.communication.SharedState; | |||
/** | |||
* Shared state for {@code AbstractEventTriggerExtensionConnector} extension. | |||
* | |||
* @since | |||
*/ | |||
public class PartInformationState extends SharedState { | |||
/** | |||
* Information passed to the widget on the client side, to allow it to | |||
* attach to the correct DOM element. | |||
*/ | |||
public String partInformation; | |||
} |
@@ -15,7 +15,7 @@ | |||
*/ | |||
package com.vaadin.shared.extension.filedownloader; | |||
import com.vaadin.shared.communication.SharedState; | |||
import com.vaadin.shared.extension.PartInformationState; | |||
/** | |||
* Shared state for FileDownloader. | |||
@@ -24,6 +24,6 @@ import com.vaadin.shared.communication.SharedState; | |||
* | |||
* @since 8.0 | |||
*/ | |||
public class FileDownloaderState extends SharedState { | |||
public class FileDownloaderState extends PartInformationState { | |||
} |
@@ -19,9 +19,9 @@ package com.vaadin.shared.ui; | |||
import java.util.HashMap; | |||
import java.util.Map; | |||
import com.vaadin.shared.communication.SharedState; | |||
import com.vaadin.shared.extension.PartInformationState; | |||
public class BrowserWindowOpenerState extends SharedState { | |||
public class BrowserWindowOpenerState extends PartInformationState { | |||
public static final String locationResource = "url"; | |||
public String target = "_blank"; |
@@ -0,0 +1,73 @@ | |||
package com.vaadin.tests.components; | |||
import com.vaadin.annotations.Widgetset; | |||
import com.vaadin.server.BrowserWindowOpener; | |||
import com.vaadin.server.ClassResource; | |||
import com.vaadin.server.ConnectorResource; | |||
import com.vaadin.server.ExternalResource; | |||
import com.vaadin.server.FileDownloader; | |||
import com.vaadin.server.VaadinRequest; | |||
import com.vaadin.tests.components.embedded.EmbeddedPdf; | |||
import com.vaadin.tests.extensions.EventTriggerExtension; | |||
import com.vaadin.tests.widgetset.TestingWidgetSet; | |||
import com.vaadin.ui.Button; | |||
import com.vaadin.ui.MenuBar; | |||
import com.vaadin.ui.MenuBar.MenuItem; | |||
@Widgetset(TestingWidgetSet.NAME) | |||
public class MenuBarDownloadBrowserOpenerUI extends AbstractTestUIWithLog { | |||
@Override | |||
protected void setup(VaadinRequest request) { | |||
ConnectorResource downloadResource = new ClassResource( | |||
EmbeddedPdf.class, "test.pdf"); | |||
ExternalResource openResource = new ExternalResource( | |||
"https://vaadin.com"); | |||
MenuBar menuBar = new MenuBar(); | |||
MenuItem download = menuBar.addItem("Download"); | |||
MenuItem saveAsNoLog = download.addItem("Save as without logging..."); | |||
MenuItem saveAsLog = download.addItem("Save as with logging...", | |||
item -> log("Download triggered")); | |||
FileDownloader fd = new FileDownloader(downloadResource); | |||
fd.extend(saveAsNoLog); | |||
FileDownloader fd2 = new FileDownloader(downloadResource); | |||
fd2.extend(saveAsLog); | |||
MenuItem open = menuBar.addItem("Open"); | |||
MenuItem openNoLog = open.addItem("Open without logging..."); | |||
MenuItem openLog = open.addItem("Open with logging...", item -> log("Open triggered")); | |||
BrowserWindowOpener bwo = new BrowserWindowOpener(openResource); | |||
bwo.extend(openNoLog); | |||
BrowserWindowOpener bwo2 = new BrowserWindowOpener(openResource); | |||
bwo2.extend(openLog); | |||
addComponent(menuBar); | |||
addComponent(new Button("Remove downloaders and openers", event -> { | |||
fd.remove(); | |||
fd2.remove(); | |||
bwo.remove(); | |||
bwo2.remove(); | |||
})); | |||
setupTestExtension(menuBar); | |||
} | |||
private void setupTestExtension(MenuBar menuBar) { | |||
EventTriggerExtension triggerable1 = new EventTriggerExtension(); | |||
EventTriggerExtension triggerable2 = new EventTriggerExtension(); | |||
MenuItem testExtension = menuBar.addItem("TestExtension"); | |||
MenuItem runMe = testExtension.addItem("RunMe"); | |||
triggerable1.extend(runMe); | |||
testExtension.addItem("AddTrigger", c -> triggerable2.extend(runMe)); | |||
testExtension.addItem("RemoveTrigger", c -> triggerable2.remove()); | |||
} | |||
} |
@@ -0,0 +1,23 @@ | |||
package com.vaadin.tests.extensions; | |||
import com.vaadin.server.AbstractExtension; | |||
import com.vaadin.server.EventTrigger; | |||
import com.vaadin.shared.extension.PartInformationState; | |||
public class EventTriggerExtension extends AbstractExtension { | |||
@Override | |||
protected PartInformationState getState() { | |||
return (PartInformationState) super.getState(); | |||
} | |||
@Override | |||
protected PartInformationState getState(boolean markAsDirty) { | |||
return (PartInformationState) super.getState(markAsDirty); | |||
} | |||
public void extend(EventTrigger eventTrigger) { | |||
super.extend(eventTrigger.getConnector()); | |||
getState().partInformation = eventTrigger.getPartInformation(); | |||
} | |||
} |
@@ -0,0 +1,13 @@ | |||
package com.vaadin.tests.widgetset.client.extension; | |||
import com.vaadin.client.extensions.AbstractEventTriggerExtensionConnector; | |||
import com.vaadin.shared.ui.Connect; | |||
import com.vaadin.tests.extensions.EventTriggerExtension; | |||
@Connect(EventTriggerExtension.class) | |||
public class EventTriggerExtensionConnector extends AbstractEventTriggerExtensionConnector{ | |||
@Override | |||
protected native void trigger() /*-{ | |||
alert("Trigger"); | |||
}-*/; | |||
} |
@@ -0,0 +1,44 @@ | |||
package com.vaadin.tests.components; | |||
import java.util.List; | |||
import org.junit.Assert; | |||
import org.junit.Test; | |||
import org.openqa.selenium.Alert; | |||
import org.openqa.selenium.remote.DesiredCapabilities; | |||
import com.vaadin.testbench.elements.MenuBarElement; | |||
import com.vaadin.testbench.parallel.Browser; | |||
import com.vaadin.tests.tb3.MultiBrowserTest; | |||
public class MenuBarDownloadBrowserOpenerUITest extends MultiBrowserTest { | |||
@Override | |||
public List<DesiredCapabilities> getBrowsersToTest() { | |||
//alerts do not work properly on PhantomJS | |||
return getBrowserCapabilities(Browser.CHROME); | |||
} | |||
@Test | |||
public void testTriggerExtension() { | |||
openTestURL(); | |||
MenuBarElement first = $(MenuBarElement.class).first(); | |||
first.clickItem("TestExtension", "RunMe"); | |||
checkAndCloseAlert(); | |||
first.clickItem("TestExtension", "AddTrigger"); | |||
first.clickItem("TestExtension", "RunMe"); | |||
checkAndCloseAlert(); | |||
checkAndCloseAlert(); | |||
first.clickItem("TestExtension", "RemoveTrigger"); | |||
first.clickItem("TestExtension", "RunMe"); | |||
checkAndCloseAlert(); | |||
} | |||
private void checkAndCloseAlert() { | |||
Alert alert = getDriver().switchTo().alert(); | |||
Assert.assertEquals("Trigger",alert.getText()); | |||
alert.dismiss(); | |||
} | |||
} |