Skip to content

Commit 1f3dfe6

Browse files
committed
v1.8.0 - Fixes #456
1 parent e8bf35c commit 1f3dfe6

File tree

4 files changed

+168
-63
lines changed

4 files changed

+168
-63
lines changed

package.json

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"private": true,
44
"displayName": "Draw.io Integration",
55
"description": "This unofficial extension integrates Draw.io into VS Code.",
6-
"version": "1.7.0",
6+
"version": "1.8.0",
77
"preRelease": false,
88
"license": "GPL-3.0",
99
"publisher": "hediet",
@@ -438,14 +438,25 @@
438438
"hediet.vscode-drawio.theme": {
439439
"title": "Draw.io Theme",
440440
"type": "string",
441+
"default": "kennedy",
442+
"enum": [
443+
"kennedy",
444+
"min"
445+
],
446+
"description": "The theme to use for the Draw.io editor. Use \"automatic\" to automatically choose a Draw.io theme that matches your current VS Code theme."
447+
},
448+
"hediet.vscode-drawio.appearance": {
449+
"title": "Draw.io Appearance",
450+
"type": "string",
441451
"default": "automatic",
442452
"enum": [
443453
"automatic",
444-
"min",
454+
"light",
445455
"dark",
446-
"kennedy"
456+
"high-contrast-light",
457+
"high-contrast"
447458
],
448-
"description": "The theme to use for the Draw.io editor. Use \"automatic\" to automatically choose a Draw.io theme that matches your current VS Code theme."
459+
"description": "The appearance to use for the Draw.io editor. Use \"automatic\" to automatically choose a Draw.io theme that matches your current VS Code theme."
449460
}
450461
}
451462
}

src/Config.ts

Lines changed: 109 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import {
1212
} from "vscode";
1313
import { Style, ColorScheme, DrawioLibraryData } from "./DrawioClient";
1414
import { BufferImpl } from "./utils/buffer";
15-
import { mapObject } from "./utils/mapObject";
1615
import { SimpleTemplate } from "./utils/SimpleTemplate";
1716
import {
1817
serializerWithDefault,
@@ -360,37 +359,65 @@ export class DiagramConfig {
360359

361360
private readonly _theme = new VsCodeSetting(`${extensionId}.theme`, {
362361
scope: this.uri,
363-
serializer: serializerWithDefault("automatic"),
362+
serializer: serializerWithDefault("kennedy"),
364363
});
365364

366-
@computed
367-
public get theme(): string {
368-
const theme = this._theme.get();
365+
private readonly _appearance = new VsCodeSetting(`${extensionId}.appearance`, {
366+
scope: this.uri,
367+
serializer: serializerWithDefault<
368+
"automatic" |
369+
"light" |
370+
"dark" |
371+
"highContrastLight" |
372+
"highContrast"
373+
>("automatic"),
374+
});
369375

370-
if (theme !== "automatic") {
371-
return theme;
376+
public get resolvedTheme(): ResolvedDrawioTheme {
377+
const themeName = this._theme.get().toLowerCase();
378+
379+
// handle 'dark' and 'automatic' for backwards compat
380+
if (themeName === 'dark') {
381+
return new ResolvedDrawioTheme('kennedy', ColorThemeKind.Dark);
382+
}
383+
if (themeName === 'automatic') {
384+
return new ResolvedDrawioTheme('kennedy', this.config.vscodeTheme.kind);
372385
}
373386

374-
return {
375-
[ColorThemeKind.Light]: "kennedy",
376-
[ColorThemeKind.Dark]: "dark",
377-
[ColorThemeKind.HighContrast]: "dark",
378-
[ColorThemeKind.HighContrastLight]: "kennedy"
379-
}[this.config.vscodeTheme.kind];
387+
const appearance = this._appearance.get().toLowerCase();
388+
389+
let resolvedAppearance = themeKindFromString(appearance);
390+
if (!resolvedAppearance) {
391+
resolvedAppearance = this.config.vscodeTheme.kind;
392+
}
393+
394+
return new ResolvedDrawioTheme(themeName, resolvedAppearance);
395+
}
396+
397+
public getVsCodeAppearance(): string {
398+
return themeKindToString(this.config.vscodeTheme.kind);
399+
}
400+
401+
@computed
402+
public get theme(): string {
403+
const t = this._theme.get().toLowerCase();
404+
if (t === 'dark' || t === 'automatic') {
405+
return 'kennedy';
406+
}
407+
return t;
380408
}
381409

382410
@computed
383411
public get appearance(): string {
384-
return {
385-
[ColorThemeKind.Light]: "0",
386-
[ColorThemeKind.Dark]: "1",
387-
[ColorThemeKind.HighContrastLight]: "2",
388-
[ColorThemeKind.HighContrast]: "3"
389-
}[this.config.vscodeTheme.kind];
412+
return this._appearance.get().toLowerCase();
390413
}
391414

392-
public async setTheme(value: string): Promise<void> {
393-
await this._theme.set(value);
415+
public async setTheme(themeName: string): Promise<void> {
416+
await this._theme.set(themeName);
417+
}
418+
419+
public async setAppearance(appearance: string): Promise<void> {
420+
await this._appearance.set(appearance as any);
394421
}
395422

396423
// #endregion
@@ -661,7 +688,7 @@ export class DiagramConfig {
661688
public readonly uri: Uri,
662689
private readonly config: Config,
663690
private readonly memento: Memento
664-
) {}
691+
) { }
665692

666693
@computed
667694
public get drawioLanguage(): string {
@@ -677,15 +704,67 @@ export class DiagramConfig {
677704

678705
type DrawioCustomLibrary = (
679706
| {
680-
xml: string;
681-
}
707+
xml: string;
708+
}
682709
| {
683-
url: string;
684-
}
710+
url: string;
711+
}
685712
| {
686-
json: string;
687-
}
713+
json: string;
714+
}
688715
| {
689-
file: string;
690-
}
716+
file: string;
717+
}
691718
) & { libName: string; entryId: string };
719+
720+
export class ResolvedDrawioTheme {
721+
public static getThemeNames(): string[] {
722+
return [
723+
"min",
724+
"kennedy",
725+
];
726+
}
727+
728+
constructor(
729+
public readonly themeName: string,
730+
public readonly appearance: ColorThemeKind,
731+
) { }
732+
733+
getAppearanceDrawioValue(): string {
734+
return {
735+
[ColorThemeKind.Light]: "0",
736+
[ColorThemeKind.Dark]: "1",
737+
[ColorThemeKind.HighContrastLight]: "2",
738+
[ColorThemeKind.HighContrast]: "3"
739+
}[this.appearance];
740+
}
741+
742+
getAppearanceStringValue(): string {
743+
return themeKindToString(this.appearance);
744+
}
745+
746+
toString(): string {
747+
if (this.appearance === ColorThemeKind.Light) {
748+
return this.themeName;
749+
}
750+
return `${this.themeName} - ${this.getAppearanceStringValue()}`;
751+
}
752+
}
753+
754+
function themeKindToString(themeKind: ColorThemeKind): string {
755+
return {
756+
[ColorThemeKind.Light]: "light",
757+
[ColorThemeKind.Dark]: "dark",
758+
[ColorThemeKind.HighContrastLight]: "high-contrast-light",
759+
[ColorThemeKind.HighContrast]: "high-contrast"
760+
}[themeKind];
761+
}
762+
763+
function themeKindFromString(themeKind: string): ColorThemeKind | undefined {
764+
return {
765+
"light": ColorThemeKind.Light,
766+
"dark": ColorThemeKind.Dark,
767+
"high-contrast-light": ColorThemeKind.HighContrastLight,
768+
"high-contrast": ColorThemeKind.HighContrast
769+
}[themeKind];
770+
}

src/DrawioClient/DrawioClientFactory.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -236,8 +236,8 @@ export class DrawioClientFactory {
236236
// Prevent injection attacks by using JSON.stringify.
237237
const patchedHtml = html
238238
.replace(/\$\$literal-vsuri\$\$/g, vsuri.toString())
239-
.replace("$$theme$$", JSON.stringify(config.theme))
240-
.replace("$$appearance$$", JSON.stringify(config.appearance))
239+
.replace("$$theme$$", JSON.stringify(config.resolvedTheme.themeName))
240+
.replace("$$appearance$$", JSON.stringify(config.resolvedTheme.getAppearanceDrawioValue()))
241241
.replace("$$lang$$", JSON.stringify(config.drawioLanguage))
242242
.replace("$$simpleLabels$$", JSON.stringify(config.simpleLabels))
243243
.replace(
@@ -284,7 +284,7 @@ export class DrawioClientFactory {
284284
</script>
285285
286286
<iframe src="${drawioUrl}?embed=1&ui=${encodeURIComponent(
287-
config.theme
287+
config.resolvedTheme.themeName
288288
)}&proto=json&configure=1&noSaveBtn=1&noExitBtn=1&simpleLabels=${encodeURIComponent(
289289
config.simpleLabels
290290
)}&lang=${encodeURIComponent(config.drawioLanguage)}"></iframe>

src/DrawioEditorService.ts

Lines changed: 41 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,20 @@ import { autorun, computed, observable, ObservableSet } from "mobx";
44
import { extname } from "path";
55
import {
66
commands,
7-
StatusBarAlignment,
7+
QuickPickItem, QuickPickItemKind, StatusBarAlignment,
88
TextDocument,
99
Uri,
1010
WebviewPanel,
1111
window,
12-
workspace,
12+
workspace
1313
} from "vscode";
14-
import { Config, DiagramConfig } from "./Config";
15-
import { DrawioBinaryDocument } from "./DrawioEditorProviderBinary";
14+
import { Config, DiagramConfig, ResolvedDrawioTheme } from "./Config";
1615
import {
1716
CustomizedDrawioClient,
18-
DrawioClientOptions,
1917
DrawioClientFactory,
18+
DrawioClientOptions,
2019
} from "./DrawioClient";
20+
import { DrawioBinaryDocument } from "./DrawioEditorProviderBinary";
2121
import { registerFailableCommand } from "./utils/registerFailableCommand";
2222

2323
const drawioChangeThemeCommand = "hediet.vscode-drawio.changeTheme";
@@ -110,7 +110,7 @@ export class DrawioEditorService {
110110
this.statusBar.command = drawioChangeThemeCommand;
111111

112112
if (activeEditor) {
113-
this.statusBar.text = `Theme: ${activeEditor.config.theme}`;
113+
this.statusBar.text = `Theme: ${activeEditor.config.resolvedTheme.toString()}`;
114114
this.statusBar.show();
115115
} else {
116116
this.statusBar.hide();
@@ -334,39 +334,54 @@ export class DrawioEditor {
334334
}
335335

336336
public async handleChangeThemeCommand(): Promise<void> {
337-
let availableThemes = [
338-
"automatic",
339-
"min",
340-
"dark",
341-
"kennedy"
342-
];
343-
344337
const originalTheme = this.config.theme;
345-
availableThemes = availableThemes.filter((t) => t !== originalTheme);
346-
availableThemes.unshift(originalTheme);
347-
338+
const originalAppearance = this.config.appearance;
339+
const availableThemes = withFirstUnique(ResolvedDrawioTheme.getThemeNames(), originalTheme);
340+
341+
const availableOptions: (QuickPickItem & { onSelect?: (preview: boolean) => void })[] = [];
342+
343+
const curVsCodeAppearance = this.config.getVsCodeAppearance();
344+
345+
const appearances = withFirstUnique(["automatic", "light", "dark"], originalAppearance);
346+
for (const appearance of appearances) {
347+
const appearanceLabel = appearance === "automatic" ? `always match VS Code theme '${curVsCodeAppearance}'` : appearance;
348+
349+
availableOptions.push({
350+
kind: QuickPickItemKind.Separator,
351+
label: appearanceLabel,
352+
});
353+
for (const theme of availableThemes) {
354+
availableOptions.push({
355+
label: `${theme} - ${appearance}`,
356+
onSelect: () => {
357+
this.config.setTheme(theme);
358+
this.config.setAppearance(appearance);
359+
}
360+
});
361+
}
362+
}
348363
const result = await window.showQuickPick(
349-
availableThemes.map((theme) => ({
350-
label: theme,
351-
description: `Selects Theme "${theme}"`,
352-
theme,
353-
})),
364+
availableOptions,
354365
{
355366
onDidSelectItem: async (item) => {
356-
await this.config.setTheme((item as any).theme);
367+
(item as any).onSelect(true);
357368
},
358369
}
359370
);
360-
361-
if (!result) {
371+
if (!result || !result.onSelect) {
362372
await this.config.setTheme(originalTheme);
373+
await this.config.setAppearance(originalAppearance);
363374
return;
364375
}
365-
366-
await this.config.setTheme(result.theme);
376+
result.onSelect(false);
367377
}
368378
}
369379

380+
function withFirstUnique<T>(items: T[], firstItem: T): T[] {
381+
const filtered = items.filter(t => t !== firstItem);
382+
return [firstItem, ...filtered];
383+
}
384+
370385
async function fileExists(uri: Uri): Promise<boolean> {
371386
try {
372387
await workspace.fs.stat(uri);

0 commit comments

Comments
 (0)