All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.gwt.user.client.ui.SplitPanel Maven / Gradle / Ivy

There is a newer version: 2.10.0
Show newest version
/*
 * 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;

import com.google.gwt.dom.client.Element;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event;

import java.util.Iterator;

/**
 * Abstract base class for {@link HorizontalSplitPanel} and
 * {@link VerticalSplitPanel}.
 * 
 * @deprecated Use {@link SplitLayoutPanel} instead, but understand that it is
 *             not a drop in replacement for this class. It requires standards
 *             mode, and is most easily used under a {@link RootLayoutPanel} (as
 *             opposed to a {@link RootPanel}
 */
@Deprecated
abstract class SplitPanel extends Panel {
  /**
   * The element that masks the screen so we can catch mouse events over
   * iframes.
   */
  private static Element glassElem = null;

  /**
   * Sets an elements positioning to absolute.
   * 
   * @param elem the element
   */
  static void addAbsolutePositoning(Element elem) {
    elem.getStyle().setProperty("position", "absolute");
  }

  /**
   * Adds clipping to an element.
   * 
   * @param elem the element
   */
  static final void addClipping(final Element elem) {
    elem.getStyle().setProperty("overflow", "hidden");
  }

  /**
   * Adds as-needed scrolling to an element.
   * 
   * @param elem the element
   */
  static final void addScrolling(final Element elem) {
    elem.getStyle().setProperty("overflow", "auto");
  }

  /**
   * Sizes and element to consume the full area of its parent using the CSS
   * properties left, right, top, and bottom. This method is used for all
   * browsers except IE6/7.
   * 
   * @param elem the element
   */
  static final void expandToFitParentUsingCssOffsets(Element elem) {
    final String zeroSize = "0px";

    addAbsolutePositoning(elem);
    setLeft(elem, zeroSize);
    setRight(elem, zeroSize);
    setTop(elem, zeroSize);
    setBottom(elem, zeroSize);
  }

  /**
   * Sizes an element to consume the full areas of its parent using 100% width
   * and height. This method is used on IE6/7 where CSS offsets don't work
   * reliably.
   * 
   * @param elem the element
   */
  static final void expandToFitParentUsingPercentages(Element elem) {
    final String zeroSize = "0px";
    final String fullSize = "100%";

    addAbsolutePositoning(elem);
    setTop(elem, zeroSize);
    setLeft(elem, zeroSize);
    setWidth(elem, fullSize);
    setHeight(elem, fullSize);
  }

  /**
   * Returns the offsetHeight element property.
   * 
   * @param elem the element
   * @return the offsetHeight property
   */
  static final int getOffsetHeight(Element elem) {
    return elem.getPropertyInt("offsetHeight");
  }

  /**
   * Returns the offsetWidth element property.
   * 
   * @param elem the element
   * @return the offsetWidth property
   */
  static final int getOffsetWidth(Element elem) {
    return elem.getPropertyInt("offsetWidth");
  }

  /**
   * Adds zero or none CSS values for padding, margin and border to prevent
   * stylesheet overrides. Returns the element for convenience to support
   * builder pattern.
   * 
   * @param elem the element
   * @return the element
   */
  static final Element preventBoxStyles(final Element elem) {
    DOM.setIntStyleAttribute(elem, "padding", 0);
    DOM.setIntStyleAttribute(elem, "margin", 0);
    elem.getStyle().setProperty("border", "none");
    return elem;
  }

  /**
   * Convenience method to set bottom offset of an element.
   * 
   * @param elem the element
   * @param size a CSS length value for bottom
   */
  static void setBottom(Element elem, String size) {
    elem.getStyle().setProperty("bottom", size);
  }

  /**
   * Sets the elements css class name.
   * 
   * @param elem the element
   * @param className the class name
   */
  static final void setClassname(final Element elem, final String className) {
    elem.setPropertyString("className", className);
  }

  /**
   * Convenience method to set the height of an element.
   * 
   * @param elem the element
   * @param height a CSS length value for the height
   */
  static final void setHeight(Element elem, String height) {
    elem.getStyle().setProperty("height", height);
  }

  /**
   * Convenience method to set the left offset of an element.
   * 
   * @param elem the element
   * @param left a CSS length value for left
   */
  static final void setLeft(Element elem, String left) {
    elem.getStyle().setProperty("left", left);
  }

  /**
   * Convenience method to set the right offset of an element.
   * 
   * @param elem the element
   * @param right a CSS length value for right
   */
  static final void setRight(Element elem, String right) {
    elem.getStyle().setProperty("right", right);
  }

  /**
   * Convenience method to set the top offset of an element.
   * 
   * @param elem the element
   * @param top a CSS length value for top
   */
  static final void setTop(Element elem, String top) {
    elem.getStyle().setProperty("top", top);
  }

  /**
   * Convenience method to set the width of an element.
   * 
   * @param elem the element
   * @param width a CSS length value for the width
   */
  static final void setWidth(Element elem, String width) {
    elem.getStyle().setProperty("width", width);
  }

  // The enclosed widgets.
  private final Widget[] widgets = new Widget[2];

  // The elements containing the widgets.
  private final Element[] elements = new Element[2];

  // The element that acts as the splitter.
  private final Element splitElem;

  // Indicates whether drag resizing is active.
  private boolean isResizing = false;

  /**
   * Initializes the split panel.
   * 
   * @param mainElem the root element for the split panel
   * @param splitElem the element that acts as the splitter
   * @param headElem the element to contain the top or left most widget
   * @param tailElem the element to contain the bottom or right most widget
   */
  SplitPanel(Element mainElem, Element splitElem, Element headElem,
      Element tailElem) {
    setElement(mainElem);
    this.splitElem = splitElem;
    elements[0] = headElem;
    elements[1] = tailElem;
    sinkEvents(Event.MOUSEEVENTS | Event.ONLOSECAPTURE);

    if (glassElem == null) {
      glassElem = DOM.createDiv();
      glassElem.getStyle().setProperty("position", "absolute");
      glassElem.getStyle().setProperty("top", "0px");
      glassElem.getStyle().setProperty("left", "0px");
      glassElem.getStyle().setProperty("margin", "0px");
      glassElem.getStyle().setProperty("padding", "0px");
      glassElem.getStyle().setProperty("border", "0px");

      // We need to set the background color or mouse events will go right
      // through the glassElem. If the SplitPanel contains an iframe, the
      // iframe will capture the event and the slider will stop moving.
      glassElem.getStyle().setProperty("background", "white");
      glassElem.getStyle().setProperty("opacity", "0.0");
      glassElem.getStyle().setProperty("filter", "alpha(opacity=0)");
    }
  }

  @Override
  public void add(Widget w) {
    if (getWidget(0) == null) {
      setWidget(0, w);
    } else if (getWidget(1) == null) {
      setWidget(1, w);
    } else {
      throw new IllegalStateException(
          "A Splitter can only contain two Widgets.");
    }
  }

  /**
   * Indicates whether the split panel is being resized.
   * 
   * @return true if the user is dragging the splitter,
   *         false otherwise
   */
  public boolean isResizing() {
    return isResizing;
  }

  public Iterator iterator() {
    return WidgetIterators.createWidgetIterator(this, widgets);
  }

  @Override
  public void onBrowserEvent(Event event) {
    switch (DOM.eventGetType(event)) {

      case Event.ONMOUSEDOWN: {
        Element target = DOM.eventGetTarget(event);
        if (splitElem.isOrHasChild(target)) {
          startResizingFrom(event.getClientX() - getAbsoluteLeft(),
              event.getClientY() - getAbsoluteTop());
          DOM.setCapture(getElement());
          event.preventDefault();
        }
        break;
      }

      case Event.ONMOUSEUP: {
        if (isResizing()) {
          // The order of these two lines is important. If we release capture
          // first, then we might trigger an onLoseCapture event before we set
          // isResizing to false.
          stopResizing();
          DOM.releaseCapture(getElement());
        }
        break;
      }

      case Event.ONMOUSEMOVE: {
        if (isResizing()) {
          assert DOM.getCaptureElement() != null;
          onSplitterResize(event.getClientX() - getAbsoluteLeft(),
              event.getClientY() - getAbsoluteTop());
          event.preventDefault();
        }
        break;
      }

      // IE automatically releases capture if the user switches windows, so we
      // need to catch the event and stop resizing.
      case Event.ONLOSECAPTURE: {
        if (isResizing()) {
          stopResizing();
        }
        break;
      }
    }
    super.onBrowserEvent(event);
  }

  @Override
  public boolean remove(Widget widget) {
    if (widgets[0] == widget) {
      setWidget(0, null);
      return true;
    } else if (widgets[1] == widget) {
      setWidget(1, null);
      return true;
    }
    return false;
  }

  /**
   * Moves the position of the splitter.
   * 
   * @param size the new size of the left region in CSS units (e.g. "10px",
   *            "1em")
   */
  public abstract void setSplitPosition(String size);

  /**
   * Gets the content element for the given index.
   * 
   * @param index the index of the element, only 0 and 1 are valid.
   * @return the element
   */
  protected Element getElement(int index) {
    return elements[index];
  }

  /**
   * Gets the element that is acting as the splitter.
   * 
   * @return the element
   */
  protected Element getSplitElement() {
    return splitElem;
  }

  /**
   * Gets one of the contained widgets.
   * 
   * @param index the index of the widget, only 0 and 1 are valid.
   * @return the widget
   */
  protected Widget getWidget(int index) {
    return widgets[index];
  }

  /**
   * Affected Elements:
   * 
    *
  • -splitter = the container containing the splitter element.
  • *
* * @see UIObject#onEnsureDebugId(String) */ @Override protected void onEnsureDebugId(String baseID) { super.onEnsureDebugId(baseID); ensureDebugId(splitElem, baseID, "splitter"); } /** * Sets one of the contained widgets. * * @param index the index, only 0 and 1 are valid * @param w the widget */ protected final void setWidget(int index, Widget w) { Widget oldWidget = widgets[index]; // Validate. if (oldWidget == w) { return; } // Detach the new child. if (w != null) { w.removeFromParent(); } // Remove the old child. if (oldWidget != null) { // Orphan old. try { orphan(oldWidget); } finally { // Physical detach old. elements[index].removeChild(oldWidget.getElement()); widgets[index] = null; } } // Logical attach new. widgets[index] = w; if (w != null) { // Physical attach new. DOM.appendChild(elements[index], w.getElement()); // Adopt new. adopt(w); } } /** * Called on each mouse drag event as the user is dragging the splitter. * * @param x the x coordinate of the mouse relative to the panel's extent * @param y the y coordinate of the mosue relative to the panel's extent */ abstract void onSplitterResize(int x, int y); /** * Called when the user starts dragging the splitter. * * @param x the x coordinate of the mouse relative to the panel's extent * @param y the y coordinate of the mouse relative to the panel's extent */ abstract void onSplitterResizeStarted(int x, int y); private void startResizingFrom(int x, int y) { isResizing = true; onSplitterResizeStarted(x, y); // Resize glassElem to take up the entire scrollable window area int height = RootPanel.getBodyElement().getScrollHeight() - 1; int width = RootPanel.getBodyElement().getScrollWidth() - 1; glassElem.getStyle().setProperty("height", height + "px"); glassElem.getStyle().setProperty("width", width + "px"); RootPanel.getBodyElement().appendChild(glassElem); } private void stopResizing() { isResizing = false; RootPanel.getBodyElement().removeChild(glassElem); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy