ListIcon Search and Select matching text

Share your advanced PureBasic knowledge/code with the community.
User avatar
einander
Enthusiast
Enthusiast
Posts: 744
Joined: Thu Jun 26, 2003 2:09 am
Location: Spain (Galicia)

ListIcon Search and Select matching text

Post by einander »

Code: Select all

;ListIcon Search and Select matching text
;PB 4.02 - Windows only
;By einander
;Based on Sparkie's Multicolor ListIcon Gadget 
;http://www.purebasic.fr/english/viewtopic.php?T=19237&highlight=multicolor+listicon

Structure LIGSearch
    Row.l
    Column.l
    TextRGB.l
    BackRGB.l
    SearchString.S
    Info.l
    Input.l
EndStructure

#LVM_GETSUBITEMRECT = $1038 

Global  _LIGSearch.LIGSearch
Global _LIG , NewList _Searched.l(), NewList _Aux.l()

_LIGSearch\TextRGB=$FF0033
_LIGSearch\BackRGB=$EBF2D8

Procedure$ RandomStr(Maxlen=20)  ; make martian text
    For i= 0 To Random(Maxlen)+1 
        A$+Chr(Random(25)+97)
        If i=5 :A$+" ":EndIf
    Next
    ProcedureReturn A$
EndProcedure 

Procedure ApiGetTextWidth(A$)
    ProcedureReturn  SendMessage_(GadgetID(_LIG), #LVM_GETSTRINGWIDTH, 0, @A$)
EndProcedure 

Procedure APIGetCharPos(A$,POS)
    ProcedureReturn ApiGetTextWidth(Left(A$,POS-1)) 
EndProcedure 

Procedure APIDetachText(DC,*rc.RECT,A$,B$,TextRGB,BackRGB)
    SetBkMode_(DC,#OPAQUE) 
    SetTextColor_(DC,TextRGB): SetBkColor_(DC,BackRGB)
    DrawText_(DC,A$,-1,*rc,#DT_NOCLIP)  ;detach whole item 
    FS=1
    SetTextColor_(DC,BackRGB):SetBkColor_(DC,TextRGB) ; invert colors
    x=*rc\left
    Repeat
        FS=FindString(A$,B$,FS)
        If FS=0:Break:EndIf
        *rc\left =x+APIGetCharPos(A$,FS)
        DrawText_(DC,B$,-1,*rc,#DT_NOCLIP)  ; detach B$
        FS+Len(B$)
    ForEver
EndProcedure 

Procedure CallBack(hwnd, msg, wParam, lParam)
    RESULT = #PB_ProcessPureBasicEvents
    Select msg
        Case #WM_NOTIFY
            *nmhdr.NMHDR = lParam
            If *nmhdr\code = #NM_CUSTOMDRAW And *nmhdr\hwndFrom = GadgetID(_LIG)
                *lvCD.NMLVCUSTOMDRAW = lParam
                Select *lvCD\nmcd\dwDrawStage  
                    Case #CDDS_PREPAINT :  RESULT = #CDRF_NOTIFYITEMDRAW
                    Case #CDDS_ITEMPREPAINT :  RESULT = #CDRF_NOTIFYSUBITEMDRAW
                    Case #CDDS_ITEMPREPAINT | #CDDS_SUBITEM :  RESULT = #CDRF_NOTIFYPOSTPAINT
                    Case #CDDS_ITEMPOSTPAINT | #CDDS_SUBITEM
                        ForEach _Aux()    
                            If *lvCD\nmcd\dwItemSpec =_Aux() And  *lvCD\iSubItem =_LIGSearch\Column  ;If Row & Column
                                Item$ = GetGadgetItemText(_LIG,_Aux(), *lvCD\iSubItem)     ; -->  item text
                                ColumnRc.RECT\left = #LVIR_LABEL+_LIGSearch\Column=0     ; -->  item rect
                                DC=*lvCD\nmcd\hdc
                                ColumnRc\top = *lvCD\iSubItem
                                SendMessage_(*lvCD\nmcd\hdr\hwndFrom, #LVM_GETSUBITEMRECT, *lvCD\nmcd\dwItemSpec, @ColumnRc)
                                If *lvCD\iSubItem = 0 :  ColumnRc\left + (GetSystemMetrics_(#SM_CXEDGE) * 3) - 2  ;  --> Adjust left margin
                                Else :  ColumnRc\left + GetSystemMetrics_(#SM_CXEDGE) * 3
                                EndIf
                                SearchString.S=_LIGSearch\SearchString
                                APIDetachText(DC,@ColumnRc,Item$,SearchString,_LIGSearch\TextRGB,_LIGSearch\BackRGB) 
                            EndIf
                        Next
                        RESULT= #CDRF_SKIPDEFAULT
                EndSelect
            EndIf
    EndSelect
    ProcedureReturn RESULT
EndProcedure
 

Macro RedrawLIG(LIG) ;-  RedrawLIG(LIG) ; redraw lListIconGadget
    SendMessage_(GadgetID(LIG), #LVM_REDRAWITEMS, 0, CountGadgetItems(LIG)-1)
EndMacro

Macro GadgetBottom(GAD) :  GadgetY(GAD)+GadgetHeight(GAD) : EndMacro
Macro GadgetRight(GAD) :  GadgetX(GAD)+GadgetWidth(GAD) : EndMacro

Procedure   SearchRow(Row)  
    If CountList(_Searched())
        SelectElement(_Searched(),Row)
        SendMessage_(GadgetID(_LIG), #LVM_GETITEMPOSITION, _Searched(), pt.POINT) ; get item position 
        SendMessage_(GadgetID(_LIG), #LVM_SCROLL, pt\x, pt\y - 150)     ; scroll to item position 
        sItem.LVITEM\mask      = #LVIF_STATE 
        sItem\state     = #LVIS_SELECTED 
        sItem\stateMask = #LVIS_SELECTED 
        SendMessage_(GadgetID(_LIG), #LVM_SETITEMSTATE, _Searched() , sItem)    ; set item state as selected      
        SelectElement(_Searched(),Row)  :  SetGadgetText(_LIGSearch\Info,Str(ListIndex(_Searched())+1)+" of "+Str(CountList(_Searched()))+ " Matches Found")
    Else :  SetGadgetText(_LIGSearch\Info,"No Matches") 
    EndIf
    RedrawLIG(_LIG)    
    SetActiveGadget(_LIGSearch\Input)
 EndProcedure 

Procedure   SearchLIGString(Row=1) 
    ClearList(_Aux()) : ClearList (_Searched())
    For i = 0 To CountGadgetItems(_LIG) - 1 
        If FindString(GetGadgetItemText(_LIG, i, _LIGSearch\Column),_LIGSearch\SearchString,1) 
            AddElement(_Aux()):AddElement(_Searched())
            _Aux()=i:_Searched()=i
        EndIf 
    Next 
    SearchRow(Row)
EndProcedure 

  ;Test it   <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
hwnd=OpenWindow(0, 100, 100,800,500 ,"Search Matching text",#WS_OVERLAPPEDWINDOW| #PB_Window_ScreenCentered)
StickyWindow(0,1)
CreateGadgetList(hwnd)
_LIG=ListIconGadget(-1, 5, 5, 710, WindowHeight(0)*0.75, "Column 0", 200, #PB_ListIcon_AlwaysShowSelection | #PB_ListIcon_FullRowSelect)
  
SetGadgetFont(_LIG, _MyFontMedium)
AddGadgetColumn(_LIG, 1, "Column 1", 200)
AddGadgetColumn(_LIG, 2, "Column 2", 200)

TextTitle=TextGadget(-1,10,GadgetBottom(_LIG)+10,200,16,"Search text")
FG=Frame3DGadget(-1,GadgetRight(TextTitle)+10,GadgetBottom(_LIG)+20,100,84,"Search in")
_LIGSearch\Input=StringGadget(-1, 10, GadgetBottom(TextTitle), 200, 30, ""     ) 
ColGad0=OptionGadget(-1,GadgetX(FG)+5,GadgetY(FG)+20,90,20,"Column 0"): SetGadgetData(ColGad0,0)
ColGad1=OptionGadget(-1,GadgetX(FG)+5,GadgetY(ColGad0)+20,90,20,"Column 1"):SetGadgetData(ColGad1,1)
ColGad2=OptionGadget(-1,GadgetX(FG)+5,GadgetY(ColGad1)+20,90,20,"Column 2"):SetGadgetData(ColGad2,2)
SetGadgetState(ColGad0,1)
_LIGSearch\Info=TextGadget(-1, 10, GadgetBottom(_LIGSearch\Input)+4, 200, 18, "", #PB_Text_Border ) 
BtnPrev=ButtonGadget(-1,10,GadgetBottom(_LIGSearch\Info)+4,95,20,"Prev")
BtnNext=ButtonGadget(-1,110,GadgetBottom(_LIGSearch\Info)+4,95,20,"Next")

SetGadgetFont(_LIGSearch\Input, _MyFontMediumBig)

For i = 0 To 13000   ; Fill the ListiconGadget
    AddGadgetItem(_LIG, -1, Str(i)+" "+RandomStr(50) + Chr(10) + RandomStr(50) +Chr(10)+RandomStr(50))
Next

SetWindowCallback(@CallBack())
SetActiveGadget(_LIGSearch\Input)

Repeat
    EV = WaitWindowEvent()
    Select EV
        Case #PB_Event_Gadget 
            Eventgadget=EventGadget()
            Select Eventgadget
                Case _LIGSearch\Input  
                    
                    _LIGSearch\SearchString=GetGadgetText(_LIGSearch\Input)
                    If Len(_LIGSearch\SearchString) 
                   
                        If _LIGSearch\SearchString<>OldSearch.S
                            SearchLIGString(0)
                            OldSearch=_LIGSearch\SearchString
                        EndIf
                    Else
                        ClearList(_Searched()):ClearList(_Aux())
                        Selected=1
                    EndIf
                Case ColGad0 To ColGad2
                    _LIGSearch\Column=GetGadgetData(Eventgadget)
                    SearchLIGString(0)
                    SetActiveGadget(_LIGSearch\Input)
                Case BtnPrev 
                    If  PreviousElement(_Searched())=0 : LastElement(_Searched()) : EndIf
                    SearchRow(ListIndex(_Searched()))
                Case BtnNext
                    If NextElement(_Searched())=0 :  FirstElement(_Searched()) : EndIf
                    SearchRow(ListIndex(_Searched()))
            EndSelect
    EndSelect
    If  CountList(_Searched())=0 And Selected
        Selected=0
        SetGadgetState(_LIG,-1)
        SetGadgetText(_LIGSearch\Info,"")
        OldSearch.S=""
    EndIf     
Until EV = #WM_CLOSE
End

    
    
 
rsts
Addict
Addict
Posts: 2736
Joined: Wed Aug 24, 2005 8:39 am
Location: Southwest OH - USA

Post by rsts »

Nice one.

Thanks for sharing.

cheers
Post Reply