| daspamer Grandmaster Cheater Supreme
 
  Reputation: 54 
 Joined: 13 Sep 2011
 Posts: 1588
 
 
 | 
			
				|  Posted: Sun Feb 02, 2020 11:03 pm    Post subject: ComboBox Suggested Items/Search functionality |   |  
				| 
 |  
				| Well came up with a solution for drop-down list. Having 50-80 items in a list and looking for specific ones can be annoying a bit especially when you don't exactly remember the name or when the autocomplete suggests a different ones without the option to view what other could partly match...
 
 
 Anyway this is an example that narrows our item list by alphanumeric text, until user has found the target or has pressed enter, then it will reset the list.
 
 When clicking on text area if a current text is a valid item it will clear it, clicking on dropdown will display the previous available items (if did not narrow it down to 1, otherwise the complete list);
 
 basically take it as it is, and only modifiy/add stuff the onChange procedure at the doAction call area...
 
 heres a demo try writing example or word and select item (narrow the list or just whatever...)
 
 NOTE: tried to explain what was I doing and in general the logic behind this, if it does not work as you hoped to or didn't understand something feel free to post or pm me.
 
 
 
  	  | Code: |  	  | local myItems = {    'Some word'; 'Another Word';
 'Well heres a thing';
 'Another thing';
 'I got this';
 'You got this';
 'Just an Example';
 'Example 1';
 'Example2';
 'Example 4 ';
 'Example - 7 and some randoma$$ words that our capture dont care about';
 };
 
 itemList = itemList or createStringList();
 itemList.clear();
 -- prepare our static stringlist that holds our items;
 -- NOTE: we shouldn't assign directly to checkbox items as we manipulate them by removing and adding items to it, and once remove we cannot retrieve it from itself..
 for _,line in pairs(myItems) do
 itemList.add(line);
 end
 
 
 local doAction = function(sender,item)
 local isExample,number = item:lower():match('(example).-([%d]*)[%D]*$') -- capture example and attempt to capture number if exists;
 if (isExample) then
 local color = 0xFF;
 local ratio = 0x10;
 if (tonumber(number)) then
 color = color - ratio * number;
 end
 sender.Color = tonumber(("%02X%02X%02X"):format(color,color,color),16);
 elseif (item:lower():find('word',0,true)) then -- third paramter for plain
 showMessage(item)
 end
 
 end
 
 
 local f = createForm();
 f.borderStyle = 'bsSizeable'
 local cb = createComboBox(f);
 cb.items = itemList;      -- assign our items ...
 cb.AutoDropDown = true;      -- when user clicks on the text a dropdown with all our items opens...
 cb.AutoComplete = false;   -- just annoying and does not work good... we better just force our user to type the correct letter;
 cb.DropDownCount = 15;      -- suit as you think..
 cb.top = 10;
 cb.left = 10;
 cb.width = f.width - cb.left * 2;
 
 
 
 cb.onKeyPress = function(sender,key)
 local _key = string.byte(key)
 local text = sender.Text;
 local items = sender.Items;
 local itemsText = items.Text:lower();
 if (_key == 8) then   -- backspace.. so let's remove last character; we can't tell if user highlighted whole text and tries to delete it.. so we gonna delete the text whenever user has clicked..
 _key = 0;
 text = text:sub(0,#text-1);
 elseif (_key == 13) then -- enter we do not really care
 return nil;
 else   -- prevent from user write a letter that do not match of the items that left;
 text = text .. key;
 if (not itemsText:find(text:lower(),0,true)) then -- does not exist so abort;
 return nil;
 end
 end
 local ourText = text:lower();
 -- if its a character or number then proceed checking and attempt to remove irrelevant items.. we can add here space and special symbols as well...
 if ((#text >= 0) and ( (_key >= 0x30 and _key <=0x39) or ( _key >= 0x41 and _key <= 0x5A) or ( _key >= 0x61 and _key <=0x7A))) then
 for i=items.Count-1,0,-1 do
 if(not items.String[i]:lower():find(ourText,0,true)) then
 items.delete(i)
 end
 end
 else   -- if its not a number or letter (backspace for example) try to re-add items from original list;
 for i=0,itemList.Count-1 do
 local cdl_s = itemList.String[i]:lower()
 if(cdl_s:find(ourText,0,true) and not itemsText:find(cdl_s,0,true)) then
 items.add(itemList.String[i])
 end
 end
 end
 sender.DropDownCount = 15; -- when removing item our DropDownCount changes but does not increase when adding back items... so we have to update it;
 return key
 end
 cb.onKeyUp = function(sender,key)
 if (key == 13) then -- let user to select first item by pressing enter;
 sender.Text = sender.items.String[0];
 sender.onChange(sender);
 return nil;
 end
 return key
 end
 cb.onMouseUp = function(sender,button,x,y)
 -- clean up text as user just pressed the text area if a valid item is selected...
 -- it seems that the dropdown arrow is 18 pixel (win10 64bit fhd monitor wih normal dpi) so if we do not click it then clear the text;
 if (button == 0 and sender.ItemIndex >= 0 and (x <= cb.width - 18)) then
 sender.clear();
 sender.Items = itemList;
 end
 end
 cb.onChange = function(sender)
 -- this part of the code tries to auto automatically select item if we have only 1 item available, and filteres invalid text given
 if (sender.Items.Count == 1 ) then   -- try to auto assign if only 1 item left..
 local str = sender.items.String[0]
 sender.Text = str;
 sender.Items = itemList;   -- re-assign our item list so we could dropdown and see items in the order we set it && and full item list...
 elseif (sender.Items.Count > 1) then
 sender.ItemIndex = sender.Items.indexOf(sender.Text); -- re update itemindex in case somewhat it has invalid text and a change event triggered;
 end
 if (sender.ItemIndex < 0) then   -- do not contiue if we do not have valid item (probably manually assigned itemIndex or bad text)
 return
 end
 -- Item successfully has been selected successfully now we can do our ting
 -- Lets work with current item and call doAction that will either change our ComboBox color or display a message as we wrote above...
 local text = sender.Text;
 doAction(sender,text);
 end
 | 
 
 Edit:
 Removed some unnecessary actions..
 _________________
 
 I'm rusty and getting older, help me re-learn lua. |  |