Package com.allen_sauer.gwt.dnd.client

Source Code of com.allen_sauer.gwt.dnd.client.MouseDragHandler

/*
* Copyright 2008 Fred Sauer
*
* 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.allen_sauer.gwt.dnd.client;

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.Event;
import com.google.gwt.user.client.ui.FocusPanel;
import com.google.gwt.user.client.ui.MouseListener;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.SourcesMouseEvents;
import com.google.gwt.user.client.ui.Widget;

import com.allen_sauer.gwt.dnd.client.util.DOMUtil;
import com.allen_sauer.gwt.dnd.client.util.Location;
import com.allen_sauer.gwt.dnd.client.util.WidgetLocation;

import java.util.HashMap;

/**
* Implementation helper class which handles mouse events for all
* draggable widgets for a given {@link DragController}.
*/
class MouseDragHandler implements MouseListener {
  private static final int ACTIVELY_DRAGGING = 3;
  private static final int DRAGGING_NO_MOVEMENT_YET = 2;
  private static final int NOT_DRAGGING = 1;

  private FocusPanel capturingWidget;
  private final DragContext context;
  private DeferredMoveCommand deferredMoveCommand = new DeferredMoveCommand(this);
  private int dragging = NOT_DRAGGING;
  private HashMap dragHandleMap = new HashMap();
  private boolean mouseDown;
  private int mouseDownOffsetX;
  private int mouseDownOffsetY;
  private Widget mouseDownWidget;

  MouseDragHandler(DragContext context) {
    this.context = context;
    initCapturingWidget();
  }

  public void onMouseDown(Widget sender, int x, int y) {
    if (dragging == ACTIVELY_DRAGGING || dragging == DRAGGING_NO_MOVEMENT_YET) {
      // Ignore additional mouse buttons depressed while still dragging
      return;
    }

    Event event = DOM.eventGetCurrentEvent();
    int button = DOM.eventGetButton(event);
    // TODO remove Event.UNDEFINED after GWT Issue 1535 is fixed
    if (button != Event.BUTTON_LEFT && button != Event.UNDEFINED) {
      return;
    }

    // mouse down (not first mouse move) determines draggable widget
    mouseDownWidget = sender;
    context.draggable = (Widget) dragHandleMap.get(mouseDownWidget);
    assert context.draggable != null;

    if (!toggleKey(event) && !context.selectedWidgets.contains(mouseDownWidget)) {
      context.dragController.clearSelection();
      context.dragController.toggleSelection(context.draggable);
    }
    DeferredCommand.addCommand(new Command() {
      public void execute() {
        DOMUtil.cancelAllDocumentSelections();
      }
    });

    mouseDown = true;
    DOM.eventPreventDefault(event);

    mouseDownOffsetX = x;
    mouseDownOffsetY = y;
    WidgetLocation loc1 = new WidgetLocation(mouseDownWidget, null);
    if (mouseDownWidget != context.draggable) {
      WidgetLocation loc2 = new WidgetLocation(context.draggable, null);
      mouseDownOffsetX += loc1.getLeft() - loc2.getLeft();
      mouseDownOffsetY += loc1.getTop() - loc2.getTop();
    }
    if (context.dragController.getBehaviorDragStartSensitivity() == 0 && !toggleKey(event)) {
      startDragging();
      actualMove(x + loc1.getLeft(), y + loc1.getTop());
    }
  }

  public void onMouseEnter(Widget sender) {
  }

  public void onMouseLeave(Widget sender) {
  }

  public void onMouseMove(Widget sender, int x, int y) {
    if (dragging == ACTIVELY_DRAGGING || dragging == DRAGGING_NO_MOVEMENT_YET) {
      // TODO remove Safari workaround after GWT issue 1807 fixed
      if (sender != capturingWidget) {
        // In Safari 1.3.2 MAC, other mouse events continue to arrive even when capturing
        return;
      }
      dragging = ACTIVELY_DRAGGING;
    } else {
      if (mouseDown) {
        if (Math.max(Math.abs(x - mouseDownOffsetX), Math.abs(y - mouseDownOffsetY)) >= context.dragController.getBehaviorDragStartSensitivity()) {
          DOMUtil.cancelAllDocumentSelections();
          if (!context.selectedWidgets.contains(context.draggable)) {
            context.dragController.toggleSelection(context.draggable);
          }
          startDragging();

          // adjust (x,y) to be relative to capturingWidget at (0,0)
          Location location = new WidgetLocation(mouseDownWidget, null);
          x += location.getLeft();
          y += location.getTop();
        }
      }
      if (dragging == NOT_DRAGGING) {
        return;
      }
    }
    // proceed with the actual drag
    DOM.eventPreventDefault(DOM.eventGetCurrentEvent());
    //    try {
    deferredMoveCommand.scheduleOrExecute(x, y);
    //    } catch (RuntimeException ex) {
    //      cancelDrag();
    //      throw ex;
    //    }
  }

  public void onMouseUp(Widget sender, int x, int y) {
    Event event = DOM.eventGetCurrentEvent();
    int button = DOM.eventGetButton(event);
    // TODO Remove Event.UNDEFINED after GWT Issue 1535 is fixed
    if (button != Event.BUTTON_LEFT && button != Event.UNDEFINED) {
      return;
    }
    mouseDown = false;

    // in case mouse down occurred elsewhere
    if (mouseDownWidget == null) {
      return;
    }

    if (dragging != ACTIVELY_DRAGGING) {
      Widget widget = (Widget) dragHandleMap.get(mouseDownWidget);
      assert widget != null;
      if (!toggleKey(event)) {
        context.dragController.clearSelection();
      }
      context.dragController.toggleSelection(widget);
      DOMUtil.cancelAllDocumentSelections();
      if (dragging == NOT_DRAGGING) {
        return;
      }
    }
    // TODO Remove Safari workaround after GWT issue 1807 fixed
    if (sender != capturingWidget) {
      // In Safari 1.3.2 MAC does not honor capturing widget for mouse up
      Location location = new WidgetLocation(sender, null);
      x += location.getLeft();
      y += location.getTop();
    }
    // Proceed with the drop
    try {
      drop(x, y);
    } finally {
      dragEndCleanup();
    }
  }

  void actualMove(int x, int y) {
    context.mouseX = x;
    context.mouseY = y;
    context.desiredDraggableX = x - mouseDownOffsetX;
    context.desiredDraggableY = y - mouseDownOffsetY;

    context.dragController.dragMove();
  }

  void makeDraggable(Widget draggable, Widget dragHandle) {
    if (dragHandle instanceof SourcesMouseEvents) {
      ((SourcesMouseEvents) dragHandle).addMouseListener(this);
      dragHandleMap.put(dragHandle, draggable);
    } else {
      throw new RuntimeException("dragHandle must implement SourcesMouseEvents to be draggable");
    }
  }

  void makeNotDraggable(Widget dragHandle) {
    if (dragHandleMap.remove(dragHandle) == null) {
      throw new RuntimeException("dragHandle was not draggable");
    }
    ((SourcesMouseEvents) dragHandle).removeMouseListener(this);
  }

  private void dragEndCleanup() {
    DOM.releaseCapture(capturingWidget.getElement());
    dragging = NOT_DRAGGING;
    context.dragEndCleanup();
  }

  private void drop(int x, int y) {
    actualMove(x, y);
    dragging = NOT_DRAGGING;

    // Does the DragController allow the drop?
    try {
      context.dragController.previewDragEnd();
    } catch (VetoDragException ex) {
      context.vetoException = ex;
    }

    context.dragController.dragEnd();
  }

  private void initCapturingWidget() {
    capturingWidget = new FocusPanel();
    capturingWidget.setPixelSize(0, 0);
    RootPanel.get().add(capturingWidget, 0, 0);
    capturingWidget.addMouseListener(this);
    DOM.setStyleAttribute(capturingWidget.getElement(), "visibility", "hidden");
    DOM.setStyleAttribute(capturingWidget.getElement(), "margin", "0px");
    DOM.setStyleAttribute(capturingWidget.getElement(), "border", "none");
  }

  private void startDragging() {
    context.dragStartCleanup();
    try {
      context.dragController.previewDragStart();
    } catch (VetoDragException ex) {
      context.vetoException = ex;
      return;
    }
    context.dragController.dragStart();

    DOM.setCapture(capturingWidget.getElement());
    dragging = DRAGGING_NO_MOVEMENT_YET;
  }

  private boolean toggleKey(Event event) {
    return DOM.eventGetCtrlKey(event) || DOM.eventGetMetaKey(event);
  }
}
TOP

Related Classes of com.allen_sauer.gwt.dnd.client.MouseDragHandler

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.