Drag and Drop for GWT

498 views
Skip to first unread message

gwt.team.rdayal

unread,
Feb 8, 2007, 2:20:18 PM2/8/07
to Google Web Toolkit
Hi,

A discussion had been started about Drag and Drop in GWT on the
Contributors list, but some of that discussion should have been taking
place on the users list.

So, basically, we want to build Drag and Drop support into GWT. The
question is, what does that mean? Most of us understand what it means
to drag and drop some sort of object, but what does dragging and
dropping mean in terms of GWT's widgets and panels?

I wanted to start a discussion about some of the use cases that you
can envision for Drag and Drop within GWT. Here are a few starters,
which are a combination of ideas from Sandy McArthur, Jason Essington,
mP, and Fred, and Chung Wu:

-Given two boxes with items in them (images, text labels, etc), move
the items back and forth between the two boxes by dragging an item
from one box to another
-Change the order of rows in a table by dragging a row to a new
position
-Multiple-select drag and drop by holding down the CTRL key, clicking
on multiple objects, holding down the mouse button and dragging them,
and then dropping them
-Dragging and dropping objects in a tree view (think files and folders
in Windows Explorer/Email messages being moved to holders in MS
Outlook)

We also need to think about behaviors when dragging:

-What happens when an object is dragged, but it is not on top of a
valid place that it can be dropped? How do we indicate this to the
user?
-Should we constrain the draggable area of an object (i.e. the object
cannot be dragged outside of the panel)

I look forward to hearing from all of you.


Rajeev

gwt.team.rdayal

unread,
Feb 8, 2007, 2:25:16 PM2/8/07
to Google Web Toolkit
Hi,

I wanted to post links to the two drag and drop demos that have been
put together:

Chung's demo:

http://dragdrop.grapier.googlepages.com/DragDrop.html

Fred's demo:

http://code.google.com/p/gwt-dnd/


Rajeev

Sandy McArthur

unread,
Feb 8, 2007, 3:22:44 PM2/8/07
to Google-We...@googlegroups.com
On 2/8/07, gwt.team.rdayal <gwt.tea...@gmail.com> wrote:
> -Change the order of rows in a table by dragging a row to a new
> position

A clarification of the use case I was trying to suggest:

Say I have a table of contact information. Each row has a series of
labels for a contact, call them: FirstNameLabel, LastNameLabel,
PhoneLabel, EmailLabel, etc. The original proposal only described
dragging Widgets around but in my ContactTable example I'd want to
drag the whole table row (or representation of that contact) around.
Dragging the PhoneLabel, if that is what the user happened to click
on, wouldn't indicate visually what was happening. Also, would want
to take this beyond reordering of table rows, to being able to drag
from a row to a CalendarEntryWidget or EmailRecipientWidget.

--
Sandy McArthur

"He who dares not offend cannot be honest."
- Thomas Paine

Luc Claes

unread,
Feb 8, 2007, 3:47:16 PM2/8/07
to Google Web Toolkit
Hi Rajeev,

Could you please have a look to beta.contactoffice.com (documents
section) ?
The beta will be extended in the next two weeks to include a complete
mail client and address book.

We've implemented a GWT drag&drop mechanism a few month ago and would
be pleased to share ideas, code and experience.

In a few words:
- We feel that a strictly widget-based d&d mechanism is too
restrictive (But a widget based d&d could be built on top of a lower
level mechanism).
- Our architecture is based on a rather classical 'DragSource' and
'DropTarget' abstraction where both sources and targets could be
implemented by any object.
- A Drag&Drop manager, hooking an events previewer, maintains a global
D&D state engine. This manager is also used to handle 'marquee
selection' and window splitters.
- For performances reasons, DragSources and DropTargets have to
(de)register themselves to the D&D manager and need to answer to
'getRectangle()' queries.
- DragSources are able to 'contain' multiple objects (ie drag multiple
mail messages or documents)
- The user feedback (= the actually dragged visible object) is
implemented as a 'DraggedWidget' that could be a clone of the
DragSource or anything else.

All this is not completely bulletproof, but works quite well.

Cheers,

Luc


On Feb 8, 8:20 pm, "gwt.team.rdayal" <gwt.team.rda...@gmail.com>
wrote:

Jason Essington

unread,
Feb 8, 2007, 4:50:59 PM2/8/07
to Google-We...@googlegroups.com
While we're looking at DnD demos, here's another GWT DnD Impl that
demonstrates my use case:
http://jason.essington.googlepages.com/DualList.html

This is your standard Dual List with the following features
1) multiple selection via shift+click
2) drag and drop of selected items between lists
3) double click will send 1 item to the other list
4) center buttons work as labeled.

This use case requires multiple widgets to be dragged at once.
It also has the concept of drop-able areas so if the widgets being
dragged aren't over a drop-able area, dropping will result in the
widgets going back to where they started.

-jason

Fred Sauer

unread,
Feb 8, 2007, 5:47:14 PM2/8/07
to Google-We...@googlegroups.com
Very nice!

What would you think of adding a CSS "cursor: move" or similar as a visual cue?
--
Fred Sauer
fr...@allen-sauer.com

Jason Essington

unread,
Feb 8, 2007, 5:59:29 PM2/8/07
to Google-We...@googlegroups.com
All of the elements have css class names, and those names are updated
on drag, on dragover, etc, so it would be pretty simple to add ...

just stuff it in the css.

-jason

Jason Essington

unread,
Feb 8, 2007, 6:08:28 PM2/8/07
to Google-We...@googlegroups.com
Check it out now, I added cursor: pointer on the list options, and it
changes to cursor: move when those options are being dragged.

simple as adding a couple of lines in the css :-)

-jason

Michal Margiel

unread,
Feb 8, 2007, 6:18:50 PM2/8/07
to Google-We...@googlegroups.com


On 2/9/07, Jason Essington <jason.e...@gmail.com> wrote:

Check it out now, I added cursor: pointer on the list options, and it
changes to cursor: move when those options are being dragged.

simple as adding a couple of lines in the css :-)

-jason

I don't see enything new ...


--
Pozdrawiam
Michał Margiel

Michal Margiel

unread,
Feb 8, 2007, 6:20:35 PM2/8/07
to Google-We...@googlegroups.com
Ups. sorry i was my opera browser.. in FF everything looks fine.


--
Pozdrawiam
Michał Margiel

Jason Essington

unread,
Feb 8, 2007, 7:02:16 PM2/8/07
to Google-We...@googlegroups.com
you'll probably have to clear your browser cache, I just updated the
CSS, so that instead of getting an I-beam over the list items you get
a pointer.

-jason

Sandy McArthur

unread,
Feb 9, 2007, 2:06:56 AM2/9/07
to Google-We...@googlegroups.com
The YUI Drag and Drop lib looks to be a very worthy API to mimic.

Like the rest of YUI it's element based instead of Widget based, mainly because YUI works at a lower level and doesn't have "widgets". Below is a summary of what I get from reading it's docs and some commentary of how that may be useful.
  • You can make elements themselves dragable or use a proxy element to represent the drag source with and icon or anything else you can come up with.
  • Configurable mouse move distance before a drag is initiated or mouse down time before a drag is initiated. This is gonna be needed for people with poor mouse skills like my grandmother.
  • Interaction groups: only drag sources and targets that are members of at least one group in common receive DnD events. This lets you optimize event firing by only activating relevant drag targets. You'd probably still want a method for a drag target to express that they don't want to receive the current drag source.
  • Drag Events: startDrag, onDrag, onDragEnter, onDragOver, onDragOut, onDragDrop, onInvalidDrop, endDrag. Would you want onMouse* events to fire to unrelated widgets during a drag? I could imaging wanting them to still fire but it'd be nice to be able to block them for performance reasons if not needed.
  • Point Mode or Intersect Mode: point mode is the mouse pointer has to be over the target, intersect mode is any part of the dragging indicator has to be over any part of the target. Point mode is faster and less ambiguous but if you have a big opaque dragable you'd want target mode. Also, what if more than one drag target is dropped on at the same time?
  • Drag constrains: keeps the dragable in an area even if the mouse moves outside that area. If you were reordering rows in a table you wouldn't want them dragged outside the table. Actually you'd only want them to drag vertically. Opposite for dragable columns.
  • X&Y ticks: ability to snap the drag to specified rows or columns. YUI uses an array if pixel offsets but I think a user pluggable function would be better.
  • Drag handles: lets the whole element be dragable but only if dragged by specific part. A DialogBox that is only dragable by it's title bar. A TextArea would need a drag handle outside the text area else you wouldn't be able to select text. Also this would be great for a resizable panel where you grab the lower right corner to resize it. There is another use case, dragging without any fixed target.
  • Lock/Unlock: I think this temporarily disables a source/target. Would be useful if a widget could go into an edit mode and you didn't want it to be a drag source/target until the edits were finished.
  • Window Scroll: need to be able to scroll the browser window while dragging if the drag source and target don't fit in the view port at the same time.
  • Padding: a way to increase the calculated drag source or target size to make it easier to hit a target.
For GWT I think it's reasonable to make Widgets be the source and targets of drag events. But Widgets would also need the ability to express that only part of them are the drag source or the drag target. Table rows or columns would be a good example.

A ListBox that has more rows than currently shown would need a way to cause it to scroll up or down while it's the drag target so user can find where they want to drop in the list.

I probably missed some interesting points but if nothing else it should be enough to get people thinking.
Message has been deleted

Sandy McArthur

unread,
Feb 9, 2007, 2:38:32 PM2/9/07
to Google-We...@googlegroups.com
On 2/9/07, Serge <ser...@yahoo.com> wrote:
> I don't see here a use case that I'm using.
>
> When the "drag" starts, the "dragged" widget stays still, and the user
> is dragging a "drag label" instead of the widget.

That is use of a Drag Proxy. The label is a proxy form representing
the drag source.

Serge

unread,
Feb 9, 2007, 2:45:56 PM2/9/07
to Google Web Toolkit
I was using YUI a little and I support Sandy.

Other use cases MOVE widgets, but a user also should be able to use
drag-and-drop to COPY widgets.

Think about copying files in Windows by dragging them with the right
button. In this case the original widget needs to stay in it's
original place, and the user should drag a "proxy" instead.

gwt.team.rdayal

unread,
Feb 12, 2007, 1:59:11 PM2/12/07
to Google Web Toolkit
Hey Luc,

Sorry, I had missed the post on this thread. As I had mentioned on the
other thread, the demo is pretty cool, and handles quite a few of the
use cases that we have been discussing. I would be interested to see
some of the code that you guys have written. Would this be possible?

Rajeev

Luc Claes

unread,
Feb 13, 2007, 4:03:20 AM2/13/07
to Google Web Toolkit
Hello Rajeev,

I made the source code of the core drag&drop classes available on our
demo server:
beta.contactoffice.com --> demo login --> 'documents' tool --> Groups
--> gwt-contrib

We don't (yet?) follow the 'contributing code' guidelines but, in the
interim, the code is published under an Apache2 license.

Luc

On Feb 12, 7:59 pm, "gwt.team.rdayal" <gwt.team.rda...@gmail.com>
wrote:

gwt.team.rdayal

unread,
Feb 19, 2007, 10:09:22 PM2/19/07
to Google Web Toolkit
Hey Luc,

Thanks for posting this. I will check out your code this week.


Rajeev

gwt.team.rdayal

unread,
Feb 19, 2007, 10:24:26 PM2/19/07
to Google Web Toolkit
@Sandy:

I would agree with you - this is a DnD implementation that has hit
upon most of the major functional areas that we would want for DnD.

Your point about "part of Widgets being the drag source or drop
target" is a good one, which leads to the hardest question we have to
answer, which is:

@Everybody:

"How does Drag and Drop affect GWT"?

Are Trees and Tables basically special cases of Drag and Drop within
GWT, or can we generalize the idea of parts of widgets being draggable/
droppable?

How about Panels? Panels are Widgets, but should they also be
draggable? If so, what is the expected behavior? I would assume that
one could drag a panel, and all widgets contained within it would also
be dragged as well. Could one drop a panel onto another panel?

We need to look at the widgets and panels that we already have within
GWT, and think about what it would mean to drag and drop them.
(dropping them can be especially complex, as there are many possible
interactions) Some of the drag behaviors and drop interactions between
widgets will seem clear, and maybe these are the default drag and drop
behaviors that will be available out-of-the-box (if we deem them to be
important enough). For those other cases that are not as important/
useful or less clear, the facilities should be available to make the
widget draggable/droppable in the manner in which the implementer
chooses.

Thoughts?


Rajeev


On Feb 9, 2:06 am, "Sandy McArthur" <sandy...@gmail.com> wrote:
> The YUI Drag and Drop <http://developer.yahoo.com/yui/dragdrop/> lib looks


> to be a very worthy API to mimic.
>
> Like the rest of YUI it's element based instead of Widget based, mainly
> because YUI works at a lower level and doesn't have "widgets". Below is a
> summary of what I get from reading it's docs and some commentary of how that
> may be useful.
>

> - You can make elements themselves dragable or use a proxy element to


> represent the drag source with and icon or anything else you can come up
> with.

> - Configurable mouse move distance before a drag is initiated or mouse


> down time before a drag is initiated. This is gonna be needed for people
> with poor mouse skills like my grandmother.

> - Interaction groups: only drag sources and targets that are members


> of at least one group in common receive DnD events. This lets you optimize
> event firing by only activating relevant drag targets. You'd probably still
> want a method for a drag target to express that they don't want to receive
> the current drag source.

> - Drag Events: startDrag, onDrag, onDragEnter, onDragOver, onDragOut,


> onDragDrop, onInvalidDrop, endDrag. Would you want onMouse* events to fire
> to unrelated widgets during a drag? I could imaging wanting them to still
> fire but it'd be nice to be able to block them for performance reasons if
> not needed.

> - Point Mode or Intersect Mode: point mode is the mouse pointer has to


> be over the target, intersect mode is any part of the dragging indicator has
> to be over any part of the target. Point mode is faster and less ambiguous
> but if you have a big opaque dragable you'd want target mode. Also, what if
> more than one drag target is dropped on at the same time?

> - Drag constrains: keeps the dragable in an area even if the mouse


> moves outside that area. If you were reordering rows in a table you wouldn't
> want them dragged outside the table. Actually you'd only want them to drag
> vertically. Opposite for dragable columns.

> - X&Y ticks: ability to snap the drag to specified rows or columns.


> YUI uses an array if pixel offsets but I think a user pluggable function
> would be better.

> - Drag handles: lets the whole element be dragable but only if dragged


> by specific part. A DialogBox that is only dragable by it's title bar. A
> TextArea would need a drag handle outside the text area else you wouldn't be
> able to select text. Also this would be great for a resizable panel where
> you grab the lower right corner to resize it. There is another use case,
> dragging without any fixed target.

> - Lock/Unlock: I think this temporarily disables a source/target.


> Would be useful if a widget could go into an edit mode and you didn't want
> it to be a drag source/target until the edits were finished.

> - Window Scroll: need to be able to scroll the browser window while


> dragging if the drag source and target don't fit in the view port at the
> same time.

> - Padding: a way to increase the calculated drag source or target size

Fred Sauer

unread,
Feb 19, 2007, 10:40:34 PM2/19/07
to Google-We...@googlegroups.com


On 2/19/07, gwt.team.rdayal <gwt.tea...@gmail.com> wrote:
"How does Drag and Drop affect GWT"?

Are Trees and Tables basically special cases of Drag and Drop within
GWT, or can we generalize the idea of parts of widgets being draggable/
droppable?

Let's call it a "drag handle", the thing by which you can drag a larger thing.

It's already been said that the draggable may not always be a subclass of Widget, e.g. a table where the rows or columns can be rearranged by dragging. Can we say the drag handle must always be a Widget? If not, what's a good use case for a drag handle that is not a Widget subclass?

Fred

Olostan

unread,
Mar 8, 2007, 6:35:03 AM3/8/07
to Google Web Toolkit
Hello.

I was searching for tree with dnd support and found this thread.
Does anybody knows about is it possible to add dnd capability to GWT's
Tree widget?

I am thinking to start work in this direction. Can anybody give any
advices/suggestions on it? As I see there is gwt-dnd contribution that
could be base for tree with dnd.

Thanks,
WBR
Valentyn Shybanov
http://olostan.org.ua/

On 20 фев, 05:40, "Fred Sauer" <f...@allen-sauer.com> wrote:

Jason Essington

unread,
Mar 8, 2007, 10:50:51 AM3/8/07
to Google-We...@googlegroups.com
I suppose if you made your treeitems in such a way that they could
capture drag events (onMouseMove) then you could update their
location as they are being dragged, and have them disconnect and
reconnect themselves onDrop.

I have run into some annoying problems with the current
implementation of Tree and ended up just rewriting the implementation
to allow it to support the things I wanted to do with it (animation,
not scroll unexpectedly, etc). Basically I tossed the entire
implementation and just (mostly) kept the API, then started over from
scratch.

There seems to be some discussion beginning on the contrib list about
improving Tree, so it may be worth throwing your $0.02 worth in those
discussions to include your use cases, so if Tree does get an
overhaul it could fit your needs.

-jason

Sandy McArthur

unread,
Mar 8, 2007, 11:55:38 AM3/8/07
to Google-We...@googlegroups.com
On 2/19/07, gwt.team.rdayal <gwt.tea...@gmail.com> wrote:
> @Everybody:
>
> "How does Drag and Drop affect GWT"?
>
> Are Trees and Tables basically special cases of Drag and Drop within
> GWT, or can we generalize the idea of parts of widgets being draggable/
> droppable?
>
> How about Panels? Panels are Widgets, but should they also be
> draggable? If so, what is the expected behavior? I would assume that
> one could drag a panel, and all widgets contained within it would also
> be dragged as well. Could one drop a panel onto another panel?
>
> We need to look at the widgets and panels that we already have within
> GWT, and think about what it would mean to drag and drop them.
> (dropping them can be especially complex, as there are many possible
> interactions) Some of the drag behaviors and drop interactions between
> widgets will seem clear, and maybe these are the default drag and drop
> behaviors that will be available out-of-the-box (if we deem them to be
> important enough). For those other cases that are not as important/
> useful or less clear, the facilities should be available to make the
> widget draggable/droppable in the manner in which the implementer
> chooses.
>
> Thoughts?

I get the impression that you are trying real hard to make the
provided DnD simpler than it should be. Too much provided logic is
just going to get in my way.

You just need to provide the hooks to make it easy to implement DnD,
at least for a first implementation. I don't want you to tell me what
it means to drag from or drop into a component. I just want reasonable
hooks to do this myself.

Let any UIObject be a drag handle for a Widget that implements a
DragSource interface. (recall that Widgets are UIObjects too.)

Let any Widget that implements a DropTarget interface receive events
about UIObjects that are potential drop points when they are dragged
over.

onAttach a Widget is expected to register itself with the DragManager.
onDetach it should unregister itself.

This way a programmer could register a Tree and it's TreeItems as
players in DnD. The whole Panel could be a DropTarget but not a
DragSource or vice versa or both. Or part of a Panel could be the DnD
players.

HTMLTable doesn't use UIObjects for table rows/cells so either it'd be
out of luck or require extra logic in the HTMLTable to find the
appropriate row/cell. Just don't dumb the event object down too much
so that the HTMLTable drag/drop logic can find the exact element that
is the current source/target.

Fred Sauer

unread,
Mar 8, 2007, 2:15:38 PM3/8/07
to Google-We...@googlegroups.com
On 3/8/07, Sandy McArthur <sand...@gmail.com> wrote:
You just need to provide the hooks to make it easy to implement DnD,
at least for a first implementation. I don't want you to tell me what
it means to drag from or drop into a component. I just want reasonable
hooks to do this myself.

Let any UIObject be a drag handle for a Widget that implements a
DragSource interface. (recall that Widgets are UIObjects too.)

Let any Widget that implements a DropTarget interface receive events
about UIObjects that are potential drop points when they are dragged
over.

onAttach a Widget is expected to register itself with the DragManager.
onDetach it should unregister itself.

This way a programmer could register a Tree and it's TreeItems as
players in DnD. The whole Panel could be a DropTarget but not a
DragSource or vice versa or both. Or part of a Panel could be the DnD
players.


First, I agree that GWT (at a minimum) needs to provide plumbing so that the application developer can implement drag-and-drop in whatever way they see fit. There's going to be lots of use cases we didn't think of.

In developing gwt-dnd (http://code.google.com/p/gwt-dnd/) I started out requiring folks to implement drag-source and drop-target type interfaces on their widgets, but found this to be burdensome since it requires every draggable widget to be extended. The additional requirements becomes especially troublesome when one tries to add drag and drop functionality to a complex, existing application.

Since all I really needed was SourcesMouseEvents, that has become the only requirement for drag sources. Now, since the widget is no longer special, I made the drag controller (~manager) implement SourcesDragEvents so that you can listen for (and veto) drag operations. In a way, the drag controller became a decorator for draggable widgets.

--
Fred Sauer
fr...@allen-sauer.com

Brill

unread,
Mar 8, 2007, 11:23:46 PM3/8/07
to Google Web Toolkit
I like the idea of having "drag containers" so that pretty much any
container can be a drag source and/or target.

- Brill Pappin

On Feb 8, 2:20 pm, "gwt.team.rdayal" <gwt.team.rda...@gmail.com>
wrote:
[...]


> We also need to think about behaviors when dragging:
>
> -What happens when an object is dragged, but it is not on top of a
> valid place that it can be dropped? How do we indicate this to the
> user?
> -Should we constrain the draggable area of an object (i.e. the object
> cannot be dragged outside of the panel)

[...]

Reply all
Reply to author
Forward
0 new messages