I’ve been using Xojo for almost 20 years now. In that time I’ve seen many features come and go. I’ve built hundreds of types of apps. I’ve tried so many different things just to see if they’ll work that it makes my head spin to think about. Xojo still surprises me from time to time.
I need to build a UI framework for something that I’m working on. I’ve done it before and it’s really not hard to do. There’s a difference this time, however, in that there’s a requirement to be able to tweak the colors as needed and have it applied across every element of that framework, which is an interesting problem.
Possible Paths
I’ve built UI frameworks before in Xojo, and I’ve solved this particular problem before as well. The end result always works, but I’m rarely happy with the solution.
- I could just make properties for the color values on each component then have some esoteric code that changes the properties of the individual component instances when needed, but that’s intensive at runtime.
- I could use a singleton class to store values within properties that the individual classes pull at runtime, with logic in computed properties for the various needs of the components, and that works but feels clumsy.
There are certainly other ways to implement this, some I’ve used in the past and others I possibly have never even realized. This time I wanted something that felt better and didn’t use a lot of memory or CPU cycles. I wanted something simple. The idea for solving this in a new way actually came to me while working on something else in JavaScript and CSS.
In CSS
A very cool feature of CSS is custom properties (or variables), which enables frameworks like Bootstrap to have a single defined value be used anywhere and everywhere. To be clear, while CSS calls them custom properties, I’ve always thought of these definitions as constants because that’s what they really are. A value is assigned to a name, and that value will be represented by that name for the life of the document. For example, I could create a custom property called “primary” that looks like this:
:root {
--primary: #0d6efd
}
Then when I want to use that color, say as the background for a button, I would reference it like this:
button {
background-color: var(--primary)
}
This gives me the ability to make one change in the CSS and have it reflected everywhere that color is used, and makes customizing designs much simpler than if the color value were set in every CSS element for every place I wanted to use it.
In Xojo
So how do I implement this in Xojo without the caveats I mentioned before? Constants.
Sure, computed constants are a thing, and they’re incredibly useful. We use them all the time for storing Pi, supplying platform-specific constant values or for language translations — and they’ve been a staple of professional Xojo development for as long as I can remember. But can they help me here? I didn’t think my plan would work, but setting up the test and hitting Run gave me such a thrill. It just worked.
So here’s what I did that I still think is a super neat (and, from my quick research, undocumented) feature of Xojo’s constants.
The first step was to create a module. We’ll just call it “FrameworkColors”. I then added a constant to that module called “Primary” with a value of “&c0d6efd”. The IDE picks up the type from the value and knows that it’s a color, a pretty blue color in fact. This module now looks something like this:
Module FrameworkColors
Constant Primary as Color = &c0d6efd
End Module
Next, I added another constant which we’ll call “ButtonBackground”. In that constant’s Default Value field, I entered “FrameworkColor.Primary” and set the Type to Color, so our module now looks something like this:
Module FrameworkColors
Constant Primary as Color = &c0d6efd
Constant ButtonBackground as Color = FrameworkColors.Primary
End Module
I did not expect this to work. I just knew this wasn’t going to compile. I really shouldn’t expect this to work, right? When I hit Run and there were no errors, I thought “Well, maybe Xojo is doing something funky and interpreting that value as what will be some random color that in no way resembles what I actually wanted.”
So I setup a test. In a window’s Paint event, I added the following code:
g.DrawingColor = FrameworkColors.ButtonBackground
g.FillOval( 0, 0, 100, 100 )
Again, I expected something strange. Either the color would be entirely wrong, I’d encounter an exception, or maybe even a crash. But no. It works. It totally works. Check it out!
Where Else Does This Work?
In an excited frenzy, I quickly tried other constant types, and it also works for Numbers and Booleans. I couldn’t figure out how to quickly make it work for strings, but I really won’t need that so I didn’t spend any time on it. If anyone knows, feel free to tweet at me or message me on the Xojo Forums and I’ll update this article.
I’m still reeling a bit that this works, and I suspect I know which engineer in Xojo’s history added this ability, but I’ll save my speculation. Whoever did it, they did a wonderful job. I love this ability and can’t believe I never thought to try it before. I hope this helps some of you in your projects, and I’d love to hear if anyone else is using this functionality and how.
Update(s)
Implementation
This is the implementation that I’m discussing here:
Project
Download the sample project here.