Page 1 of 2

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

Posted: Thu Dec 11, 2008 6:27 pm
by eddy
Windows only - Updated code for PB 4.30
- SetListIconSorting ( sort listicon items )
- supports x64 platform
- SetListIconHeader with header options :
  • Fixed : fixed width
  • AutoResize : mouseclick to fit column contents / fill width if last column
  • NoDrag : disable drag 'n' drop
- EXTENDED : SetGadgetItemAttribute (supports #PB_Ignore)
  • SetGadgetItemAttribute(#List1, -1, #PB_ListIcon_ColumnWidth, #PB_Ignore, Column) ; AutoResize specific column
  • SetGadgetItemAttribute(#List1, -1, #PB_ListIcon_ColumnWidth, #PB_Ignore, #PB_Ignore) ; AutoFill last column
- EXTENDED : AddGadgetColumn (supports #PB_Ignore)
  • AddGadgetColumn(#List1, 3, "ColumnTitle", #PB_Ignore) ; AutoFill new column

Code: Select all

;{/// UTILS
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
;}
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
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

Posted: Thu Dec 11, 2008 6:39 pm
by srod
Hi Eddy,

thanks for sharing.

A couple of things -if you don't mind a little feedback?

First, in your demo the column which is implied should not be dragable, is in fact dragable here on Vista! The only thing that seems to have been disabled is the visual elements of the drag; but I can certainly drag that column here!

Also, the fixed columns still resize if you double-click the column separator. You probably want to sort that out.

Posted: Thu Dec 11, 2008 6:49 pm
by eddy
srod wrote: First, in your demo the column which is implied should not be dragable, is in fact dragable here on Vista! The only thing that seems to have been disabled is the visual elements of the drag; but I can certainly drag that column here!

Also, the fixed columns still resize if you double-click the column separator. You probably want to sort that out.
Fixed
- you can make a test.
- Does the AutoFill function work correctly on vista :?:
It's a simple width calculation.
There's a windows message to do it but it does not work correctly if column orders are modified.

Example 1 - header click - autoresize functionality

Code: Select all

; ********************
; 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

Posted: Thu Dec 11, 2008 6:55 pm
by srod
Confirmed - fixed! :)

One slight annoyance which you may or may not wish to address. The column which cannot be resized still shows the sizing cursor when the mouse is over the divider etc. Fix this and then it's perfect! :wink:

Posted: Thu Dec 11, 2008 6:56 pm
by srod
When you say 'autofill' do you mean 'auto-fit' ? If so then yes it seems to work fine here.

Posted: Thu Dec 11, 2008 7:01 pm
by eddy
- AutoFit : if it's not the last AutoResize column (it will fit column content width)
- AutoFill : if it's the last AutoResize column (it will fill the empty gadget width)

An AutoFill column is updated automaticly after any gadget resizing

Posted: Thu Dec 11, 2008 7:02 pm
by Rings
edit the title , windows only code.

Posted: Thu Dec 11, 2008 7:02 pm
by srod
In which case - yes it seems to work fine here. :)

Posted: Fri Dec 12, 2008 12:59 am
by eddy
updated
- ADDED : SetListIconSorting
  • SetListIconSortFunction(#List2, #True, @My_ListIcon_SortFunction()) ; define sort function - single sort arrow
  • SortListIcon(#List2, 1, #True) ; sort items in ascending order
  • SortListIcon(#List2, 1, #False) ; sort items in descending order
NB: This function does not alter any gadget item data stored in your listicon.

exmaple 2 - sorting column

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

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", 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

Posted: Fri Dec 12, 2008 2:21 pm
by eddy
wip
- OK I found how to display sort-up-down arrow ( tested on XP, Wista )
- I wonder if I can implement easily the multi-column sorting.

Posted: Sat Dec 13, 2008 4:49 pm
by eddy
[updated]
- UPDATED : include file (above) :)

- MODIFIED : example 1 é 2
- MODIFIED : sort functionality updated (not yet finished )
- ADDED : column header arrow (90% not yet finished )
- ADDED : columns order
- ADDED : sort header flags & sort commands flags
- FIXED : column resizing vs column autofilling

Code: Select all

   #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
TODO :
- multi-column / single-column sorting

Posted: Sun Dec 14, 2008 2:42 am
by eddy
wip
- OK, I found a way to add listicon group. :) ( position < -1 )
- But the sort function does not support the item groups :?

Code: Select all

SetListIconGroupView(#List2, 0)
SetListIconGroupView(#List2, 1)

Code: Select all

ItemGroup=-100
AddGadgetItem(#List2, ItemGroup, "GROUP TITLE")
AddGadgetItem(#List2, -1, "item1"+#LF$+"text..."+#LF$+"last...", ImageID(1), ItemGroup)

ItemGroup=#ListIconGroup_Position+1 
AddGadgetItem(#List2, ItemGroup, "GROUP TITLE") 
AddGadgetItem(#List2, -1, "item1"+#LF$+"text..."+#LF$+"last...", ImageID(1), ItemGroup)

screenshot :
Image

Posted: Wed Dec 17, 2008 11:13 am
by Seldon
Impressive work ! That's going to be the ultimate ListIconGadget ! Many thanks !

Posted: Wed Dec 17, 2008 10:27 pm
by eddy
I give up, I can't found a solution

Posted: Fri Dec 19, 2008 5:52 am
by eddy
updated
- ADDED : multi-column / single-column sorting
- ADDED : enable / disable group view
- ADDED : get / set group items
- EXTENDED : GetGadgetItemText / SetGadgetItemText
- UPDATED : example 2

Code: Select all

SetListIconSortFunction(#List2, #True, 0) ;single sort arrow and use default sort function 
SetListIconSortFunction(#List2, #False, @My_ListIcon_SortFunction()) ;multi sort arrows and use custom sort function
Todo
- improve groups sorting