From b551ccd7cd56654d7f41baecff3e914fdd7ddb78 Mon Sep 17 00:00:00 2001 From: Michael Webster Date: Mon, 2 Jan 2017 10:16:11 -0500 Subject: [PATCH] recent applet: Rework to be non-destructive when updating the recent list (this brings a lot of the recent changes to the menu applet over to this one.) --- .../applets/recent@cinnamon.org/applet.js | 190 +++++++++++++----- 1 file changed, 143 insertions(+), 47 deletions(-) diff --git a/files/usr/share/cinnamon/applets/recent@cinnamon.org/applet.js b/files/usr/share/cinnamon/applets/recent@cinnamon.org/applet.js index 720ab9a610..02d2ff5b15 100644 --- a/files/usr/share/cinnamon/applets/recent@cinnamon.org/applet.js +++ b/files/usr/share/cinnamon/applets/recent@cinnamon.org/applet.js @@ -17,12 +17,17 @@ function MyPopupMenuItem() MyPopupMenuItem.prototype = { __proto__: PopupMenu.PopupBaseMenuItem.prototype, - _init: function(icon, text, params) - { + + _init: function(icon, text, uri, params) { PopupMenu.PopupBaseMenuItem.prototype._init.call(this, params); this.box = new St.BoxLayout({ style_class: 'popup-combobox-item' }); this.icon = icon; - this.box.add(this.icon); + this.uri = uri; + + if (this.icon) { + this.box.add(this.icon); + } + this.label = new St.Label({ text: text }); this.box.add(this.label); this.addActor(this.box); @@ -45,81 +50,172 @@ MyApplet.prototype = { this.menuManager = new PopupMenu.PopupMenuManager(this); this.menu = new Applet.AppletPopupMenu(this, orientation); - this.menuManager.addMenu(this.menu); - + this.menuManager.addMenu(this.menu); + + this.recentsScrollBox = new St.ScrollView({ x_fill: true, y_fill: false, y_align: St.Align.START }); + this.recentsScrollBox.set_auto_scrolling(true); + + this.recentsBox = new St.BoxLayout({ vertical:true }); + this.recentsScrollBox.add_actor(this.recentsBox); + this.recentsScrollBox.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC); + this.menu.actor.add_actor(this.recentsScrollBox); + this.menu.actor.height = 400 / global.ui_scale; + this.RecentManager = new DocInfo.DocManager(); this.privacy_settings = new Gio.Settings( {schema_id: PRIVACY_SCHEMA} ); + this._recentButtons = []; this._display(); - this.RecentManager.connect('changed', Lang.bind(this, this._redisplay)); - this.privacy_settings.connect("changed::" + REMEMBER_RECENT_KEY, Lang.bind(this, this._redisplay)); + this.RecentManager.connect('changed', Lang.bind(this, this._refreshRecents)); + this.privacy_settings.connect("changed::" + REMEMBER_RECENT_KEY, Lang.bind(this, this._refreshRecents)); } catch (e) { global.logError(e); } }, - + on_applet_clicked: function(event) { - this.menu.toggle(); + this.menu.toggle(); }, - + _display: function() { - if (!this.privacy_settings.get_boolean(REMEMBER_RECENT_KEY)) { - let item = new PopupMenu.PopupMenuItem(_("Recent file tracking is currently disabled.")); - item.actor.reactive = false; - this.menu.addMenuItem(item); - - let icon = new St.Icon({ icon_name: 'ok', icon_type: St.IconType.FULLCOLOR, icon_size: 16 }); - item = new MyPopupMenuItem(icon, _("Click here to enable it"), {}); - item.connect("activate", Lang.bind(this, function () { - this.privacy_settings.set_boolean(REMEMBER_RECENT_KEY, true); - })) - this.menu.addMenuItem(item); - - return; - } - for (let id = 0; id < 15 && id < this.RecentManager._infosByTimestamp.length; id++) { - let icon = this.RecentManager._infosByTimestamp[id].createIcon(22); - let menuItem = new MyPopupMenuItem(icon, this.RecentManager._infosByTimestamp[id].name, {}); - this.menu.addMenuItem(menuItem); - menuItem.connect('activate', Lang.bind(this, this._launchFile, this.RecentManager._infosByTimestamp[id])); - } - if (this.RecentManager._infosByTimestamp.length > 0) { - this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem()); - let icon = new St.Icon({ icon_name: 'edit-clear', icon_type: St.IconType.SYMBOLIC, icon_size: 22 }); - let menuItem = new MyPopupMenuItem(icon, _("Clear list"), {}); - this.menu.addMenuItem(menuItem); - menuItem.connect('activate', Lang.bind(this, this._clearAll)); - } else { - this.menu.addMenuItem(new PopupMenu.PopupMenuItem(_("No recent documents"))); - } - }, - - _redisplay: function() { - this.menu.removeAll(); - this._display(); + this._refreshRecents(); }, _launchFile: function(a, b, c, docinfo) { docinfo.launch(); }, - + _clearAll: function() { let GtkRecent = new Gtk.RecentManager(); GtkRecent.purge_items(); }, - + destroy: function() { this.RecentManager.disconnectAll(); this.actor._delegate = null; this.menu.destroy(); this.actor.destroy(); + this._recentButtons = null; this.emit('destroy'); + }, + + _refreshRecents: function() { + if (this.privacy_settings.get_boolean(REMEMBER_RECENT_KEY)) { + let new_recents = []; + let have_recents = false; + + if (this.RecentManager._infosByTimestamp.length > 0) { + let id = 0; + while (id < this.RecentManager._infosByTimestamp.length) { + let uri = this.RecentManager._infosByTimestamp[id].uri; + + let new_button = null; + + new_button = this._recentButtons.find(button => ((button.uri) && (button.uri == uri))); + + if (new_button == undefined) { + let icon = this.RecentManager._infosByTimestamp[id].createIcon(22); + let menuItem = new MyPopupMenuItem(icon, this.RecentManager._infosByTimestamp[id].name, uri, {}); + this.menu.addMenuItem(menuItem); + menuItem.connect('activate', Lang.bind(this, this._launchFile, this.RecentManager._infosByTimestamp[id])); + new_button = menuItem; + } + + new_recents.push(new_button); + + id++; + } + + let recent_clear_button = null; + + recent_clear_button = this._recentButtons.find(button => ((button.uri) && (button.uri == "clear"))); + + if (recent_clear_button == undefined) { + let icon = new St.Icon({ icon_name: 'edit-clear', icon_type: St.IconType.SYMBOLIC, icon_size: 22 }); + let menuItem = new MyPopupMenuItem(icon, _("Clear list"), "clear", {}); + menuItem.connect('activate', Lang.bind(this, this._clearAll)); + + recent_clear_button = menuItem; + } + + have_recents = true; + new_recents.push(recent_clear_button); + } else { + let no_recents_button = null; + + no_recents_button = this._recentButtons.find(button => ((button.uri) && (button.uri == "no-recents"))); + + if (no_recents_button == undefined) { + let menuItem = new MyPopupMenuItem(null, _("No recent documents"), "no-recents", {}); + + no_recents_button = menuItem; + } + + new_recents.push(no_recents_button); + } + + let to_remove = []; + + /* Remove no-longer-valid items */ + for (let i = 0; i < this._recentButtons.length; i++) { + let button = this._recentButtons[i]; + + if (button.uri == "no-recents" && have_recents) { + to_remove.push(button); + } else { + if (new_recents.indexOf(button) == -1) { + to_remove.push(button); + } + } + } + + if (to_remove.length > 0) { + for (let i in to_remove) { + to_remove[i].destroy(); + this._recentButtons.splice(this._recentButtons.indexOf(to_remove[i]), 1); + } + } + + to_remove = []; + + /* Now, add new actors, shuffle existing actors */ + + let placeholder = this.recentsBox.get_first_child(); + + for (let i = 0; i < new_recents.length; i++) { + let actor = new_recents[i].actor; + + let parent = actor.get_parent(); + if (parent != null) { + parent.remove_child(actor); + } + + if (actor != placeholder) { + this.recentsBox.insert_child_above(actor, placeholder); + } else { + this.recentsBox.add_child(actor); + } + + placeholder = actor; + } + + this._recentButtons = new_recents; + + this.actor.show(); + } else { + for (let i = 0; i < this._recentButtons.length; i ++) { + this._recentButtons[i].destroy(); + } + + this._recentButtons = []; + this.actor.hide(); + } } }; function main(metadata, orientation, panel_height, instance_id) { let myApplet = new MyApplet(orientation, panel_height, instance_id); - return myApplet; + return myApplet; }