上一篇文章我介紹了vscode從入口文件開始一直到渲染進程的運行流程。今天我們通過實現 dark mode 來了解一下workbench.
先看一下效果圖鎮場子, 本篇文章只介紹邏輯實現. 具體UI不探討.
我個人的話實現dark mode其實是使用了兩套主題. 其實vscode有提供dark mode api. 不過比較麻煩。 因爲我個人遇到的實際場景是不需要讓用戶切換主題的。所以我就選了兩套主題做切換來實現 僞dark mode
我們從workbench.ts裏的startup
開始。這裏開始vscode會渲染我們看到的UI. 所以我們可以給 workbench.ts 加倆函數分別是 startupDarkModeButton
和 changeThemeHandle
分別負責button的渲染和切換主題邏輯
private startupDarkModeButton(instantiationService: IInstantiationService) {
const node = document.createElement("input");
node.id = "dark-mode-button";
node.style.backgroundColor = "blue";
node.value = "dark mode";
node.type = "checkbox";
node.style.height = "26px";
node.style.width = "100px";
node.style.color = "#ffffff";
// 這裏我就隨便加入到body裏面了...本文章只討論實現方式
document.body.insertBefore(node, document.getElementById('monaco-parts-splash'))
node.onchange = async () => {
this.changeThemeHandle(instantiationService, node);
}
}
private changeThemeHandle(instantiationService: IInstantiationService, checkbox: HTMLInputElement) {
const themeIDs: string[] = [
// 正常主題
"vs thenikso-github-plus-theme-themes-github-plus-theme-json",
// dark mode 主題
"vs-dark vscode-theme-defaults-themes-dark_vs-json"
];
// invokeFunction 主要是獲取ServicesAccessor
instantiationService.invokeFunction((accessor: ServicesAccessor) => {
const workbenchThemeService: IWorkbenchThemeService = accessor.get(IWorkbenchThemeService);
// 切換主題
workbenchThemeService.setColorTheme(BELLCODE_THEMES[Number(el.checked)], undefined)
})
}
然後在 startup
函數內調用我們的startupDarkModeButton
函數來掛載我們的小按鈕
startup(): IInstantiationService {
try {
// Configure emitter leak warning threshold
setGlobalLeakWarningThreshold(175);
// ARIA
setARIAContainer(document.body);
// Services
const instantiationService = this.initServices(this.serviceCollection);
instantiationService.invokeFunction(async accessor => {
const lifecycleService = accessor.get(ILifecycleService);
const storageService = accessor.get(IStorageService);
const configurationService = accessor.get(IConfigurationService);
// Layout
this.initLayout(accessor);
// Registries
this.startRegistries(accessor);
// Context Keys
this._register(instantiationService.createInstance(WorkbenchContextKeysHandler));
// Register Listeners
this.registerListeners(lifecycleService, storageService, configurationService);
// Render Workbench
this.renderWorkbench(instantiationService, accessor.get(INotificationService) as NotificationService, storageService, configurationService);
// Workbench Layout
this.createWorkbenchLayout();
// Layout
this.layout();
// mount dark mode button
this.startupDarkModeButton();
// Restore
try {
await this.restoreWorkbench(accessor.get(IEditorService), accessor.get(IEditorGroupsService), accessor.get(IViewletService), accessor.get(IPanelService), accessor.get(ILogService), lifecycleService);
} catch (error) {
onUnexpectedError(error);
}
});
return instantiationService;
} catch (error) {
onUnexpectedError(error);
throw error; // rethrow because this is a critical issue we cannot handle properly here
}
}
簡單的兩個函數我們就基本實現了主題切換。如果像我的效果圖一樣自己寫了一些組件怎麼辦呢? 明天我們就講講如何擴展vscode UI。如果你覺得每天的文章內容過於簡單有問題可以私信我。 每天進步一點點.