diff --git a/package-lock.json b/package-lock.json index 198602ff..0979222c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8437,6 +8437,21 @@ } } }, + "react-icons": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-3.9.0.tgz", + "integrity": "sha512-gKbYKR+4QsD3PmIHLAM9TDDpnaTsr3XZeK1NTAb6WQQ+gxEdJ0xuCgLq0pxXdS7Utg2AIpcVhM1ut/jlDhcyNg==", + "requires": { + "camelcase": "^5.0.0" + }, + "dependencies": { + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" + } + } + }, "react-is": { "version": "16.12.0", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.12.0.tgz", diff --git a/package.json b/package.json index c42cb601..5c0e7fb3 100644 --- a/package.json +++ b/package.json @@ -67,6 +67,7 @@ "prop-types": "15.6.0", "react": "^16.8.6", "react-dom": "^16.8.6", + "react-icons": "3.9.0", "react-toastify": "^5.5.0", "sprintf": "0.1.5", "three": "0.89.0" diff --git a/web/app/sketcher/actions/commonActions.js b/web/app/sketcher/actions/commonActions.js new file mode 100644 index 00000000..3396416f --- /dev/null +++ b/web/app/sketcher/actions/commonActions.js @@ -0,0 +1,85 @@ +import {MdZoomOutMap} from "react-icons/md"; +import {AiOutlineCopy, AiOutlineExport, AiOutlineFile, AiOutlineFolderOpen, AiOutlineSave} from "react-icons/ai"; +import * as ui from "../../ui/ui"; + +export default [ + + { + id: 'New', + shortName: 'New', + kind: 'Common', + description: 'Create new sketch', + icon: AiOutlineFile, + + invoke: (ctx) => { + ctx.app.newSketch(); + } + }, + + { + id: 'Clone', + shortName: 'Clone', + kind: 'Common', + description: 'Clone sketch', + icon: AiOutlineCopy, + + invoke: (ctx, e) => { + ctx.app.cloneSketch(); + } + }, + + { + id: 'Open', + shortName: 'Open', + kind: 'Common', + description: 'Open sketch', + icon: AiOutlineFolderOpen, + + invoke: (ctx, e) => { + ctx.app._sketchesList.refresh(); + ui.openWin(ctx.app._sketchesWin, e); + } + }, + + { + id: 'Save', + shortName: 'Save', + kind: 'Common', + description: 'Save sketch', + icon: AiOutlineSave, + + invoke: (ctx) => { + const sketchData = ctx.viewer.io.serializeSketch(); + const sketchId = ctx.app.getSketchId(); + localStorage.setItem(sketchId, sketchData); + } + }, + + { + id: 'Export', + shortName: 'Export', + kind: 'Common', + description: 'Export sketch to other formats', + icon: AiOutlineExport, + + invoke: (ctx, e) => { + ui.openWin(ctx.app._exportWin, e); + } + + }, + + { + id: 'Fit', + shortName: 'Fit', + kind: 'Common', + description: 'Fit Sketch On Screen', + icon: MdZoomOutMap, + + invoke: (ctx) => { + ctx.viewer.toolManager.releaseControl(); + ctx.app.fit(); + ctx.viewer.refresh(); + } + + }, +] \ No newline at end of file diff --git a/web/app/sketcher/actions/index.js b/web/app/sketcher/actions/index.js index 5430323b..0775d677 100644 --- a/web/app/sketcher/actions/index.js +++ b/web/app/sketcher/actions/index.js @@ -3,16 +3,30 @@ import {getDescription, MatchIndex, matchSelection} from "../selectionMatcher"; import {toast} from "react-toastify"; import operationActions from "./operationActions"; import constraintGlobalActions from "./constraintGlobalActions"; +import measureActions from "./measureActions"; +import toolActions from "./toolActions"; +import commonActions from "./commonActions"; const ALL_CONTEXTUAL_ACTIONS = [ ...constraintActions, ...operationActions, - ...constraintGlobalActions +]; + +const ACTIONS = [ + ...constraintGlobalActions, + ...measureActions, + ...toolActions, + ...commonActions //keep going here ]; +const ALL_ACTIONS = [ + ...ALL_CONTEXTUAL_ACTIONS, + ...ACTIONS +]; + const index = {}; -ALL_CONTEXTUAL_ACTIONS.forEach(a => index[a.id] = a); +ALL_ACTIONS.forEach(a => index[a.id] = a); Object.freeze(index); export function matchAvailableActions(selection) { diff --git a/web/app/sketcher/actions/measureActions.js b/web/app/sketcher/actions/measureActions.js new file mode 100644 index 00000000..fbeb614d --- /dev/null +++ b/web/app/sketcher/actions/measureActions.js @@ -0,0 +1,65 @@ +import {MirrorGeneratorIcon} from "../icons/generators/GeneratorIcons"; +import {MirrorGeneratorSchema} from "../generators/mirrorGenerator"; +import {AddCircleDimTool, AddFreeDimTool, AddHorizontalDimTool, AddVerticalDimTool} from "../tools/dim"; +import { + MeasureCircleToolIcon, + MeasureFreeToolIcon, + MeasureHorizontalToolIcon, + MeasureVerticalToolIcon +} from "../icons/tools/ToolIcons"; + +export default [ + + { + id: 'MeasureDistance', + shortName: 'Measure Distance', + kind: 'Tool', + description: 'Measure distance between two points', + icon: MeasureFreeToolIcon, + + invoke: (ctx) => { + ctx.viewer.toolManager.takeControl(new AddFreeDimTool(ctx.viewer, ctx.viewer.dimLayer)); + } + + }, + + + { + id: 'MeasureHDistance', + shortName: 'Measure Horizontal Distance', + kind: 'Tool', + description: 'Measure horizontal distance between two points', + icon: MeasureHorizontalToolIcon, + + invoke: (ctx) => { + ctx.viewer.toolManager.takeControl(new AddHorizontalDimTool(ctx.viewer, ctx.viewer.dimLayer)); + } + + }, + + { + id: 'MeasureVDistance', + shortName: 'Measure Vertical Distance', + kind: 'Tool', + description: 'Measure vertical distance between two points', + icon: MeasureVerticalToolIcon, + + invoke: (ctx) => { + ctx.viewer.toolManager.takeControl(new AddVerticalDimTool(ctx.viewer, ctx.viewer.dimLayer)); + } + + }, + + { + id: 'MeasureCircle', + shortName: 'Measure Circle', + kind: 'Tool', + description: 'Measure circle diameter', + icon: MeasureCircleToolIcon, + + invoke: (ctx) => { + ctx.viewer.toolManager.takeControl(new AddCircleDimTool(ctx.viewer, ctx.viewer.dimLayer)); + } + + }, +]; \ No newline at end of file diff --git a/web/app/sketcher/actions/operationActions.js b/web/app/sketcher/actions/operationActions.js index 70d0295a..0a22a9fd 100644 --- a/web/app/sketcher/actions/operationActions.js +++ b/web/app/sketcher/actions/operationActions.js @@ -1,7 +1,8 @@ import {Generator} from "../id-generator"; import {SketchGenerator} from "../generators/sketchGenerator"; import {MirrorGeneratorSchema} from "../generators/mirrorGenerator"; -import {MirrorGeneratorIcon} from "../icons/generators/GeneratorIcons"; +import {MirrorGeneratorIcon, OffsetGeneratorIcon} from "../icons/generators/GeneratorIcons"; +import {OffsetTool} from "../tools/offset"; export default [ @@ -12,7 +13,7 @@ export default [ description: 'Mirror Objects', icon: MirrorGeneratorIcon, - wizard: MirrorGeneratorSchema.params , + wizard: MirrorGeneratorSchema.params, invoke: (ctx, params) => { @@ -24,5 +25,20 @@ export default [ }, + + { + id: 'Offset', + shortName: 'Offset', + kind: 'Generator', + description: 'Offset', + icon: OffsetGeneratorIcon, + + invoke: (ctx) => { + ctx.viewer.toolManager.takeControl(new OffsetTool(ctx.viewer)); + } + + }, + + ]; diff --git a/web/app/sketcher/actions/toolActions.js b/web/app/sketcher/actions/toolActions.js new file mode 100644 index 00000000..419f0f29 --- /dev/null +++ b/web/app/sketcher/actions/toolActions.js @@ -0,0 +1,177 @@ +import {RectangleTool} from "../tools/rectangle"; +import { + ArcToolIcon, + BezierToolIcon, + CircleToolIcon, + EllipseArcToolIcon, + EllipseToolIcon, + LineToolIcon, + MultiLineToolIcon, + PointToolIcon, + RectangleToolIcon +} from "../icons/tools/ToolIcons"; +import {AddSegmentTool} from "../tools/segment"; +import {BezierCurveTool} from "../tools/bezier-curve"; +import {EllipseTool} from "../tools/ellipse"; +import {AddPointTool} from "../tools/point"; +import {AddArcTool} from "../tools/arc"; +import {EditCircleTool} from "../tools/circle"; +import {IoIosHand} from "react-icons/io"; +import {ReferencePointTool} from "../tools/origin"; +import {GiCrosshair} from "react-icons/gi"; + +export default [ + + { + id: 'PanTool', + shortName: 'Pan', + kind: 'Tool', + description: 'Pan mode', + icon: IoIosHand, + + invoke: (ctx) => { + ctx.viewer.toolManager.releaseControl(); + + } + + }, + + { + id: 'ReferencePointTool', + shortName: 'Set Origin', + kind: 'Tool', + description: 'Sets reference point for commands', + icon: GiCrosshair, + command: 'origin', + invoke: (ctx) => { + ctx.viewer.toolManager.takeControl(new ReferencePointTool(ctx.viewer)); + } + + }, + + { + id: 'PointTool', + shortName: 'Point', + kind: 'Tool', + description: 'Add a point', + icon: PointToolIcon, + command: 'point', + invoke: (ctx) => { + ctx.viewer.toolManager.takeControl(new AddPointTool(ctx.viewer)); + + } + + }, + + + { + id: 'SegmentTool', + shortName: 'Segment', + kind: 'Tool', + description: 'Add a segment', + icon: LineToolIcon, + command: 'line', + + invoke: (ctx) => { + ctx.viewer.toolManager.takeControl(new AddSegmentTool(ctx.viewer, false)); + + }, + }, + + { + id: 'MultiLineTool', + shortName: 'Multi Line', + kind: 'Tool', + description: 'Multi line', + icon: MultiLineToolIcon, + command: 'mline', + + invoke: (ctx) => { + ctx.viewer.toolManager.takeControl(new AddSegmentTool(ctx.viewer, true)); + + } + + }, + + { + id: 'CircleTool', + shortName: 'Circle', + kind: 'Tool', + description: 'Add a circle', + icon: CircleToolIcon, + command: 'circle', + + invoke: (ctx) => { + ctx.viewer.toolManager.takeControl(new EditCircleTool(ctx.viewer)); + } + + }, + + { + id: 'ArcTool', + shortName: 'Arc', + kind: 'Tool', + description: 'Add an arc', + icon: ArcToolIcon, + command: 'arc', + + invoke: (ctx) => { + ctx.viewer.toolManager.takeControl(new AddArcTool(ctx.viewer)); + } + + }, + + { + id: 'EllipseTool', + shortName: 'Ellipse', + kind: 'Tool', + description: 'Add an ellipse', + icon: EllipseToolIcon, + + invoke: (ctx) => { + ctx.viewer.toolManager.takeControl(new EllipseTool(ctx.viewer, false)); + } + + }, + + { + id: 'EllipseArcTool', + shortName: 'Elliptical Arc', + kind: 'Tool', + description: 'Add elliptical arc', + icon: EllipseArcToolIcon, + + invoke: (ctx) => { + ctx.viewer.toolManager.takeControl(new EllipseTool(ctx.viewer, true)); + } + + }, + + { + id: 'BezierTool', + shortName: 'Bezier', + kind: 'Tool', + description: 'Add a bezier curve', + icon: BezierToolIcon, + + invoke: (ctx) => { + ctx.viewer.toolManager.takeControl(new BezierCurveTool(ctx.viewer)); + } + + }, + + { + id: 'RectangleTool', + shortName: 'Rectangle', + kind: 'Tool', + description: 'Creates rectangle', + icon: RectangleToolIcon, + command: 'rect', + + invoke: (ctx) => { + ctx.viewer.toolManager.takeControl(new RectangleTool(ctx.viewer)); + } + + }, +]; + diff --git a/web/app/sketcher/components/SketcherApp.jsx b/web/app/sketcher/components/SketcherApp.jsx index de6231f8..23d13106 100644 --- a/web/app/sketcher/components/SketcherApp.jsx +++ b/web/app/sketcher/components/SketcherApp.jsx @@ -10,7 +10,7 @@ import SketcherOperationWizard from "./SketcherOperationWizard"; import {StageControl} from "./StageControl"; import {Scope} from "./Scope"; import {SketcherToolbar} from "./SketcherToolbar"; -import {sketcherRightToolbarConfig} from "../uiConfig"; +import {sketcherRightToolbarConfig, sketcherTopToolbarConfig} from "../uiConfig"; export const SketcherAppContext = React.createContext({}); @@ -27,6 +27,10 @@ export function SketcherApp({applicationContext}) { , document.getElementById('right-toolbar') )} + {ReactDOM.createPortal( + , + document.getElementById('top-toolbar') + )} ; diff --git a/web/app/sketcher/components/SketcherToolbar.jsx b/web/app/sketcher/components/SketcherToolbar.jsx index a4223e53..110cda82 100644 --- a/web/app/sketcher/components/SketcherToolbar.jsx +++ b/web/app/sketcher/components/SketcherToolbar.jsx @@ -2,11 +2,17 @@ import React, {useContext} from 'react'; import {getSketcherAction} from "../actions"; import {SketcherAppContext} from "./SketcherApp"; import ls from './SketcherToolbar.less'; +import cx from 'classnames'; -export function SketcherToolbar({actions}) { +export function SketcherToolbar({actions, horizontal=false, compact}) { - return
- {actions.map(action => )} + return
+ {actions.map((action, index) => { + if (action === '-') { + return
+ } + return + })}
; } @@ -22,7 +28,7 @@ export function SketcherActionButton({actionId}) { const Icon = action.icon; - return ; diff --git a/web/app/sketcher/components/SketcherToolbar.less b/web/app/sketcher/components/SketcherToolbar.less index 18117755..47ab6419 100644 --- a/web/app/sketcher/components/SketcherToolbar.less +++ b/web/app/sketcher/components/SketcherToolbar.less @@ -1,13 +1,33 @@ @focus-color: #0065dc; @focus-color-secondary: rgba(3, 102, 214, .3); +@separator: 15px; .root { height: 100%; display: flex; - flex-direction: column; align-items: center; + &.vertical { + flex-direction: column; + button { + margin: 2px 4px; + } + .separator { + height: @separator; + } + } + + + &.horizontal { + button { + margin: 4px 2px; + } + .separator { + width: @separator; + } + } + button { background: #606060; @@ -18,14 +38,25 @@ box-shadow: 0 0 0 2px @focus-color-secondary; outline: none; } - margin: 2px 4px; padding: 1px; flex-basis: 36px; + display: flex; } svg { - width: 36px; - height: 36px; + width: 34px; + height: 34px; } + &.compact svg { + width: 28px; + height: 28px; + transform: scale(0.9); + } + + :global(.action-kind-Common) { + svg { + transform: scale(0.7); + } + } } \ No newline at end of file diff --git a/web/app/sketcher/icons/constraints/lock-constraint.svg b/web/app/sketcher/icons/constraints/lock-constraint.svg index 0354addc..11bc8b54 100644 --- a/web/app/sketcher/icons/constraints/lock-constraint.svg +++ b/web/app/sketcher/icons/constraints/lock-constraint.svg @@ -1,3 +1,27 @@ + + } +export function OffsetGeneratorIcon(props) { + + return +} \ No newline at end of file diff --git a/web/app/sketcher/icons/generators/offset-generator.svg b/web/app/sketcher/icons/generators/offset-generator.svg new file mode 100644 index 00000000..85a48a6d --- /dev/null +++ b/web/app/sketcher/icons/generators/offset-generator.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + diff --git a/web/app/sketcher/icons/tools/ToolIcons.jsx b/web/app/sketcher/icons/tools/ToolIcons.jsx new file mode 100644 index 00000000..e82a09c6 --- /dev/null +++ b/web/app/sketcher/icons/tools/ToolIcons.jsx @@ -0,0 +1,80 @@ +import React from 'react'; +import {SvgIcon} from 'svg/SvgIcon'; +import measureCircleContent from './measure-circle-tool.svg'; +import measureFreeContent from './measure-free-tool.svg'; +import measureHorizontalContent from './measure-horizontal-tool.svg'; +import measureVerticalContent from './measure-vertical-tool.svg'; +import rectangleContent from './rectangle-tool.svg'; +import bezierContent from './bezier-tool.svg'; +import ellipseContent from './ellipse-tool.svg'; +import ellipseArcContent from './ellipse-arc-tool.svg'; +import arcContent from './arc-tool.svg'; +import circleContent from './circle-tool.svg'; +import mlineContent from './mline-tool.svg'; +import lineContent from './line-tool.svg'; +import pointContent from './point-tool.svg'; + +export function MeasureCircleToolIcon(props) { + + return +} + +export function MeasureFreeToolIcon(props) { + + return +} + +export function MeasureHorizontalToolIcon(props) { + + return +} + +export function MeasureVerticalToolIcon(props) { + + return +} + +export function RectangleToolIcon(props) { + + return +} + +export function BezierToolIcon(props) { + + return +} + +export function EllipseArcToolIcon(props) { + + return +} + +export function EllipseToolIcon(props) { + + return +} + +export function ArcToolIcon(props) { + + return +} + +export function CircleToolIcon(props) { + + return +} + +export function MultiLineToolIcon(props) { + + return +} + +export function LineToolIcon(props) { + + return +} + +export function PointToolIcon(props) { + + return +} diff --git a/web/app/sketcher/icons/tools/arc-tool.svg b/web/app/sketcher/icons/tools/arc-tool.svg new file mode 100644 index 00000000..f083bb80 --- /dev/null +++ b/web/app/sketcher/icons/tools/arc-tool.svg @@ -0,0 +1,19 @@ + + + + + + + + + diff --git a/web/app/sketcher/icons/tools/bezier-tool.svg b/web/app/sketcher/icons/tools/bezier-tool.svg new file mode 100644 index 00000000..9f2b66f0 --- /dev/null +++ b/web/app/sketcher/icons/tools/bezier-tool.svg @@ -0,0 +1,14 @@ + + + + + + + + \ No newline at end of file diff --git a/web/app/sketcher/icons/tools/circle-tool.svg b/web/app/sketcher/icons/tools/circle-tool.svg new file mode 100644 index 00000000..0e91e7a1 --- /dev/null +++ b/web/app/sketcher/icons/tools/circle-tool.svg @@ -0,0 +1,14 @@ + + + + + + + + diff --git a/web/app/sketcher/icons/tools/ellipse-arc-tool.svg b/web/app/sketcher/icons/tools/ellipse-arc-tool.svg new file mode 100644 index 00000000..bdc4d6f9 --- /dev/null +++ b/web/app/sketcher/icons/tools/ellipse-arc-tool.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + diff --git a/web/app/sketcher/icons/tools/ellipse-tool.svg b/web/app/sketcher/icons/tools/ellipse-tool.svg new file mode 100644 index 00000000..5f8ad211 --- /dev/null +++ b/web/app/sketcher/icons/tools/ellipse-tool.svg @@ -0,0 +1,16 @@ + + + + + + + + + diff --git a/web/app/sketcher/icons/tools/line-tool.svg b/web/app/sketcher/icons/tools/line-tool.svg new file mode 100644 index 00000000..57cb1e6e --- /dev/null +++ b/web/app/sketcher/icons/tools/line-tool.svg @@ -0,0 +1,12 @@ + + + + + + diff --git a/web/app/sketcher/icons/tools/measure-circle-tool.svg b/web/app/sketcher/icons/tools/measure-circle-tool.svg new file mode 100644 index 00000000..50baa3aa --- /dev/null +++ b/web/app/sketcher/icons/tools/measure-circle-tool.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + diff --git a/web/app/sketcher/icons/tools/measure-free-tool.svg b/web/app/sketcher/icons/tools/measure-free-tool.svg new file mode 100644 index 00000000..ef69c4ea --- /dev/null +++ b/web/app/sketcher/icons/tools/measure-free-tool.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + diff --git a/web/app/sketcher/icons/tools/measure-horizontal-tool.svg b/web/app/sketcher/icons/tools/measure-horizontal-tool.svg new file mode 100644 index 00000000..1a1e399c --- /dev/null +++ b/web/app/sketcher/icons/tools/measure-horizontal-tool.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + diff --git a/web/app/sketcher/icons/tools/measure-vertical-tool.svg b/web/app/sketcher/icons/tools/measure-vertical-tool.svg new file mode 100644 index 00000000..30ad56ce --- /dev/null +++ b/web/app/sketcher/icons/tools/measure-vertical-tool.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + diff --git a/web/app/sketcher/icons/tools/mline-tool.svg b/web/app/sketcher/icons/tools/mline-tool.svg new file mode 100644 index 00000000..756caa6b --- /dev/null +++ b/web/app/sketcher/icons/tools/mline-tool.svg @@ -0,0 +1,12 @@ + + + + + + diff --git a/web/app/sketcher/icons/tools/point-tool.svg b/web/app/sketcher/icons/tools/point-tool.svg new file mode 100644 index 00000000..f437cdbc --- /dev/null +++ b/web/app/sketcher/icons/tools/point-tool.svg @@ -0,0 +1,12 @@ + + + + + + diff --git a/web/app/sketcher/icons/tools/rectangle-tool.svg b/web/app/sketcher/icons/tools/rectangle-tool.svg new file mode 100644 index 00000000..9a1f3855 --- /dev/null +++ b/web/app/sketcher/icons/tools/rectangle-tool.svg @@ -0,0 +1,16 @@ + + + + + + + + + + diff --git a/web/app/sketcher/sketcher-app.js b/web/app/sketcher/sketcher-app.js index 9c08d44a..1d9a02c3 100644 --- a/web/app/sketcher/sketcher-app.js +++ b/web/app/sketcher/sketcher-app.js @@ -24,7 +24,7 @@ function App2D() { var app = this; this.viewer = new Viewer(document.getElementById('viewer'), IO); - this.context = createAppContext(this.viewer); + this.context = createAppContext(this.viewer, this); this.winManager = new ui.WinManager(); this.inputManager = new InputManager(this); @@ -80,29 +80,12 @@ function App2D() { } checkForTerminalVisibility(); - this.registerAction('new', "Create New Sketch", function () { - app.newSketch(); - }); - this.registerAction('terminal', "Open/Close Terminal Window", function () { app.commandsWin.toggle(); checkForTerminalVisibility(); app.viewer.refresh(); }); - this.registerAction('open', "Open Sketch", function (e) { - app._sketchesList.refresh(); - ui.openWin(app._sketchesWin, e); - }); - - this.registerAction('clone', "Clone Sketch", function () { - app.cloneSketch(); - }); - - this.registerAction('export', "Export", function (e) { - ui.openWin(app._exportWin, e); - }); - this.registerAction('exportSVG', "Export To SVG", function () { IO.exportTextData(app.viewer.io.svgExport(), app.getSketchId() + ".ui.styles.init.svg"); }); @@ -123,88 +106,7 @@ function App2D() { app.viewer.historyManager.checkpoint(); }); - this.registerAction('referencePoint', "Set Reference Point", function () { - app.viewer.toolManager.takeControl(new ReferencePointTool(app.viewer)); - }, "origin"); - this.registerAction('addPoint', "Add Point", function () { - app.viewer.toolManager.takeControl(new AddPointTool(app.viewer)); - }, "point"); - - this.registerAction('addSegment', "Add Segment", function () { - app.viewer.toolManager.takeControl(new AddSegmentTool(app.viewer, false)); - }, 'line'); - - this.registerAction('addMultiSegment', "Add Multi Segment", function () { - app.viewer.toolManager.takeControl(new AddSegmentTool(app.viewer, true)); - }, 'mline'); - - this.registerAction('addArc', "Add Arc", function () { - app.viewer.toolManager.takeControl(new AddArcTool(app.viewer)); - }, 'arc'); - - this.registerAction('addCircle', "Add Circle", function () { - app.viewer.toolManager.takeControl(new EditCircleTool(app.viewer)); - }, 'circle'); - - this.registerAction('addEllipse', "Add Ellipse", function () { - app.viewer.toolManager.takeControl(new EllipseTool(app.viewer, false)); - }); - - this.registerAction('addEllipticalArc', "Add Elliptical Arc", function () { - app.viewer.toolManager.takeControl(new EllipseTool(app.viewer, true)); - }); - - this.registerAction('addBezierCurve', "Add Bezier Curve", function () { - app.viewer.toolManager.takeControl(new BezierCurveTool(app.viewer)); - }); - - this.registerAction('addRectangle', "Add Rectangle", function () { - app.viewer.toolManager.takeControl(new RectangleTool(app.viewer)); - }, 'rect'); - - this.registerAction('offsetTool', "Polygon Offset", function () { - app.viewer.toolManager.takeControl(new OffsetTool(app.viewer)); - }); - - this.registerAction('pan', "Pan", function () { - app.viewer.toolManager.releaseControl(); - }); - - this.registerAction('addFillet', "Add Fillet", function () { - app.viewer.toolManager.takeControl(new FilletTool(app.viewer)); - }); - - this.registerAction('addDim', "Add Dimension", function () { - app.viewer.toolManager.takeControl(new AddFreeDimTool(app.viewer, app.viewer.dimLayer)); - }); - - this.registerAction('addHDim', "Add Horizontal Dimension", function () { - app.viewer.toolManager.takeControl(new AddHorizontalDimTool(app.viewer, app.viewer.dimLayer)); - }); - - this.registerAction('addVDim', "Add Vertical Dimension", function () { - app.viewer.toolManager.takeControl(new AddVerticalDimTool(app.viewer, app.viewer.dimLayer)); - }); - - this.registerAction('addCircleDim', "Add Circle Dimension", function () { - app.viewer.toolManager.takeControl(new AddCircleDimTool(app.viewer, app.viewer.dimLayer)); - }); - - this.registerAction('save', "Save", function () { - var sketchData = app.viewer.io.serializeSketch(); - var sketchId = app.getSketchId(); - localStorage.setItem(app.getSketchId(), sketchData); - app.viewer.historyManager.checkpoint(); - }); - - this.registerAction('lockConvex', "Lock Convexity", function () { - app.viewer.parametricManager.lockConvex(app.viewer.selected, alert); - }); - - this.registerAction('analyzeConstraint', "Analyze Constraint", function () { - app.viewer.parametricManager.analyze(alert); - }); this.registerAction('solve', "Solve System", function () { app.viewer.parametricManager.solve(); @@ -216,10 +118,6 @@ function App2D() { app.viewer.refresh(); }); - this.registerAction('fit', "Fit Sketch On Screen", function () { - app.fit(); - app.viewer.refresh(); - }); this.registerAction('genSerpinski', "Generate Serpinki Triangle off of a segment", function () { genSerpinski(app.viewer); @@ -407,13 +305,13 @@ App2D.prototype.handleTerminalInput = function(commandStr) { } }; -function createAppContext(viewer) { +function createAppContext(viewer, app) { return { viewer, + app, ui: { $constraintEditRequest: stream(), $wizardRequest: stream() - } }; } diff --git a/web/app/sketcher/styles.js b/web/app/sketcher/styles.js index ef975c16..c8c888ac 100644 --- a/web/app/sketcher/styles.js +++ b/web/app/sketcher/styles.js @@ -33,6 +33,12 @@ export const Styles = { fillStyle : "#00FF00" }, + HIGHLIGHT2 : { + lineWidth : 2, + strokeStyle : "#ff961f", + fillStyle : "#ff961f" + }, + DIM : { lineWidth : 1, strokeStyle : "#bcffc1", diff --git a/web/app/sketcher/tools/loop-pick.js b/web/app/sketcher/tools/loop-pick.js index 33a29a46..d112fba7 100644 --- a/web/app/sketcher/tools/loop-pick.js +++ b/web/app/sketcher/tools/loop-pick.js @@ -25,17 +25,11 @@ export class LoopPickTool extends Tool { } clearMarked() { - for (let obj of this.marked) { - obj.marked = null; - } - this.marked.clear(); + this.viewer.withdrawAll('tool'); } mark(obj) { - if (!this.marked.has(obj)) { - obj.marked = Styles.SNAP; - this.marked.add(obj); - } + this.viewer.capture('tool', obj); } otherEnd(point) { @@ -59,7 +53,8 @@ export class LoopPickTool extends Tool { const graph = { connections : (p) => { - const conns = p.linked.slice(); + const conns = [] + p.visitLinked(l => conns.push(l)); conns.push(this.otherEnd(p)); return conns; }, diff --git a/web/app/sketcher/uiConfig.js b/web/app/sketcher/uiConfig.js index 25d9ad0e..5db39ea0 100644 --- a/web/app/sketcher/uiConfig.js +++ b/web/app/sketcher/uiConfig.js @@ -1,5 +1,25 @@ import constraintGlobalActions from "./actions/constraintGlobalActions"; +import measureActions from "./actions/measureActions"; +import toolActions from "./actions/toolActions"; +import commonActions from "./actions/commonActions"; export const sketcherRightToolbarConfig = constraintGlobalActions.map(a => a.id); -export const sketcherTopToolbarConfig = []; \ No newline at end of file +export const sketcherTopToolbarConfig = [ + ...commonActions.map(a => a.id), + ...toolActions.map(a => a.id), + 'Offset', + '-', + ...measureActions.map(a => a.id) +]; + +insertAfter(sketcherTopToolbarConfig, 'Export', '-'); +insertAfter(sketcherTopToolbarConfig, 'PanTool', '-'); +insertAfter(sketcherTopToolbarConfig, 'BezierTool', '-'); + +function insertAfter(arr, item, toAdd) { + const index = arr.indexOf(item); + if (index !== -1) { + arr.splice(index+1, 0, toAdd); + } +} \ No newline at end of file diff --git a/web/css/app.less b/web/css/app.less index e1f86af4..4d6e68d9 100644 --- a/web/css/app.less +++ b/web/css/app.less @@ -141,11 +141,10 @@ html, body { } .tool-caption .btn { - width:14px; - height:14px; - font-size: 10px; - line-height: 11px; - margin-top: -1px; + display: flex; + align-items: center; + align-self: stretch; + padding: 0 2px; } .tool-caption .fa { @@ -210,15 +209,18 @@ html, body { .win .tool-caption { cursor: default; - height: 15px; + display: flex; + justify-content: space-between; + line-height: 1.8; + align-items: center; } .win .tool-caption .rm { border: 0; border-radius: 0px; color: white; font-size: 16px; - height: 17px; - padding-left: 5px; + padding: 0 5px; + margin: -2px 0 -2px 0; } .sep { diff --git a/web/sketcher.html b/web/sketcher.html index 62e28811..ebce5229 100644 --- a/web/sketcher.html +++ b/web/sketcher.html @@ -13,35 +13,9 @@ -
+
- - +