From fec7f7dd736af3296a2df52acd07f3eadb8123c3 Mon Sep 17 00:00:00 2001
From: sharkiecodes <lanyi_stroud@brown.edu>
Date: Thu, 1 May 2025 00:44:14 -0400
Subject: marquee selection

---
 src/client/views/nodes/scrapbook/ScrapbookBox.tsx | 231 +++++++++++++++++++++-
 1 file changed, 230 insertions(+), 1 deletion(-)

(limited to 'src/client/views/nodes/scrapbook/ScrapbookBox.tsx')

diff --git a/src/client/views/nodes/scrapbook/ScrapbookBox.tsx b/src/client/views/nodes/scrapbook/ScrapbookBox.tsx
index 33761efc9..731715964 100644
--- a/src/client/views/nodes/scrapbook/ScrapbookBox.tsx
+++ b/src/client/views/nodes/scrapbook/ScrapbookBox.tsx
@@ -12,21 +12,36 @@ import { FieldView, FieldViewProps } from '../FieldView';
 import { DragManager } from '../../../util/DragManager';
 import { RTFCast, StrCast, toList } from '../../../../fields/Types';
 import { undoable } from '../../../util/UndoManager';
+import { ScrapbookItemConfig, ScrapbookPreset } from './ScrapbookPreset';
+
+enum ScrapbookPresetType {
+    Classic = 'Classic',
+    Default = 'Default',
+    Collage = 'Collage',
+    Spotlight = 'Spotlight',
+}
+
 // Scrapbook view: a container that lays out its child items in a grid/template
 export class ScrapbookBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
     @observable createdDate: string;
+     @observable configs : ScrapbookItemConfig[]
 
     constructor(props: FieldViewProps) {
         super(props);
         makeObservable(this);
         this.createdDate = this.getFormattedDate();
 
+        this.configs = 
+        ScrapbookPreset.createPreset(presetType);
+
         // ensure we always have a List<Doc> in dataDoc['items']
         if (!this.dataDoc[this.fieldKey]) {
             this.dataDoc[this.fieldKey] = new List<Doc>();
         }
         this.createdDate = this.getFormattedDate();
+        //this.initScrapbook(ScrapbookPresetType.Default);
         this.setTitle();
+        //this.setLayout(ScrapbookPreset.Spotlight);
     }
 
     public static LayoutString(fieldStr: string) {
@@ -41,6 +56,188 @@ export class ScrapbookBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
         });
     }
 
+    
+    @action
+    initScrapbook(presetType: ScrapbookPresetType) {
+      // 1) ensure title is set
+      const title = `Scrapbook - ${this.createdDate}`;
+      if (this.dataDoc.title !== title) {
+        this.dataDoc.title = title;
+      }
+    
+      // 2) build placeholders from the preset
+      const configs = ScrapbookPreset.createPreset(presetType);
+      const placeholders: Doc[] = [];
+    
+      for (const cfg of configs) {
+        if (cfg.children) {
+          // --- nested container ---
+          const childDocs = cfg.children.map(child => {
+            const doc = Docs.Create.TextDocument(child.tag);
+            doc.accepts_docType = child.type;
+            doc.accepts_tagType = child.acceptTag ?? child.tag;
+    
+            const ph = new Doc();
+            ph.proto    = doc;
+            ph.original = doc;
+            ph.x        = child.x;
+            ph.y        = child.y;
+            if (child.width  != null) ph._width  = child.width;
+            if (child.height != null) ph._height = child.height;
+            return ph;
+          });
+    
+          const protoW = cfg.containerWidth ?? cfg.width;
+          const protoH = cfg.containerHeight ?? cfg.height;
+          const containerProto = Docs.Create.StackingDocument(
+            childDocs,
+            {
+              ...(protoW != null ? { _width:  protoW } : {}),
+              ...(protoH != null ? { _height: protoH } : {}),
+              title: cfg.tag
+            }
+          );
+    
+          const ph = new Doc();
+          ph.proto    = containerProto;
+          ph.original = containerProto;
+          ph.x        = cfg.x;
+          ph.y        = cfg.y;
+          if (cfg.width  != null) ph._width  = cfg.width;
+          if (cfg.height != null) ph._height = cfg.height;
+          placeholders.push(ph);
+    
+        } else {
+          // --- flat placeholder ---
+          const doc = Docs.Create.TextDocument(cfg.tag);
+          doc.accepts_docType = cfg.type;
+          doc.accepts_tagType = cfg.acceptTag ?? cfg.tag;
+    
+          const ph = new Doc();
+          ph.proto    = doc;
+          ph.original = doc;
+          ph.x        = cfg.x;
+          ph.y        = cfg.y;
+          if (cfg.width  != null) ph._width  = cfg.width;
+          if (cfg.height != null) ph._height = cfg.height;
+          placeholders.push(ph);
+        }
+      }
+    
+      // 3) commit them into the field
+      this.dataDoc[this.fieldKey] = new List<Doc>(placeholders);
+    }
+    @action
+    //INACTIVE VER ignore!! not in use rn, implementation ver 1
+    setLayout(preset: ScrapbookPreset) {
+        // helper to wrap a TextDocument proto in a Doc with positioning
+        function makePlaceholder(
+            proto: Doc, x: number, y: number,
+            width: number, height: number
+        ): Doc {
+            const d = new Doc();
+            d.proto = proto;
+            d.original = proto;
+            d.x = x;
+            d.y = y;
+            d._width = width;
+            d._height = height;
+            return d;
+        }
+    
+        let placeholders: Doc[];
+    
+        switch (preset) {
+            case ScrapbookPresetType.Classic:
+                // One large landscape image on top, caption below, sidebar at right
+                const imgClassic = Docs.Create.TextDocument('image');
+                imgClassic.accepts_docType = DocumentType.IMG;
+                imgClassic.accepts_tagType = 'LANDSCAPE';
+                const phImageClassic = makePlaceholder(imgClassic, 0, -120, 300, 180);
+    
+                const captionClassic = Docs.Create.TextDocument('caption');
+                captionClassic.accepts_docType = DocumentType.RTF;
+                captionClassic.accepts_tagType = 'caption';
+                const phCaptionClassic = makePlaceholder(captionClassic, 0, 80, 300, 60);
+    
+                const sidebarClassic = Docs.Create.TextDocument('sidebar');
+                sidebarClassic.accepts_docType = DocumentType.RTF;
+                sidebarClassic.accepts_tagType = 'lengthy description';
+                const phSidebarClassic = makePlaceholder(sidebarClassic, 320, -50, 80, 200);
+    
+                placeholders = [phImageClassic, phCaptionClassic, phSidebarClassic];
+                break;
+    
+            case ScrapbookPresetType.Collage:
+                // Grid of four person images, small captions under each
+                const personDocs: Doc[] = [];
+                for (let i = 0; i < 4; i++) {
+                    const img = Docs.Create.TextDocument(`person ${i+1}`);
+                    img.accepts_docType = DocumentType.IMG;
+                    img.accepts_tagType = 'PERSON';
+                    // position in 2x2 grid
+                    const x = (i % 2) * 160 - 80;
+                    const y = Math.floor(i / 2) * 160 - 80;
+                    personDocs.push(makePlaceholder(img, x, y, 150, 120));
+    
+                    const cap = Docs.Create.TextDocument(`caption ${i+1}`);
+                    cap.accepts_docType = DocumentType.RTF;
+                    cap.accepts_tagType = 'caption';
+                    personDocs.push(makePlaceholder(cap, x, y + 70, 150, 30));
+                }
+                placeholders = personDocs;
+                break;
+    
+            case ScrapbookPresetType.Spotlight:
+                // Full-width title, then a stacking of an internal person image + landscape, then description
+                const titleSpot = Docs.Create.TextDocument('title');
+                titleSpot.accepts_docType = DocumentType.RTF;
+                titleSpot.accepts_tagType = 'title';
+                const phTitleSpot = makePlaceholder(titleSpot, 0, -180, 400, 60);
+    
+                const internalImg = Docs.Create.TextDocument('<person>');
+                internalImg.accepts_docType = DocumentType.IMG;
+                internalImg.accepts_tagType = 'PERSON';
+                const phInternal = makePlaceholder(internalImg, -100, -120, 120, 160);
+    
+                const landscapeImg = Docs.Create.TextDocument('<landscape>');
+                landscapeImg.accepts_docType = DocumentType.IMG;
+                landscapeImg.accepts_tagType = 'LANDSCAPE';
+                const phLandscape = makePlaceholder(landscapeImg, 50, 0, 200, 160);
+    
+                const stack = Docs.Create.StackingDocument(
+                    [phInternal, phLandscape],
+                    { _width: 360, _height: 180, title: 'spotlight stack' }
+                );
+                const phStack = (() => {
+                    const d = new Doc();
+                    d.proto = stack;
+                    d.original = stack;
+                    d.x = 8;
+                    d.y = -84;
+                    d._width = 360;
+                    d._height = 180;
+                    return d;
+                })();
+    
+                const descSpot = Docs.Create.TextDocument('description');
+                descSpot.accepts_docType = DocumentType.RTF;
+                descSpot.accepts_tagType = 'lengthy description';
+                const phDescSpot = makePlaceholder(descSpot, 0, 140, 400, 100);
+    
+                placeholders = [phTitleSpot, phStack, phDescSpot];
+                break;
+    
+            default:
+                placeholders = [];
+        }
+    
+        // finally assign into the dataDoc
+        this.dataDoc[this.fieldKey] = new List<Doc>(placeholders);
+    }
+
+    
+
     @action
     setTitle() {
         const title = `Scrapbook - ${this.createdDate}`;
@@ -120,13 +317,14 @@ export class ScrapbookBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
            difference between passing a new List<Doc> versus just the raw array?
            */
 
-            this.dataDoc[this.fieldKey] = new List<Doc>([placeholder, placeholder2, placeholder3, placeholder4]);
+          this.dataDoc[this.fieldKey] = this.dataDoc[this.fieldKey] ?? new List<Doc>([placeholder, placeholder2, placeholder3, placeholder4]);
 
           
         }
     }
 
     componentDidMount() {
+        //this.initScrapbook(ScrapbookPresetType.Default);
         this.setTitle();
     }
 
@@ -222,6 +420,37 @@ export class ScrapbookBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
     }
 }
 
+
+
+function extractScrapbookConfigs(docs: Doc[]): ScrapbookItemConfig[] {
+    return docs.map(doc => extractConfig(doc));
+}
+
+// function extractConfig(doc: Doc): ScrapbookItemConfig {
+//     const layoutKey = Doc.LayoutDataKey(doc);
+//     const childDocs = doc[layoutKey] ? DocListCast(doc[layoutKey]) : [];
+
+//     const isContainer = childDocs.length > 0;
+
+//     const cfg: ScrapbookItemConfig = {
+//         type: isContainer ? DocumentType.COL : doc.$type,
+//         tag: 
+//         acceptTag: doc.accepts_tagType,
+//         x: doc.x || 0,
+//         y: doc.y || 0,
+//         width: doc._width,
+//         height: doc._height,
+//     };
+
+//     if (isContainer) {
+//         cfg.containerWidth = doc.proto._width;
+//         cfg.containerHeight = doc.proto._height;
+//         cfg.children = childDocs.map(child => extractConfig(child));
+//     }
+
+//     return cfg;
+// }
+
 // Register scrapbook
 Docs.Prototypes.TemplateMap.set(DocumentType.SCRAPBOOK, {
     layout: { view: ScrapbookBox, dataField: 'items' },
-- 
cgit v1.2.3-70-g09d2

