mirror of
https://github.com/xibyte/jsketcher
synced 2026-01-01 13:23:32 +01:00
migrate sketch export dialog
This commit is contained in:
parent
167167be89
commit
557b3474ee
16 changed files with 116 additions and 87 deletions
|
|
@ -1,17 +1,9 @@
|
|||
import React, {useEffect, useMemo, useRef} from 'react';
|
||||
import React, {useMemo} from 'react';
|
||||
|
||||
export function SvgIcon({content, size, ...props}) {
|
||||
|
||||
const divEl = useRef(null);
|
||||
|
||||
const className = size&&'icon-'+size;
|
||||
|
||||
useEffect(() => {
|
||||
if (divEl.current) {
|
||||
divEl.current.innerHTML = content;
|
||||
}
|
||||
}, [divEl]);
|
||||
|
||||
const style = useMemo(() => {
|
||||
return {
|
||||
display: 'flex',
|
||||
|
|
@ -19,7 +11,7 @@ export function SvgIcon({content, size, ...props}) {
|
|||
};
|
||||
}, [props.style]);
|
||||
|
||||
return <div className={className} ref={divEl} {...props} style={style}/>
|
||||
return <div className={className} {...props} style={style} dangerouslySetInnerHTML={{__html: content}}/>
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@ import React from 'react';
|
|||
|
||||
import ls from './Stack.less'
|
||||
|
||||
export default function Stack({children}) {
|
||||
return <div className={ls.root}>{children}</div>
|
||||
export default function Stack(props) {
|
||||
return <div className={ls.root} {...props} />
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -2,9 +2,9 @@ import React from 'react';
|
|||
|
||||
import cx from 'classnames';
|
||||
|
||||
export default function Button({type, onClick, className, children}) {
|
||||
export default function Button({type, onClick, className, ...props}) {
|
||||
|
||||
return <button onClick={onClick} className={cx(type, className)}>{children}</button>
|
||||
return <button onClick={onClick} className={cx(type, className)} {...props} />
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
import '../css/app.less'
|
||||
import 'ui/styles/init/index.less';
|
||||
|
||||
import App2D from './sketcher/sketcher-app';
|
||||
import {Layer} from './sketcher/viewer2d';
|
||||
import * as ui from './ui/ui.js';
|
||||
import * as toolkit from './ui/toolkit';
|
||||
import {Constraints} from './sketcher/parametric'
|
||||
import './utils/jqueryfy'
|
||||
import '../css/app.less'
|
||||
import 'ui/styles/init/index.less';
|
||||
|
||||
import ReactDOM from "react-dom";
|
||||
import {SketcherApp} from "./sketcher/components/SketcherApp";
|
||||
|
|
@ -25,16 +26,6 @@ function initializeSketcherApplication() {
|
|||
app.loadFromLocalStorage();
|
||||
app.fit();
|
||||
|
||||
var actionsWin = new ui.Window($('#actions'), app.winManager);
|
||||
|
||||
ui.bindOpening( $('#showActions'), actionsWin );
|
||||
var addAction = ui.createActionsWinBuilder(actionsWin);
|
||||
|
||||
for (var p = 0; p < app._actionsOrder.length; ++p) {
|
||||
var act = app.actions[app._actionsOrder[p]];
|
||||
addAction(act.desc, act.action);
|
||||
$('.act-' + act.id).click(act.action).attr('title', act.desc);
|
||||
}
|
||||
|
||||
|
||||
const constraintsView = app.dock.views['Constraints'];
|
||||
|
|
|
|||
|
|
@ -65,9 +65,11 @@ export default [
|
|||
icon: AiOutlineExport,
|
||||
|
||||
invoke: (ctx, e) => {
|
||||
ui.openWin(ctx.app._exportWin, e);
|
||||
ctx.ui.$exportDialogRequest.next({
|
||||
x: e.pageX,
|
||||
y: e.pageY
|
||||
});
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
|
|
|||
31
web/app/sketcher/actions/exportActions.js
Normal file
31
web/app/sketcher/actions/exportActions.js
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
import {IO} from "../io";
|
||||
import React from "react";
|
||||
import {AiOutlineExport} from "react-icons/ai";
|
||||
|
||||
|
||||
export default [
|
||||
{
|
||||
id: 'ExportSVG',
|
||||
shortName: 'Export to SVG',
|
||||
kind: 'Export',
|
||||
description: 'Export sketch to SVG',
|
||||
icon: AiOutlineExport,
|
||||
|
||||
invoke: (ctx) => {
|
||||
IO.exportTextData(ctx.viewer.io.svgExport(), ctx.app.getSketchId() + ".svg");
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
id: 'ExportDXF',
|
||||
shortName: 'Export to DXF',
|
||||
kind: 'Export',
|
||||
description: 'Export sketch to DXF',
|
||||
icon: AiOutlineExport,
|
||||
|
||||
invoke: (ctx) => {
|
||||
IO.exportTextData(ctx.viewer.io.dxfExport(), ctx.app.getSketchId() + ".dxf");
|
||||
}
|
||||
|
||||
},
|
||||
];
|
||||
|
|
@ -6,6 +6,7 @@ import constraintGlobalActions from "./constraintGlobalActions";
|
|||
import measureActions from "./measureActions";
|
||||
import toolActions from "./toolActions";
|
||||
import commonActions from "./commonActions";
|
||||
import exportActions from "./exportActions";
|
||||
|
||||
const ALL_CONTEXTUAL_ACTIONS = [
|
||||
...constraintActions,
|
||||
|
|
@ -16,7 +17,8 @@ const ACTIONS = [
|
|||
...constraintGlobalActions,
|
||||
...measureActions,
|
||||
...toolActions,
|
||||
...commonActions
|
||||
...commonActions,
|
||||
...exportActions
|
||||
//keep going here
|
||||
];
|
||||
|
||||
|
|
|
|||
29
web/app/sketcher/components/ExportDialog.jsx
Normal file
29
web/app/sketcher/components/ExportDialog.jsx
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
import React from 'react';
|
||||
import {useStreamWithUpdater} from "ui/effects";
|
||||
import Window from "../../../../modules/ui/components/Window";
|
||||
import Stack from "../../../../modules/ui/components/Stack";
|
||||
import {SketcherActionButton} from "./SketcherActionButton";
|
||||
|
||||
export function ExportDialog() {
|
||||
|
||||
const [request, setRequest] = useStreamWithUpdater(ctx => ctx.ui.$exportDialogRequest);
|
||||
|
||||
if (!request) {
|
||||
return null;
|
||||
}
|
||||
const x = request.x || 200;
|
||||
const y = request.y || 200;
|
||||
return <Window title='Format' initLeft={x} initTop={y}
|
||||
className='sketcher-window'
|
||||
onClose={() => setRequest(null)}>
|
||||
|
||||
<Stack style={style}>
|
||||
<div><SketcherActionButton actionId='ExportSVG' text={true}/></div>
|
||||
<div><SketcherActionButton actionId='ExportDXF' text={true}/></div>
|
||||
</Stack>
|
||||
</Window>
|
||||
}
|
||||
|
||||
const style = {
|
||||
fontSize: 12,
|
||||
};
|
||||
|
|
@ -52,12 +52,12 @@ function SketchList() {
|
|||
{items.map(item => <div key={item} style={listStyle} className='hover'
|
||||
onClick={() => app.openSketch(item)}>
|
||||
{item}
|
||||
{' '}
|
||||
<Button type='danger'><RiDeleteBinLine onClick={e => {
|
||||
|
||||
<Button style={{marginLeft: 5}} type='danger'><RiDeleteBinLine onClick={e => {
|
||||
e.stopPropagation();
|
||||
if (confirm("Selected sketch will be REMOVED! Are you sure?")) {
|
||||
localStorage.removeItem(App2D.STORAGE_PREFIX + item);
|
||||
setModification(m => m + 1);
|
||||
e.stopPropagation();
|
||||
}
|
||||
}}/> </Button>
|
||||
</div>)}
|
||||
|
|
|
|||
21
web/app/sketcher/components/SketcherActionButton.jsx
Normal file
21
web/app/sketcher/components/SketcherActionButton.jsx
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
import {getSketcherAction} from "../actions";
|
||||
import React, {useContext} from "react";
|
||||
import {SketcherAppContext} from "./SketcherApp";
|
||||
|
||||
export function SketcherActionButton({actionId, text=false}) {
|
||||
|
||||
const action = getSketcherAction(actionId);
|
||||
|
||||
if (!action) {
|
||||
return <span>?{actionId}?</span>;
|
||||
}
|
||||
|
||||
const ctx = useContext(SketcherAppContext);
|
||||
|
||||
const Icon = action.icon;
|
||||
|
||||
return <button onClick={e => action.invoke(ctx, e)} title={action.description} className={`action-kind-${action.kind} ${text ? 'icon-button' : ''}`}>
|
||||
{Icon && <Icon />} {(text || !Icon) && action.shortName}
|
||||
</button>;
|
||||
|
||||
}
|
||||
|
|
@ -12,6 +12,7 @@ import {Scope} from "./Scope";
|
|||
import {SketcherToolbar} from "./SketcherToolbar";
|
||||
import {sketcherRightToolbarConfig, sketcherTopToolbarConfig} from "../uiConfig";
|
||||
import {SketchManager} from "./SketchManager";
|
||||
import {ExportDialog} from "./ExportDialog";
|
||||
|
||||
export const SketcherAppContext = React.createContext({});
|
||||
|
||||
|
|
@ -33,7 +34,10 @@ export function SketcherApp({applicationContext}) {
|
|||
document.getElementById('top-toolbar')
|
||||
)}
|
||||
{ReactDOM.createPortal(
|
||||
<Scope><SketchManager /></Scope>,
|
||||
<React.Fragment>
|
||||
<Scope><SketchManager /></Scope>
|
||||
<Scope><ExportDialog /></Scope>
|
||||
</React.Fragment>,
|
||||
document.getElementById('global-windows')
|
||||
)}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
import React, {useContext} from 'react';
|
||||
import {getSketcherAction} from "../actions";
|
||||
import {SketcherAppContext} from "./SketcherApp";
|
||||
import React from 'react';
|
||||
import ls from './SketcherToolbar.less';
|
||||
import cx from 'classnames';
|
||||
import {SketcherActionButton} from "./SketcherActionButton";
|
||||
|
||||
export function SketcherToolbar({actions, horizontal=false, compact}) {
|
||||
|
||||
|
|
@ -15,21 +14,3 @@ export function SketcherToolbar({actions, horizontal=false, compact}) {
|
|||
})}
|
||||
</div>;
|
||||
}
|
||||
|
||||
export function SketcherActionButton({actionId}) {
|
||||
|
||||
const action = getSketcherAction(actionId);
|
||||
|
||||
if (!action) {
|
||||
return <span>?{actionId}?</span>;
|
||||
}
|
||||
|
||||
const ctx = useContext(SketcherAppContext);
|
||||
|
||||
const Icon = action.icon;
|
||||
|
||||
return <button onClick={e => action.invoke(ctx, e)} title={action.description} className={`action-kind-${action.kind}`}>
|
||||
{Icon ? <Icon /> : action.shortName}
|
||||
</button>;
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,8 @@ import diff_match_patch from 'diff-match-patch';
|
|||
function HistoryManager(viewer) {
|
||||
this.viewer = viewer;
|
||||
this.dmp = new diff_match_patch();
|
||||
this.init(this.viewer.io.serializeSketch());
|
||||
this.init({});
|
||||
// this.init(this.viewer.io.serializeSketch());
|
||||
}
|
||||
|
||||
HistoryManager.prototype.init = function(sketchData) {
|
||||
|
|
|
|||
|
|
@ -15,10 +15,6 @@ function App2D() {
|
|||
this.winManager = new ui.WinManager();
|
||||
this.inputManager = new InputManager(this);
|
||||
|
||||
this._exportWin = new ui.Window($('#exportManager'), app.winManager);
|
||||
|
||||
$('#exportManager li').click(function() {ui.closeWin(app._exportWin);});
|
||||
|
||||
this.constraintFilter = {};
|
||||
this.actions = {};
|
||||
this.commands = {};
|
||||
|
|
@ -72,14 +68,6 @@ function App2D() {
|
|||
app.viewer.refresh();
|
||||
});
|
||||
|
||||
this.registerAction('exportSVG', "Export To SVG", function () {
|
||||
IO.exportTextData(app.viewer.io.svgExport(), app.getSketchId() + ".ui.styles.init.svg");
|
||||
});
|
||||
|
||||
this.registerAction('exportDXF', "Export To DXF", function () {
|
||||
IO.exportTextData(app.viewer.io.dxfExport(), app.getSketchId() + ".dxf");
|
||||
});
|
||||
|
||||
this.registerAction('undo', "Undo", function () {
|
||||
app.viewer.historyManager.undo();
|
||||
});
|
||||
|
|
@ -261,7 +249,8 @@ function createAppContext(viewer, app) {
|
|||
ui: {
|
||||
$constraintEditRequest: stream(),
|
||||
$wizardRequest: stream(),
|
||||
$sketchManagerRequest: stream()
|
||||
$sketchManagerRequest: stream(),
|
||||
$exportDialogRequest: stream()
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -80,6 +80,10 @@ html, body {
|
|||
padding-left: 5px;
|
||||
}
|
||||
|
||||
.dock-node {
|
||||
border-bottom: 1px solid black;
|
||||
}
|
||||
|
||||
.selected {
|
||||
background-color: #333;
|
||||
color: #ccc;
|
||||
|
|
@ -190,7 +194,6 @@ html, body {
|
|||
}
|
||||
|
||||
.sketcher-window {
|
||||
background: #666;
|
||||
border: 5px solid #444444;
|
||||
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
<span class="logo" style="float:left">sketcher <sup> 2D</sup></span>
|
||||
<div style="display: flex" id="top-toolbar"></div>
|
||||
</div>
|
||||
<div style="width: 100%; height: calc(100% - 59px); display: flex;">
|
||||
<div style="width: 100%; height: calc(100% - 65px); display: flex;">
|
||||
|
||||
<div id="dock" class="panel b-right scroll" style="width: 245px; height: 100%; flex-shrink: 0;"></div>
|
||||
|
||||
|
|
@ -32,7 +32,6 @@
|
|||
|
||||
<div id="status" class="panel b-top" style="width: 100%; height:22px;">
|
||||
<div class="button-group" style="float: left">
|
||||
<span id='showActions' class="dock-btn" ><i class="fa fa-slack"></i></span>
|
||||
</div>
|
||||
<div class="status-item coordinates-info">0.000:0.000</div>
|
||||
<div class="status-item tool-info"></div>
|
||||
|
|
@ -41,22 +40,6 @@
|
|||
<div style="width: 0; height: 0" id="global-windows">
|
||||
</div>
|
||||
|
||||
<div id="actions" class="scroll win" style="display: none;">
|
||||
<div class="tool-caption" >ACTIONS</div>
|
||||
<div class="content">
|
||||
<div><input class="btn txt-btn" style="width: 100%;" type="submit" value="$value$"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="exportManager" class="scroll win" style="display: none;">
|
||||
<div class="tool-caption" >FORMAT</div>
|
||||
<div class="content panel" style="padding: 0;">
|
||||
<ul class="tlist">
|
||||
<li class="act-exportSVG">SVG</li>
|
||||
<li class="act-exportDXF">DXF</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="commands" class="win" style="display: none; height: 200px; width: 700px;">
|
||||
<div class="tool-caption" >COMMANDS</div>
|
||||
|
|
|
|||
Loading…
Reference in a new issue