Quite a few of my coding projects have a large text field where the user is expected to do a lot of typing. Actually, it would appear that none of my projects have a large text field. I suppose I should make markdowner and scripsi official jezra.net projects. Anyway, both of the previously mentioned apps have a large text field where the user types and types and types( hey, they are text editing programs ).
- scripsi is a special purpose dual paned text editor written in Vala
- markdowner is a special purpose text editor written in Python
Both applications use the GTK+ toolkit to create the user interface.
The Problem
When a GTK TextView widget is used to create a large text input area, if the user's cursor travels past the viewable area of the TextView, which happens when typing to the bottom of the screen, the cursor is below the visible area and the user will need to stop typing and scroll the TextView until it is visible. If the user were a typing ninja then I suppose they wouldn't care about typing without knowing what text is showing up in the TextView. Well, I am not a typing ninja.
The Solution
There is probably a more elegant solution to the problem, but I couldn't find it so you are stuck with what I figured out, and this is my solution:
When the text changes, get the coordinates of the cursor and scroll to those coordinates. This will ensure that the cursor is always visible to the user. How would you like to see a working example in Vala?
Enter the Vala
using Gtk;
public static void main( string[] args) {
//initialize gtk
Gtk.init(ref args);
//make a window
Window window = new Window();
//make a textbuffer
TextBuffer textBuffer = new TextBuffer(null);
//make a textview with our buffer
TextView textView= new TextView.with_buffer(textBuffer);
//let the textview wrap at word or char
textView.set_wrap_mode(WrapMode.WORD_CHAR);
//we need to know when the text buffer changes
textBuffer.changed.connect( ()=>{
//make a textiterator
TextIter iter = TextIter();
//what is the cursors x coordinate?
int x = textView.virtual_cursor_x;
//what is the cursors y coordinate?
int y = textView.virtual_cursor_y;
//get the text iter at the cursor's coordinates
textView.get_iter_at_location(out iter,x,y);
//scroll to the cursor's text iter
textView.scroll_to_iter(iter,0,false,0,0);
});
//make a scrolledwindow to hold the textviw
ScrolledWindow scroll = new ScrolledWindow (null, null);
//set the scrollwindow's scrolling policy
scroll.set_policy (PolicyType.AUTOMATIC, PolicyType.AUTOMATIC);
//add the textview to the scollwindow
scroll.add (textView);
//add the scrollwindow to our window
window.add(scroll);
//show all the widgets
window.show_all();
//run the gtk main loop
Gtk.main();
}
Save the above code in a file named "cursor.vala" and compile with
Now I need to port the code to Python and implement the change in markdowner.
Now quit reading, and go fix a problem with a dirty hack.
Also, I'm still working on that FOSScon blog post; depending on how things go, you might even see it today!