0069: TextView and TextBuffer
These two widgets, working together, give us the basis for text/code editors, word processors, and other DTP software. The TextView
not only shows us what’s contained in the TextBuffer
, it gives us access so we can edit, append, etc.
A Simple Text Editor
To get the TextView
into a Window
in any kind of useful way also means using a ScrolledWindow
as an intermediary container. After all, there’s no point in having hundreds of lines of text if you only have visual access to the first dozen. (There’s nothing like typing blind to keep you both focused and stressed.)
So, we stuff a ScrolledWindow
into our usual AppBox
, and stuff the TextView
into the ScrolledWindow
… like this:
class AppBox : Box
{
bool expand = true, fill = true;
uint globalPadding = 10, localPadding = 5;
ScrolledTextWindow scrolledTextWindow;
this()
{
super(Orientation.VERTICAL, globalPadding);
scrolledTextWindow = new ScrolledTextWindow();
packStart(scrolledTextWindow, expand, fill, localPadding); // TOP justify
} // this()
} // class AppBox
class ScrolledTextWindow : ScrolledWindow
{
MyTextView myTextView;
this()
{
super();
myTextView = new MyTextView();
add(myTextView);
} // this()
} // class ScrolledTextWindow
TextBuffer
We don’t have to instantiate the TextBuffer
because the TextView
already has one associated with it when it’s instantiated. But, there is some flexibility here. We could end up with this association between a TextView
and a TextBuffer
in a few different ways:
- instantiate a
TextView
and grab a pointer to itsTextBuffer
(as we’re doing in this example), - instantiate the
TextBuffer
first and pass it to theTextView
’s overloaded constructor—which doesn’t seem all that useful to me unless you… - instantiate one
TextView
and pass itsTextBuffer
along to the constructors for one or more otherTextView
s so they can share.
But in this example, we’ll do it the simplest way:
class MyTextView : TextView
{
TextBuffer textBuffer;
string content = "Now is the English of our discontent.";
this()
{
super();
textBuffer = getBuffer();
textBuffer.setText(content);
} // this()
} // class MyTextView
Within the MyTextView
constructor, a quick call to getBuffer()
gives us access and from there, we give it some content with setText()
.
But for thoroughness sake, let’s also look at a shared TextBuffer
…
TextViews with a Shared TextBuffer
Now, this gets a bit more complex. At some point in the hierarchy, we’ve got to establish a pointer to the first TextView
’s TextBuffer
and pass it along to the others. I decided to do this at the AppBox
level which makes the most sense to me:
class AppBox : Box
{
bool expand = true, fill = true;
uint globalPadding = 10, localPadding = 5;
ScrolledTextWindow scrolledTextWindow;
TextView masterTextView;
DependentTextView dependentTextView;
TextBuffer sharedTextBuffer;
this()
{
super(Orientation.VERTICAL, globalPadding);
scrolledTextWindow = new ScrolledTextWindow();
packStart(scrolledTextWindow, expand, fill, localPadding); // TOP justify
// grab the TextBuffer pointer
masterTextView = cast(TextView)scrolledTextWindow.getChild();
sharedTextBuffer = masterTextView.getBuffer();
dependentTextView = new DependentTextView(sharedTextBuffer);
packStart(dependentTextView, expand, fill, localPadding);
} // this()
} // class AppBox
Grabbing a pointer to the first TextView
’s TextBuffer
proves to be a two-step operation because the result of getChild()
has to be cast()
as a TextView
. If not, the result is a generic Widget
which doesn’t give us access to the TextView
’s getBuffer()
function.
And to complete this multi-association, the DependentTextView
class looks like this:
class DependentTextView : TextView
{
this(TextBuffer sharedTextBuffer)
{
super(sharedTextBuffer);
} // this()
} // class DependentTextView
At this level, things are dead simple. The constructor takes the TextBuffer
pointer as an argument and passes it along to the super-constructor.
If you type, copy, cut, or paste in one TextView
, your actions are mirrored in the other… I’m sure there are uses for this type of thing, otherwise, why have this functionality, right?
Conclusion
And that’s the basics of the TextView
widget and its associated TextBuffer
. Turning them into something more useful, such as a full-blown text editor, we’ll leave for another time.
Happy coding.
Comments? Questions? Observations?
Did we miss a tidbit of information that would make this post even more informative? Let's talk about it in the comments.
- come on over to the D Language Forum and look for one of the gtkDcoding announcement posts,
- drop by the GtkD Forum,
- follow the link below to email me, or
- go to the gtkDcoding Facebook page.
You can also subscribe via RSS so you won't miss anything. Thank you very much for dropping by.
© Copyright 2024 Ron Tarrant