use redux to manage dialog
parent
69b2fff6d1
commit
53ad7c97e9
|
@ -153,6 +153,7 @@ class Sketch {
|
|||
|
||||
|
||||
activate() {
|
||||
console.log('activatee')
|
||||
window.addEventListener('keydown', this.onKeyPress)
|
||||
this.canvas.addEventListener('pointerdown', this.onPick)
|
||||
this.canvas.addEventListener('pointermove', this.onHover)
|
||||
|
|
|
@ -10,8 +10,8 @@ body {
|
|||
height: 100%;
|
||||
font-family: sans-serif;
|
||||
overflow: hidden;
|
||||
--topNavH: 48px;
|
||||
--sideNavW: 240px;
|
||||
--topNavH: 3rem;
|
||||
--sideNavW: 15rem;
|
||||
}
|
||||
|
||||
#c {
|
||||
|
@ -38,8 +38,10 @@ body {
|
|||
|
||||
.dialog {
|
||||
position: absolute;
|
||||
top: var(--topNavH);
|
||||
left: var(--sideNavW);
|
||||
height: var(--topNavH);
|
||||
left:0;
|
||||
right:0;
|
||||
top:0;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -2,15 +2,15 @@
|
|||
import ReactDOM from 'react-dom'
|
||||
import React, { useState } from 'react'
|
||||
|
||||
import { createStore, applyMiddleware} from 'redux'
|
||||
import { createStore, applyMiddleware } from 'redux'
|
||||
import { Provider } from 'react-redux'
|
||||
import { reducer } from './reducer'
|
||||
import logger from 'redux-logger'
|
||||
|
||||
import { Tree } from './tree'
|
||||
import { NavBar } from './navBar'
|
||||
import { ToolTip} from './toolTip'
|
||||
import { Dialog } from './dialog'
|
||||
import { ToolTip } from './toolTip'
|
||||
|
||||
|
||||
import './app.css'
|
||||
|
||||
|
@ -31,14 +31,15 @@ const preloadedState = {
|
|||
const store = createStore(reducer, {}, applyMiddleware(logger))
|
||||
// const store = createStore(reducer, sc.loadState(), applyMiddleware(logger))
|
||||
|
||||
|
||||
const App = ({ store }) => {
|
||||
const [dialog, setDialog] = useState()
|
||||
|
||||
|
||||
return <Provider store={store}>
|
||||
<NavBar setDialog={setDialog}/>
|
||||
|
||||
<NavBar />
|
||||
<Tree />
|
||||
<Dialog {...{dialog, setDialog}}/>
|
||||
<ToolTip/>
|
||||
<ToolTip />
|
||||
</Provider>
|
||||
};
|
||||
|
||||
|
|
|
@ -3,64 +3,71 @@
|
|||
import React, { useEffect, useReducer, useRef, useState } from 'react';
|
||||
|
||||
import { useDispatch, useSelector } from 'react-redux'
|
||||
|
||||
import { MdDone, MdClose } from 'react-icons/md'
|
||||
import { GiVerticalFlip } from 'react-icons/gi'
|
||||
import * as Icon from "./icons";
|
||||
|
||||
|
||||
export const Dialog = ({ dialog, setDialog }) => {
|
||||
if (!dialog) return null
|
||||
|
||||
|
||||
export const Dialog = () => {
|
||||
|
||||
const dialog = useSelector(state => state.ui.dialog)
|
||||
const dispatch = useDispatch()
|
||||
const treeEntriesById = useSelector(state => state.treeEntries.byId)
|
||||
const activeSketchId = useSelector(state => state.treeEntries.activeSketchId)
|
||||
|
||||
const ref = useRef()
|
||||
|
||||
useEffect(() => {
|
||||
if (!ref.current) return
|
||||
ref.current.focus()
|
||||
}, [])
|
||||
}, [dialog])
|
||||
|
||||
const extrude = () => {
|
||||
let sketch
|
||||
if (sc.activeSketch) {
|
||||
sketch = sc.activeSketch
|
||||
} else if (sc.selected.length === 1 && sc.selected[0].userData.type == 'sketch') {
|
||||
sketch = treeEntriesById[sc.selected[0].name]
|
||||
} else {
|
||||
console.log('invalid selection')
|
||||
return
|
||||
}
|
||||
|
||||
setDialog(null)
|
||||
sc.extrude(sketch, ref.current.value)
|
||||
|
||||
sc.extrude(dialog.target, ref.current.value)
|
||||
sc.render()
|
||||
forceUpdate()
|
||||
}
|
||||
|
||||
dispatch({ type: "clear-dialog" })
|
||||
forceUpdate()
|
||||
|
||||
}
|
||||
|
||||
const [_, forceUpdate] = useReducer(x => x + 1, 0);
|
||||
|
||||
return <div className='dialog w-40 h-10 flex items-center bg-gray-700'>
|
||||
{/* return <div className='w-40 h-full flex items-center bg-gray-700'> */}
|
||||
<input className='w-1/2' type="number" {...useNumField(1)} step="0.1" ref={ref} />
|
||||
<Icon.Flip className="btn w-auto h-full p-2"
|
||||
onClick={() => ref.current.value *= -1}
|
||||
/>
|
||||
<MdDone
|
||||
className="btn w-auto h-full p-2"
|
||||
onClick={extrude}
|
||||
/>
|
||||
<MdClose className="btn w-auto h-full p-2"
|
||||
onClick={() => setDialog(null)}
|
||||
/>
|
||||
</div>
|
||||
switch (dialog.action) {
|
||||
case 'extrude':
|
||||
return <>
|
||||
<input className='w-1/2' type="number" defaultValue="1" step="0.1" ref={ref} />
|
||||
<Icon.Flip className="btn w-auto h-full p-2"
|
||||
onClick={() => ref.current.value *= -1}
|
||||
/>
|
||||
<MdDone
|
||||
className="btn w-auto h-full p-2"
|
||||
onClick={extrude}
|
||||
/>
|
||||
<MdClose className="btn w-auto h-full p-2"
|
||||
onClick={() => dispatch({ type: "clear-dialog" })}
|
||||
/>
|
||||
</>
|
||||
case 'sketch':
|
||||
return <>
|
||||
<MdDone
|
||||
className="btn w-auto h-full p-2"
|
||||
onClick={() => {
|
||||
// dispatch({ type: 'update-descendents', sketch})
|
||||
sc.activeSketch.deactivate()
|
||||
sc.render()
|
||||
forceUpdate()
|
||||
}}
|
||||
/>
|
||||
<MdClose className="btn w-auto h-full p-2"
|
||||
onClick={() => dispatch({ type: "clear-dialog" })}
|
||||
/>
|
||||
</>
|
||||
default:
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export const useNumField = (initValue = 0) => {
|
||||
const [value, setValue] = useState(initValue);
|
||||
const onChange = e => setValue(e.target.value);
|
||||
return { value, onChange };
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -7,12 +7,12 @@ import { useDispatch, useSelector } from 'react-redux'
|
|||
import { FaEdit } from 'react-icons/fa'
|
||||
import { MdDone, MdSave, MdFolder } from 'react-icons/md'
|
||||
import * as Icon from "./icons";
|
||||
import { Dialog } from './dialog'
|
||||
|
||||
|
||||
export const NavBar = ({ setDialog }) => {
|
||||
export const NavBar = () => {
|
||||
const dispatch = useDispatch()
|
||||
const activeSketchId = useSelector(state => state.treeEntries.activeSketchId)
|
||||
|
||||
const treeEntriesById = useSelector(state => state.treeEntries.byId)
|
||||
|
||||
const boolOp = (code) => {
|
||||
if (sc.selected.length != 2 || !sc.selected.every(e => e.userData.type == 'mesh')) return
|
||||
|
@ -21,11 +21,11 @@ export const NavBar = ({ setDialog }) => {
|
|||
sc.render()
|
||||
forceUpdate()
|
||||
}
|
||||
const extrude = () => { setDialog(true) }
|
||||
|
||||
const addSketch = () => {
|
||||
sc.addSketch()
|
||||
console.log(!!sc.activeSketch, 'state')
|
||||
dispatch({ type: 'set-dialog', action: 'sketch' })
|
||||
|
||||
forceUpdate()
|
||||
}
|
||||
|
||||
|
@ -45,14 +45,18 @@ export const NavBar = ({ setDialog }) => {
|
|||
// }, [treeEntriesById])
|
||||
|
||||
|
||||
const btnz = [
|
||||
[MdDone, () => {
|
||||
const sketchModeButtons = [
|
||||
// [MdDone, () => {
|
||||
// // dispatch({ type: 'update-descendents', sketch})
|
||||
|
||||
// sc.activeSketch.deactivate()
|
||||
// sc.render()
|
||||
// forceUpdate()
|
||||
// }, 'Finish'],
|
||||
[Icon.Extrude, () => {
|
||||
sc.activeSketch.deactivate()
|
||||
// dispatch({ type: 'update-descendents', sketch})
|
||||
sc.render()
|
||||
forceUpdate()
|
||||
}, 'Finish'],
|
||||
[Icon.Extrude, extrude, 'Extrude [e]'],
|
||||
dispatch({ type: 'set-dialog', action: 'extrude', target: sc.activeSketch })
|
||||
}, 'Extrude [e]'],
|
||||
[Icon.Dimension, () => sc.activeSketch.command('d'), 'Dimension [d]'],
|
||||
[Icon.Line, () => sc.activeSketch.command('l'), 'Line [l]'],
|
||||
[Icon.Arc, () => sc.activeSketch.command('a'), 'Arc [a]'],
|
||||
|
@ -63,9 +67,12 @@ export const NavBar = ({ setDialog }) => {
|
|||
]
|
||||
|
||||
|
||||
const btnz2 = [
|
||||
const partModeButtons = [
|
||||
[FaEdit, addSketch, 'Sketch [s]'],
|
||||
[Icon.Extrude, extrude, 'Extrude [e]'],
|
||||
[Icon.Extrude, () => {
|
||||
dispatch({ type: 'set-dialog', action: 'extrude', target: treeEntriesById[sc.selected[0].name] })
|
||||
}, 'Extrude [e]'],
|
||||
|
||||
[Icon.Union, () => boolOp('u'), 'Union'],
|
||||
[Icon.Subtract, () => boolOp('s'), 'Subtract'],
|
||||
[Icon.Intersect, () => boolOp('i'), 'Intersect'],
|
||||
|
@ -77,19 +84,26 @@ export const NavBar = ({ setDialog }) => {
|
|||
const [_, forceUpdate] = useReducer(x => x + 1, 0);
|
||||
|
||||
return <div className='topNav flex justify-center items-center bg-gray-700'>
|
||||
|
||||
<div className='w-40 h-full flex items-center mr-12'>
|
||||
<Dialog />
|
||||
</div>
|
||||
{
|
||||
activeSketchId ?
|
||||
btnz.map(([Icon, fcn, txt, shortcut], idx) => (
|
||||
sketchModeButtons.map(([Icon, fcn, txt, shortcut], idx) => (
|
||||
<Icon className="btn w-auto h-full p-3.5" tooltip={txt}
|
||||
onClick={fcn} key={idx}
|
||||
/>
|
||||
))
|
||||
:
|
||||
btnz2.map(([Icon, fcn, txt, shortcut], idx) => (
|
||||
partModeButtons.map(([Icon, fcn, txt, shortcut], idx) => (
|
||||
<Icon className="btn w-auto h-full p-3.5" tooltip={txt}
|
||||
onClick={fcn} key={idx}
|
||||
/>
|
||||
))
|
||||
}
|
||||
<div className='w-40 h-full flex items-center'>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
}
|
||||
}
|
|
@ -82,9 +82,25 @@ export function treeEntries(state = defaultState, action) {
|
|||
}
|
||||
}
|
||||
|
||||
export function ui(state = {dialog:{}}, action) {
|
||||
switch (action.type) {
|
||||
|
||||
case 'set-dialog':
|
||||
return update(state, {
|
||||
dialog: { $set: { target: action.target, action: action.action } },
|
||||
})
|
||||
case 'clear-dialog':
|
||||
return update(state, {
|
||||
dialog: { $set: {} },
|
||||
})
|
||||
default:
|
||||
return state
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
export const reducer = combineReducers({
|
||||
ui,
|
||||
treeEntries
|
||||
})
|
|
@ -13,7 +13,7 @@ export const Tree = () => {
|
|||
|
||||
return <div className='sideNav flex flex-col bg-gray-800'>
|
||||
{treeEntries.allIds.map((entId, idx) => (
|
||||
<TreeEntry key={idx} entId={entId} />
|
||||
<TreeEntry key={idx} entId={entId}/>
|
||||
))}
|
||||
</div>
|
||||
|
||||
|
@ -28,6 +28,8 @@ const treeIcons = {
|
|||
|
||||
const TreeEntry = ({ entId }) => {
|
||||
|
||||
|
||||
|
||||
const state = useSelector(state => state.treeEntries)
|
||||
const treeEntries = useSelector(state => state.treeEntries.byId)
|
||||
const dispatch = useDispatch()
|
||||
|
@ -54,6 +56,7 @@ const TreeEntry = ({ entId }) => {
|
|||
sketch.activate()
|
||||
sc.clearSelection()
|
||||
sc.activeSketch = sketch;
|
||||
dispatch({ type: 'set-dialog', action: 'sketch' })
|
||||
sc.render()
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue