Skip to content

Commit

Permalink
Implemented: Import images in bulk #532
Browse files Browse the repository at this point in the history
  • Loading branch information
mvladic committed Nov 17, 2024
1 parent d8fe5b2 commit dd4d67e
Show file tree
Hide file tree
Showing 3 changed files with 124 additions and 14 deletions.
60 changes: 48 additions & 12 deletions packages/project-editor/features/bitmap/bitmap.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ import { getThemedColor } from "project-editor/features/style/theme";

import { showGenericDialog } from "project-editor/core/util";

import { AbsoluteFileInput } from "project-editor/ui-components/FileInput";
import { MultipleAbsoluteFileInput } from "project-editor/ui-components/FileInput";
import { getProject, findStyle } from "project-editor/project/project";

import { ProjectEditor } from "project-editor/project-editor-interface";
Expand Down Expand Up @@ -241,12 +241,18 @@ export class Bitmap extends EezObject {
validators.required,
validators.invalidCharacters("."),
validators.unique({}, parent)
]
],
visible: (values: any) => {
return !(
values.imageFilePaths &&
values.imageFilePaths.length > 1
);
}
},
{
name: "imageFilePath",
name: "imageFilePaths",
displayName: "Image",
type: AbsoluteFileInput,
type: MultipleAbsoluteFileInput,
validators: [validators.required],
options: {
filters: [
Expand Down Expand Up @@ -287,16 +293,46 @@ export class Bitmap extends EezObject {
}
});

const name: string = result.values.name;
const bpp: number = result.values.bpp;

return createBitmap(
projectStore,
result.values.imageFilePath,
undefined,
name,
bpp
);
if (result.values.imageFilePaths.length == 1) {
const name: string = result.values.name;

return createBitmap(
projectStore,
result.values.imageFilePaths[0],
undefined,
name,
bpp
);
} else {
projectStore.undoManager.setCombineCommands(true);

for (let i = 0; i < result.values.imageFilePaths.length; i++) {
const filePath = result.values.imageFilePaths[i];

let name = getUniquePropertyValue(
projectStore.project.bitmaps,
"name",
path.parse(filePath).name
) as string;

const bitmap = await createBitmap(
projectStore,
filePath,
undefined,
name,
bpp
);
if (bitmap) {
projectStore.addObject(parent, bitmap);
}
}

projectStore.undoManager.setCombineCommands(false);

return undefined;
}
},
icon: "material:image",
afterLoadHook: (bitmap: Bitmap, project) => {
Expand Down
6 changes: 4 additions & 2 deletions packages/project-editor/lvgl/widgets/Base.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1054,8 +1054,10 @@ export class LVGLWidget extends Widget {
referencedObjectCollectionPath: "lvglGroups/groups",
propertyGridGroup: generalGroup,
hideInPropertyGrid: (widget: LVGLWidget) =>
ProjectEditor.getProject(widget).lvglGroups.groups.length ==
0 || widget instanceof LVGLScreenWidget
(ProjectEditor.getProject(widget).lvglGroups.groups
.length == 0 &&
!widget.group) ||
widget instanceof LVGLScreenWidget
},
{
name: "groupIndex",
Expand Down
72 changes: 72 additions & 0 deletions packages/project-editor/ui-components/FileInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,78 @@ export class AbsoluteFileInput extends FieldComponent {

////////////////////////////////////////////////////////////////////////////////

export class MultipleAbsoluteFileInput extends FieldComponent {
static contextType = ProjectContext;
declare context: React.ContextType<typeof ProjectContext>;

onClear = () => {
this.props.onChange(undefined);
};

onSelect = async () => {
const result = await dialog.showOpenDialog({
properties: ["openFile", "multiSelections"],
filters: this.props.fieldProperties.options.filters
});

if (result.filePaths && result.filePaths.length > 0) {
this.props.onChange(result.filePaths);
}
};

get value() {
const value = this.props.values[this.props.fieldProperties.name];
if (!value) {
return "";
}

if (value.length > 1) {
return `${value.length} images selected`;
}

return value;
}

render() {
let clearButton: JSX.Element | undefined;

if (this.props.values[this.props.fieldProperties.name]) {
clearButton = (
<button
className="btn btn-default"
type="button"
onClick={this.onClear}
>
<Icon icon="material:close" size={17} />
</button>
);
}

return (
<div className="input-group">
<input
type="text"
className="form-control"
value={this.value}
readOnly
/>
<>
{clearButton}
<button
className="btn btn-secondary"
type="button"
onClick={this.onSelect}
>
&hellip;
</button>
</>
</div>
);
}
}

////////////////////////////////////////////////////////////////////////////////

export class AbsoluteFileSaveInput extends FieldComponent {
static contextType = ProjectContext;
declare context: React.ContextType<typeof ProjectContext>;
Expand Down

0 comments on commit dd4d67e

Please sign in to comment.