appDisplay: Show a dot when application is running

Show a dot in running applications.
Design request.
This commit is contained in:
Carlos Soriano 2014-10-16 19:51:30 +02:00
parent c5daf63976
commit 8891261dea
5 changed files with 102 additions and 37 deletions

View File

@ -492,7 +492,11 @@ StScrollBar {
} }
} }
.dash-item-container > StWidget {
padding: 4px 8px;
}
.dash-label { //osd tooltip .dash-label { //osd tooltip
border-radius: 7px; border-radius: 7px;
padding: 4px 12px; padding: 4px 12px;
@ -561,6 +565,12 @@ StScrollBar {
} }
} }
.app-well-app-running-dot { //running apps indicator
width: 10px; height: 3px;
background-color: $selected_bg_color;
margin-bottom: 2px; //FIXME will happen :)
}
%icon_tile { %icon_tile {
border-radius: 4px; border-radius: 4px;

View File

@ -1399,6 +1399,9 @@ StScrollBar {
width: 24px; width: 24px;
height: 24px; } height: 24px; }
.dash-item-container > StWidget {
padding: 4px 8px; }
.dash-label { .dash-label {
border-radius: 7px; border-radius: 7px;
padding: 4px 12px; padding: 4px 12px;
@ -1468,6 +1471,12 @@ StScrollBar {
border-image: none; border-image: none;
background-image: none; } background-image: none; }
.app-well-app-running-dot {
width: 10px;
height: 3px;
background-color: #215d9c;
margin-bottom: 2px; }
.search-provider-icon, .search-provider-icon,
.list-search-result, .app-well-app > .overview-icon, .list-search-result, .app-well-app > .overview-icon,
.show-apps > .overview-icon, .show-apps > .overview-icon,

View File

@ -1517,13 +1517,33 @@ const AppIcon = new Lang.Class({
this.id = app.get_id(); this.id = app.get_id();
this.name = app.get_name(); this.name = app.get_name();
this.actor = new St.Button({ style_class: 'app-well-app', // We need to make it track_hover so dash item can connect to
// the hover signal of the actor in _hookupLabel to call
// shouldShowTooltip when hovered.
this.actor = new St.Widget({ layout_manager: new Clutter.BinLayout(),
reactive: true, reactive: true,
button_mask: St.ButtonMask.ONE | St.ButtonMask.TWO, track_hover: true });
can_focus: true,
x_fill: true, this._dot = new St.Widget({ style_class: 'app-well-app-running-dot',
y_fill: true }); layout_manager: new Clutter.BinLayout(),
x_expand: true, y_expand: true,
x_align: Clutter.ActorAlign.CENTER,
y_align: Clutter.ActorAlign.END });
this._dot.hide();
this._button = new St.Button({ style_class: 'app-well-app',
reactive: true,
button_mask: St.ButtonMask.ONE | St.ButtonMask.TWO,
can_focus: true,
x_fill: true,
y_fill: true });
this.actor.add_actor(this._button);
this.actor.add_actor(this._dot);
this.actor._delegate = this; this.actor._delegate = this;
this._button._delegate = this;
if (!iconParams) if (!iconParams)
iconParams = {}; iconParams = {};
@ -1531,20 +1551,20 @@ const AppIcon = new Lang.Class({
iconParams['createIcon'] = Lang.bind(this, this._createIcon); iconParams['createIcon'] = Lang.bind(this, this._createIcon);
iconParams['setSizeManually'] = true; iconParams['setSizeManually'] = true;
this.icon = new IconGrid.BaseIcon(app.get_name(), iconParams); this.icon = new IconGrid.BaseIcon(app.get_name(), iconParams);
this.actor.set_child(this.icon.actor); this._button.set_child(this.icon.actor);
this.actor.label_actor = this.icon.label; this.actor.label_actor = this.icon.label;
this.actor.connect('leave-event', Lang.bind(this, this._onLeaveEvent)); this._button.connect('leave-event', Lang.bind(this, this._onLeaveEvent));
this.actor.connect('button-press-event', Lang.bind(this, this._onButtonPress)); this._button.connect('button-press-event', Lang.bind(this, this._onButtonPress));
this.actor.connect('touch-event', Lang.bind(this, this._onTouchEvent)); this._button.connect('touch-event', Lang.bind(this, this._onTouchEvent));
this.actor.connect('clicked', Lang.bind(this, this._onClicked)); this._button.connect('clicked', Lang.bind(this, this._onClicked));
this.actor.connect('popup-menu', Lang.bind(this, this._onKeyboardPopupMenu)); this._button.connect('popup-menu', Lang.bind(this, this._onKeyboardPopupMenu));
this._menu = null; this._menu = null;
this._menuManager = new PopupMenu.PopupMenuManager(this); this._menuManager = new PopupMenu.PopupMenuManager(this);
this._draggable = DND.makeDraggable(this.actor); this._draggable = DND.makeDraggable(this._button);
this._draggable.connect('drag-begin', Lang.bind(this, this._draggable.connect('drag-begin', Lang.bind(this,
function () { function () {
this._removeMenuTimeout(); this._removeMenuTimeout();
@ -1569,6 +1589,18 @@ const AppIcon = new Lang.Class({
this._updateRunningStyle(); this._updateRunningStyle();
}, },
// Needed for containers that want to track focus of the widget
// for i.e. scroll the container when navigating through items
getFocusReceiver: function () {
return this._button;
},
// Needed for containers that want to change style of the widget
// for i.e. set as selected when searching in shell
getStyleReceiver: function () {
return this._button;
},
_onDestroy: function() { _onDestroy: function() {
if (this._stateChangedId > 0) if (this._stateChangedId > 0)
this.app.disconnect(this._stateChangedId); this.app.disconnect(this._stateChangedId);
@ -1588,10 +1620,13 @@ const AppIcon = new Lang.Class({
}, },
_updateRunningStyle: function() { _updateRunningStyle: function() {
if (this.app.state != Shell.AppState.STOPPED) if (this.app.state != Shell.AppState.STOPPED) {
this.actor.add_style_class_name('running'); this._button.add_style_class_name('running');
else this._dot.show();
this.actor.remove_style_class_name('running'); } else {
this._button.remove_style_class_name('running');
this._dot.hide();
}
}, },
_setPopupTimeout: function() { _setPopupTimeout: function() {
@ -1606,7 +1641,7 @@ const AppIcon = new Lang.Class({
}, },
_onLeaveEvent: function(actor, event) { _onLeaveEvent: function(actor, event) {
this.actor.fake_release(); this._button.fake_release();
this._removeMenuTimeout(); this._removeMenuTimeout();
}, },
@ -1644,7 +1679,7 @@ const AppIcon = new Lang.Class({
popupMenu: function() { popupMenu: function() {
this._removeMenuTimeout(); this._removeMenuTimeout();
this.actor.fake_release(); this._button.fake_release();
this._draggable.fakeRelease(); this._draggable.fakeRelease();
if (!this._menu) { if (!this._menu) {
@ -1663,7 +1698,7 @@ const AppIcon = new Lang.Class({
this.emit('menu-state-changed', true); this.emit('menu-state-changed', true);
this.actor.set_hover(true); this._button.set_hover(true);
this._menu.popup(); this._menu.popup();
this._menuManager.ignoreRelease(); this._menuManager.ignoreRelease();
this.emit('sync-tooltip'); this.emit('sync-tooltip');
@ -1680,7 +1715,7 @@ const AppIcon = new Lang.Class({
}, },
_onMenuPoppedDown: function() { _onMenuPoppedDown: function() {
this.actor.sync_hover(); this._button.sync_hover();
this.emit('menu-state-changed', false); this.emit('menu-state-changed', false);
}, },

View File

@ -278,20 +278,6 @@ const IconGrid = new Lang.Class({
this._grid.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth)); 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('get-preferred-height', Lang.bind(this, this._getPreferredHeight));
this._grid.connect('allocate', Lang.bind(this, this._allocate)); this._grid.connect('allocate', Lang.bind(this, this._allocate));
this._grid.connect('actor-added', Lang.bind(this, this._childAdded));
this._grid.connect('actor-removed', Lang.bind(this, this._childRemoved));
},
_keyFocusIn: function(actor) {
this.emit('key-focus-in', actor);
},
_childAdded: function(grid, child) {
child._iconGridKeyFocusInId = child.connect('key-focus-in', Lang.bind(this, this._keyFocusIn));
},
_childRemoved: function(grid, child) {
child.disconnect(child._iconGridKeyFocusInId);
}, },
_getPreferredWidth: function (grid, forHeight, alloc) { _getPreferredWidth: function (grid, forHeight, alloc) {
@ -682,6 +668,10 @@ const IconGrid = new Lang.Class({
this._grid.destroy_all_children(); this._grid.destroy_all_children();
}, },
_keyFocusIn: function(actor) {
this.emit('key-focus-in', actor._associatedItem);
},
addItem: function(item, index) { addItem: function(item, index) {
if (!item.icon instanceof BaseIcon) if (!item.icon instanceof BaseIcon)
throw new Error('Only items with a BaseIcon icon property can be added to IconGrid'); throw new Error('Only items with a BaseIcon icon property can be added to IconGrid');
@ -691,9 +681,26 @@ const IconGrid = new Lang.Class({
this._grid.insert_child_at_index(item.actor, index); this._grid.insert_child_at_index(item.actor, index);
else else
this._grid.add_actor(item.actor); this._grid.add_actor(item.actor);
// Maybe the item actor acts as a container, so ask the item if
// it has a specific actor to track focus
let focusReceiver = item.actor;
if (item.getFocusReceiver)
focusReceiver = item.getFocusReceiver();
focusReceiver._associatedItem = item.actor;
focusReceiver._iconGridKeyFocusInId = focusReceiver.connect('key-focus-in', Lang.bind(this, this._keyFocusIn));
}, },
removeItem: function(item) { removeItem: function(item) {
let focusReceiver = item.actor;
if (item.getFocusReceiver)
focusReceiver = item.getFocusReceiver();
focusReceiver._associatedItem = null;
focusReceiver.disconnect(focusReceiver._iconGridKeyFocusInId);
this._grid.remove_child(item.actor); this._grid.remove_child(item.actor);
}, },

View File

@ -659,11 +659,15 @@ const SearchResults = new Lang.Class({
if (!result) if (!result)
return; return;
let styleReceiver = result.actor;
if (result.getStyleReceiver)
styleReceiver = result.getStyleReceiver();
if (selected) { if (selected) {
result.actor.add_style_pseudo_class('selected'); styleReceiver.add_style_pseudo_class('selected');
Util.ensureActorVisibleInScrollView(this._scrollView, result.actor); Util.ensureActorVisibleInScrollView(this._scrollView, result.actor);
} else { } else {
result.actor.remove_style_pseudo_class('selected'); styleReceiver.remove_style_pseudo_class('selected');
} }
} }
}); });