A classical carry-over of dirty values...
Problem arises, when starting an unconditional wait on the same object monitor,
which previously conducted a timed wait. Then the obsolete timeout from the previous
wait remained in place, causing our Sync-Wrapper (erroneously) to assume a timed wait
and then pthread to return immediately from this timed wait.
The result was permanent idle looping in the ProcDispatcher, after the first command was processed
- most notably the NOBUG logging flags have been renamed now
- but for the configuration, I'll stick to "GUI" for now,
since "Stage" would be bewildering for an occasional user
- in a similar vein, most documentation continues to refer to the GUI
the new structure causes them now to be installed into $TARGET/stage
which is simply not what I want. I still consider $TARGET/gui the better choice,
since an administrator or packager is not aware of our layer namings.
The existing solution was half baked anyway, it did not really replicate the source tree.
On the other hand, I want to retain the location of the CSS files within the GUI tree,
since I consider it a good practice, to keep "code-like" resources with the actual code,
and not far away in some arcane "data" directory.
No I've noticed, that the env.GuiResource() function is only used once, for this very task.
So, for the time being, we can keep it simple and deditaced to that task, i.e
we pick up all CSS files we find and install it into a single target directory.
NOTE: this issue has brought to my attention two further, completely unrelated issues
* Ticket #1192 (Lumiera hangs on failed GUI start)
* The ProcDispatcher does an idle wait, due to an error in timed-wait implementation
Considering this since some time, since it more and more occurred to me
the existing conventional names are a misfit. And they are dull and clumsy.
This fall, I mentioned it to Benny, and he seemed to be rather favourable towards that idea,
which encourages me just to go ahead. Unfortunately, I am alone on the coding frontier
right now, which has several downsides, but at least it gives me the ability
to pull off radical moves.
...in accordance to our general design guideline: we don't duplicate
actual model values within the controllers/presenters, since our widgets
act themselves as view-model
This change demonstrates how to deal properly with possible duplicate entities
with similar symbolic ID: define a RandomID (to guarantee a distinct hash on each instance).
In the actual implementation, this should happen already within the domain model,
not when constructing the diff (obviously of course...)
This change also adds a mutation sequence to inject the actual track name
same pattern as the existing EntryID, i.e. a human readable symbol plus a hash
but the hash is just random, instead of deriving it from the symbol text.
Use case is when we explicitly need a distinct identity, even when the
human readable symbolic name is the same. Actual example: the fork root in the timeline
so this seems to be the better approach for dealing with this insidious problem.
In some cases -- as here most prominently with the root track within the timeline --
we have to care within the domain model to prepare unique ids even for sub objects
treated as attributes. In the actual case, without that special attention,
all timelines would hold onto an attribute "fork" with the same ID, based
on the type of the nested object plus the string "fork". Thus all root track
representations in the GUI would end up listening to the same ID on the UI-Bus...
...rather extend the "object builder" DSL notation to allow passing in a given EntryID literally.
Rationale is, we should handle the problem of unique IDs on the level of the domain model.
If we attempt to "fix" this within GenNode, the price would be to make the ETD creation stateful
this is not a problem, strictly sepaking, locally.
But it becomes a problem once the GUI uses those attribute IDs
as Element-IDs for tangible UI entities, which need to be uniquely
addressable via the UI-Bus.
An obvious solution is to inject randomness into the Attribute ID hash
these recursively nested helper entities work together with the TimelineCanvas
and enable the latter to draw the track background in the Timeline Widget and
to find out about the vertical coordinates where to place content (Clip, Effects, Markers)
Gtk::Viewport allows to add the ability to scroll a partial view window
for a container larger than the available display area. The position
and movement of this window is controlled by Gtk::Adjustments,
which can be located elsewhere.
Here we use the existing Adjustments of the ScrolledWindow
holding the body canvas; this setup makes the header pane follow
the scroll movements of the body
bottom line is to do most autmatically, and to establish a slave-relation
navigation-area -> timeline-ruler
header-pane-content -> corresponding track-body
this can be accomplished mostly by connecting the aproprieate signals,
thus these widgets will live within the Layout-Manager, which consequently
is renamed into TimelineLayout
the solution idea is to use a helper frame, and an "anchor functor",
which is passed down from the respective parent context, and which
does the actual work of injecting the child widgets at the apropriate
position within the parent display.
This is an obsolete feature, since the JavaScript engine in modern browsers
is way faster than it used to be, and people are accustomed to some loading time
due to all those "single page applications".
I haven't seen this splash screen even on the old Firefox for quite some time;
moreover, the TiddlyWiki 2.9.1 now displays a "JavaScript is required" alert
anyway, so there is really no need for all this messing around.
The (very old and long abandoned) SplashScreenPlugin
was written in a very hackish style, as it injected a <div> with the splash screen into the <head> tag.
In those olde days when evil reigned, browsers just happily displayed such documents.
But our new gem, Firefox Quantum, now "sanitises" such a malformed document
by closing the Head right before the <div> and relocating the opening BODY tag
to this place. Which then causes the TiddlyWiki self-modification routine
to flounder, because the opening body tag is now in the middle of a "markup area",
which is replaced by existing tiddler content (in this case the "MarkupPreHead" tiddler).
So we end up without an opening Body tag, and this is what we save -- Resulting in a corrupted wiki!
The obvious fix is to use the MarkupPreBody instead
Firefox Quantum adopted the idiotic behaviour of Chrome and does no longer
retrieve Cookies for pages read from local file system. It stores the Cookie
data into its local cookies.sqlite, but it does not retrieve it anymore.
For aledged "security reasons", however it happily retrieves HTML 5 web storage
Since TiddlyWiki classic just accesses the document.cookie at 3 points,
it is easy to patch around that problem. Just check, if we're using a modern
browser with support for HTML5 web storage and branch accordingly.
Basically, TiddlyWiki "classic" is in maintenance mode, but it is still supported.
This minor upgarde brings some bugfixes, most notably a minor adjustment to work well
with the new Firefox Quantum, which switched to the more restricted WebExtensions
and discontinued support for the old-style XUL based plug-ins.
This bold move by the firefox project placed a lot of well established, mature
extensions on the brink of extinction. Especially TiddlyWiki has gradually lost
its original appeal of a low-ceremony guerrilla wiki. However, it is still
a sweet little gem for experienced users, albeit a bit brittle to use.
You are now either
- forced to enter the target destination on each save
- or forced to arrange tiddly wiki to reside within your default download folder
and use a firefox plug-in to automate the save process (I use at the moment
https://addons.mozilla.org/en-GB/firefox/addon/file-backups/
- or forced to install a 100 MB blurb of java-script based local server
to run TiddlyWikiDesktop
The bitter irony of the situation is, what still works more-or-less painless
is to place your TiddlyWiki into the cloud. Yikes, here we go.
seems to work surprisingly well...
the diff application poceeds in the GUI up to the point
where the TrackPresenter need to be inserted into a two-fold display context
To drive the timeline display in the UI ahead, the plan is to have
a faked action, which injects dummy population diff messages into the GUI,
resulting in the build-up of a typical simple session timeline
decision: for now we will represent *every* Timeline present in the Session.
Later it would also possible to skip some representation; however we'd need
a way to store such presentation state such that we'd be able to get at this
persisted stat right at this point here, when processing the Diff.
other than the regular way of building an object,
we do expect a minimal structure to be sent right within the INS message.
Rationale: the standard way would allow for too much leeway and created
unwanted intermediary states. The non-standard way decided upon here
is well within the limits of our diff language
Problem is, the InteractionDirector, being the representation of the model root,
needs to manage and maintain the collection of "timelines". However, these
can not be widgets, rather, they need to attach to widgets living within
the GUI widget structure proper, i.e. within the TimelinePanel
proposed solution is to build a smart handle based on WLink,
but also delegating the DiffMutable interface
This involves a fundamental decision about how to build structures in the Lumiera UI:
They shall be solely created in response to diff messages. Which leads us to
introduce a new (and quite challenging) concept: the »DiffConstituent«
This marks start of actual work on this fundamental task.
Extensive planning from 2016 is available, together with an almost
complete diff binding for the entities involved into timeline display.
''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
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.