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

View File

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

View File

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

View File

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

View File

@ -10,6 +10,7 @@ import { IPanel, PanelUpdateEvent, Parameters } from '../panel/types';
import { IDockviewPanelModel } from './dockviewPanelModel'; import { IDockviewPanelModel } from './dockviewPanelModel';
import { DockviewComponent } from './dockviewComponent'; import { DockviewComponent } from './dockviewComponent';
import { DockviewPanelRenderer } from '../overlayRenderContainer'; import { DockviewPanelRenderer } from '../overlayRenderContainer';
import { WillFocusEvent } from '../api/panelApi';
export interface IDockviewPanel extends IDisposable, IPanel { export interface IDockviewPanel extends IDisposable, IPanel {
readonly view: IDockviewPanelModel; readonly view: IDockviewPanelModel;
@ -93,7 +94,24 @@ export class DockviewPanel
} }
focus(): void { 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 { 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 { class LeakageMonitor {
readonly events = new Map<Event<any>, Stacktrace>(); 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; return this._groups.get(id)?.value;
} }
public doSetGroupActive(group: T | undefined, skipFocus?: boolean): void { public doSetGroupActive(group: T | undefined): void {
if (this._activeGroup === group) { if (this._activeGroup === group) {
return; return;
} }
if (this._activeGroup) { if (this._activeGroup) {
this._activeGroup.setActive(false); this._activeGroup.setActive(false);
if (!skipFocus) {
this._activeGroup.focus?.();
}
} }
if (group) { if (group) {
group.setActive(true); group.setActive(true);
if (!skipFocus) {
group.focus?.();
}
} }
this._activeGroup = group; this._activeGroup = group;

View File

@ -7,7 +7,7 @@ import {
IPanel, IPanel,
Parameters, Parameters,
} from '../panel/types'; } from '../panel/types';
import { PanelApi, PanelApiImpl } from '../api/panelApi'; import { PanelApi, PanelApiImpl, WillFocusEvent } from '../api/panelApi';
export interface BasePanelViewState { export interface BasePanelViewState {
readonly id: string; readonly id: string;
@ -84,7 +84,14 @@ export abstract class BasePanelView<T extends PanelApiImpl>
} }
focus(): void { 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 { layout(width: number, height: number): void {

View File

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