diff --git a/src/vs/workbench/contrib/example/browser/common/stockDetailsService.ts b/src/vs/workbench/contrib/example/browser/common/stockDetailsService.ts new file mode 100644 index 0000000..5b98cbb --- /dev/null +++ b/src/vs/workbench/contrib/example/browser/common/stockDetailsService.ts @@ -0,0 +1,42 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { createDecorator } from '../../../../../platform/instantiation/common/instantiation.js'; +import { Emitter, Event } from '../../../../../base/common/event.js'; + +/** + * 定义服务接口和标识符 + */ +export const IStockDetailsService = createDecorator('stockDetailsService'); + +/** + * 股票详情接口 + */ +export interface StockDetail { + code: string; +} + +/** + * 股票详情服务接口 + */ +export interface IStockDetailsService { + readonly _serviceBrand: undefined; // 用于类型检查的标识,强制接口与服务绑定 + readonly onStockSelected: Event; + selectStock(stock: StockDetail): void; +} + +/** + * 股票详情服务实现 + */ +export class StockDetailsService implements IStockDetailsService { + public readonly _serviceBrand: undefined; // 实现接口要求 + + private readonly _onStockSelected = new Emitter(); + public readonly onStockSelected: Event = this._onStockSelected.event; + + public selectStock(stock: StockDetail): void { + this._onStockSelected.fire(stock); + } +} diff --git a/src/vs/workbench/contrib/example/browser/example.contribution.ts b/src/vs/workbench/contrib/example/browser/example.contribution.ts index dc6ca0b..6f10211 100644 --- a/src/vs/workbench/contrib/example/browser/example.contribution.ts +++ b/src/vs/workbench/contrib/example/browser/example.contribution.ts @@ -16,14 +16,20 @@ import { registerIcon } from '../../../../platform/theme/common/iconRegistry.js' import { Codicon } from '../../../../base/common/codicons.js'; import { ExampleViewContainer } from './views/exampleViewContainer.js'; import { ExampleView } from './views/exampleView.js'; +import { AuxiliaryView } from './views/auxiliaryView.js'; +import { AuiliaryViewContainer } from './views/auiliaryViewContainer.js'; +import { PanelView } from './views/panelView.js'; +import { PanelViewContainer } from './views/panelViewContainer.js'; import { IViewPaneOptions } from '../../../browser/parts/views/viewPane.js'; import { EditorPaneDescriptor, IEditorPaneRegistry } from '../../../browser/editor.js'; import { EditorExtensions } from '../../../common/editor.js'; import { StockDetailsEditor } from './editors/StockDetailsEditor.js'; import { StockDetailsInput } from './editors/StockDetailsInput.js'; +import { IStockDetailsService, StockDetailsService } from './common/stockDetailsService.js'; +import { InstantiationType, registerSingleton } from '../../../../platform/instantiation/common/extensions.js'; - - +// 注册消息传递服务 +registerSingleton(IStockDetailsService, StockDetailsService, InstantiationType.Delayed); // 如果需要为 Extensions 使用别名,可以在此处赋值 const ViewContainerExtensions = Extensions; @@ -36,7 +42,7 @@ const exampleIcon = registerIcon( localize('exampleViewIcon', 'Example View 的图标') ); -// 注册视图容器 +// 注册侧边栏视图容器 const viewContainer = Registry.as(ViewContainerExtensions.ViewContainersRegistry).registerViewContainer( { id: 'workbench.view.example', @@ -54,13 +60,14 @@ const exampleViewOptions: IViewPaneOptions = { title: '示例视图', }; +//生成本地化字符串对象 function localizedString(key: string, defaultMessage: string, original: string): ILocalizedString { - console.log('Registering Example View Container...'); + console.log(`Registering Example View Container... Key: ${key}`); // eslint-disable-next-line local/code-no-unexternalized-strings return { value: localize(key, defaultMessage), original }; } -// 注册视图 +// 注册侧边栏视图 Registry.as(ViewExtensions.ViewsRegistry).registerViews( [ { @@ -76,13 +83,70 @@ Registry.as(ViewExtensions.ViewsRegistry).registerViews( Registry.as(EditorExtensions.EditorPane).registerEditorPane( EditorPaneDescriptor.create( StockDetailsEditor, // 编辑器的类 - StockDetailsEditor.ID, // 编辑器唯一标识符 + StockDetailsEditor.ID, // 编辑器唯一标识符hi localize('stockDetails', 'Stock Details') // 编辑器的本地化名称 ), [new SyncDescriptor(StockDetailsInput)] // 绑定的 EditorInput 类型 ); +// 注册图标 +const auxiliaryIcon = registerIcon( + 'auxiliary-view-icon', + Codicon.beaker, + localize('auxiliaryViewIcon', 'Auxiliary View Icon') +); + +// 注册副侧边栏容器 +const auxiliaryContainer = Registry.as(Extensions.ViewContainersRegistry).registerViewContainer( + { + id: 'workbench.view.auxiliaryExample', + title: { value: localize('auxiliaryExample', '副侧边栏示例'), original: 'Auxiliary Example' }, + ctorDescriptor: new SyncDescriptor(AuiliaryViewContainer), + icon: auxiliaryIcon, + order: 1, // 确保显示顺序 + hideIfEmpty: true,// 如果没有视图则隐藏 + }, + ViewContainerLocation.AuxiliaryBar // 注册到副侧边栏 +); + +// 注册副侧边栏视图 +Registry.as(Extensions.ViewsRegistry).registerViews( + [ + { + id: 'auxiliaryExampleView', + name: localizedString('auxiliaryExampleView', '副侧边栏视图', 'auxiliaryExampleView'), // 使用 localize 返回的值 + ctorDescriptor: new SyncDescriptor(AuxiliaryView), // 使用 ExampleView 的类定义 + }, + ], + auxiliaryContainer +); + +//注册底栏容器 +const panelContainer = Registry.as(Extensions.ViewContainersRegistry).registerViewContainer( + { + id: 'workbench.view.panelExample', + title: { value: localize('panelExample', '底栏示例'), original: 'Panel Example' }, + ctorDescriptor: new SyncDescriptor(PanelViewContainer), + icon: auxiliaryIcon, + order: 6, // 确保显示顺序 + hideIfEmpty: true,// 如果没有视图则隐藏 + }, + ViewContainerLocation.Panel // 注册底栏 +); + +//注册底栏视图 +Registry.as(Extensions.ViewsRegistry).registerViews( + [ + { + id: 'panelExample', + name: localizedString('panelExample', '底栏视图', 'panelExample'), + ctorDescriptor: new SyncDescriptor(PanelView), + }, + ], + panelContainer +); + + -console.log('StockDetailsEditor 注册完成'); console.log('初始化完成'); diff --git a/src/vs/workbench/contrib/example/browser/views/auiliaryViewContainer.ts b/src/vs/workbench/contrib/example/browser/views/auiliaryViewContainer.ts new file mode 100644 index 0000000..0dc9c08 --- /dev/null +++ b/src/vs/workbench/contrib/example/browser/views/auiliaryViewContainer.ts @@ -0,0 +1,52 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { ViewPaneContainer } from '../../../../browser/parts/views/viewPaneContainer.js'; +import { IInstantiationService } from '../../../../../platform/instantiation/common/instantiation.js'; +import { IConfigurationService } from '../../../../../platform/configuration/common/configuration.js'; +import { IExtensionService } from '../../../../services/extensions/common/extensions.js'; +import { ITelemetryService } from '../../../../../platform/telemetry/common/telemetry.js'; +import { IThemeService } from '../../../../../platform/theme/common/themeService.js'; +import { IStorageService } from '../../../../../platform/storage/common/storage.js'; +import { IWorkbenchLayoutService } from '../../../../services/layout/browser/layoutService.js'; +import { IContextMenuService } from '../../../../../platform/contextview/browser/contextView.js'; +import { IViewDescriptorService } from '../../../../common/views.js'; +import { IWorkspaceContextService } from '../../../../../platform/workspace/common/workspace.js'; + + +export class AuiliaryViewContainer extends ViewPaneContainer { + constructor( + @IInstantiationService instantiationService: IInstantiationService, + @IConfigurationService configurationService: IConfigurationService, + @IWorkbenchLayoutService layoutService: IWorkbenchLayoutService, + @IContextMenuService contextMenuService: IContextMenuService, + @ITelemetryService telemetryService: ITelemetryService, + @IExtensionService extensionService: IExtensionService, + @IThemeService themeService: IThemeService, + @IStorageService storageService: IStorageService, + @IViewDescriptorService viewDescriptorService: IViewDescriptorService, + @IWorkspaceContextService contextService: IWorkspaceContextService + ) { + super( + 'workbench.view.auxiliaryExample', + { mergeViewWithContainerWhenSingleView: true }, + instantiationService, + configurationService, + layoutService, + contextMenuService, + telemetryService, + extensionService, + themeService, + storageService, + contextService, + viewDescriptorService + ); + } + + override getTitle(): string { + return ''; // 返回空字符串,确保没有容器标题和冒号 + } + +} diff --git a/src/vs/workbench/contrib/example/browser/views/auxiliaryView.ts b/src/vs/workbench/contrib/example/browser/views/auxiliaryView.ts new file mode 100644 index 0000000..0a6fd2d --- /dev/null +++ b/src/vs/workbench/contrib/example/browser/views/auxiliaryView.ts @@ -0,0 +1,80 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { IViewPaneOptions, ViewPane } from '../../../../browser/parts/views/viewPane.js'; + +import { IKeybindingService } from '../../../../../platform/keybinding/common/keybinding.js'; +import { IContextMenuService } from '../../../../../platform/contextview/browser/contextView.js'; +import { IConfigurationService } from '../../../../../platform/configuration/common/configuration.js'; +import { IContextKeyService } from '../../../../../platform/contextkey/common/contextkey.js'; +import { IViewDescriptorService } from '../../../../common/views.js'; +import { IInstantiationService } from '../../../../../platform/instantiation/common/instantiation.js'; +import { IOpenerService } from '../../../../../platform/opener/common/opener.js'; +import { IThemeService } from '../../../../../platform/theme/common/themeService.js'; +import { ITelemetryService } from '../../../../../platform/telemetry/common/telemetry.js'; +import { IAccessibleViewService } from '../../../../../platform/accessibility/browser/accessibleView.js'; +import { IHoverService } from '../../../../../platform/hover/browser/hover.js'; +import * as DOM from '../../../../../base/browser/dom.js'; + +import { IStockDetailsService, StockDetail } from '../common/stockDetailsService.js'; + +export class AuxiliaryView extends ViewPane { + private stockDetailContainer: HTMLElement | undefined; + + constructor( + options: IViewPaneOptions, + @IKeybindingService keybindingService: IKeybindingService, + @IContextMenuService contextMenuService: IContextMenuService, + @IConfigurationService configurationService: IConfigurationService, + @IContextKeyService contextKeyService: IContextKeyService, + @IViewDescriptorService viewDescriptorService: IViewDescriptorService, + @IInstantiationService instantiationService: IInstantiationService, + @IOpenerService openerService: IOpenerService, + @IThemeService themeService: IThemeService, + @ITelemetryService telemetryService: ITelemetryService, + @IHoverService hoverService: IHoverService, + @IAccessibleViewService accessibleViewService: IAccessibleViewService, + @IStockDetailsService private readonly stockDetailsService: IStockDetailsService // 注入股票消息传递服务 + ) { + super( + options, + keybindingService, + contextMenuService, + configurationService, + contextKeyService, + viewDescriptorService, + instantiationService, + openerService, + themeService, + telemetryService, + hoverService + ); + + // 订阅股票选中事件 + this.stockDetailsService.onStockSelected(this.handleStockSelected, this); + } + + override renderBody(container: HTMLElement): void { + super.renderBody(container); + + // 创建容器,用于显示股票详情 + this.stockDetailContainer = DOM.$('div', { class: 'stock-detail' }); + container.appendChild(this.stockDetailContainer); + + // 初始化时显示默认信息 + this.stockDetailContainer.textContent = '请选择股票以查看详情'; + } + + private handleStockSelected(stock: StockDetail): void { + // 更新容器内容 + if (this.stockDetailContainer) { + this.stockDetailContainer.textContent = `股票代码: ${stock.code}`; + } + } + + override layoutBody(height: number, width: number): void { + // 布局逻辑,如果需要调整高度和宽度 + } +} diff --git a/src/vs/workbench/contrib/example/browser/views/exampleView.ts b/src/vs/workbench/contrib/example/browser/views/exampleView.ts index 8a81130..29a42f2 100644 --- a/src/vs/workbench/contrib/example/browser/views/exampleView.ts +++ b/src/vs/workbench/contrib/example/browser/views/exampleView.ts @@ -22,6 +22,9 @@ import { URI } from '../../../../../base/common/uri.js'; import './media/exampleViewContainer.css'; import { IEditorService } from '../../../../services/editor/common/editorService.js'; import { StockDetailsInput } from '../editors/StockDetailsInput.js'; +import { IWorkbenchLayoutService, Parts } from '../../../../services/layout/browser/layoutService.js'; +import { IStockDetailsService, StockDetail } from '../common/stockDetailsService.js'; + export class ExampleView extends ViewPane { constructor( @@ -36,7 +39,9 @@ export class ExampleView extends ViewPane { @IThemeService themeService: IThemeService, @ITelemetryService telemetryService: ITelemetryService, @IHoverService hoverService: IHoverService, - @IAccessibleViewService accessibleViewService: IAccessibleViewService + @IAccessibleViewService accessibleViewService: IAccessibleViewService, + @IEditorService private readonly editorService: IEditorService, + @IStockDetailsService private readonly stockDetailsService: IStockDetailsService ) { super( options, @@ -52,58 +57,11 @@ export class ExampleView extends ViewPane { hoverService, ); + + // 监听活动编辑器的变化 + this.editorService.onDidActiveEditorChange(() => this.onActiveEditorChange()); } - // 您可以在这里添加自定义的视图逻辑 - - // override renderBody(container: HTMLElement): void { - // super.renderBody(container); - - // // 创建一个用于股票列表的容器 - // const stockListContainer = DOM.$('.stock-list-container'); - // stockListContainer.style.padding = '10px'; - // stockListContainer.style.overflowY = 'auto'; - // stockListContainer.style.maxHeight = '100%'; - - // // 模拟股票列表 - // const mockStockData = [ - // { name: 'Stock A', code: '000001', price: '100.00' }, - // { name: 'Stock B', code: '000002', price: '200.00' }, - // { name: 'Stock C', code: '000003', price: '300.00' }, - // { name: 'Stock D', code: '000004', price: '400.00' }, - // { name: 'Stock E', code: '000005', price: '500.00' }, - // ]; - - // // 创建列表元素 - // const ul = DOM.$('ul'); - // ul.style.listStyleType = 'none'; - // ul.style.margin = '0'; - // ul.style.padding = '0'; - - // // 遍历伪数据并创建每个列表项 - // mockStockData.forEach(stock => { - // const li = DOM.$('li'); - // li.style.display = 'flex'; - // li.style.justifyContent = 'space-between'; - // li.style.padding = '8px'; - // li.style.borderBottom = '1px solid #ccc'; - - // const name = DOM.$('span'); - // name.textContent = `${stock.name} (${stock.code})`; - - // const price = DOM.$('span'); - // price.textContent = `¥${stock.price}`; - - // li.appendChild(name); - // li.appendChild(price); - // ul.appendChild(li); - // }); - - // // 将列表添加到容器中 - // stockListContainer.appendChild(ul); - // container.appendChild(stockListContainer); - // } - override renderBody(container: HTMLElement): void { super.renderBody(container); @@ -130,15 +88,6 @@ export class ExampleView extends ViewPane { container.appendChild(ul); // 将列表附加到容器中 } - // private openStockDetails(stock: { name: string; code: string; price: number }): void { - // const uri = URI.parse(`stock-details://${stock.code}`); // 自定义 URI - // const editorInput = new StockDetailsInput(uri); // 创建新的输入实例 - - // const editorService = this.instantiationService.invokeFunction(accessor => accessor.get(IEditorService)); // 获取编辑器服务 - // editorService.openEditor(editorInput, { pinned: true }).then(() => { // 打开编辑器 - // console.log(`Opened details for ${stock.name}`); - // }); - // } private openStockDetails(stock: { name: string; code: string; price: number }): void { if (!stock.code || stock.code.trim() === '') { @@ -157,6 +106,26 @@ export class ExampleView extends ViewPane { }).catch(err => { console.error(`打开股票详情失败: ${err.message}`); }); + + // 通知服务选中股票 + const stockDetailsService = this.instantiationService.invokeFunction(accessor => accessor.get(IStockDetailsService)); + + stockDetailsService.selectStock(stock); + + // 打开副侧边栏 + const layoutService = this.instantiationService.invokeFunction(accessor => accessor.get(IWorkbenchLayoutService)); + layoutService.setPartHidden(false, Parts.AUXILIARYBAR_PART); // 打开副侧边栏 + } + + private onActiveEditorChange(): void { + const activeEditor = this.editorService.activeEditor; + console.log('活动编辑器已更改:', activeEditor); + if (activeEditor instanceof StockDetailsInput) { + const stockDetail: StockDetail = { + code: activeEditor.getCode() // 创建包含 code 的对象 + }; + this.stockDetailsService.selectStock(stockDetail); // 传递对象 + } } override layoutBody(height: number, width: number): void { diff --git a/src/vs/workbench/contrib/example/browser/views/panelView.ts b/src/vs/workbench/contrib/example/browser/views/panelView.ts new file mode 100644 index 0000000..4b1895f --- /dev/null +++ b/src/vs/workbench/contrib/example/browser/views/panelView.ts @@ -0,0 +1,80 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { IViewPaneOptions, ViewPane } from '../../../../browser/parts/views/viewPane.js'; + +import { IKeybindingService } from '../../../../../platform/keybinding/common/keybinding.js'; +import { IContextMenuService } from '../../../../../platform/contextview/browser/contextView.js'; +import { IConfigurationService } from '../../../../../platform/configuration/common/configuration.js'; +import { IContextKeyService } from '../../../../../platform/contextkey/common/contextkey.js'; +import { IViewDescriptorService } from '../../../../common/views.js'; +import { IInstantiationService } from '../../../../../platform/instantiation/common/instantiation.js'; +import { IOpenerService } from '../../../../../platform/opener/common/opener.js'; +import { IThemeService } from '../../../../../platform/theme/common/themeService.js'; +import { ITelemetryService } from '../../../../../platform/telemetry/common/telemetry.js'; +import { IAccessibleViewService } from '../../../../../platform/accessibility/browser/accessibleView.js'; +import { IHoverService } from '../../../../../platform/hover/browser/hover.js'; +import * as DOM from '../../../../../base/browser/dom.js'; + +import { IStockDetailsService, StockDetail } from '../common/stockDetailsService.js'; + +export class PanelView extends ViewPane { + private stockDetailContainer: HTMLElement | undefined; + + constructor( + options: IViewPaneOptions, + @IKeybindingService keybindingService: IKeybindingService, + @IContextMenuService contextMenuService: IContextMenuService, + @IConfigurationService configurationService: IConfigurationService, + @IContextKeyService contextKeyService: IContextKeyService, + @IViewDescriptorService viewDescriptorService: IViewDescriptorService, + @IInstantiationService instantiationService: IInstantiationService, + @IOpenerService openerService: IOpenerService, + @IThemeService themeService: IThemeService, + @ITelemetryService telemetryService: ITelemetryService, + @IHoverService hoverService: IHoverService, + @IAccessibleViewService accessibleViewService: IAccessibleViewService, + @IStockDetailsService private readonly stockDetailsService: IStockDetailsService // 注入股票消息传递服务 + ) { + super( + options, + keybindingService, + contextMenuService, + configurationService, + contextKeyService, + viewDescriptorService, + instantiationService, + openerService, + themeService, + telemetryService, + hoverService + ); + + // 订阅股票选中事件 + this.stockDetailsService.onStockSelected(this.handleStockSelected, this); + } + + override renderBody(container: HTMLElement): void { + super.renderBody(container); + + // 创建容器,用于显示股票详情 + this.stockDetailContainer = DOM.$('div', { class: 'stock-detail' }); + container.appendChild(this.stockDetailContainer); + + // 初始化时显示默认信息 + this.stockDetailContainer.textContent = '请选择股票以查看详情'; + } + + private handleStockSelected(stock: StockDetail): void { + // 更新容器内容 + if (this.stockDetailContainer) { + this.stockDetailContainer.textContent = `股票代码: ${stock.code}`; + } + } + + override layoutBody(height: number, width: number): void { + // 布局逻辑,如果需要调整高度和宽度 + } +} diff --git a/src/vs/workbench/contrib/example/browser/views/panelViewContainer.ts b/src/vs/workbench/contrib/example/browser/views/panelViewContainer.ts new file mode 100644 index 0000000..0fff62b --- /dev/null +++ b/src/vs/workbench/contrib/example/browser/views/panelViewContainer.ts @@ -0,0 +1,52 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { ViewPaneContainer } from '../../../../browser/parts/views/viewPaneContainer.js'; +import { IInstantiationService } from '../../../../../platform/instantiation/common/instantiation.js'; +import { IConfigurationService } from '../../../../../platform/configuration/common/configuration.js'; +import { IExtensionService } from '../../../../services/extensions/common/extensions.js'; +import { ITelemetryService } from '../../../../../platform/telemetry/common/telemetry.js'; +import { IThemeService } from '../../../../../platform/theme/common/themeService.js'; +import { IStorageService } from '../../../../../platform/storage/common/storage.js'; +import { IWorkbenchLayoutService } from '../../../../services/layout/browser/layoutService.js'; +import { IContextMenuService } from '../../../../../platform/contextview/browser/contextView.js'; +import { IViewDescriptorService } from '../../../../common/views.js'; +import { IWorkspaceContextService } from '../../../../../platform/workspace/common/workspace.js'; + + +export class PanelViewContainer extends ViewPaneContainer { + constructor( + @IInstantiationService instantiationService: IInstantiationService, + @IConfigurationService configurationService: IConfigurationService, + @IWorkbenchLayoutService layoutService: IWorkbenchLayoutService, + @IContextMenuService contextMenuService: IContextMenuService, + @ITelemetryService telemetryService: ITelemetryService, + @IExtensionService extensionService: IExtensionService, + @IThemeService themeService: IThemeService, + @IStorageService storageService: IStorageService, + @IViewDescriptorService viewDescriptorService: IViewDescriptorService, + @IWorkspaceContextService contextService: IWorkspaceContextService + ) { + super( + 'workbench.view.auxiliaryExample', + { mergeViewWithContainerWhenSingleView: true }, + instantiationService, + configurationService, + layoutService, + contextMenuService, + telemetryService, + extensionService, + themeService, + storageService, + contextService, + viewDescriptorService + ); + } + + override getTitle(): string { + return ''; // 返回空字符串,确保没有容器标题和冒号 + } + +}