0077: Notebook I – The Basics
Today, we’ll be digging into the GTK Notebook
, the basic widget used to build a multi-document interface (MDI). Each tab in a Notebook
can contain pretty much whatever you want from a text document to a 2D or 3D graphic, even a visual representation of an audio file or JBC™ (Just a Bunch of Controls).
But, enough buildup. Let’s get to it.
A Single-tab Notebook
Before we construct a Notebook
, we need to decide where the tabs will go:
PositionType.LEFT
,PositionType.RIGHT
,PositionType.TOP
, orPositionType.BOTTOM
.
And, yeah, that’s the entire list of options available in the PositionType enum
.
Let’s set up a derived class:
class MyNotebook : Notebook
{
PositionType tabPosition = PositionType.TOP;
string tabLabel = "Demo Tab";
Label myTabLabel;
MyTextView myTextview;
this()
{
super();
setTabPos(tabPosition);
myTabLabel = new Label(tabLabel);
myTextview = new MyTextView();
appendPage(myTextview, myTabLabel);
} // this()
} // class MyNotebook
Class Attributes
In the attributes list, we find our tab position followed by a bunch of other (pretty-much) self-explanatory stuff, but here’s a quick run-down, anyway:
- a string for the tab’s
Label
, - the actual
Label
we’ll stuff into the tab, and - a derivative of a
TextView
that we’ll stuff into the tab’s work area/page.
The Constructor
Still following the code snippet above, after calling the super-constructor, we:
- set the tabs to appear at the top,
- instantiate the
Label
andTextView
derivatives, and finally, - call the
appendPage()
function to cram everything in there.
I won’t go over the TextView
or the Label
derivative classes here since we’ve talked about those many times in earlier posts.
And that is all there is to it.
But Wait…
When you compile and run this demo (in Windows, at least) you’ll notice that the tab’s Label
text shows along with a little blue bar underneath so we know it’s selected, but there’s no visible tab background. It doesn’t even have an outline.
Of course, if you’ve already been messing around with themes other than the default GTK theme available on Windows, your tabs might already be visible. But for those of us who haven’t, this brings us to explore a couple of solutions.
Making Tabs Visible in Windows 10: the Universal Method
One way to go about this is to change the theme for all GTK apps. This is not a well-documented process, but a quick-n-dirty solution is to give your GTK
apps a win32 theme. It’s not the best solution because it gives everything a Windows 7 look. It also spits out warnings on the command line. One workaround for that is don’t run your app from the command line, which may or may not be appealing.
Either way, here’s what you do:
- as administrator, open
C:\Program Files\Gtk-Runtime\etc\gtk-3.0\settings.ini
, - find all lines starting with
gtk
and comment them out by typing an octothorp (#) at the begining of each (you could delete them if you want, but by commenting them out, you can easily revert… which I’m sure you will once you see the results), - go to a new line and add this:
gtk-theme-name=win32
- save and close the file.
Now you can open any of your GTK apps/demos and travel back in time to the Windows 7 era.
Like I said, it’s not the best solution, but you end up with visible tabs.
And here’s another way to go about it…
Making Tabs Visible: the Application-level Method
This isn’t an ideal solution either because we don’t get control over such things as the shape of the tabs, but we do get some control… and it looks better than a Windows 7 theme superimposed onto a Windows 10 application.
A Call for Participation
I haven’t tried this on Linux (or any other OS) but I’m sure it’ll work. If anyone tries it, please tell us about your results (see list of contact options at the bottom of this page).
(now, back to our show)
If you recall, we covered how to decorate widgets using CSS in Blog Post #0073 when we were talking about the Frame
widget and what we did there can be adapted here. Below is the CSS class we used before, but with cssPath
set to the file we’re working with for this demo:
class CSS // GTK4 compliant
{
CssProvider provider;
string cssPath = "./css/visible_tabs.css";
this(StyleContext styleContext)
{
provider = new CssProvider();
provider.loadFromPath(cssPath);
styleContext.addProvider(provider, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
} // this()
} // class CSS
So, like before, we’ll:
- create a CSS class (this time, specifically for tabs), and
- attach it to the
Notebook
’sStyleContext
.
Changes to Class Attributes
For each Widget
where we want CSS styling, we add this line in the class preamble:
CSS css;
The we go to…
The Constructor
Here, we add this line:
css = new CSS(getStyleContext());
And remember, this also has to be done in the constructor for each widget where CSS will be used.
One more thing to look at…
The visible_tabs.css File
The file is short-n-sweet:
tab
{
background-color: #f2f2f2;
}
The CSS Name for tabs is tab
and we just need to set the color.
But, there’s one more way to go about this, one that appeals to me because we bring the CSS selector inside our D code file where it can’t get misplaced.
Embedding CSS in D
The CSS selector can be a string
or an enum
(follow the second code link above and look for the CSS class at the bottom of the file) and it’s associated with the CssProvider
using loadFromData()
instead of loadFromPath()
. A quick rewrite of the CSS
class makes this happen:
class CSS // GTK4 compliant
{
CssProvider provider;
string myCSS = "tab { background-color: #f2f2f2; }";
this(StyleContext styleContext)
{
provider = new CssProvider();
provider.loadFromData(myCSS);
styleContext.addProvider(provider, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
} // this()
} // class CSS
Nothing has to change in the class(s) using the CSS
.
Conclusion
Next time, we’ll carry on and look at multiple tabs (why else are we playing around with tabs?) and eventually get into:
- reordering tabs,
- customized tabs (wherein we draw our own tab shapes from scratch),
- adding and removing tabs, and
- signals associated with the
Notebook
widget and its tabs/pages.
Until then, be nice to each other.
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