Drag and Drop (for "Cards")

Just starting out? Need help? Post your questions and find answers here.
User avatar
bembulak
Posts: 95
Joined: Wed Feb 26, 2014 9:53 am

Drag and Drop (for "Cards")

Post 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!
Kind regards,

bembulak
User avatar
useful
Posts: 135
Joined: Tue Feb 25, 2014 1:15 pm

Re: Drag and Drop (for "Cards")

Post by useful »

2B or not 2B = FF
User avatar
bembulak
Posts: 95
Joined: Wed Feb 26, 2014 9:53 am

Re: Drag and Drop (for "Cards")

Post 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.
Kind regards,

bembulak
User avatar
Peter
Posts: 1197
Joined: Mon Feb 24, 2014 10:17 pm
Location: 127.0.0.1:9080
Contact:

Re: Drag and Drop (for "Cards")

Post 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/
Dirk Geppert
Posts: 332
Joined: Fri Sep 22, 2017 7:02 am

Re: Drag and Drop (for "Cards")

Post 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())
User avatar
bembulak
Posts: 95
Joined: Wed Feb 26, 2014 9:53 am

Re: Drag and Drop (for "Cards")

Post 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?
Kind regards,

bembulak
User avatar
Peter
Posts: 1197
Joined: Mon Feb 24, 2014 10:17 pm
Location: 127.0.0.1:9080
Contact:

Re: Drag and Drop (for "Cards")

Post 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)
User avatar
bembulak
Posts: 95
Joined: Wed Feb 26, 2014 9:53 am

Re: Drag and Drop (for "Cards")

Post 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.
Kind regards,

bembulak
munfraid
Posts: 135
Joined: Sat Mar 24, 2018 1:33 pm

Re: Drag and Drop (for "Cards")

Post 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?
Post Reply