Package net.mygwt.ui.client.widget

Source Code of net.mygwt.ui.client.widget.SplitBar

/*
* MyGWT Widget Library
* Copyright(c) 2007, MyGWT.
* licensing@mygwt.net
*
* http://mygwt.net/license
*/
package net.mygwt.ui.client.widget;

import net.mygwt.ui.client.Events;
import net.mygwt.ui.client.Style;
import net.mygwt.ui.client.MyDOM;
import net.mygwt.ui.client.MyGWT;
import net.mygwt.ui.client.event.BaseEvent;
import net.mygwt.ui.client.event.Listener;
import net.mygwt.ui.client.fx.Draggable;
import net.mygwt.ui.client.util.Rectangle;

import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.Widget;

/**
* Creates draggable splitter bar on the side of a widget.
*
* <dl>
* <dt><b>Styles:</b></dt>
* <dd>NORTH, WEST, SOUTH, EAST</dd>
*
* <dl>
* <dt><b>Events:</b></dt>
*
* <dd><b>Resize</b> : (widget, item, size)<br>
* <div>Fires after the split bar has been moved.</div>
* <ul>
* <li>widget : this</li>
* <li>item : the widget being resized</li>
* <li>size : the new size</li>
* </ul>
* </dd>
*
* <dd><b>DragStart</b> : (widget,event)
* <div>Fires after a drag has started.</div>
* <ul>
* <li>widget : this</li>
* <li>event : the dom event</li>
* </ul>
* </dd>
*
* <dd><b>DragEnd</b> : (widget,event)
* <div>Fires after a drag has ended.</div>
* <ul>
* <li>widget : this</li>
* <li>event : the dom event</li>
* </ul>
* </dd>
*
* <dl>
*/
public class SplitBar extends Component {

  /**
   * Transparent shim that allows drags over iframes.
   */
  private static HTML shim;

  static {
    shim = new HTML("&nbsp;");
    shim.setStyleName("my-splitbar-shim");
    shim.setVisible(false);
    RootPanel.get().add(shim);
  }

  /**
   * minSize specifies the minimum size of the resize widget. Default value is
   * 10;
   */
  public int minSize = 10;

  /**
   * maxSize specifies the maximum size of the resize widget. Default value is
   * 2000;
   */
  public int maxSize = 2000;

  /**
   * barWidth specifies width of bar in pixels. Default value is 4;
   */
  public int barWidth = 4;

  /**
   * autoSize specifies if the size of the the resize widget should be updated
   * automatically after a drag operation using a proxy. Default value is
   * <code>true</code>
   */
  public boolean autoSize = true;

  /**
   * offsetLeft specifies the amount of pixels the bar should be offset to the
   * left. Default value is 0.
   */
  public int offsetLeft = 0;

  /**
   * offsetTop specifies the amount of pixels the bar should be offset to the
   * top. Default value is 0.
   */
  public int offsetTop = 0;

  private Element resizeElem;
  private Component resizeWidget;
  private Component containerWidget;
  private int style;
  private Draggable draggable;
  private Rectangle startBounds;
  private Listener listener;

  /**
   * Creates a new split bar.
   *
   * @param style the bar location
   * @param resizeWidget the widget being resized
   */
  public SplitBar(final int style, Component resizeWidget) {
    this.style = style;
    this.resizeWidget = resizeWidget;
    this.resizeElem = resizeWidget.getElement();

    final Widget fSplitBar = this;

    listener = new Listener() {
      public void handleEvent(BaseEvent be) {
        switch (be.type) {
          case Events.Attach:
            RootPanel.get().add(fSplitBar);
            updateHandle();
            break;
          case Events.Detach:
            RootPanel.get().remove(fSplitBar);
            break;
          case Events.Resize:
            updateHandle();
            break;
        }
      }
    };

    resizeWidget.addListener(Events.Attach, listener);
    resizeWidget.addListener(Events.Detach, listener);
    resizeWidget.addListener(Events.Resize, listener);

    setElement(DOM.createDiv());

    if (style == Style.SOUTH || style == Style.NORTH) {
      setStyleName("my-hsplitbar");
    } else {
      setStyleName("my-vsplitbar");
    }
    MyDOM.setStyleAttribute(getElement(), "position", "absolute");

    draggable = new Draggable(this);
    draggable.proxyStyle = "my-splitbar-proxy";

    Listener dragListener = new Listener() {
      public void handleEvent(BaseEvent be) {
        if (be.type == Events.DragStart) {
          onStartDrag(be);
        }
        if (be.type == Events.DragEnd) {
          onEndDrag(be);
        }
      }

    };
    draggable.addListener(Events.DragStart, dragListener);
    draggable.addListener(Events.DragEnd, dragListener);

    sinkEvents(Event.MOUSEEVENTS);

    if (resizeWidget.isAttached()) {
      BaseEvent be = new BaseEvent();
      be.type = Events.Attach;
      listener.handleEvent(be);
    }
  }

  /**
   * Creates a new split bar.
   *
   * @param style the bar location
   * @param resizeWidget the widget being resized
   * @param container the widget the split bar proxy will be sized to
   */
  public SplitBar(int style, Component resizeWidget, Component container) {
    this(style, resizeWidget);
    this.containerWidget = container;
    draggable.container = container;
  }

  /**
   * Returns the split bar's draggable instance.
   *
   * @return the draggable instance
   */
  public Draggable getDraggable() {
    return draggable;
  }

  /**
   * Returns the resize widget.
   *
   * @return the resize widget
   */
  public Widget getResizeWidget() {
    return resizeWidget;
  }

  /**
   * Returns the split bar's style information.
   *
   * @return the style information
   */
  public int getStyle() {
    return style;
  }

  /**
   * Removes the split bar from the resize widget.
   */
  public void release() {
    resizeWidget.removeListener(Events.Attach, listener);
    resizeWidget.removeListener(Events.Detach, listener);
    resizeWidget.removeListener(Events.Resize, listener);
    RootPanel.get().remove(this);
  }

  public void updateHandle() {
    if (!resizeWidget.isAttached()) {
      return;
    }
    Rectangle rect = MyDOM.getBounds(resizeElem, false);
    int x = rect.x;
    int y = rect.y;

    if (!MyDOM.isVisibleBox()) {
      y -= MyDOM.getDecorationWidth(resizeElem, Style.TOP);
      x -= MyDOM.getDecorationWidth(resizeElem, Style.LEFT);
    }

    int w = rect.width;
    int h = rect.height;

    switch (style) {
      case Style.SOUTH:
        MyDOM.setBounds(getElement(), x + offsetLeft, y + h + offsetTop, w, barWidth,
            false);
        break;
      case Style.WEST:
        MyDOM.setBounds(getElement(), x - barWidth + offsetLeft, y + offsetTop, barWidth,
            h, false);
        break;
      case Style.NORTH:
        MyDOM.setBounds(getElement(), x + offsetLeft, y - barWidth + offsetTop, w,
            barWidth, false);
        break;
      case Style.EAST:
        MyDOM.setBounds(getElement(), x + w + offsetLeft, y + offsetTop, barWidth, h,
            false);
        break;
    }

  }

  private void onEndDrag(BaseEvent bee) {
    shim.setVisible(false);

    int x = bee.x;
    int y = bee.y;
    int width = resizeWidget.getOffsetWidth();
    int height = resizeWidget.getOffsetHeight();

    int diffY = y - startBounds.y + 4;
    int diffX = x - startBounds.x + 4;
   
    resizeWidget.setEnabled(true);

    BaseEvent be = new BaseEvent(this);
    be.item = resizeWidget;

    switch (style) {
      case Style.NORTH: {
        be.size = height - diffY;
        if (autoSize) {
          MyDOM.setY(resizeElem, y);
          MyDOM.setHeight(resizeElem, height - diffY);
        }
        break;
      }
      case Style.SOUTH: {
        be.size = height + diffY;
        if (autoSize) {
          MyDOM.setHeight(resizeElem, diffY);
          resizeWidget.setHeight(diffY);
        }
        break;
      }
      case Style.WEST: {
        be.size = width - diffX;
        if (autoSize) {
          MyDOM.setX(getElement(), x);
          resizeWidget.setWidth(width - diffX);
        }
        break;
      }
      case Style.EAST: {
        be.size = width + diffX;
        if (autoSize) {
          resizeWidget.setWidth(diffX);
        }
        break;
      }
    }
    be.type = Events.DragEnd;
    be.widget = this;
    fireEvent(Events.DragEnd, be);
   
    fireEvent(Events.Resize, be);
    updateHandle();
  }

  private void onStartDrag(BaseEvent be) {
    be.type = Events.DragStart;
    be.widget = this;
    fireEvent(Events.DragStart, be);
   
    if (MyGWT.isIE) {
      shim.setVisible(true);
    }
   
    resizeWidget.setEnabled(false);

    if (containerWidget != null) {
      switch (style) {
        case Style.WEST:
        case Style.EAST:
          int h = containerWidget.getHeight(true);
          be.height = h;
          break;
        case Style.NORTH:
        case Style.SOUTH:
          int w = containerWidget.getWidth(true);
          be.width = w;
          break;
      }
    }

    startBounds = new Rectangle();
    startBounds.y = be.getClientY();
    startBounds.x = be.getClientX();

    boolean v = style == Style.WEST || style == Style.EAST;
    int size;
    if (v) {
      size = MyDOM.getWidth(resizeElem, false);
    } else {
      size = MyDOM.getHeight(resizeElem, false);
    }

    int c1 = size - minSize;
    int c2 = Math.max(maxSize - size, 0);
    if (v) {
      draggable.constrainVertical = true;
      draggable.setXConstraint(style == Style.WEST ? c2 : c1, style == Style.WEST ? c1
          : c2);
    } else {
      draggable.constrainHorizontal = true;
      draggable.setYConstraint(style == Style.NORTH ? c2 : c1, style == Style.NORTH ? c1
          : c2);
    }
  }

}
TOP

Related Classes of net.mygwt.ui.client.widget.SplitBar

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.