Page 1 of 2

Move scrollbar to top of EditorGadget

Posted: Fri Jul 19, 2019 12:34 am
by Columbo
In my program I have a EditGadget which is populated by a record from a database. When reading the contents of the current record in the EditorGadget, if you use the scrollbar to scroll down to the end of the content and then move to the next record, the scrollbar is at the bottom of the EditorGadget forcing you to scroll back up in order to read the beginning of the next record. Is there any way to programmatically move the scrollbar to the top of each new record?

Re: Move scrollbar to top of EditorGadget

Posted: Fri Jul 19, 2019 8:56 am
by RSBasic
For Windows:

Code: Select all

SendMessage_(GadgetID(#Gadget), #EM_SCROLL, #SB_TOP, 0)

Re: Move scrollbar to top of EditorGadget

Posted: Fri Jul 19, 2019 4:08 pm
by Columbo
Works perfectly. Thank you very much RSBasic.

Re: Move scrollbar to top of EditorGadget

Posted: Tue Dec 17, 2019 2:24 pm
by Borstensohn
I have a similar question, and that is: How can the scrollbar in the EditorGadget scroll down automatically under Linux?

To explain more detailed: When a text from a file is loaded into the EditorGadget, I’d love the gadget’s scrollbar to scroll down, without the need for the user to push the PgDn (page down) key.

The code below works with the ListViewGadget, but not with the EditorGadget. Has anybody an idea, how this could be solved? Remember: Under Linux, not Windows. Thanks in advance.

Code: Select all


EnableExplicit

Enumeration
	#wndFenster
	#edtEditor
	#lstListe
EndEnumeration

Global.i hoehe, zeilen, listenzeilen

If OpenWindow(#wndFenster, 0, 0, 400, 400, "Rollbalken soll ans Ende rollen, will aber nicht.", #PB_Window_SystemMenu | #PB_Window_ScreenCentered) 
	EditorGadget(#edtEditor, 20, 20, 360, 120, #PB_Editor_WordWrap)
	SetGadgetText(#edtEditor, "Dies" + #CRLF$ + "ist" + #CRLF$ + "ein" + #CRLF$ + "sehr" + #CRLF$ + "hoher" + #CRLF$ + "Text," + #CRLF$ + "wenngleich" + #CRLF$ + "auch" + #CRLF$ + "kein" + #CRLF$ + "hochgeistiger.")
;Alternative:
;	AddGadgetItem(#edtEditor, 0, "Dies")
;	AddGadgetItem(#edtEditor, 1, "ist")
;	AddGadgetItem(#edtEditor, 2, "ein")
;	AddGadgetItem(#edtEditor, 3, "sehr")
;	AddGadgetItem(#edtEditor, 4, "hoher")
;	AddGadgetItem(#edtEditor, 5, "Text")
;	AddGadgetItem(#edtEditor, 6, "wenngleich")
;	AddGadgetItem(#edtEditor, 7, "auch")
;	AddGadgetItem(#edtEditor, 8, "kein")
;	AddGadgetItem(#edtEditor, 8, "hochgeistiger")
	SetActiveGadget(#edtEditor)
	SetGadgetState(#edtEditor, zeilen-1)
	
	ListViewGadget(#lstListe, 20, 160, 360, 120)
	AddGadgetItem(#lstListe, 0, "Dies")
	AddGadgetItem(#lstListe, 1, "ist")
	AddGadgetItem(#lstListe, 2, "ein")
	AddGadgetItem(#lstListe, 3, "sehr")
	AddGadgetItem(#lstListe, 4, "hoher")
	AddGadgetItem(#lstListe, 5, "Text")
	AddGadgetItem(#lstListe, 6, "wenngleich")
	AddGadgetItem(#lstListe, 7, "auch")
	AddGadgetItem(#lstListe, 8, "kein")
	AddGadgetItem(#lstListe, 8, "hochgeistiger")
	listenzeilen = CountGadgetItems(#lstListe)
	SetGadgetState(#lstListe, listenzeilen-1)

	Repeat
		Select WaitWindowEvent(20) 
			Case  #PB_Event_CloseWindow 
				End 
		EndSelect
	ForEver
EndIf

Re: Move scrollbar to top of EditorGadget

Posted: Tue Dec 17, 2019 2:53 pm
by Shardik
Have you already taken a look into my list of cross-platform examples?

Re: Move scrollbar to top of EditorGadget

Posted: Tue Dec 17, 2019 3:31 pm
by Borstensohn
Thanks, Shardik, your example Set cursor is the most interesting for me. I changed the editor’s content like this (see below), so that a scrollbar appears:

Code: Select all

SetGadgetText(#Editor, "The" + #LF$ + "quick" + #LF$ + "brown" + #LF$ + "fox" + #LF$ + "jumps" + #LF$ + "over" + #LF$ + "the" + #LF$ + "lazy" + #LF$ + "dog.")
And the cursor jumps to the desired position (let’s say to the last word), but the scrollbar does not move down.

Re: Move scrollbar to top of EditorGadget

Posted: Tue Dec 17, 2019 3:33 pm
by #NULL
Try the code from
EditorGadget:
- Add line and keep it visible

Re: Move scrollbar to top of EditorGadget

Posted: Tue Dec 17, 2019 4:06 pm
by Borstensohn
Thanks, #NULL, but this example simulates adding of text lines. When a real user adds text, the scrollbar moves accordingly, so that’s not my point actually. What I am looking for is: After loading text into the Gadget editor, the scrollbar should scroll to the end of the text, without user interaction. So, when a text is loaded, the user should see the last text line, so that she or he can keep on writing, without the need to manually scroll down to the last sentence/line.

But my wish seems to be quite unusual, because in the meantime I tested several text editors, also one word processing program, and all of them always started with the scroll bar at the top position. I found no way in the options to change that. So I'll take that as standard behavior.

Re: Move scrollbar to top of EditorGadget

Posted: Tue Dec 17, 2019 4:17 pm
by #NULL
I have this one (possibly from Shardik or from somewhere else in the forum):

Code: Select all

  Procedure scrollToEnd(gadget)
    ; use subsystem gtk2, otherwise might not work with horizontal scrollbar (last line not visible and it scrolls the the right too)
    CompilerIf #PB_Compiler_OS = #PB_OS_Windows
      SendMessage_(GadgetID(gadget), #EM_SETSEL, -2, -1)
    CompilerElse
      Protected end_mark,*buffer, end_iter.GtkTextIter
      *buffer=gtk_text_view_get_buffer_(GadgetID(gadget))
      gtk_text_buffer_get_end_iter_(*buffer,@end_iter)
      end_mark=gtk_text_buffer_create_mark_(*buffer,"end_mark",@end_iter,#False)
      gtk_text_view_scroll_mark_onscreen_(GadgetID(gadget),end_mark)
    CompilerEndIf
  EndProcedure

Re: Move scrollbar to top of EditorGadget

Posted: Tue Dec 17, 2019 4:35 pm
by IdeasVacuum
In Windows, you can do something like this:

Code: Select all

Define.i iScrollMin, iScrollMax                                                    
                                                                                   
If GetWindowLongPtr_(GadgetID(#Editor), #GWL_STYLE) & #WS_VSCROLL              
                                                                                   
         GetScrollRange_(GadgetID(#Editor), #SB_VERT, @iScrollMin, @iScrollMax)
           SetScrollPos_(GadgetID(#Editor), #SB_VERT, iScrollMax, #True)       
EndIf                                                                              

Re: Move scrollbar to top of EditorGadget

Posted: Tue Dec 17, 2019 4:43 pm
by Borstensohn
Does not work for me, @IdeasVacuum. I tried with GTK3 and GTK2 (compiler options > library subsystem > gtk2).
Maybe I’ll try under Windows, but not today, I think.

Thanks for your help to all of you, guys, much appreciated!

Oh, by the way: I have PureBasic 5.71 LTS (x64).

Re: Move scrollbar to top of EditorGadget

Posted: Tue Dec 17, 2019 5:12 pm
by #NULL
Works here, both with gtk2 and gtk3:

Code: Select all

EnableExplicit

Procedure scrollToEnd(gadget)
  ; use subsystem gtk2, otherwise might not work with horizontal scrollbar (last line not visible and it scrolls the the right too)
  CompilerIf #PB_Compiler_OS = #PB_OS_Windows
    SendMessage_(GadgetID(gadget), #EM_SETSEL, -2, -1)
  CompilerElse
    Protected end_mark,*buffer, end_iter.GtkTextIter
    *buffer=gtk_text_view_get_buffer_(GadgetID(gadget))
    gtk_text_buffer_get_end_iter_(*buffer,@end_iter)
    end_mark=gtk_text_buffer_create_mark_(*buffer,"end_mark",@end_iter,#False)
    gtk_text_view_scroll_mark_onscreen_(GadgetID(gadget),end_mark)
  CompilerEndIf
EndProcedure

Enumeration
   #wndFenster
   #edtEditor
   #lstListe
EndEnumeration

Global.i hoehe, zeilen, listenzeilen

If OpenWindow(#wndFenster, 0, 0, 400, 400, "Rollbalken soll ans Ende rollen, will aber nicht.", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
   EditorGadget(#edtEditor, 20, 20, 360, 120);, #PB_Editor_WordWrap)
   SetGadgetText(#edtEditor, "Dies" + #CRLF$ + "ist" + #CRLF$ + "ein" + #CRLF$ + "sehr" + #CRLF$ + "hoher" + #CRLF$ + "Text," + #CRLF$ + "wenngleich" + #CRLF$ + "auch" + #CRLF$ + "kein" + #CRLF$ + "hochgeistiger.")
;Alternative:
;   AddGadgetItem(#edtEditor, 0, "Dies")
;   AddGadgetItem(#edtEditor, 1, "ist")
;   AddGadgetItem(#edtEditor, 2, "ein")
;   AddGadgetItem(#edtEditor, 3, "sehr")
;   AddGadgetItem(#edtEditor, 4, "hoher")
;   AddGadgetItem(#edtEditor, 5, "Text")
;   AddGadgetItem(#edtEditor, 6, "wenngleich")
;   AddGadgetItem(#edtEditor, 7, "auch")
;   AddGadgetItem(#edtEditor, 8, "kein")
;   AddGadgetItem(#edtEditor, 8, "hochgeistiger")
   SetActiveGadget(#edtEditor)
   ;SetGadgetState(#edtEditor, zeilen-1)
   
   scrollToEnd(#edtEditor)

   
   ListViewGadget(#lstListe, 20, 160, 360, 120)
   AddGadgetItem(#lstListe, 0, "Dies")
   AddGadgetItem(#lstListe, 1, "ist")
   AddGadgetItem(#lstListe, 2, "ein")
   AddGadgetItem(#lstListe, 3, "sehr")
   AddGadgetItem(#lstListe, 4, "hoher")
   AddGadgetItem(#lstListe, 5, "Text")
   AddGadgetItem(#lstListe, 6, "wenngleich")
   AddGadgetItem(#lstListe, 7, "auch")
   AddGadgetItem(#lstListe, 8, "kein")
   AddGadgetItem(#lstListe, 8, "hochgeistiger")
   listenzeilen = CountGadgetItems(#lstListe)
   SetGadgetState(#lstListe, listenzeilen-1)

   Repeat
      Select WaitWindowEvent(20)
         Case  #PB_Event_CloseWindow
            End
      EndSelect
   ForEver
EndIf
Only if the last line is longer then it will also scroll to the right unfortunately. I avoid this in some of my codes by adding empty dummy lines after the actual content, and removing them before adding new content. But then there is a bug on Windows that needed additional handling. Goes like this (just copied from my code, doesn't compile like that):

Code: Select all

  Procedure messageToEditorLog(message.s)
    Shared editorLog, messages(), messagesMutex
    Protected NewList lines.s(), txt.s, i
    
    ; remove last dummy lines (" ")
    
    CompilerIf #PB_Compiler_OS = #PB_OS_Windows
      
      ; workaround for : https://www.purebasic.fr/english/viewtopic.php?f=4&t=54963
      
      ; get text, split into lines
      txt = GetGadgetText(editorLog)
      For i=1 To CountString(txt, #CRLF$) + 1
        AddElement(lines())
        lines() = StringField(txt, i, #CRLF$)
      Next
      ; remove last " " lines
      While LastElement(lines()) And lines() = " "
        DeleteElement(lines())
      Wend
      ; put back to gadget
      txt = ""
      ForEach lines()
        If Len(txt) > 0
          txt + #CRLF$
        EndIf
        txt + lines()
      Next
      SetGadgetText(editorLog, txt)
      
    CompilerElse
      
      ; works in linux
      
      ; remove last " " items
      While GetGadgetItemText(editorLog, CountGadgetItems(editorLog) - 1) = " "
        RemoveGadgetItem(editorLog, CountGadgetItems(editorLog) - 1)
      Wend
    CompilerEndIf
    
    ; add actual message
    AddGadgetItem(editorLog, -1, message)
    
    ; add dummy " " lines for end scroll
    For i = 1 To 2
      AddGadgetItem(editorLog, -1, " ")
    Next
    
    scrollToEnd(editorLog)
  EndProcedure

Re: Move scrollbar to top of EditorGadget

Posted: Wed Dec 18, 2019 8:55 pm
by Borstensohn
Wow, fantastic, #NULL, it works like a charm, thank you so much!
And the code of your procedure separates the beginners (like me) from the geniuses (like you). :)

Re: Move scrollbar to top of EditorGadget

Posted: Thu Dec 19, 2019 3:05 pm
by Borstensohn
Well, on large texts it only works correctly with compiler option Library Subsystem: gtk2, otherwise (default GTK 3) the scrollbar stops after 24 lines or so. But that’s okay so far, I can use GTK 2.

Re: Move scrollbar to top of EditorGadget

Posted: Thu Dec 19, 2019 3:53 pm
by firace
#NULL wrote: Only if the last line is longer then it will also scroll to the right unfortunately.
I had the same issue and solved it with the following:

Code: Select all

 SendMessage_(GadgetID(gadget), #WM_VSCROLL, #SB_BOTTOM, #Null)
Instead of

Code: Select all

   SendMessage_(GadgetID(gadget), #EM_SETSEL, -2, -1)