diff --git a/modules/ui/components/ImgIcon.jsx b/modules/ui/components/ImgIcon.tsx
similarity index 61%
rename from modules/ui/components/ImgIcon.jsx
rename to modules/ui/components/ImgIcon.tsx
index ad6f9b76..f7c8d8eb 100644
--- a/modules/ui/components/ImgIcon.jsx
+++ b/modules/ui/components/ImgIcon.tsx
@@ -1,6 +1,11 @@
import React from 'react';
-export default function ImgIcon({url, size, style, ...props}) {
+type ImgIconParams = { url: string; size: string|number; style?: any; };
+
+export default function ImgIcon(inprops: ImgIconParams) {
+
+ const {url, size, style, ...props} = inprops;
+
return
-};
\ No newline at end of file
+}
\ No newline at end of file
diff --git a/modules/workbenches/modeler/features/boolean_tool/boolean.operation.ts b/modules/workbenches/modeler/features/boolean_tool/boolean.operation.ts
index 9d9ee51e..58a247a1 100644
--- a/modules/workbenches/modeler/features/boolean_tool/boolean.operation.ts
+++ b/modules/workbenches/modeler/features/boolean_tool/boolean.operation.ts
@@ -1,23 +1,20 @@
-import { roundValueForPresentation as r } from 'cad/craft/operationHelper';
-import { MFace } from "cad/model/mface";
-import { ApplicationContext } from "context";
-import { MDFCommand } from "cad/mdf/mdf";
-import { EntityKind } from "cad/model/entities";
-import Vector from "math/vector";
-import { BooleanDefinition } from "cad/craft/schema/common/BooleanDefinition";
-import { MShell } from 'cad/model/mshell';
+import {roundValueForPresentation as r} from 'cad/craft/operationHelper';
+import {ApplicationContext} from "context";
+import {EntityKind} from "cad/model/entities";
+import {BooleanDefinition} from "cad/craft/schema/common/BooleanDefinition";
+import {OperationDescriptor} from "cad/craft/operationPlugin";
interface BooleanParams {
tools: [];
boolean: BooleanDefinition
}
-const BooleanOperation: MDFCommand = {
+const BooleanOperation: OperationDescriptor = {
id: 'boolean_tool',
label: 'Boolean',
icon: 'img/cad/Boolean',
info: 'Booleans 2D sketch',
- paramsInfo: ({ tools, boolean }) => `(${r(tools)} ${r(boolean)})`,
+ paramsInfo: ({tools, boolean}) => `(${r(tools)} ${r(boolean)})`,
run: (params: BooleanParams, ctx: ApplicationContext) => {
console.log(params);
let occ = ctx.occService;
diff --git a/modules/workbenches/modeler/features/extrude/extrude.operation.ts b/modules/workbenches/modeler/features/extrude/extrude.operation.ts
index 1844a32e..1ab77cf4 100644
--- a/modules/workbenches/modeler/features/extrude/extrude.operation.ts
+++ b/modules/workbenches/modeler/features/extrude/extrude.operation.ts
@@ -1,10 +1,10 @@
import {roundValueForPresentation as r} from 'cad/craft/operationHelper';
import {MFace} from "cad/model/mface";
import {ApplicationContext} from "context";
-import {MDFCommand} from "cad/mdf/mdf";
import {EntityKind} from "cad/model/entities";
import {BooleanDefinition} from "cad/craft/schema/common/BooleanDefinition";
import {UnitVector} from "math/vector";
+import {OperationDescriptor} from "cad/craft/operationPlugin";
interface ExtrudeParams {
@@ -14,13 +14,12 @@ interface ExtrudeParams {
boolean: BooleanDefinition
}
-const ExtrudeOperation: MDFCommand = {
+const ExtrudeOperation: OperationDescriptor = {
id: 'EXTRUDE',
label: 'Extrude',
icon: 'img/cad/extrude',
info: 'extrudes 2D sketch',
paramsInfo: ({length}) => `(${r(length)})`,
- mutualExclusiveFields: ['datumAxisVector', 'edgeVector', 'sketchSegmentVector'],
run: (params: ExtrudeParams, ctx: ApplicationContext) => {
let occ = ctx.occService;
diff --git a/modules/workbenches/modeler/features/hole_tool/index.ts b/modules/workbenches/modeler/features/hole_tool/index.ts
index a0c25e0a..a186cc10 100644
--- a/modules/workbenches/modeler/features/hole_tool/index.ts
+++ b/modules/workbenches/modeler/features/hole_tool/index.ts
@@ -1,137 +1,140 @@
-import { roundValueForPresentation as r } from 'cad/craft/operationHelper';
-import { MFace } from "cad/model/mface";
-import { ApplicationContext } from "context";
-import { MDFCommand } from "cad/mdf/mdf";
-import { EntityKind } from "cad/model/entities";
+import {roundValueForPresentation as r} from 'cad/craft/operationHelper';
+import {ApplicationContext} from "context";
+import {EntityKind} from "cad/model/entities";
+import {OperationDescriptor} from "cad/craft/operationPlugin";
interface HoleParams {
- diameter: number;
- depth: number;
- counterBoreDiameter: number;
- counterBoreDepth: number;
- countersinkDiameter: number;
- countersinkAngle: number;
- holeType: string;
+ diameter: number;
+ depth: number;
+ counterBoreDiameter: number;
+ counterBoreDepth: number;
+ countersinkDiameter: number;
+ countersinkAngle: number;
+ holeType: string;
}
-const HoleOperation: MDFCommand = {
- id: 'hole_tool',
- label: 'hole',
- icon: 'img/cad/Shell',
- info: 'creates hole features',
- paramsInfo: ({ diameter, depth, counterBoreDiameter, counterBoreDepth, countersinkDiameter, countersinkAngle, holeType, }) => `(${r(depth)} ${r(counterBoreDiameter)}) ${r(counterBoreDepth)})`,
+const HoleOperation: OperationDescriptor = {
+ id: 'hole_tool',
+ label: 'hole',
+ icon: 'img/cad/Shell',
+ info: 'creates hole features',
+ paramsInfo: ({
+ diameter,
+ depth,
+ counterBoreDiameter,
+ counterBoreDepth,
+ countersinkDiameter,
+ countersinkAngle,
+ holeType,
+ }) => `(${r(depth)} ${r(counterBoreDiameter)}) ${r(counterBoreDepth)})`,
- run: (params: HoleParams, ctx: ApplicationContext) => {
- console.log(params);
- let occ = ctx.occService;
- const oci = occ.commandInterface;
+ run: (params: HoleParams, ctx: ApplicationContext) => {
+ console.log(params);
+ let occ = ctx.occService;
+ const oci = occ.commandInterface;
- var returnObject = {
- consumed: [],
- created: []
- };
+ var returnObject = {
+ consumed: [],
+ created: []
+ };
- oci.pcylinder("basehole", params.diameter / 2, params.depth);
+ oci.pcylinder("basehole", params.diameter / 2, params.depth);
- if (params.holeType == "normal") {
- returnObject.created.push(occ.io.getShell("basehole"));
- }
+ if (params.holeType == "normal") {
+ returnObject.created.push(occ.io.getShell("basehole"));
+ }
- if (params.holeType == "counterbore") {
- oci.pcylinder("counterbore", params.counterBoreDiameter / 2, params.counterBoreDepth);
+ if (params.holeType == "counterbore") {
+ oci.pcylinder("counterbore", params.counterBoreDiameter / 2, params.counterBoreDepth);
- oci.bop("basehole", "counterbore");
- oci.bopfuse("result");
+ oci.bop("basehole", "counterbore");
+ oci.bopfuse("result");
- returnObject.created.push(occ.io.getShell("result"));
- }
+ returnObject.created.push(occ.io.getShell("result"));
+ }
- if (params.holeType == "countersink") {
+ if (params.holeType == "countersink") {
- let heightFromDiameterAndAngle = (params.countersinkDiameter - params.diameter) / (Math.tan((params.countersinkAngle / 180 * Math.PI) / 2));
+ let heightFromDiameterAndAngle = (params.countersinkDiameter - params.diameter) / (Math.tan((params.countersinkAngle / 180 * Math.PI) / 2));
- oci.pcone("countersink", params.countersinkDiameter / 2, 0, heightFromDiameterAndAngle);
- oci.bop("basehole", "countersink");
- oci.bopfuse("result");
- returnObject.created.push(occ.io.getShell("result"));
- }
+ oci.pcone("countersink", params.countersinkDiameter / 2, 0, heightFromDiameterAndAngle);
+ oci.bop("basehole", "countersink");
+ oci.bopfuse("result");
+ returnObject.created.push(occ.io.getShell("result"));
+ }
+ console.log(returnObject);
+ return returnObject;
- console.log(returnObject);
-
- return returnObject;
-
+ },
+ form: [
+ {
+ type: 'selection',
+ name: 'sketch',
+ capture: [EntityKind.FACE],
+ label: 'faces',
+ multi: true,
+ defaultValue: {
+ usePreselection: true,
+ preselectionIndex: 0
+ },
},
- form: [
- {
- type: 'selection',
- name: 'sketch',
- capture: [EntityKind.FACE],
- label: 'faces',
- multi: true,
- defaultValue: {
- usePreselection: true,
- preselectionIndex: 0
- },
- },
- {
- type: 'choice',
- label: 'HoleType',
- name: "holeType",
- style: "dropdown",
- defaultValue: "counterbore",
- values: ['counterbore', 'countersink', 'normal',],
- },
+ {
+ type: 'choice',
+ label: 'HoleType',
+ name: "holeType",
+ style: "dropdown",
+ defaultValue: "counterbore",
+ values: ['counterbore', 'countersink', 'normal',],
+ },
- {
- type: 'number',
- name: "diameter",
- defaultValue: 10,
- label: 'Hole ⌀'
- },
- {
- type: 'number',
- name: "depth",
- defaultValue: 100,
- label: 'Hole ↧'
- },
+ {
+ type: 'number',
+ name: "diameter",
+ defaultValue: 10,
+ label: 'Hole ⌀'
+ },
+ {
+ type: 'number',
+ name: "depth",
+ defaultValue: 100,
+ label: 'Hole ↧'
+ },
-
- {
- type: 'number',
- name: "counterBoreDiameter",
- defaultValue: 20,
- label: '⌴ ⌀'
- },
- {
- type: 'number',
- name: "counterBoreDepth",
- defaultValue: 10,
- label: '⌴ ↧'
- },
+ {
+ type: 'number',
+ name: "counterBoreDiameter",
+ defaultValue: 20,
+ label: '⌴ ⌀'
+ },
+ {
+ type: 'number',
+ name: "counterBoreDepth",
+ defaultValue: 10,
+ label: '⌴ ↧'
+ },
-
- {
- type: 'number',
- name: "countersinkDiameter",
- defaultValue: 20,
- label: '⌵ ⌀'
- },
- {
- type: 'number',
- name: "countersinkAngle",
- defaultValue: 90,
- label: '⌵ Angle'
- },
- ],
+ {
+ type: 'number',
+ name: "countersinkDiameter",
+ defaultValue: 20,
+ label: '⌵ ⌀'
+ },
+ {
+ type: 'number',
+ name: "countersinkAngle",
+ defaultValue: 90,
+ label: '⌵ Angle'
+ },
+ ],
}
export default HoleOperation;
\ No newline at end of file
diff --git a/modules/workbenches/modeler/features/primitive_box/index.ts b/modules/workbenches/modeler/features/primitive_box/index.ts
index 21f19ced..e260930e 100644
--- a/modules/workbenches/modeler/features/primitive_box/index.ts
+++ b/modules/workbenches/modeler/features/primitive_box/index.ts
@@ -1,83 +1,77 @@
-import { ApplicationContext } from 'context';
-import { roundValueForPresentation as r } from 'cad/craft/operationHelper';
-
-import { MDFCommand } from "cad/mdf/mdf";
-import { EntityKind } from "cad/model/entities";
-import { BooleanDefinition } from "cad/craft/schema/common/BooleanDefinition";
-
-
+import {ApplicationContext} from 'context';
+import {roundValueForPresentation as r} from 'cad/craft/operationHelper';
+import {EntityKind} from "cad/model/entities";
+import {BooleanDefinition} from "cad/craft/schema/common/BooleanDefinition";
+import {OperationDescriptor} from "cad/craft/operationPlugin";
interface PrimitiveBoxParams {
- x: Number,
- y: Number,
- z: Number,
- locations: {},
- boolean: BooleanDefinition,
+ x: Number,
+ y: Number,
+ z: Number,
+ locations: {},
+ boolean: BooleanDefinition,
}
-const PrimitiveBoxOperation: MDFCommand = {
- id: 'primitive_box',
- label: 'Primitive Box',
- icon: 'img/cad/extrude',
- info: 'Primitive Box',
- paramsInfo: ({ x, y, z }) => `(${r(x)} , ${r(y)} , ${r(z)})`,
- form: [
- {
- type: 'number',
- label: 'X',
- name: 'x',
- defaultValue: 50,
- },
- {
- type: 'number',
- label: 'Y',
- name: 'y',
- defaultValue: 50,
- },
- {
- type: 'number',
- label: 'Z',
- name: 'z',
- defaultValue: 50,
- },
- {
- type: 'selection',
- name: 'locations',
- capture: [EntityKind.DATUM],
- label: 'locations',
- multi: false,
- optional: true,
- defaultValue: {
- usePreselection: true,
- preselectionIndex: 0
- },
- },
-
- {
- type: 'boolean',
- name: 'boolean',
- label: 'boolean',
- optional: true,
- }
-
- ],
-
-
-
-
-
- run: (params: PrimitiveBoxParams, ctx: ApplicationContext) => {
-
- let occ = ctx.occService;
- const oci = occ.commandInterface;
-
-
- oci.box("b", params.x,params.y,params.z);
-
- return occ.utils.applyBooleanModifier(["b"], params.boolean);
-
+const PrimitiveBoxOperation: OperationDescriptor = {
+ id: 'primitive_box',
+ label: 'Primitive Box',
+ icon: 'img/cad/extrude',
+ info: 'Primitive Box',
+ paramsInfo: ({x, y, z}) => `(${r(x)} , ${r(y)} , ${r(z)})`,
+ form: [
+ {
+ type: 'number',
+ label: 'X',
+ name: 'x',
+ defaultValue: 50,
},
+ {
+ type: 'number',
+ label: 'Y',
+ name: 'y',
+ defaultValue: 50,
+ },
+ {
+ type: 'number',
+ label: 'Z',
+ name: 'z',
+ defaultValue: 50,
+ },
+ {
+ type: 'selection',
+ name: 'locations',
+ capture: [EntityKind.DATUM],
+ label: 'locations',
+ multi: false,
+ optional: true,
+ defaultValue: {
+ usePreselection: true,
+ preselectionIndex: 0
+ },
+ },
+
+ {
+ type: 'boolean',
+ name: 'boolean',
+ label: 'boolean',
+ optional: true,
+ }
+
+ ],
+
+
+ run: (params: PrimitiveBoxParams, ctx: ApplicationContext) => {
+
+ let occ = ctx.occService;
+ const oci = occ.commandInterface;
+
+
+ oci.box("b", params.x, params.y, params.z);
+
+ return occ.utils.applyBooleanModifier(["b"], params.boolean);
+
+ },
}
export default PrimitiveBoxOperation;
\ No newline at end of file
diff --git a/modules/workbenches/modeler/features/revolve_tool/revolve.operation.ts b/modules/workbenches/modeler/features/revolve_tool/revolve.operation.ts
index f1993437..287c746e 100644
--- a/modules/workbenches/modeler/features/revolve_tool/revolve.operation.ts
+++ b/modules/workbenches/modeler/features/revolve_tool/revolve.operation.ts
@@ -1,12 +1,10 @@
-import { roundValueForPresentation as r } from 'cad/craft/operationHelper';
-import { MFace } from "cad/model/mface";
-import { ApplicationContext } from "context";
-import { MDFCommand } from "cad/mdf/mdf";
-import { EntityKind } from "cad/model/entities";
-import Vector from "math/vector";
-import { BooleanDefinition } from "cad/craft/schema/common/BooleanDefinition";
-import * as vec from "math/vec";
+import {roundValueForPresentation as r} from 'cad/craft/operationHelper';
+import {MFace} from "cad/model/mface";
+import {ApplicationContext} from "context";
+import {EntityKind} from "cad/model/entities";
+import {BooleanDefinition} from "cad/craft/schema/common/BooleanDefinition";
import Axis from "math/axis";
+import {OperationDescriptor} from "cad/craft/operationPlugin";
interface RevolveParams {
angle: number;
@@ -14,14 +12,13 @@ interface RevolveParams {
axis: Axis,
boolean: BooleanDefinition
}
-
-const RevolveOperation: MDFCommand = {
+
+const RevolveOperation: OperationDescriptor = {
id: 'Revolve',
label: 'Revolve',
icon: 'img/cad/Revolve',
info: 'Revolves 2D sketch',
- paramsInfo: ({ angle }) => `(${r(angle)})`,
- mutualExclusiveFields: ['datumAxisVector', 'edgeVector', 'sketchSegmentVector'],
+ paramsInfo: ({angle}) => `(${r(angle)})`,
run: (params: RevolveParams, ctx: ApplicationContext) => {
console.log(params);
let occ = ctx.occService;
@@ -43,12 +40,6 @@ const RevolveOperation: MDFCommand = {
});
-
-
-
-
-
-
return occ.utils.applyBooleanModifier(tools, params.boolean);
},
diff --git a/modules/workbenches/modeler/features/shell_tool/shell.operation.ts b/modules/workbenches/modeler/features/shell_tool/shell.operation.ts
index 94388fa3..099aaa33 100644
--- a/modules/workbenches/modeler/features/shell_tool/shell.operation.ts
+++ b/modules/workbenches/modeler/features/shell_tool/shell.operation.ts
@@ -1,8 +1,8 @@
-import { roundValueForPresentation as r } from 'cad/craft/operationHelper';
-import { MFace } from "cad/model/mface";
-import { ApplicationContext } from "context";
-import { MDFCommand } from "cad/mdf/mdf";
-import { EntityKind } from "cad/model/entities";
+import {roundValueForPresentation as r} from 'cad/craft/operationHelper';
+import {MFace} from "cad/model/mface";
+import {ApplicationContext} from "context";
+import {EntityKind} from "cad/model/entities";
+import {OperationDescriptor} from "cad/craft/operationPlugin";
interface ShellParams {
@@ -10,21 +10,18 @@ interface ShellParams {
faces: [MFace];
}
-const ShellOperation: MDFCommand = {
+const ShellOperation: OperationDescriptor = {
id: 'shell_tool',
label: 'Shell',
icon: 'img/cad/Shell',
info: 'Shells 2D sketch',
- paramsInfo: ({ thickness }) => `(${r(thickness)})`,
+ paramsInfo: ({thickness}) => `(${r(thickness)})`,
run: (params: ShellParams, ctx: ApplicationContext) => {
console.log(params);
let occ = ctx.occService;
const oci = occ.commandInterface;
-
-
-
var bodiesToShell = [];
var returnObject = {
consumed: [],
diff --git a/web/app/cad/craft/operationPlugin.ts b/web/app/cad/craft/operationPlugin.ts
index 9d2896b2..23be7cea 100644
--- a/web/app/cad/craft/operationPlugin.ts
+++ b/web/app/cad/craft/operationPlugin.ts
@@ -5,10 +5,13 @@ import {ActionAppearance} from "../actions/actionSystemPlugin";
import {ApplicationContext, CoreContext} from "context";
import {OperationResult} from "./craftPlugin";
import {OperationSchema, SchemaField, schemaIterator, unwrapMetadata} from "cad/craft/schema/schema";
-import {FieldWidgetProps} from "cad/mdf/ui/uiDefinition";
+import {FormDefinition} from "cad/mdf/ui/uiDefinition";
import {Types} from "cad/craft/schema/types";
import {EntityTypeSchema} from "cad/craft/schema/types/entityType";
import {FlattenPath, ParamsPath} from "cad/craft/wizard/wizardTypes";
+import {IconDeclaration} from "cad/icons/IconDeclaration";
+import {resolveIcon} from "cad/craft/ui/iconResolver";
+import {loadDeclarativeForm} from "cad/mdf/declarativeFormLoader";
export function activate(ctx: ApplicationContext) {
@@ -19,7 +22,14 @@ export function activate(ctx: ApplicationContext) {
};
function addOperation(descriptor: OperationDescriptor, actions) {
- let {id, label, info, icon, actionParams} = descriptor;
+ let {id, label, info, icon, actionParams, form, schema} = descriptor;
+
+ if (!schema) {
+ let {schema: derivedSchema, form: loadedForm} = loadDeclarativeForm(form as FormDefinition);
+ schema = derivedSchema;
+ form = loadedForm;
+ }
+
let appearance: ActionAppearance = {
label,
info
@@ -28,7 +38,7 @@ export function activate(ctx: ApplicationContext) {
appearance.icon32 = icon + '32.png';
appearance.icon96 = icon + '96.png';
} else {
- appearance.icon = icon;
+ appearance.icon = resolveIcon(icon);
}
let opAction = {
id: id,
@@ -38,10 +48,16 @@ export function activate(ctx: ApplicationContext) {
};
actions.push(opAction);
- let schemaIndex = createSchemaIndex(descriptor.schema);
- registry$.mutate(registry => registry[id] = Object.assign({appearance, schemaIndex}, descriptor, {
- run: (request, opContext) => runOperation(request, descriptor, opContext)
- }));
+ let schemaIndex = createSchemaIndex(schema);
+
+ let operation = {
+ appearance,
+ schemaIndex,
+ ...descriptor,
+ schema, form
+ };
+
+ registry$.mutate(registry => registry[id] = operation);
}
function registerOperations(operations) {
@@ -60,22 +76,9 @@ export function activate(ctx: ApplicationContext) {
return op;
}
- let handlers = [];
-
- function runOperation(request, descriptor, opContext) {
- for (let handler of handlers) {
- let result = handler(descriptor.id, request, opContext);
- if (result) {
- return result;
- }
- }
- return descriptor.run(request, opContext);
- }
-
ctx.operationService = {
registerOperations,
- get,
- handlers
+ get
};
ctx.services.operation = ctx.operationService;
@@ -90,31 +93,28 @@ export interface Operation extends OperationDescriptor{
icon96: string;
icon: string|IconType;
};
- schemaIndex: SchemaIndex
+ schemaIndex: SchemaIndex;
+ form: () => React.ReactNode;
+ schema: OperationSchema;
}
export interface OperationDescriptor {
id: string;
label: string;
info: string;
- icon: IconType | string | ((props: any) => JSX.Element);
+ icon: IconDeclaration | IconType | string | ((props: any) => JSX.Element);
actionParams?: any;
run: (request: R, opContext: CoreContext) => OperationResult | Promise;
paramsInfo: (params: R) => string,
previewGeomProvider?: (params: R) => OperationGeometryProvider,
- form: () => React.ReactNode,
- schema: OperationSchema,
+ form: FormDefinition | (() => React.ReactNode),
+ schema?: OperationSchema,
onParamsUpdate?: (params, name, value) => void,
}
export interface OperationService {
registerOperations(descriptior: OperationDescriptor[]);
get(operationId: string): Operation;
- handlers: ((
- id: string,
- request: any,
- opContext: CoreContext
- ) => void)[]
}
export type Index = {
diff --git a/web/app/cad/craft/schema/initializeBySchema.ts b/web/app/cad/craft/schema/initializeBySchema.ts
index 0ddca6f3..ff96323b 100644
--- a/web/app/cad/craft/schema/initializeBySchema.ts
+++ b/web/app/cad/craft/schema/initializeBySchema.ts
@@ -10,8 +10,8 @@ export default function initializeBySchema(schema: OperationSchema, context: App
let md = schema[field] as SchemaField;
if (md.type === Types.array) {
- if (md.items.type === Types.entity && md.items.defaultValue !== undefined) {
- const defaultValue = md.items.defaultValue;
+ if (md.items.type === Types.entity && md.defaultValue !== undefined) {
+ const defaultValue = md.defaultValue;
if (defaultValue.usePreselection === true) {
const entitySchema = md.items;
const currentSelection =
diff --git a/web/app/cad/craft/schema/materializeParams.ts b/web/app/cad/craft/schema/materializeParams.ts
index 0b3f56af..b1a3b758 100644
--- a/web/app/cad/craft/schema/materializeParams.ts
+++ b/web/app/cad/craft/schema/materializeParams.ts
@@ -33,12 +33,14 @@ function materializeParamsImpl(ctx: CoreContext,
result: any,
parentReportError: OperationParamsErrorReporter) {
+ const notProvided = value => value === undefined || value === null || value === '';
+
for (let field of Object.keys(schema)) {
const reportError = parentReportError.dot(field);
const md = schema[field];
let value = params[field];
- if (value === undefined || value === null || value === '') {
+ if (notProvided(value)) {
if (!md.optional) {
reportError('required');
}
@@ -50,6 +52,9 @@ function materializeParamsImpl(ctx: CoreContext,
value = md.resolve(
ctx, value, md as any, reportError
)
+ if (notProvided(value) && !md.optional) {
+ reportError('required');
+ }
}
// if (md.type === Types.NUMBER) {
diff --git a/web/app/cad/craft/schema/schema.ts b/web/app/cad/craft/schema/schema.ts
index 3bb77d89..693f60cf 100644
--- a/web/app/cad/craft/schema/schema.ts
+++ b/web/app/cad/craft/schema/schema.ts
@@ -28,7 +28,7 @@ export type OperationFlattenSchema = {
};
export interface BaseSchemaField {
- defaultValue: OperationParamValue,
+ defaultValue?: OperationParamValue,
optional: boolean,
label?: string,
resolve?: ValueResolver
diff --git a/web/app/cad/craft/schema/types/arrayType.ts b/web/app/cad/craft/schema/types/arrayType.ts
index a8df2004..05cdaea5 100644
--- a/web/app/cad/craft/schema/types/arrayType.ts
+++ b/web/app/cad/craft/schema/types/arrayType.ts
@@ -11,6 +11,10 @@ export interface ArrayTypeSchema extends BaseSchemaField {
min: number;
max: number;
+
+ defaultValue: {
+ usePreselection: boolean;
+ }
}
export const ArrayType: Type = {
diff --git a/web/app/cad/craft/schema/types/entityType.ts b/web/app/cad/craft/schema/types/entityType.ts
index afed12c5..effbf7b0 100644
--- a/web/app/cad/craft/schema/types/entityType.ts
+++ b/web/app/cad/craft/schema/types/entityType.ts
@@ -10,7 +10,10 @@ export interface EntityTypeSchema extends BaseSchemaField {
allowedKinds: EntityKind[];
- initializeBySelection: boolean | number;
+ defaultValue?: {
+ usePreselection: boolean;
+ preselectionIndex: number;
+ }
}
export const EntityType: Type = {
diff --git a/web/app/cad/mdf/mdfIconResolver.tsx b/web/app/cad/craft/ui/iconResolver.tsx
similarity index 88%
rename from web/app/cad/mdf/mdfIconResolver.tsx
rename to web/app/cad/craft/ui/iconResolver.tsx
index 742921ae..4dd02e2f 100644
--- a/web/app/cad/mdf/mdfIconResolver.tsx
+++ b/web/app/cad/craft/ui/iconResolver.tsx
@@ -4,7 +4,7 @@ import React from 'react';
import { AiOutlineQuestion } from 'react-icons/ai';
import { IconType } from 'react-icons/lib';
-export function resolveMDFIcon(iconDef: IconDeclaration | IconType) {
+export function resolveIcon(iconDef: IconDeclaration | IconType) {
if (iconDef.iconType || iconDef.iconSet) {
return (props) =>
} else {
diff --git a/web/app/cad/craft/wizard/wizardSelectionPlugin.ts b/web/app/cad/craft/wizard/wizardSelectionPlugin.ts
index 187e5b2a..5879aa1a 100644
--- a/web/app/cad/craft/wizard/wizardSelectionPlugin.ts
+++ b/web/app/cad/craft/wizard/wizardSelectionPlugin.ts
@@ -111,14 +111,15 @@ function createPickHandlerFromSchema(wizCtx: WizardContext) {
function deselectIfNeeded(id) {
for (let entityRef of schemaIndex.entities) {
- const val = wizCtx.readParam(entityRef.field.path);
+ let val = wizCtx.readParam(entityRef.field.path);
if (val === id) {
update(entityRef.field.path, undefined, entityRef.field.flattenedPath);
return true;
} else if (Array.isArray(val)) {
let index = val.indexOf(id);
if (index !== -1) {
- update(entityRef.field.path, val.splice(index, 1), entityRef.field.flattenedPath);
+ val = val.slice(index, 1);
+ update(entityRef.field.path, val, entityRef.field.flattenedPath);
return true;
}
}
diff --git a/web/app/cad/icons/DeclarativeIcon.tsx b/web/app/cad/icons/DeclarativeIcon.tsx
index 65876130..c05f6f0c 100644
--- a/web/app/cad/icons/DeclarativeIcon.tsx
+++ b/web/app/cad/icons/DeclarativeIcon.tsx
@@ -8,12 +8,12 @@ interface IconRenderProps {
size: IconSize
}
-export function DeclaredIcon(props: IconRenderProps & IconDeclaration & React.HTMLAttributes) {
+export function DeclaredIcon({iconSet, iconType, ...props}: IconRenderProps & IconDeclaration & React.HTMLAttributes) {
- if (props.iconSet) {
- return
+ if (iconSet) {
+ return
} else {
- return
+ return
}
}
diff --git a/web/app/cad/icons/IconDeclaration.ts b/web/app/cad/icons/IconDeclaration.ts
index 628f31cc..373669e9 100644
--- a/web/app/cad/icons/IconDeclaration.ts
+++ b/web/app/cad/icons/IconDeclaration.ts
@@ -4,7 +4,7 @@ export enum IconSize {
small = 'small',
medium = 'medium',
large = 'large'
-};
+}
export interface IconSetDef {
iconType: IconType;
diff --git a/web/app/cad/mdf/mdf.ts b/web/app/cad/mdf/declarativeFormLoader.ts
similarity index 52%
rename from web/app/cad/mdf/mdf.ts
rename to web/app/cad/mdf/declarativeFormLoader.ts
index 39c6e82d..e4bc32b1 100644
--- a/web/app/cad/mdf/mdf.ts
+++ b/web/app/cad/mdf/declarativeFormLoader.ts
@@ -1,54 +1,24 @@
-import {IconDeclaration} from "cad/icons/IconDeclaration";
-import {CoreContext} from "context";
-import {IconType} from "react-icons";
-import {OperationResult} from "../craft/craftPlugin";
-import {OperationDescriptor} from "../craft/operationPlugin";
-import {resolveMDFIcon} from "./mdfIconResolver";
import {OperationSchema} from "cad/craft/schema/schema";
import {
DynamicWidgetProps,
FieldWidgetProps,
FormDefinition,
isContainerWidgetProps,
- isFieldWidgetProps, isSubFormWidgetProps,
+ isFieldWidgetProps,
+ isSubFormWidgetProps,
UIDefinition
} from "cad/mdf/ui/uiDefinition";
import {uiDefinitionToReact} from "cad/mdf/ui/render";
import {ComponentLibrary, DynamicComponents} from "cad/mdf/ui/componentRegistry";
-export interface MDFCommand {
- id: string;
- label: string;
- info: string;
- icon: IconType | IconDeclaration;
- run: (request: R, opContext: CoreContext) => OperationResult | Promise;
- paramsInfo: (params: R) => string,
- mutualExclusiveFields?: string[],
- form: FormDefinition
-}
-
-export function loadMDFCommand(mdfCommand: MDFCommand): OperationDescriptor {
+export function loadDeclarativeForm(form: FormDefinition) {
const uiDefinition: UIDefinition = {
type: 'group',
- content: mdfCommand.form
+ content: form
}
const derivedSchema = deriveSchema(uiDefinition);
return {
- id: mdfCommand.id,
- label: mdfCommand.label,
- icon: resolveMDFIcon(mdfCommand.icon),
- info: mdfCommand.info,
- paramsInfo: mdfCommand.paramsInfo,
- onParamsUpdate: (params, name, value) => {
- if (mdfCommand.mutualExclusiveFields) {
- handleMutualExclusiveFields(mdfCommand.mutualExclusiveFields, params, name, value);
- }
- },
- run: mdfCommand.run,
- // actionParams: {
- // ...requiresFaceSelection(1)
- // },
form: uiDefinitionToReact(uiDefinition),
schema: derivedSchema
}
@@ -95,14 +65,3 @@ export function deriveSchema(uiDefinition: UIDefinition): OperationSchema {
return schema;
}
-
-
-export function handleMutualExclusiveFields(mutualExclusiveFields, params, name, value) {
- if (mutualExclusiveFields.includes(name)) {
- mutualExclusiveFields.forEach(param => {
- if (param !== name) {
- delete params[param];
- }
- })
- }
-}
\ No newline at end of file
diff --git a/web/app/cad/mdf/mdfExtrudeExample.ts b/web/app/cad/mdf/mdfExtrudeExample.ts
deleted file mode 100644
index a2a163f7..00000000
--- a/web/app/cad/mdf/mdfExtrudeExample.ts
+++ /dev/null
@@ -1,65 +0,0 @@
-import { roundValueForPresentation as r } from '../craft/operationHelper';
-
-
-export const MDF_EXTRUDE_EXAMPLE = {
- id: 'EXTRUDE',
- label: 'Extrude',
- icon: 'img/cad/extrude',
- info: 'extrudes 2D sketch',
- paramsInfo: ({ value }) => `(${r(value)})`,
- mutualExclusiveFields: ['datumAxisVector', 'edgeVector', 'sketchSegmentVector'],
- run: (params, ctx) => {
- return ctx.craftEngine.cutExtrude(false, params);
- },
- schema: {
- value: {
- type: 'number',
- defaultValue: 50,
- label: 'height'
- },
- wierdField: {
- type: 'number',
- defaultValue: 50,
- label: 'weird field'
- },
- prism: {
- type: 'number',
- min: 0,
- defaultValue: 1
- },
- angle: {
- type: 'number',
- defaultValue: 0
- },
- rotation: {
- type: 'number',
- defaultValue: 0
- },
- face: {
- type: 'face',
- initializeBySelection: 0
- },
- datumAxisVector: {
- type: 'datumAxis',
- optional: true,
- label: 'datum axis'
- },
- edgeVector: {
- type: 'edge',
- optional: true,
- label: 'edge',
- accept: edge => edge.brepEdge.curve.degree === 1
- },
- sketchSegmentVector: {
- type: 'sketchObject',
- optional: true,
- label: 'sketch segment',
- accept: obj => obj.isSegment
- },
- flip: {
- type: 'boolean',
- defaultValue: false,
- }
-
- }
-}
diff --git a/web/app/cad/mdf/ui/AxisWidget.tsx b/web/app/cad/mdf/ui/AxisWidget.tsx
index 193dde2c..8dabd52d 100644
--- a/web/app/cad/mdf/ui/AxisWidget.tsx
+++ b/web/app/cad/mdf/ui/AxisWidget.tsx
@@ -40,7 +40,6 @@ export interface AxisWidgetProps extends FieldBasicProps {
type: 'axis';
- resolve: ValueResolver;
}
const ENTITY_CAPTURE = [EntityKind.EDGE, EntityKind.SKETCH_OBJECT, EntityKind.DATUM_AXIS, EntityKind.FACE];
@@ -65,6 +64,7 @@ export const AxisBasedWidgetDefinition = (props: AxisBasedWidgetProps) => ({
type: 'sub-form',
name: props.name,
resolve: props.resolve,
+ optional: props.optional,
content: [
{
name: "vectorEntity",
diff --git a/web/app/cad/mdf/ui/ChoiceWidget.tsx b/web/app/cad/mdf/ui/ChoiceWidget.tsx
index 0e24a2ec..62af6f6d 100644
--- a/web/app/cad/mdf/ui/ChoiceWidget.tsx
+++ b/web/app/cad/mdf/ui/ChoiceWidget.tsx
@@ -1,9 +1,10 @@
import {ComboBoxField, NumberField} from "cad/craft/wizard/components/form/Fields";
import React from "react";
-import {OperationSchema} from "cad/craft/schema/schema";
+import {flattenPath, OperationSchema} from "cad/craft/schema/schema";
import {FieldBasicProps, fieldToSchemaGeneric} from "cad/mdf/ui/field";
import {Types} from "cad/craft/schema/types";
import {ComboBoxOption} from "ui/components/controls/ComboBoxControl";
+import {FormContext, FormContextData} from "cad/craft/wizard/components/form/Form";
export interface ChoiceWidgetProps extends FieldBasicProps {
@@ -17,9 +18,22 @@ export interface ChoiceWidgetProps extends FieldBasicProps {
export function ChoiceWidget(props: ChoiceWidgetProps) {
if (!props.style || props.style === 'dropdown') {
- return
- {props.values.map(value => {value})}
-
+
+ return
+ {
+ (ctx: FormContextData) => {
+ const value = ctx.readParam(props.name);
+ let nonExistent = null;
+ if (!props.values.includes(value as any)) {
+ nonExistent = {value ? value+'' : ''}
+ }
+ return
+ {nonExistent}
+ {props.values.map(value => {value})}
+ ;
+ }
+ }
+
} else {
throw 'implement me';
}
diff --git a/web/app/cad/mdf/ui/SelectionWidget.tsx b/web/app/cad/mdf/ui/SelectionWidget.tsx
index aaba4812..c2721398 100644
--- a/web/app/cad/mdf/ui/SelectionWidget.tsx
+++ b/web/app/cad/mdf/ui/SelectionWidget.tsx
@@ -30,7 +30,6 @@ SelectionWidget.propsToSchema = (props: SelectionWidgetProps) => {
let value = {
type: Types.entity,
allowedKinds: props.capture,
- initializeBySelection: true,
} as SchemaField;
if (props.multi) {
diff --git a/web/app/cad/part/partOperationsPlugin.js b/web/app/cad/part/partOperationsPlugin.js
index aefe7660..95be76ab 100644
--- a/web/app/cad/part/partOperationsPlugin.js
+++ b/web/app/cad/part/partOperationsPlugin.js
@@ -1,4 +1,3 @@
-import extrudeOperation from '../craft/cutExtrude/extrudeOperation';
import cutOperation from '../craft/cutExtrude/cutOperation';
import planeOperation from '../craft/primitives/simplePlane/simplePlaneOperation';
import filletOperation from '../craft/fillet/filletOperation';
@@ -15,32 +14,31 @@ import coneOperation from '../craft/primitives/cone/coneOperation';
import spatialCurveOperation from '../craft/spatialCurve/spatialCurveOperation';
import loftOperation from '../craft/loft/loftOperation';
import {intersectionOperation, subtractOperation, unionOperation} from '../craft/boolean/booleanOperation';
-import { loadMDFCommand } from '../mdf/mdf';
import WorkbenchRegistry from 'workbenches/registry';
export function activate({services}) {
- services.operation.registerOperations([
- planeOperation,
- boxOperation,
- // extrudeOperation,
- cutOperation,
- revolveOperation,
- filletOperation,
- createDatumOperation,
- moveDatumOperation,
- rotateDatumOperation,
- datumOperation,
- sphereOperation,
- cylinderOperation,
- torusOperation,
- coneOperation,
- spatialCurveOperation,
- loftOperation,
- intersectionOperation,
- subtractOperation,
- unionOperation,
- ]);
- WorkbenchRegistry.forEach(w => {
- services.operation.registerOperations(w.features.map(loadMDFCommand));
- });
+ services.operation.registerOperations([
+ planeOperation,
+ boxOperation,
+ // extrudeOperation,
+ cutOperation,
+ revolveOperation,
+ filletOperation,
+ createDatumOperation,
+ moveDatumOperation,
+ rotateDatumOperation,
+ datumOperation,
+ sphereOperation,
+ cylinderOperation,
+ torusOperation,
+ coneOperation,
+ spatialCurveOperation,
+ loftOperation,
+ intersectionOperation,
+ subtractOperation,
+ unionOperation,
+ ]);
+ WorkbenchRegistry.forEach(w => {
+ services.operation.registerOperations(w.features);
+ });
}
\ No newline at end of file