Replace Dash application display with AppWell
The new class AppWell implements the application favorite well in the Dash component. The previous AppDisplay remains for use in the More... mode now. Delete DEFAULT_APPLICATIONS; this is now in GConf. Rename getMostUsedApps to getTopApps since we now have the idea of explicit favorites. Delete some GenericDisplay-related calls from overlay related to the seletion - we'll reimplement keyboard nav in a more coherent way later.
This commit is contained in:
parent
88c9a23866
commit
12f78a08cd
@ -7,32 +7,6 @@ const Shell = imports.gi.Shell;
|
||||
|
||||
const Main = imports.ui.main;
|
||||
|
||||
// TODO - move this into GConf once we're not a plugin anymore
|
||||
// but have taken over metacity
|
||||
// This list is taken from GNOME Online popular applications
|
||||
// http://online.gnome.org/applications
|
||||
// but with nautilus removed (since it should already be running)
|
||||
// and evince, totem, and gnome-file-roller removed (since they're
|
||||
// usually started by opening documents, not by opening the app
|
||||
// directly)
|
||||
const DEFAULT_APPLICATIONS = [
|
||||
'mozilla-firefox.desktop',
|
||||
'gnome-terminal.desktop',
|
||||
'evolution.desktop',
|
||||
'gedit.desktop',
|
||||
'mozilla-thunderbird.desktop',
|
||||
'rhythmbox.desktop',
|
||||
'epiphany.desktop',
|
||||
'xchat.desktop',
|
||||
'openoffice.org-1.9-writer.desktop',
|
||||
'emacs.desktop',
|
||||
'gnome-system-monitor.desktop',
|
||||
'openoffice.org-1.9-calc.desktop',
|
||||
'eclipse.desktop',
|
||||
'openoffice.org-1.9-impress.desktop',
|
||||
'vncviewer.desktop'
|
||||
];
|
||||
|
||||
function AppInfo(appId) {
|
||||
this._init(appId);
|
||||
}
|
||||
@ -41,8 +15,9 @@ AppInfo.prototype = {
|
||||
_init : function(appId) {
|
||||
this.appId = appId;
|
||||
this._gAppInfo = Gio.DesktopAppInfo.new(appId);
|
||||
if (!this._gAppInfo)
|
||||
if (!this._gAppInfo) {
|
||||
throw new Error('Unknown appId ' + appId);
|
||||
}
|
||||
|
||||
this.id = this._gAppInfo.get_id();
|
||||
this.name = this._gAppInfo.get_name();
|
||||
@ -96,40 +71,64 @@ function getAppInfo(appId) {
|
||||
return info;
|
||||
}
|
||||
|
||||
// getMostUsedApps:
|
||||
// getTopApps:
|
||||
// @count: maximum number of apps to retrieve
|
||||
//
|
||||
// Gets a list of #AppInfos for the @count most-frequently-used
|
||||
// applications
|
||||
// applications, with explicitly-chosen favorites first.
|
||||
//
|
||||
// Return value: the list of #AppInfo
|
||||
function getMostUsedApps(count) {
|
||||
function getTopApps(count) {
|
||||
let appMonitor = Shell.AppMonitor.get_default();
|
||||
|
||||
let matches = [], alreadyAdded = {};
|
||||
|
||||
let favs = getFavorites();
|
||||
for (let i = 0; i < favs.length && favs.length <= count; i++) {
|
||||
let appId = favs[i].appId;
|
||||
|
||||
if (alreadyAdded[appId])
|
||||
continue;
|
||||
alreadyAdded[appId] = true;
|
||||
|
||||
matches.push(favs[i]);
|
||||
}
|
||||
|
||||
// Ask for more apps than we need, since the list of recently used
|
||||
// apps might contain an app we don't have a desktop file for
|
||||
let apps = appMonitor.get_most_used_apps (0, Math.round(count * 1.5));
|
||||
let matches = [], alreadyAdded = {};
|
||||
|
||||
for (let i = 0; i < apps.length && matches.length <= count; i++) {
|
||||
let appId = apps[i] + ".desktop";
|
||||
if (alreadyAdded[appId])
|
||||
continue;
|
||||
alreadyAdded[appId] = true;
|
||||
let appInfo = getAppInfo(appId);
|
||||
if (appInfo) {
|
||||
matches.push(appInfo);
|
||||
alreadyAdded[appId] = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Fill the list with default applications it's not full yet
|
||||
for (let i = 0; i < DEFAULT_APPLICATIONS.length && matches.length <= count; i++) {
|
||||
let appId = DEFAULT_APPLICATIONS[i];
|
||||
if (alreadyAdded[appId])
|
||||
continue;
|
||||
|
||||
let appInfo = getAppInfo(appId);
|
||||
if (appInfo)
|
||||
matches.push(appInfo);
|
||||
}
|
||||
|
||||
return matches;
|
||||
}
|
||||
|
||||
function _idListToInfos(ids) {
|
||||
let infos = [];
|
||||
for (let i = 0; i < ids.length; i++) {
|
||||
let display = getAppInfo(ids[i]);
|
||||
if (display == null)
|
||||
continue;
|
||||
infos.push(display);
|
||||
}
|
||||
return infos;
|
||||
}
|
||||
|
||||
function getFavorites() {
|
||||
let system = Shell.AppSystem.get_default();
|
||||
|
||||
return _idListToInfos(system.get_favorites());
|
||||
}
|
||||
|
||||
function getRunning() {
|
||||
let monitor = Shell.AppMonitor.get_default();
|
||||
return _idListToInfos(monitor.get_running_app_ids());
|
||||
}
|
||||
|
@ -5,16 +5,21 @@ const Clutter = imports.gi.Clutter;
|
||||
const Pango = imports.gi.Pango;
|
||||
const Gio = imports.gi.Gio;
|
||||
const Gtk = imports.gi.Gtk;
|
||||
const Tidy = imports.gi.Tidy;
|
||||
const Shell = imports.gi.Shell;
|
||||
const Lang = imports.lang;
|
||||
const Signals = imports.signals;
|
||||
const Mainloop = imports.mainloop;
|
||||
|
||||
const AppInfo = imports.misc.appInfo;
|
||||
const DND = imports.ui.dnd;
|
||||
const GenericDisplay = imports.ui.genericDisplay;
|
||||
|
||||
const ENTERED_MENU_COLOR = new Clutter.Color();
|
||||
ENTERED_MENU_COLOR.from_pixel(0x00ff0022);
|
||||
|
||||
const APP_ICON_SIZE = 48;
|
||||
|
||||
const MENU_ICON_SIZE = 24;
|
||||
const MENU_SPACING = 15;
|
||||
|
||||
@ -147,6 +152,7 @@ MenuItem.prototype = {
|
||||
}
|
||||
Signals.addSignalMethods(MenuItem.prototype);
|
||||
|
||||
|
||||
/* This class represents a display containing a collection of application items.
|
||||
* The applications are sorted based on their popularity by default, and based on
|
||||
* their name if some search filter is applied.
|
||||
@ -173,16 +179,15 @@ AppDisplay.prototype = {
|
||||
this._appMonitor = Shell.AppMonitor.get_default();
|
||||
this._appSystem = Shell.AppSystem.get_default();
|
||||
this._appsStale = true;
|
||||
this._appSystem.connect('changed', Lang.bind(this, function(appSys) {
|
||||
this._appSystem.connect('installed-changed', Lang.bind(this, function(appSys) {
|
||||
this._appsStale = true;
|
||||
// We still need to determine what events other than search can trigger
|
||||
// a change in the set of applications that are being shown while the
|
||||
// user in in the overlay mode, however let's redisplay just in case.
|
||||
this._redisplay(false);
|
||||
this._redisplayMenus();
|
||||
}));
|
||||
this._appSystem.connect('favorites-changed', Lang.bind(this, function(appSys) {
|
||||
this._redisplay(false);
|
||||
}));
|
||||
this._appMonitor.connect('changed', Lang.bind(this, function(monitor) {
|
||||
this._appsStale = true;
|
||||
this._redisplay(false);
|
||||
}));
|
||||
|
||||
@ -353,7 +358,7 @@ AppDisplay.prototype = {
|
||||
|
||||
// Sets the list of the displayed items based on the most used apps.
|
||||
_setDefaultList : function() {
|
||||
let matchedInfos = AppInfo.getMostUsedApps(MAX_ITEMS);
|
||||
let matchedInfos = AppInfo.getTopApps(MAX_ITEMS);
|
||||
this._matchedItems = matchedInfos.map(function(info) { return info.appId; });
|
||||
},
|
||||
|
||||
@ -430,3 +435,197 @@ AppDisplay.prototype = {
|
||||
};
|
||||
|
||||
Signals.addSignalMethods(AppDisplay.prototype);
|
||||
|
||||
function WellDisplayItem(appInfo, isFavorite) {
|
||||
this._init(appInfo, isFavorite);
|
||||
}
|
||||
|
||||
WellDisplayItem.prototype = {
|
||||
_init : function(appInfo, isFavorite) {
|
||||
this.appInfo = appInfo;
|
||||
|
||||
this.isFavorite = isFavorite;
|
||||
|
||||
this.actor = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
|
||||
width: APP_ICON_SIZE,
|
||||
reactive: true });
|
||||
this.actor._delegate = this;
|
||||
this.actor.connect('button-release-event', Lang.bind(this, function (b, e) {
|
||||
this.launch();
|
||||
this.emit('activated');
|
||||
}));
|
||||
|
||||
let draggable = DND.makeDraggable(this.actor);
|
||||
|
||||
this._icon = appInfo.createIcon(APP_ICON_SIZE);
|
||||
|
||||
this.actor.append(this._icon, Big.BoxPackFlags.NONE);
|
||||
|
||||
let count = Shell.AppMonitor.get_default().get_window_count(appInfo.appId);
|
||||
|
||||
this._name = new Clutter.Text({ color: GenericDisplay.ITEM_DISPLAY_NAME_COLOR,
|
||||
font_name: "Sans 12px",
|
||||
ellipsize: Pango.EllipsizeMode.END,
|
||||
text: appInfo.name });
|
||||
if (count > 0) {
|
||||
let runningBox = new Big.Box({ /* border_color: GenericDisplay.ITEM_DISPLAY_NAME_COLOR,
|
||||
border: 1,
|
||||
padding: 1 */ });
|
||||
runningBox.append(this._name, Big.BoxPackFlags.EXPAND);
|
||||
this.actor.append(runningBox, Big.BoxPackFlags.NONE);
|
||||
} else {
|
||||
this.actor.append(this._name, Big.BoxPackFlags.NONE);
|
||||
}
|
||||
},
|
||||
|
||||
// Opens an application represented by this display item.
|
||||
launch : function() {
|
||||
this.appInfo.launch();
|
||||
},
|
||||
|
||||
// Draggable interface - FIXME deduplicate with GenericDisplay
|
||||
getDragActor: function(stageX, stageY) {
|
||||
this.dragActor = this.appInfo.createIcon(APP_ICON_SIZE);
|
||||
|
||||
// If the user dragged from the icon itself, then position
|
||||
// the dragActor over the original icon. Otherwise center it
|
||||
// around the pointer
|
||||
let [iconX, iconY] = this._icon.get_transformed_position();
|
||||
let [iconWidth, iconHeight] = this._icon.get_transformed_size();
|
||||
if (stageX > iconX && stageX <= iconX + iconWidth &&
|
||||
stageY > iconY && stageY <= iconY + iconHeight)
|
||||
this.dragActor.set_position(iconX, iconY);
|
||||
else
|
||||
this.dragActor.set_position(stageX - this.dragActor.width / 2, stageY - this.dragActor.height / 2);
|
||||
return this.dragActor;
|
||||
},
|
||||
|
||||
// Returns the original icon that is being used as a source for the cloned texture
|
||||
// that represents the item as it is being dragged.
|
||||
getDragActorSource: function() {
|
||||
return this._icon;
|
||||
}
|
||||
};
|
||||
|
||||
Signals.addSignalMethods(WellDisplayItem.prototype);
|
||||
|
||||
function WellArea(width, isFavorite) {
|
||||
this._init(width, isFavorite);
|
||||
}
|
||||
|
||||
WellArea.prototype = {
|
||||
_init : function(width, isFavorite) {
|
||||
this.isFavorite = isFavorite;
|
||||
|
||||
this.actor = new Tidy.Grid({ width: width });
|
||||
this.actor._delegate = this;
|
||||
},
|
||||
|
||||
redisplay: function (infos) {
|
||||
let children;
|
||||
|
||||
children = this.actor.get_children();
|
||||
children.forEach(Lang.bind(this, function (v) {
|
||||
v.destroy();
|
||||
}));
|
||||
|
||||
for (let i = 0; i < infos.length; i++) {
|
||||
let display = new WellDisplayItem(infos[i], this.isFavorite);
|
||||
display.connect('activated', Lang.bind(this, function (display) {
|
||||
this.emit('activated', display);
|
||||
}));
|
||||
this.actor.add_actor(display.actor);
|
||||
};
|
||||
},
|
||||
|
||||
// Draggable target interface
|
||||
acceptDrop : function(source, actor, x, y, time) {
|
||||
let global = Shell.Global.get();
|
||||
|
||||
if (!(source instanceof WellDisplayItem)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let appSystem = Shell.AppSystem.get_default();
|
||||
let id = source.appInfo.appId;
|
||||
if (source.isFavorite && (!this.isFavorite)) {
|
||||
Mainloop.idle_add(function () {
|
||||
appSystem.remove_favorite(id);
|
||||
});
|
||||
} else if ((!source.isFavorite) && this.isFavorite) {
|
||||
Mainloop.idle_add(function () {
|
||||
appSystem.add_favorite(id);
|
||||
});
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Signals.addSignalMethods(WellArea.prototype);
|
||||
|
||||
function AppWell(width) {
|
||||
this._init(width);
|
||||
}
|
||||
|
||||
AppWell.prototype = {
|
||||
_init : function(width) {
|
||||
this._menus = [];
|
||||
this._menuDisplays = [];
|
||||
|
||||
this.actor = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
|
||||
width: width });
|
||||
|
||||
this._appSystem = Shell.AppSystem.get_default();
|
||||
this._appMonitor = Shell.AppMonitor.get_default();
|
||||
|
||||
this._appSystem.connect('installed-changed', Lang.bind(this, function(appSys) {
|
||||
this._redisplay();
|
||||
}));
|
||||
this._appSystem.connect('favorites-changed', Lang.bind(this, function(appSys) {
|
||||
this._redisplay();
|
||||
}));
|
||||
this._appMonitor.connect('changed', Lang.bind(this, function(monitor) {
|
||||
this._redisplay();
|
||||
}));
|
||||
|
||||
this._favoritesArea = new WellArea(width, true);
|
||||
this._favoritesArea.connect('activated', Lang.bind(this, function (a, display) {
|
||||
this.emit('activated');
|
||||
}));
|
||||
this.actor.append(this._favoritesArea.actor, Big.BoxPackFlags.NONE);
|
||||
|
||||
this._runningBox = new Big.Box({ border_color: GenericDisplay.ITEM_DISPLAY_NAME_COLOR,
|
||||
border: 1,
|
||||
corner_radius: 3,
|
||||
padding: GenericDisplay.PREVIEW_BOX_PADDING });
|
||||
this._runningArea = new WellArea(width, false);
|
||||
this._runningArea.connect('activated', Lang.bind(this, function (a, display) {
|
||||
this.emit('activated');
|
||||
}));
|
||||
this._runningBox.append(this._runningArea.actor, Big.BoxPackFlags.EXPAND);
|
||||
this.actor.append(this._runningBox, Big.BoxPackFlags.NONE);
|
||||
|
||||
this._redisplay();
|
||||
},
|
||||
|
||||
_redisplay: function() {
|
||||
let arrayToObject = function(a) {
|
||||
let o = {};
|
||||
for (let i = 0; i < a.length; i++)
|
||||
o[a[i]] = 1;
|
||||
return o;
|
||||
};
|
||||
let favorites = AppInfo.getFavorites();
|
||||
let favoriteIds = arrayToObject(favorites.map(function (e) { return e.appId; }));
|
||||
let running = AppInfo.getRunning().filter(function (e) {
|
||||
return !(e.appId in favoriteIds);
|
||||
});
|
||||
this._favoritesArea.redisplay(favorites);
|
||||
this._runningArea.redisplay(running);
|
||||
}
|
||||
};
|
||||
|
||||
Signals.addSignalMethods(AppWell.prototype);
|
||||
|
@ -283,7 +283,6 @@ Dash.prototype = {
|
||||
this._searchEntry.entry.connect('activate', function (se) {
|
||||
// only one of the displays will have an item selected, so it's ok to
|
||||
// call activateSelected() on all of them
|
||||
me._appDisplay.activateSelected();
|
||||
me._docDisplay.activateSelected();
|
||||
me._resultsAppsSection.display.activateSelected();
|
||||
me._resultsDocsSection.display.activateSelected();
|
||||
@ -329,11 +328,9 @@ Dash.prototype = {
|
||||
|
||||
this._appsContent = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL });
|
||||
this._appsSection.append(this._appsContent, Big.BoxPackFlags.EXPAND);
|
||||
this._appDisplay = new AppDisplay.AppDisplay(this._displayWidth, this._itemDisplayHeight / 2, DASH_COLUMNS, DASH_SECTION_PADDING);
|
||||
let sideArea = this._appDisplay.getSideArea();
|
||||
sideArea.hide();
|
||||
this._appsContent.append(sideArea, Big.BoxPackFlags.NONE);
|
||||
this._appsContent.append(this._appDisplay.actor, Big.BoxPackFlags.EXPAND);
|
||||
this._appWell = new AppDisplay.AppWell(this._displayWidth);
|
||||
this._appWell.actor.show();
|
||||
this._appsContent.append(this._appWell.actor, Big.BoxPackFlags.EXPAND);
|
||||
|
||||
let moreAppsBox = new Big.Box({x_align: Big.BoxAlignment.END});
|
||||
this._moreAppsLink = new Link.Link({ color: DASH_TEXT_COLOR,
|
||||
@ -444,13 +441,12 @@ Dash.prototype = {
|
||||
let itemDetailsAvailableWidth = this._detailsWidth - DASH_SECTION_PADDING * 2 - DASH_BORDER_WIDTH * 2;
|
||||
let itemDetailsAvailableHeight = detailsHeight - DASH_SECTION_PADDING * 2 - DASH_BORDER_WIDTH * 2;
|
||||
|
||||
this._appDisplay.setAvailableDimensionsForItemDetails(itemDetailsAvailableWidth, itemDetailsAvailableHeight);
|
||||
this._docDisplay.setAvailableDimensionsForItemDetails(itemDetailsAvailableWidth, itemDetailsAvailableHeight);
|
||||
this._resultsAppsSection.display.setAvailableDimensionsForItemDetails(itemDetailsAvailableWidth, itemDetailsAvailableHeight);
|
||||
this._resultsDocsSection.display.setAvailableDimensionsForItemDetails(itemDetailsAvailableWidth, itemDetailsAvailableHeight);
|
||||
|
||||
/* Proxy the activated signals */
|
||||
this._appDisplay.connect('activated', function(appDisplay) {
|
||||
this._appWell.connect('activated', function(well) {
|
||||
me.emit('activated');
|
||||
});
|
||||
this._docDisplay.connect('activated', function(docDisplay) {
|
||||
@ -462,27 +458,7 @@ Dash.prototype = {
|
||||
this._resultsDocsSection.display.connect('activated', function(resultsDocsDisplay) {
|
||||
me.emit('activated');
|
||||
});
|
||||
this._appDisplay.connect('selected', function(appDisplay) {
|
||||
// We allow clicking on any item to select it, so if an
|
||||
// item in the app display is selected, we need to make sure that
|
||||
// no item in the doc display has the selection.
|
||||
me._docDisplay.unsetSelected();
|
||||
me._resultsDocsSection.display.unsetSelected();
|
||||
me._resultsAppsSection.display.unsetSelected();
|
||||
if (me._firstSelectAfterOverlayShow) {
|
||||
me._firstSelectAfterOverlayShow = false;
|
||||
} else if (!me._detailsShowing()) {
|
||||
me._detailsPane.show();
|
||||
me.emit('panes-displayed');
|
||||
}
|
||||
me._detailsContent.remove_all();
|
||||
me._detailsContent.append(me._appDisplay.selectedItemDetails, Big.BoxPackFlags.NONE);
|
||||
});
|
||||
this._docDisplay.connect('selected', function(docDisplay) {
|
||||
// We allow clicking on any item to select it, so if an
|
||||
// item in the doc display is selected, we need to make sure that
|
||||
// no item in the app display has the selection.
|
||||
me._appDisplay.unsetSelected();
|
||||
me._resultsDocsSection.display.unsetSelected();
|
||||
me._resultsAppsSection.display.unsetSelected();
|
||||
if (!me._detailsShowing()) {
|
||||
@ -493,7 +469,6 @@ Dash.prototype = {
|
||||
me._detailsContent.append(me._docDisplay.selectedItemDetails, Big.BoxPackFlags.NONE);
|
||||
});
|
||||
this._resultsDocsSection.display.connect('selected', function(resultsDocDisplay) {
|
||||
me._appDisplay.unsetSelected();
|
||||
me._docDisplay.unsetSelected();
|
||||
me._resultsAppsSection.display.unsetSelected();
|
||||
if (!me._detailsShowing()) {
|
||||
@ -504,7 +479,6 @@ Dash.prototype = {
|
||||
me._detailsContent.append(me._resultsDocsSection.display.selectedItemDetails, Big.BoxPackFlags.NONE);
|
||||
});
|
||||
this._resultsAppsSection.display.connect('selected', function(resultsAppDisplay) {
|
||||
me._appDisplay.unsetSelected();
|
||||
me._docDisplay.unsetSelected();
|
||||
me._resultsDocsSection.display.unsetSelected();
|
||||
if (!me._detailsShowing()) {
|
||||
@ -514,12 +488,6 @@ Dash.prototype = {
|
||||
me._detailsContent.remove_all();
|
||||
me._detailsContent.append(me._resultsAppsSection.display.selectedItemDetails, Big.BoxPackFlags.NONE);
|
||||
});
|
||||
this._appDisplay.connect('redisplayed', function(appDisplay) {
|
||||
me._ensureItemSelected();
|
||||
});
|
||||
this._docDisplay.connect('redisplayed', function(docDisplay) {
|
||||
me._ensureItemSelected();
|
||||
});
|
||||
|
||||
this._moreAppsLink.connect('clicked',
|
||||
function(o, event) {
|
||||
@ -543,7 +511,6 @@ Dash.prototype = {
|
||||
show: function() {
|
||||
let global = Shell.Global.get();
|
||||
|
||||
this._appDisplay.show();
|
||||
this._appsContent.show();
|
||||
this._docDisplay.show();
|
||||
global.stage.set_key_focus(this._searchEntry.entry);
|
||||
@ -567,22 +534,6 @@ Dash.prototype = {
|
||||
this._unsetSearchMode();
|
||||
},
|
||||
|
||||
// Ensures that one of the displays has the selection if neither owns it after the
|
||||
// latest redisplay. This can be applicable if the display that earlier had the
|
||||
// selection no longer has any items, or if their is a single section being shown
|
||||
// in the expanded view and it went from having no matching items to having some.
|
||||
// We first try to place the selection in the applications section, because it is
|
||||
// displayed above the documents section.
|
||||
_ensureItemSelected: function() {
|
||||
if (!this._appDisplay.hasSelected() && !this._docDisplay.hasSelected()) {
|
||||
if (this._appDisplay.hasItems()) {
|
||||
this._appDisplay.selectFirstItem();
|
||||
} else if (this._docDisplay.hasItems()) {
|
||||
this._docDisplay.selectFirstItem();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// Sets the 'More' mode for browsing applications.
|
||||
_setMoreAppsMode: function() {
|
||||
if (this._moreAppsMode)
|
||||
@ -811,6 +762,7 @@ Overlay.prototype = {
|
||||
// the item on any workspace.
|
||||
handleDragOver : function(source, actor, x, y, time) {
|
||||
if (source instanceof GenericDisplay.GenericDisplayItem) {
|
||||
log("unsetting more mode");
|
||||
this._dash.unsetMoreMode();
|
||||
return true;
|
||||
}
|
||||
|
@ -284,7 +284,7 @@ AppsWidget.prototype = {
|
||||
this.actor = new Big.Box({ spacing: 2 });
|
||||
this.collapsedActor = new Big.Box({ spacing: 2});
|
||||
|
||||
let apps = AppInfo.getMostUsedApps(5);
|
||||
let apps = AppInfo.getTopApps(5);
|
||||
for (let i = 0; i < apps.length; i++)
|
||||
this.addItem(apps[i]);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user