Skip to content

Commit b705635

Browse files
committed
implementation of the new outline provider
1 parent 9920027 commit b705635

File tree

6 files changed

+452
-9
lines changed

6 files changed

+452
-9
lines changed

package.json

Lines changed: 179 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,20 @@
2525
"customEditorOutline"
2626
],
2727
"contributes": {
28+
"submenus": [
29+
{
30+
"id": "designer.outline.editSubmenu",
31+
"label": "Edit"
32+
},
33+
{
34+
"id": "designer.outline.modifySubmenu",
35+
"label": "Modify"
36+
},
37+
{
38+
"id": "designer.outline.viewSubmenu",
39+
"label": "View"
40+
}
41+
],
2842
"menus": {
2943
"editor/title": [
3044
{
@@ -39,6 +53,99 @@
3953
"when": "true",
4054
"group": "navigation"
4155
}
56+
],
57+
"customEditor/outline/toolbar": [
58+
{
59+
"command": "designer.outline.toggleLock",
60+
"group": "inline",
61+
"when": "true"
62+
},
63+
{
64+
"command": "designer.outline.toggleHideInDesigner",
65+
"group": "inline",
66+
"when": "true"
67+
},
68+
{
69+
"command": "designer.outline.toggleHideAtRuntime",
70+
"group": "inline",
71+
"when": "true"
72+
}
73+
],
74+
"customEditor/outline/context": [
75+
{
76+
"submenu": "designer.outline.editSubmenu",
77+
"group": "1_edit"
78+
},
79+
{
80+
"submenu": "designer.outline.modifySubmenu",
81+
"group": "2_modify"
82+
},
83+
{
84+
"submenu": "designer.outline.viewSubmenu",
85+
"group": "3_view"
86+
},
87+
{
88+
"command": "designer.outline.expandChildren",
89+
"group": "4_expandCollapse@1"
90+
},
91+
{
92+
"command": "designer.outline.collapseChildren",
93+
"group": "4_expandCollapse@2"
94+
}
95+
],
96+
"designer.outline.editSubmenu": [
97+
{
98+
"command": "designer.outline.copy",
99+
"group": "1_clipboard@1"
100+
},
101+
{
102+
"command": "designer.outline.cut",
103+
"group": "1_clipboard@2"
104+
},
105+
{
106+
"command": "designer.outline.paste",
107+
"group": "1_clipboard@3"
108+
},
109+
{
110+
"command": "designer.outline.delete",
111+
"group": "2_delete@1"
112+
}
113+
],
114+
"designer.outline.modifySubmenu": [
115+
{
116+
"command": "designer.outline.rotateLeft",
117+
"group": "1_rotate@1"
118+
},
119+
{
120+
"command": "designer.outline.rotateRight",
121+
"group": "1_rotate@2"
122+
},
123+
{
124+
"command": "designer.outline.toFront",
125+
"group": "2_order@1"
126+
},
127+
{
128+
"command": "designer.outline.moveForward",
129+
"group": "2_order@2"
130+
},
131+
{
132+
"command": "designer.outline.moveBackward",
133+
"group": "2_order@3"
134+
},
135+
{
136+
"command": "designer.outline.toBack",
137+
"group": "2_order@4"
138+
}
139+
],
140+
"designer.outline.viewSubmenu": [
141+
{
142+
"command": "designer.outline.moveTo",
143+
"group": "1_navigation@1"
144+
},
145+
{
146+
"command": "designer.outline.jumpTo",
147+
"group": "1_navigation@2"
148+
}
42149
]
43150
},
44151
"commands": [
@@ -49,6 +156,77 @@
49156
"light": "resources/light/editor.svg",
50157
"dark": "resources/dark/editor.svg"
51158
}
159+
},
160+
{
161+
"command": "designer.outline.toggleLock",
162+
"title": "Toggle Lock",
163+
"icon": "$(lock)"
164+
},
165+
{
166+
"command": "designer.outline.toggleHideInDesigner",
167+
"title": "Toggle Hide in Designer",
168+
"icon": "$(eye)"
169+
},
170+
{
171+
"command": "designer.outline.toggleHideAtRuntime",
172+
"title": "Toggle Hide at Runtime",
173+
"icon": "$(eye-closed)"
174+
},
175+
{
176+
"command": "designer.outline.copy",
177+
"title": "Copy"
178+
},
179+
{
180+
"command": "designer.outline.cut",
181+
"title": "Cut"
182+
},
183+
{
184+
"command": "designer.outline.paste",
185+
"title": "Paste"
186+
},
187+
{
188+
"command": "designer.outline.delete",
189+
"title": "Delete"
190+
},
191+
{
192+
"command": "designer.outline.rotateLeft",
193+
"title": "Rotate Left"
194+
},
195+
{
196+
"command": "designer.outline.rotateRight",
197+
"title": "Rotate Right"
198+
},
199+
{
200+
"command": "designer.outline.toFront",
201+
"title": "To Front"
202+
},
203+
{
204+
"command": "designer.outline.moveForward",
205+
"title": "Move Forward"
206+
},
207+
{
208+
"command": "designer.outline.moveBackward",
209+
"title": "Move Backward"
210+
},
211+
{
212+
"command": "designer.outline.toBack",
213+
"title": "To Back"
214+
},
215+
{
216+
"command": "designer.outline.moveTo",
217+
"title": "Move To"
218+
},
219+
{
220+
"command": "designer.outline.jumpTo",
221+
"title": "Jump To"
222+
},
223+
{
224+
"command": "designer.outline.expandChildren",
225+
"title": "Expand Children"
226+
},
227+
{
228+
"command": "designer.outline.collapseChildren",
229+
"title": "Collapse Children"
52230
}
53231
],
54232
"customEditors": [
@@ -119,4 +297,4 @@
119297
"es-module-shims": "^2.8.0",
120298
"typescript": "^5.8.3"
121299
}
122-
}
300+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import * as vscode from 'vscode';
2+
3+
export interface SerializedOutlineItem {
4+
id: string;
5+
label: string;
6+
detail?: string;
7+
icon?: string;
8+
contextValue?: string;
9+
children?: SerializedOutlineItem[];
10+
}
11+
12+
function convertItems(items: SerializedOutlineItem[]): vscode.CustomEditorOutlineItem[] {
13+
return items.map(item => ({
14+
id: item.id,
15+
label: item.label,
16+
detail: item.detail,
17+
icon: item.icon ? new vscode.ThemeIcon(item.icon) : undefined,
18+
contextValue: item.contextValue,
19+
children: item.children ? convertItems(item.children) : undefined,
20+
}));
21+
}
22+
23+
export class DesignerOutlineProvider implements vscode.CustomEditorOutlineProvider {
24+
private readonly _onDidChangeOutline = new vscode.EventEmitter<void>();
25+
readonly onDidChangeOutline = this._onDidChangeOutline.event;
26+
27+
private readonly _onDidChangeActiveItem = new vscode.EventEmitter<string | undefined>();
28+
readonly onDidChangeActiveItem = this._onDidChangeActiveItem.event;
29+
30+
private _items: vscode.CustomEditorOutlineItem[] = [];
31+
private _webview: vscode.Webview | undefined;
32+
33+
setWebview(webview: vscode.Webview): void {
34+
this._webview = webview;
35+
}
36+
37+
updateFromWebview(serializedItems: SerializedOutlineItem[]): void {
38+
this._items = convertItems(serializedItems);
39+
this._onDidChangeOutline.fire();
40+
}
41+
42+
setActive(itemId: string | undefined): void {
43+
this._onDidChangeActiveItem.fire(itemId);
44+
}
45+
46+
provideOutline(_token: vscode.CancellationToken): vscode.CustomEditorOutlineItem[] {
47+
return this._items;
48+
}
49+
50+
revealItem(itemId: string): void {
51+
this._webview?.postMessage({ type: 'reveal', id: itemId });
52+
}
53+
54+
sendCommand(command: string): void {
55+
this._webview?.postMessage({ type: 'outlineCommand', command });
56+
}
57+
}

src/vscode/DesignerTextEditor.ts

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import * as vscode from 'vscode';
2+
import { DesignerOutlineProvider } from './DesignerOutlineProvider.js';
23

34
export function getNonce() {
45
let text = '';
@@ -11,19 +12,21 @@ export function getNonce() {
1112

1213
export class DesignerTextEditor implements vscode.CustomTextEditorProvider {
1314

14-
public static register(context: vscode.ExtensionContext): vscode.Disposable {
15-
const provider = new DesignerTextEditor(context);
15+
public static register(context: vscode.ExtensionContext): [vscode.Disposable[], DesignerOutlineProvider] {
16+
let outlineProvider = new DesignerOutlineProvider();
17+
const provider = new DesignerTextEditor(context, outlineProvider);
1618
const providerRegistration = vscode.window.registerCustomEditorProvider(DesignerTextEditor.viewType, provider, {
1719
webviewOptions: {
1820
retainContextWhenHidden: true
1921
}
2022
});
21-
return providerRegistration;
23+
const outlineRegistration = vscode.window.registerCustomEditorOutlineProvider('designer.designerTextEditor', outlineProvider)
24+
return [[providerRegistration, outlineRegistration], outlineProvider];
2225
}
2326

2427
private static readonly viewType = 'designer.designerTextEditor';
2528

26-
constructor(private readonly context: vscode.ExtensionContext) { }
29+
constructor(private readonly context: vscode.ExtensionContext, private readonly outline: DesignerOutlineProvider) { }
2730

2831
public async addCustomElementsJsons(webviewPanel: vscode.WebviewPanel) {
2932
//TODO:
@@ -139,8 +142,16 @@ export class DesignerTextEditor implements vscode.CustomTextEditorProvider {
139142
}
140143
}
141144
return;
145+
case 'outlineData':
146+
this.outline.updateFromWebview(e.items);
147+
return;
148+
case 'outlineActiveItem':
149+
this.outline.setActive(e.id);
150+
return;
142151
}
143152
});
153+
154+
this.outline.setWebview(webviewPanel.webview);
144155
}
145156

146157
/**

src/vscode/extension.ts

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,40 @@
11
import * as vscode from 'vscode';
22
import { DesignerTextEditor } from './DesignerTextEditor.js';
33

4+
const outlineCommands = [
5+
'designer.outline.toggleLock',
6+
'designer.outline.toggleHideInDesigner',
7+
'designer.outline.toggleHideAtRuntime',
8+
'designer.outline.copy',
9+
'designer.outline.cut',
10+
'designer.outline.paste',
11+
'designer.outline.delete',
12+
'designer.outline.rotateLeft',
13+
'designer.outline.rotateRight',
14+
'designer.outline.toFront',
15+
'designer.outline.moveForward',
16+
'designer.outline.moveBackward',
17+
'designer.outline.toBack',
18+
'designer.outline.moveTo',
19+
'designer.outline.jumpTo',
20+
'designer.outline.expandChildren',
21+
'designer.outline.collapseChildren',
22+
];
23+
424
export function activate(context: vscode.ExtensionContext) {
5-
//context.subscriptions.push(
6-
// vscode.window.registerWebviewViewProvider(ColorsViewProvider.viewType, provider));
7-
context.subscriptions.push(DesignerTextEditor.register(context));
25+
const [registrations, outlineProvider] = DesignerTextEditor.register(context);
26+
context.subscriptions.push(...registrations);
827

928
vscode.commands.registerCommand('designer.openInDesignerTextEditor', (uri: vscode.Uri) => {
1029
vscode.commands.executeCommand('vscode.openWith', uri, 'designer.designerTextEditor');
1130
});
31+
32+
for (const cmd of outlineCommands) {
33+
context.subscriptions.push(
34+
vscode.commands.registerCommand(cmd, () => {
35+
const shortName = cmd.replace('designer.outline.', '');
36+
outlineProvider.sendCommand(shortName);
37+
})
38+
);
39+
}
1240
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
declare module 'vscode' {
2+
3+
export interface CustomEditorOutlineItem {
4+
readonly id: string;
5+
readonly label: string;
6+
readonly detail?: string;
7+
readonly tooltip?: string;
8+
readonly icon?: ThemeIcon;
9+
readonly contextValue?: string;
10+
readonly children?: CustomEditorOutlineItem[];
11+
}
12+
13+
export interface CustomEditorOutlineProvider {
14+
readonly onDidChangeOutline: Event<void>;
15+
readonly onDidChangeActiveItem: Event<string | undefined>;
16+
provideOutline(token: CancellationToken): ProviderResult<CustomEditorOutlineItem[]>;
17+
revealItem(itemId: string): void;
18+
}
19+
20+
export namespace window {
21+
export function registerCustomEditorOutlineProvider(viewType: string, provider: CustomEditorOutlineProvider): Disposable;
22+
}
23+
}

0 commit comments

Comments
 (0)