mirror of
https://github.com/xibyte/jsketcher
synced 2025-12-06 16:33:15 +01:00
174 lines
No EOL
5.4 KiB
JavaScript
174 lines
No EOL
5.4 KiB
JavaScript
import {state} from 'lstream';
|
|
import initializeBySchema from '../schema/initializeBySchema';
|
|
import {clone, EMPTY_OBJECT} from 'gems/objects';
|
|
import materializeParams from '../schema/materializeParams';
|
|
import {createFunctionList} from 'gems/func';
|
|
import {onParamsUpdate} from '../cutExtrude/extrudeOperation';
|
|
import {propsChangeTracker} from 'lstream/utils';
|
|
import {OperationSchema, schemaIterator} from "cad/craft/schema/schema";
|
|
|
|
export function activate(ctx) {
|
|
|
|
let {streams, services} = ctx;
|
|
|
|
streams.wizard = {};
|
|
|
|
streams.wizard.insertOperation = state(EMPTY_OBJECT);
|
|
|
|
streams.wizard.effectiveOperation = state(EMPTY_OBJECT);
|
|
|
|
streams.wizard.insertOperation.attach(insertOperationReq => {
|
|
if (insertOperationReq.type) {
|
|
let type = insertOperationReq.type;
|
|
let operation = ctx.services.operation.get(type);
|
|
streams.wizard.effectiveOperation.value = {
|
|
type: operation.id,
|
|
initialOverrides: insertOperationReq.initialOverrides,
|
|
changingHistory: false
|
|
};
|
|
}
|
|
});
|
|
|
|
function gotoEditHistoryModeIfNeeded({pointer, history, hints}) {
|
|
if (pointer !== history.length - 1) {
|
|
let {type, params} = history[pointer + 1];
|
|
streams.wizard.effectiveOperation.value = {
|
|
type,
|
|
params,
|
|
noWizardFocus: hints && hints.noWizardFocus,
|
|
changingHistory: true
|
|
};
|
|
} else {
|
|
streams.wizard.effectiveOperation.value = EMPTY_OBJECT;
|
|
}
|
|
|
|
}
|
|
|
|
streams.craft.modifications.attach(mod => {
|
|
if (streams.wizard.insertOperation.value.type) {
|
|
return;
|
|
}
|
|
gotoEditHistoryModeIfNeeded(mod);
|
|
});
|
|
|
|
streams.wizard.wizardContext = streams.wizard.effectiveOperation.map(opRequest => {
|
|
let wizCtx = null;
|
|
if (opRequest.type) {
|
|
|
|
let operation = ctx.services.operation.get(opRequest.type);
|
|
|
|
let params;
|
|
let {changingHistory, noWizardFocus} = opRequest;
|
|
if (changingHistory) {
|
|
params = flattenParams(opRequest.params, operation.schema);
|
|
} else {
|
|
params = initializeBySchema(operation.workingSchema, ctx);
|
|
if (opRequest.initialOverrides) {
|
|
applyOverrides(params, opRequest.initialOverrides);
|
|
}
|
|
}
|
|
|
|
let workingRequest$ = state({
|
|
type: opRequest.type,
|
|
params
|
|
});
|
|
|
|
let materializedWorkingRequest$ = workingRequest$.map(req => {
|
|
let params = {};
|
|
let errors = [];
|
|
let unflatten = unflattenParams(req.params, operation.schema);
|
|
materializeParams(ctx, unflatten, operation.schema, params, errors);
|
|
if (errors.length !== 0) {
|
|
return INVALID_REQUEST;
|
|
}
|
|
return {
|
|
type: req.type,
|
|
params
|
|
};
|
|
}).remember(INVALID_REQUEST).filter(r => r !== INVALID_REQUEST).throttle(500);
|
|
const state$ = state({});
|
|
const updateParams = mutator => workingRequest$.mutate(data => mutator(data.params));
|
|
const updateState = mutator => state$.mutate(state => mutator(state));
|
|
const updateParam = (name, value) => {
|
|
updateParams(params => {
|
|
if (operation.onParamsUpdate) {
|
|
operation.onParamsUpdate(params, name, value, params[name]);
|
|
}
|
|
params[name] = value;
|
|
});
|
|
};
|
|
|
|
const disposerList = createFunctionList();
|
|
wizCtx = {
|
|
workingRequest$, materializedWorkingRequest$, state$, updateParams, updateParam, updateState,
|
|
operation, changingHistory, noWizardFocus,
|
|
addDisposer: disposerList.add,
|
|
dispose: disposerList.call,
|
|
ID: ++REQUEST_COUNTER,
|
|
};
|
|
}
|
|
return wizCtx;
|
|
}).remember(null);
|
|
|
|
streams.wizard.wizardContext.pairwise().attach(([oldContext, newContext]) => {
|
|
if (oldContext) {
|
|
oldContext.dispose();
|
|
}
|
|
});
|
|
|
|
services.wizard = {
|
|
|
|
open: (type, initialOverrides) => {
|
|
streams.wizard.insertOperation.value = {
|
|
type,
|
|
initialOverrides
|
|
};
|
|
},
|
|
|
|
cancel: () => {
|
|
streams.wizard.insertOperation.value = EMPTY_OBJECT;
|
|
gotoEditHistoryModeIfNeeded(streams.craft.modifications.value);
|
|
},
|
|
|
|
applyWorkingRequest: () => {
|
|
let wizCtx = streams.wizard.wizardContext.value;
|
|
let {type, params} = wizCtx.workingRequest$.value;
|
|
let request = {
|
|
type,
|
|
params: unflattenParams(params, wizCtx.operation.schema)
|
|
};
|
|
const setError = error => streams.wizard.wizardContext.mutate(ctx => ctx.state$.mutate(state => state.error = error));
|
|
if (streams.wizard.insertOperation.value.type) {
|
|
ctx.services.craft.modify(request, () => streams.wizard.insertOperation.value = EMPTY_OBJECT, setError );
|
|
} else {
|
|
ctx.services.craft.modifyInHistoryAndStep(request, () => streams.wizard.effectiveOperation.value = EMPTY_OBJECT, setError);
|
|
}
|
|
},
|
|
|
|
isInProgress: () => streams.wizard.wizardContext.value !== null
|
|
};
|
|
}
|
|
|
|
function flattenParams(params, originalSchema) {
|
|
const flatParams = {};
|
|
schemaIterator(originalSchema, (path, flattenedPath, schemaField) => {
|
|
flatParams[flattenedPath] = _.get(params, path);
|
|
});
|
|
return flatParams;
|
|
}
|
|
|
|
function unflattenParams(params, originalSchema) {
|
|
const unflatParams = {};
|
|
schemaIterator(originalSchema, (path, flattenedPath, schemaField) => {
|
|
_.set(unflatParams, path, params[flattenedPath]);
|
|
});
|
|
return unflatParams;
|
|
}
|
|
|
|
|
|
function applyOverrides(params, initialOverrides) {
|
|
Object.assign(params, initialOverrides);
|
|
}
|
|
|
|
const INVALID_REQUEST = {};
|
|
let REQUEST_COUNTER = 0; |