Commit graph

1355 commits

Author SHA1 Message Date
ffcac2ea1e Structure-Change: implement a simplistic implementation of re-ordering
...verified by the rather conceptual unit test
2019-12-06 23:19:09 +01:00
305ff8e6cc Structure-Change: draft API for re-ordering attached widgets
basically this attempts to work around an "impedance mismatch" caused by relying on Lumiera's Diff framework.
Applying a diff might alter the structural order of components, without those componets
being aware of the change. If especially those components are attached into some
UI layout, or otherwise delegate to display widgets, we need a dedicated mechanism
to reestablish those display elements in proper order after applying the change.

The typical examples is a sequence of sub-Tracks, which might have been reordert due
to applying rules down in the Steam Layer. The resulting diff will propagate the
new order of sub-Tracks up into the UI, yet now all of the elaborate layout and
space allocation done in the presentation code needs to be adjusted or even
recomputed to accomodate the change.
2019-12-06 21:53:43 +01:00
8ba315561f Structure-Change: in-depth analysis of design alternatives
...leading to the conclusion to use this as a design pattern rather,
without trying to evolve it into a fundamental backbone framework
2019-12-05 22:25:48 +01:00
3bedbd1dff Structure-Change: attempt to solve a problem with cross-type access 2019-12-02 00:35:17 +01:00
ed409c3570 Structure-Change: exapnd on the idea of a generic Visitor
...to form a single framework for view attachment.
Obviously, we have two quite distinct cases to cover
- attaching a widget onto a canvas
- hooking a widget as subtree into a grid/tree control
2019-12-02 00:35:10 +01:00
1bcdf9860c Structure-Change: continue design/analysis 2019-12-02 00:34:41 +01:00
c573630ac1 Structure-Change: draft a design based on ViewHook / ViewHookable
By applying a Diff, the children of some timeline element (track) may be re-ordered.
This imposes specific problems, since these elements hold onto slave-Widgets,
which are already attached into some elaborated and nested widget structure.
To keep complexity under control, we can not allow the TrackPresenter to have
any knowledge regarding the implementation structure of these target widgets.

Thus I am pondering the idea to represent that relation as an abstracted ViewHook link
2019-12-02 00:34:20 +01:00
37d2e52c1e ClipDisplay: also verify invocation of widget relocation via ViewHook
...obviously this is just a dummy implementation and serves only to verify the design
2019-11-08 21:37:09 +01:00
bdf3351f55 ClipDisplay: basic implementation of ViewHook helper 2019-11-08 20:49:37 +01:00
bf283e8843 QA: check for possible misalignment through placement new (-> #1204) 2019-11-08 01:14:36 +01:00
f9d8f6eb55 ClipDisplay: draft desired properties of the ViewHook helper
...which serves to solve the problem with Canvas access.
Basically we do not want each and every Clip widget to be aware of the concrete canvas implementation widget;
and in addition, automated removal of widgets from the Canvas seems desirable
2019-09-30 02:49:02 +02:00
7c7b910545 ClipDisplay: plot a structure for connecting ClipWidgets with the display canvas 2019-09-29 01:32:34 +02:00
03c358fe86 Timeline: squeeze in some test/diagnostics code to inject a button onto each track
This is dummy/test/diagnostics code and should be removed when the track display code is complete!
It can be activated by sending a "mark"-Message via the UI-Bus, towards the
Timeline element to be tested (Tip: use the same ID as used when injecting
the Timeline via the TestControl Dialog box). When receiving this message
(asynchronously), the TimelineControler asks each nested TrackPresnter
to inject a Button with the corresponding track name onto the BodyCanvasWidget.

This allows us to verify the coordinate calculation and size allocation --
and indeed, the numbers are not yet correct (TODO)
2019-09-07 19:24:54 +02:00
cae013c4f4 Timeline: store current track start coordinates while calculating allocation
admittedly this is a bit sketchy, but I don't have a better framework to hinge upon right now.
Thus we store the vertical start coordinates and the offset of the content area
as a side effect, while calculating the TrackProfile
2019-09-07 17:31:58 +02:00
4785ff8caa Timeline: integrate support for a margin on the timeline content
...which has the nice additional effect of exposing box-shadow on the outside of the content area too.
Thus the content area now behaves equivalent to the rulers, and adjacent
content space of simple tracks without rulers and nesting can be slightly
offset from each other through a margin in CSS
2019-09-07 17:31:53 +02:00
fa4a9014a1 Timeline: nail the problem with calculating overall vertical space
In the end, I used the profile building pass to also calculate and sum up the vertical offsets.
Seems to be the only sane approach to get really precise values, since adjacent
upwards slopes can be combined at various places (and I do not want to use the
actual drawing code for this calculation)
2019-08-29 23:02:44 +02:00
4d2766963b Timeline: size allocation is not yet correct...
need to investigate and probably need to store per track offset values
already while building the track profile. The primary reason for the
observed discrepancy seems to be the rather flexible combination of
slope borders.
2019-08-29 16:19:47 +02:00
360209a381 Timeline: verify visible track structure (and fix a bug with header placement) 2019-08-29 16:19:40 +02:00
737505979b Timeline: also observe additional space for decorations added via CSS 2019-08-23 03:56:38 +02:00
346b5ae769 Timeline: now settle the drawing code with the insights gained thus far
Especially note the tricks we need to play in order to allow for (limited) usage of CSS3 box-shadows.
The reason is, all these CSS3 effects are rendered in one shot and combinend on the StyleContext::render_background() call
Thus we need to ensure that the background is properly aligned with the frames
2019-08-23 03:04:22 +02:00
fc5eaf857c Timeline: find a workaround to cause the Box to reflow the rulerCanvas
seemingly, the Box with PACK_SHRINK allocates a zero height to the rulerCanvas initally,
which is correct at that point, since the widgets are not yet realised.
However, when we later set_size() on the rulerCanvas, the enclosing Box should reflow.
It does indeed if the child widget is a button or something similar, however,
somehow this reflowing does not work when we set_size on the canvas.

A workaround is to place a new set_size_request().

TODO: do this more precisely, and only on the rulerCanvas. To the contrary,
the mainCanvas is placed into a scolling-pane and thus does not need a size-Request.
Moreover, the latter automatically communicates with the hadjustment() / vadjustment() of
the enclosing scrollbars.
2019-08-22 17:34:32 +02:00
2390385dc5 Timeline: implement function to set the drawing canvas size
as can be verified with the debugger, it sets the correct sizes now.
And it is called only once (unless the content size actually changes).

TODO: however, the visible display of the GTK widgets is not adjusted
2019-08-21 19:13:55 +02:00
8c0b3258cb Timeline: investigate details of CSS box-shadow and dawing strategy
- decide upon the actual drawing strategy
- document our approach chosen thus far
- add a new function to fill in the overall canvas size (TODO)
2019-08-21 17:48:25 +02:00
81253cb152 Timeline: some analysis and planning regarding space allocation 2019-08-08 19:08:04 +02:00
a508ad751f Investigation: clarify handling of CSS3 box-shadow for custom drawing
- CSS3 effects like box-shadow are applied with the StyleContext::render_background() function
  * first, an outset box-shadow is rendered _outside_ the box given as parameter to `render_background()`
  * then the box is filled with the background colour
  * and last, an inset box-shadow is rendered _inside_ the area of a would-be border,
    without rendering the border itself.
  * consequently we can not shade the border itself and we can not shade the content
2019-08-08 19:08:04 +02:00
7bf7c51375 Investigation: inconclusive further research (context_save/restore)
Indeed I had missed to connect the new "free standing" StyleContext to
some Gdk::Screen, typically the default screen (connected to the current
top level window). But seemingly this was not really necessary, since,
somehow magically, the style context must have connected itself to some
screen, otherwise it wouldn't be able to access the CSS cascade.

Anyhow, fixing this omission does not resolve our problem.
Nor does any combination of re-connecting, invalidating etc.

I poked around in the GTK (C) code a lot, but could not spot any obvious
missing initialisation step. To much magic around here. Without massive
debugging into GTK internals, I don't see any way to further this
investigation. And, moreover there is a viable workaround
(namely to set and remove the classes explicitly, which works as intended)

I posted a question on Stackoverflow and for now
I'll file this topic as "inconclusive"
https://stackoverflow.com/q/57342478
2019-08-08 19:08:04 +02:00
8824be440a Investigation: integrate findings thus far into our timeline drawing code
DONE
 - can now control the border size through a set of modifier classes

OPEN
 - but context_save()/restore() does not work; seem to loose all styling
 - not clear how to deal with CSS3 effects like box-shadow
2019-08-03 16:41:46 +02:00
06aa5c4c8c Investigation: get the border resizing to work
...as it turns out, a problem with Cascading prevented the additional classes to become effective
2019-08-03 15:45:36 +02:00
0280000854 Investigation: setup a minimal standalone GTK application
...to find out about GTK's implementation of some aspects of CSS
through Gtk::StyleContext and friends

Basically this is a clone of the existing gtk-canvas-experiment application
2019-08-01 00:02:56 +02:00
e6e68e2e68 Timeline: investigate options to build a suitable ramp style
...somehow does not yet work as intended...

- unable to control the border-width from code
- Gtk::StyleContext::add_class(name) does not seem to have any effect
2019-07-30 19:20:58 +02:00
b5c2009933 Timeline: first attempt at drawing ramps and borders
...does not work out as expected
 - frames are painted solid, not inset/outset
 - unable to manipulate the border width from code
2019-07-20 17:39:49 +02:00
b2c2787ddc Timeline: populate additional Style-Advice for nested ruler tracks 2019-07-20 01:24:17 +02:00
eca09e3ab5 Timeline: work out how Ruler tracks can be managed 2019-07-20 01:24:17 +02:00
d1e2ddc56e Timeline: refactor common drawing code into an abstract baseclass 2019-07-15 00:25:08 +02:00
713178aecd Timeline: better save the number of pinned elements as dedicated field
...within the Profile object, instead of sneaking this info into the prelude verb
2019-07-15 00:06:59 +02:00
ec50407167 Timeline: start implementing some bits of the drawing code
Use a "catchy" style definition with lime background to make the drawing visible
2019-07-14 17:53:21 +02:00
bc4f7604a2 Timeline: draft a scheme to use custom class names within CSS selectors
We can add our custom classes to custom widgets, and we can set the
widget name, which can be used as #id selector from CSS

Unfortunately we can not set the main CSS node name for CustomWidgets defined through GTKmm (C++)
The latter is only possible when deriving the custom widget in plain-C, which is quite tedious.
On a second thought, this limitation is not so severe as it might seem, because
most of the time you actually do *not* want to change the CSS node name,
because you want to match against existing rules in the theme (e.g. box, or paned)

The actual case here would have been an exception to this rule, since here
it would be nice to anchor the whole custom timeline drawing in an "body.timeline" element


NOTE: Current state for the selector path is now:

window.background box.vertical box[2/3].horizontal widget[2/2] widget paned.vertical widget box.vertical notebook[1/1].frame paned.horizontal.timeline-page box.vertical.timeline.timeline-body fork.timeline
2019-07-13 21:04:33 +02:00
826df93955 Timeline: publish virtual CSS path and style context via Advice system
...and perform the initialisation once, when attaching the first timeline to the UI
Now our code produces the following Gtk::WidgetPath (note the last node, which our code added)

window:backdrop:dir-ltr.background box:backdrop:dir-ltr.vertical box:backdrop:dir-ltr[2/3].horizontal widget:backdrop:dir-ltr[2/2] widget:backdrop:dir-ltr paned:backdrop:dir-ltr.vertical widget:backdrop:dir-ltr box:backdrop:dir-ltr.vertical notebook:backdrop:dir-ltr[1/1].frame paned:backdrop:dir-ltr.horizontal box:backdrop:dir-ltr.vertical fork.timeline
2019-07-13 18:04:02 +02:00
6b4bf0a6ea Library: allow to check if Advice was explicitly given
For context: The »Advice System« was coined a long time ago, in 2010,
based on the vague impression that it might be useful for that kind of application
we are about to build here. And, as can be expected, none of the usage situations
envisioned at that time was brought to bear. Non the less, the facility came in
handy at times, precisely because it is cross-cutting and allows to pass
information without imposing any systematic relationship between the
communication partners.

And now we've got again such a situation.
The global style manager in the UI has to build a virtual CSS path,
which is needed by drawing code somewhere deep down, and we absolutely
do not want to pass a reference to the style manager over 20 recursive calls.

The alternatives would be
 (1) to turn the style manager into a public service
 (2) to have a static access function somewhere
 (3) to use a global variable.
For rationale, (1) would be overblown, because we do not actually request
a service to do work for us, rather we need some global piece of information.
(2) would be equivalent to (1), just more confusing. And (3) is basically
what the Advice system does, with the added benefit of a clear-cut service
access point and a well defined lifecycle.

This changeset adds the ability to check if actual Advice has been published,
which allows us to invoke the (possibly expensive) GTK path building and
style context building code only once.
2019-07-13 17:00:23 +02:00
d5cbeab2d8 Timeline: GTK-Code to construct a "virtal" CSS path (see #1168)
This code was cooked up by following the example of gtk_widget_path_append_for_widget()
See gtkwidget.c, 16413
2019-07-13 00:59:05 +02:00
60d28fea2c Timeline: establish a way to pass a StyleContext via Advice system
- at some (yet to be defined) location, a virtual WidgetPath is constructed
  and used to build a Gtk::StyleContext in accordance to the curren CSS

- within the drawing routine, we use Lumiera's Advice-System to access this info
2019-07-12 23:58:25 +02:00
06163f6016 Timeline: filter to select the pinned prefix part of the profile
...when rendering this part, which shall be always visible.
And the rest of the profile needs to be rendered into a second canvas,
which is placed within a pane with scrollbar.

Implemented as a statefull iterator filter
2019-06-21 23:18:44 +02:00
ac3f1d8bef Timeline: implement access mechanism through getter lambda
works, but not really convinced yet...
2019-06-21 20:00:44 +02:00
6b6ed5e0eb Timeline: need accessor function for profile
TODO / WIP.
We can no longer just grab the profile by reference;
rather we need a sensible way how to activate the recomputation logic
2019-06-20 19:01:15 +02:00
77805a5c8c Timeline: handle notification of structural updates 2019-06-20 18:53:12 +02:00
83c462abc3 Timeline: investigate how to handle profile rebuilding
as it turns out, the core problem is that we need a way to detect and signal
structural changes to the logical UI model
2019-06-20 15:36:09 +02:00
d5af020520 Timeline: possible solution for construction of the TrackProfile
...not yet really convinced though
...how does this relate to the "display evaluation pass" of the Layout Manager?
2019-06-15 21:45:38 +02:00
c87ca5d632 Timeline: generalise unsafe access to embedded profile data
While somewhat ugly, I deem this acceptable in such a context,
where the implementation handles its own embedded storage structure.
2019-06-15 17:41:17 +02:00
a105e02b52 Timeline: wire distinct grounding/overlay renderers
TODO:
 - actual draw operations not yet implemented
 - find a way how to select the prelude / body part of the track profile

This is a consequence of subsuming the timeline ruler under the concept of an overview track
2019-06-13 18:17:46 +02:00
3f04bb8698 Timeline: sort out how to link the ProfileInterpreter into the draw function 2019-06-13 17:54:06 +02:00