0010: Observing CheckButtons

Results of this example:
Current example output
Current example output
Current example terminal output
Current example terminal output (click for enlarged view)

Today’s mission is to have a button exhibit different behaviour depending on the state of another widget, a CheckButton.

Another Import

Right at the top, as usual, we have to add an import statement:

import gtk.CheckButton;

The Observer

Now, skip to the end of the file to look at the ObserverButton class:

class ObserverButton : Button
{
	string label = "Take Action";
	
	string standardMessage = "Droids? We don't need no stinking droids!";
	string switchMessage = "These aren't the droids you're looking for.";
	CheckButton checkButton;

	this(CheckButton extCheckButton)
	{
		super(label);
		addOnClicked(&doSomething);
		checkButton = extCheckButton;
		
	} // this()
	
	
	void doSomething(Button b)
	{
		if(checkButton.getActive() == true)
		{
			writeln(switchMessage);
		}
		else
		{
			writeln(standardMessage);
		}
		
	} // doSomething()
	
} // class ObserverButton

This is the observer half of the observer/observed class objects that make up the observer pattern. Our other button (which we’ll look at in a moment, as dull as it is) is watched so the ObserverButton knows which of two actions to take.

You’ll notice, below the label and other strings representing actions we can take with this button, there’s a pointer to a CheckButton. It’s passed in through the ObserverButton’s constructor and assigned to a local variable so we can call its getActive() function which reads the state of the CheckButton.

The Callback: doSomething()

If you look at the callback (so aptly named: doSomething) you’ll see the simple logic used to decide which of the two messages to spit out to the command shell.

Everything else here is off-the-shelf, so let’s look at…

The ObservationBox

Not that there’s anything really new here. All we do is establish the box as parent to both buttons. If we’d built them outside the box, we’d have to drag them in here anyway, so why not?

And Now for Something Completely… Toggled

Results of this example:
Current example output
Current example output
Current example terminal output
Current example terminal output (click for enlarged view)

Imports

Here, the CheckButton is replaced by the ToggleButton. The statement:

import gtk.CheckButton;

has been replaced by:

import gtk.ToggleButton;

ObservationBox

Take a look at the ObservationBox class:

class ObservationBox : Box
{
	this()
	{
		super(Orientation.VERTICAL, 5);
		
		ObservedToggleButton observedToggle = new ObservedToggleButton();
		ObserverButton myObserverButton = new ObserverButton(observedToggle);

		add(myObserverButton);
		add(observedToggle);
		
	} // this()
	
} // class ObservationBox

We’re still adding two buttons, but the ObservedToggleButton is more elaborate than the simple CheckButton used in the first example. So, let’s go look at that:

class ObservedToggleButton : ToggleButton
{
	string onText = "Toggle is on.";
	string offText = "Toggle is off.";
	string onLabel = "Toggle: ON";
	string offLabel = "Toggle: OFF";
	
	this()
	{
		super(onLabel);
		addOnClicked(&toggleMode);
		setMode(true);
		
		writeln(onText);
		
	} // this()
	
	
	void toggleMode(Button b)
	{
		if(getMode() == true)
		{
			setMode(false);
			writeln(offText);
			setLabel(offLabel);
		}
		else
		{
			setMode(true);
			writeln(onText);
			setLabel(onLabel);
		}
	
	} // toggleMode()
	
} // class MyToggleButton

This is what can happen if we want to hook something up to one of the ToggleButton’s signals, giving it something else to do besides sitting there looking oh-so pretty. All those strings are there to tell us the state of things, not just in the command shell, but on the ToggleButton’s label, too.

And in the constructor, we’re using a new signal, the onToggle signal, which we hook up with addOnToggled().

A little side note: if we’d wanted to add a callback to the CheckButton, instead of using the onClicked signal (inherited from Button) we could have used onToggle there, too. But because CheckButton inherits the signal from ToggleButton, we’d have to add an extra import statement:

import gtk.ToggleButton;
import gtk.CheckButton;

in order to get access to the signal and the all-important hook-up function, addOnToggled().

And that’s pretty much it. The ObserverButton is almost identical to the one in the CheckButton example. The only significant difference being that it calls the ObservedToggleButton’s getMode() to find its state rather than the getActive() function used with the first example.

And that is a day’s work, two examples that do very much the same thing, a CheckButton and a ToggleButton. You might think there’s so little difference that only one is actually needed and maybe that’s the case. But when you think about it, the CheckButton’s state is visually obvious the moment you glance at it. With a ToggleButton, we’ve got to go the extra mile and make changes to the label. We could also have changed the colour of the button if we really wanted it to stand out. Either way, though, in the end it comes down to which is more appealing for the GUI design you’re working on.

And that’s it. Until next time, may your wookies eat cookies and don’t stare into any novas.

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.

You can also subscribe via RSS so you won't miss anything. Thank you very much for dropping by.

© Copyright 2023 Ron Tarrant