| /* |
| * 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 UserAgent.gwt.xml. |
| 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(); |
| } |
| } |