Search code examples
c++widgetcontainersgtkmm3

c++ gtkmm 3.0 toggle content in container widget in a Gtk::Window


I would love to create an application that is able to show different contents in the middle of a fixed size touchscreen. In my romantic imagination, I will have two thin buttons on the left and right side of the screen to toggle through the contents in the middle. I want those contents to show pictures with changing information on them (Gtk::DrawingArea) or have buttons arranged in a Gtk::grid for example. Basically, I want to have changing Gtk:Windows in the middle of a Gtk::Window without titlebars. But a window in a window does not make sense. I searched for gtkmm container widgets, but do not know which one to choose. Probably, there is none and I need a completely different approach?

My first approach was to set up a Gtk::Window named "GrundStruktur" containing one grid for two buttons left and right and a placeholder for a general Gtk::Widget.

The main function:

#include "GrundStruktur.h"
#include "Dachgeschoss.h"
#include <memory>
#include <gtkmm/application.h>
#include <gtkmm/button.h>

int main (int argc, char *argv[])
{
  auto app = Gtk::Application::create(argc, argv, "LBW.Touchscreen.DG");
  //std::unique_ptr<Gtk::Widget> hey = std::make_unique<Gtk::Button> ("Oha");
  //std::unique_ptr<Gtk::Widget> ho = std::make_unique<Gtk::Button> ("Aho");
  Gtk::Widget * ho = new Gtk::Button("Aho");
  Gtk::Widget * hey = new Gtk::Button("Oha");
  GrundStruktur grundStruktur{ho, hey};
  return app->run(grundStruktur);
}

GrundStruktur's contructor takes a std::initializer_list with pointers to Gtk::Widgets. For testing purposes, I created two Gtk::Buttons, to pass to GrundStruktur. I wanted to use std::unique_ptr instead of classic pointers to the heap, but did not manage to get it going with an initializer_list. But I can only concentrate on one problem after the other;-)

GrundStruktur looks like this:

#include <memory>
#include <gtkmm/window.h>
#include <gtkmm/grid.h>
#include <gtkmm/button.h>

class GrundStruktur : public Gtk::Window
{
    public:
        //GrundStruktur(std::initializer_list<std::unique_ptr<Gtk::Widget> > il);
        GrundStruktur(std::initializer_list<Gtk::Widget* > il);
        ~GrundStruktur();

    private:
        Gtk::Grid grid_haupt_teilung; 
        
        Gtk::Button button_mitte_wechsel_links;
        Gtk::Button button_mitte_wechsel_rechts;

        std::vector<Gtk::Widget* > Mitte;
        //std::vector<std::unique_ptr<Gtk::Widget > > Mitte;
        
        //Signal handlers:
        void links_modus();  //durchtoggeln links
        void rechts_modus(); //durchtoggeln rechts
};

The std::vector<Gtk::Widget* > Mitte is supposed to hold the pointers to the Widgets for the screen middle. If the user presses the Gtk::Button button_mitte_wechsel_links the next Widget is supposed to be shown on the screen. And so on.

Here is the contructor:

GrundStruktur::GrundStruktur(std::initializer_list<Gtk::Widget* > il) : Mitte(il)
{
    set_default_size(800, 480);
    set_size_request(800, 480);
    set_decorated(false);
    set_resizable(false);  
    set_position(Gtk::WIN_POS_CENTER);

    button_mitte_wechsel_links = Gtk::Button("<");
    button_mitte_wechsel_rechts = Gtk::Button(">");

    grid_haupt_teilung.set_orientation(Gtk::ORIENTATION_HORIZONTAL);

    grid_haupt_teilung.attach(button_mitte_wechsel_links,  0, 0);
    grid_haupt_teilung.attach(*Mitte.front(),              1, 0);
    grid_haupt_teilung.attach(button_mitte_wechsel_rechts, 2, 0);

    add(grid_haupt_teilung);
button_mitte_wechsel_links.signal_clicked().connect(sigc::mem_fun(*this,&GrundStruktur::links_modus));
    button_mitte_wechsel_rechts.signal_clicked().connect(sigc::mem_fun(*this,&GrundStruktur::rechts_modus));

    show_all_children();
}

With my test buttons in main() hey and ho it works. Gtk::Buttons are Gtk::Widgets - fine. But if I want to set up a custom Widget container to hold a Gtk::Grid for example, I do not know which one to take. In the gtkmm documentation there is for example a Gtk::Fixed Widget, which I might be able to use, but I am unable to derive a custom class from Gtk::Fixed.

Which is the widget-type for my custom Widget in the middle of the screen? Is a Gtk::Widget the right choice? I am thankful for every idea.


Solution

  • I was able to figure it out. The answer is easy. A Gtk::Grid is a Gtk::Widget that can be filled with basically any content. A content in the middle of the screen simply has to be derived from Gtk::Grid.