12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250 |
- /*
- @VaadinApache2LicenseForJavaFiles@
- */
-
- package com.vaadin.terminal.gwt.client.ui;
-
- import java.util.ArrayList;
- import java.util.Arrays;
- import java.util.Comparator;
- import java.util.Set;
-
- import com.google.gwt.core.client.Scheduler;
- import com.google.gwt.core.client.Scheduler.ScheduledCommand;
- import com.google.gwt.event.dom.client.BlurEvent;
- import com.google.gwt.event.dom.client.BlurHandler;
- import com.google.gwt.event.dom.client.DomEvent.Type;
- import com.google.gwt.event.dom.client.FocusEvent;
- import com.google.gwt.event.dom.client.FocusHandler;
- import com.google.gwt.event.dom.client.KeyDownEvent;
- import com.google.gwt.event.dom.client.KeyDownHandler;
- import com.google.gwt.event.dom.client.ScrollEvent;
- import com.google.gwt.event.dom.client.ScrollHandler;
- import com.google.gwt.event.shared.EventHandler;
- 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.Element;
- import com.google.gwt.user.client.Event;
- import com.google.gwt.user.client.Window;
- import com.google.gwt.user.client.ui.Frame;
- import com.google.gwt.user.client.ui.HasWidgets;
- 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.Console;
- import com.vaadin.terminal.gwt.client.Container;
- import com.vaadin.terminal.gwt.client.EventId;
- import com.vaadin.terminal.gwt.client.Focusable;
- import com.vaadin.terminal.gwt.client.RenderSpace;
- import com.vaadin.terminal.gwt.client.UIDL;
- import com.vaadin.terminal.gwt.client.Util;
- import com.vaadin.terminal.gwt.client.VPaintableWidget;
- import com.vaadin.terminal.gwt.client.ui.ShortcutActionHandler.BeforeShortcutActionListener;
- import com.vaadin.terminal.gwt.client.ui.ShortcutActionHandler.ShortcutActionHandlerOwner;
-
- /**
- * "Sub window" component.
- *
- * @author Vaadin Ltd
- */
- public class VWindow extends VOverlay implements Container,
- ShortcutActionHandlerOwner, ScrollHandler, KeyDownHandler,
- FocusHandler, BlurHandler, BeforeShortcutActionListener, Focusable {
-
- /**
- * Minimum allowed height of a window. This refers to the content area, not
- * the outer borders.
- */
- private static final int MIN_CONTENT_AREA_HEIGHT = 100;
-
- /**
- * Minimum allowed width of a window. This refers to the content area, not
- * the outer borders.
- */
- private static final int MIN_CONTENT_AREA_WIDTH = 150;
-
- private static ArrayList<VWindow> windowOrder = new ArrayList<VWindow>();
-
- private static boolean orderingDefered;
-
- public static final String CLASSNAME = "v-window";
-
- /**
- * Difference between offsetWidth and inner width for the content area.
- */
- private int contentAreaBorderPadding = -1;
- /**
- * Pixels used by inner borders and paddings horizontally (calculated only
- * once). This is the difference between the width of the root element and
- * the content area, such that if root element width is set to "XYZpx" the
- * inner width (width-border-padding) of the content area is
- * X-contentAreaRootDifference.
- */
- private int contentAreaToRootDifference = -1;
-
- private static final int STACKING_OFFSET_PIXELS = 15;
-
- public static final int Z_INDEX = 10000;
-
- private VPaintableWidget layout;
-
- private Element contents;
-
- private Element header;
-
- private Element footer;
-
- private Element resizeBox;
-
- private final FocusableScrollPanel contentPanel = new FocusableScrollPanel();
-
- private boolean dragging;
-
- private int startX;
-
- private int startY;
-
- private int origX;
-
- private int origY;
-
- private boolean resizing;
-
- private int origW;
-
- private int origH;
-
- private Element closeBox;
-
- protected ApplicationConnection client;
-
- private String id;
-
- ShortcutActionHandler shortcutHandler;
-
- /** Last known positionx read from UIDL or updated to application connection */
- private int uidlPositionX = -1;
-
- /** Last known positiony read from UIDL or updated to application connection */
- private int uidlPositionY = -1;
-
- private boolean vaadinModality = false;
-
- private boolean resizable = true;
-
- private boolean draggable = true;
-
- private boolean resizeLazy = false;
-
- private Element modalityCurtain;
- private Element draggingCurtain;
-
- private Element headerText;
-
- private boolean closable = true;
-
- boolean dynamicWidth = false;
- boolean dynamicHeight = false;
- boolean layoutRelativeWidth = false;
- boolean layoutRelativeHeight = false;
-
- // If centered (via UIDL), the window should stay in the centered -mode
- // until a position is received from the server, or the user moves or
- // resizes the window.
- boolean centered = false;
-
- private RenderSpace renderSpace = new RenderSpace(MIN_CONTENT_AREA_WIDTH,
- MIN_CONTENT_AREA_HEIGHT, true);
-
- private String width;
-
- private String height;
-
- private boolean immediate;
-
- private Element wrapper, wrapper2;
-
- private ClickEventHandler clickEventHandler = new ClickEventHandler(this,
- VPanel.CLICK_EVENT_IDENTIFIER) {
-
- @Override
- protected <H extends EventHandler> HandlerRegistration registerHandler(
- H handler, Type<H> type) {
- return addDomHandler(handler, type);
- }
- };
-
- private boolean visibilityChangesDisabled;
-
- private int bringToFrontSequence = -1;
-
- private VLazyExecutor delayedContentsSizeUpdater = new VLazyExecutor(200,
- new ScheduledCommand() {
-
- public void execute() {
- updateContentsSize();
- }
- });
-
- public VWindow() {
- super(false, false, true); // no autohide, not modal, shadow
- // Different style of shadow for windows
- setShadowStyle("window");
-
- final int order = windowOrder.size();
- setWindowOrder(order);
- windowOrder.add(this);
- constructDOM();
- setPopupPosition(order * STACKING_OFFSET_PIXELS, order
- * STACKING_OFFSET_PIXELS);
- contentPanel.addScrollHandler(this);
- contentPanel.addKeyDownHandler(this);
- contentPanel.addFocusHandler(this);
- contentPanel.addBlurHandler(this);
- }
-
- public void bringToFront() {
- int curIndex = windowOrder.indexOf(this);
- if (curIndex + 1 < windowOrder.size()) {
- windowOrder.remove(this);
- windowOrder.add(this);
- for (; curIndex < windowOrder.size(); curIndex++) {
- windowOrder.get(curIndex).setWindowOrder(curIndex);
- }
- }
- }
-
- /**
- * Returns true if this window is the topmost VWindow
- *
- * @return
- */
- private boolean isActive() {
- return windowOrder.get(windowOrder.size() - 1).equals(this);
- }
-
- private void setWindowOrder(int order) {
- setZIndex(order + Z_INDEX);
- }
-
- @Override
- protected void setZIndex(int zIndex) {
- super.setZIndex(zIndex);
- if (vaadinModality) {
- DOM.setStyleAttribute(getModalityCurtain(), "zIndex", "" + zIndex);
- }
- }
-
- protected Element getModalityCurtain() {
- if (modalityCurtain == null) {
- modalityCurtain = DOM.createDiv();
- modalityCurtain.setClassName(CLASSNAME + "-modalitycurtain");
- }
- return modalityCurtain;
- }
-
- protected void constructDOM() {
- setStyleName(CLASSNAME);
-
- header = DOM.createDiv();
- DOM.setElementProperty(header, "className", CLASSNAME + "-outerheader");
- headerText = DOM.createDiv();
- DOM.setElementProperty(headerText, "className", CLASSNAME + "-header");
- contents = DOM.createDiv();
- DOM.setElementProperty(contents, "className", CLASSNAME + "-contents");
- footer = DOM.createDiv();
- DOM.setElementProperty(footer, "className", CLASSNAME + "-footer");
- resizeBox = DOM.createDiv();
- DOM.setElementProperty(resizeBox, "className", CLASSNAME + "-resizebox");
- closeBox = DOM.createDiv();
- DOM.setElementProperty(closeBox, "className", CLASSNAME + "-closebox");
- DOM.appendChild(footer, resizeBox);
-
- wrapper = DOM.createDiv();
- DOM.setElementProperty(wrapper, "className", CLASSNAME + "-wrap");
-
- wrapper2 = DOM.createDiv();
- DOM.setElementProperty(wrapper2, "className", CLASSNAME + "-wrap2");
-
- DOM.appendChild(wrapper2, closeBox);
- DOM.appendChild(wrapper2, header);
- DOM.appendChild(header, headerText);
- DOM.appendChild(wrapper2, contents);
- DOM.appendChild(wrapper2, footer);
- DOM.appendChild(wrapper, wrapper2);
- DOM.appendChild(super.getContainerElement(), wrapper);
-
- sinkEvents(Event.MOUSEEVENTS | Event.TOUCHEVENTS | Event.ONCLICK
- | Event.ONLOSECAPTURE);
-
- setWidget(contentPanel);
-
- }
-
- public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
- id = uidl.getId();
- this.client = client;
-
- // Workaround needed for Testing Tools (GWT generates window DOM
- // slightly different in different browsers).
- DOM.setElementProperty(closeBox, "id", id + "_window_close");
-
- if (uidl.hasAttribute("invisible")) {
- hide();
- return;
- }
-
- if (!uidl.hasAttribute("cached")) {
- if (uidl.getBooleanAttribute("modal") != vaadinModality) {
- setVaadinModality(!vaadinModality);
- }
- if (!isAttached()) {
- setVisible(false); // hide until possible centering
- show();
- }
- if (uidl.getBooleanAttribute("resizable") != resizable) {
- setResizable(!resizable);
- }
- resizeLazy = uidl.hasAttribute(VView.RESIZE_LAZY);
-
- setDraggable(!uidl.hasAttribute("fixedposition"));
-
- // Caption must be set before required header size is measured. If
- // the caption attribute is missing the caption should be cleared.
- setCaption(uidl.getStringAttribute("caption"),
- uidl.getStringAttribute("icon"));
- }
-
- visibilityChangesDisabled = true;
- if (client.updateComponent(this, uidl, false)) {
- return;
- }
- visibilityChangesDisabled = false;
-
- clickEventHandler.handleEventHandlerRegistration(client);
-
- immediate = uidl.hasAttribute("immediate");
-
- setClosable(!uidl.getBooleanAttribute("readonly"));
-
- // Initialize the position form UIDL
- int positionx = uidl.getIntVariable("positionx");
- int positiony = uidl.getIntVariable("positiony");
- if (positionx >= 0 || positiony >= 0) {
- if (positionx < 0) {
- positionx = 0;
- }
- if (positiony < 0) {
- positiony = 0;
- }
- setPopupPosition(positionx, positiony);
- }
-
- boolean showingUrl = false;
- int childIndex = 0;
- UIDL childUidl = uidl.getChildUIDL(childIndex++);
- while ("open".equals(childUidl.getTag())) {
- // TODO multiple opens with the same target will in practice just
- // open the last one - should we fix that somehow?
- final String parsedUri = client.translateVaadinUri(childUidl
- .getStringAttribute("src"));
- if (!childUidl.hasAttribute("name")) {
- final Frame frame = new Frame();
- DOM.setStyleAttribute(frame.getElement(), "width", "100%");
- DOM.setStyleAttribute(frame.getElement(), "height", "100%");
- DOM.setStyleAttribute(frame.getElement(), "border", "0px");
- frame.setUrl(parsedUri);
- contentPanel.setWidget(frame);
- showingUrl = true;
- } else {
- final String target = childUidl.getStringAttribute("name");
- Window.open(parsedUri, target, "");
- }
- childUidl = uidl.getChildUIDL(childIndex++);
- }
-
- final VPaintableWidget lo = client.getPaintable(childUidl);
- if (layout != null) {
- if (layout != lo) {
- // remove old
- client.unregisterPaintable(layout);
- contentPanel.remove(layout.getWidgetForPaintable());
- // add new
- if (!showingUrl) {
- contentPanel.setWidget(lo.getWidgetForPaintable());
- }
- layout = lo;
- }
- } else if (!showingUrl) {
- contentPanel.setWidget(lo.getWidgetForPaintable());
- layout = lo;
- }
-
- dynamicWidth = !uidl.hasAttribute("width");
- dynamicHeight = !uidl.hasAttribute("height");
-
- layoutRelativeWidth = uidl.hasAttribute("layoutRelativeWidth");
- layoutRelativeHeight = uidl.hasAttribute("layoutRelativeHeight");
-
- if (dynamicWidth && layoutRelativeWidth) {
- /*
- * Relative layout width, fix window width before rendering (width
- * according to caption)
- */
- setNaturalWidth();
- }
-
- layout.updateFromUIDL(childUidl, client);
- if (!dynamicHeight && layoutRelativeWidth) {
- /*
- * Relative layout width, and fixed height. Must update the size to
- * be able to take scrollbars into account (layout gets narrower
- * space if it is higher than the window) -> only vertical scrollbar
- */
- client.runDescendentsLayout(this);
- }
-
- /*
- * No explicit width is set and the layout does not have relative width
- * so fix the size according to the layout.
- */
- if (dynamicWidth && !layoutRelativeWidth) {
- setNaturalWidth();
- }
-
- if (dynamicHeight && layoutRelativeHeight) {
- // Prevent resizing until height has been fixed
- resizable = false;
- }
-
- // we may have actions and notifications
- if (uidl.getChildCount() > 1) {
- final int cnt = uidl.getChildCount();
- for (int i = 1; i < cnt; i++) {
- childUidl = uidl.getChildUIDL(i);
- if (childUidl.getTag().equals("actions")) {
- if (shortcutHandler == null) {
- shortcutHandler = new ShortcutActionHandler(id, client);
- }
- shortcutHandler.updateActionMap(childUidl);
- }
- }
-
- }
-
- // setting scrollposition must happen after children is rendered
- contentPanel.setScrollPosition(uidl.getIntVariable("scrollTop"));
- contentPanel.setHorizontalScrollPosition(uidl
- .getIntVariable("scrollLeft"));
-
- // Center this window on screen if requested
- // This has to be here because we might not know the content size before
- // everything is painted into the window
- if (uidl.getBooleanAttribute("center")) {
- // mark as centered - this is unset on move/resize
- centered = true;
- center();
- } else {
- // don't try to center the window anymore
- centered = false;
- }
- updateShadowSizeAndPosition();
- setVisible(true);
-
- boolean sizeReduced = false;
- // ensure window is not larger than browser window
- if (getOffsetWidth() > Window.getClientWidth()) {
- setWidth(Window.getClientWidth() + "px");
- sizeReduced = true;
- }
- if (getOffsetHeight() > Window.getClientHeight()) {
- setHeight(Window.getClientHeight() + "px");
- sizeReduced = true;
- }
-
- if (dynamicHeight && layoutRelativeHeight) {
- /*
- * Window height is undefined, layout is 100% high so the layout
- * should define the initial window height but on resize the layout
- * should be as high as the window. We fix the height to deal with
- * this.
- */
-
- int h = contents.getOffsetHeight() + getExtraHeight();
- int w = getElement().getOffsetWidth();
-
- client.updateVariable(id, "height", h, false);
- client.updateVariable(id, "width", w, true);
- }
-
- if (sizeReduced) {
- // If we changed the size we need to update the size of the child
- // component if it is relative (#3407)
- client.runDescendentsLayout(this);
- }
-
- Util.runWebkitOverflowAutoFix(contentPanel.getElement());
-
- client.getView().scrollIntoView(uidl);
-
- if (uidl.hasAttribute("bringToFront")) {
- /*
- * Focus as a side-efect. Will be overridden by
- * ApplicationConnection if another component was focused by the
- * server side.
- */
- contentPanel.focus();
- bringToFrontSequence = uidl.getIntAttribute("bringToFront");
- deferOrdering();
- }
- }
-
- /**
- * Calling this method will defer ordering algorithm, to order windows based
- * on servers bringToFront and modality instructions. Non changed windows
- * will be left intact.
- */
- private static void deferOrdering() {
- if (!orderingDefered) {
- orderingDefered = true;
- Scheduler.get().scheduleFinally(new Command() {
- public void execute() {
- doServerSideOrdering();
- }
- });
- }
- }
-
- private static void doServerSideOrdering() {
- orderingDefered = false;
- VWindow[] array = windowOrder.toArray(new VWindow[windowOrder.size()]);
- Arrays.sort(array, new Comparator<VWindow>() {
- public int compare(VWindow o1, VWindow o2) {
- /*
- * Order by modality, then by bringtofront sequence.
- */
-
- if (o1.vaadinModality && !o2.vaadinModality) {
- return 1;
- } else if (!o1.vaadinModality && o2.vaadinModality) {
- return -1;
- } else if (o1.bringToFrontSequence > o2.bringToFrontSequence) {
- return 1;
- } else if (o1.bringToFrontSequence < o2.bringToFrontSequence) {
- return -1;
- } else {
- return 0;
- }
- }
- });
- for (int i = 0; i < array.length; i++) {
- VWindow w = array[i];
- if (w.bringToFrontSequence != -1 || w.vaadinModality) {
- w.bringToFront();
- w.bringToFrontSequence = -1;
- }
- }
- }
-
- @Override
- public void setVisible(boolean visible) {
- /*
- * Visibility with VWindow works differently than with other Paintables
- * in Vaadin. Invisible VWindows are not attached to DOM at all. Flag is
- * used to avoid visibility call from
- * ApplicationConnection.updateComponent();
- */
- if (!visibilityChangesDisabled) {
- super.setVisible(visible);
- }
- }
-
- private void setDraggable(boolean draggable) {
- if (this.draggable == draggable) {
- return;
- }
-
- this.draggable = draggable;
-
- if (!this.draggable) {
- header.getStyle().setProperty("cursor", "default");
- } else {
- header.getStyle().setProperty("cursor", "");
- }
-
- }
-
- private void setNaturalWidth() {
- /*
- * Use max(layout width, window width) i.e layout content width or
- * caption width. We remove the previous set width so the width is
- * allowed to shrink. All widths are measured as outer sizes, i.e. the
- * borderWidth is added to the content.
- */
-
- DOM.setStyleAttribute(getElement(), "width", "");
-
- // Content
- int contentWidth = contentPanel.getElement().getScrollWidth();
- contentWidth += getContentAreaToRootDifference();
-
- // Window width (caption)
- int windowCaptionWidth = getOffsetWidth();
-
- int naturalWidth = (contentWidth > windowCaptionWidth ? contentWidth
- : windowCaptionWidth);
-
- setWidth(naturalWidth + "px");
- }
-
- private int getContentAreaToRootDifference() {
- if (contentAreaToRootDifference < 0) {
- measure();
- }
- return contentAreaToRootDifference;
- }
-
- private void measure() {
- if (!isAttached()) {
- return;
- }
-
- contentAreaBorderPadding = Util.measureHorizontalPaddingAndBorder(
- contents, 4);
- int wrapperPaddingBorder = Util.measureHorizontalPaddingAndBorder(
- wrapper, 0)
- + Util.measureHorizontalPaddingAndBorder(wrapper2, 0);
-
- contentAreaToRootDifference = wrapperPaddingBorder
- + contentAreaBorderPadding;
-
- }
-
- /**
- * Sets the closable state of the window. Additionally hides/shows the close
- * button according to the new state.
- *
- * @param closable
- * true if the window can be closed by the user
- */
- protected void setClosable(boolean closable) {
- if (this.closable == closable) {
- return;
- }
-
- this.closable = closable;
- if (closable) {
- DOM.setStyleAttribute(closeBox, "display", "");
- } else {
- DOM.setStyleAttribute(closeBox, "display", "none");
- }
-
- }
-
- /**
- * Returns the closable state of the sub window. If the sub window is
- * closable a decoration (typically an X) is shown to the user. By clicking
- * on the X the user can close the window.
- *
- * @return true if the sub window is closable
- */
- protected boolean isClosable() {
- return closable;
- }
-
- @Override
- public void show() {
- if (vaadinModality) {
- showModalityCurtain();
- }
- super.show();
- }
-
- @Override
- public void hide() {
- if (vaadinModality) {
- hideModalityCurtain();
- }
- super.hide();
- }
-
- private void setVaadinModality(boolean modality) {
- vaadinModality = modality;
- if (vaadinModality) {
- if (isAttached()) {
- showModalityCurtain();
- }
- deferOrdering();
- } else {
- if (modalityCurtain != null) {
- if (isAttached()) {
- hideModalityCurtain();
- }
- modalityCurtain = null;
- }
- }
- }
-
- private void showModalityCurtain() {
- DOM.setStyleAttribute(getModalityCurtain(), "zIndex",
- "" + (windowOrder.indexOf(this) + Z_INDEX));
- if (isShowing()) {
- RootPanel.getBodyElement().insertBefore(getModalityCurtain(),
- getElement());
- } else {
- DOM.appendChild(RootPanel.getBodyElement(), getModalityCurtain());
- }
- }
-
- private void hideModalityCurtain() {
- DOM.removeChild(RootPanel.getBodyElement(), modalityCurtain);
- }
-
- /*
- * Shows (or hides) an empty div on top of all other content; used when
- * resizing or moving, so that iframes (etc) do not steal event.
- */
- private void showDraggingCurtain(boolean show) {
- if (show && draggingCurtain == null) {
-
- draggingCurtain = DOM.createDiv();
- DOM.setStyleAttribute(draggingCurtain, "position", "absolute");
- DOM.setStyleAttribute(draggingCurtain, "top", "0px");
- DOM.setStyleAttribute(draggingCurtain, "left", "0px");
- DOM.setStyleAttribute(draggingCurtain, "width", "100%");
- DOM.setStyleAttribute(draggingCurtain, "height", "100%");
- DOM.setStyleAttribute(draggingCurtain, "zIndex", ""
- + VOverlay.Z_INDEX);
-
- DOM.appendChild(RootPanel.getBodyElement(), draggingCurtain);
- } else if (!show && draggingCurtain != null) {
-
- DOM.removeChild(RootPanel.getBodyElement(), draggingCurtain);
- draggingCurtain = null;
- }
-
- }
-
- private void setResizable(boolean resizability) {
- resizable = resizability;
- if (resizability) {
- DOM.setElementProperty(footer, "className", CLASSNAME + "-footer");
- DOM.setElementProperty(resizeBox, "className", CLASSNAME
- + "-resizebox");
- } else {
- DOM.setElementProperty(footer, "className", CLASSNAME + "-footer "
- + CLASSNAME + "-footer-noresize");
- DOM.setElementProperty(resizeBox, "className", CLASSNAME
- + "-resizebox " + CLASSNAME + "-resizebox-disabled");
- }
- }
-
- @Override
- public void setPopupPosition(int left, int top) {
- if (top < 0) {
- // ensure window is not moved out of browser window from top of the
- // screen
- top = 0;
- }
- super.setPopupPosition(left, top);
- if (left != uidlPositionX && client != null) {
- client.updateVariable(id, "positionx", left, false);
- uidlPositionX = left;
- }
- if (top != uidlPositionY && client != null) {
- client.updateVariable(id, "positiony", top, false);
- uidlPositionY = top;
- }
- }
-
- public void setCaption(String c) {
- setCaption(c, null);
- }
-
- public void setCaption(String c, String icon) {
- String html = Util.escapeHTML(c);
- if (icon != null) {
- icon = client.translateVaadinUri(icon);
- html = "<img src=\"" + Util.escapeAttribute(icon)
- + "\" class=\"v-icon\" />" + html;
- }
- DOM.setInnerHTML(headerText, html);
- }
-
- @Override
- protected Element getContainerElement() {
- // in GWT 1.5 this method is used in PopupPanel constructor
- if (contents == null) {
- return super.getContainerElement();
- }
- return contents;
- }
-
- @Override
- public void onBrowserEvent(final Event event) {
- boolean bubble = true;
-
- final int type = event.getTypeInt();
-
- final Element target = DOM.eventGetTarget(event);
-
- if (client != null && header.isOrHasChild(target)) {
- // Handle window caption tooltips
- client.handleTooltipEvent(event, this);
- }
-
- if (resizing || resizeBox == target) {
- onResizeEvent(event);
- bubble = false;
- } else if (isClosable() && target == closeBox) {
- if (type == Event.ONCLICK) {
- onCloseClick();
- }
- bubble = false;
- } else if (dragging || !contents.isOrHasChild(target)) {
- onDragEvent(event);
- bubble = false;
- } else if (type == Event.ONCLICK) {
- // clicked inside window, ensure to be on top
- if (!isActive()) {
- bringToFront();
- }
- }
-
- /*
- * If clicking on other than the content, move focus to the window.
- * After that this windows e.g. gets all keyboard shortcuts.
- */
- if (type == Event.ONMOUSEDOWN
- && !contentPanel.getElement().isOrHasChild(target)
- && target != closeBox) {
- contentPanel.focus();
- }
-
- if (!bubble) {
- event.stopPropagation();
- } else {
- // Super.onBrowserEvent takes care of Handlers added by the
- // ClickEventHandler
- super.onBrowserEvent(event);
- }
- }
-
- private void onCloseClick() {
- client.updateVariable(id, "close", true, true);
- }
-
- private void onResizeEvent(Event event) {
- if (resizable) {
- switch (event.getTypeInt()) {
- case Event.ONMOUSEDOWN:
- case Event.ONTOUCHSTART:
- if (!isActive()) {
- bringToFront();
- }
- showDraggingCurtain(true);
- if (BrowserInfo.get().isIE()) {
- DOM.setStyleAttribute(resizeBox, "visibility", "hidden");
- }
- resizing = true;
- startX = Util.getTouchOrMouseClientX(event);
- startY = Util.getTouchOrMouseClientY(event);
- origW = getElement().getOffsetWidth();
- origH = getElement().getOffsetHeight();
- DOM.setCapture(getElement());
- event.preventDefault();
- break;
- case Event.ONMOUSEUP:
- case Event.ONTOUCHEND:
- setSize(event, true);
- case Event.ONTOUCHCANCEL:
- DOM.releaseCapture(getElement());
- case Event.ONLOSECAPTURE:
- showDraggingCurtain(false);
- if (BrowserInfo.get().isIE()) {
- DOM.setStyleAttribute(resizeBox, "visibility", "");
- }
- resizing = false;
- break;
- case Event.ONMOUSEMOVE:
- case Event.ONTOUCHMOVE:
- if (resizing) {
- centered = false;
- setSize(event, false);
- event.preventDefault();
- }
- break;
- default:
- event.preventDefault();
- break;
- }
- }
- }
-
- /**
- * TODO check if we need to support this with touch based devices.
- *
- * Checks if the cursor was inside the browser content area when the event
- * happened.
- *
- * @param event
- * The event to be checked
- * @return true, if the cursor is inside the browser content area
- *
- * false, otherwise
- */
- private boolean cursorInsideBrowserContentArea(Event event) {
- if (event.getClientX() < 0 || event.getClientY() < 0) {
- // Outside to the left or above
- return false;
- }
-
- if (event.getClientX() > Window.getClientWidth()
- || event.getClientY() > Window.getClientHeight()) {
- // Outside to the right or below
- return false;
- }
-
- return true;
- }
-
- private void setSize(Event event, boolean updateVariables) {
- if (!cursorInsideBrowserContentArea(event)) {
- // Only drag while cursor is inside the browser client area
- return;
- }
-
- int w = Util.getTouchOrMouseClientX(event) - startX + origW;
- if (w < MIN_CONTENT_AREA_WIDTH + getContentAreaToRootDifference()) {
- w = MIN_CONTENT_AREA_WIDTH + getContentAreaToRootDifference();
- }
-
- int h = Util.getTouchOrMouseClientY(event) - startY + origH;
- if (h < MIN_CONTENT_AREA_HEIGHT + getExtraHeight()) {
- h = MIN_CONTENT_AREA_HEIGHT + getExtraHeight();
- }
-
- setWidth(w + "px");
- setHeight(h + "px");
-
- if (updateVariables) {
- // sending width back always as pixels, no need for unit
- client.updateVariable(id, "width", w, false);
- client.updateVariable(id, "height", h, immediate);
- }
-
- if (updateVariables || !resizeLazy) {
- // Resize has finished or is not lazy
- updateContentsSize();
- } else {
- // Lazy resize - wait for a while before re-rendering contents
- delayedContentsSizeUpdater.trigger();
- }
- }
-
- private void updateContentsSize() {
- // Update child widget dimensions
- if (client != null) {
- client.handleComponentRelativeSize(layout.getWidgetForPaintable());
- client.runDescendentsLayout((HasWidgets) layout
- .getWidgetForPaintable());
- }
-
- Util.runWebkitOverflowAutoFix(contentPanel.getElement());
- }
-
- @Override
- /**
- * Width is set to the out-most element (v-window).
- *
- * This function should never be called with percentage values (it will
- * throw an exception)
- */
- public void setWidth(String width) {
- this.width = width;
- if (!isAttached()) {
- return;
- }
- if (width != null && !"".equals(width)) {
- int rootPixelWidth = -1;
- if (width.indexOf("px") < 0) {
- /*
- * Convert non-pixel values to pixels by setting the width and
- * then measuring it. Updates the "width" variable with the
- * pixel width.
- */
- DOM.setStyleAttribute(getElement(), "width", width);
- rootPixelWidth = getElement().getOffsetWidth();
- width = rootPixelWidth + "px";
- } else {
- rootPixelWidth = Integer.parseInt(width.substring(0,
- width.indexOf("px")));
- }
-
- // "width" now contains the new width in pixels
-
- // Apply the new pixel width
- getElement().getStyle().setProperty("width", width);
-
- // Caculate the inner width of the content area
- int contentAreaInnerWidth = rootPixelWidth
- - getContentAreaToRootDifference();
- if (contentAreaInnerWidth < MIN_CONTENT_AREA_WIDTH) {
- contentAreaInnerWidth = MIN_CONTENT_AREA_WIDTH;
- int rootWidth = contentAreaInnerWidth
- + getContentAreaToRootDifference();
- DOM.setStyleAttribute(getElement(), "width", rootWidth + "px");
- }
-
- renderSpace.setWidth(contentAreaInnerWidth);
-
- updateShadowSizeAndPosition();
- }
- }
-
- @Override
- /**
- * Height is set to the out-most element (v-window).
- *
- * This function should never be called with percentage values (it will
- * throw an exception)
- *
- * @param height A CSS string specifying the new height of the window.
- * An empty string or null clears the height and lets
- * the browser to compute it based on the window contents.
- */
- public void setHeight(String height) {
- if (!isAttached()
- || (height == null ? this.height == null : height
- .equals(this.height))) {
- return;
- }
- if (height == null || "".equals(height)) {
- getElement().getStyle().clearHeight();
- contentPanel.getElement().getStyle().clearHeight();
- // Reset to default, the exact value does not actually
- // matter as an undefined-height parent should not have
- // a relative-height child anyway.
- renderSpace.setHeight(MIN_CONTENT_AREA_HEIGHT);
- } else {
- getElement().getStyle().setProperty("height", height);
- int contentHeight = getElement().getOffsetHeight()
- - getExtraHeight();
- if (contentHeight < MIN_CONTENT_AREA_HEIGHT) {
- contentHeight = MIN_CONTENT_AREA_HEIGHT;
- int rootHeight = contentHeight + getExtraHeight();
- getElement().getStyle()
- .setProperty("height", rootHeight + "px");
- }
- renderSpace.setHeight(contentHeight);
- contentPanel.getElement().getStyle()
- .setProperty("height", contentHeight + "px");
- }
- this.height = height;
- updateShadowSizeAndPosition();
- }
-
- private int extraH = 0;
-
- private int getExtraHeight() {
- extraH = header.getOffsetHeight() + footer.getOffsetHeight();
- return extraH;
- }
-
- private void onDragEvent(Event event) {
- switch (DOM.eventGetType(event)) {
- case Event.ONTOUCHSTART:
- if (event.getTouches().length() > 1) {
- return;
- }
- case Event.ONMOUSEDOWN:
- if (!isActive()) {
- bringToFront();
- }
- beginMovingWindow(event);
- break;
- case Event.ONMOUSEUP:
- case Event.ONTOUCHEND:
- case Event.ONTOUCHCANCEL:
- case Event.ONLOSECAPTURE:
- stopMovingWindow();
- break;
- case Event.ONMOUSEMOVE:
- case Event.ONTOUCHMOVE:
- moveWindow(event);
- break;
- default:
- break;
- }
- }
-
- private void moveWindow(Event event) {
- if (dragging) {
- centered = false;
- if (cursorInsideBrowserContentArea(event)) {
- // Only drag while cursor is inside the browser client area
- final int x = Util.getTouchOrMouseClientX(event) - startX
- + origX;
- final int y = Util.getTouchOrMouseClientY(event) - startY
- + origY;
- setPopupPosition(x, y);
- }
- DOM.eventPreventDefault(event);
- }
- }
-
- private void beginMovingWindow(Event event) {
- if (draggable) {
- showDraggingCurtain(true);
- dragging = true;
- startX = Util.getTouchOrMouseClientX(event);
- startY = Util.getTouchOrMouseClientY(event);
- origX = DOM.getAbsoluteLeft(getElement());
- origY = DOM.getAbsoluteTop(getElement());
- DOM.setCapture(getElement());
- DOM.eventPreventDefault(event);
- }
- }
-
- private void stopMovingWindow() {
- dragging = false;
- showDraggingCurtain(false);
- DOM.releaseCapture(getElement());
- }
-
- @Override
- public boolean onEventPreview(Event event) {
- if (dragging) {
- onDragEvent(event);
- return false;
- } else if (resizing) {
- onResizeEvent(event);
- return false;
- } else if (vaadinModality) {
- // return false when modal and outside window
- final Element target = event.getEventTarget().cast();
- if (DOM.getCaptureElement() != null) {
- // Allow events when capture is set
- return true;
- }
-
- if (!DOM.isOrHasChild(getElement(), target)) {
- // not within the modal window, but let's see if it's in the
- // debug window
- Widget w = Util.findWidget(target, null);
- while (w != null) {
- if (w instanceof Console) {
- return true; // allow debug-window clicks
- } else if (w instanceof VPaintableWidget) {
- return false;
- }
- w = w.getParent();
- }
- return false;
- }
- }
- return true;
- }
-
- @Override
- public void addStyleDependentName(String styleSuffix) {
- // VWindow's getStyleElement() does not return the same element as
- // getElement(), so we need to override this.
- setStyleName(getElement(), getStylePrimaryName() + "-" + styleSuffix,
- true);
- }
-
- @Override
- protected void onAttach() {
- super.onAttach();
-
- setWidth(width);
- setHeight(height);
- }
-
- public RenderSpace getAllocatedSpace(Widget child) {
- if (child == layout) {
- return renderSpace;
- } else {
- // Exception ??
- return null;
- }
- }
-
- public boolean hasChildComponent(Widget component) {
- if (component == layout) {
- return true;
- } else {
- return false;
- }
- }
-
- public void replaceChildComponent(Widget oldComponent, Widget newComponent) {
- contentPanel.setWidget(newComponent);
- }
-
- public boolean requestLayout(Set<Widget> children) {
- if (dynamicWidth && !layoutRelativeWidth) {
- setNaturalWidth();
- }
- if (centered) {
- center();
- }
- updateShadowSizeAndPosition();
- // layout size change may affect its available space (scrollbars)
- client.handleComponentRelativeSize(layout.getWidgetForPaintable());
- return true;
- }
-
- public void updateCaption(VPaintableWidget component, UIDL uidl) {
- // NOP, window has own caption, layout captio not rendered
- }
-
- public ShortcutActionHandler getShortcutActionHandler() {
- return shortcutHandler;
- }
-
- public void onScroll(ScrollEvent event) {
- client.updateVariable(id, "scrollTop",
- contentPanel.getScrollPosition(), false);
- client.updateVariable(id, "scrollLeft",
- contentPanel.getHorizontalScrollPosition(), false);
-
- }
-
- public void onKeyDown(KeyDownEvent event) {
- if (shortcutHandler != null) {
- shortcutHandler
- .handleKeyboardEvent(Event.as(event.getNativeEvent()));
- return;
- }
- }
-
- public void onBlur(BlurEvent event) {
- if (client.hasEventListeners(this, EventId.BLUR)) {
- client.updateVariable(id, EventId.BLUR, "", true);
- }
- }
-
- public void onFocus(FocusEvent event) {
- if (client.hasEventListeners(this, EventId.FOCUS)) {
- client.updateVariable(id, EventId.FOCUS, "", true);
- }
- }
-
- public void onBeforeShortcutAction(Event e) {
- // NOP, nothing to update just avoid workaround ( causes excess
- // blur/focus )
- }
-
- public void focus() {
- contentPanel.focus();
- }
-
- public Widget getWidgetForPaintable() {
- return this;
- }
-
- }
|