[gnome-shell] [appDisplay] Factor out WellGrid/AppIcon
- From: Florian Müllner <fmuellner src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-shell] [appDisplay] Factor out WellGrid/AppIcon
- Date: Thu, 23 Sep 2010 17:11:57 +0000 (UTC)
commit 8c1bf346a9e13ca9658060e5551c43ebb36fed5a
Author: Florian Müllner <fmuellner gnome org>
Date: Wed Jul 21 04:22:19 2010 +0200
[appDisplay] Factor out WellGrid/AppIcon
All mockups now use a representation for documents/places similar to
the one used for applications. Rename AppIcon to BaseIcon and move its
code together with WellGrid out of appDisplay to stress their general
usefulness.
https://bugzilla.gnome.org/show_bug.cgi?id=625887
data/theme/gnome-shell.css | 2 +-
js/Makefile.am | 3 +-
js/ui/appDisplay.js | 182 +++----------------------------------
js/ui/iconGrid.js | 219 ++++++++++++++++++++++++++++++++++++++++++++
js/ui/panel.js | 10 +-
5 files changed, 240 insertions(+), 176 deletions(-)
---
diff --git a/data/theme/gnome-shell.css b/data/theme/gnome-shell.css
index cd70ec3..0e96be8 100644
--- a/data/theme/gnome-shell.css
+++ b/data/theme/gnome-shell.css
@@ -547,7 +547,7 @@ StTooltip {
width: 440px;
}
-#dashAppWell {
+.icon-grid {
spacing: 6px;
-shell-grid-item-size: 70px;
}
diff --git a/js/Makefile.am b/js/Makefile.am
index 6412c71..bcafa50 100644
--- a/js/Makefile.am
+++ b/js/Makefile.am
@@ -21,6 +21,7 @@ nobase_dist_js_DATA = \
ui/environment.js \
ui/extensionSystem.js \
ui/genericDisplay.js \
+ ui/iconGrid.js \
ui/lightbox.js \
ui/link.js \
ui/lookingGlass.js \
@@ -46,4 +47,4 @@ nobase_dist_js_DATA = \
ui/windowManager.js \
ui/workspace.js \
ui/workspacesView.js \
- ui/workspaceSwitcherPopup.js
\ No newline at end of file
+ ui/workspaceSwitcherPopup.js
diff --git a/js/ui/appDisplay.js b/js/ui/appDisplay.js
index a23d170..55d0768 100644
--- a/js/ui/appDisplay.js
+++ b/js/ui/appDisplay.js
@@ -12,6 +12,7 @@ const _ = Gettext.gettext;
const AppFavorites = imports.ui.appFavorites;
const DND = imports.ui.dnd;
+const IconGrid = imports.ui.iconGrid;
const Main = imports.ui.main;
const Overview = imports.ui.overview;
const PopupMenu = imports.ui.popupMenu;
@@ -20,8 +21,7 @@ const Tweener = imports.ui.tweener;
const Workspace = imports.ui.workspace;
const Params = imports.misc.params;
-const APPICON_SIZE = 48;
-const WELL_MAX_COLUMNS = 8;
+const WELL_MAX_COLUMNS = 16;
const WELL_MAX_SEARCH_ROWS = 1;
const MENU_POPUP_TIMEOUT = 600;
@@ -32,7 +32,7 @@ function AlphabeticalView() {
AlphabeticalView.prototype = {
_init: function() {
this.actor = new St.BoxLayout({ vertical: true });
- this._grid = new WellGrid();
+ this._grid = new IconGrid.IconGrid();
this._appSystem = Shell.AppSystem.get_default();
this.actor.add(this._grid.actor, { y_align: St.Align.START, expand: true });
},
@@ -222,7 +222,7 @@ AppSearchResultDisplay.prototype = {
_init: function (provider) {
Search.SearchResultDisplay.prototype._init.call(this, provider);
- this._grid = new WellGrid({ rowLimit: WELL_MAX_SEARCH_ROWS });
+ this._grid = new IconGrid.IconGrid({ rowLimit: WELL_MAX_SEARCH_ROWS });
this.actor = new St.Bin({ name: 'dashAppSearchResults',
x_align: St.Align.START });
this.actor.set_child(this._grid.actor);
@@ -368,23 +368,18 @@ function AppIcon(app) {
}
AppIcon.prototype = {
+ __proto__: IconGrid.BaseIcon.prototype,
+
_init : function(app) {
this.app = app;
- this.actor = new St.Bin({ style_class: 'app-icon',
- x_fill: true,
- y_fill: true });
- this.actor._delegate = this;
-
- let box = new St.BoxLayout({ vertical: true });
- this.actor.set_child(box);
+ let label = this.app.get_name();
- this.icon = this.app.create_icon_texture(APPICON_SIZE);
-
- box.add(this.icon, { expand: true, x_fill: false, y_fill: false });
+ IconGrid.BaseIcon.prototype._init.call(this, label);
+ },
- this._name = new St.Label({ text: this.app.get_name() });
- box.add_actor(this._name);
+ createIcon: function(iconSize) {
+ return this.app.create_icon_texture(iconSize);
}
};
@@ -587,7 +582,7 @@ AppWellIcon.prototype = {
},
getDragActor: function() {
- return this.app.create_icon_texture(APPICON_SIZE);
+ return this.app.create_icon_texture(this._icon.iconSize);
},
// Returns the original actor that should align with the actor
@@ -763,157 +758,6 @@ AppIconMenu.prototype = {
};
Signals.addSignalMethods(AppIconMenu.prototype);
-function WellGrid(params) {
- this._init(params);
-}
-
-WellGrid.prototype = {
- _init: function(params) {
- params = Params.parse(params, { rowLimit: null });
- this._rowLimit = params.rowLimit;
-
- this.actor = new St.BoxLayout({ name: 'dashAppWell', vertical: true });
- // Pulled from CSS, but hardcode some defaults here
- this._spacing = 0;
- this._item_size = 48;
- this._grid = new Shell.GenericContainer();
- this.actor.add(this._grid, { expand: true, y_align: St.Align.START });
- this.actor.connect('style-changed', Lang.bind(this, this._onStyleChanged));
-
- this._grid.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth));
- this._grid.connect('get-preferred-height', Lang.bind(this, this._getPreferredHeight));
- this._grid.connect('allocate', Lang.bind(this, this._allocate));
- },
-
- _getPreferredWidth: function (grid, forHeight, alloc) {
- let children = this._grid.get_children();
- let nColumns = children.length;
- let totalSpacing = Math.max(0, nColumns - 1) * this._spacing;
- // Kind of a lie, but not really an issue right now. If
- // we wanted to support some sort of hidden/overflow that would
- // need higher level design
- alloc.min_size = this._item_size;
- alloc.natural_size = nColumns * this._item_size + totalSpacing;
- },
-
- _getPreferredHeight: function (grid, forWidth, alloc) {
- let children = this._grid.get_children();
- let [nColumns, usedWidth] = this._computeLayout(forWidth);
- let nRows;
- if (nColumns > 0)
- nRows = Math.ceil(children.length / nColumns);
- else
- nRows = 0;
- if (this._rowLimit)
- nRows = Math.min(nRows, this._rowLimit);
- let totalSpacing = Math.max(0, nRows - 1) * this._spacing;
- let height = nRows * this._item_size + totalSpacing;
- alloc.min_size = height;
- alloc.natural_size = height;
- },
-
- _allocate: function (grid, box, flags) {
- let children = this._grid.get_children();
- let availWidth = box.x2 - box.x1;
- let availHeight = box.y2 - box.y1;
-
- let [nColumns, usedWidth] = this._computeLayout(availWidth);
-
- let overallPaddingX = Math.floor((availWidth - usedWidth) / 2);
-
- let x = box.x1 + overallPaddingX;
- let y = box.y1;
- let columnIndex = 0;
- let rowIndex = 0;
- for (let i = 0; i < children.length; i++) {
- let [childMinWidth, childMinHeight, childNaturalWidth, childNaturalHeight]
- = children[i].get_preferred_size();
-
- /* Center the item in its allocation horizontally */
- let width = Math.min(this._item_size, childNaturalWidth);
- let childXSpacing = Math.max(0, width - childNaturalWidth) / 2;
- let height = Math.min(this._item_size, childNaturalHeight);
- let childYSpacing = Math.max(0, height - childNaturalHeight) / 2;
-
- let childBox = new Clutter.ActorBox();
- if (St.Widget.get_default_direction() == St.TextDirection.RTL) {
- let _x = box.x2 - (x + width);
- childBox.x1 = Math.floor(_x - childXSpacing);
- } else {
- childBox.x1 = Math.floor(x + childXSpacing);
- }
- childBox.y1 = Math.floor(y + childYSpacing);
- childBox.x2 = childBox.x1 + width;
- childBox.y2 = childBox.y1 + height;
-
- if (this._rowLimit && rowIndex >= this._rowLimit) {
- this._grid.set_skip_paint(children[i], true);
- } else {
- children[i].allocate(childBox, flags);
- this._grid.set_skip_paint(children[i], false);
- }
-
- columnIndex++;
- if (columnIndex == nColumns) {
- columnIndex = 0;
- rowIndex++;
- }
-
- if (columnIndex == 0) {
- y += this._item_size + this._spacing;
- x = box.x1 + overallPaddingX;
- } else {
- x += this._item_size + this._spacing;
- }
- }
- },
-
- _computeLayout: function (forWidth) {
- let children = this._grid.get_children();
- let nColumns = 0;
- let usedWidth = 0;
- while (nColumns < WELL_MAX_COLUMNS &&
- (usedWidth + this._item_size <= forWidth)) {
- usedWidth += this._item_size + this._spacing;
- nColumns += 1;
- }
-
- if (nColumns > 0)
- usedWidth -= this._spacing;
-
- return [nColumns, usedWidth];
- },
-
- _onStyleChanged: function() {
- let themeNode = this.actor.get_theme_node();
- let [success, len] = themeNode.get_length('spacing', false);
- if (success)
- this._spacing = len;
- [success, len] = themeNode.get_length('-shell-grid-item-size', false);
- if (success)
- this._item_size = len;
- this._grid.queue_relayout();
- },
-
- removeAll: function () {
- this._grid.get_children().forEach(Lang.bind(this, function (child) {
- child.destroy();
- }));
- },
-
- addItem: function(actor) {
- this._grid.add_actor(actor);
- },
-
- getItemAtIndex: function(index) {
- return this._grid.get_children()[index];
- },
-
- visibleItemsCount: function() {
- return this._grid.get_children().length - this._grid.get_n_skip_paint();
- }
-};
-
function AppWell() {
this._init();
}
@@ -926,7 +770,7 @@ AppWell.prototype = {
this._favorites = [];
- this._grid = new WellGrid();
+ this._grid = new IconGrid.IconGrid();
this.actor = this._grid.actor;
this.actor._delegate = this;
diff --git a/js/ui/iconGrid.js b/js/ui/iconGrid.js
new file mode 100644
index 0000000..e728caf
--- /dev/null
+++ b/js/ui/iconGrid.js
@@ -0,0 +1,219 @@
+/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
+
+const Clutter = imports.gi.Clutter;
+const Shell = imports.gi.Shell;
+const St = imports.gi.St;
+
+const Lang = imports.lang;
+const Params = imports.misc.params;
+
+const ICON_SIZE = 48;
+
+
+function BaseIcon(label, createIcon) {
+ this._init(label, createIcon);
+}
+
+BaseIcon.prototype = {
+ _init : function(label, createIcon) {
+ this.actor = new St.Bin({ style_class: 'overview-icon',
+ x_fill: true,
+ y_fill: true });
+ this.actor._delegate = this;
+
+ this.actor.connect('style-changed',
+ Lang.bind(this, this._onStyleChanged));
+
+ let box = new St.BoxLayout({ vertical: true });
+ this.actor.set_child(box);
+
+ this.iconSize = ICON_SIZE;
+ this._iconBin = new St.Bin();
+
+ box.add(this._iconBin, { expand: true, x_fill: false, y_fill: false });
+
+ this._name = new St.Label({ text: label });
+ box.add_actor(this._name);
+
+ if (createIcon)
+ this.createIcon = createIcon;
+
+ this.icon = this.createIcon(this.iconSize);
+ this._iconBin.set_child(this.icon);
+ },
+
+ // This can be overridden by a subclass, or by the createIcon
+ // parameter to _init()
+ createIcon: function(size) {
+ throw new Error('no implementation of createIcon in ' + this);
+ },
+
+ _onStyleChanged: function() {
+ let node = this.actor.get_theme_node();
+ let [success, len] = node.get_length('icon-size', false);
+ if (success) {
+ if (len == this.iconSize)
+ return;
+
+ this.icon.destroy();
+ this.iconSize = len;
+ this.icon = this.createIcon(this.iconSize);
+ this._iconBin.set_child(this.icon);
+ }
+ }
+};
+
+function IconGrid(params) {
+ this._init(params);
+}
+
+IconGrid.prototype = {
+ _init: function(params) {
+ params = Params.parse(params, { rowLimit: null, columnLimit: null });
+ this._rowLimit = params.rowLimit;
+ this._colLimit = params.columnLimit;
+
+ this.actor = new St.BoxLayout({ style_class: 'icon-grid',
+ vertical: true });
+ // Pulled from CSS, but hardcode some defaults here
+ this._spacing = 0;
+ this._item_size = ICON_SIZE;
+ this._grid = new Shell.GenericContainer();
+ this.actor.add(this._grid, { expand: true, y_align: St.Align.START });
+ this.actor.connect('style-changed', Lang.bind(this, this._onStyleChanged));
+
+ this._grid.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth));
+ this._grid.connect('get-preferred-height', Lang.bind(this, this._getPreferredHeight));
+ this._grid.connect('allocate', Lang.bind(this, this._allocate));
+ },
+
+ _getPreferredWidth: function (grid, forHeight, alloc) {
+ let children = this._grid.get_children();
+ let nColumns = this._colLimit ? Math.min(this._colLimit,
+ children.length)
+ : children.length;
+ let totalSpacing = Math.max(0, nColumns - 1) * this._spacing;
+ // Kind of a lie, but not really an issue right now. If
+ // we wanted to support some sort of hidden/overflow that would
+ // need higher level design
+ alloc.min_size = this._item_size;
+ alloc.natural_size = nColumns * this._item_size + totalSpacing;
+ },
+
+ _getPreferredHeight: function (grid, forWidth, alloc) {
+ let children = this._grid.get_children();
+ let [nColumns, usedWidth] = this._computeLayout(forWidth);
+ let nRows;
+ if (nColumns > 0)
+ nRows = Math.ceil(children.length / nColumns);
+ else
+ nRows = 0;
+ if (this._rowLimit)
+ nRows = Math.min(nRows, this._rowLimit);
+ let totalSpacing = Math.max(0, nRows - 1) * this._spacing;
+ let height = nRows * this._item_size + totalSpacing;
+ alloc.min_size = height;
+ alloc.natural_size = height;
+ },
+
+ _allocate: function (grid, box, flags) {
+ let children = this._grid.get_children();
+ let availWidth = box.x2 - box.x1;
+ let availHeight = box.y2 - box.y1;
+
+ let [nColumns, usedWidth] = this._computeLayout(availWidth);
+
+ let overallPaddingX = Math.floor((availWidth - usedWidth) / 2);
+
+ let x = box.x1 + overallPaddingX;
+ let y = box.y1;
+ let columnIndex = 0;
+ let rowIndex = 0;
+ for (let i = 0; i < children.length; i++) {
+ let [childMinWidth, childMinHeight, childNaturalWidth, childNaturalHeight]
+ = children[i].get_preferred_size();
+
+ /* Center the item in its allocation horizontally */
+ let width = Math.min(this._item_size, childNaturalWidth);
+ let childXSpacing = Math.max(0, width - childNaturalWidth) / 2;
+ let height = Math.min(this._item_size, childNaturalHeight);
+ let childYSpacing = Math.max(0, height - childNaturalHeight) / 2;
+
+ let childBox = new Clutter.ActorBox();
+ if (St.Widget.get_default_direction() == St.TextDirection.RTL) {
+ let _x = box.x2 - (x + width);
+ childBox.x1 = Math.floor(_x - childXSpacing);
+ } else {
+ childBox.x1 = Math.floor(x + childXSpacing);
+ }
+ childBox.y1 = Math.floor(y + childYSpacing);
+ childBox.x2 = childBox.x1 + width;
+ childBox.y2 = childBox.y1 + height;
+
+ if (this._rowLimit && rowIndex >= this._rowLimit) {
+ this._grid.set_skip_paint(children[i], true);
+ } else {
+ children[i].allocate(childBox, flags);
+ this._grid.set_skip_paint(children[i], false);
+ }
+
+ columnIndex++;
+ if (columnIndex == nColumns) {
+ columnIndex = 0;
+ rowIndex++;
+ }
+
+ if (columnIndex == 0) {
+ y += this._item_size + this._spacing;
+ x = box.x1 + overallPaddingX;
+ } else {
+ x += this._item_size + this._spacing;
+ }
+ }
+ },
+
+ _computeLayout: function (forWidth) {
+ let children = this._grid.get_children();
+ let nColumns = 0;
+ let usedWidth = 0;
+ while ((this._colLimit == null || nColumns < this._colLimit) &&
+ (usedWidth + this._item_size <= forWidth)) {
+ usedWidth += this._item_size + this._spacing;
+ nColumns += 1;
+ }
+
+ if (nColumns > 0)
+ usedWidth -= this._spacing;
+
+ return [nColumns, usedWidth];
+ },
+
+ _onStyleChanged: function() {
+ let themeNode = this.actor.get_theme_node();
+ let [success, len] = themeNode.get_length('spacing', false);
+ if (success)
+ this._spacing = len;
+ [success, len] = themeNode.get_length('-shell-grid-item-size', false);
+ if (success)
+ this._item_size = len;
+ this._grid.queue_relayout();
+ },
+
+ removeAll: function () {
+ this._grid.get_children().forEach(Lang.bind(this, function (child) {
+ child.destroy();
+ }));
+ },
+
+ addItem: function(actor) {
+ this._grid.add_actor(actor);
+ },
+
+ getItemAtIndex: function(index) {
+ return this._grid.get_children()[index];
+ },
+
+ visibleItemsCount: function() {
+ return this._grid.get_children().length - this._grid.get_n_skip_paint();
+ }
+};
diff --git a/js/ui/panel.js b/js/ui/panel.js
index 057e0e1..1f05710 100644
--- a/js/ui/panel.js
+++ b/js/ui/panel.js
@@ -11,7 +11,6 @@ const Signals = imports.signals;
const Gettext = imports.gettext.domain('gnome-shell');
const _ = Gettext.gettext;
-const AppDisplay = imports.ui.appDisplay;
const Calendar = imports.ui.calendar;
const Overview = imports.ui.overview;
const PopupMenu = imports.ui.popupMenu;
@@ -219,10 +218,11 @@ AppMenuButton.prototype = {
this._updateId = 0;
this._animationStep = 0;
- this._clipWidth = AppDisplay.APPICON_SIZE / 2;
+ this._clipWidth = PANEL_ICON_SIZE;
this._direction = SPINNER_SPEED;
- this._spinner = new AnimatedIcon('process-working.png', 24);
+ this._spinner = new AnimatedIcon('process-working.png',
+ PANEL_ICON_SIZE);
this._container.add_actor(this._spinner.actor);
this._spinner.actor.lower_bottom();
@@ -304,7 +304,7 @@ AppMenuButton.prototype = {
}
if (this._animationStep > 1)
this._animationStep = 1;
- this._clipWidth = this._label.actor.width - (this._label.actor.width - AppDisplay.APPICON_SIZE / 2) * (1 - this._animationStep);
+ this._clipWidth = this._label.actor.width - (this._label.actor.width - PANEL_ICON_SIZE) * (1 - this._animationStep);
if (this.actor.get_direction() == St.TextDirection.LTR) {
this._label.actor.set_clip(0, 0, this._clipWidth + this._shadow.width, this.actor.height);
} else {
@@ -454,7 +454,7 @@ AppMenuButton.prototype = {
let targetApp = this._focusedApp != null ? this._focusedApp : this._lastStartedApp;
if (targetApp != null) {
- let icon = targetApp.get_faded_icon(AppDisplay.APPICON_SIZE);
+ let icon = targetApp.get_faded_icon(2 * PANEL_ICON_SIZE);
this._label.setText(targetApp.get_name());
// TODO - _quit() doesn't really work on apps in state STARTING yet
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]