chore: replace all cn comments of fe to en version by volc api (#320)
This commit is contained in:
@@ -37,9 +37,9 @@ interface ActivityBarProps {
|
||||
}
|
||||
|
||||
/**
|
||||
* activitybar 有两种状态
|
||||
* - 选中态 select 同时高亮和左侧有蓝色竖线
|
||||
* - 激活态 active 仅高亮
|
||||
* Activitybar has two states
|
||||
* - Select state with both highlight and blue vertical bar on the left
|
||||
* - active only highlighted
|
||||
*/
|
||||
export const ActivityBar: React.FC<ActivityBarProps> = ({
|
||||
list,
|
||||
|
||||
@@ -117,7 +117,7 @@ export default function (i) {
|
||||
function mousewheelHandler(e) {
|
||||
const [deltaX, deltaY] = getDeltaFromEvent(e);
|
||||
|
||||
// FIXME: mousewheel 滚动的时候有问题
|
||||
// FIXME: There is a problem with the mousewheel rolling
|
||||
if (shouldBeConsumedByChild(e.target, deltaX, deltaY)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -16,11 +16,11 @@
|
||||
|
||||
export const CUSTOM_TAB_BAR_CONTAINER = 'custom-tabBar-container';
|
||||
|
||||
// 前边的 action
|
||||
// Previous actions
|
||||
export const PRE_TAB_BAR_ACTION_CONTAINER = 'pre-flow-tabBar-action-container';
|
||||
// 后边的 action
|
||||
// The action behind
|
||||
export const TAB_BAR_ACTION_CONTAINER = 'flow-tabBar-action-container';
|
||||
// tab bar 滚动区域
|
||||
// Tab bar scrolling area
|
||||
export const TAB_BAR_SCROLL_CONTAINER = 'flow-tabBar-scroll-container';
|
||||
|
||||
// toolbar
|
||||
@@ -28,5 +28,5 @@ export const TAB_BAR_TOOLBAR = 'flow-toolbar-container';
|
||||
export const TAB_BAR_TOOLBAR_ITEM = 'flow-toolbar-item';
|
||||
export const DISABLE_HANDLE_EVENT = 'disable-handle-event';
|
||||
|
||||
/** DebugBar 可拖拽区域 classname */
|
||||
/** DebugBar Draggable classname */
|
||||
export const DEBUG_BAR_DRAGGABLE = 'flow-debug-bar-draggable';
|
||||
|
||||
@@ -26,13 +26,13 @@ import { Menu, MenuFactory } from './menu';
|
||||
export type CanHandle = string | ((command?: string) => boolean);
|
||||
|
||||
/**
|
||||
* 全局 contextmenu 监听
|
||||
* Global contextmenu listening
|
||||
*/
|
||||
@injectable()
|
||||
export class ContextMenu {
|
||||
@inject(MenuFactory) menuFactory: MenuFactory;
|
||||
|
||||
// 全局主菜单
|
||||
// Global Main Menu
|
||||
menu: Menu;
|
||||
|
||||
@postConstruct()
|
||||
@@ -41,15 +41,15 @@ export class ContextMenu {
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除项
|
||||
* delete item
|
||||
*/
|
||||
deleteItem(canHandle: CanHandle) {
|
||||
if (typeof canHandle === 'string') {
|
||||
// 精确删除
|
||||
// precise deletion
|
||||
const item = this._items.find(i => i.command === canHandle);
|
||||
ArrayExt.removeFirstOf(this._items, item);
|
||||
} else {
|
||||
// 模糊删除
|
||||
// blur delete
|
||||
this._items.forEach(i => {
|
||||
if (canHandle(i.command)) {
|
||||
ArrayExt.removeFirstOf(this._items, i);
|
||||
@@ -59,7 +59,7 @@ export class ContextMenu {
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加项
|
||||
* add item
|
||||
*/
|
||||
addItem(options: ContextMenu.IItemOptions): Disposable {
|
||||
const item = Private.createItem(options, this._idTick++);
|
||||
@@ -72,14 +72,14 @@ export class ContextMenu {
|
||||
}
|
||||
|
||||
/**
|
||||
* 手动关闭 menu
|
||||
* Manually close the menu
|
||||
*/
|
||||
close() {
|
||||
this.menu.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开事件
|
||||
* open event
|
||||
*/
|
||||
open(event: React.MouseEvent, args?: any): boolean {
|
||||
Menu.saveWindowData();
|
||||
@@ -141,8 +141,8 @@ export namespace ContextMenu {
|
||||
/**
|
||||
* The CSS selector for the context menu item.
|
||||
*
|
||||
* 只有当当前元素冒泡途径 selector 元素,才会触发这个 contextmenu 事件。
|
||||
* 底层通过 querySelector 获取,需要加上 commas
|
||||
* The contextmenu event is triggered only when the current element is bubbling through the selector element.
|
||||
* The bottom layer is obtained through querySelector, and commas need to be added.
|
||||
*/
|
||||
selector: string;
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ import { type CanHandle, ContextMenu } from './context-menu';
|
||||
export const MenuService = Symbol('MenuService');
|
||||
|
||||
/**
|
||||
* menu service 注册
|
||||
* Menu service registration
|
||||
*/
|
||||
export interface MenuService {
|
||||
addMenuItem: (options: ContextMenu.IItemOptions) => void;
|
||||
|
||||
@@ -1022,19 +1022,19 @@ export namespace Menu {
|
||||
|
||||
/**
|
||||
* custom shortcut
|
||||
* 专门为第三方快捷键预留
|
||||
* Specially reserved for third-party shortcuts
|
||||
*/
|
||||
customShortcut?: string;
|
||||
|
||||
/**
|
||||
* 回显 tooltip 文案
|
||||
* Echo tooltip copy
|
||||
*/
|
||||
tooltip?: string | ((props: { disabled?: boolean }) => string);
|
||||
|
||||
/**
|
||||
* 返回为 true 的才会被保留在 menu 回显。
|
||||
* 默认不传,满足 selector 条件一定会被回显在菜单内。
|
||||
* disabled 通过 command isEnabled 控制
|
||||
* Only those that return true will be retained in the menu echo.
|
||||
* The default is not passed, and the selector condition will definitely be echoed in the menu.
|
||||
* Disabled Control via command isEnabled
|
||||
*/
|
||||
filter?: (args: any) => boolean;
|
||||
}
|
||||
@@ -1071,7 +1071,7 @@ export namespace Menu {
|
||||
*/
|
||||
readonly label: string;
|
||||
|
||||
/** 不建议使用,极端场景兼容。custom shortcut string, without ShortcutService */
|
||||
/** Not recommended, compatible with extreme scenes. custom shortcut string, without ShortcutService */
|
||||
readonly customShortcut?: string;
|
||||
|
||||
/**
|
||||
@@ -1124,7 +1124,7 @@ export namespace Menu {
|
||||
*/
|
||||
readonly keyBinding: null;
|
||||
|
||||
/** tooltip 内容 */
|
||||
/** Tooltip content */
|
||||
readonly tooltip?: string | ((props: { disabled?: boolean }) => string);
|
||||
}
|
||||
|
||||
|
||||
@@ -314,7 +314,7 @@ export class ViewCommonContribution
|
||||
},
|
||||
{
|
||||
execute: () => {
|
||||
// 没有 focus 内容的时候默认打开 problem
|
||||
// Open the problem by default when there is no focus content
|
||||
if (!this.shell.bottomPanel?.currentTitle) {
|
||||
this.commandService.executeCommand(Command.Default.VIEW_PROBLEMS);
|
||||
}
|
||||
@@ -364,51 +364,51 @@ export class ViewCommonContribution
|
||||
}
|
||||
|
||||
registerShortcuts(registry: ShortcutsRegistry): void {
|
||||
// 关闭当前所有 tab
|
||||
// Close all current tabs
|
||||
registry.registerHandlers({
|
||||
keybinding: 'alt shift w',
|
||||
commandId: Command.Default.VIEW_CLOSE_ALL_WIDGET,
|
||||
});
|
||||
|
||||
// 打开下一个 tab
|
||||
// Open next tab
|
||||
registry.registerHandlers({
|
||||
keybinding: 'alt shift rightarrow',
|
||||
commandId: Command.Default.VIEW_OPEN_NEXT_TAB,
|
||||
preventDefault: true,
|
||||
});
|
||||
|
||||
// 打开上一个 tab
|
||||
// Open previous tab
|
||||
registry.registerHandlers({
|
||||
keybinding: 'alt shift leftarrow',
|
||||
commandId: Command.Default.VIEW_OEPN_LAST_TAB,
|
||||
preventDefault: true,
|
||||
});
|
||||
|
||||
// 关闭当前 tab
|
||||
// Close the current tab
|
||||
registry.registerHandlers({
|
||||
keybinding: 'alt w',
|
||||
commandId: Command.Default.VIEW_CLOSE_CURRENT_WIDGET,
|
||||
});
|
||||
|
||||
// 打开刚刚关闭当前 tab
|
||||
// Open Just closed the current tab
|
||||
registry.registerHandlers({
|
||||
keybinding: 'alt shift t',
|
||||
commandId: Command.Default.VIEW_REOPEN_LAST_WIDGET,
|
||||
});
|
||||
|
||||
// 关闭除了当前打开的 tab 以外的所有 tab
|
||||
// Close all tabs except the currently open tab
|
||||
registry.registerHandlers({
|
||||
keybinding: 'meta alt t',
|
||||
commandId: Command.Default.VIEW_CLOSE_OTHER_WIDGET,
|
||||
});
|
||||
|
||||
// 关闭除了当前打开的 tab 以外的所有 tab
|
||||
// Close all tabs except the currently open tab
|
||||
registry.registerHandlers({
|
||||
keybinding: 'meta j',
|
||||
commandId: Command.Default.VIEW_CLOSE_BOTTOM_PANEL,
|
||||
});
|
||||
|
||||
// 全屏模式
|
||||
// Full screen mode
|
||||
registry.registerHandlers({
|
||||
keybinding: 'alt f',
|
||||
commandId: Command.Default.VIEW_FULL_SCREEN,
|
||||
|
||||
@@ -81,7 +81,7 @@ import { MAIN_PANEL_ID } from './constants';
|
||||
const DefaultFallbackRender = () => <div>Something went wrong.</div>;
|
||||
|
||||
/**
|
||||
* 点位背景插件
|
||||
* Point background plugin
|
||||
*/
|
||||
export const createViewPlugin = definePluginCreator<ViewPluginOptions>({
|
||||
onBind: ({ bind }, opts) => {
|
||||
@@ -167,9 +167,9 @@ export const createViewPlugin = definePluginCreator<ViewPluginOptions>({
|
||||
const viewManager = ctx.get<ViewManager>(ViewManager);
|
||||
await viewManager.init(opts);
|
||||
},
|
||||
// 页面渲染完成后 attach dom
|
||||
// After the page is rendered, attach dom
|
||||
onLayoutInit: async (ctx, opts) => {
|
||||
// 预设 contextmenu
|
||||
// contextmenu
|
||||
if (!opts.presetConfig?.disableContextMenu) {
|
||||
const menuService = ctx.container.get<MenuService>(MenuService);
|
||||
menuService.addMenuItem({
|
||||
@@ -197,14 +197,14 @@ export const createViewPlugin = definePluginCreator<ViewPluginOptions>({
|
||||
await viewManager.attach(opts);
|
||||
const eventService = ctx.container.get<EventService>(EventService);
|
||||
const menuService = ctx.container.get<MenuService>(MenuService);
|
||||
// 劫持全局的 contextmenu
|
||||
// Hijack the global contextmenu
|
||||
eventService.listenGlobalEvent('contextmenu', (e: React.MouseEvent) => {
|
||||
if (domEditable(e.target as HTMLElement)) {
|
||||
return;
|
||||
}
|
||||
const hasMenu = menuService.open(e);
|
||||
if (!opts.presetConfig?.disableContextMenu || hasMenu) {
|
||||
// 在 ide 内部永远阻塞右键
|
||||
// Always block right button inside IDE
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
@@ -593,8 +593,8 @@ export namespace Drag {
|
||||
*/
|
||||
export interface IOptions {
|
||||
/**
|
||||
* 由于有一个 lm-cursor-backdrop 元素,用于阻止拖拽分屏过程中触发的 hover 事件
|
||||
* 因此引入一个额外的配置,配置这个元素的边界位置
|
||||
* Due to the lm-cursor-backdrop element, it is used to prevent the hover event from being triggered during dragging and dropping the split screen.
|
||||
* Therefore, an additional configuration is introduced to configure the boundary position of this element
|
||||
*/
|
||||
backdropTransform?: BackDropTransform;
|
||||
|
||||
|
||||
@@ -623,7 +623,7 @@ export class DockPanel extends Widget {
|
||||
const widgets = await factory();
|
||||
let replaceRef: Widget;
|
||||
widgets.forEach((widget: Widget, idx: number) => {
|
||||
// 第一个执行分屏,后续都是 widget-all
|
||||
// The first one executes the split screen, and the follow-up is widget-all.
|
||||
if (idx === 0) {
|
||||
this.bindWidget(event, widget, zone, target);
|
||||
replaceRef = widget;
|
||||
@@ -1128,7 +1128,7 @@ export namespace DockPanel {
|
||||
*/
|
||||
export interface IOptions {
|
||||
/**
|
||||
* 最大分屏数量限制
|
||||
* Maximum number of split screens
|
||||
*/
|
||||
splitOptions?: SplitOptions;
|
||||
/**
|
||||
@@ -1630,15 +1630,15 @@ namespace Private {
|
||||
}
|
||||
|
||||
/**
|
||||
* 递归遍历布局树,计算 tab-area 的数量
|
||||
* Recursively traverse the layout tree to count the number of tab-areas
|
||||
* @param area DockLayout.Area
|
||||
* @returns number 分屏数量
|
||||
* @returns number number of split screens
|
||||
*/
|
||||
function countTabAreas(area: DockLayout.AreaConfig | null): number {
|
||||
if (area?.type === 'tab-area') {
|
||||
return 1; // 找到一个 tab 区域
|
||||
return 1; // Find a tab area
|
||||
} else if (area?.type === 'split-area') {
|
||||
// 遍历子区域,递归计算每个区域的数量
|
||||
// Traverse the subregions and recursively calculate the number of each region
|
||||
return area.children.reduce(
|
||||
(count, child) => count + countTabAreas(child),
|
||||
0,
|
||||
@@ -1698,7 +1698,7 @@ namespace Private {
|
||||
// Hit test the dock layout at the given client position.
|
||||
const target = layout.hitTestTabAreas(clientX, clientY);
|
||||
|
||||
// 最大分屏数量限制
|
||||
// Maximum number of split screens
|
||||
if (splitOptions?.maxSplitCount) {
|
||||
const layoutConfig = layout.saveLayout();
|
||||
const currentScreens = countTabAreas(layoutConfig.main);
|
||||
@@ -1706,10 +1706,10 @@ namespace Private {
|
||||
return { zone: 'invalid', target: null };
|
||||
}
|
||||
if (currentScreens >= splitOptions.maxSplitCount) {
|
||||
// 如果数量超出最大屏幕数,此时只能充满屏幕,不能分屏
|
||||
// If the number exceeds the maximum number of screens, the screen can only be filled at this time, not split-screen.
|
||||
return { zone: 'widget-all', target };
|
||||
}
|
||||
// 限制只能左右分屏
|
||||
// Limit can only split screen left and right
|
||||
if (splitOptions?.splitOrientation === 'horizontal') {
|
||||
if (target && target.x < target.width / 4) {
|
||||
return { zone: 'widget-left', target };
|
||||
@@ -1719,7 +1719,7 @@ namespace Private {
|
||||
}
|
||||
return { zone: 'widget-all', target };
|
||||
}
|
||||
// 限制只能上下分屏
|
||||
// Restriction can only be split screen up and down
|
||||
if (splitOptions?.splitOrientation === 'vertical') {
|
||||
if (target && target.y < target.height / 4) {
|
||||
return { zone: 'widget-top', target };
|
||||
@@ -1732,7 +1732,7 @@ namespace Private {
|
||||
}
|
||||
|
||||
// Test the edge zones when in multiple document mode.
|
||||
// 分屏方向限制的时候,禁用 root 层的区域判断
|
||||
// When the split-screen orientation is restricted, disable the area judgment of the root layer
|
||||
if (panel.mode === 'multiple-document') {
|
||||
// Get the client rect for the dock panel.
|
||||
const panelRect = panel.node.getBoundingClientRect();
|
||||
|
||||
@@ -21,7 +21,7 @@ import { createPortal } from '../utils';
|
||||
import { ApplicationShell } from '../shell/application-shell';
|
||||
import { ViewOptions } from '../constants/view-options';
|
||||
|
||||
// 控制 debug
|
||||
// Control debugging
|
||||
@injectable()
|
||||
export class DebugService {
|
||||
@inject(ViewOptions) viewOptions: ViewOptions;
|
||||
|
||||
@@ -26,22 +26,22 @@ import { MimeData } from '../lumino/coreutils';
|
||||
|
||||
export interface DragPropsType {
|
||||
/**
|
||||
* 拖拽打开分屏的 URI
|
||||
* Drag and drop to open the split-screen URI.
|
||||
*/
|
||||
uris: URI[];
|
||||
/**
|
||||
* startDrag event 位置数据
|
||||
* StartDrag event location data
|
||||
*/
|
||||
position: {
|
||||
clientX: number;
|
||||
clientY: number;
|
||||
};
|
||||
/**
|
||||
* 拖拽元素回显,不传不展示
|
||||
* Drag and drop elements to echo, no transmission or display
|
||||
*/
|
||||
dragImage?: HTMLElement;
|
||||
/**
|
||||
* 拖拽完成后回调
|
||||
* Callback after dragging is complete
|
||||
* action: 'move' | 'copy' | 'link' | 'none'
|
||||
*/
|
||||
callback: (action: Drag.DropAction) => void;
|
||||
@@ -49,7 +49,7 @@ export interface DragPropsType {
|
||||
}
|
||||
|
||||
/**
|
||||
* DragService 主要用于分屏操作
|
||||
* DragService is mainly used for split-screen operation
|
||||
*/
|
||||
@injectable()
|
||||
export class DragService {
|
||||
@@ -60,7 +60,7 @@ export class DragService {
|
||||
@inject(ViewRenderer) viewRenderer: ViewRenderer;
|
||||
|
||||
/**
|
||||
* 业务侧手动拖拽触发分屏(侧边栏文件树拖拽进入开始分屏)
|
||||
* Manually drag and drop on the business side to trigger the split screen (drag the sidebar file tree into the start split screen)
|
||||
*/
|
||||
startDrag({
|
||||
uris,
|
||||
@@ -94,7 +94,7 @@ export class DragService {
|
||||
proposedAction: 'move',
|
||||
supportedActions: 'move',
|
||||
/**
|
||||
* 仅支持在主面板区域分屏
|
||||
* Only supports split screen in the main panel area
|
||||
*/
|
||||
source: this.shell.mainPanel,
|
||||
backdropTransform,
|
||||
|
||||
@@ -100,7 +100,7 @@ export interface HoverRequest {
|
||||
position: HoverPosition;
|
||||
cssClasses?: string[];
|
||||
visualPreview?: (width: number) => HTMLElement | undefined;
|
||||
/** hover 位置偏移 */
|
||||
/** Hover position offset */
|
||||
offset?: number;
|
||||
}
|
||||
|
||||
|
||||
@@ -41,21 +41,21 @@ export class ViewService {
|
||||
private prevPanelMap = new Map<LayoutPanelType, boolean>();
|
||||
|
||||
/**
|
||||
* 唤起底部面板
|
||||
* Evoke the bottom panel
|
||||
*/
|
||||
toggleBottomLayout() {
|
||||
this.shell.bottomSplitLayout.setRelativeSizes([0.7, 0.3]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 隐藏底部面板
|
||||
* Hide bottom panel
|
||||
*/
|
||||
hideBottomLayout() {
|
||||
this.shell.bottomSplitLayout.setRelativeSizes([1, 0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有打开的 tab title
|
||||
* Get all open tab titles
|
||||
*/
|
||||
getOpenTitles() {
|
||||
let titles: CustomTitleType[] = [];
|
||||
@@ -69,7 +69,7 @@ export class ViewService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前 panel 打开的所有 tab
|
||||
* Get all tabs currently open in the panel
|
||||
*/
|
||||
getAllTabsFromArea(
|
||||
area: LayoutPanelType.MAIN_PANEL | LayoutPanelType.BOTTOM_PANEL,
|
||||
@@ -86,7 +86,7 @@ export class ViewService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭除了当前 tab 以外的所有 tab
|
||||
* Close all tabs except the current tab
|
||||
*/
|
||||
closeOtherTabs(dispose = true) {
|
||||
try {
|
||||
@@ -111,7 +111,7 @@ export class ViewService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开主面板的下一个 tab
|
||||
* Open the next tab in the main panel
|
||||
*/
|
||||
openNextTab() {
|
||||
const tabBars = (
|
||||
@@ -135,7 +135,7 @@ export class ViewService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开主面板的上一个 tab
|
||||
* Open the previous tab of the main panel
|
||||
*/
|
||||
openLastTab() {
|
||||
const tabBars = (
|
||||
@@ -160,7 +160,7 @@ export class ViewService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 开启全屏模式
|
||||
* Enable full screen mode
|
||||
*/
|
||||
enableFullScreenMode() {
|
||||
if (this.isFullScreenMode) {
|
||||
@@ -178,7 +178,7 @@ export class ViewService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭全屏模式
|
||||
* Turn off full screen mode
|
||||
*/
|
||||
disableFullScreenMode() {
|
||||
if (!this.isFullScreenMode) {
|
||||
@@ -196,7 +196,7 @@ export class ViewService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 全屏模式切换
|
||||
* full screen mode toggle
|
||||
*/
|
||||
switchFullScreenMode() {
|
||||
if (!this.isFullScreenMode) {
|
||||
@@ -207,14 +207,14 @@ export class ViewService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置当前 activityBar 激活 item
|
||||
* Set the current activityBar item
|
||||
*/
|
||||
setActivityBarUri(uri: URI) {
|
||||
this.shell.activityBarWidget.setCurrentUri(uri);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前 activityBar 激活的 item
|
||||
* Get the current activityBar active item
|
||||
*/
|
||||
get activityBarUri() {
|
||||
return this.shell.activityBarWidget.currentUri;
|
||||
|
||||
@@ -124,7 +124,7 @@ export class ApplicationShell extends Widget {
|
||||
closeWidgetUriStack: URI[] = [];
|
||||
|
||||
/**
|
||||
* 当前 focus widget 变化
|
||||
* Current focus widget change
|
||||
*/
|
||||
protected readonly onCurrentWidgetChangeEmitter = new Emitter<
|
||||
AbstractWidget | undefined
|
||||
@@ -146,15 +146,15 @@ export class ApplicationShell extends Widget {
|
||||
this.bottomPanel.hide();
|
||||
|
||||
this.topPanel = this.createPanel(LayoutPanelType.TOP_BAR);
|
||||
// 扩展,目前暂时未用到。
|
||||
// Extension, not currently in use.
|
||||
this.rightToolbar = this.createPanel(LayoutPanelType.RIGHT_BAR);
|
||||
// 默认模式下 rightToolbar 隐藏
|
||||
// Default mode rightToolbar hide
|
||||
this.rightToolbar.hide();
|
||||
this.statusBar = this.createPanel(LayoutPanelType.STATUS_BAR);
|
||||
this.activityBar = this.createPanel(LayoutPanelType.ACTIVITY_BAR);
|
||||
this.secondarySidebar = this.createPanel(LayoutPanelType.SECONDARY_SIDEBAR);
|
||||
|
||||
// 创建左侧面板
|
||||
// Create left panel
|
||||
this.leftPanelHandler = this.sidePanelHandlerFactory();
|
||||
this.leftPanelHandler.create('left');
|
||||
this.leftPanelHandler.expand();
|
||||
@@ -163,7 +163,7 @@ export class ApplicationShell extends Widget {
|
||||
this.primarySidebar.id = uri.displayName;
|
||||
this.widgetManager.setWidget(uri.toString(), this.primarySidebar);
|
||||
|
||||
// 默认右侧隐藏
|
||||
// Default right side hide
|
||||
this.secondarySidebar.hide();
|
||||
this.layout = createLayout?.(this) || this.createLayout();
|
||||
|
||||
@@ -219,7 +219,7 @@ export class ApplicationShell extends Widget {
|
||||
default:
|
||||
throw new Error(`Unexpected area: ${options?.area}`);
|
||||
}
|
||||
// topBar 和 statusbar 不监听
|
||||
// topBar and statusbar do not listen
|
||||
if (
|
||||
area !== LayoutPanelType.STATUS_BAR &&
|
||||
area !== LayoutPanelType.TOP_BAR
|
||||
@@ -270,7 +270,7 @@ export class ApplicationShell extends Widget {
|
||||
}
|
||||
}
|
||||
|
||||
// 给本地持久化消费使用的方法
|
||||
// Methods for local persistent consumption
|
||||
setCurrentWidget(widget?: ReactWidget) {
|
||||
this._currentWidget = widget;
|
||||
this._currentWidgetParent = widget?.parent;
|
||||
@@ -311,10 +311,10 @@ export class ApplicationShell extends Widget {
|
||||
|
||||
const leftRightSplitLayout = createSplitLayout(
|
||||
[
|
||||
// 左边的不可伸缩 bar
|
||||
// Unretractable bar on the left
|
||||
this.primarySidebar,
|
||||
middleContentPanel,
|
||||
// 右边的不可伸缩 bar
|
||||
// Non-retractable bar on the right
|
||||
this.secondarySidebar,
|
||||
],
|
||||
[0, 1, 0],
|
||||
@@ -325,10 +325,10 @@ export class ApplicationShell extends Widget {
|
||||
|
||||
const centerLayout = createBoxLayout(
|
||||
[
|
||||
// 左边的不可伸缩 bar
|
||||
// Unretractable bar on the left
|
||||
this.activityBar,
|
||||
mainDockPanel,
|
||||
// 右边的不可伸缩 bar
|
||||
// Non-retractable bar on the right
|
||||
this.rightToolbar,
|
||||
],
|
||||
[0, 1, 0],
|
||||
@@ -395,7 +395,7 @@ export class ApplicationShell extends Widget {
|
||||
}
|
||||
|
||||
/**
|
||||
* 将当前选中的 widget 的 tab 滚动到视区内
|
||||
* Scroll the tab of the currently selected widget to the viewport
|
||||
*/
|
||||
tabbarIntoView(behavior?: boolean) {
|
||||
const { mainPanel } = this;
|
||||
@@ -435,7 +435,7 @@ export class ApplicationShell extends Widget {
|
||||
const index = this.closeWidgetUriStack.findIndex(p =>
|
||||
isURIMatch(p, uri),
|
||||
);
|
||||
// 有重复的先删除,再 push
|
||||
// If there are duplicates, delete them first, and then push them.
|
||||
if (index !== -1) {
|
||||
this.closeWidgetUriStack.splice(index, 1);
|
||||
}
|
||||
@@ -458,11 +458,11 @@ export class ApplicationShell extends Widget {
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* layout 相关
|
||||
* Layout related
|
||||
*/
|
||||
|
||||
getLayoutData(): LayoutData {
|
||||
// 记录子分屏 layout 数据
|
||||
// Record subscreen layout data
|
||||
const widgets: Widget[] = [];
|
||||
this.primarySidebar.widgets.forEach(_widget => {
|
||||
widgets.push(_widget);
|
||||
@@ -518,7 +518,7 @@ export class ApplicationShell extends Widget {
|
||||
}
|
||||
}
|
||||
|
||||
// 下边是 tabs 切换,等 mainPanel 切换成 dockpanel 的时候启用
|
||||
// Below is tabs switching, which will be enabled when mainPanel switches to dockpanel.
|
||||
// activateWithLabel(widget: Widget) {
|
||||
// this.mainPanel.activateWidget(widget);
|
||||
// }
|
||||
|
||||
@@ -33,16 +33,16 @@ import { type LayoutData } from './types';
|
||||
import { ApplicationShell } from './application-shell';
|
||||
|
||||
/**
|
||||
* 在会话之间存储和恢复 widget 其内部状态的接口
|
||||
* Interface for storing and restoring the internal state of widgets between sessions
|
||||
*/
|
||||
interface StatefulWidget {
|
||||
/**
|
||||
* widget 内部的状态,返回 undefined 将不会保存
|
||||
* The internal state of the widget, returning undefined will not save
|
||||
*/
|
||||
storeState(): object | undefined;
|
||||
|
||||
/**
|
||||
* 复原存储的状态
|
||||
* Restore the stored state
|
||||
*/
|
||||
restoreState(state: object): void;
|
||||
}
|
||||
@@ -57,30 +57,30 @@ const CustomPreferenceContribution = Symbol('CustomPreferenceContribution');
|
||||
|
||||
interface CustomPreferenceContribution {
|
||||
/**
|
||||
* 注册 command
|
||||
* Registration command
|
||||
*/
|
||||
registerCustomPreferences(restorer: LayoutRestorer): void;
|
||||
}
|
||||
|
||||
export interface CustomPreferenceConfig {
|
||||
/**
|
||||
* 该配置唯一 key
|
||||
* Unique key for this configuration
|
||||
*/
|
||||
key: string;
|
||||
/**
|
||||
* 标题
|
||||
* title
|
||||
*/
|
||||
title: string;
|
||||
/**
|
||||
* 描述
|
||||
* describe
|
||||
*/
|
||||
descprition?: string;
|
||||
/**
|
||||
* 顺序
|
||||
* order
|
||||
*/
|
||||
order: number;
|
||||
/**
|
||||
* 值设置器配置
|
||||
* value setter configuration
|
||||
*/
|
||||
setting:
|
||||
| {
|
||||
@@ -100,7 +100,7 @@ export interface CustomPreferenceConfig {
|
||||
}>;
|
||||
};
|
||||
/**
|
||||
* 默认值
|
||||
* default value
|
||||
*/
|
||||
default: any;
|
||||
}
|
||||
@@ -125,29 +125,29 @@ type RestoreState = LayoutData & {
|
||||
};
|
||||
|
||||
/**
|
||||
* 整个 restore 的流程:
|
||||
* The entire restore process:
|
||||
*
|
||||
* -------------------- 初始化 --------------------
|
||||
* 1. 读取 options 配置,等待 DockPanel、SplitLayout 实例化完成
|
||||
* 2. 从数据源 (目前是 localStorage) 读取持久化数据,包含 layoutData 和 innerState
|
||||
* 3. 遍历 layoutData 中的 widget uri 根据保存的 uri 线索重新创建 widget
|
||||
* 3.1. 根据 uri 找到 Factory,根据 uri 和 Factory 创建 widget
|
||||
* 3.2. 用 portal 挂载,这是本 ide widget 的挂载方式决定的
|
||||
* 3.3. 运行 widget.init,这是 ReactWidget 决定的
|
||||
* 3.4. shell.stack(widget),持久化的 widget 全部都需要被 stack
|
||||
* 4. 依次 restore 各个 panel 和 layout
|
||||
* -------------------- initialization --------------------
|
||||
* 1. Read the options configuration and wait for the DockPanel and SplitLayout instantiation to complete
|
||||
* 2. Read persistent data from a data source (currently localStorage), including layoutData and innerState
|
||||
* 3. Traverse the widget URIs in layoutData and recreate the widget according to the saved URI clues.
|
||||
* 3.1. Find Factory according to URI, create widget according to URI and Factory
|
||||
* 3.2. Mount with portal, which is determined by the mounting method of this ide widget
|
||||
* 3.3. Run widget.init, which is determined by ReactWidget
|
||||
* 3.4. Shell.stack (widget), all persistent widgets need to be stacked
|
||||
* 4. Sequentially restore panels and layouts
|
||||
*
|
||||
* -------------------- 运行中 --------------------
|
||||
* 5. widget dispose 时,将 state 存于 innerState
|
||||
* 6. widget create 时,从 innerState 中取数据回填
|
||||
* (注意,这里都是和内存交互,和持久化数据源无关)
|
||||
* -------------------- running --------------------
|
||||
* 5. widget disposed, save state in innerState
|
||||
* 6. When the widget is created, backfill the data from innerState
|
||||
* (Note that this is all about interacting with memory and has nothing to do with persistent data sources.)
|
||||
*
|
||||
* -------------------- 销毁 --------------------
|
||||
* 7. 应用销毁前读取 layoutData,和 innerState 一起存入持久化数据源
|
||||
* 7.1. layoutData 中的 widget 对象仅保留它的 uri,并且会转化为 string 的形式存储
|
||||
* -------------------- destroy --------------------
|
||||
* 7. Read the layoutData before the application is destroyed, and store it in the persistent data source together with innerState
|
||||
* 7.1. A widget object in layoutData only retains its URI and is stored as a string
|
||||
*
|
||||
* Q:为什么 innerState 作为内存 state 也需要被存储?
|
||||
* A:被打开又被关闭的 widget state 只存在 inner 中,没有被 layoutData 囊括
|
||||
* Q: Why does innerState need to be stored as memory state?
|
||||
* A: The widget state that is opened and closed only exists in inner, not included by layoutData
|
||||
*/
|
||||
|
||||
@injectable()
|
||||
@@ -170,7 +170,7 @@ class LayoutRestorer {
|
||||
protected readonly widgetManager: WidgetManager;
|
||||
|
||||
/**
|
||||
* 维护在内存中的持久化数据,在应用初始化时从源读取,但不会用于持久化初始化
|
||||
* Maintains persistent data in memory that is read from the source during application initialization, but not used for persistent initialization
|
||||
*/
|
||||
innerState: Record<string, any> = {};
|
||||
|
||||
@@ -200,7 +200,7 @@ class LayoutRestorer {
|
||||
private unloadEvent: undefined | Disposable;
|
||||
|
||||
public init(options: ViewPluginOptions) {
|
||||
/** 没地方放,暂时放这里 */
|
||||
/** No place to put it, put it here for now */
|
||||
this.windowService.onStart();
|
||||
this.viewOptions = options;
|
||||
const { getStorageKey } = options || {};
|
||||
@@ -394,7 +394,7 @@ class LayoutRestorer {
|
||||
}
|
||||
|
||||
/**
|
||||
* 持久化布局数据
|
||||
* persistent layout data
|
||||
*/
|
||||
storeLayout() {
|
||||
if (this.disabled) {
|
||||
@@ -413,7 +413,7 @@ class LayoutRestorer {
|
||||
}
|
||||
|
||||
/**
|
||||
* 取出布局数据
|
||||
* Retrieve layout data
|
||||
*/
|
||||
async restoreLayout() {
|
||||
if (this.disabled) {
|
||||
|
||||
@@ -17,10 +17,10 @@
|
||||
import { type DockPanel, type Widget } from '../lumino/widgets';
|
||||
|
||||
/**
|
||||
* 版本号控制向下不兼容问题
|
||||
* Version number control backward incompatibility issue
|
||||
*/
|
||||
export type ApplicationShellLayoutVersion =
|
||||
/** 初始化版本 */
|
||||
/** initialization version */
|
||||
0.2;
|
||||
|
||||
export const applicationShellLayoutVersion: ApplicationShellLayoutVersion = 0.2;
|
||||
@@ -51,7 +51,7 @@ export interface LayoutData {
|
||||
widgets?: Widget[];
|
||||
};
|
||||
bottomPanel?: DockPanel.ILayoutConfig & {
|
||||
// 是否折叠
|
||||
// Whether to fold
|
||||
expanded?: boolean;
|
||||
};
|
||||
split?: {
|
||||
|
||||
@@ -34,7 +34,7 @@ export enum LayoutPanelType {
|
||||
SECONDARY_SIDEBAR = 'secondarySidebar',
|
||||
BOTTOM_PANEL = 'bottomPanel',
|
||||
STATUS_BAR = 'statusBar',
|
||||
// 暂时未用到,留作扩展
|
||||
// Not used yet, reserved for expansion
|
||||
RIGHT_BAR = 'rightBar',
|
||||
}
|
||||
|
||||
@@ -50,34 +50,34 @@ export const allLayoutEnums = [
|
||||
];
|
||||
|
||||
/**
|
||||
* widget 描述数据
|
||||
* Widget description data
|
||||
*/
|
||||
interface WidgetDescription {
|
||||
uri: URI;
|
||||
innerState: string;
|
||||
}
|
||||
interface TabPanelData {
|
||||
/** 固定值 */
|
||||
/** fixed value */
|
||||
type: 'tab-area';
|
||||
/** 当前激活的 tab */
|
||||
/** Currently active tab */
|
||||
currentIndex?: number;
|
||||
widgets?: WidgetDescription[];
|
||||
}
|
||||
/**
|
||||
* main panel 的数据结构
|
||||
* Main panel data structure
|
||||
*/
|
||||
interface MainPanelData {
|
||||
main?: TabPanelData;
|
||||
}
|
||||
interface BottomPanelData {
|
||||
main?: TabPanelData;
|
||||
/** 是否默认折叠 */
|
||||
/** Whether to fold by default */
|
||||
expanded?: boolean;
|
||||
}
|
||||
|
||||
export interface ActivityBarItem {
|
||||
/**
|
||||
* menu 位置
|
||||
* Menu location
|
||||
*/
|
||||
position: 'top' | 'bottom';
|
||||
/**
|
||||
@@ -85,11 +85,11 @@ export interface ActivityBarItem {
|
||||
*/
|
||||
uri: URI;
|
||||
/**
|
||||
* tooltip 提示文案
|
||||
* Tooltip Copywriting
|
||||
*/
|
||||
tooltip?: string;
|
||||
/**
|
||||
* 业务侧劫持实现 item 点击
|
||||
* Business side hijacking implementation item click
|
||||
*/
|
||||
onClick?: (e: React.MouseEvent<HTMLDivElement, MouseEvent>) => void;
|
||||
}
|
||||
@@ -100,15 +100,15 @@ export interface StatusBarItem {
|
||||
}
|
||||
|
||||
/**
|
||||
* 支持传入 DockPanel options
|
||||
* Support for incoming DockPanel options
|
||||
*/
|
||||
export interface SplitOptions {
|
||||
/**
|
||||
* 最大分屏数量限制
|
||||
* Maximum number of split screens
|
||||
*/
|
||||
maxSplitCount: number;
|
||||
/**
|
||||
* 分屏方向限制,不传则不限制
|
||||
* Split screen direction limit, no limit if not transmitted
|
||||
*/
|
||||
splitOrientation?: 'horizontal' | 'vertical';
|
||||
}
|
||||
@@ -123,7 +123,7 @@ export interface SplitScreenConfig {
|
||||
bottom?: DockPanelConfig;
|
||||
}
|
||||
|
||||
/** 预设数据 */
|
||||
/** default data */
|
||||
export interface LayoutData {
|
||||
debugBar?: {
|
||||
render: () => ReactElementType;
|
||||
@@ -138,63 +138,63 @@ export interface LayoutData {
|
||||
statusBarItems?: StatusBarItem[];
|
||||
defaultWidgets?: URI[];
|
||||
|
||||
/** 持久化数据 */
|
||||
/** persistent data */
|
||||
mainPanel?: MainPanelData;
|
||||
bottomPanel?: BottomPanelData;
|
||||
}
|
||||
|
||||
export interface PresetConfigType {
|
||||
/**
|
||||
* 自定义分屏规则配置
|
||||
* Custom split-screen rule configuration
|
||||
*/
|
||||
splitScreenConfig?: SplitScreenConfig;
|
||||
/**
|
||||
* 禁用预置右键菜单
|
||||
* Disable preset right-click menu
|
||||
*/
|
||||
disableContextMenu?: boolean;
|
||||
/**
|
||||
* 禁用全屏
|
||||
* Disable full screen
|
||||
*/
|
||||
disableFullScreen?: boolean;
|
||||
}
|
||||
|
||||
export interface ViewPluginOptions {
|
||||
// 预置配置
|
||||
// preset configuration
|
||||
presetConfig?: PresetConfigType;
|
||||
/**
|
||||
* 所有自定义 widget 工厂
|
||||
* All custom widget factories
|
||||
*/
|
||||
widgetFactories?: WidgetFactory[];
|
||||
/**
|
||||
* widget 报错渲染
|
||||
* Widget error rendering
|
||||
*/
|
||||
widgetFallbackRender?: React.FC<{ widget: ReactWidget } & FallbackProps>;
|
||||
/**
|
||||
* 默认布局信息
|
||||
* Default layout information
|
||||
*/
|
||||
defaultLayoutData?: LayoutData;
|
||||
|
||||
/**
|
||||
* 持久化数据存储的 key
|
||||
* The key to persistent data storage
|
||||
*/
|
||||
getStorageKey?: () => string;
|
||||
|
||||
/**
|
||||
* 关闭持久化逻辑
|
||||
* Turn off persistence logic
|
||||
*/
|
||||
restoreDisabled?: boolean;
|
||||
/**
|
||||
* 自定义设置
|
||||
* custom settings
|
||||
*/
|
||||
customPreferenceConfigs?: CustomPreferenceConfig[];
|
||||
|
||||
/**
|
||||
* 自定义 IDE 布局
|
||||
* Custom IDE layout
|
||||
*/
|
||||
customLayout?: (shell: ApplicationShell) => BoxLayout;
|
||||
}
|
||||
|
||||
/**
|
||||
* 菜单路径
|
||||
* menu path
|
||||
*/
|
||||
export type MenuPath = string[];
|
||||
|
||||
@@ -33,7 +33,7 @@ export class ViewManager {
|
||||
@named(ViewContribution)
|
||||
viewContributions: ContributionProvider<ViewContribution>;
|
||||
|
||||
// 通过 widgetManager 进行注入
|
||||
// Injection via widgetManager
|
||||
@inject(WidgetManager) widgetManager: WidgetManager;
|
||||
|
||||
@inject(ViewOptions) options: ViewOptions;
|
||||
@@ -69,7 +69,7 @@ export class ViewManager {
|
||||
viewOptions.defaultLayoutData?.defaultWidgets?.forEach(uri => {
|
||||
this.openerService.open(uri);
|
||||
});
|
||||
// activityBar 由内部自定义,比较特殊
|
||||
// activityBar is customized internally and is special.
|
||||
const activityBar = this.shell.activityBarWidget;
|
||||
this.viewRenderer.addReactPortal(activityBar);
|
||||
activityBar?.initView?.(
|
||||
|
||||
@@ -50,7 +50,7 @@ export class ViewRenderer {
|
||||
comp: React.FunctionComponent;
|
||||
}[] = [];
|
||||
|
||||
// 全局挂载,进入画布只会执行一次。
|
||||
// Global mount, entering the canvas will only be executed once.
|
||||
globalReactPortals: {
|
||||
key?: string;
|
||||
comp: React.FunctionComponent;
|
||||
@@ -86,8 +86,8 @@ export class ViewRenderer {
|
||||
}, 0);
|
||||
|
||||
/**
|
||||
* 转成 react
|
||||
* 注入 shell,避免 inject cycle
|
||||
* To react
|
||||
* Inject shell to avoid injection cycle
|
||||
*/
|
||||
toReactComponent(shell: ApplicationShell): React.FC {
|
||||
if (this.reactComp) {
|
||||
|
||||
@@ -134,7 +134,7 @@ export class WidgetManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用工厂模式注册
|
||||
* Register with factory mode
|
||||
*/
|
||||
async getOrCreateWidgetFromURI<T extends ReactWidget>(
|
||||
uri: URI,
|
||||
|
||||
@@ -156,7 +156,7 @@ export class FlowDockPanel extends DockPanel {
|
||||
}
|
||||
|
||||
handleEvent(event: Event): void {
|
||||
// 避免不同 dock-panel 之间的 tab 相互拖拽
|
||||
// Avoid dragging tabs between different dock-panels
|
||||
const dragSourceId = (event as Event & { source?: HTMLElement }).source?.id;
|
||||
const targetArea = (event.target as HTMLElement)?.closest?.(
|
||||
`#${dragSourceId}`,
|
||||
@@ -165,7 +165,7 @@ export class FlowDockPanel extends DockPanel {
|
||||
return;
|
||||
}
|
||||
|
||||
// 禁止分屏
|
||||
// Disable split screen
|
||||
if (this._options?.disabledSplitScreen) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ import { Panel, BoxLayout, BoxPanel, PanelLayout } from '../../lumino/widgets';
|
||||
export const SidePanelHandlerFactory = Symbol('SidePanelHandlerFactory');
|
||||
|
||||
/**
|
||||
* 侧边栏分级面板 handler
|
||||
* Sidebar grading panel handler
|
||||
*/
|
||||
@injectable()
|
||||
export class SidePanelHandler {
|
||||
|
||||
@@ -35,8 +35,8 @@ export abstract class ReactWidget extends AbstractWidget {
|
||||
uri?: URI;
|
||||
|
||||
/**
|
||||
* 容器 widget
|
||||
* 该属性只会在子面板内存在。方便通过父容器访问属性。
|
||||
* Container widget
|
||||
* This property only exists in the child panel. It is convenient to access the property through the parent container.
|
||||
*/
|
||||
wrapperWidget?: ReactWidget;
|
||||
|
||||
@@ -71,8 +71,8 @@ export abstract class ReactWidget extends AbstractWidget {
|
||||
|
||||
/**
|
||||
*
|
||||
* @param uri 初始化的 uri
|
||||
* @param childContainer view props 传入 widget 属性的时候才会有 childContainer
|
||||
* @Param uri Initialized uri
|
||||
* @param childContainer view props will only have childContainer when the widget property is passed in
|
||||
*/
|
||||
init(uri: URI, childContainer?: interfaces.Container): void {
|
||||
this.uri = uri;
|
||||
|
||||
@@ -176,7 +176,7 @@ export class DebugBarWidget extends ReactWidget {
|
||||
|
||||
render() {
|
||||
return (
|
||||
// 不走 lumino widget 逻辑,通过 css 控制显隐
|
||||
// Do not use the lumino widget logic, control the hidden through css
|
||||
<div
|
||||
className="debug-bar-widget-container"
|
||||
ref={this.ref}
|
||||
|
||||
@@ -36,9 +36,9 @@ import {
|
||||
import { type Message } from '../../lumino/messaging';
|
||||
import { SPLIT_PANEL_CLASSNAME } from '../../constants/view';
|
||||
|
||||
// 展开状态 className
|
||||
// Expand state className
|
||||
const EXPAND_CLASSNAME = 'expand';
|
||||
// 关闭状态 className
|
||||
// Close state className
|
||||
const CLOSE_CLASSNAME = 'close';
|
||||
|
||||
export interface SplitPanelType {
|
||||
@@ -64,14 +64,14 @@ export abstract class SplitWidget
|
||||
@inject(LayoutRestorer) protected layoutRestorer: LayoutRestorer;
|
||||
|
||||
/**
|
||||
* 存在表示启用内部分区
|
||||
* 使用 Orientation 标明布局分割方向
|
||||
* 水平 - horizontal
|
||||
* 垂直 - vertical
|
||||
* Presence indicates that internal partitioning is enabled
|
||||
* Use Orientation to indicate the layout split direction
|
||||
* Horizontal - horizontal
|
||||
* Vertical - vertical
|
||||
*/
|
||||
private _orientation: SplitLayout.Orientation | undefined;
|
||||
|
||||
/** 默认布局,初始化子面板的时候使用该布局 */
|
||||
/** Default layout, used when initializing subpanels */
|
||||
private _defaultStretch?: number[];
|
||||
|
||||
get defaultStretch() {
|
||||
@@ -113,7 +113,7 @@ export abstract class SplitWidget
|
||||
}
|
||||
|
||||
/**
|
||||
* 所有分区面板
|
||||
* All partition panels
|
||||
*/
|
||||
protected panels: Panel[] = [];
|
||||
|
||||
@@ -122,19 +122,19 @@ export abstract class SplitWidget
|
||||
splitPanels: SplitPanelType[] = [];
|
||||
|
||||
/**
|
||||
* 方向
|
||||
* direction
|
||||
*/
|
||||
direction?: BoxLayout.Direction = 'left-to-right';
|
||||
|
||||
protected onFitRequest(msg: Message): void {
|
||||
super.onFitRequest(msg);
|
||||
// 水平布局生效
|
||||
// Horizontal layout takes effect
|
||||
if (!this.panels?.length || this.orientation !== 'horizontal') {
|
||||
return;
|
||||
}
|
||||
/**
|
||||
* 修复 lumino 原生问题
|
||||
* 劫持 fit 方法,当面板 close 的时候移除前一个 handler
|
||||
* Fix lumino native issues
|
||||
* Hijack the fit method, remove the previous handler when the panel is closed
|
||||
*/
|
||||
this.panels.forEach(panel => {
|
||||
const panelDom = panel?.node;
|
||||
@@ -169,16 +169,16 @@ export abstract class SplitWidget
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化 panel node className
|
||||
* Initialize panel node className
|
||||
*/
|
||||
addClassNames() {
|
||||
// 数据不存在的时候不执行 classname 逻辑
|
||||
// Does not execute classname logic when data does not exist
|
||||
if (!this.storeData?.panelClose) {
|
||||
return;
|
||||
}
|
||||
this.panels.forEach((_, idx) => {
|
||||
// 1. 默认 expand 状态
|
||||
// 2. storeData 存储状态为 close 时初始化为 close
|
||||
// 1. Default expand state
|
||||
// 2. storeData is initialized to close when the storage state is closed
|
||||
const isExpand = !this.storeData?.panelClose?.[idx];
|
||||
if (!isExpand) {
|
||||
this.closePanel(idx);
|
||||
@@ -189,7 +189,7 @@ export abstract class SplitWidget
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据 uri 获取 widget
|
||||
* Get widget by URI
|
||||
*/
|
||||
getWidget(uri: URI) {
|
||||
const id = this.widgetManager.uriToWidgetID(uri);
|
||||
@@ -197,7 +197,7 @@ export abstract class SplitWidget
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据 widget uri 获取 expand 状态
|
||||
* Get expanded state according to widget uri
|
||||
*/
|
||||
getWidgetExpand(uri?: URI): boolean {
|
||||
if (!uri) {
|
||||
@@ -209,7 +209,7 @@ export abstract class SplitWidget
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建 panel
|
||||
* Create panel
|
||||
*/
|
||||
protected async createPanels(stretch: number[]) {
|
||||
this.splitPanels.sort(
|
||||
@@ -218,11 +218,11 @@ export abstract class SplitWidget
|
||||
return Promise.all(
|
||||
this.splitPanels.map(async ({ widgetUri, widget }, idx) => {
|
||||
const panel = this.createPanel(widgetUri);
|
||||
// 面板关闭状态
|
||||
// Panel closed status
|
||||
if (stretch?.[idx] === 0) {
|
||||
panel.node.classList.add(CLOSE_CLASSNAME);
|
||||
} else {
|
||||
// 默认 expand
|
||||
// Default expand
|
||||
panel.node.classList.add(EXPAND_CLASSNAME);
|
||||
}
|
||||
let panelWidget;
|
||||
@@ -246,7 +246,7 @@ export abstract class SplitWidget
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过 uri 展开 / 收起子面板
|
||||
* Expand/retract subpanels via URI
|
||||
*/
|
||||
toggleSubWidget(uri?: URI) {
|
||||
if (!uri || !this.layout) {
|
||||
@@ -261,8 +261,8 @@ export abstract class SplitWidget
|
||||
// const currentHandler = handlers[idx];
|
||||
const isExpand = panel.node.classList.contains(EXPAND_CLASSNAME);
|
||||
if (idx === expandIdx && isExpand) {
|
||||
// 执行 close panel
|
||||
// 隐藏 handler,避免关闭 panel 调整。
|
||||
// Execute close panel
|
||||
// Hide handlers to avoid closing panel adjustments.
|
||||
// currentHandler.classList.add('lm-mod-hidden');
|
||||
relativeSizes[idx] = 0;
|
||||
panel.node.classList.remove(EXPAND_CLASSNAME);
|
||||
@@ -308,10 +308,10 @@ export abstract class SplitWidget
|
||||
panel.node.classList.add(EXPAND_CLASSNAME);
|
||||
}
|
||||
|
||||
/** 通过 relativeSizes 直接控制面板开关 */
|
||||
/** Direct control panel switches via relativeSizes */
|
||||
/**
|
||||
* 为什么 RelativeSizes 不直接和 expand 状态绑定:
|
||||
* 面板关闭状态下可能默认展示标题高度,无法根据 relativeSizes 直接判断
|
||||
* Why RelativeSizes is not directly bound to the expand state:
|
||||
* When the panel is closed, the title height may be displayed by default, which cannot be directly judged according to relativeSizes.
|
||||
*/
|
||||
syncPanelRelativeSizes(sizes: number[]) {
|
||||
this.contentPanel.setRelativeSizes(sizes);
|
||||
@@ -331,9 +331,9 @@ export abstract class SplitWidget
|
||||
this.contentPanel.setRelativeSizes(sizes);
|
||||
}
|
||||
|
||||
/** 默认初始化分区布局 */
|
||||
/** Default initialization of partition layout */
|
||||
protected getDefaultStretch() {
|
||||
// 从默认配置中取
|
||||
// From the default configuration
|
||||
if (this.defaultStretch) {
|
||||
return this.defaultStretch;
|
||||
}
|
||||
@@ -343,7 +343,7 @@ export abstract class SplitWidget
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建 container
|
||||
* Create container
|
||||
*/
|
||||
protected async createContainer() {
|
||||
const stretch = this.getDefaultStretch();
|
||||
@@ -363,7 +363,7 @@ export abstract class SplitWidget
|
||||
}
|
||||
|
||||
/**
|
||||
* 默认不渲染
|
||||
* Default does not render
|
||||
*/
|
||||
render(): ReactElementType {
|
||||
return null;
|
||||
|
||||
@@ -79,7 +79,7 @@ export class CustomTabBar extends TabBar<Widget> {
|
||||
|
||||
this.scrollBarFactory = () =>
|
||||
new PerfectScrollbar(this.scrollContainer, {
|
||||
// 兼容鼠标模式下的滚动
|
||||
// Compatible scrolling in mouse mode
|
||||
useBothWheelAxes: true,
|
||||
suppressScrollY: true,
|
||||
});
|
||||
@@ -106,7 +106,7 @@ export class CustomTabBar extends TabBar<Widget> {
|
||||
handleEvent(event: Event): void {
|
||||
const canSuperHandle = this.getHandleEvent(event.target as HTMLElement);
|
||||
|
||||
// 不能阻塞 pointerup,否则 toolbar 展示会触发分屏拖拽
|
||||
// Cannot block pointerup, otherwise the toolbar display will trigger split-screen drag
|
||||
if (canSuperHandle || event.type === 'pointerup') {
|
||||
super.handleEvent(event);
|
||||
}
|
||||
|
||||
@@ -224,7 +224,7 @@ export class TabBarRenderer extends TabBar.Renderer {
|
||||
data.title.label,
|
||||
);
|
||||
} else {
|
||||
// 业务侧自己的 react 组件
|
||||
// The business side's own react component
|
||||
const virtualIconDOM = {
|
||||
render: (host: HTMLElement) => {
|
||||
const currentRoot = this.labelNodeRoot.get(host);
|
||||
@@ -264,10 +264,10 @@ export class TabBarRenderer extends TabBar.Renderer {
|
||||
const baseClassName = this.createIconClass(data);
|
||||
|
||||
if (typeof data.title.iconLabel === 'string') {
|
||||
// 使用 vscode iconClass
|
||||
// Using vscode iconClass
|
||||
return h.i({ className: codicon(data.title.iconLabel) });
|
||||
} else {
|
||||
// 业务侧自己的 react 组件
|
||||
// The business side's own react component
|
||||
const virtualIconDOM = {
|
||||
render: (host: HTMLElement) => {
|
||||
const currentRoot = this.iconNodeRoot.get(host);
|
||||
@@ -303,7 +303,7 @@ export class TabBarRenderer extends TabBar.Renderer {
|
||||
if (title) {
|
||||
const label = title.label || title.caption;
|
||||
if (this.tabBar.orientation === 'horizontal') {
|
||||
// 老的 preview
|
||||
// Old preview
|
||||
// this.hoverService.requestHover({
|
||||
// content: this.renderEnhancedPreview(title),
|
||||
// target: event.currentTarget,
|
||||
@@ -311,7 +311,7 @@ export class TabBarRenderer extends TabBar.Renderer {
|
||||
// cssClasses: ['extended-tab-preview'],
|
||||
// visualPreview: width => this.renderVisualPreview(width, title),
|
||||
// });
|
||||
// 使用外部的 tooltip 组件
|
||||
// Using an external tooltip component
|
||||
label &&
|
||||
this.hoverService.requestHover({
|
||||
content: label,
|
||||
@@ -342,7 +342,7 @@ export class TabBarRenderer extends TabBar.Renderer {
|
||||
Command.Default.VIEW_SAVING_WIDGET_CLOSE_CONFIRM,
|
||||
[title],
|
||||
);
|
||||
// 保存关闭提示
|
||||
// Save close prompt
|
||||
} else {
|
||||
title?.owner.close();
|
||||
}
|
||||
@@ -353,12 +353,12 @@ export class TabBarRenderer extends TabBar.Renderer {
|
||||
event: MouseEvent,
|
||||
title?: CustomTitleType,
|
||||
) => {
|
||||
// 禁用全屏时禁止 tab 双击触发全屏
|
||||
// Disable full screen when disabling tab double-clicking to trigger full screen
|
||||
if (this.shell.disableFullScreen) {
|
||||
return;
|
||||
}
|
||||
const isMainPanel = title?.owner?.parent?.id === MAIN_PANEL_ID;
|
||||
// 主编辑区才会触发全屏
|
||||
// The main editing area will only trigger full screen.
|
||||
if (
|
||||
this.tabBar &&
|
||||
event.currentTarget instanceof HTMLElement &&
|
||||
|
||||
@@ -84,7 +84,7 @@ export class TabBarToolbar extends ReactWidget {
|
||||
) as ReactWidget;
|
||||
return (factory?.toolbarItems || [])
|
||||
.filter(item => {
|
||||
// 默认是 ToolbarAlign.TRAILING
|
||||
// Default is ToolbarAlign. TRAILING
|
||||
if (!this.align) {
|
||||
return !item.align || item.align === ToolbarAlign.TRAILING;
|
||||
}
|
||||
|
||||
@@ -23,49 +23,49 @@ import { type ReactWidget } from './react-widget';
|
||||
export const WidgetFactory = Symbol('WidgetFactory');
|
||||
|
||||
export interface ToolbarItem {
|
||||
// 1. 携带 commandId 走命令模式
|
||||
// 1. Carry the commandId into command mode
|
||||
commandId?: string;
|
||||
tooltip?: string;
|
||||
// 2. 携带 render 走直接渲染的模式
|
||||
// 2. Carry the render to the direct rendering mode
|
||||
render?: (widget: ReactWidget) => React.ReactElement<any, any> | null;
|
||||
|
||||
/**
|
||||
* toolbar 对齐位置,默认是 ToolbarAlign.TRAILING
|
||||
* Toolbar alignment position, the default is ToolbarAlign. TRAILING
|
||||
*/
|
||||
align?: ToolbarAlign;
|
||||
}
|
||||
|
||||
export interface WidgetFactory {
|
||||
/**
|
||||
* widget 面板所在的区域
|
||||
* The area where the widget panel is located
|
||||
*/
|
||||
area: LayoutPanelType;
|
||||
/**
|
||||
* widget 面板的 toolbar,只有 dockpanel 才会渲染
|
||||
* The toolbar of the widget panel, only dockpanel will render
|
||||
*/
|
||||
toolbarItems?: ToolbarItem[];
|
||||
/**
|
||||
* 通过 render 方法注入
|
||||
* Injection via render method
|
||||
*/
|
||||
render?: () => React.ReactElement<any, any> | null;
|
||||
/**
|
||||
* 通过 widget 方式注入
|
||||
* Inject via widget
|
||||
*/
|
||||
createWidget?: (uri: URI) => MaybePromise<ReactWidget>;
|
||||
/**
|
||||
* 指定 widget class
|
||||
* Specify the widget class
|
||||
*/
|
||||
widget?: AsClass<ReactWidget>;
|
||||
/**
|
||||
* 根据 uri 进行面板匹配
|
||||
* Panel matching based on URI
|
||||
*/
|
||||
canHandle?: (uri: URI) => boolean;
|
||||
/**
|
||||
* 通过 uri 生成 widget id
|
||||
* Generate widget id by URI
|
||||
*/
|
||||
getId?: (uri: URI) => string;
|
||||
/**
|
||||
* 业务侧通过 uri 正则匹配
|
||||
* Business side regular matching through URI
|
||||
*/
|
||||
match?: RegExp;
|
||||
}
|
||||
|
||||
@@ -72,14 +72,14 @@ export class WidgetOpenHandler implements OpenHandler {
|
||||
...options,
|
||||
area,
|
||||
});
|
||||
/** 创建 widget 时尝试从内存中恢复状态 */
|
||||
/** Attempt to restore state from memory when creating a widget */
|
||||
this.layoutRestorer.restoreWidget(widget);
|
||||
/** 监听销毁时尝试保存状态到内存中 */
|
||||
/** Attempt to save state to memory while listening for destruction */
|
||||
widget.onDispose(() => this.layoutRestorer.storeWidget(widget));
|
||||
}
|
||||
widget.parent?.show();
|
||||
/**
|
||||
* 如果打开的是 bottom,并且底部比较打开的不够高则自动打开一定高度
|
||||
* If the bottom is opened, and the bottom is not high enough compared to the open one, it will automatically open a certain height.
|
||||
*/
|
||||
if (
|
||||
area === LayoutPanelType.BOTTOM_PANEL &&
|
||||
@@ -118,7 +118,7 @@ export class WidgetOpenHandler implements OpenHandler {
|
||||
widget.uri = uri;
|
||||
widget.onOpenRequest?.(uri, options);
|
||||
|
||||
// 区域唯一展示
|
||||
// The only display in the region
|
||||
widget.show();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user