/* * Copyright 2011 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; import com.google.gwt.dom.client.Document; import com.google.gwt.dom.client.Element; import com.google.gwt.dom.client.Style.Overflow; import com.google.gwt.dom.client.Style.Position; import com.google.gwt.dom.client.Style.Unit; import com.google.gwt.dom.client.Style.Visibility; import com.google.gwt.event.dom.client.HasScrollHandlers; import com.google.gwt.event.dom.client.ScrollEvent; import com.google.gwt.event.dom.client.ScrollHandler; import com.google.gwt.event.shared.HandlerRegistration; import com.google.gwt.user.client.Event; /** * Abstract parent class for scrollbars implemented using the native browser * scrollbars. */ public abstract class AbstractNativeScrollbar extends Widget implements HasScrollHandlers { private static int nativeHeight = -1; private static int nativeWidth = -1; private static boolean nativeRtl = false; /** * Get the height of a native horizontal scrollbar. * * <p> * This method assumes that all native scrollbars on the page have the same * height. * * @return the height in pixels */ public static int getNativeScrollbarHeight() { maybeRecalculateNativeScrollbarSize(); return nativeHeight; } /** * Get the width of a native vertical scrollbar. * * <p> * This method assumes that all native vertical scrollbars on the page have * the same width. * * @return the height in pixels */ public static int getNativeScrollbarWidth() { maybeRecalculateNativeScrollbarSize(); return nativeWidth; } /** * Check whether or not the native vertical scrollbar is aligned on the left * side of the scrollable element in RTL mode. * * @return true if left aligned, false if not */ public static boolean isScrollbarLeftAlignedInRtl() { maybeRecalculateNativeScrollbarSize(); return nativeRtl; } /** * Recalculate the height and width of a native scrollbar. */ private static void maybeRecalculateNativeScrollbarSize() { // Check if the size has already been calculated. if (nativeHeight > -1) { return; } // Create a scrollable element and attach it to the body. Element scrollable = Document.get().createDivElement(); scrollable.getStyle().setPosition(Position.ABSOLUTE); scrollable.getStyle().setTop(0.0, Unit.PX); scrollable.getStyle().setLeft(0.0, Unit.PX); scrollable.getStyle().setHeight(100.0, Unit.PX); scrollable.getStyle().setWidth(100.0, Unit.PX); scrollable.getStyle().setOverflow(Overflow.SCROLL); scrollable.getStyle().setVisibility(Visibility.HIDDEN); scrollable.getStyle().setProperty("direction", "rtl"); Document.get().getBody().appendChild(scrollable); // Add some content. Element content = Document.get().createDivElement(); content.setInnerText("content"); scrollable.appendChild(content); // Measure the height and width. nativeHeight = scrollable.getOffsetHeight() - scrollable.getClientHeight(); nativeWidth = scrollable.getOffsetWidth() - scrollable.getClientWidth(); nativeRtl = (content.getAbsoluteLeft() > scrollable.getAbsoluteLeft()); // Detach the scrollable element. scrollable.removeFromParent(); } public HandlerRegistration addScrollHandler(ScrollHandler handler) { // Sink the event on the scrollable element, not the root element. Event.sinkEvents(getScrollableElement(), Event.ONSCROLL); return addHandler(handler, ScrollEvent.getType()); } /** * Get the scrollable element. * * @return the scrollable element */ protected abstract Element getScrollableElement(); @Override protected void onAttach() { super.onAttach(); /* * Attach the event listener in onAttach instead of onLoad so users cannot * accidentally override it. */ Event.setEventListener(getScrollableElement(), this); } @Override protected void onDetach() { /* * Detach the event listener in onDetach instead of onUnload so users cannot * accidentally override it. */ Event.setEventListener(getScrollableElement(), null); super.onDetach(); } }