Page 1 of 1

Drag and Drop (for "Cards")

Posted: Fri Jan 06, 2023 3:23 pm
by bembulak
Hi,

I've been playing around with Windows and Gadgets for a few days now. I'd like to drag and drop Gadgets around, but just can't bring anything to work.

My Idea was to have a window with some containers (FrameGadget or ContainerGadget?) and to move child-objects (canvas?) from on Frame to another.
Alternative would be to have windows and make them snappy according to their pos on the available space.

There is no drag and drop section in the help (current full version of SB, 2.40).

Is there no support for it, or is it so obvious and easy (and I don't see the solution for it)?

Thanks!

Re: Drag and Drop (for "Cards")

Posted: Fri Jan 06, 2023 3:28 pm
by useful

Re: Drag and Drop (for "Cards")

Posted: Fri Jan 06, 2023 4:20 pm
by bembulak
useful wrote: Fri Jan 06, 2023 3:28 pm Drag & Drop Yes! https://www.purebasic.com/documentation/
Drag & Drop No! https://www.spiderbasic.com/documentation/
Thank you.

Re: Drag and Drop (for "Cards")

Posted: Fri Jan 06, 2023 9:31 pm
by Peter
With some knowledge of JavaScript, D&D is relatively easy to implement:

Code: Select all

If OpenWindow(0, 0, 0, 800, 800, "", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  ContainerGadget(0, 200, 200, 400, 400, #PB_Container_Single) : CloseGadgetList()
EndIf

GID = GadgetID(0)

! $(v_gid.div).draggable();
See: https://jqueryui.com/draggable/ and https://jqueryui.com/droppable/

Re: Drag and Drop (for "Cards")

Posted: Sat Jan 07, 2023 5:22 pm
by Dirk Geppert
@Peter: good to know! That opens up new horizons! :D

Code: Select all

Procedure Events()
  
  SetGadgetText(1, "Dragged to: " + Str(GadgetX(1)) + ", " + Str(GadgetY(1)))
  
EndProcedure

If OpenWindow(0, 0, 0, 800, 800, "", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  ContainerGadget(0, 200, 200, 400, 400, #PB_Container_Single) : CloseGadgetList()
  SetGadgetColor(0, #PB_Gadget_BackColor, #Red)
  ButtonGadget(1, 200, 700, 300, 50, "Drag me around")
EndIf

GID = GadgetID(0)

! $(v_gid.div).draggable();

GID = GadgetID(1)

! $(v_gid.div).draggable();

BindGadgetEvent(1, @Events())

Re: Drag and Drop (for "Cards")

Posted: Wed Jan 11, 2023 5:30 pm
by bembulak
That's really interesting!

The frame gets the "dropped Gadget" as parameter, right? Is there a way to get from the jQuery 'ui' object back to the SB Gadget-ID?

Example:

Code: Select all

; https://jqueryui.com/draggable/
; 

Enumeration
  #window
  #frame
  #button
EndEnumeration

Procedure ButtonHandler()
  Debug "Button click event on gadget #" + EventGadget()
EndProcedure
  
OpenWindow(#window, 10, 10, 460, 480, "Click test", #PB_Window_SystemMenu)
FrameGadget(#frame, 5, 5, 450, 200, "Drop on me!")
FRM = GadgetID(#frame)
! $(v_frm.div).droppable({
! drop: function(event, ui) {
  Debug "You dropped something onto me!"
  ; How to Get the GadgetID from function param "ui"?
  ! console.log(ui);
  Debug("the Frame: " + Str(#frame))
  Debug("the Gadget: " + Str(EventGadget()))
!}
!});

ButtonGadget(#button, 10, 220, 180, 30, "Click me")
GID2 = GadgetID(#Button)
! $(v_gid2.div).draggable();  
! $(v_gid2.div).on( "dragstop", function( event, ui ) { console.log("I was dropped");console.log(ui)} );
BindGadgetEvent(#button, @ButtonHandler())

In the browser's Dev-Tools, I see that the 'ui' is something like:

Code: Select all

// a lot more lines and not expanded:
Object { draggable: {…}, helper: {…}, position: {…}, offset: {…} }
draggable: Object { 0: div.ui-draggable
, length: 1 }
helper: Object { 0: div.ui-draggable
, length: 1 }
offset: Object { top: 83.79998779296875, left: 115.80000305175781 }
position: Object { top: 44.99998474121094, left: 105 }
<prototype>: Object { … }
If I had multiple objects, how would I determine, which was dropped onto the Frame? Any ideas?

Re: Drag and Drop (for "Cards")

Posted: Wed Jan 11, 2023 6:26 pm
by Peter
For example, you can use callbacks to find out which target was dropped on:

Code: Select all

Enumeration
  #window
  #card1
  #card2
  #card3
  #target1
  #target2
EndEnumeration

Procedure DroppedOnTarget1Callback()
  MessageRequester("Dropped on #target1")
EndProcedure

Procedure DroppedOnTarget2Callback()
  MessageRequester("Dropped on #target2")
EndProcedure

Procedure MakeDraggable(Gadget)
  
  Protected GID = GadgetID(Gadget)
  ! $(v_gid.div).draggable();
  
EndProcedure

Procedure MakeDroppable(Gadget, Callback)
  
  Protected GID = GadgetID(Gadget)
  ! $(v_gid.div).droppable({
  !   drop: function( event, ui ) {
  !     v_callback();
  !   }
  ! });  
  
EndProcedure

Procedure SetCanvasBackgroundColor(CanvasGadget, Color)
  If GadgetType(CanvasGadget) <> #PB_GadgetType_Canvas : ProcedureReturn : EndIf
  If StartDrawing(CanvasOutput(CanvasGadget))
    Box(0, 0, GadgetWidth(CanvasGadget), GadgetHeight(CanvasGadget), Color)
    StopDrawing()
  EndIf
EndProcedure



OpenWindow(#window, #PB_Ignore, #PB_Ignore, 800, 600, "", #PB_Window_ScreenCentered)

; Targets

CanvasGadget(#target1, 300, 10, 200, 200, #PB_Canvas_Border)
MakeDroppable(#target1, @DroppedOnTarget1Callback())

CanvasGadget(#target2, 300, 300, 200, 200, #PB_Canvas_Border)
MakeDroppable(#target2, @DroppedOnTarget2Callback())

; Cards

CanvasGadget(#card1, 10, 10, 100, 150, #PB_Canvas_Border)
SetCanvasBackgroundColor(#card1, #Red)
MakeDraggable(#card1)

CanvasGadget(#card2, 15, 15, 100, 150, #PB_Canvas_Border)
SetCanvasBackgroundColor(#card2, #Blue)
MakeDraggable(#card2)

CanvasGadget(#card3, 20, 20, 100, 150, #PB_Canvas_Border)
SetCanvasBackgroundColor(#card3, #Green)
MakeDraggable(#card3)

Re: Drag and Drop (for "Cards")

Posted: Wed Jan 11, 2023 8:10 pm
by bembulak
Peter wrote: Wed Jan 11, 2023 6:26 pm For example, you can use callbacks to find out which target was dropped on:

Code: Select all

Enumeration
  #window
  #card1
  #card2
  #card3
  #target1
  #target2
EndEnumeration

Procedure DroppedOnTarget1Callback()
  MessageRequester("Dropped on #target1")
EndProcedure

Procedure DroppedOnTarget2Callback()
  MessageRequester("Dropped on #target2")
EndProcedure

Procedure MakeDraggable(Gadget)
  
  Protected GID = GadgetID(Gadget)
  ! $(v_gid.div).draggable();
  
EndProcedure

Procedure MakeDroppable(Gadget, Callback)
  
  Protected GID = GadgetID(Gadget)
  ! $(v_gid.div).droppable({
  !   drop: function( event, ui ) {
  !     v_callback();
  !   }
  ! });  
  
EndProcedure

Procedure SetCanvasBackgroundColor(CanvasGadget, Color)
  If GadgetType(CanvasGadget) <> #PB_GadgetType_Canvas : ProcedureReturn : EndIf
  If StartDrawing(CanvasOutput(CanvasGadget))
    Box(0, 0, GadgetWidth(CanvasGadget), GadgetHeight(CanvasGadget), Color)
    StopDrawing()
  EndIf
EndProcedure



OpenWindow(#window, #PB_Ignore, #PB_Ignore, 800, 600, "", #PB_Window_ScreenCentered)

; Targets

CanvasGadget(#target1, 300, 10, 200, 200, #PB_Canvas_Border)
MakeDroppable(#target1, @DroppedOnTarget1Callback())

CanvasGadget(#target2, 300, 300, 200, 200, #PB_Canvas_Border)
MakeDroppable(#target2, @DroppedOnTarget2Callback())

; Cards

CanvasGadget(#card1, 10, 10, 100, 150, #PB_Canvas_Border)
SetCanvasBackgroundColor(#card1, #Red)
MakeDraggable(#card1)

CanvasGadget(#card2, 15, 15, 100, 150, #PB_Canvas_Border)
SetCanvasBackgroundColor(#card2, #Blue)
MakeDraggable(#card2)

CanvasGadget(#card3, 20, 20, 100, 150, #PB_Canvas_Border)
SetCanvasBackgroundColor(#card3, #Green)
MakeDraggable(#card3)
Wow, that's fantastic! Thank you.

Your contributions to this community are priceless.

Re: Drag and Drop (for "Cards")

Posted: Wed Mar 06, 2024 9:04 pm
by munfraid
Yes, this is really awesome, thanks for this!
Unfortunately it just works with the mouse. On touch devices it's not working. Is there a way to make this possible?