From 1f85c25a457a4fdc65420bb73fa89491445c7b04 Mon Sep 17 00:00:00 2001 From: Jouni Koivuviita Date: Thu, 16 Oct 2008 11:42:19 +0000 Subject: [PATCH] Fixes #2141: Subwindow rendering broken in IE6 and IE7 Needed a bit more tweaking than simple themeing. IWindow not sets all its dimensions (those sent from server) as its outer width and height. Previously dimensions were set as "inner dimensions" i.e. content area width. svn changeset:5647/svn branch:trunk --- WebContent/ITMILL/themes/default/styles.css | 33 ++- .../ITMILL/themes/default/window/window.css | 33 ++- .../gwt/client/ApplicationConnection.java | 19 +- .../terminal/gwt/client/ui/IWindow.java | 230 +++++++++++------- .../itmill/toolkit/ui/AbstractComponent.java | 2 + 5 files changed, 193 insertions(+), 124 deletions(-) diff --git a/WebContent/ITMILL/themes/default/styles.css b/WebContent/ITMILL/themes/default/styles.css index 09ab8448c6..b069d9dd16 100644 --- a/WebContent/ITMILL/themes/default/styles.css +++ b/WebContent/ITMILL/themes/default/styles.css @@ -2242,6 +2242,7 @@ input.i-modified, } .i-window { color: #464f52; + font-family: "Trebuchet MS", geneva, helvetica, arial, tahoma, verdana, sans-serif; font-size: 13px; line-height: 18px; background: transparent url(window/img/bottom-left.png) no-repeat left bottom; @@ -2249,13 +2250,6 @@ input.i-modified, .i-window-wrap { background: transparent url(window/img/top-left.png) no-repeat; - /* Somehow this won't inherit from .i-window */ - font-family: "Trebuchet MS", geneva, helvetica, arial, tahoma, verdana, sans-serif; - zoom: 1; /* For IE, otherwise it won't render properly (width will be out of control) */ -} - -.i-window-wrap2 { - zoom: 1; /* For IE, otherwise it won't render properly (width will be out of control) */ } .i-window-outerheader { @@ -2275,10 +2269,13 @@ input.i-modified, white-space: nowrap; text-overflow: ellipsis; overflow: hidden; - width: 100%; text-shadow: 0 1px 0 #fff; } +* html .i-window-header { + width: 100%; +} + .i-window-header .i-icon { vertical-align: middle; /* This has to be 'middle', not 'bottom', to allow larger icons than 16px */ } @@ -2291,7 +2288,7 @@ input.i-modified, } /* Partial fix for bug #1106 */ -/* Target Firefox 2 (somehow this will force almost all window borders on top of a flash object) */ +/* Target Firefox 2 (somehow this will force almost all window borders on top of a Flash object) */ .i-window-contents, x:-moz-any-link { overflow: hidden; } @@ -2307,11 +2304,13 @@ input.i-modified, } .i-window-resizebox { - position: absolute; - bottom: 4px; - right: 4px; + position: relative; /* Needed to position the element over ScrollPanel, which is also relatively positioned */ + display: inline; /* fix IE6 double float margin bug */ + float: right; width: 10px; height: 10px; + margin-right: 5px; + margin-top: -7px; cursor: se-resize; background: transparent url(window/img/resize.png); overflow: hidden; @@ -2350,15 +2349,13 @@ input.i-modified, /* IE6 workaround for position:fixed; */ * html .i-window-modalitycurtain { position: absolute; - top: expression((ignoreMe = document.documentElement.scrollTop) + "px"); + top: expression(document.documentElement.scrollTop + "px"); } /* IE specific styles */ * html .i-window { width: 0; /* min-size for IE6 */ - overflow: hidden; - zoom: 1; } @@ -2456,7 +2453,7 @@ input.i-modified, * html .i-shadow-window { background: #000; - filter: progid:DXImageTransform.Microsoft.Blur(pixelRadius=6) alpha(opacity=20); - margin-top: -4px; - margin-left: -6px; + filter: progid:DXImageTransform.Microsoft.Blur(pixelRadius=5) alpha(opacity=20); + margin-top: 2px; + margin-left: 2px; } diff --git a/WebContent/ITMILL/themes/default/window/window.css b/WebContent/ITMILL/themes/default/window/window.css index a7d513bca0..611c46d112 100644 --- a/WebContent/ITMILL/themes/default/window/window.css +++ b/WebContent/ITMILL/themes/default/window/window.css @@ -1,5 +1,6 @@ .i-window { color: #464f52; + font-family: "Trebuchet MS", geneva, helvetica, arial, tahoma, verdana, sans-serif; font-size: 13px; line-height: 18px; background: transparent url(img/bottom-left.png) no-repeat left bottom; @@ -7,13 +8,6 @@ .i-window-wrap { background: transparent url(img/top-left.png) no-repeat; - /* Somehow this won't inherit from .i-window */ - font-family: "Trebuchet MS", geneva, helvetica, arial, tahoma, verdana, sans-serif; - zoom: 1; /* For IE, otherwise it won't render properly (width will be out of control) */ -} - -.i-window-wrap2 { - zoom: 1; /* For IE, otherwise it won't render properly (width will be out of control) */ } .i-window-outerheader { @@ -33,10 +27,13 @@ white-space: nowrap; text-overflow: ellipsis; overflow: hidden; - width: 100%; text-shadow: 0 1px 0 #fff; } +* html .i-window-header { + width: 100%; +} + .i-window-header .i-icon { vertical-align: middle; /* This has to be 'middle', not 'bottom', to allow larger icons than 16px */ } @@ -49,7 +46,7 @@ } /* Partial fix for bug #1106 */ -/* Target Firefox 2 (somehow this will force almost all window borders on top of a flash object) */ +/* Target Firefox 2 (somehow this will force almost all window borders on top of a Flash object) */ .i-window-contents, x:-moz-any-link { overflow: hidden; } @@ -65,11 +62,13 @@ } .i-window-resizebox { - position: absolute; - bottom: 4px; - right: 4px; + position: relative; /* Needed to position the element over ScrollPanel, which is also relatively positioned */ + display: inline; /* fix IE6 double float margin bug */ + float: right; width: 10px; height: 10px; + margin-right: 5px; + margin-top: -7px; cursor: se-resize; background: transparent url(img/resize.png); overflow: hidden; @@ -108,15 +107,13 @@ /* IE6 workaround for position:fixed; */ * html .i-window-modalitycurtain { position: absolute; - top: expression((ignoreMe = document.documentElement.scrollTop) + "px"); + top: expression(document.documentElement.scrollTop + "px"); } /* IE specific styles */ * html .i-window { width: 0; /* min-size for IE6 */ - overflow: hidden; - zoom: 1; } @@ -214,7 +211,7 @@ * html .i-shadow-window { background: #000; - filter: progid:DXImageTransform.Microsoft.Blur(pixelRadius=6) alpha(opacity=20); - margin-top: -4px; - margin-left: -6px; + filter: progid:DXImageTransform.Microsoft.Blur(pixelRadius=5) alpha(opacity=20); + margin-top: 2px; + margin-left: 2px; } \ No newline at end of file diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ApplicationConnection.java b/src/com/itmill/toolkit/terminal/gwt/client/ApplicationConnection.java index 6e0b4e3493..f26badf08a 100755 --- a/src/com/itmill/toolkit/terminal/gwt/client/ApplicationConnection.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ApplicationConnection.java @@ -313,6 +313,7 @@ public class ApplicationConnection { if (heightOfLoadElement == 0 && cssWaits < MAX_CSS_WAITS) { (new Timer() { + @Override public void run() { handleWhenCSSLoaded(response); } @@ -363,6 +364,7 @@ public class ApplicationConnection { // show initial throbber if (loadTimer == null) { loadTimer = new Timer() { + @Override public void run() { showLoadingIndicator(); } @@ -443,6 +445,7 @@ public class ApplicationConnection { DOM.setStyleAttribute(loadElement, "top", updatedY + "px"); // Initialize other timers loadTimer2 = new Timer() { + @Override public void run() { DOM.setElementProperty(loadElement, "className", "i-loading-indicator-delay"); @@ -452,6 +455,7 @@ public class ApplicationConnection { loadTimer2.schedule(1200); loadTimer3 = new Timer() { + @Override public void run() { DOM.setElementProperty(loadElement, "className", "i-loading-indicator-wait"); @@ -530,6 +534,7 @@ public class ApplicationConnection { final JSONObject timedRedirect = meta.get("timedRedirect") .isObject(); redirectTimer = new Timer() { + @Override public void run() { redirect(timedRedirect.get("url").isString() .stringValue()); @@ -1060,9 +1065,17 @@ public class ApplicationConnection { boolean horizontalScrollBar = false; boolean verticalScrollBar = false; - RenderSpace renderSpace = Util.getLayout(widget).getAllocatedSpace( - widget); + Container parent = Util.getLayout(widget); + RenderSpace renderSpace; + // Parent-less components (like sub-windows) are relative to browser + // window. + if (parent == null) { + renderSpace = new RenderSpace(Window.getClientWidth(), Window + .getClientHeight()); + } else { + renderSpace = parent.getAllocatedSpace(widget); + } if (relativeSize.getHeight() >= 0) { if (renderSpace != null) { @@ -1293,6 +1306,7 @@ public class ApplicationConnection { private boolean isPending = false; + @Override public void schedule(int delayMillis) { if (!isPending) { super.schedule(delayMillis); @@ -1300,6 +1314,7 @@ public class ApplicationConnection { } } + @Override public void run() { getConsole().log( "Running re-layout of " + view.getClass().getName()); diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/IWindow.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/IWindow.java index 77d2573f54..7be391c286 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/IWindow.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/IWindow.java @@ -46,10 +46,16 @@ public class IWindow extends IToolkitOverlay implements Container, public static final String CLASSNAME = "i-window"; /** - * pixels used by inner borders and paddings horizontally (calculated on - * attach) + * Pixels used by inner borders and paddings horizontally (calculated only + * once) */ - private int borderWidthHorizontal = 0; + private int borderWidth = -1; + + /** + * Pixels used by inner borders and paddings vertically (calculated only + * once) + */ + private int borderHeight = -1; private static final int STACKING_OFFSET_PIXELS = 15; @@ -208,16 +214,21 @@ public class IWindow extends IToolkitOverlay implements Container, DOM.setElementProperty(closeBox, "id", id + "_window_close"); if (uidl.hasAttribute("invisible")) { - this.hide(); + hide(); return; } - if (client.updateComponent(this, uidl, false)) { - return; + if (!uidl.hasAttribute("cached")) { + if (uidl.getBooleanAttribute("modal") != modal) { + setModal(!modal); + } + if (!isAttached()) { + show(); + } } - if (uidl.getBooleanAttribute("modal") != modal) { - setModal(!modal); + if (client.updateComponent(this, uidl, false)) { + return; } if (uidl.getBooleanAttribute("resizable") != resizable) { @@ -240,56 +251,6 @@ public class IWindow extends IToolkitOverlay implements Container, // parameters } - if (!isAttached()) { - show(); - } - - // Initialize the size from UIDL - /* - * FIXME non-pixel size is set as "outer size", pixels are applied for - * content area. This is due history as earlier only pixels where - * allowed. - */ - if (uidl.hasAttribute("width")) { - final String width = uidl.getStringAttribute("width"); - if (width.indexOf("px") < 0) { - /* - * Only using non-pixel size for initial size measurement. Then - * fix content area with pixels. - */ - DOM.setStyleAttribute(getElement(), "width", width); - int elementPropertyInt = DOM.getElementPropertyInt( - getElement(), "offsetWidth"); - DOM.setStyleAttribute(getElement(), "width", ""); - elementPropertyInt -= (DOM.getElementPropertyInt(getElement(), - "offsetWidth") - DOM.getElementPropertyInt(contents, - "offsetWidth")); - setWidth(elementPropertyInt + "px"); - } else { - setWidth(width); - } - } - - // Height set after show so we can detect space used by decorations - if (uidl.hasAttribute("height")) { - final String height = uidl.getStringAttribute("height"); - if (height.indexOf("%") > 0) { - int winHeight = Window.getClientHeight(); - float percent = Float.parseFloat(height.substring(0, height - .indexOf("%"))) / 100.0f; - int contentPixels = (int) (winHeight * percent); - contentPixels -= (DOM.getElementPropertyInt(getElement(), - "offsetHeight") - DOM.getElementPropertyInt(contents, - "offsetHeight")); - // FIXME hardcoded contents elements border size - contentPixels -= 1; - - setHeight(contentPixels + "px"); - } else { - setHeight(height); - } - } - if (uidl.hasAttribute("caption")) { setCaption(uidl.getStringAttribute("caption"), uidl .getStringAttribute("icon")); @@ -336,6 +297,13 @@ public class IWindow extends IToolkitOverlay implements Container, } lo.updateFromUIDL(childUidl, client); + // If no explicit width is specified, calculate natural width for window + // and set it explicitly + if (!uidl.hasAttribute("width")) { + final int naturalWidth = getElement().getOffsetWidth(); + setWidth(naturalWidth + "px"); + } + // we may have actions and notifications if (uidl.getChildCount() > 1) { final int cnt = uidl.getChildCount(); @@ -601,15 +569,15 @@ public class IWindow extends IToolkitOverlay implements Container, if (resizing || resizeBox == target) { onResizeEvent(event); - DOM.eventCancelBubble(event, true); + event.cancelBubble(true); } else if (target == closeBox) { if (type == Event.ONCLICK) { onCloseClick(); - DOM.eventCancelBubble(event, true); + event.cancelBubble(true); } } else if (dragging || !DOM.isOrHasChild(contents, target)) { onDragEvent(event); - DOM.eventCancelBubble(event, true); + event.cancelBubble(true); } else if (type == Event.ONCLICK) { // clicked inside window, ensure to be on top if (!isActive()) { @@ -624,59 +592,70 @@ public class IWindow extends IToolkitOverlay implements Container, private void onResizeEvent(Event event) { if (resizable) { - switch (DOM.eventGetType(event)) { + switch (event.getTypeInt()) { case Event.ONMOUSEDOWN: if (!isActive()) { bringToFront(); } showDraggingCurtain(true); + if (BrowserInfo.get().isIE()) { + DOM.setStyleAttribute(resizeBox, "visibility", "hidden"); + } resizing = true; - startX = DOM.eventGetScreenX(event); - startY = DOM.eventGetScreenY(event); - origW = getWidget().getOffsetWidth(); - origH = getWidget().getOffsetHeight(); + startX = event.getScreenX(); + startY = event.getScreenY(); + origW = getElement().getOffsetWidth(); + origH = getElement().getOffsetHeight(); DOM.setCapture(getElement()); - DOM.eventPreventDefault(event); + event.preventDefault(); break; case Event.ONMOUSEUP: showDraggingCurtain(false); + if (BrowserInfo.get().isIE()) { + DOM.setStyleAttribute(resizeBox, "visibility", ""); + } resizing = false; DOM.releaseCapture(getElement()); setSize(event, true); break; case Event.ONLOSECAPTURE: showDraggingCurtain(false); + if (BrowserInfo.get().isIE()) { + DOM.setStyleAttribute(resizeBox, "visibility", ""); + } resizing = false; case Event.ONMOUSEMOVE: if (resizing) { setSize(event, false); - DOM.eventPreventDefault(event); + event.preventDefault(); } break; default: - DOM.eventPreventDefault(event); + event.preventDefault(); break; } } } - public void setSize(Event event, boolean updateVariables) { - int w = DOM.eventGetScreenX(event) - startX + origW; + private void setSize(Event event, boolean updateVariables) { + int w = event.getScreenX() - startX + origW; if (w < MIN_WIDTH) { w = MIN_WIDTH; } - int h = DOM.eventGetScreenY(event) - startY + origH; + + int h = event.getScreenY() - startY + origH; if (h < MIN_HEIGHT) { h = MIN_HEIGHT; } + 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, false); } - // Update shadow size & position // Update child widget dimensions if (client != null) { @@ -685,17 +664,73 @@ public class IWindow extends IToolkitOverlay implements Container, } @Override + /* + * Width is set to the out-most element (i-window). + * + * This function should never be called with percentage values (it will + * throw an exception) + */ public void setWidth(String width) { + if (!isAttached()) { + return; + } if (!"".equals(width)) { - DOM - .setStyleAttribute( - getElement(), - "width", - (Integer.parseInt(width.substring(0, - width.length() - 2)) + borderWidthHorizontal) - + "px"); + // Convert non-pixel values to pixels + if (width.indexOf("px") < 0) { + DOM.setStyleAttribute(getElement(), "width", width); + width = getElement().getOffsetWidth() + "px"; + } + + DOM.setStyleAttribute(getElement(), "width", width); + + // IE6 needs the actual inner content width on the content element, + // otherwise it won't wrap the content properly (no scrollbars + // appear, content flows out of window) + if (BrowserInfo.get().isIE6()) { + int contentWidth = (Integer.parseInt(width.substring(0, width + .length() - 2)) - borderWidth); + if (contentWidth < 0) { + contentWidth = 0; + } + DOM.setStyleAttribute(contentPanel.getElement(), "width", + contentWidth + "px"); + } + updateShadowSizeAndPosition(); + } + } + + @Override + /* + * Height is set to the out-most element (i-window). + * + * This function should never be called with percentage values (it will + * throw an exception) + */ + public void setHeight(String height) { + if (!isAttached()) { + return; + } + if (!"".equals(height)) { + // Convert non-pixel values to pixels + if (height.indexOf("px") < 0) { + DOM.setStyleAttribute(getElement(), "height", height); + height = getElement().getOffsetHeight() + "px"; + } + + DOM.setStyleAttribute(contentPanel.getElement(), "position", + "absolute"); + final int usedHeight = getElement().getOffsetHeight(); + DOM.setStyleAttribute(contentPanel.getElement(), "position", + "relative"); + + height = (Integer + .parseInt(height.substring(0, height.length() - 2)) - usedHeight) + + "px"; + + DOM.setStyleAttribute(contentPanel.getElement(), "height", height); + + updateShadowSizeAndPosition(); } - updateShadowSizeAndPosition(); } private void onDragEvent(Event event) { @@ -769,13 +804,36 @@ public class IWindow extends IToolkitOverlay implements Container, @Override protected void onAttach() { super.onAttach(); + // Calculate space required by window borders, so we can accurately // calculate space for content - final int contentWidth = DOM.getElementPropertyInt(contentPanel - .getElement(), "offsetWidth"); - final int windowWidth = DOM.getElementPropertyInt(getElement(), - "offsetWidth"); - borderWidthHorizontal = windowWidth - contentWidth; + + // IE (IE6 especially) requires some magic tricks to pull the border + // size correctly (remember that we want to accomodate for paddings as + // well) + if (BrowserInfo.get().isIE()) { + DOM.setStyleAttribute(contents, "width", "7000px"); + DOM.setStyleAttribute(contentPanel.getElement(), "width", "7000px"); + int contentWidth = DOM.getElementPropertyInt(contentPanel + .getElement(), "offsetWidth"); + contentWidth = DOM.getElementPropertyInt(contentPanel.getElement(), + "offsetWidth"); + final int windowWidth = DOM.getElementPropertyInt(getElement(), + "offsetWidth"); + DOM.setStyleAttribute(contentPanel.getElement(), "width", ""); + DOM.setStyleAttribute(contents, "width", ""); + + borderWidth = windowWidth - contentWidth; + } + + // Standards based browsers get away with it a little easier :) + else { + final int contentWidth = DOM.getElementPropertyInt(contentPanel + .getElement(), "offsetWidth"); + final int windowWidth = DOM.getElementPropertyInt(getElement(), + "offsetWidth"); + borderWidth = windowWidth - contentWidth; + } } public RenderSpace getAllocatedSpace(Widget child) { diff --git a/src/com/itmill/toolkit/ui/AbstractComponent.java b/src/com/itmill/toolkit/ui/AbstractComponent.java index a641ef3bd8..7155c759c6 100644 --- a/src/com/itmill/toolkit/ui/AbstractComponent.java +++ b/src/com/itmill/toolkit/ui/AbstractComponent.java @@ -161,6 +161,7 @@ public abstract class AbstractComponent implements Component, MethodEventSource * indicate that "style" should not be used to switch client * side implementation, only to style the component. */ + @Deprecated public String getStyle() { return getStyleName(); } @@ -177,6 +178,7 @@ public abstract class AbstractComponent implements Component, MethodEventSource * indicate that "style" should not be used to switch client * side implementation, only to style the component. */ + @Deprecated public void setStyle(String style) { setStyleName(style); } -- 2.39.5