genericDisplay: Remove unused module
GenericDisplay used to provide a common base class for places and recent items, none of which exists anymore. As of current mockups, display items in "Finding and Reminding" should be based on BaseIcon / IconGrid instead.
This commit is contained in:
parent
39b0c88c76
commit
56f6c9c5f6
@ -441,42 +441,6 @@ StTooltip StLabel {
|
|||||||
spacing: 4px;
|
spacing: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* GenericDisplay */
|
|
||||||
|
|
||||||
.generic-display-container {
|
|
||||||
spacing: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.generic-display-item {
|
|
||||||
height: 50px;
|
|
||||||
border-radius: 4px;
|
|
||||||
color: #ffffff;
|
|
||||||
font-size: 14px;
|
|
||||||
spacing: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.generic-display-item:selected {
|
|
||||||
background-color: rgba(79,111,173,0.66);
|
|
||||||
}
|
|
||||||
|
|
||||||
.generic-display-item-text {
|
|
||||||
spacing: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.generic-display-item-description {
|
|
||||||
font-size: 12px;
|
|
||||||
color: #bababa;
|
|
||||||
}
|
|
||||||
|
|
||||||
.generic-display-details {
|
|
||||||
font-size: 14px;
|
|
||||||
color: #ffffff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.generic-display-details-name {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Apps */
|
/* Apps */
|
||||||
|
|
||||||
.icon-grid {
|
.icon-grid {
|
||||||
|
@ -24,7 +24,6 @@ nobase_dist_js_DATA = \
|
|||||||
ui/endSessionDialog.js \
|
ui/endSessionDialog.js \
|
||||||
ui/environment.js \
|
ui/environment.js \
|
||||||
ui/extensionSystem.js \
|
ui/extensionSystem.js \
|
||||||
ui/genericDisplay.js \
|
|
||||||
ui/iconGrid.js \
|
ui/iconGrid.js \
|
||||||
ui/lightbox.js \
|
ui/lightbox.js \
|
||||||
ui/link.js \
|
ui/link.js \
|
||||||
|
@ -60,8 +60,7 @@ function getDocManager() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DocManager wraps the DocSystem, primarily to expose DocInfo objects
|
* DocManager wraps the DocSystem, primarily to expose DocInfo objects.
|
||||||
* which conform to the GenericDisplay item API.
|
|
||||||
*/
|
*/
|
||||||
function DocManager() {
|
function DocManager() {
|
||||||
this._init();
|
this._init();
|
||||||
|
@ -1,693 +0,0 @@
|
|||||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
||||||
|
|
||||||
const Gtk = imports.gi.Gtk;
|
|
||||||
const Lang = imports.lang;
|
|
||||||
const Signals = imports.signals;
|
|
||||||
const St = imports.gi.St;
|
|
||||||
|
|
||||||
const DND = imports.ui.dnd;
|
|
||||||
const Main = imports.ui.main;
|
|
||||||
|
|
||||||
const RedisplayFlags = { NONE: 0,
|
|
||||||
FULL: 1 << 1,
|
|
||||||
SUBSEARCH: 1 << 2,
|
|
||||||
IMMEDIATE: 1 << 3 };
|
|
||||||
|
|
||||||
// Used by subclasses
|
|
||||||
const ITEM_DISPLAY_ICON_SIZE = 48;
|
|
||||||
const PREVIEW_ICON_SIZE = 96;
|
|
||||||
|
|
||||||
/* This is a virtual class that represents a single display item containing
|
|
||||||
* a name, a description, and an icon. It allows selecting an item and represents
|
|
||||||
* it by highlighting it with a different background color than the default.
|
|
||||||
*/
|
|
||||||
function GenericDisplayItem() {
|
|
||||||
this._init();
|
|
||||||
}
|
|
||||||
|
|
||||||
GenericDisplayItem.prototype = {
|
|
||||||
_init: function() {
|
|
||||||
this.actor = new St.BoxLayout({ style_class: 'generic-display-item',
|
|
||||||
reactive: true });
|
|
||||||
|
|
||||||
this.actor._delegate = this;
|
|
||||||
this.actor.connect('button-release-event',
|
|
||||||
Lang.bind(this,
|
|
||||||
function() {
|
|
||||||
// Activates the item by launching it
|
|
||||||
this.emit('activate');
|
|
||||||
return true;
|
|
||||||
}));
|
|
||||||
|
|
||||||
let draggable = DND.makeDraggable(this.actor);
|
|
||||||
draggable.connect('drag-begin',
|
|
||||||
Lang.bind(this, function() {
|
|
||||||
Main.overview.beginItemDrag(this);
|
|
||||||
}));
|
|
||||||
draggable.connect('drag-end',
|
|
||||||
Lang.bind(this, function() {
|
|
||||||
Main.overview.endItemDrag(this);
|
|
||||||
}));
|
|
||||||
|
|
||||||
this._iconBin = new St.Bin();
|
|
||||||
this.actor.add(this._iconBin);
|
|
||||||
|
|
||||||
this._infoText = new St.BoxLayout({ style_class: 'generic-display-item-text',
|
|
||||||
vertical: true });
|
|
||||||
this.actor.add(this._infoText, { expand: true, y_fill: false });
|
|
||||||
|
|
||||||
this._name = null;
|
|
||||||
this._description = null;
|
|
||||||
this._icon = null;
|
|
||||||
|
|
||||||
this._initialLoadComplete = false;
|
|
||||||
|
|
||||||
// An array of details description actors that we create over time for the item.
|
|
||||||
// It is used for updating the description text inside the details actor when
|
|
||||||
// the description text for the item is updated.
|
|
||||||
this._detailsDescriptions = [];
|
|
||||||
},
|
|
||||||
|
|
||||||
//// Draggable object interface ////
|
|
||||||
|
|
||||||
// Returns a cloned texture of the item's icon to represent the item as it
|
|
||||||
// is being dragged.
|
|
||||||
getDragActor: function(stageX, stageY) {
|
|
||||||
return this._createIcon();
|
|
||||||
},
|
|
||||||
|
|
||||||
// Returns the item icon, a separate copy of which is used to
|
|
||||||
// represent the item as it is being dragged. This is used to
|
|
||||||
// determine a snap-back location for the drag icon if it does
|
|
||||||
// not get accepted by any drop target.
|
|
||||||
getDragActorSource: function() {
|
|
||||||
return this._icon;
|
|
||||||
},
|
|
||||||
|
|
||||||
//// Public methods ////
|
|
||||||
|
|
||||||
// Highlights the item by setting a different background color than the default
|
|
||||||
// if isSelected is true, removes the highlighting otherwise.
|
|
||||||
markSelected: function(isSelected) {
|
|
||||||
if (isSelected)
|
|
||||||
this.actor.add_style_pseudo_class('selected');
|
|
||||||
else
|
|
||||||
this.actor.remove_style_pseudo_class('selected');
|
|
||||||
},
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Returns an actor containing item details. In the future details can have more information than what
|
|
||||||
* the preview pop-up has and be item-type specific.
|
|
||||||
*/
|
|
||||||
createDetailsActor: function() {
|
|
||||||
|
|
||||||
let details = new St.BoxLayout({ style_class: 'generic-display-container',
|
|
||||||
vertical: true });
|
|
||||||
|
|
||||||
let mainDetails = new St.BoxLayout({ style_class: 'generic-display-container' });
|
|
||||||
|
|
||||||
// Inner box with name and description
|
|
||||||
let textDetails = new St.BoxLayout({ style_class: 'generic-display-details',
|
|
||||||
vertical: true });
|
|
||||||
let detailsName = new St.Label({ style_class: 'generic-display-details-name',
|
|
||||||
text: this._name.text });
|
|
||||||
textDetails.add(detailsName);
|
|
||||||
|
|
||||||
let detailsDescription = new St.Label({ text: this._description.text });
|
|
||||||
textDetails.add(detailsDescription);
|
|
||||||
|
|
||||||
this._detailsDescriptions.push(detailsDescription);
|
|
||||||
|
|
||||||
mainDetails.add(textDetails, { expand: true });
|
|
||||||
|
|
||||||
let previewIcon = this._createPreviewIcon();
|
|
||||||
let largePreviewIcon = this._createLargePreviewIcon();
|
|
||||||
|
|
||||||
if (previewIcon != null && largePreviewIcon == null) {
|
|
||||||
mainDetails.insert_actor(previewIcon, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
details.add(mainDetails);
|
|
||||||
|
|
||||||
if (largePreviewIcon != null) {
|
|
||||||
details.add(largePreviewIcon);
|
|
||||||
}
|
|
||||||
|
|
||||||
return details;
|
|
||||||
},
|
|
||||||
|
|
||||||
// Destroys the item.
|
|
||||||
destroy: function() {
|
|
||||||
this.actor.destroy();
|
|
||||||
},
|
|
||||||
|
|
||||||
//// Pure virtual public methods ////
|
|
||||||
|
|
||||||
// Performes an action associated with launching this item, such as opening a file or an application.
|
|
||||||
launch: function() {
|
|
||||||
throw new Error('Not implemented');
|
|
||||||
},
|
|
||||||
|
|
||||||
//// Protected methods ////
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Creates the graphical elements for the item based on the item information.
|
|
||||||
*
|
|
||||||
* nameText - name of the item
|
|
||||||
* descriptionText - short description of the item
|
|
||||||
*/
|
|
||||||
_setItemInfo: function(nameText, descriptionText) {
|
|
||||||
if (this._name != null) {
|
|
||||||
// this also removes this._name from the parent container,
|
|
||||||
// so we don't need to call this.actor.remove_actor(this._name) directly
|
|
||||||
this._name.destroy();
|
|
||||||
this._name = null;
|
|
||||||
}
|
|
||||||
if (this._description != null) {
|
|
||||||
this._description.destroy();
|
|
||||||
this._description = null;
|
|
||||||
}
|
|
||||||
if (this._icon != null) {
|
|
||||||
// though we get the icon from elsewhere, we assume its ownership here,
|
|
||||||
// and therefore should be responsible for distroying it
|
|
||||||
this._icon.destroy();
|
|
||||||
this._icon = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._icon = this._createIcon();
|
|
||||||
this._iconBin.set_child(this._icon);
|
|
||||||
|
|
||||||
this._name = new St.Label({ style_class: 'generic-display-item-name',
|
|
||||||
text: nameText });
|
|
||||||
this._infoText.add(this._name);
|
|
||||||
|
|
||||||
this._description = new St.Label({ style_class: 'generic-display-item-description',
|
|
||||||
text: descriptionText ? descriptionText : '' });
|
|
||||||
this._infoText.add(this._description);
|
|
||||||
},
|
|
||||||
|
|
||||||
// Sets the description text for the item, including the description text
|
|
||||||
// in the details actors that have been created for the item.
|
|
||||||
_setDescriptionText: function(text) {
|
|
||||||
this._description.text = text;
|
|
||||||
for (let i = 0; i < this._detailsDescriptions.length; i++) {
|
|
||||||
let detailsDescription = this._detailsDescriptions[i];
|
|
||||||
if (detailsDescription != null) {
|
|
||||||
detailsDescription.text = text;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
//// Virtual protected methods ////
|
|
||||||
|
|
||||||
// Creates and returns a large preview icon, but only if we have a detailed image.
|
|
||||||
_createLargePreviewIcon : function() {
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
|
|
||||||
//// Pure virtual protected methods ////
|
|
||||||
|
|
||||||
// Returns an icon for the item.
|
|
||||||
_createIcon: function() {
|
|
||||||
throw new Error('Not implemented');
|
|
||||||
},
|
|
||||||
|
|
||||||
// Returns a preview icon for the item.
|
|
||||||
_createPreviewIcon: function() {
|
|
||||||
throw new Error('Not implemented');
|
|
||||||
}
|
|
||||||
|
|
||||||
//// Private methods ////
|
|
||||||
};
|
|
||||||
|
|
||||||
Signals.addSignalMethods(GenericDisplayItem.prototype);
|
|
||||||
|
|
||||||
/* This is a virtual class that represents a display containing a collection of items
|
|
||||||
* that can be filtered with a search string.
|
|
||||||
*/
|
|
||||||
function GenericDisplay() {
|
|
||||||
this._init();
|
|
||||||
}
|
|
||||||
|
|
||||||
GenericDisplay.prototype = {
|
|
||||||
_init : function() {
|
|
||||||
this._search = '';
|
|
||||||
this._expanded = false;
|
|
||||||
|
|
||||||
this.actor = new St.ScrollView({ x_fill: true,
|
|
||||||
y_fill: false,
|
|
||||||
vshadows: true });
|
|
||||||
this._list = new St.BoxLayout({ style_class: 'generic-display-container',
|
|
||||||
vertical: true });
|
|
||||||
this.actor.add_actor(this._list);
|
|
||||||
this.actor.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
|
|
||||||
|
|
||||||
this._pendingRedisplay = RedisplayFlags.NONE;
|
|
||||||
this.actor.connect('notify::mapped', Lang.bind(this, this._onMappedNotify));
|
|
||||||
|
|
||||||
// map<itemId, Object> where Object represents the item info
|
|
||||||
this._allItems = {};
|
|
||||||
// set<itemId>
|
|
||||||
this._matchedItems = {};
|
|
||||||
// sorted array of items matched by search
|
|
||||||
this._matchedItemKeys = [];
|
|
||||||
// map<itemId, GenericDisplayItem>
|
|
||||||
this._displayedItems = {};
|
|
||||||
this._openDetailIndex = -1;
|
|
||||||
this._selectedIndex = -1;
|
|
||||||
},
|
|
||||||
|
|
||||||
//// Public methods ////
|
|
||||||
|
|
||||||
// Sets the search string and displays the matching items.
|
|
||||||
setSearch: function(text) {
|
|
||||||
let lowertext = text.toLowerCase();
|
|
||||||
if (lowertext == this._search) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let flags = RedisplayFlags.IMMEDIATE;
|
|
||||||
if (this._search != '') {
|
|
||||||
// Because we combine search terms with OR, we have to be sure that no new term
|
|
||||||
// was introduced before deciding that the new search results will be a subset of
|
|
||||||
// the existing search results.
|
|
||||||
if (lowertext.indexOf(this._search) == 0 &&
|
|
||||||
lowertext.split(/\s+/).length == this._search.split(/\s+/).length) {
|
|
||||||
flags |= RedisplayFlags.SUBSEARCH;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this._search = lowertext;
|
|
||||||
this._redisplay(flags);
|
|
||||||
},
|
|
||||||
|
|
||||||
// Launches the item that is currently selected, closing the Overview
|
|
||||||
activateSelected: function() {
|
|
||||||
if (this._selectedIndex != -1) {
|
|
||||||
let selected = this._findDisplayedByIndex(this._selectedIndex);
|
|
||||||
selected.launch();
|
|
||||||
this.unsetSelected();
|
|
||||||
Main.overview.hide();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
// Moves the selection one up. If the selection was already on the top item, it's moved
|
|
||||||
// to the bottom one. Returns true if the selection actually moved up, false if it wrapped
|
|
||||||
// around to the bottom.
|
|
||||||
selectUp: function() {
|
|
||||||
let count = this._getVisibleCount();
|
|
||||||
let selectedUp = true;
|
|
||||||
let prev = this._selectedIndex - 1;
|
|
||||||
if (this._selectedIndex <= 0) {
|
|
||||||
prev = count - 1;
|
|
||||||
selectedUp = false;
|
|
||||||
}
|
|
||||||
this._selectIndex(prev);
|
|
||||||
return selectedUp;
|
|
||||||
},
|
|
||||||
|
|
||||||
// Moves the selection one down. If the selection was already on the bottom item, it's moved
|
|
||||||
// to the top one. Returns true if the selection actually moved down, false if it wrapped
|
|
||||||
// around to the top.
|
|
||||||
selectDown: function() {
|
|
||||||
let count = this._getVisibleCount();
|
|
||||||
let selectedDown = true;
|
|
||||||
let next = this._selectedIndex + 1;
|
|
||||||
if (this._selectedIndex == count - 1) {
|
|
||||||
next = 0;
|
|
||||||
selectedDown = false;
|
|
||||||
}
|
|
||||||
this._selectIndex(next);
|
|
||||||
return selectedDown;
|
|
||||||
},
|
|
||||||
|
|
||||||
// Selects the first item among the displayed items.
|
|
||||||
selectFirstItem: function() {
|
|
||||||
if (this.hasItems())
|
|
||||||
this._selectIndex(0);
|
|
||||||
},
|
|
||||||
|
|
||||||
// Selects the last item among the displayed items.
|
|
||||||
selectLastItem: function() {
|
|
||||||
let count = this._getVisibleCount();
|
|
||||||
if (this.hasItems())
|
|
||||||
this._selectIndex(count - 1);
|
|
||||||
},
|
|
||||||
|
|
||||||
// Returns true if the display has some item selected.
|
|
||||||
hasSelected: function() {
|
|
||||||
return this._selectedIndex != -1;
|
|
||||||
},
|
|
||||||
|
|
||||||
// Removes selection if some display item is selected.
|
|
||||||
unsetSelected: function() {
|
|
||||||
this._selectIndex(-1);
|
|
||||||
},
|
|
||||||
|
|
||||||
// Returns true if the display has any displayed items.
|
|
||||||
hasItems: function() {
|
|
||||||
// TODO: figure out why this._list.displayedCount is returning a
|
|
||||||
// positive number when this._mathedItems.length is 0
|
|
||||||
// This can be triggered if a search string is entered for which there are no matches.
|
|
||||||
// log('this._mathedItems.length: ' + this._matchedItems.length + ' this._list.displayedCount ' + this._list.displayedCount);
|
|
||||||
return this._matchedItemKeys.length > 0;
|
|
||||||
},
|
|
||||||
|
|
||||||
getMatchedItemsCount: function() {
|
|
||||||
return this._matchedItemKeys.length;
|
|
||||||
},
|
|
||||||
|
|
||||||
// Load the initial state
|
|
||||||
load: function() {
|
|
||||||
this._redisplay(RedisplayFlags.FULL);
|
|
||||||
},
|
|
||||||
|
|
||||||
// Should be called when the display is closed
|
|
||||||
resetState: function() {
|
|
||||||
this._filterReset();
|
|
||||||
this._openDetailIndex = -1;
|
|
||||||
this.actor.get_vscroll_bar().get_adjustment().value = 0;
|
|
||||||
},
|
|
||||||
|
|
||||||
// Returns an actor which acts as a sidebar; this is used for
|
|
||||||
// the applications category view
|
|
||||||
getNavigationArea: function () {
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
|
|
||||||
createDetailsForIndex: function(index) {
|
|
||||||
let item = this._findDisplayedByIndex(index);
|
|
||||||
return item.createDetailsActor();
|
|
||||||
},
|
|
||||||
|
|
||||||
//// Protected methods ////
|
|
||||||
|
|
||||||
_recreateDisplayItems: function() {
|
|
||||||
this._removeAllDisplayItems();
|
|
||||||
this._setDefaultList();
|
|
||||||
for (let itemId in this._allItems) {
|
|
||||||
this._addDisplayItem(itemId);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
// Creates a display item based on the information associated with itemId
|
|
||||||
// and adds it to the list of displayed items, but does not yet display it.
|
|
||||||
_addDisplayItem : function(itemId) {
|
|
||||||
if (this._displayedItems.hasOwnProperty(itemId)) {
|
|
||||||
log('Tried adding a display item for ' + itemId + ', but an item with this item id is already among displayed items.');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let itemInfo = this._allItems[itemId];
|
|
||||||
let displayItem = this._createDisplayItem(itemInfo);
|
|
||||||
|
|
||||||
displayItem.connect('activate',
|
|
||||||
Lang.bind(this,
|
|
||||||
function() {
|
|
||||||
// update the selection
|
|
||||||
this._selectIndex(this._list.get_children().indexOf(displayItem.actor));
|
|
||||||
this.activateSelected();
|
|
||||||
}));
|
|
||||||
|
|
||||||
displayItem.connect('show-details',
|
|
||||||
Lang.bind(this,
|
|
||||||
function() {
|
|
||||||
let index = this._list.get_children().indexOf(displayItem.actor);
|
|
||||||
/* Close the details pane if already open */
|
|
||||||
if (index == this._openDetailIndex) {
|
|
||||||
this._openDetailIndex = -1;
|
|
||||||
this.emit('show-details', -1);
|
|
||||||
} else {
|
|
||||||
this._openDetailIndex = index;
|
|
||||||
this.emit('show-details', index);
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
this._displayedItems[itemId] = displayItem;
|
|
||||||
},
|
|
||||||
|
|
||||||
// Removes an item identifed by the itemId from the displayed items.
|
|
||||||
_removeDisplayItem: function(itemId) {
|
|
||||||
let children = this._list.get_children();
|
|
||||||
let count = children.length;
|
|
||||||
let displayItem = this._displayedItems[itemId];
|
|
||||||
let displayItemIndex = children.indexOf(displayItem.actor);
|
|
||||||
|
|
||||||
if (this.hasSelected() && count == 1) {
|
|
||||||
this.unsetSelected();
|
|
||||||
} else if (this.hasSelected() && displayItemIndex < this._selectedIndex) {
|
|
||||||
this.selectUp();
|
|
||||||
}
|
|
||||||
|
|
||||||
displayItem.destroy();
|
|
||||||
|
|
||||||
delete this._displayedItems[itemId];
|
|
||||||
},
|
|
||||||
|
|
||||||
// Removes all displayed items.
|
|
||||||
_removeAllDisplayItems: function() {
|
|
||||||
this.unsetSelected();
|
|
||||||
for (itemId in this._displayedItems)
|
|
||||||
this._removeDisplayItem(itemId);
|
|
||||||
},
|
|
||||||
|
|
||||||
// Return true if there's an active search or other constraint
|
|
||||||
// on the list
|
|
||||||
_filterActive: function() {
|
|
||||||
return this._search != '';
|
|
||||||
},
|
|
||||||
|
|
||||||
// Called when we are resetting state
|
|
||||||
_filterReset: function() {
|
|
||||||
this.unsetSelected();
|
|
||||||
},
|
|
||||||
|
|
||||||
_compareSearchMatch: function(a, b) {
|
|
||||||
let countA = this._matchedItems[a];
|
|
||||||
let countB = this._matchedItems[b];
|
|
||||||
if (countA > countB)
|
|
||||||
return -1;
|
|
||||||
else if (countA < countB)
|
|
||||||
return 1;
|
|
||||||
else
|
|
||||||
return this._compareItems(a, b);
|
|
||||||
},
|
|
||||||
|
|
||||||
_setMatches: function(matches) {
|
|
||||||
this._matchedItems = matches;
|
|
||||||
this._matchedItemKeys = [];
|
|
||||||
for (let itemId in this._matchedItems) {
|
|
||||||
this._matchedItemKeys.push(itemId);
|
|
||||||
}
|
|
||||||
this._matchedItemKeys.sort(Lang.bind(this, this._compareSearchMatch));
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* _redisplaySubSearch:
|
|
||||||
* A somewhat more optimized function called when we know
|
|
||||||
* that we're going to be displaying a subset of the items
|
|
||||||
* we already had, in the same order. In that case, we can
|
|
||||||
* just hide the actors that shouldn't be shown.
|
|
||||||
*/
|
|
||||||
_redisplaySubSearch: function() {
|
|
||||||
let matches = this._getSearchMatchedItems(true);
|
|
||||||
|
|
||||||
// Just hide all from the old set,
|
|
||||||
// we'll show the ones we want below
|
|
||||||
for (let itemId in this._displayedItems) {
|
|
||||||
let item = this._displayedItems[itemId];
|
|
||||||
item.actor.hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
this._setMatches(matches);
|
|
||||||
|
|
||||||
for (let itemId in matches) {
|
|
||||||
let item = this._displayedItems[itemId];
|
|
||||||
item.actor.show();
|
|
||||||
}
|
|
||||||
this._list.queue_relayout();
|
|
||||||
},
|
|
||||||
|
|
||||||
_redisplayReordering: function() {
|
|
||||||
if (!this._filterActive()) {
|
|
||||||
this._setDefaultList();
|
|
||||||
} else {
|
|
||||||
this._setMatches(this._getSearchMatchedItems(false));
|
|
||||||
}
|
|
||||||
this._list.remove_all();
|
|
||||||
for (let i = 0; i < this._matchedItemKeys.length; i++) {
|
|
||||||
let itemId = this._matchedItemKeys[i];
|
|
||||||
let item = this._displayedItems[itemId];
|
|
||||||
item.actor.show();
|
|
||||||
this._list.add_actor(item.actor);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Updates the displayed items, applying the search string if one exists.
|
|
||||||
* @flags: Flags controlling redisplay behavior as follows:
|
|
||||||
* SUBSEARCH - Indicates that the current _search is a superstring of the previous
|
|
||||||
* one, which implies we only need to re-search through previous results.
|
|
||||||
* FULL - Indicates that we need recreate all displayed items.
|
|
||||||
* IMMEDIATE - Do the full redisplay even if we're not mapped. This is useful
|
|
||||||
* if you want to get the number of matched items and show/hide a section based on
|
|
||||||
* that number.
|
|
||||||
*/
|
|
||||||
_redisplay: function(flags) {
|
|
||||||
let immediate = (flags & RedisplayFlags.IMMEDIATE) != 0;
|
|
||||||
if (!immediate && !this.actor.mapped) {
|
|
||||||
this._pendingRedisplay |= flags;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let isSubSearch = (flags & RedisplayFlags.SUBSEARCH) != 0;
|
|
||||||
let fullReload = (flags & RedisplayFlags.FULL) != 0;
|
|
||||||
|
|
||||||
let hadSelected = this.hasSelected();
|
|
||||||
this.unsetSelected();
|
|
||||||
|
|
||||||
if (!this._initialLoadComplete)
|
|
||||||
fullReload = true;
|
|
||||||
|
|
||||||
if (!this._refreshCache())
|
|
||||||
fullReload = true;
|
|
||||||
|
|
||||||
if (fullReload) {
|
|
||||||
this._recreateDisplayItems();
|
|
||||||
this._initialLoadComplete = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isSubSearch) {
|
|
||||||
this._redisplaySubSearch();
|
|
||||||
} else {
|
|
||||||
this._redisplayReordering();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hadSelected) {
|
|
||||||
this._selectedIndex = -1;
|
|
||||||
this.selectFirstItem();
|
|
||||||
}
|
|
||||||
|
|
||||||
this.emit('redisplayed');
|
|
||||||
},
|
|
||||||
|
|
||||||
//// Pure virtual protected methods ////
|
|
||||||
|
|
||||||
// Performs the steps needed to have the latest information about the items.
|
|
||||||
// Implementation should return %true if we are up to date, and %false
|
|
||||||
// if a full reload occurred.
|
|
||||||
_refreshCache: function() {
|
|
||||||
throw new Error('Not implemented');
|
|
||||||
},
|
|
||||||
|
|
||||||
// Sets the list of the displayed items based on the default sorting order.
|
|
||||||
// The default sorting order is specific to each implementing class.
|
|
||||||
_setDefaultList: function() {
|
|
||||||
throw new Error('Not implemented');
|
|
||||||
},
|
|
||||||
|
|
||||||
// Compares items associated with the item ids based on the order in which the
|
|
||||||
// items should be displayed.
|
|
||||||
// Intended to be used as a compareFunction for array.sort().
|
|
||||||
// Returns an integer value indicating the result of the comparison.
|
|
||||||
_compareItems: function(itemIdA, itemIdB) {
|
|
||||||
throw new Error('Not implemented');
|
|
||||||
},
|
|
||||||
|
|
||||||
// Checks if the item info can be a match for the search string.
|
|
||||||
// Returns a boolean flag indicating if that's the case.
|
|
||||||
_isInfoMatching: function(itemInfo, search) {
|
|
||||||
throw new Error('Not implemented');
|
|
||||||
},
|
|
||||||
|
|
||||||
// Creates a display item based on itemInfo.
|
|
||||||
_createDisplayItem: function(itemInfo) {
|
|
||||||
throw new Error('Not implemented');
|
|
||||||
},
|
|
||||||
|
|
||||||
//// Private methods ////
|
|
||||||
|
|
||||||
_getItemSearchScore: function(itemId, terms) {
|
|
||||||
let item = this._allItems[itemId];
|
|
||||||
let score = 0;
|
|
||||||
for (let i = 0; i < terms.length; i++) {
|
|
||||||
let term = terms[i];
|
|
||||||
if (this._isInfoMatching(item, term)) {
|
|
||||||
score++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return score;
|
|
||||||
},
|
|
||||||
|
|
||||||
_getSearchMatchedItems: function(isSubSearch) {
|
|
||||||
// Break the search up into terms, and search for each
|
|
||||||
// individual term. Keep track of the number of terms
|
|
||||||
// each item matched.
|
|
||||||
let terms = this._search.split(/\s+/);
|
|
||||||
let matchScores = {};
|
|
||||||
|
|
||||||
if (isSubSearch) {
|
|
||||||
for (let i = 0; i < this._matchedItemKeys.length; i++) {
|
|
||||||
let itemId = this._matchedItemKeys[i];
|
|
||||||
let score = this._getItemSearchScore(itemId, terms);
|
|
||||||
if (score > 0)
|
|
||||||
matchScores[itemId] = score;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (let itemId in this._displayedItems) {
|
|
||||||
let score = this._getItemSearchScore(itemId, terms);
|
|
||||||
if (score > 0)
|
|
||||||
matchScores[itemId] = score;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return matchScores;
|
|
||||||
},
|
|
||||||
|
|
||||||
// Returns a display item based on its index in the ordering of the
|
|
||||||
// display children.
|
|
||||||
_findDisplayedByIndex: function(index) {
|
|
||||||
let actor = this._list.get_children()[index];
|
|
||||||
return this._findDisplayedByActor(actor);
|
|
||||||
},
|
|
||||||
|
|
||||||
// Returns a display item based on the actor that represents it in
|
|
||||||
// the display.
|
|
||||||
_findDisplayedByActor: function(actor) {
|
|
||||||
for (itemId in this._displayedItems) {
|
|
||||||
let item = this._displayedItems[itemId];
|
|
||||||
if (item.actor == actor) {
|
|
||||||
return item;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
|
|
||||||
// Selects (e.g. highlights) a display item at the provided index,
|
|
||||||
// updates this.selectedItemDetails actor, and emits 'selected' signal.
|
|
||||||
_selectIndex: function(index) {
|
|
||||||
// Cleanup from the previous item
|
|
||||||
if (this.hasSelected()) {
|
|
||||||
this._findDisplayedByIndex(this._selectedIndex).markSelected(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
this._selectedIndex = index;
|
|
||||||
if (index < 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Mark the new item as selected and create its details pane
|
|
||||||
let item = this._findDisplayedByIndex(index);
|
|
||||||
item.markSelected(true);
|
|
||||||
this.emit('selected');
|
|
||||||
},
|
|
||||||
|
|
||||||
_getVisibleCount: function() {
|
|
||||||
return this._list.get_n_children();
|
|
||||||
},
|
|
||||||
|
|
||||||
_onMappedNotify: function () {
|
|
||||||
let mapped = this.actor.mapped;
|
|
||||||
if (mapped && this._pendingRedisplay > RedisplayFlags.NONE)
|
|
||||||
this._redisplay(this._pendingRedisplay);
|
|
||||||
|
|
||||||
this._pendingRedisplay = RedisplayFlags.NONE;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Signals.addSignalMethods(GenericDisplay.prototype);
|
|
@ -15,7 +15,6 @@ const AppDisplay = imports.ui.appDisplay;
|
|||||||
const Dash = imports.ui.dash;
|
const Dash = imports.ui.dash;
|
||||||
const DND = imports.ui.dnd;
|
const DND = imports.ui.dnd;
|
||||||
const DocDisplay = imports.ui.docDisplay;
|
const DocDisplay = imports.ui.docDisplay;
|
||||||
const GenericDisplay = imports.ui.genericDisplay;
|
|
||||||
const Lightbox = imports.ui.lightbox;
|
const Lightbox = imports.ui.lightbox;
|
||||||
const Main = imports.ui.main;
|
const Main = imports.ui.main;
|
||||||
const MessageTray = imports.ui.messageTray;
|
const MessageTray = imports.ui.messageTray;
|
||||||
|
Loading…
Reference in New Issue
Block a user