diff --git a/src/gui/ctrl/actions.hpp b/src/gui/ctrl/actions.hpp index c85f57162..acde2fa3a 100644 --- a/src/gui/ctrl/actions.hpp +++ b/src/gui/ctrl/actions.hpp @@ -27,6 +27,12 @@ ** The individual menu options are bound to functors (closures), which use a _global UI context_ ** to access the target objects or invoke the signals. ** + ** @todo the old `Gtk::Action` and `Gtk::ActionGroup` are planned to be deprecated. + ** Recommendation is to rely on `Gtk::Builder` and `Gtk::SimpleAction` instead. + ** As of 5/2017, it is not clear to what extent this might force us into additional + ** "desktop integration" we do not need nor want (like automatically connecting to + ** D-Bus). For that reason, we'll postpone this transition for the time being /////////////////////TICKET #1068 + ** ** @see ui-manager.hpp ** @see gtk-lumiera.cpp */ @@ -55,7 +61,6 @@ namespace ctrl { using Gtk::ToggleAction; using Gtk::AccelKey; using Gtk::StockID; - using Gtk::Main; /////////////////////////////////////////////////////////////////////////////////////TICKET #1032 replace Main -> Application using Glib::ustring; using ::util::_Fmt; using std::string; diff --git a/src/gui/ctrl/ui-manager.cpp b/src/gui/ctrl/ui-manager.cpp index 318a8bbb9..934490a70 100644 --- a/src/gui/ctrl/ui-manager.cpp +++ b/src/gui/ctrl/ui-manager.cpp @@ -55,37 +55,50 @@ namespace ctrl { using workspace::StyleManager; - namespace { // dummy command line for GTK - int argc =0; - } - // dtors via smart-ptr invoked from here... - UiManager::~UiManager() - { } + UiManager::~UiManager() { } /** - * Initialise the GTK framework libraries + * Initialise the GTK framework libraries. + * @remark in 5/2017 we abandoned the (deprecated) `Gtk::Main`, + * but we did not switch to `Gtk::Application`, rather we just + * incorporated the framework initialisation code directly into + * our own code base. This allows us to ignore all the shiny new + * D-Bus and desktop integration stuff. */ ApplicationBase::ApplicationBase() - : Gtk::UIManager() - , gtkMain_(&argc, nullptr) { Glib::thread_init(); + //---------------------------------------------copied from Gtk::Main + gtk_init (nullptr, nullptr); + Gtk::Main::init_gtkmm_internals(); + //---------------------------------------------copied from Gtk::Main Gdl::init(); } + ApplicationBase::~ApplicationBase() + { + //---------------------------------------------copied from Gtk::Main + // Release the gtkmm type registration tables, + // allowing Main to be instantiated again: + Glib::wrap_register_cleanup(); + Glib::Error::register_cleanup(); + //---------------------------------------------copied from Gtk::Main + } + /** - * Initialise the interface globally on application start. - * Setup the main application menu and bind the corresponding actions. - * Register the icon configuration and sizes and lookup all the icons. - * @see lumiera::Config + * @remark Creating the UiManager initialises the interface globally on application start. + * It wires the global services and attaches to the UI-Bus, defines the main + * application menu and binds the corresponding actions. Moreover, the StyleManager + * register the icon configuration and sizes and loads the icon definitions. */ UiManager::UiManager (UiBus& bus) : ApplicationBase() + , Gtk::UIManager() , globals_{new GlobalCtx{bus, *this}} , actions_{new Actions{*globals_}} , styleManager_{new StyleManager{}} @@ -96,7 +109,8 @@ namespace ctrl { /** * @remarks this function is invoked once from the main application object, - * immediately prior to starting the GTK event loop. */ + * immediately prior to starting the GTK event loop. + */ void UiManager::createApplicationWindow() { @@ -105,17 +119,33 @@ namespace ctrl { } + /** + * Run the GTK UI. + * @remarks this function is equivalent to calling Gtk::Main::run() + * In GTK-3.0.3, the implementation is already based on libGIO; + * after possibly handling command line arguments (which does not apply + * in our case), it invokes `g_main_loop_run()`, which in turn ends up + * polling the main context via `g_main_context_iterate()`, until the + * use count drops to zero. This is the "event loop". + */ void UiManager::performMainLoop() { - gtkMain_.run(); // GTK event loop + gtk_main(); // GTK event loop } + /** + * @note this function can be invoked from an UI event, since it just + * signals shutdown to the GTK event loop by invoking `gtk_main_quit()`. + * The latter will finish processing of the current event and then return + * from the UiManager::performmainLoop() call, which eventually causes the + * UI subsystem to signal termination to the Lumiera application as a whole. + */ void UiManager::terminateUI() { - gtkMain_.quit(); + gtk_main_quit(); } void diff --git a/src/gui/ctrl/ui-manager.hpp b/src/gui/ctrl/ui-manager.hpp index b286b1191..3a8048756 100644 --- a/src/gui/ctrl/ui-manager.hpp +++ b/src/gui/ctrl/ui-manager.hpp @@ -23,12 +23,16 @@ /** @file ui-manager.hpp - ** Manager for global user interface concerns and global state. - ** The central UiManager instance is owned by the GtkLumiera object and initialised in GTK-main. - ** It establishes and wires the top-level entities of the UI-Layer and thus, indirectly offers - ** services to provide Icons and other resources, to open and manage workspace windows, to - ** form and issue (global) actions and to delve into the UI representation of top-level parts - ** of the session model. Notable connections established herein: + ** Manager for global user interface concerns, framework integration and global state. + ** The central UiManager instance is owned by the GtkLumiera (plug-in) object and has the + ** responsibility to operate the _UI framework_. It establishes and wires the top-level entities + ** of the UI-Layer and thus, indirectly offers services to provide Icons and other resources, to + ** open and manage workspace windows, to form and issue (global) actions and to delve into the + ** UI representation of top-level parts of the session model. And, last but not least, it + ** exposes the functions to start and stop the GTK event loop. + ** + ** The initialisation and shutdown of the framework is handled by the ApplicationBase parent, + ** while the constituents of the Lumiera UI backbone are allocated as member fields: ** - connection to the [UI-Bus](\ref ui-bus.hpp) ** - the global Actions available though the menu ** - the InteractionDirector (top-level controller) @@ -67,23 +71,28 @@ namespace ctrl { /** Framework initialisation base */ class ApplicationBase - : public Gtk::UIManager - , boost::noncopyable + : boost::noncopyable { protected: - Gtk::Main gtkMain_; ApplicationBase(); + ~ApplicationBase(); }; /** - * Manage global concerns regarding a coherent user interface. - * Offers access to some global UI resources, and establishes - * further global services to create workspace windows, to bind - * menu / command actions and to enter the top-level model parts. + * The Lumiera UI framework and backbone object. + * Initialises the GTK and GLib framework, starts and stops the + * GTK event loop, and manages global concerns regarding a coherent user interface. + * Offers access to some global UI resources, and establishes further global services + * to create workspace windows, to bind menu / command actions and to create interface + * widgets for working with the the top-level model parts. + * @note UiManager itself is _not a model::Controller,_ and thus not directly connected + * as a first-class entity to the Bus, but it operates the GlobalCtx, and thus in + * turn holds the interact::InteractionDirector, which corresponds to the model root. */ class UiManager : public ApplicationBase + , public Gtk::UIManager { unique_ptr globals_; unique_ptr actions_; @@ -92,11 +101,10 @@ namespace ctrl { public: /** - * There is one global UiManager instance, - * which is created by [the Application](\ref GtkLumiera) - * and allows access to the UI-Bus backbone. The UiManager itself - * is _not a model::Controller,_ and thus not directly connected to the Bus. - * Rather, supports the top-level windows for creating a consistent interface. + * Initialise the GTK framework and the Lumiera UI backbone. + * There is one global UiManager instance, which is created by + * [the Application](\ref GtkLumiera). + * @see #performMainLoop */ UiManager (UiBus& bus); ~UiManager (); diff --git a/wiki/renderengine.html b/wiki/renderengine.html index 43107fd1a..79cbebe36 100644 --- a/wiki/renderengine.html +++ b/wiki/renderengine.html @@ -2747,7 +2747,7 @@ Command instances are like prototypes -- thus each additional level of different see the description in → CommandSetup -
+
All communication between Proc-Layer and GUI has to be routed through the respective LayerSeparationInterfaces. Following a fundamental design decision within Lumiera, these interface are //intended to be language agnostic// — forcing them to stick to the least common denominator. Which creates the additional problem of how to create a smooth integration without forcing the architecture into functional decomposition style. To solve this problem, we rely on ''messaging'' rather than on a //business facade// -- our facade interfaces are rather narrow and limited to lifecycle management. In addition, the UI exposes a [[notification facade|GuiNotificationFacade]] for pushing back status information created as result of the edit operations, the build process and the render tasks.
 
 !anatomy of the Proc/GUI interface
@@ -3127,7 +3127,7 @@ Applying a diff changes the structure, that is, the structure of the local model
 Together this means we get a fix up stage after model changes, where the display is re-adjusted to fit the new situation. This works in concert with the [[display manager|TimelineDisplayManager]] representing only those elements as actual widgets, which get a real chance to become visible. This way we can build on the assumption that the actual number of widgets to be managed any time remains so small as to get away with simple linear list processing. It remains to be seen how far this assumption can be pushed -- the problem is that the GTK container components don't support anything beyond such simple linear list processing; there isn't even a call to remove all child widgets of a container in a single pass.
 
-
+
To a large extent, the Lumiera user interface is built around a //backbone structure,// known as the UI-Bus.
 But there are some dedicated top-level entities, collaborating to maintain a consistent application lifecycle
 ;Application
@@ -3137,7 +3137,7 @@ But there are some dedicated top-level entities, collaborating to maintain a con
 :the backbone of the user interface
 :as central communication system, the UI-Bus has a star shaped topology with a central router and attached CoreService
 ;UI Manager
-:maintain a coherent global interface
+:maintain a coherent global interface and perform the GTK event loop
 :responsible for all global framework concerns, resources and global application state
 ;Interaction Director
 :establish the connection between global interaction state and global session state
diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm
index 5e71233f8..a00bd2942 100644
--- a/wiki/thinkPad.ichthyo.mm
+++ b/wiki/thinkPad.ichthyo.mm
@@ -635,9 +635,9 @@
 
 
 
-
+
 
-
+
 
 
 
@@ -730,7 +730,7 @@
 
 
 
-
+
 
 
 
@@ -745,6 +745,40 @@
 
 
 
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
 
 
 
@@ -759,7 +793,11 @@
 
 
 
-
+
+
+
+
+
 
 
 
@@ -779,26 +817,32 @@
 
 
 
-
-
+
+
+
+
 
+
 
 
 
-
+
 
-
+
 
 
 
-
+
 
 
+
+
 
 
 
 
-
+
+
 
 
 
@@ -1800,9 +1844,10 @@
 
 
 
-
+
+
 
-
+
 
 
 
@@ -1909,9 +1954,8 @@
 
 
 
-
+
 
-
 
 
 
@@ -1924,12 +1968,46 @@
 
 
 
-
+
 
+
 
 
 
-
+
+
+  
+    
+  
+  
+    

+ Begründung: +

+

+ Das neue System ist anscheinend fest integriert in Gio::Application. +

+

+ Mir ist nicht klar, wieso ein Fenster/Widget das Interface Gio::Actionable implementieren muß. +

+

+ Ich werde den Verdacht nicht los, daß hier das Ziel verfolgt wird, eine "Action" von den +

+

+ Grenzen der Applikation zu befreien und direkt in den Desktop zu integrieren. +

+

+ Mit Desktop ist natürlich der Gnome-Desktop gemeint. Was diesen Verdacht bestärkt, +

+

+ ist, daß Gio::Application sofort auch gleich eine dBus-Verbindung hochfährt. +

+ + +
+ +
+ + @@ -1941,16 +2019,19 @@ - + - + + + + + - @@ -16619,7 +16700,7 @@ - + @@ -16628,8 +16709,141 @@

...nicht mehr das klassische gtk::Main

+

+ +

+

+ Wozu das? +

+
    +
  • + Design: Main war ein Singleton; aber sein dtor hat auch Plattform-Aufräum-Arbeiten gemacht +
  • +
  • + Framework: anscheinend ist hier eine Tendenz in Richtung auf ein integriertes Framework im Gange; im Besonderen will man "Aktionen" direkt aus dem Desktop aufrufen können
    +
  • +
-
+ + +
+
+ + + + + + + + + + + + + + +

+ warum? +

+

+ nur wegen ApplictationWindow! +

+

+ Denn dieses setzte eine "Registrierung" voraus. +

+

+ Alles in ein Framework zwingen. Alternativlos, capisce? +

+ + +
+ +
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ initialisiert das +

+

+ Framework +

+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ ...das heißt, es wurde "retrofitted". +

+

+ die Lib Gio bietet ein generisches "Main-Loop-Framework", +

+

+ in dem ein Main-Context gepollt wird, solange, bis ein use-count auf Null geht. +

+

+ Gtk-Main verwendet inzwischen den gleichen Mechanismus +

+ + +
+