feat: align focus/active methods

This commit is contained in:
mathuo 2024-01-27 20:26:00 +00:00
parent b901f4de0c
commit 586400019f
No known key found for this signature in database
GPG Key ID: C6EEDEFD6CA07281
10 changed files with 65 additions and 28 deletions

View File

@ -106,6 +106,8 @@ export class DockviewPanelApiImpl
this._group = group;
this.addDisposables(
this.disposable,
this._onDidRendererChange,

View File

@ -1,4 +1,4 @@
import { Emitter, Event } from '../events';
import { DockviewEvent, Emitter, Event } from '../events';
import { CompositeDisposable, MutableDisposable } from '../lifecycle';
import { IPanel, Parameters } from '../panel/types';
@ -51,6 +51,14 @@ export interface PanelApi {
* The panel height in pixels
*/
readonly height: number;
readonly onWillFocus: Event<WillFocusEvent>;
}
export class WillFocusEvent extends DockviewEvent {
constructor() {
super();
}
}
/**
@ -75,8 +83,8 @@ export class PanelApiImpl extends CompositeDisposable implements PanelApi {
});
readonly onDidFocusChange: Event<FocusEvent> = this._onDidChangeFocus.event;
//
readonly _onFocusEvent = new Emitter<void>();
readonly onFocusEvent: Event<void> = this._onFocusEvent.event;
readonly _onWillFocus = new Emitter<WillFocusEvent>();
readonly onWillFocus: Event<WillFocusEvent> = this._onWillFocus.event;
//
readonly _onDidVisibilityChange = new Emitter<VisibilityEvent>({
replay: true,
@ -101,7 +109,6 @@ export class PanelApiImpl extends CompositeDisposable implements PanelApi {
readonly _onUpdateParameters = new Emitter<Parameters>();
readonly onUpdateParameters: Event<Parameters> =
this._onUpdateParameters.event;
//
get isFocused() {
return this._isFocused;
@ -144,10 +151,11 @@ export class PanelApiImpl extends CompositeDisposable implements PanelApi {
this._onDidChangeFocus,
this._onDidVisibilityChange,
this._onDidActiveChange,
this._onFocusEvent,
this._onWillFocus,
this._onActiveChange,
this._onVisibilityChange,
this._onUpdateParameters
this._onUpdateParameters,
this._onWillFocus
);
}

View File

@ -386,9 +386,7 @@ export class TabsContainer
return;
}
this.group.model.openPanel(panel, {
skipFocus: alreadyFocused,
});
this.group.model.openPanel(panel);
}),
tab.onDrop((event) => {
this._onDrop.fire({

View File

@ -1609,10 +1609,9 @@ export class DockviewComponent
doSetGroupAndPanelActive(
group: DockviewGroupPanel | undefined,
skipFocus?: boolean
): void {
const activePanel = this.activePanel;
super.doSetGroupActive(group, skipFocus);
super.doSetGroupActive(group);
if (this._activeGroup?.activePanel !== activePanel) {
this._onDidActivePanelChange.fire(this._activeGroup?.activePanel);

View File

@ -323,7 +323,7 @@ export class DockviewGroupPanelModel
this.handleDropEvent(event.event, 'center', event.index);
}),
this.contentContainer.onDidFocus(() => {
this.accessor.doSetGroupActive(this.groupPanel, true);
this.accessor.doSetGroupActive(this.groupPanel);
}),
this.contentContainer.onDidBlur(() => {
// noop
@ -340,6 +340,10 @@ export class DockviewGroupPanelModel
);
}
focusContent(): void {
this.contentContainer.element.focus();
}
initialize(): void {
if (this.options?.panels) {
this.options.panels.forEach((panel) => {
@ -504,7 +508,6 @@ export class DockviewGroupPanelModel
panel: IDockviewPanel,
options: {
index?: number;
skipFocus?: boolean;
skipSetPanelActive?: boolean;
skipSetGroupActive?: boolean;
} = {}
@ -537,10 +540,7 @@ export class DockviewGroupPanelModel
}
if (!skipSetGroupActive) {
this.accessor.doSetGroupActive(
this.groupPanel,
!!options.skipFocus
);
this.accessor.doSetGroupActive(this.groupPanel);
}
this.updateContainer();

View File

@ -10,6 +10,7 @@ import { IPanel, PanelUpdateEvent, Parameters } from '../panel/types';
import { IDockviewPanelModel } from './dockviewPanelModel';
import { DockviewComponent } from './dockviewComponent';
import { DockviewPanelRenderer } from '../overlayRenderContainer';
import { WillFocusEvent } from '../api/panelApi';
export interface IDockviewPanel extends IDisposable, IPanel {
readonly view: IDockviewPanelModel;
@ -93,7 +94,24 @@ export class DockviewPanel
}
focus(): void {
this.api._onFocusEvent.fire();
/**
* This is a progmatic request of focus -
* We need to tell the active panel that it can choose it's focus
* If the panel doesn't choose the panels container for it
*/
if (!this.api.isActive) {
this.api.setActive();
}
const event = new WillFocusEvent();
this.api._onWillFocus.fire(event);
if (event.defaultPrevented) {
return;
}
this.group.model.focusContent();
}
public toJSON(): GroupviewPanelState {

View File

@ -23,6 +23,17 @@ export namespace Event {
};
};
}
export class DockviewEvent {
private _defaultPrevented = false;
get defaultPrevented(): boolean {
return this._defaultPrevented;
}
preventDefault(): void {
this._defaultPrevented = true;
}
}
class LeakageMonitor {
readonly events = new Map<Event<any>, Stacktrace>();

View File

@ -246,22 +246,16 @@ export abstract class BaseGrid<T extends IGridPanelView>
return this._groups.get(id)?.value;
}
public doSetGroupActive(group: T | undefined, skipFocus?: boolean): void {
public doSetGroupActive(group: T | undefined): void {
if (this._activeGroup === group) {
return;
}
if (this._activeGroup) {
this._activeGroup.setActive(false);
if (!skipFocus) {
this._activeGroup.focus?.();
}
}
if (group) {
group.setActive(true);
if (!skipFocus) {
group.focus?.();
}
}
this._activeGroup = group;

View File

@ -7,7 +7,7 @@ import {
IPanel,
Parameters,
} from '../panel/types';
import { PanelApi, PanelApiImpl } from '../api/panelApi';
import { PanelApi, PanelApiImpl, WillFocusEvent } from '../api/panelApi';
export interface BasePanelViewState {
readonly id: string;
@ -84,7 +84,14 @@ export abstract class BasePanelView<T extends PanelApiImpl>
}
focus(): void {
this.api._onFocusEvent.fire();
const event = new WillFocusEvent();
this.api._onWillFocus.fire(event);
if (event.defaultPrevented) {
return;
}
this._element.focus();
}
layout(width: number, height: number): void {

View File

@ -22,7 +22,7 @@ export interface IPanel extends IDisposable {
layout(width: number, height: number): void;
update(event: PanelUpdateEvent<Parameters>): void;
toJSON(): object;
focus?(): void;
focus(): void;
}
export interface IFrameworkPart extends IDisposable {