Drag+Drop in a listicon

Just starting out? Need help? Post your questions and find answers here.
coffee
User
User
Posts: 77
Joined: Fri Oct 06, 2017 10:43 am

Drag+Drop in a listicon

Post by coffee »

hi,
i know that this might be a stupid question, but i am looking for an example/demo for dragging more than 1 line in a ListIconGadget from one place to another.
i like to select lets say 3 lines in a ListIconGadget and move it lets say to the top of the list and drop it there.
anybody some demo code?
thanks in advance
IdeasVacuum
Always Here
Always Here
Posts: 6425
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: Drag+Drop in a listicon

Post by IdeasVacuum »

IdeasVacuum
If it sounds simple, you have not grasped the complexity.
Marc56us
Addict
Addict
Posts: 1479
Joined: Sat Feb 08, 2014 3:26 pm

Re: Drag+Drop in a listicon

Post by Marc56us »

i know that this might be a stupid question, but i am looking for an example/demo for dragging more than 1 line in a ListIconGadget from one place to another.
i like to select lets say 3 lines in a ListIconGadget and move it lets say to the top of the list and drop it there.
:arrow: Principle: At the start of the 'drag', create a list with the elements selected by the user. At the arrival of the 'drop' add the elements one by one.

Code: Select all

; Drop multi selection from listicon to listicon
; in reply to https://www.purebasic.fr/english/viewtopic.php?f=13&t=75475&p=555737
; Marc56us - 2020/06/06

EnableExplicit

; ----------------------------------------------------------------------
Enumeration FormWindow
    #Window_0
EndEnumeration

Enumeration FormGadget
    #ListIcon_0
    #ListIcon_1
EndEnumeration


Procedure OpenWindow_0(x = 0, y = 0, width = 600, height = 400)
    OpenWindow(#Window_0, x, y, width, height, "", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
    ListIconGadget(#ListIcon_0, 10, 10, 285, 380, "Column 1", 100, #PB_ListIcon_MultiSelect | #PB_ListIcon_GridLines | #PB_ListIcon_FullRowSelect)
    AddGadgetItem(#ListIcon_0, -1, "AAA")
    AddGadgetItem(#ListIcon_0, -1, "BBB")
    AddGadgetItem(#ListIcon_0, -1, "CCC")
    AddGadgetItem(#ListIcon_0, -1, "DDD")
    AddGadgetItem(#ListIcon_0, -1, "EEE")
    AddGadgetItem(#ListIcon_0, -1, "FFF")
    AddGadgetItem(#ListIcon_0, -1, "GGG")
    AddGadgetItem(#ListIcon_0, -1, "HHH")
    ListIconGadget(#ListIcon_1, 305, 10, 285, 380, "Column 1", 100)
EndProcedure
; ----------------------------------------------------------------------

OpenWindow_0()
SetWindowTitle(#Window_0, "Select Elements with CTRL+Mouse then drop do right")
EnableGadgetDrop(#ListIcon_1, #PB_Drop_Private, #PB_Drag_Move, 1)
Define i
Global NewList Txt$()


Procedure Add_To_Right()
    ForEach Txt$()
        AddGadgetItem(#ListIcon_1, -1, Txt$())
    Next
EndProcedure


Repeat
    Select WaitWindowEvent()         
        Case #PB_Event_CloseWindow    
            End   
            
        Case #PB_Event_Gadget
            If EventGadget() = #ListIcon_0  
                Select EventType() 
                    Case #PB_EventType_DragStart
                        ; Create list with selected elements
                        For i = 0 To CountGadgetItems(#ListIcon_0)
                            If GetGadgetItemState(#ListIcon_0, i) = #PB_ListIcon_Selected
                                AddElement(Txt$()) : Txt$() = GetGadgetItemText(#ListIcon_0, i)
                            EndIf
                        Next
                        ; Drop 
                        DragPrivate(1, #PB_Drag_Move)
  
                EndSelect
            EndIf           
            
        Case #PB_Event_GadgetDrop   
            If EventGadget() = #ListIcon_1
                Add_To_Right()
            EndIf
    EndSelect
ForEver

End
This is a quick and dirty example. To be added: manage duplicates, reset the temporary list to zero, etc.
Enjoy.

:wink:

Edit: Sorry, I didn't understand (read too fast and mistranslated) that you wanted to move several items in the same gadget and not from one gadget to another.
Last edited by Marc56us on Sun Jun 07, 2020 8:20 am, edited 1 time in total.
JHPJHP
Addict
Addict
Posts: 2129
Joined: Sat Oct 09, 2010 3:47 am
Contact:

Drag+Drop in a listicon

Post by JHPJHP »

Hi coffee,

The following download included an example that allowed for multiple items to be selected and moved in a ListIconGadget; it has been updated with Drag & Drop.

Windows Services & Other Stuff\Other_Stuff\GadgetStuff\ListIconGadget\MoveMultipleItems.pb

NB*: Borrowed the DragCallBack Procedure from srod that can be found here.
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8433
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Re: Drag+Drop in a listicon

Post by netmaestro »

JHPJHP: Very glad to see your contrast back up where it belongs. Your contributions are much appreciated!
BERESHEIT
coffee
User
User
Posts: 77
Joined: Fri Oct 06, 2017 10:43 am

Re: Drag+Drop in a listicon

Post by coffee »

thanks JHPJHP and Marc56us.

that really helped.
davido
Addict
Addict
Posts: 1890
Joined: Fri Nov 09, 2012 11:04 pm
Location: Uttoxeter, UK

Re: Drag+Drop in a listicon

Post by davido »

@Marc56us,
I found your example very useful. Thank you.

Note: As I move multiple groups I needed to insert ClearList() after line 56.
DE AA EB
Marc56us
Addict
Addict
Posts: 1479
Joined: Sat Feb 08, 2014 3:26 pm

Re: Drag+Drop in a listicon

Post by Marc56us »

Thanks davido :wink: (I like to reinvent new wheels :mrgreen: )

@coffee
If even non-consecutive selected elements are to be placed consecutively at the top, then this simple solution is possible.
1. List selected elements
2. Create two lists (selected and unselected)
3. Empty the gadget
4. Fill in with list A and then list B.

Code: Select all

; Drop multi selection inside listicon
; in reply to https://www.purebasic.fr/english/viewtopic.php?f=13&t=75475&p=555737
; Marc56us - 2020/06/07

EnableExplicit

; ----------------------------------------------------------------------
Enumeration FormWindow
    #Window_0
EndEnumeration

Enumeration FormGadget
    #ListIcon_0
EndEnumeration


Procedure OpenWindow_0(x = 0, y = 0, width = 600, height = 400)
    OpenWindow(#Window_0, x, y, width, height, "", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
    ListIconGadget(#ListIcon_0, 10, 10, 285, 380, "Column 1", 100, #PB_ListIcon_MultiSelect | #PB_ListIcon_GridLines | #PB_ListIcon_FullRowSelect)
    AddGadgetItem(#ListIcon_0, -1, "AAA")
    AddGadgetItem(#ListIcon_0, -1, "BBB")
    AddGadgetItem(#ListIcon_0, -1, "CCC")
    AddGadgetItem(#ListIcon_0, -1, "DDD")
    AddGadgetItem(#ListIcon_0, -1, "EEE")
    AddGadgetItem(#ListIcon_0, -1, "FFF")
    AddGadgetItem(#ListIcon_0, -1, "GGG")
    AddGadgetItem(#ListIcon_0, -1, "HHH")
EndProcedure
; ----------------------------------------------------------------------

OpenWindow_0()
SetWindowTitle(#Window_0, "Select Elements with CTRL+Mouse then drop on top")
EnableGadgetDrop(#ListIcon_0, #PB_Drop_Private, #PB_Drag_Move, 1)
Define i
Global NewList List_A$()
Global NewList List_B$()


Procedure Add_To_Right()
    ClearGadgetItems(#ListIcon_0)
    ; Refill gadget with Selected then un selected
    ForEach List_A$()
        AddGadgetItem(#ListIcon_0, -1, List_A$())
    Next    
    ForEach List_B$()
        AddGadgetItem(#ListIcon_0, -1, List_B$())
    Next
EndProcedure


Repeat
    Select WaitWindowEvent()         
        Case #PB_Event_CloseWindow   
            End   
           
        Case #PB_Event_Gadget
            If EventGadget() = #ListIcon_0 
                Select EventType()
                    Case #PB_EventType_DragStart
                        ClearList(List_A$())
                        ClearList(List_B$())
                        ; Create 2 lists A: Selected B: not selected
                        For i = 0 To CountGadgetItems(#ListIcon_0)
                            If GetGadgetItemState(#ListIcon_0, i) = #PB_ListIcon_Selected
                                AddElement(List_A$()) : List_A$() = GetGadgetItemText(#ListIcon_0, i)
                            Else
                                AddElement(List_B$()) : List_B$() = GetGadgetItemText(#ListIcon_0, i)
                            EndIf
                        Next
                        ; Drop
                        DragPrivate(1, #PB_Drag_Move)
 
                EndSelect
            EndIf           
           
        Case #PB_Event_GadgetDrop   
            If EventGadget() = #ListIcon_0
                Add_To_Right()
            EndIf
    EndSelect
ForEver

End
This version doesn't care on which element the list is dropping, it always places on line 1

If you want the selected elements to start somewhere else than on the first line, you have to retrieve the target line of the drag and drop by GetGadgetState(#ListIcon_0) and then cut the list of unselected elements and place the first element (and next) of selected elements at this point.
(I don't know if I explain the idea well, especially since I don't speak English). :oops:

:wink:
JHPJHP
Addict
Addict
Posts: 2129
Joined: Sat Oct 09, 2010 3:47 am
Contact:

Re: Drag+Drop in a listicon

Post by JHPJHP »

Hi netmaestro,
JHPJHP: Very glad to see your contrast back up where it belongs. Your contributions are much appreciated!
Thank you for your kind words.

It's not forgotten that you and a few others were a great support for me when I first took up PureBasic.
Your continuing contributions still inspire a growing community.
startup
Enthusiast
Enthusiast
Posts: 105
Joined: Wed Feb 25, 2015 5:55 pm

Re: Drag+Drop in a listicon

Post by startup »

Thank you very much Marc56us for this example. Would it be asked to much, if you know, how to show some small bar at the place you are dragging to?
Marc56us
Addict
Addict
Posts: 1479
Joined: Sat Feb 08, 2014 3:26 pm

Re: Drag+Drop in a listicon

Post by Marc56us »

startup wrote:Thank you very much Marc56us for this example. Would it be asked to much, if you know, how to show some small bar at the place you are dragging to?
Thanks you startup,

I know it's possible with a cursor change API, but I don't know how to do it simply.
Search with the keywords: "purebasic change mouse cursor"

:wink:
User avatar
Shardik
Addict
Addict
Posts: 1989
Joined: Thu Apr 21, 2005 2:38 pm
Location: Germany

Re: Drag+Drop in a listicon

Post by Shardik »

startup wrote:Would it be asked to much, if you know, how to show some small bar at the place you are dragging to?
You may take a look into this example (only for Windows) which demonstrates how to drag and copy a single line inside a ListIconGadget to a new position marked by an insertion line. You still have to modify this example for dragging more than one line.
startup
Enthusiast
Enthusiast
Posts: 105
Joined: Wed Feb 25, 2015 5:55 pm

Re: Drag+Drop in a listicon

Post by startup »

Well thank you all for the help. Shardik's link contained the bar I wanted.
Thanks again.
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4663
Joined: Sun Apr 12, 2009 6:27 am

Re: Drag+Drop in a listicon

Post by RASHAD »

Hi coffee
ListIcon D&D with scroll up and down too

Code: Select all

Import "UxTheme.lib"
  SetWindowTheme(hwnd, classname.p-unicode, titlename)
EndImport

Structure LVINSERTMARK
  cbSize.l
  dwFlags.l
  iItem.l
  dwReserved.l
EndStructure

Procedure DragCallback(Action)
  Shared HeaderHeight
  Shared RowHeight
  Shared RowInsertionIndex

  Protected CursorPositon.POINT
  Protected InsertMark.LVINSERTMARK
  Protected Rectangle.RECT
  SendMessage_(GadgetID(0),#LVM_SETINSERTMARKCOLOR,0,$0000FF)
  
  InsertMark\cbSize = SizeOf(LVINSERTMARK)
  GetCursorPos_(CursorPositon)
  GetWindowRect_(GadgetID(0), Rectangle)

  If PtInRect_(Rectangle, CursorPositon \ x + (CursorPositon \ y) << 32)
    MapWindowPoints_(0, GadgetID(0), CursorPositon, 1)
    
    If CursorPositon\y < 2*RowHeight
      SendMessage_(GadgetID(0),#WM_VSCROLL,#SB_LINEUP, 0)
    ElseIf CursorPositon\y > (GadgetHeight(0)-2*RowHeight)
      SendMessage_(GadgetID(0),#WM_VSCROLL,#SB_LINEDOWN, 0)
    EndIf
    
    SendMessage_(GadgetID(0), #LVM_INSERTMARKHITTEST, @CursorPositon,
      @InsertMark)

    If SendMessage_(GadgetID(0), #LVM_SETINSERTMARK, 0, @InsertMark)
      RowInsertionIndex = InsertMark\iItem

      If (CursorPositon\y - HeaderHeight) % RowHeight > RowHeight * 0.5
        RowInsertionIndex + 1
      EndIf
    EndIf
    ProcedureReturn #True
  EndIf
EndProcedure

Procedure ListIconGadgetMove(Gad, iFrom, iTo)
  For i = 0 To CountGadgetItems(0)-1
    Text$ = Text$ + GetGadgetItemText(Gad, iFrom,i)+Chr(10)
  Next
  RemoveGadgetItem(Gad,iFrom)
  AddGadgetItem(Gad,iTo,Text$)
EndProcedure

  Procedure winCB(hWnd, uMsg, wParam, lParam)
  result = #PB_ProcessPureBasicEvents
  Select uMsg
    Case #WM_NOTIFY
      *nmhdr.NMHDR = lParam
      *lvCD.NMLVCUSTOMDRAW = lParam
      If *lvCD\nmcd\hdr\hwndFrom=GadgetID(0) And *lvCD\nmcd\hdr\code = #NM_CUSTOMDRAW   
        Select *lvCD\nmcd\dwDrawStage
          Case #CDDS_PREPAINT
            result = #CDRF_NOTIFYITEMDRAW
          Case #CDDS_ITEMPREPAINT
            result = #CDRF_DODEFAULT | #CDRF_NOTIFYPOSTPAINT
          Case #CDDS_ITEMPOSTPAINT
            item = *lvCD\nmcd\dwItemSpec
            If *lvCD\nmcd\uItemState & #CDIS_FOCUS
              iconRect.RECT\left = #LVIR_ICON
              SendMessage_(GadgetID(0), #LVM_GETITEMRECT, item, @iconRect)
              itemRect.RECT\left = #LVIR_BOUNDS
              SendMessage_(GadgetID(0), #LVM_GETITEMRECT, item, @itemRect)
              itemRect\left + iconRect\left
              DrawFocusRect_(*lvCD\nmcd\hdc, itemRect)
            EndIf
            result = #CDRF_DODEFAULT
        EndSelect
      EndIf
  EndSelect
  ProcedureReturn result
EndProcedure

LoadFont(0,"Tahoma",14)
OpenWindow(0, 0, 0, 800, 600, "Drag'n drop test", #PB_Window_MinimizeGadget|#PB_Window_ScreenCentered | #PB_Window_SizeGadget)
SetWindowCallback(@winCB())

ListIconGadget(0, 10, 10, 780, 580, "Test", 200 , #PB_ListIcon_GridLines | #PB_ListIcon_FullRowSelect|#PB_ListIcon_HeaderDragDrop)
AddGadgetColumn(0, 1, "Address", 200)
AddGadgetColumn(0, 2, "Address", 200)

For a=0 To 1000
  addtext$ = "Column 0  item # " + Str(a) + Chr(10) + "Column 1  item # " + Str(a) + Chr(10) + "Column 2  item # " + Str(a)
  AddGadgetItem(0,-1, addtext$)
Next

SetGadgetFont(0,FontID(0))
EnableGadgetDrop(0, #PB_Drop_Private, #PB_Drag_Move, 1)
SetDragCallback(@DragCallback())

GetClientRect_(SendMessage_(GadgetID(0), #LVM_GETHEADER, 0, 0), @Rectangle.RECT)
HeaderHeight = Rectangle\bottom - Rectangle\top

RowHeight = SendMessage_(GadgetID(0), #LVM_GETITEMSPACING, #True, 0) >> 16

DragItem = -1

Repeat
  Select WaitWindowEvent()
    Case #WM_MOUSELEAVE
      dragf = 1
      
    Case #PB_Event_SizeWindow
      ResizeGadget(0,#PB_Ignore,#PB_Ignore,WindowWidth(0)-20,WindowHeight(0)-20) 
         
    Case #PB_Event_Gadget
      Select EventGadget()
        Case 0
          Select EventType()
            Case #PB_EventType_DragStart
              ShowScrollBar_(GadgetID(0),#SB_BOTH	,0)
              SetWindowTheme(GadgetID(0), "" , "STATUS")
              DragItem = GetGadgetState(0)          
              DragPrivate(1, #PB_Drag_Move) 
          EndSelect
      EndSelect      
           
    Case #PB_Event_GadgetDrop
      If EventDropPrivate() = 1
        ShowScrollBar_(GadgetID(0),#SB_BOTH	,1)
        SetWindowTheme(GadgetID(0), "Listview" , 0)
        TargetItem = GetGadgetState(0)
        If DragItem >= 0
          ListIconGadgetMove(0, DragItem, TargetItem)
        EndIf
        SendMessage_(GadgetID(0),#LVM_SETINSERTMARKCOLOR,0, $FFFFFF)
        SetGadgetState(0,TargetItem)
      EndIf
     
    Case #PB_Event_CloseWindow
      Quit = 1
      
  EndSelect
Until Quit = 1

Egypt my love
coffee
User
User
Posts: 77
Joined: Fri Oct 06, 2017 10:43 am

Re: Drag+Drop in a listicon

Post by coffee »

hi RASHAD,

this is neat. Howto more than 1 row?
Post Reply