4 | 4 |
|
5 | 5 |
--- a/extensions/apps-menu/extension.js
|
6 | 6 |
+++ b/extensions/apps-menu/extension.js
|
7 | |
@@ -124,10 +124,9 @@ const ApplicationMenuItem = new Lang.Cla
|
8 | |
|
9 | |
const CategoryMenuItem = new Lang.Class({
|
10 | |
Name: 'CategoryMenuItem',
|
11 | |
- Extends: PopupMenu.PopupBaseMenuItem,
|
12 | |
+ Extends: PopupMenu.PopupMenuItem,
|
13 | |
|
14 | |
_init: function(button, category) {
|
15 | |
- this.parent();
|
16 | |
this._category = category;
|
17 | |
this._button = button;
|
18 | |
|
19 | |
@@ -140,8 +139,121 @@ const CategoryMenuItem = new Lang.Class(
|
|
7 |
@@ -114,7 +114,7 @@ class ApplicationMenuItem extends PopupM
|
|
8 |
}
|
|
9 |
};
|
|
10 |
|
|
11 |
-class CategoryMenuItem extends PopupMenu.PopupBaseMenuItem {
|
|
12 |
+class CategoryMenuItem extends PopupMenu.PopupMenuItem {
|
|
13 |
constructor(button, category) {
|
|
14 |
super();
|
|
15 |
this._category = category;
|
|
16 |
@@ -129,8 +129,121 @@ class CategoryMenuItem extends PopupMenu
|
20 | 17 |
else
|
21 | 18 |
name = _("Favorites");
|
22 | 19 |
|
23 | 20 |
- this.actor.add_child(new St.Label({ text: name }));
|
24 | |
- this.actor.connect('motion-event', Lang.bind(this, this._onMotionEvent));
|
25 | |
+ this.parent(name);
|
|
21 |
- this.actor.connect('motion-event', this._onMotionEvent.bind(this));
|
|
22 |
+ this._init(name);
|
26 | 23 |
+
|
27 | 24 |
+ //this.actor.connect('motion-event', Lang.bind(this, this._onMotionEvent));
|
28 | |
+ },
|
29 | |
+
|
30 | |
+ activate: function(event) {
|
|
25 |
+ }
|
|
26 |
+
|
|
27 |
+ activate(event) {
|
31 | 28 |
+ this._button.selectCategory(this._category, this);
|
32 | 29 |
+ //this._button.scrollToCatButton(this);
|
33 | 30 |
+ // we don't chain up here so that clicking on a category doesn't
|
34 | 31 |
+ // close the menu
|
35 | |
+ },
|
36 | |
+
|
37 | |
+ _isNavigatingSubmenu: function([x, y]) {
|
|
32 |
+ }
|
|
33 |
+
|
|
34 |
+ _isNavigatingSubmenu([x, y]) {
|
38 | 35 |
+ let [posX, posY] = this.actor.get_transformed_position();
|
39 | 36 |
+
|
40 | 37 |
+ if (this._oldX == -1) {
|
|
89 | 86 |
+ return true;
|
90 | 87 |
+
|
91 | 88 |
+ return false;
|
92 | |
+ },
|
93 | |
+
|
94 | |
+ _onMotionEvent: function(actor, event) {
|
|
89 |
+ }
|
|
90 |
+
|
|
91 |
+ _onMotionEvent(actor, event) {
|
95 | 92 |
+ if (!Clutter.get_pointer_grab()) {
|
96 | 93 |
+ this._oldX = -1;
|
97 | 94 |
+ this._oldY = -1;
|
|
107 | 104 |
+ this.actor.hover = false;
|
108 | 105 |
+ Clutter.ungrab_pointer();
|
109 | 106 |
+ return false;
|
110 | |
+ },
|
111 | |
+
|
112 | |
+ setActive: function(active, params) {
|
|
107 |
+ }
|
|
108 |
+
|
|
109 |
+ setActive(active, params) {
|
113 | 110 |
+ if (active) {
|
114 | 111 |
+ this._button.selectCategory(this._category, this);
|
115 | 112 |
+ //this._button.scrollToCatButton(this);
|
116 | 113 |
+ }
|
117 | |
+ this.parent(active, params);
|
118 | |
+ }
|
119 | |
+});
|
120 | |
+const ParentCategoryMenuItem = new Lang.Class({
|
121 | |
+ Name: 'ParentCategoryMenuItem',
|
122 | |
+ Extends: PopupMenu.PopupSubMenuMenuItem,
|
123 | |
+
|
124 | |
+ _init: function(button, category) {
|
125 | |
+ this._category = category;
|
|
114 |
+ super.setActive(active, params);
|
|
115 |
+ }
|
|
116 |
+};
|
|
117 |
+
|
|
118 |
+class ParentCategoryMenuItem extends PopupMenu.PopupSubMenuMenuItem {
|
|
119 |
+ constructor(text, wantIcon, button, category) {
|
|
120 |
+ super(text, wantIcon);
|
|
121 |
+ this._category = category;
|
126 | 122 |
+ this._button = button;
|
127 | 123 |
+
|
128 | 124 |
+ this._oldX = -1;
|
|
134 | 130 |
+ else
|
135 | 131 |
+ name = _("Favorites");
|
136 | 132 |
+
|
137 | |
+ this.parent(name, false);
|
|
133 |
+ this._init(name, false);
|
138 | 134 |
+
|
139 | 135 |
+ //this.actor.connect('motion-event', Lang.bind(this, this._onMotionEvent));
|
140 | |
},
|
141 | |
|
142 | |
activate: function(event) {
|
143 | |
@@ -233,12 +345,29 @@ const CategoryMenuItem = new Lang.Class(
|
144 | |
setActive: function(active, params) {
|
|
136 |
+
|
|
137 |
}
|
|
138 |
|
|
139 |
activate(event) {
|
|
140 |
@@ -222,12 +335,26 @@ class CategoryMenuItem extends PopupMenu
|
|
141 |
setActive(active, params) {
|
145 | 142 |
if (active) {
|
146 | 143 |
this._button.selectCategory(this._category, this);
|
147 | 144 |
- this._button.scrollToCatButton(this);
|
148 | 145 |
+ //this._button.scrollToCatButton(this);
|
149 | 146 |
}
|
150 | |
this.parent(active, params);
|
151 | |
}
|
152 | |
});
|
153 | |
|
154 | |
+const PopupMenuScrollView = new Lang.Class({
|
155 | |
+ Name: 'PopupMenuScrollView',
|
156 | |
+ Extends: PopupMenu.PopupMenuSection,
|
157 | |
+
|
158 | |
+ _init: function() {
|
159 | |
+ this.parent();
|
|
147 |
super.setActive(active, params);
|
|
148 |
}
|
|
149 |
};
|
|
150 |
|
|
151 |
+class PopupMenuScrollView extends PopupMenu.PopupMenuSection {
|
|
152 |
+ constructor() {
|
|
153 |
+ super();
|
160 | 154 |
+
|
161 | 155 |
+ this.actor = new St.ScrollView({ style_class: 'vfade',
|
162 | 156 |
+ hscrollbar_policy: Gtk.PolicyType.NEVER,
|
|
165 | 159 |
+ this.actor.add_actor(this.box);
|
166 | 160 |
+ this.actor._delegate = this;
|
167 | 161 |
+ this.actor.clip_to_allocation = true;
|
168 | |
+ },
|
169 | |
+});
|
170 | |
+
|
171 | |
const ApplicationsMenu = new Lang.Class({
|
172 | |
Name: 'ApplicationsMenu',
|
173 | |
Extends: PopupMenu.PopupMenu,
|
174 | |
@@ -473,7 +602,7 @@ const ApplicationsButton = new Lang.Clas
|
175 | |
this._installedChangedId = appSys.connect('installed-changed', Lang.bind(this, function() {
|
176 | |
if (this.menu.isOpen) {
|
177 | |
this._redisplay();
|
178 | |
- this.mainBox.show();
|
179 | |
+ this.mainBox.actor.show();
|
180 | |
} else {
|
181 | |
this.reloadFlag = true;
|
182 | |
}
|
183 | |
@@ -546,7 +675,8 @@ const ApplicationsButton = new Lang.Clas
|
|
162 |
+ }
|
|
163 |
+};
|
|
164 |
+
|
|
165 |
class ApplicationsMenu extends PopupMenu.PopupMenu {
|
|
166 |
constructor(sourceActor, arrowAlignment, arrowSide, button) {
|
|
167 |
super(sourceActor, arrowAlignment, arrowSide);
|
|
168 |
@@ -462,7 +589,7 @@ class ApplicationsButton extends PanelMe
|
|
169 |
_onTreeChanged() {
|
|
170 |
if (this.menu.isOpen) {
|
|
171 |
this._redisplay();
|
|
172 |
- this.mainBox.show();
|
|
173 |
+ this.mainBox.actor.show();
|
|
174 |
} else {
|
|
175 |
this.reloadFlag = true;
|
|
176 |
}
|
|
177 |
@@ -536,7 +663,8 @@ class ApplicationsButton extends PanelMe
|
184 | 178 |
this._redisplay();
|
185 | 179 |
this.reloadFlag = false;
|
186 | 180 |
}
|
|
188 | 182 |
+ //this.categoriesBox.box.width = this._menuContainerGetPreferredWidth(this.categoriesBox.box);
|
189 | 183 |
+ this.mainBox.actor.show();
|
190 | 184 |
}
|
191 | |
this.parent(menu, open);
|
192 | |
},
|
193 | |
@@ -562,11 +692,11 @@ const ApplicationsButton = new Lang.Clas
|
194 | |
|
195 | |
_redisplay: function() {
|
|
185 |
super._onOpenStateChanged(menu, open);
|
|
186 |
}
|
|
187 |
@@ -550,11 +678,11 @@ class ApplicationsButton extends PanelMe
|
|
188 |
|
|
189 |
_redisplay() {
|
196 | 190 |
this.applicationsBox.destroy_all_children();
|
197 | 191 |
- this.categoriesBox.destroy_all_children();
|
198 | 192 |
+ this.categoriesBox.box.destroy_all_children();
|
199 | 193 |
this._display();
|
200 | |
},
|
201 | |
|
202 | |
- _loadCategory: function(categoryId, dir) {
|
203 | |
+ _loadCategory: function(dir, parentCategory) {
|
|
194 |
}
|
|
195 |
|
|
196 |
- _loadCategory(categoryId, dir) {
|
|
197 |
+ _loadCategory(dir, parentCategory) {
|
204 | 198 |
let iter = dir.iter();
|
205 | 199 |
let nextType;
|
206 | 200 |
while ((nextType = iter.next()) != GMenu.TreeItemType.INVALID) {
|
207 | |
@@ -581,12 +711,24 @@ const ApplicationsButton = new Lang.Clas
|
208 | |
let app = appSys.lookup_app(id);
|
209 | |
if (!app)
|
210 | |
app = new Shell.App({ app_info: entry.get_app_info() });
|
211 | |
- if (app.get_app_info().should_show())
|
212 | |
- this.applicationsByCategory[categoryId].push(app);
|
213 | |
+ if (app.get_app_info().should_show()) {
|
214 | |
+ let menu_id = dir.get_menu_id();
|
215 | |
+ this.applicationsByCategory[menu_id].push(app);
|
216 | |
+ }
|
|
201 |
@@ -575,8 +703,18 @@ class ApplicationsButton extends PanelMe
|
|
202 |
this.applicationsByCategory[categoryId].push('separator');
|
217 | 203 |
} else if (nextType == GMenu.TreeItemType.DIRECTORY) {
|
218 | 204 |
let subdir = iter.get_directory();
|
219 | 205 |
- if (!subdir.get_is_nodisplay())
|
|
232 | 218 |
+
|
233 | 219 |
}
|
234 | 220 |
}
|
235 | |
},
|
236 | |
@@ -607,8 +749,8 @@ const ApplicationsButton = new Lang.Clas
|
237 | |
},
|
238 | |
|
239 | |
scrollToCatButton: function(button) {
|
|
221 |
}
|
|
222 |
@@ -597,8 +735,8 @@ class ApplicationsButton extends PanelMe
|
|
223 |
}
|
|
224 |
|
|
225 |
scrollToCatButton(button) {
|
240 | 226 |
- let catsScrollBoxAdj = this.categoriesScrollBox.get_vscroll_bar().get_adjustment();
|
241 | 227 |
- let catsScrollBoxAlloc = this.categoriesScrollBox.get_allocation_box();
|
242 | 228 |
+ let catsScrollBoxAdj = this.categoriesBox.actor.get_vscroll_bar().get_adjustment();
|
|
244 | 230 |
let currentScrollValue = catsScrollBoxAdj.get_value();
|
245 | 231 |
let boxHeight = catsScrollBoxAlloc.y2 - catsScrollBoxAlloc.y1;
|
246 | 232 |
let buttonAlloc = button.actor.get_allocation_box();
|
247 | |
@@ -622,10 +764,16 @@ const ApplicationsButton = new Lang.Clas
|
248 | |
},
|
249 | |
|
250 | |
_createLayout: function() {
|
|
233 |
@@ -612,10 +750,16 @@ class ApplicationsButton extends PanelMe
|
|
234 |
}
|
|
235 |
|
|
236 |
_createLayout() {
|
251 | 237 |
+ // https://mail.gnome.org/archives/gnome-shell-list/2014-January/msg00010.html
|
252 | |
+ this.menu._setOpenedSubMenu = Lang.bind(this, function(submenu) {
|
|
238 |
+ this.menu._setOpenedSubMenu = (submenu) => {
|
253 | 239 |
+ this._openedSubMenu = submenu;
|
254 | |
+ });
|
|
240 |
+ };
|
255 | 241 |
+
|
256 | 242 |
let section = new PopupMenu.PopupMenuSection();
|
257 | 243 |
this.menu.addMenuItem(section);
|
|
263 | 249 |
this.applicationsScrollBox = new St.ScrollView({ x_fill: true, y_fill: false,
|
264 | 250 |
y_align: St.Align.START,
|
265 | 251 |
style_class: 'apps-menu vfade' });
|
266 | |
@@ -637,41 +785,54 @@ const ApplicationsButton = new Lang.Clas
|
267 | |
vscroll.connect('scroll-stop', Lang.bind(this, function() {
|
|
252 |
@@ -627,44 +771,77 @@ class ApplicationsButton extends PanelMe
|
|
253 |
vscroll.connect('scroll-stop', () => {
|
268 | 254 |
this.menu.passEvents = false;
|
269 | |
}));
|
|
255 |
});
|
270 | 256 |
- this.categoriesScrollBox = new St.ScrollView({ x_fill: true, y_fill: false,
|
271 | 257 |
- y_align: St.Align.START,
|
272 | 258 |
- style_class: 'vfade' });
|
273 | 259 |
- this.categoriesScrollBox.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
|
274 | 260 |
- vscroll = this.categoriesScrollBox.get_vscroll_bar();
|
275 | |
- vscroll.connect('scroll-start', Lang.bind(this, function() {
|
276 | |
- this.menu.passEvents = true;
|
277 | |
- }));
|
278 | |
- vscroll.connect('scroll-stop', Lang.bind(this, function() {
|
279 | |
- this.menu.passEvents = false;
|
280 | |
- }));
|
|
261 |
- vscroll.connect('scroll-start', () => { this.menu.passEvents = true; });
|
|
262 |
- vscroll.connect('scroll-stop', () => { this.menu.passEvents = false; });
|
281 | 263 |
- this.leftBox.add(this.categoriesScrollBox, { expand: true,
|
282 | 264 |
- x_fill: true, y_fill: true,
|
283 | 265 |
- y_align: St.Align.START });
|
|
266 |
+// this.categoriesScrollBox = new St.ScrollView({ x_fill: true, y_fill: false,
|
|
267 |
+// y_align: St.Align.START,
|
|
268 |
+ // style_class: 'vfade' });
|
|
269 |
+// this.categoriesScrollBox.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
|
|
270 |
+// vscroll = this.categoriesScrollBox.get_vscroll_bar();
|
|
271 |
+// vscroll.connect('scroll-start', () => { this.menu.passEvents = true; });
|
|
272 |
+// vscroll.connect('scroll-stop', () => { this.menu.passEvents = false; });
|
|
273 |
+// this.leftBox.add(this.categoriesScrollBox, { expand: true,
|
|
274 |
+// x_fill: true, y_fill: true,
|
|
275 |
+// y_align: St.Align.START });
|
284 | 276 |
|
285 | 277 |
let activities = new ActivitiesMenuItem(this);
|
286 | 278 |
- this.leftBox.add(activities.actor, { expand: false,
|
287 | 279 |
- x_fill: true, y_fill: false,
|
288 | 280 |
- y_align: St.Align.START });
|
|
281 |
+// this.leftBox.add(activities.actor, { expand: false,
|
|
282 |
+// x_fill: true, y_fill: false,
|
|
283 |
+// y_align: St.Align.START });
|
289 | 284 |
|
290 | 285 |
this.applicationsBox = new St.BoxLayout({ vertical: true });
|
291 | 286 |
this.applicationsScrollBox.add_actor(this.applicationsBox);
|
292 | 287 |
- this.categoriesBox = new St.BoxLayout({ vertical: true });
|
293 | 288 |
- this.categoriesScrollBox.add_actor(this.categoriesBox);
|
294 | |
-
|
|
289 |
+// this.categoriesBox = new St.BoxLayout({ vertical: true });
|
|
290 |
+// this.categoriesScrollBox.add_actor(this.categoriesBox);
|
|
291 |
|
295 | 292 |
- this.mainBox.add(this.leftBox);
|
296 | 293 |
- this.mainBox.add(this._createVertSeparator(), { expand: false, x_fill: false, y_fill: true});
|
297 | 294 |
- this.mainBox.add(this.applicationsScrollBox, { expand: true, x_fill: true, y_fill: true });
|
298 | 295 |
- section.actor.add_actor(this.mainBox);
|
|
296 |
+// this.mainBox.add(this.leftBox);
|
|
297 |
+// this.mainBox.add(this._createVertSeparator(), { expand: false, x_fill: false, y_fill: true});
|
|
298 |
+// this.mainBox.add(this.applicationsScrollBox, { expand: true, x_fill: true, y_fill: true });
|
|
299 |
+// section.actor.add_actor(this.mainBox);
|
299 | 300 |
+ this.categoriesBox = new PopupMenuScrollView();
|
300 | 301 |
+ vscroll = this.categoriesBox.actor.get_vscroll_bar();
|
301 | |
+ vscroll.connect('scroll-start', Lang.bind(this, function() {
|
302 | |
+ this.menu.passEvents = true;
|
303 | |
+ }));
|
304 | |
+ vscroll.connect('scroll-stop', Lang.bind(this, function() {
|
305 | |
+ this.menu.passEvents = false;
|
306 | |
+ }));
|
|
302 |
+ vscroll.connect('scroll-start', () => { this.menu.passEvents = true; });
|
|
303 |
+ vscroll.connect('scroll-stop', () => { this.menu.passEvents = false; });
|
307 | 304 |
+ this.leftBox.addMenuItem(this.categoriesBox);
|
308 | 305 |
+ // FIXME we re-add it to apply the right properties, but re-adding
|
309 | 306 |
+ // it causes a warning
|
|
320 | 317 |
+ this.mainBox.actor.add(this.applicationsScrollBox, { expand: true,
|
321 | 318 |
+ x_fill: true, y_fill: true });
|
322 | 319 |
+ section.addMenuItem(this.mainBox);
|
323 | |
+ },
|
324 | |
+
|
325 | |
+ _menuContainerGetPreferredWidth: function(container) {
|
|
320 |
+ }
|
|
321 |
+
|
|
322 |
+ _menuContainerGetPreferredWidth(container) {
|
326 | 323 |
+ let max_width = 0;
|
327 | 324 |
+ for (let child = container.get_first_child();
|
328 | 325 |
+ child;
|
|
333 | 330 |
+ max_width = Math.max(max_width, child.width);
|
334 | 331 |
+ }
|
335 | 332 |
+ return max_width;
|
336 | |
},
|
337 | |
|
338 | |
_display: function() {
|
|
333 |
}
|
|
334 |
|
|
335 |
_display() {
|
339 | 336 |
this._applicationsButtons.clear();
|
340 | 337 |
- this.mainBox.style=('width: 35em;');
|
341 | 338 |
- this.mainBox.hide();
|
|
344 | 341 |
|
345 | 342 |
//Load categories
|
346 | 343 |
this.applicationsByCategory = {};
|
347 | |
@@ -679,7 +840,7 @@ const ApplicationsButton = new Lang.Clas
|
348 | |
tree.load_sync();
|
349 | |
let root = tree.get_root_directory();
|
|
344 |
this._tree.load_sync();
|
|
345 |
let root = this._tree.get_root_directory();
|
350 | 346 |
let categoryMenuItem = new CategoryMenuItem(this, null);
|
351 | 347 |
- this.categoriesBox.add_actor(categoryMenuItem.actor);
|
352 | 348 |
+ this.categoriesBox.addMenuItem(categoryMenuItem);
|
353 | 349 |
let iter = root.iter();
|
354 | 350 |
let nextType;
|
355 | 351 |
while ((nextType = iter.next()) != GMenu.TreeItemType.INVALID) {
|
356 | |
@@ -688,10 +849,12 @@ const ApplicationsButton = new Lang.Clas
|
|
352 |
@@ -673,10 +850,12 @@ class ApplicationsButton extends PanelMe
|
357 | 353 |
if (!dir.get_is_nodisplay()) {
|
358 | 354 |
let categoryId = dir.get_menu_id();
|
359 | 355 |
this.applicationsByCategory[categoryId] = [];
|
|
370 | 366 |
}
|
371 | 367 |
}
|
372 | 368 |
}
|
373 | |
@@ -700,8 +863,9 @@ const ApplicationsButton = new Lang.Clas
|
|
369 |
@@ -685,8 +864,9 @@ class ApplicationsButton extends PanelMe
|
374 | 370 |
//Load applications
|
375 | 371 |
this._displayButtons(this._listApplications(null));
|
376 | 372 |
|
|
379 | 375 |
+ let height = this.categoriesBox.actor.height + MENU_HEIGHT_OFFSET + 'px';
|
380 | 376 |
+ this.mainBox.actor.style+=('height: ' + height);
|
381 | 377 |
+ this.categoriesBox.box.width = 300;
|
382 | |
},
|
383 | |
|
384 | |
_clearApplicationsBox: function(selectedActor) {
|
|
378 |
}
|
|
379 |
|
|
380 |
selectCategory(dir, categoryMenuItem) {
|