Lumiera
The new emerging NLE for GNU/Linux
/*
  gtk-uring-app.hpp  -  simple GTK Host Application

   Copyright (C)
     2025,            Benny Lyons <benny.lyons@gmx.net>
     2025,2026        Hermann Vosseler <Ichthyostega@web.de>

  This program is free software; you can redistribute it and/or modify it
  under the terms of the GNU GPL version 2+ See the LICENSE file for details.

* ************************************************************************/

#ifndef GTK_URING_APP_H
#define GTK_URING_APP_H

#include "commons.hpp"

#include <gtkmm/window.h>
#include <gtkmm/button.h>
#include <gtkmm/application.h>
#include <glibmm/dispatcher.h>

#include <functional>
#include <memory>

using std::unique_ptr;
using Glib::ustring;
using std::move;



/**
 * Minimalist GTK application, used as framework for a demo of reading and displaying video.
 * @tparam CTX custom data context to allocate while periodic processing is active
 * @remark The actual actions can be installed as functors / callbacks
 *       - onClick() installs a function to be invoked when the button is first clicked;
 *         this function must return a _context object,_ which represents "the process"
 *         and will be copied into heap storage; the further functors will receive context.
 *       - onClose(CTX&) will be invoked when the application is shut down
 */
template<class CTX>
class GtkUringApp
  : public Gtk::Application
  {
    class DemoWindow
      : public Gtk::Window
      {
      public:
        DemoWindow()
          {
            set_resizable (false);
            add (button_);
            button_.show();
          }

        Gtk::Button button_{"click to start video..."};
      };

    DemoWindow demoWindow_;


  public:
    GtkUringApp (ustring appID)
      : Gtk::Application{appID}
      {
        demoWindow_.set_title (appID);
      }


    using StartTask = std::function<unique_ptr<CTX>(Gtk::Window&)>;
    using CloseTask = std::function<void(CTX&)>;

    GtkUringApp&
    onClick (StartTask task)
      {
        startTask_ = move(task);
        return *this;
      }
    GtkUringApp&
    onClose (CloseTask task)
      {
        closeTask_ = move(task);
        return *this;
      }

    int
    run()
      {
        demoWindow_.button_.signal_clicked().connect(
            sigc::mem_fun (*this, &GtkUringApp::triggerProcessing));

        return Gtk::Application::run (demoWindow_);
      }                       // blocks while application is active


  private:
    std::unique_ptr<CTX> processor_;
    StartTask startTask_;
    CloseTask closeTask_;

    void
    triggerProcessing()
      {
        if (processor_) return;

        if (startTask_)
          {
            processor_ = startTask_(demoWindow_);

            demoWindow_.button_.set_sensitive(false); // disable the button
            demoWindow_.button_.set_label("active");

            auto closeHook = [this]{
                                     if (closeTask_)
                                       closeTask_(*processor_);
                                   };

            this->signal_shutdown().connect (closeHook);
          }
      }
  };

#endif /*GTK_URING_APP_H*/