From 83edfcd06b659839f161121728de02aca91d4af8 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Thu, 30 May 2019 00:20:35 -0400 Subject: added image rotation. added double click on stacking views. need to cleanup/fix DocumentView click events --- .../views/collections/CollectionStackingView.scss | 2 +- .../views/collections/CollectionStackingView.tsx | 15 +++++++++++---- .../views/nodes/CollectionFreeFormDocumentView.tsx | 21 +-------------------- src/client/views/nodes/DocumentView.tsx | 12 +++++++++++- src/client/views/nodes/ImageBox.tsx | 19 +++++++++++++++++-- 5 files changed, 41 insertions(+), 28 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/CollectionStackingView.scss b/src/client/views/collections/CollectionStackingView.scss index 0e4a8bb7e..4d240342c 100644 --- a/src/client/views/collections/CollectionStackingView.scss +++ b/src/client/views/collections/CollectionStackingView.scss @@ -31,7 +31,7 @@ align-items: center; } - .collectionStackingview-masonryGrid { + .collectionStackingView-masonryGrid { display:grid; width:100%; height:100%; diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 6d44aa37d..943e8dd5f 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -83,10 +83,17 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { }) } onClick = (e: React.MouseEvent) => { + let hitBackground = (e.target as any).className === "collectionStackingView-masonryGrid" || + (e.target as any).className === "collectionStackingView"; if (this.props.active()) { - let rect = (this.masonryGridRef!.firstChild! as HTMLElement).getBoundingClientRect(); - if (e.clientX < rect.left || e.clientX > rect.right || e.clientY > rect.bottom) this.props.select(false); - e.stopPropagation(); + if (!hitBackground) + e.stopPropagation(); + } + if (hitBackground) { + if (!this.props.active() && this.props.ContainingCollectionView && this.props.ContainingCollectionView.props.active()) { + e.stopPropagation(); + } + this.props.select(false); } } render() { @@ -96,7 +103,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { let cells = Math.floor((this.props.PanelWidth() - leftMargin) / (itemCols * (this.gridSize + this.gridGap))); return (
e.stopPropagation()}> -
{ - document.removeEventListener("pointerup", this.onPointerUp); - if (Math.abs(e.clientX - this._downX) < 2 && Math.abs(e.clientY - this._downY) < 2) { - this._doubleTap = true; - } - } onClick = async (e: React.MouseEvent) => { e.stopPropagation(); - if (this._doubleTap) { - this.props.addDocTab(this.props.Document, "inTab"); - SelectionManager.DeselectAll(); - this.props.Document.libraryBrush = false; - } let altKey = e.altKey; let ctrlKey = e.ctrlKey; if (Math.abs(e.clientX - this._downX) < Utils.DRAG_THRESHOLD && diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 98f4f050a..36c14fbf2 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -183,13 +183,21 @@ export class DocumentView extends DocComponent(Docu } } + _doubleTap = false; onClick = (e: React.MouseEvent): void => { - if (CurrentUserUtils.MainDocId !== this.props.Document[Id] && + if (this._doubleTap && !this.props.isTopMost) { + this.props.addDocTab(this.props.Document, "inTab"); + SelectionManager.DeselectAll(); + this.props.Document.libraryBrush = false; + e.stopPropagation(); + } + else if (CurrentUserUtils.MainDocId !== this.props.Document[Id] && (Math.abs(e.clientX - this._downX) < Utils.DRAG_THRESHOLD && Math.abs(e.clientY - this._downY) < Utils.DRAG_THRESHOLD)) { SelectionManager.SelectDoc(this, e.ctrlKey); } } + private _lastTap: number = 0; _hitExpander = false; onPointerDown = (e: React.PointerEvent): void => { this._downX = e.clientX; @@ -222,6 +230,8 @@ export class DocumentView extends DocComponent(Docu onPointerUp = (e: PointerEvent): void => { document.removeEventListener("pointermove", this.onPointerMove); document.removeEventListener("pointerup", this.onPointerUp); + this._doubleTap = (Date.now() - this._lastTap < 300 && e.button === 0 && Math.abs(e.clientX - this._downX) < 2 && Math.abs(e.clientY - this._downY) < 2); + this._lastTap = Date.now(); } deleteClicked = (): void => { diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index d70068295..8ea6c5436 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -12,11 +12,11 @@ import React = require("react"); import { createSchema, makeInterface, listSpec } from '../../../new_fields/Schema'; import { DocComponent } from '../DocComponent'; import { positionSchema } from './DocumentView'; -import { FieldValue, Cast, StrCast, PromiseValue } from '../../../new_fields/Types'; +import { FieldValue, Cast, StrCast, PromiseValue, NumCast } from '../../../new_fields/Types'; import { ImageField } from '../../../new_fields/URLField'; import { List } from '../../../new_fields/List'; import { InkingControl } from '../InkingControl'; -import { Doc } from '../../../new_fields/Doc'; +import { Doc, WidthSym, HeightSym } from '../../../new_fields/Doc'; import { faImage } from '@fortawesome/free-solid-svg-icons'; import { library } from '@fortawesome/fontawesome-svg-core'; var path = require('path'); @@ -136,6 +136,17 @@ export class ImageBox extends DocComponent(ImageD Utils.CopyText(url); }, icon: "expand-arrows-alt" }); + ContextMenu.Instance.addItem({ + description: "Rotate", event: action(() => { + this.props.Document.rotation = (NumCast(this.props.Document.rotation) + 90) % 360; + let nw = this.props.Document.nativeWidth; + this.props.Document.nativeWidth = this.props.Document.nativeHeight; + this.props.Document.nativeHeight = nw; + let w = this.props.Document.width; + this.props.Document.width = this.props.Document.height; + this.props.Document.height = w; + }), icon: "expand-arrows-alt" + }); } } @@ -199,6 +210,9 @@ export class ImageBox extends DocComponent(ImageD else if (field instanceof List) paths = field.filter(val => val instanceof ImageField).map(p => this.choosePath((p as ImageField).url)); // } let interactive = InkingControl.Instance.selectedTool ? "" : "-interactive"; + let rotation = NumCast(this.props.Document.rotation, 0); + let aspect = (rotation % 180) ? this.props.Document[HeightSym]() / this.props.Document[WidthSym]() : 1; + let shift = (rotation % 180) ? (this.props.Document[HeightSym]() - this.props.Document[WidthSym]() / aspect) / 2 : 0; return (
(ImageD