上一篇文章我介绍了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。如果你觉得每天的文章内容过于简单有问题可以私信我。 每天进步一点点.