gnome-shell/js/ui/docDisplay.js
Marina Zhurakhinskaya 48cda5b179 Create two base classes: GenericDisplayItem and GenericDisplay, as
well as corresponding classes for applications and documents that inherit from
them. 

Use half the height of the sideshow in the overlay mode for the
AppDisplay, and the other half for the DocDisplay. 

Enable moving the selection between the two displays by using up and down arrow keys. 

Enable activating any item by clicking on it, in addition to activating the currently selected item by pressing Enter.

Apply search entry content to both sets of items.


svn path=/trunk/; revision=132
2008-12-20 04:27:57 +00:00

185 lines
7.0 KiB
JavaScript

/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const Signals = imports.signals;
const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const Gtk = imports.gi.Gtk;
const Shell = imports.gi.Shell;
const GenericDisplay = imports.ui.genericDisplay;
/* This class represents a single display item containing information about a document.
*
* docInfo - GtkRecentInfo object containing information about the document
* availableWidth - total width available for the item
*/
function DocDisplayItem(docInfo, availableWidth) {
this._init(docInfo, availableWidth);
}
DocDisplayItem.prototype = {
__proto__: GenericDisplay.GenericDisplayItem.prototype,
_init : function(docInfo, availableWidth) {
GenericDisplay.GenericDisplayItem.prototype._init.call(this, availableWidth);
this._docInfo = docInfo;
let name = docInfo.get_display_name();
// we can possibly display tags in the space for description in the future
let description = "";
let icon = new Clutter.Texture({width: 48, height: 48});
Shell.clutter_texture_set_from_pixbuf(icon, docInfo.get_icon(48));
this._setItemInfo(name, description, icon);
},
//// Public methods ////
// Returns the document info associated with this display item.
getDocInfo : function() {
return this._docInfo;
},
//// Public method overrides ////
// Opens a document represented by this display item.
launch : function() {
let appName = this._docInfo.last_application();
let appData = this._docInfo.get_application_info(appName);
let success = appData[0];
let appExec = appData[1];
let count = appData[2];
let time = appData[3];
if (success) {
log("Will open a document with the following command: " + appExec);
// TODO: Change this once better support for creating GAppInfo is added to
// GtkRecentInfo, as right now this relies on the fact that the file uri is
// already a part of appExec, so we don't supply any files to appInfo.launch().
let appInfo = Gio.app_info_create_from_commandline(appExec, null, 0, null);
appInfo.launch([], null, null);
} else {
log("Failed to get application info for " + this._docInfo.get_uri());
}
}
};
/* This class represents a display containing a collection of document items.
* The documents are sorted by how recently they were last visited.
*
* width - width available for the display
* height - height available for the display
*/
function DocDisplay(width, height) {
this._init(width, height);
}
DocDisplay.prototype = {
__proto__: GenericDisplay.GenericDisplay.prototype,
_init : function(width, height) {
GenericDisplay.GenericDisplay.prototype._init.call(this, width, height);
let me = this;
this._recentManager = Gtk.RecentManager.get_default();
this._docsStale = true;
this._recentManager.connect('changed', function(recentManager, userData) {
me._docsStale = true;
// Changes in local recent files should not happen when we are in the overlay mode,
// but redisplaying right away is cool when we use Zephyr.
// Also, we might be displaying remote documents, like Google Docs, in the future
// which might be edited by someone else.
me._redisplay();
});
},
//// Protected method overrides ////
// Gets the list of recent items from the recent items manager.
_refreshCache : function() {
let me = this;
if (!this._docsStale)
return;
this._allItems = {};
let docs = this._recentManager.get_items();
for (let i = 0; i < docs.length; i++) {
let docInfo = docs[i];
let docId = docInfo.get_uri();
// we use GtkRecentInfo URI as an item Id
this._allItems[docId] = docInfo;
}
this._docsStale = false;
},
// Sets the list of the displayed items based on how recently they were last visited.
_setDefaultList : function() {
this._removeAllDisplayItems();
// It seems to be an implementation detail of the Mozilla JavaScript that object
// properties are returned during the iteration in the same order in which they were
// defined, but it is not a guarantee according to this
// https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Statements/for...in
// So while this._allItems associative array seems to always be ordered by last visited,
// as the results of this._recentManager.get_items() based on which it is constructed are,
// we should do the sorting manually anyway.
// TODO: would it be better to store an additional array of doc ids as they are
// returned by this._recentManager.get_items() to avoid having to do this sorting?
// This function is called each time the search string is set back to '', so we are
// doing the sorting over the same items multiple times.
let docIds = [];
for (docId in this._allItems) {
docIds.push(docId);
}
this._sortItems(docIds);
let added = 0;
for (let i = 0; i < docIds.length && added < this._maxItems; i++) {
let docInfo = this._allItems[docIds[i]];
// docInfo.exists() checks if the resource still exists
if (docInfo.exists()) {
this._addDisplayItem(docIds[i]);
added += 1;
}
}
},
// Sorts the list of item ids in-place based on how recently the items associated with
// the ids were last visited.
_sortItems : function(itemIds) {
let me = this;
itemIds.sort(function (a,b) {
let docA = me._allItems[a];
let docB = me._allItems[b];
if (docA.get_visited() > docB.get_visited())
return -1;
else if (docA.get_visited() < docB.get_visited())
return 1;
else
return 0;
});
},
// Checks if the item info can be a match for the search string by checking
// the name of the document. Item info is expected to be GtkRecentInfo.
// Returns a boolean flag indicating if itemInfo is a match.
_isInfoMatching : function(itemInfo, search) {
if (search == null || search == '')
return true;
let name = itemInfo.get_display_name().toLowerCase();
if (name.indexOf(search) >= 0)
return true;
// TODO: we can also check doc URIs, so that
// if you search for a directory name, we display recent files from it
return false;
},
// Creates a DocDisplayItem based on itemInfo, which is expected be a GtkRecentInfo object.
_createDisplayItem: function(itemInfo) {
return new DocDisplayItem(itemInfo, this._width);
}
};
Signals.addSignalMethods(DocDisplay.prototype);