Package net.mygwt.ui.client.fx

Source Code of net.mygwt.ui.client.fx.Draggable

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

import net.mygwt.ui.client.Events;
import net.mygwt.ui.client.MyDOM;
import net.mygwt.ui.client.Style;
import net.mygwt.ui.client.event.BaseEvent;
import net.mygwt.ui.client.event.Listener;
import net.mygwt.ui.client.util.Observable;
import net.mygwt.ui.client.util.Rectangle;
import net.mygwt.ui.client.widget.Component;

import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.DeferredCommand;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.EventPreview;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.KeyboardListener;
import com.google.gwt.user.client.ui.Widget;

/**
* Adds drag behavior to any widget. Drag operations can be initiated from the
* widget itself, or another widget, such as the header in a dialog.
*
* <p>
* It is possible to specify event targets that will be ignored. If the target
* element has a 'my-nodrag' style it will not trigger a drag operation.
* </p>
*
* <dl>
* <dt><b>Events:</b></dt>
*
* <dd><b>DragStart</b> : (source this, widget this, event)
* <div>Fires after a drag has started.</div>
* <ul>
* <li>source : this</li>
* <li>widget : this</li>
* <li>event : the dom event</li>
* </ul>
* </dd>
*
* <dd><b>DragEnd</b> : (source this, widget this, event)
* <div>Fires after a drag has ended.</div>
* <ul>
* <li>source : this</li>
* <li>widget : this</li>
* <li>event : the dom event</li>
* </ul>
* </dd>
* </dl>
*/
public class Draggable extends Observable {

  /**
   * <code>true</code> to use a proxy widget during drag operation. Default
   * value is <code>true</code>
   */
  public boolean useProxy = true;

  /**
   * proxyStyle is the style name used for proxy drags. Default value is
   * 'my-drag-proxy'.
   */
  public String proxyStyle = "my-drag-proxy";

  /**
   * <code>true</code> to stop vertical movement. Default value is
   * <code>false</code>
   */
  public boolean constrainVertical = false;

  /**
   * <code>true</code> to stop horizontal movement. Default value is
   * <code>false</code>
   */
  public boolean constrainHorizontal = false;

  /**
   * <code>true</code> to set client area constraints. Default value is
   * <code>true</code>
   */
  public boolean constrainClient = true;

  /**
   * <code>true</code> to move source widget aftet a proxy drag. Default
   * values is <code>true</code>
   */
  public boolean moveAfterProxyDrag = true;

  /**
   * If specified, drag will be constrained by container bounds.
   */
  public Widget container;

  /**
   * <code>true</code> to set proxy dimensions the same as the drag widget.
   * Default value is <code>true</code>
   */
  public boolean sizeProxyToSource = true;

  private Component dragWidget;
  private Component handle;
  private boolean dragging;
  private boolean enabled = true;
  private int dragStartX, dragStartY;
  private int lastX, lastY;
  private int clientWidth, clientHeight;
  private int conX, conY, conWidth, conHeight;
  private Rectangle startBounds;
  private Element proxyElem;
  private EventPreview preview;
  private int xLeft = Style.DEFAULT, xRight = Style.DEFAULT;
  private int xTop = Style.DEFAULT, xBottom = Style.DEFAULT;

  /**
   * Creates a new draggable instance.
   *
   * @param dragWidget the widget to be dragged
   */
  public Draggable(Component dragWidget) {
    this(dragWidget, dragWidget);
  }

  /**
   * Create a new draggable instance.
   *
   * @param dragWidget the widget to be dragged
   * @param handle the widget drags will be initiated from
   */
  public Draggable(final Component dragWidget, Component handle) {
    this.dragWidget = dragWidget;
    this.handle = handle;

    MyDOM.makePositionable(dragWidget.getElement());

    handle.sinkEvents(Event.MOUSEEVENTS);
    handle.addListener(Events.MouseDown, new Listener() {
      public void handleEvent(BaseEvent be) {
        onMouseDown(be);
      }
    });

    preview = new EventPreview() {
      public boolean onEventPreview(Event event) {
        switch (DOM.eventGetType(event)) {

          case Event.ONKEYDOWN:
            int key = DOM.eventGetKeyCode(event);
            if (key == KeyboardListener.KEY_ESCAPE && dragging) {
              cancelDrag();
            }
            break;
          case Event.ONMOUSEMOVE:
            onMouseMove(event);
            break;
          case Event.ONMOUSEUP:
            stopDrag(event);
            break;
        }
        return false;
      }
    };
  }

  /**
   * Returns the drag handle.
   *
   * @return the drag handle
   */
  public Widget getDragHandle() {
    return handle;
  }

  /**
   * Returns the widget being dragged.
   *
   * @return the drag widget
   */
  public Widget getDragWidget() {
    return dragWidget;
  }

  /**
   * Returns <code>true</code> if a drag is in progress.
   *
   * @return the drag state
   */
  public boolean isDragging() {
    return dragging;
  }

  /**
   * Enables dragging if the argument is <code>true</code>, and disables it
   * otherwise.
   *
   * @param enabled the new enabled state
   */
  public void setEnabled(boolean enabled) {
    this.enabled = enabled;
  }

  /**
   * Constrains the horizontal travel.
   *
   * @param left the number of pixels the element can move to the left
   * @param right the number of pixels the element can move to the right
   */
  public void setXConstraint(int left, int right) {
    xLeft = left;
    xRight = right;
  }

  /**
   * Constrains the vertical travel.
   *
   * @param top the number of pixels the element can move to the up
   * @param bottom the number of pixels the element can move to the down
   */
  public void setYConstraint(int top, int bottom) {
    xTop = top;
    xBottom = bottom;
  }

  private void cancelDrag() {
    if (dragging) {
      DOM.removeEventPreview(preview);
      dragging = false;
      if (useProxy) {
        MyDOM.setVisible(proxyElem, false);
      }
    }
  }

  private void onMouseDown(BaseEvent be) {
    Element target = be.getTarget();
    String s = DOM.getElementProperty(target, "className");
    if (s != null && s.indexOf("my-nodrag") != -1) {
      return;
    }

    startBounds = MyDOM.getBounds(dragWidget.getElement(), true);

    dragWidget.disable();
    startDrag(be.event);

    DOM.addEventPreview(preview);

    clientWidth = Window.getClientWidth() + MyDOM.getBodyScrollLeft();
    clientHeight = Window.getClientHeight() + MyDOM.getBodyScrollTop();

    dragStartX = be.getClientX();
    dragStartY = be.getClientY();

    if (container != null) {
      conX = container.getAbsoluteLeft();
      conY = container.getAbsoluteTop();
      conWidth = container.getOffsetWidth();
      conHeight = container.getOffsetHeight();
    }
  }

  private void onMouseMove(Event event) {
    int x = DOM.eventGetClientX(event);
    int y = DOM.eventGetClientY(event);

    if (dragging) {
      int left = startBounds.x + (x - dragStartX);
      int top = startBounds.y + (y - dragStartY);

      int width = dragWidget.getOffsetWidth();
      int height = dragWidget.getOffsetHeight();

      if (constrainClient) {
        left = Math.max(left, 0);
        top = Math.max(top, 0);
        left = Math.min(clientWidth - width, left);
        top = Math.min(clientHeight - height, top);
      }

      if (container != null) {
        left = Math.max(left, conX);
        top = Math.max(top, conY);
        left = Math.min(conX + conWidth - dragWidget.getOffsetWidth(), left);
        top = Math.min(conY + conHeight - dragWidget.getOffsetHeight(), top);
      }

      if (xLeft != Style.DEFAULT) {
        left = Math.max(startBounds.x - xLeft, left);
      }
      if (xRight != Style.DEFAULT) {
        left = Math.min(startBounds.x + xRight, left);
      }

      if (xTop != Style.DEFAULT) {
        top = Math.max(startBounds.y - xTop, top);

      }
      if (xBottom != Style.DEFAULT) {
        top = Math.min(startBounds.y + xBottom, top);
      }

      if (constrainHorizontal) {
        left = startBounds.x;
      }
      if (constrainVertical) {
        top = startBounds.y;
      }

      lastX = left;
      lastY = top;

      if (useProxy) {
        MyDOM.setLocation(proxyElem, left, top);
      } else {
        MyDOM.setLocation(dragWidget.getElement(), left, top);
      }
    }
  }

  private void startDrag(Event event) {
    if (!enabled) {
      return;
    }
   
    DOM.setIntStyleAttribute(dragWidget.getElement(), "zIndex", MyDOM.getZIndex());
   
    BaseEvent be = new BaseEvent(dragWidget);
    be.event = event;
    fireEvent(Events.DragStart, be);

    dragging = true;
    if (useProxy) {
      if (proxyElem == null) {
        proxyElem = DOM.createDiv();
        MyDOM.setStyleName(proxyElem, proxyStyle);
        MyDOM.disableTextSelection(proxyElem);
        Element body = MyDOM.getBody();
        DOM.appendChild(body, proxyElem);
        DOM.setIntStyleAttribute(proxyElem, "zIndex", MyDOM.getZIndex());
      }
      MyDOM.setVisible(proxyElem, true);
      if (sizeProxyToSource) {
        MyDOM.setBounds(proxyElem, startBounds);
      }

      // did listeners change size?
      if (be.height > 0) {
        MyDOM.setHeight(proxyElem, be.height, true);
      }
      if (be.width > 0) {
        MyDOM.setWidth(proxyElem, be.width, true);
      }
    }
  }

  private void stopDrag(Event event) {
    if (dragging) {
      DOM.removeEventPreview(preview);
      dragging = false;
      if (useProxy) {
        if (moveAfterProxyDrag) {
          Rectangle rect = MyDOM.getBounds(proxyElem, false);
          MyDOM.setLocation(dragWidget.getElement(), rect.x, rect.y);
        }
        Element body = MyDOM.getBody();
        DOM.removeChild(body, proxyElem);
        proxyElem = null;
      }
      BaseEvent be = new BaseEvent(dragWidget);
      be.event = event;
      be.x = lastX;
      be.y = lastY;
      fireEvent(Events.DragEnd, be);
    }
    DeferredCommand.addCommand(new Command() {
      public void execute() {
        dragWidget.enable();
      }
    });
  }

}
TOP

Related Classes of net.mygwt.ui.client.fx.Draggable

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.