''a new hope''
This was quite a long way until we're back at the point of
re-building the timeline anew.
Stash the canvas research code to make room for new things to come
this turned out to be more tricky than expected.
When we initially configure the UI and invoke this->show_all(),
seemingly some draw-callbacks will be scheduled into the event loop.
Just set_visible(false) on the relevant buttons directly after that call
will have no effect (since the widget is still hidden at that point anyway,
it is not yet mapped and realised).
Thus we need to schedule a callback with the Glib::signal_idle(),
so our state detection runs after the initial mapping of the UI
NOTE: there is a minor itch, which I don't address right now:
when adding the error state and thus revealing the additional buttons,
the error log grabs some additional horizontal space, even while there
would be ample space for the additional buttons within the button bar.
When the error state is cleared and the buttons thus hidden again,
the additional horizontal space is dropped and the error log gets
narrower. Probably we'd need some special GTK call to re-allocate
the required space properly
solved by temporarily adding a CSS class.
Mostly this was an issue of writing the Stylesheet properly.
Hint: use the GTK+ inspector, i.e. run with
GTK_DEBUG=interactive target/lumiera
Even while we (still) have the goal to ship our own stylesheet and provide
the typical subdued media-aplication look, right now this porting and styling effort (#1023)
is unfinished and handled with rather low priority (writing code is more important
than toying with styles and looks).
This alternative stylesheet is meant to be used with a typical "light" desktop theme.
We'll add just the bare minimum of definitions to make lumiera work well in that setup.
And right now, I'll use that setup to continue with my development work
In GTK-2 you'd always use a theming engine.
During the transitional period, GTK-3 followed that path,
but at the point when the new CSS based system was mature enough,
this approach was discouraged, since it means to ship additional
executable code and defeats the purpose of configuring the look
of the application through one coherent set of rules.
As it turns out, debian continued to ship the 'adwaita' for some
extended transitional period, but in Stretch it is gone, which broke
our half-way ported stylesheet.
This changeset removes the use of a theming engine, and fixes tha
basic look by adding the background-color: inherit, which pushes aside
many (but not all) of the default theme definitions.
However, our stylesheet remains mostly broken and TODO for now
Basically we create a pair of marks, with left/right gravity and then
inject the content between. Unfortunately, when the insert position
is the very end of the buffer (which it always is), this trick
leads to nesting the marked regions into each other.
As a remedy, we first insert the trailing newline,
and then attach the insert position one step before
discard all other info log messages and retain only the entries marked as error.
This is also a proof-of-concept regarding position bookmarks and markup.
Implemented by populating a new buffer and swapping it into place.
== possible Scenario ==
1. Gui: sigTerm invoked
2. last Subsystem -> cleans all remaining Subsy entries
3. main-Thread wakens
4. leaves main() und undloads the GUI plug-in
5. which destroys the `DependencyFactory<LocationQuery>` placed in static memory
6. the Gui-Thread returns from sigTerm() and invokes `~UiManager()`
7. which indirectly deregisters through `InteractionDirector` the `LocationQuery` Service
8. `DependInject::Service::shutdown()` grabs the Lock ==> **BOOM**
== Solution ==
Ensure all dtors of the UI backbone are invoked ''prior'' to calling sigTerm()
The very backbone structure of the Lumiera UI, the UI-Bus is now fully defined
and proven to be operative, including asynchronous dispatch of messages
an a generic notification mechanism
A communication chain, triggered from a button in a non-modal dialog box,
passing invocation into another thread, dispatched by the ProcDispatcher,
then again passing thread boundaries to push a response back into the UI.
This is a milestone, and integrates several components built during the last years.
- a text input field
- a trigger to invoke the showInfo function on GuiNotification
- triggers to send state mark messages via GuiNotification into the UI-Bus
- a combo box to define the action-ID within those state mark messages
With these controls, it should be possible to execute all the variations
of the Tangible element protocol and verify the respective behaviour
has been coded up properly within the receiving ErrorLogDisplay widget
Note the key point (and the next step to code up) is for #1099 to
invoke a dummy/demo command in Proc-Layer, which in turn pushes an
reaction via the GuiNotification facade back into the UI asynchronously...
wrap up the helpers and wire the connection to the UI-Bus.
Then attempt a direct invocation, still within the GTK thread.
While this might seem as just some silly experiment, in fact it is
*** THE FUCKING FIRST TIME to transmit a visible action to a real widget ***
this links together and integrates various efforts achieved during the last years
Gtk::Notebook is a quite powerful container foundation to build complex dialog widgets with multible pages on tabs.
Hower, the construction, wiring an setup is notoriously tedious, due to the repetitiveness
and the sheer amount of child widgets spread over various pages.
This design draft is an attempt to mitigate the required boilerplate, without
overly much obscuring the structure. The basic idea is to package each page into
a locally defined child struct, which is actually heap allocated and managed automatically.
This way, each child page gets its own namespace, and wiring to other components
is made explicit by passing named ctor arguments -- while the overall structure
of building and wiring of widgets stays close to the habits of Gtkmm programming.
...which gives us already the base functionality required to run the first tests
- can be triggered from the Help menu
- non-modal dialog (Gtk::Dialog)
- attached as child / slave-Window to the current active workspace window
- window manager hint to keep it on top
- have a notebook control within the dialog
- attached (passively) to the UI-Bus
...just to decide not to follow-up too much on that topic right now.
As it turns out, GTK seems to be lacking in that respect. I have plotted
some ideas how we could work around that discrepancy in future...
And for this simple DemoGuiRoundtrip, we'll just use direct styling,
but we'll store a table of bookmarks for the error entries, allowing
us to add further features later on top
after an extended digression to fix our matcher for tests on the EventLog,
the new helper abstractions gui::model::Expander and gui::model::Revealer
are now covered and ready for use.
In this special case here, the controller uses both the Expander and Revealer
inherited from model::Tangible; yet both are wired to access the actual
display widget via the getter, and delegate to the Expander rsp. Revealer
located within the widget. Which in turn are wired when creating the widget
within the InfoboxPanel.
Bottom line -- we have a generic scheme now, and the actual implementation
is filled in as lambda, at the point where the component or widget is created
...it should have been this way all the time.
Generic code might otherwise be ill guided to assume a conversion
from the Iterator to its value type, while in fact an explicit dereferentiation is necessary
as it turns out, we need to set the property_expand() on the child widget
within Gtk::Expander explicitly, to cause the child to grab and additional
available screen space (which obviously is what we want in case of a
log display with scrollbars)
basically Gtk::Expander will do the trick.
However, resizing of the enclosing panel is not handled properly,
the log does not expand to take up the available space, as it did
automaticall when just added directly into the frame
no need to define a private function on Wizard anymore, it just forwards the call
to the service actually implementing the view allocation. For now this is the
PanelLocator (and eventually this will be the ViewLocator / ViewSpecDSL)
PanelLocator is a sub component of the WindowLocator (top-level GUI service).
Eventually this shall become a mere widget/component access service, with the
actual lookup and allocation logic layered on top through ViewLocator, configurable
via ViewSpec-DSL.
We can not implement the full scheme right now, since we're lacking knowledge
about internals of a typical Lumiera UI widget
This is only a premature hack, since the whole structure of PanelManager is somewhat broken.
Moreover, the ViewLocator is not really ready for use yet, so this hack at least
allows us to "reach into" a top-level window and "grab" the pannel we need.