// here's a really simple gtkmm example that shows how a hierarchy of
// widgets is created.

// I've upgraded it just a bit to have it popup a window when
// requested.

// The quit button is still a class of its own, and its callback is
// still private to it.

// The popup and close buttons are both just instances of
// Gtk::Button.  They both get their labels assigned when they are
// instantiated, in the initialization list for their parent objects'
// constructors.

// The close button's callback is hooked up in the popup window's
// constructor, since I need its *this to be value when I hook it up.

// The popup button's callback is hooked up in the Gui's constructor,
// since I need to have both mainWin and popUpWin available to do it.
// In this case, I both created an openMe method in the PopUpWin class
// (I could just as well have hooked the signal up to the hide()
// method directly, but this shows adding a method for the callback to
// talk to), and I made a method for mainWin that would hook up the
// callback -- this let me keep the popup button private.

// The simplest way to compile this will be with
// $ g++ -o myexample myexample.cc `pkg-config --libs --cflags gtkmm-2.4`

// First, we need a #include for every class we're going to import
// from gtkmm
#include <gtkmm/button.h>
#include <gtkmm/frame.h>
#include <gtkmm/main.h>
#include <gtkmm/box.h>
#include <gtkmm/window.h>

// We also need to #include signals
#include <sigc++/signal.h>

// The popup window will contain a "Close" button
class PopUpWin : public Gtk::Window {
  private:
	Gtk::Button closeButton;
	
	void closeMe()
	{
		hide();
	}
	
  public:
	void openMe()
	{
		show_all();
	}

	PopUpWin() :
	  closeButton("Close")
	{
		add(closeButton);
		closeButton.signal_clicked().connect(sigc::mem_fun(*this, &PopUpWin::hide));
	}
	

};

// The main window will contain a 'PopUp' button and a 'Quit' button.
// These will have to be in a vbox 
// In this case, I'm defining the button as a nested class within MainWin.
class MainWin : public Gtk::Window {

  private:
	// The popup button will popup the popup window.  The signal to do
	// this is hooked up in the Gui's constructor since I need both
	// the popup window and the popupbutton defined to be able to do
	// it.
	Gtk::Button popUpButton;
        
    // The Quit button just has a method to exit the program when the
    // button is clicked.  This method can be hooked up to the button
    // itself.
    class QuitButton : public Gtk::Button {
      private:
        void quit()
        {
            exit(0);
        }
        
      public:
        // The constructor for the QuitButton class defines its label
        // by using its base class's constructor, with label.  Then,
        // within the body of the constructor, I hook up the quit
        // button.
        QuitButton() :
          Gtk::Button("Quit")
        {
            signal_clicked().connect(sigc::mem_fun(*this, &MainWin::QuitButton::quit));
        }
    } quitButton;
    
    // I didn't subclass my inner frame.  Typically, if I'm not adding
    // any functionality, I rarely make a subclass.
    Gtk::Frame innerFrame;
	Gtk::VBox vbox;
	
  public:
    MainWin() :
	  popUpButton("PopUp")
    {
		add(innerFrame);

        // since I didn't subclass innerFrame, I just use its member
        // functions from the mainwin class.
		innerFrame.set_border_width(5);
		innerFrame.set_label("This is my Frame");
		innerFrame.add(vbox);
		vbox.add(popUpButton);
		vbox.add(quitButton);

        // This shows the whole widget tree
        show_all();
    }

	void setPopUp(PopUpWin& popUp)
	{
		popUpButton.signal_clicked().connect(sigc::mem_fun(popUp, &PopUpWin::openMe));
	}
};

// I could have made the main window a nested class within the GUI,
// too.  This way I have an example of nesting, and an example of not
// nesting.  It's pretty much a judgement call whether you want to
// nest classes or not (I rarely do it).
class Gui : public Gtk::Main {
  public:
    MainWin mainWin;
	PopUpWin popUp;
    Gui(int argc, char **argv) :
      Gtk::Main(argc, argv)
    {
		// When I get in here, MainWin and PopUpwin have both been
		// instantiated.  So I can hook up the popup button and bring
		// up the popup window with it
		mainWin.setPopUp(popUp);
	}
};

int main(int argc, char **argv)
{
    // one fine point that has caused me no end of grief:  the gui has
    // to be instantiated after main() is started, or else you don't
    // have argc and argv yet, and everything goes bad.
    Gui gui(argc, argv);
    
    gui.run(gui.mainWin);
}

