As I've posted a couple of times in another section of this forum, I'm creating a very simple GUI composit control. This is not something that is going to be overly useful, rather it's an exercise in trying to learn how the JUCE framework works and how to understand it better.
Some of you may have seen other posts of mine where I mention that I'm just getting back into C++ after about a 15 year haitus due to other technologies I've been using over the years. On top of that, I'm trying to learn the JUCE framework as well. Taking on a lot all at once. :)
In specifics I think what I'm trying to achieve here is figuring out messaging works in this environment. If I have composite controls made up of composite controls, how do I get all the communications ( events ) working up and down the heirarchy.
In C# and in Adobe Flex, that world works in a highly event driven paradigm, which in the C++ world is as well, but seems to be handled a little differently. In adobe flex you would have something like this.
myButton.addEventListener( ButtonClick, "someFunctionName" );
Where myButton is an instance of a Button class. ButtonClick is a defined type of event you want to listen for and "someFunctionName" is the name of the function that gets executed when a ButtonClick event occurs. Also, those events can propagate back up the heirarchy chain. Bubbling.
I understand that the event handling here in JUCE is based on the observer pattern. But that is where I'm getting a little thrown off. I'll address that more in a minute, but for now, I'd like to show you what I have so far in my composite component project...
FilePickerCtrl Consists of :
1) Text Button
2) Text Editor
This is a composit control and it's goal is to simply supply a button to press which bring up the JUCE file chooser dialog box, once a user has chosen a file, the full path to the file gets populated into the text editor for display (could have just been a label I suppose ), at the same time, I save that path string into a private variable. Oh and because this uses a TextButton class, the FilePickerCtrl also extends Button::Listener. This is to trap the click event so I can handle it in the FilePickerCtrl itself.
XMLFilePreviewDisplayCtrl consts of :
1) TreeView
2) FilePickerCtrl
The purpose of this control is to bring together the functionality of the FilePickerCtrl and the ability to display the file in the tree view. Specifically I will be choosing an XML and display it's data/heirarchy in the TreeView.
The way I'd like this control to handle user interaction is
1) User presses the button on the FilePickerCtrl
2) The file path gets saved into the FilePickeCtrl's private _path variable.
3) An event is fired from the FilePickerCtrl that lets the parent XMLFilePreviewDisplayCtrl know that a file has been chosen.
4) The XMLFilePrevewDisplayCtrl then loads that file.
Now, here is where I'm thrown off by the observer pattern the way it's been implimented in JUCE. It's the use of the CTRL::Listener object. Where CTRL is say a Button. I've looked at the code and can see that the Listener is a ( pardon me here not sure of the proper terminology) imbedded class in the Button class. (Just using the button class as an example here). What exactly is the need for this listener class? When I look at the code shown
class JUCE_API Listener
{
public:
/** Destructor. */
virtual ~Listener() {}
/** Called when the button is clicked. */
virtual void buttonClicked (Button*) = 0;
/** Called when the button's state changes. */
virtual void buttonStateChanged (Button*) {}
};
Is it safe to say that this is to enforce that who ever uses the TextButton class ( or any other class inheriting from Button ) is forced to implement buttonClicked ? But if that is the case, why add the overhead of this class in the first place? Just have the buttonClicked as a virtual function directly on the Button class? Please understand I'm not saying this is wrong... Far from it, I'm simply trying to understand the engineering mindset behind it so I can learn from it.
One thing that crossed my mind was flexability... Maybe someone would want a button but didn't want to create an event handler for it??? Again, I'd love to know the thought process behind it.
And this is where I come across another question...
The FilePickerCtrl has a button, and because of this, this class inherits from Button::Listener as well as Component. I don't see a point in allowing any further in heritace. Lets just say for simplicity sake, nobody would ever take this control and inhert from it to create yet another control... It is what it is...
What is at this point, the proper architecture (as it relates to JUCE) to ensure that the XMLFilePreviewCtrl gets notified when that FilePickerCtrl button is clicked? Would I want to create my own FilePickerCtrl::Listener class that looks identical to the code above? Or do I at this point drop concept of the Listener class and go with a more traditional observer patten and if so... Then the FilePickerCtrl would have either a single observer or a collection of observers that it would notify by calling a notify method on the observer.
Sorry for the long post... I'm just trying to ensure that whatever I do fits seemlessly with the juce framework...