2019-07-31 22:54:23 +02:00
|
|
|
|
/*
|
|
|
|
|
|
gtk-style-experiment.cpp - simple application to investigate GTK styling
|
|
|
|
|
|
|
Copyright: clarify and simplify the file headers
* Lumiera source code always was copyrighted by individual contributors
* there is no entity "Lumiera.org" which holds any copyrights
* Lumiera source code is provided under the GPL Version 2+
== Explanations ==
Lumiera as a whole is distributed under Copyleft, GNU General Public License Version 2 or above.
For this to become legally effective, the ''File COPYING in the root directory is sufficient.''
The licensing header in each file is not strictly necessary, yet considered good practice;
attaching a licence notice increases the likeliness that this information is retained
in case someone extracts individual code files. However, it is not by the presence of some
text, that legally binding licensing terms become effective; rather the fact matters that a
given piece of code was provably copyrighted and published under a license. Even reformatting
the code, renaming some variables or deleting parts of the code will not alter this legal
situation, but rather creates a derivative work, which is likewise covered by the GPL!
The most relevant information in the file header is the notice regarding the
time of the first individual copyright claim. By virtue of this initial copyright,
the first author is entitled to choose the terms of licensing. All further
modifications are permitted and covered by the License. The specific wording
or format of the copyright header is not legally relevant, as long as the
intention to publish under the GPL remains clear. The extended wording was
based on a recommendation by the FSF. It can be shortened, because the full terms
of the license are provided alongside the distribution, in the file COPYING.
2024-11-17 23:42:55 +01:00
|
|
|
|
Copyright (C)
|
|
|
|
|
|
2019, Hermann Vosseler <Ichthyostega@web.de>
|
2019-07-31 22:54:23 +02:00
|
|
|
|
|
Copyright: clarify and simplify the file headers
* Lumiera source code always was copyrighted by individual contributors
* there is no entity "Lumiera.org" which holds any copyrights
* Lumiera source code is provided under the GPL Version 2+
== Explanations ==
Lumiera as a whole is distributed under Copyleft, GNU General Public License Version 2 or above.
For this to become legally effective, the ''File COPYING in the root directory is sufficient.''
The licensing header in each file is not strictly necessary, yet considered good practice;
attaching a licence notice increases the likeliness that this information is retained
in case someone extracts individual code files. However, it is not by the presence of some
text, that legally binding licensing terms become effective; rather the fact matters that a
given piece of code was provably copyrighted and published under a license. Even reformatting
the code, renaming some variables or deleting parts of the code will not alter this legal
situation, but rather creates a derivative work, which is likewise covered by the GPL!
The most relevant information in the file header is the notice regarding the
time of the first individual copyright claim. By virtue of this initial copyright,
the first author is entitled to choose the terms of licensing. All further
modifications are permitted and covered by the License. The specific wording
or format of the copyright header is not legally relevant, as long as the
intention to publish under the GPL remains clear. The extended wording was
based on a recommendation by the FSF. It can be shortened, because the full terms
of the license are provided alongside the distribution, in the file COPYING.
2024-11-17 23:42:55 +01:00
|
|
|
|
**Lumiera** is free software; you can redistribute it and/or modify it
|
|
|
|
|
|
under the terms of the GNU General Public License as published by the
|
|
|
|
|
|
Free Software Foundation; either version 2 of the License, or (at your
|
|
|
|
|
|
option) any later version. See the file COPYING for further details.
|
2019-07-31 22:54:23 +02:00
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** @file gtk-style-experiment.cpp
|
|
|
|
|
|
** Simple GTK Application frame to investigate some aspects of GTK's CSS implementation.
|
|
|
|
|
|
** Especially the goal is to _grab some existing CSS styling_ with a Gtk::StyleContext
|
|
|
|
|
|
** and use this for custom drawing. Within Lumiera, we use custom drawing for some parts
|
|
|
|
|
|
** of the Timeline UI presentation.
|
2019-07-31 23:56:51 +02:00
|
|
|
|
**
|
2021-01-23 16:45:04 +01:00
|
|
|
|
** # Setup for investigation
|
2019-07-31 23:56:51 +02:00
|
|
|
|
** - add a separate dummy Gtk::Frame widget as `testFrame_`
|
|
|
|
|
|
** - apply custom styling to that frame, by virtue of a CSS class '.experiment'
|
2019-08-04 17:00:18 +02:00
|
|
|
|
** - pick up the Gtk::StyleContext of that `testFrame_` to get the CSS path
|
|
|
|
|
|
** - build a "free standing" new Gtk::StyleContext and apply the CSS path found
|
|
|
|
|
|
** - use this style context to draw a custom frame and background onto the canvas
|
2019-07-31 23:56:51 +02:00
|
|
|
|
** - control extension of that custom drawing through the top margin CSS setting of testFrame_
|
|
|
|
|
|
**
|
2021-01-23 16:45:04 +01:00
|
|
|
|
** # Findings
|
2019-08-04 17:00:18 +02:00
|
|
|
|
** - it works as intended
|
|
|
|
|
|
** - however, care must be taken to apply CSS cascading properly (generic vs specific selectors)
|
|
|
|
|
|
** - the context_save/restore functionality seems to be broken on a "free standing" style context;
|
|
|
|
|
|
** however it works as expected on a style context associated to an existing and realised widget.
|
|
|
|
|
|
** - workaround is to add / remove classes explicitly.
|
|
|
|
|
|
** - 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-07-31 22:54:23 +02:00
|
|
|
|
** @see stage::timeline::BodyCanvasWidget
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "stage/gtk-base.hpp"
|
2019-07-31 23:27:33 +02:00
|
|
|
|
#include "lib/searchpath.hpp"
|
2019-08-03 13:34:56 +02:00
|
|
|
|
#include "lib/format-cout.hpp"
|
2019-08-03 15:45:36 +02:00
|
|
|
|
#include "lib/format-util.hpp"
|
2019-07-31 22:54:23 +02:00
|
|
|
|
#include "lib/error.hpp"
|
2019-07-31 23:27:33 +02:00
|
|
|
|
#include "lib/util.hpp"
|
2019-07-31 22:54:23 +02:00
|
|
|
|
|
2019-07-31 23:27:33 +02:00
|
|
|
|
#include <string>
|
|
|
|
|
|
|
2019-08-03 15:45:36 +02:00
|
|
|
|
using util::join;
|
2019-07-31 23:27:33 +02:00
|
|
|
|
using std::string;
|
2019-07-31 22:54:23 +02:00
|
|
|
|
|
|
|
|
|
|
namespace research {
|
|
|
|
|
|
|
2019-07-31 23:27:33 +02:00
|
|
|
|
namespace {
|
|
|
|
|
|
const string STYLESHEET_NAME{"gtk-style-experiment.css"};
|
2019-08-04 17:00:18 +02:00
|
|
|
|
const string RESOURCE_PATH {"$ORIGIN/gui"};
|
2019-07-31 23:27:33 +02:00
|
|
|
|
|
|
|
|
|
|
const string CLASS_experiment{"experiment"};
|
2019-08-03 15:45:36 +02:00
|
|
|
|
const string CLASS_slopeDeep1{"track-slope-deep1"};
|
2019-08-03 13:34:56 +02:00
|
|
|
|
|
|
|
|
|
|
string
|
|
|
|
|
|
slopeClassName(int depth)
|
|
|
|
|
|
{
|
|
|
|
|
|
switch (depth)
|
|
|
|
|
|
{
|
|
|
|
|
|
case 1: return "track-slope-deep1";
|
|
|
|
|
|
case 2: return "track-slope-deep2";
|
|
|
|
|
|
case 3: return "track-slope-deep3";
|
|
|
|
|
|
case 4: return "track-slope-deep4";
|
|
|
|
|
|
default:return "track-slope-verydeep";
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2019-07-31 23:27:33 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
using CairoC = stage::PCairoContext const&;
|
|
|
|
|
|
using StyleC = stage::PStyleContext const&;
|
|
|
|
|
|
|
|
|
|
|
|
using stage::PStyleContext;
|
|
|
|
|
|
|
2019-07-31 22:54:23 +02:00
|
|
|
|
|
|
|
|
|
|
class Canvas
|
|
|
|
|
|
: public Gtk::Layout
|
|
|
|
|
|
{
|
2019-07-31 23:27:33 +02:00
|
|
|
|
bool shallDraw_ = false;
|
2019-07-31 22:54:23 +02:00
|
|
|
|
bool recalcExtension_ = false;
|
|
|
|
|
|
|
2019-07-31 23:27:33 +02:00
|
|
|
|
StyleC style_;
|
|
|
|
|
|
|
2019-07-31 22:54:23 +02:00
|
|
|
|
public:
|
2019-07-31 23:27:33 +02:00
|
|
|
|
Canvas(StyleC refStyle)
|
|
|
|
|
|
: style_{refStyle}
|
|
|
|
|
|
{ }
|
|
|
|
|
|
|
2019-07-31 22:54:23 +02:00
|
|
|
|
void adjustSize();
|
|
|
|
|
|
void enableDraw (bool);
|
|
|
|
|
|
|
2019-08-03 13:34:56 +02:00
|
|
|
|
int xBorderSiz = 1;
|
|
|
|
|
|
int xObservedSize = -1;
|
|
|
|
|
|
string xObservedPath;
|
2019-08-03 15:45:36 +02:00
|
|
|
|
string xObservedClzz;
|
2019-08-03 13:34:56 +02:00
|
|
|
|
|
2019-07-31 22:54:23 +02:00
|
|
|
|
private:
|
|
|
|
|
|
virtual bool on_draw (Cairo::RefPtr<Cairo::Context> const&) override;
|
|
|
|
|
|
|
|
|
|
|
|
void determineExtension();
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class StyleTestPanel
|
|
|
|
|
|
: public Gtk::Box
|
|
|
|
|
|
{
|
|
|
|
|
|
public:
|
|
|
|
|
|
StyleTestPanel();
|
|
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
Gtk::Box twoParts_;
|
|
|
|
|
|
Gtk::ButtonBox buttons_;
|
|
|
|
|
|
Gtk::Button button_1_;
|
|
|
|
|
|
Gtk::Button button_2_;
|
|
|
|
|
|
Gtk::CheckButton toggleDraw_;
|
2019-07-31 23:56:51 +02:00
|
|
|
|
Gtk::Frame testFrame_;
|
2019-07-31 22:54:23 +02:00
|
|
|
|
Gtk::Frame frame_;
|
|
|
|
|
|
Gtk::ScrolledWindow scroller_;
|
2019-07-31 23:27:33 +02:00
|
|
|
|
|
|
|
|
|
|
PStyleContext pStyle_;
|
2019-07-31 22:54:23 +02:00
|
|
|
|
Canvas canvas_;
|
|
|
|
|
|
|
2019-07-31 23:56:51 +02:00
|
|
|
|
PStyleContext setupStyle(Gtk::Widget const&);
|
2019-07-31 23:27:33 +02:00
|
|
|
|
|
2019-07-31 22:54:23 +02:00
|
|
|
|
void experiment_1();
|
|
|
|
|
|
void experiment_2();
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* ===== Implementation ===== */
|
|
|
|
|
|
|
|
|
|
|
|
StyleTestPanel::StyleTestPanel()
|
|
|
|
|
|
: Box{}
|
2019-07-31 23:27:33 +02:00
|
|
|
|
, twoParts_{Gtk::ORIENTATION_VERTICAL}
|
|
|
|
|
|
, buttons_{}
|
2019-07-31 23:56:51 +02:00
|
|
|
|
, testFrame_{"testFrame"}
|
2019-07-31 23:27:33 +02:00
|
|
|
|
, frame_{"Gtk::StyleContext Experiments"}
|
|
|
|
|
|
, scroller_{}
|
|
|
|
|
|
, pStyle_{}
|
|
|
|
|
|
, canvas_{pStyle_}
|
2019-07-31 22:54:23 +02:00
|
|
|
|
{
|
|
|
|
|
|
twoParts_.pack_start(buttons_, Gtk::PACK_SHRINK);
|
|
|
|
|
|
twoParts_.pack_start(frame_);
|
|
|
|
|
|
|
|
|
|
|
|
buttons_.set_layout(Gtk::BUTTONBOX_START);
|
|
|
|
|
|
|
|
|
|
|
|
// buttons to trigger experiments
|
|
|
|
|
|
button_1_.set_label("_grow");
|
|
|
|
|
|
button_1_.set_use_underline();
|
|
|
|
|
|
button_1_.set_tooltip_markup("<b>Experiment 1</b>:\ngrow the border size");
|
|
|
|
|
|
button_1_.signal_clicked().connect(
|
|
|
|
|
|
mem_fun(*this, &StyleTestPanel::experiment_1));
|
|
|
|
|
|
buttons_.add(button_1_);
|
|
|
|
|
|
|
|
|
|
|
|
button_2_.set_label("_dump");
|
|
|
|
|
|
button_2_.set_use_underline();
|
|
|
|
|
|
button_2_.set_tooltip_markup("<b>Experiment 2</b>:\ndump style information");
|
|
|
|
|
|
button_2_.signal_clicked().connect(
|
|
|
|
|
|
mem_fun(*this, &StyleTestPanel::experiment_2));
|
|
|
|
|
|
buttons_.add(button_2_);
|
|
|
|
|
|
|
2019-07-31 23:56:51 +02:00
|
|
|
|
// a Gtk::Frame widget used as source for our StyleContext
|
|
|
|
|
|
testFrame_.get_style_context()->add_class(CLASS_experiment);
|
2019-08-03 15:45:36 +02:00
|
|
|
|
testFrame_.get_style_context()->add_class(CLASS_slopeDeep1);
|
2019-07-31 23:56:51 +02:00
|
|
|
|
buttons_.add(testFrame_);
|
|
|
|
|
|
|
2019-07-31 22:54:23 +02:00
|
|
|
|
toggleDraw_.set_label("draw");
|
|
|
|
|
|
toggleDraw_.signal_clicked().connect(
|
|
|
|
|
|
[this]() {
|
|
|
|
|
|
canvas_.enableDraw (this->toggleDraw_.get_active());
|
|
|
|
|
|
});
|
|
|
|
|
|
buttons_.add(toggleDraw_);
|
|
|
|
|
|
//(End)buttons...
|
|
|
|
|
|
|
|
|
|
|
|
frame_.add(scroller_);
|
|
|
|
|
|
frame_.set_border_width(5);
|
|
|
|
|
|
|
|
|
|
|
|
scroller_.set_shadow_type(Gtk::SHADOW_IN);
|
|
|
|
|
|
scroller_.property_expand() = true; // dynamically grab any available additional space
|
|
|
|
|
|
scroller_.set_border_width(10);
|
|
|
|
|
|
scroller_.add(canvas_);
|
|
|
|
|
|
|
2019-07-31 23:56:51 +02:00
|
|
|
|
pStyle_ = setupStyle (testFrame_);
|
2019-07-31 23:27:33 +02:00
|
|
|
|
|
2019-07-31 22:54:23 +02:00
|
|
|
|
canvas_.adjustSize();
|
|
|
|
|
|
|
|
|
|
|
|
// show everything....
|
|
|
|
|
|
this->add(twoParts_);
|
|
|
|
|
|
this->show_all();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2019-07-31 23:27:33 +02:00
|
|
|
|
|
|
|
|
|
|
PStyleContext
|
2019-07-31 23:56:51 +02:00
|
|
|
|
StyleTestPanel::setupStyle (Gtk::Widget const& srcWidget)
|
2019-07-31 23:27:33 +02:00
|
|
|
|
{
|
|
|
|
|
|
auto screen = Gdk::Screen::get_default();
|
|
|
|
|
|
auto css_provider = Gtk::CssProvider::create();
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
css_provider->load_from_path (lib::resolveModulePath (STYLESHEET_NAME, RESOURCE_PATH));
|
|
|
|
|
|
}
|
|
|
|
|
|
catch(Glib::Error const& failure)
|
|
|
|
|
|
{
|
|
|
|
|
|
WARN (stage, "Failure while loading stylesheet '%s': %s", cStr(STYLESHEET_NAME), cStr(failure.what()));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Gtk::StyleContext::add_provider_for_screen (screen, css_provider,
|
|
|
|
|
|
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
|
|
|
|
|
|
|
2019-08-03 22:12:36 +02:00
|
|
|
|
// auto style = srcWidget.get_style_context();
|
|
|
|
|
|
|
|
|
|
|
|
Gtk::WidgetPath path = srcWidget.get_path();
|
|
|
|
|
|
PStyleContext style = Gtk::StyleContext::create();
|
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-03 23:26:37 +02:00
|
|
|
|
style->set_screen(Gdk::Screen::get_default());
|
2019-08-03 22:12:36 +02:00
|
|
|
|
style->set_path(path);
|
2019-08-03 15:45:36 +02:00
|
|
|
|
return style;
|
2019-07-31 23:27:33 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2019-07-31 22:54:23 +02:00
|
|
|
|
void
|
|
|
|
|
|
StyleTestPanel::experiment_1()
|
|
|
|
|
|
{
|
|
|
|
|
|
frame_.set_label("Experiment 1... GROW");
|
2019-08-03 13:34:56 +02:00
|
|
|
|
canvas_.xBorderSiz += 1;
|
2019-07-31 22:54:23 +02:00
|
|
|
|
canvas_.adjustSize();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
|
StyleTestPanel::experiment_2()
|
|
|
|
|
|
{
|
|
|
|
|
|
frame_.set_label("Experiment 2... DUMP");
|
2019-08-03 13:34:56 +02:00
|
|
|
|
|
2019-08-03 15:45:36 +02:00
|
|
|
|
cout << "xBorderSize = "<<canvas_.xBorderSiz <<endl;
|
|
|
|
|
|
cout << "xClass = "<<canvas_.xObservedClzz <<endl;
|
2019-08-03 13:34:56 +02:00
|
|
|
|
cout << "style.path: " << canvas_.xObservedPath <<endl;
|
|
|
|
|
|
cout << "style.border.top = " << canvas_.xObservedSize <<endl;
|
|
|
|
|
|
cout << "................\n\n";
|
2019-07-31 22:54:23 +02:00
|
|
|
|
}
|
2019-08-04 17:00:18 +02:00
|
|
|
|
|
|
|
|
|
|
|
2019-07-31 22:54:23 +02:00
|
|
|
|
|
|
|
|
|
|
/* === Canvas drawing code === */
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
|
Canvas::enableDraw (bool yes)
|
|
|
|
|
|
{
|
|
|
|
|
|
shallDraw_ = yes;
|
|
|
|
|
|
|
|
|
|
|
|
// force redrawing of the visible area...
|
|
|
|
|
|
auto win = get_window();
|
|
|
|
|
|
if (win)
|
|
|
|
|
|
{
|
|
|
|
|
|
int w = get_allocation().get_width();
|
|
|
|
|
|
int h = get_allocation().get_height();
|
|
|
|
|
|
Gdk::Rectangle rect{0, 0, w, h};
|
|
|
|
|
|
win->invalidate_rect(rect, false);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
|
Canvas::adjustSize()
|
|
|
|
|
|
{
|
|
|
|
|
|
recalcExtension_ = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
|
Canvas::determineExtension()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (not recalcExtension_) return;
|
|
|
|
|
|
|
|
|
|
|
|
uint extH=200, extV=200;
|
2019-08-03 13:34:56 +02:00
|
|
|
|
// ADD HERE: Code do find extension of the canvas dynamically...
|
|
|
|
|
|
//
|
2019-07-31 22:54:23 +02:00
|
|
|
|
recalcExtension_ = false;
|
|
|
|
|
|
set_size (extH, extV);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool
|
2019-07-31 23:27:33 +02:00
|
|
|
|
Canvas::on_draw(CairoC cox)
|
2019-07-31 22:54:23 +02:00
|
|
|
|
{
|
|
|
|
|
|
if (shallDraw_)
|
|
|
|
|
|
{
|
|
|
|
|
|
uint extH, extV;
|
|
|
|
|
|
determineExtension();
|
|
|
|
|
|
get_size (extH, extV);
|
|
|
|
|
|
|
|
|
|
|
|
auto adjH = get_hadjustment();
|
|
|
|
|
|
auto adjV = get_vadjustment();
|
|
|
|
|
|
double offH = adjH->get_value();
|
|
|
|
|
|
double offV = adjV->get_value();
|
|
|
|
|
|
|
|
|
|
|
|
cox->save();
|
|
|
|
|
|
cox->translate(-offH, -offV);
|
|
|
|
|
|
|
|
|
|
|
|
// draw red diagonal line
|
|
|
|
|
|
cox->set_source_rgb(0.8, 0.0, 0.0);
|
|
|
|
|
|
cox->set_line_width (10.0);
|
|
|
|
|
|
cox->move_to(0, 0);
|
|
|
|
|
|
cox->line_to(extH, extV);
|
|
|
|
|
|
cox->stroke();
|
|
|
|
|
|
cox->restore();
|
|
|
|
|
|
|
2019-07-31 23:56:51 +02:00
|
|
|
|
//////////////////TEST drawing via Gtk::StyleContext
|
|
|
|
|
|
{
|
|
|
|
|
|
int marT = style_->get_margin().get_top();
|
2019-08-03 13:34:56 +02:00
|
|
|
|
|
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-03 23:26:37 +02:00
|
|
|
|
|
2019-08-03 13:34:56 +02:00
|
|
|
|
if (xBorderSiz > 1) {
|
2019-08-04 17:00:18 +02:00
|
|
|
|
// style_->context_save(); // <<<---does not work. Asked on SO: https://stackoverflow.com/q/57342478
|
|
|
|
|
|
style_->add_class(slopeClassName(xBorderSiz));
|
2019-08-03 13:34:56 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
xObservedSize = style_->get_border().get_top();
|
|
|
|
|
|
xObservedPath = string{style_->get_path().to_string()};
|
2019-08-03 15:45:36 +02:00
|
|
|
|
xObservedClzz = join(style_->list_classes(), " ");
|
|
|
|
|
|
|
|
|
|
|
|
int height = marT + 2 * xObservedSize;
|
2019-07-31 23:56:51 +02:00
|
|
|
|
style_->render_frame (cox
|
2019-08-03 15:45:36 +02:00
|
|
|
|
,20 // left start of the rectangle
|
|
|
|
|
|
,20 // top of the rectangle
|
|
|
|
|
|
,50 // width of the area
|
|
|
|
|
|
,height // height to fill
|
2019-07-31 23:56:51 +02:00
|
|
|
|
);
|
2019-08-04 17:00:18 +02:00
|
|
|
|
// NOTE: all box-shadow effects are rendered *here*
|
|
|
|
|
|
style_->render_background (cox
|
|
|
|
|
|
,40
|
|
|
|
|
|
,60
|
|
|
|
|
|
,80
|
|
|
|
|
|
,height
|
|
|
|
|
|
);
|
2019-08-03 13:34:56 +02:00
|
|
|
|
|
|
|
|
|
|
if (xBorderSiz > 1) {
|
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-03 23:26:37 +02:00
|
|
|
|
// style_->context_restore();
|
|
|
|
|
|
style_->remove_class(slopeClassName(xBorderSiz));
|
2019-08-03 13:34:56 +02:00
|
|
|
|
}
|
2019-07-31 23:56:51 +02:00
|
|
|
|
}
|
|
|
|
|
|
//////////////////TEST drawing via Gtk::StyleContext
|
|
|
|
|
|
|
2019-07-31 22:54:23 +02:00
|
|
|
|
// cause child widgets to be redrawn
|
|
|
|
|
|
bool event_is_handled = Gtk::Layout::on_draw(cox);
|
|
|
|
|
|
|
|
|
|
|
|
// any drawing which follows happens on top of child widgets...
|
|
|
|
|
|
cox->save();
|
|
|
|
|
|
cox->translate(-offH, -offV);
|
|
|
|
|
|
|
|
|
|
|
|
cox->set_source_rgb(0.2, 0.4, 0.9);
|
|
|
|
|
|
cox->set_line_width (2.0);
|
|
|
|
|
|
cox->rectangle(0,0, extH, extV);
|
|
|
|
|
|
cox->stroke();
|
|
|
|
|
|
cox->restore();
|
|
|
|
|
|
|
|
|
|
|
|
return event_is_handled;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
return Gtk::Layout::on_draw(cox);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Window
|
|
|
|
|
|
: public Gtk::Window
|
|
|
|
|
|
{
|
|
|
|
|
|
StyleTestPanel demoPanel_;
|
|
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
Window()
|
|
|
|
|
|
: demoPanel_{}
|
|
|
|
|
|
{
|
|
|
|
|
|
this->add (demoPanel_);
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
}//namespace research
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
|
main (int argc, char* argv[])
|
|
|
|
|
|
{
|
|
|
|
|
|
NOTICE (main, "*** GTK Style Experiment ***");
|
|
|
|
|
|
|
|
|
|
|
|
auto guiApp = Gtk::Application::create (argc, argv);
|
|
|
|
|
|
|
|
|
|
|
|
research::Window window;
|
|
|
|
|
|
return guiApp->run(window);
|
|
|
|
|
|
}
|