2016-12-22 4 views
0

Я пытаюсь предоставить свою собственную реализацию GtkStyleProvider, так как «обычный» поставщик CSS - это большая работа и дополнительная обработка для использования в моем случае.GtkStyleProvider - предоставление собственной реализации

Я хочу, чтобы иметь возможность создавать виджеты на основе некоторого внутреннего состояния, и для этого в CSS мне придется выписать огромную строку CSS (перевод таких вещей, как Pango.FontDescription s в объявления в стиле CSS) на основании любого изменения состояния, а затем подавать его в GktCssProvider, который будет обрабатывать его назад в Gtk-land. Сравните с пользовательским провайдером, который просто сигнализирует (каким-то образом) о том, что его виджеты-клиенты должны задавать его по стилю, и он передает новый стиль, основанный непосредственно на состоянии.

Похоже, что GtkStyleProvider - это способ добиться этого - я могу сделать провайдера, который возвращает стиль, основанный на определенном состоянии, и добавит его как поставщика стиля в соответствующий GtkStyleContext. Интерфейс (С)

// 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() никогда, кажется, называется, и поэтому не может быть предоставлен не на заказ стиль.

Замена DerivedStyleProvider на «нормальный» поставщик CSS отлично работает.

Каков правильный способ реализации пользовательского GtkStyleProvider (на любом языке)?

+0

Я быстро посмотрел на GtkCssProvider и реализовал * два * интерфейса, 'GtkStyleProvider' и' GtkStyleProviderPrivate'. Возможно, вам также необходимо обеспечить реализацию для второго интерфейса. Я не эксперт Gtk +, хотя ... –

+0

Объявление (код C) находится здесь: https://github.com/GNOME/gtk/blob/master/gtk/gtkstyleproviderprivate.h –

+0

Кстати: почему вам приходится тяжело настройте свой стиль ui в любом случае? Здесь я чувствую запах [проблемы XY] (http://xyproblem.info/). Возможно, вы захотите сделать шаг назад и переосмыслить свой дизайн. Нарисуйте пользовательский интерфейс самостоятельно с помощью Clutter, Cairo или чего-то подобного. –

ответ

2

Глядя на реализации GtkCssProvider, которая, как представляется, использовать не только GtkStyleProviderInterface, но и GtkStyleProviderPrivateInterface, и много сложного пользовательское шунтирование (по-видимому, по соображениям эффективности, в соответствии с дружелюбными людьми на он GTK + канал IRC), я решил просто используйте обычный метод CSS и просто займитесь созданием CSS вручную в виде строки.

Механизм:

  • GtkCssProvider создается
  • Provider прилагается к соответствующему контексту стиле с gtk_style_context_add_provider() (или глобальной gtk_style_context_add_provider_for_screen())
  • менеджер данных посылает сигнал о том, что данные изменились
  • Это связано с моим переводчиком Data-> CSS, который генерирует новую строку CSS для соответствующих GtkCssProvider
  • Эта строка передается существующему провайдеру с gtk_css_provider_load_from_data().
  • Любые изменения пользовательского интерфейса, возникающие в результате этого обновления будет происходить автоматически

Я полагаю, что проблема, скорее всего, что я не в полной мере понять, как работает GTK + внизу.Если вы рассматриваете CSS как канонический стиль «оракул» для пользовательского интерфейса, то я полагаю, что обновление CSS действительно на самом деле является правильным подходом, и я ожидаю доступ к низкоуровневому доступу, который возможно технически возможен, но не является «правильным» в GTK +.

Этот низкоуровневый доступ - это то, что я ожидал от других фреймворков, где у вас (только) есть прямой контроль над стилями вещей, таких как «цвет фона» виджетов, и нет слоя CSS для его абстрагирования, но просто не работает в GTK + (не более).

По крайней мере, так я это понимаю!

+0

Да, это то, к чему я тоже пришел. Как и вы, я действительно хотел, чтобы у меня был прямой доступ к свойствам, но я понял, что все написано так, что CSS является источником. Внутреннее преобразование этого в материал GObject не является общедоступным API, вероятно, потому что обещание об этом было бы кошмаром для обслуживания и стоять на пути перезаписывания/оптимизации парсера и т. Д. Поскольку машинное оборудование стиля должно потреблять CSS, имеет смысл иметь это как единственный маршрут, тогда им нужно поддерживать только одну поверхность API. –

Смежные вопросы