Drag and drop in list icon - Show visual indicator?

Windows specific forum
camille
User
User
Posts: 66
Joined: Tue Nov 19, 2019 12:52 pm

Drag and drop in list icon - Show visual indicator?

Post by camille »

Hi,

is there a way to show a visual indicator (like a line) when dragging and dropping inside a list icon gadget?

E.g. like in this short .gif animation (it's made in AutoHotkey)?

https://imgur.com/a/fxuIgmP

It's way easier to understand where the drop will happen (before or after a specific row) than with the current PB solution (the drag and drop library)...
IdeasVacuum
Always Here
Always Here
Posts: 6425
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: Drag and drop in list icon - Show visual indicator?

Post by IdeasVacuum »

Hi

I think you can do it in a loop: while drag-drop is activated, track mouse position, move line to mouse position (or to an offset of the position as required).

The "line" can be a 1 or 2 pixel high Borderless Window (Sticky).
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
User avatar
Shardik
Addict
Addict
Posts: 1989
Joined: Thu Apr 21, 2005 2:38 pm
Location: Germany

Re: Drag and drop in list icon - Show visual indicator?

Post by Shardik »

I have tested the following example successfully on Windows 7 SP1 x64 with PB 5.71 x86 and on Windows 10 Version 1809 with PB 5.46 x64 in ASCII and Unicode mode:

Code: Select all

EnableExplicit

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

Define HeaderHeight.I
Define Rectangle.RECT
Define Row.I
Define RowHeight.I
Define RowInsertionIndex.I

Procedure DragCallback(Action.I)
  Shared HeaderHeight.I
  Shared RowHeight.I
  Shared RowInsertionIndex.I

  Protected CursorPositon.POINT
  Protected InsertMark.LVINSERTMARK
  Protected Rectangle.RECT

  InsertMark\cbSize = SizeOf(LVINSERTMARK)
  GetCursorPos_(CursorPositon)
  GetWindowRect_(GadgetID(1), Rectangle)

  If PtInRect_(Rectangle, CursorPositon \ x + (CursorPositon \ y) << 32)
    MapWindowPoints_(0, GadgetID(1), CursorPositon, 1)

    ; ----- Display insertion line
    SendMessage_(GadgetID(1), #LVM_INSERTMARKHITTEST, @CursorPositon,
      @InsertMark)

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

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

    ProcedureReturn #True
  EndIf
EndProcedure

OpenWindow(0, 100, 100, 730, 118, "Drag row from left to right")

ListIconGadget(0, 10, 10, WindowWidth(0) / 2 - 15, WindowHeight(0) - 20,
  "Name", 100, #PB_ListIcon_GridLines | #PB_ListIcon_FullRowSelect)
AddGadgetColumn(0, 1, "Address", GadgetWidth(0) - GetGadgetItemAttribute(0, 0,
  #PB_ListIcon_ColumnWidth) - 4)
AddGadgetItem(0, -1, "Harry Rannit" + #LF$ +
  "12 Parliament Way, Battle Street, By the Bay")
AddGadgetItem(0, -1, "Ginger Brokeit" + #LF$ +
  "130 PureBasic Road, BigTown, CodeCity")
AddGadgetItem(0, -1, "Didi Foundit" + #LF$ +
  "321 Logo Drive, Mouse House, Downtown")

ListIconGadget(1, WindowWidth(0) / 2 + 5, 10, WindowWidth(0) / 2 - 15,
  WindowHeight(0) - 20,  "Name", 100,
  #PB_ListIcon_GridLines | #PB_ListIcon_FullRowSelect)
AddGadgetColumn(1, 1, "Address", GadgetWidth(0) - GetGadgetItemAttribute(0, 0,
  #PB_ListIcon_ColumnWidth) - 4)
EnableGadgetDrop(1, #PB_Drop_Text, #PB_Drag_Copy)
SetDragCallback(@DragCallback())

; ----- Get height of header row
GetClientRect_(SendMessage_(GadgetID(1), #LVM_GETHEADER, 0, 0), @Rectangle)
HeaderHeight = Rectangle\bottom - Rectangle\top

; ----- Get height of single row
RowHeight = SendMessage_(GadgetID(0), #LVM_GETITEMSPACING, #True, 0) >> 16

Repeat
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow
      Break
    Case #PB_Event_Gadget
      If EventGadget() = 0 And EventType() = #PB_EventType_DragStart
        Row = GetGadgetState(0)

        If Row >= 0
          DragText(GetGadgetItemText(0, Row, 0) + #LF$ +
            GetGadgetItemText(0, Row, 1), #PB_Drag_Copy)
        EndIf
      EndIf
    Case #PB_Event_GadgetDrop
      AddGadgetItem(1, RowInsertionIndex, EventDropText())
  EndSelect
ForEver
Update: I had to change cbSize and iItem in structure LVINSERTMARK from Integer to Long because tatanas reported that my example didn't work in Windows 7 SP1 x64 with PB 5.71 x64. And in Windows 10 I thought to have tested with PB 5.46 x64 but indeed I also had tested with the x86 compiler so the declaration error slipped through. Sorry for that!
Last edited by Shardik on Sun Jan 05, 2020 10:35 pm, edited 4 times in total.
camille
User
User
Posts: 66
Joined: Tue Nov 19, 2019 12:52 pm

Re: Drag and drop in list icon - Show visual indicator?

Post by camille »

@IdeasVacuum
Thanks for the idea!

@Shardik
Thanks a lot for the code! There is one minor thing that bothers me. Would it be possible
to disable the row highlighting while hovering over the destination list icon gadget so
that only the drag bar is visible (and not the changed background color of the rows)?
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4636
Joined: Sun Apr 12, 2009 6:27 am

Re: Drag and drop in list icon - Show visual indicator?

Post by RASHAD »

@Shardik
Very good one :)
Thanks for sharing and Happy new year

Code: Select all

EnableExplicit

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

Structure LVINSERTMARK
  cbSize.I
  dwFlags.L
  iItem.I
  dwReserved.L
EndStructure

Define HeaderHeight.I
Define Rectangle.RECT
Define Row.I
Define RowHeight.I
Define RowInsertionIndex.I

Procedure DragCallback(Action.I)
  Shared HeaderHeight.I
  Shared RowHeight.I
  Shared RowInsertionIndex.I

  Protected CursorPositon.POINT
  Protected InsertMark.LVINSERTMARK
  Protected Rectangle.RECT

  InsertMark\cbSize = SizeOf(LVINSERTMARK)
  GetCursorPos_(CursorPositon)
  GetWindowRect_(GadgetID(1), Rectangle)

  If PtInRect_(Rectangle, CursorPositon \ x + (CursorPositon \ y) << 32)
    MapWindowPoints_(0, GadgetID(1), CursorPositon, 1)

    ; ----- Display insertion line
    SendMessage_(GadgetID(1), #LVM_INSERTMARKHITTEST, @CursorPositon,
      @InsertMark)

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

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

    ProcedureReturn #True
  EndIf
EndProcedure

OpenWindow(0, 0, 0, 730, 500, "Drag row from left to right", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)

ListIconGadget(0, 10, 10, WindowWidth(0) / 2 - 15, WindowHeight(0) - 20,
  "Name", 100, #PB_ListIcon_GridLines | #PB_ListIcon_FullRowSelect)
AddGadgetColumn(0, 1, "Address", GadgetWidth(0) - GetGadgetItemAttribute(0, 0,
  #PB_ListIcon_ColumnWidth) - 4)
AddGadgetItem(0, -1, "Harry Rannit" + #LF$ +
  "12 Parliament Way, Battle Street, By the Bay")
AddGadgetItem(0, -1, "Ginger Brokeit" + #LF$ +
  "130 PureBasic Road, BigTown, CodeCity")
AddGadgetItem(0, -1, "Didi Foundit" + #LF$ +
  "321 Logo Drive, Mouse House, Downtown")

ListIconGadget(1, WindowWidth(0) / 2 + 5, 10, WindowWidth(0) / 2 - 15,
  WindowHeight(0) - 20,  "Name", 100,
  #PB_ListIcon_GridLines | #PB_ListIcon_FullRowSelect)
AddGadgetColumn(1, 1, "Address", GadgetWidth(0) - GetGadgetItemAttribute(0, 0,
  #PB_ListIcon_ColumnWidth) - 4)
SetWindowTheme(GadgetID(1), "explorer", 0)
EnableGadgetDrop(1, #PB_Drop_Text, #PB_Drag_Copy)
SetDragCallback(@DragCallback())

; ----- Get height of header row
GetClientRect_(SendMessage_(GadgetID(1), #LVM_GETHEADER, 0, 0), @Rectangle)
HeaderHeight = Rectangle\bottom - Rectangle\top

; ----- Get height of single row
RowHeight = SendMessage_(GadgetID(0), #LVM_GETITEMSPACING, #True, 0) >> 16
SendMessage_(GadgetID(1),#LVM_SETINSERTMARKCOLOR,0,$0000FF)
Repeat
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow
      Break
    Case #PB_Event_Gadget
      If EventGadget() = 0 And EventType() = #PB_EventType_DragStart
        Row = GetGadgetState(0)

        If Row >= 0
          DragText(GetGadgetItemText(0, Row, 0) + #LF$ +
            GetGadgetItemText(0, Row, 1), #PB_Drag_Copy)
        EndIf
      EndIf
    Case #PB_Event_GadgetDrop
      AddGadgetItem(1, RowInsertionIndex, EventDropText())
  EndSelect
ForEver
Egypt my love
BarryG
Addict
Addict
Posts: 3292
Joined: Thu Apr 18, 2019 8:17 am

Re: Drag and drop in list icon - Show visual indicator?

Post by BarryG »

Thank you, Shardik and Rashad. Very nice!
User avatar
C87
Enthusiast
Enthusiast
Posts: 176
Joined: Mon Jul 17, 2017 7:22 am
Location: Cotswolds England

Re: Drag and drop in list icon - Show visual indicator?

Post by C87 »

RASHAD's code had the lines :

Code: Select all

Import "UxTheme.lib"
  SetWindowTheme(hwnd, classname.p-unicode, titlename)
EndImport
I haven't come across the use of Libraries in Active Topics before this post, or maybe looked but didn't see! There are brief details on using a User23.lib in HELP, under a search for 'Library' and/or Import/EndImport functions.

In the \PureBasic\PureLibraries\Windows folder set are 85 .imp files and 107 .lib files
However, I am unable to see any details of using the rest of the .lib and .imp files and the parameters required in each.
Would someone be able to point me in the right direction?

Many thanks and all the best to everyone using PureB for the New Year.
If it's falling over......just remember the computer is never wrong!
User avatar
Shardik
Addict
Addict
Posts: 1989
Joined: Thu Apr 21, 2005 2:38 pm
Location: Germany

Re: Drag and drop in list icon - Show visual indicator?

Post by Shardik »

Unfortunately RASHAD's clever extention of my example still displays a light blue highlighting of the target item as camille and tatanas reported in this thread. In that thread I presented this example eliminating the highlighting at all and a second example for drag 'n drop inside a single ListIconGadget also without highlighting.
camille
User
User
Posts: 66
Joined: Tue Nov 19, 2019 12:52 pm

Re: Drag and drop in list icon - Show visual indicator?

Post by camille »

In any case, thanks a lot for your support, RASHAD! :D
Post Reply