make all menus position static / allow creation custom context menus

This commit is contained in:
Val Erastov 2019-02-24 14:42:49 -08:00
parent 415b832d8f
commit a1e2b80948
11 changed files with 129 additions and 24 deletions

View file

@ -13,9 +13,9 @@ export class Adjuster extends React.Component {
if (!this.el) {
return;
}
let w = this.el.offsetWidth;
let h = this.el.offsetHeight;
let holder = this.el.parentNode;
let w = this.el.clientWidth;
let h = this.el.clientHeight;
let holder = document.documentElement;
const fit = (prop, pos, dim, holderDim) => {
if (pos !== undefined) {
@ -43,10 +43,10 @@ export class Adjuster extends React.Component {
}
}
fit('left', left, w, holder.offsetWidth);
fit('right', right,w, holder.offsetWidth);
fit('top', top, h, holder.offsetHeight);
fit('bottom', bottom, h, holder.offsetHeight);
fit('left', left, w, holder.clientWidth);
fit('right', right,w, holder.clientWidth);
fit('top', top, h, holder.clientHeight);
fit('bottom', bottom, h, holder.clientHeight);
this.el.style.visibility = 'visible';
};
@ -63,7 +63,7 @@ export class Adjuster extends React.Component {
return <div ref={el => this.el = el}
style={{
visibility: 'hidden',
position: 'absolute', zIndex,
position: 'fixed', zIndex,
...style}} {...props}>
{children}
</div>;

View file

@ -26,15 +26,15 @@ export default class Folder extends React.Component{
render() {
let {title, closable, className, children} = this.props;
return <div className={cx(ls.root, className)}>
<Title title={title} onClick={closable ? this.tweakClose : null} isClosed={this.isClosed()}/>
<Title onClick={closable ? this.tweakClose : null} isClosed={this.isClosed()}>{title}</Title>
{!this.isClosed() && children}
</div>
}
}
export function Title({title, isClosed, onClick}) {
export function Title({children, isClosed, onClick}) {
return <div className={ls.title} onClick={onClick}>
<span className={ls.handle}><Fa fw icon={isClosed ? 'chevron-right' : 'chevron-down'}/></span>
{' '}{title}
{' '}{children}
</div>;
}

View file

@ -4,6 +4,7 @@ import PropTypes from 'prop-types';
import ls from './Menu.less';
import AuxWidget from "./AuxWidget";
import cx from 'classnames';
import Fa from './Fa';
export default function Menu({children, x, y, orientationUp, centered, menuId, ...props}) {
return <AuxWidget
@ -23,7 +24,7 @@ export function MenuSeparator() {
}
export function MenuItem({icon, label, hotKey, style, disabled, onClick, ...props}, {closeAllUpPopups}) {
export function MenuItem({icon, label, hotKey, style, disabled, onClick, children, ...props}, {closeAllUpPopups}) {
if (hotKey) {
hotKey = hotKey.replace(/\s/g, '');
@ -43,6 +44,69 @@ export function MenuItem({icon, label, hotKey, style, disabled, onClick, ...prop
</div>;
}
export class ContextMenu extends React.Component {
state = {
active: false
};
onClick = e => {
e.preventDefault();
this.setState({
active: true,
x: e.clientX,
y: e.clientY
});
};
close = () => {
this.setState({active: false})
};
componentDidMount() {
this.detacher = this.context.onCloseAll.attach(this.close);
}
componentWillUnmount() {
this.detacher();
}
render() {
return <span className={ls.contextMenu}>
<span onContextMenu={this.onClick}>{this.props.children}</span>
<span onClick={this.onClick} className={ls.contextMenuBtn}><Fa fw icon='ellipsis-h'/></span>
{this.state.active && <Menu x={this.state.x} y={this.state.y}>
{this.props.items}
</Menu>}
</span>
}
getChildContext() {
return {
closeMenu: this.close
};
}
static contextTypes = {
onCloseAll: PropTypes.object
};
static childContextTypes = {
closeMenu: PropTypes.func
};
}
export function ContextMenuItem({onClick, ...props}, {closeMenu}) {
return <MenuItem onClick={() => {
closeMenu();
onClick();
}} {...props}/>;
}
ContextMenuItem.contextTypes = {
closeMenu: PropTypes.func
};
MenuItem.contextTypes = {
closeAllUpPopups: PropTypes.func
};

View file

@ -46,3 +46,21 @@
color: @font-color-suppressed;
}
.contextMenu {
&:hover .contextMenuBtn {
color: #fff;
}
}
.contextMenuBtn {
display: inline-block;
padding: 2px 3px;
color: #ffffff33;
&:hover {
color: #fff;
}
&:active {
color: #7f0807;
}
}

View file

@ -3,9 +3,9 @@ import React from 'react';
import ls from './Button.less'
import cx from 'classnames';
export default function Button({type, onClick, children}) {
export default function Button({type, onClick, className, children}) {
return <button onClick={onClick} className={cx(ls[type], ls.button)}>{children}</button>
return <button onClick={onClick} className={cx(ls[type], ls.button, className)}>{children}</button>
}

View file

@ -6,7 +6,7 @@ export class StackSection extends React.Component {
render() {
const {title, children} = this.props;
return <React.Fragment>
<Title title={title} />
<Title>{title}</Title>
{children}
</React.Fragment>;
}

View file

@ -24,3 +24,15 @@
.inlineBlock {
display: inline-block;
}
a {
color: @font-color;
text-decoration: underline;
&:hover {
color: @color-text-highlight
}
}
.scrollable {
overflow: auto;
}

View file

@ -24,5 +24,7 @@
@color-neutral: #66727d;
@color-highlight: #003f5d;
@color-text-highlight: #9cdaf7;
//@work-area-toolbar-bg-color: ;
//@work-area-toolbar-font-color: ;

View file

@ -5,9 +5,12 @@ import MenuHolder from '../menu/MenuHolder';
import WindowSystem from 'ui/WindowSystem';
import ActionInfo from '../actionInfo/ActionInfo';
import ContributedComponents from './ContributedComponents';
import {stream} from '../../../../../modules/lstream';
export default class UISystem extends React.Component {
onCloseAll = stream();
render() {
return <div {...this.props} onMouseDown={this.closeAllUpPopups} >
<MenuHolder />
@ -26,11 +29,13 @@ export default class UISystem extends React.Component {
closeAllUpPopups = () => {
this.context.services.menu.closeAll();
this.context.services.action.showHintFor(null);
this.onCloseAll.next();
};
getChildContext() {
return {
closeAllUpPopups: this.closeAllUpPopups
closeAllUpPopups: this.closeAllUpPopups,
onCloseAll: this.onCloseAll
}
}
@ -39,7 +44,8 @@ export default class UISystem extends React.Component {
};
static childContextTypes = {
closeAllUpPopups: PropTypes.func
closeAllUpPopups: PropTypes.func,
onCloseAll: PropTypes.object
};
}

View file

@ -1,6 +1,9 @@
export const menuAboveElementHint = el => ({
export const menuAboveElementHint = el => {
let {top, left, bottom} = el.getBoundingClientRect();
return ({
orientationUp: true,
flatBottom: true,
x: el.offsetParent.offsetParent.offsetLeft + el.offsetLeft,
y: el.offsetParent.offsetHeight - el.offsetTop
x: left,
y: document.documentElement.clientHeight - top
});
};

View file

@ -2,7 +2,7 @@ export default [
{
id: 'file',
cssIcons: ['file'],
actions: ['Save', 'StlExport', 'ImagePngExport', '-', 'IMPORT_STL', '-', 'ReassignSketch']
actions: ['Save', 'StlExport', 'ImagePngExport', 'NativeFormatExport', '-', 'NativeFormatImport', '-', 'ReassignSketch']
},
{
id: 'craft',