mirror of
https://github.com/xibyte/jsketcher
synced 2025-12-26 18:33:04 +01:00
operation history wizard
This commit is contained in:
parent
f3f7354033
commit
9e5933fbe1
14 changed files with 107 additions and 31 deletions
|
|
@ -26,7 +26,7 @@ export default class Folder extends React.Component{
|
|||
let {title, closable, children} = this.props;
|
||||
return <div className={ls.root}>
|
||||
<div className={ls.title} onClick={closable ? this.tweakClose : null}>
|
||||
<Fa fw icon={this.isClosed() ? 'chevron-right' : 'chevron-down'}/>
|
||||
<span className={ls.handle}><Fa fw icon={this.isClosed() ? 'chevron-right' : 'chevron-down'}/></span>
|
||||
{title}
|
||||
</div>
|
||||
{!this.isClosed() && children}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,17 @@
|
|||
@import "~ui/styles/theme";
|
||||
|
||||
.root {
|
||||
background-color: @bg-color-alt;
|
||||
}
|
||||
|
||||
.title {
|
||||
border-bottom: 1px solid @border-color;
|
||||
background-color: @bg-color;
|
||||
padding: 0.3rem 0.6rem;
|
||||
line-height: 1.7;
|
||||
}
|
||||
|
||||
.handle {
|
||||
font-size: 0.8rem;
|
||||
color: @font-color-suppressed;
|
||||
}
|
||||
|
|
@ -6,10 +6,6 @@ export default function Stack({children}) {
|
|||
return <div className={ls.root}>{children}</div>
|
||||
}
|
||||
|
||||
Window.defaultProps = {
|
||||
type: 'neutral',
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -2,8 +2,7 @@
|
|||
@import '../styles/mixins';
|
||||
|
||||
.root > * {
|
||||
|
||||
border-bottom: 1px solid @border-color;
|
||||
padding: 0.3rem 0.6rem;
|
||||
|
||||
line-height: 1.7;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ export default class Window extends React.Component {
|
|||
}
|
||||
|
||||
render() {
|
||||
let {initWidth, initLeft, initTop, children, title, minimizable, onClose, ...props} = this.props;
|
||||
let {initWidth, initLeft, initTop, setFocus, children, title, minimizable, onClose, ...props} = this.props;
|
||||
return <div className={ls.root} style={this.getStyle()} {...props} ref={this.keepRef}>
|
||||
<div className={ls.bar + ' disable-selection'}>
|
||||
<div><b>{title.toUpperCase()}</b></div>
|
||||
|
|
@ -41,8 +41,8 @@ export default class Window extends React.Component {
|
|||
}
|
||||
|
||||
componentDidMount() {
|
||||
if (this.props.onFocus) {
|
||||
this.props.onFocus(this.el);
|
||||
if (this.props.setFocus) {
|
||||
this.props.setFocus(this.el);
|
||||
} else {
|
||||
this.el.focus();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,5 +2,4 @@
|
|||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: baseline;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
|
@ -1,8 +1,12 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
export default function connect(WrappedComponent, tokens, {staticProps, mapProps, mapActions, mapSelfProps}) {
|
||||
|
||||
export default function connect(WrappedComponent, tokens, config) {
|
||||
if (!config) {
|
||||
config = DEFAULT_CONFIG;
|
||||
}
|
||||
let {staticProps, mapProps, mapActions, mapSelfProps} = config;
|
||||
|
||||
mapProps = createMapper(mapProps);
|
||||
|
||||
mapActions = mapActions || function({dispatch}) {
|
||||
|
|
@ -82,6 +86,8 @@ function createMapper(mapper, comp) {
|
|||
return mapper;
|
||||
}
|
||||
|
||||
const DEFAULT_CONFIG = {};
|
||||
|
||||
export function DEFAULT_MAPPER(state) {
|
||||
let props = {};
|
||||
state.forEach(stateItem => Object.assign(props, stateItem));
|
||||
|
|
|
|||
|
|
@ -14,8 +14,8 @@ export function activate({bus, services}) {
|
|||
bus.subscribe(TOKENS.HISTORY_POINTER, (pointer) => {
|
||||
let history = getHistory();
|
||||
if (pointer < history.length) {
|
||||
resetInternal(history.slice(0, pointer));
|
||||
bus.setState(TOKENS.MODIFICATIONS, {pointer});
|
||||
reset(history.slice(0, pointer));
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -29,12 +29,22 @@ export function activate({bus, services}) {
|
|||
});
|
||||
}
|
||||
|
||||
function reset(modifications) {
|
||||
function resetInternal(modifications) {
|
||||
services.cadRegistry.reset();
|
||||
for (let request of modifications) {
|
||||
modifyInternal(request);
|
||||
}
|
||||
bus.dispatch(TOKENS.DID_MODIFY);
|
||||
}
|
||||
|
||||
function reset(modifications) {
|
||||
resetInternal(modifications);
|
||||
bus.updateState(TOKENS.MODIFICATIONS,
|
||||
() => {
|
||||
return {
|
||||
history: modifications,
|
||||
pointer: modifications.length - 1
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function modifyInternal(request) {
|
||||
|
|
@ -56,7 +66,6 @@ export function activate({bus, services}) {
|
|||
pointer: pointer++
|
||||
}
|
||||
});
|
||||
bus.dispatch(TOKENS.DID_MODIFY);
|
||||
}
|
||||
|
||||
services.craft = {
|
||||
|
|
@ -67,5 +76,4 @@ export function activate({bus, services}) {
|
|||
export const TOKENS = {
|
||||
MODIFICATIONS: createToken('craft', 'modifications'),
|
||||
HISTORY_POINTER: createToken('craft', 'historyPointer'),
|
||||
DID_MODIFY: createToken('craft', 'didModify')
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,10 +1,44 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import Stack from 'ui/components/Stack';
|
||||
import connect from 'ui/connect';
|
||||
import Fa from 'ui/components/Fa';
|
||||
import ImgIcon from 'ui/components/ImgIcon';
|
||||
import ls from './OperationHistory.less'
|
||||
|
||||
export default class OperationHistory extends React.Component {
|
||||
import {TOKENS as CRAFT_TOKENS} from '../../craft/craftPlugin';
|
||||
|
||||
render() {
|
||||
return <div >
|
||||
OperationHistory
|
||||
</div>
|
||||
function OperationHistory({history, pointer}, {services: {operation: operationService}}) {
|
||||
return <Stack>
|
||||
|
||||
{history.map(({type, params}, index) => {
|
||||
|
||||
let {appearance, paramsInfo} = getDescriptor(type, operationService.registry);
|
||||
return <div key={index} className={ls.item}>
|
||||
{appearance && <ImgIcon url={appearance.icon32} size={16}/>}
|
||||
<span>{type} {paramsInfo && paramsInfo(params)} </span>
|
||||
<span className={ls.buttons}>
|
||||
<Fa icon='edit' />
|
||||
<Fa icon='image' />
|
||||
<Fa icon='remove' />
|
||||
</span>
|
||||
</div>;
|
||||
})}
|
||||
|
||||
</Stack>;
|
||||
}
|
||||
|
||||
const EMPTY_DESCRIPTOR = {};
|
||||
function getDescriptor(type, registry) {
|
||||
let descriptor = registry[type];
|
||||
if (!descriptor) {
|
||||
descriptor = EMPTY_DESCRIPTOR;
|
||||
}
|
||||
}
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
OperationHistory.contextTypes = {
|
||||
services: PropTypes.object
|
||||
};
|
||||
|
||||
export default connect(OperationHistory, CRAFT_TOKENS.MODIFICATIONS);
|
||||
|
|
|
|||
8
web/app/cad/dom/components/OperationHistory.less
Normal file
8
web/app/cad/dom/components/OperationHistory.less
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
.item {
|
||||
word-wrap: break-word;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.buttons {
|
||||
|
||||
}
|
||||
16
web/app/cad/dom/components/PartPanel.jsx
Normal file
16
web/app/cad/dom/components/PartPanel.jsx
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
import React, {Fragment} from 'react';
|
||||
import ObjectExplorer from './ObjectExplorer';
|
||||
import OperationHistory from './OperationHistory';
|
||||
import Folder from 'ui/components/Folder';
|
||||
import Fa from '../../../../../modules/ui/components/Fa';
|
||||
|
||||
export default function PartPanel() {
|
||||
return <Fragment>
|
||||
<Folder title={<span> <Fa fw icon='cubes' /> Model</span>}>
|
||||
<ObjectExplorer/>
|
||||
</Folder>
|
||||
<Folder title={<span> <Fa fw icon='history' /> Modifications</span>}>
|
||||
<OperationHistory/>
|
||||
</Folder>
|
||||
</Fragment>;
|
||||
}
|
||||
|
|
@ -2,12 +2,11 @@ import React from 'react';
|
|||
import PlugableControlBar from './PlugableControlBar';
|
||||
|
||||
import ls from './View3d.less';
|
||||
import ObjectExplorer from './ObjectExplorer';
|
||||
import OperationHistory from './OperationHistory';
|
||||
import Abs from 'ui/components/Abs';
|
||||
import {PlugableToolbarLeft, PlugableToolbarLeftSecondary, PlugableToolbarRight} from "./PlugableToolbar";
|
||||
import {PlugableToolbarLeft, PlugableToolbarLeftSecondary, PlugableToolbarRight} from './PlugableToolbar';
|
||||
import UISystem from './UISystem';
|
||||
import WizardManager from './wizard/WizardManager';
|
||||
import PartPanel from './PartPanel';
|
||||
|
||||
|
||||
export default class View3d extends React.Component {
|
||||
|
|
@ -20,8 +19,7 @@ export default class View3d extends React.Component {
|
|||
render() {
|
||||
return <UISystem className={ls.root} >
|
||||
<div className={ls.sideBar}>
|
||||
<ObjectExplorer/>
|
||||
<OperationHistory/>
|
||||
<PartPanel />
|
||||
</div>
|
||||
<div className={ls.viewer} id='viewer-container'>
|
||||
<Abs left='0.8em' top='0.8em' className={ls.leftToolbarGroup}>
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ export default class Wizard extends React.Component {
|
|||
title={title}
|
||||
onClose={this.onClose}
|
||||
onKeyDown={this.onKeyDown}
|
||||
onFocus={this.focusFirstInput}>
|
||||
setFocus={this.focusFirstInput}>
|
||||
<Stack >
|
||||
{metadata.map(([name, type, , params], index) => {
|
||||
return <Field key={index}>
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ export function activate({bus, services}) {
|
|||
services.appTabs.show(sceneFace.id, 'Sketch ' + sceneFace.id, 'sketcher.html#' + sketchURL);
|
||||
}
|
||||
|
||||
bus.subscribe(CRAFT_TOKENS.DID_MODIFY, updateAllSketches);
|
||||
bus.subscribe(CRAFT_TOKENS.MODIFICATIONS, updateAllSketches);
|
||||
|
||||
services.sketcher = {
|
||||
sketchFace, updateAllSketches
|
||||
|
|
|
|||
Loading…
Reference in a new issue