GtkStyleProvider - 提供自己的实现
GtkStyleProvider - providing own implementation
我正在尝试提供我自己的 GtkStyleProvider
实现,因为 "normal" CSS 提供程序在我的案例中需要大量工作和额外处理。
我希望能够根据某些内部状态提供小部件样式,并且要在 CSS 中执行此操作,我必须写出一大串 CSS(翻译内容像 Pango.FontDescription
s 到 CSS 风格的声明)基于任何状态的变化,然后将它送入 GktCssProvider
将处理它 back进入 Gtk 领域。与自定义提供程序相比,自定义提供程序只会(以某种方式)发出信号表明其客户端小部件应该向其询问样式,并直接根据状态分发新样式。
似乎 GtkStyleProvider
是实现这一目标的一种方式 - 我可以制作一个提供者 returns 基于某种状态的样式,并将其作为样式提供者添加到相关 GtkStyleContext
. (C)界面为
// deprecated - return NULL in new code
GtkIconFactory * gtk_style_provider_get_icon_factory (
GtkStyleProvider *provider,
GtkWidgetPath *path);)
// deprecated - return NULL in new code
GtkStyleProperties * gtk_style_provider_get_style (
GtkStyleProvider *provider,
GtkWidgetPath *path))
// return true if property found and has a value, else false
gboolean gtk_style_provider_get_style_property (
GtkStyleProvider *provider,
GtkWidgetPath *path,
GtkStateFlags state,
GParamSpec *pspec,
GValue *value);
为此,我写了这样的东西,我希望它能工作,但什么也没做,因为它应该总是报告 属性 未设置:
# compile with: valac styleprov.vala --pkg gtk+-3.0 --pkg gdk-3.0
using Gtk;
using Gdk;
public class DerivedStyleProvider : Object, Gtk.StyleProvider
{
public unowned Gtk.IconFactory get_icon_factory (Gtk.WidgetPath path)
{
return (Gtk.IconFactory) null; // Evil cast to work around buggy declaration in VAPI file
}
public Gtk.StyleProperties get_style (Gtk.WidgetPath path)
{
return (Gtk.StyleProperties) null; // Evil cast to work around buggy declaration in VAPI file
}
public bool get_style_property (Gtk.WidgetPath path,
Gtk.StateFlags state,
GLib.ParamSpec pspec,
out GLib.Value value)
{
stdout.printf("get_style_property");
// Compiler happiness for testing
value = Value (typeof (string));
return false; //TODO
}
}
public class styleprov.MainWindow : Gtk.Window
{
construct {
DerivedStyleProvider styleProvider = new DerivedStyleProvider();
// but this would work
//Gtk.CssProvider styleProvider = new Gtk.CssProvider();
//styleProvider.load_from_data("*{ background-color: #ff0000; }");
StyleContext.add_provider_for_screen(this.get_screen(),
styleProvider,
Gtk.STYLE_PROVIDER_PRIORITY_USER);
}
}
class styleprov.Main : GLib.Object
{
public void run() {
styleprov.MainWindow mainWindow = new styleprov.MainWindow();
mainWindow.show_all();
}
public static int main (string[] args) {
Gtk.init (ref args);
Main app = new Main();
app.run();
Gtk.main ();
return 0;
}
}
编译正常,运行正常,但几乎会发出警告:
(styleprov:32365): GLib-GObject-WARNING **: gsignal.c:2523: signal '-gtk-private-changed' is invalid for instance '0x1154ac0' of type 'DerivedStyleProvider'
(styleprov:32365): Gtk-WARNING **: (gtkstylecascade.c:256):gtk_style_cascade_lookup: code should not be reached
(styleprov:32365): Gtk-WARNING **: (gtkstylecascade.c:256):gtk_style_cascade_lookup: code should not be reached
...several of these....
尽管有警告,get_style_property()
方法似乎从未被调用,因此无法提供自定义样式。
用 "normal" CSS 提供程序替换 DerivedStyleProvider
工作正常。
实现自定义 GtkStyleProvider
(任何语言)的正确方法是什么?
查看 GtkCssProvider
的实现,它似乎不仅使用了 GtkStyleProviderInterface
,还使用了 GtkStyleProviderPrivateInterface
,以及大量复杂的自定义绕过(显然是出于效率原因,根据GTK+ IRC 频道上的好心人),我决定只使用普通的 CSS 方法,只处理手动构建 CSS 作为字符串。
机制是:
- 创建了一个
GtkCssProvider
- Provider 附加到具有
gtk_style_context_add_provider()
(或全局 gtk_style_context_add_provider_for_screen()
)的相关样式上下文
- 数据管理器发出数据已更改的信号
- 这被我的 Data->CSS 翻译器捕获,它为相关的
GtkCssProvider
生成一个新的 CSS 字符串
- 此字符串通过
gtk_css_provider_load_from_data()
馈送到现有提供程序。
- 该更新导致的任何 UI 更改都会自动发生
我想问题很可能是我没有完全理解 GTK+ 是如何工作的。如果您将 CSS 视为 规范样式 "oracle" 用于 UI,那么我认为更新 CSS 确实 实际上是正确的方法,我期待一种技术上可能可行的低级别访问,但不是 "correct" GTK+ 方式。
这种低级访问是我对其他框架的期望,在这些框架中,您(仅)可以直接控制 "background colour" 小部件的样式,并且没有 CSS层来抽象它,但这不是它在 GTK+ 中的工作方式(不再)。
至少我是这么理解的!
我正在尝试提供我自己的 GtkStyleProvider
实现,因为 "normal" CSS 提供程序在我的案例中需要大量工作和额外处理。
我希望能够根据某些内部状态提供小部件样式,并且要在 CSS 中执行此操作,我必须写出一大串 CSS(翻译内容像 Pango.FontDescription
s 到 CSS 风格的声明)基于任何状态的变化,然后将它送入 GktCssProvider
将处理它 back进入 Gtk 领域。与自定义提供程序相比,自定义提供程序只会(以某种方式)发出信号表明其客户端小部件应该向其询问样式,并直接根据状态分发新样式。
似乎 GtkStyleProvider
是实现这一目标的一种方式 - 我可以制作一个提供者 returns 基于某种状态的样式,并将其作为样式提供者添加到相关 GtkStyleContext
. (C)界面为
// deprecated - return NULL in new code
GtkIconFactory * gtk_style_provider_get_icon_factory (
GtkStyleProvider *provider,
GtkWidgetPath *path);)
// deprecated - return NULL in new code
GtkStyleProperties * gtk_style_provider_get_style (
GtkStyleProvider *provider,
GtkWidgetPath *path))
// return true if property found and has a value, else false
gboolean gtk_style_provider_get_style_property (
GtkStyleProvider *provider,
GtkWidgetPath *path,
GtkStateFlags state,
GParamSpec *pspec,
GValue *value);
为此,我写了这样的东西,我希望它能工作,但什么也没做,因为它应该总是报告 属性 未设置:
# compile with: valac styleprov.vala --pkg gtk+-3.0 --pkg gdk-3.0
using Gtk;
using Gdk;
public class DerivedStyleProvider : Object, Gtk.StyleProvider
{
public unowned Gtk.IconFactory get_icon_factory (Gtk.WidgetPath path)
{
return (Gtk.IconFactory) null; // Evil cast to work around buggy declaration in VAPI file
}
public Gtk.StyleProperties get_style (Gtk.WidgetPath path)
{
return (Gtk.StyleProperties) null; // Evil cast to work around buggy declaration in VAPI file
}
public bool get_style_property (Gtk.WidgetPath path,
Gtk.StateFlags state,
GLib.ParamSpec pspec,
out GLib.Value value)
{
stdout.printf("get_style_property");
// Compiler happiness for testing
value = Value (typeof (string));
return false; //TODO
}
}
public class styleprov.MainWindow : Gtk.Window
{
construct {
DerivedStyleProvider styleProvider = new DerivedStyleProvider();
// but this would work
//Gtk.CssProvider styleProvider = new Gtk.CssProvider();
//styleProvider.load_from_data("*{ background-color: #ff0000; }");
StyleContext.add_provider_for_screen(this.get_screen(),
styleProvider,
Gtk.STYLE_PROVIDER_PRIORITY_USER);
}
}
class styleprov.Main : GLib.Object
{
public void run() {
styleprov.MainWindow mainWindow = new styleprov.MainWindow();
mainWindow.show_all();
}
public static int main (string[] args) {
Gtk.init (ref args);
Main app = new Main();
app.run();
Gtk.main ();
return 0;
}
}
编译正常,运行正常,但几乎会发出警告:
(styleprov:32365): GLib-GObject-WARNING **: gsignal.c:2523: signal '-gtk-private-changed' is invalid for instance '0x1154ac0' of type 'DerivedStyleProvider'
(styleprov:32365): Gtk-WARNING **: (gtkstylecascade.c:256):gtk_style_cascade_lookup: code should not be reached
(styleprov:32365): Gtk-WARNING **: (gtkstylecascade.c:256):gtk_style_cascade_lookup: code should not be reached
...several of these....
尽管有警告,get_style_property()
方法似乎从未被调用,因此无法提供自定义样式。
用 "normal" CSS 提供程序替换 DerivedStyleProvider
工作正常。
实现自定义 GtkStyleProvider
(任何语言)的正确方法是什么?
查看 GtkCssProvider
的实现,它似乎不仅使用了 GtkStyleProviderInterface
,还使用了 GtkStyleProviderPrivateInterface
,以及大量复杂的自定义绕过(显然是出于效率原因,根据GTK+ IRC 频道上的好心人),我决定只使用普通的 CSS 方法,只处理手动构建 CSS 作为字符串。
机制是:
- 创建了一个
GtkCssProvider
- Provider 附加到具有
gtk_style_context_add_provider()
(或全局gtk_style_context_add_provider_for_screen()
)的相关样式上下文 - 数据管理器发出数据已更改的信号
- 这被我的 Data->CSS 翻译器捕获,它为相关的
GtkCssProvider
生成一个新的 CSS 字符串
- 此字符串通过
gtk_css_provider_load_from_data()
馈送到现有提供程序。 - 该更新导致的任何 UI 更改都会自动发生
我想问题很可能是我没有完全理解 GTK+ 是如何工作的。如果您将 CSS 视为 规范样式 "oracle" 用于 UI,那么我认为更新 CSS 确实 实际上是正确的方法,我期待一种技术上可能可行的低级别访问,但不是 "correct" GTK+ 方式。
这种低级访问是我对其他框架的期望,在这些框架中,您(仅)可以直接控制 "background colour" 小部件的样式,并且没有 CSS层来抽象它,但这不是它在 GTK+ 中的工作方式(不再)。
至少我是这么理解的!