From c5681b1376f609a307b6a01b7de8d45aa5756662 Mon Sep 17 00:00:00 2001 From: Eugene Pankov Date: Sat, 31 Jul 2021 17:57:43 +0200 Subject: [PATCH] allow rearranging panes within a tab --- .../src/components/splitTab.component.ts | 12 +++ .../components/splitTabDropZone.component.ts | 2 +- .../splitTabPaneLabel.component.scss | 34 ++++++++ .../components/splitTabPaneLabel.component.ts | 80 +++++++++++++++++++ tabby-core/src/configDefaults.linux.yaml | 2 + tabby-core/src/configDefaults.macos.yaml | 2 + tabby-core/src/configDefaults.windows.yaml | 2 + tabby-core/src/hotkeys.ts | 4 + tabby-core/src/index.ts | 2 + tabby-terminal/src/frontends/xtermFrontend.ts | 3 - 10 files changed, 139 insertions(+), 4 deletions(-) create mode 100644 tabby-core/src/components/splitTabPaneLabel.component.scss create mode 100644 tabby-core/src/components/splitTabPaneLabel.component.ts diff --git a/tabby-core/src/components/splitTab.component.ts b/tabby-core/src/components/splitTab.component.ts index 742d816f..3e216424 100644 --- a/tabby-core/src/components/splitTab.component.ts +++ b/tabby-core/src/components/splitTab.component.ts @@ -152,6 +152,14 @@ export interface SplitDropZoneInfo { (tabDropped)='onTabDropped($event, dropZone)' > + + `, styles: [require('./splitTab.component.scss')], }) @@ -374,6 +382,10 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit } if (thing instanceof BaseTabComponent) { + if (thing.parent instanceof SplitTabComponent) { + thing.parent.removeTab(thing) + } + thing.removeFromContainer() thing.parent = this } diff --git a/tabby-core/src/components/splitTabDropZone.component.ts b/tabby-core/src/components/splitTabDropZone.component.ts index f784acee..55aea12f 100644 --- a/tabby-core/src/components/splitTabDropZone.component.ts +++ b/tabby-core/src/components/splitTabDropZone.component.ts @@ -34,7 +34,7 @@ export class SplitTabDropZoneComponent extends SelfPositioningComponent { ) { super(element) this.subscribeUntilDestroyed(app.tabDragActive$, tab => { - this.isActive = !!tab && tab !== this.parent + this.isActive = !!tab && tab !== this.parent && tab !== this.dropZone.relativeToTab this.layout() }) } diff --git a/tabby-core/src/components/splitTabPaneLabel.component.scss b/tabby-core/src/components/splitTabPaneLabel.component.scss new file mode 100644 index 00000000..a55d72f6 --- /dev/null +++ b/tabby-core/src/components/splitTabPaneLabel.component.scss @@ -0,0 +1,34 @@ +:host { + position: absolute; + background: rgba(255, 255, 255, .25); + display: flex; + align-items: center; + justify-content: center; + pointer-events: none; + z-index: 10; + opacity: 0; + transition: .125s opacity cubic-bezier(0.86, 0, 0.07, 1); +} + +div { + background: rgba(0, 0, 0, .7); + padding: 20px 30px; + font-size: 18px; + color: #fff; + display: flex; + align-items: center; + border-radius: 5px; + cursor: move; +} + +:host.active { + opacity: 1; + + > div { + pointer-events: initial; + } +} + +label { + margin: 0; +} diff --git a/tabby-core/src/components/splitTabPaneLabel.component.ts b/tabby-core/src/components/splitTabPaneLabel.component.ts new file mode 100644 index 00000000..571abd15 --- /dev/null +++ b/tabby-core/src/components/splitTabPaneLabel.component.ts @@ -0,0 +1,80 @@ +/* eslint-disable @typescript-eslint/explicit-module-boundary-types */ +import { Component, Input, HostBinding, ElementRef } from '@angular/core' +import { HotkeysService } from '../services/hotkeys.service' +import { AppService } from '../services/app.service' +import { BaseTabComponent } from './baseTab.component' +import { SelfPositioningComponent } from './selfPositioning.component' + +/** @hidden */ +@Component({ + selector: 'split-tab-pane-label', + template: ` +
+ + +
+ `, + styles: [require('./splitTabPaneLabel.component.scss')], +}) +export class SplitTabPaneLabelComponent extends SelfPositioningComponent { + @Input() tab: BaseTabComponent + @Input() parent: BaseTabComponent + @HostBinding('class.active') isActive = false + + // eslint-disable-next-line @typescript-eslint/no-useless-constructor + constructor ( + element: ElementRef, + hotkeys: HotkeysService, + private app: AppService, + ) { + super(element) + this.subscribeUntilDestroyed(hotkeys.hotkey$, hk => { + if (hk === 'rearrange-panes' && this.parent.hasFocus) { + this.isActive = true + this.layout() + } + }) + this.subscribeUntilDestroyed(hotkeys.hotkeyOff$, hk => { + if (hk === 'rearrange-panes') { + this.isActive = false + } + }) + } + + ngOnChanges () { + this.layout() + } + + onTabDragStart (tab: BaseTabComponent): void { + this.app.emitTabDragStarted(tab) + } + + onTabDragEnd (): void { + setTimeout(() => { + this.app.emitTabDragEnded() + this.app.emitTabsChanged() + }) + } + + layout () { + const tabElement: HTMLElement|undefined = this.tab.viewContainerEmbeddedRef?.rootNodes[0] + + if (!tabElement) { + // being destroyed + return + } + + this.setDimensions( + tabElement.offsetLeft, + tabElement.offsetTop, + tabElement.clientWidth, + tabElement.clientHeight, + 'px' + ) + } +} diff --git a/tabby-core/src/configDefaults.linux.yaml b/tabby-core/src/configDefaults.linux.yaml index a5cfca77..7cd27e94 100644 --- a/tabby-core/src/configDefaults.linux.yaml +++ b/tabby-core/src/configDefaults.linux.yaml @@ -18,6 +18,8 @@ hotkeys: - 'Ctrl-Shift-PageUp' move-tab-right: - 'Ctrl-Shift-PageDown' + rearrange-panes: + - 'Ctrl-Shift' tab-1: - 'Alt-1' tab-2: diff --git a/tabby-core/src/configDefaults.macos.yaml b/tabby-core/src/configDefaults.macos.yaml index 5c76a1c6..d833eda6 100644 --- a/tabby-core/src/configDefaults.macos.yaml +++ b/tabby-core/src/configDefaults.macos.yaml @@ -16,6 +16,8 @@ hotkeys: - '⌘-Shift-Left' move-tab-right: - '⌘-Shift-Right' + rearrange-panes: + - '⌘-Shift' tab-1: - '⌘-1' tab-2: diff --git a/tabby-core/src/configDefaults.windows.yaml b/tabby-core/src/configDefaults.windows.yaml index cb2517d6..5afd4112 100644 --- a/tabby-core/src/configDefaults.windows.yaml +++ b/tabby-core/src/configDefaults.windows.yaml @@ -19,6 +19,8 @@ hotkeys: - 'Ctrl-Shift-PageUp' move-tab-right: - 'Ctrl-Shift-PageDown' + rearrange-panes: + - 'Ctrl-Shift' tab-1: - 'Alt-1' tab-2: diff --git a/tabby-core/src/hotkeys.ts b/tabby-core/src/hotkeys.ts index d96a82f3..22efc28a 100644 --- a/tabby-core/src/hotkeys.ts +++ b/tabby-core/src/hotkeys.ts @@ -46,6 +46,10 @@ export class AppHotkeyProvider extends HotkeyProvider { id: 'move-tab-right', name: 'Move tab to the right', }, + { + id: 'rearrange-panes', + name: 'Show pane labels (for rearranging)', + }, { id: 'tab-1', name: 'Tab 1', diff --git a/tabby-core/src/index.ts b/tabby-core/src/index.ts index b58e3335..ea1a388c 100644 --- a/tabby-core/src/index.ts +++ b/tabby-core/src/index.ts @@ -23,6 +23,7 @@ import { SelectorModalComponent } from './components/selectorModal.component' import { SplitTabComponent, SplitTabRecoveryProvider } from './components/splitTab.component' import { SplitTabSpannerComponent } from './components/splitTabSpanner.component' import { SplitTabDropZoneComponent } from './components/splitTabDropZone.component' +import { SplitTabPaneLabelComponent } from './components/splitTabPaneLabel.component' import { UnlockVaultModalComponent } from './components/unlockVaultModal.component' import { WelcomeTabComponent } from './components/welcomeTab.component' import { TransfersMenuComponent } from './components/transfersMenu.component' @@ -100,6 +101,7 @@ const PROVIDERS = [ SplitTabComponent, SplitTabSpannerComponent, SplitTabDropZoneComponent, + SplitTabPaneLabelComponent, UnlockVaultModalComponent, WelcomeTabComponent, TransfersMenuComponent, diff --git a/tabby-terminal/src/frontends/xtermFrontend.ts b/tabby-terminal/src/frontends/xtermFrontend.ts index e46017d5..bc56ece7 100644 --- a/tabby-terminal/src/frontends/xtermFrontend.ts +++ b/tabby-terminal/src/frontends/xtermFrontend.ts @@ -92,9 +92,6 @@ export class XTermFrontend extends Frontend { event.preventDefault() ret = false } - this.hotkeysService.processKeystrokes() - this.hotkeysService.emitKeyEvent(event) - return ret }