Get number of lines in EditorGadget (cross-platform)
Posted: Sun Dec 21, 2014 12:42 pm
				
				The following example demonstrates how to get the number of lines currently contained in an EditorGadget (works also with flag #PB_Editor_WordWrap set and counts even the lines in a currently invisible part of the EditorGadget which need moving the scroll bar to become visible). In Windows it's quite easy by simply using
But in Linux and MacOS it's much more difficult needing a bunch of API functions, so that I have put together the following true cross-platform example:
			Code: Select all
CountGadgetItems(EditorGadgetID)Code: Select all
EnableExplicit
#Text = "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam " +
  "nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, " +
  "sed diam voluptua. At vero eos et accusam et justo duo dolores et ea " +
  "rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum " +
  "dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, " +
  "sed diam nonumy eirmod tempor invidunt ut labor."
CompilerIf #PB_Compiler_OS = #PB_OS_MacOS
  Procedure.I GetLineHeight(EditorGadgetID.I)
    Protected Dictionary.I
    Protected Font.I
    Protected i.I
    Protected KeyArray.I
    Protected KeyName.I
    Protected LineHeight.CGFloat
    
    Dictionary = CocoaMessage(0, GadgetID(EditorGadgetID), "typingAttributes")
    KeyArray = CocoaMessage(0, Dictionary, "allKeys")
    
    For i = 0 To CocoaMessage(0, KeyArray, "count") - 1
      KeyName = CocoaMessage(0, KeyArray, "objectAtIndex:", i)
      
      If PeekS(CocoaMessage(0, KeyName, "UTF8String"), -1, #PB_UTF8) = "NSFont"
        Font = CocoaMessage(0, Dictionary, "objectForKey:", KeyName)
        
        If Font
          CocoaMessage(@LineHeight, CocoaMessage(0, GadgetID(EditorGadgetID),
            "layoutManager"), "defaultLineHeightForFont:", Font)
        EndIf
        
        Break
      EndIf
    Next i
    
    ProcedureReturn Int(LineHeight)
  EndProcedure
CompilerEndIf
Procedure.I GetLineCount(WindowID.I, EditorGadgetID.I)
  Protected LineCount.I
  
  CompilerSelect #PB_Compiler_OS
    CompilerCase #PB_OS_Linux
      Protected LineHeight.I
      Protected TextBlockHeight.I
      Protected TextIter.GtkTextIter
      Protected TextView.I = GadgetID(EditorGadgetID)
      Protected y.I
      ; ----- Get height of a single text line for font used in EditorGadget
      If StartDrawing(WindowOutput(WindowID))
        DrawingFont(GetGadgetFont(EditorGadgetID))
        LineHeight = TextHeight("Test")
        StopDrawing()
      EndIf
      
      ; ----- Get height of complete wrapped text block in EditorGadget
      gtk_text_view_get_line_at_y_(TextView, @TextIter, GadgetY(EditorGadgetID), 0)
      gtk_text_view_get_line_yrange_(TextView, @TextIter, @y, @TextBlockHeight)
      
      ; ----- Calculate number of lines (also invisible ones)
      LineCount = TextBlockHeight / LineHeight            
    CompilerCase #PB_OS_MacOS
      Protected LineHeight.I
      Protected Rect.NSRect
      Protected TextBlockHeight.I
      ; ----- Get height of complete wrapped text block in EditorGadget
      CocoaMessage(@Rect, CocoaMessage(0, GadgetID(EditorGadgetID),
        "layoutManager"), "usedRectForTextContainer:", CocoaMessage(0,
        GadgetID(EditorGadgetID), "textContainer"))
      ; ----- Calculate number of lines (also invisible ones)
      LineCount = Int(Rect\size\height) / GetLineHeight(EditorGadgetID)
    CompilerCase #PB_OS_Windows
      LineCount = CountGadgetItems(EditorGadgetID)
  CompilerEndSelect
  ProcedureReturn LineCount
EndProcedure
OpenWindow(0, 200, 100, 300, 400, "EditorGadget")
EditorGadget(0, 5, 5, WindowWidth(0) - 10, WindowHeight(0) - 10,
  #PB_Editor_WordWrap)
; ----- Workaround for Linux bug in flag #PB_Editor_WordWrap
CompilerIf #PB_Compiler_OS = #PB_OS_Linux
  gtk_text_view_set_wrap_mode_(GadgetID(0), #GTK_WRAP_WORD)
CompilerEndIf
SetGadgetFont(0, LoadFont(0, "Arial", 15))
SetGadgetText(0, #Text)
; ----- Wait until text is displayed (Necessary on Linux and MacOS!)
While WindowEvent() : Wend
MessageRequester("Info", "Number of lines in EditorGadget: " + GetLineCount(0, 0))
Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow