0109: SFX – Using bindProperty() to Sync Properties Over Multiple Widgets

This post is the result of a discussion with Ferhat Kurtulmuş on the D Forum. He pointed out that bindProperty() can be used to sync up the sensitivity of a bunch of widgets. Change one and they all change. It sounded rather intriguing, so let’s have a look, shall we?

Widget Sync

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

Looking at the screen-shot, you’ll see a list of three Switchs and, at the bottom, a single standard Button that will control their sensitivity. The standard Button only changes the "sensitive" flag on the first Switch. The rest have theirs bound to that of the first. Anyway, let’s have a look at how it works…

Adding Companion Widgets

The function that sets all this up is part of the MyButton class and looks like this:

void addCompanion(Widget widget)
{
	companions ~= widget;
		
	if(companions[0] != widget)
	{
		companions[0].bindProperty("sensitive", widget, "sensitive", GBindingFlags.DEFAULT);
	}

} // addCompanion()

The if() statement makes sure the zeroeth Switch has already been assigned to the companions array before doing anything. It then names that zeroeth Switch as the observed Switch, so to speak, and binds its sensitive property to any other Switch widgets passed into the addCompanion() function.

This example only uses Switches, but you can use anything, really, as long as you up-cast to Widget as you pass it to addCompanion().

Making the List of Switches Insensitive

This is done in the onButtonPress() callback:

bool onButtonPress(Event e, Widget w)
{
	if(companions[0].getSensitive() is false)
	{
		writeln("Activating switch");
		companions[0].setSensitive(true);
		setLabel(labelText[1]);
	}
	else
	{
		writeln("Deactivating switch.");
		companions[0].setSensitive(false);
		setLabel(labelText[0]);
	}
		
	return(true);
		
} // onButtonPress()

This is pretty much the same as the onButtonPress() function we saw in the first demo we talked about in Blog Post #0104. The only difference is that we’re working with an array of companion widgets instead of just one.

The MySwitch class is identical, so the only thing left to look at is…

The ButtonGrid Constructor

And really, all we’re looking at here is how these Switches are all stuffed into the UI and associated, each with the first…

this()
{
	switchLabel1 = new Label("Insensitize Me");
	attach(switchLabel1, 0, 0, 1, 1);
	mySwitch1 = new MySwitch();
	attach(mySwitch1, 1, 0, 1, 1);
		
	switchLabel2 = new Label("Insensitize Me, too");
	attach(switchLabel2, 0, 2, 1, 1);
	mySwitch2 = new MySwitch();
	attach(mySwitch2, 1, 2, 1, 1);
		
	switchLabel3 = new Label("Me, three!");
	attach(switchLabel3, 0, 3, 1, 1);
	mySwitch3 = new MySwitch();
	attach(mySwitch3, 1, 3, 1, 1);

	myButton = new MyButton();
	attach(myButton, 0, 4, 2, 1);
	myButton.addCompanion(cast(Widget)mySwitch1);
	myButton.addCompanion(cast(Widget)mySwitch2);
	myButton.addCompanion(cast(Widget)mySwitch3);

	setBorderWidth(borderWidth);
	setMarginBottom(10);
	setColumnSpacing(columnSpacing);
	setRowSpacing(rowSpacing);
		
} // this()

The first three sets of four statements each add a Switch along with a Label. The only tricky bit in there is making sure we count Grid rows and columns correctly. That’s something that, I’m sure, could be automated if one put some effort into it. Perhaps that’ll be the subject of a future post. Anyway…

Once we add myButton—the standard Button that triggers all this insensitivity—we drop it onto the Grid and then call myButton.addCompanion() for each Switch.

The rest is all stuff we’ve done before.

Conclusion

There’s no limit to how many Widgets—or which type(s) of Widgets—we can add to the list. Since addCompanion() is set up to add a generic Widget, all you have to do is use the cast() function to match what addCompanion() needs and you’re all set. And with ObjectG being everybody’s great-grandparental unit, you don’t have to worry about climbing too far up the hierarchy to access the bindProperty() function.

That’s it for now. Take care of each other and don’t let the bad guys win.

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