diff --git a/packages/sprotty/src/features/select/select.ts b/packages/sprotty/src/features/select/select.ts index bfbef39f..2b631637 100644 --- a/packages/sprotty/src/features/select/select.ts +++ b/packages/sprotty/src/features/select/select.ts @@ -36,6 +36,7 @@ import { SButton } from '../button/model'; import { SwitchEditModeAction } from '../edit/edit-routing'; import { SRoutingHandle } from '../routing/model'; import { SRoutableElement } from '../routing/model'; +import { findViewportScrollbar } from '../viewport/scroll'; import { isSelectable, Selectable } from './model'; /** @@ -212,12 +213,12 @@ export class SelectMouseListener extends MouseListener { const selectableTarget = findParentByFeature(target, isSelectable); if (selectableTarget !== undefined || target instanceof SModelRoot) { this.hasDragged = false; + } + if (selectableTarget !== undefined) { let deselectedElements: SModelElement[] = []; // multi-selection? if (!isCtrlOrCmd(event)) { - deselectedElements = toArray(target.root.index.all() - .filter(element => isSelectable(element) && element.selected - && !(selectableTarget instanceof SRoutingHandle && element === selectableTarget.parent as SModelElement))); + deselectedElements = this.collectElementsToDeselect(target, selectableTarget); } if (selectableTarget !== undefined) { if (!selectableTarget.selected) { @@ -236,6 +237,12 @@ export class SelectMouseListener extends MouseListener { return []; } + protected collectElementsToDeselect(target: SModelElement, selectableTarget: (SModelElement & Selectable) | undefined): SModelElement[] { + return toArray(target.root.index.all() + .filter(element => isSelectable(element) && element.selected + && !(selectableTarget instanceof SRoutingHandle && element === selectableTarget.parent as SModelElement))); + } + protected handleButton(target: SModelElement, event: MouseEvent): (Action | Promise)[] | undefined { if (this.buttonHandlerRegistry !== undefined && target instanceof SButton && target.enabled) { const buttonHandler = this.buttonHandlerRegistry.get(target.type); @@ -283,12 +290,17 @@ export class SelectMouseListener extends MouseListener { return []; } - override mouseUp(target: SModelElement, event: MouseEvent): Action[] { + override mouseUp(target: SModelElement, event: MouseEvent): (Action | Promise)[] { if (event.button === 0) { if (!this.hasDragged) { const selectableTarget = findParentByFeature(target, isSelectable); - if (selectableTarget !== undefined && this.wasSelected) { - return [new SelectAction([selectableTarget.id], [])]; + if (selectableTarget !== undefined) { + if (this.wasSelected) { + return [new SelectAction([selectableTarget.id], [])]; + } + } else if (target instanceof SModelRoot && !findViewportScrollbar(event)) { + // Mouse up on root but not over ViewPort's scroll bars > deselect all + return this.handleDeselectAll(this.collectElementsToDeselect(target, undefined), event); } } } diff --git a/packages/sprotty/src/features/viewport/scroll.ts b/packages/sprotty/src/features/viewport/scroll.ts index 6dbd968b..e5fe8313 100644 --- a/packages/sprotty/src/features/viewport/scroll.ts +++ b/packages/sprotty/src/features/viewport/scroll.ts @@ -180,14 +180,7 @@ export class ScrollMouseListener extends MouseListener { } protected getScrollbar(event: MouseEvent): HTMLElement | undefined { - let element = event.target as HTMLElement | null; - while (element) { - if (element.classList && element.classList.contains('sprotty-projection-bar')) { - return element; - } - element = element.parentElement; - } - return undefined; + return findViewportScrollbar(event); } protected getScrollbarOrientation(scrollbar: HTMLElement): 'horizontal' | 'vertical' { @@ -209,3 +202,14 @@ export class ScrollMouseListener extends MouseListener { } } + +export function findViewportScrollbar(event: MouseEvent): HTMLElement | undefined { + let element = event.target as HTMLElement | null; + while (element) { + if (element.classList && element.classList.contains('sprotty-projection-bar')) { + return element; + } + element = element.parentElement; + } + return undefined; +}