Merge lp:~elementary-pantheon/granite/lp-1066136 into lp:~elementary-pantheon/granite/granite

Proposed by Victor Martinez
Status: Merged
Merged at revision: 422
Proposed branch: lp:~elementary-pantheon/granite/lp-1066136
Merge into: lp:~elementary-pantheon/granite/granite
Diff against target: 179 lines (+59/-36)
1 file modified
lib/Widgets/ModeButton.vala (+59/-36)
To merge this branch: bzr merge lp:~elementary-pantheon/granite/lp-1066136
Reviewer Review Type Date Requested Status
David Gomes (community) Approve
Review via email: mp+129546@code.launchpad.net

Commit message

Fix bug #1066136: Removing an item from the ModeButton widget renders consecutive item indexes invalid.

Description of the change

This branch fixes Bug #1066136: Removing an item from the ModeButton widget renders consecutive item indexes invalid.

The approach followed here is using an internal hash map to keep a strong key-item association, and smarter code for creating a new index in ModeButton.append().

You can find more information (and even a test) in the bug report. Thanks in advance for the review!

To post a comment you must log in.
Revision history for this message
David Gomes (davidgomes) wrote :

The code really looks fine, but I believe that before a merge this should have some more testing, we really can't break ModeButton.

Revision history for this message
Victor Martinez (victored) wrote :

I don't think this breaks anything, unless some application is using lp:1066136 as a feature rather than a bug xD

We'll never know unless we merge it. It's better to figure out we broke something before it's already too-late to fix it in this development cycle.

Revision history for this message
Sergey "Shnatsel" Davidoff (shnatsel) wrote :

I wonder why this is still not merged...

Revision history for this message
David Gomes (davidgomes) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'lib/Widgets/ModeButton.vala'
--- lib/Widgets/ModeButton.vala 2012-09-26 20:49:21 +0000
+++ lib/Widgets/ModeButton.vala 2012-10-13 02:12:20 +0000
@@ -21,6 +21,15 @@
2121
22 public class ModeButton : Gtk.Box {22 public class ModeButton : Gtk.Box {
2323
24 private class Item : Gtk.ToggleButton {
25 public int index { get; construct; }
26 public Item (int index) {
27 Object (index: index);
28 can_focus = false;
29 add_events (Gdk.EventMask.SCROLL_MASK);
30 }
31 }
32
24 public signal void mode_added (int index, Gtk.Widget widget);33 public signal void mode_added (int index, Gtk.Widget widget);
25 public signal void mode_removed (int index, Gtk.Widget widget);34 public signal void mode_removed (int index, Gtk.Widget widget);
26 public signal void mode_changed (Gtk.Widget widget);35 public signal void mode_changed (Gtk.Widget widget);
@@ -31,16 +40,19 @@
31 }40 }
3241
33 public uint n_items {42 public uint n_items {
34 get { return get_children ().length (); }43 get { return item_map.size; }
35 }44 }
3645
37 private int _selected = -1;46 private int _selected = -1;
47 private Gee.HashMap<int, Item> item_map;
3848
39 public ModeButton () {49 public ModeButton () {
40 homogeneous = true;50 homogeneous = true;
41 spacing = 0;51 spacing = 0;
42 can_focus = false;52 can_focus = false;
4353
54 item_map = new Gee.HashMap<int, Item> ();
55
44 var style = get_style_context ();56 var style = get_style_context ();
45 style.add_class (Gtk.STYLE_CLASS_LINKED);57 style.add_class (Gtk.STYLE_CLASS_LINKED);
46 style.add_class ("raised"); // needed for toolbars58 style.add_class ("raised"); // needed for toolbars
@@ -59,41 +71,42 @@
59 }71 }
6072
61 public int append (Gtk.Widget w) {73 public int append (Gtk.Widget w) {
62 var button = new Gtk.ToggleButton ();74 int index;
63 button.can_focus = false;75 for (index = item_map.size; item_map.has_key (index); index++);
64 button.add_events (Gdk.EventMask.SCROLL_MASK);76 assert (item_map[index] == null);
65 button.scroll_event.connect (on_scroll_event);77
6678 var item = new Item (index);
67 button.add (w);79 item.scroll_event.connect (on_scroll_event);
6880 item.add (w);
69 button.button_press_event.connect ( () => {81
70 set_active (get_children ().index (button));82 item.button_press_event.connect (() => {
83 set_active (item.index);
71 return true;84 return true;
72 });85 });
7386
74 add (button);87 item_map[index] = item;
75 button.show_all ();88
7689 add (item);
77 var children = get_children ();90 item.show_all ();
78 int item_index = (int)children.length () - 1;91
79 mode_added (item_index, w);92 mode_added (index, w);
80 return item_index;93
94 return index;
81 }95 }
8296
83 public void set_active (int new_active_index) {97 public void set_active (int new_active_index) {
84 var children = get_children ();98 return_if_fail (item_map.has_key (new_active_index));
85 return_if_fail (new_active_index >= 0 && new_active_index < children.length ());99 var new_item = item_map[new_active_index] as Item;
86
87 var new_item = children.nth_data (new_active_index) as Gtk.ToggleButton;
88100
89 if (new_item != null) {101 if (new_item != null) {
102 assert (new_item.index == new_active_index);
90 new_item.set_active (true);103 new_item.set_active (true);
91104
92 if (_selected == new_active_index)105 if (_selected == new_active_index)
93 return;106 return;
94107
95 // Unselect the previous item108 // Unselect the previous item
96 var old_item = children.nth_data (_selected) as Gtk.ToggleButton;109 var old_item = item_map[_selected] as Item;
97 if (old_item != null)110 if (old_item != null)
98 old_item.set_active (false);111 old_item.set_active (false);
99112
@@ -104,24 +117,24 @@
104 }117 }
105118
106 public void set_item_visible (int index, bool val) {119 public void set_item_visible (int index, bool val) {
107 var children = get_children ();120 return_if_fail (item_map.has_key (index));
108 return_if_fail (index >= 0 && index < children.length ());121 var item = item_map[index] as Item;
109
110 var item = children.nth_data (index);
111122
112 if (item != null) {123 if (item != null) {
124 assert (item.index == index);
113 item.no_show_all = !val;125 item.no_show_all = !val;
114 item.visible = val;126 item.visible = val;
115 }127 }
116 }128 }
117129
118 public new void remove (int index) {130 public new void remove (int index) {
119 var children = get_children ();131 return_if_fail (item_map.has_key (index));
120 return_if_fail (index >= 0 && index < children.length ());132 var item = item_map[index] as Item;
121133
122 var item = children.nth_data (index) as Gtk.Bin;
123 if (item != null) {134 if (item != null) {
135 assert (item.index == index);
124 mode_removed (index, item.get_child ());136 mode_removed (index, item.get_child ());
137 item_map.unset (index);
125 item.destroy ();138 item.destroy ();
126 }139 }
127 }140 }
@@ -133,6 +146,8 @@
133 base.remove (button);146 base.remove (button);
134 }147 }
135148
149 item_map.clear ();
150
136 _selected = -1;151 _selected = -1;
137 }152 }
138153
@@ -152,18 +167,26 @@
152 return false;167 return false;
153 }168 }
154169
155 int new_item = selected;170 // Try to find a valid item, since there could be invisible items in
156171 // the middle and those shouldn't be selected. We use the children list
157 // Try to find a valid item, since there could be invisible items in the middle172 // instead of item_map because order matters here.
158 // and those shouldn't be selected
159 var children = get_children ();173 var children = get_children ();
160 uint n_children = children.length ();174 uint n_children = children.length ();
161175
176 var selected_item = item_map[selected];
177 if (selected_item == null)
178 return false;
179
180 int new_item = children.index (selected_item);
181 if (new_item < 0)
182 return false;
183
162 do {184 do {
163 new_item += offset;185 new_item += offset;
164 var item = children.nth_data (new_item);186 var item = children.nth_data (new_item) as Item;
165 if (item != null && item.visible) {187
166 selected = new_item;188 if (item != null && item.visible && item.sensitive) {
189 selected = item.index;
167 break;190 break;
168 }191 }
169 } while (new_item >= 0 && new_item < n_children);192 } while (new_item >= 0 && new_item < n_children);

Subscribers

People subscribed via source and target branches