Introduce a SlideLayout layout manager

SlideLayout is a fixed layout that takes care of requesting and
allocating the right sizes so its contents can slide horizontally as the
actor is resized.
Sliding is controlled with a slideX and slideDirection properties, which
do the right thing wrt. RTL automatically.

Also add a SlidingControl base class that will be used by the overview
to pack and slide the workspace thumbnail switcher and the dash.

https://bugzilla.gnome.org/show_bug.cgi?id=682050
This commit is contained in:
Cosimo Cecchi 2013-02-14 14:41:38 -05:00
parent 30179bb60d
commit 93bde0cae2
2 changed files with 145 additions and 0 deletions

View File

@ -68,6 +68,7 @@ nobase_dist_js_DATA = \
ui/shellMountOperation.js \
ui/notificationDaemon.js \
ui/overview.js \
ui/overviewControls.js \
ui/panel.js \
ui/panelMenu.js \
ui/pointerWatcher.js \

144
js/ui/overviewControls.js Normal file
View File

@ -0,0 +1,144 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const Lang = imports.lang;
const St = imports.gi.St;
const Main = imports.ui.main;
const SIDE_CONTROLS_ANIMATION_TIME = 0.2;
const SlideDirection = {
LEFT: 0,
RIGHT: 1
};
const SlideLayout = new Lang.Class({
Name: 'SlideLayout',
Extends: Clutter.FixedLayout,
_init: function(params) {
this._slideX = 1;
this._direction = SlideDirection.LEFT;
this.parent(params);
},
_getRealSlideDirection: function(child) {
let direction = this._direction;
let rtl = (child.text_direction == Clutter.TextDirection.RTL);
if (rtl)
direction = (direction == SlideDirection.LEFT) ?
SlideDirection.RIGHT : SlideDirection.LEFT;
return direction;
},
vfunc_get_preferred_width: function(container, forHeight) {
let child = container.get_first_child();
let [minWidth, natWidth] = child.get_preferred_width(forHeight);
minWidth *= this._slideX;
natWidth *= this._slideX;
return [minWidth, natWidth];
},
vfunc_allocate: function(container, box, flags) {
let child = container.get_first_child();
let [, , natWidth, natHeight] = child.get_preferred_size();
let availWidth = Math.round(box.x2 - box.x1);
let availHeight = Math.round(box.y2 - box.y1);
let realDirection = this._getRealSlideDirection(child);
let translationX = (realDirection == SlideDirection.LEFT) ?
(availWidth - natWidth) : (natWidth - availWidth);
let actorBox = new Clutter.ActorBox({ x1: translationX,
y1: 0,
x2: child.x_expand ? availWidth : natWidth,
y2: child.y_expand ? availHeight : natHeight });
child.allocate(actorBox, flags);
},
set slideX(value) {
this._slideX = value;
this.layout_changed();
},
get slideX() {
return this._slideX;
},
set slideDirection(direction) {
this._direction = direction;
this.layout_changed();
},
get slideDirection() {
return this._direction;
}
});
const SlidingControl = new Lang.Class({
Name: 'SlidingControl',
_init: function() {
this.visible = true;
this.inDrag = false;
this.layout = new SlideLayout();
this.actor = new St.Widget({ layout_manager: this.layout,
clip_to_allocation: true });
Main.overview.connect('showing', Lang.bind(this, this._onOverviewShowing));
Main.overview.connect('item-drag-begin', Lang.bind(this, this._onDragBegin));
Main.overview.connect('item-drag-end', Lang.bind(this, this._onDragEnd));
Main.overview.connect('item-drag-cancelled', Lang.bind(this, this._onDragEnd));
Main.overview.connect('window-drag-begin', Lang.bind(this, this._onDragBegin));
Main.overview.connect('window-drag-cancelled', Lang.bind(this, this._onDragEnd));
Main.overview.connect('window-drag-end', Lang.bind(this, this._onDragEnd));
},
getSlide: function() {
throw new Error('getSlide() must be overridden');
},
updateSlide: function() {
Tweener.addTween(this.layout, { slideX: this.getSlide(),
time: SIDE_CONTROLS_ANIMATION_TIME,
transition: 'easeOutQuad' });
},
_onOverviewShowing: function() {
// reset any translation and make sure the actor is visible when
// entering the overview
this.visible = true;
this.layout.slideX = this.getSlide();
},
_onDragBegin: function() {
this.inDrag = true;
this.updateSlide();
},
_onDragEnd: function() {
this.inDrag = false;
this.updateSlide();
},
slideIn: function() {
this.visible = true;
this.updateSlide();
},
slideOut: function() {
this.visible = false;
this.updateSlide();
}
});