diff --git a/web/app/cad/actions/actionSystemPlugin.js b/web/app/cad/actions/actionSystemPlugin.js deleted file mode 100644 index 21e23aae..00000000 --- a/web/app/cad/actions/actionSystemPlugin.js +++ /dev/null @@ -1,94 +0,0 @@ -import {enableAnonymousActionHint} from './anonHint'; -import * as stream from 'lstream'; -import {LOG_FLAGS} from '../logFlags'; - -export function activate(context) { - - let {streams} = context; - - streams.action = { - appearance: {}, - state: {}, - hint: stream.state(null) - }; - - let runners = {}; - - let showAnonymousActionHint = enableAnonymousActionHint(context); - - function run(id, data) { - let state = streams.action.state[id].value; - let runner = runners[id]; - if (!state||!runner) { - console.warn('request to run nonexistent action') - return; - } - if (state.enabled) { - if (LOG_FLAGS.ACTION_RUN) { - console.log("RUNNING ACTION: " + id); - } - runner(context, data); - } else { - showAnonymousActionHint(id); - } - } - - function register(action) { - streams.action.appearance[action.id] = stream.state(action.appearance); - - runners[action.id] = action.invoke; - - let initialState = { - hint: '', - enabled: true, - visible: true - }; - - let actionStateStream = stream.state(initialState); - streams.action.state[action.id] = actionStateStream; - - if (action.update && action.listens) { - - action.listens(streams).attach(data => { - actionStateStream.mutate(v => { - v.hint = ''; - v.enabled = true; - v.visible = true; - action.update(v, data, context) - return v; - }) - }); - } - } - - function registerAction(action) { - register(action); - } - - function registerActions(actions) { - actions.forEach(action => register(action)); - } - - function showHintFor(request) { - if (request) { - let {actionId, x, y, requester} = request; - let actionState = streams.action.state[actionId].value; - let actionAppearance = streams.action.appearance[actionId].value; - if (actionState && actionAppearance) { - streams.action.hint.value = { - actionId, x, y, requester, - info: actionAppearance.info, - hint: actionState.hint - }; - } - } else { - if (streams.action.hint.value !== null) { - streams.action.hint.value = null; - } - } - } - - context.services.action = {run, registerAction, registerActions, showHintFor} -} - - diff --git a/web/app/cad/actions/actionSystemPlugin.ts b/web/app/cad/actions/actionSystemPlugin.ts new file mode 100644 index 00000000..005869d0 --- /dev/null +++ b/web/app/cad/actions/actionSystemPlugin.ts @@ -0,0 +1,165 @@ +import {enableAnonymousActionHint} from './anonHint'; +import * as stream from 'lstream'; +import {state, StateStream, Stream} from 'lstream'; +import {LOG_FLAGS} from '../logFlags'; +import {ApplicationContext} from "context"; +import {IconType} from "react-icons"; + +export function activate(context: ApplicationContext) { + + let {streams} = context; + + + const appearanceStreams: ActionAppearanceStreams = {}; + const stateStreams: ActionStateStreams = {}; + const hint$: StateStream = state(null); + + streams.action = { + appearance: appearanceStreams, + state: stateStreams, + hint: hint$ + }; + + let runners = {}; + + let showAnonymousActionHint = enableAnonymousActionHint(context); + + function run(id: string, data: any): void { + let state = streams.action.state[id].value; + let runner = runners[id]; + if (!state||!runner) { + console.warn('request to run nonexistent action'); + return; + } + if (state.enabled) { + if (LOG_FLAGS.ACTION_RUN) { + console.log("RUNNING ACTION: " + id); + } + runner(context, data); + } else { + showAnonymousActionHint(id); + } + } + + function register(action: ActionDefinition): void { + streams.action.appearance[action.id] = stream.state(action.appearance); + + runners[action.id] = action.invoke; + + let initialState = { + hint: '', + enabled: true, + visible: true + }; + + let actionStateStream = stream.state(initialState); + streams.action.state[action.id] = actionStateStream; + + if (action.update && action.listens) { + + action.listens(context).attach(data => { + actionStateStream.mutate(v => { + v.hint = ''; + v.enabled = true; + v.visible = true; + action.update(v, data, context); + return v; + }) + }); + } + } + + function registerAction(action: ActionDefinition): void { + register(action); + } + + function registerActions(actions: ActionDefinition[]): void { + actions.forEach(action => register(action)); + } + + function showHintFor(request: HintRequest) { + if (request) { + let {actionId, x, y, requester} = request; + let actionState = streams.action.state[actionId].value; + let actionAppearance = streams.action.appearance[actionId].value; + if (actionState && actionAppearance) { + streams.action.hint.value = { + actionId, x, y, requester, + info: actionAppearance.info, + hint: actionState.hint + }; + } + } else { + if (streams.action.hint.value !== null) { + streams.action.hint.value = null; + } + } + } + + context.actionService = {run, registerAction, registerActions, showHintFor, appearanceStreams, stateStreams, hint$}; + + context.services.action = context.actionService; +} + + +export interface ActionAppearanceStreams { + [actionId: string]: StateStream +} + +export interface ActionStateStreams { + [actionId: string]: StateStream +} + +export interface ActionState { + hint: string, + enabled: boolean, + visible: boolean +} + +export interface HintRequest { + actionId: string; + x: number; + y: number; + requester: any; +} + +export interface Hint extends HintRequest { + info: string; + hint: string; +} + +export interface ActionAppearance { + info: string, + label: string, + icon32?: string, + icon96?: string, + icon?: IconType +} + +export interface ActionDefinition { + id: string, + appearance: ActionAppearance, + invoke: (ApplicationContext, any) => void; + update?: (ActionState, T, ApplicationContext) => void; + listens?: (ApplicationContext) => Stream; +} + +export interface ActionService { + + run(id: string, data: any): void; + registerAction(action: ActionDefinition): void; + registerActions(actions: ActionDefinition[]): void; + showHintFor(request: HintRequest): void; + + appearanceStreams: ActionAppearanceStreams; + stateStreams: ActionStateStreams; + hint$: StateStream; +} + +declare module 'context' { + interface ApplicationContext { + + actionService: ActionService; + } +} +