Drag-n-drop within Fl_Browser

38 views
Skip to first unread message

Rob McDonald

unread,
Jun 30, 2016, 4:28:00 PM6/30/16
to fltk.general
I currently use a Fl_Browser to display a list of items to the user.

I typically maintain my own list.  Any time I add or delete entries, I do a clear() followed by a loop where I add() all my entries.  (I.e. I don't use move() remove() replace() swap() or insert()).

I would like to allow the user to drag-n-drop items in the list to re-order them.  Is this possible?

It seems like it would quickly get ugly if you have to write your own low-level handler using Fl::event_x(), Fl::event_y(), and Fl::event() -- especially for cases with a long list and a vertical scrollbar.

Any ideas?

Rob

Albrecht Schlosser

unread,
Jul 1, 2016, 6:55:04 AM7/1/16
to fltkg...@googlegroups.com
On 30.06.2016 22:27 Rob McDonald wrote:
> I currently use a Fl_Browser to display a list of items to the user.
>
> I typically maintain my own list. Any time I add or delete entries, I
> do a clear() followed by a loop where I add() all my entries. (I.e. I
> don't use move() remove() replace() swap() or insert()).
>
> I would like to allow the user to drag-n-drop items in the list to
> re-order them. Is this possible?

I don't think this is possible with the core FLTK widgets.

> It seems like it would quickly get ugly if you have to write your own
> low-level handler using Fl::event_x(), Fl::event_y(), and Fl::event() --
> especially for cases with a long list and a vertical scrollbar.

You're probably right, that doesn't sound like an easy job. Particularly
giving visual feedback during the drag seems to be difficult.

> Any ideas?

Sorry, no. I can only recommend looking at test/browser.cxx; maybe you
get some ideas. I'd particularly look at swap_cb() that swaps the first
two _selected_ browser items it finds. You need to switch to the multi
browser option to see what it does. But this doesn't help much with the
drag'n'drop operation you need to implement in your own handle() method.

Rob McDonald

unread,
Jul 1, 2016, 11:53:43 AM7/1/16
to fltk.general, Albrech...@online.de

No problem.  I don't think this is a critical need, so we'll just find another way to reorder the list.  I appreciate the time you spent thinking about it to confirm the level of difficulty.

Thanks,

Rob

 

Greg Ercolano

unread,
Jul 1, 2016, 3:31:46 PM7/1/16
to fltkg...@googlegroups.com
On 06/30/16 13:27, Rob McDonald wrote:
> I currently use a Fl_Browser to display a list of items to the user.
> I typically maintain my own list. Any time I add or delete entries, I do a clear() followed by a loop where I add() all my entries. (I.e. I don't use move() remove() replace() swap() or insert()).
> I would like to allow the user to drag-n-drop items in the list to re-order them. Is this possible?

I would think it should be possible, and perhaps not that hard.

I know I did this once with some commercial software, and could swear
someone offered up a patch to add DND to Fl_Tree, but I can't locate it
at the moment.

I recall testing it, and it drew a line at the insertion point during the drag,
which wasn't too hard; it was easy during the drag events to draw the insertion
line into the item the mouse was hovered over.

Not sure if it'd be hard with Fl_Browser.

I might give it a shot; if I can I'll post some demo code..

Greg Ercolano

unread,
Jul 1, 2016, 4:50:08 PM7/1/16
to fltkg...@googlegroups.com
On 07/01/16 12:31, Greg Ercolano wrote:
> On 06/30/16 13:27, Rob McDonald wrote:
>> I would like to allow the user to drag-n-drop items in the list to re-order them. Is this possible?
>
> I would think it should be possible, and perhaps not that hard.
> [..]
> I might give it a shot; if I can I'll post some demo code..

Yep, not too hard:
___________________________________________________________________________ snip

#include <FL/Fl.H>
#include <FL/Fl_Double_Window.H>
#include <FL/Fl_Browser.H>
#include <FL/fl_draw.H>
#include <string.h> // sprintf()
//
// Demonstrate draggable Fl_Browser items - er...@seriss.com 07/01/16
//
class MyBrowser : public Fl_Browser {
void *dragitem;
void change_cursor(Fl_Cursor newcursor) {
fl_cursor(newcursor, FL_BLACK, FL_WHITE);
}
void *item_under_mouse() {
int X, Y, W, H; bbox(X, Y, W, H);
if (!Fl::event_inside(X, Y, W, H)) return 0; // probably scrollbar
return find_item(Fl::event_y());
}
int handle(int event) {
int ret = 0;
switch ( event ) {
case FL_PUSH: {
if ( Fl::event_button() == 1 ) { // left mouse to start drag?
if ( (dragitem = item_under_mouse()) ) { // clicked on an item?
item_select(dragitem, 1); redraw(); // select the dragged item
change_cursor(FL_CURSOR_HAND); // change cursor
ret = 1;
}
}
break;
}
case FL_DRAG: {
if ( dragitem ) {
ret = 1;
void *dst_item = item_under_mouse();
if ( dst_item != dragitem ) {
item_swap(dragitem, dst_item); redraw();
}
}
break;
}
case FL_LEAVE:
case FL_RELEASE: {
if ( dragitem ) {
change_cursor(FL_CURSOR_DEFAULT); // ensure normal cursor
item_select(dragitem, 0); redraw(); // deselect dragged item
dragitem = 0; // disable item drag mode
ret = 1;
}
break;
}
}
if ( dragitem ) return(1); // dragging? don't pass event to Fl_Browser
return(Fl_Browser::handle(event) ? 1 : ret);
}
public:
MyBrowser(int X,int Y,int W,int H) : Fl_Browser(X,Y,W,H)
{ dragitem = 0; }
~MyBrowser()
{ }
};
int main(int argc, char **argv) {
char s[80];
Fl_Double_Window *win = new Fl_Double_Window(300,600);
win->begin();
MyBrowser *brow = new MyBrowser(10,10,win->w()-20,win->h()-20);
for ( int t=0; t<50; t++ ) // Add 50 numbered items
{ sprintf(s, "item %d", t); brow->add(s); }
win->end();
win->resizable(brow);
win->show();
return Fl::run();
}
___________________________________________________________________________ snip

Greg Ercolano

unread,
Jul 1, 2016, 6:19:03 PM7/1/16
to fltkg...@googlegroups.com
On 07/01/16 13:50, Greg Ercolano wrote:
> On 07/01/16 12:31, Greg Ercolano wrote:
>> On 06/30/16 13:27, Rob McDonald wrote:
>>> I would like to allow the user to drag-n-drop items in the list to re-order them. Is this possible?
>>
>> I would think it should be possible, and perhaps not that hard.
>> [..]
>> I might give it a shot; if I can I'll post some demo code..
>
> Yep, not too hard:
> [snip]

Added this to my cheat page:
http://seriss.com/people/erco/fltk/#Fl_Browser_DND_Reorder

..where you'll also find some code improvements to what I posted earlier,
namely better behavior with an FL_MULTI_BROWSER, such that Shift-Click
selection extension works predictably, and keeps the focus box on the
currently dragged item.

In a multi-select browser context, I think one can't really tell
if a click-drag should move an item, or drag a selection?

Because of this, the above cheat page version disables drag-selection
in favor of letting you drag an item, but still lets you use Shift-click
to extend a selection.

If there's a better way, let me know.

anmol....@gmail.com

unread,
Oct 5, 2020, 8:56:05 AM10/5/20
to fltk.general
An old thread, but if someone seeks it, I had to replace dragged with was_moved to make it compile.

Greg Ercolano

unread,
Oct 5, 2020, 11:39:53 AM10/5/20
to fltkg...@googlegroups.com

Oh, thanks! Fixed.
Reply all
Reply to author
Forward
0 new messages