Skip to content

Commit c0aa770

Browse files
committedDec 29, 2024
FocusWidget action for the Dashboard projects
1 parent bf3d91c commit c0aa770

File tree

8 files changed

+170
-15
lines changed

8 files changed

+170
-15
lines changed
 

‎npm-module/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"author": "Envox <eez@envox.hr>",
44
"description": "EEZ Studio for building standalone dashboard applications",
55
"repository": "https://github.com/eez-open/studio",
6-
"version": "0.0.54",
6+
"version": "0.0.56",
77
"revision": "1",
88
"license": "GPL-3.0-only",
99
"files": ["packages", "libs", "resources"]

‎packages/home/main.tsx

-9
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ import { LineMarkers } from "project-editor/flow/connection-line/ConnectionLineC
2424

2525
import "home/settings";
2626
import { extensionsCatalog } from "./extensions-manager/catalog";
27-
import { initProjectEditor } from "project-editor/project-editor-bootstrap";
2827
import { buildProject } from "home/build-project";
2928
import { layoutModels } from "eez-studio-ui/side-dock";
3029

@@ -84,14 +83,6 @@ ipcRenderer.on(
8483
}
8584
);
8685

87-
ipcRenderer.on("show-documentation-browser", async () => {
88-
const { showDocumentationBrowser } = await import(
89-
"home/documentation-browser"
90-
);
91-
await initProjectEditor(tabs, ProjectEditorTab);
92-
showDocumentationBrowser();
93-
});
94-
9586
ipcRenderer.on("show-about-box", async () => {
9687
showAboutBox();
9788
});

‎packages/home/tabs-store.tsx

+16
Original file line numberDiff line numberDiff line change
@@ -1331,3 +1331,19 @@ export function openProject(filePath: string, runMode: boolean) {
13311331
console.error(err);
13321332
}
13331333
}
1334+
1335+
ipcRenderer.on("show-documentation-browser", async () => {
1336+
if (
1337+
tabs.activeTab instanceof ProjectEditorTab &&
1338+
tabs.activeTab.projectStore &&
1339+
tabs.activeTab.projectStore.runtime
1340+
) {
1341+
return;
1342+
}
1343+
1344+
const { showDocumentationBrowser } = await import(
1345+
"home/documentation-browser"
1346+
);
1347+
await initProjectEditor(tabs, ProjectEditorTab);
1348+
showDocumentationBrowser();
1349+
});

‎packages/project-editor/flow/components/actions/file.tsx

+8-4
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ registerActionComponents("File", [
147147
name: "encoding",
148148
type: "expression",
149149
valueType: "string",
150-
formText: `"ascii", "base64", "hex", "ucs2", "ucs-2", "utf16le", "utf-16le", "utf8", "utf-8", "binary" or "latin1"`
150+
formText: `"ascii", "base64", "hex", "ucs2", "ucs-2", "utf16le", "utf-16le", "utf8", "utf-8", "utf8-bom", "binary" or "latin1"`
151151
}
152152
],
153153
execute: (context: IDashboardComponentContext) => {
@@ -157,12 +157,14 @@ registerActionComponents("File", [
157157
return;
158158
}
159159

160-
const encodingValue = context.evalProperty("encoding");
160+
let encodingValue = context.evalProperty("encoding");
161161
if (typeof encodingValue != "string") {
162162
context.throwError("${encoding} is not a string");
163163
return;
164164
}
165165

166+
let contentValue = context.evalProperty("content");
167+
166168
const encodings = [
167169
"ascii",
168170
"base64",
@@ -176,6 +178,10 @@ registerActionComponents("File", [
176178
"binary",
177179
"latin1"
178180
];
181+
if (encodingValue == "utf8-bom") {
182+
encodingValue = "utf8";
183+
contentValue = "\ufeff" + contentValue;
184+
}
179185
if (encodings.indexOf(encodingValue) == -1) {
180186
context.throwError(
181187
`Unsupported encoding value ${encodingValue}, supported: ${encodings.join(
@@ -185,8 +191,6 @@ registerActionComponents("File", [
185191
return;
186192
}
187193

188-
const contentValue = context.evalProperty("content");
189-
190194
context = context.startAsyncExecution();
191195

192196
(async function () {

‎packages/project-editor/flow/components/actions/index.tsx

+107
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ import {
122122
CALL_ACTION_ICON,
123123
CALL_NATIVE_ACTION_ICON,
124124
CLIPBOARD_WRITE_ICON,
125+
FOCUS_WIDGET_ICON,
125126
LANGUAGE_ICON,
126127
LOG_ICON,
127128
PALETTE_ICON,
@@ -4835,6 +4836,110 @@ export class PrintToPDFActionComponent extends ActionComponent {
48354836

48364837
////////////////////////////////////////////////////////////////////////////////
48374838

4839+
export class FocusWidgetActionComponent extends ActionComponent {
4840+
static classInfo = makeDerivedClassInfo(ActionComponent.classInfo, {
4841+
componentPaletteGroupName: "GUI",
4842+
properties: [
4843+
makeExpressionProperty(
4844+
{
4845+
name: "widget",
4846+
type: PropertyType.MultilineText,
4847+
propertyGridGroup: specificGroup
4848+
},
4849+
"widget"
4850+
)
4851+
],
4852+
defaultValue: {},
4853+
icon: FOCUS_WIDGET_ICON,
4854+
componentHeaderColor: "#DEB887",
4855+
execute: (context: IDashboardComponentContext) => {
4856+
const widget = context.evalProperty<number>("widget");
4857+
if (widget == undefined) {
4858+
context.throwError(`Invalid Widget property`);
4859+
return;
4860+
}
4861+
4862+
const widgetInfo =
4863+
context.WasmFlowRuntime.getWidgetHandleInfo(widget);
4864+
4865+
if (!widgetInfo) {
4866+
context.throwError(`Invalid Widget handle`);
4867+
return;
4868+
}
4869+
4870+
const widgetContext = new DashboardComponentContext(
4871+
context.WasmFlowRuntime,
4872+
widgetInfo.flowStateIndex,
4873+
widgetInfo.componentIndex
4874+
);
4875+
4876+
const executionState =
4877+
widgetContext.getComponentExecutionState<any>();
4878+
4879+
if (!executionState) {
4880+
context.throwError(`Widget not initialized`);
4881+
return;
4882+
}
4883+
4884+
if (!executionState.focus) {
4885+
context.throwError(`Widget doesn't support focus`);
4886+
return;
4887+
}
4888+
4889+
executionState.focus();
4890+
4891+
context.propagateValueThroughSeqout();
4892+
}
4893+
});
4894+
4895+
widget: string;
4896+
4897+
override makeEditable() {
4898+
super.makeEditable();
4899+
4900+
makeObservable(this, {
4901+
widget: observable
4902+
});
4903+
}
4904+
4905+
getInputs() {
4906+
return [
4907+
{
4908+
name: "@seqin",
4909+
type: "any" as ValueType,
4910+
isSequenceInput: true,
4911+
isOptionalInput: true
4912+
},
4913+
...super.getInputs()
4914+
];
4915+
}
4916+
4917+
getOutputs() {
4918+
return [
4919+
{
4920+
name: "@seqout",
4921+
type: "null" as ValueType,
4922+
isSequenceOutput: true,
4923+
isOptionalOutput: true
4924+
},
4925+
...super.getOutputs()
4926+
];
4927+
}
4928+
4929+
getBody(flowContext: IFlowContext): React.ReactNode {
4930+
if (!this.widget) {
4931+
return null;
4932+
}
4933+
return (
4934+
<div className="body">
4935+
<pre>{this.widget}</pre>
4936+
</div>
4937+
);
4938+
}
4939+
}
4940+
4941+
////////////////////////////////////////////////////////////////////////////////
4942+
48384943
registerClass("StartActionComponent", StartActionComponent);
48394944
registerClass("EndActionComponent", EndActionComponent);
48404945
registerClass("InputActionComponent", InputActionComponent);
@@ -4902,3 +5007,5 @@ registerClass("NoopActionComponent", NoopActionComponent);
49025007
registerClass("CommentActionComponent", CommentActionComponent);
49035008

49045009
registerClass("PrintToPDFActionComponent", PrintToPDFActionComponent);
5010+
5011+
registerClass("FocusWidgetActionComponent", FocusWidgetActionComponent);

‎packages/project-editor/flow/components/widgets/dashboard/index.tsx

+27
Original file line numberDiff line numberDiff line change
@@ -612,6 +612,10 @@ registerClass("TextInputWidget", TextInputWidget);
612612

613613
////////////////////////////////////////////////////////////////////////////////
614614

615+
class NumberInputDashboardExecutionState {
616+
focus?: () => void;
617+
}
618+
615619
const NumberInputDashboardWidgetElement = observer(
616620
class NumberInputDashboardWidgetElement extends React.Component<{
617621
className: string;
@@ -636,6 +640,16 @@ const NumberInputDashboardWidgetElement = observer(
636640
if (this.props.flowContext.flowState && this.inputElement.current) {
637641
this.inputElement.current.focus();
638642
}
643+
644+
let executionState =
645+
this.props.flowContext.flowState?.getComponentExecutionState<NumberInputDashboardExecutionState>(
646+
this.props.component
647+
);
648+
if (executionState) {
649+
executionState.focus = () => {
650+
this.inputElement.current?.focus();
651+
};
652+
}
639653
}
640654

641655
dispose: IReactionDisposer;
@@ -812,6 +826,18 @@ export class NumberInputDashboardWidget extends Widget {
812826
paramExpressionType: `struct:${SLIDER_CHANGE_EVENT_STRUCT_NAME}`,
813827
oldName: "action"
814828
}
829+
},
830+
831+
execute: (context: IDashboardComponentContext) => {
832+
Widget.classInfo.execute!(context);
833+
834+
let executionState =
835+
context.getComponentExecutionState<NumberInputDashboardExecutionState>();
836+
if (!executionState) {
837+
context.setComponentExecutionState<NumberInputDashboardExecutionState>(
838+
new NumberInputDashboardExecutionState()
839+
);
840+
}
815841
}
816842
});
817843

@@ -2605,3 +2631,4 @@ import "project-editor/flow/components/widgets/dashboard/embedded-dashboard";
26052631

26062632
import { assignProperty } from "project-editor/flow/runtime/worker-dashboard-component-context";
26072633
import { guid } from "eez-studio-shared/guid";
2634+
import { IDashboardComponentContext } from "eez-studio-types";

‎packages/project-editor/flow/runtime/wasm-runtime.tsx

+2-1
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,6 @@ import { getClassByName } from "project-editor/core/object";
7979
import { FLOW_EVENT_KEYDOWN } from "project-editor/flow/runtime/flow-events";
8080
import { preloadAllBitmaps } from "project-editor/features/bitmap/bitmap";
8181
import { releaseRuntimeDashboardStates } from "project-editor/flow/runtime/component-execution-states";
82-
import { hasClass } from "eez-studio-shared/dom";
8382
import { findBitmap } from "project-editor/project/assets";
8483

8584
interface IGlobalVariableBase {
@@ -1186,6 +1185,7 @@ export class WasmRuntime extends RemoteRuntime {
11861185
//key = e.key;
11871186
}
11881187

1188+
/*
11891189
if (e.target instanceof HTMLInputElement) {
11901190
if (
11911191
(key != "Tab" && key != "ShiftTab") ||
@@ -1208,6 +1208,7 @@ export class WasmRuntime extends RemoteRuntime {
12081208
12091209
e.preventDefault();
12101210
e.stopPropagation();
1211+
*/
12111212

12121213
let valuePtr = createWasmValue(this.worker.wasm, key);
12131214

‎packages/project-editor/ui-components/icons.tsx

+9
Original file line numberDiff line numberDiff line change
@@ -3549,3 +3549,12 @@ export const CALL_NATIVE_ACTION_ICON: any = (
35493549
<path d="M4 18v-3.7a1.5 1.5 0 0 0-1.5-1.5H2v-1.6h.5A1.5 1.5 0 0 0 4 9.7V6a3 3 0 0 1 3-3h1v2H7a1 1 0 0 0-1 1v4.1A2 2 0 0 1 4.626 12 2 2 0 0 1 6 13.9V18a1 1 0 0 0 1 1h1v2H7a3 3 0 0 1-3-3m16-3.7V18a3 3 0 0 1-3 3h-1v-2h1a1 1 0 0 0 1-1v-4.1a2 2 0 0 1 1.374-1.9A2 2 0 0 1 18 10.1V6a1 1 0 0 0-1-1h-1V3h1a3 3 0 0 1 3 3v3.7a1.5 1.5 0 0 0 1.5 1.5h.5v1.6h-.5a1.5 1.5 0 0 0-1.5 1.5" />
35503550
</svg>
35513551
);
3552+
3553+
export const FOCUS_WIDGET_ICON: any = (
3554+
<svg viewBox="0 0 24 24">
3555+
<path
3556+
fill="currentColor"
3557+
d="M5 21q-.825 0-1.412-.587T3 19v-4h2v4h4v2zm10 0v-2h4v-4h2v4q0 .825-.587 1.413T19 21zM3 9V5q0-.825.588-1.412T5 3h4v2H5v4zm16 0V5h-4V3h4q.825 0 1.413.588T21 5v4zm-7 8q-2.075 0-3.537-1.463T7 12t1.463-3.537T12 7t3.538 1.463T17 12t-1.463 3.538T12 17"
3558+
/>
3559+
</svg>
3560+
);

0 commit comments

Comments
 (0)