Page 1 of 1

ListIcon Sorting

Posted: Mon Oct 04, 2004 2:08 pm
by Num3
Would be nice to have some sort of built in procedure to attach a sorting routine when one clicks on the ListIcon Header...

Something like:

If event=#PB_ListIcon_HeaderClick
If EventType()=Column#x
ListIconSortProcedure(#List,@UserSortingProcedure)
endif
endif

Posted: Mon Oct 04, 2004 2:14 pm
by blueznl
yep, i could use that...

Posted: Mon Oct 04, 2004 2:39 pm
by Dare2
Agree.

Posted: Tue Oct 05, 2004 4:19 pm
by naw
That would be nice for lots of gadgets - ComboBoxes / ListIconGadget / ListViewGadget.

I would like to have Sort(#Gid, PrimaryField, SecondaryField...)

Until then, I found this by Danilo

viewtopic.php?t=9113

I just about got it working with *different* Gadget IDs but I dont really understand the code...

Posted: Tue Oct 05, 2004 4:41 pm
by Num3
naw wrote:That would be nice for lots of gadgets - ComboBoxes / ListIconGadget / ListViewGadget.

I would like to have Sort(#Gid, PrimaryField, SecondaryField...)

Until then, I found this by Danilo

viewtopic.php?t=9113

I just about got it working with *different* Gadget IDs but I dont really understand the code...
I've been using this code...

Shame it does not work for numbers :(

Posted: Tue Oct 05, 2004 6:09 pm
by naw
Did you *adapt* it so that it works with other Gadget IDs. I tried, but - well- I just cant get those pesky arrows to display...

:-(

Posted: Fri Oct 08, 2004 8:43 pm
by MrMat
Num3 wrote:Shame it does not work for numbers :(
Do you mean sorting by number instead of by the string? If so change change the two lines

Code: Select all

If A$ > B$
to

Code: Select all

If Val(A$) > Val(B$)
or ValF for floats and it should compare them as you want.

Add my vote for something like this to be built in, including adding the arrows to the column headers :D

Posted: Sat Oct 09, 2004 10:57 am
by Num3
MrMat wrote:
Num3 wrote:Shame it does not work for numbers :(
Do you mean sorting by number instead of by the string? If so change change the two lines

Code: Select all

If A$ > B$
to

Code: Select all

If Val(A$) > Val(B$)
or ValF for floats and it should compare them as you want.

Add my vote for something like this to be built in, including adding the arrows to the column headers :D
Man, you just solved me a 3 week problem!
I was using linked list to sort tables, now i can use the gadget itself for sorting!!!

Thanks!

Re: ListIcon Sorting

Posted: Mon Oct 11, 2004 11:55 am
by naw
Num3 wrote:Would be nice to have some sort of built in procedure to attach a sorting routine when one clicks on the ListIcon Header...

Something like:

If event=#PB_ListIcon_HeaderClick
If EventType()=Column#x
ListIconSortProcedure(#List,@UserSortingProcedure)
endif
endif
Better still, would be:

Code: Select all

ListIconGadget(0,0,0,500,200,"",0,#PB_Sortable)

Posted: Mon Oct 11, 2004 1:22 pm
by RJP Computing
Can we get a posting of the updated code. That would be very helpful.

Thanks

Posted: Wed Oct 13, 2004 8:04 am
by blueznl
naw, yeah, we'd best have both, so programs can do a standard sort after filling the list, but allow the user to change the on screen display (by marking the columns as sortable that's solved :-))

arrows... oh, the little triangles... yes, of course :-)

Posted: Wed Oct 13, 2004 4:39 pm
by MrMat
I've changed the sorting code so that it works equally well with strings and integers and modified the data in the columns to demonstrate this. It'll also intermix uppercase and lowercase strings so if you don't like that change ucasea.s = UCase(A$) and ucaseb.s = UCase(B$) to ucasea.s = A$ and ucaseb.s = B$. Best way to see is to try it:

Code: Select all

;
; ListIconGagdet column header images
; with image switching
;
; by Danilo, 11.01.2004
;
;
; credits:
;   - sort function from PureArea.net code archive,
;     file  : ListIcon_SortbyColumn.pb
;     writer: unknown
;
Procedure CreateListIconArrows(StartImage)
  ; by Danilo, 11.01.2004
  ;
  ; generate 2 small 16x16 arrows, up & down
  ;
  For img = 0 To 1
    CreateImage(StartImage+img,16,16)
    StartDrawing(ImageOutput())
    background = GetSysColor_(#COLOR_BTNFACE)
    FrontColor(Red(background),Green(background),Blue(background))
    Box(0,0,16,16)
    If img = 0 : Start=7 : Else : Start = 2 : EndIf
    For a = 6 To 10
      Line(Start,a,13-Start*2,0,0)
      Start+1
    Next a
    StopDrawing()
  Next
EndProcedure


Procedure AddListIconColumn(gadget,pos,width,align,text$,hImage)
  ; by Danilo, 11.01.2004
  ;
  ; Add column to ListIconGadget
  ;
  ;   gadget = the PB gadget number
  ;   pos    = position of the new column
  ;   width  = with     of the new column
  ;   align  = align    of the text in the column:
  ;            #LI_CENTERED, #LI_LEFT, #LI_RIGHT
  ;   text$  = column header text
  ;   hImage = image handle __OR__ index of already added image!
  ;
  #LVCF_IMAGE = $10
  #LVCFMT_COL_HAS_IMAGES = $8000
  #LI_CENTERED = #LVCFMT_CENTER
  #LI_LEFT     = #LVCFMT_LEFT
  #LI_RIGHT    = #LVCFMT_RIGHT
  Structure LVCOLUMN
    lv.LV_COLUMN
    iImage.l
    iOrder.l
  EndStructure
  If GetObjectType_(hImage)=#OBJ_BITMAP
    ; Add Image to List
    hImgL = SendMessage_(GadgetID(gadget),#LVM_GETIMAGELIST,#LVSIL_SMALL,0)
    If hImgL=0
      hImgL = ImageList_Create_(16,16,#ILC_COLOR32,1,1)
      SendMessage_(GadgetID(gadget),#LVM_SETIMAGELIST,#LVSIL_SMALL,hImgL)
    EndIf
    idx = ImageList_Add_(hImgL,hImage,0)
  Else
    ; was an index
    idx = hImage
  EndIf
  LVC.LVCOLUMN
  LVC\lv\mask = #LVCF_IMAGE|#LVCF_TEXT|#LVCF_WIDTH|#LVCF_FMT
  LVC\lv\fmt     = align|#LVCFMT_COL_HAS_IMAGES
  LVC\lv\pszText = @text$
  LVC\lv\cchTextMax = Len(text$)
  LVC\lv\iSubItem = pos
  LVC\lv\cx   = width
  LVC\iImage  = idx
  LVC\iOrder  = pos
  SendMessage_(GadgetID(gadget),#LVM_INSERTCOLUMN,pos,@LVC)
EndProcedure


Procedure GetListIconColumnImage(gadget,column)
  ; by Danilo, 11.01.2004
  ;
  ; returns the image_index of the column-header-image
  ;
  LVC.LVCOLUMN
  LVC\lv\mask = #LVCF_IMAGE
  SendMessage_(GadgetID(gadget),#LVM_GETCOLUMN,column,@LVC)
  ProcedureReturn LVC\iImage
EndProcedure


Procedure ChangeListIconColumnImage(gadget,column,Image_Index)
  ; by Danilo, 11.01.2004
  ;
  ; change the image_index of the column-header-image
  ;
  LVC.LVCOLUMN
  LVC\lv\mask = #LVCF_IMAGE
  LVC\iImage  = Image_Index
  ProcedureReturn SendMessage_(GadgetID(gadget),#LVM_SETCOLUMN,column,@LVC)
EndProcedure


Procedure SetListIconColumnText(gadget,index,Text$)
  ; by Danilo, 15.12.2003 - english chat (for 'Karbon')
  ;
  ; change column header text
  ;
  lvc.LV_COLUMN
  lvc\mask    = #LVCF_TEXT
  lvc\pszText = @Text$
  SendMessage_(GadgetID(gadget),#LVM_SETCOLUMN,index,@lvc)
EndProcedure


Procedure SetListIconColumnWidth(gadget,index,new_width)
  ; by Danilo, 15.12.2003 - english chat (for 'Karbon')
  ;
  ; change column header width
  ;
  SendMessage_(GadgetID(gadget),#LVM_SETCOLUMNWIDTH,index,new_width)
EndProcedure


Procedure SetListIconColumnFormat(gadget,index,format)
  ; by Danilo, 15.12.2003 - english chat (for 'Karbon')
  ;
  ; change text alignment for columns
  ;
  lvc.LV_COLUMN
  lvc\mask = #LVCF_FMT
  Select format
  Case 0: lvc\fmt = #LVCFMT_LEFT
  Case 1: lvc\fmt = #LVCFMT_CENTER
  Case 2: lvc\fmt = #LVCFMT_RIGHT
  EndSelect
  SendMessage_(GadgetID(gadget),#LVM_SETCOLUMN,index,@lvc)
EndProcedure




Procedure UpdatelParam(ListIconGadget,columns)
  ;
  ; PureArea.net CodeArchiv, by unknown
  ;
  ; modified by Danilo, 11.01.2004
  ;
  ItemCount = SendMessage_(ListIconGadget, #LVM_GETITEMCOUNT, 0, 0)
  lvi.LV_ITEM
  lvi\mask = #LVIF_PARAM
  lvi\iItem = 0
  While ItemCount>0
    lvi\lParam = lvi\iItem
    For SubItem = 0 To columns-1
      lvi\iSubItem = SubItem
      SendMessage_(ListIconGadget, #LVM_SETITEM, 0, @lvi)
    Next SubItem
    lvi\iItem +1
    ItemCount -1
  Wend
EndProcedure


Procedure ListIconSortFunction(lParam1,lParam2,lParamSort)
  ;
  ; PureArea.net CodeArchiv, by unknown
  ;
  ; modified by Danilo, 11.01.2004
  ;
  A$ = Space(200)
  B$ = Space(200)
  result = 0
  lvi.LV_ITEM
  lvi\iSubItem = lParamSort&$FFFF
  lvi\pszText = @A$
  lvi\cchTextMax = 200
  lvi\mask = #LVIF_TEXT
  SendMessage_(GadgetID(0), #LVM_GETITEMTEXT,lParam1,@lvi)
  lvi\pszText = @B$
  SendMessage_(GadgetID(0), #LVM_GETITEMTEXT,lParam2,@lvi)
  
  If A$ = B$
    ProcedureReturn 0 ; equal
  EndIf
  
  x = (lParamSort>>16)&$FFFF
  ucasea.s = UCase(A$)
  ucaseb.s = UCase(B$)
  vala.l = Val(ucasea)
  valb.l = Val(ucaseb)
  If x
    x = 1
  Else
    x = -1
  Endif
  If (vala = 0 And A$<>"0") Or (valb = 0 And B$<>"0")
    If ucasea > ucaseb
      ProcedureReturn  x
    Else
      ProcedureReturn -x
    EndIf
  Else
    If vala > valb
      ProcedureReturn  x
    Else
      ProcedureReturn -x
    EndIf
  Endif
  ProcedureReturn result
EndProcedure




;
;- Window Callback
;
Procedure WinProc(hWnd,Msg,wParam,lParam)
  result = #PB_ProcessPureBasicEvents
  Select Msg
  Case #WM_NOTIFY
    *NMHDR.NMHDR = lParam
    If *NMHDR\hWndFrom = GadgetID(0) ; comes from our ListIconGadget
      If *NMHDR\code = #LVN_COLUMNCLICK
        *NMLV.NMLISTVIEW = lParam
        column = *NMLV\iSubItem
        ; switch images:
        index  = GetListIconColumnImage(0,column)
        ChangeListIconColumnImage(0,column,index!1)
        ; sort
        SendMessage_(GadgetID(0),#LVM_SORTITEMS,column|((index)<<16),@ListIconSortFunction())
        UpdatelParam(GadgetID(0),5)
      EndIf
    EndIf
  EndSelect
  ProcedureReturn result
EndProcedure


;
;- program start
;
CreateListIconArrows(0)

OpenWindow(0,0,0,500,200,#PB_Window_SystemMenu|#PB_Window_ScreenCentered,"LV")
SetWindowCallback(@WinProc())
CreateGadgetList(WindowID())
ListIconGadget(0,0,0,500,200,"",0,#PB_ListIcon_FullRowSelect|#PB_ListIcon_AlwaysShowSelection)
AddListIconColumn(0,1,150,#LI_LEFT    ,"Column 1",UseImage(0)) ; add Image 0
AddListIconColumn(0,2,120,#LI_CENTERED,"Column 2",UseImage(1)) ; add Image 1
AddListIconColumn(0,3, 90,#LI_CENTERED,"Column 3",0)           ; use Image index 0
AddListIconColumn(0,4,105,#LI_RIGHT   ,"Column 4",1)           ; use Image index 1

For a = 0 To 100
  A$ = "COLUMN 1, Row "+RSet(Str(  a  ),3,"0")
  length.b = 5 + Random(10)
  B$=""
  For loop = 1 To length
    B$ + Chr(65 + Random(60))
  Next
  C$ = Str(Random(10000))
  If a % 2 = 0
    D$ = B$
  Else
    D$ = C$
  EndIf
  AddGadgetItem(0,-1,Chr(10)+A$+Chr(10)+B$+Chr(10)+C$+Chr(10)+D$)
Next

UpdatelParam(GadgetID(0),5)

Repeat:Until WaitWindowEvent()=#PB_Event_CloseWindow
It'll be a tiny bit slower than the original routine but hopefully it isn't noticeable (at least with smallish lists... :roll:)

Posted: Wed Oct 20, 2004 1:19 pm
by naw
MrMat,

Thank you - will be using this a lot....

Posted: Thu Oct 21, 2004 1:30 am
by MrMat
My pleasure! Danilo did all the hard work though, so thank you Danilo! :-D

Posted: Thu Oct 21, 2004 9:03 pm
by Denis
I send a piece of code on french forum with a listicon (like explorergadget but only with one folder). I explain how to sort the listicon but its in french.

May be it could help you.


http://purebasic.hmt-forum.com/viewtopic.php?t=1652

This code use my Lib MoreListiconGadget