diff options
author | Eric <ericmabr@gmail.com> | 2023-02-22 17:18:24 -0500 |
---|---|---|
committer | Eric <ericmabr@gmail.com> | 2023-02-22 17:18:24 -0500 |
commit | 2e3f56ed2bfc97191f514c5edbf618897dfb6a9d (patch) | |
tree | 0ffb7f51352db766c3ef7a076a74b92a9b18c89c /src/client/views/nodes/ImageBox.tsx | |
parent | ef7fa18c57cfd2fdfd076eab29cd7a6ea8a1008e (diff) | |
parent | 32f5040c44dc302e3dd53cecd9be4cd51a474d3f (diff) |
Merge branch 'master' into UI_Update_Eric_Ma
Diffstat (limited to 'src/client/views/nodes/ImageBox.tsx')
-rw-r--r-- | src/client/views/nodes/ImageBox.tsx | 71 |
1 files changed, 58 insertions, 13 deletions
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index e93bab149..ae851d6a6 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -11,7 +11,7 @@ import { ComputedField } from '../../../fields/ScriptField'; import { BoolCast, Cast, NumCast, StrCast } from '../../../fields/Types'; import { ImageField } from '../../../fields/URLField'; import { TraceMobx } from '../../../fields/util'; -import { emptyFunction, OmitKeys, returnEmptyString, returnFalse, returnOne, setupMoveUpEvents, Utils } from '../../../Utils'; +import { DashColor, emptyFunction, OmitKeys, returnEmptyString, returnFalse, returnOne, setupMoveUpEvents, Utils } from '../../../Utils'; import { GooglePhotos } from '../../apis/google_docs/GooglePhotosClientUtils'; import { CognitiveServices, Confidence, Service, Tag } from '../../cognitive_services/CognitiveServices'; import { Docs, DocUtils } from '../../documents/Documents'; @@ -26,12 +26,15 @@ import { ViewBoxAnnotatableComponent, ViewBoxAnnotatableProps } from '../DocComp import { MarqueeAnnotator } from '../MarqueeAnnotator'; import { AnchorMenu } from '../pdf/AnchorMenu'; import { StyleProp } from '../StyleProvider'; +import { DocFocusOptions, OpenWhere } from './DocumentView'; import { FaceRectangles } from './FaceRectangles'; import { FieldView, FieldViewProps } from './FieldView'; import './ImageBox.scss'; -import React = require('react'); import { PresBox } from './trails'; -import { DocFocusOptions, DocumentViewProps } from './DocumentView'; +import React = require('react'); +import Color = require('color'); +import { LinkDocPreview } from './LinkDocPreview'; +import { DocumentManager } from '../../util/DocumentManager'; export const pageSchema = createSchema({ googlePhotosUrl: 'string', @@ -50,6 +53,8 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp public static LayoutString(fieldKey: string) { return FieldView.LayoutString(ImageBox, fieldKey); } + private _ignoreScroll = false; + private _forcedScroll = false; private _dropDisposer?: DragManager.DragDropDisposer; private _disposers: { [name: string]: IReactionDisposer } = {}; private _getAnchor: (savedAnnotations: Opt<ObservableMap<number, HTMLDivElement[]>>, addAsAnnotation: boolean) => Opt<Doc> = () => undefined; @@ -118,6 +123,16 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp }, { fireImmediately: true } ); + this._disposers.scroll = reaction( + () => this.layoutDoc._scrollTop, + s_top => { + this._forcedScroll = true; + !this._ignoreScroll && this._mainCont.current && (this._mainCont.current.scrollTop = NumCast(s_top)); + this._mainCont.current?.scrollTo({ top: NumCast(s_top) }); + this._forcedScroll = false; + }, + { fireImmediately: true } + ); } componentWillUnmount() { @@ -155,6 +170,21 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp setUseAlt = () => (this.layoutDoc[this.fieldKey + '-useAlt'] = !this.layoutDoc[this.fieldKey + '-useAlt']); @undoBatch + setNativeSize = action(() => { + const scaling = (this.props.DocumentView?.().props.ScreenToLocalTransform().Scale || 1) / NumCast(this.rootDoc._viewScale, 1); + const nscale = NumCast(this.props.PanelWidth()) / scaling; + const nh = nscale / NumCast(this.dataDoc[this.fieldKey + '-nativeHeight']); + const nw = nscale / NumCast(this.dataDoc[this.fieldKey + '-nativeWidth']); + this.dataDoc[this.fieldKey + '-nativeHeight'] = NumCast(this.dataDoc[this.fieldKey + '-nativeHeight']) * nh; + this.dataDoc[this.fieldKey + '-nativeWidth'] = NumCast(this.dataDoc[this.fieldKey + '-nativeWidth']) * nw; + this.rootDoc._panX = nh * NumCast(this.rootDoc._panX); + this.rootDoc._panY = nw * NumCast(this.rootDoc._panY); + this.dataDoc._panXMax = this.dataDoc._panXMax ? nh * NumCast(this.dataDoc._panXMax) : undefined; + this.dataDoc._panXMin = this.dataDoc._panXMin ? nh * NumCast(this.dataDoc._panXMin) : undefined; + this.dataDoc._panYMax = this.dataDoc._panYMax ? nw * NumCast(this.dataDoc._panYMax) : undefined; + this.dataDoc._panYMin = this.dataDoc._panYMin ? nw * NumCast(this.dataDoc._panYMin) : undefined; + }); + @undoBatch rotate = action(() => { const nw = NumCast(this.dataDoc[this.fieldKey + '-nativeWidth']); const nh = NumCast(this.dataDoc[this.fieldKey + '-nativeHeight']); @@ -188,6 +218,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp const croppingProto = Doc.GetProto(cropping); croppingProto.annotationOn = undefined; croppingProto.isPrototype = true; + croppingProto.backgroundColor = undefined; croppingProto.proto = Cast(this.rootDoc.proto, Doc, null)?.proto; // set proto of cropping's data doc to be IMAGE_PROTO croppingProto.type = DocumentType.IMG; croppingProto.layout = ImageBox.LayoutString('data'); @@ -204,7 +235,11 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp croppingProto.panYMax = anchh / viewScale; if (addCrop) { DocUtils.MakeLink({ doc: region }, { doc: cropping }, 'cropped image', ''); + cropping.x = NumCast(this.rootDoc.x) + this.rootDoc[WidthSym](); + cropping.y = NumCast(this.rootDoc.y); + this.props.addDocTab(cropping, OpenWhere.inParent); } + DocumentManager.Instance.AddViewRenderedCb(cropping, dv => setTimeout(() => (dv.ComponentView as ImageBox).setNativeSize(), 200)); this.props.bringToFront(cropping); return cropping; }; @@ -215,6 +250,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp const funcs: ContextMenuProps[] = []; funcs.push({ description: 'Rotate Clockwise 90', event: this.rotate, icon: 'redo-alt' }); funcs.push({ description: `Show ${this.layoutDoc._showFullRes ? 'Dynamic Res' : 'Full Res'}`, event: this.resolution, icon: 'expand' }); + funcs.push({ description: 'Set Native Pixel Size', event: this.setNativeSize, icon: 'expand-arrows-alt' }); funcs.push({ description: `${this.layoutDoc[this.fieldKey + '-useAlt'] ? 'Show Alternate' : 'Show Primary'}`, event: this.setUseAlt, icon: 'image' }); funcs.push({ description: 'Copy path', event: () => Utils.CopyText(this.choosePath(field.url)), icon: 'copy' }); if (!Doc.noviceMode) { @@ -281,6 +317,8 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp return !tags ? null : <img id={'google-tags'} src={'/assets/google_tags.png'} />; }; + getScrollHeight = () => (this.props.fitWidth?.(this.rootDoc) !== false && NumCast(this.rootDoc._viewScale, 1) === NumCast(this.rootDoc._viewScaleMin, 1) ? this.nativeSize.nativeHeight : undefined); + @computed private get considerDownloadIcon() { const data = this.dataDoc[this.fieldKey]; @@ -345,8 +383,9 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp @computed get content() { TraceMobx(); - const srcpath = this.paths[0]; - const fadepath = this.paths.lastElement(); + const col = DashColor(this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor)); + const srcpath = this.layoutDoc.hideImage ? '' : this.paths[0]; + const fadepath = this.layoutDoc.hideImage ? '' : this.paths.lastElement(); const { nativeWidth, nativeHeight, nativeOrientation } = this.nativeSize; const rotation = NumCast(this.dataDoc[this.fieldKey + '-rotation']); const aspect = rotation % 180 ? nativeHeight / nativeWidth : 1; @@ -364,7 +403,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp return ( <div className="imageBox-cont" key={this.layoutDoc[Id]} ref={this.createDropTarget} onPointerDown={this.marqueeDown}> - <div className="imageBox-fader" style={{ overflow: Array.from(this.props.docViewPath?.()).slice(-1)[0].fitWidth ? 'auto' : undefined }}> + <div className="imageBox-fader" style={{ opacity: col.alpha() }}> <img key="paths" src={srcpath} style={{ transform, transformOrigin }} draggable={false} width={nativeWidth} /> {fadepath === srcpath ? null : ( <div @@ -381,7 +420,6 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp ); } - screenToLocalTransform = this.props.ScreenToLocalTransform; contentFunc = () => [this.content]; private _mainCont: React.RefObject<HTMLDivElement> = React.createRef(); @@ -392,6 +430,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp TraceMobx(); return <div className="imageBox-annotationLayer" style={{ height: this.props.PanelHeight() }} ref={this._annotationLayer} />; } + screenToLocalTransform = () => this.props.ScreenToLocalTransform().translate(0, NumCast(this.layoutDoc._scrollTop) * this.props.ScreenToLocalTransform().Scale); marqueeDown = (e: React.PointerEvent) => { if (!e.altKey && e.button === 0 && NumCast(this.rootDoc._viewScale, 1) <= NumCast(this.rootDoc.viewScaleMin, 1) && this.props.isContentActive(true) && ![InkTool.Highlighter, InkTool.Pen, InkTool.Write].includes(Doc.ActiveTool)) { setupMoveUpEvents( @@ -415,11 +454,6 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp this.props.select(false); }; savedAnnotations = () => this._savedAnnotations; - styleProvider = (doc: Opt<Doc>, props: Opt<DocumentViewProps>, property: string): any => { - if (property === StyleProp.BoxShadow) return undefined; - return this.props.styleProvider?.(doc, props, property); - }; - render() { TraceMobx(); const borderRad = this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.BorderRounding); @@ -429,17 +463,27 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp className="imageBox" onContextMenu={this.specificContextMenu} ref={this._mainCont} + onScroll={action(e => { + if (!this._forcedScroll) { + if (this.layoutDoc._scrollTop || this._mainCont.current?.scrollTop) { + this._ignoreScroll = true; + this.layoutDoc._scrollTop = this._mainCont.current?.scrollTop; + this._ignoreScroll = false; + } + } + })} style={{ width: this.props.PanelWidth() ? undefined : `100%`, height: this.props.PanelWidth() ? undefined : `100%`, pointerEvents: this.layoutDoc._lockedPosition ? 'none' : undefined, borderRadius, + overflow: this.layoutDoc.fitWidth || this.props.fitWidth?.(this.rootDoc) ? 'auto' : undefined, }}> <CollectionFreeFormView {...OmitKeys(this.props, ['NativeWidth', 'NativeHeight', 'setContentView']).omit} renderDepth={this.props.renderDepth + 1} fieldKey={this.annotationKey} - styleProvider={this.styleProvider} + styleProvider={this.props.styleProvider} CollectionView={undefined} isAnnotationOverlay={true} annotationLayerHostsContent={true} @@ -447,6 +491,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp PanelHeight={this.props.PanelHeight} ScreenToLocalTransform={this.screenToLocalTransform} select={emptyFunction} + getScrollHeight={this.getScrollHeight} NativeDimScaling={returnOne} whenChildContentsActiveChanged={this.whenChildContentsActiveChanged} removeDocument={this.removeDocument} |