blob: dda18b781fccf3d516eb304837d182dd9126edaf [file] [log] [blame]
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.gwt.user.client.ui.impl;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.Style.Display;
import com.google.gwt.dom.client.Style.Overflow;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.DeferredCommand;
/**
* Implementation class used by {@link com.google.gwt.user.client.ui.PopupPanel}.
* This implementation is identical to the implementation provided by
* {@link com.google.gwt.user.client.ui.impl.PopupImpl} in the case where
* Mozilla is NOT running on the Mac.
* <p>
* A different implemention is provided for the Mac in order to prevent
* scrollbars underneath the PopupPanel from being rendered on top of the
* PopupPanel (issue #410). Unfortunately, the solution that fixes this problem
* for the Mac causes a problem with dragging a
* {@link com.google.gwt.user.client.ui.DialogBox} on Linux. While dragging the
* DialogBox (especially diagonally), it jitters significantly.
* </p>
* <p>
* We did not introduce a deferred binding rule for Mozilla on the Mac because
* this is the first instance in which we have a Mozilla-related bug fix which
* does not work on all platforms.
* </p>
* <p>
* This implementation can be simplified in the event that the jittering problem
* on Linux is fixed, or the scrollbar rendering problem on the Mac is fixed.
* </p>
*/
public class PopupImplMozilla extends PopupImpl {
/**
* Cache the value to avoid repeated calls.
*/
private static boolean isFF2Mac = isFF2Mac();
private static native boolean isFF2Mac() /*-{
function makeVersion(result) {
return (parseInt(result[1]) * 1000) + parseInt(result[2]);
}
var ua = navigator.userAgent;
if (ua.indexOf("Macintosh") != -1) {
// Version logic taken from UserAgentPropertyGenerator
var result = /rv:([0-9]+)\.([0-9]+)/.exec(ua);
if (result && result.length == 3) {
// Gecko 1.8 and earlier had the scrollbar bug on OS X.
// (Firefox3 == Gecko 1.9)
if (makeVersion(result) <= 1008) {
return true;
}
}
}
return false;
}-*/;
@Override
public Element createElement() {
final Element outerElem = DOM.createDiv();
if (isFF2Mac) {
// To solve the scrollbar rendering problem on the Mac, we have to make
// the PopupPanel a 'heavyweight' element by setting a style of
// 'overflow:auto' on the outermost div. This ensures that all of the
// elements that are children of this div will be rendered on top of
// any underlying scrollbars.
// Unfortunately, if we add a border to the outer div (which has
// a style of 'overflow:auto'), the border will not be rendered on top
// of underlying scrollbars. To get around this problem, we introduce an
// inner div which acts as the new containing element for the PopupPanel,
// and this element is the one to which all styling is applied to.
outerElem.setInnerHTML("<div></div>");
// Mozilla determines the default stacking order for heavyweight elements
// by their order on the page. If the PopupPanel is declared before
// another
// heavyweight element on the page, then the scrollbars of the heavyweight
// element will still shine through the PopupPanel. By setting
// 'overflow:auto' after all of the elements on the page have been
// rendered,
// the PopupPanel becomes the highest element in the stacking order.
DeferredCommand.addCommand(new Command() {
public void execute() {
outerElem.getStyle().setOverflow(Overflow.AUTO);
}
});
}
return outerElem;
}
@Override
public Element getContainerElement(Element outerElem) {
return isFF2Mac ? outerElem.getFirstChildElement() : outerElem;
}
@Override
public Element getStyleElement(Element outerElem) {
return isFF2Mac ? outerElem : super.getStyleElement(outerElem);
}
@Override
public void setClip(Element popup, String rect) {
super.setClip(popup, rect);
popup.getStyle().setDisplay(Display.NONE);
popup.getStyle().clearDisplay();
}
}