From 917dca85ce548528accb0250a27e9cb1e725fade Mon Sep 17 00:00:00 2001 From: Val Erastov Date: Sun, 18 Feb 2018 22:09:13 -0800 Subject: [PATCH] refactor and fix brep debugger action --- modules/bus/index.js | 4 +- modules/bus/store.js | 2 +- modules/scene/sceneGraph.js | 9 ++++ modules/ui/WindowSystem.jsx | 37 +++++++++----- modules/ui/components/Window.jsx | 50 +++++++++++++++---- modules/ui/components/Window.less | 8 +++ modules/ui/connect.jsx | 2 + .../debug/debugger/BrepDebuggerWindow.jsx | 45 +++++++++++++++++ .../debug/debugger/BrepDebuggerWindow.less | 11 ++++ web/app/brep/debug/debugger/brepDebugger.less | 21 -------- web/app/cad/debugPlugin.js | 39 ++++----------- .../dom/components/ContributedComponents.jsx | 29 +++++++++++ web/app/cad/dom/components/UISystem.jsx | 7 ++- web/app/cad/dom/domPlugin.js | 5 +- web/app/cad/legacy/mesh/wizards/revolve.js | 2 +- 15 files changed, 193 insertions(+), 78 deletions(-) create mode 100644 web/app/brep/debug/debugger/BrepDebuggerWindow.jsx create mode 100644 web/app/brep/debug/debugger/BrepDebuggerWindow.less create mode 100644 web/app/cad/dom/components/ContributedComponents.jsx diff --git a/modules/bus/index.js b/modules/bus/index.js index 933db7e7..8fc68694 100644 --- a/modules/bus/index.js +++ b/modules/bus/index.js @@ -18,7 +18,7 @@ export default class Bus { return callback; }; - unSubscribe(key, callback) { + unsubscribe(key, callback) { const listenerList = this.listeners[key]; for (let i = 0; i < listenerList.length; i++) { if (listenerList[i] === callback) { @@ -51,7 +51,7 @@ export default class Bus { } disconnectFromState(connection) { - this.stateConnections.get(connection).forEach(token => this.unSubscribe(token, connection)); + this.stateConnections.get(connection).forEach(token => this.unsubscribe(token, connection)); this.stateConnections.delete(connection); } diff --git a/modules/bus/store.js b/modules/bus/store.js index a55a4ab3..758ba412 100644 --- a/modules/bus/store.js +++ b/modules/bus/store.js @@ -17,7 +17,7 @@ export class Store { return callback; }; - unSubscribe(key, callback) { + unsubscribe(key, callback) { const listenerList = this.listeners[key]; for (let i = 0; i < listenerList.length; i++) { if (listenerList[i] === callback) { diff --git a/modules/scene/sceneGraph.js b/modules/scene/sceneGraph.js index dd5c2a2c..cce8cc38 100644 --- a/modules/scene/sceneGraph.js +++ b/modules/scene/sceneGraph.js @@ -11,5 +11,14 @@ export function createGroup() { return new THREE.Object3D(); } +export function clearGroup(group) { + while (group.children.length) { + const o = group.children[0]; + clearGroup(o); + o.material.dispose(); + o.geometry.dispose(); + group.remove(o); + } +} diff --git a/modules/ui/WindowSystem.jsx b/modules/ui/WindowSystem.jsx index 8df09111..9c92c0f6 100644 --- a/modules/ui/WindowSystem.jsx +++ b/modules/ui/WindowSystem.jsx @@ -1,25 +1,38 @@ import React from 'react'; +import PropTypes from 'prop-types'; export default class WindowSystem extends React.Component { constructor() { super(); - this.state = { - windows: [] - } + this.moveHandler = null; + } + + componentDidMount() { + document.body.onmousemove = e => { + if (this.moveHandler !== null) { + this.moveHandler(e); + } + }; + } + + componentWillUnMount() { } render() { - return this.state.windows; - } - - addWindow(window) { - this.setState({windows: [...this.state.windows, window]}); + return this.props.children; } - removeWindow(window) { - let windows = [...this.state.windows]; - windows.splice(windows.indexOf(window), 1); - this.setState({windows}); + childContext = { + setWindowMoveHandler: moveHandler => this.moveHandler = moveHandler + }; + + getChildContext() { + return this.childContext; } + + static childContextTypes = { + setWindowMoveHandler: PropTypes.func + } + } diff --git a/modules/ui/components/Window.jsx b/modules/ui/components/Window.jsx index ad798173..4e6234c7 100644 --- a/modules/ui/components/Window.jsx +++ b/modules/ui/components/Window.jsx @@ -1,31 +1,38 @@ import React from 'react'; -import PropTypes from 'prop-types'; import ls from './Window.less' import Fa from "./Fa"; +import WindowSystem from '../WindowSystem'; +import cx from 'classnames'; + export default class Window extends React.Component { - constructor({initWidth, initLeft, initTop}) { + constructor({initWidth, initLeft, initTop, initHeight}) { super(); this.state = { width: initWidth, + height: initHeight, left: initLeft, top: initTop - } + }; + this.dragOrigin = null; } render() { - let {initWidth, initLeft, initTop, setFocus, children, title, minimizable, onClose, ...props} = this.props; - return
-
-
{title.toUpperCase()}
+ let {initWidth, initHeight, initLeft, initTop, setFocus, className, + children, title, icon, minimizable, onClose, ...props} = this.props; + return
+
+
{icon}{title.toUpperCase()}
{minimizable && _} +
+
+ {children}
- {children}
} @@ -35,8 +42,7 @@ export default class Window extends React.Component { width: this.state.width, height: this.state.height, left: this.state.left, - top: this.state.top, - zIndex: 1 + top: this.state.top } } @@ -47,9 +53,33 @@ export default class Window extends React.Component { this.el.focus(); } } + + startDrag = e => { + this.dragOrigin = {x : e.pageX, y : e.pageY}; + this.originLocation = { + left: this.state.left, + top: this.state.top + }; + this.context.setWindowMoveHandler(this.doDrag); + }; + doDrag = e => { + if (this.dragOrigin) { + let dx = e.pageX - this.dragOrigin.x; + let dy = e.pageY - this.dragOrigin.y; + this.setState({left : this.originLocation.left + dx, top : this.originLocation.top + dy}); + } + }; + + stopDrag = e => { + this.dragOrigin = null; + this.context.setWindowMoveHandler(null); + }; + keepRef = el => this.el = el; + static contextTypes = WindowSystem.childContextTypes; + } Window.defaultProps = { diff --git a/modules/ui/components/Window.less b/modules/ui/components/Window.less index 33fb2ba5..44bd8c19 100644 --- a/modules/ui/components/Window.less +++ b/modules/ui/components/Window.less @@ -3,7 +3,10 @@ .root { position: absolute; + z-index: 1; background-color: @bg-color-alt; + display: flex; + flex-direction: column; } .bar { @@ -22,3 +25,8 @@ padding: 0.6rem 0.5rem 0.6rem 0.5rem; .button-behavior(@color-danger); } + +.content { + overflow-y: auto; + flex-grow: 1; +} diff --git a/modules/ui/connect.jsx b/modules/ui/connect.jsx index a7638c09..9be91bd5 100644 --- a/modules/ui/connect.jsx +++ b/modules/ui/connect.jsx @@ -1,6 +1,8 @@ import React from 'react'; import PropTypes from 'prop-types'; +export const PROPAGATE_SELF_PROPS = v => v; + export default function connect(WrappedComponent, tokens, config) { if (!config) { config = DEFAULT_CONFIG; diff --git a/web/app/brep/debug/debugger/BrepDebuggerWindow.jsx b/web/app/brep/debug/debugger/BrepDebuggerWindow.jsx new file mode 100644 index 00000000..2fc78484 --- /dev/null +++ b/web/app/brep/debug/debugger/BrepDebuggerWindow.jsx @@ -0,0 +1,45 @@ +import React from 'react'; +import Window from 'ui/components/Window'; +import BrepDebugger from './brepDebugger'; +import connect, {PROPAGATE_SELF_PROPS} from 'ui/connect'; +import {addToGroup, clearGroup, createGroup, removeFromGroup} from 'scene/sceneGraph'; +import {createToken} from 'bus'; +import Fa from 'ui/components/Fa'; + +import ls from './BrepDebuggerWindow.less'; + +export const BREP_DEBUG_WINDOW_VISIBLE = createToken('debug', 'brepDebugWindowVisible') + +class BrepDebuggerWindow extends React.Component { + + componentWillMount() { + this.brepDebugGroup = createGroup(); + addToGroup(this.props.auxGroup, this.brepDebugGroup); + } + + componentWillUnmount() { + clearGroup(); + removeFromGroup(this.props.auxGroup, this.brepDebugGroup); + } + + render() { + if (!this.props.visible) { + return null; + } + return } + title='Brep Debugger' + className={ls.root} + onClose={this.props.close}> + + ; + } +} + +export default connect(BrepDebuggerWindow, BREP_DEBUG_WINDOW_VISIBLE, { + mapProps: ([visible]) => ({visible}), + mapActions: ({dispatch}) => ({ + close: () => dispatch(BREP_DEBUG_WINDOW_VISIBLE, false) + }), + mapSelfProps: PROPAGATE_SELF_PROPS +}); \ No newline at end of file diff --git a/web/app/brep/debug/debugger/BrepDebuggerWindow.less b/web/app/brep/debug/debugger/BrepDebuggerWindow.less new file mode 100644 index 00000000..04ccb7ea --- /dev/null +++ b/web/app/brep/debug/debugger/BrepDebuggerWindow.less @@ -0,0 +1,11 @@ +.root { + z-index: 998; + border: 2px solid rgb(49, 121, 255); + box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5); + + & :global(.x-Window-content) { + font-size: 1.2rem; + background: #eee; + color: #1a1a1a; + } +} diff --git a/web/app/brep/debug/debugger/brepDebugger.less b/web/app/brep/debug/debugger/brepDebugger.less index 8c184e7d..26cd9592 100644 --- a/web/app/brep/debug/debugger/brepDebugger.less +++ b/web/app/brep/debug/debugger/brepDebugger.less @@ -1,24 +1,3 @@ -:global -#brep-debugger { - font-size: 1.2rem; - position: absolute; - z-index: 998; - left:10px; - top:10px; - bottom: 20px; - overflow: auto; - background: #eee; - border: 5px solid rgb(49, 121, 255); - box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5); - color: #1a1a1a; - & .tool-caption { - padding: 0.4rem; - background-color: rgb(238, 255, 246); - cursor: default; - user-select: none - } -} - :global .brep-debugger { diff --git a/web/app/cad/debugPlugin.js b/web/app/cad/debugPlugin.js index 8946021b..8296421b 100644 --- a/web/app/cad/debugPlugin.js +++ b/web/app/cad/debugPlugin.js @@ -1,18 +1,16 @@ -import {checkForSelectedFaces} from './actions/actionHelpers' -import {nurbsToThreeGeom, triangulateToThree} from './scene/wrappers/brepSceneObject' -import {createSolidMaterial} from './scene/wrappers/sceneObject' -import DPR from 'dpr' +import {checkForSelectedFaces} from './actions/actionHelpers'; +import {nurbsToThreeGeom, triangulateToThree} from './scene/wrappers/brepSceneObject'; +import {createSolidMaterial} from './scene/wrappers/sceneObject'; +import DPR from 'dpr'; import Vector from 'math/vector'; -import * as ui from '../ui/ui'; import React from 'react'; -import ReactDOM from 'react-dom'; -import BrepDebugger from './../brep/debug/debugger/brepDebugger'; -import {TOKENS as UI_TOKENS} from "./dom/uiEntryPointsPlugin"; -import {IO} from '../sketcher/io'; +import {TOKENS as UI_TOKENS} from './dom/uiEntryPointsPlugin'; import {readSketchFloat} from './sketch/sketchReader'; import {TOKENS as CRAFT_TOKENS} from './craft/craftPlugin'; import {toLoops} from '../brep/brep-io'; +import {contributeComponent} from './dom/components/ContributedComponents'; +import BrepDebuggerWindow, {BREP_DEBUG_WINDOW_VISIBLE} from '../brep/debug/debugger/BrepDebuggerWindow'; export function activate({bus, services}) { @@ -20,6 +18,8 @@ export function activate({bus, services}) { services.action.registerActions(DebugActions); services.menu.registerMenus([DebugMenuConfig]); bus.updateState(UI_TOKENS.CONTROL_BAR_LEFT, actions => [...actions, 'menu.debug']); + bus.enableState(BREP_DEBUG_WINDOW_VISIBLE, false); + contributeComponent(); } function addGlobalDebugActions({viewer, cadScene, cadRegistry}) { @@ -384,25 +384,8 @@ const DebugActions = [ label: 'open BREP debugger', info: 'open the BREP debugger in a window', }, - invoke: ({services: {cadScene}}) => { - // require('../brep/debug/debugger/brepDebugger.less'); - let debuggerWinDom = document.getElementById('brep-debugger'); - if (!debuggerWinDom) { - //Temporary hack until win infrastructure is done for 3d - debuggerWinDom = document.createElement('div'); - debuggerWinDom.setAttribute('id', 'brep-debugger'); - debuggerWinDom.innerHTML = '
Brep Debugger
'; - document.body.appendChild(debuggerWinDom); - debuggerWinDom.debuggerWin = new ui.Window($(debuggerWinDom), new ui.WinManager()); - let brepDebugGroup = new THREE.Object3D(); - cadScene.auxGroup.add(brepDebugGroup); - - ReactDOM.render( - , - debuggerWinDom.getElementsByClassName('content')[0] - ); - } - debuggerWinDom.debuggerWin.show(); + invoke: ({bus}) => { + bus.dispatch(BREP_DEBUG_WINDOW_VISIBLE, true); } } diff --git a/web/app/cad/dom/components/ContributedComponents.jsx b/web/app/cad/dom/components/ContributedComponents.jsx new file mode 100644 index 00000000..043c5b00 --- /dev/null +++ b/web/app/cad/dom/components/ContributedComponents.jsx @@ -0,0 +1,29 @@ +import React from 'react'; + +const CONTRIBUTED_COMPONENTS = []; + +const mounted = new Set(); + +export default class ContributedComponents extends React.Component { + + + componentDidMount() { + mounted.add(this); + } + + + componentWillUnmount() { + mounted.delete(this); + } + + render() { + return CONTRIBUTED_COMPONENTS; + } +} + + + +export function contributeComponent(comp) { + CONTRIBUTED_COMPONENTS.push(comp); + mounted.forEach(c => c.forceUpdate()); +} \ No newline at end of file diff --git a/web/app/cad/dom/components/UISystem.jsx b/web/app/cad/dom/components/UISystem.jsx index e19af091..bcf900b8 100644 --- a/web/app/cad/dom/components/UISystem.jsx +++ b/web/app/cad/dom/components/UISystem.jsx @@ -5,6 +5,7 @@ import {TOKENS as MENU_TOKENS} from '../menu/menuPlugin'; import WindowSystem from 'ui/WindowSystem'; import ActionInfo from '../actionInfo/ActionInfo'; +import ContributedComponents from './ContributedComponents'; export default class UISystem extends React.Component { @@ -12,8 +13,10 @@ export default class UISystem extends React.Component { return
- - {this.props.children} + + {this.props.children} + +
} diff --git a/web/app/cad/dom/domPlugin.js b/web/app/cad/dom/domPlugin.js index c4246be2..99a169bc 100644 --- a/web/app/cad/dom/domPlugin.js +++ b/web/app/cad/dom/domPlugin.js @@ -1,8 +1,11 @@ import {TOKENS as APP_TABS_TOKENS} from "./appTabsPlugin"; +import {contributeComponent} from './components/ContributedComponents'; export function activate({bus, services}) { + services.dom = { - viewerContainer: document.getElementById('viewer-container') + viewerContainer: document.getElementById('viewer-container'), + contributeComponent }; bus.subscribe(APP_TABS_TOKENS.TABS, ({activeTab}) => { diff --git a/web/app/cad/legacy/mesh/wizards/revolve.js b/web/app/cad/legacy/mesh/wizards/revolve.js index 36860c58..3b114386 100644 --- a/web/app/cad/legacy/mesh/wizards/revolve.js +++ b/web/app/cad/legacy/mesh/wizards/revolve.js @@ -145,7 +145,7 @@ RevolveWizard.prototype.createRequest = function(done) { }; RevolveWizard.prototype.dispose = function() { - this.app.bus.unSubscribe('selection-sketch-object', this.selectionListener); + this.app.bus.unsubscribe('selection-sketch-object', this.selectionListener); OpWizard.prototype.dispose.call(this); };