From d58195a0470b3882d6b43b18f1f4ab7a373a671f Mon Sep 17 00:00:00 2001
From: Stanley Yip <stanley_yip@brown.edu>
Date: Sat, 12 Oct 2019 17:02:31 -0400
Subject: marquee now relies on pdf-style menu. pdf-style menu is now
 componentized so that other things can use it

---
 src/client/views/AntimodeMenu.tsx | 114 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 114 insertions(+)
 create mode 100644 src/client/views/AntimodeMenu.tsx

(limited to 'src/client/views/AntimodeMenu.tsx')

diff --git a/src/client/views/AntimodeMenu.tsx b/src/client/views/AntimodeMenu.tsx
new file mode 100644
index 000000000..9b0ba6312
--- /dev/null
+++ b/src/client/views/AntimodeMenu.tsx
@@ -0,0 +1,114 @@
+import React = require("react");
+import { observer } from "mobx-react";
+import { observable, action } from "mobx";
+import "./AntimodeMenu.scss";
+
+export default abstract class AntimodeMenu extends React.Component {
+    protected _offsetY: number = 0;
+    protected _offsetX: number = 0;
+    protected _mainCont: React.RefObject<HTMLDivElement> = React.createRef();
+    protected _dragging: boolean = false;
+
+    @observable protected _top: number = -300;
+    @observable protected _left: number = -300;
+    @observable protected _opacity: number = 1;
+    @observable protected _transition: string = "opacity 0.5s";
+    @observable protected _transitionDelay: string = "";
+
+    @observable public Pinned: boolean = false;
+
+    @action
+    public jumpTo = (x: number, y: number, forceJump: boolean = false) => {
+        if (!this.Pinned || forceJump) {
+            this._transition = this._transitionDelay = "";
+            this._opacity = 1;
+            this._left = x;
+            this._top = y;
+        }
+    }
+
+    @action
+    public fadeOut = (forceOut: boolean) => {
+        if (!this.Pinned) {
+            if (this._opacity === 0.2) {
+                this._transition = "opacity 0.1s";
+                this._transitionDelay = "";
+                this._opacity = 0;
+                this._left = this._top = -300;
+            }
+
+            if (forceOut) {
+                this._transition = "";
+                this._transitionDelay = "";
+                this._opacity = 0;
+                this._left = this._top = -300;
+            }
+        }
+    }
+
+    @action
+    protected pointerLeave = (e: React.PointerEvent) => {
+        if (!this.Pinned) {
+            this._transition = "opacity 0.5s";
+            this._transitionDelay = "1s";
+            this._opacity = 0.2;
+            setTimeout(() => this.fadeOut(false), 3000);
+        }
+    }
+
+    @action
+    protected pointerEntered = (e: React.PointerEvent) => {
+        this._transition = "opacity 0.1s";
+        this._transitionDelay = "";
+        this._opacity = 1;
+    }
+
+    @action
+    protected togglePin = (e: React.MouseEvent) => {
+        this.Pinned = !this.Pinned;
+    }
+
+    protected dragStart = (e: React.PointerEvent) => {
+        document.removeEventListener("pointermove", this.dragging);
+        document.addEventListener("pointermove", this.dragging);
+        document.removeEventListener("pointerup", this.dragEnd);
+        document.addEventListener("pointerup", this.dragEnd);
+
+        this._offsetX = this._mainCont.current!.getBoundingClientRect().width - e.nativeEvent.offsetX;
+        this._offsetY = e.nativeEvent.offsetY;
+
+        e.stopPropagation();
+        e.preventDefault();
+    }
+
+    @action
+    protected dragging = (e: PointerEvent) => {
+        this._left = e.pageX - this._offsetX;
+        this._top = e.pageY - this._offsetY;
+
+        e.stopPropagation();
+        e.preventDefault();
+    }
+
+    protected dragEnd = (e: PointerEvent) => {
+        document.removeEventListener("pointermove", this.dragging);
+        document.removeEventListener("pointerup", this.dragEnd);
+        e.stopPropagation();
+        e.preventDefault();
+    }
+
+    protected handleContextMenu = (e: React.MouseEvent) => {
+        e.stopPropagation();
+        e.preventDefault();
+    }
+
+    protected getElement(buttons: JSX.Element[]) {
+        return (
+            <div className="antimodeMenu-cont" onPointerLeave={this.pointerLeave} onPointerEnter={this.pointerEntered} ref={this._mainCont} onContextMenu={this.handleContextMenu}
+                style={{ left: this._left, top: this._top, opacity: this._opacity, transition: this._transition, transitionDelay: this._transitionDelay }}>
+                {buttons}
+                <div className="antimodeMenu-dragger" onPointerDown={this.dragStart} style={{ width: this.Pinned ? "20px" : "0px" }} />
+            </div>
+        );
+    }
+}
\ No newline at end of file
-- 
cgit v1.2.3-70-g09d2


From 1cb74bdb046a618fa017edca7de674992d067752 Mon Sep 17 00:00:00 2001
From: Stanley Yip <stanley_yip@brown.edu>
Date: Sun, 13 Oct 2019 13:41:08 -0400
Subject: ahh

---
 src/client/views/AntimodeMenu.tsx | 14 ++++++++++++++
 src/client/views/InkingCanvas.tsx |  2 +-
 2 files changed, 15 insertions(+), 1 deletion(-)

(limited to 'src/client/views/AntimodeMenu.tsx')

diff --git a/src/client/views/AntimodeMenu.tsx b/src/client/views/AntimodeMenu.tsx
index 9b0ba6312..408df8bc2 100644
--- a/src/client/views/AntimodeMenu.tsx
+++ b/src/client/views/AntimodeMenu.tsx
@@ -3,6 +3,10 @@ import { observer } from "mobx-react";
 import { observable, action } from "mobx";
 import "./AntimodeMenu.scss";
 
+/**
+ * This is an abstract class that serves as the base for a PDF-style or Marquee-style
+ * menu. To use this class, look at PDFMenu.tsx or MarqueeOptionsMenu.tsx for an example.
+ */
 export default abstract class AntimodeMenu extends React.Component {
     protected _offsetY: number = 0;
     protected _offsetX: number = 0;
@@ -18,6 +22,12 @@ export default abstract class AntimodeMenu extends React.Component {
     @observable public Pinned: boolean = false;
 
     @action
+    /**
+     * @param x
+     * @param y
+     * @param forceJump: If the menu is pinned down, do you want to force it to jump to the new location?
+     * Called when you want the menu to show up at a location
+     */
     public jumpTo = (x: number, y: number, forceJump: boolean = false) => {
         if (!this.Pinned || forceJump) {
             this._transition = this._transitionDelay = "";
@@ -28,6 +38,10 @@ export default abstract class AntimodeMenu extends React.Component {
     }
 
     @action
+    /**
+     * @param forceOut: Do you want the menu to disappear immediately or to slowly fadeout?
+     * Called when you want the menu to disappear
+     */
     public fadeOut = (forceOut: boolean) => {
         if (!this.Pinned) {
             if (this._opacity === 0.2) {
diff --git a/src/client/views/InkingCanvas.tsx b/src/client/views/InkingCanvas.tsx
index 1cfa8d644..0eb4c66a2 100644
--- a/src/client/views/InkingCanvas.tsx
+++ b/src/client/views/InkingCanvas.tsx
@@ -183,7 +183,7 @@ export class InkingCanvas extends React.Component<InkCanvasProps> {
         let svgCanvasStyle = InkingControl.Instance.selectedTool !== InkTool.None && !this.props.Document.isBackground ? "canSelect" : "noSelect";
         return (
             <div className="inkingCanvas">
-                <div className={`inkingCanvas-${svgCanvasStyle}`} onPointerDown={this.onPointerDown} />
+                <div className={`inkingCanvas-${svgCanvasStyle}`} onPointerDown={this.onPointerDown} onTouchStart={(e) => e.stopPropagation()} />
                 {this.props.children()}
                 {this.drawnPaths}
             </div >
-- 
cgit v1.2.3-70-g09d2

