diff options
-rw-r--r-- | src/client/views/Touchable.tsx | 2 | ||||
-rw-r--r-- | src/client/views/nodes/DocumentView.tsx | 91 | ||||
-rw-r--r-- | src/client/views/nodes/RadialMenu.tsx | 132 | ||||
-rw-r--r-- | src/client/views/nodes/RadialMenuItem.tsx | 146 |
4 files changed, 156 insertions, 215 deletions
diff --git a/src/client/views/Touchable.tsx b/src/client/views/Touchable.tsx index 49b2116f1..7d9184bea 100644 --- a/src/client/views/Touchable.tsx +++ b/src/client/views/Touchable.tsx @@ -137,11 +137,9 @@ export abstract class Touchable<T = {}> extends React.Component<T> { } handle1PointerHoldStart = (e: React.TouchEvent): any => { - console.log("Hold"); e.stopPropagation(); e.preventDefault(); document.removeEventListener("touchmove", this.onTouch); - document.removeEventListener("touchend", this.onTouchEnd); } }
\ No newline at end of file diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 49d35637e..e6c6aaa08 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -107,33 +107,38 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu @computed get nativeHeight() { return this.layoutDoc.nativeHeight || 0; } @computed get onClickHandler() { return this.props.onClick ? this.props.onClick : this.Document.onClick; } - private _firstX:number=0; - private _firstY:number=0; + private _firstX: number = 0; + private _firstY: number = 0; - - handle1PointerHoldStart= (e: React.TouchEvent): any =>{ + + handle1PointerHoldStart = (e: React.TouchEvent): any => { this.onRadialMenu(e); - let page =e.touches[0]; - this._firstX=page.pageX; - this._firstY=page.pageY; + const pt = InteractionUtils.GetMyTargetTouches(e, this.prevPoints)[0]; + this._firstX = pt.pageX; + this._firstY = pt.pageY; + e.stopPropagation(); + e.preventDefault(); document.removeEventListener("touchmove", this.onTouch); - document.removeEventListener("touchend", this.onTouchEnd); + document.removeEventListener("touchmove", this.handle1PointerHoldMove); document.addEventListener("touchmove", this.handle1PointerHoldMove); + document.removeEventListener("touchend", this.handle1PointerHoldEnd); document.addEventListener("touchend", this.handle1PointerHoldEnd); } - handle1PointerHoldMove = (event: TouchEvent): void => { - let e=event.touches[0]; - Math.abs(e.pageX-this._firstX)>150 ||Math.abs(e.pageY-this._firstY)>150? this.handleRelease():null; + handle1PointerHoldMove = (e: TouchEvent): void => { + const pt = InteractionUtils.GetMyTargetTouches(e, this.prevPoints)[0]; + if (Math.abs(pt.pageX - this._firstX) > 150 || Math.abs(pt.pageY - this._firstY) > 150) { + this.handleRelease(); + } document.removeEventListener("touchmove", this.handle1PointerHoldMove); document.addEventListener("touchmove", this.handle1PointerHoldMove); document.removeEventListener("touchend", this.handle1PointerHoldEnd); document.addEventListener("touchend", this.handle1PointerHoldEnd); } - handleRelease(){ - RadialMenu.Instance.closeMenu() + handleRelease() { + RadialMenu.Instance.closeMenu(); document.removeEventListener("touchmove", this.handle1PointerHoldMove); document.removeEventListener("touchend", this.handle1PointerHoldEnd); } @@ -145,56 +150,24 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu } @action - onRadialMenu = async (event: React.TouchEvent): Promise<void> => { - // the touch onContextMenu is button 0, the pointer onContextMenu is button 2 - // if (e.button === 0) { - // e.preventDefault(); - // return; - // } - let e = event.touches[0]; - // if (Math.abs(this._downX - e.clientX) > 3 || Math.abs(this._downY - e.clientY) > 3 || - // // event.isDefaultPrevented()) { - // // event.preventDefault(); - // return; - // } - // event.preventDefault(); - - let rm = RadialMenu.Instance; - rm.openMenu(); - const one = RadialMenu.Instance.findByDescription("one..."); - const two = RadialMenu.Instance.findByDescription("two..."); - const three = RadialMenu.Instance.findByDescription("three..."); - const four= RadialMenu.Instance.findByDescription("four..."); - // const five= RadialMenu.Instance.findByDescription("five..."); - // const six= RadialMenu.Instance.findByDescription("six..."); - // const seven= RadialMenu.Instance.findByDescription("seven..."); - - - !one?rm.addItem({ description: "one one one one one one one one one", event: () => this.props.addDocTab(Docs.Create.KVPDocument(this.props.Document, { width: 300, height: 300 }), undefined, "onRight"), icon: "layer-group",selected:-1 }):null; - !two?rm.addItem({ description: "two", event: () => this.props.addDocTab(Docs.Create.KVPDocument(this.props.Document, { width: 300, height: 300 }), undefined, "onRight"), icon: "layer-group",selected:-1 }):null; - !three?rm.addItem({ description: "three", event: () => this.props.addDocTab(Docs.Create.KVPDocument(this.props.Document, { width: 300, height: 300 }), undefined, "onRight"), icon: "layer-group",selected:-1 }):null; - !four?rm.addItem({ description: "four", event: () => this.props.addDocTab(Docs.Create.KVPDocument(this.props.Document, { width: 300, height: 300 }), undefined, "onRight"), icon: "layer-group",selected:-1 }):null; - // !five?rm.addItem({ description: "five", event: () => this.props.addDocTab(Docs.Create.KVPDocument(this.props.Document, { width: 300, height: 300 }), undefined, "onRight"), icon: "layer-group",selected:-1 }):null; + onRadialMenu = (e: React.TouchEvent): void => { + const pt = InteractionUtils.GetMyTargetTouches(e, this.prevPoints)[0]; + + RadialMenu.Instance.openMenu(); + + RadialMenu.Instance.addItem({ description: "Open Fields", event: () => this.props.addDocTab(Docs.Create.KVPDocument(this.props.Document, { width: 300, height: 300 }), undefined, "onRight"), icon: "layer-group", selected: -1 }); + RadialMenu.Instance.addItem({ description: "Delete this document", event: () => this.props.ContainingCollectionView?.removeDocument(this.props.Document), icon: "trash", selected: -1 }); + RadialMenu.Instance.addItem({ description: "Open in a new tab", event: () => this.props.addDocTab(this.props.Document, undefined, "onRight"), icon: "tab", selected: -1 }); + RadialMenu.Instance.addItem({ description: "four", event: () => this.props.addDocTab(Docs.Create.KVPDocument(this.props.Document, { width: 300, height: 300 }), undefined, "onRight"), icon: "layer-group", selected: -1 }); // !six?rm.addItem({ description: "six", event: () => this.props.addDocTab(Docs.Create.KVPDocument(this.props.Document, { width: 300, height: 300 }), undefined, "onRight"), icon: "layer-group" ,selected:-1}):null; // !seven?rm.addItem({ description: "seven", event: () => this.props.addDocTab(Docs.Create.KVPDocument(this.props.Document, { width: 300, height: 300 }), undefined, "onRight"), icon: "layer-group" ,selected:-1}):null; - runInAction(() => { - // cm.addItem({ - // description: "Share", - // event: () => SharingManager.Instance.open(this), - // icon: "external-link-alt" - // }); - - if (!this.topMost) { - // DocumentViews should stop propagation of this event - } - RadialMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15); - if (!SelectionManager.IsSelected(this, true)) { - SelectionManager.SelectDoc(this, false); - } - }); + RadialMenu.Instance.displayMenu(pt.pageX - 15, pt.pageY - 15); + if (!SelectionManager.IsSelected(this, true)) { + SelectionManager.SelectDoc(this, false); + } } - + @action componentDidMount() { this._mainCont.current && (this._dropDisposer = DragManager.MakeDropTarget(this._mainCont.current, this.drop.bind(this))); diff --git a/src/client/views/nodes/RadialMenu.tsx b/src/client/views/nodes/RadialMenu.tsx index d8750a192..74c5f53bd 100644 --- a/src/client/views/nodes/RadialMenu.tsx +++ b/src/client/views/nodes/RadialMenu.tsx @@ -1,13 +1,11 @@ import React = require("react"); import { observer } from "mobx-react"; import { action, observable, computed, IReactionDisposer, reaction, runInAction } from "mobx"; -import { RadialMenuItem, RadialMenuProps, OriginalMenuProps } from "./RadialMenuItem"; +import { RadialMenuItem, RadialMenuProps } from "./RadialMenuItem"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import Measure from "react-measure"; import "./RadialMenu.scss"; - - @observer export class RadialMenu extends React.Component { static Instance: RadialMenu; @@ -30,36 +28,36 @@ export class RadialMenu extends React.Component { onPointerDown = (e: PointerEvent) => { this._mouseDown = true; this._mouseX = e.clientX; - this._mouseY = e.clientY; + this._mouseY = e.clientY; document.addEventListener("pointermove", this.onPointerMove); } - @observable - private _closest:number=-1; + @observable + private _closest: number = -1; @action onPointerMove = (e: PointerEvent) => { const curX = e.clientX; const curY = e.clientY; - const deltX = this._mouseX-curX - const deltY = this._mouseY-curY - const scale = Math.hypot(deltY,deltX) + const deltX = this._mouseX - curX; + const deltY = this._mouseY - curY; + const scale = Math.hypot(deltY, deltX); - if (scale <150 && scale > 50){ - const rad = Math.atan2(deltY,deltX)+Math.PI; - let closest =0; + if (scale < 150 && scale > 50) { + const rad = Math.atan2(deltY, deltX) + Math.PI; + let closest = 0; let closestval = 999999999; - for (let x =0; x<this._items.length; x++){ - let curmin= (x/this._items.length)*2*Math.PI; - if (rad-curmin<closestval && rad-curmin>0){ - closestval=rad-curmin - closest=x; + for (let x = 0; x < this._items.length; x++) { + const curmin = (x / this._items.length) * 2 * Math.PI; + if (rad - curmin < closestval && rad - curmin > 0) { + closestval = rad - curmin; + closest = x; } } - this._closest=closest; + this._closest = closest; } - else{ - this._closest=-1; + else { + this._closest = -1; } } @action @@ -72,8 +70,8 @@ export class RadialMenu extends React.Component { } this._shouldDisplay && (this._display = true); document.removeEventListener("pointermove", this.onPointerMove); - if (this._closest!==-1){ - this._items[this._closest].event(); + if (this._closest !== -1) { + this._items[this._closest]?.event(); } } componentWillUnmount() { @@ -94,7 +92,7 @@ export class RadialMenu extends React.Component { ); } - componentDidUpdate = () =>{ + componentDidUpdate = () => { this.previewcircle(); } @@ -112,23 +110,14 @@ export class RadialMenu extends React.Component { return this._items; } - findByDescription = (target: string, toLowerCase = false) => { - return this._items.find(menuItem => { - let reference = menuItem.description; - toLowerCase && (reference = reference.toLowerCase()); - return reference === target; - }); - } - - @action addItem(item: RadialMenuProps) { if (this._items.indexOf(item) === -1) { this._items.push(item); } } - - @observable + + @observable private _items: Array<RadialMenuProps> = []; @action @@ -166,7 +155,7 @@ export class RadialMenu extends React.Component { } @computed get menuItems() { - return this._items.map((item,index) => <RadialMenuItem {...item} key={item.description} closeMenu={this.closeMenu} max={this._items.length} min={index} selected={this._closest} />); + return this._items.map((item, index) => <RadialMenuItem {...item} key={item.description} closeMenu={this.closeMenu} max={this._items.length} min={index} selected={this._closest} />); } @action @@ -188,60 +177,45 @@ export class RadialMenu extends React.Component { } - previewcircle(){ - if (document.getElementById("newCanvas")!==null){ - var c : any= document.getElementById("newCanvas"); - if (c.getContext){ - var ctx = c.getContext("2d"); - ctx.beginPath(); - ctx.arc(150, 150, 50, 0, 2 * Math.PI); - ctx.fillStyle="white"; - ctx.fill() - ctx.font = "12px Arial"; - ctx.fillStyle = "black"; - ctx.textAlign = "center"; - let description =""; - if (this._closest!==-1){ - description = this._items[this._closest].description; - } - if (description.length>15){ - description= description.slice(0,12); - description += "..."; - } - ctx.fillText(description, 150, 150, 90); + previewcircle() { + if (document.getElementById("newCanvas") !== null) { + const c: any = document.getElementById("newCanvas"); + if (c.getContext) { + const ctx = c.getContext("2d"); + ctx.beginPath(); + ctx.arc(150, 150, 50, 0, 2 * Math.PI); + ctx.fillStyle = "white"; + ctx.fill(); + ctx.font = "12px Arial"; + ctx.fillStyle = "black"; + ctx.textAlign = "center"; + let description = ""; + if (this._closest !== -1) { + description = this._items[this._closest].description; + } + if (description.length > 15) { + description = description.slice(0, 12); + description += "..."; + } + ctx.fillText(description, 150, 150, 90); + } } } - } - + render() { if (!this._display) { return null; } - const style = this._yRelativeToTop ? { left: this._mouseX-150, top: this._mouseY-150 } : - { left: this._mouseX-150, top: this._mouseY-150 }; + const style = this._yRelativeToTop ? { left: this._mouseX - 150, top: this._mouseY - 150 } : + { left: this._mouseX - 150, top: this._mouseY - 150 }; - const contents = ( - <> - {this.menuItems} - </> - ); - // return ( - // <Measure offset onResize={action((r: any) => { this._width = r.offset.width; this._height = r.offset.height; })}> - // {({ measureRef }) => ( - // <div className="radialMenu-cont" style={style} ref={measureRef}> - // {contents} - // </div> - // ) - // } - // </Measure> - // ); return ( - <div className="radialMenu-cont" style={style}> - <canvas id="newCanvas" style={{position:"absolute"}}height="300" width="300"> Your browser does not support the HTML5 canvas tag.</canvas> - {contents} - </div> + <div className="radialMenu-cont" style={style}> + <canvas id="newCanvas" style={{ position: "absolute" }} height="300" width="300"> Your browser does not support the HTML5 canvas tag.</canvas> + {this.menuItems} + </div> ); } diff --git a/src/client/views/nodes/RadialMenuItem.tsx b/src/client/views/nodes/RadialMenuItem.tsx index 4ca257df5..fdc732d3f 100644 --- a/src/client/views/nodes/RadialMenuItem.tsx +++ b/src/client/views/nodes/RadialMenuItem.tsx @@ -8,114 +8,110 @@ import { UndoManager } from "../../util/UndoManager"; library.add(faAngleRight); -export interface OriginalMenuProps { +export interface RadialMenuProps { description: string; event: (stuff?: any) => void; undoable?: boolean; icon: IconProp; closeMenu?: () => void; min?: number; - max?:number; - selected:number; + max?: number; + selected: number; } -export type RadialMenuProps = OriginalMenuProps; - @observer -export class RadialMenuItem extends React.Component<RadialMenuProps & { selected?: boolean }> { +export class RadialMenuItem extends React.Component<RadialMenuProps> { - componentDidMount = () =>{ + componentDidMount = () => { this.setcircle(); } - componentDidUpdate = () =>{ + componentDidUpdate = () => { this.setcircle(); } - handleEvent = async (e: React.MouseEvent<HTMLDivElement>) => { - if ("event" in this.props) { - this.props.closeMenu && this.props.closeMenu(); - let batch: UndoManager.Batch | undefined; - if (this.props.undoable !== false) { - batch = UndoManager.StartBatch(`Context menu event: ${this.props.description}`); - } - await this.props.event({ x: e.clientX, y: e.clientY }); - batch && batch.end(); + handleEvent = async (e: React.PointerEvent) => { + this.props.closeMenu && this.props.closeMenu(); + let batch: UndoManager.Batch | undefined; + if (this.props.undoable !== false) { + batch = UndoManager.StartBatch(`Context menu event: ${this.props.description}`); } + await this.props.event({ x: e.clientX, y: e.clientY }); + batch && batch.end(); } - setcircle(){ - let circlemin=0; - let circlemax=1 - this.props.min? circlemin=this.props.min:null; - this.props.max? circlemax=this.props.max:null; - if (document.getElementById("myCanvas")!==null){ - var c : any= document.getElementById("myCanvas"); - let color = "white" - switch(circlemin%3){ - case 1: + setcircle() { + let circlemin = 0; + let circlemax = 1 + this.props.min ? circlemin = this.props.min : null; + this.props.max ? circlemax = this.props.max : null; + if (document.getElementById("myCanvas") !== null) { + var c: any = document.getElementById("myCanvas"); + let color = "white" + switch (circlemin % 3) { + case 1: + color = "#c2c2c5"; + break; + case 0: + color = "#f1efeb"; + break; + case 2: + color = "lightgray"; + break; + } + if (circlemax % 3 === 1 && circlemin === circlemax - 1) { color = "#c2c2c5"; - break; - case 0: - color = "#f1efeb"; - break; - case 2: - color = "lightgray"; - break; - } - if (circlemax%3===1 && circlemin===circlemax-1){ - color="#c2c2c5"; - } + } - if (this.props.selected === this.props.min){ - color="#808080"; - - } - if (c.getContext){ - var ctx = c.getContext("2d"); - ctx.beginPath(); - ctx.arc(150, 150, 150, (circlemin/circlemax)*2*Math.PI, ((circlemin+1)/circlemax) * 2 * Math.PI); - ctx.arc(150, 150, 50, ((circlemin+1)/circlemax)*2*Math.PI, (circlemin/circlemax) * 2 * Math.PI,true); - ctx.fillStyle=color; - ctx.fill() + if (this.props.selected === this.props.min) { + color = "#808080"; + + } + if (c.getContext) { + var ctx = c.getContext("2d"); + ctx.beginPath(); + ctx.arc(150, 150, 150, (circlemin / circlemax) * 2 * Math.PI, ((circlemin + 1) / circlemax) * 2 * Math.PI); + ctx.arc(150, 150, 50, ((circlemin + 1) / circlemax) * 2 * Math.PI, (circlemin / circlemax) * 2 * Math.PI, true); + ctx.fillStyle = color; + ctx.fill() + } } } - } - calculatorx(){ - let circlemin=0; - let circlemax=1 - this.props.min? circlemin=this.props.min:null; - this.props.max? circlemax=this.props.max:null; - let avg = ((circlemin/circlemax)+((circlemin+1)/circlemax))/2; - let degrees = 360*avg; - let x= 100*Math.cos(degrees*Math.PI/180); - let y =-125*Math.sin(degrees*Math.PI/180); + calculatorx() { + let circlemin = 0; + let circlemax = 1 + this.props.min ? circlemin = this.props.min : null; + this.props.max ? circlemax = this.props.max : null; + let avg = ((circlemin / circlemax) + ((circlemin + 1) / circlemax)) / 2; + let degrees = 360 * avg; + let x = 100 * Math.cos(degrees * Math.PI / 180); + let y = -125 * Math.sin(degrees * Math.PI / 180); return x; } - calculatory(){ - - let circlemin=0; - let circlemax=1 - this.props.min? circlemin=this.props.min:null; - this.props.max? circlemax=this.props.max:null; - let avg = ((circlemin/circlemax)+((circlemin+1)/circlemax))/2; - let degrees = 360*avg; - let x= 125*Math.cos(degrees*Math.PI/180); - let y =-100*Math.sin(degrees*Math.PI/180); + calculatory() { + + let circlemin = 0; + let circlemax = 1 + this.props.min ? circlemin = this.props.min : null; + this.props.max ? circlemax = this.props.max : null; + let avg = ((circlemin / circlemax) + ((circlemin + 1) / circlemax)) / 2; + let degrees = 360 * avg; + let x = 125 * Math.cos(degrees * Math.PI / 180); + let y = -100 * Math.sin(degrees * Math.PI / 180); return y; } render() { - return ( - <div className={"radialMenu-item" + (this.props.selected ? " radialMenu-itemSelected" : "")} onClick={this.handleEvent}> - <canvas id="myCanvas" height="300" width="300"> Your browser does not support the HTML5 canvas tag.</canvas> - <FontAwesomeIcon icon={this.props.icon} size="3x" style={{ position:"absolute", left:this.calculatorx()+150-19, top:this.calculatory()+150-19}} /> - </div> - ); + return ( + <div className={"radialMenu-item" + (this.props.selected ? " radialMenu-itemSelected" : "")} onPointerUp={this.handleEvent}> + <canvas id="myCanvas" height="300" width="300"> Your browser does not support the HTML5 canvas tag.</canvas> + <FontAwesomeIcon icon={this.props.icon} size="3x" style={{ position: "absolute", left: this.calculatorx() + 150 - 19, top: this.calculatory() + 150 - 19 }} /> + </div> + ); } }
\ No newline at end of file |