localize workingParams to wizard context

This commit is contained in:
Val Erastov 2018-12-10 23:14:08 -08:00
parent 1df6de49a5
commit b4305c5a16
7 changed files with 154 additions and 153 deletions

View file

@ -1 +1,18 @@
export const NOOP = () => {};
export const NOOP = () => {};
export function createFunctionList() {
const fnList = [];
const add = fn => fnList.push(fn);
const call = () => {
fnList.forEach(fn => {
try {
fn();
} catch(e) {
console.error(e);
}
});
};
return {
add, call
}
}

View file

@ -8,27 +8,26 @@ import ls from './Wizard.less';
import CadError from '../../../../utils/errors';
import {FormContext} from './form/Form';
import connect from 'ui/connect';
import mapContext from 'ui/mapContext';
import {combine} from 'lstream';
@connect(streams => streams.wizard.workingRequest)
@mapContext(ctx => ({
updateParam: (name, value) => {
let workingRequest$ = ctx.streams.wizard.workingRequest;
if (workingRequest$.value.params && workingRequest$.value.type) {
workingRequest$.mutate(data => {
data.params[name] = value;
data.state.activeParam = name;
})
}
},
setActiveParam: name => ctx.streams.wizard.workingRequest.mutate(data => data.state && (data.state.activeParam = name))
}))
@connect((streams, props) => combine(props.context.workingRequest$, props.context.state$)
.map(([workingRequest, state]) => ({
...workingRequest,
activeParam: state.activeParam
})))
export default class Wizard extends React.Component {
state = {
hasError: false,
};
updateParam = (name, value) => {
this.props.context.updateParams(params => params[name] = value);
};
setActiveParam = param => {
this.props.context.updateState(state => state.activeParam = param);
};
componentDidCatch() {
this.setState({hasInternalError: true});
@ -39,24 +38,16 @@ export default class Wizard extends React.Component {
return <span>operation error</span>;
}
let {left, type, params, state, resolveOperation, updateParam, setActiveParam} = this.props;
if (!type) {
return null;
}
let operation = resolveOperation(type);
if (!operation) {
console.error('unknown operation ' + type);
return null;
}
let {left, type, params, state, context} = this.props;
let operation = context.operation;
let title = (operation.label || type).toUpperCase();
let formContext = {
data: params,
activeParam: state.activeParam,
setActiveParam,
updateParam
activeParam: this.props.activeParam,
setActiveParam: this.setActiveParam,
updateParam: this.updateParam
};
let Form = operation.form;
@ -127,7 +118,7 @@ export default class Wizard extends React.Component {
let {code, userMessage, kind} = error;
printError = !code;
if (CadError.ALGORITMTHM_ERROR_KINDS.includes(kind)) {
stateUpdate.algorithmError = true
stateUpdate.algorithmError = true;
}
if (code && kind === CadError.KIND.INTERNAL_ERROR) {
console.warn('Operation Error Code: ' + code);

View file

@ -3,23 +3,21 @@ import Wizard from './Wizard';
import connect from 'ui/connect';
import decoratorChain from 'ui/decoratorChain';
import mapContext from 'ui/mapContext';
import {finishHistoryEditing} from '../../craftHistoryUtils';
function WizardManager({type, changingHistory, resolve, cancel, stepHistory, insertOperation, cancelHistoryEdit, applyWorkingRequest}) {
if (!type) {
function WizardManager({wizardContext, type, changingHistory, cancel, cancelHistoryEdit, applyWorkingRequest}) {
if (!wizardContext) {
return null;
}
return <Wizard resolveOperation={resolve}
return <Wizard key={wizardContext.ID}
context={wizardContext}
onCancel={changingHistory ? cancelHistoryEdit : cancel}
onOK={applyWorkingRequest} />
}
export default decoratorChain(
connect(streams => streams.wizard.effectiveOperation),
mapContext((ctx, props) => ({
connect(streams => streams.wizard.wizardContext.map(wizardContext => ({wizardContext}))),
mapContext(ctx => ({
cancel: ctx.services.wizard.cancel,
resolve: type => ctx.services.operation.get(type),
cancelHistoryEdit: () => ctx.streams.craft.modifications.update(modifications => finishHistoryEditing(modifications)),
applyWorkingRequest: ctx.services.wizard.applyWorkingRequest
}))
)

View file

@ -1,7 +1,8 @@
import {stream, state} from 'lstream';
import {state} from 'lstream';
import initializeBySchema from '../intializeBySchema';
import {clone, EMPTY_OBJECT} from 'gems/objects';
import materializeParams from '../materializeParams';
import {createFunctionList} from 'gems/func';
export function activate(ctx) {
@ -46,12 +47,12 @@ export function activate(ctx) {
gotoEditHistoryModeIfNeeded(mod);
});
streams.wizard.workingRequestChanged = stream();
streams.wizard.workingRequest = streams.wizard.effectiveOperation.map(opRequest => {
let request = EMPTY_OBJECT;
streams.wizard.wizardContext = streams.wizard.effectiveOperation.map(opRequest => {
let wizCtx = null;
if (opRequest.type) {
let operation = ctx.services.operation.get(opRequest.type);
let params;
if (opRequest.changingHistory) {
params = clone(opRequest.params)
@ -61,34 +62,45 @@ export function activate(ctx) {
applyOverrides(params, opRequest.initialOverrides);
}
}
request = {
let workingRequest$ = state({
type: opRequest.type,
params,
state: {}
};
}
streams.wizard.workingRequestChanged.next(request);
return request
}).remember(EMPTY_OBJECT);
streams.wizard.materializedWorkingRequest = streams.wizard.workingRequest.map(req => {
if (req.type) {
let operation = ctx.services.operation.get(req.type);
let params = {};
let errors = [];
materializeParams(ctx.services, req.params, operation.schema, params, errors, []);
if (errors.length !== 0) {
console.log(errors);
return INVALID_REQUEST;
}
return {
type: req.type,
params
});
let materializedWorkingRequest$ = workingRequest$.map(req => {
let params = {};
let errors = [];
materializeParams(ctx.services, req.params, operation.schema, params, errors, []);
if (errors.length !== 0) {
console.log(errors);
return INVALID_REQUEST;
}
return {
type: req.type,
params
};
}).filter(r => r !== INVALID_REQUEST).remember();
const state$ = state({});
const updateParams = mutator => workingRequest$.mutate(data => mutator(data.params));
const updateState = mutator => state$.mutate(state => mutator(state));
const disposerList = createFunctionList();
wizCtx = {
workingRequest$, materializedWorkingRequest$, state$, operation, updateParams, updateState,
addDisposer: disposerList.add,
dispose: disposerList.call,
ID: ++REQUEST_COUNTER,
};
}
return EMPTY_OBJECT;
}).filter(r => r !== INVALID_REQUEST).remember();
return wizCtx;
}).remember(null);
streams.wizard.wizardContext.pairwise().attach(([oldContext, newContext]) => {
if (oldContext) {
oldContext.dispose();
}
});
services.wizard = {
open: (type, initialOverrides) => {
@ -104,7 +116,7 @@ export function activate(ctx) {
},
applyWorkingRequest: () => {
let {type, params} = streams.wizard.workingRequest.value;
let {type, params} = streams.wizard.wizardContext.value.workingRequest$.value;
let request = clone({type, params});
if (streams.wizard.insertOperation.value.type) {
ctx.services.craft.modify(request, () => streams.wizard.insertOperation.value = EMPTY_OBJECT);
@ -119,4 +131,5 @@ function applyOverrides(params, initialOverrides) {
Object.assign(params, initialOverrides);
}
const INVALID_REQUEST = {};
const INVALID_REQUEST = {};
let REQUEST_COUNTER = 0;

View file

@ -1,37 +1,34 @@
import {DATUM, EDGE, FACE, SHELL, SKETCH_OBJECT} from '../../scene/entites';
import {EDGE, FACE, SHELL, SKETCH_OBJECT} from '../../scene/entites';
export function activate(ctx) {
const wizardPickHandler = createPickHandlerFromSchema(ctx);
ctx.streams.wizard.workingRequestChanged.attach(({type, params}) => {
ctx.streams.wizard.wizardContext.attach(wizCtx => {
ctx.services.marker.clear();
if (type) {
if (wizCtx) {
const wizardPickHandler = createPickHandlerFromSchema(wizCtx);
ctx.services.pickControl.setPickHandler(wizardPickHandler);
wizCtx.workingRequest$.attach(({type, params}) => {
const marker = ctx.services.marker;
marker.startSession();
let {schema, schemaIndex} = wizCtx.operation;
schemaIndex.entityParams.forEach(param => {
let color = schema[param].markColor;
let val = params[param];
let entity = schemaIndex.entitiesByParam[param];
if (Array.isArray(val)) {
val.forEach(id => marker.mark(entity, id, color));
} else {
if (val) {
marker.mark(entity, val, color);
}
}
});
marker.commit();
});
} else {
ctx.services.pickControl.setPickHandler(null);
}
});
ctx.streams.wizard.workingRequest.attach(({type, params}) => {
const marker = ctx.services.marker;
marker.startSession();
if (type && params) {
let {schema, schemaIndex} = ctx.services.operation.get(type);
schemaIndex.entityParams.forEach(param => {
let color = schema[param].markColor;
let val = params[param];
let entity = schemaIndex.entitiesByParam[param];
if (Array.isArray(val)) {
val.forEach(id => marker.mark(entity, id, color));
} else {
if (val) {
marker.mark(entity, val, color);
}
}
});
}
marker.commit();
});
}
const singleUpdater = (params, param, id) => params[param] = id;
@ -45,11 +42,20 @@ const arrayUpdater = (params, param, id) => {
}
};
function createPickHandlerFromSchema(ctx) {
function createPickHandlerFromSchema(wizCtx) {
function update(paramsMutator, paramToMakeActive) {
wizCtx.updateParams(paramsMutator);
wizCtx.updateState(state => {
state.activeParam = paramToMakeActive;
});
}
return model => {
const modelType = model.TYPE;
const {type: opType, state, params} = ctx.streams.wizard.workingRequest.value;
let {schema, schemaIndex} = ctx.services.operation.get(opType);
const params = wizCtx.workingRequest$.value.params;
const state = wizCtx.state$.value;
let {schema, schemaIndex} = wizCtx.operation;
const {entitiesByType, entitiesByParam, entityParams} = schemaIndex;
const activeMd = state.activeParam && schema[state.activeParam];
@ -58,15 +64,14 @@ function createPickHandlerFromSchema(ctx) {
function select(param, entity, md, id) {
const updater = md.type === 'array' ? arrayUpdater : singleUpdater;
let paramToMakeActive = getNextActiveParam(param, md);
ctx.streams.wizard.workingRequest.mutate(r => {
updater(r.params, param, id);
r.state.activeParam = paramToMakeActive;
});
update(params => {
updater(params, param, id);
}, paramToMakeActive);
}
function getNextActiveParam(currParam, currMd) {
if (currMd.type !== 'array') {
let entityGroup = entitiesByType[currMd.type];
let entityGroup = entitiesByType[activeEntity];
if (entityGroup) {
const index = entityGroup.indexOf(currParam);
const nextIndex = (index + 1) % entityGroup.length;
@ -93,23 +98,20 @@ function createPickHandlerFromSchema(ctx) {
for (let param of entityParams) {
let val = params[param];
if (val === id) {
ctx.streams.wizard.workingRequest.mutate(r => {
r.params[param] = undefined;
r.state.activeParam = param;
});
update(params => {
params[param] = undefined;
}, param);
return true;
} else if (Array.isArray(val)) {
let index = val.indexOf(id);
if (index !== -1) {
ctx.streams.wizard.workingRequest.mutate(r => {
r.params[param].splice(index, 1);
r.state.activeParam = param;
});
update(params => {
params[param].splice(index, 1)
}, param);
return true;
}
}
}
}
if (deselectIfNeeded(model.id)) {
@ -142,12 +144,6 @@ function createPickHandlerFromSchema(ctx) {
} else {
selectToFirst(EDGE, model.id);
}
} else if (modelType === DATUM) {
if (activeEntity === DATUM) {
selectActive(model.id);
} else {
selectToFirst(DATUM, model.id);
}
}
return false;
};

View file

@ -3,46 +3,29 @@ import {createPreviewer} from './scenePreviewer';
export function activate(ctx) {
let {streams, services} = ctx;
const updateParams = mutator => streams.wizard.workingRequest.mutate(data => mutator(data.params));
let previewContext = {
operation: null,
previewer: null
};
streams.wizard.materializedWorkingRequest.attach(({type, params}) => {
if (!type) {
if (previewContext.previewer) {
previewContext.previewer.dispose();
previewContext.previewer = null;
previewContext.operation = null;
ctx.services.viewer.requestRender();
}
streams.wizard.wizardContext.attach(wizCtx => {
if (!wizCtx) {
return;
}
if (type !== previewContext.operation) {
if (previewContext.previewer != null) {
previewContext.previewer.dispose();
let {operation, materializedWorkingRequest$} = wizCtx;
if (operation.previewGeomProvider || operation.previewer) {
let previewer = null;
materializedWorkingRequest$.attach(({type, params}) => {
if (previewer === null) {
if (operation.previewGeomProvider) {
previewer = createPreviewer(operation.previewGeomProvider, services, params);
} else if (operation.previewer) {
previewer = operation.previewer(ctx, params, wizCtx.updateParams);
}
wizCtx.addDisposer(() => {
previewer.dispose();
ctx.services.viewer.requestRender();
});
} else {
previewer.update(params);
}
ctx.services.viewer.requestRender();
previewContext.previewer = null;
}
let operation = services.operation.get(type);
if (operation.previewGeomProvider) {
previewContext.previewer = createPreviewer(operation.previewGeomProvider, services, params);
ctx.services.viewer.requestRender();
} else if (operation.previewer) {
previewContext.previewer = operation.previewer(ctx, params, updateParams);
ctx.services.viewer.requestRender();
} else {
previewContext.previewer = null;
}
previewContext.operation = type;
} else {
if (previewContext.previewer) {
previewContext.previewer.update(params);
ctx.services.viewer.requestRender();
}
});
}
});
}

View file

@ -21,6 +21,9 @@ function createMarker(findEntity, requestRender) {
function doMark(entity, id, color) {
let mObj = findEntity(entity, id);
if (!mObj) {
throw 'illegal state';
}
marked.set(id, mObj);
mObj.ext.view && mObj.ext.view.mark(color);
}