It is currently Mon Apr 06, 2020 7:16 am

All times are UTC + 1 hour




Post new topic Reply to topic  [ 2 posts ] 
Author Message
 Post subject: Cross plattform multiple email address autocomplete
PostPosted: Mon Nov 12, 2012 7:55 am 
Offline
Addict
Addict
User avatar

Joined: Mon Jun 06, 2005 2:35 pm
Posts: 1223
Location: germany
Hi,

I just want to share my multiple email address autocomplete code. To enter, simply type the address. To finish some input (dividing addresses) type comma (,), semicolon (;) or a blank ( ).

It works by using a ordinary StringGadget and simply adding the following to your event loop (adapt to your needs):
Code:
If EventGadget() = MyStringGadgetID.i And EventType() = #PB_EventType_Change
  AutoCompleteStringGadget(MyStringGadgetID.i, MailAddressesLinkedList())
EndIf


Complete code and example implementation:
Code:
EnableExplicit

CompilerIf #PB_Compiler_OS = #PB_OS_MacOS
  CompilerIf #PB_Compiler_Version < 470 Or (#PB_Compiler_Version >= 500 And Subsystem("Carbon"))
    ImportC ""
      GetControlData(ControlRef.L, ControlPartCode.L, TagName.L, BufferSize.L, *Buffer, *ActualSize)
      SetControlData(ControlRef.L, ControlPartCode.L, TagName.L, BufferSize.L, *Buffer)
    EndImport
   
    #kControlEditTextPart = 5
    #kControlEditTextSelectionTag = $73656C65
   
    Structure ControlEditTextSelectionRec
      SelStart.W
      SelEnd.W
    EndStructure
  CompilerElse
    Global NSRangeZero.NSRange
    Procedure.i acTextEditor(Gadget.i)
      Protected TextField.i = GadgetID(Gadget)
      Protected Window.i = CocoaMessage(0, TextField, "window")
      ProcedureReturn CocoaMessage(0, Window, "fieldEditor:", #YES, "forObject:", TextField)
    EndProcedure
  CompilerEndIf
CompilerEndIf

; Sets the selection in a StringGadget() independent of Operating System
; If Start.i < 1, every selection is removed.
; If Length.i = 0, only the cursor is set.
Procedure SetStringGadgetSelection(GadgetID.i, Start.i, Length.i)
  If Start.i > 0 And Length.i > -1
    ; Set selection
    CompilerSelect #PB_Compiler_OS
      CompilerCase #PB_OS_Windows
        SendMessage_(GadgetID(GadgetID), #EM_SETSEL, Start.i - 1, Start.i + Length.i - 1)
      CompilerCase #PB_OS_Linux
        gtk_editable_select_region_(GadgetID(GadgetID), Start - 1, Start -1 + Length)
      CompilerCase #PB_OS_MacOS
        CompilerIf #PB_Compiler_Version < 470 Or (#PB_Compiler_Version >= 500 And Subsystem("Carbon"))
          Protected TextSelection.ControlEditTextSelectionRec
          TextSelection\selStart = Start - 1
          TextSelection\selEnd = Start -1 + Length
          SetControlData(GadgetID(GadgetID), #kControlEditTextPart, #kControlEditTextSelectionTag, SizeOf(ControlEditTextSelectionRec), @TextSelection)
        CompilerElse
          Protected Range.NSRange\location = Start - 1 : Range\length = Length
          CocoaMessage(0, acTextEditor(GadgetID), "setSelectedRange:@", @Range)
        CompilerEndIf
    CompilerEndSelect
  Else
    ; Deselect all
    CompilerSelect #PB_Compiler_OS
      CompilerCase #PB_OS_Windows
        SendMessage_(GadgetID(GadgetID.i), #EM_SETSEL, -1, 0)
      CompilerCase #PB_OS_Linux
        gtk_editable_delete_selection_(GadgetID(GadgetID))
      CompilerCase #PB_OS_MacOS
        CompilerIf #PB_Compiler_Version < 470 Or (#PB_Compiler_Version >= 500 And Subsystem("Carbon"))
          TextSelection\selStart = -1
          TextSelection\selEnd = -1
          SetControlData(GadgetID(GadgetID), #kControlEditTextPart, #kControlEditTextSelectionTag, SizeOf(ControlEditTextSelectionRec), @TextSelection)
        CompilerElse
          CocoaMessage(0, acTextEditor(GadgetID), "setSelectedRange:@", @NSRangeZero)
        CompilerEndIf
    CompilerEndSelect
  EndIf
EndProcedure

Procedure.i GetStringGadgetSelectionStart(GadgetID.i)
  ; Get selection
  Protected Start.i = 0
  Protected Stop.i = 0
  CompilerSelect #PB_Compiler_OS
    CompilerCase #PB_OS_Windows
      SendMessage_(GadgetID(GadgetID.i), #EM_GETSEL, @Start.i, @Stop.i)
      ProcedureReturn Start.i + 1
    CompilerCase #PB_OS_Linux
      gtk_editable_get_selection_bounds_(GadgetID(GadgetID), @Start, @Stop)
      ProcedureReturn Start + 1
    CompilerCase #PB_OS_MacOS
      CompilerIf #PB_Compiler_Version < 470 Or (#PB_Compiler_Version >= 500 And Subsystem("Carbon"))
        Protected TextSelection.ControlEditTextSelectionRec
        GetControlData(GadgetID(GadgetID), #kControlEditTextPart, #kControlEditTextSelectionTag, SizeOf(ControlEditTextSelectionRec), @TextSelection.ControlEditTextSelectionRec, 0)
        ProcedureReturn TextSelection\SelStart + 1
      CompilerElse
        Protected Range.NSRange
        CocoaMessage(@Range, acTextEditor(GadgetID), "selectedRange")
        ProcedureReturn Range\location + 1
      CompilerEndIf
  CompilerEndSelect
EndProcedure

Procedure.i GetStringGadgetSelectionLength(GadgetID.i)
  ; Get selection
  Protected Start.i = 0
  Protected Stop.i = 0
  CompilerSelect #PB_Compiler_OS
    CompilerCase #PB_OS_Windows
      SendMessage_(GadgetID(GadgetID), #EM_GETSEL, @Start.i, @Stop.i)
      ProcedureReturn Stop.i - Start.i
    CompilerCase #PB_OS_Linux
      gtk_editable_get_selection_bounds_(GadgetID(GadgetID), @Start, @Stop)
      ProcedureReturn Stop - Start
    CompilerCase #PB_OS_MacOS
      CompilerIf #PB_Compiler_Version < 470 Or (#PB_Compiler_Version >= 500 And Subsystem("Carbon"))
        Protected TextSelection.ControlEditTextSelectionRec
        GetControlData(GadgetID(GadgetID), #kControlEditTextPart, #kControlEditTextSelectionTag, SizeOf(ControlEditTextSelectionRec), @TextSelection.ControlEditTextSelectionRec, 0)
        ProcedureReturn TextSelection\SelEnd - TextSelection\SelStart
      CompilerElse
        Protected Range.NSRange
        CocoaMessage(@Range, acTextEditor(GadgetID), "selectedRange")
        ProcedureReturn Range\length
      CompilerEndIf
  CompilerEndSelect
EndProcedure

Procedure.i AutoCompleteFindStringRev(String$, StringToFind$, StringToFind2$ = "", StringToFind3$ = "")
  Protected x.i = 0
  String$ = UCase(String$)
  StringToFind$ = UCase(StringToFind$)
  StringToFind2$ = UCase(StringToFind2$)
  StringToFind3$ = UCase(StringToFind3$)
  For x.i = Len(String$) To 1 Step -1
    If Mid(String$, x.i, Len(StringToFind$)) = StringToFind$
      ProcedureReturn x.i
    EndIf
    If Mid(String$, x.i, Len(StringToFind2$)) = StringToFind2$
      ProcedureReturn x.i
    EndIf
    If Mid(String$, x.i, Len(StringToFind3$)) = StringToFind3$
      ProcedureReturn x.i
    EndIf
  Next
  ProcedureReturn 0
EndProcedure

Procedure AutoCompleteStringGadget(strGadgID.i, List Options.s())
  Static NewMap LastLength.i()
  Static NewMap LastAddress.s()
  Protected StandardDivider.s = ","
  Protected TempText.s        = ""
  Protected RightChar.s       = ""
  Protected Offset.i          = 1
  Protected Left.i            = 0
  Protected Part.s            = ""
  Protected Content.s         = GetGadgetText(strGadgID.i)
 
  Left.i = AutoCompleteFindStringRev(Content.s, ",", ";", " ")
  If Left.i > 0: Offset.i = Left.i + 1: EndIf
  Part.s = UCase(Trim(Mid(Content.s, Offset.i)))
 
  If Len(Content.s) > LastLength(Str(strGadgID.i))
    RightChar.s = Right(Content.s, 1)
    If LastAddress(Str(strGadgID.i)) <> "" And (RightChar.s = "," Or RightChar.s = ";" Or RightChar.s = " ")
      Left.i = AutoCompleteFindStringRev(Left(Content.s, Left.i - 1), ",", ";", " ")
      Offset.i  = 1
      If Left.i > 0: Offset.i = Left.i + 1: EndIf
      TempText.s = Left(Content.s, Offset.i - 1) + Options() + StandardDivider.s
      SetGadgetText(strGadgID.i, TempText.s)
      SetStringGadgetSelection(strGadgID.i, Len(TempText.s) + 1, 0)
      LastAddress(Str(strGadgID.i)) = ""
    EndIf
    If Len(Part.s) > 0
      LastAddress(Str(strGadgID.i)) = ""
      ForEach Options()
        If Left(UCase(Options()), Len(Part.s)) = Part.s
          TempText.s = Left(Content.s, Offset.i - 1) + Options()
          SetGadgetText(strGadgID.i, TempText.s)
          SetStringGadgetSelection(strGadgID.i, Offset.i + Len(Part.s), 500)
          LastAddress(Str(strGadgID.i)) = Options()
          Break
        EndIf
      Next
    EndIf
  EndIf
  LastLength(Str(strGadgID.i)) = Len(Content.s) 
EndProcedure

; EXAMPLE USAGE:
; ================================================================================

NewList MailAddresses.s()
AddElement(MailAddresses())
MailAddresses() = "apple@company.com"
AddElement(MailAddresses())
MailAddresses() = "apple2@company.com"
AddElement(MailAddresses())
MailAddresses() = "berry@company.com"
AddElement(MailAddresses())
MailAddresses() = "peach@company.com"
AddElement(MailAddresses())
MailAddresses() = "banana@company.com"

If OpenWindow(0, 200, 300, 395, 160, "PureBasic Window", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
 
  Define strGadgID.i = StringGadget(#PB_Any, 10, 10, 380, 26, "")
  Define btnGadgID.i = ButtonGadget(#PB_Any, 10, 40, 380, 26, "Button")
 
  SetActiveGadget(strGadgID.i)
 
  Repeat
    Define Event.i = WaitWindowEvent()
   
    If Event.i = #PB_Event_CloseWindow
      Define Quit.i = 1
    EndIf
    If Event.i = #PB_Event_Gadget
      Define et.i = EventType()
      Define gd.i = EventGadget()
     
      If gd.i = strGadgID.i And et.i = #PB_EventType_Change
        AutoCompleteStringGadget(gd.i, MailAddresses())
      EndIf
    EndIf
  Until Quit.i = 1
EndIf
End


It works on Windows, MacOS X and Linux. I tested on Windows 7, MacOS 10.7 and Ubuntu 11.04.

Any enhancements welcome :-)

Kukulkan


Last edited by Kukulkan on Mon Nov 12, 2012 4:38 pm, edited 1 time in total.

Top
 Profile  
Reply with quote  
 Post subject: Re: Cross plattform multiple email address autocomplete
PostPosted: Mon Nov 12, 2012 3:30 pm 
Offline
Addict
Addict
User avatar

Joined: Wed Feb 17, 2010 12:00 am
Posts: 1324
Location: (Embarrassed to say country)
Nicely done....Thanks for sharing.


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 2 posts ] 

All times are UTC + 1 hour


Who is online

Users browsing this forum: Derren and 6 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  

 


Powered by phpBB © 2008 phpBB Group
subSilver+ theme by Canver Software, sponsor Sanal Modifiye