GtkStyleProvider - 提供自己的实现

时间:2016-12-22 05:46:13

标签: css c gtk styling vala

我正在尝试提供我自己的GtkStyleProvider实现,因为“普通”CSS提供程序需要大量的工作和额外的处理才能在我的情况下使用。

我希望能够基于某些内部状态提供小部件样式,并且要在CSS中执行此操作,我必须写出一大串CSS(将Pango.FontDescription之类的内容翻译成CSS-样式声明)基于状态的任何变化,然后将其提供给GktCssProvider,它将返回处理到Gtk-land。与自定义提供程序相比,它只是发出信号(不知何故)其客户端小部件应该询问它的样式,并直接根据状态分发新的样式。

似乎GtkStyleProvider是实现这一目标的一种方式 - 我可以创建一个基于某个状态返回样式的提供程序,并将其作为样式提供程序添加到相关的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()方法,因此无法提供自定义样式。

用“普通”CSS提供程序替换DerivedStyleProvider可以正常工作。

实现自定义GtkStyleProvider(使用任何语言)的正确方法是什么?

1 个答案:

答案 0 :(得分:2)

查看GtkCssProvider的实现,它似乎不仅使用GtkStyleProviderInterface而且还使用GtkStyleProviderPrivateInterface,以及许多复杂的自定义绕过(显然出于效率原因,根据友好情况而定)关于GTK + IRC频道的人,我决定只使用普通的CSS方法,只是手工构建CSS作为字符串。

机制是:

  • 创建GtkCssProvider
  • 提供商已使用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 实际上是正确的方法,并且我期待可能在技术上可行的低级访问,但不是"正确"在GTK +方式。

这种低级访问是我对其他框架的期望,在这些框架中,您(仅)可以直接控制诸如"背景颜色"之类的事物的样式。小部件,并没有CSS层来抽象它,但不是它在GTK +中的工作方式(更多)。

至少,这就是我的理解!