Skip to content

Commit a67b107

Browse files
committed
1 parent a1b7ee7 commit a67b107

5 files changed

Lines changed: 204 additions & 29 deletions

File tree

packages/project-editor/features/style/theme.tsx

Lines changed: 192 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,16 @@ import {
1515
registerClass,
1616
PropertyType,
1717
getParent,
18-
IMessage
18+
IMessage,
19+
setParent,
20+
SerializedData
1921
} from "project-editor/core/object";
2022
import {
2123
ProjectStore,
2224
IContextMenuContext,
2325
getProjectStore,
24-
createObject
26+
createObject,
27+
objectToClipboardData
2528
} from "project-editor/store";
2629
import { replaceObjectReference } from "project-editor/core/search";
2730

@@ -88,7 +91,7 @@ const ColorItem = observer(
8891
}
8992

9093
get themeColor() {
91-
return this.selectedTheme.colors[this.colorIndex];
94+
return this.selectedTheme?.colors[this.colorIndex]??"#000000";
9295
}
9396

9497
changedThemeColor: string | undefined;
@@ -463,20 +466,12 @@ export class Color extends EezObject {
463466
return color;
464467
},
465468

466-
onAfterPaste: (newColor: Color, fromColor: Color) => {
467-
const project = ProjectEditor.getProject(newColor);
468-
469-
const fromTheme =
470-
project._store.navigationStore.selectedThemeObject.get() as Theme;
471-
if (fromTheme) {
472-
for (const theme of project.themes) {
473-
project.setThemeColor(
474-
theme.objID,
475-
newColor.objID,
476-
project.getThemeColor(fromTheme.objID, fromColor.objID)
477-
);
478-
}
479-
}
469+
objectsToClipboardData: (colors: Color[]) => {
470+
const projectStore = ProjectEditor.getProjectStore(colors[0]);
471+
const themeColorsClipboardData = new ThemeColorsClipboardData();
472+
themeColorsClipboardData.addColors(projectStore, colors);
473+
setParent(themeColorsClipboardData, projectStore.project);
474+
return objectToClipboardData(projectStore, themeColorsClipboardData);
480475
},
481476

482477
extendContextMenu: (
@@ -613,16 +608,12 @@ export class Theme extends EezObject implements ITheme {
613608
return theme;
614609
},
615610

616-
onAfterPaste: (newTheme: Theme, fromTheme: Theme) => {
617-
const project = ProjectEditor.getProject(newTheme);
618-
619-
for (const color of project.colors) {
620-
project.setThemeColor(
621-
newTheme.objID,
622-
color.objID,
623-
project.getThemeColor(fromTheme.objID, color.objID)
624-
);
625-
}
611+
objectsToClipboardData: (themes: Theme[]) => {
612+
const projectStore = ProjectEditor.getProjectStore(themes[0]);
613+
const themeColorsClipboardData = new ThemeColorsClipboardData();
614+
themeColorsClipboardData.addThemes(projectStore, themes);
615+
setParent(themeColorsClipboardData, projectStore.project);
616+
return objectToClipboardData(projectStore, themeColorsClipboardData);
626617
}
627618
};
628619

@@ -667,6 +658,180 @@ registerClass("Theme", Theme);
667658

668659
////////////////////////////////////////////////////////////////////////////////
669660

661+
export class ThemeColorsClipboardData extends EezObject {
662+
data: {
663+
kind: "themes" | "colors";
664+
themes: {
665+
name: string;
666+
colors: string[];
667+
}[];
668+
colorNames: string[];
669+
};
670+
671+
static classInfo: ClassInfo = {
672+
properties: [
673+
{
674+
name: "data",
675+
type: PropertyType.Any
676+
}
677+
],
678+
679+
pasteItemHook: (
680+
object: IEezObject,
681+
clipboardData: {
682+
serializedData: SerializedData;
683+
pastePlace: EezObject;
684+
}
685+
) => {
686+
const projectStore = ProjectEditor.getProjectStore(
687+
clipboardData.pastePlace
688+
);
689+
const themeColorsClipboardData = clipboardData.serializedData
690+
.object as ThemeColorsClipboardData;
691+
692+
let closeCombineCommands = false;
693+
if (!projectStore.undoManager.combineCommands) {
694+
projectStore.undoManager.setCombineCommands(true);
695+
closeCombineCommands = true;
696+
}
697+
698+
const newObjects: EezObject[] = [];
699+
700+
if (themeColorsClipboardData.data.kind == "themes") {
701+
for (const colorName of themeColorsClipboardData.data.colorNames) {
702+
const color = projectStore.project.colors.find(
703+
color => color.name == colorName
704+
);
705+
if (!color) {
706+
projectStore.addObject(
707+
projectStore.project.colors,
708+
createObject<Color>(
709+
projectStore,
710+
{
711+
name: colorName
712+
},
713+
Color
714+
)
715+
);
716+
}
717+
}
718+
719+
for (const theme of themeColorsClipboardData.data.themes) {
720+
const newTheme = projectStore.addObject(
721+
projectStore.project.themes,
722+
createObject<Theme>(
723+
projectStore,
724+
{
725+
name: theme.name
726+
},
727+
Theme
728+
)
729+
);
730+
731+
newObjects.push(newTheme);
732+
733+
for (const color of projectStore.project.colors) {
734+
const index =
735+
themeColorsClipboardData.data.colorNames.findIndex(
736+
colorName => colorName == color.name
737+
);
738+
projectStore.project.setThemeColor(
739+
newTheme.objID,
740+
color.objID,
741+
index != -1 ? theme.colors[index] : "#000000"
742+
);
743+
}
744+
}
745+
} else {
746+
for (const theme of themeColorsClipboardData.data.themes) {
747+
const theme2 = projectStore.project.themes.find(
748+
theme2 => theme2.name == theme.name
749+
);
750+
if (!theme2) {
751+
projectStore.addObject(
752+
projectStore.project.themes,
753+
createObject<Theme>(
754+
projectStore,
755+
{
756+
name: theme.name
757+
},
758+
Theme
759+
)
760+
);
761+
}
762+
}
763+
764+
for (
765+
let colorIndex = 0;
766+
colorIndex < themeColorsClipboardData.data.colorNames.length;
767+
colorIndex++
768+
) {
769+
const colorName =
770+
themeColorsClipboardData.data.colorNames[colorIndex];
771+
772+
const newColor = projectStore.addObject(
773+
projectStore.project.colors,
774+
createObject<Color>(
775+
projectStore,
776+
{
777+
name: colorName
778+
},
779+
Color
780+
)
781+
);
782+
783+
newObjects.push(newColor);
784+
785+
for (const theme of themeColorsClipboardData.data.themes) {
786+
const theme2 = projectStore.project.themes.find(
787+
theme2 => theme2.name == theme.name
788+
)!;
789+
projectStore.project.setThemeColor(
790+
theme2.objID,
791+
newColor.objID,
792+
theme.colors[colorIndex]
793+
);
794+
}
795+
}
796+
}
797+
798+
if (closeCombineCommands) {
799+
projectStore.undoManager.setCombineCommands(false);
800+
}
801+
802+
return newObjects;
803+
}
804+
};
805+
806+
addThemes(projectStore: ProjectStore, themes: Theme[]) {
807+
this.data = {
808+
kind: "themes",
809+
themes: themes.map(theme => ({
810+
name: theme.name,
811+
colors: theme.colors
812+
})),
813+
colorNames: projectStore.project.colors.map(color => color.name)
814+
};
815+
}
816+
817+
addColors(projectStore: ProjectStore, colors: Color[]) {
818+
this.data = {
819+
kind: "colors",
820+
themes: projectStore.project.themes.map(theme => ({
821+
name: theme.name,
822+
colors: colors.map(color =>
823+
projectStore.project.getThemeColor(theme.objID, color.objID)
824+
)
825+
})),
826+
colorNames: colors.map(color => color.name)
827+
};
828+
}
829+
}
830+
831+
registerClass("ThemeColorsClipboardData", ThemeColorsClipboardData);
832+
833+
////////////////////////////////////////////////////////////////////////////////
834+
670835
function getThemedColorInProject(
671836
project: Project,
672837
colorValue: string

packages/project-editor/project-editor-create.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ import { Style } from "project-editor/features/style/style";
132132
import { evalProperty } from "project-editor/flow/helper";
133133
import { migrateLvglVersion } from "./lvgl/migrate";
134134
import { FlowTabState } from "project-editor/flow/flow-tab-state";
135-
import { Color } from "project-editor/features/style/theme";
135+
import { Color, ThemeColorsClipboardData } from "project-editor/features/style/theme";
136136
import { UserProperty } from "./flow/user-property";
137137
import { LVGLActionComponent } from "project-editor/lvgl/actions";
138138
import { FlowEditor } from "project-editor/flow/editor/editor";
@@ -201,6 +201,7 @@ export async function createProjectEditor(
201201
BitmapClass: Bitmap,
202202
FontClass: Font,
203203
ColorClass: Color,
204+
ThemeColorsClipboardDataClass: ThemeColorsClipboardData,
204205
LVGLWidgetClass: LVGLWidget,
205206
LVGLScreenWidgetClass: LVGLScreenWidget,
206207
LVGLContainerWidgetClass: LVGLContainerWidget,

packages/project-editor/project-editor-interface.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ import type { Style } from "project-editor/features/style/style";
108108
import type { evalProperty } from "project-editor/flow/helper";
109109
import type { migrateLvglVersion } from "project-editor/lvgl/migrate";
110110
import type { FlowTabState } from "project-editor/flow/flow-tab-state";
111-
import type { Color } from "project-editor/features/style/theme";
111+
import type { Color, ThemeColorsClipboardData } from "project-editor/features/style/theme";
112112
import type { UserProperty } from "project-editor/flow/user-property";
113113
import type { LVGLActionComponent } from "project-editor/lvgl/actions";
114114
import type { FlowEditor } from "project-editor/flow/editor/editor";
@@ -157,6 +157,7 @@ export interface IProjectEditor {
157157
BitmapClass: typeof Bitmap;
158158
FontClass: typeof Font;
159159
ColorClass: typeof Color;
160+
ThemeColorsClipboardDataClass: typeof ThemeColorsClipboardData;
160161
LVGLWidgetClass: typeof LVGLWidget;
161162
LVGLScreenWidgetClass: typeof LVGLScreenWidget;
162163
LVGLContainerWidgetClass: typeof LVGLContainerWidget;

packages/project-editor/store/clipboard.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import {
2020
SerializedData,
2121
PropertyInfo
2222
} from "project-editor/core/object";
23+
import { ProjectEditor } from "project-editor/project-editor-interface";
2324

2425
import {
2526
createObject,
@@ -336,6 +337,10 @@ export function findPastePlaceInsideAndOutside(
336337
}
337338

338339
if (serializedData.object) {
340+
if (serializedData.object instanceof ProjectEditor.ThemeColorsClipboardDataClass) {
341+
return ProjectEditor.getProject(object);
342+
}
343+
339344
if (!canContain(object, serializedData.object)) {
340345
return undefined;
341346
}

packages/project-editor/store/paste-with-dependencies.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1881,6 +1881,9 @@ export function canPasteWithDependencies(
18811881
if (serializedData.object instanceof ProjectEditor.BuildFileClass) {
18821882
return false;
18831883
}
1884+
if (serializedData.object instanceof ProjectEditor.ThemeColorsClipboardDataClass) {
1885+
return false;
1886+
}
18841887
} else if (serializedData.objects) {
18851888
if (
18861889
!serializedData.objects.find(

0 commit comments

Comments
 (0)