0004: OOP Buttons, with and without Arguments

NB: In any given example file, to find the code that’s new since the previous example, look for a comment like this:

// *** NEW ***

This time around, the companion code is here and here.

I’ve defined two classes in this example. The first one, TestRigWindow, you’ve already seen in the OOP version of the base code file. The second one, we’ll talk about in a moment.

General Principles of OOP

Not all of them; that would be far beyond the scope of this blog post (or the blog in its entirety) so I’ll just say this…

OOP is about code organization. It’s about cutting back on bugs or at least having a better idea of where to look for them. No system of this kind is perfect, but that’s life. A class is meant to encapsulate specific data as well as any functions that act upon that data. The point is to protect the data from outside influences that might screw things up.

With that in mind, let’s look at the new class.

The MyButton Class

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

And here it is:

class MyButton : Button
{
	string labelText = "Click this";

	this()
	{
		super(label);
		addOnClicked(&buttonAction);
		
	} // this()
	
	
	void buttonAction(Button b)
	{
		writeln("Action taken.");
		
	} // buttonAction()
	
} // class MyButton

MyButton isn’t the name I’d use for production. It would be more descriptive of the data/actions involved, but for this example, it’ll do.

Since we don’t have any data, we only need to encapsulate actions and a constructor. All the constructor does is call its parent class while passing along its label text, and then hook up the signal we’re going to track for this button.

The other function, buttonAction() stands in for whatever function might work on whatever data we might use… if we had data. All it does is write a line to the shell so we know it’s there and working.

But if We Pass an Argument…

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

Here’s the second version of this class:

class MyButton : Button
{
	string labelText = "Click this";

	this()
	{
		string message = "Next time, don't bring the Wookie.";
		
		super(labelText);
		//addOnClicked(delegate void(Button b) { buttonAction(message); });
		addOnClicked(delegate void(_) { buttonAction(message); });
		
	} // this()
	

	void buttonAction(string message)
	{
		writeln("The message is: ", message);
		
	} // buttonAction()
	
} // class MyButton

You’ll notice the signal hook-up is different this time around. Even though we’re in scope, we need to use a delegate so we can pass an argument along to buttonAction(). Also note that there’s another way of phrasing this hook-up and it’s commented out so as not to confuse things. But either way will work. The second way uses an underscore as a placeholder of sorts. It’s effectively saying: pass the originator along as a first argument and the compiler is smart enough to figure out that, in this case, the originator is a GTK Button.

And everything else should be obvious. (If not, email me.)

And that’s it for this time. Next time we’ll look at how to open a window of a specific size. Until then, happy D-coding and may the widgets be with you.

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