diff --git a/modules/workbenches/modeler/index.ts b/modules/workbenches/modeler/index.ts index 5980f283..8e090cec 100644 --- a/modules/workbenches/modeler/index.ts +++ b/modules/workbenches/modeler/index.ts @@ -20,6 +20,7 @@ import { PatternLinearOperation } from "./features/patternLinear/patternLinear.o import { PatternRadialOperation } from "./features/patternRadial/patternRadial.operation" //imports of action type commands import { GetVolume } from './actions/getVolume/getVolume.action'; +import {GiCubes} from "react-icons/gi"; export const ModelerWorkspace: WorkbenchConfig = { @@ -55,5 +56,6 @@ export const ModelerWorkspace: WorkbenchConfig = { "CYLINDER", "BOX", "CONE", "SPHERE", "TORUS", "-", "HOLE_TOOL", "-", 'GET_VOLUME', ] - } + }, + icon: GiCubes } \ No newline at end of file diff --git a/modules/workbenches/sheetMetal/index.ts b/modules/workbenches/sheetMetal/index.ts index 25f73d00..5418fb65 100644 --- a/modules/workbenches/sheetMetal/index.ts +++ b/modules/workbenches/sheetMetal/index.ts @@ -1,8 +1,9 @@ -import { WorkbenchConfig } from "cad/workbench/workbenchService"; +import {WorkbenchConfig} from "cad/workbench/workbenchService"; //imports of feature history type commands -import { smTabOperation } from "./features/smTab/smTab.operation"; -import { smFlangeOperation } from "./features/smFlange/smFlange.operation"; +import {smTabOperation} from "./features/smTab/smTab.operation"; +import {smFlangeOperation} from "./features/smFlange/smFlange.operation"; +import {SiKaufland} from "react-icons/si"; //imports of action type commands @@ -27,5 +28,6 @@ export const sheetMetalWorkspace: WorkbenchConfig = { "HOLE_TOOL", "-", "SM_TAB","SM_FLANGE" ] - } + }, + icon: SiKaufland } \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index d3978264..d6524205 100644 --- a/package-lock.json +++ b/package-lock.json @@ -25,7 +25,7 @@ "react": "^16.13.1", "react-color": "^2.19.3", "react-dom": "^16.13.1", - "react-icons": "^4.2.0", + "react-icons": "^4.4.0", "react-toastify": "^5.5.0", "sprintf": "0.1.5", "three": "^0.118.3" @@ -12046,9 +12046,9 @@ } }, "node_modules/react-icons": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.2.0.tgz", - "integrity": "sha512-rmzEDFt+AVXRzD7zDE21gcxyBizD/3NqjbX6cmViAgdqfJ2UiLer8927/QhhrXQV7dEj/1EGuOTPp7JnLYVJKQ==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.4.0.tgz", + "integrity": "sha512-fSbvHeVYo/B5/L4VhB7sBA1i2tS8MkT0Hb9t2H1AVPkwGfVHLJCqyr2Py9dKMxsyM63Eng1GkdZfbWj+Fmv8Rg==", "peerDependencies": { "react": "*" } @@ -25715,9 +25715,9 @@ } }, "react-icons": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.2.0.tgz", - "integrity": "sha512-rmzEDFt+AVXRzD7zDE21gcxyBizD/3NqjbX6cmViAgdqfJ2UiLer8927/QhhrXQV7dEj/1EGuOTPp7JnLYVJKQ==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.4.0.tgz", + "integrity": "sha512-fSbvHeVYo/B5/L4VhB7sBA1i2tS8MkT0Hb9t2H1AVPkwGfVHLJCqyr2Py9dKMxsyM63Eng1GkdZfbWj+Fmv8Rg==", "requires": {} }, "react-is": { diff --git a/package.json b/package.json index 5b05f642..55387bef 100644 --- a/package.json +++ b/package.json @@ -81,7 +81,7 @@ "react": "^16.13.1", "react-color": "^2.19.3", "react-dom": "^16.13.1", - "react-icons": "^4.2.0", + "react-icons": "^4.4.0", "react-toastify": "^5.5.0", "sprintf": "0.1.5", "three": "^0.118.3", diff --git a/web/app/cad/actions/ActionButtonBehavior.jsx b/web/app/cad/actions/ActionButtonBehavior.jsx index e35143cf..330f67a1 100644 --- a/web/app/cad/actions/ActionButtonBehavior.jsx +++ b/web/app/cad/actions/ActionButtonBehavior.jsx @@ -1,5 +1,6 @@ import React, {useContext} from 'react'; import {AppContext} from "../dom/components/AppContext"; +import {isMenuAction} from "cad/dom/menu/menuPlugin"; export function ActionButtonBehavior({children, actionId}) { @@ -21,7 +22,16 @@ export function ActionButtonBehavior({children, actionId}) { 'data-action-id': actionId, onClick: e => { canceled = true; - actionService.run(actionId, e); + let data; + if (isMenuAction(actionId)) { + data = { + x: e.pageX, + y: e.pageY + } + } else { + data = e; + } + actionService.run(actionId, data); }, onMouseEnter: e => { updateCoords(e); diff --git a/web/app/cad/actions/coreActions.js b/web/app/cad/actions/coreActions.js index 16dc1a15..473d2af1 100644 --- a/web/app/cad/actions/coreActions.js +++ b/web/app/cad/actions/coreActions.js @@ -1,5 +1,6 @@ import * as ActionHelpers from './actionHelpers' import {AiOutlineExport} from "react-icons/ai"; +import {CurrentWorkbenchIcon} from "cad/workbench/CurrentWorkbenchIcon"; export default [ { diff --git a/web/app/cad/dom/components/HeadsUpToolbar.jsx b/web/app/cad/dom/components/HeadsUpToolbar.jsx index 5b2b4114..8a7eeae9 100644 --- a/web/app/cad/dom/components/HeadsUpToolbar.jsx +++ b/web/app/cad/dom/components/HeadsUpToolbar.jsx @@ -11,13 +11,12 @@ export const HeadsUpToolbar = connect(streams => combine( streams.ui.toolbars.headsUpQuickActions).map(([actions, showTitles, quickActions]) => ({actions, showTitles, quickActions})))( function HeadsUpToolbar({actions, showTitles, quickActions}) { return -
- -
-
{quickActions.map(actionId => )}
+
+ +
} ); diff --git a/web/app/cad/dom/components/HeadsUpToolbar.less b/web/app/cad/dom/components/HeadsUpToolbar.less index 70a36343..060a24e7 100644 --- a/web/app/cad/dom/components/HeadsUpToolbar.less +++ b/web/app/cad/dom/components/HeadsUpToolbar.less @@ -3,8 +3,8 @@ flex-direction: column; justify-content: space-evenly; flex: 0 0; - border-left: 1px solid #8e8e8e; - padding-left: 3px; + border-right: 1px solid #8e8e8e; + padding-right: 3px; & > * { font-size: 16px; padding: 5px 2px; diff --git a/web/app/cad/dom/menu/MenuHolder.jsx b/web/app/cad/dom/menu/MenuHolder.jsx index 10575a0c..538d8c36 100644 --- a/web/app/cad/dom/menu/MenuHolder.jsx +++ b/web/app/cad/dom/menu/MenuHolder.jsx @@ -13,6 +13,9 @@ function MenuHolder({menus}) { } function ActionMenu({actions, keymap, ...menuState}) { + if (!Array.isArray(actions)) { + actions = actions(); + } return {actions.map((action, index) => { if (action === '-') { diff --git a/web/app/cad/sketch/sketcherUIContrib.ts b/web/app/cad/sketch/sketcherUIContrib.ts index e1f815ca..2140f6aa 100644 --- a/web/app/cad/sketch/sketcherUIContrib.ts +++ b/web/app/cad/sketch/sketcherUIContrib.ts @@ -6,7 +6,7 @@ import constraintGlobalActions from "../../sketcher/actions/constraintGlobalActi import generalToolActions from "../../sketcher/actions/generalToolActions"; import sketcherControlActions from "./sketcherControlActions"; import {ApplicationContext} from "context"; -import {WorkbenchConfig} from "cad/workbench/workbenchService"; +import {RiCompasses2Line} from "react-icons/ri"; export default function (ctx: ApplicationContext) { @@ -53,10 +53,9 @@ export default function (ctx: ApplicationContext) { ui: { toolbar: SKETCHER_MODE_HEADS_UP_ACTIONS, toolbarStyle: 'compact' - } + }, + icon: RiCompasses2Line }); - - } const SKETCHER_PREFIX = 'sketcher.'; diff --git a/web/app/cad/workbench/CurrentWorkbenchIcon.tsx b/web/app/cad/workbench/CurrentWorkbenchIcon.tsx new file mode 100644 index 00000000..311ae5cb --- /dev/null +++ b/web/app/cad/workbench/CurrentWorkbenchIcon.tsx @@ -0,0 +1,8 @@ +import React from "react"; +import {useStream} from "ui/effects"; + +export function CurrentWorkbenchIcon() { + const currentWorkbench = useStream(ctx => ctx.workbenchService.currentWorkbench$); + const Icon = currentWorkbench.icon; + return ; +} \ No newline at end of file diff --git a/web/app/cad/workbench/uiConfigPlugin.js b/web/app/cad/workbench/uiConfigPlugin.js index 38a8b898..204de06f 100644 --- a/web/app/cad/workbench/uiConfigPlugin.js +++ b/web/app/cad/workbench/uiConfigPlugin.js @@ -19,7 +19,7 @@ export function activate(ctx) { ['ShowSketches', {label: 'sketches'}], ['DeselectAll', {label: null}], ['ToggleCameraMode', {label: null}] ]; - streams.ui.toolbars.headsUpQuickActions.value = ['Save', 'StlExport']; + streams.ui.toolbars.headsUpQuickActions.value = ['Save', 'StlExport', 'menu.workbenches']; ctx.actionService.registerActions(CoreActions); ctx.actionService.registerActions(OperationActions); diff --git a/web/app/cad/workbench/workbenchPlugin.ts b/web/app/cad/workbench/workbenchPlugin.ts index 94e60d15..8965b7a4 100644 --- a/web/app/cad/workbench/workbenchPlugin.ts +++ b/web/app/cad/workbench/workbenchPlugin.ts @@ -1,9 +1,10 @@ import {ApplicationContext} from "context"; import {WorkbenchService} from "cad/workbench/workbenchService"; +import {CurrentWorkbenchIcon} from "cad/workbench/CurrentWorkbenchIcon"; declare module 'context' { - interface CoreContext { + interface ApplicationContext { workbenchService: WorkbenchService; } @@ -15,6 +16,20 @@ export const WorkbenchPlugin = { activate(ctx: ApplicationContext) { ctx.workbenchService = new WorkbenchService(ctx); + + ctx.services.menu.registerMenus([ + { + id: 'workbenches', + label: 'workbenches', + icon: CurrentWorkbenchIcon, + + info: 'switch workbench', + actions: () => { + const workbenches = ctx.workbenchService.workbenches$.value; + return Object.keys(workbenches).filter(w => w !== 'sketcher').map(w => 'workbench.switch.' + workbenches[w].workbenchId) + } + } + ]); } } diff --git a/web/app/cad/workbench/workbenchService.ts b/web/app/cad/workbench/workbenchService.ts index 5cffefc6..0a180a06 100644 --- a/web/app/cad/workbench/workbenchService.ts +++ b/web/app/cad/workbench/workbenchService.ts @@ -4,6 +4,8 @@ import {state} from "lstream"; import {Index} from "gems/indexType"; import {ApplicationContext, CoreContext} from "context"; import {ActionRef} from "cad/dom/uiPlugin"; +import {IconDeclaration} from "cad/icons/IconDeclaration"; +import {CurrentWorkbenchIcon} from "cad/workbench/CurrentWorkbenchIcon"; export class WorkbenchService { @@ -21,7 +23,7 @@ export class WorkbenchService { ctx.uiService.streams.toolbars.headsUp.next(workbenchConfig.ui.toolbar); const toolbarStyle = workbenchConfig.ui.toolbarStyle || 'large' ctx.uiService.streams.toolbars.headsUpShowTitles.next(toolbarStyle === "large"); - }) + }); } getWorkbenchConfig(workbenchId: string): WorkbenchConfig { @@ -39,6 +41,20 @@ export class WorkbenchService { ...workbenches, [workbenchConfig.workbenchId]: workbenchConfig })); + + this.ctx.actionService.registerAction( + { + id: 'workbench.switch.' + workbenchConfig.workbenchId, + appearance: { + icon: workbenchConfig.icon, + label: workbenchConfig.workbenchId, + info: 'switches to ' + workbenchConfig.workbenchId, + }, + invoke: (ctx) => { + this.switchWorkbench(workbenchConfig.workbenchId); + } + } + ); } switchWorkbench(workbenchId: string) { @@ -65,4 +81,5 @@ export interface WorkbenchConfig { features: OperationDescriptor[]; actions: ActionDefinition[]; ui: WorkbenchUIConfig; + icon: IconDeclaration } \ No newline at end of file