Page 1 of 1

Re: Cross plattform StringGadget text selection

Posted: Thu Nov 01, 2012 3:34 pm
by Shardik
I have added support for Linux and MacOS X with Carbon framework (PB 4.61 and older or PB 5.00 with subsystem Carbon):

Code: Select all

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 ; 'sele'
    
    Structure ControlEditTextSelectionRec
      SelStart.W
      SelEnd.W
    EndStructure
  CompilerElse
    Global NSRangeZero.NSRange
    Procedure.i TextEditor(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, TextEditor(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, TextEditor(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, TextEditor(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, TextEditor(GadgetID), "selectedRange")
        ProcedureReturn Range\length
      CompilerEndIf
  CompilerEndSelect
EndProcedure

If OpenWindow(0, 200, 300, 195, 160, "PureBasic Window", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
 
  Define strGadgID.i = StringGadget(#PB_Any, 10, 10, 180, 20, "Testcontent")
 
  SetActiveGadget(strGadgID.i)
 
  SetStringGadgetSelection(strGadgID.i, 3, 4) ; mark 4 characters beginning with the 3rd character
 
  Debug "Cursor before " + Str(GetStringGadgetSelectionStart(strGadgID.i))
  Debug "Marked characters: " + Str(GetStringGadgetSelectionLength(strGadgID.i))
 
  Repeat
    Define Event.i = WaitWindowEvent()
    If Event.i = #PB_Event_CloseWindow
      Define Quit.i = 1
    EndIf
  Until Quit.i = 1
EndIf
End
Update: I had to change

Code: Select all

#kControlEditTextSelectionTag = 'sele'
to

Code: Select all

#kControlEditTextSelectionTag = $73656C65 ; 'sele'
for the Carbon code in order to work correctly with both ASCII and Unicode compilation.

Re: Cross plattform StringGadget text selection

Posted: Fri Nov 02, 2012 7:58 am
by Kukulkan
Wow, just tested the last version of Shardik on Windows and Mac OS and it works great! Linux will get tested today, too.

Thank you! :D

I plan to do some autocomplete stringgadget for entering (multiple) email addresses. If ready, I will post the source here in the forum (based on this code).

Kukulkan

Re: Cross plattform StringGadget text selection

Posted: Fri Nov 02, 2012 8:42 am
by Shardik
Kukulkan wrote:Wow, just tested the last version of Shardik on Windows and Mac OS and it works great!
I forgot to say that I took wilbert's version with added MacOS X Cocoa support (default setting in PB 5.00) and added MacOS X Carbon support plus Linux. Did you test both Cocoa and Carbon versions on MacOS X? :wink:

Re: Cross plattform StringGadget text selection

Posted: Fri Nov 02, 2012 9:41 am
by Kukulkan
No, I just tested Cocoa method as I only compile with this.

I just tested now and it does not work with Carbon subsystem. It marks the whole text and GetStringGadgetSelectionLength() result is also wrong :(

Kukulkan

Re: Cross plattform StringGadget text selection

Posted: Fri Nov 02, 2012 10:21 am
by Shardik
Kukulkan wrote:I just tested now and it does not work with Carbon subsystem. It marks the whole text and GetStringGadgetSelectionLength() result is also wrong :(
Sorry to hear that! With which MacOS X version did you test? I tested with Snow Leopard (10.6.8 ) and the results of Cocoa and Carbon (PB 4.61 and PB 5.00 x86 with subsystem Carbon) were both identical (and the same as in Windows and Linux)...

Re: Cross plattform StringGadget text selection

Posted: Fri Nov 02, 2012 10:24 am
by wilbert
@Kukulkan, a little remark about my SetStringGadgetSelection cocoa code with Start < 1.
My current solution clears the selection and sets the cursor to the beginning of the text.
I don't know exactly what your goal is but if you want the focus on the Gadget also gone, there's a better way to accomplish that with.

Re: Cross plattform StringGadget text selection

Posted: Fri Nov 02, 2012 11:14 am
by Kukulkan
Hi,
With which MacOS X version did you test?
I'm using MacOS 10.7.4 (Lion).
My current solution clears the selection and sets the cursor to the beginning of the text. I don't know exactly what your goal is but if you want the focus on the Gadget also gone, there's a better way to accomplish that with.
No, keeping focus is good! If someone does not need, he can use SetActiveGadget() function.

Kukulkan

Re: Cross plattform StringGadget text selection

Posted: Fri Nov 02, 2012 2:20 pm
by Shardik
Kukulkan wrote:I just tested now and it does not work with Carbon subsystem. It marks the whole text and GetStringGadgetSelectionLength() result is also wrong :(
Kukulkan wrote:I'm using MacOS 10.7.4 (Lion).
Sorry, but I can't reproduce your described Carbon error neither in MacOS X 10.6.8 (Snow Leopard) nor in MacOS X 10.7.5 (Lion) using PB 4.61 and PB 5.00 x86 Beta 6 and Beta 8 with subsystem Carbon! I always obtain this result (the same as with Cocoa, Linux and Windows):

Image

Re: Cross plattform StringGadget text selection

Posted: Fri Nov 02, 2012 2:50 pm
by Kukulkan
This is how it looks on my Lion with "Subsystem = Carbon" run from IDE:

Image

I'm using PB 5.00 Beta 7

Kukulkan

Re: Cross plattform StringGadget text selection

Posted: Fri Nov 02, 2012 6:36 pm
by Shardik
I think I have solved our Carbon problem: I assume you have activated "Create unicode executable" in the Compiler Options. With unicode compilation I obtain the same result as you have documented... :wink:

I only had to change

Code: Select all

#kControlEditTextSelectionTag = 'sele'
in my above code to

Code: Select all

#kControlEditTextSelectionTag = $73656C65 ; 'sele'
and now the Carbon code works correctly in ASCII and Unicode mode. Sorry for my mistake... :wink:

Re: Cross plattform StringGadget text selection

Posted: Tue Dec 08, 2015 8:14 am
by davido
@Shardik,
Very useful.
Thank you for taking the trouble to make it cross-platform. :D