From bc4f7604a2899007d72b7dc60c4dfcda88a51a8a Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sat, 13 Jul 2019 21:02:30 +0200 Subject: [PATCH] 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 --- src/common/ui-protocol.cpp | 2 + src/include/ui-protocol.hpp | 2 + src/stage/timeline/body-canvas-widget.cpp | 7 +- src/stage/timeline/timeline-widget.cpp | 2 + src/stage/workspace/ui-style.cpp | 2 + wiki/thinkPad.ichthyo.mm | 265 +++++++++++++++++++++- 6 files changed, 271 insertions(+), 9 deletions(-) diff --git a/src/common/ui-protocol.cpp b/src/common/ui-protocol.cpp index aef3dc97d..c105d0785 100644 --- a/src/common/ui-protocol.cpp +++ b/src/common/ui-protocol.cpp @@ -63,6 +63,8 @@ namespace stage { const Symbol NODE_fork{"fork"}; const Symbol CLASS_timeline{"timeline"}; + const Symbol CLASS_timeline_page{"timeline-page"}; + const Symbol CLASS_timeline_body{"timeline-body"}; /** */ diff --git a/src/include/ui-protocol.hpp b/src/include/ui-protocol.hpp index c7c5c7039..9c54d0c98 100644 --- a/src/include/ui-protocol.hpp +++ b/src/include/ui-protocol.hpp @@ -102,6 +102,8 @@ namespace stage { extern const Symbol NODE_fork; extern const Symbol CLASS_timeline; + extern const Symbol CLASS_timeline_page; + extern const Symbol CLASS_timeline_body; }// namespace stage diff --git a/src/stage/timeline/body-canvas-widget.cpp b/src/stage/timeline/body-canvas-widget.cpp index a36e9e7ab..96b24164b 100644 --- a/src/stage/timeline/body-canvas-widget.cpp +++ b/src/stage/timeline/body-canvas-widget.cpp @@ -39,6 +39,7 @@ //#include "lib/format-string.hpp" //#include "lib/format-cout.hpp" +#include "include/ui-protocol.hpp" #include "common/advice.hpp" #include "lib/util.hpp" @@ -246,7 +247,8 @@ namespace timeline { BodyCanvasWidget::BodyCanvasWidget (DisplayManager& displayManager) - : Gtk::Box{Gtk::ORIENTATION_VERTICAL} + : Glib::ObjectBase("body") // enables use of custom CSS properties (on 'gtkmm__CustomObject_body') + , Gtk::Box{Gtk::ORIENTATION_VERTICAL} , layout_{displayManager} , profile_{} , rootBody_{nullptr} @@ -254,6 +256,9 @@ namespace timeline { , rulerCanvas_{makeRenderer(layout_,getProfile), makeRenderer(layout_,getProfile)} , mainCanvas_ {makeRenderer(layout_,getProfile), makeRenderer(layout_,getProfile)} { + get_style_context()->add_class(cuString{CLASS_timeline}); + get_style_context()->add_class(cuString{CLASS_timeline_body}); + // respond to any structure changes of the timeline by recomputing the TrackProfile layout_.signalStructureChange_.connect (sigc::mem_fun (*this, &BodyCanvasWidget::slotStructureChange)); diff --git a/src/stage/timeline/timeline-widget.cpp b/src/stage/timeline/timeline-widget.cpp index 2f6c2bde1..e1402feb1 100644 --- a/src/stage/timeline/timeline-widget.cpp +++ b/src/stage/timeline/timeline-widget.cpp @@ -34,6 +34,7 @@ #include "stage/timeline/timeline-widget.hpp" #include "stage/timeline/timeline-controller.hpp" #include "stage/timeline/timeline-layout.hpp" +#include "include/ui-protocol.hpp" //#include "stage/workspace/workspace-window.hpp" //#include "stage/ui-bus.hpp" @@ -72,6 +73,7 @@ namespace timeline { , layout_{new TimelineLayout{*this}} , control_{new TimelineController{identity, trackID, nexus, *layout_}} { + get_style_context()->add_class(cuString{CLASS_timeline_page}); show_all(); } diff --git a/src/stage/workspace/ui-style.cpp b/src/stage/workspace/ui-style.cpp index eb28d7da6..2255b33e0 100644 --- a/src/stage/workspace/ui-style.cpp +++ b/src/stage/workspace/ui-style.cpp @@ -136,6 +136,8 @@ namespace workspace { gtk_widget_path_iter_set_object_name (path.gobj(), pos, NODE_fork); // override the generic node name with a custom widget type "fork" path.iter_add_class(pos, cuString{CLASS_timeline}); // decorate this CSS node with a CSS class ".timeline" (distinguish it from asset bins) // deliberately we *do not* invoke path.iter_set_name(pos, "id") to add an #ID + for (int i=0; iset_path (path); styleAdvice_.setAdvice (style); // publish as Advice "style(trackBody)" diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index e9690993e..f54b3e640 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -7095,7 +7095,7 @@ - + @@ -18219,7 +18219,8 @@ - + + @@ -18251,8 +18252,9 @@ - + + @@ -18611,6 +18613,7 @@ + @@ -18623,6 +18626,67 @@ + + + + + + + + + + + + + +

+ weil dies ggfs vom Theme her schon gestyled wird +

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

+ ...denn die CSS-Node-Namen von Custom-Widgets kann man via GTKmm nicht ändern. +

+

+ Das geht nur, wenn man das Custom-Widget direkt per C erzeugt, +

+

+ weil der betreffende Aufruf gtk_widget_class_set_css_name (GTK_WIDGET_GET_CLASS(gobj()), "my-node") +

+

+ in der C "class init function" passieren muß +

+ + +
+ + +
+
+
+
+
@@ -21718,7 +21782,7 @@ - + @@ -21758,9 +21822,73 @@ + + + + + + +

+ "Widget is in a background toplevel window" +

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

+ nur der letzte Node wird gegen pseudo-Klassen gematcht +

+ + +
+
+ + + + + + +

+     for (uint i=0; i<pos; ++i) +

+

+       gtk_widget_path_iter_set_state(path.gobj(), i, GTK_STATE_FLAG_NORMAL); +

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

+ 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 +

+ + +
+ +
+
+ + + + + + - - @@ -30976,7 +31104,7 @@ - + @@ -43517,6 +43645,24 @@ + + + + + + + + +

+ "Widget is in a background toplevel window" +

+ + +
+ +
+
+
@@ -43604,7 +43750,93 @@
- + + + + + + +

+ this->set_name("my-widget") +

+ + +
+ + + + + + + +

+ (2019 / Debian-Stretch) +

+

+ Das schließe ich aus einem Kommentar im GTKmm-Tutorial +

+

+   // Set the widget name to use in the CSS file. +

+

+   set_name("my-widget"); +

+

+ +

+

+   // If you make a custom widget in C code, based on gtk+'s GtkWidget, there is +

+

+   // an alternative to gtk_widget_set_name(): Set a CSS name for your custom +

+

+   // class (instead of the widget instance) with gtk_widget_class_set_css_name() +

+

+   // (new in gtk+ 3.19.1). That's not possible for custom widgets defined in gtkmm. +

+

+   // gtk_widget_class_set_css_name() must be called in the class init function, +

+

+   // which can't be customized, when the widget is based on gtkmm's Gtk::Widget. +

+

+   // +

+

+   // Another alternative: The custom widget inherits the CSS name "widget" from +

+

+   // GtkWidget. That name can be used in the CSS file. This is not a very good +

+

+   // alternative. GtkWidget's CSS name is not documented. It can probably be +

+

+   // changed or removed in the future. +

+ + +
+ + + + + + + +

+ gtk_widget_class_set_css_name (GTK_WIDGET_GET_CLASS(gobj()), "body"); +

+ + +
+
+ + +
@@ -43619,6 +43851,23 @@ + + + + + + + + + + + + + + + + +