appDisplay: Separate PageIndicators to a separate file
In order to cater for emoji panel usage, we want something like PageIndicators except: - It should have horizontal disposition - It should not be animatable (?) - It should not be reactive Separated PageIndicators into a base, non-animated widget, and an AnimatedPageIndicators that can be used on appDisplay.js. Reactiveness is set through an extra method, and layout is set as a construct argument.
This commit is contained in:
parent
2a9923628b
commit
fab390826e
@ -78,6 +78,7 @@
|
|||||||
<file>ui/overview.js</file>
|
<file>ui/overview.js</file>
|
||||||
<file>ui/overviewControls.js</file>
|
<file>ui/overviewControls.js</file>
|
||||||
<file>ui/padOsd.js</file>
|
<file>ui/padOsd.js</file>
|
||||||
|
<file>ui/pageIndicators.js</file>
|
||||||
<file>ui/panel.js</file>
|
<file>ui/panel.js</file>
|
||||||
<file>ui/panelMenu.js</file>
|
<file>ui/panelMenu.js</file>
|
||||||
<file>ui/pointerWatcher.js</file>
|
<file>ui/pointerWatcher.js</file>
|
||||||
|
@ -19,6 +19,7 @@ const IconGrid = imports.ui.iconGrid;
|
|||||||
const Main = imports.ui.main;
|
const Main = imports.ui.main;
|
||||||
const Overview = imports.ui.overview;
|
const Overview = imports.ui.overview;
|
||||||
const OverviewControls = imports.ui.overviewControls;
|
const OverviewControls = imports.ui.overviewControls;
|
||||||
|
const PageIndicators = imports.ui.pageIndicators;
|
||||||
const PopupMenu = imports.ui.popupMenu;
|
const PopupMenu = imports.ui.popupMenu;
|
||||||
const Tweener = imports.ui.tweener;
|
const Tweener = imports.ui.tweener;
|
||||||
const Workspace = imports.ui.workspace;
|
const Workspace = imports.ui.workspace;
|
||||||
@ -245,116 +246,6 @@ class BaseAppView {
|
|||||||
};
|
};
|
||||||
Signals.addSignalMethods(BaseAppView.prototype);
|
Signals.addSignalMethods(BaseAppView.prototype);
|
||||||
|
|
||||||
var PageIndicatorsActor = GObject.registerClass(
|
|
||||||
class PageIndicatorsActor extends St.BoxLayout {
|
|
||||||
_init() {
|
|
||||||
super._init({ style_class: 'page-indicators',
|
|
||||||
vertical: true,
|
|
||||||
x_expand: true, y_expand: true,
|
|
||||||
x_align: Clutter.ActorAlign.END,
|
|
||||||
y_align: Clutter.ActorAlign.CENTER,
|
|
||||||
reactive: true,
|
|
||||||
clip_to_allocation: true });
|
|
||||||
}
|
|
||||||
|
|
||||||
vfunc_get_preferred_height(forWidth) {
|
|
||||||
// We want to request the natural height of all our children as our
|
|
||||||
// natural height, so we chain up to St.BoxLayout, but we only request 0
|
|
||||||
// as minimum height, since it's not that important if some indicators
|
|
||||||
// are not shown
|
|
||||||
let [, natHeight] = super.vfunc_get_preferred_height(forWidth);
|
|
||||||
return [0, natHeight];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
class PageIndicators {
|
|
||||||
constructor() {
|
|
||||||
this.actor = new PageIndicatorsActor();
|
|
||||||
this._nPages = 0;
|
|
||||||
this._currentPage = undefined;
|
|
||||||
|
|
||||||
this.actor.connect('notify::mapped', () => {
|
|
||||||
this.animateIndicators(IconGrid.AnimationDirection.IN);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
setNPages(nPages) {
|
|
||||||
if (this._nPages == nPages)
|
|
||||||
return;
|
|
||||||
|
|
||||||
let diff = nPages - this._nPages;
|
|
||||||
if (diff > 0) {
|
|
||||||
for (let i = 0; i < diff; i++) {
|
|
||||||
let pageIndex = this._nPages + i;
|
|
||||||
let indicator = new St.Button({ style_class: 'page-indicator',
|
|
||||||
button_mask: St.ButtonMask.ONE |
|
|
||||||
St.ButtonMask.TWO |
|
|
||||||
St.ButtonMask.THREE,
|
|
||||||
toggle_mode: true,
|
|
||||||
checked: pageIndex == this._currentPage });
|
|
||||||
indicator.child = new St.Widget({ style_class: 'page-indicator-icon' });
|
|
||||||
indicator.connect('clicked', () => {
|
|
||||||
this.emit('page-activated', pageIndex);
|
|
||||||
});
|
|
||||||
this.actor.add_actor(indicator);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
let children = this.actor.get_children().splice(diff);
|
|
||||||
for (let i = 0; i < children.length; i++)
|
|
||||||
children[i].destroy();
|
|
||||||
}
|
|
||||||
this._nPages = nPages;
|
|
||||||
this.actor.visible = (this._nPages > 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
setCurrentPage(currentPage) {
|
|
||||||
this._currentPage = currentPage;
|
|
||||||
|
|
||||||
let children = this.actor.get_children();
|
|
||||||
for (let i = 0; i < children.length; i++)
|
|
||||||
children[i].set_checked(i == this._currentPage);
|
|
||||||
}
|
|
||||||
|
|
||||||
animateIndicators(animationDirection) {
|
|
||||||
if (!this.actor.mapped)
|
|
||||||
return;
|
|
||||||
|
|
||||||
let children = this.actor.get_children();
|
|
||||||
if (children.length == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (let i = 0; i < this._nPages; i++)
|
|
||||||
Tweener.removeTweens(children[i]);
|
|
||||||
|
|
||||||
let offset;
|
|
||||||
if (this.actor.get_text_direction() == Clutter.TextDirection.RTL)
|
|
||||||
offset = -children[0].width;
|
|
||||||
else
|
|
||||||
offset = children[0].width;
|
|
||||||
|
|
||||||
let isAnimationIn = animationDirection == IconGrid.AnimationDirection.IN;
|
|
||||||
let delay = isAnimationIn ? INDICATORS_ANIMATION_DELAY :
|
|
||||||
INDICATORS_ANIMATION_DELAY_OUT;
|
|
||||||
let baseTime = isAnimationIn ? INDICATORS_BASE_TIME : INDICATORS_BASE_TIME_OUT;
|
|
||||||
let totalAnimationTime = baseTime + delay * this._nPages;
|
|
||||||
let maxTime = isAnimationIn ? INDICATORS_ANIMATION_MAX_TIME :
|
|
||||||
INDICATORS_ANIMATION_MAX_TIME_OUT;
|
|
||||||
if (totalAnimationTime > maxTime)
|
|
||||||
delay -= (totalAnimationTime - maxTime) / this._nPages;
|
|
||||||
|
|
||||||
for (let i = 0; i < this._nPages; i++) {
|
|
||||||
children[i].translation_x = isAnimationIn ? offset : 0;
|
|
||||||
Tweener.addTween(children[i],
|
|
||||||
{ translation_x: isAnimationIn ? 0 : offset,
|
|
||||||
time: baseTime + delay * i,
|
|
||||||
transition: 'easeInOutQuad',
|
|
||||||
delay: isAnimationIn ? VIEWS_SWITCH_ANIMATION_DELAY : 0
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Signals.addSignalMethods(PageIndicators.prototype);
|
|
||||||
|
|
||||||
var AllView = class AllView extends BaseAppView {
|
var AllView = class AllView extends BaseAppView {
|
||||||
constructor() {
|
constructor() {
|
||||||
super({ usePagination: true }, null);
|
super({ usePagination: true }, null);
|
||||||
@ -373,13 +264,13 @@ var AllView = class AllView extends BaseAppView {
|
|||||||
St.PolicyType.EXTERNAL);
|
St.PolicyType.EXTERNAL);
|
||||||
this._adjustment = this._scrollView.vscroll.adjustment;
|
this._adjustment = this._scrollView.vscroll.adjustment;
|
||||||
|
|
||||||
this._pageIndicators = new PageIndicators();
|
this._pageIndicators = new PageIndicators.AnimatedPageIndicators();
|
||||||
this._pageIndicators.connect('page-activated',
|
this._pageIndicators.connect('page-activated',
|
||||||
(indicators, pageIndex) => {
|
(indicators, pageIndex) => {
|
||||||
this.goToPage(pageIndex);
|
this.goToPage(pageIndex);
|
||||||
});
|
});
|
||||||
this._pageIndicators.actor.connect('scroll-event', this._onScroll.bind(this));
|
this._pageIndicators.connect('scroll-event', this._onScroll.bind(this));
|
||||||
this.actor.add_actor(this._pageIndicators.actor);
|
this.actor.add_actor(this._pageIndicators);
|
||||||
|
|
||||||
this.folderIcons = [];
|
this.folderIcons = [];
|
||||||
|
|
||||||
|
142
js/ui/pageIndicators.js
Normal file
142
js/ui/pageIndicators.js
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||||
|
|
||||||
|
const Clutter = imports.gi.Clutter;
|
||||||
|
const GObject = imports.gi.GObject;
|
||||||
|
const St = imports.gi.St;
|
||||||
|
|
||||||
|
const Tweener = imports.ui.tweener;
|
||||||
|
const { ANIMATION_TIME_OUT, ANIMATION_MAX_DELAY_OUT_FOR_ITEM, AnimationDirection } = imports.ui.iconGrid;
|
||||||
|
|
||||||
|
var INDICATORS_BASE_TIME = 0.25;
|
||||||
|
var INDICATORS_BASE_TIME_OUT = 0.125;
|
||||||
|
var INDICATORS_ANIMATION_DELAY = 0.125;
|
||||||
|
var INDICATORS_ANIMATION_DELAY_OUT = 0.0625;
|
||||||
|
var INDICATORS_ANIMATION_MAX_TIME = 0.75;
|
||||||
|
var SWITCH_TIME = 0.4;
|
||||||
|
var INDICATORS_ANIMATION_MAX_TIME_OUT =
|
||||||
|
Math.min (SWITCH_TIME,
|
||||||
|
ANIMATION_TIME_OUT + ANIMATION_MAX_DELAY_OUT_FOR_ITEM);
|
||||||
|
|
||||||
|
var ANIMATION_DELAY = 0.1;
|
||||||
|
|
||||||
|
var PageIndicators = GObject.registerClass({
|
||||||
|
Signals: { 'page-activated': { param_types: [GObject.TYPE_INT] } }
|
||||||
|
}, class PageIndicators extends St.BoxLayout {
|
||||||
|
_init(vertical = true) {
|
||||||
|
super._init({ style_class: 'page-indicators',
|
||||||
|
vertical,
|
||||||
|
x_expand: true, y_expand: true,
|
||||||
|
x_align: vertical ? Clutter.ActorAlign.END : Clutter.ActorAlign.CENTER,
|
||||||
|
y_align: vertical ? Clutter.ActorAlign.CENTER : Clutter.ActorAlign.END,
|
||||||
|
reactive: true,
|
||||||
|
clip_to_allocation: true });
|
||||||
|
this._nPages = 0;
|
||||||
|
this._currentPage = undefined;
|
||||||
|
this._reactive = true;
|
||||||
|
this._reactive = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
vfunc_get_preferred_height(forWidth) {
|
||||||
|
// We want to request the natural height of all our children as our
|
||||||
|
// natural height, so we chain up to St.BoxLayout, but we only request 0
|
||||||
|
// as minimum height, since it's not that important if some indicators
|
||||||
|
// are not shown
|
||||||
|
let [, natHeight] = super.vfunc_get_preferred_height(forWidth);
|
||||||
|
return [0, natHeight];
|
||||||
|
}
|
||||||
|
|
||||||
|
setReactive(reactive) {
|
||||||
|
let children = this.get_children();
|
||||||
|
for (let i = 0; i < children.length; i++)
|
||||||
|
children[i].reactive = reactive;
|
||||||
|
|
||||||
|
this._reactive = reactive;
|
||||||
|
}
|
||||||
|
|
||||||
|
setNPages(nPages) {
|
||||||
|
if (this._nPages == nPages)
|
||||||
|
return;
|
||||||
|
|
||||||
|
let diff = nPages - this._nPages;
|
||||||
|
if (diff > 0) {
|
||||||
|
for (let i = 0; i < diff; i++) {
|
||||||
|
let pageIndex = this._nPages + i;
|
||||||
|
let indicator = new St.Button({ style_class: 'page-indicator',
|
||||||
|
button_mask: St.ButtonMask.ONE |
|
||||||
|
St.ButtonMask.TWO |
|
||||||
|
St.ButtonMask.THREE,
|
||||||
|
toggle_mode: true,
|
||||||
|
reactive: this._reactive,
|
||||||
|
checked: pageIndex == this._currentPage });
|
||||||
|
indicator.child = new St.Widget({ style_class: 'page-indicator-icon' });
|
||||||
|
indicator.connect('clicked', () => {
|
||||||
|
this.emit('page-activated', pageIndex);
|
||||||
|
});
|
||||||
|
this.add_actor(indicator);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let children = this.get_children().splice(diff);
|
||||||
|
for (let i = 0; i < children.length; i++)
|
||||||
|
children[i].destroy();
|
||||||
|
}
|
||||||
|
this._nPages = nPages;
|
||||||
|
this.visible = (this._nPages > 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
setCurrentPage(currentPage) {
|
||||||
|
this._currentPage = currentPage;
|
||||||
|
|
||||||
|
let children = this.get_children();
|
||||||
|
for (let i = 0; i < children.length; i++)
|
||||||
|
children[i].set_checked(i == this._currentPage);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var AnimatedPageIndicators = GObject.registerClass(
|
||||||
|
class AnimatedPageIndicators extends PageIndicators {
|
||||||
|
_init() {
|
||||||
|
super._init(true);
|
||||||
|
|
||||||
|
this.connect('notify::mapped', () => {
|
||||||
|
this.animateIndicators(AnimationDirection.IN);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
animateIndicators(animationDirection) {
|
||||||
|
if (!this.mapped)
|
||||||
|
return;
|
||||||
|
|
||||||
|
let children = this.get_children();
|
||||||
|
if (children.length == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (let i = 0; i < this._nPages; i++)
|
||||||
|
Tweener.removeTweens(children[i]);
|
||||||
|
|
||||||
|
let offset;
|
||||||
|
if (this.get_text_direction() == Clutter.TextDirection.RTL)
|
||||||
|
offset = -children[0].width;
|
||||||
|
else
|
||||||
|
offset = children[0].width;
|
||||||
|
|
||||||
|
let isAnimationIn = animationDirection == AnimationDirection.IN;
|
||||||
|
let delay = isAnimationIn ? INDICATORS_ANIMATION_DELAY :
|
||||||
|
INDICATORS_ANIMATION_DELAY_OUT;
|
||||||
|
let baseTime = isAnimationIn ? INDICATORS_BASE_TIME : INDICATORS_BASE_TIME_OUT;
|
||||||
|
let totalAnimationTime = baseTime + delay * this._nPages;
|
||||||
|
let maxTime = isAnimationIn ? INDICATORS_ANIMATION_MAX_TIME :
|
||||||
|
INDICATORS_ANIMATION_MAX_TIME_OUT;
|
||||||
|
if (totalAnimationTime > maxTime)
|
||||||
|
delay -= (totalAnimationTime - maxTime) / this._nPages;
|
||||||
|
|
||||||
|
for (let i = 0; i < this._nPages; i++) {
|
||||||
|
children[i].translation_x = isAnimationIn ? offset : 0;
|
||||||
|
Tweener.addTween(children[i], {
|
||||||
|
translation_x: isAnimationIn ? 0 : offset,
|
||||||
|
time: baseTime + delay * i,
|
||||||
|
transition: 'easeInOutQuad',
|
||||||
|
delay: isAnimationIn ? ANIMATION_DELAY : 0
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
Loading…
Reference in New Issue
Block a user