0073: The Frame, Part II – Shadows & CSS
Frame Off
Today, we start with the irony of looking at the invisible Frame
. Turning off visibility is one way of dealing with the aesthetic problem we talked about last time and this is done with a call to setShadowType(
) as seen in the FrameOff
class:
class FrameOff : Frame
{
private:
string titleLabel = "Coordinates";
FrameChildGrid frameChildGrid;
public:
this()
{
super(titleLabel);
setShadowType(ShadowType.NONE);
frameChildGrid = new FrameChildGrid();
add(frameChildGrid);
} // this()
} // class FrameOff
This class is identical to the FrameOn
class we looked at last time, with the exception of this one statement. ShadowType.NONE
gives the results seen in the above screen shot.
Frame Styling
Turning visibility on or off is considered styling, and so is giving the Frame a 3D look. But whereas we use setShadowType()
to set visibility, all other styling is done with CSS.
Styling Frames with CSS
To use CSS in GTK, we need to do three things:
- write a
CSS
file (which can be an actual file or handled as a string within your code), - associate it with our application’s
GDK Screen
, and - tell our application to use this association.
But before we dive in, let’s start with a point of basic terminology…
Step One: Writing a CSS File
In CSS (Cascading Style Sheet) terms, the bits of code used to set properties for various elements are called selectors. For GTK’s purposes, selectors can be written in files ending in the .css
extension similar to this:
border
{
border-style: outset;
/* border-style: inset; */
/* border-style: solid; */
/* border-style: none; */
}
In this example, I’ve laid out the four possible styles of the Frame
border while commenting out three of them. Here’s what these options mean:
outset
: give theFrame
a 3D styling and make it look raised from the ‘page,’inset
: another 3D styling, this time seemingly recessed into the ‘page,’solid
: a plain, solid line, andnone
: which has the same effect assetShadowType(ShadowType.NONE)
.
If we save this file in a local css
directory with the name frame.css
, step one is done. Now let’s look at…
Step Two: The Association Between a CSS File and Our Application
This is a two-step process, with a total of five sub-steps, in which we:
- have the widget provide its
StyleContext
to the CSS object, - instantiate a
CssProvider
object which serves as a wrapper of sorts for our CSS file (css/frame.css
), - pull in that
.css
file, and - set up the association between the CSS file and the
StyleContext
.
That code, encapsulated in a nice, neat package looks like this:
class CSS // GTK4 compliant
{
CssProvider provider;
string cssPath = "./css/frame.css";
this(StyleContext styleContext)
{
provider = new CssProvider();
provider.loadFromPath(cssPath);
styleContext.addProvider(provider, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
} // this()
} // class CSS
Step Three: Telling Our Widget to Use CSS
This is the simplest step because it’s one statement. However, it has to be done for every Widget
that needs CSS decoration.
First, in the class attributes, we declare the CSS object:
CSS css = new CSS();
Then in the class constructor, we add this line:
css = new CSS(getStyleContext());
Which means our entire FrameOn
class will look like this:
class FrameOn : Frame
{
private:
CSS css;
string titleLabel = "Coordinates";
FrameChildGrid frameChildGrid;
float xAlign = 0.05, yAlign = 0.5;
public:
this()
{
super(titleLabel);
css = new CSS(getStyleContext());
setLabelAlign(xAlign, yAlign);
frameChildGrid = new FrameChildGrid();
add(frameChildGrid);
} // this()
} // class FrameOn
CSS Property Names
Disclaimer: The following demo is downright ugly and is meant solely to demonstrate coding technique, not design sensibilities.
The reason why CSS names work is because GTK has a convention for naming widgets and their properties. Some names are set up by GTK
, but you can also roll up your sleeves and add some yourself.
For the sake of demonstration, let’s assume you wanna gain control over a Label
’s background color. In class form, it might look like this:
class CSSLabel : Label
{
CSS css;
this(string textLabel, string cssName)
{
super(textLabel);
// css stuff
setName(cssName);
css = new CSS(getStyleContext());
} // this()
} // class CSSLabel
Now our .css
file can refer to our Label like this:
label#label1
{
font-family: Arial, Helvetica, sans-serif;
color: red;
font-size: 26px;
background-color: yellow;
} /* label1 */
The selector name, label#label1
, tells GTK that only widgets derived from an entity with a CSS name of label
—and further, these descendants must be named label1
—only those widgets will get this styling. Leaving out this drill-down aspect, we could also write the selector name like this:
#label1
Drop the CSS class into your application and you’re off to the races.
CSS and the GTK Inspector
With your application up and running, you can use the GTK Inspector by hitting Ctrl-Shift-D
(how apropos) to look at CSS names, both the ones you yourself have assigned and the ones assigned by default. Not all CSS names show up in the Inspector, but here’s a handy reference.
And if I haven’t covered enough detail in this writing, you can find more on CSS and GTK here.
Conclusion
And that’s the basics of both Frames and CSS. It should be remembered, however, that it’s easy to get carried away and over-style an application. Sometime down the road, we may come back to this subject, but it’s an issue of design rather than coding, so it’s a low priority for now.
Until next time.
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