Coding Policies within UI-Layer =============================== NOTE: for the time being, this is a loose collection of Conventions and Policies deemed adequate for work on the Lumiera UI-Layer Architecture ------------ The UI is loaded as Plug-In, which instantiates a `GtkLumiera` object. All of the UI activity happens within the blocking function `GtkLumiera::run()`. This UI activity boils down to run the GTK event loop; we use a dedicated thread, and all of the GUI thus performs single-threaded and need not be thread-safe. All UI activities thus need to be short running and with deterministic outcome. It is strictly prohibited to spawn other threads from within the event loop. We hold up a strict distinction between the _UI mechanics_ and the _core editing concerns_. The latter _must not be implemented within the UI-Layer._ Rather, you need to send an `act(CommandID)` message over the UI-Bus, which causes the corresponding Proc-Layer command script to be dispatched within the Session thread. It is good practice to give an immediate visual clue regarding the fact of sending such a command (e.g. pressing a button). But be prepared that the actual feedback of invoking a command happens asynchronously. UI-Model ~~~~~~~~ In short: _there is no dedicated UI-Model._ Stateful working data goes directly into the widgets. However, some widgets or controllers are special, insofar they correspond to and reflect some entities within the _Session model._ These special entities must be implemented as subclasses of `gui::model::Tangible`. These are always connected to the UI-Bus, and they are populated and mutated by receiving diff messages pushed up from the Proc-Layer. There is an _inner circle_ of UI backbone services. These are all mutually dependent on each other and their start-up sequence is intricate. Implement global and cross-cutting concerns here. In case some widget or controller needs access to such a service, then you should prefer using `lib::Depend`, and install the corresponding service via `lib::DependInject::ServiceInstance`. Code organisation ----------------- GTK is massive and compilation times tend to be problematic in the UI-Layer. Thus you should be diligent with the organisation of includes. Try to confine the more heavyweight includes within the implementation translation units. Use forward declarations and PImpl if possible. However, it is fine to write a mere implementation widget in header-only fashion, in case this improves the locality and readability of code. NOTE: `using namespace Gtk` and similar wildcard includes are prohibited. We are forced to observe a tricky include sequence, due to NoBug's `ERROR` macro, and also in order to get I18N right. Thus any actual translation unit should ensure that effectively the first include is that of 'gui/gtk-base.hpp'.footnote:[you need not include it literally. It is perfectly fine if you can be sure the first included header somehow drags in 'gtk-base.hpp' before any other header.]