import com.vaadin.terminal.gwt.client.communication.RpcManager;
import com.vaadin.terminal.gwt.client.communication.SharedState;
import com.vaadin.terminal.gwt.client.communication.StateChangeEvent;
-import com.vaadin.terminal.gwt.client.ui.RootConnector;
import com.vaadin.terminal.gwt.client.ui.VContextMenu;
import com.vaadin.terminal.gwt.client.ui.VNotification;
import com.vaadin.terminal.gwt.client.ui.VNotification.HideEvent;
import com.vaadin.terminal.gwt.client.ui.WindowConnector;
import com.vaadin.terminal.gwt.client.ui.dd.VDragAndDropManager;
+import com.vaadin.terminal.gwt.client.ui.root.RootConnector;
import com.vaadin.terminal.gwt.server.AbstractCommunicationManager;
/**
private Timer loadTimer3;
private Element loadElement;
- private final RootConnector view;
+ private final RootConnector rootConnector;
protected boolean applicationRunning = false;
}
public ApplicationConnection() {
- view = GWT.create(RootConnector.class);
+ rootConnector = GWT.create(RootConnector.class);
rpcManager = GWT.create(RpcManager.class);
layoutManager = GWT.create(LayoutManager.class);
layoutManager.setConnection(this);
initializeClientHooks();
- view.init(cnf.getRootPanelId(), this);
+ rootConnector.init(cnf.getRootPanelId(), this);
showLoadingIndicator();
}
if (loadElement == null) {
loadElement = DOM.createDiv();
DOM.setStyleAttribute(loadElement, "position", "absolute");
- DOM.appendChild(view.getWidget().getElement(), loadElement);
+ DOM.appendChild(rootConnector.getWidget().getElement(), loadElement);
VConsole.log("inserting load indicator");
}
DOM.setElementProperty(loadElement, "className", "v-loading-indicator");
meta = json.getValueMap("meta");
if (meta.containsKey("repaintAll")) {
repaintAll = true;
- view.getWidget().clear();
+ rootConnector.getWidget().clear();
getConnectorMap().clear();
if (meta.containsKey("invalidLayouts")) {
validatingLayouts = true;
if (!cc.getParent().getChildren().contains(cc)) {
VConsole.error("ERROR: Connector is connected to a parent but the parent does not contain the connector");
}
- } else if ((cc instanceof RootConnector && cc == getView())) {
+ } else if ((cc instanceof RootConnector && cc == getRootConnector())) {
// RootConnector for this connection, leave as-is
} else if (cc instanceof WindowConnector
- && getView().hasSubWindow((WindowConnector) cc)) {
+ && getRootConnector().hasSubWindow((WindowConnector) cc)) {
// Sub window attached to this RootConnector, leave
// as-is
} else {
// RootConnector has been created but not
// initialized as the connector id has not been
// known
- connectorMap.registerConnector(connectorId, view);
- view.doInit(connectorId, ApplicationConnection.this);
+ connectorMap.registerConnector(connectorId, rootConnector);
+ rootConnector.doInit(connectorId, ApplicationConnection.this);
}
} catch (final Throwable e) {
VConsole.error(e);
@Override
public void run() {
- VConsole.log("Running re-layout of " + view.getClass().getName());
- runDescendentsLayout(view.getWidget());
+ VConsole.log("Running re-layout of " + rootConnector.getClass().getName());
+ runDescendentsLayout(rootConnector.getWidget());
isPending = false;
}
};
*
* @return the main view
*/
- public RootConnector getView() {
- return view;
+ public RootConnector getRootConnector() {
+ return rootConnector;
}
/**
import com.vaadin.terminal.gwt.client.ui.VGridLayout;
import com.vaadin.terminal.gwt.client.ui.VMeasuringOrderedLayout;
import com.vaadin.terminal.gwt.client.ui.VTabsheetPanel;
-import com.vaadin.terminal.gwt.client.ui.VView;
import com.vaadin.terminal.gwt.client.ui.VWindow;
import com.vaadin.terminal.gwt.client.ui.WindowConnector;
+import com.vaadin.terminal.gwt.client.ui.root.VRoot;
/**
* ComponentLocator provides methods for generating a String locator for a given
return null;
}
- if (w instanceof VView) {
+ if (w instanceof VRoot) {
return "";
} else if (w instanceof VWindow) {
Connector windowConnector = ConnectorMap.get(client)
.getConnector(w);
- List<WindowConnector> subWindowList = client.getView()
+ List<WindowConnector> subWindowList = client.getRootConnector()
.getSubWindows();
int indexOfSubWindow = subWindowList.indexOf(windowConnector);
return PARENTCHILD_SEPARATOR + "VWindow[" + indexOfSubWindow + "]";
if (part.equals(ROOT_ID)) {
w = RootPanel.get();
} else if (part.equals("")) {
- w = client.getView().getWidget();
+ w = client.getRootConnector().getWidget();
} else if (w == null) {
String id = part;
// Must be old static pid (PID_S*)
if (connector == null) {
// Lookup by debugId
// TODO Optimize this
- connector = findConnectorById(client.getView(),
+ connector = findConnectorById(client.getRootConnector(),
id.substring(5));
}
* compatibility
*/
if (widgetClassName.equals("VWindow")) {
- List<WindowConnector> windows = client.getView()
+ List<WindowConnector> windows = client.getRootConnector()
.getSubWindows();
List<VWindow> windowWidgets = new ArrayList<VWindow>(
windows.size());
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
-import com.vaadin.terminal.gwt.client.ui.RootConnector;
import com.vaadin.terminal.gwt.client.ui.VLazyExecutor;
import com.vaadin.terminal.gwt.client.ui.VNotification;
import com.vaadin.terminal.gwt.client.ui.VOverlay;
import com.vaadin.terminal.gwt.client.ui.WindowConnector;
+import com.vaadin.terminal.gwt.client.ui.root.RootConnector;
/**
* A helper console for client side development. The debug console can also be
for (ApplicationConnection a : ApplicationConfiguration
.getRunningApplications()) {
ComponentConnector connector = Util.getConnectorForElement(
- a, a.getView().getWidget(), eventTarget);
+ a, a.getRootConnector().getWidget(), eventTarget);
if (connector == null) {
connector = Util.getConnectorForElement(a,
RootPanel.get(), eventTarget);
for (ApplicationConnection a : ApplicationConfiguration
.getRunningApplications()) {
ComponentConnector paintable = Util.getConnectorForElement(
- a, a.getView().getWidget(), eventTarget);
+ a, a.getRootConnector().getWidget(), eventTarget);
if (paintable == null) {
paintable = Util.getConnectorForElement(a,
RootPanel.get(), eventTarget);
}
protected void dumpConnectorInfo(ApplicationConnection a) {
- RootConnector root = a.getView();
+ RootConnector root = a.getRootConnector();
log("================");
log("Connector hierarchy for Root: " + root.getState().getCaption()
+ " (" + root.getConnectorId() + ")");
import com.vaadin.terminal.gwt.client.communication.ServerRpc;
import com.vaadin.terminal.gwt.client.communication.SharedState;
import com.vaadin.terminal.gwt.client.communication.StateChangeEvent;
+import com.vaadin.terminal.gwt.client.ui.root.RootConnector;
public abstract class AbstractComponentConnector extends AbstractConnector
implements ComponentConnector {
+++ /dev/null
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-package com.vaadin.terminal.gwt.client.ui;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.core.client.Scheduler;
-import com.google.gwt.dom.client.NativeEvent;
-import com.google.gwt.dom.client.Style;
-import com.google.gwt.dom.client.Style.Position;
-import com.google.gwt.event.shared.HandlerRegistration;
-import com.google.gwt.user.client.Command;
-import com.google.gwt.user.client.DOM;
-import com.google.gwt.user.client.Event;
-import com.google.gwt.user.client.History;
-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.terminal.gwt.client.ApplicationConnection;
-import com.vaadin.terminal.gwt.client.BrowserInfo;
-import com.vaadin.terminal.gwt.client.ComponentConnector;
-import com.vaadin.terminal.gwt.client.ComponentState;
-import com.vaadin.terminal.gwt.client.Connector;
-import com.vaadin.terminal.gwt.client.ConnectorHierarchyChangeEvent;
-import com.vaadin.terminal.gwt.client.ConnectorMap;
-import com.vaadin.terminal.gwt.client.Focusable;
-import com.vaadin.terminal.gwt.client.MouseEventDetails;
-import com.vaadin.terminal.gwt.client.Paintable;
-import com.vaadin.terminal.gwt.client.UIDL;
-import com.vaadin.terminal.gwt.client.Util;
-import com.vaadin.terminal.gwt.client.VConsole;
-import com.vaadin.terminal.gwt.client.communication.RpcProxy;
-import com.vaadin.terminal.gwt.client.communication.ServerRpc;
-import com.vaadin.terminal.gwt.client.communication.StateChangeEvent;
-import com.vaadin.terminal.gwt.client.communication.StateChangeEvent.StateChangeHandler;
-import com.vaadin.terminal.gwt.client.ui.Component.LoadStyle;
-import com.vaadin.ui.Root;
-
-@Component(value = Root.class, loadStyle = LoadStyle.EAGER)
-public class RootConnector extends AbstractComponentContainerConnector
- implements Paintable {
-
- public static class RootState extends ComponentState {
- private Connector content;
-
- public Connector getContent() {
- return content;
- }
-
- public void setContent(Connector content) {
- this.content = content;
- }
-
- }
-
- public interface RootServerRPC extends ClickRPC, ServerRpc {
-
- }
-
- private RootServerRPC rpc;
-
- private HandlerRegistration childStateChangeHandlerRegistration;
-
- private final StateChangeHandler childStateChangeHandler = new StateChangeHandler() {
- public void onStateChanged(StateChangeEvent stateChangeEvent) {
- // TODO Should use a more specific handler that only reacts to
- // size changes
- onChildSizeChange();
- }
- };
-
- @Override
- protected void init() {
- super.init();
- rpc = RpcProxy.create(RootServerRPC.class, this);
- }
-
- public void updateFromUIDL(final UIDL uidl, ApplicationConnection client) {
- ConnectorMap paintableMap = ConnectorMap.get(getConnection());
- getWidget().rendering = true;
- getWidget().id = getConnectorId();
- boolean firstPaint = getWidget().connection == null;
- getWidget().connection = client;
-
- getWidget().immediate = getState().isImmediate();
- getWidget().resizeLazy = uidl.hasAttribute(VView.RESIZE_LAZY);
- String newTheme = uidl.getStringAttribute("theme");
- if (getWidget().theme != null && !newTheme.equals(getWidget().theme)) {
- // Complete page refresh is needed due css can affect layout
- // calculations etc
- getWidget().reloadHostPage();
- } else {
- getWidget().theme = newTheme;
- }
- // this also implicitly removes old styles
- String styles = "";
- styles += getWidget().getStylePrimaryName() + " ";
- if (getState().hasStyles()) {
- for (String style : getState().getStyles()) {
- styles += style + " ";
- }
- }
- if (!client.getConfiguration().isStandalone()) {
- styles += getWidget().getStylePrimaryName() + "-embedded";
- }
- getWidget().setStyleName(styles.trim());
-
- clickEventHandler.handleEventHandlerRegistration();
-
- if (!getWidget().isEmbedded() && getState().getCaption() != null) {
- // only change window title if we're in charge of the whole page
- com.google.gwt.user.client.Window.setTitle(getState().getCaption());
- }
-
- // Process children
- int childIndex = 0;
-
- // Open URL:s
- boolean isClosed = false; // was this window closed?
- while (childIndex < uidl.getChildCount()
- && "open".equals(uidl.getChildUIDL(childIndex).getTag())) {
- final UIDL open = uidl.getChildUIDL(childIndex);
- final String url = client.translateVaadinUri(open
- .getStringAttribute("src"));
- final String target = open.getStringAttribute("name");
- if (target == null) {
- // source will be opened to this browser window, but we may have
- // to finish rendering this window in case this is a download
- // (and window stays open).
- Scheduler.get().scheduleDeferred(new Command() {
- public void execute() {
- VView.goTo(url);
- }
- });
- } else if ("_self".equals(target)) {
- // This window is closing (for sure). Only other opens are
- // relevant in this change. See #3558, #2144
- isClosed = true;
- VView.goTo(url);
- } else {
- String options;
- if (open.hasAttribute("border")) {
- if (open.getStringAttribute("border").equals("minimal")) {
- options = "menubar=yes,location=no,status=no";
- } else {
- options = "menubar=no,location=no,status=no";
- }
-
- } else {
- options = "resizable=yes,menubar=yes,toolbar=yes,directories=yes,location=yes,scrollbars=yes,status=yes";
- }
-
- if (open.hasAttribute("width")) {
- int w = open.getIntAttribute("width");
- options += ",width=" + w;
- }
- if (open.hasAttribute("height")) {
- int h = open.getIntAttribute("height");
- options += ",height=" + h;
- }
-
- Window.open(url, target, options);
- }
- childIndex++;
- }
- if (isClosed) {
- // don't render the content, something else will be opened to this
- // browser view
- getWidget().rendering = false;
- return;
- }
-
- // Handle other UIDL children
- UIDL childUidl;
- while ((childUidl = uidl.getChildUIDL(++childIndex)) != null) {
- String tag = childUidl.getTag().intern();
- if (tag == "actions") {
- if (getWidget().actionHandler == null) {
- getWidget().actionHandler = new ShortcutActionHandler(
- getWidget().id, client);
- }
- getWidget().actionHandler.updateActionMap(childUidl);
- } else if (tag == "execJS") {
- String script = childUidl.getStringAttribute("script");
- VView.eval(script);
- } else if (tag == "notifications") {
- for (final Iterator<?> it = childUidl.getChildIterator(); it
- .hasNext();) {
- final UIDL notification = (UIDL) it.next();
- VNotification.showNotification(client, notification);
- }
- }
- }
-
- if (uidl.hasAttribute("focused")) {
- // set focused component when render phase is finished
- Scheduler.get().scheduleDeferred(new Command() {
- public void execute() {
- ComponentConnector paintable = (ComponentConnector) uidl
- .getPaintableAttribute("focused", getConnection());
-
- final Widget toBeFocused = paintable.getWidget();
- /*
- * Two types of Widgets can be focused, either implementing
- * GWT HasFocus of a thinner Vaadin specific Focusable
- * interface.
- */
- if (toBeFocused instanceof com.google.gwt.user.client.ui.Focusable) {
- final com.google.gwt.user.client.ui.Focusable toBeFocusedWidget = (com.google.gwt.user.client.ui.Focusable) toBeFocused;
- toBeFocusedWidget.setFocus(true);
- } else if (toBeFocused instanceof Focusable) {
- ((Focusable) toBeFocused).focus();
- } else {
- VConsole.log("Could not focus component");
- }
- }
- });
- }
-
- // Add window listeners on first paint, to prevent premature
- // variablechanges
- if (firstPaint) {
- Window.addWindowClosingHandler(getWidget());
- Window.addResizeHandler(getWidget());
- }
-
- // finally set scroll position from UIDL
- if (uidl.hasVariable("scrollTop")) {
- getWidget().scrollable = true;
- getWidget().scrollTop = uidl.getIntVariable("scrollTop");
- DOM.setElementPropertyInt(getWidget().getElement(), "scrollTop",
- getWidget().scrollTop);
- getWidget().scrollLeft = uidl.getIntVariable("scrollLeft");
- DOM.setElementPropertyInt(getWidget().getElement(), "scrollLeft",
- getWidget().scrollLeft);
- } else {
- getWidget().scrollable = false;
- }
-
- // Safari workaround must be run after scrollTop is updated as it sets
- // scrollTop using a deferred command.
- if (BrowserInfo.get().isSafari()) {
- Util.runWebkitOverflowAutoFix(getWidget().getElement());
- }
-
- getWidget().scrollIntoView(uidl);
-
- if (uidl.hasAttribute(VView.FRAGMENT_VARIABLE)) {
- getWidget().currentFragment = uidl
- .getStringAttribute(VView.FRAGMENT_VARIABLE);
- if (!getWidget().currentFragment.equals(History.getToken())) {
- History.newItem(getWidget().currentFragment, true);
- }
- } else {
- // Initial request for which the server doesn't yet have a fragment
- // (and haven't shown any interest in getting one)
- getWidget().currentFragment = History.getToken();
-
- // Include current fragment in the next request
- client.updateVariable(getWidget().id, VView.FRAGMENT_VARIABLE,
- getWidget().currentFragment, false);
- }
-
- getWidget().rendering = false;
- }
-
- public void init(String rootPanelId,
- ApplicationConnection applicationConnection) {
- DOM.sinkEvents(getWidget().getElement(), Event.ONKEYDOWN
- | Event.ONSCROLL);
-
- // iview is focused when created so element needs tabIndex
- // 1 due 0 is at the end of natural tabbing order
- DOM.setElementProperty(getWidget().getElement(), "tabIndex", "1");
-
- RootPanel root = RootPanel.get(rootPanelId);
-
- // Remove the v-app-loading or any splash screen added inside the div by
- // the user
- root.getElement().setInnerHTML("");
-
- root.addStyleName("v-theme-"
- + applicationConnection.getConfiguration().getThemeName());
-
- root.add(getWidget());
-
- if (applicationConnection.getConfiguration().isStandalone()) {
- // set focus to iview element by default to listen possible keyboard
- // shortcuts. For embedded applications this is unacceptable as we
- // don't want to steal focus from the main page nor we don't want
- // side-effects from focusing (scrollIntoView).
- getWidget().getElement().focus();
- }
- }
-
- private ClickEventHandler clickEventHandler = new ClickEventHandler(this) {
-
- @Override
- protected void fireClick(NativeEvent event,
- MouseEventDetails mouseDetails) {
- rpc.click(mouseDetails);
- }
-
- };
-
- public void updateCaption(ComponentConnector component) {
- // NOP The main view never draws caption for its layout
- }
-
- @Override
- public VView getWidget() {
- return (VView) super.getWidget();
- }
-
- @Override
- protected Widget createWidget() {
- return GWT.create(VView.class);
- }
-
- protected void onChildSizeChange() {
- ComponentConnector child = (ComponentConnector) getState().getContent();
- Style childStyle = child.getWidget().getElement().getStyle();
- /*
- * Must set absolute position if the child has relative height and
- * there's a chance of horizontal scrolling as some browsers will
- * otherwise not take the scrollbar into account when calculating the
- * height. Assuming v-view does not have an undefined width for now, see
- * #8460.
- */
- if (child.isRelativeHeight() && !BrowserInfo.get().isIE9()) {
- childStyle.setPosition(Position.ABSOLUTE);
- } else {
- childStyle.clearPosition();
- }
- }
-
- /**
- * Checks if the given sub window is a child of this Root Connector
- *
- * @deprecated Should be replaced by a more generic mechanism for getting
- * non-ComponentConnector children
- * @param wc
- * @return
- */
- @Deprecated
- public boolean hasSubWindow(WindowConnector wc) {
- return getChildren().contains(wc);
- }
-
- /**
- * Return an iterator for current subwindows. This method is meant for
- * testing purposes only.
- *
- * @return
- */
- public List<WindowConnector> getSubWindows() {
- ArrayList<WindowConnector> windows = new ArrayList<WindowConnector>();
- for (ComponentConnector child : getChildren()) {
- if (child instanceof WindowConnector) {
- windows.add((WindowConnector) child);
- }
- }
- return windows;
- }
-
- @Override
- public RootState getState() {
- return (RootState) super.getState();
- }
-
- @Override
- public void onConnectorHierarchyChange(ConnectorHierarchyChangeEvent event) {
- super.onConnectorHierarchyChange(event);
-
- ComponentConnector oldChild = null;
- ComponentConnector newChild = (ComponentConnector) getState()
- .getContent();
-
- for (ComponentConnector c : event.getOldChildren()) {
- if (!(c instanceof WindowConnector)) {
- oldChild = c;
- break;
- }
- }
-
- if (oldChild != newChild) {
- if (childStateChangeHandlerRegistration != null) {
- childStateChangeHandlerRegistration.removeHandler();
- childStateChangeHandlerRegistration = null;
- }
- getWidget().setWidget(newChild.getWidget());
- childStateChangeHandlerRegistration = newChild
- .addStateChangeHandler(childStateChangeHandler);
- // Must handle new child here as state change events are already
- // fired
- onChildSizeChange();
- }
-
- for (ComponentConnector c : getChildren()) {
- if (c instanceof WindowConnector) {
- WindowConnector wc = (WindowConnector) c;
- wc.setWindowOrderAndPosition();
- }
- }
-
- // Close removed sub windows
- for (ComponentConnector c : event.getOldChildren()) {
- if (c.getParent() != this && c instanceof WindowConnector) {
- ((WindowConnector) c).getWidget().hide();
- }
- }
- }
-}
import com.vaadin.terminal.gwt.client.BrowserInfo;
import com.vaadin.terminal.gwt.client.UIDL;
import com.vaadin.terminal.gwt.client.Util;
+import com.vaadin.terminal.gwt.client.ui.root.VRoot;
public class VNotification extends VOverlay {
public static void showNotification(ApplicationConnection client,
final UIDL notification) {
boolean onlyPlainText = notification
- .hasAttribute(VView.NOTIFICATION_HTML_CONTENT_NOT_ALLOWED);
+ .hasAttribute(VRoot.NOTIFICATION_HTML_CONTENT_NOT_ALLOWED);
String html = "";
if (notification.hasAttribute(ATTRIBUTE_NOTIFICATION_ICON)) {
final String parsedUri = client.translateVaadinUri(notification
+++ /dev/null
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-
-package com.vaadin.terminal.gwt.client.ui;
-
-import java.util.ArrayList;
-
-import com.google.gwt.core.client.Scheduler;
-import com.google.gwt.core.client.Scheduler.ScheduledCommand;
-import com.google.gwt.event.logical.shared.ResizeEvent;
-import com.google.gwt.event.logical.shared.ResizeHandler;
-import com.google.gwt.event.logical.shared.ValueChangeEvent;
-import com.google.gwt.event.logical.shared.ValueChangeHandler;
-import com.google.gwt.event.shared.HandlerRegistration;
-import com.google.gwt.user.client.Command;
-import com.google.gwt.user.client.DOM;
-import com.google.gwt.user.client.Event;
-import com.google.gwt.user.client.History;
-import com.google.gwt.user.client.Timer;
-import com.google.gwt.user.client.Window;
-import com.google.gwt.user.client.ui.SimplePanel;
-import com.vaadin.terminal.gwt.client.ApplicationConnection;
-import com.vaadin.terminal.gwt.client.BrowserInfo;
-import com.vaadin.terminal.gwt.client.ComponentConnector;
-import com.vaadin.terminal.gwt.client.Focusable;
-import com.vaadin.terminal.gwt.client.UIDL;
-import com.vaadin.terminal.gwt.client.Util;
-import com.vaadin.terminal.gwt.client.VConsole;
-import com.vaadin.terminal.gwt.client.ui.ShortcutActionHandler.ShortcutActionHandlerOwner;
-
-/**
- *
- */
-public class VView extends SimplePanel implements ResizeHandler,
- Window.ClosingHandler, ShortcutActionHandlerOwner, Focusable {
-
- public static final String FRAGMENT_VARIABLE = "fragment";
-
- private static final String CLASSNAME = "v-view";
-
- public static final String NOTIFICATION_HTML_CONTENT_NOT_ALLOWED = "useplain";
-
- String theme;
-
- String id;
-
- ShortcutActionHandler actionHandler;
-
- /** stored width for IE resize optimization */
- private int width;
-
- /** stored height for IE resize optimization */
- private int height;
-
- ApplicationConnection connection;
-
- /** Identifies the click event */
- public static final String CLICK_EVENT_ID = "click";
-
- /**
- * We are postponing resize process with IE. IE bugs with scrollbars in some
- * situations, that causes false onWindowResized calls. With Timer we will
- * give IE some time to decide if it really wants to keep current size
- * (scrollbars).
- */
- private Timer resizeTimer;
-
- int scrollTop;
-
- int scrollLeft;
-
- boolean rendering;
-
- boolean scrollable;
-
- boolean immediate;
-
- boolean resizeLazy = false;
-
- /**
- * Attribute name for the lazy resize setting .
- */
- public static final String RESIZE_LAZY = "rL";
-
- private HandlerRegistration historyHandlerRegistration;
-
- /**
- * The current URI fragment, used to avoid sending updates if nothing has
- * changed.
- */
- String currentFragment;
-
- /**
- * Listener for URI fragment changes. Notifies the server of the new value
- * whenever the value changes.
- */
- private final ValueChangeHandler<String> historyChangeHandler = new ValueChangeHandler<String>() {
- public void onValueChange(ValueChangeEvent<String> event) {
- String newFragment = event.getValue();
-
- // Send the new fragment to the server if it has changed
- if (!newFragment.equals(currentFragment) && connection != null) {
- currentFragment = newFragment;
- connection.updateVariable(id, FRAGMENT_VARIABLE, newFragment,
- true);
- }
- }
- };
-
- private VLazyExecutor delayedResizeExecutor = new VLazyExecutor(200,
- new ScheduledCommand() {
- public void execute() {
- windowSizeMaybeChanged(Window.getClientWidth(),
- Window.getClientHeight());
- }
-
- });
-
- public VView() {
- super();
- setStyleName(CLASSNAME);
-
- // Allow focusing the view by using the focus() method, the view
- // should not be in the document focus flow
- getElement().setTabIndex(-1);
- }
-
- @Override
- protected void onAttach() {
- super.onAttach();
- historyHandlerRegistration = History
- .addValueChangeHandler(historyChangeHandler);
- currentFragment = History.getToken();
- }
-
- @Override
- protected void onDetach() {
- super.onDetach();
- historyHandlerRegistration.removeHandler();
- historyHandlerRegistration = null;
- }
-
- /**
- * Called when the window might have been resized.
- *
- * @param newWidth
- * The new width of the window
- * @param newHeight
- * The new height of the window
- */
- protected void windowSizeMaybeChanged(int newWidth, int newHeight) {
- boolean changed = false;
- if (width != newWidth) {
- width = newWidth;
- changed = true;
- VConsole.log("New window width: " + width);
- }
- if (height != newHeight) {
- height = newHeight;
- changed = true;
- VConsole.log("New window height: " + height);
- }
- if (changed) {
- VConsole.log("Running layout functions due to window resize");
- Util.runWebkitOverflowAutoFix(getElement());
-
- sendClientResized();
-
- connection.doLayout(false);
- }
- }
-
- public String getTheme() {
- return theme;
- }
-
- /**
- * Used to reload host page on theme changes.
- */
- static native void reloadHostPage()
- /*-{
- $wnd.location.reload();
- }-*/;
-
- /**
- * Evaluate the given script in the browser document.
- *
- * @param script
- * Script to be executed.
- */
- static native void eval(String script)
- /*-{
- try {
- if (script == null) return;
- $wnd.eval(script);
- } catch (e) {
- }
- }-*/;
-
- /**
- * Returns true if the body is NOT generated, i.e if someone else has made
- * the page that we're running in. Otherwise we're in charge of the whole
- * page.
- *
- * @return true if we're running embedded
- */
- public boolean isEmbedded() {
- return !getElement().getOwnerDocument().getBody().getClassName()
- .contains(ApplicationConnection.GENERATED_BODY_CLASSNAME);
- }
-
- /**
- * Tries to scroll paintable referenced from given UIDL snippet to be
- * visible.
- *
- * @param uidl
- */
- void scrollIntoView(final UIDL uidl) {
- if (uidl.hasAttribute("scrollTo")) {
- Scheduler.get().scheduleDeferred(new Command() {
- public void execute() {
- final ComponentConnector paintable = (ComponentConnector) uidl
- .getPaintableAttribute("scrollTo", connection);
- paintable.getWidget().getElement().scrollIntoView();
- }
- });
- }
- }
-
- @Override
- public void onBrowserEvent(Event event) {
- super.onBrowserEvent(event);
- int type = DOM.eventGetType(event);
- if (type == Event.ONKEYDOWN && actionHandler != null) {
- actionHandler.handleKeyboardEvent(event);
- return;
- } else if (scrollable && type == Event.ONSCROLL) {
- updateScrollPosition();
- }
- }
-
- /**
- * Updates scroll position from DOM and saves variables to server.
- */
- private void updateScrollPosition() {
- int oldTop = scrollTop;
- int oldLeft = scrollLeft;
- scrollTop = DOM.getElementPropertyInt(getElement(), "scrollTop");
- scrollLeft = DOM.getElementPropertyInt(getElement(), "scrollLeft");
- if (connection != null && !rendering) {
- if (oldTop != scrollTop) {
- connection.updateVariable(id, "scrollTop", scrollTop, false);
- }
- if (oldLeft != scrollLeft) {
- connection.updateVariable(id, "scrollLeft", scrollLeft, false);
- }
- }
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * com.google.gwt.event.logical.shared.ResizeHandler#onResize(com.google
- * .gwt.event.logical.shared.ResizeEvent)
- */
- public void onResize(ResizeEvent event) {
- onResize();
- }
-
- /**
- * Called when a resize event is received.
- */
- void onResize() {
- /*
- * IE (pre IE9 at least) will give us some false resize events due to
- * problems with scrollbars. Firefox 3 might also produce some extra
- * events. We postpone both the re-layouting and the server side event
- * for a while to deal with these issues.
- *
- * We may also postpone these events to avoid slowness when resizing the
- * browser window. Constantly recalculating the layout causes the resize
- * operation to be really slow with complex layouts.
- */
- boolean lazy = resizeLazy || BrowserInfo.get().isIE8();
-
- if (lazy) {
- delayedResizeExecutor.trigger();
- } else {
- windowSizeMaybeChanged(Window.getClientWidth(),
- Window.getClientHeight());
- }
- }
-
- /**
- * Send new dimensions to the server.
- */
- private void sendClientResized() {
- connection.updateVariable(id, "height", height, false);
- connection.updateVariable(id, "width", width, immediate);
- }
-
- public native static void goTo(String url)
- /*-{
- $wnd.location = url;
- }-*/;
-
- public void onWindowClosing(Window.ClosingEvent event) {
- // Change focus on this window in order to ensure that all state is
- // collected from textfields
- // TODO this is a naive hack, that only works with text fields and may
- // cause some odd issues. Should be replaced with a decent solution, see
- // also related BeforeShortcutActionListener interface. Same interface
- // might be usable here.
- VTextField.flushChangesFromFocusedTextField();
- }
-
- private native static void loadAppIdListFromDOM(ArrayList<String> list)
- /*-{
- var j;
- for(j in $wnd.vaadin.vaadinConfigurations) {
- list.@java.util.Collection::add(Ljava/lang/Object;)(j);
- }
- }-*/;
-
- public ShortcutActionHandler getShortcutActionHandler() {
- return actionHandler;
- }
-
- public void focus() {
- getElement().focus();
- }
-
-}
getWidget().setHeight(Window.getClientHeight() + "px");
}
- client.getView().getWidget().scrollIntoView(uidl);
-
if (uidl.hasAttribute("bringToFront")) {
/*
* Focus as a side-efect. Will be overridden by
--- /dev/null
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+package com.vaadin.terminal.gwt.client.ui.root;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.core.client.Scheduler;
+import com.google.gwt.dom.client.NativeEvent;
+import com.google.gwt.dom.client.Style;
+import com.google.gwt.dom.client.Style.Position;
+import com.google.gwt.event.shared.HandlerRegistration;
+import com.google.gwt.user.client.Command;
+import com.google.gwt.user.client.DOM;
+import com.google.gwt.user.client.Event;
+import com.google.gwt.user.client.History;
+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.terminal.gwt.client.ApplicationConnection;
+import com.vaadin.terminal.gwt.client.BrowserInfo;
+import com.vaadin.terminal.gwt.client.ComponentConnector;
+import com.vaadin.terminal.gwt.client.ConnectorHierarchyChangeEvent;
+import com.vaadin.terminal.gwt.client.ConnectorMap;
+import com.vaadin.terminal.gwt.client.Focusable;
+import com.vaadin.terminal.gwt.client.MouseEventDetails;
+import com.vaadin.terminal.gwt.client.Paintable;
+import com.vaadin.terminal.gwt.client.UIDL;
+import com.vaadin.terminal.gwt.client.Util;
+import com.vaadin.terminal.gwt.client.VConsole;
+import com.vaadin.terminal.gwt.client.communication.RpcProxy;
+import com.vaadin.terminal.gwt.client.communication.StateChangeEvent;
+import com.vaadin.terminal.gwt.client.communication.StateChangeEvent.StateChangeHandler;
+import com.vaadin.terminal.gwt.client.ui.AbstractComponentContainerConnector;
+import com.vaadin.terminal.gwt.client.ui.ClickEventHandler;
+import com.vaadin.terminal.gwt.client.ui.Component;
+import com.vaadin.terminal.gwt.client.ui.Component.LoadStyle;
+import com.vaadin.terminal.gwt.client.ui.ShortcutActionHandler;
+import com.vaadin.terminal.gwt.client.ui.VNotification;
+import com.vaadin.terminal.gwt.client.ui.WindowConnector;
+import com.vaadin.ui.Root;
+
+@Component(value = Root.class, loadStyle = LoadStyle.EAGER)
+public class RootConnector extends AbstractComponentContainerConnector
+ implements Paintable {
+
+ private RootServerRPC rpc = RpcProxy.create(RootServerRPC.class, this);
+
+ private HandlerRegistration childStateChangeHandlerRegistration;
+
+ private final StateChangeHandler childStateChangeHandler = new StateChangeHandler() {
+ public void onStateChanged(StateChangeEvent stateChangeEvent) {
+ // TODO Should use a more specific handler that only reacts to
+ // size changes
+ onChildSizeChange();
+ }
+ };
+
+ @Override
+ protected void init() {
+ super.init();
+ }
+
+ public void updateFromUIDL(final UIDL uidl, ApplicationConnection client) {
+ ConnectorMap paintableMap = ConnectorMap.get(getConnection());
+ getWidget().rendering = true;
+ getWidget().id = getConnectorId();
+ boolean firstPaint = getWidget().connection == null;
+ getWidget().connection = client;
+
+ getWidget().immediate = getState().isImmediate();
+ getWidget().resizeLazy = uidl.hasAttribute(VRoot.RESIZE_LAZY);
+ String newTheme = uidl.getStringAttribute("theme");
+ if (getWidget().theme != null && !newTheme.equals(getWidget().theme)) {
+ // Complete page refresh is needed due css can affect layout
+ // calculations etc
+ getWidget().reloadHostPage();
+ } else {
+ getWidget().theme = newTheme;
+ }
+ // this also implicitly removes old styles
+ String styles = "";
+ styles += getWidget().getStylePrimaryName() + " ";
+ if (getState().hasStyles()) {
+ for (String style : getState().getStyles()) {
+ styles += style + " ";
+ }
+ }
+ if (!client.getConfiguration().isStandalone()) {
+ styles += getWidget().getStylePrimaryName() + "-embedded";
+ }
+ getWidget().setStyleName(styles.trim());
+
+ clickEventHandler.handleEventHandlerRegistration();
+
+ if (!getWidget().isEmbedded() && getState().getCaption() != null) {
+ // only change window title if we're in charge of the whole page
+ com.google.gwt.user.client.Window.setTitle(getState().getCaption());
+ }
+
+ // Process children
+ int childIndex = 0;
+
+ // Open URL:s
+ boolean isClosed = false; // was this window closed?
+ while (childIndex < uidl.getChildCount()
+ && "open".equals(uidl.getChildUIDL(childIndex).getTag())) {
+ final UIDL open = uidl.getChildUIDL(childIndex);
+ final String url = client.translateVaadinUri(open
+ .getStringAttribute("src"));
+ final String target = open.getStringAttribute("name");
+ if (target == null) {
+ // source will be opened to this browser window, but we may have
+ // to finish rendering this window in case this is a download
+ // (and window stays open).
+ Scheduler.get().scheduleDeferred(new Command() {
+ public void execute() {
+ VRoot.goTo(url);
+ }
+ });
+ } else if ("_self".equals(target)) {
+ // This window is closing (for sure). Only other opens are
+ // relevant in this change. See #3558, #2144
+ isClosed = true;
+ VRoot.goTo(url);
+ } else {
+ String options;
+ if (open.hasAttribute("border")) {
+ if (open.getStringAttribute("border").equals("minimal")) {
+ options = "menubar=yes,location=no,status=no";
+ } else {
+ options = "menubar=no,location=no,status=no";
+ }
+
+ } else {
+ options = "resizable=yes,menubar=yes,toolbar=yes,directories=yes,location=yes,scrollbars=yes,status=yes";
+ }
+
+ if (open.hasAttribute("width")) {
+ int w = open.getIntAttribute("width");
+ options += ",width=" + w;
+ }
+ if (open.hasAttribute("height")) {
+ int h = open.getIntAttribute("height");
+ options += ",height=" + h;
+ }
+
+ Window.open(url, target, options);
+ }
+ childIndex++;
+ }
+ if (isClosed) {
+ // don't render the content, something else will be opened to this
+ // browser view
+ getWidget().rendering = false;
+ return;
+ }
+
+ // Handle other UIDL children
+ UIDL childUidl;
+ while ((childUidl = uidl.getChildUIDL(++childIndex)) != null) {
+ String tag = childUidl.getTag().intern();
+ if (tag == "actions") {
+ if (getWidget().actionHandler == null) {
+ getWidget().actionHandler = new ShortcutActionHandler(
+ getWidget().id, client);
+ }
+ getWidget().actionHandler.updateActionMap(childUidl);
+ } else if (tag == "execJS") {
+ String script = childUidl.getStringAttribute("script");
+ VRoot.eval(script);
+ } else if (tag == "notifications") {
+ for (final Iterator<?> it = childUidl.getChildIterator(); it
+ .hasNext();) {
+ final UIDL notification = (UIDL) it.next();
+ VNotification.showNotification(client, notification);
+ }
+ }
+ }
+
+ if (uidl.hasAttribute("focused")) {
+ // set focused component when render phase is finished
+ Scheduler.get().scheduleDeferred(new Command() {
+ public void execute() {
+ ComponentConnector paintable = (ComponentConnector) uidl
+ .getPaintableAttribute("focused", getConnection());
+
+ final Widget toBeFocused = paintable.getWidget();
+ /*
+ * Two types of Widgets can be focused, either implementing
+ * GWT HasFocus of a thinner Vaadin specific Focusable
+ * interface.
+ */
+ if (toBeFocused instanceof com.google.gwt.user.client.ui.Focusable) {
+ final com.google.gwt.user.client.ui.Focusable toBeFocusedWidget = (com.google.gwt.user.client.ui.Focusable) toBeFocused;
+ toBeFocusedWidget.setFocus(true);
+ } else if (toBeFocused instanceof Focusable) {
+ ((Focusable) toBeFocused).focus();
+ } else {
+ VConsole.log("Could not focus component");
+ }
+ }
+ });
+ }
+
+ // Add window listeners on first paint, to prevent premature
+ // variablechanges
+ if (firstPaint) {
+ Window.addWindowClosingHandler(getWidget());
+ Window.addResizeHandler(getWidget());
+ }
+
+ // finally set scroll position from UIDL
+ if (uidl.hasVariable("scrollTop")) {
+ getWidget().scrollable = true;
+ getWidget().scrollTop = uidl.getIntVariable("scrollTop");
+ DOM.setElementPropertyInt(getWidget().getElement(), "scrollTop",
+ getWidget().scrollTop);
+ getWidget().scrollLeft = uidl.getIntVariable("scrollLeft");
+ DOM.setElementPropertyInt(getWidget().getElement(), "scrollLeft",
+ getWidget().scrollLeft);
+ } else {
+ getWidget().scrollable = false;
+ }
+
+ // Safari workaround must be run after scrollTop is updated as it sets
+ // scrollTop using a deferred command.
+ if (BrowserInfo.get().isSafari()) {
+ Util.runWebkitOverflowAutoFix(getWidget().getElement());
+ }
+
+ if (uidl.hasAttribute("scrollTo")) {
+ final ComponentConnector connector = (ComponentConnector) uidl
+ .getPaintableAttribute("scrollTo", getConnection());
+ scrollIntoView(connector);
+ }
+
+ if (uidl.hasAttribute(VRoot.FRAGMENT_VARIABLE)) {
+ getWidget().currentFragment = uidl
+ .getStringAttribute(VRoot.FRAGMENT_VARIABLE);
+ if (!getWidget().currentFragment.equals(History.getToken())) {
+ History.newItem(getWidget().currentFragment, true);
+ }
+ } else {
+ // Initial request for which the server doesn't yet have a fragment
+ // (and haven't shown any interest in getting one)
+ getWidget().currentFragment = History.getToken();
+
+ // Include current fragment in the next request
+ client.updateVariable(getWidget().id, VRoot.FRAGMENT_VARIABLE,
+ getWidget().currentFragment, false);
+ }
+
+ getWidget().rendering = false;
+ }
+
+ public void init(String rootPanelId,
+ ApplicationConnection applicationConnection) {
+ DOM.sinkEvents(getWidget().getElement(), Event.ONKEYDOWN
+ | Event.ONSCROLL);
+
+ // iview is focused when created so element needs tabIndex
+ // 1 due 0 is at the end of natural tabbing order
+ DOM.setElementProperty(getWidget().getElement(), "tabIndex", "1");
+
+ RootPanel root = RootPanel.get(rootPanelId);
+
+ // Remove the v-app-loading or any splash screen added inside the div by
+ // the user
+ root.getElement().setInnerHTML("");
+
+ root.addStyleName("v-theme-"
+ + applicationConnection.getConfiguration().getThemeName());
+
+ root.add(getWidget());
+
+ if (applicationConnection.getConfiguration().isStandalone()) {
+ // set focus to iview element by default to listen possible keyboard
+ // shortcuts. For embedded applications this is unacceptable as we
+ // don't want to steal focus from the main page nor we don't want
+ // side-effects from focusing (scrollIntoView).
+ getWidget().getElement().focus();
+ }
+ }
+
+ private ClickEventHandler clickEventHandler = new ClickEventHandler(this) {
+
+ @Override
+ protected void fireClick(NativeEvent event,
+ MouseEventDetails mouseDetails) {
+ rpc.click(mouseDetails);
+ }
+
+ };
+
+ public void updateCaption(ComponentConnector component) {
+ // NOP The main view never draws caption for its layout
+ }
+
+ @Override
+ public VRoot getWidget() {
+ return (VRoot) super.getWidget();
+ }
+
+ @Override
+ protected Widget createWidget() {
+ return GWT.create(VRoot.class);
+ }
+
+ protected ComponentConnector getContent() {
+ return (ComponentConnector) getState().getContent();
+ }
+
+ protected void onChildSizeChange() {
+ ComponentConnector child = getContent();
+ Style childStyle = child.getWidget().getElement().getStyle();
+ /*
+ * Must set absolute position if the child has relative height and
+ * there's a chance of horizontal scrolling as some browsers will
+ * otherwise not take the scrollbar into account when calculating the
+ * height. Assuming v-view does not have an undefined width for now, see
+ * #8460.
+ */
+ if (child.isRelativeHeight() && !BrowserInfo.get().isIE9()) {
+ childStyle.setPosition(Position.ABSOLUTE);
+ } else {
+ childStyle.clearPosition();
+ }
+ }
+
+ /**
+ * Checks if the given sub window is a child of this Root Connector
+ *
+ * @deprecated Should be replaced by a more generic mechanism for getting
+ * non-ComponentConnector children
+ * @param wc
+ * @return
+ */
+ @Deprecated
+ public boolean hasSubWindow(WindowConnector wc) {
+ return getChildren().contains(wc);
+ }
+
+ /**
+ * Return an iterator for current subwindows. This method is meant for
+ * testing purposes only.
+ *
+ * @return
+ */
+ public List<WindowConnector> getSubWindows() {
+ ArrayList<WindowConnector> windows = new ArrayList<WindowConnector>();
+ for (ComponentConnector child : getChildren()) {
+ if (child instanceof WindowConnector) {
+ windows.add((WindowConnector) child);
+ }
+ }
+ return windows;
+ }
+
+ @Override
+ public RootState getState() {
+ return (RootState) super.getState();
+ }
+
+ @Override
+ public void onConnectorHierarchyChange(ConnectorHierarchyChangeEvent event) {
+ super.onConnectorHierarchyChange(event);
+
+ ComponentConnector oldChild = null;
+ ComponentConnector newChild = getContent();
+
+ for (ComponentConnector c : event.getOldChildren()) {
+ if (!(c instanceof WindowConnector)) {
+ oldChild = c;
+ break;
+ }
+ }
+
+ if (oldChild != newChild) {
+ if (childStateChangeHandlerRegistration != null) {
+ childStateChangeHandlerRegistration.removeHandler();
+ childStateChangeHandlerRegistration = null;
+ }
+ getWidget().setWidget(newChild.getWidget());
+ childStateChangeHandlerRegistration = newChild
+ .addStateChangeHandler(childStateChangeHandler);
+ // Must handle new child here as state change events are already
+ // fired
+ onChildSizeChange();
+ }
+
+ for (ComponentConnector c : getChildren()) {
+ if (c instanceof WindowConnector) {
+ WindowConnector wc = (WindowConnector) c;
+ wc.setWindowOrderAndPosition();
+ }
+ }
+
+ // Close removed sub windows
+ for (ComponentConnector c : event.getOldChildren()) {
+ if (c.getParent() != this && c instanceof WindowConnector) {
+ ((WindowConnector) c).getWidget().hide();
+ }
+ }
+ }
+
+ /**
+ * Tries to scroll the viewport so that the given connector is in view.
+ *
+ * @param componentConnector
+ * The connector which should be visible
+ *
+ */
+ public void scrollIntoView(final ComponentConnector componentConnector) {
+ if (componentConnector == null) {
+ return;
+ }
+
+ Scheduler.get().scheduleDeferred(new Command() {
+ public void execute() {
+ componentConnector.getWidget().getElement().scrollIntoView();
+ }
+ });
+ }
+
+}
--- /dev/null
+package com.vaadin.terminal.gwt.client.ui.root;
+
+import com.vaadin.terminal.gwt.client.communication.ServerRpc;
+import com.vaadin.terminal.gwt.client.ui.AbstractComponentConnector;
+import com.vaadin.terminal.gwt.client.ui.AbstractComponentConnector.ClickRPC;
+
+public interface RootServerRPC extends ClickRPC, ServerRpc {
+
+}
\ No newline at end of file
--- /dev/null
+package com.vaadin.terminal.gwt.client.ui.root;
+
+import com.vaadin.terminal.gwt.client.ComponentState;
+import com.vaadin.terminal.gwt.client.Connector;
+
+public class RootState extends ComponentState {
+ private Connector content;
+
+ public Connector getContent() {
+ return content;
+ }
+
+ public void setContent(Connector content) {
+ this.content = content;
+ }
+
+}
\ No newline at end of file
--- /dev/null
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.terminal.gwt.client.ui.root;
+
+import java.util.ArrayList;
+
+import com.google.gwt.core.client.Scheduler.ScheduledCommand;
+import com.google.gwt.event.logical.shared.ResizeEvent;
+import com.google.gwt.event.logical.shared.ResizeHandler;
+import com.google.gwt.event.logical.shared.ValueChangeEvent;
+import com.google.gwt.event.logical.shared.ValueChangeHandler;
+import com.google.gwt.event.shared.HandlerRegistration;
+import com.google.gwt.user.client.DOM;
+import com.google.gwt.user.client.Event;
+import com.google.gwt.user.client.History;
+import com.google.gwt.user.client.Timer;
+import com.google.gwt.user.client.Window;
+import com.google.gwt.user.client.ui.SimplePanel;
+import com.vaadin.terminal.gwt.client.ApplicationConnection;
+import com.vaadin.terminal.gwt.client.BrowserInfo;
+import com.vaadin.terminal.gwt.client.Focusable;
+import com.vaadin.terminal.gwt.client.Util;
+import com.vaadin.terminal.gwt.client.VConsole;
+import com.vaadin.terminal.gwt.client.ui.ShortcutActionHandler;
+import com.vaadin.terminal.gwt.client.ui.ShortcutActionHandler.ShortcutActionHandlerOwner;
+import com.vaadin.terminal.gwt.client.ui.VLazyExecutor;
+import com.vaadin.terminal.gwt.client.ui.VTextField;
+
+/**
+ *
+ */
+public class VRoot extends SimplePanel implements ResizeHandler,
+ Window.ClosingHandler, ShortcutActionHandlerOwner, Focusable {
+
+ public static final String FRAGMENT_VARIABLE = "fragment";
+
+ private static final String CLASSNAME = "v-view";
+
+ public static final String NOTIFICATION_HTML_CONTENT_NOT_ALLOWED = "useplain";
+
+ String theme;
+
+ String id;
+
+ ShortcutActionHandler actionHandler;
+
+ /** stored width for IE resize optimization */
+ private int width;
+
+ /** stored height for IE resize optimization */
+ private int height;
+
+ ApplicationConnection connection;
+
+ /** Identifies the click event */
+ public static final String CLICK_EVENT_ID = "click";
+
+ /**
+ * We are postponing resize process with IE. IE bugs with scrollbars in some
+ * situations, that causes false onWindowResized calls. With Timer we will
+ * give IE some time to decide if it really wants to keep current size
+ * (scrollbars).
+ */
+ private Timer resizeTimer;
+
+ int scrollTop;
+
+ int scrollLeft;
+
+ boolean rendering;
+
+ boolean scrollable;
+
+ boolean immediate;
+
+ boolean resizeLazy = false;
+
+ /**
+ * Attribute name for the lazy resize setting .
+ */
+ public static final String RESIZE_LAZY = "rL";
+
+ private HandlerRegistration historyHandlerRegistration;
+
+ /**
+ * The current URI fragment, used to avoid sending updates if nothing has
+ * changed.
+ */
+ String currentFragment;
+
+ /**
+ * Listener for URI fragment changes. Notifies the server of the new value
+ * whenever the value changes.
+ */
+ private final ValueChangeHandler<String> historyChangeHandler = new ValueChangeHandler<String>() {
+ public void onValueChange(ValueChangeEvent<String> event) {
+ String newFragment = event.getValue();
+
+ // Send the new fragment to the server if it has changed
+ if (!newFragment.equals(currentFragment) && connection != null) {
+ currentFragment = newFragment;
+ connection.updateVariable(id, FRAGMENT_VARIABLE, newFragment,
+ true);
+ }
+ }
+ };
+
+ private VLazyExecutor delayedResizeExecutor = new VLazyExecutor(200,
+ new ScheduledCommand() {
+ public void execute() {
+ windowSizeMaybeChanged(Window.getClientWidth(),
+ Window.getClientHeight());
+ }
+
+ });
+
+ public VRoot() {
+ super();
+ setStyleName(CLASSNAME);
+
+ // Allow focusing the view by using the focus() method, the view
+ // should not be in the document focus flow
+ getElement().setTabIndex(-1);
+ }
+
+ @Override
+ protected void onAttach() {
+ super.onAttach();
+ historyHandlerRegistration = History
+ .addValueChangeHandler(historyChangeHandler);
+ currentFragment = History.getToken();
+ }
+
+ @Override
+ protected void onDetach() {
+ super.onDetach();
+ historyHandlerRegistration.removeHandler();
+ historyHandlerRegistration = null;
+ }
+
+ /**
+ * Called when the window might have been resized.
+ *
+ * @param newWidth
+ * The new width of the window
+ * @param newHeight
+ * The new height of the window
+ */
+ protected void windowSizeMaybeChanged(int newWidth, int newHeight) {
+ boolean changed = false;
+ if (width != newWidth) {
+ width = newWidth;
+ changed = true;
+ VConsole.log("New window width: " + width);
+ }
+ if (height != newHeight) {
+ height = newHeight;
+ changed = true;
+ VConsole.log("New window height: " + height);
+ }
+ if (changed) {
+ VConsole.log("Running layout functions due to window resize");
+ Util.runWebkitOverflowAutoFix(getElement());
+
+ sendClientResized();
+
+ connection.doLayout(false);
+ }
+ }
+
+ public String getTheme() {
+ return theme;
+ }
+
+ /**
+ * Used to reload host page on theme changes.
+ */
+ static native void reloadHostPage()
+ /*-{
+ $wnd.location.reload();
+ }-*/;
+
+ /**
+ * Evaluate the given script in the browser document.
+ *
+ * @param script
+ * Script to be executed.
+ */
+ static native void eval(String script)
+ /*-{
+ try {
+ if (script == null) return;
+ $wnd.eval(script);
+ } catch (e) {
+ }
+ }-*/;
+
+ /**
+ * Returns true if the body is NOT generated, i.e if someone else has made
+ * the page that we're running in. Otherwise we're in charge of the whole
+ * page.
+ *
+ * @return true if we're running embedded
+ */
+ public boolean isEmbedded() {
+ return !getElement().getOwnerDocument().getBody().getClassName()
+ .contains(ApplicationConnection.GENERATED_BODY_CLASSNAME);
+ }
+
+ @Override
+ public void onBrowserEvent(Event event) {
+ super.onBrowserEvent(event);
+ int type = DOM.eventGetType(event);
+ if (type == Event.ONKEYDOWN && actionHandler != null) {
+ actionHandler.handleKeyboardEvent(event);
+ return;
+ } else if (scrollable && type == Event.ONSCROLL) {
+ updateScrollPosition();
+ }
+ }
+
+ /**
+ * Updates scroll position from DOM and saves variables to server.
+ */
+ private void updateScrollPosition() {
+ int oldTop = scrollTop;
+ int oldLeft = scrollLeft;
+ scrollTop = DOM.getElementPropertyInt(getElement(), "scrollTop");
+ scrollLeft = DOM.getElementPropertyInt(getElement(), "scrollLeft");
+ if (connection != null && !rendering) {
+ if (oldTop != scrollTop) {
+ connection.updateVariable(id, "scrollTop", scrollTop, false);
+ }
+ if (oldLeft != scrollLeft) {
+ connection.updateVariable(id, "scrollLeft", scrollLeft, false);
+ }
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * com.google.gwt.event.logical.shared.ResizeHandler#onResize(com.google
+ * .gwt.event.logical.shared.ResizeEvent)
+ */
+ public void onResize(ResizeEvent event) {
+ onResize();
+ }
+
+ /**
+ * Called when a resize event is received.
+ */
+ void onResize() {
+ /*
+ * IE (pre IE9 at least) will give us some false resize events due to
+ * problems with scrollbars. Firefox 3 might also produce some extra
+ * events. We postpone both the re-layouting and the server side event
+ * for a while to deal with these issues.
+ *
+ * We may also postpone these events to avoid slowness when resizing the
+ * browser window. Constantly recalculating the layout causes the resize
+ * operation to be really slow with complex layouts.
+ */
+ boolean lazy = resizeLazy || BrowserInfo.get().isIE8();
+
+ if (lazy) {
+ delayedResizeExecutor.trigger();
+ } else {
+ windowSizeMaybeChanged(Window.getClientWidth(),
+ Window.getClientHeight());
+ }
+ }
+
+ /**
+ * Send new dimensions to the server.
+ */
+ private void sendClientResized() {
+ connection.updateVariable(id, "height", height, false);
+ connection.updateVariable(id, "width", width, immediate);
+ }
+
+ public native static void goTo(String url)
+ /*-{
+ $wnd.location = url;
+ }-*/;
+
+ public void onWindowClosing(Window.ClosingEvent event) {
+ // Change focus on this window in order to ensure that all state is
+ // collected from textfields
+ // TODO this is a naive hack, that only works with text fields and may
+ // cause some odd issues. Should be replaced with a decent solution, see
+ // also related BeforeShortcutActionListener interface. Same interface
+ // might be usable here.
+ VTextField.flushChangesFromFocusedTextField();
+ }
+
+ private native static void loadAppIdListFromDOM(ArrayList<String> list)
+ /*-{
+ var j;
+ for(j in $wnd.vaadin.vaadinConfigurations) {
+ list.@java.util.Collection::add(Ljava/lang/Object;)(j);
+ }
+ }-*/;
+
+ public ShortcutActionHandler getShortcutActionHandler() {
+ return actionHandler;
+ }
+
+ public void focus() {
+ getElement().focus();
+ }
+
+}
import com.vaadin.terminal.gwt.client.Connector;
import com.vaadin.terminal.gwt.client.ui.Component;
import com.vaadin.terminal.gwt.client.ui.Component.LoadStyle;
-import com.vaadin.terminal.gwt.client.ui.RootConnector;
+import com.vaadin.terminal.gwt.client.ui.root.RootConnector;
import com.vaadin.terminal.gwt.client.ui.UnknownComponentConnector;
import com.vaadin.terminal.gwt.server.ClientConnector;
import com.vaadin.terminal.WrappedRequest;
import com.vaadin.terminal.WrappedRequest.BrowserDetails;
import com.vaadin.terminal.gwt.client.MouseEventDetails;
-import com.vaadin.terminal.gwt.client.ui.RootConnector.RootServerRPC;
-import com.vaadin.terminal.gwt.client.ui.RootConnector.RootState;
import com.vaadin.terminal.gwt.client.ui.VNotification;
-import com.vaadin.terminal.gwt.client.ui.VView;
+import com.vaadin.terminal.gwt.client.ui.root.RootServerRPC;
+import com.vaadin.terminal.gwt.client.ui.root.RootState;
+import com.vaadin.terminal.gwt.client.ui.root.VRoot;
import com.vaadin.tools.ReflectTools;
import com.vaadin.ui.Window.CloseListener;
private int browserWindowHeight = -1;
/** Identifies the click event */
- private static final String CLICK_EVENT_ID = VView.CLICK_EVENT_ID;
+ private static final String CLICK_EVENT_ID = VRoot.CLICK_EVENT_ID;
private DirtyConnectorTracker dirtyConnectorTracker = new DirtyConnectorTracker(
this);
}
if (!n.isHtmlContentAllowed()) {
target.addAttribute(
- VView.NOTIFICATION_HTML_CONTENT_NOT_ALLOWED, true);
+ VRoot.NOTIFICATION_HTML_CONTENT_NOT_ALLOWED, true);
}
target.addAttribute(
VNotification.ATTRIBUTE_NOTIFICATION_POSITION,
}
if (fragment != null) {
- target.addAttribute(VView.FRAGMENT_VARIABLE, fragment);
+ target.addAttribute(VRoot.FRAGMENT_VARIABLE, fragment);
}
if (isResizeLazy()) {
- target.addAttribute(VView.RESIZE_LAZY, true);
+ target.addAttribute(VRoot.RESIZE_LAZY, true);
}
}
actionManager.handleActions(variables, this);
}
- if (variables.containsKey(VView.FRAGMENT_VARIABLE)) {
- String fragment = (String) variables.get(VView.FRAGMENT_VARIABLE);
+ if (variables.containsKey(VRoot.FRAGMENT_VARIABLE)) {
+ String fragment = (String) variables.get(VRoot.FRAGMENT_VARIABLE);
setFragment(fragment, true);
}