Auto-scroll on drag (Tree)

Hi,

In our application, we use a Tree inside a Panel and allow nodes of the tree to be rearranged using drag and drop.
Some times our tree gets big, enabling the scroll bar.
The scroll bar becomes an issue when a node needs to be dragged to hidden areas of the tree. Vaadin doesn’t seem to support automatic scroll when the node is dragged to the edges of the panel.

How would you suggest I deal with this limitation?
gwt-dnd seems to support that, but I’d prefer not to re-write Vaadin’s drag and drop using gwt-dnd.

Thanks for your help,
Rafael

This feature will most likely be implemented sooner or later into Vaadin, but at the moment there’s not much you can do about it.

One possibility, although probably quite slow and unreliable, would be to use the Panel.setScrollTop method while dragging a tree item.

You can use [tt]
setScrollTop()
[/tt] to set the scroll position in a Panel. I think you could use a [tt]
ServerSideCriterion
[/tt] to scroll the Panel when the mouse pointer hovers over a button or some other component during drag.

You could, for example, put a component above and below the Panel so that when the mouse pointer moves over them, you scroll the Panel a bit. You can get the mouse position from the details object with [tt]
getMouseEvent().getClientY()
[/tt], so you can scroll more if the mouse pointer is farther in the “scroll region”.

So, much like in the
Panel scrolling example
, except that you would trigger scrolling from [tt]
ServerSideCriterion
[/tt] instead on click events.

I need to resolve the same situation as the original poster did. Is this still the best approach for dealing with this?

Using the ServerSideCriterion I am able to detect when a drag begins, but I don’t see how you detect “when the mouse pointer moves over them”. I haven’t seen any components with mouse entered/exited events or mouse hover events. Would I need to create a custom GWT component to send these events?

Also, what is the details object you are referring to when you said “You can get the mouse position from the details object with getMouseEvent().getClientY()”?

Thanks in advance.

With “details object” I mean
TargetDetails
.

The accept() method in ServerSideCriterion gets a DragAndDropEvent as parameter, which has getTargetDetails() to get the target details object.

The accept() method is called a bit like in a “mouse over event”, and as you get where it hovers, you can do things there, such as scroll the Panel (or whereever you have your tree).

I haven’t tried that, but I think it could work. A kind of a hack though.

There’s ticket for scrollling in a Table during drag (
#4246
), but Tree doesn’t have a scroll bar in itself, so it would have to be implemented in Panel and all other layouts that provide a scroll bar. Well, now that I come to think of it, TreeTable has a scroll bar, so if the enhancement for the Table gets done, you can use it in TreeTable.

Over the weekend I spent some time trying to get this to work. I came pretty close, but I can’t get it to work. The crux of the problem is that I need a way to determine when a drag operation has ended (whether it was successfully dropped or it was aborted) and I cannot see a way to do that.

Allow me to provide some highlights for the solution I came up with:

I was able to determine that a drag operation had begun within the tree by embedding the detection logic within the accept method of the tree’s drop handler, as you suggested.

Initially, I tried performing the scroll itself from within the accept method. However, you don’t have control over when and how often that method is fired. Specifically, if the mouse is motionless the method will not fire. For our needs, if the user holds the mouse near the top of the tree while dragging, we want it to scroll periodically.

So for the next step, as was suggested, I placed a components above and below the tree to receive mouse events (ONMOUSEOVER, ONMOUSEOUT, ONMOUSEMOVE). I made custom client side components for this, and they worked fine until I started dragging. When the drag operation begins all components stopped receiving mouse events. I tried this on the custom components, on the enclosing panel and on the tree itself before I discovered that the drag operation has the page’s root element capture the mouse…

(You can see that this happens by looking in the VDragAndDropManager.startDrag(…) method. Within that method, search for Event.setCapture(…))

So to overcome that I switched over to a NativePreviewHandler to capture mouse events within an extended VPanel which I am calling VAutoScrollPanel. Using this technique I was able to receive the mouse events while dragging,

OK, so at this point I had a panel which could auto scroll based on mouse position during a drag operation… but it also performed the auto scroll when not dragging, which is not desired. So I added in a flag you can set from the Tree’s DropHandler’s accept method which lets you turn the autoscroll mode on/off.

However, as far as I can tell, there’s no way to determine when a drag operation has ended unless it succeeds and the DropHandler.drop() method is called. If the drag is aborted, no notification is sent anywhere, as far as I can tell.

I tried listening for events with ID Event.ONLOSECAPTURE (so that I could see when the drag and drop logic calls Event.releaseCapture()) within my nativePreviewHandler, but this event is not raised when the drag operation ends (even though you can clearly see that the root element releases the capture). When the drag operation was begin, I made sure that the ONLOSECAPTURE event was sunk for the root element to make sure this wasn’t why it wasn’t firing.

So I can turn on auto scroll, but I can’t turn it off.

Some things that would have been nice to have while working on this:

NativePreviewHandler’s do not provide a getX() and getY() method like the vaadin mouse events do, which makes sense because the native events are not associated with a particular element yet. However, it would have been nice to have a utility method similar to java swing’s SwingUtilities.convertPointFromScreen(Point p, Component c) method. Instead, I had to copy the code for getX() and getY() out of the MouseEvent class.

It would be nice if VDragAndDropManager allowed you to add listeners for beginDrag and endDrag operations.

Hi,

First of I’m impressed you got that far. IMO that is a really needed feature (should be in Vaadin by default), and I know that things aren’t that simple when it comes to drag and drop in cross browser environment like Vaadin.

I’d suggest you to take a slightly different approach. I’d build make the scrolling VDragAndDropWrappers responsibility. This way it would be easy to notice when the drag ends. Also (in case you want to make you solution super cool) it would be possible to make the auto scrolling component independent feature.

While I was about to suggest this, I noticed thought that overriding its implementation was not possible. My bad. Now its since this change:
http://dev.vaadin.com/changeset/18283

You need a nightly build for that. I just manually launched a build so it should be available within two hours.

Now using deferred binding, you can use your own extended implementation of the manager:
http://code.google.com/webtoolkit/doc/latest/DevGuideCodingBasicsDeferred.html

In case you need any help on this issue, please ask. I’m eager to help you on this as long as I can see the result and develop it further into the core. Getting this into 6.6 release would be awesome.

cheers,
matti

As far as I can tell, the Tree component doesn’t use VDragAndDropWrapper for its Drag and Drop implementation. Instead it supplies it’s own customized implementation. However, the tree itself doesn’t provide its scrolling behavior, so it wasn’t clear where this logic should go. I decided to place it in the VPanel class because of Marko’s suggestion that the logic would have to be placed there (as well as in all other layouts that provide a scroll bar).

Thanks for making this change, however the VDragAndDropManager class has a private constructor, so I cannot extend it for replacement (yet). It will be interesting to see how I can clean things up once I’m able to do this.

I appreciate the help. I’ve requested permission from my company to share what I come up with. I will keep you posted.

Hi,

Sorry, I ment VDragAndDropMananger not VDragAndDropWrapper…

The implementation of VDragAndDropManager can (now) be changed with GWT’s deferred binding. Add following rule to you widgetset (GWT module description file).



	<replace-with
		class="my.own.custom.VDragAndDropManager">
		<when-type-is
			class="com.vaadin.terminal.gwt.client.ui.dd.VDragAndDropManager" />
	</replace-with>

Good luck to your quest!

matti

Hi

I am new to vaadin

I have implemented a tree inside a Panel ,
There if go to the last node of my tree or say the hidden part of panel by scrolling down ,
then if i select anything ,the scroll bar immidiatly goes up ,which is very irritating, as user cant see what he selected .

Please let me know if anything can be done for this .

Thanks

neha


This is the peice of code

HorizontalLayout options = new HorizontalLayout();
options.setSpacing(true);
options.setSizeFull();

Panel jobType = new Panel(“jobType”);
// options.setExpandRatio(jobType, 1f);
jobType.setCaption(“jobType”);
jobType.getContent().setHeight(“100%”);
jobType.getContent().setWidth(“100%”);
jobType.setScrollable(true);
jobType.setSizeFull();

options.addComponent(jobType);

and now to this i add a tree
jobTypes = new TreeCheckBox(“”); [where TreeCheckBox extends Tree]

	jobType.getContent().addComponent(jobTypes);
	jobType.getContent().setSizeUndefined();

Which Vaadin version are you using? Which browser and version?

Some such (browser-specific) issues were addressed in Vaadin 6.5.5 and Vaadin 6.6.0, but there seems to be one related Opera 11 issue left.

Hi Henri

Thanks for the reply

I was running my application in IE (8) .There it is an issue

I have checked this issue just now in mozilla ,and there it is working fine :slight_smile:

Thanks again
neha …

Hi Pete,

It’s been a while since this post but I was wondering if you could share your solution. I’m facing the same problem and I’m not as skilled / smart as you.

Many thanks in advance,
Luis

Hi i also need this functionality. Is there any roadmap or solution presented in Vaadin7?

Yeah, me too. There is
#4246
but it hasn’t seen activity for over a year. This is really missing as it makes drag and drop useless for all but the smallest tables/trees. It would also be nice to be able to open nodes by hovering over them for a while as it is done in most file managers.