Avoid duplicate keywords in a combobox

Share your advanced PureBasic knowledge/code with the community.
User avatar
flaith
Enthusiast
Enthusiast
Posts: 704
Joined: Mon Apr 25, 2005 9:28 pm
Location: $300:20 58 FC 60 - Rennes
Contact:

Avoid duplicate keywords in a combobox

Post by flaith »

For my project, I need to enter keywords, keep only the last 10 of them and avoid duplicate keywords in my combo.

Here is the code I'm using :

Code: Select all

EnableExplicit

Enumeration
  #SEARCH_WIN
  #SEARCH_COMBO
  #SEARCH_BUTTON_OK
EndEnumeration

Procedure.i CheckAddItem(__Item.s, List __lKeywords.s())
  Protected.i _posItem = 0, _index = 0, _Found = #False, _indexInList = ListSize(__lKeywords())
  
  If _indexInList > 0
    ForEach __lKeywords()
      If __lKeywords() = __Item
        _Found   = #True
        Break
      EndIf
      _posItem + 1
    Next
    
    If Not _Found
      AddElement(__lKeywords())
        __lKeywords() = __Item
    EndIf
  Else
    ; First time use, need to add
    AddElement(__lKeywords())
      __lKeywords() = __Item
  EndIf
  
  ;Populate the combobox  
  ClearGadgetItems(#SEARCH_COMBO)
  
  ;Get the last 10 max keywords in the combobox
  ResetList(__lKeywords())
  For _index = 1 To 10
    If NextElement(__lKeywords())
      AddGadgetItem(#SEARCH_COMBO, -1, __lKeywords())
    EndIf
  Next

  ; Set the item in the combobox if found
  If _Found : Debug _posItem : SetGadgetState(#SEARCH_COMBO, _posItem) : EndIf
  ProcedureReturn _posItem
EndProcedure

Procedure SearchDB()
  Protected.i _Quit = #False, _PosItem = 0
  Protected.s NewList _lKeywords()

  If OpenWindow(#SEARCH_WIN, 0, 0, 270, 180, "Adding unique value inside ComboBox", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
    ComboBoxGadget(#SEARCH_COMBO, 10, 10, 220, 21, #PB_ComboBox_Editable|#PB_ComboBox_LowerCase)
      AddGadgetItem(#SEARCH_COMBO, -1, "")
    ButtonGadget(#SEARCH_BUTTON_OK, 230, 9, 30, 23, "Ok")

    SetGadgetState(#SEARCH_COMBO, 0)
    SetActiveGadget(#SEARCH_COMBO)

    Repeat 
      Select WaitWindowEvent()
        Case #PB_Event_CloseWindow
          _Quit = #True
        Case #WM_KEYDOWN
          Select EventwParam()
            Case #VK_RETURN
              _PosItem = CheckAddItem(GetGadgetText(#SEARCH_COMBO), _lKeywords())
              SetActiveGadget(#SEARCH_COMBO)
              Debug GetGadgetItemText(#SEARCH_COMBO, _PosItem)
            Case #VK_ESCAPE
              _Quit = #True
          EndSelect
        Case #PB_Event_Gadget
          Select EventGadget()
            Case #SEARCH_BUTTON_OK
              _PosItem = CheckAddItem(GetGadgetText(#SEARCH_COMBO), _lKeywords())
              SetActiveGadget(#SEARCH_COMBO)
              Debug GetGadgetItemText(#SEARCH_COMBO, _PosItem)
          EndSelect
      EndSelect
    Until _Quit
  EndIf
EndProcedure

SearchDB()
“Fear is a reaction. Courage is a decision.” - WC
User avatar
Kiffi
Addict
Addict
Posts: 1504
Joined: Tue Mar 02, 2004 1:20 pm
Location: Amphibios 9

Re: Avoid duplicate keywords in a combobox

Post by Kiffi »

IMO there is no need to use a linkedlist:

Code: Select all

Procedure CheckAddItem2(NewKeyword.s)
	
	Protected Counter, Found
	
	For Counter = 0 To CountGadgetItems(#SEARCH_COMBO) - 1
		If GetGadgetItemText(#SEARCH_COMBO, Counter) = NewKeyword
			Found = #True
			Break
		EndIf
	Next
	
	If Not Found
		AddGadgetItem(#SEARCH_COMBO, -1, NewKeyword)
		SetGadgetState(#SEARCH_COMBO, 0)
	EndIf
	
EndProcedure
_Greetings ... __Kiffi
Hygge
User avatar
flaith
Enthusiast
Enthusiast
Posts: 704
Joined: Mon Apr 25, 2005 9:28 pm
Location: $300:20 58 FC 60 - Rennes
Contact:

Re: Avoid duplicate keywords in a combobox

Post by flaith »

:D Thanks a lot Kiffi

Actually, for my project, I need to keep each keywords for the next time we will execute the application, so I keep it in a linked list :wink:
“Fear is a reaction. Courage is a decision.” - WC
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Re: Avoid duplicate keywords in a combobox

Post by netmaestro »

Very quick and easy way to avoid duplicates, I usually use it to count actual number of colors used in an image but there are many applications for this simple and fast device:

Code: Select all

Global NewMap words.b()

Procedure CheckAdd(word.s)
  If Not FindMapElement(words(), word)
    words(word) = 1
    AddElement(...[]
BERESHEIT
User avatar
flaith
Enthusiast
Enthusiast
Posts: 704
Joined: Mon Apr 25, 2005 9:28 pm
Location: $300:20 58 FC 60 - Rennes
Contact:

Re: Avoid duplicate keywords in a combobox

Post by flaith »

Thanks for the tip netmaestro :)
Actually, it seems my code didn't work as expected, means that the itemindex is different.
Because I just want to keep the last 10 keywords.
I select the last keywords inserted and populate the combobox from the last list. So I think I need to do that before checking the new keywords, and add it if he's not in the list. More code to do :oops: :wink:
“Fear is a reaction. Courage is a decision.” - WC
User avatar
flaith
Enthusiast
Enthusiast
Posts: 704
Joined: Mon Apr 25, 2005 9:28 pm
Location: $300:20 58 FC 60 - Rennes
Contact:

Re: Avoid duplicate keywords in a combobox

Post by flaith »

New version :

Code: Select all

EnableExplicit

#KEEP_MAX_IN_COMBO    = 20

Enumeration
  #SEARCH_WIN
  #SEARCH_COMBO
  #SEARCH_BUTTON_OK
EndEnumeration

Structure CS_KEYWORD
  IndexInList.i
  Keyword.s
EndStructure

Procedure.i CheckAddItem(__Item.s, List __lKeywords.CS_KEYWORD())
  Protected.i _posItem = 0, _index = 0, _Found = #False, _indexInList = ListSize(__lKeywords())
  Protected.s NewList _lTemp.CS_KEYWORD()

  For _posItem = 0 To CountGadgetItems(#SEARCH_COMBO) - 1
    If GetGadgetItemText(#SEARCH_COMBO, _posItem) = __Item
      _Found   = #True
      Break
    EndIf
  Next

  If Not _Found
    AddElement(__lKeywords())
      __lKeywords()\Keyword     = __Item
      __lKeywords()\IndexInList = _indexInList
    AddGadgetItem(#SEARCH_COMBO, -1, __Item)
  EndIf
  SortStructuredList(__lKeywords(), #PB_Sort_Descending, OffsetOf(CS_KEYWORD\IndexInList), TypeOf(CS_KEYWORD\IndexInList))

  ;Get the last #KEEP_MAX_IN_COMBO max keywords in the combobox
  If _indexInList > 0
    ResetList(__lKeywords())
    For _index = 1 To #KEEP_MAX_IN_COMBO
      If NextElement(__lKeywords())
        AddElement(_lTemp())
          _lTemp()\IndexInList = __lKeywords()\IndexInList
          _lTemp()\Keyword     = __lKeywords()\Keyword
      EndIf
    Next

    ;Populate the combobox
    ClearGadgetItems(#SEARCH_COMBO)
    ForEach _lTemp()
      AddGadgetItem(#SEARCH_COMBO, -1, _lTemp()\Keyword)
    Next
  EndIf
  
  ;Need to make a second check with the new items in the combo
  _Found = #False
  For _posItem = 0 To CountGadgetItems(#SEARCH_COMBO) - 1
    If GetGadgetItemText(#SEARCH_COMBO, _posItem) = __Item
      _Found   = #True
      Break
    EndIf
  Next
  
  If Not _Found
    ;Select first item
    SetGadgetState(#SEARCH_COMBO, 0)
  Else
    SetGadgetState(#SEARCH_COMBO, _posItem)
  EndIf
  
  ProcedureReturn _posItem
EndProcedure

Procedure SearchDB()
  Protected.i _Quit = #False, _PosItem = 0
  Protected.s NewList _lKeywords.CS_KEYWORD()

  If OpenWindow(#SEARCH_WIN, 0, 0, 270, 180, "Adding unique value inside ComboBox", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
    ComboBoxGadget(#SEARCH_COMBO, 10, 10, 220, 21, #PB_ComboBox_Editable|#PB_ComboBox_LowerCase)
      AddGadgetItem(#SEARCH_COMBO, -1, "")
    ButtonGadget(#SEARCH_BUTTON_OK, 230, 9, 30, 23, "Ok")

    SetGadgetState(#SEARCH_COMBO, 0)
    SetActiveGadget(#SEARCH_COMBO)

    Repeat 
      Select WaitWindowEvent()
        Case #PB_Event_CloseWindow
          _Quit = #True
        Case #WM_KEYDOWN
          Select EventwParam()
            Case #VK_RETURN
              _PosItem = CheckAddItem(GetGadgetText(#SEARCH_COMBO), _lKeywords())
              SetActiveGadget(#SEARCH_COMBO)
            Case #VK_ESCAPE
              _Quit = #True
          EndSelect
        Case #PB_Event_Gadget
          Select EventGadget()
            Case #SEARCH_BUTTON_OK
              _PosItem = CheckAddItem(GetGadgetText(#SEARCH_COMBO), _lKeywords())
              SetActiveGadget(#SEARCH_COMBO)
          EndSelect
      EndSelect
    Until _Quit
  EndIf
EndProcedure

SearchDB()
Because I'm late in my project (1 month already :P ), I didn't optimize the code
If you know how, I will be grateful :wink:
“Fear is a reaction. Courage is a decision.” - WC
User avatar
Joakim Christiansen
Addict
Addict
Posts: 2452
Joined: Wed Dec 22, 2004 4:12 pm
Location: Norway
Contact:

Re: Avoid duplicate keywords in a combobox

Post by Joakim Christiansen »

Kiffi wrote:_Greetings ... __Kiffi
:lol:
I see what you did there!
I like logic, hence I dislike humans but love computers.
IdeasVacuum
Always Here
Always Here
Posts: 6426
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: Avoid duplicate keywords in a combobox

Post by IdeasVacuum »

Actually, for my project, I need to keep each keywords for the next time we will execute the application
So, use Kiffy's simple code. on exit from your application, simply save the contents of the combo to a file - which can be read and loaded next time the app is run.
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
User avatar
flaith
Enthusiast
Enthusiast
Posts: 704
Joined: Mon Apr 25, 2005 9:28 pm
Location: $300:20 58 FC 60 - Rennes
Contact:

Re: Avoid duplicate keywords in a combobox

Post by flaith »

Indeed :wink:
“Fear is a reaction. Courage is a decision.” - WC
Post Reply