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

And here it is:

class MyButton : Button
{
	this(string label)
	{
		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 Have Data…

Here’s the second version of this class:

class MyButton : Button
{
private:
	this(string label)
	{
		string message = "Next time, don't bring the Wookie.";
		
		super(label);
		//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

And now we have data. I’ve used ‘private’ to protect the data and the functions from outside interference. Since there’s no reason for any other entity to have access, nothing in this class is public. We can still call the constructor, even though strictly speaking it’s private, because by using ‘new MyButton()’ the constructor isn’t being called directly, but as part of a lower-level process for instantiating the object.

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 crash 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.

If you'd like to leave a comment, come on over to the D Language Forum and look for one of the gtkDcoding announcement posts. Or 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.

© Copyright 2019 Ron Tarrant