Switch GenericDisplay to ShellOverflowList for dynamic height

This converts GenericDisplay to totally dynamic layout, where
we display as many items as we can, and the rest cleanly overflow
into pages.

For now, remove multi-column; to readd this, we can pack multiple
display items into a single ShellOverflowList item.
This commit is contained in:
Colin Walters 2009-07-04 15:30:12 -04:00
parent a1908d9db1
commit 15e862f974
4 changed files with 61 additions and 108 deletions

View File

@ -169,15 +169,15 @@ Signals.addSignalMethods(MenuItem.prototype);
* *
* width - width available for the display * width - width available for the display
*/ */
function AppDisplay(width, numberOfColumns, columnGap) { function AppDisplay(width) {
this._init(width, numberOfColumns, columnGap); this._init(width);
} }
AppDisplay.prototype = { AppDisplay.prototype = {
__proto__: GenericDisplay.GenericDisplay.prototype, __proto__: GenericDisplay.GenericDisplay.prototype,
_init : function(width, numberOfColumns, columnGap) { _init : function(width) {
GenericDisplay.GenericDisplay.prototype._init.call(this, width, numberOfColumns, columnGap); GenericDisplay.GenericDisplay.prototype._init.call(this, width);
this._menus = []; this._menus = [];
this._menuDisplays = []; this._menuDisplays = [];
@ -429,8 +429,8 @@ AppDisplay.prototype = {
}, },
// Creates an AppDisplayItem based on itemInfo, which is expected be an AppInfo object. // Creates an AppDisplayItem based on itemInfo, which is expected be an AppInfo object.
_createDisplayItem: function(itemInfo) { _createDisplayItem: function(itemInfo, width) {
return new AppDisplayItem(itemInfo, this._columnWidth); return new AppDisplayItem(itemInfo, width);
} }
}; };

View File

@ -67,15 +67,15 @@ DocDisplayItem.prototype = {
* *
* width - width available for the display * width - width available for the display
*/ */
function DocDisplay(width, numberOfColumns, columnGap) { function DocDisplay(width) {
this._init(width, numberOfColumns, columnGap); this._init(width);
} }
DocDisplay.prototype = { DocDisplay.prototype = {
__proto__: GenericDisplay.GenericDisplay.prototype, __proto__: GenericDisplay.GenericDisplay.prototype,
_init : function(width, numberOfColumns, columnGap) { _init : function(width) {
GenericDisplay.GenericDisplay.prototype._init.call(this, width, numberOfColumns, columnGap); GenericDisplay.GenericDisplay.prototype._init.call(this, width);
let me = this; let me = this;
this._recentManager = Gtk.RecentManager.get_default(); this._recentManager = Gtk.RecentManager.get_default();
this._docsStale = true; this._docsStale = true;
@ -170,8 +170,8 @@ DocDisplay.prototype = {
}, },
// Creates a DocDisplayItem based on itemInfo, which is expected to be a DocInfo object. // Creates a DocDisplayItem based on itemInfo, which is expected to be a DocInfo object.
_createDisplayItem: function(itemInfo) { _createDisplayItem: function(itemInfo, width) {
return new DocDisplayItem(itemInfo, this._columnWidth); return new DocDisplayItem(itemInfo, width);
} }
}; };

View File

@ -333,29 +333,28 @@ Signals.addSignalMethods(GenericDisplayItem.prototype);
* *
* width - width available for the display * width - width available for the display
*/ */
function GenericDisplay(width, numberOfColumns, columnGap) { function GenericDisplay(width) {
this._init(width, numberOfColumns, columnGap); this._init(width);
} }
GenericDisplay.prototype = { GenericDisplay.prototype = {
_init : function(width, numberOfColumns, columnGap) { _init : function(width) {
this._search = ''; this._search = '';
this._expanded = false; this._expanded = false;
this._width = null; this._width = width;
this._columnWidth = null;
this._numberOfColumns = numberOfColumns;
this._columnGap = columnGap;
if (this._columnGap == null)
this._columnGap = DEFAULT_COLUMN_GAP;
this._maxItemsPerPage = null; this._maxItemsPerPage = null;
this._grid = new Tidy.Grid({width: this._width }); this._list = new Shell.OverflowList({ width: this._width,
spacing: 6.0,
item_height: ITEM_DISPLAY_HEIGHT });
this._setDimensionsAndMaxItems(width, 0); this._list.connect('notify::n-pages', Lang.bind(this, function (grid, alloc) {
this._updateDisplayControl(true);
}));
this._list.connect('notify::page', Lang.bind(this, function (grid, alloc) {
this._updateDisplayControl(false);
}));
this._grid.column_major = true;
this._grid.column_gap = this._columnGap;
// map<itemId, Object> where Object represents the item info // map<itemId, Object> where Object represents the item info
this._allItems = {}; this._allItems = {};
// an array of itemIds of items that match the current request // an array of itemIds of items that match the current request
@ -364,17 +363,16 @@ GenericDisplay.prototype = {
// map<itemId, GenericDisplayItem> // map<itemId, GenericDisplayItem>
this._displayedItems = {}; this._displayedItems = {};
this._displayedItemsCount = 0; this._displayedItemsCount = 0;
this._pageDisplayed = 0;
this._selectedIndex = -1; this._selectedIndex = -1;
// These two are public - .actor is the normal "actor subclass" property, // These two are public - .actor is the normal "actor subclass" property,
// but we also expose a .displayControl actor which is separate. // but we also expose a .displayControl actor which is separate.
// See also getSideArea. // See also getSideArea.
this.actor = this._grid; this.actor = this._list;
this.displayControl = new Big.Box({ background_color: ITEM_DISPLAY_BACKGROUND_COLOR, this.displayControl = new Big.Box({ background_color: ITEM_DISPLAY_BACKGROUND_COLOR,
spacing: 12, spacing: 12,
orientation: Big.BoxOrientation.HORIZONTAL}); orientation: Big.BoxOrientation.HORIZONTAL});
this._availableWidthForItemDetails = this._columnWidth; this._availableWidthForItemDetails = width;
this.selectedItemDetails = new Big.Box({}); this.selectedItemDetails = new Big.Box({});
}, },
@ -461,34 +459,15 @@ GenericDisplay.prototype = {
return this._displayedItemsCount > 0; return this._displayedItemsCount > 0;
}, },
// Readjusts display layout and the items displayed based on the new dimensions.
setExpanded: function(expanded, baseWidth, expandWidth, numberOfColumns) {
this._expanded = expanded;
this._numberOfColumns = numberOfColumns;
this._setDimensionsAndMaxItems(baseWidth, expandWidth);
this._grid.width = this._width;
this._pageDisplayed = 0;
this._displayMatchedItems(true);
let gridWidth = this._width;
let sideArea = this.getSideArea();
if (sideArea) {
if (expanded)
sideArea.show();
else
sideArea.hide();
}
this.emit('expanded');
},
// Updates the displayed items and makes the display actor visible. // Updates the displayed items and makes the display actor visible.
show: function() { show: function() {
this._grid.show(); this._list.show();
this._redisplay(true); this._redisplay(true);
}, },
// Hides the display actor. // Hides the display actor.
hide: function() { hide: function() {
this._grid.hide(); this._list.hide();
this._filterReset(); this._filterReset();
this._removeAllDisplayItems(); this._removeAllDisplayItems();
}, },
@ -517,9 +496,7 @@ GenericDisplay.prototype = {
let hadSelected = this.hasSelected(); let hadSelected = this.hasSelected();
this._removeAllDisplayItems(); this._removeAllDisplayItems();
for (let i = 0; i < this._matchedItems.length; i++) {
for (let i = this._maxItemsPerPage * this._pageDisplayed; i < this._matchedItems.length && i < this._maxItemsPerPage * (this._pageDisplayed + 1); i++) {
this._addDisplayItem(this._matchedItems[i]); this._addDisplayItem(this._matchedItems[i]);
} }
@ -528,8 +505,6 @@ GenericDisplay.prototype = {
this.selectFirstItem(); this.selectFirstItem();
} }
this._updateDisplayControl(resetDisplayControl);
// We currently redisplay matching items and raise the sideshow as part of two different callbacks. // We currently redisplay matching items and raise the sideshow as part of two different callbacks.
// Checking what is under the pointer after a timeout allows us to not merge these callbacks into one, at least for now. // Checking what is under the pointer after a timeout allows us to not merge these callbacks into one, at least for now.
Mainloop.timeout_add(5, Mainloop.timeout_add(5,
@ -559,7 +534,7 @@ GenericDisplay.prototype = {
} }
let itemInfo = this._allItems[itemId]; let itemInfo = this._allItems[itemId];
let displayItem = this._createDisplayItem(itemInfo); let displayItem = this._createDisplayItem(itemInfo, this._width);
displayItem.connect('activate', displayItem.connect('activate',
Lang.bind(this, Lang.bind(this,
@ -575,7 +550,7 @@ GenericDisplay.prototype = {
// update the selection // update the selection
this._selectIndex(this._getIndexOfDisplayedActor(displayItem.actor)); this._selectIndex(this._getIndexOfDisplayedActor(displayItem.actor));
})); }));
this._grid.add_actor(displayItem.actor); this._list.add_actor(displayItem.actor);
this._displayedItems[itemId] = displayItem; this._displayedItems[itemId] = displayItem;
this._displayedItemsCount++; this._displayedItemsCount++;
}, },
@ -585,7 +560,7 @@ GenericDisplay.prototype = {
let displayItem = this._displayedItems[itemId]; let displayItem = this._displayedItems[itemId];
let displayItemIndex = this._getIndexOfDisplayedActor(displayItem.actor); let displayItemIndex = this._getIndexOfDisplayedActor(displayItem.actor);
if (this.hasSelected() && (this._displayedItemsCount == 1 || !this._grid.visible)) { if (this.hasSelected() && (this._displayedItemsCount == 1 || !this._list.visible)) {
this.unsetSelected(); this.unsetSelected();
} else if (this.hasSelected() && displayItemIndex < this._selectedIndex) { } else if (this.hasSelected() && displayItemIndex < this._selectedIndex) {
this.selectUp(); this.selectUp();
@ -625,7 +600,7 @@ GenericDisplay.prototype = {
* their own while the user was browsing through the result pages. * their own while the user was browsing through the result pages.
*/ */
_redisplay: function(resetPage) { _redisplay: function(resetPage) {
if (!this._grid.visible) if (!this._list.visible)
return; return;
this._refreshCache(); this._refreshCache();
@ -635,7 +610,7 @@ GenericDisplay.prototype = {
this._doSearchFilter(); this._doSearchFilter();
if (resetPage) if (resetPage)
this._pageDisplayed = 0; this._list.page = 0;
this._displayMatchedItems(true); this._displayMatchedItems(true);
@ -676,24 +651,6 @@ GenericDisplay.prototype = {
//// Private methods //// //// Private methods ////
// Sets this._width, this._columnWidth, and this._maxItemsPerPage based on the
// space available for the display, number of columns, and the number of items it can fit.
_setDimensionsAndMaxItems: function(baseWidth, expandWidth) {
this._width = baseWidth + expandWidth;
let gridWidth;
let sideArea = this.getSideArea();
if (this._expanded && sideArea) {
gridWidth = expandWidth;
sideArea.width = baseWidth;
} else {
gridWidth = this._width;
}
this._columnWidth = (gridWidth - this._columnGap * (this._numberOfColumns - 1)) / this._numberOfColumns;
let maxItemsInColumn = 5; // Math.floor(height / ITEM_DISPLAY_HEIGHT);
this._maxItemsPerPage = maxItemsInColumn * this._numberOfColumns;
this._grid.width = gridWidth;
},
_getSearchMatchedItems: function() { _getSearchMatchedItems: function() {
let matchedItemsForSearch = {}; let matchedItemsForSearch = {};
// Break the search up into terms, and search for each // Break the search up into terms, and search for each
@ -746,10 +703,9 @@ GenericDisplay.prototype = {
})); }));
}, },
// Displays the page specified by the pageNumber argument. The pageNumber is 0-based. // Displays the page specified by the pageNumber argument.
_displayPage: function(pageNumber) { _displayPage: function(pageNumber) {
this._pageDisplayed = pageNumber; this._list.page = pageNumber;
this._displayMatchedItems(false);
}, },
/* /*
@ -763,29 +719,29 @@ GenericDisplay.prototype = {
_updateDisplayControl: function(resetDisplayControl) { _updateDisplayControl: function(resetDisplayControl) {
if (resetDisplayControl) { if (resetDisplayControl) {
this.displayControl.remove_all(); this.displayControl.remove_all();
let pageNumber = 0; let nPages = this._list.n_pages;
for (let i = 0; i < this._matchedItems.length; i = i + this._maxItemsPerPage) { let pageNumber = this._list.page;
let pageControl = new Link.Link({ color: (pageNumber == this._pageDisplayed) ? DISPLAY_CONTROL_SELECTED_COLOR : ITEM_DISPLAY_DESCRIPTION_COLOR, for (let i = 0; i < nPages; i++) {
let pageControl = new Link.Link({ color: (i == pageNumber) ? DISPLAY_CONTROL_SELECTED_COLOR : ITEM_DISPLAY_DESCRIPTION_COLOR,
font_name: "Sans Bold 16px", font_name: "Sans Bold 16px",
text: (pageNumber + 1) + "", text: (i+1) + "",
height: LABEL_HEIGHT, height: LABEL_HEIGHT,
reactive: (pageNumber == this._pageDisplayed) ? false : true}); reactive: (i == pageNumber) ? false : true});
this.displayControl.append(pageControl.actor, Big.BoxPackFlags.NONE); this.displayControl.append(pageControl.actor, Big.BoxPackFlags.NONE);
// we use pageNumberLocalScope to get the page number right in the callback function // we use pageNumberLocalScope to get the page number right in the callback function
let pageNumberLocalScope = pageNumber; let pageNumberLocalScope = i;
pageControl.connect('clicked', pageControl.connect('clicked',
Lang.bind(this, Lang.bind(this,
function(o, event) { function(o, event) {
this._displayPage(pageNumberLocalScope); this._displayPage(pageNumberLocalScope);
})); }));
pageNumber ++;
} }
} else { } else {
let pageControlActors = this.displayControl.get_children(); let pageControlActors = this.displayControl.get_children();
for (let i = 0; i < pageControlActors.length; i++) { for (let i = 0; i < pageControlActors.length; i++) {
let pageControlActor = pageControlActors[i]; let pageControlActor = pageControlActors[i];
if (i == this._pageDisplayed) { if (i == this._list.page) {
pageControlActor.color = DISPLAY_CONTROL_SELECTED_COLOR; pageControlActor.color = DISPLAY_CONTROL_SELECTED_COLOR;
pageControlActor.reactive = false; pageControlActor.reactive = false;
} else { } else {
@ -799,7 +755,7 @@ GenericDisplay.prototype = {
// Returns a display item based on its index in the ordering of the // Returns a display item based on its index in the ordering of the
// display children. // display children.
_findDisplayedByIndex: function(index) { _findDisplayedByIndex: function(index) {
let displayedActors = this._grid.get_children(); let displayedActors = this._list.get_children();
let actor = displayedActors[index]; let actor = displayedActors[index];
return this._findDisplayedByActor(actor); return this._findDisplayedByActor(actor);
}, },
@ -819,7 +775,7 @@ GenericDisplay.prototype = {
// Returns and index that the actor has in the ordering of the display's // Returns and index that the actor has in the ordering of the display's
// children. // children.
_getIndexOfDisplayedActor: function(actor) { _getIndexOfDisplayedActor: function(actor) {
let children = this._grid.get_children(); let children = this._list.get_children();
for (let i = 0; i < children.length; i++) { for (let i = 0; i < children.length; i++) {
if (children[i] == actor) if (children[i] == actor)
return i; return i;

View File

@ -30,7 +30,6 @@ const DASH_MIN_WIDTH = 250;
const DASH_OUTER_PADDING = 4; const DASH_OUTER_PADDING = 4;
const DASH_SECTION_PADDING = 6; const DASH_SECTION_PADDING = 6;
const DASH_SECTION_SPACING = 6; const DASH_SECTION_SPACING = 6;
const DASH_COLUMNS = 1;
const DASH_CORNER_RADIUS = 5; const DASH_CORNER_RADIUS = 5;
// This is the height of section components other than the item display. // This is the height of section components other than the item display.
const DASH_SECTION_MISC_HEIGHT = (LABEL_HEIGHT + DASH_SECTION_SPACING) * 2 + DASH_SECTION_PADDING; const DASH_SECTION_MISC_HEIGHT = (LABEL_HEIGHT + DASH_SECTION_SPACING) * 2 + DASH_SECTION_PADDING;
@ -168,7 +167,7 @@ ItemResults.prototype = {
// LABEL_HEIGHT is the height of this._resultsText and GenericDisplay.LABEL_HEIGHT is the height // LABEL_HEIGHT is the height of this._resultsText and GenericDisplay.LABEL_HEIGHT is the height
// of the display controls. // of the display controls.
this._displayHeight = resultsHeight - LABEL_HEIGHT - GenericDisplay.LABEL_HEIGHT - DASH_SECTION_SPACING * 2; this._displayHeight = resultsHeight - LABEL_HEIGHT - GenericDisplay.LABEL_HEIGHT - DASH_SECTION_SPACING * 2;
this.display = new displayClass(resultsWidth, DASH_COLUMNS, DASH_SECTION_SPACING); this.display = new displayClass(resultsWidth);
this.actor.append(this.display.actor, Big.BoxPackFlags.EXPAND); this.actor.append(this.display.actor, Big.BoxPackFlags.EXPAND);
@ -181,7 +180,6 @@ ItemResults.prototype = {
_setSearchMode: function() { _setSearchMode: function() {
this.actor.height = this._resultsHeight / NUMBER_OF_SECTIONS_IN_SEARCH; this.actor.height = this._resultsHeight / NUMBER_OF_SECTIONS_IN_SEARCH;
let displayHeight = this._displayHeight - this._resultsHeight * (NUMBER_OF_SECTIONS_IN_SEARCH - 1) / NUMBER_OF_SECTIONS_IN_SEARCH; let displayHeight = this._displayHeight - this._resultsHeight * (NUMBER_OF_SECTIONS_IN_SEARCH - 1) / NUMBER_OF_SECTIONS_IN_SEARCH;
this.display.setExpanded(false, this._resultsWidth, 0, DASH_COLUMNS);
this.actor.remove_all(); this.actor.remove_all();
this.actor.append(this._resultsText, Big.BoxPackFlags.NONE); this.actor.append(this._resultsText, Big.BoxPackFlags.NONE);
this.actor.append(this.display.actor, Big.BoxPackFlags.EXPAND); this.actor.append(this.display.actor, Big.BoxPackFlags.EXPAND);
@ -190,7 +188,6 @@ ItemResults.prototype = {
_unsetSearchMode: function() { _unsetSearchMode: function() {
this.actor.height = this._resultsHeight; this.actor.height = this._resultsHeight;
this.display.setExpanded(false, this._resultsWidth, 0, DASH_COLUMNS);
this.actor.remove_all(); this.actor.remove_all();
this.actor.append(this._resultsText, Big.BoxPackFlags.NONE); this.actor.append(this._resultsText, Big.BoxPackFlags.NONE);
this.actor.append(this.display.actor, Big.BoxPackFlags.EXPAND); this.actor.append(this.display.actor, Big.BoxPackFlags.EXPAND);
@ -379,7 +376,7 @@ Dash.prototype = {
height: LABEL_HEIGHT}); height: LABEL_HEIGHT});
this._docsSection.append(this._docsText, Big.BoxPackFlags.NONE); this._docsSection.append(this._docsText, Big.BoxPackFlags.NONE);
this._docDisplay = new DocDisplay.DocDisplay(this._displayWidth, DASH_COLUMNS, DASH_SECTION_PADDING); this._docDisplay = new DocDisplay.DocDisplay(this._displayWidth);
this._docsSection.append(this._docDisplay.actor, Big.BoxPackFlags.EXPAND); this._docsSection.append(this._docDisplay.actor, Big.BoxPackFlags.EXPAND);
let moreDocsBox = new Big.Box({x_align: Big.BoxAlignment.END}); let moreDocsBox = new Big.Box({x_align: Big.BoxAlignment.END});