import { Doc, DocListCast, Field } from '../../fields/Doc'; import { Copy, Id } from '../../fields/FieldSymbols'; import { List } from '../../fields/List'; import { ObjectField } from '../../fields/ObjectField'; import { NumCast, StrCast } from '../../fields/Types'; import { SerializationHelper } from '../util/SerializationHelper'; export interface MarqueeViewBounds { left: number; top: number; width: number; height: number; } export interface pinDataTypes { scrollable?: boolean; dataviz?: number[]; pannable?: boolean; collectionType?: boolean; inkable?: boolean; filters?: boolean; pivot?: boolean; temporal?: boolean; clippable?: boolean; datarange?: boolean; dataview?: boolean; poslayoutview?: boolean; dataannos?: boolean; map?: boolean; } export interface PinProps { audioRange?: boolean; activeFrame?: number; currentFrame?: number; hidePresBox?: boolean; pinViewport?: MarqueeViewBounds; // pin a specific viewport on a freeform view (use MarqueeView.CurViewBounds to compute if no region has been selected) pinDocLayout?: boolean; // pin layout info (width/height/x/y) pinAudioPlay?: boolean; // pin audio annotation pinData?: pinDataTypes; } /** * copies values from the targetDoc (which is the prototype of the pinDoc) to * reserved fields on the pinDoc so that those values can be restored to the * target doc when navigating to it. * @param pinDoc Doc that will store pinned metadata * @param pinProps description of props to pin * @param targetDoc Doc that is being pinned */ export function PinDocView(pinDocIn: Doc, pinProps: PinProps, targetDoc: Doc) { const pinDoc = pinDocIn; pinDoc.presentation = true; pinDoc.config = ''; if (pinProps.pinDocLayout) { pinDoc.config_pinLayout = true; pinDoc.config_x = NumCast(targetDoc.x); pinDoc.config_y = NumCast(targetDoc.y); pinDoc.config_rotation = NumCast(targetDoc.rotation); pinDoc.config_width = NumCast(targetDoc.width); pinDoc.config_height = NumCast(targetDoc.height); } if (pinProps.pinAudioPlay) pinDoc.presentation_playAudio = true; if (pinProps.pinData) { pinDoc.config_pinData = pinProps.pinData.scrollable || pinProps.pinData.temporal || pinProps.pinData.pannable || pinProps.pinData.collectionType || pinProps.pinData.clippable || pinProps.pinData.datarange || pinProps.pinData.dataview || pinProps.pinData.poslayoutview || pinProps?.activeFrame !== undefined; const fkey = Doc.LayoutDataKey(targetDoc); if (pinProps.pinData.dataview) { pinDoc.config_usePath = targetDoc[fkey + '_usePath']; pinDoc.config_data = Field.Copy(targetDoc[fkey]); } if (pinProps.pinData.dataannos) { const fieldKey = '$' + Doc.LayoutDataKey(targetDoc) + +'_annotations'; pinDoc.config_annotations = new List(DocListCast(targetDoc[fieldKey]).filter(doc => !doc.layout_unrendered)); } if (pinProps.pinData.inkable) { pinDoc.config_fillColor = targetDoc.fillColor; pinDoc.config_color = targetDoc.color; pinDoc.config_width = targetDoc._width; pinDoc.config_height = targetDoc._height; } if (pinProps.pinData.scrollable) pinDoc.config_scrollTop = targetDoc._layout_scrollTop; if (pinProps.pinData.clippable) { const fieldKey = Doc.LayoutDataKey(targetDoc); pinDoc.config_clipWidth = targetDoc[fieldKey + '_clipWidth']; } if (pinProps.pinData.datarange) { pinDoc.config_xRange = undefined; // targetDoc?.xrange; pinDoc.config_yRange = undefined; // targetDoc?.yrange; } if (pinProps.pinData.map) { // pinDoc.config_latitude = targetDoc?.latitude; // pinDoc.config_longitude = targetDoc?.longitude; pinDoc.config_map_zoom = targetDoc?.map_zoom; pinDoc.config_map_type = targetDoc?.map_type; // ... } if (pinProps.pinData.poslayoutview) pinDoc.config_pinLayoutData = new List( DocListCast(targetDoc[fkey] as ObjectField).map(d => JSON.stringify({ id: d[Id], x: NumCast(d.x), y: NumCast(d.y), w: NumCast(d._width), h: NumCast(d._height), fill: StrCast(d._fillColor), back: StrCast(d._backgroundColor), data: SerializationHelper.Serialize(d.data instanceof ObjectField ? d.data[Copy]() : ''), text: SerializationHelper.Serialize(d.text instanceof ObjectField ? d.text[Copy]() : ''), }) ) ); if (pinProps.pinData.collectionType) pinDoc.config_type_collection = targetDoc._type_collection; if (pinProps.pinData.filters) pinDoc.config_docFilters = ObjectField.MakeCopy(targetDoc.childFilters as ObjectField) ?? new List(); if (pinProps.pinData.pivot) pinDoc.config_pivotField = targetDoc._pivotField; if (pinProps.pinData.pannable) { pinDoc.config_panX = NumCast(targetDoc._freeform_panX); pinDoc.config_panY = NumCast(targetDoc._freeform_panY); pinDoc.config_viewScale = NumCast(targetDoc._freeform_scale, 1); } if (pinProps.pinData.temporal) { pinDoc.config_clipStart = targetDoc._layout_currentTimecode; const duration = NumCast(pinDoc[`${Doc.LayoutDataKey(pinDoc)}_duration`], NumCast(targetDoc.config_clipStart) + 0.1); pinDoc.config_clipEnd = NumCast(pinDoc.config_clipStart) + NumCast(targetDoc.clipEnd, duration); } } if (pinProps?.pinViewport) { // If pinWithView option set then update scale and x / y props of slide const bounds = pinProps.pinViewport; pinDoc.config_pinView = true; pinDoc.config_viewScale = NumCast(targetDoc._freeform_scale, 1); pinDoc.config_panX = bounds.left + bounds.width / 2; pinDoc.config_panY = bounds.top + bounds.height / 2; pinDoc.config_viewBounds = new List([bounds.left, bounds.top, bounds.left + bounds.width, bounds.top + bounds.height]); } }