aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/collections
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/collections')
-rw-r--r--src/client/views/collections/CollectionCarousel3DView.tsx2
-rw-r--r--src/client/views/collections/CollectionCarouselView.tsx11
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx113
-rw-r--r--src/client/views/collections/collectionFreeForm/MarqueeOptionsMenu.tsx3
-rw-r--r--src/client/views/collections/collectionFreeForm/MarqueeView.tsx13
5 files changed, 109 insertions, 33 deletions
diff --git a/src/client/views/collections/CollectionCarousel3DView.tsx b/src/client/views/collections/CollectionCarousel3DView.tsx
index 38f681e87..4f3ce9d9b 100644
--- a/src/client/views/collections/CollectionCarousel3DView.tsx
+++ b/src/client/views/collections/CollectionCarousel3DView.tsx
@@ -79,7 +79,7 @@ export class CollectionCarousel3DView extends CollectionSubView() {
// suppressSetHeight={true}
NativeWidth={returnZero}
NativeHeight={returnZero}
- fitWidth={undefined}
+ fitWidth={this._props.childLayoutFitWidth}
onDoubleClickScript={this.onChildDoubleClick}
renderDepth={this._props.renderDepth + 1}
LayoutTemplate={this._props.childLayoutTemplate}
diff --git a/src/client/views/collections/CollectionCarouselView.tsx b/src/client/views/collections/CollectionCarouselView.tsx
index 2adad68e0..8b083de15 100644
--- a/src/client/views/collections/CollectionCarouselView.tsx
+++ b/src/client/views/collections/CollectionCarouselView.tsx
@@ -8,7 +8,7 @@ import * as React from 'react';
import { StopEvent, returnFalse, returnOne, returnTrue, returnZero } from '../../../ClientUtils';
import { emptyFunction } from '../../../Utils';
import { Doc, Opt } from '../../../fields/Doc';
-import { DocCast, NumCast, ScriptCast, StrCast } from '../../../fields/Types';
+import { Cast, DocCast, NumCast, ScriptCast, StrCast } from '../../../fields/Types';
import { DocumentType } from '../../documents/DocumentTypes';
import { DragManager } from '../../util/DragManager';
import { ContextMenu } from '../ContextMenu';
@@ -144,6 +144,7 @@ export class CollectionCarouselView extends CollectionSubView() {
revealItems.push({description: 'Quiz Cards', event: () => {this.layoutDoc.filterOp = cardMode.QUIZ;}, icon: 'pencil',}); // prettier-ignore
!revealOptions && cm.addItem({ description: 'Filter Flashcards', addDivider: false, noexpand: true, subitems: revealItems, icon: 'layer-group' });
};
+ childFitWidth = (doc: Doc) => Cast(this.Document.childLayoutFitWidth, 'boolean', this._props.childLayoutFitWidth?.(doc) ?? Cast(doc.layout_fitWidth, 'boolean', null));
@computed get content() {
const index = NumCast(this.layoutDoc._carousel_index);
const curDoc = this.carouselItems?.[index];
@@ -154,10 +155,11 @@ export class CollectionCarouselView extends CollectionSubView() {
<div className="collectionCarouselView-image" key="image">
<DocumentView
{...this._props}
- NativeWidth={returnZero}
- NativeHeight={returnZero}
- fitWidth={undefined}
+ // NativeWidth={returnZero}
+ // NativeHeight={returnZero}
+ fitWidth={returnTrue}
setContentViewBox={undefined}
+ containerViewPath={this.DocumentView?.().docViewPath}
onDoubleClickScript={this.onContentDoubleClick}
onClickScript={this.onContentClick}
isDocumentActive={this._props.childDocumentsActive?.() ? this._props.isDocumentActive : this._props.isContentActive}
@@ -169,6 +171,7 @@ export class CollectionCarouselView extends CollectionSubView() {
Document={curDoc.layout}
TemplateDataDocument={DocCast(curDoc.layout.resolvedDataDoc)}
PanelHeight={this.panelHeight}
+ PanelWidth={this._props.PanelWidth}
/>
</div>
{!carouselShowsCaptions ? null : (
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 5b7f09be3..62632e8c2 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -55,6 +55,8 @@ import { CollectionFreeFormPannableContents } from './CollectionFreeFormPannable
import { CollectionFreeFormRemoteCursors } from './CollectionFreeFormRemoteCursors';
import './CollectionFreeFormView.scss';
import { MarqueeView } from './MarqueeView';
+import { DrawingOptions, SmartDrawHandler } from '../../smartdraw/SmartDrawHandler';
+import { AnnotationPalette } from '../../smartdraw/AnnotationPalette';
@observer
class CollectionFreeFormOverlayView extends React.Component<{ elements: () => ViewDefResult[] }> {
@@ -1239,6 +1241,69 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
};
@action
+ showSmartDraw = (e: PointerEvent, doubleTap?: boolean) => {
+ SmartDrawHandler.Instance.displaySmartDrawHandler(e.pageX, e.pageY, this.createDrawing, this.removeDrawing);
+ };
+
+ _drawing: Doc[] = [];
+ _drawingContainer: Doc | undefined = undefined;
+ @undoBatch
+ createDrawing = (strokeData: [InkData, string, string][], opts: DrawingOptions, gptRes: string, containerDoc?: Doc) => {
+ this._drawing = [];
+ const xf = this.screenToFreeformContentsXf;
+ // this._drawingContainer = undefined;
+ strokeData.forEach((stroke: [InkData, string, string]) => {
+ const bounds = InkField.getBounds(stroke[0]);
+ const B = xf.transformBounds(bounds.left, bounds.top, bounds.width, bounds.height);
+ const inkWidth = ActiveInkWidth() * this.ScreenToLocalBoxXf().Scale;
+ const inkDoc = Docs.Create.InkDocument(
+ stroke[0],
+ { title: 'stroke',
+ x: B.x - inkWidth / 2,
+ y: B.y - inkWidth / 2,
+ _width: B.width + inkWidth,
+ _height: B.height + inkWidth,
+ stroke_showLabel: BoolCast(Doc.UserDoc().activeInkHideTextLabels)}, // prettier-ignore
+ inkWidth,
+ opts.autoColor ? stroke[1] : ActiveInkColor(),
+ ActiveInkBezierApprox(),
+ stroke[2] === 'none' ? ActiveFillColor() : stroke[2],
+ ActiveArrowStart(),
+ ActiveArrowEnd(),
+ ActiveDash(),
+ ActiveIsInkMask()
+ );
+ this._drawing.push(inkDoc);
+ this.addDocument(inkDoc);
+ });
+ const collection = this._marqueeViewRef.current?.collection(undefined, true, this._drawing);
+ if (collection) {
+ const docData = collection[DocData];
+ docData.title = opts.text.match(/^(.*?)~~~.*$/)?.[1] || opts.text;
+ docData.drawingInput = opts.text;
+ docData.drawingComplexity = opts.complexity;
+ docData.drawingColored = opts.autoColor;
+ docData.drawingSize = opts.size;
+ docData.drawingData = gptRes;
+ this._drawingContainer = collection;
+ }
+ this._batch?.end();
+ };
+
+ removeDrawing = (doc?: Doc) => {
+ this._batch = UndoManager.StartBatch('regenerateDrawing');
+ if (doc) {
+ const docData = doc[DocData];
+ const children = DocListCast(docData.data);
+ this._props.removeDocument?.(doc);
+ this._props.removeDocument?.(children);
+ } else {
+ if (this._drawingContainer) this._props.removeDocument?.(this._drawingContainer);
+ }
+ this._drawing = [];
+ };
+
+ @action
zoom = (pointX: number, pointY: number, deltaY: number): void => {
if (this.Document.isGroup || this.Document[(this._props.viewField ?? '_') + 'freeform_noZoom']) return;
let deltaScale = deltaY > 0 ? 1 / 1.05 : 1.05;
@@ -1688,7 +1753,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
.forEach(entry =>
elements.push({
ele: this.getChildDocView(entry[1]),
- bounds: (entry[1].opacity === 0 ? { payload:undefined, type:"", ...entry[1], width: 0, height: 0 } : { payload:undefined, type:"",...entry[1] }),
+ bounds: entry[1].opacity === 0 ? { payload: undefined, type: '', ...entry[1], width: 0, height: 0 } : { payload: undefined, type: '', ...entry[1] },
inkMask: BoolCast(entry[1].pair.layout.stroke_isInkMask) ? NumCast(entry[1].pair.layout.opacity, 1) : -1,
})
);
@@ -1810,26 +1875,27 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
Object.values(this._disposers).forEach(disposer => disposer?.());
}
- updateIcon = () => {
+ updateIcon = (usePanelDimensions?: boolean) => {
const contentDiv = this.DocumentView?.().ContentDiv;
- contentDiv && UpdateIcon(
- this.layoutDoc[Id] + '-icon' + new Date().getTime(),
- contentDiv,
- NumCast(this.layoutDoc._width),
- NumCast(this.layoutDoc._height),
- this._props.PanelWidth(),
- this._props.PanelHeight(),
- 0,
- 1,
- false,
- '',
- (iconFile, nativeWidth, nativeHeight) => {
- this.dataDoc.icon = new ImageField(iconFile);
- this.dataDoc.icon_nativeWidth = nativeWidth;
- this.dataDoc.icon_nativeHeight = nativeHeight;
- }
- );
- }
+ contentDiv &&
+ UpdateIcon(
+ this.layoutDoc[Id] + '-icon' + new Date().getTime(),
+ contentDiv,
+ usePanelDimensions ? this._props.PanelWidth() : NumCast(this.layoutDoc._width),
+ usePanelDimensions ? this._props.PanelHeight() : NumCast(this.layoutDoc._height),
+ this._props.PanelWidth(),
+ this._props.PanelHeight(),
+ 0,
+ 1,
+ false,
+ '',
+ (iconFile, nativeWidth, nativeHeight) => {
+ this.dataDoc.icon = new ImageField(iconFile);
+ this.dataDoc.icon_nativeWidth = nativeWidth;
+ this.dataDoc.icon_nativeHeight = nativeHeight;
+ }
+ );
+ };
@action
onCursorMove = (e: React.PointerEvent) => {
@@ -1941,6 +2007,13 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
}),
icon: 'eye',
});
+ optionItems.push({
+ description: 'Show Drawing Editor',
+ event: action(() => {
+ !SmartDrawHandler.Instance._showRegenerate ? SmartDrawHandler.Instance.displayRegenerate(this._downX, this._downY - 10, this.createDrawing, this.removeDrawing) : SmartDrawHandler.Instance.hideRegenerate();
+ }),
+ icon: 'pen-to-square',
+ });
this._props.renderDepth &&
optionItems.push({
description: 'Use Background Color as Default',
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeOptionsMenu.tsx b/src/client/views/collections/collectionFreeForm/MarqueeOptionsMenu.tsx
index f02cd9d45..b3fdd9379 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeOptionsMenu.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeOptionsMenu.tsx
@@ -3,6 +3,7 @@ import { IconButton } from 'browndash-components';
import { computed, makeObservable } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
+import { Doc } from '../../../../fields/Doc';
import { unimplementedFunction } from '../../../../Utils';
import { SettingsManager } from '../../../util/SettingsManager';
import { AntimodeMenu, AntimodeMenuProps } from '../../AntimodeMenu';
@@ -12,7 +13,7 @@ export class MarqueeOptionsMenu extends AntimodeMenu<AntimodeMenuProps> {
// eslint-disable-next-line no-use-before-define
static Instance: MarqueeOptionsMenu;
- public createCollection: (e: KeyboardEvent | React.PointerEvent | undefined, group?: boolean) => void = unimplementedFunction;
+ public createCollection: (e: KeyboardEvent | React.PointerEvent | undefined, group?: boolean, selection?: Doc[]) => Doc | void = unimplementedFunction;
public delete: (e: KeyboardEvent | React.PointerEvent | undefined) => void = unimplementedFunction;
public summarize: (e: KeyboardEvent | React.PointerEvent | undefined) => void = unimplementedFunction;
public showMarquee: () => void = unimplementedFunction;
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index dc15c83c5..63e36fc31 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -362,7 +362,7 @@ export class MarqueeView extends ObservableReactComponent<SubCollectionViewProps
this.hideMarquee();
});
- getCollection = action((selected: Doc[], creator: Opt<(documents: Array<Doc>, options: DocumentOptions, id?: string) => Doc>, makeGroup: Opt<boolean>) => {
+ public static getCollection = action((selected: Doc[], creator: Opt<(documents: Array<Doc>, options: DocumentOptions, id?: string) => Doc>, makeGroup: Opt<boolean>, bounds: MarqueeViewBounds) => {
const newCollection = creator
? creator(selected, { title: 'nested stack' })
: ((doc: Doc) => {
@@ -374,14 +374,13 @@ export class MarqueeView extends ObservableReactComponent<SubCollectionViewProps
return doc;
})(Doc.MakeCopy(Doc.UserDoc().emptyCollection as Doc, true));
newCollection.isSystem = undefined;
- newCollection._width = this.Bounds.width;
- newCollection._height = this.Bounds.height;
+ newCollection._width = bounds.width || 1; // if width/height are unset/0, then groups won't autoexpand to contain their children
+ newCollection._height = bounds.height || 1;
newCollection._dragWhenActive = makeGroup;
- newCollection.x = this.Bounds.left;
- newCollection.y = this.Bounds.top;
+ newCollection.x = bounds.left;
+ newCollection.y = bounds.top;
newCollection.layout_fitWidth = true;
selected.forEach(d => Doc.SetContainer(d, newCollection));
- this.hideMarquee();
return newCollection;
});
@@ -418,7 +417,7 @@ export class MarqueeView extends ObservableReactComponent<SubCollectionViewProps
this._props.removeDocument?.(selected);
}
- const newCollection = this.getCollection(selected, (e as KeyboardEvent)?.key === 't' ? Docs.Create.StackingDocument : undefined, group);
+ const newCollection = MarqueeView.getCollection(selected, (e as KeyboardEvent)?.key === 't' ? Docs.Create.StackingDocument : undefined, group, this.Bounds);
newCollection._freeform_panX = this.Bounds.left + this.Bounds.width / 2;
newCollection._freeform_panY = this.Bounds.top + this.Bounds.height / 2;
newCollection._currentFrame = activeFrame;