Skip to content

Commit db7eb75

Browse files
Catedswaruqi
andauthored
feat(configureView(new), status, xmake): Add new view (#304)
* ✨ feat(configureView(new), status, xmake): Add new view Based on the current status management, a tree display page of project configuration has been added to the Activity Bar section. Since there is no decoupling of Status and StatusBarItem, try to read the information by adding a getter while reflesh when calling the setter to keep the data in sync. #303 * Update xmake.ts --------- Co-authored-by: ruki <[email protected]>
1 parent 52b8071 commit db7eb75

File tree

4 files changed

+283
-25
lines changed

4 files changed

+283
-25
lines changed

package.json

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -275,8 +275,7 @@
275275
{
276276
"command": "xmake.setTargetToolchain",
277277
"title": "toolchain",
278-
"category": "XMake",
279-
"enablement": "view == xmakeExplorer"
278+
"category": "XMake"
280279
},
281280
{
282281
"command": "xmakeExplorer.rebuild",
@@ -750,6 +749,14 @@
750749
},
751750
"views": {
752751
"xmake-explorer": [
752+
{
753+
"type": "tree",
754+
"id": "xmakeConfigureView",
755+
"name": "Configure",
756+
"icon": "res/logo-mono.svg",
757+
"contextualTitle": "XMake Configure",
758+
"when": "xmakeEnabled"
759+
},
753760
{
754761
"type": "tree",
755762
"id": "xmakeExplorer",

src/configureView.ts

Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
2+
'use strict';
3+
4+
// This file implements the TreeView for XMake configuration in VS Code.
5+
// It defines the data structure, item types, and data provider for the configuration view.
6+
7+
import * as vscode from 'vscode';
8+
import { Status } from './status';
9+
10+
11+
// Enum for item types in the configuration view: folder or entry
12+
enum XMakeConfigureViewItemType {
13+
FOLDER,
14+
ENTRY
15+
}
16+
17+
18+
// Folder item info type
19+
type XMakeConfigureViewFolderInfo = {
20+
type: XMakeConfigureViewItemType.FOLDER;
21+
name: string;
22+
}
23+
24+
25+
// Entry item info type (leaf node)
26+
type XMakeConfigureViewEntryInfo = {
27+
type: XMakeConfigureViewItemType.ENTRY;
28+
name: string;
29+
value: string;
30+
}
31+
32+
33+
// Map entry names to their corresponding command and title
34+
const XMakeCommandMap: Record<string, { command: string, title: string }> = {
35+
"Name": { command: "setProjectRoot", title: "Change Project Name" },
36+
"Platform": { command: "setTargetPlat", title: "Change Platform" },
37+
"Architecture": { command: "setTargetArch", title: "Change Architecture" },
38+
"Toolchain": { command: "setTargetToolchain", title: "Change Toolchain" },
39+
"Mode": { command: "setBuildMode", title: "Change Mode" },
40+
"Target": { command: "setDefaultTarget", title: "Change Target" }
41+
};
42+
43+
44+
// TreeItem for the XMake configuration view
45+
class XMakeConfigureViewItem extends vscode.TreeItem {
46+
info: XMakeConfigureViewFolderInfo | XMakeConfigureViewEntryInfo;
47+
48+
/**
49+
* Construct a TreeItem for either a folder or an entry.
50+
* @param info Folder or entry info
51+
*/
52+
constructor(info: XMakeConfigureViewFolderInfo | XMakeConfigureViewEntryInfo) {
53+
let label: string;
54+
let collapsibleState: vscode.TreeItemCollapsibleState;
55+
let description: string | undefined = undefined;
56+
57+
if (info.type === XMakeConfigureViewItemType.FOLDER) {
58+
label = info.name;
59+
collapsibleState = vscode.TreeItemCollapsibleState.Expanded;
60+
} else {
61+
label = info.name;
62+
description = info.value;
63+
collapsibleState = vscode.TreeItemCollapsibleState.None;
64+
}
65+
super(label, collapsibleState);
66+
this.info = info;
67+
// Assign command for entry items so they are clickable
68+
if (info.type === XMakeConfigureViewItemType.ENTRY) {
69+
this.command = {
70+
command: `xmake.${XMakeCommandMap[info.name].command}`,
71+
title: XMakeCommandMap[info.name].title,
72+
}
73+
// For debug: log command registration
74+
console.log(`Command registered: ${this.command.command} with title: ${this.command.title}`);
75+
}
76+
if (description) {
77+
this.description = description;
78+
}
79+
}
80+
}
81+
82+
83+
// The root structure of the configuration view: folders and their children
84+
const ROOT_STRUCTURE = [
85+
{ type: XMakeConfigureViewItemType.FOLDER, name: "Project", children: ["Name"] },
86+
{ type: XMakeConfigureViewItemType.FOLDER, name: "Configure", children: ["Platform", "Architecture", "Toolchain", "Mode"] },
87+
{ type: XMakeConfigureViewItemType.FOLDER, name: "Build", children: ["Target"] }
88+
];
89+
90+
91+
// Map entry names to Status property keys
92+
const XMakeStatusMap: Record<string, string> = {
93+
"Name": "project",
94+
"Platform": "plat",
95+
"Architecture": "arch",
96+
"Toolchain": "toolchain",
97+
"Mode": "mode",
98+
"Target": "target"
99+
};
100+
101+
102+
// Data provider for the XMake configuration TreeView
103+
class XMakeConfigureViewDataProvider implements vscode.TreeDataProvider<XMakeConfigureViewItem> {
104+
private status: Status;
105+
private _onDidChangeTreeData:
106+
vscode.EventEmitter<XMakeConfigureViewItem | undefined | void> =
107+
new vscode.EventEmitter();
108+
readonly onDidChangeTreeData:
109+
vscode.Event<XMakeConfigureViewItem | undefined | void> =
110+
this._onDidChangeTreeData.event;
111+
112+
/**
113+
* Refresh the tree view by firing the change event.
114+
*/
115+
refresh(): void {
116+
this._onDidChangeTreeData.fire();
117+
}
118+
119+
/**
120+
* @param status The Status instance for current configuration
121+
*/
122+
constructor(status?: Status) {
123+
this.status = status;
124+
}
125+
126+
/**
127+
* Get the TreeItem for a given element.
128+
*/
129+
getTreeItem(element: XMakeConfigureViewItem): XMakeConfigureViewItem {
130+
return element;
131+
}
132+
133+
/**
134+
* Get the children for a given element (or root folders if no element).
135+
*/
136+
getChildren(element?: XMakeConfigureViewItem): vscode.ProviderResult<XMakeConfigureViewItem[]> {
137+
if (!element) {
138+
// Return root folders
139+
return ROOT_STRUCTURE.map(folder =>
140+
new XMakeConfigureViewItem({
141+
type: XMakeConfigureViewItemType.FOLDER,
142+
name: folder.name
143+
})
144+
);
145+
}
146+
if (element.info.type === XMakeConfigureViewItemType.FOLDER) {
147+
// Return entries under the folder
148+
const folder = ROOT_STRUCTURE.find(f => f.name === element.info.name);
149+
if (!folder) return [];
150+
return folder.children.map(childName => {
151+
let value = "unknown";
152+
if (this.status && typeof this.status === 'object') {
153+
const key = XMakeStatusMap[childName];
154+
value = this.status[key] ?? "unknown";
155+
}
156+
return new XMakeConfigureViewItem({
157+
type: XMakeConfigureViewItemType.ENTRY,
158+
name: childName,
159+
value: value
160+
});
161+
});
162+
}
163+
return [];
164+
}
165+
}
166+
167+
168+
/**
169+
* Controller class for the XMake configuration TreeView.
170+
* Handles data provider, refresh, and disposal.
171+
*/
172+
export class XMakeConfigureView implements vscode.Disposable {
173+
private _dataProvider: XMakeConfigureViewDataProvider;
174+
private _treeView: vscode.TreeView<vscode.TreeItem>;
175+
176+
/**
177+
* @param status The Status instance for current configuration
178+
*/
179+
constructor(status: Status) {
180+
this._dataProvider = new XMakeConfigureViewDataProvider(status);
181+
this._treeView = vscode.window.createTreeView(
182+
"xmakeConfigureView",
183+
{ treeDataProvider: this._dataProvider }
184+
)
185+
}
186+
187+
/**
188+
* Refresh the configuration view.
189+
*/
190+
refresh(): void {
191+
this._dataProvider.refresh();
192+
}
193+
194+
/**
195+
* Dispose the tree view and its resources.
196+
*/
197+
dispose() {
198+
this._treeView.dispose();
199+
}
200+
}

src/status.ts

Lines changed: 52 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22

33
// imports
44
import * as vscode from 'vscode';
5-
import {log} from './log';
6-
import {config} from './config';
5+
import { log } from './log';
6+
import { config } from './config';
77

88
// the status class
99
export class Status implements vscode.Disposable {
@@ -110,33 +110,33 @@ export class Status implements vscode.Disposable {
110110
public dispose() {
111111

112112
for (const item of [this._projectButton,
113-
this._platButton,
114-
this._archButton,
115-
this._modeButton,
116-
this._buildButton,
117-
this._targetButton,
118-
this._runButton,
119-
this._debugButton,
120-
this._macroRecordButton,
121-
this._macroPlaybackButton,
122-
this._toolChainButton]) {
113+
this._platButton,
114+
this._archButton,
115+
this._modeButton,
116+
this._buildButton,
117+
this._targetButton,
118+
this._runButton,
119+
this._debugButton,
120+
this._macroRecordButton,
121+
this._macroPlaybackButton,
122+
this._toolChainButton]) {
123123
item.dispose();
124124
}
125125
}
126126

127127
// update visibility
128128
private updateVisibility() {
129129
for (const item of [this._projectButton,
130-
this._platButton,
131-
this._archButton,
132-
this._modeButton,
133-
this._buildButton,
134-
this._targetButton,
135-
this._runButton,
136-
this._debugButton,
137-
this._macroRecordButton,
138-
this._macroPlaybackButton,
139-
this._toolChainButton]) {
130+
this._platButton,
131+
this._archButton,
132+
this._modeButton,
133+
this._buildButton,
134+
this._targetButton,
135+
this._runButton,
136+
this._debugButton,
137+
this._macroRecordButton,
138+
this._macroPlaybackButton,
139+
this._toolChainButton]) {
140140
if (this.visible && !!item.text) {
141141
item.show();
142142
} else {
@@ -161,31 +161,61 @@ export class Status implements vscode.Disposable {
161161
this._projectButton.text = `XMake: ${value}`;
162162
}
163163

164+
// get the project root
165+
public get project(): string {
166+
return this._projectButton.text.replace('XMake: ', '');
167+
}
168+
164169
// set the target platform
165170
public set plat(value: string) {
166171
this._platButton.text = value;
167172
}
168173

174+
// get the target platform
175+
public get plat(): string {
176+
return this._platButton.text;
177+
}
178+
169179
// set the toolchain
170180
public set toolchain(value: string) {
171181
this._toolChainButton.text = value;
172182
}
173183

184+
// get the toolchain
185+
public get toolchain(): string {
186+
return this._toolChainButton.text;
187+
}
188+
174189
// set the target architecture
175190
public set arch(value: string) {
176191
this._archButton.text = value;
177192
}
178193

194+
// get the target architecture
195+
public get arch(): string {
196+
return this._archButton.text;
197+
}
198+
179199
// set the build mode
180200
public set mode(value: string) {
181201
this._modeButton.text = value;
182202
}
183203

204+
// get the build mode
205+
public get mode(): string {
206+
return this._modeButton.text;
207+
}
208+
184209
// set the default target
185210
public set target(value: string) {
186211
this._targetButton.text = value;
187212
}
188213

214+
// get the default target
215+
public get target(): string {
216+
return this._targetButton.text;
217+
}
218+
189219
// start to record
190220
public startRecord() {
191221
this._macroRecordButton.command = 'xmake.onMacroEnd';

0 commit comments

Comments
 (0)