js/appDisplay: Implement side page previews while DnDing
When DnDing an icon, we show both previous/next page, and optionally a "placeholder" actor to allow creating new pages. These sides on the scrollview are drop targets themselves, allowing to drop an app onto the next/prev page without further navigation. Still, preserve the checks to maybe switch to prev/next page without finishing the DnD operation, for finer grained operations. Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1630>
This commit is contained in:
parent
d75ed55ed8
commit
a00db66ffe
@ -141,6 +141,10 @@ $app_grid_fg_color: #fff;
|
|||||||
background: rgba(255, 255, 255, 0.05);
|
background: rgba(255, 255, 255, 0.05);
|
||||||
width: 88px;
|
width: 88px;
|
||||||
|
|
||||||
|
&.dnd {
|
||||||
|
background: rgba(255, 255, 255, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
&.next {
|
&.next {
|
||||||
&:ltr { border-radius: 15px 0px 0px 15px; }
|
&:ltr { border-radius: 15px 0px 0px 15px; }
|
||||||
&:rtl { border-radius: 0px 15px 15px 0px; }
|
&:rtl { border-radius: 0px 15px 15px 0px; }
|
||||||
|
@ -56,6 +56,7 @@ var SidePages = {
|
|||||||
NONE: 0,
|
NONE: 0,
|
||||||
PREVIOUS: 1 << 0,
|
PREVIOUS: 1 << 0,
|
||||||
NEXT: 1 << 1,
|
NEXT: 1 << 1,
|
||||||
|
DND: 1 << 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
function _getCategories(info) {
|
function _getCategories(info) {
|
||||||
@ -155,6 +156,7 @@ var BaseAppView = GObject.registerClass({
|
|||||||
enable_mouse_scrolling: false,
|
enable_mouse_scrolling: false,
|
||||||
});
|
});
|
||||||
this._scrollView.set_policy(St.PolicyType.EXTERNAL, St.PolicyType.NEVER);
|
this._scrollView.set_policy(St.PolicyType.EXTERNAL, St.PolicyType.NEVER);
|
||||||
|
this._scrollView._delegate = this;
|
||||||
|
|
||||||
this._canScroll = true; // limiting scrolling speed
|
this._canScroll = true; // limiting scrolling speed
|
||||||
this._scrollTimeoutId = 0;
|
this._scrollTimeoutId = 0;
|
||||||
@ -607,6 +609,7 @@ var BaseAppView = GObject.registerClass({
|
|||||||
dragMotion: this._onDragMotion.bind(this),
|
dragMotion: this._onDragMotion.bind(this),
|
||||||
};
|
};
|
||||||
DND.addDragMonitor(this._dragMonitor);
|
DND.addDragMonitor(this._dragMonitor);
|
||||||
|
this._slideSidePages(SidePages.PREVIOUS | SidePages.NEXT | SidePages.DND);
|
||||||
}
|
}
|
||||||
|
|
||||||
_onDragMotion(dragEvent) {
|
_onDragMotion(dragEvent) {
|
||||||
@ -615,6 +618,14 @@ var BaseAppView = GObject.registerClass({
|
|||||||
|
|
||||||
const appIcon = dragEvent.source;
|
const appIcon = dragEvent.source;
|
||||||
|
|
||||||
|
this._dropPage = this._pageForCoords(dragEvent.x, dragEvent.y);
|
||||||
|
if (this._dropPage &&
|
||||||
|
this._dropPage === SidePages.PREVIOUS &&
|
||||||
|
this._grid.currentPage === 0) {
|
||||||
|
delete this._dropPage;
|
||||||
|
return DND.DragMotionResult.NO_DROP;
|
||||||
|
}
|
||||||
|
|
||||||
// Handle the drag overshoot. When dragging to above the
|
// Handle the drag overshoot. When dragging to above the
|
||||||
// icon grid, move to the page above; when dragging below,
|
// icon grid, move to the page above; when dragging below,
|
||||||
// move to the page below.
|
// move to the page below.
|
||||||
@ -633,12 +644,15 @@ var BaseAppView = GObject.registerClass({
|
|||||||
}
|
}
|
||||||
|
|
||||||
this._resetOvershoot();
|
this._resetOvershoot();
|
||||||
|
this._slideSidePages(SidePages.NONE);
|
||||||
|
delete this._dropPage;
|
||||||
}
|
}
|
||||||
|
|
||||||
_onDragCancelled() {
|
_onDragCancelled() {
|
||||||
// At this point, the positions aren't stored yet, thus _redisplay()
|
// At this point, the positions aren't stored yet, thus _redisplay()
|
||||||
// will move all items to their original positions
|
// will move all items to their original positions
|
||||||
this._redisplay();
|
this._redisplay();
|
||||||
|
this._slideSidePages(SidePages.NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
_canAccept(source) {
|
_canAccept(source) {
|
||||||
@ -656,8 +670,16 @@ var BaseAppView = GObject.registerClass({
|
|||||||
if (!this._canAccept(source))
|
if (!this._canAccept(source))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (this._dropPage) {
|
||||||
|
const increment = this._dropPage === SidePages.NEXT ? 1 : -1;
|
||||||
|
const { currentPage, nPages } = this._grid;
|
||||||
|
const page = Math.min(currentPage + increment, nPages);
|
||||||
|
const position = page < nPages ? -1 : 0;
|
||||||
|
|
||||||
|
this._moveItem(source, page, position);
|
||||||
|
this.goToPage(page);
|
||||||
|
} else if (this._delayedMoveData) {
|
||||||
// Dropped before the icon was moved
|
// Dropped before the icon was moved
|
||||||
if (this._delayedMoveData) {
|
|
||||||
const { page, position } = this._delayedMoveData;
|
const { page, position } = this._delayedMoveData;
|
||||||
|
|
||||||
this._moveItem(source, page, position);
|
this._moveItem(source, page, position);
|
||||||
@ -1048,10 +1070,17 @@ var BaseAppView = GObject.registerClass({
|
|||||||
let translationX = (1 - adjustment.value) * 100 * page;
|
let translationX = (1 - adjustment.value) * 100 * page;
|
||||||
translationX = rtl ? -translationX : translationX;
|
translationX = rtl ? -translationX : translationX;
|
||||||
const nextPage = this._grid.currentPage + page;
|
const nextPage = this._grid.currentPage + page;
|
||||||
if (nextPage >= 0 &&
|
const hasFollowingPage = nextPage >= 0 &&
|
||||||
nextPage < this._grid.nPages - 1) {
|
nextPage < this._grid.nPages;
|
||||||
|
|
||||||
|
if (hasFollowingPage) {
|
||||||
const items = this._grid.getItemsAtPage(nextPage);
|
const items = this._grid.getItemsAtPage(nextPage);
|
||||||
items.forEach(item => (item.translation_x = translationX));
|
items.forEach(item => (item.translation_x = translationX));
|
||||||
|
}
|
||||||
|
if (hasFollowingPage ||
|
||||||
|
(page > 0 &&
|
||||||
|
this._grid.layout_manager.allow_incomplete_pages &&
|
||||||
|
(state & SidePages.DND) !== 0)) {
|
||||||
indicator.set({
|
indicator.set({
|
||||||
visible: true,
|
visible: true,
|
||||||
opacity: adjustment.value * 255,
|
opacity: adjustment.value * 255,
|
||||||
@ -1085,8 +1114,17 @@ var BaseAppView = GObject.registerClass({
|
|||||||
this._pagesShown = state;
|
this._pagesShown = state;
|
||||||
const showingNextPage = state & SidePages.NEXT;
|
const showingNextPage = state & SidePages.NEXT;
|
||||||
const showingPrevPage = state & SidePages.PREVIOUS;
|
const showingPrevPage = state & SidePages.PREVIOUS;
|
||||||
|
const dnd = state & SidePages.DND;
|
||||||
let adjustment;
|
let adjustment;
|
||||||
|
|
||||||
|
if (dnd) {
|
||||||
|
this._nextPageIndicator.add_style_class_name('dnd');
|
||||||
|
this._prevPageIndicator.add_style_class_name('dnd');
|
||||||
|
} else {
|
||||||
|
this._nextPageIndicator.remove_style_class_name('dnd');
|
||||||
|
this._prevPageIndicator.remove_style_class_name('dnd');
|
||||||
|
}
|
||||||
|
|
||||||
adjustment = this._getPagePreviewAdjustment(1);
|
adjustment = this._getPagePreviewAdjustment(1);
|
||||||
if (showingNextPage) {
|
if (showingNextPage) {
|
||||||
adjustment = this._setupPagePreview(1, state);
|
adjustment = this._setupPagePreview(1, state);
|
||||||
|
Loading…
Reference in New Issue
Block a user