Merge lp:~victored/granite/mode-button-fixes into lp:~elementary-pantheon/granite/granite

Proposed by Victor Martinez
Status: Merged
Approved by: xapantu
Approved revision: 165
Merged at revision: 167
Proposed branch: lp:~victored/granite/mode-button-fixes
Merge into: lp:~elementary-pantheon/granite/granite
Diff against target: 424 lines (+243/-111)
2 files modified
data/style/ModeButton.css (+0/-45)
lib/Widgets/ModeButton.vala (+243/-66)
To merge this branch: bzr merge lp:~victored/granite/mode-button-fixes
Reviewer Review Type Date Requested Status
xapantu Pending
Review via email: mp+89569@code.launchpad.net

Description of the change

[Granite.Widgets.ModeButton]

New API functions.
Removed deprecated elements.

To post a comment you must log in.
165. By Victor Martinez

Make style_provider and widget_style internal

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== removed file 'data/style/ModeButton.css'
2--- data/style/ModeButton.css 2011-09-17 22:51:19 +0000
3+++ data/style/ModeButton.css 1970-01-01 00:00:00 +0000
4@@ -1,45 +0,0 @@
5-/*
6-* Copyright (C) 2011 Giulio Collura
7-*
8-* This program is free software: you can redistribute it and/or modify
9-* it under the terms of the GNU General Public License as published by
10-* the Free Software Foundation, either version 3 of the License, or
11-* (at your option) any later version.
12-*
13-* This program is distributed in the hope that it will be useful,
14-* but WITHOUT ANY WARRANTY; without even the implied warranty of
15-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16-* GNU General Public License for more details.
17-*
18-* You should have received a copy of the GNU General Public License
19-* along with this program. If not, see <http://www.gnu.org/licenses/>.
20-*/
21-
22-.modebutton {
23- -GtkToolbar-button-relief: normal;
24- border-radius: 0 0 0 0;
25- border-style: solid;
26- border-width: 1 0 1 1;
27-
28- -unico-outer-stroke-width: 1 0 1 0;
29- -unico-outer-stroke-radius: 0 0 0 0;
30-}
31-
32-.modebutton:active,
33-.modebutton:insensitive {
34- -unico-outer-stroke-width: 1 0 1 0;
35-}
36-
37-.modebutton:nth-child(first) {
38- border-radius: 3 0 0 3;
39- border-width: 1 0 1 1;
40-
41- -unico-outer-stroke-width: 1 0 1 1;
42-}
43-
44-.modebutton:nth-child(last) {
45- border-radius: 0 3 3 0;
46- border-width: 1;
47-
48- -unico-outer-stroke-width: 1 1 1 0;
49-}
50
51=== modified file 'lib/Widgets/ModeButton.vala'
52--- lib/Widgets/ModeButton.vala 2011-11-30 18:38:01 +0000
53+++ lib/Widgets/ModeButton.vala 2012-01-22 04:04:23 +0000
54@@ -1,34 +1,74 @@
55-//
56+//
57 // Copyright (C) 2008 Christian Hergert <chris@dronelabs.com>
58 // Copyright (C) 2011 Giulio Collura
59-//
60+//
61 // This program is free software: you can redistribute it and/or modify
62 // it under the terms of the GNU General Public License as published by
63 // the Free Software Foundation, either version 3 of the License, or
64 // (at your option) any later version.
65-//
66+//
67 // This program is distributed in the hope that it will be useful,
68 // but WITHOUT ANY WARRANTY; without even the implied warranty of
69 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
70 // GNU General Public License for more details.
71-//
72+//
73 // You should have received a copy of the GNU General Public License
74 // along with this program. If not, see <http://www.gnu.org/licenses/>.
75-//
76+//
77
78 using Gtk;
79 using Gdk;
80
81 namespace Granite.Widgets {
82-
83- public class ModeButton : HBox {
84-
85+
86+ public class ModeButton : Gtk.Box {
87+
88 public signal void mode_added (int index, Gtk.Widget widget);
89 public signal void mode_removed (int index, Gtk.Widget widget);
90 public signal void mode_changed (Gtk.Widget widget);
91- static CssProvider style_provider;
92-
93+
94+ /* Style properties. Please note that style class names are for internal
95+ usage only. Theme developers should use GraniteWidgetsModeButton instead.
96+ */
97+
98+ internal static CssProvider style_provider;
99+ internal static StyleContext widget_style;
100+
101+ private const int style_priority = Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION;
102+
103+ private const string STYLESHEET = """
104+ .GraniteModeButton .button {
105+ -GtkToolbar-button-relief: normal;
106+ border-radius: 0 0 0 0;
107+ border-style: solid;
108+ border-width: 1 0 1 1;
109+
110+ -unico-outer-stroke-width: 1 0 1 0;
111+ -unico-outer-stroke-radius: 0 0 0 0;
112+ }
113+
114+ .GraniteModeButton .button:active,
115+ .GraniteModeButton .button:insensitive {
116+ -unico-outer-stroke-width: 1 0 1 0;
117+ }
118+
119+ .GraniteModeButton .button:first-child {
120+ border-radius: 3 0 0 3;
121+ border-width: 1 0 1 1;
122+
123+ -unico-outer-stroke-width: 1 0 1 1;
124+ }
125+
126+ .GraniteModeButton .button:last-child {
127+ border-radius: 0 3 3 0;
128+ border-width: 1;
129+
130+ -unico-outer-stroke-width: 1 1 1 0;
131+ }
132+ """;
133+
134 private int _selected = -1;
135+
136 public int selected {
137 get {
138 return _selected;
139@@ -37,86 +77,118 @@
140 set_active(value);
141 }
142 }
143-
144+
145+ public uint n_items {
146+ get {
147+ return get_children().length();
148+ }
149+ }
150+
151 public ModeButton () {
152-
153-
154- if(style_provider == null)
155+
156+ if (style_provider == null)
157 {
158 style_provider = new CssProvider ();
159 try {
160- style_provider.load_from_path (RESOURCES_DIR + "/style/ModeButton.css");
161+ style_provider.load_from_data (STYLESHEET, -1);
162 } catch (Error e) {
163- warning ("Could not add css provider. Some widgets will not look as intended. %s", e.message);
164+ warning ("GraniteModeButton: %s. The widget will not look as intended", e.message);
165 }
166 }
167-
168+
169+ widget_style = get_style_context ();
170+ widget_style.add_class ("GraniteModeButton");
171+
172 homogeneous = true;
173 spacing = 0;
174-
175 app_paintable = true;
176- set_visual (get_screen ().get_rgba_visual());
177-
178+ set_visual (get_screen().get_rgba_visual());
179+
180 can_focus = true;
181-
182- }
183-
184+ }
185+
186+ public void append_pixbuf (Gdk.Pixbuf? pixbuf) {
187+ if (pixbuf == null)
188+ return;
189+
190+ var image = new Image.from_pixbuf (pixbuf);
191+ append (image);
192+ }
193+
194+ public void append_text (string? text) {
195+ if (text == null)
196+ return;
197+
198+ append (new Gtk.Label(text));
199+ }
200+
201+ /**
202+ * This is the recommended function for adding icons to the ModeButton widget.
203+ * If you pass the name of a symbolic icon, it will be properly themed for
204+ * every state of the widget. That is, it will match the foreground color
205+ * defined by the theme for each state (active, prelight, insensitive, etc.)
206+ */
207+ public void append_icon (string icon_name, Gtk.IconSize size) {
208+ append_mode_button_item (null, icon_name, size);
209+ }
210+
211 public void append (Gtk.Widget w) {
212-
213- var button = new ToggleButton ();
214- button.add(w);
215- //button.width_request = 30;
216- button.can_focus = false;
217- button.get_style_context ().add_class ("modebutton");
218- button.get_style_context ().add_class ("raised");
219- button.get_style_context ().add_provider (style_provider, 600);
220-
221- button.button_press_event.connect (() => {
222-
223- int select = get_children ().index (button);
224- set_active (select);
225- return true;
226-
227- });
228-
229- add (button);
230- button.show_all ();
231-
232- mode_added((int)get_children ().length (), w);
233-
234- }
235-
236- public void set_active (int new_active) {
237-
238- if (new_active >= get_children ().length () || _selected == new_active)
239+ append_mode_button_item (w, null, null);
240+ }
241+
242+ /**
243+ * This function adds the foreground style properties of the given style
244+ * context to the widget's icons. This is useful when you want to make the widget
245+ * adapt its symbolic icon color to that of the parent in case the GTK+
246+ * theme has not set them correctly. This function only affects the behavior
247+ * of icons added with append_icon().
248+ */
249+ public void set_icon_foreground_style (Gtk.StyleContext icon_style) {
250+ foreach (weak Widget button in get_children ()) {
251+ (button as ModeButtonItem).set_icon_foreground_style (icon_style);
252+ }
253+ }
254+
255+ public void set_active (int new_active_index) {
256+
257+ if (new_active_index >= get_children().length () || _selected == new_active_index)
258 return;
259-
260+
261 if (_selected >= 0)
262- ((ToggleButton) get_children ().nth_data (_selected)).set_active (false);
263-
264- _selected = new_active;
265- ((ToggleButton) get_children ().nth_data (_selected)).set_active (true);
266- mode_changed(((ToggleButton) get_children ().nth_data (_selected)).get_child());
267-
268- }
269-
270- public new void remove(int number)
271+ ((ToggleButton) get_children().nth_data(_selected)).set_active (false);
272+
273+ _selected = new_active_index;
274+ ((ToggleButton) get_children().nth_data(_selected)).set_active (true);
275+
276+ mode_changed(((ToggleButton) get_children().nth_data(_selected)).get_child());
277+ }
278+
279+ public void set_item_visible(int index, bool val) {
280+ var item = get_children().nth_data(index);
281+ if(item == null)
282+ return;
283+
284+ item.set_no_show_all(!val);
285+ item.set_visible(val);
286+ }
287+
288+ public new void remove(int index)
289 {
290- mode_removed(number, (get_children ().nth_data (number) as Gtk.Bin).get_child ());
291- get_children ().nth_data (number).destroy();
292+ mode_removed(index, (get_children().nth_data(index) as Gtk.Bin).get_child ());
293+ get_children().nth_data(index).destroy();
294 }
295-
296+
297 public void clear_children () {
298-
299+
300 foreach (weak Widget button in get_children ()) {
301 button.hide ();
302 if (button.get_parent () != null)
303 base.remove (button);
304 }
305+
306 _selected = -1;
307-
308 }
309-
310+
311 protected override bool scroll_event (EventScroll ev) {
312 if(ev.direction == Gdk.ScrollDirection.DOWN) {
313 selected ++;
314@@ -127,6 +199,111 @@
315
316 return false;
317 }
318+
319+ private void append_mode_button_item (Gtk.Widget? w, string? icon_name, Gtk.IconSize? size) {
320+ var button = new ModeButtonItem ();
321+
322+ /* Modifying properties */
323+ if (icon_name != null && size != null && w == null) {
324+ button.set_icon (icon_name, size);
325+ } else {
326+ button.add(w);
327+ }
328+
329+ button.button_press_event.connect (() => {
330+ int selected = get_children().index (button);
331+ set_active (selected);
332+ return true;
333+ });
334+
335+ add(button);
336+ button.show_all ();
337+
338+ mode_added((int)get_children().length(), w);
339+ }
340+
341+ }
342+
343+ private class ModeButtonItem : Gtk.ToggleButton {
344+
345+ /* The main purpose of this class is handling icon theming */
346+
347+ private bool has_themed_icon;
348+ private StyleContext? icon_style;
349+
350+ private string icon_name = "";
351+ private Gtk.IconSize? icon_size = null;
352+
353+ private const int style_priority = Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION;
354+
355+ public ModeButtonItem () {
356+ can_focus = false;
357+ has_themed_icon = false;
358+
359+ icon_style = null;
360+
361+ get_style_context().add_class ("button");
362+ get_style_context().add_class ("raised");
363+ get_style_context().add_provider (ModeButton.style_provider, style_priority);
364+
365+ /* We need to track state changes in order to modify the icon */
366+ state_flags_changed.connect ( () => {
367+ if (has_themed_icon)
368+ load_icon ();
369+ });
370+ }
371+
372+ public void set_icon_foreground_style (StyleContext? icon_style) {
373+ this.icon_style = icon_style;
374+ }
375+
376+ public new void set_icon (string name, Gtk.IconSize size) {
377+ icon_name = name;
378+ icon_size = size;
379+
380+ has_themed_icon = true;
381+
382+ load_icon ();
383+ }
384+
385+ public new void set_image (Gtk.Image? image) {
386+ if (image == null)
387+ return;
388+
389+ /* Remove previous images */
390+ foreach (weak Widget _image in get_children ()) {
391+ if (this.get_parent () != null && _image is Gtk.Image)
392+ _image.destroy();
393+ }
394+
395+ /* Add new image */
396+ add (image);
397+
398+ show_all ();
399+ }
400+
401+ private void load_icon () {
402+ set_image (new Image.from_pixbuf (render_themed_icon()));
403+ }
404+
405+ private Gdk.Pixbuf? render_themed_icon () {
406+ Gdk.Pixbuf? rv = null;
407+
408+ int width = 0, height = 0;
409+ icon_size_lookup (icon_size, out width, out height);
410+
411+ try {
412+ var themed_icon = new GLib.ThemedIcon.with_default_fallbacks (icon_name);
413+ Gtk.IconInfo? icon_info = IconTheme.get_default().lookup_by_gicon (themed_icon as GLib.Icon, height, Gtk.IconLookupFlags.GENERIC_FALLBACK);
414+ if (icon_info != null)
415+ rv = icon_info.load_symbolic_for_context (icon_style ?? ModeButton.widget_style);
416+ }
417+ catch (Error err) {
418+ warning ("%s", err.message);
419+ }
420+
421+ return rv;
422+ }
423 }
424 }
425

Subscribers

People subscribed via source and target branches