--- /dev/null
- int newViewHeight = parentElement.getClientHeight();
- int newViewWidth = parentElement.getClientWidth();
-
- // Send the view dimensions if they have changed
- if (newViewHeight != viewHeight || newViewWidth != viewWidth) {
- viewHeight = newViewHeight;
- viewWidth = newViewWidth;
- connection.updateVariable(id, "height", newViewHeight, false);
- connection.updateVariable(id, "width", newViewWidth, immediate);
- }
+/*
+@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.dom.client.Element;
+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.ComponentConnector;
+import com.vaadin.terminal.gwt.client.ConnectorMap;
+import com.vaadin.terminal.gwt.client.Focusable;
+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.TouchScrollDelegate;
+import com.vaadin.terminal.gwt.client.ui.VLazyExecutor;
+import com.vaadin.terminal.gwt.client.ui.textfield.VTextField;
+
+/**
+ *
+ */
+public class VRoot extends SimplePanel implements ResizeHandler,
+ Window.ClosingHandler, ShortcutActionHandlerOwner, Focusable {
+
+ public static final String FRAGMENT_VARIABLE = "fragment";
+
++ public static final String BROWSER_HEIGHT_VAR = "browserHeight";
++
++ public static final String BROWSER_WIDTH_VAR = "browserWidth";
++
+ private static final String CLASSNAME = "v-view";
+
+ public static final String NOTIFICATION_HTML_CONTENT_NOT_ALLOWED = "useplain";
+
+ String theme;
+
+ String id;
+
+ ShortcutActionHandler actionHandler;
+
+ /*
+ * Last known window size used to detect whether VView should be layouted
+ * again. Detection must be based on window size, because the VView size
+ * might be fixed and thus not automatically adapt to changed window sizes.
+ */
+ private int windowWidth;
+ private int windowHeight;
+
+ /*
+ * Last know view size used to detect whether new dimensions should be sent
+ * to the server.
+ */
+ private int viewWidth;
+ private int viewHeight;
+
+ 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>() {
+ @Override
+ 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() {
+ @Override
+ 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);
+ TouchScrollDelegate.enableTouchScrolling(this, getElement());
+ }
+
+ @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;
+ ComponentConnector connector = ConnectorMap.get(connection)
+ .getConnector(this);
+ if (windowWidth != newWidth) {
+ windowWidth = newWidth;
+ changed = true;
+ connector.getLayoutManager().reportOuterWidth(connector, newWidth);
+ VConsole.log("New window width: " + windowWidth);
+ }
+ if (windowHeight != newHeight) {
+ windowHeight = newHeight;
+ changed = true;
+ connector.getLayoutManager()
+ .reportOuterHeight(connector, newHeight);
+ VConsole.log("New window height: " + windowHeight);
+ }
+ if (changed) {
+ /*
+ * If the window size has changed, layout the VView again and send
+ * new size to the server if the size changed. (Just checking VView
+ * size would cause us to ignore cases when a relatively sized VView
+ * should shrink as the content's size is fixed and would thus not
+ * automatically shrink.)
+ */
+ VConsole.log("Running layout functions due to window resize");
+
+ sendClientResized();
+
+ connector.getLayoutManager().layoutNow();
+ }
+ }
+
+ 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)
+ */
+ @Override
+ 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() {
+ Element parentElement = getElement().getParentElement();
++ int viewHeight = parentElement.getClientHeight();
++ int viewWidth = parentElement.getClientWidth();
++
++ connection.updateVariable(id, "height", viewHeight, false);
++ connection.updateVariable(id, "width", viewWidth, false);
++
++ int windowWidth = Window.getClientWidth();
++ int windowHeight = Window.getClientHeight();
++
++ connection.updateVariable(id, BROWSER_WIDTH_VAR, windowWidth, false);
++ connection.updateVariable(id, BROWSER_HEIGHT_VAR, windowHeight,
++ immediate);
+ }
+
+ public native static void goTo(String url)
+ /*-{
+ $wnd.location = url;
+ }-*/;
+
+ @Override
+ 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) {
+ // $entry not needed as function is not exported
+ list.@java.util.Collection::add(Ljava/lang/Object;)(j);
+ }
+ }-*/;
+
+ @Override
+ public ShortcutActionHandler getShortcutActionHandler() {
+ return actionHandler;
+ }
+
+ @Override
+ public void focus() {
+ getElement().focus();
+ }
+
+}
* @since 3.0
*/
@SuppressWarnings("serial")
-@ClientWidget(VWindow.class)
-public class Window extends Panel implements URIHandler, ParameterHandler,
- FocusNotifier, BlurNotifier {
+public class Window extends Panel implements FocusNotifier, BlurNotifier,
+ Vaadin6Component {
- /**
- * <b>Application window only</b>. A border style used for opening resources
- * in a window without a border.
- */
- public static final int BORDER_NONE = 0;
-
- /**
- * <b>Application window only</b>. A border style used for opening resources
- * in a window with a minimal border.
- */
- public static final int BORDER_MINIMAL = 1;
-
- /**
- * <b>Application window only</b>. A border style that indicates that the
- * default border style should be used when opening resources.
- */
- public static final int BORDER_DEFAULT = 2;
-
- /**
- * <b>Application window only</b>. The user terminal for this window.
- */
- private Terminal terminal = null;
-
- /**
- * <b>Application window only</b>. The application this window is attached
- * to or null.
- */
- private Application application = null;
-
- /**
- * <b>Application window only</b>. List of URI handlers for this window.
- */
- private LinkedList<URIHandler> uriHandlerList = null;
-
- /**
- * <b>Application window only</b>. List of parameter handlers for this
- * window.
- */
- private LinkedList<ParameterHandler> parameterHandlerList = null;
-
- /**
- * <b>Application window only</b>. List of sub windows in this window. A sub
- * window cannot have other sub windows.
- */
- private final LinkedHashSet<Window> subwindows = new LinkedHashSet<Window>();
-
- /**
- * <b>Application window only</b>. Explicitly specified theme of this window
- * or null if the application theme should be used.
- */
- private String theme = null;
-
- /**
- * <b>Application window only</b>. Resources to be opened automatically on
- * next repaint. The list is automatically cleared when it has been sent to
- * the client.
- */
- private final LinkedList<OpenResource> openList = new LinkedList<OpenResource>();
-
- /**
- * <b>Application window only</b>. Unique name of the window used to
- * identify it.
- */
- private String name = null;
-
- /**
- * <b>Application window only.</b> Border mode of the Window.
- */
- private int border = BORDER_DEFAULT;
-
- /**
- * <b>Sub window only</b>. Top offset in pixels for the sub window (relative
- * to the parent application window) or -1 if unspecified.
- */
- private int positionY = -1;
-
- /**
- * <b>Sub window only</b>. Left offset in pixels for the sub window
- * (relative to the parent application window) or -1 if unspecified.
- */
- private int positionX = -1;
-
- /**
- * <b>Application window only</b>. A list of notifications that are waiting
- * to be sent to the client. Cleared (set to null) when the notifications
- * have been sent.
- */
- private LinkedList<Notification> notifications;
-
- /**
- * <b>Sub window only</b>. Modality flag for sub window.
- */
- private boolean modal = false;
+ private WindowServerRpc rpc = new WindowServerRpc() {
- /**
- * <b>Sub window only</b>. Controls if the end user can resize the window.
- */
- private boolean resizable = true;
-
- /**
- * <b>Sub window only</b>. Controls if the end user can move the window by
- * dragging.
- */
- private boolean draggable = true;
-
- /**
- * <b>Sub window only</b>. Flag which is true if the window is centered on
- * the screen.
- */
- private boolean centerRequested = false;
-
- /**
- * Should resize recalculate layouts lazily (as opposed to immediately)
- */
- private boolean resizeLazy = false;
-
- /**
- * Component that should be focused after the next repaint. Null if no focus
- * change should take place.
- */
- private Focusable pendingFocus;
-
- /**
- * <b>Application window only</b>. A list of javascript commands that are
- * waiting to be sent to the client. Cleared (set to null) when the commands
- * have been sent.
- */
- private ArrayList<String> jsExecQueue = null;
-
- /**
- * The component that should be scrolled into view after the next repaint.
- * Null if nothing should be scrolled into view.
- */
- private Component scrollIntoView;
+ public void click(MouseEventDetails mouseDetails) {
+ fireEvent(new ClickEvent(Window.this, mouseDetails));
+ }
+ };
+ private int browserWindowWidth = -1;
+
+ private int browserWindowHeight = -1;
+
/**
* Creates a new unnamed window with a default layout.
*/
*/
@Override
public void focus() {
- if (getParent() != null) {
- /*
- * When focusing a sub-window it basically means it should be
- * brought to the front. Instead of just moving the keyboard focus
- * we focus the window and bring it top-most.
- */
- bringToFront();
- } else {
- super.focus();
- }
- }
-
- /**
- * Notifies the child components and subwindows that the window is attached
- * to the application.
- */
- @Override
- public void attach() {
- super.attach();
- for (Window w : subwindows) {
- w.attach();
- }
+ /*
+ * When focusing a sub-window it basically means it should be brought to
+ * the front. Instead of just moving the keyboard focus we focus the
+ * window and bring it top-most.
+ */
+ super.focus();
+ bringToFront();
}
- /**
- * Notifies the child components and subwindows that the window is detached
- * from the application.
- */
@Override
- public void detach() {
- super.detach();
- for (Window w : subwindows) {
- w.detach();
- }
+ public WindowState getState() {
+ return (WindowState) super.getState();
}
+ /**
+ * Gets the height of the viewport area of the browser window where this
+ * window is displayed.
+ *
+ * @return the browser viewport height in pixels
+ */
+ public int getBrowserWindowHeight() {
+ // Size only reported by VView -> data only available from application
+ // level window
+ if (getParent() != null) {
+ return (getParent()).getBrowserWindowHeight();
+ }
+
+ return browserWindowHeight;
+ }
+
+ /**
+ * Gets the width of the viewport area of the browser window where this
+ * window is displayed.
+ *
+ * @return the browser viewport width in pixels
+ */
+ public int getBrowserWindowWidth() {
+ // Size only reported by VView -> data only available from application
+ // level window
+ if (getParent() != null) {
+ return (getParent()).getBrowserWindowWidth();
+ }
+
+ return browserWindowWidth;
+ }
}