Subscribe Bookmark RSS Feed
Craige_Hales

Staff

Joined:

Mar 21, 2013

MouseBox ListBox Drag and Drop

question that prompted this script:

Trouble with mousebox behavior?

9774_DragDrop.png

Comments

Hi Craige, I'm trying to make your listboxes more general because I love these but I'd like to make any number of them and put them anywhere.  I've got it working but it seems really finicky with the selection.  Is there anything you can think of to change the sensitivity or anything of the mousebox?  I don't want to have to rely on child/parent relations. 

Names Default to here(1);

linked = Function({list}, {},

       Mousebox(

              <<SetDragEnable(1),

              //<<SetTrackEnable(1),

              <<SetDropEnable(1),

              <<Set Drag Begin(

                     Function({this, clickPt},

                           this<<Set Drop Enable(0);

                     )

              ),

              /*<<SetTrack(

                     Function({this, clickPt},

                           this << Set DropEnable(0);

                           sel = (this << child)<<Get Selected;

                           this << SetUserData(sel)

                     )

              ),

              <<SetDropTrack(

                     Function({this, clickPt},

                           {destbox, sourcebox, lb, items, i, lb_source, lb_dest, index},

                           destbox = this << GetDestBox;

                           sourcebox = this << GetSourceBox;

                           show(sourcebox);

                           /*lb_source = sourcebox << child;

                           sel = lb_source << Get Selected;

                           lb_dest = destbox << child;

                           items = lb_source << Get Items;

                           for(i = 1, i<=nitems(sel), i++,

                                  index = Contains(lb_source<<Get Items, sel);

                                  lb_source << Remove Item(index);

                                  lb_dest << Append(sel);

                           );

                           show(destbox, sel, text, lb, index, items);

                           sourcebox << Set Drop Enable(1);

                           1;*/

                     )                   

              ),*/

              <<Set Drag End(

                     Function({this, clickPt, how},

                           this<<Set Drop Enable(1);

                     )

              ),

              <<SetDropCommit(

                     Function({this, clickPt, text},

                           {destbox, sourcebox, lb, items, i, lb_source, lb_dest, index},

                           destbox = this << GetDestBox;

                           sourcebox = this << GetSourceBox;

                           show(sourcebox);

                           lb_source = sourcebox << child;

                           sel = lb_source << Get Selected;

                           lb_dest = destbox << child;

                           items = lb_source << Get Items;

                           for(i = 1, i<=nitems(sel), i++,

                                  index = Contains(lb_source<<Get Items, sel);

                                  lb_source << Remove Item(index);

                                  lb_dest << Append(sel)

                           );

                           show(destbox, sel, text, lb, index, items);

                           sourcebox << Set Drop Enable(1);

                           1;

                     )

              ),

              listbox(list)

       )

);

new window("Test",

       Hlistbox(

              linked({"1", "2", "3"}),

              linked({"4", "5", "6"}),

              linked({"8", "9", "14"})

       )

);

new window("Other Window", //not sure if this is a good or bad thing yet

       linked({"test", "other these", "stuff"})

);

Craige_Hales

The original JSL does not scale beyond two boxes, and it would be very hard to get it to work, generic or not, for more than two because of the assumption that "the other box" sourced the drag.  There is a comment at the beginning of the code explaining why MouseBox uses the track (mouse moves but button not pressed) method rather than the click or drag methods...both click and drag would prevent the ListBox from making a selection (and then sourcing the drag).   The original JSL is a work-around for something the ListBox doesn't currently do.

Without changes to the internal ListBox support, I don't think you'll find a completely satisfactory way to drag'n'drop between three or more listboxes.  You should be able to make multiple pairs of boxes, I think, using the original code; there is a cross-talk test (checking the other box's selection matches the dragged text) that will detect most abuse attempts.

If you don't need to remove the selected item from the source ListBox, then the problem is a lot simpler.  Use the dropped text to make a clone and don't even worry about finding the other box since you don't need to remove the item.

----

You can build some pretty cool drag'n'drop GUIs with the <<sourceBox and <<destBox messages.  One of the keys to using them is to make dragBegin supply a string for its return code.  That's the string that dropCommit will receive.  The scripting index for MouseBox setDropTrack has a 15-puzzle example with this JSL:

dragBegin = Function( {this, clickPt},

    {x, y} = this << getUserData;

    If( nextToBlank( x, y ),

       ((this << child) << child) << getText/* the message is the textbox content */

    , /* else */

       0 /* suppress the drag */

    );

);/* function to remove the character from the source cell, but only if the drop was successful */

The bold lines show two ways to use the return value: ignoring the drag attempt when the 15-puzzle piece can't be moved, or returning the letter if it can be moved.  The example has some other features too, like the userData that helps figure out which squares are adjacent.

Craige

Thanks Craig.  I'm starting to figure it out I think. 

Is the Key in Get/SetKey another way to store information or does it have some other use?

Craige_Hales

setKey is a keystroke handler similar to the click/track/drag handlers.  Key strokes .  GetUserData is what you want; use an associative array or list or matrix if you need more than one value.

Thank you. 

Article Labels
Article Tags
Contributors