feat: manually mirror opencoze's code from bytedance
Change-Id: I09a73aadda978ad9511264a756b2ce51f5761adf
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { inject, injectable } from 'inversify';
|
||||
|
||||
import { DebugBarWidget } from '../widget/react-widgets/debug-bar-widget';
|
||||
import { createPortal } from '../utils';
|
||||
import { ApplicationShell } from '../shell/application-shell';
|
||||
import { ViewOptions } from '../constants/view-options';
|
||||
|
||||
// 控制 debug
|
||||
@injectable()
|
||||
export class DebugService {
|
||||
@inject(ViewOptions) viewOptions: ViewOptions;
|
||||
|
||||
@inject(ApplicationShell) shell: ApplicationShell;
|
||||
|
||||
@inject(DebugBarWidget) debugBarWidget: DebugBarWidget;
|
||||
|
||||
show() {
|
||||
this.debugBarWidget.show();
|
||||
this.debugBarWidget.update();
|
||||
}
|
||||
|
||||
hide() {
|
||||
this.debugBarWidget.hide();
|
||||
this.debugBarWidget.update();
|
||||
}
|
||||
|
||||
createPortal() {
|
||||
const originRenderer = this.debugBarWidget.render.bind(this.debugBarWidget);
|
||||
const portal = createPortal(
|
||||
this.debugBarWidget,
|
||||
originRenderer,
|
||||
this.viewOptions.widgetFallbackRender!,
|
||||
);
|
||||
this.shell.node.insertBefore(this.debugBarWidget.node, null);
|
||||
this.hide();
|
||||
return portal;
|
||||
}
|
||||
}
|
||||
104
frontend/packages/project-ide/view/src/services/drag-service.ts
Normal file
104
frontend/packages/project-ide/view/src/services/drag-service.ts
Normal file
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { inject, injectable } from 'inversify';
|
||||
import { type URI } from '@coze-project-ide/core';
|
||||
|
||||
import { WidgetManager } from '../widget-manager';
|
||||
import { type ReactWidget } from '../widget/react-widget';
|
||||
import { ViewRenderer } from '../view-renderer';
|
||||
import { ApplicationShell } from '../shell';
|
||||
import { Drag } from '../lumino/dragdrop';
|
||||
import { MimeData } from '../lumino/coreutils';
|
||||
|
||||
export interface DragPropsType {
|
||||
/**
|
||||
* 拖拽打开分屏的 URI
|
||||
*/
|
||||
uris: URI[];
|
||||
/**
|
||||
* startDrag event 位置数据
|
||||
*/
|
||||
position: {
|
||||
clientX: number;
|
||||
clientY: number;
|
||||
};
|
||||
/**
|
||||
* 拖拽元素回显,不传不展示
|
||||
*/
|
||||
dragImage?: HTMLElement;
|
||||
/**
|
||||
* 拖拽完成后回调
|
||||
* action: 'move' | 'copy' | 'link' | 'none'
|
||||
*/
|
||||
callback: (action: Drag.DropAction) => void;
|
||||
backdropTransform?: Drag.BackDropTransform;
|
||||
}
|
||||
|
||||
/**
|
||||
* DragService 主要用于分屏操作
|
||||
*/
|
||||
@injectable()
|
||||
export class DragService {
|
||||
@inject(ApplicationShell) shell: ApplicationShell;
|
||||
|
||||
@inject(WidgetManager) widgetManager: WidgetManager;
|
||||
|
||||
@inject(ViewRenderer) viewRenderer: ViewRenderer;
|
||||
|
||||
/**
|
||||
* 业务侧手动拖拽触发分屏(侧边栏文件树拖拽进入开始分屏)
|
||||
*/
|
||||
startDrag({
|
||||
uris,
|
||||
position,
|
||||
dragImage,
|
||||
callback,
|
||||
backdropTransform,
|
||||
}: DragPropsType) {
|
||||
const { clientX, clientY } = position;
|
||||
const mimeData = new MimeData();
|
||||
const factory = async () => {
|
||||
const widgets: ReactWidget[] = [];
|
||||
await Promise.all(
|
||||
uris.map(async uri => {
|
||||
const factory = this.widgetManager.getFactoryFromURI(uri)!;
|
||||
const widget = await this.widgetManager.getOrCreateWidgetFromURI(
|
||||
uri,
|
||||
factory,
|
||||
);
|
||||
this.viewRenderer.addReactPortal(widget);
|
||||
widgets.push(widget);
|
||||
}),
|
||||
);
|
||||
return widgets;
|
||||
};
|
||||
mimeData.setData('application/vnd.lumino.widget-factory', factory);
|
||||
const drag = new Drag({
|
||||
document,
|
||||
mimeData,
|
||||
dragImage,
|
||||
proposedAction: 'move',
|
||||
supportedActions: 'move',
|
||||
/**
|
||||
* 仅支持在主面板区域分屏
|
||||
*/
|
||||
source: this.shell.mainPanel,
|
||||
backdropTransform,
|
||||
});
|
||||
drag.start(clientX, clientY).then(callback);
|
||||
}
|
||||
}
|
||||
315
frontend/packages/project-ide/view/src/services/hover-service.ts
Normal file
315
frontend/packages/project-ide/view/src/services/hover-service.ts
Normal file
@@ -0,0 +1,315 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import type React from 'react';
|
||||
|
||||
import { type Root, createRoot } from 'react-dom/client';
|
||||
import { inject, injectable } from 'inversify';
|
||||
import {
|
||||
type Disposable,
|
||||
DisposableCollection,
|
||||
} from '@flowgram-adapter/common';
|
||||
import { LabelService } from '@coze-project-ide/core';
|
||||
|
||||
import { HOVER_TOOLTIP_LABEL } from '../constants';
|
||||
|
||||
export function createDisposableTimer(
|
||||
...args: Parameters<typeof setTimeout>
|
||||
): Disposable {
|
||||
const handle = setTimeout(...args);
|
||||
return { dispose: () => clearTimeout(handle) };
|
||||
}
|
||||
export function animationFrame(n = 1): Promise<void> {
|
||||
return new Promise(resolve => {
|
||||
function frameFunc(): void {
|
||||
if (n <= 0) {
|
||||
resolve();
|
||||
} else {
|
||||
n--;
|
||||
requestAnimationFrame(frameFunc);
|
||||
}
|
||||
}
|
||||
frameFunc();
|
||||
});
|
||||
}
|
||||
|
||||
export type HoverPosition = 'left' | 'right' | 'top' | 'bottom';
|
||||
|
||||
export namespace HoverPosition {
|
||||
export function invertIfNecessary(
|
||||
position: HoverPosition,
|
||||
target: DOMRect,
|
||||
host: DOMRect,
|
||||
totalWidth: number,
|
||||
totalHeight: number,
|
||||
enableCustomHost: boolean,
|
||||
): HoverPosition {
|
||||
if (position === 'left') {
|
||||
if (enableCustomHost) {
|
||||
if (target.left - target.width < 0) {
|
||||
return 'right';
|
||||
}
|
||||
} else if (target.left - host.width < 0) {
|
||||
return 'right';
|
||||
}
|
||||
} else if (position === 'right') {
|
||||
if (enableCustomHost) {
|
||||
if (target.right + target.width > totalWidth) {
|
||||
return 'left';
|
||||
}
|
||||
} else if (target.right + host.width > totalWidth) {
|
||||
return 'left';
|
||||
}
|
||||
} else if (position === 'top') {
|
||||
if (enableCustomHost) {
|
||||
if (target.top - target.height < 0) {
|
||||
return 'bottom';
|
||||
}
|
||||
} else if (target.top - host.height < 0) {
|
||||
return 'bottom';
|
||||
}
|
||||
} else if (position === 'bottom') {
|
||||
if (enableCustomHost) {
|
||||
if (target.bottom + target.height > totalHeight) {
|
||||
return 'top';
|
||||
}
|
||||
} else if (target.bottom + host.height > totalHeight) {
|
||||
return 'top';
|
||||
}
|
||||
}
|
||||
return position;
|
||||
}
|
||||
}
|
||||
|
||||
export interface HoverRequest {
|
||||
content: string | HTMLElement | React.ReactNode;
|
||||
target: HTMLElement;
|
||||
position: HoverPosition;
|
||||
cssClasses?: string[];
|
||||
visualPreview?: (width: number) => HTMLElement | undefined;
|
||||
/** hover 位置偏移 */
|
||||
offset?: number;
|
||||
}
|
||||
|
||||
@injectable()
|
||||
export class HoverService {
|
||||
@inject(LabelService) labelService: LabelService;
|
||||
|
||||
protected static hostClassName = 'flow-hover';
|
||||
|
||||
protected static styleSheetId = 'flow-hover-style';
|
||||
|
||||
protected _hoverHost: HTMLElement | undefined;
|
||||
|
||||
reactRoot: Root | null = null;
|
||||
|
||||
protected get hoverHost(): HTMLElement {
|
||||
if (!this._hoverHost) {
|
||||
this._hoverHost = document.createElement('div');
|
||||
this._hoverHost.classList.add(HoverService.hostClassName);
|
||||
this._hoverHost.style.position = 'absolute';
|
||||
}
|
||||
return this._hoverHost;
|
||||
}
|
||||
|
||||
protected pendingTimeout: Disposable | undefined;
|
||||
|
||||
protected hoverTarget: HTMLElement | undefined;
|
||||
|
||||
protected lastHidHover = Date.now();
|
||||
|
||||
protected enableCustomHost = false;
|
||||
|
||||
// protected timer: any = null;
|
||||
|
||||
protected readonly disposeOnHide = new DisposableCollection();
|
||||
|
||||
enableCustomHoverHost() {
|
||||
if (!this._hoverHost) {
|
||||
this.enableCustomHost = true;
|
||||
this._hoverHost = document.createElement('div');
|
||||
this.reactRoot = createRoot(this._hoverHost);
|
||||
this._hoverHost.style.position = 'absolute';
|
||||
}
|
||||
}
|
||||
|
||||
requestHover(r: HoverRequest): void {
|
||||
if (r.target !== this.hoverTarget) {
|
||||
this.cancelHover();
|
||||
// clearTimeout(this.timer);
|
||||
this.pendingTimeout = createDisposableTimer(
|
||||
() => this.renderHover(r),
|
||||
this.getHoverDelay(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
protected async renderHover(request: HoverRequest): Promise<void> {
|
||||
const host = this.hoverHost;
|
||||
let firstChild: HTMLElement | undefined;
|
||||
const { target, content, position, cssClasses, offset } = request;
|
||||
if (cssClasses) {
|
||||
host.classList.add(...cssClasses);
|
||||
}
|
||||
this.hoverTarget = target;
|
||||
|
||||
if (!this.reactRoot && content instanceof HTMLElement) {
|
||||
host.appendChild(content);
|
||||
firstChild = content;
|
||||
} else if (!this.reactRoot && typeof content === 'string') {
|
||||
host.textContent = content;
|
||||
}
|
||||
|
||||
host.style.top = '0px';
|
||||
host.style.left = '0px';
|
||||
document.body.append(host);
|
||||
|
||||
if (request.visualPreview) {
|
||||
const width = firstChild
|
||||
? firstChild.offsetWidth
|
||||
: this.hoverHost.offsetWidth;
|
||||
const visualPreview = request.visualPreview(width);
|
||||
if (visualPreview) {
|
||||
host.appendChild(visualPreview);
|
||||
}
|
||||
}
|
||||
|
||||
await animationFrame();
|
||||
const newPos = this.setHostPosition(target, host, position, offset);
|
||||
|
||||
if (this.reactRoot) {
|
||||
const renderer = this.labelService.renderer(HOVER_TOOLTIP_LABEL, {
|
||||
content,
|
||||
position: newPos,
|
||||
key: new Date().getTime(),
|
||||
});
|
||||
this.reactRoot.render(renderer);
|
||||
}
|
||||
|
||||
this.disposeOnHide.push({
|
||||
dispose: () => {
|
||||
this.lastHidHover = Date.now();
|
||||
host.classList.remove(newPos);
|
||||
if (cssClasses) {
|
||||
host.classList.remove(...cssClasses);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
this.listenForMouseOut();
|
||||
}
|
||||
|
||||
protected listenForMouseOut(): void {
|
||||
const handleMouseMove = (e: MouseEvent) => {
|
||||
if (!this.hoverTarget) {
|
||||
return;
|
||||
}
|
||||
if (
|
||||
e.target instanceof Node &&
|
||||
!this.hoverHost.contains(e.target) &&
|
||||
!this.hoverTarget?.contains(e.target)
|
||||
) {
|
||||
// clearTimeout(this.timer);
|
||||
// this.timer = setTimeout(() => {
|
||||
// this.cancelHover();
|
||||
// }, 300);
|
||||
this.cancelHover();
|
||||
}
|
||||
};
|
||||
document.addEventListener('mousemove', handleMouseMove);
|
||||
this.disposeOnHide.push({
|
||||
dispose: () => document.removeEventListener('mousemove', handleMouseMove),
|
||||
});
|
||||
}
|
||||
|
||||
protected getHoverDelay(): number {
|
||||
return Date.now() - this.lastHidHover < 200 ? 0 : 200;
|
||||
}
|
||||
|
||||
protected setHostPosition(
|
||||
target: HTMLElement,
|
||||
host: HTMLElement,
|
||||
position: HoverPosition,
|
||||
offset?: number,
|
||||
): HoverPosition {
|
||||
const hostRect = host.getBoundingClientRect();
|
||||
const targetRect = target.getBoundingClientRect();
|
||||
const documentHeight = document.documentElement.scrollHeight;
|
||||
const documentWidth = document.body.getBoundingClientRect().width;
|
||||
const calcOffset = offset || 0;
|
||||
|
||||
position = HoverPosition.invertIfNecessary(
|
||||
position,
|
||||
targetRect,
|
||||
hostRect,
|
||||
documentWidth,
|
||||
documentHeight,
|
||||
this.enableCustomHost,
|
||||
);
|
||||
|
||||
if (position === 'top' || position === 'bottom') {
|
||||
const targetMiddleWidth = targetRect.left + targetRect.width / 2;
|
||||
const middleAlignment = targetMiddleWidth - hostRect.width / 2;
|
||||
const furthestRight = Math.min(
|
||||
documentWidth - hostRect.width,
|
||||
middleAlignment,
|
||||
);
|
||||
const top =
|
||||
position === 'top'
|
||||
? targetRect.top - hostRect.height + calcOffset
|
||||
: targetRect.bottom - calcOffset;
|
||||
const left = Math.max(0, furthestRight);
|
||||
host.style.top = `${top}px`;
|
||||
host.style.left = `${left}px`;
|
||||
} else {
|
||||
const targetMiddleHeight = targetRect.top + targetRect.height / 2;
|
||||
const middleAlignment = targetMiddleHeight - hostRect.height / 2;
|
||||
const furthestTop = Math.min(
|
||||
documentHeight - hostRect.height,
|
||||
middleAlignment,
|
||||
);
|
||||
const left =
|
||||
position === 'left'
|
||||
? targetRect.left - hostRect.width - calcOffset
|
||||
: targetRect.right + calcOffset;
|
||||
const top = Math.max(0, furthestTop);
|
||||
host.style.left = `${left}px`;
|
||||
host.style.top = `${top}px`;
|
||||
}
|
||||
host.classList.add(position);
|
||||
return position;
|
||||
}
|
||||
|
||||
protected unRender(): void {
|
||||
this.hoverHost.remove();
|
||||
this.hoverHost.replaceChildren();
|
||||
}
|
||||
|
||||
cancelHover(): void {
|
||||
if (this.reactRoot) {
|
||||
const renderer = this.labelService.renderer(HOVER_TOOLTIP_LABEL, {
|
||||
visible: false,
|
||||
key: new Date().getTime(),
|
||||
});
|
||||
this.reactRoot.render(renderer);
|
||||
} else {
|
||||
this.unRender();
|
||||
}
|
||||
this.pendingTimeout?.dispose();
|
||||
this.disposeOnHide.dispose();
|
||||
this.hoverTarget = undefined;
|
||||
}
|
||||
}
|
||||
222
frontend/packages/project-ide/view/src/services/view-service.ts
Normal file
222
frontend/packages/project-ide/view/src/services/view-service.ts
Normal file
@@ -0,0 +1,222 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { inject, injectable } from 'inversify';
|
||||
import { Emitter } from '@flowgram-adapter/common';
|
||||
import { type URI } from '@coze-project-ide/core';
|
||||
|
||||
import { WidgetOpenHandler } from '../widget/widget-open-handler';
|
||||
import { type ReactWidget } from '../widget/react-widget';
|
||||
import { type FlowDockPanel } from '../widget/dock-panel';
|
||||
import { type CustomTitleType, LayoutPanelType } from '../types';
|
||||
import { ApplicationShell } from '../shell';
|
||||
import { type DockLayout } from '../lumino/widgets';
|
||||
import { ALL_PANEL_TYPES } from '../constants/view';
|
||||
|
||||
@injectable()
|
||||
export class ViewService {
|
||||
@inject(ApplicationShell) shell: ApplicationShell;
|
||||
|
||||
@inject(WidgetOpenHandler) protected readonly openHandler: WidgetOpenHandler;
|
||||
|
||||
private isFullScreenMode = false;
|
||||
|
||||
private onFullScreenModeChangeEmitter = new Emitter<boolean>();
|
||||
|
||||
onFullScreenModeChange = this.onFullScreenModeChangeEmitter.event;
|
||||
|
||||
private prevPanelMap = new Map<LayoutPanelType, boolean>();
|
||||
|
||||
/**
|
||||
* 唤起底部面板
|
||||
*/
|
||||
toggleBottomLayout() {
|
||||
this.shell.bottomSplitLayout.setRelativeSizes([0.7, 0.3]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 隐藏底部面板
|
||||
*/
|
||||
hideBottomLayout() {
|
||||
this.shell.bottomSplitLayout.setRelativeSizes([1, 0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有打开的 tab title
|
||||
*/
|
||||
getOpenTitles() {
|
||||
let titles: CustomTitleType[] = [];
|
||||
const tabBars = (
|
||||
this.shell.mainPanel.layout as unknown as DockLayout
|
||||
).tabBars();
|
||||
for (const tabBar of tabBars) {
|
||||
titles = titles.concat(tabBar.titles as CustomTitleType[]);
|
||||
}
|
||||
return titles;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前 panel 打开的所有 tab
|
||||
*/
|
||||
getAllTabsFromArea(
|
||||
area: LayoutPanelType.MAIN_PANEL | LayoutPanelType.BOTTOM_PANEL,
|
||||
) {
|
||||
const widgets =
|
||||
area === LayoutPanelType.MAIN_PANEL
|
||||
? this.shell.mainPanel.widgets()
|
||||
: this.shell.bottomPanel.widgets();
|
||||
const dockPanels: any[] = [];
|
||||
for (const dockPanel of widgets) {
|
||||
dockPanels.push(dockPanel);
|
||||
}
|
||||
return dockPanels;
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭除了当前 tab 以外的所有 tab
|
||||
*/
|
||||
closeOtherTabs(dispose = true) {
|
||||
try {
|
||||
const parentWidget = this.shell.currentWidget?.parent;
|
||||
if (!parentWidget) {
|
||||
return;
|
||||
}
|
||||
const widgets = (parentWidget as FlowDockPanel).tabBars();
|
||||
for (const customTabBar of widgets) {
|
||||
[...customTabBar.titles].map(title => {
|
||||
if (title.label !== customTabBar.currentTitle?.label) {
|
||||
customTabBar.removeTab(title);
|
||||
if (dispose) {
|
||||
title.owner.dispose();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开主面板的下一个 tab
|
||||
*/
|
||||
openNextTab() {
|
||||
const tabBars = (
|
||||
this.shell.mainPanel.layout as unknown as DockLayout
|
||||
).tabBars();
|
||||
|
||||
for (const tabbar of tabBars) {
|
||||
const idx = tabbar.titles.findIndex(
|
||||
title => title.owner === this.shell.currentWidget,
|
||||
);
|
||||
if (idx !== -1) {
|
||||
const nextUri = (
|
||||
tabbar.titles[(idx + 1) % tabbar.titles.length].owner as ReactWidget
|
||||
)?.getResourceURI();
|
||||
|
||||
if (nextUri) {
|
||||
this.openHandler.open(nextUri);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开主面板的上一个 tab
|
||||
*/
|
||||
openLastTab() {
|
||||
const tabBars = (
|
||||
this.shell.mainPanel.layout as unknown as DockLayout
|
||||
).tabBars();
|
||||
|
||||
for (const tabbar of tabBars) {
|
||||
const idx = tabbar.titles.findIndex(
|
||||
title => title.owner === this.shell.currentWidget,
|
||||
);
|
||||
if (idx !== -1) {
|
||||
const nextUri = (
|
||||
tabbar.titles[(idx - 1 + tabbar.titles.length) % tabbar.titles.length]
|
||||
.owner as ReactWidget
|
||||
)?.getResourceURI();
|
||||
|
||||
if (nextUri) {
|
||||
this.openHandler.open(nextUri);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 开启全屏模式
|
||||
*/
|
||||
enableFullScreenMode() {
|
||||
if (this.isFullScreenMode) {
|
||||
return;
|
||||
}
|
||||
ALL_PANEL_TYPES.forEach(type => {
|
||||
if (type !== LayoutPanelType.MAIN_PANEL) {
|
||||
const panel = this.shell.getPanelFromArea(type);
|
||||
this.prevPanelMap.set(type, panel.isHidden);
|
||||
panel.hide();
|
||||
}
|
||||
});
|
||||
this.isFullScreenMode = true;
|
||||
this.onFullScreenModeChangeEmitter.fire(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭全屏模式
|
||||
*/
|
||||
disableFullScreenMode() {
|
||||
if (!this.isFullScreenMode) {
|
||||
return;
|
||||
}
|
||||
ALL_PANEL_TYPES.forEach(type => {
|
||||
if (type !== LayoutPanelType.MAIN_PANEL) {
|
||||
const panel = this.shell.getPanelFromArea(type);
|
||||
const isHidden = Boolean(this.prevPanelMap.get(type));
|
||||
panel.setHidden(isHidden);
|
||||
}
|
||||
});
|
||||
this.isFullScreenMode = false;
|
||||
this.onFullScreenModeChangeEmitter.fire(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 全屏模式切换
|
||||
*/
|
||||
switchFullScreenMode() {
|
||||
if (!this.isFullScreenMode) {
|
||||
this.enableFullScreenMode();
|
||||
} else {
|
||||
this.disableFullScreenMode();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置当前 activityBar 激活 item
|
||||
*/
|
||||
setActivityBarUri(uri: URI) {
|
||||
this.shell.activityBarWidget.setCurrentUri(uri);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前 activityBar 激活的 item
|
||||
*/
|
||||
get activityBarUri() {
|
||||
return this.shell.activityBarWidget.currentUri;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user