PB5.2: ListIcon Group,Order,HeaderIcon,SortArrow,FillColumn

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

PB5.2: ListIcon Group,Order,HeaderIcon,SortArrow,FillColumn

Post by eddy »

  • Reorder Columns
  • Column header icon
  • Column sort arrows
  • Options to disable column resizing and dragging
  • Group view
  • Auto sort on click column header
  • Sort groups & items (customizable via function)
  • Collapsible group (not fully supported by winXP)
  • New event types: header left/right click, reorderColumns...


Image

Code: Select all

EnableExplicit
Enumeration
   ;add missing Windows platform constants if necessary...
   CompilerIf Not Defined(HDF_BITMAP_ON_RIGHT, #PB_Constant)
      #HDF_BITMAP_ON_RIGHT=$1000
      #LVGS_COLLAPSED=$1
      #LVGS_COLLAPSIBLE=$8
      #LVGS_HIDDEN = $2
      #LVM_GETGROUPCOUNT = #LVM_FIRST + 152
   CompilerEndIf
   
   ;ListIcon new event types
   #PB_EventType_HeaderLeftClick = #PB_EventType_FirstCustomValue+1111
   #PB_EventType_HeaderRightClick
   #PB_EventType_ReorderColumns
   
   ;ListIcon Attributes
   #ListIconAttribute_GroupView=1
   #ListIconAttribute_SortAuto
   #ListIconAttribute_SortMultiColumn
   #ListIconAttribute_AvailableColumnWidth
   
   ;ListIcon Header Flags
   #ListIconHeader_None=0
   #ListIconHeader_SortArrow_Down =%1
   #ListIconHeader_SortArrow_Up =%10
   #ListIconHeader_SortArrow_Changing =%100
   #ListIconHeader_LeftIcon =%1000
   #ListIconHeader_RightIcon =%10000
   #ListIconHeader_NoDrag =%100000
   #ListIconHeader_NoManualResize =%1000000
   #ListIconHeader_NoAutoResize =%10000000
   ;(internal use only)
   #ListIconHeader_AnySortArrow =#ListIconHeader_SortArrow_Down | #ListIconHeader_SortArrow_Up
   #ListIconHeader_AnyIcon =#ListIconHeader_LeftIcon | #ListIconHeader_RightIcon
   
   ;ListIcon GroupID max value
   #ListIconGroupID_MaxValue=%1<<16-1
   
   ;ListIcon Group Flags (conbinaison allowed)
   #ListIconGroups_Collapsed=%1<<16
   #ListIconGroups_Collapsible=%10<<16 ;not supported by winXP
   #ListIconGroups_Hidden=%100<<16
EndEnumeration

Structure LISTICON_PARAMS
   Map GroupName$()
   Map GroupIDs.i()
   List HeaderFlags.i()
   Gadget.i
   *GadgetID
   *OriginalCallback
   *ColHeader
   *CustomData
   IsSortingItems.b
   IsSortAuto.b
   IsSortMulti.b
   IsGroupViewEnabled.b
EndStructure
Structure LVGROUP1 Align #PB_Structure_AlignC
   cbSize.l
   mask.l
   *pszHeader
   cchHeader.l
   *pszFooter
   cchFooter.l
   iGroupId.l
   stateMask.l
   state.l
   uAlign.l
EndStructure

Procedure.i InternalListIconParams(Gadget)
   Protected *params.LISTICON_PARAMS=GetProp_(GadgetID(Gadget), "LISTICON_INTERNAL_PARAMS")
   With *params
      If Not *params
         *params=AllocateMemory(SizeOf(LISTICON_PARAMS))
         InitializeStructure(*params, LISTICON_PARAMS)
         \Gadget=Gadget
         \GadgetID=GadgetID(Gadget)
         \ColHeader=SendMessage_(\GadgetID, #LVM_GETHEADER, 0, 0)
         Protected *newCallback=GetRuntimeInteger("InternalListIconCallback()")
         \OriginalCallback=SetWindowLongPtr_(\GadgetID, #GWL_WNDPROC, *newCallback)
         Protected colCount=SendMessage_(*params\ColHeader, #HDM_GETITEMCOUNT, 0, 0)
         Protected colIndex
         For colIndex=1 To colCount : AddElement(\HeaderFlags()) : Next
         SetProp_(\GadgetID, "LISTICON_INTERNAL_PARAMS", *params)
      EndIf
      ProcedureReturn *params
   EndWith
EndProcedure

Procedure.i CountListIconColumns(Gadget)
   Protected *params.LISTICON_PARAMS=InternalListIconParams(Gadget)
   Protected colCount = SendMessage_(*params\ColHeader, #HDM_GETITEMCOUNT, 0, 0)
   ProcedureReturn colCount
EndProcedure
Procedure.i CountListIconGroups(Gadget)
   Protected *params.LISTICON_PARAMS=InternalListIconParams(Gadget)
   Protected groupCount = SendMessage_(*params\GadgetID, #LVM_GETGROUPCOUNT, 0, 0)
   ProcedureReturn groupCount
EndProcedure
Procedure.i GetListIconAttribute(Gadget, Attribute)
   Protected *params.LISTICON_PARAMS=InternalListIconParams(Gadget)
   With *params
      Select Attribute
         Case #ListIconAttribute_GroupView
            ProcedureReturn SendMessage_(\GadgetID, #LVM_ISGROUPVIEWENABLED, 0, 0)
         Case #ListIconAttribute_SortAuto
            ProcedureReturn \IsSortAuto
         Case #ListIconAttribute_SortMultiColumn
            ProcedureReturn \IsSortMulti
         Case #ListIconAttribute_AvailableColumnWidth
            Protected column, colCount=CountListIconColumns(Gadget)
            Protected columnWidth=GadgetWidth(Gadget)-4
            For column=0 To colCount-1
               columnWidth-GetGadgetItemAttribute(Gadget, -1, #PB_ListIcon_ColumnWidth, column)
            Next
            If GetWindowLongPtr_(\GadgetID, #GWL_STYLE)& #WS_VSCROLL
               columnWidth-GetSystemMetrics_(#SM_CXVSCROLL)
            EndIf
            ProcedureReturn columnWidth
      EndSelect
   EndWith
EndProcedure
Procedure.i SetListIconAttribute(Gadget, Attribute, Value)
   Protected *params.LISTICON_PARAMS=InternalListIconParams(Gadget)
   Protected result
   With *params
      Select Attribute
         Case #ListIconAttribute_GroupView
            \IsGroupViewEnabled=Bool(Value)
            result=Bool(SendMessage_(\GadgetID, #LVM_ENABLEGROUPVIEW, Bool(Value), 0)<>-1)
         Case #ListIconAttribute_SortAuto
            \IsSortAuto=Bool(Value)
            result=#True
         Case #ListIconAttribute_SortMultiColumn
            \IsSortMulti=Bool(Value)
            result=#True
         Case #ListIconAttribute_AvailableColumnWidth
            Protected column, columnsToResize, columnWidth, columnWidthToAdd, lastToResize=-1
            Protected availableWidth=GetListIconAttribute(Gadget, #ListIconAttribute_AvailableColumnWidth)-Value
            PushListPosition(\HeaderFlags())
            ForEach \HeaderFlags()
               If Not (\HeaderFlags()& #ListIconHeader_NoAutoResize)
                  columnsToResize+1
                  lastToResize=ListIndex(\HeaderFlags())
               EndIf
            Next
            If columnsToResize
               columnWidthToAdd=Round(availableWidth/columnsToResize, #PB_Round_Down)
               ForEach \HeaderFlags()
                  column=ListIndex(\HeaderFlags())
                  If Not (\HeaderFlags()& #ListIconHeader_NoAutoResize)
                     columnWidth=GetGadgetItemAttribute(Gadget, -1, #PB_ListIcon_ColumnWidth, column)
                     If column=lastToResize
                        columnWidth+availableWidth
                     Else
                        columnWidth+columnWidthToAdd
                        availableWidth-columnWidthToAdd
                     EndIf
                     SetGadgetItemAttribute(Gadget, -1, #PB_ListIcon_ColumnWidth, columnWidth, column)
                  EndIf
               Next
            EndIf
            PopListPosition(\HeaderFlags())
            result=#True
      EndSelect
   EndWith
   ;returns TRUE if successful
   ProcedureReturn result
EndProcedure

Procedure SetListIconHeader(Gadget, Column, Flags=0, *ImageID=0)
   Protected *params.LISTICON_PARAMS=InternalListIconParams(Gadget)
   Protected *colHeader=*params\ColHeader
   Protected item.HD_ITEM, result
   With item
      \mask=#HDI_FORMAT|#HDI_BITMAP
      If Not SendMessage_(*colHeader, #HDM_GETITEM, Column, item) : ProcedureReturn : EndIf
      \fmt & ~#HDF_SORTDOWN & ~#HDF_SORTUP & ~#HDF_BITMAP & ~#HDF_BITMAP_ON_RIGHT
      \fmt | #HDF_STRING
      
      ;change sort arrow (shift between bits)
      If Flags & #ListIconHeader_SortArrow_Changing
         If Not (Flags & #ListIconHeader_AnyIcon)
            Protected newFlags=(Flags & %11)
            If (newFlags=0) : newFlags=1 : Else : newFlags<<1 : EndIf
            If (newFlags & %100) : newFlags=0 : EndIf
         EndIf
         Flags & ~%111 | newFlags
      EndIf
      
      If Flags & #ListIconHeader_AnySortArrow
         ;show/hide arrow (=> remove icon)
         \hbm=0
         \iImage=-1
         If Flags & #ListIconHeader_SortArrow_Down : \fmt |#HDF_SORTDOWN : EndIf
         If Flags & #ListIconHeader_SortArrow_Up : \fmt | #HDF_SORTUP : EndIf
      ElseIf Flags & #ListIconHeader_AnyIcon
         ;show/hide icon (=> remove arrow)
         \fmt |(#HDF_BITMAP *Bool(*ImageID))
         \fmt |(#HDF_BITMAP_ON_RIGHT *Bool(*ImageID And Flags & #ListIconHeader_RightIcon))
         \hbm=*ImageID
      Else
         ;hide icon and arrow
         \hbm=0
         \iImage=-1
      EndIf
   EndWith
   
   With *params
      PushListPosition(\HeaderFlags())
      If Not \IsSortMulti And Flags & #ListIconHeader_AnySortArrow
         ;keep only one sort arrow (=> single column sorting)
         ForEach \HeaderFlags()
            Protected col=ListIndex(\HeaderFlags())
            If col<>Column And \HeaderFlags()& #ListIconHeader_AnySortArrow
               \HeaderFlags()& ~#ListIconHeader_AnySortArrow
               SetListIconHeader(\Gadget, col, \HeaderFlags())
            EndIf
         Next
      EndIf
      If SelectElement(\HeaderFlags(), Column)
         ;save and apply header flags
         \HeaderFlags()=Flags
         result=SendMessage_(*colHeader, #HDM_SETITEM, Column, item)
      EndIf
      PopListPosition(\HeaderFlags())
      
      ;returns TRUE if successful
      ProcedureReturn result
   EndWith
EndProcedure
Procedure.i GetListIconHeader(Gadget, Column, *ImageID=0)
   Protected *params.LISTICON_PARAMS=InternalListIconParams(Gadget)
   Protected item.HD_ITEM, Flags=0
   With *params
      PushListPosition(\HeaderFlags())
      SelectElement(\HeaderFlags(), Column)
      Flags=\HeaderFlags()
      
      item\mask=#HDI_FORMAT|#HDI_BITMAP
      If *ImageID And Flags & #ListIconHeader_AnyIcon And SendMessage_(\ColHeader, #HDM_GETITEM, Column, item)
         PokeI(*ImageID, item\hbm)
      EndIf
      PopListPosition(\HeaderFlags())
      
      ;returns header Flags and Image if possible
      ProcedureReturn Flags
   EndWith
EndProcedure
Procedure.i GetListIconColumnOrder(Gadget, Array ColumnOrders(1))
   Protected *params.LISTICON_PARAMS=InternalListIconParams(Gadget)
   Protected *colHeader=*params\ColHeader
   Protected colCount = CountListIconColumns(Gadget), i
   
   If colCount
      ReDim ColumnOrders(colCount-1)
      Dim order.Long(colCount-1)
      If SendMessage_(*colHeader, #HDM_GETORDERARRAY, colCount, order())
         For i=0 To colCount-1 : ColumnOrders(i)=order(i)\l : Next
         ;retrieves count of columnOrders
         ProcedureReturn colCount
      EndIf
   EndIf
EndProcedure
Procedure SetListIconColumnOrder(Gadget, Array ColumnOrders(1))
   Protected *params.LISTICON_PARAMS=InternalListIconParams(Gadget)
   Protected *colHeader=*params\ColHeader
   Protected colCount = CountListIconColumns(Gadget), i
   
   If ArraySize(ColumnOrders())=colCount-1
      Protected Dim order.Long(colCount-1)
      For i=0 To colCount-1 : order(i)\l=ColumnOrders(i) : Next
      If SendMessage_(*colHeader, #HDM_SETORDERARRAY, colCount, order())
         PostEvent(#PB_Event_Gadget, #PB_All, Gadget, #PB_EventType_ReorderColumns, #PB_All)
         ;returns TRUE if successful
         ProcedureReturn #True
      EndIf
   EndIf
EndProcedure

Procedure SetListIconGroups(Gadget, Map GroupIDs(), Flags=#PB_Ignore)
   Protected *params.LISTICON_PARAMS=InternalListIconParams(Gadget)
   Protected *gadgetID=*params\GadgetID
   Protected groupName$, groupID, groupState, group.LVGROUP1
   
   With *params
      ClearMap(\GroupIDs())
      ClearMap(\GroupName$())
   EndWith
   
   If Flags<>#PB_Ignore
      If Flags & #ListIconGroups_Collapsible : groupState | #LVGS_COLLAPSIBLE : EndIf
      If Flags & #ListIconGroups_Collapsed : groupState | #LVGS_COLLAPSED : EndIf
      If Flags & #ListIconGroups_Hidden : groupState | #LVGS_HIDDEN : EndIf
   EndIf
   
   PushMapPosition(GroupIDs())
   ForEach GroupIDs()
      With group
         groupName$=MapKey(GroupIDs())
         groupID=GroupIDs()& #ListIconGroupID_MaxValue
         *params\GroupName$(""+groupID)=groupName$
         *params\GroupIDs(groupName$)=groupID
         
         \cbSize = SizeOf(LVGROUP1)
         \mask = #LVGF_GROUPID | #LVGF_ALIGN | #LVGF_STATE | #LVGF_HEADER
         \iGroupId = groupID
         \state = groupState
         \uAlign = #LVGA_HEADER_LEFT
         \pszHeader=0
         \cchHeader=0
         
         If GroupIDs()& #ListIconGroups_Collapsible : \state | #LVGS_COLLAPSIBLE : EndIf
         If GroupIDs()& #ListIconGroups_Collapsed : \state | #LVGS_COLLAPSED : EndIf
         If GroupIDs()& #ListIconGroups_Hidden : \state | #LVGS_HIDDEN : EndIf
         
         CompilerIf #PB_Compiler_Unicode = 0
            Protected groupNameUNICODE$ = Space(260*2+2)
            PokeS(@groupNameUNICODE$, groupName$, 260, #PB_Unicode)
            \pszHeader = @groupNameUNICODE$
            \cchHeader = Len(groupName$)
         CompilerElse
            \pszHeader = @groupName$
            \cchHeader = Len(groupName$)
         CompilerEndIf
         
         If SendMessage_(*gadgetID, #LVM_HASGROUP, groupID, 0)
            ;\mask=#LVGF_GROUPID | #LVGF_STATE| #LVGF_ALIGN | #LVGF_HEADER
            ;\stateMask=#LVGS_COLLAPSIBLE|#LVGS_COLLAPSED|#LVGS_HIDDEN
            ;If SendMessage_(*gadgetID, #LVM_GETGROUPINFO, groupID, group)
            ;   \mask=#LVGF_GROUPID | #LVGF_STATE| #LVGF_ALIGN | #LVGF_HEADER
            ;   \stateMask=#LVGS_COLLAPSIBLE|#LVGS_COLLAPSED|#LVGS_HIDDEN
            ;   \state=#LVGS_COLLAPSED
            ;   Debug "x"+\pszHeader+" "+\cchHeader
            ;   Debug SendMessage_(*gadgetID, #LVM_SETGROUPINFO, groupID, @group)
            ;EndIf
         Else
            SendMessage_(*gadgetID, #LVM_INSERTGROUP, -1, group)
         EndIf
      EndWith
   Next
   PopMapPosition(GroupIDs())
   
   ;returns TRUE if successful
   ProcedureReturn #True
EndProcedure
Procedure.i GetListIconGroups(Gadget, Map GroupIDs(), Flags=#PB_Ignore)
   Protected *params.LISTICON_PARAMS=InternalListIconParams(Gadget)
   Protected *gadgetID=*params\GadgetID
   Protected groupState, groupName$, groupID, group.LVGROUP1
   
   If Flags<>#PB_Ignore
      If Flags & #ListIconGroups_Collapsible : groupState | #LVGS_COLLAPSIBLE : EndIf
      If Flags & #ListIconGroups_Collapsed : groupState | #LVGS_COLLAPSED : EndIf
      If Flags & #ListIconGroups_Hidden : groupState | #LVGS_HIDDEN : EndIf
   EndIf
   
   ClearMap(GroupIDs())
   PushMapPosition(*params\GroupIDs())
   ForEach *params\GroupIDs()
      With group
         groupID=*params\GroupIDs()
         \cbSize = SizeOf(LVGROUP1)
         \mask = #LVGF_GROUPID | #LVGF_ALIGN | #LVGF_STATE | #LVGF_HEADER
         \stateMask = #LVGS_COLLAPSIBLE|#LVGS_COLLAPSED|#LVGS_HIDDEN
         \pszHeader=0
         If SendMessage_(*gadgetID, #LVM_GETGROUPINFO, groupID, group)
            If Flags=#PB_Ignore Or (\state & groupState)=groupState
               CompilerIf #PB_Compiler_Unicode = 0
                  groupName$=PeekS(\pszHeader, 260, #PB_Unicode)
               CompilerElse
                  groupName$=PeekS(\pszHeader)
               CompilerEndIf
               GroupIDs(groupName$)=groupID
               If \state & #LVGS_COLLAPSIBLE : GroupIDs()| #ListIconGroups_Collapsible : EndIf
               If \state & #LVGS_COLLAPSED : GroupIDs()| #ListIconGroups_Collapsed : EndIf
               If \state & #LVGS_HIDDEN : GroupIDs()| #ListIconGroups_Hidden : EndIf
               ;Debug \uAlign
               ;Debug \state
            EndIf
         EndIf
      EndWith
   Next
   PopMapPosition(*params\GroupIDs())
   
   ;returns GroupIDs according to state Flags (element map & count)
   ProcedureReturn MapSize(GroupIDs())
EndProcedure
Procedure.i GetListIconGroupItems(Gadget, Array GroupItems(1), GroupID=#PB_All)
   Protected *params.LISTICON_PARAMS=InternalListIconParams(Gadget)
   Protected *gadgetID=*params\GadgetID
   Protected itemPos, itemLast=CountGadgetItems(Gadget)-1, itemCount, item.LVITEM
   
   If GroupID=#PB_All
      itemCount=itemLast+1
      ReDim GroupItems(itemLast)
      For itemPos=0 To itemLast
         With item
            \mask=#LVIF_GROUPID
            \iItem=itemPos
            \iSubItem=0
            If SendMessage_(*gadgetID, #LVM_GETITEM, 0, item)
               GroupItems(itemPos)=\iGroupID
            EndIf
         EndWith
      Next
      ;returns collection of GroupID per item position (element array & count)
      ProcedureReturn itemCount
   Else
      GroupID & #ListIconGroupID_MaxValue
      For itemPos=0 To itemLast
         With item
            \mask=#LVIF_GROUPID
            \iItem=itemPos
            \iSubItem=0
            If SendMessage_(*gadgetID, #LVM_GETITEM, 0, item) And \iGroupID=GroupID
               ReDim GroupItems(itemCount)
               GroupItems(itemCount)=itemPos
               itemCount+1
            EndIf
         EndWith
      Next
      ;returns collection of Item Positions linked to GroupID (element array & count)
      ProcedureReturn itemCount
   EndIf
EndProcedure
Procedure SetListIconGroupItems(Gadget, Array GroupItems(1), GroupID=#PB_All)
   Protected *params.LISTICON_PARAMS=InternalListIconParams(Gadget)
   Protected *gadgetID=*params\GadgetID
   Protected itemPos, itemIndex, itemLast=ArraySize(GroupItems()), item.LVITEM
   
   If GroupID=#PB_All
      For itemPos=0 To itemLast
         With item
            \mask=#LVIF_GROUPID | #LVIF_STATE
            \iItem=itemPos
            \iSubItem=0
            If Not SendMessage_(*gadgetID, #LVM_GETITEM, 0, item)
               ProcedureReturn #False
            EndIf
            \iGroupID=GroupItems(itemPos)& #ListIconGroupID_MaxValue
            If Not SendMessage_(*gadgetID, #LVM_SETITEM, 0, item)
               ProcedureReturn #False
            EndIf
         EndWith
      Next
   Else
      GroupID & #ListIconGroupID_MaxValue
      For itemIndex=0 To itemLast
         With item
            itemPos=GroupItems(itemIndex)
            \mask=#LVIF_GROUPID | #LVIF_STATE
            \iItem=itemPos
            \iSubItem=0
            If Not SendMessage_(*gadgetID, #LVM_GETITEM, 0, item)
               ProcedureReturn #False
            EndIf
            \iGroupID=GroupID
            If Not SendMessage_(*gadgetID, #LVM_SETITEM, 0, item)
               ProcedureReturn #False
            EndIf
         EndWith
      Next
   EndIf
   
   ;returns TRUE if successful
   ProcedureReturn #True
EndProcedure

Procedure.i SortListIconElements(ID1, ID2, *params.LISTICON_PARAMS)
   With *params
      If \IsSortingItems
         ;default method to sort items
         
         ProcedureReturn 1
      Else
         ;default method to sort groups
         Protected name1$=\GroupName$(""+ID1)
         Protected name2$=\GroupName$(""+ID2)
         ProcedureReturn CompareMemoryString(@name1$, @name2$, #PB_String_NoCase)
      EndIf
   EndWith
EndProcedure
Procedure.i SortListIconGroups(Gadget, *SortFunction=0, *CustomData=0)
   Protected *params.LISTICON_PARAMS=InternalListIconParams(Gadget)
   With *params
      \CustomData=*CustomData
      \Gadget=Gadget
      \IsSortingItems=#False
      If *SortFunction=0 : *SortFunction=@SortListIconElements() : EndIf
      ProcedureReturn SendMessage_(\gadgetID, #LVM_SORTGROUPS, *SortFunction, *params)
   EndWith
EndProcedure
Procedure.i SortListIconGroupItems(Gadget, *SortFunction=0, *CustomData=0)
   Protected *params.LISTICON_PARAMS=InternalListIconParams(Gadget)
   With *params
      \CustomData=*CustomData
      \Gadget=Gadget
      \IsSortingItems=#True
      If *SortFunction=0 : *SortFunction=@SortListIconElements() : EndIf
      ProcedureReturn SendMessage_(\gadgetID, #LVM_SORTITEMS, *params, *SortFunction)
   EndWith
EndProcedure

Runtime Procedure InternalListIconCallback(Window, Message, wParam, lParam)
   Protected *params.LISTICON_PARAMS=InternalListIconParams(GetDlgCtrlID_(Window))
   With *params
      Protected column, headerFlags, headerImageID, mouseButton
      Protected code, *notify.NMHDR, *hdnotify.HD_NOTIFY, *column.LVCOLUMN
      Select Message
            ;Case #LVM_ARRANGE
            ;Case #LVM_UPDATE
            ;Case #LVM_REDRAWITEMS
            ;Case #LVM_SETCOLUMNWIDTH, #LVM_SETCOLUMNWIDTHA, #LVM_SETCOLUMNWIDTHW
            ;Case #LVM_SETCOLUMN, #LVM_SETCOLUMNA, #LVM_SETCOLUMNW
         Case #WM_NCDESTROY
            SetWindowLongPtr_(\GadgetID, #GWL_WNDPROC, \OriginalCallback)
            FreeMemory(*params)
            
         Case #LVM_DELETECOLUMN
            column=wParam
            PushListPosition(\HeaderFlags())
            SelectElement(\HeaderFlags(), column)
            DeleteElement(\HeaderFlags())
            PopListPosition(\HeaderFlags())
            
         Case #LVM_INSERTCOLUMN, #LVM_INSERTCOLUMNA, #LVM_INSERTCOLUMNW
            column=wParam
            PushListPosition(\HeaderFlags())
            SelectElement(\HeaderFlags(), column)
            InsertElement(\HeaderFlags())
            PopListPosition(\HeaderFlags())
            
         Case #WM_PARENTNOTIFY
            If wParam =#WM_RBUTTONDOWN
               
               
            EndIf
            
         Case #WM_NOTIFY
            *notify=lParam
            code=*notify\code
            If *notify\hwndFrom=\ColHeader
               *hdnotify=lParam
               column=*hdnotify\Iitem
               mouseButton=*hdnotify\iButton
               Select code
                  Case #NM_RCLICK
                     Protected TestHit.HD_HITTESTINFO
                     TestHit\pt\x=DesktopMouseX()
                     TestHit\pt\y=DesktopMouseY()
                     ScreenToClient_(\ColHeader, TestHit\pt)
                     column = SendMessage_(\ColHeader, #HDM_HITTEST, 0, TestHit)
                     If column>=0
                        PostEvent(#PB_Event_Gadget, #PB_All, \Gadget, #PB_EventType_HeaderRightClick, column)
                     EndIf
                     
                  Case #HDN_ITEMCHANGED, #HDN_ITEMCHANGEDW, #HDN_ITEMCHANGEDA
                     
                  Case #HDN_BEGINDRAG
                     If column>=0 And GetListIconHeader(\Gadget, column)& #ListIconHeader_NoDrag
                        SetCapture_(0)
                        ProcedureReturn 1
                     EndIf
                  Case #HDN_BEGINTRACK, #HDN_BEGINTRACKA, #HDN_BEGINTRACKW
                     If column>=0 And GetListIconHeader(\Gadget, column)& #ListIconHeader_NoManualResize
                        ProcedureReturn 1
                     EndIf
                     
                  Case #HDN_ENDDRAG
                     PostEvent(#PB_Event_Gadget, #PB_All, \Gadget, #PB_EventType_ReorderColumns, column)
                     
                  Case #HDN_ITEMCLICK, #HDN_ITEMCLICKW, #HDN_ITEMCLICKA
                     PostEvent(#PB_Event_Gadget, #PB_All, \Gadget, #PB_EventType_HeaderLeftClick, column)
                     
                     If \IsSortAuto
                        headerFlags=GetListIconHeader(\Gadget, column, @headerImageID)|#ListIconHeader_SortArrow_Changing
                        SetListIconHeader(\Gadget, column, headerFlags, headerImageID)
                     EndIf
               EndSelect
            EndIf
      EndSelect
      
      ProcedureReturn CallWindowProc_(\OriginalCallback, Window, Message, wParam, lParam)
   EndWith
EndProcedure

; ********************************
; LISTICON FEATURES
; ********************************

DisableExplicit
CompilerIf #PB_Compiler_IsMainFile
   If OpenWindow(100, 0, 0, 450, 400, "ListIcon Plus", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
      
      headerIcon=CreateImage(#PB_Any, 16, 16, 32, $34F011)
      itemIcon=CreateImage(#PB_Any, 16, 16, 32, $FE1110)
      
      ButtonGadget(30, 10, 360, 100, 20, "Report")
      ButtonGadget(31, 120, 360, 100, 20, "Large Icon")
      ButtonGadget(32, 230, 360, 100, 20, "Small Icon")
      CheckBoxGadget(33, 350, 360, 90, 20, "Group View")
      SetGadgetState(33, #True)
      
      If ListIconGadget(20, 5, 5, 440, 350, "No.", 60, PB_ListIcon_GridLines|
                                                       #PB_ListIcon_CheckBoxes|
                                                       #PB_ListIcon_HeaderDragDrop|
                                                       #PB_ListIcon_FullRowSelect|
                                                       #PB_ListIcon_AlwaysShowSelection)
         AddGadgetColumn(20, 1, "item", 100)
         AddGadgetColumn(20, 2, "price", 70)
         AddGadgetColumn(20, 3, "count", 70)
         AddGadgetItem(20, -1, "1."+#LF$+"coffee"+#LF$+"100$"+#LF$+"1"+#LF$)
         AddGadgetItem(20, -1, "2."+#LF$+"sugar"+#LF$+"200$"+#LF$+"100"+#LF$)
         AddGadgetItem(20, -1, "3."+#LF$+"banana"+#LF$+"200$"+#LF$+"2"+#LF$)
         AddGadgetItem(20, -1, "4."+#LF$+"choco"+#LF$+"20$"+#LF$+"2"+#LF$)
         AddGadgetItem(20, -1, "5."+#LF$+"big box"+#LF$+"NA"+#LF$+"NA"+#LF$, ImageID(itemIcon))
         
         AddGadgetItem(20, -1, "6."+#LF$+"big box"+#LF$+"NA"+#LF$+"NA"+#LF$, ImageID(itemIcon))
         AddGadgetItem(20, -1, "7."+#LF$+"big box"+#LF$+"NA"+#LF$+"NA"+#LF$, ImageID(itemIcon))
         AddGadgetItem(20, -1, "8."+#LF$+"big box"+#LF$+"NA"+#LF$+"NA"+#LF$, ImageID(itemIcon))
         
         SetGadgetItemColor(20, 1, #PB_Gadget_BackColor, RGB(241, 211, 72))
         SetGadgetItemState(20, 0, #True)
         
         ;set listicon header options
         SetListIconHeader(20, 0, #ListIconHeader_RightIcon, ImageID(headerIcon))
         SetListIconHeader(20, 1, #ListIconHeader_SortArrow_Down)
         SetListIconHeader(20, 2, #ListIconHeader_LeftIcon, ImageID(headerIcon))
         SetListIconHeader(20, 3, #ListIconHeader_SortArrow_Up)
         ;get listicon header options
         headerFlags=GetListIconHeader(20, 2, @headerImageID)
         If headerFlags=#ListIconHeader_LeftIcon
            Debug "Retrieve header Flags: OK"
         EndIf
         If headerImageID=ImageID(headerIcon)
            Debug "Retrieve header ImageID: OK"
         EndIf
         StartDrawing(ImageOutput(headerIcon))
         Box(2, 2, 11, 11, RGB(11, 111, 78))
         DrawImage(headerImageID, 3, 3)
         StopDrawing()
         ;get column order
         Debug "Columns="+CountListIconColumns(20)
         Dim columnOrder(0)
         GetListIconColumnOrder(20, columnOrder())
         ;set column order
         Swap columnOrder(2), columnOrder(3)
         SetListIconColumnOrder(20, columnOrder())
         
         ;enable group view mode
         Debug "GroupView is enabled="+GetListIconAttribute(20, #ListIconAttribute_GroupView)
         Debug "GroupView is enabled="+SetListIconAttribute(20, #ListIconAttribute_GroupView, #True)
         
         ;define all groups and sort all groups
         NewMap groups()
         groups("Other")=200 | #ListIconGroups_Collapsed
         groups("Food")=100
         groups("Unknown")=80
         groups("B")=10
         groups("C")=11
         groups("Z")=5
         SetListIconGroups(20, groups(), #ListIconGroups_Collapsible)
         
         NewMap findGroups()
         Debug "Collapsed Groups="+GetListIconGroups(20, findGroups(), #ListIconGroups_Collapsed)+" / "+CountListIconGroups(20)
         
         ;assign items to FOOD groups
         Dim itemsToAssign(2)
         itemsToAssign(0)=0
         itemsToAssign(1)=1
         itemsToAssign(2)=2
         SetListIconGroupItems(20, itemsToAssign(), groups("Food"))
         Debug "Items assigned To FOOD group="+GetListIconGroupItems(20, itemsToAssign(), groups("Food"))
         
         ;assign items to OTHER groups
         ReDim itemsToAssign(0)
         itemsToAssign(0)=4
         SetListIconGroupItems(20, itemsToAssign(), groups("Other"))
         Debug "Items assigned To OTHER group="+GetListIconGroupItems(20, itemsToAssign(), groups("Other"))
         
         ReDim itemsToAssign(0)
         itemsToAssign(0)=5
         SetListIconGroupItems(20, itemsToAssign(), groups("B"))
         ReDim itemsToAssign(0)
         itemsToAssign(0)=6
         SetListIconGroupItems(20, itemsToAssign(), groups("C"))
         ReDim itemsToAssign(0)
         itemsToAssign(0)=7
         SetListIconGroupItems(20, itemsToAssign(), groups("Z"))
         
         ;sort all groups and items
         SortListIconGroups(20)
         SortListIconGroupItems(20)
         Debug "AutoSort is enabled="+GetListIconAttribute(20, #ListIconAttribute_SortAuto)
         Debug "AutoSort is enabled="+SetListIconAttribute(20, #ListIconAttribute_SortAuto, #True)
      EndIf
      
      Repeat
         e=WaitWindowEvent()
         g=EventGadget()
         t=EventType()
         w=EventWindow()
         pos=GetGadgetState(20)
         info=EventData()
         
         If e=#PB_Event_Gadget
            If g=30 : SetGadgetAttribute(20, #PB_ListIcon_DisplayMode, #PB_ListIcon_Report) : EndIf
            If g=31 : SetGadgetAttribute(20, #PB_ListIcon_DisplayMode, #PB_ListIcon_LargeIcon) : EndIf
            If g=32 : SetGadgetAttribute(20, #PB_ListIcon_DisplayMode, #PB_ListIcon_SmallIcon) : EndIf
            If g=33 And t=#PB_EventType_LeftClick
               Debug "GroupView is enabled="+SetListIconAttribute(20, #ListIconAttribute_GroupView, GetGadgetState(33))
            EndIf
            
            If g=20
               If t=#PB_EventType_Change
                  Debug "Selected item="+pos+" => "+GetGadgetItemText(20, pos, 0)+" "+GetGadgetItemText(20, pos, 1)
               ElseIf t=#PB_EventType_LeftClick
                  Debug "Collapsed Groups="+GetListIconGroups(20, findGroups(), #ListIconGroups_Collapsed)+" / "+CountListIconGroups(20)
               ElseIf t=#PB_EventType_HeaderLeftClick
                  Debug "Selected column="+info+" => "+GetGadgetItemText(20, -1, info)
               ElseIf t=#PB_EventType_ReorderColumns
                  If EventData()=#PB_All
                     GetListIconColumnOrder(20, columnOrder())
                     For i=0 To ArraySize(columnOrder()) : order$+columnOrder(i)+", " : Next
                     Debug "Reordered column=ALL => order: "+order$
                  Else
                     Debug "Reordered column="+info+" => "+GetGadgetItemText(20, -1, info)
                  EndIf
               EndIf
            EndIf
         EndIf
      Until e=#PB_Event_CloseWindow
   EndIf
CompilerEndIf
Last edited by eddy on Sun Jul 28, 2013 7:16 pm, edited 23 times in total.
Imagewin10 x64 5.72 | IDE | PB plugin | Tools | Sprite | JSON | visual tool
rsts
Addict
Addict
Posts: 2736
Joined: Wed Aug 24, 2005 8:39 am
Location: Southwest OH - USA

Re: PB5.2 : ListIcon Order-Group-Sort-Arrow-HeaderIcon

Post by rsts »

Another dandy!

Thanks for sharing :D
User avatar
eddy
Addict
Addict
Posts: 1479
Joined: Mon May 26, 2003 3:07 pm
Location: Nantes

Re: PB5.2 : ListIcon Group,Reorder,Sort,Arrow,HeaderIcon

Post by eddy »

Updated
2013/07/28
- added: GetListIconAttribute
  • #ListIconAttribute_AvailableColumnWidth (use to fill last column width)
- updated: Add/RemoveGadgetColumn() supported
- updated: Get/SetListIconHeader (options to lock columns)
  • #ListIconHeader_NoManualResize
    #ListIconHeader_NoAutoResize
2013/07/27
- added: new listicon event types
  • #PB_EventType_HeaderClick (EventData() retrieves the selected column)
    #PB_EventType_ReorderColumns (EventData() retrieves the selected column or #PB_All)
- added: Get/SetListIconAttribute
  • #ListIconAttribute_GroupView
    #ListIconAttribute_SortAuto
    #ListIconAttribute_SortMultiColumn
- updated: column header arrow: change when clicking (only if #ListIconAttribute_SortAuto attribute is enabled)
- updated: Get/SetListIconHeader (rename constants)
  • #ListIconHeader_NoDrag
    #ListIconHeader_NoResize
2013/07/26
- added: Get/SetListIconHeader
  • #ListIconHeader_None
    #ListIconHeader_SortArrow_Up
    #ListIconHeader_SortArrow_Down
    #ListIconHeader_LeftIcon
    #ListIconHeader_RightIcon
- added: Get/SetListIconGroups
  • #ListIconGroups_Collapsed
    #ListIconGroups_Collapsible
    #ListIconGroups_Hidden
- added: Get/SetListIconGroupItems
- added: Get/SetListIconColumnOrder
Last edited by eddy on Sun Jul 28, 2013 5:52 pm, edited 5 times in total.
Imagewin10 x64 5.72 | IDE | PB plugin | Tools | Sprite | JSON | visual tool
User avatar
eddy
Addict
Addict
Posts: 1479
Joined: Mon May 26, 2003 3:07 pm
Location: Nantes

Re: PB5.2 : ListIcon Group,Reorder,Sort,Arrow,HeaderIcon

Post by eddy »

Image

Code: Select all

; *****************************************************
; LISTICON COLUMN CONSTRAINTS AND AUTORESIZING
; *****************************************************

DisableExplicit
CompilerIf #PB_Compiler_IsMainFile
   If OpenWindow(100, 0, 0, 510, 200, "Test - Column header special flags", #PB_Window_SystemMenu|
                                                                            #PB_Window_SizeGadget|
                                                                            #PB_Window_MaximizeGadget|
                                                                            #PB_Window_ScreenCentered)
      SmartWindowRefresh(100, #True)
      headerIcon=CreateImage(#PB_Any, 16, 16, 32, $34F011)
      
      If ListIconGadget(20, 5, 5, 500, 100, "No Drag", 60, #PB_ListIcon_HeaderDragDrop|#PB_ListIcon_FullRowSelect)
         ;enable listicon auto sort when clicking colmun header
         SetListIconAttribute(20, #ListIconAttribute_SortAuto, #True)
         ;enable multi-columns sort arrows
         SetListIconAttribute(20, #ListIconAttribute_SortMultiColumn, #True)
         
         ;add columns and fill last column (specify column header options)
         AddGadgetColumn(20, 1, "No Manual Resize", 80)
         AddGadgetColumn(20, 2, "No Auto Resize", 90)
         AddGadgetColumn(20, 3, "Normal", GetListIconAttribute(20, #ListIconAttribute_AvailableColumnWidth))
         SetListIconHeader(20, 0, #ListIconHeader_LeftIcon|
                                  #ListIconHeader_NoDrag, ImageID(headerIcon))
         SetListIconHeader(20, 1, #ListIconHeader_RightIcon|
                                  #ListIconHeader_NoManualResize, ImageID(headerIcon))
         SetListIconHeader(20, 2, #ListIconHeader_SortArrow_Up|
                                  #ListIconHeader_NoAutoResize)
         
         ;add items
         For i=1 To 100
            AddGadgetItem(20, -1, ""+i+"."+#LF$+"Product"+#LF$+Random(200)+"$"+#LF$+Random(10)+#LF$, ImageID(CreateImage(#PB_Any, 16, 16, 32, Random($FFFFFF))))
         Next
         
      EndIf
      Repeat
         e=WaitWindowEvent()
         If e=#PB_Event_SizeWindow
            ResizeGadget(20, #PB_Ignore, #PB_Ignore, WindowWidth(100)-10, WindowHeight(100)-50)
            SetListIconAttribute(20, #ListIconAttribute_AvailableColumnWidth, 0)   ;<--- auto resize  columns
         EndIf
      Until e=#PB_Event_CloseWindow
   EndIf
CompilerEndIf
Image

Code: Select all

; ********************************
; LISTICON EVENTS
; ********************************

DisableExplicit
CompilerIf #PB_Compiler_IsMainFile
   If OpenWindow(100, 0, 0, 510, 200, "Test - Column header special flags", #PB_Window_SystemMenu|
                                                                            #PB_Window_MaximizeGadget|
                                                                            #PB_Window_ScreenCentered)
      SmartWindowRefresh(100, #True)
      headerIcon=CreateImage(#PB_Any, 16, 16, 32, $34F011)
      
      If CreatePopupMenu(0)
         MenuItem(1, "Sort UP")
         MenuItem(2, "Sort DOWN")
         MenuItem(3, "Filter...")
         MenuBar()
         OpenSubMenu("Options")
         MenuItem(4, "Show Icons")
         MenuItem(5, "Show Labels")
         CloseSubMenu()
      EndIf
      
      NewMap findGroups()
      Dim columnOrder(0)
      
      If ListIconGadget(20, 5, 5, 500, 190, "Fixed", 60, #PB_ListIcon_HeaderDragDrop|#PB_ListIcon_FullRowSelect)
         ;enable listicon auto sort when clicking colmun header
         SetListIconAttribute(20, #ListIconAttribute_SortAuto, #True)
         ;enable multi-columns sort arrows
         SetListIconAttribute(20, #ListIconAttribute_SortMultiColumn, #True)
         
         ;add columns
         AddGadgetColumn(20, 1, "Col1 (with menu)", 80)
         AddGadgetColumn(20, 2, "Col2 (with menu)", 90)
         AddGadgetColumn(20, 3, "Col3 (with menu)", 100)
         
         ;set column header options
         SetListIconHeader(20, 0, #ListIconHeader_LeftIcon|
                                  #ListIconHeader_NoDrag|
                                  #ListIconHeader_NoManualResize, ImageID(headerIcon))
         
         
         ;add groups and enable group view mode
         NewMap groupIDs()
         groupIDs("BIG")=100
         groupIDs("SMALL")=101
         groupIDs("TINY")=102
         groupIDs("MEDIEUM")=103 | #ListIconGroups_Collapsed
         SetListIconGroups(20, groupIDs(), #ListIconGroups_Collapsible)
         SetListIconAttribute(20, #ListIconAttribute_GroupView, #True)
         
         ;add items into groups
         Dim groupItems(100)
         For i=0 To ArraySize(groupItems())
            AddGadgetItem(20, -1, ""+i+"."+#LF$+"Product"+#LF$+Random(200)+"$"+#LF$+Random(10)+#LF$, ImageID(CreateImage(#PB_Any, 16, 16, 32, Random($FFFFFF))))
            groupItems(i)=Random(102, 100)
         Next
         SetListIconGroupItems(20, groupItems())
         
         ;auto size columns to fit gadget width
         SetListIconAttribute(20, #ListIconAttribute_AvailableColumnWidth, 0)
         
         ;reorder columns 
         GetListIconColumnOrder(20, columnOrder())
         SetListIconColumnOrder(20, columnOrder())
      EndIf
      
      Repeat
         e=WaitWindowEvent()
         g=EventGadget()
         t=EventType()
         w=EventWindow()
         pos=GetGadgetState(20)
         
         If e=#PB_Event_Gadget            
            If g=20
               column=EventData()         
               If t=#PB_EventType_Change
                  Debug "Selected item="+pos+" => "+GetGadgetItemText(20, pos, 0)+" "+GetGadgetItemText(20, pos, 1)
               ElseIf t=#PB_EventType_LeftClick                  
                  Debug "Collapsed Groups="+GetListIconGroups(20, findGroups(), #ListIconGroups_Collapsed)+" / "+CountListIconGroups(20)
               ElseIf t=#PB_EventType_HeaderLeftClick
                  Debug "Left Click column header="+column+" => "+GetGadgetItemText(20, -1, column)
               ElseIf t=#PB_EventType_HeaderRightClick
                  Debug "Right Click column header="+column+" => "+GetGadgetItemText(20, -1, column)
                  If column>0
                     DisplayPopupMenu(0,WindowID(GetActiveWindow()))
                  EndIf                   
               ElseIf t=#PB_EventType_ReorderColumns
                  If EventData()=#PB_All
                     GetListIconColumnOrder(20, columnOrder())
                     For i=0 To ArraySize(columnOrder()) : order$+columnOrder(i)+", " : Next
                     Debug "Reordered column=ALL => order: "+order$
                  Else
                     Debug "Reordered column="+column+" => "+GetGadgetItemText(20, -1, column)
                  EndIf
               EndIf
            EndIf
         EndIf 
      Until e=#PB_Event_CloseWindow
   EndIf
CompilerEndIf
Last edited by eddy on Sun Jul 28, 2013 7:13 pm, edited 7 times in total.
Imagewin10 x64 5.72 | IDE | PB plugin | Tools | Sprite | JSON | visual tool
User avatar
eddy
Addict
Addict
Posts: 1479
Joined: Mon May 26, 2003 3:07 pm
Location: Nantes

Re: PB5.2: ListIcon Group,Order,HeaderIcon,SortArrow,FillCol

Post by eddy »

updated
- auto size columns
- updated: example above
- improvement: add push/poplistposition() to prevent infinite loop
Imagewin10 x64 5.72 | IDE | PB plugin | Tools | Sprite | JSON | visual tool
Rjevsky
User
User
Posts: 23
Joined: Tue Jul 18, 2017 3:41 pm

Re: PB5.2: ListIcon Group,Order,HeaderIcon,SortArrow,FillCol

Post by Rjevsky »

Hello! The group crash if ListIconGadget with #PB_ListIcon_GridLines
Post Reply