fredsa / gwt-dnd

Library providing easy to use mouse or touch based drag-and-drop capabilities to GWT
43 stars 41 forks source link

Problems using a DnD boundary panel within a scroll panel #81

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
Let me illustrate that on the following case (see also attached sample 
application).
A "page" (absolute panel) contains some "boxes" (absolute panels as children of 
a page).
Pages are drop targets, boxes are drop targets and drag sources.
(Compare to issue 80, same test case)

In release 2.6.4. were already some fixes related to scroll panels although I 
think there are more
problems:
1. Drop targets outside the visible scroll area won't work. The reason for this 
is the method
   DropControllerCollection.resetCache() which filters them out. If you comment out the filtering 
   lines, it works.

  void resetCache(Panel boundaryPanel, DragContext context) {
    ArrayList<Candidate> list = new ArrayList<Candidate>();

    if (context.draggable != null) {
      //WidgetArea boundaryArea = new WidgetArea(boundaryPanel, null);
      for (DropController dropController : dropControllerList) {
        Candidate candidate = new Candidate(dropController);
        //if (DOM.isOrHasChild(context.draggable.getElement(), 
candidate.getDropTarget().getElement())) {
        //  continue;
        //}
        // FIXME: censhare: always add!
        //if (candidate.getTargetArea().intersects(boundaryArea)) {
          list.add(candidate);
        //}
      }
    }

    sortedCandidates = list.toArray(new Candidate[list.size()]);
    Arrays.sort(sortedCandidates);
  }

2. The new auto scroll feature during drag does not work very well. Sometimes 
it does not start 
or it
   jumps to much. It least in my test case. Why not using the context.draggable instead of the 
   context.positioner widget? I have a much smoother scrolling with it.

3. Several offset problems after scrolling during drag. Scrolling can be 
triggered either by auto 
   scrolling or when e.g. using mouse wheel. Try the attached test case! I found a solution for my
   case, but I assume this is not a general solution for all applications. 
   Here's the summary of my changes:
   - PickupDragController.java methods dragStart() and dragMove(). There's the line
     DropController newDropController = getIntersectDropController(context.mouseX, 
context.mouseY);
     I've replaced it by the following code:

    com.google.gwt.dom.client.Element parent = 
context.boundaryPanel.getElement().getOffsetParent();
        int fixX = parent.getAbsoluteLeft();
        int fixY = parent.getAbsoluteTop();
        DropController newDropController = getIntersectDropController(context.mouseX - 
boundaryOffsetX + fixX, 
            context.mouseY - boundaryOffsetY + fixY, context);

   - MouseDragHandler.java method onMouseMove(), I needed to add:
        x += location.getLeft();
        y += location.getTop();
     on line 282 before the startDragging();

   - WidgetArea.java, I'm still using the version 2.6.4. with the following modification in the 
     constructor:
      while (elem != null && (p = elem.getOffsetParent()) != null) {
      setLeft(getLeft() + elem.getScrollLeft());
      setTop(getTop() + elem.getScrollTop());

      /* commented out:
      int temp;
      if ((temp = getWidth() + DOMUtil.getClientWidth(elem)) > 0) {
        setRight(getRight() + temp);
      }
      if ((temp = getHeight() + DOMUtil.getClientHeight(elem)) > 0) {
        setBottom(getBottom() + temp);
      }
      */

      elem = p;
    }

Original issue reported on code.google.com by m...@censhare.de on 23 Jul 2009 at 9:21

Attachments:

GoogleCodeExporter commented 9 years ago

Original comment by fredsa on 27 Jul 2009 at 2:18

GoogleCodeExporter commented 9 years ago
Thanks again for the detailed test cases and problem descriptions, as well as 
digging into the code.

Items 1 and 3 fixed should be fixed in r956. As a start resetCache() is called 
at most once every 100ms. I may 
review this over time. Feedback would be appreciated.

Original comment by fredsa on 27 Jul 2009 at 3:16

GoogleCodeExporter commented 9 years ago
For item #2 I did review the widget that is used to scrollIntoView() and 
committed a change in r957 to improve 
scrolling when the user has selected multiple widgets (via CTRL/META-click). 
gwt-dnd now uses the widget 
under the mouse (=the last widget selected) rather than the first widget 
selected (which may be noticeably 
separated from the last widget selected).

I am still using the positioner so as to avoid the boundary panel from growing 
inappropriately when when 
setBehaviorConstrainedToBoundaryPanel(true) is in effect.

Original comment by fredsa on 27 Jul 2009 at 5:01

GoogleCodeExporter commented 9 years ago
Answer to comment 2:
I'd like to try out your fixes and will give you feedback!
Although I have problems to get a distribution jar from svn. You made the 
changes in the trunk and there I get 
compile error about missing CssResource and ClientBundle classes. So I assume 
you're working already on GWT 
2.0 version, which I can't at the moment.
Are you planning to merge the changes into the GWT1.7 branch as well? 

Original comment by m...@censhare.de on 27 Jul 2009 at 8:28

GoogleCodeExporter commented 9 years ago
Answer to comment 3:
You're right, when using the draggable the boundary panel might grow 
inappropriately.
I fixed this by an additional check, like this:
        int dragProxyWidth = dragProxyAbsLeft + dragProxy.getOffsetWidth() + getScrollElement().getScrollLeft();
        int dragProxyHeight = dragProxyAbsTop + dragProxy.getOffsetHeight() + 
getScrollElement().getScrollTop();
        if (dragProxyWidth < boundaryPanelWidth && dragProxyHeight < boundaryPanelHeight) {
            dragProxy.getElement().scrollIntoView();
        }

Original comment by m...@censhare.de on 27 Jul 2009 at 8:32

GoogleCodeExporter commented 9 years ago
Yes, gwt-dnd trunk is using features from GWT trunk. New features are unlikely 
to be 
ported back to the 1.7 branch, but bug fixes certainly make sense.

As for the jumping around when scrolling: any chance you're using standards 
mode? If 
so, this issue may be affecting you as well:
  http://code.google.com/p/google-web-toolkit/issues/detail?id=3883

Original comment by fredsa on 27 Jul 2009 at 4:13

GoogleCodeExporter commented 9 years ago
For the autoscrolling problem, with the attached Testcase I couldn't make it 
really working. 
I tried all different kinds of host pages, but the effect is always the same: 
auto scrolling only works randomly 
when moving a lot around. E.g. when moving the draggable slowly to an edge 
nothing happens.

With the following code in the test case this works pretty well. Put the method 
to the Box- and 
PageDropController class:
        @Override
        public void onMove(DragContext context) {
            Widget movable = ((PickupDragController) context.dragController).movablePanel;
            int dragProxyWidth = movable.getAbsoluteLeft() + movable.getOffsetWidth() + 
scrollPanel.getElement().getScrollLeft();
            int dragProxyHeight = movable.getAbsoluteTop() + movable.getOffsetHeight() + 
scrollPanel.getElement().getScrollTop();

            // scroll pages into view. Need to avoid scrolling outside to right and bottom
            if (dragProxyWidth < boundaryPanel.getOffsetWidth() && dragProxyHeight < 
boundaryPanel.getOffsetHeight()) {
                movable.getElement().scrollIntoView();
            }
        }

One remark: it would be nice that the movable panel is somehow accessible 
during a drag, e.g. via the drag 
context. For this test I just made the movablePanel in PickupDragController 
public.

Original comment by m...@censhare.de on 28 Jul 2009 at 9:48

GoogleCodeExporter commented 9 years ago
Item #2: We have still problems with your mouse over implementation. It might 
be a
good idea to add a optional activation flag for the scroll into view feature.

Original comment by f...@censhare.de on 22 Dec 2009 at 11:41

GoogleCodeExporter commented 9 years ago
Sure. It's there:
  dragController.setBehaviorScrollIntoView(false);

Original comment by fredsa on 29 Dec 2009 at 8:26