ListIcon+Column AutoResize,Edit,Group,Sort Arrow,HeaderClick

Share your advanced PureBasic knowledge/code with the community.
User avatar
eddy
Addict
Addict
Posts: 1479
Joined: Mon May 26, 2003 3:07 pm
Location: Nantes

Post by eddy »

updated
- ADDED : edit function

EXAMPLE 3 - edit listicon items

Code: Select all

; ********************
; EXAMPLE @ eddy
; ********************

Procedure My_ListIcon_SortFunction(ID, Column, SortAsc, itemIndex1, itemIndex2, *GadgetItemData1, *GadgetItemData2)
   Protected result
   Protected A$=GetGadgetItemText(ID, itemIndex1, Column)
   Protected B$=GetGadgetItemText(ID, itemIndex2, Column)
   
   If A$=B$
      result=0
   ElseIf A$>B$
      result=1
   Else
      result=-1
   EndIf
   If Not SortAsc
      result=-result
   EndIf
   ProcedureReturn result
EndProcedure
Procedure My_ListIcon_EditFunction(ID, Position, Column, EditorID, EditorState)
   Select EditorState
      Case #ListIconEditor_BeforeEdit
         If Column>0
            ProcedureReturn #ListIconEditor_BeginEdit
         EndIf
      Case #ListIconEditor_CancelEdit
         If GetGadgetText(EditorID)=""
            ProcedureReturn #ListIconEditor_CancelChanges
         Else
            ProcedureReturn #ListIconEditor_ApplyChanges
         EndIf
   EndSelect
EndProcedure

Enumeration
   #Win
   #Status
   #Button1
   #Button2
   #List2
EndEnumeration
Global w=640
Global h=480
OpenWindow(#Win, 0, 0, w, h, "Sorting / Dragging / Autosizing ... columns", #PB_Window_SystemMenu | #PB_Window_WindowCentered | #PB_Window_SizeGadget)
SmartWindowRefresh(#Win, 1)
CreateStatusBar(#Status, WindowID(#win))
StatusBarText(#Status, 0, "Default sorting function (single column)")
ButtonGadget(#Button1, 4, 4, w-8, 30, "Column1 : enable sorting / Column2 : reset sorting / Column3 : disable sorting")
ButtonGadget(#Button2, 4, 40, w-8, 30, "Toggle GroupView ")

ListIconGadgetPlus(#List2, 4, 84, w-8, h-130, "fixed", 80, #PB_ListIcon_CheckBoxes | #PB_ListIcon_FullRowSelect)
AddGadgetColumn(#List2, 1, "C1: autosize", 90)
AddGadgetColumn(#List2, 2, "C2: autosize + sort", 180)
AddGadgetColumn(#List2, 300, "C3: autosize + sort", #PB_Ignore)
SetListIconGroupView(#list2, 1)

;********************
;add listicon item and group
;********************
Global ItemPos, ItemGroup, ItemColumns.s, ItemData.i
Global ItemIcon=CreateImage(0, 32, 32)
StartDrawing(ImageOutput(0))
   FillArea(0, 0, #White, #White)
   Box(1, 1, 30, 30, #Red)
StopDrawing()
For ItemPos=0 To 10
   ItemData=1000*(#True And ItemPos=4)
   ItemColumns=Str(ItemPos)
   ItemColumns+#LF$+RSet(Str(Random(50)*7), 4, "0")+" > here is my very long text ..."
   ItemColumns+#LF$+"an other long text ..."+Str(ElapsedMilliseconds())
   ItemColumns+#LF$+"GetGadgetItemData = "+Str(ItemData)
   
   Select ItemPos
      Case 0
         ItemGroup=#ListIconGroup_Position+0
         AddGadgetItem(#List2, ItemGroup, "GROUP 0")
      Case 3
         ItemGroup=#ListIconGroup_Position+1
         AddGadgetItem(#List2, ItemGroup, "GROUP 1")
      Case 7
         ItemGroup=#ListIconGroup_Position+2
         AddGadgetItem(#List2, ItemGroup, "GROUP 2")
   EndSelect
   AddGadgetItem(#List2, ItemPos, ItemColumns, ItemIcon, ItemGroup)
   SetGadgetItemData(#List2, ItemPos, ItemData)
   SetGadgetItemColor(#List2, ItemPos, #PB_Gadget_FrontColor, #Blue, 1)
   Delay(20)
Next

;********************
;attach items to group
;********************
AddGadgetItem(#List2, -100, "")
AddGadgetItem(#List2, 11, ""+#LF$+"item in hidden group"+#LF$+"item in hidden group"+#LF$+"item in hidden group", ItemIcon)
AddGadgetItem(#List2, 12, ""+#LF$+"XX"+#LF$+"item in hidden group"+#LF$+"XX", ItemIcon)

Dim AttachItems_To_Group(1)
AttachItems_To_Group(0)=11
AttachItems_To_Group(1)=12
SetListIconGroupItems(#List2, -100, AttachItems_To_Group())

;********************
;get / set item text
;********************
SetGadgetItemText(#List2, -100, "GROUP IS RENAMED...")
Debug "item= "+GetGadgetItemText(#List2, 10, 0)
Debug "item= "+GetGadgetItemText(#List2, 10, 1)
Debug "item= "+GetGadgetItemText(#List2, -100)

;********************
;change header & sorting
;********************
SetListIconHeader(#List2, 0, #ListIconHeader_NoDrag | #ListIconHeader_FixedSize)
SetListIconHeader(#List2, 1, #ListIconHeader_AutoSize)
SetListIconHeader(#List2, 2, #ListIconHeader_AutoSize | #ListIconHeader_Sort_Up)
SetListIconHeader(#List2, 3, #ListIconHeader_AutoSize | #ListIconHeader_Sort)

;********************
;change editor parameters
;********************
SetListIconEditFunction(#List2, @My_ListIcon_EditFunction())

Repeat
   Global e=WaitWindowEvent()
   Global g=EventGadget()
   Global t=EventType()
   
   If e=#PB_Event_SizeWindow
      ResizeGadget(#list2, #PB_Ignore, #PB_Ignore, WindowWidth(#Win)-8, WindowHeight(#Win)-120)
   EndIf
   If e=#PB_Event_Gadget And g=#Button1
      SetListIconHeader(#List2, 1, #ListIconHeader_Sort_Down)
      SetListIconHeader(#List2, 2, #ListIconHeader_Sort_None)
      SetListIconHeader(#List2, 3, #ListIconHeader_Sort_Disabled)
      SetGadgetItemText(#List2, -1, "C1: autosize + sort", 1)
      SetGadgetItemText(#List2, -1, "C3: autosize", 3)
      SetGadgetItemAttribute(#List2, -1, #PB_ListIcon_ColumnWidth, #PB_Ignore, 1)
      SetGadgetItemAttribute(#List2, -1, #PB_ListIcon_ColumnWidth, #PB_Ignore, #PB_Ignore)
   EndIf
   If e=#PB_Event_Gadget And g=#Button2
      SetListIconGroupView(#List2, 1-GetListIconGroupView(#List2))
   EndIf
   If e=#PB_Event_Gadget And g=#List2 And t=#PB_EventType_LeftClick
      Global s=GetGadgetState(g)
      If s>-1
         Debug GetGadgetItemText(g, s, 0)+" > ItemData= "+Str(GetGadgetItemData(g, s))
         
         Global Order
         Global Dim ColumnsOrder(0)
         If GetListIconColumnOrder(g, ColumnsOrder())
            For Order=0 To ArraySize(ColumnsOrder())-1
               Debug "Order="+Str(Order)+" Column="+Str(ColumnsOrder(Order))
            Next
            Debug ""
         EndIf
      EndIf
   EndIf
   If e=#PB_Event_Gadget And g=#List2
      If t=#PB_EventType_LeftDoubleClick
         ;EditListIcon(#List2)
      EndIf
      If t=#PB_EventType_LeftClick
         ;          If EditListIcon(#List2, #ListIconEditor_GetChanges)=""
         ;             EditListIcon(#List2, #ListIconEditor_CancelChanges)
         ;          Else
         ;             EditListIcon(#List2, #ListIconEditor_ApplyChanges)
         ;          EndIf
      EndIf
   EndIf
Until e=#PB_Event_CloseWindow
Imagewin10 x64 5.72 | IDE | PB plugin | Tools | Sprite | JSON | visual tool
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

Seem to be a lot of problems with the cell editing Eddy. It crashes here quite often (Vista 32). If you double click cell after cell I also find string gadgets being left behind etc. I encountered all this with my early work on EsGRID and know what a pain it can be!
I may look like a mule, but I'm not a complete ass.
AAT
Enthusiast
Enthusiast
Posts: 259
Joined: Sun Jun 15, 2008 3:13 am
Location: Russia

Post by AAT »

srod wrote:Seem to be a lot of problems with the cell editing Eddy. It crashes here quite often (Vista 32).
There is no crashes or other problems in XP.
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

AAT wrote:
srod wrote:Seem to be a lot of problems with the cell editing Eddy. It crashes here quite often (Vista 32).
There is no crashes or other problems in XP.
Confirmed - no problem on XP.

Right, I made a mistake when running on Vista; the crashing was my fault! :oops: Sorry about that!

What does happen on Vista, however, is that many double-clicks are not being registered and thus cells are not being edited. Yes it is very difficult to edit a cell; very intermittent!

**EDIT : seems that the #ListIconEditor_BeginEdit style is not being picked up in many cases here on Vista.
I may look like a mule, but I'm not a complete ass.
User avatar
Michael Vogel
Addict
Addict
Posts: 2808
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

Re: ListIcon+Column AutoResize,Edit,Group,Sort Arrow,HeaderC

Post by Michael Vogel »

Found this brilliant code example when searching for a sort of ListIcon gadgets which is fast enough for longer lists and keeps also the color information of each entry.

Just changed the Text$ in the parameter line to @Text$ to get it working on PB4.5, some more optimization may have to be done:

• some compiler warnings ("...can cause issues...") are still present...
• one code line forces to enable the unicode option before compiling

Here is the modified code including all examples:

Code: Select all

; Define
    CompilerIf Defined(GADGET_VT, #PB_Structure)=#False
        Structure GADGET_VT  ; PB_GadgetVT
            GadgetType.i      ; gadget type (used by GadgetType command)
            SizeOf.i          ; Size of structure

            *GadgetCallback
            *FreeGadget
            *GetGadgetState
            *SetGadgetState
            *GetGadgetText
            *SetGadgetText
            *AddGadgetItem2
            *AddGadgetItem3
            *RemoveGadgetItem
            *ClearGadgetItemList
            *ResizeGadget
            *CountGadgetItems
            *GetGadgetItemState
            *SetGadgetItemState
            *GetGadgetItemText
            *SetGadgetItemText
            *OpenGadgetList2
            *GadgetX
            *GadgetY
            *GadgetWidth
            *GadgetHeight
            *HideGadget
            *AddGadgetColumn
            *RemoveGadgetColumn
            *GetGadgetAttribute
            *SetGadgetAttribute
            *GetGadgetItemAttribute2
            *SetGadgetItemAttribute2
            *SetGadgetColor
            *GetGadgetColor
            *SetGadgetItemColor2
            *GetGadgetItemColor2
            *SetGadgetItemData
            *GetGadgetItemData
        EndStructure
    CompilerEndIf
    CompilerIf Defined(GADGET, #PB_Structure)=#False
        Structure GADGET     ; PB_Gadget
            hwnd.i            ; gadget window handle
            *VT.GADGET_VT     ; gadget commands
            *GadgetData       ; gadget data           (used by SetGadgetData command)
            *OldCallback      ; window CALLBACK       (used by purebasic CALLBACK)
            Dates.i[4]        ; .....
        EndStructure
    CompilerEndIf
    CompilerIf Defined(HDN_BEGINDRAG, #PB_Constant)=#False
        Enumeration
            #HDN_ENDDRAG=#HDN_FIRST-11
            #HDN_BEGINDRAG
            #HDN_GETDISPINFO

            #HDF_SORTUP=$400
            #HDF_SORTDOWN=$200
        EndEnumeration
    CompilerEndIf
    CompilerIf Defined(PB_ListIcon_Item, #PB_Structure)=#False
        Structure PB_ListIcon_Item ; undocumented PB stuff
            *UserData
        EndStructure
    CompilerEndIf
; EndDefine
; Define Enum
    Enumeration ;ListIconPlus Flags
        ;header flags
        #ListIconHeader_Normal=0
        #ListIconHeader_AutoSize=1
        #ListIconHeader_FixedSize=2
        #ListIconHeader_NoDrag=4
        #ListIconHeader_Sort=8

        ;header sort commands
        #ListIconHeader_Sort_Up=#ListIconHeader_Sort | 16     ;sorting enabled & arrow up
        #ListIconHeader_Sort_Down=#ListIconHeader_Sort | 32   ;sorting enabled & arrow down
        #ListIconHeader_Sort_None=#ListIconHeader_Sort | 64   ;sorting enabled & hidden arrow
        #ListIconHeader_Sort_Disabled=128                     ;sorting disabled

        ;group flags
        #ListIconGroup_Position=-1<<(SizeOf(Integer)*8-1)
        #ListIconGroup_TextLengthMax=100

        ;editor commands
        #ListIconEditor_GetChanges=-100

        #ListIconEditor_BeforeEdit
        #ListIconEditor_BeginEdit
        #ListIconEditor_CancelEdit
        #ListIconEditor_CancelChanges
        #ListIconEditor_ApplyChanges
    EndEnumeration
    Structure LGP_PARAMS
        ID.i                 ;stored original gadget ID
        CB.i                 ;stored original gadget callback
        *VT.GADGET_VT        ;stored original gadget commands

        header.i             ;listicon header
        *headerFlags.integer ;listicon header flags

        columns.i            ;columns count
        columnsRedraw.b      ;columns redrawing (e.g: add new column, resize column )
        columnToFill.i       ;column to fill (last AutoSize column)

        *SortFunction        ;sort function
        SortSingleColumn.b   ;sort single column (multi-column sorting if #FALSE)

        *EditFunction        ;edit function
        *EditorCB            ;text editor callback
        Editor.i             ;text editor
        EditorCol.i          ;text editor column
        EditorPos.i          ;text editor position
    EndStructure
    Structure LGP_SORTING
        ID.i
        SortAsc.b ;sort mode (ascending order / descending order)
        Column.i ;sort column
        *SortFunction ;sort function
    EndStructure
    Structure LGP_ITEM
        index.i ;item index (for sorting)
        *olddata ;stored UserData (will be restored at the end of sorting)
    EndStructure
; EndDefine
Prototype.s LGP_GetGadgetItemText(*gadget.GADGET, Position, Column, *unknown)
ProcedureDLL.s LGP_GetGadgetItemText(*gadget.GADGET, Position, Column, *unknown)
    Protected *params.LGP_PARAMS=GetProp_(*gadget\hwnd, "GadgetInfo")

    If *params
        With *params
            Protected GroupID

            If Position<-1
                GroupID=Position

                Protected LVGROUP.LVGROUP
                LVGROUP\cbSize=SizeOf(LVGROUP)
                LVGROUP\mask=#LVGF_GROUPID | #LVGF_HEADER
                LVGROUP\iGroupId=GroupID
                SendMessage_(*gadget\hwnd, #LVM_GETGROUPINFO, GroupID, @LVGROUP)
                Protected text$=PeekS(LVGROUP\pszHeader,1000,#PB_Unicode)

                ProcedureReturn text$
            Else
                Protected GetItemText.LGP_GetGadgetItemText=\VT\GetGadgetItemText
                ProcedureReturn GetItemText(*gadget.GADGET, Position, Column, *unknown)
            EndIf
        EndWith
    EndIf
EndProcedure
Procedure LGP_AddGadgetColumn(*gadget.GADGET, Position, Title$, Width)
    Protected *params.LGP_PARAMS=GetProp_(*gadget\hwnd, "GadgetInfo")

    If *params
        With *params
            Protected WidthAUTO=0
            If Width=#PB_Ignore
                Width=100
                WidthAUTO=1
            EndIf

            \columnsRedraw=1
            CallFunctionFast(\VT\AddGadgetColumn,*gadget, Position,@Title$,Width)
            \columnsRedraw=0

            If WidthAUTO
                SetGadgetItemAttribute(\ID, 0, #PB_ListIcon_ColumnWidth, #PB_Ignore, #PB_Ignore)
            EndIf
        EndWith
    EndIf
EndProcedure
Procedure LGP_AddGadgetItem(*gadget.GADGET, Position, Text$, ImageID=0, Flags=0)
    Protected *params.LGP_PARAMS=GetProp_(*gadget\hwnd, "GadgetInfo")

    If *params
        With *params
            Protected GroupID

            If Position<-1
                GroupID=Position

                Text$=LSet(Text$, #ListIconGroup_TextLengthMax)
                Protected *Text=AllocateMemory(StringByteLength(Text$, #PB_Unicode)+2)
                PokeS(*Text, Text$, MemorySize(*Text), #PB_Unicode)

                Protected LVGROUP.LVGROUP
                LVGROUP\cbSize=SizeOf(LVGROUP)
                LVGROUP\mask=#LVGF_GROUPID | #LVGF_ALIGN | #LVGF_HEADER | #LVGF_STATE
                LVGROUP\uAlign=#LVGA_HEADER_LEFT
                LVGROUP\iGroupId=GroupID
                LVGROUP\pszHeader=*Text
                LVGROUP\cchHeader=MemorySize(*Text)
                ;LVGROUP\state=2;8
                ;LVGROUP\statemask=LVGROUP\state

                SendMessage_(*gadget\hwnd, #LVM_INSERTGROUP, -1, @LVGROUP)

                FreeMemory(*Text)
            Else
                GroupID=Flags
                CallFunctionFast(\VT\AddGadgetItem2, *gadget, Position,@Text$, ImageID)

                If Position=-1
                    Position=CountGadgetItems(\ID)-1
                EndIf

                Protected LVITEM.LVITEM
                LVITEM\mask=#LVIF_GROUPID | #LVIF_STATE
                LVITEM\iItem=Position
                LVITEM\iSubItem=0
                If SendMessage_(*gadget\hwnd, #LVM_GETITEM, 0, @LVITEM)
                    LVITEM\iGroupID=GroupID
                    SendMessage_(*gadget\hwnd, #LVM_SETITEM, 0, @LVITEM)
                EndIf
            EndIf
        EndWith
    EndIf
EndProcedure
Procedure LGP_RemoveGadgetItem(*gadget.GADGET, Position)
    Protected *params.LGP_PARAMS=GetProp_(*gadget\hwnd, "GadgetInfo")

    If *params
        With *params
            Protected GroupID

            If Position<-1
                GroupID=Position

                SendMessage_(*gadget\hwnd, #LVM_REMOVEGROUP, GroupID, 0)
            Else
                CallFunctionFast(\VT\RemoveGadgetItem, *gadget, Position)
            EndIf
        EndWith
    EndIf
EndProcedure
Procedure LGP_SetGadgetItemText(*gadget.GADGET, Position, Text$, Column)
    Protected *params.LGP_PARAMS=GetProp_(*gadget\hwnd, "GadgetInfo")

    If *params
        With *params
            Protected GroupID

            If Position<-1
                GroupID=Position

                Protected LVGROUP.LVGROUP
                LVGROUP\cbSize=SizeOf(LVGROUP)
                LVGROUP\mask=#LVGF_HEADER | #LVGF_GROUPID
                LVGROUP\iGroupId=GroupID
                SendMessage_(*gadget\hwnd, #LVM_GETGROUPINFO, GroupID, @LVGROUP)

                Text$=LSet(Text$, #ListIconGroup_TextLengthMax)
                Protected *Text=LVGROUP\pszHeader
                Protected lg=StringByteLength(Text$, #PB_Unicode)+2
                PokeS(*Text, Text$, lg, #PB_Unicode)
            Else
                CallFunctionFast(\VT\SetGadgetItemText, *gadget, Position,@Text$, Column)
            EndIf
        EndWith
    EndIf
EndProcedure
Procedure LGP_SetGadgetItemAttribute(*gadget.GADGET, Item, Attribute, Value, Column=0)
    Protected *params.LGP_PARAMS=GetProp_(*gadget\hwnd, "GadgetInfo")

    If *params
        With *params

            If Attribute=#PB_ListIcon_ColumnWidth And Value=#PB_Ignore And Column=#PB_Ignore
                ;{/// RESIZE COLUMN : AUTOFILL

                    ;column to fill (last column if none)
                    Column=\columnToFill
                    If Column=-1 : Column=\columns-1 : EndIf

                    ;column width calculation
                    Protected col
                    Value=GadgetWidth(\ID)-5
                    For col=0 To \columns-1
                        If col=Column : Continue : EndIf
                        Value-GetGadgetItemAttribute(\ID, -1, #PB_ListIcon_ColumnWidth, col)
                    Next
                    If GetWindowLongPtr_(GadgetID(\ID), #GWL_STYLE) & #WS_VSCROLL
                        Value-GetSystemMetrics_(#SM_CXVSCROLL)
                    EndIf

                    ;column width updating
                    \columnsRedraw=1
                    SetGadgetItemAttribute(\ID, -1, #PB_ListIcon_ColumnWidth, Value, Column)
                    \columnsRedraw=0

                    ;fix scrollbar display
                    SendMessage_(*gadget\hwnd, #LVM_SCROLL, 0, 0)

                ;}
            ElseIf Attribute=#PB_ListIcon_ColumnWidth And Value=#PB_Ignore And (Column>=0 And Column<\columns)
                ;{/// RESIZE COLUMN : AUTOSIZE
                    SetGadgetItemAttribute(\ID, -1, #PB_ListIcon_ColumnWidth, #LVSCW_AUTOSIZE, column)
                ;}
            Else
                ;{/// RESIZE COLUMN : WIDTH
                    CallFunctionFast(\VT\SetGadgetItemAttribute2, *gadget, Item, Attribute, Value, Column)
                ;}
            EndIf
        EndWith
    EndIf
EndProcedure
Procedure LGP_SortDefault(ID, Column, SortAsc, itemIndex1, itemIndex2, *GadgetItemData1, *GadgetItemData2)
    Protected result
    Protected A$=GetGadgetItemText(ID, itemIndex1, Column)
    Protected B$=GetGadgetItemText(ID, itemIndex2, Column)
    ;not used - *GadgetItemData1
    ;not used - *GadgetItemData2

    If A$=B$
        result=0
    ElseIf A$>B$
        result=1
    Else
        result=-1
    EndIf
    If Not SortAsc
        result=-result
    EndIf
    ProcedureReturn result
EndProcedure
Procedure LGP_SortList(*item1.PB_ListIcon_Item, *item2.PB_ListIcon_Item, *LGP_SORTING.LGP_SORTING)
    Protected *LGP_ITEM1.LGP_ITEM=*item1\UserData
    Protected *LGP_ITEM2.LGP_ITEM=*item2\UserData

    With *LGP_SORTING
        ProcedureReturn CallFunctionFast(\SortFunction, \ID, \Column, \SortAsc, *LGP_ITEM1\index, *LGP_ITEM2\index, *LGP_ITEM1\olddata, *LGP_ITEM2\olddata)
    EndWith
EndProcedure
Procedure LGP_EditorCB(EditorWindow, Message, wParam, lParam)
    Protected Window=GetParent_(EditorWindow)
    Protected *params.LGP_PARAMS=GetProp_(Window, "GadgetInfo")

    If *params
        With *params
            Protected EditorPos
            Protected EditorCol
            Protected EditorState

            Select Message
            Case #WM_KEYDOWN
                ;{/// EDITOR : CANCEL (by keypress)
                    If wParam=#VK_RETURN Or wParam=#VK_ESCAPE
                        EditorState=CallFunctionFast(\EditFunction, \ID, \EditorPos, \EditorCol, \Editor, #ListIconEditor_CancelEdit)
                        SendMessage_(Window, #LVM_EDITLABEL, EditorState, 0)
                        ProcedureReturn #True
                    EndIf
                ;}
            Case #WM_KILLFOCUS
                ;{/// EDITOR : CANCEL (by focus)
                    If \EditFunction And IsGadget(\Editor)
                        EditorState=CallFunctionFast(\EditFunction, \ID, \EditorPos, \EditorCol, \Editor, #ListIconEditor_CancelEdit)
                        SendMessage_(Window, #LVM_EDITLABEL, EditorState, 0)
                        ProcedureReturn #False
                    EndIf
                ;}
            EndSelect

            ProcedureReturn CallWindowProc_(\EditorCB, EditorWindow, Message, wParam, lParam)
        EndWith
    EndIf
EndProcedure
Procedure LGP_CB(Window, Message, wParam, lParam)
    Protected *params.LGP_PARAMS=GetProp_(Window, "GadgetInfo")

    If *params
        With *params

            Select Message
                ;Case #WM_ERASEBKGND
                ;Case #WM_PAINT
                ;Case #LVM_SETCOLUMN, #LVM_SETCOLUMNA, #LVM_SETCOLUMNW
                ;Case #LVM_SETCOLUMNWIDTH, #LVM_SETCOLUMNWIDTHA, #LVM_SETCOLUMNWIDTHW

            Case #WM_NCDESTROY
                ;{/// FREE GADGET
                    If \headerFlags=0
                        FreeMemory(\headerFlags)
                    EndIf
                ;}

            Case #LVM_GETHEADER
                ;{/// COLUMN : PARAMETERS (\columnToFill)
                    Protected headerOrder
                    Protected Dim headerOrder(\columns)
                    SendMessage_(\header, #HDM_GETORDERARRAY, \Columns, @headerOrder())

                    \columnToFill=-1
                    For headerOrder=\Columns-1 To 0 Step -1
                        Protected *thisHeaderFlags.Integer=\headerFlags+headerOrder(headerOrder)*SizeOf(Integer)
                        If (*thisHeaderFlags\i & #ListIconHeader_AutoSize)
                            \columnToFill=headerOrder(headerOrder)
                            Break
                        EndIf
                    Next
                ;}

            Case #LVM_INSERTCOLUMN, #LVM_INSERTCOLUMNA, #LVM_INSERTCOLUMNW, #LVM_DELETECOLUMN
                ;{/// COLUMN : ADD,REMOVE (\HeaderFlags, \Columns)
                    Protected *mem_s.Integer
                    Protected *mem_d.Integer
                    Protected mem_lg
                    Select Message
                    Case #LVM_DELETECOLUMN
                        Protected ColumnRemoved=wParam
                        If ColumnRemoved>=0 And ColumnRemoved<\Columns
                            ;delete HeaderFlags entry
                            If ColumnRemoved<\Columns-1
                                *mem_s=\headerFlags+(ColumnRemoved+1)*SizeOf(Integer)
                                *mem_d=\headerFlags+(ColumnRemoved+0)*SizeOf(Integer)
                                mem_lg=(\Columns-ColumnRemoved-1)*SizeOf(Integer)
                                MoveMemory(*mem_s, *mem_d, mem_lg)
                            EndIf

                            ;resize Columns and HeaderFlags
                            \columns-1
                            If \columns=0
                                FreeMemory(\headerFlags)
                                \headerFlags=0
                            Else
                                ReAllocateMemory(\headerFlags, \columns*SizeOf(Integer))
                            EndIf
                        EndIf
                    Default
                        Protected ColumnAdded=wParam
                        If ColumnAdded>=0
                            ;resize Columns and HeaderFlags
                            \columns+1
                            If \columns=1
                                \headerFlags=AllocateMemory(\columns*SizeOf(Integer))
                            Else
                                ReAllocateMemory(\headerFlags, \columns*SizeOf(Integer))
                            EndIf

                            ;insert HeaderFlags entry
                            If ColumnAdded<\Columns-1
                                *mem_s=\headerFlags+(ColumnAdded+0)*SizeOf(Integer)
                                *mem_d=\headerFlags+(ColumnAdded+1)*SizeOf(Integer)
                                mem_lg=(\Columns-ColumnAdded-1)*SizeOf(Integer)
                                MoveMemory(*mem_s, *mem_d, mem_lg)
                                *mem_s\i=0
                            EndIf
                        EndIf
                    EndSelect
                ;}

            Case #LVM_SORTITEMS
                ;{/// COLUMN : SORTING
                    If lparam=#Null

                        ;change item datas
                        Protected itemCount=CountGadgetItems(\ID)-1
                        Protected index
                        For index=0 To itemCount
                            Protected *LGP_ITEM.LGP_ITEM=AllocateMemory(SizeOf(LGP_ITEM))
                            *LGP_ITEM\olddata=GetGadgetItemData(\ID, index)
                            *LGP_ITEM\index=index
                            SetGadgetItemData(\ID, index, *LGP_ITEM)
                        Next

                        ;sort column
                        SendMessage_(Window, #LVM_SORTITEMS, wParam, @LGP_SortList())

                        ;restore item datas
                        For index=0 To itemCount
                            *LGP_ITEM.LGP_ITEM=GetGadgetItemData(\ID, index)
                            SetGadgetItemData(\ID, index, *LGP_ITEM\olddata)
                            FreeMemory(*LGP_ITEM)
                        Next

                        ;refresh group if necessary
                        If SendMessage_(Window, #LVM_ISGROUPVIEWENABLED, 0, 0)
                            SendMessage_(Window, #WM_SETREDRAW, 0, 0)
                            SendMessage_(Window, #LVM_ENABLEGROUPVIEW, 0, 0)
                            SendMessage_(Window, #LVM_ENABLEGROUPVIEW, 1, 0)
                            SendMessage_(Window, #WM_SETREDRAW, 1, 0)
                        EndIf

                        ProcedureReturn #True
                    EndIf
                ;}

            Case #WM_SIZE
                ;{/// COLUMN : AUTOFILLING (only if gadget is resizing)
                    If \columnToFill>-1 And Not \columnsRedraw
                        SetGadgetItemAttribute(\ID, -1, #PB_ListIcon_ColumnWidth, #PB_Ignore, #PB_Ignore)
                    EndIf
                ;}

            Case #WM_LBUTTONDBLCLK
                ;{/// EDITOR : CHECKING
                    If \EditFunction
                        Protected EditorPos
                        Protected EditorCol
                        Protected EditorState

                        Protected lp=EventlParam()
                        Protected LVHITTESTINFO.LVHITTESTINFO
                        LVHITTESTINFO\pt\x=PeekW(@lp)
                        LVHITTESTINFO\pt\y=PeekW(@lp+SizeOf(word))
                        SendMessage_(Window, #LVM_SUBITEMHITTEST, 0, @LVHITTESTINFO)
                        EditorPos=LVHITTESTINFO\iItem
                        EditorCol=LVHITTESTINFO\iSubItem
                        EditorState=CallFunctionFast(\EditFunction, \ID, EditorPos, EditorCol, 0, #ListIconEditor_BeforeEdit)
                        If EditorState=#ListIconEditor_BeginEdit
                            SendMessage_(Window, #LVM_EDITLABEL, EditorPos, EditorCol)
                        EndIf
                    EndIf
                ;}

            Case #LVM_EDITLABEL
                ;{/// EDITOR : OPEN
                    EditorPos=wParam
                    EditorCol=lParam
                    If IsGadget(\Editor)
                        Select EditorPos
                        Case #ListIconEditor_GetChanges
                        Case #ListIconEditor_ApplyChanges
                            SetGadgetItemText(\ID, \EditorPos, GetGadgetText(\Editor), \EditorCol)
                            FreeGadget(\Editor)
                        Case #ListIconEditor_CancelChanges
                            FreeGadget(\Editor)
                        EndSelect
                    EndIf

                    If EditorPos=#PB_Ignore
                        EditorPos=GetGadgetState(\ID)
                    EndIf
                    If EditorCol=#PB_Ignore
                        lp=EventlParam()
                        LVHITTESTINFO.LVHITTESTINFO
                        LVHITTESTINFO\pt\x=PeekW(@lp)
                        LVHITTESTINFO\pt\y=PeekW(@lp+SizeOf(word))
                        SendMessage_(Window, #LVM_SUBITEMHITTEST, 0, @LVHITTESTINFO)
                        EditorCol=LVHITTESTINFO\iSubItem
                    EndIf

                    If EditorPos>=0 And EditorPos<CountGadgetItems(\ID)
                        If EditorCol>=0 And EditorCol<\columns
                            Protected rc.RECT
                            rc\top=EditorCol
                            rc\left=#LVIR_BOUNDS
                            SendMessage_(Window, #LVM_GETSUBITEMRECT, EditorPos, @rc)
                            If EditorCol=0
                                rc\right=rc\left+SendMessage_(Window, #LVM_GETCOLUMNWIDTH, 0, 0)
                            EndIf

                            UseGadgetList(Window)
                            Protected Text$=GetGadgetItemText(\ID, EditorPos, EditorCol)
                            Protected x=rc\left
                            Protected y=rc\top
                            Protected w=rc\right-rc\left
                            Protected h=rc\bottom-rc\top
                            \Editor=StringGadget(#PB_Any, x, y, w, h, Text$, #ES_MULTILINE | #ES_AUTOVSCROLL)
                            \EditorCol=EditorCol
                            \EditorPos=EditorPos
                            \EditorCB=SetWindowLongPtr_(GadgetID(\Editor), #GWLP_WNDPROC, @LGP_EditorCB())
                            SetActiveGadget(\Editor)
                        EndIf
                    EndIf

                    ProcedureReturn 0
                ;}

            Case #WM_NOTIFY
                Protected *HD_NOTIFY.HD_NOTIFY=lParam
                Protected Code=*HD_NOTIFY\hdr\code
                Protected Column=*HD_NOTIFY\Iitem
                Protected MouseButton=*HD_NOTIFY\iButton
                Protected AutoResize=GetProp_(\header, "LGP_SetGadgetItemAttribute")

                ;Find header flags
                If Column>=0 Or Column<\columns
                    Protected *headerFlags.Integer=\headerFlags+Column*SizeOf(Integer)
                EndIf

                Select code
                    ;Case #HDN_ITEMCHANGED, #HDN_ITEMCHANGEDA, #HDN_ITEMCHANGEDW
                    ;Case #HDN_ITEMCHANGING, #HDN_ITEMCHANGINGW, #HDN_ITEMCHANGINGA
                    ;Case #HDN_TRACK
                    ;Case #HDN_ENDDRAG

                Case #HDN_BEGINDRAG
                    ;{/// COLUMN HEADER : NODRAG
                        If (*headerFlags\i & #ListIconHeader_NoDrag)
                            SetCapture_(0)
                            ProcedureReturn #True
                        EndIf
                    ;}

                Case #HDN_ITEMCLICK, #HDN_ITEMCLICKW, #HDN_ITEMCLICKA
                    ;{/// COLUMN HEADER : AUTOSIZE
                        If (*headerFlags\i & #ListIconHeader_AutoSize)
                            If \columnToFill=Column
                                SetGadgetItemAttribute(\ID, -1, #PB_ListIcon_ColumnWidth, #PB_Ignore, #PB_Ignore)
                            Else
                                SetGadgetItemAttribute(\ID, -1, #PB_ListIcon_ColumnWidth, #PB_Ignore, Column)
                                SetGadgetItemAttribute(\ID, -1, #PB_ListIcon_ColumnWidth, #PB_Ignore, #PB_Ignore)
                            EndIf
                        EndIf
                    ;}

                    ;{/// COLUMN HEADER : SORT (UP,DOWN,NONE)
                        If (*headerFlags\i & #ListIconHeader_Sort)
                            Protected HD_ITEM.HD_ITEM
                            Protected SortAsc

                            HD_ITEM\mask=#HDI_FORMAT
                            SendMessage_(\header, #HDM_GETITEM, Column, @HD_ITEM)
                            If (HD_ITEM\fmt & #HDF_SORTDOWN)
                                SortAsc=0
                            Else
                                SortAsc=1
                            EndIf

                            ;sort single column
                            If (\SortSingleColumn)
                                Protected col
                                For col=0 To \columns-1
                                    Protected *hf.Integer=\headerFlags+col*SizeOf(Integer)
                                    If (*hf\i & #ListIconHeader_Sort)
                                        *hf\i & ~#ListIconHeader_Sort_Up
                                        *hf\i & ~#ListIconHeader_Sort_Down
                                        *hf\i | #ListIconHeader_Sort_None
                                    EndIf

                                    Protected hi.HD_ITEM
                                    hi\mask=#HDI_FORMAT
                                    SendMessage_(\header, #HDM_GETITEM, col, @hi)
                                    hi\fmt & ~#HDF_SORTUP & ~#HDF_SORTDOWN
                                    SendMessage_(\header, #HDM_SETITEM, col, @hi)
                                Next
                            EndIf

                            ;set arrow and flag
                            If SortAsc=1
                                HD_ITEM\fmt & ~#HDF_SORTUP | #HDF_SORTDOWN
                                SendMessage_(\header, #HDM_SETITEM, Column, @HD_ITEM)
                                *headerFlags\i & ~#ListIconHeader_Sort_None
                                *headerFlags\i & ~#ListIconHeader_Sort_Up
                                *headerFlags\i | #ListIconHeader_Sort_Down
                            Else
                                HD_ITEM\fmt & ~#HDF_SORTDOWN | #HDF_SORTUP
                                SendMessage_(\header, #HDM_SETITEM, Column, @HD_ITEM)
                                *headerFlags\i & ~#ListIconHeader_Sort_None
                                *headerFlags\i & ~#ListIconHeader_Sort_Down
                                *headerFlags\i | #ListIconHeader_Sort_Up
                            EndIf

                            ;sort column
                            Protected LGP_SORTING.LGP_SORTING
                            LGP_SORTING\ID=\ID
                            LGP_SORTING\SortAsc=SortAsc
                            LGP_SORTING\Column=Column
                            LGP_SORTING\SortFunction=\SortFunction
                            SendMessage_(GadgetID(\ID), #LVM_SORTITEMS, @LGP_SORTING, #Null)
                        EndIf
                    ;}

                Case #HDN_BEGINTRACK, #HDN_BEGINTRACKA, #HDN_BEGINTRACKW, #HDN_DIVIDERDBLCLICK, #HDN_DIVIDERDBLCLICKA, #HDN_DIVIDERDBLCLICKW
                    ;{/// COLUMN HEADER : FIXED
                        If (*headerFlags\i & #ListIconHeader_FixedSize) And Not \columnsRedraw
                            ProcedureReturn #True
                        EndIf
                    ;}

                    ;{/// COLUMN HEADER : DIVIDER MOVE
                        Select code
                        Case #HDN_BEGINTRACK, #HDN_BEGINTRACKA, #HDN_BEGINTRACKW
                            \columnsRedraw=1
                        EndSelect
                    ;}

                    ;{/// EDITOR : CANCEL (by divider)
                        If \EditFunction And IsGadget(\Editor)
                            EditorState=CallFunctionFast(\EditFunction, \ID, \EditorPos, \EditorCol, \Editor, #ListIconEditor_CancelEdit)
                            SendMessage_(Window, #LVM_EDITLABEL, EditorState, 0)
                        EndIf
                    ;}

                Case #HDN_ENDTRACK, #HDN_ENDTRACKA, #HDN_ENDTRACKW
                    ;{/// COLUMN HEADER : DIVIDER STOP
                        \columnsRedraw=0
                    ;}
                EndSelect
            EndSelect

            ProcedureReturn CallWindowProc_(\CB, Window, Message, wParam, lParam)
        EndWith
    EndIf
EndProcedure

ProcedureDLL GetListIconColumns(ID) ;count listicon columns
    Protected *gadget.GADGET=IsGadget(ID)
    Protected *params.LGP_PARAMS=GetProp_(*gadget\hwnd, "GadgetInfo")

    If *params
        With *params
            \columns=SendMessage_(\header, #HDM_GETITEMCOUNT, #Null, #Null)
            ProcedureReturn \columns
        EndWith
    EndIf
EndProcedure
ProcedureDLL.b GetListIconColumnOrder(ID, Array ColumnsOrder(1)) ;get column order (ColumnOrder: an array of position)
    Protected *gadget.GADGET=IsGadget(ID)
    Protected *params.LGP_PARAMS=GetProp_(*gadget\hwnd, "GadgetInfo")

    If *params
        With *params
            If \columns
                ReDim ColumnsOrder(\columns-1)
                If SendMessage_(\header, #HDM_GETORDERARRAY, \Columns, @ColumnsOrder())
                    ProcedureReturn #True
                EndIf
            EndIf
        EndWith
    EndIf
EndProcedure
ProcedureDLL SetListIconColumnOrder(ID, Array ColumnsOrder(1)) ;set column order (ColumnOrder: an array of position)
    Protected *gadget.GADGET=IsGadget(ID)
    Protected *params.LGP_PARAMS=GetProp_(*gadget\hwnd, "GadgetInfo")

    If *params
        With *params
            If ArraySize(ColumnsOrder())=\Columns-1
                SendMessage_(\header, #HDM_SETORDERARRAY, \Columns, @ColumnsOrder())
            EndIf
        EndWith
    EndIf
EndProcedure
ProcedureDLL.b GetListIconGroupItems(ID, GroupID, Array GroupItems(1))
    Protected *gadget.GADGET=IsGadget(ID)
    Protected *params.LGP_PARAMS=GetProp_(*gadget\hwnd, "GadgetInfo")

    If *params
        With *params
            Protected Position
            Protected Index
            For Position=0 To CountGadgetItems(ID)-1
                Protected LVITEM.LVITEM
                LVITEM\mask=#LVIF_GROUPID
                LVITEM\iItem=Position
                LVITEM\iSubItem=0
                If SendMessage_(*gadget\hwnd, #LVM_GETITEM, 0, @LVITEM) And LVITEM\iGroupID=GroupID
                    Index=ArraySize(GroupItems())
                    GroupItems(Index)=Position
                    Index+1
                    ReDim GroupItems(Index)
                EndIf
            Next

            If Index>0
                ReDim GroupItems(Index-1)
                ProcedureReturn #True
            EndIf
        EndWith
    EndIf
EndProcedure
ProcedureDLL SetListIconGroupItems(ID, GroupID, Array GroupItems(1))
    Protected *gadget.GADGET=IsGadget(ID)
    Protected *params.LGP_PARAMS=GetProp_(*gadget\hwnd, "GadgetInfo")

    If *params
        With *params
            Protected i
            For i=0 To ArraySize(GroupItems())
                Protected LVITEM.LVITEM
                Protected Position=GroupItems(i)
                LVITEM\mask=#LVIF_GROUPID | #LVIF_STATE
                LVITEM\iItem=Position
                LVITEM\iSubItem=0
                If SendMessage_(*gadget\hwnd, #LVM_GETITEM, 0, @LVITEM)
                    LVITEM\iGroupID=GroupID
                    SendMessage_(*gadget\hwnd, #LVM_SETITEM, 0, @LVITEM)
                EndIf
            Next
        EndWith
    EndIf
EndProcedure
ProcedureDLL GetListIconGroupView(ID) ;get groupview state (#True if enabled)
    ProcedureReturn SendMessage_(GadgetID(ID), #LVM_ISGROUPVIEWENABLED, 0, 0)
EndProcedure
ProcedureDLL SetListIconGroupView(ID, EnableListIconGroups.b) ;set groupview state (#True if enabled)
    Protected Window=GadgetID(ID)
    SendMessage_(Window, #WM_SETREDRAW, 0, 0)
    SendMessage_(Window, #LVM_ENABLEGROUPVIEW, EnableListIconGroups, 0)
    SendMessage_(Window, #WM_SETREDRAW, 1, 0)
EndProcedure
ProcedureDLL GetListIconHeader(ID, Column) ;get header flags
    Protected *gadget.GADGET=IsGadget(ID)
    Protected *params.LGP_PARAMS=GetProp_(*gadget\hwnd, "GadgetInfo")

    If *params
        With *params
            ;find column header
            Protected *headerFlags.Integer=\headerFlags+Column*SizeOf(Integer)
            ProcedureReturn *headerFlags\i
        EndWith
    EndIf
EndProcedure
ProcedureDLL SetListIconHeader(ID, Column, ListIconHeaderFlags=#PB_Ignore, ImageID=#PB_Ignore) ;set header options
    Protected *gadget.GADGET=IsGadget(ID)
    Protected *params.LGP_PARAMS=GetProp_(*gadget\hwnd, "GadgetInfo")

    If *params
        With *params
            ;Find header flags
            If Column>=0 Or Column<\columns
                Protected *headerFlags.Integer=\headerFlags+Column*SizeOf(Integer)
            EndIf

            ;{/// HEADER FLAGS
                Select ListIconHeaderFlags
                Case #PB_Ignore
                    ;do nothing
                Case #ListIconHeader_Sort_Up, #ListIconHeader_Sort_Down, #ListIconHeader_Sort_None, #ListIconHeader_Sort_Disabled
                    ;change only the sorting flags
                    *headerFlags\i & ~#ListIconHeader_Sort_Up
                    *headerFlags\i & ~#ListIconHeader_Sort_Down
                    *headerFlags\i & ~#ListIconHeader_Sort_None
                    If ListIconHeaderFlags<>#ListIconHeader_Sort_Disabled
                        *headerFlags\i | ListIconHeaderFlags
                    EndIf
                Default
                    ;change flags
                    *headerFlags\i=ListIconHeaderFlags
                EndSelect
            ;}

            ;{/// HEADER DISPLAY
                Protected HD_ITEM.HD_ITEM
                HD_ITEM\mask=#HDI_FORMAT
                If SendMessage_(\header, #HDM_GETITEM, Column, @HD_ITEM)
                    ;show arrow
                    HD_ITEM\fmt & ~#HDF_SORTDOWN
                    HD_ITEM\fmt & ~#HDF_SORTUP
                    If (*headerFlags\i & #ListIconHeader_Sort_Down)=#ListIconHeader_Sort_Down
                        HD_ITEM\fmt | #HDF_SORTDOWN
                    ElseIf (*headerFlags\i & #ListIconHeader_Sort_Up)=#ListIconHeader_Sort_Up
                        HD_ITEM\fmt | #HDF_SORTUP
                    EndIf
                    ;show image
                    If ImageID<>#PB_Ignore
                        If ImageID=0
                            HD_ITEM\fmt & ~#HDF_BITMAP
                            HD_ITEM\iImage=-1
                        Else
                            #HDF_BITMAP_ON_RIGHT=$1000
                            HD_ITEM\fmt | #HDF_RIGHT | #HDF_BITMAP_ON_RIGHT
                            HD_ITEM\iImage=-1
                            HD_ITEM\hbm=ImageID
                        EndIf
                    EndIf

                    SendMessage_(\header, #HDM_SETITEM, Column, @HD_ITEM)
                EndIf
            ;}

            SendMessage_(*gadget\hwnd, #LVM_GETHEADER, 0, 0)
        EndWith
    EndIf
EndProcedure
ProcedureDLL SetListIconEditFunction(ID, *EditFunction)
    Protected *gadget.GADGET=IsGadget(ID)
    Protected *params.LGP_PARAMS=GetProp_(*gadget\hwnd, "GadgetInfo")

    If *params
        With *params
            ;define sort function
            Select *EditFunction
            Case 0
                \EditFunction=#Null
            Default
                \EditFunction=*EditFunction
            EndSelect
        EndWith
    EndIf
EndProcedure
ProcedureDLL SetListIconSortFunction(ID, SingleSortArrow.b, *SortFunction=#PB_Ignore) ;set sorting mode and define function to use
    Protected *gadget.GADGET=IsGadget(ID)
    Protected *params.LGP_PARAMS=GetProp_(*gadget\hwnd, "GadgetInfo")

    If *params
        With *params
            ;define sort function
            Select *SortFunction
            Case #PB_Ignore
            Case 0
                \SortFunction=@LGP_SortDefault()
            Default
                \SortFunction=*SortFunction
            EndSelect

            ;define sort mode
            \SortSingleColumn=SingleSortArrow
        EndWith
    EndIf
EndProcedure
ProcedureDLL SortListIcon(ID, Column, SortAsc.b) ;sort listicon items (in Ascending order if SortAsc=1)
    Protected *gadget.GADGET=IsGadget(ID)
    Protected *params.LGP_PARAMS=GetProp_(*gadget\hwnd, "GadgetInfo")

    If *params
        With *params
            ;sort column
            Protected LGP_SORTING.LGP_SORTING
            LGP_SORTING\ID=\ID
            LGP_SORTING\SortAsc=SortAsc
            LGP_SORTING\Column=Column
            LGP_SORTING\SortFunction=\SortFunction
            SendMessage_(GadgetID(\ID), #LVM_SORTITEMS, @LGP_SORTING, #Null)

        EndWith
    EndIf
EndProcedure
ProcedureDLL.s EditListIcon(ID, Position=#PB_Ignore, Column=#PB_Ignore)
    Protected *gadget.GADGET=IsGadget(ID)
    Protected *params.LGP_PARAMS=GetProp_(*gadget\hwnd, "GadgetInfo")

    If *params
        With *params
            If IsGadget(\Editor)
                Protected EditorPos=Position
                Protected EditorCol=Column

                Select EditorPos
                Case #ListIconEditor_GetChanges
                    ProcedureReturn GetGadgetText(\Editor)
                Case #ListIconEditor_ApplyChanges
                    SetGadgetItemText(\ID, \EditorPos, GetGadgetText(\Editor), \EditorCol)
                    FreeGadget(\Editor)
                    ProcedureReturn GetGadgetItemText(\ID, \EditorPos, \EditorCol)
                Case #ListIconEditor_CancelChanges
                    FreeGadget(\Editor)
                    ProcedureReturn
                EndSelect
            EndIf

            SendMessage_(*gadget\hwnd, #LVM_EDITLABEL, Position, Column)
        EndWith
    EndIf
EndProcedure
ProcedureDLL ListIconGadgetPlus(ID, x, y, Width, Height, Title$, TitleWidth, Flags=0) ; create listicon gadget
    ;gadget
    If IsGadget(ID) : FreeGadget(ID) : EndIf
    Protected result=ListIconGadget(ID, x, y, Width, Height, Title$, TitleWidth, Flags)
    If result=0 : ProcedureReturn 0 : EndIf
    If ID=#PB_Any : ID=result : EndIf

    ;set commands
    Protected *gadget.GADGET=IsGadget(ID)
    With *gadget
        Static LGP_GADGETVT_NEW.GADGET_VT
        Static LGP_GADGETVT_OLD.GADGET_VT

        If LGP_GADGETVT_OLD\AddGadgetColumn=0
            LGP_GADGETVT_OLD\AddGadgetColumn=\VT\AddGadgetColumn
            LGP_GADGETVT_OLD\SetGadgetItemAttribute2=\VT\SetGadgetItemAttribute2
            LGP_GADGETVT_OLD\AddGadgetItem2=\VT\AddGadgetItem2
            LGP_GADGETVT_OLD\AddGadgetItem3=\VT\AddGadgetItem3
            LGP_GADGETVT_OLD\RemoveGadgetItem=\VT\RemoveGadgetItem
            LGP_GADGETVT_OLD\SetGadgetItemText=\VT\SetGadgetItemText
            LGP_GADGETVT_OLD\GetGadgetItemText=\VT\GetGadgetItemText
            LGP_GADGETVT_OLD\SetGadgetItemState=\VT\SetGadgetItemState
            LGP_GADGETVT_OLD\GetGadgetItemState=\VT\GetGadgetItemState

            CopyMemory(\VT, @LGP_GADGETVT_NEW, SizeOf(GADGET_VT))
            LGP_GADGETVT_NEW\AddGadgetColumn=@LGP_AddGadgetColumn()
            LGP_GADGETVT_NEW\SetGadgetItemAttribute2=@LGP_SetGadgetItemAttribute()
            LGP_GADGETVT_NEW\AddGadgetItem2=@LGP_AddGadgetItem()
            LGP_GADGETVT_NEW\AddGadgetItem3=@LGP_AddGadgetItem()
            LGP_GADGETVT_NEW\RemoveGadgetItem=@LGP_RemoveGadgetItem()
            LGP_GADGETVT_NEW\SetGadgetItemText=@LGP_SetGadgetItemText()
            LGP_GADGETVT_NEW\GetGadgetItemText=@LGP_GetGadgetItemText()
            ;LGP_GADGETVT_NEW\SetGadgetItemState=@LGP_SetGadgetItemState()
            ;LGP_GADGETVT_NEW\GetGadgetItemState=@LGP_GetGadgetItemState()
        EndIf

        \VT=@LGP_GADGETVT_NEW
    EndWith

    ;set parameters
    Protected *LGP_PARAMS.LGP_PARAMS=AllocateMemory(SizeOf(LGP_PARAMS))
    With *LGP_PARAMS
        \ID=ID
        \CB=GetWindowLongPtr_(GadgetID(ID), #GWL_WNDPROC)
        \VT=@LGP_GADGETVT_OLD
        \header=SendMessage_(GadgetID(ID), #LVM_GETHEADER, 0, 0)
        \headerFlags=AllocateMemory(1*SizeOf(Integer))
        \columns=1
        \columnToFill=-1
        \SortFunction=@LGP_SortDefault()
        \SortSingleColumn=#True
        SetProp_(GadgetID(ID), "GadgetInfo", *LGP_PARAMS)
    EndWith

    ;set callback
    SetWindowLongPtr_(GadgetID(ID), #GWL_WNDPROC, @LGP_CB())

    ;if AUTOFILL first column
    If TitleWidth=#PB_Ignore
        SetGadgetItemAttribute(ID, 0, #PB_ListIcon_ColumnWidth, #PB_Ignore, #PB_Ignore)
    EndIf

    ProcedureReturn result
EndProcedure



Procedure Ex1();
    ; ********************
    ; EXAMPLE @ eddy
    ; ********************

    Enumeration
        #Win
        #List1
        #List2
        #Splitter1
    EndEnumeration

    Global w=640
    Global h=480
    OpenWindow(#Win, 0, 0, w, h, "Hidden / Fixed / Autosizing / Dragging ... columns | column header clickable ", #PB_Window_SystemMenu | #PB_Window_WindowCentered)

    ListIconGadgetPlus(#List1, 0, 0, 0, 0, "autosize", 70, #PB_ListIcon_GridLines | #PB_ListIcon_HeaderDragDrop | #PB_ListIcon_FullRowSelect)
    AddGadgetColumn(#List1, 1, "fixed", 40)
    AddGadgetColumn(#List1, 2, "autosize", 70)
    AddGadgetColumn(#List1, 3, "autosize (drag'n drop disabled)", #PB_Ignore)
    SetListIconHeader(#List1, 0, #ListIconHeader_AutoSize)
    SetListIconHeader(#List1, 1, #ListIconHeader_FixedSize | #ListIconHeader_NoDrag)
    SetListIconHeader(#List1, 2, #ListIconHeader_AutoSize)
    SetListIconHeader(#List1, 3, #ListIconHeader_AutoSize | #ListIconHeader_NoDrag)
    AddGadgetItem(#List1, -1, "a long text ... a long text"+#LF$+"BB"+#LF$+"short"+#LF$+"DD"+#LF$)
    AddGadgetItem(#List1, -1, "AA"+#LF$+"BB"+#LF$+"a long text ... a long text"+#LF$+"DD"+#LF$)

    ListIconGadgetPlus(#List2, 0, 0, 0, 0, "hidden", 0, #PB_ListIcon_GridLines | #PB_ListIcon_HeaderDragDrop | #PB_ListIcon_FullRowSelect)
    AddGadgetColumn(#List2, 1, "autosize", 70)
    AddGadgetColumn(#List2, 2, "normal", 100)
    AddGadgetColumn(#List2, 3, "autosize (manual resizing disabled)", 70)
    SetListIconHeader(#List2, 0, #ListIconHeader_FixedSize | #ListIconHeader_NoDrag)
    SetListIconHeader(#List2, 1, #ListIconHeader_AutoSize)
    SetListIconHeader(#List2, 2, #ListIconHeader_Normal)
    SetListIconHeader(#List2, 3, #ListIconHeader_AutoSize | #ListIconHeader_FixedSize)
    AddGadgetItem(#List2, -1, "hidden"+#LF$+"short"+#LF$+"CC"+#LF$+"a long text ... a long text"+#LF$)
    AddGadgetItem(#List2, -1, "hidden"+#LF$+"a long text ... a long text"+#LF$+"CC"+#LF$+"visible"+#LF$)

    SetGadgetItemColor(#List1, 0, #PB_Gadget_BackColor, #Cyan, 3)
    SetGadgetItemColor(#List2, 0, #PB_Gadget_BackColor, #Yellow, 3)

    SplitterGadget(#Splitter1, 4, 4, w-8, h-8, #List1, #List2)

    Repeat
        Global e=WaitWindowEvent()
    Until e=#PB_Event_CloseWindow

EndProcedure

Procedure My_ListIcon_SortFunction(ID, Column, SortAsc, itemIndex1, itemIndex2, *GadgetItemData1, *GadgetItemData2)
    Protected result
    Protected A$=GetGadgetItemText(ID, itemIndex1, Column)
    Protected B$=GetGadgetItemText(ID, itemIndex2, Column)

    If A$=B$
        result=0
    ElseIf A$>B$
        result=1
    Else
        result=-1
    EndIf
    If Not SortAsc
        result=-result
    EndIf
    ProcedureReturn result
EndProcedure

Procedure Ex2();
    #ListIconHeader_Sort=8

    ;header sort commands
    #ListIconHeader_Sort_Up=#ListIconHeader_Sort | 16     ;sorting enabled & arrow up
    #ListIconHeader_Sort_Down=#ListIconHeader_Sort | 32   ;sorting enabled & arrow down
    #ListIconHeader_Sort_None=#ListIconHeader_Sort | 64   ;sorting enabled & hidden arrow
    #ListIconHeader_Sort_Disabled=128                     ;sorting disabled

    ; ********************
    ; EXAMPLE @ eddy
    ; ********************


    Enumeration
        #Win
        #Status
        #Button1
        #Button2
        ;#List2
    EndEnumeration
    Global w=640
    Global h=480
    OpenWindow(#Win, 0, 0, w, h, "Sorting / Dragging / Autosizing ... columns", #PB_Window_SystemMenu | #PB_Window_WindowCentered | #PB_Window_SizeGadget)
    SmartWindowRefresh(#Win, 1)
    CreateStatusBar(#Status, WindowID(#win))
    AddStatusBarField(90)

    StatusBarText(#Status, 0, "Default sorting function (single column)")
    
    ButtonGadget(#Button1, 4, 4, w-8, 30, "Column1 : enable sorting / Column2 : reset sorting / Column3 : disable sorting")
    ButtonGadget(#Button2, 4, 40, w-8, 30, "Toggle GroupView ")

    ListIconGadgetPlus(#List2, 4, 84, w-8, h-130, "fixed", 40, #PB_ListIcon_FullRowSelect)
    AddGadgetColumn(#List2, 1, "C1: autosize", 90)
    AddGadgetColumn(#List2, 2, "C2: autosize + sort", 180)
    AddGadgetColumn(#List2, 300, "C3: autosize + sort", #PB_Ignore)
    SetListIconGroupView(#list2, 1)

    ;********************
    ;add listicon item and group
    ;********************
    Global ItemPos, ItemGroup, ItemColumns.s, ItemData.i
    Global ItemIcon=CreateImage(0, 32, 32)
    StartDrawing(ImageOutput(0))
    FillArea(0, 0, #White, #White)
    Box(1, 1, 30, 30, #Red)
    StopDrawing()
    For ItemPos=0 To 10
        ItemData=1000*(#True And ItemPos=4)
        ItemColumns=Str(ItemPos)
        ItemColumns+#LF$+RSet(Str(Random(50)*7), 4, "0")+" > here is my very long text ..."
        ItemColumns+#LF$+"an other long text ..."+Str(ElapsedMilliseconds())
        ItemColumns+#LF$+"GetGadgetItemData = "+Str(ItemData)

        Select ItemPos
        Case 0
            ItemGroup=#ListIconGroup_Position+0
            AddGadgetItem(#List2, ItemGroup, "GROUP 0")
        Case 3
            ItemGroup=#ListIconGroup_Position+1
            AddGadgetItem(#List2, ItemGroup, "GROUP 1")
        Case 7
            ItemGroup=#ListIconGroup_Position+2
            AddGadgetItem(#List2, ItemGroup, "GROUP 2")
        EndSelect
        AddGadgetItem(#List2, ItemPos, ItemColumns, ItemIcon, ItemGroup)
        SetGadgetItemData(#List2, ItemPos, ItemData)
        Delay(20)
    Next

    ;********************
    ;attach items to group
    ;********************
    AddGadgetItem(#List2, -100, "")
    AddGadgetItem(#List2, 11, ""+#LF$+"item in hidden group"+#LF$+"item in hidden group"+#LF$+"item in hidden group", ItemIcon)
    AddGadgetItem(#List2, 12, ""+#LF$+"XX"+#LF$+"item in hidden group"+#LF$+"XX", ItemIcon)

    Dim AttachItems_To_Group(1)
    AttachItems_To_Group(0)=11
    AttachItems_To_Group(1)=12
    SetListIconGroupItems(#List2, -100, AttachItems_To_Group())

    ;********************
    ;get / set item text
    ;********************
    SetGadgetItemText(#List2, -100, "GROUP IS RENAMED...")
    Debug "item= "+GetGadgetItemText(#List2, 10, 0)
    Debug "item= "+GetGadgetItemText(#List2, 10, 1)
    Debug "item= "+GetGadgetItemText(#List2, -100)

    ;********************
    ;change header & sorting
    ;********************
    SetListIconHeader(#List2, 0, #ListIconHeader_NoDrag | #ListIconHeader_FixedSize)
    SetListIconHeader(#List2, 1, #ListIconHeader_AutoSize)
    SetListIconHeader(#List2, 2, #ListIconHeader_AutoSize | #ListIconHeader_Sort_Up)
    SetListIconHeader(#List2, 3, #ListIconHeader_AutoSize | #ListIconHeader_Sort)

    ;SetListIconSortFunction(#List2, #True)
    ;SetListIconSortFunction(#List2, #True, @My_ListIcon_SortFunction())
    ;SortListIcon(#List2, 1, #True)

    ;********************
    ;change list order
    ;********************
    Dim ColumnsOrders(3)
    ColumnsOrders(0)=0
    ColumnsOrders(1)=1
    ColumnsOrders(2)=3
    ColumnsOrders(3)=2
    SetListIconColumnOrder(#List2, ColumnsOrders())

    Repeat
        Global e=WaitWindowEvent()
        Global g=EventGadget()
        Global t=EventType()

        If e=#PB_Event_SizeWindow
            ResizeGadget(#list2, #PB_Ignore, #PB_Ignore, WindowWidth(#Win)-8, WindowHeight(#Win)-120)
        EndIf
        If e=#PB_Event_Gadget And g=#Button1
            SetListIconHeader(#List2, 1, #ListIconHeader_Sort_Down)
            SetListIconHeader(#List2, 2, #ListIconHeader_Sort_None)
            SetListIconHeader(#List2, 3, #ListIconHeader_Sort_Disabled)
            SetGadgetItemText(#List2, -1, "C1: autosize + sort", 1)
            SetGadgetItemText(#List2, -1, "C3: autosize", 3)
            SetGadgetItemAttribute(#List2, -1, #PB_ListIcon_ColumnWidth, #PB_Ignore, 1)
            SetGadgetItemAttribute(#List2, -1, #PB_ListIcon_ColumnWidth, #PB_Ignore, #PB_Ignore)
        EndIf
        If e=#PB_Event_Gadget And g=#Button2
            SetListIconGroupView(#List2, 1-GetListIconGroupView(#List2))
        EndIf
        If e=#PB_Event_Gadget And g=#List2 And t=#PB_EventType_LeftClick
            Global s=GetGadgetState(g)
            If s>-1
                Debug GetGadgetItemText(g, s, 0)+" > ItemData= "+Str(GetGadgetItemData(g, s))

                Global Order
                Global Dim ColumnsOrder(0)
                If GetListIconColumnOrder(g, ColumnsOrder())
                    For Order=0 To ArraySize(ColumnsOrder())-1
                        Debug "Order="+Str(Order)+" Column="+Str(ColumnsOrder(Order))
                    Next
                    Debug ""
                EndIf
            EndIf
        EndIf
    Until e=#PB_Event_CloseWindow

EndProcedure

Procedure My_ListIcon_EditFunction(ID, Position, Column, EditorID, EditorState)
    Select EditorState
    Case #ListIconEditor_BeforeEdit
        If Column>0
            ProcedureReturn #ListIconEditor_BeginEdit
        EndIf
    Case #ListIconEditor_CancelEdit
        If GetGadgetText(EditorID)=""
            ProcedureReturn #ListIconEditor_CancelChanges
        Else
            ProcedureReturn #ListIconEditor_ApplyChanges
        EndIf
    EndSelect
EndProcedure

Procedure Ex3();
    ; ********************
    ; EXAMPLE @ eddy
    ; ********************

    Enumeration
        #Win
        #Status
        #Button1
        #Button2
        ;#List2;
    EndEnumeration
    Global w=640
    Global h=480
    OpenWindow(#Win, 0, 0, w, h, "Sorting / Dragging / Autosizing ... columns", #PB_Window_SystemMenu | #PB_Window_WindowCentered | #PB_Window_SizeGadget)
    SmartWindowRefresh(#Win, 1)
    CreateStatusBar(#Status, WindowID(#win))
    AddStatusBarField(900)
    StatusBarText(#Status, 0, "Default sorting function (single column)")
    ButtonGadget(#Button1, 4, 4, w-8, 30, "Column1 : enable sorting / Column2 : reset sorting / Column3 : disable sorting")
    ButtonGadget(#Button2, 4, 40, w-8, 30, "Toggle GroupView ")

    ListIconGadgetPlus(#List2, 4, 84, w-8, h-130, "fixed", 80, #PB_ListIcon_CheckBoxes | #PB_ListIcon_FullRowSelect)
    AddGadgetColumn(#List2, 1, "C1: autosize", 90)
    AddGadgetColumn(#List2, 2, "C2: autosize + sort", 180)
    AddGadgetColumn(#List2, 300, "C3: autosize + sort", #PB_Ignore)
    SetListIconGroupView(#list2, 1)

    ;********************
    ;add listicon item and group
    ;********************
    Global ItemPos, ItemGroup, ItemColumns.s, ItemData.i
    Global ItemIcon=CreateImage(0, 32, 32)
    StartDrawing(ImageOutput(0))
    FillArea(0, 0, #White, #White)
    Box(1, 1, 30, 30, #Red)
    StopDrawing()
    For ItemPos=0 To 10
        ItemData=1000*(#True And ItemPos=4)
        ItemColumns=Str(ItemPos)
        ItemColumns+#LF$+RSet(Str(Random(50)*7), 4, "0")+" > here is my very long text ..."
        ItemColumns+#LF$+"an other long text ..."+Str(ElapsedMilliseconds())
        ItemColumns+#LF$+"GetGadgetItemData = "+Str(ItemData)

        Select ItemPos
        Case 0
            ItemGroup=#ListIconGroup_Position+0
            AddGadgetItem(#List2, ItemGroup, "GROUP 0")
        Case 3
            ItemGroup=#ListIconGroup_Position+1
            AddGadgetItem(#List2, ItemGroup, "GROUP 1")
        Case 7
            ItemGroup=#ListIconGroup_Position+2
            AddGadgetItem(#List2, ItemGroup, "GROUP 2")
        EndSelect
        AddGadgetItem(#List2, ItemPos, ItemColumns, ItemIcon, ItemGroup)
        SetGadgetItemData(#List2, ItemPos, ItemData)
        SetGadgetItemColor(#List2, ItemPos, #PB_Gadget_FrontColor, #Blue, 1)
        Delay(20)
    Next
    SetGadgetItemColor(#List2,3,#PB_Gadget_BackColor,#Yellow)

    ;********************
    ;attach items to group
    ;********************
    AddGadgetItem(#List2, -100, "")
    AddGadgetItem(#List2, 11, ""+#LF$+"item in hidden group"+#LF$+"item in hidden group"+#LF$+"item in hidden group", ItemIcon)
    AddGadgetItem(#List2, 12, ""+#LF$+"XX"+#LF$+"item in hidden group"+#LF$+"XX", ItemIcon)

    Dim AttachItems_To_Group(1)
    AttachItems_To_Group(0)=11
    AttachItems_To_Group(1)=12
    SetListIconGroupItems(#List2, -100, AttachItems_To_Group())

    ;********************
    ;get / set item text
    ;********************
    SetGadgetItemText(#List2, -100, "GROUP IS RENAMED...")
    Debug "item= "+GetGadgetItemText(#List2, 10, 0)
    Debug "item= "+GetGadgetItemText(#List2, 10, 1)
    Debug "item= "+GetGadgetItemText(#List2, -100)

    ;********************
    ;change header & sorting
    ;********************
    SetListIconHeader(#List2, 0, #ListIconHeader_NoDrag | #ListIconHeader_FixedSize)
    SetListIconHeader(#List2, 1, #ListIconHeader_AutoSize)
    SetListIconHeader(#List2, 2, #ListIconHeader_AutoSize | #ListIconHeader_Sort_Up)
    SetListIconHeader(#List2, 3, #ListIconHeader_AutoSize | #ListIconHeader_Sort)

    ;********************
    ;change editor parameters
    ;********************
    SetListIconEditFunction(#List2, @My_ListIcon_EditFunction())

    Repeat
        Global e=WaitWindowEvent()
        Global g=EventGadget()
        Global t=EventType()

        If e=#PB_Event_SizeWindow
            ResizeGadget(#list2, #PB_Ignore, #PB_Ignore, WindowWidth(#Win)-8, WindowHeight(#Win)-120)
        EndIf
        If e=#PB_Event_Gadget And g=#Button1
            SetListIconHeader(#List2, 1, #ListIconHeader_Sort_Down)
            SetListIconHeader(#List2, 2, #ListIconHeader_Sort_None)
            SetListIconHeader(#List2, 3, #ListIconHeader_Sort_Disabled)
            SetGadgetItemText(#List2, -1, "C1: autosize + sort", 1)
            SetGadgetItemText(#List2, -1, "C3: autosize", 3)
            SetGadgetItemAttribute(#List2, -1, #PB_ListIcon_ColumnWidth, #PB_Ignore, 1)
            SetGadgetItemAttribute(#List2, -1, #PB_ListIcon_ColumnWidth, #PB_Ignore, #PB_Ignore)
        EndIf
        If e=#PB_Event_Gadget And g=#Button2
            SetListIconGroupView(#List2, 1-GetListIconGroupView(#List2))
        EndIf
        If e=#PB_Event_Gadget And g=#List2 And t=#PB_EventType_LeftClick
            Global s=GetGadgetState(g)
            If s>-1
                Debug GetGadgetItemText(g, s, 0)+" > ItemData= "+Str(GetGadgetItemData(g, s))

                Global Order
                Global Dim ColumnsOrder(0)
                If GetListIconColumnOrder(g, ColumnsOrder())
                    For Order=0 To ArraySize(ColumnsOrder())-1
                        Debug "Order="+Str(Order)+" Column="+Str(ColumnsOrder(Order))
                    Next
                    Debug ""
                EndIf
            EndIf
        EndIf
        If e=#PB_Event_Gadget And g=#List2
            If t=#PB_EventType_LeftDoubleClick
                ;EditListIcon(#List2)
            EndIf
            If t=#PB_EventType_LeftClick
                ;          If EditListIcon(#List2, #ListIconEditor_GetChanges)=""
                ;             EditListIcon(#List2, #ListIconEditor_CancelChanges)
                ;          Else
                ;             EditListIcon(#List2, #ListIconEditor_ApplyChanges)
                ;          EndIf
            EndIf
        EndIf
    Until e=#PB_Event_CloseWindow

EndProcedure

Ex3();
User avatar
Kiffi
Addict
Addict
Posts: 1504
Joined: Tue Mar 02, 2004 1:20 pm
Location: Amphibios 9

Re: ListIcon+Column AutoResize,Edit,Group,Sort Arrow,HeaderC

Post by Kiffi »

Thanks for the code! :D

I have found a bug:

* Click on "Toggle GroupView"
* Resize Column1 (make it wider)
* Click on "Toggle GroupView" again

-> endless loop

(PB4.51 / Vista Business SP2 / 32 Bit)

Greetings ... Kiffi
Hygge
TerryHough
Enthusiast
Enthusiast
Posts: 781
Joined: Fri Apr 25, 2003 6:51 pm
Location: NC, USA
Contact:

Re: ListIcon+Column AutoResize,Edit,Group,Sort Arrow,HeaderC

Post by TerryHough »

Windows only - Updated code for PB 4.30
Anybody have eddy's code working with PB 4.51? I haven't been able to get it to compile.
bhatkins2000
New User
New User
Posts: 9
Joined: Fri Apr 28, 2006 4:20 pm
Location: Missouri

Re: ListIcon+Column AutoResize,Edit,Group,Sort Arrow,HeaderC

Post by bhatkins2000 »

This is exactly the kind of thing that I need. What I need to know is how to get it to work.

I am not a complete beginner but would like someone to point me in the right direction. I see that these are proceduredlls (in a lot of cases). What do I need to do to get those to work?

thanks for any help.
User avatar
minimy
Enthusiast
Enthusiast
Posts: 634
Joined: Mon Jul 08, 2013 8:43 pm
Location: off world

Re: ListIcon+Column AutoResize,Edit,Group,Sort Arrow,HeaderC

Post by minimy »

Thanks for your contribution.

CallFunctionFast(*params\VT\AddGadgetColumn, *gadget, Position, Title$, Width)

Line 164 bad parameter type, number expected instead stream.

Why happend this?

When run the code an error window appear. Why?
If translation=Error: reply="Sorry, Im Spanish": Endif
Post Reply