001: /*
002: * Copyright 2007 Google Inc.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License"); you may not
005: * use this file except in compliance with the License. You may obtain a copy of
006: * the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
012: * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
013: * License for the specific language governing permissions and limitations under
014: * the License.
015: */
016: package com.google.gwt.user.client.ui.impl;
017:
018: import com.google.gwt.user.client.Command;
019: import com.google.gwt.user.client.DeferredCommand;
020: import com.google.gwt.user.client.DOM;
021: import com.google.gwt.user.client.Element;
022:
023: /**
024: * Implementation class used by {@link com.google.gwt.user.client.ui.PopupPanel}.
025: * This implementation is identical to the implementation provided by
026: * {@link com.google.gwt.user.client.ui.impl.PopupImpl} in the case where
027: * Mozilla is NOT running on the Mac.
028: * <p>
029: * A different implemention is provided for the Mac in order to prevent
030: * scrollbars underneath the PopupPanel from being rendered on top of the
031: * PopupPanel (issue #410). Unfortunately, the solution that fixes this problem
032: * for the Mac causes a problem with dragging a
033: * {@link com.google.gwt.user.client.ui.DialogBox} on Linux. While dragging the
034: * DialogBox (especially diagonally), it jitters significantly.
035: * </p>
036: * <p>
037: * We did not introduce a deferred binding rule for Mozilla on the Mac because
038: * this is the first instance in which we have a Mozilla-related bug fix which
039: * does not work on all platforms.
040: * </p>
041: * <p>
042: * This implementation can be simplified in the event that the jittering problem
043: * on Linux is fixed, or the scrollbar rendering problem on the Mac is fixed.
044: * </p>
045: */
046: public class PopupImplMozilla extends PopupImpl {
047:
048: /**
049: * Cache the value to avoid repeated calls.
050: */
051: private static boolean isMac = isMac();
052:
053: private static native boolean isMac() /*-{
054: if (navigator.userAgent.indexOf("Macintosh") != -1) {
055: return true;
056: }
057: return false;
058: }-*/;
059:
060: @Override
061: public Element createElement() {
062: final Element outerElem = DOM.createDiv();
063:
064: if (isMac) {
065: // To solve the scrollbar rendering problem on the Mac, we have to make
066: // the PopupPanel a 'heavyweight' element by setting a style of
067: // 'overflow:auto' on the outermost div. This ensures that all of the
068: // elements that are children of this div will be rendered on top of
069: // any underlying scrollbars.
070:
071: // Unfortunately, if we add a border to the outer div (which has
072: // a style of 'overflow:auto'), the border will not be rendered on top
073: // of underlying scrollbars. To get around this problem, we introduce an
074: // inner div which acts as the new containing element for the PopupPanel,
075: // and this element is the one to which all styling is applied to.
076: DOM.setInnerHTML(outerElem, "<div></div>");
077:
078: // Mozilla determines the default stacking order for heavyweight elements
079: // by their order on the page. If the PopupPanel is declared before
080: // another
081: // heavyweight element on the page, then the scrollbars of the heavyweight
082: // element will still shine through the PopupPanel. By setting
083: // 'overflow:auto' after all of the elements on the page have been
084: // rendered,
085: // the PopupPanel becomes the highest element in the stacking order.
086: DeferredCommand.addCommand(new Command() {
087: public void execute() {
088: DOM
089: .setStyleAttribute(outerElem, "overflow",
090: "auto");
091: }
092: });
093: }
094:
095: return outerElem;
096: }
097:
098: @Override
099: public Element getContainerElement(Element outerElem) {
100: return isMac ? DOM.getFirstChild(outerElem) : outerElem;
101: }
102: }
|