-
Notifications
You must be signed in to change notification settings - Fork 8
/
gtk-widget.vala
137 lines (124 loc) · 4.19 KB
/
gtk-widget.vala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/**
* This is the functions that superrides GtkMenuBar vtable.
*/
internal class Widget {
[CCode (cname="G_STRUCT_OFFSET(GtkWidgetClass, parent_set)")]
private extern const int OffsetParentSet;
private static delegate void ParentSetFunc(Gtk.Widget? widget, Gtk.Widget? old_parent);
public Widget() {
Superrider.superride(typeof(Gtk.Widget), OffsetParentSet, (void*)parent_set);
}
~Widget() {
/*FIXME: remove all extra data members */
}
public static void parent_set(Gtk.Widget? widget, Gtk.Widget? old_parent) {
ParentSetFunc super = (ParentSetFunc) Superrider.peek_super(typeof(Gtk.Widget), OffsetParentSet);
if(super != null) super(widget, old_parent);
if(widget is Gtk.MenuBar || widget is Gtk.Menu) return;
var parent = widget.parent;
Gtk.MenuBar menubar = null;
if(parent != null) {
menubar = get_menubar(parent);
}
set_menubar_r(widget, menubar);
}
public static unowned Gtk.MenuBar get_menubar(Gtk.Widget widget) {
if(widget is Gtk.MenuBar) return widget as Gtk.MenuBar;
unowned Gtk.MenuBar menubar = (Gtk.MenuBar) widget.get_data("globalmenu-menubar");
return menubar;
}
private static void set_menubar(Gtk.Widget widget, Gtk.MenuBar? menubar) {
/* never called on a Gtk.MenuBar.
* if reached the assertion, check the bt and figure out why.
*
* */
assert(!(widget is Gtk.MenuBar));
var old_menubar = get_menubar(widget);
if(old_menubar == menubar) return;
if(old_menubar != null) {
try_disconnect_label(widget);
try_disconnect_menuitem(widget);
MenuBar.queue_changed(old_menubar);
}
widget.set_data("globalmenu-menubar", (void*) menubar);
if(menubar != null) {
try_connect_label(widget);
try_connect_menuitem(widget);
MenuBar.queue_changed(menubar);
}
}
/* This function is called by MenuBar.set_children_menubars */
internal static void set_menubar_r(Gtk.Widget widget, Gtk.MenuBar? menubar) {
/* Stop ASAP if we find ourself started the recursive set menubar process
* from a widget that is hierarchically above a menubar.
*
* This should happen only if when menubar == null. When a widget is being
* reparented we know it for sure, if the widget is above a menubar.
* */
if(menubar == null && (widget is Gtk.MenuBar)) {
return;
}
set_menubar(widget, menubar);
if(widget is Gtk.Container) {
List<weak Gtk.Widget> children = (widget as Gtk.Container).get_children();
foreach(var child in children) {
set_menubar_r(child, menubar);
}
}
if(widget is Gtk.MenuItem) {
var item = widget as Gtk.MenuItem;
if(item.submenu != null)
set_menubar_r(item.submenu, menubar);
}
}
private static void try_connect_label(Gtk.Widget widget) {
if(widget is Gtk.Label)
widget.notify["label"] += simple_changed;
}
private static void try_connect_menuitem(Gtk.Widget widget) {
if(widget is Gtk.MenuItem) {
widget.notify["submenu"] += recursive_changed;
widget.notify["visible"] += simple_changed;
widget.notify["sensitive"] += simple_changed;
}
if(widget is Gtk.CheckMenuItem) {
widget.notify["active"] += simple_changed;
widget.notify["inconsistent"] += simple_changed;
widget.notify["draw-as-radio"] += simple_changed;
}
}
private static void try_disconnect_menuitem(Gtk.Widget widget) {
if(widget is Gtk.MenuItem) {
widget.notify -= simple_changed;
widget.notify -= recursive_changed;
}
}
private static void try_disconnect_label(Gtk.Widget widget) {
if(widget is Gtk.Label)
widget.notify -= simple_changed;
}
private static void simple_changed(Gtk.Widget widget, ParamSpec pspec) {
var menubar = Widget.get_menubar(widget);
assert(menubar != null);
MenuBar.queue_changed(menubar);
}
private static void recursive_changed(Gtk.Widget widget, ParamSpec pspec) {
assert(widget is Gtk.MenuItem);
var item = widget as Gtk.MenuItem;
var submenu = item.submenu;
var old_submenu = (Gtk.Menu) item.get_data("old_submenu");
var menubar = Widget.get_menubar(widget);
if(submenu == old_submenu) {
simple_changed(widget, pspec);
return;
}
if(old_submenu != null) {
Widget.set_menubar_r(old_submenu, null);
}
if(submenu != null) {
Widget.set_menubar_r(submenu, menubar);
}
widget.set_data("old_submenu", (void*)submenu);
simple_changed(widget, pspec);
}
}