aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client/documents/Documents.ts5
-rw-r--r--src/client/util/DocumentManager.ts6
-rw-r--r--src/client/views/.DS_Storebin6148 -> 6148 bytes
-rw-r--r--src/client/views/MainView.tsx3
-rw-r--r--src/client/views/collections/CollectionDockingView.scss62
-rw-r--r--src/client/views/collections/CollectionDockingView.tsx24
-rw-r--r--src/client/views/collections/CollectionMenu.scss16
-rw-r--r--src/client/views/collections/CollectionStackingView.tsx26
-rw-r--r--src/client/views/collections/CollectionStackingViewFieldColumn.tsx4
-rw-r--r--src/client/views/collections/CollectionTreeView.tsx1
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss139
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx81
-rw-r--r--src/client/views/nodes/CollectionFreeFormDocumentView.tsx132
-rw-r--r--src/client/views/nodes/DocumentView.tsx3
-rw-r--r--src/client/views/nodes/FieldView.tsx1
-rw-r--r--src/client/views/nodes/PresBox.scss672
-rw-r--r--src/client/views/nodes/PresBox.tsx1651
-rw-r--r--src/client/views/pdf/PDFViewer.tsx9
-rw-r--r--src/client/views/presentationview/PresElementBox.scss175
-rw-r--r--src/client/views/presentationview/PresElementBox.tsx145
-rw-r--r--src/fields/Doc.ts4
-rw-r--r--src/typings/index.d.ts7
22 files changed, 2850 insertions, 316 deletions
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 40eae0528..0da93aa7a 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -134,6 +134,11 @@ export interface DocumentOptions {
currentFrame?: number; // the current frame of a frame-based collection (e.g., progressive slide)
lastFrame?: number; // the last frame of a frame-based collection (e.g., progressive slide)
activeFrame?: number; // the active frame of a document in a frame base collection
+ appearFrame?: number; // the frame in which the document appears
+ presTransition?: number; //the time taken for the transition TO a document
+ presDuration?: number; //the duration of the slide in presentation view
+ // xArray?: number[];
+ // yArray?: number[];
borderRounding?: string;
boxShadow?: string;
dontRegisterChildViews?: boolean;
diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index 523dbfca0..d18eac374 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -127,6 +127,10 @@ export class DocumentManager {
CollectionDockingView.AddRightSplit(doc);
finished?.();
}
+ // static openInPlace = (doc: Doc, finished?: () => void) => {
+ // CollectionDockingView.AddTab(doc);
+ // finished?.();
+ // }
public jumpToDocument = async (
targetDoc: Doc, // document to display
willZoom: boolean, // whether to zoom doc to take up most of screen
@@ -176,7 +180,7 @@ export class DocumentManager {
const targetDocContextView = getFirstDocView(targetDocContext);
targetDocContext._scrollY = 0; // this will force PDFs to activate and load their annotations / allow scrolling
if (targetDocContextView) { // we found a context view and aren't forced to create a new one ... focus on the context first..
- targetDocContext._viewTransition = "transform 500ms";
+ targetDocContext._viewTransition = "transform 10000ms";
targetDocContextView.props.focus(targetDocContextView.props.Document, willZoom);
// now find the target document within the context
diff --git a/src/client/views/.DS_Store b/src/client/views/.DS_Store
index 3717a2923..3ce88292c 100644
--- a/src/client/views/.DS_Store
+++ b/src/client/views/.DS_Store
Binary files differ
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index bb73df75c..58478ce92 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -148,7 +148,8 @@ export class MainView extends React.Component {
fa.faEye, fa.faArrowsAlt, fa.faQuoteLeft, fa.faSortAmountDown, fa.faAlignLeft, fa.faAlignCenter, fa.faAlignRight, fa.faHeading, fa.faRulerCombined,
fa.faFillDrip, fa.faLink, fa.faUnlink, fa.faBold, fa.faItalic, fa.faChevronLeft, fa.faUnderline, fa.faStrikethrough, fa.faSuperscript, fa.faSubscript,
fa.faIndent, fa.faEyeDropper, fa.faPaintRoller, fa.faBars, fa.faBrush, fa.faShapes, fa.faEllipsisH, fa.faHandPaper, fa.faMap, fa.faUser, faHireAHelper,
- fa.faBezierCurve, fa.faCircle, fa.faLongArrowAltRight, fa.faPenFancy, fa.faAngleDoubleRight, faBuffer);
+ fa.faBezierCurve, fa.faCircle, fa.faLongArrowAltRight, fa.faPenFancy, fa.faAngleDoubleRight, fa.faAngleUp, fa.faAngleDown, fa.faPlayCircle, fa.faClock,
+ fa.faRocket, fa.faExchangeAlt, faBuffer);
this.initEventListeners();
this.initAuthenticationRouters();
}
diff --git a/src/client/views/collections/CollectionDockingView.scss b/src/client/views/collections/CollectionDockingView.scss
index 1895c06a1..9b14df760 100644
--- a/src/client/views/collections/CollectionDockingView.scss
+++ b/src/client/views/collections/CollectionDockingView.scss
@@ -18,6 +18,68 @@
}
}
}
+
+.miniPres:hover {
+ opacity: 1;
+}
+
+.miniPres {
+ position: absolute;
+ overflow: hidden;
+ right: 10;
+ top: 10;
+ opacity: 0.1;
+ transition: all 0.4s;
+ /* border: solid 1px; */
+ color: white;
+ /* box-shadow: black 0.4vw 0.4vw 0.8vw; */
+
+ .miniPresOverlay {
+ display: grid;
+ grid-template-columns: auto auto auto auto auto auto auto auto;
+ grid-template-rows: 100%;
+ height: 100%;
+ justify-items: center;
+ align-items: center;
+
+ .miniPres-button-text {
+ display: flex;
+ height: 30;
+ font-weight: 400;
+ min-width: 100%;
+ border-radius: 5px;
+ align-items: center;
+ justify-content: center;
+ transition: all 0.3s;
+ }
+
+ .miniPres-divider {
+ width: 1px;
+ height: 80%;
+ border-right: solid 2px #5a5a5a;
+ }
+
+ .miniPres-button {
+ display: flex;
+ height: 30;
+ min-width: 30;
+ border-radius: 100%;
+ align-items: center;
+ justify-content: center;
+ transition: all 0.3s;
+ }
+
+ .miniPres-button:hover {
+ background-color: #5a5a5a;
+ }
+
+ .miniPres-button-text:hover {
+ background-color: #5a5a5a;
+ }
+ }
+}
+
+
.lm_title {
margin-top: 3px;
border-radius: 5px;
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 4952dedc9..f658e9816 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -31,6 +31,8 @@ import { SnappingManager } from '../../util/SnappingManager';
import { CollectionFreeFormView } from './collectionFreeForm/CollectionFreeFormView';
import { listSpec } from '../../../fields/Schema';
import { clamp } from 'lodash';
+import { PresBox } from '../nodes/PresBox';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
const _global = (window /* browser */ || global /* node */) as any;
@observer
@@ -837,6 +839,27 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
return false;
}), emptyFunction, emptyFunction);
}
+ getCurrentFrame = (): number => {
+ const presTargetDoc = Cast(PresBox.Instance.childDocs[PresBox.Instance.itemIndex].presentationTargetDoc, Doc, null);
+ const currentFrame = Cast(presTargetDoc.currentFrame, "number", null);
+ return currentFrame;
+ }
+ renderMiniPres() {
+ return <div className="miniPres" style={{
+ width: 400, height: 50, background: '#323232'
+ }}>
+ <div className="miniPresOverlay" >
+ <div className="miniPres-button" onClick={PresBox.Instance.back}><FontAwesomeIcon icon={"arrow-left"} /></div>
+ <div className="miniPres-button" onClick={() => PresBox.Instance.startOrResetPres(PresBox.Instance.itemIndex)}><FontAwesomeIcon icon={PresBox.Instance.layoutDoc.presStatus === "auto" ? "pause" : "play"} /></div>
+ <div className="miniPres-button" onClick={PresBox.Instance.next}><FontAwesomeIcon icon={"arrow-right"} /></div>
+ <div className="miniPres-divider"></div>
+ <div className="miniPres-button-text">Slide {PresBox.Instance.itemIndex + 1} / {PresBox.Instance.childDocs.length}</div>
+ {/* <div className="miniPres-button-text">{this.getCurrentFrame}</div> */}
+ <div className="miniPres-divider"></div>
+ <div className="miniPres-button-text" onClick={PresBox.Instance.updateMinimize}>EXIT</div>
+ </div>
+ </div>;
+ }
renderMiniMap() {
return <div className="miniMap" style={{
width: this.returnMiniSize(), height: this.returnMiniSize(), background: StrCast(this._document!._backgroundColor,
@@ -919,6 +942,7 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
ContainingCollectionView={undefined}
ContainingCollectionDoc={undefined} />
{document._viewType === CollectionViewType.Freeform && !this._document?.hideMinimap ? this.renderMiniMap() : (null)}
+ {document._viewType === CollectionViewType.Freeform && this._document?.miniPres ? this.renderMiniPres() : (null)}
</>;
}
diff --git a/src/client/views/collections/CollectionMenu.scss b/src/client/views/collections/CollectionMenu.scss
index 9da204787..7201afcc0 100644
--- a/src/client/views/collections/CollectionMenu.scss
+++ b/src/client/views/collections/CollectionMenu.scss
@@ -2,8 +2,8 @@
.collectionMenu-cont {
- position:relative;
- display:inline-flex;
+ position: relative;
+ display: inline-flex;
width: 100%;
opacity: 0.9;
z-index: 9001;
@@ -12,14 +12,15 @@
color: white;
transform-origin: top left;
top: 0;
- width:100%;
+ width: 100%;
.antimodeMenu-button {
padding: 0;
width: 30px;
display: flex;
+
svg {
- margin:auto;
+ margin: auto;
}
}
@@ -108,6 +109,7 @@
margin-top: auto;
margin-bottom: auto;
}
+
.collectionViewBaseChrome-viewSpecs {
margin-left: 5px;
display: grid;
@@ -318,12 +320,14 @@
text-align: center;
display: block;
}
+
.color-previewI {
width: 80%;
height: 20%;
bottom: 0;
position: absolute;
}
+
.color-previewII {
width: 80%;
height: 80%;
@@ -336,7 +340,7 @@
margin: auto;
/* Make the buttons appear below each other */
}
-
+
.btn-draw {
display: inline-flex;
margin: auto;
@@ -364,6 +368,7 @@
}
}
+
.numKeyframe {
flex-direction: column;
padding-top: 5px;
@@ -374,6 +379,7 @@
display: block;
margin: auto;
}
+
border-right: solid gray 1px;
}
}
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index 312dd92f0..425dc90e4 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -184,7 +184,7 @@ export class CollectionStackingView extends CollectionSubView(StackingDocument)
if (found) {
const top = found.getBoundingClientRect().top;
const localTop = this.props.ScreenToLocalTransform().transformPoint(0, top);
- smoothScroll(500, this._mainCont!, localTop[1] + this._mainCont!.scrollTop);
+ smoothScroll(doc.presTransition ? Number(doc.presTransition) : 500, this._mainCont!, localTop[1] + this._mainCont!.scrollTop);
}
afterFocus && setTimeout(() => {
if (afterFocus?.()) { }
@@ -286,14 +286,26 @@ export class CollectionStackingView extends CollectionSubView(StackingDocument)
}
});
if (super.onInternalDrop(e, de)) {
- const newDoc = de.complete.docDragData.droppedDocuments[0];
+ const newDocs = de.complete.docDragData.droppedDocuments;
const docs = this.childDocList;
if (docs) {
- if (targInd === -1) targInd = docs.length;
- else targInd = docs.indexOf(this.filteredChildren[targInd]);
- const srcInd = docs.indexOf(newDoc);
- docs.splice(srcInd, 1);
- docs.splice((targInd > srcInd ? targInd - 1 : targInd) + plusOne, 0, newDoc);
+ newDocs.map((doc, i) => {
+ if (i === 0) {
+ if (targInd === -1) targInd = docs.length;
+ else targInd = docs.indexOf(this.filteredChildren[targInd]);
+ const srcInd = docs.indexOf(doc);
+ docs.splice(srcInd, 1);
+ docs.splice((targInd > srcInd ? targInd - 1 : targInd) + plusOne, 0, doc);
+ } else {
+ if (targInd === -1) targInd = docs.length;
+ else targInd = docs.indexOf(this.filteredChildren[targInd]);
+ const srcInd = docs.indexOf(doc);
+ const firstInd = docs.indexOf(newDocs[0]);
+ docs.splice(srcInd, 1);
+ // docs.splice((targInd > srcInd ? targInd - 1 : targInd) + plusOne, 0, doc);
+ docs.splice(firstInd + 1, 0, doc);
+ }
+ });
}
}
}
diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
index a6983de05..26d2ee8a3 100644
--- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
+++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
@@ -346,7 +346,7 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
</div> : (null);
for (let i = 0; i < cols; i++) templatecols += `${style.columnWidth / style.numGroupColumns}px `;
const chromeStatus = this.props.parent.props.Document._chromeStatus;
-
+ const type = this.props.parent.props.Document.type;
return <>
{this.props.parent.Document._columnsHideIfEmpty ? (null) : headingView}
{
@@ -366,7 +366,7 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
{this.props.parent.children(this.props.docList, uniqueHeadings.length)}
{singleColumn ? (null) : this.props.parent.columnDragger}
</div>
- {(chromeStatus !== 'view-mode' && chromeStatus !== 'disabled') ?
+ {(chromeStatus !== 'view-mode' && chromeStatus !== 'disabled' && type !== 'presentation') ?
<div key={`${heading}-add-document`} className="collectionStackingView-addDocumentButton"
style={{ width: style.columnWidth / style.numGroupColumns }}>
<EditableView {...newEditableViewProps} menuCallback={this.menuCallback} />
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 705871a6f..b8996c178 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -130,6 +130,7 @@ class TreeView extends React.Component<TreeViewProps> {
}
protected createTreeDropTarget = (ele: HTMLDivElement) => {
+ console.log("ele");
this._treedropDisposer?.();
ele && (this._treedropDisposer = DragManager.MakeDropTarget(ele, this.treeDrop.bind(this), undefined, this.preTreeDrop.bind(this)), this.doc);
}
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss
index 92aee3776..2b07c4efb 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss
@@ -13,16 +13,153 @@
}
.collectionfreeformview-viewdef {
- > .collectionFreeFormDocumentView-container {
+ >.collectionFreeFormDocumentView-container {
pointer-events: none;
+
.contentFittingDocumentDocumentView-previewDoc {
pointer-events: all;
}
}
+
+ svg.presPaths {
+ position: absolute;
+ z-index: 100000;
+ overflow: visible;
+ }
+
+ svg.presPaths-hidden {
+ display: none;
+ }
}
.collectionfreeformview-none {
touch-action: none;
+
+ svg.presPaths {
+ position: absolute;
+ z-index: 100000;
+ overflow: visible;
+ }
+
+ svg.presPaths-hidden {
+ display: none;
+ }
+}
+
+.pathOrder {
+ position: absolute;
+ z-index: 200000;
+
+ .pathOrder-frame {
+ position: absolute;
+ width: 40;
+ text-align: center;
+ font-size: 30;
+ background-color: #69a6db;
+ font-family: Roboto;
+ font-weight: 300;
+ }
+}
+
+.progressivizeButton {
+ position: absolute;
+ display: grid;
+ grid-template-columns: auto 20px auto;
+ transform: translate(-105%, 0);
+ align-items: center;
+ border: black solid 1px;
+ border-radius: 3px;
+ justify-content: center;
+ width: 40;
+ z-index: 30000;
+ height: 20;
+ overflow: hidden;
+ background-color: #d5dce2;
+ transition: all 1s;
+
+ .progressivizeButton-prev:hover {
+ color: #5a9edd;
+ }
+
+ .progressivizeButton-frame {
+ justify-self: center;
+ text-align: center;
+ width: 15px;
+ }
+
+ .progressivizeButton-next:hover {
+ color: #5a9edd;
+ }
+}
+
+.resizable {
+ background: rgba(0, 0, 0, 0.2);
+ width: 100px;
+ height: 100px;
+ position: absolute;
+ top: 100px;
+ left: 100px;
+
+ .resizers {
+ width: 100%;
+ height: 100%;
+ border: 3px solid #69a6db;
+ box-sizing: border-box;
+
+ .resizer {
+ position: absolute;
+ width: 10px;
+ height: 10px;
+ border-radius: 50%;
+ /*magic to turn square into circle*/
+ background: white;
+ border: 3px solid #69a6db;
+ }
+
+ .resizer.top-left {
+ left: -3px;
+ top: -3px;
+ cursor: nwse-resize;
+ /*resizer cursor*/
+ }
+
+ .resizer.top-right {
+ right: -3px;
+ top: -3px;
+ cursor: nesw-resize;
+ }
+
+ .resizer.bottom-left {
+ left: -3px;
+ bottom: -3px;
+ cursor: nesw-resize;
+ }
+
+ .resizer.bottom-right {
+ right: -3px;
+ bottom: -3px;
+ cursor: nwse-resize;
+ }
+ }
+}
+
+.progressivizeMove-frame {
+ width: 20px;
+ border-radius: 2px;
+ z-index: 100000;
+ color: white;
+ text-align: center;
+ background-color: #5a9edd;
+ transform: translate(-110%, 110%);
+}
+
+.progressivizeButton:hover {
+ box-shadow: 0px 2px 3px rgba(0, 0, 0, 0.5);
+
+ .progressivizeButton-frame {
+ background-color: #5a9edd;
+ color: white;
+ }
}
.collectionFreeform-customText {
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 57336131a..151acb64d 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -1,7 +1,7 @@
import { library } from "@fortawesome/fontawesome-svg-core";
import { faEye } from "@fortawesome/free-regular-svg-icons";
import { faBraille, faChalkboard, faCompass, faCompressArrowsAlt, faExpandArrowsAlt, faFileUpload, faPaintBrush, faTable, faUpload } from "@fortawesome/free-solid-svg-icons";
-import { action, computed, IReactionDisposer, observable, ObservableMap, reaction, runInAction } from "mobx";
+import { action, computed, IReactionDisposer, observable, ObservableMap, reaction, runInAction, trace } from "mobx";
import { observer } from "mobx-react";
import { computedFn } from "mobx-utils";
import { Doc, DocListCast, HeightSym, Opt, WidthSym } from "../../../../fields/Doc";
@@ -46,6 +46,7 @@ import "./CollectionFreeFormView.scss";
import MarqueeOptionsMenu from "./MarqueeOptionsMenu";
import { MarqueeView } from "./MarqueeView";
import React = require("react");
+import { PresBox } from "../../nodes/PresBox";
import { SearchUtil } from "../../../util/SearchUtil";
import { LinkManager } from "../../../util/LinkManager";
@@ -76,8 +77,7 @@ export type collectionFreeformViewProps = {
forceScaling?: boolean; // whether to force scaling of content (needed by ImageBox)
viewDefDivClick?: ScriptField;
childPointerEvents?: boolean;
- scaleField?: string; // used by formattedTextBox when displaying a sidebar freeform view which needs its own scale field
- noOverlay?: boolean; // used to suppress docs in the overlay (z) layer (ie, for minimap since overlay doesn't scale)
+ scaleField?: string;
};
@observer
@@ -213,7 +213,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
const layoutDoc = Doc.Layout(d);
if (this.Document.currentFrame !== undefined) {
const vals = CollectionFreeFormDocumentView.getValues(d, NumCast(d.activeFrame, 1000));
- CollectionFreeFormDocumentView.setValues(this.Document.currentFrame, d, x + vals.x - dropPos[0], y + vals.y - dropPos[1], vals.opacity);
+ CollectionFreeFormDocumentView.setValues(this.Document.currentFrame, d, x + vals.x - dropPos[0], y + vals.y - dropPos[1], vals.h, vals.w, vals.opacity);
} else {
d.x = x + NumCast(d.x) - dropPos[0];
d.y = y + NumCast(d.y) - dropPos[1];
@@ -911,7 +911,8 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
// !doc.z && NumCast(this.layoutDoc.scale) < 1 && this.scaleAtPt(DocumentView._focusHack, 1); // [NumCast(doc.x), NumCast(doc.y)], 1);
// } else {
if (DocListCast(this.dataDoc[this.props.fieldKey]).includes(doc)) {
- if (!doc.z) this.setPan(newPanX, newPanY, "transform 500ms", true); // docs that are floating in their collection can't be panned to from their collection -- need to propagate the pan to a parent freeform somehow
+ // glr: freeform transform speed can be set through user by adjusting for presentation transform
+ if (!doc.z) this.setPan(newPanX, newPanY, doc.presTransition ? `transform ${doc.presTransition}ms` : "transform 500ms", true); // docs that are floating in their collection can't be panned to from their collection -- need to propagate the pan to a parent freeform somehow
}
Doc.BrushDoc(this.props.Document);
this.props.focus(this.props.Document);
@@ -954,8 +955,8 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
DataDoc: childData,
Document: childLayout,
LibraryPath: this.libraryPath,
- LayoutTemplate: childLayout.z ? undefined : this.props.ChildLayoutTemplate,
- LayoutTemplateString: childLayout.z ? undefined : this.props.ChildLayoutString,
+ LayoutTemplate: this.props.ChildLayoutTemplate,
+ LayoutTemplateString: this.props.ChildLayoutString,
FreezeDimensions: this.props.freezeChildDimensions,
layoutKey: undefined,
setupDragLines: this.setupDragLines,
@@ -1397,6 +1398,9 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
<CollectionFreeFormViewPannableContents
centeringShiftX={this.centeringShiftX}
centeringShiftY={this.centeringShiftY}
+ presPaths={BoolCast(this.Document.presPathView)}
+ progressivize={BoolCast(this.Document.editProgressivize)}
+ zoomProgressivize={BoolCast(this.Document.editZoomProgressivize)}
transition={Cast(this.layoutDoc._viewTransition, "string", null)}
viewDefDivClick={this.props.viewDefDivClick}
zoomScaling={this.zoomScaling} panX={this.panX} panY={this.panY}>
@@ -1437,7 +1441,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
}}>
{this.Document._freeformLOD && !this.props.active() && !this.props.isAnnotationOverlay && !this.props.annotationsKey && this.props.renderDepth > 0 ?
this.placeholder : this.marqueeView}
- {!this.props.noOverlay ? <CollectionFreeFormOverlayView elements={this.elementFunc} /> : (null)}
+ <CollectionFreeFormOverlayView elements={this.elementFunc} />
<div className={"pullpane-indicator"}
style={{
@@ -1480,11 +1484,69 @@ interface CollectionFreeFormViewPannableContentsProps {
viewDefDivClick?: ScriptField;
children: () => JSX.Element[];
transition?: string;
+ presPaths?: boolean;
+ progressivize?: boolean;
+ zoomProgressivize?: boolean;
}
@observer
class CollectionFreeFormViewPannableContents extends React.Component<CollectionFreeFormViewPannableContentsProps>{
+ @computed get zoomProgressivize() {
+ if (this.props.zoomProgressivize) {
+ console.log("should render");
+ return (
+ <>
+ {PresBox.Instance.zoomProgressivizeContainer}
+ </>
+ );
+ }
+ }
+
+ @computed get progressivize() {
+ if (this.props.progressivize) {
+ console.log("should render");
+ return (
+ <>
+ {PresBox.Instance.progressivizeChildDocs}
+ </>
+ );
+ }
+ }
+
+ @computed get presPaths() {
+ const presPaths = "presPaths" + (this.props.presPaths ? "" : "-hidden");
+ if (this.props.presPaths) {
+ return (
+ <>
+ <div>{PresBox.Instance.order}</div>
+ <svg className={presPaths}>
+ <defs>
+ <marker id="arrow" markerWidth="3" overflow="visible" markerHeight="3" refX="5" refY="5" orient="auto" markerUnits="strokeWidth">
+ <path d="M0,0 L0,6 L9,3 z" fill="#69a6db" />
+ </marker>
+ <marker id="square" markerWidth="3" markerHeight="3" overflow="visible"
+ refX="5" refY="5" orient="auto" markerUnits="strokeWidth">
+ <path d="M 5,1 L 9,5 5,9 1,5 z" fill="#69a6db" />
+ </marker>
+ <marker id="markerSquare" markerWidth="7" markerHeight="7" refX="4" refY="4"
+ orient="auto" overflow="visible">
+ <rect x="1" y="1" width="5" height="5" fill="#69a6db" />
+ </marker>
+
+ <marker id="markerArrow" markerWidth="5" markerHeight="5" refX="2" refY="7"
+ orient="auto" overflow="visible">
+ <path d="M2,2 L2,13 L8,7 L2,2" fill="#69a6db" />
+ </marker>
+ </defs>;
+ {PresBox.Instance.paths}
+ </svg>
+ </>
+ );
+ }
+ }
+
render() {
+ // trace();
const freeformclass = "collectionfreeformview" + (this.props.viewDefDivClick ? "-viewDef" : "-none");
const cenx = this.props.centeringShiftX();
const ceny = this.props.centeringShiftY();
@@ -1497,6 +1559,9 @@ class CollectionFreeFormViewPannableContents extends React.Component<CollectionF
transition: this.props.transition
}}>
{this.props.children()}
+ {this.presPaths}
+ {this.progressivize}
+ {this.zoomProgressivize}
</div>;
}
}
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index ce39c3735..c29547eac 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -11,11 +11,15 @@ import { Document } from "../../../fields/documentSchemas";
import { TraceMobx } from "../../../fields/util";
import { ContentFittingDocumentView } from "./ContentFittingDocumentView";
import { List } from "../../../fields/List";
-import { numberRange } from "../../../Utils";
+import { numberRange, smoothScroll } from "../../../Utils";
import { ComputedField } from "../../../fields/ScriptField";
import { listSpec } from "../../../fields/Schema";
import { DocumentType } from "../../documents/DocumentTypes";
+import { Zoom, Fade, Flip, Rotate, Bounce, Roll, LightSpeed } from 'react-reveal';
+import { PresBox } from "./PresBox";
import { InkingStroke } from "../InkingStroke";
+import { PDFViewer } from "../pdf/PDFViewer";
+import { PDFBox } from "./PDFBox";
export interface CollectionFreeFormDocumentViewProps extends DocumentViewProps {
dataProvider?: (doc: Doc, replica: string) => { x: number, y: number, zIndex?: number, opacity?: number, highlight?: boolean, z: number, transition?: string } | undefined;
@@ -74,30 +78,64 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
public static getValues(doc: Doc, time: number) {
const timecode = Math.round(time);
return ({
+ h: Cast(doc["h-indexed"], listSpec("number"), [NumCast(doc._height)]).reduce((p, h, i) => (i <= timecode && h !== undefined) || p === undefined ? h : p, undefined as any as number),
+ w: Cast(doc["w-indexed"], listSpec("number"), [NumCast(doc._width)]).reduce((p, w, i) => (i <= timecode && w !== undefined) || p === undefined ? w : p, undefined as any as number),
x: Cast(doc["x-indexed"], listSpec("number"), [NumCast(doc.x)]).reduce((p, x, i) => (i <= timecode && x !== undefined) || p === undefined ? x : p, undefined as any as number),
y: Cast(doc["y-indexed"], listSpec("number"), [NumCast(doc.y)]).reduce((p, y, i) => (i <= timecode && y !== undefined) || p === undefined ? y : p, undefined as any as number),
+ scroll: Cast(doc["scroll-indexed"], listSpec("number"), [NumCast(doc._scrollTop, 0)]).reduce((p, s, i) => (i <= timecode && s !== undefined) || p === undefined ? s : p, undefined as any as number),
opacity: Cast(doc["opacity-indexed"], listSpec("number"), [NumCast(doc.opacity, 1)]).reduce((p, o, i) => i <= timecode || p === undefined ? o : p, undefined as any as number),
});
}
- public static setValues(time: number, d: Doc, x?: number, y?: number, opacity?: number) {
+ public static setValues(time: number, d: Doc, x?: number, y?: number, h?: number, w?: number, scroll?: number, opacity?: number) {
const timecode = Math.round(time);
+ const hindexed = Cast(d["h-indexed"], listSpec("number"), []).slice();
+ const windexed = Cast(d["w-indexed"], listSpec("number"), []).slice();
const xindexed = Cast(d["x-indexed"], listSpec("number"), []).slice();
const yindexed = Cast(d["y-indexed"], listSpec("number"), []).slice();
const oindexed = Cast(d["opacity-indexed"], listSpec("number"), []).slice();
+ const scrollIndexed = Cast(d["scroll-indexed"], listSpec("number"), []).slice();
xindexed[timecode] = x as any as number;
yindexed[timecode] = y as any as number;
+ hindexed[timecode] = h as any as number;
+ windexed[timecode] = w as any as number;
oindexed[timecode] = opacity as any as number;
+ scrollIndexed[timecode] = scroll as any as number;
d["x-indexed"] = new List<number>(xindexed);
d["y-indexed"] = new List<number>(yindexed);
+ d["h-indexed"] = new List<number>(hindexed);
+ d["w-indexed"] = new List<number>(windexed);
d["opacity-indexed"] = new List<number>(oindexed);
+ d["scroll-indexed"] = new List<number>(scrollIndexed);
}
+
+ public static updateScrollframe(doc: Doc, time: number) {
+ let _pdfViewer: PDFViewer | undefined;
+ const timecode = Math.round(time);
+ const scrollIndexed = Cast(doc['scroll-indexed'], listSpec("number"), null);
+ scrollIndexed?.length <= timecode + 1 && scrollIndexed.push(undefined as any as number);
+ setTimeout(() => doc.dataTransition = "inherit", 1010);
+ }
+
+ public static setupScroll(doc: Doc, timecode: number, scrollProgressivize: boolean = false) {
+ const scrollList = new List<number>();
+ scrollList[timecode] = NumCast(doc._scrollTop);
+ doc["scroll-indexed"] = scrollList;
+ doc.activeFrame = ComputedField.MakeFunction("self.currentFrame");
+ doc._scrollTop = ComputedField.MakeInterpolated("scroll", "activeFrame");
+ }
+
+
public static updateKeyframe(docs: Doc[], time: number) {
const timecode = Math.round(time);
docs.forEach(doc => {
const xindexed = Cast(doc['x-indexed'], listSpec("number"), null);
const yindexed = Cast(doc['y-indexed'], listSpec("number"), null);
+ const hindexed = Cast(doc['h-indexed'], listSpec("number"), null);
+ const windexed = Cast(doc['w-indexed'], listSpec("number"), null);
const opacityindexed = Cast(doc['opacity-indexed'], listSpec("number"), null);
+ hindexed?.length <= timecode + 1 && hindexed.push(undefined as any as number);
+ windexed?.length <= timecode + 1 && windexed.push(undefined as any as number);
xindexed?.length <= timecode + 1 && xindexed.push(undefined as any as number);
yindexed?.length <= timecode + 1 && yindexed.push(undefined as any as number);
opacityindexed?.length <= timecode + 1 && opacityindexed.push(undefined as any as number);
@@ -111,18 +149,53 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
setTimeout(() => docs.forEach(doc => doc.dataTransition = "inherit"), 1010);
}
+ public static setupZoom(doc: Doc, zoomProgressivize: boolean = false) {
+ const width = new List<number>();
+ const height = new List<number>();
+ const top = new List<number>();
+ const left = new List<number>();
+ width.push(NumCast(doc.width));
+ height.push(NumCast(doc.height));
+ top.push(NumCast(doc.height) / -2);
+ left.push(NumCast(doc.width) / -2);
+ doc["viewfinder-width-indexed"] = width;
+ doc["viewfinder-height-indexed"] = height;
+ doc["viewfinder-top-indexed"] = top;
+ doc["viewfinder-left-indexed"] = left;
+ }
+
public static setupKeyframes(docs: Doc[], timecode: number, progressivize: boolean = false) {
docs.forEach((doc, i) => {
+ if (!doc.appearFrame) doc.appearFrame = i;
const curTimecode = progressivize ? i : timecode;
const xlist = new List<number>(numberRange(timecode + 1).map(i => undefined) as any as number[]);
const ylist = new List<number>(numberRange(timecode + 1).map(i => undefined) as any as number[]);
- const olist = new List<number>(numberRange(timecode + 1).map(t => progressivize && t < i ? 0 : 1));
+ const wlist = new List<number>(numberRange(timecode + 1).map(i => undefined) as any as number[]);
+ const hlist = new List<number>(numberRange(timecode + 1).map(i => undefined) as any as number[]);
+ const olist = new List<number>(numberRange(timecode + 1).map(t => progressivize && t < (doc.appearFrame ? doc.appearFrame : i) ? 0 : 1));
+ let oarray: List<number>;
+ console.log(doc.title + "AF: " + doc.appearFrame);
+ console.log("timecode: " + timecode);
+ oarray = olist;
+ oarray.fill(0, 0, NumCast(doc.appearFrame) - 1);
+ oarray.fill(1, NumCast(doc.appearFrame), timecode);
+ // oarray.fill(0, 0, NumCast(doc.appearFrame) - 1);
+ // oarray.fill(1, NumCast(doc.appearFrame), timecode);
+ // console.log(oarray);
+ wlist[curTimecode] = NumCast(doc._width);
+ hlist[curTimecode] = NumCast(doc._height);
xlist[curTimecode] = NumCast(doc.x);
ylist[curTimecode] = NumCast(doc.y);
+ doc.xArray = xlist;
+ doc.yArray = ylist;
doc["x-indexed"] = xlist;
doc["y-indexed"] = ylist;
- doc["opacity-indexed"] = olist;
+ doc["w-indexed"] = wlist;
+ doc["h-indexed"] = hlist;
+ doc["opacity-indexed"] = oarray;
doc.activeFrame = ComputedField.MakeFunction("self.context?.currentFrame||0");
+ doc._height = ComputedField.MakeInterpolated("h", "activeFrame");
+ doc._width = ComputedField.MakeInterpolated("w", "activeFrame");
doc.x = ComputedField.MakeInterpolated("x", "activeFrame");
doc.y = ComputedField.MakeInterpolated("y", "activeFrame");
doc.opacity = ComputedField.MakeInterpolated("opacity", "activeFrame");
@@ -135,6 +208,44 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
this.props.Document.y = NumCast(this.props.Document.y) + y;
}
+ @computed get freeformNodeDiv() {
+ const node = <DocumentView {...this.props}
+ nudge={this.nudge}
+ dragDivName={"collectionFreeFormDocumentView-container"}
+ ContentScaling={this.contentScaling}
+ ScreenToLocalTransform={this.getTransform}
+ backgroundColor={this.props.backgroundColor}
+ opacity={this.opacity}
+ NativeHeight={this.NativeHeight}
+ NativeWidth={this.NativeWidth}
+ PanelWidth={this.panelWidth}
+ PanelHeight={this.panelHeight} />;
+ if (PresBox.Instance && this.layoutDoc === PresBox.Instance.childDocs[PresBox.Instance.itemIndex]?.presentationTargetDoc) {
+ const effectProps = {
+ left: this.layoutDoc.presEffectDirection === 'left',
+ right: this.layoutDoc.presEffectDirection === 'right',
+ top: this.layoutDoc.presEffectDirection === 'top',
+ bottom: this.layoutDoc.presEffectDirection === 'bottom',
+ opposite: true,
+ delay: this.layoutDoc.presTransition,
+ // when: this.layoutDoc === PresBox.Instance.childDocs[PresBox.Instance.itemIndex]?.presentationTargetDoc,
+ };
+ switch (this.layoutDoc.presEffect) {
+ case "Zoom": return (<Zoom {...effectProps}>{node}</Zoom>); break;
+ case "Fade": return (<Fade {...effectProps}>{node}</Fade>); break;
+ case "Flip": return (<Flip {...effectProps}>{node}</Flip>); break;
+ case "Rotate": return (<Rotate {...effectProps}>{node}</Rotate>); break;
+ case "Bounce": return (<Bounce {...effectProps}>{node}</Bounce>); break;
+ case "Roll": return (<Roll {...effectProps}>{node}</Roll>); break;
+ case "LightSpeed": return (<LightSpeed {...effectProps}>{node}</LightSpeed>); break;
+ case "None": return node; break;
+ default: return node; break;
+ }
+ } else {
+ return node;
+ }
+ }
+
contentScaling = () => this.nativeWidth > 0 && !this.props.fitToBox && !this.freezeDimensions ? this.width / this.nativeWidth : 1;
panelWidth = () => (this.sizeProvider?.width || this.props.PanelWidth?.());
panelHeight = () => (this.sizeProvider?.height || this.props.PanelHeight?.());
@@ -165,6 +276,7 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
display: this.ZInd === -99 ? "none" : undefined,
pointerEvents: this.props.Document.isBackground || this.Opacity === 0 || this.props.Document.type === DocumentType.INK || this.props.Document.isInkMask ? "none" : this.props.pointerEvents ? "all" : undefined
}} >
+
{Doc.UserDoc().renderStyle !== "comic" ? (null) :
<div style={{ width: "100%", height: "100%", position: "absolute" }}>
<svg style={{ transform: `scale(1,${this.props.PanelHeight() / this.props.PanelWidth()})`, transformOrigin: "top left", overflow: "visible" }} viewBox="0 0 12 14">
@@ -174,17 +286,7 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
</div>}
{!this.props.fitToBox ?
- <DocumentView {...this.props}
- nudge={this.nudge}
- dragDivName={"collectionFreeFormDocumentView-container"}
- ContentScaling={this.contentScaling}
- ScreenToLocalTransform={this.getTransform}
- backgroundColor={this.props.backgroundColor}
- opacity={this.opacity}
- NativeHeight={this.NativeHeight}
- NativeWidth={this.NativeWidth}
- PanelWidth={this.panelWidth}
- PanelHeight={this.panelHeight} />
+ <>{this.freeformNodeDiv}</>
: <ContentFittingDocumentView {...this.props}
ContainingCollectionDoc={this.props.ContainingCollectionDoc}
DataDoc={this.props.DataDoc}
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 15cf9556b..b3bfadf4f 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -963,13 +963,12 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
const fullDegree = Doc.isBrushedHighlightedDegree(this.props.Document);
const borderRounding = this.layoutDoc.borderRounding;
const localScale = fullDegree;
-
const highlightColors = Cast(Doc.UserDoc().activeWorkspace, Doc, null)?.darkScheme ?
["transparent", "#65350c", "#65350c", "yellow", "magenta", "cyan", "orange"] :
["transparent", "maroon", "maroon", "yellow", "magenta", "cyan", "orange"];
const highlightStyles = ["solid", "dashed", "solid", "solid", "solid", "solid", "solid"];
let highlighting = fullDegree && this.layoutDoc.type !== DocumentType.FONTICON && this.layoutDoc._viewType !== CollectionViewType.Linear && this.props.Document.type !== DocumentType.INK;
- highlighting = highlighting && this.props.focus !== emptyFunction; // bcz: hack to turn off highlighting onsidebar panel documents. need to flag a document as not highlightable in a more direct way
+ highlighting = highlighting && this.props.focus !== emptyFunction && this.layoutDoc.title !== "[pres element template]"; // bcz: hack to turn off highlighting onsidebar panel documents. need to flag a document as not highlightable in a more direct way
const topmost = this.topMost ? "-topmost" : "";
return <div className={`documentView-node${topmost}`}
id={this.props.Document[Id]}
diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index 48e1f6ce3..5d5bc1d73 100644
--- a/src/client/views/nodes/FieldView.tsx
+++ b/src/client/views/nodes/FieldView.tsx
@@ -45,6 +45,7 @@ export interface FieldViewProps {
whenActiveChanged: (isActive: boolean) => void;
dontRegisterView?: boolean;
focus: (doc: Doc) => void;
+ presMultiSelect?: (doc: Doc) => void; //added for selecting multiple documents in a presentation
ignoreAutoHeight?: boolean;
PanelWidth: () => number;
PanelHeight: () => number;
diff --git a/src/client/views/nodes/PresBox.scss b/src/client/views/nodes/PresBox.scss
index 9f6af1bde..b06503472 100644
--- a/src/client/views/nodes/PresBox.scss
+++ b/src/client/views/nodes/PresBox.scss
@@ -1,7 +1,9 @@
.presBox-cont {
position: absolute;
+ display: block;
pointer-events: inherit;
z-index: 2;
+ font-family: Roboto;
box-shadow: #AAAAAA .2vw .2vw .4vw;
width: 100%;
min-width: 20px;
@@ -12,73 +14,667 @@
transition: 0.7s opacity ease;
.presBox-listCont {
- position: absolute;
+ position: relative;
height: calc(100% - 25px);
width: 100%;
+ margin-top: 3px;
+ }
+
+ .presBox-toolbar {
+ display: none;
+ }
+
+ .presBox-toolbar.active {
+ position: relative;
+ display: inline-flex;
+ align-items: center;
+ height: 30px;
+ width: 100%;
+ color: white;
+ background-color: #323232;
+
+ .toolbar-button {
+ margin-left: 10px;
+ margin-right: 10px;
+ letter-spacing: 0;
+ display: flex;
+ align-items: center;
+ transition: 0.5s;
+ }
+
+ .toolbar-button.active {
+ color: #AEDDF8;
+ }
+
+ .toolbar-transitionButtons {
+ display: block;
+
+ .toolbar-transition {
+ display: flex;
+ font-size: 10;
+ width: 100;
+ background-color: rgba(0, 0, 0, 0);
+ min-width: max-content;
+
+ .toolbar-icon {
+ margin-right: 5px;
+ }
+ }
+ }
+ }
+
+ .toolbar-moreInfo {
+ position: absolute;
+ right: 5px;
+ display: flex;
+ width: max-content;
+ height: 25px;
+ /* background-color: pink; */
+ justify-content: center;
+ transform: rotate(90deg);
+ align-items: center;
+ transition: 0.7s ease;
+
+ .toolbar-moreInfoBall {
+ width: 4px;
+ height: 4px;
+ border-radius: 100%;
+ background-color: white;
+ margin: 1px;
+ position: relative;
+ }
+ }
+
+ .toolbar-moreInfo.active {
+ transform: rotate(0deg);
}
- .presBox-buttons {
+ .toolbar-divider {
+ border-left: solid #ffffff70 0.5px;
+ height: 20px;
+ }
+}
+
+.dropdown {
+ font-size: 10;
+ margin-left: 5px;
+ color: darkgrey;
+ transition: 0.5s ease;
+}
+
+.dropdown.active {
+ transform: rotate(180deg);
+ color: #AEDDF8;
+ opacity: 0.8;
+}
+
+.presBox-ribbon {
+ position: relative;
+ display: none;
+ font-family: Roboto;
+ background-color: white;
+ color: black;
+ width: 100%;
+ height: 0;
+ z-index: 100;
+ transition: 0.7s;
+
+ .ribbon-doubleButton {
+ display: inline-flex;
+ }
+
+ .toolbar-slider {
+ position: relative;
+ align-self: center;
+ justify-self: left;
+ -webkit-appearance: none;
+ transform: rotateY(180deg);
+ background-color: #40B3D8;
+ margin-top: 5px;
width: 100%;
- background: gray;
- padding-top: 5px;
- padding-bottom: 5px;
+ max-width: 120px;
+ height: 2.5px;
+ left: 0px;
+ }
+
+ .toolbar-slider:focus {
+ outline: none;
+ }
+
+ .effectDirection {
+ justify-self: center;
+ align-self: center;
+ align-items: center;
+ justify-content: center;
+ grid-template-columns: 13px 13px 13px;
display: grid;
- grid-column-end: 4;
- grid-column-start: 1;
+ }
- .presBox-viewPicker {
- height: 25;
+ .toolbar-slider::-webkit-slider-thumb {
+ -webkit-appearance: none;
+ background-color: #40B3D8;
+ border: 1px white solid;
+ border-radius: 100%;
+ width: 9px;
+ height: 9px;
+ }
+
+ .slider-headers {
+ position: relative;
+ display: grid;
+ justify-content: space-between;
+ width: 100%;
+ height: max-content;
+ max-width: 120px;
+ grid-template-columns: auto auto auto;
+ grid-template-rows: max-content;
+ font-weight: 100;
+ /* margin-top: 5px; */
+ font-size: 8px;
+ }
+
+ .slider-value {
+ top: -20;
+ color: #2f86a2;
+ position: absolute;
+ }
+
+ .slider-value.none,
+ .slider-headers.none,
+ .toolbar-slider.none {
+ display: none;
+ }
+
+ .dropdown-header {
+ padding-bottom: 10px;
+ font-weight: 800;
+ text-align: center;
+ font-size: 16;
+ width: 90%;
+ color: black;
+ transform: translate(5%, 0px);
+ border-bottom: solid 2px darkgrey;
+ }
+
+
+ .ribbon-textInput {
+ border-radius: 2px;
+ height: 20px;
+ font-size: 10;
+ font-weight: 100;
+ align-self: center;
+ justify-self: center;
+ padding-left: 10px;
+ border: solid 1px black;
+ min-width: 80px;
+ width: 100%;
+ }
+
+ .ribbon-frameSelector {
+ border: black solid 1px;
+ width: 60px;
+ height: 20px;
+ display: grid;
+ grid-template-columns: auto 27px auto;
+ position: relative;
+ border-radius: 5px;
+ overflow: hidden;
+ align-items: center;
+ justify-self: left;
+
+ .fwdKeyframe,
+ .backKeyframe {
+ cursor: pointer;
position: relative;
- display: inline-block;
- grid-column: 1/2;
- min-width: 15px;
+ height: 100%;
+ background: #d5dce2;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ text-align: center;
+ color: black;
}
- select {
- background: #323232;
- color: white;
+ .numKeyframe {
+ font-size: 10;
+ font-weight: 600;
+ position: relative;
+ color: black;
+ display: flex;
+ width: 100%;
+ height: 100%;
+ text-align: center;
+ align-items: center;
+ justify-content: center;
}
+ }
- .presBox-button {
- margin-right: 2.5%;
- margin-left: 2.5%;
- height: 25px;
- border-radius: 5px;
+ .ribbon-final-box {
+ align-self: flex-start;
+ justify-self: center;
+ display: grid;
+ grid-template-rows: auto auto;
+ padding-left: 10px;
+ padding-right: 10px;
+ letter-spacing: normal;
+ min-width: max-content;
+ width: 100%;
+ font-size: 13;
+ font-weight: 600;
+ position: relative;
+
+
+ .ribbon-final-button {
+ position: relative;
+ font-size: 10;
+ font-weight: normal;
+ letter-spacing: normal;
display: flex;
+ justify-content: center;
align-items: center;
- background: #323232;
+ margin-bottom: 5px;
+ height: 25px;
color: white;
-
- svg {
- margin: auto;
- }
+ width: 100%;
+ max-width: 120;
+ padding-left: 10;
+ padding-right: 10;
+ border-radius: 10px;
+ background-color: #979797;
}
- .collectionViewBaseChrome-viewPicker {
- min-width: 50;
- width: 5%;
- height: 25;
+ .ribbon-final-button-hidden {
position: relative;
- display: inline-block;
+ font-size: 10;
+ font-weight: normal;
+ letter-spacing: normal;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ margin-bottom: 5px;
+ height: 25px;
+ color: lightgrey;
+ width: 100%;
+ max-width: 120;
+ padding-left: 10;
+ padding-right: 10;
+ border-radius: 10px;
+ background-color: black;
+ }
+ }
+
+ .selectedList {
+ display: block;
+ min-width: 50;
+ max-width: 120;
+ height: 70;
+ overflow-y: scroll;
+
+ .selectedList-items {
+ font-size: 7;
+ font-weight: normal;
}
}
- .presBox-backward,
- .presBox-forward {
- width: 25px;
+ .ribbon-button {
+ font-size: 10;
+ font-weight: 200;
+ height: 20;
+ border: solid 1px black;
+ display: flex;
+ margin-top: 5px;
+ margin-bottom: 5px;
border-radius: 5px;
- top: 50%;
+ margin-right: 5px;
+ width: max-content;
+ justify-content: center;
+ align-items: center;
+ padding-right: 10px;
+ padding-left: 10px;
+ }
+
+ .ribbon-button.active {
+ background-color: #5B9FDD;
+ }
+
+ .ribbon-button:hover {
+ background-color: lightgrey;
+ }
+
+ svg.svg-inline--fa.fa-thumbtack.fa-w-12.toolbar-thumbtack {
+ right: 40;
position: absolute;
+ transform: rotate(45deg);
+ }
+
+ .ribbon-box {
+ display: grid;
+ grid-template-rows: max-content auto;
+ justify-self: center;
+ padding-left: 10px;
+ padding-right: 10px;
+ letter-spacing: normal;
+ width: 100%;
+ font-weight: 600;
+ position: relative;
+ font-size: 13;
+ border-right: solid 2px darkgrey;
+
+ .presBox-dropdown:hover {
+ border: solid 1px #378AD8;
+
+ .presBox-dropdownOption {
+ font-size: 10;
+ display: block;
+ padding-left: 5px;
+ padding-right: 5px;
+ padding-top: 3;
+ padding-bottom: 3;
+ }
+
+ .presBox-dropdownOption:hover {
+ position: relative;
+ background-color: lightgrey;
+ }
+
+ .presBox-dropdownOption.active {
+ position: relative;
+ background-color: #aedef8;
+ }
+
+ .presBox-dropdownOptions {
+ position: absolute;
+ top: 19px;
+ left: -1px;
+ z-index: 200;
+ width: 85%;
+ min-width: max-content;
+ display: block;
+ background: #FFFFFF;
+ border: 0.5px solid #979797;
+ box-sizing: border-box;
+ box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.25);
+ }
+
+ .presBox-dropdownIcon {
+ color: #378AD8;
+ }
+ }
+
+ .presBox-dropdown {
+ display: grid;
+ grid-template-columns: auto 20%;
+ position: relative;
+ border: solid 1px black;
+ font-size: 10;
+ height: 20;
+ padding-left: 5px;
+ align-items: center;
+ margin-top: 5px;
+ margin-bottom: 5px;
+ font-weight: 200;
+ width: 100%;
+ min-width: max-content;
+ max-width: 120;
+ overflow: visible;
+
+ .presBox-dropdownOptions {
+ display: none;
+ }
+
+ .presBox-dropdownIcon {
+ position: relative;
+ color: black;
+ align-self: center;
+ justify-self: center;
+ margin-right: 2px;
+ }
+ }
+ }
+}
+
+.presBox-ribbon.active {
+ display: grid;
+ grid-template-columns: auto auto auto auto auto;
+ grid-template-rows: 100%;
+ height: 100px;
+ padding-top: 5px;
+ padding-bottom: 5px;
+ border: solid 1px black;
+ // overflow: auto;
+
+ ::-webkit-scrollbar {
+ -webkit-appearance: none;
+ height: 3px;
+ width: 8px;
+ }
+
+ ::-webkit-scrollbar-thumb {
+ border-radius: 2px;
+ }
+}
+
+.dropdown-play-button {
+ font-size: 12;
+ padding-left: 5px;
+ padding-right: 5px;
+ padding-top: 5px;
+ padding-bottom: 5px;
+ text-align: left;
+ justify-content: left;
+}
+
+.dropdown-play-button:hover {
+ background-color: lightgrey;
+}
+
+.presBox-button-left {
+ position: relative;
+ align-self: flex-start;
+ justify-self: flex-start;
+ width: 80%;
+ height: 100%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ border-radius: 4px;
+ border-bottom-right-radius: 0;
+ border-top-right-radius: 0;
+}
+
+.presBox-button-right {
+ position: relative;
+ text-align: center;
+ border-left: solid 1px darkgrey;
+ width: 20%;
+ height: 100%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ border-radius: 4px;
+ border-bottom-left-radius: 0;
+ border-top-left-radius: 0;
+}
+
+.presBox-button-right.active {
+ background-color: #223063;
+ border: #aedcf6 solid 1px;
+ box-shadow: 0px 4px 10px rgba(0, 0, 0, 0.8);
+}
+
+.dropdown-play {
+ right: 0px;
+ top: calc(100% + 2px);
+ display: none;
+ border-radius: 5px;
+ width: max-content;
+ min-height: 20px;
+ height: max-content;
+ box-shadow: 0px 4px 10px rgba(0, 0, 0, 0.8);
+ z-index: 200;
+ background-color: white;
+ color: black;
+ position: absolute;
+ overflow: hidden;
+}
+
+.dropdown-play.active {
+ display: block;
+}
+
+.layout-container {
+ overflow-x: scroll;
+ display: flex;
+ width: 100%;
+ /* max-width: 200px; */
+ min-width: 100px;
+ height: 100%;
+ // border: solid 1px;
+ /* display: block; */
+ align-self: center;
+
+ .layout:hover {
+ border: solid 2px #5c9edd;
+ }
+
+ .layout {
+ position: relative;
+ top: 10%;
+ height: 80%;
+ margin-right: 10;
+ min-width: 90px;
+ width: 90px;
+ border: solid black 1px;
+ display: grid;
+ grid-template-rows: 20px 30px;
+ align-items: center;
+ text-align: center;
+
+ .header {
+ font-size: 10;
+ font-weight: 600;
+ width: 70%;
+ height: max-content;
+ align-self: center;
+ justify-self: center;
+ border: solid 0.8px black;
+ }
+
+ .subheader {
+ font-size: 8;
+ font-weight: 400;
+ width: 70%;
+ height: 90%;
+ align-self: center;
+ justify-self: center;
+ border: solid 0.4px black;
+ }
+ }
+}
+
+.presBox-buttons {
+ position: relative;
+ width: 100%;
+ background: gray;
+ padding-top: 5px;
+ padding-bottom: 5px;
+ display: grid;
+ grid-template-columns: auto auto;
+
+ .presBox-viewPicker {
+ height: 25;
+ position: relative;
display: inline-block;
+ grid-column: 1;
+ border-radius: 5px;
+ min-width: 15px;
+ max-width: 100px;
+ left: 8px;
+ }
+
+ .presBox-presentPanel {
+ display: flex;
+ justify-self: end;
+ width: 100%;
+ max-width: 300px;
+ min-width: 150px;
+ }
+
+
+
+ select {
+ background: #323232;
+ color: white;
}
- .presBox-backward {
- left: 5;
+ .presBox-button {
+ margin-right: 2.5px;
+ margin-left: 2.5px;
+ height: 25px;
+ border-radius: 5px;
+ display: none;
+ justify-content: center;
+ align-content: center;
+ align-items: center;
+ text-align: center;
+ letter-spacing: normal;
+ width: inherit;
+ background: #323232;
+ color: white;
}
- .presBox-forward {
- right: 5;
+ .presBox-button.active {
+ display: flex;
+ }
+
+ .presBox-button.active:hover {
+ background-color: #233163;
+ }
+
+ .presBox-button.edit {
+ display: flex;
+ max-width: 25px;
+ }
+
+ .presBox-button.present {
+ display: flex;
+ min-width: 100px;
+ width: 100px;
+ position: absolute;
+ right: 8px;
+
+ .present-icon {
+ margin-right: 7px;
+ }
}
+
+
+
+ .collectionViewBaseChrome-viewPicker {
+ min-width: 50;
+ width: 5%;
+ height: 25;
+ position: relative;
+ display: inline-block;
+ left: 8px;
+ }
+}
+
+.presBox-backward,
+.presBox-forward {
+ width: 25px;
+ border-radius: 5px;
+ top: 50%;
+ position: absolute;
+ display: inline-block;
+}
+
+.presBox-backward {
+ left: 5;
+}
+
+.presBox-forward {
+ right: 5;
}
// CSS adjusted for mobile devices
diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx
index a304ced18..c04c6c409 100644
--- a/src/client/views/nodes/PresBox.tsx
+++ b/src/client/views/nodes/PresBox.tsx
@@ -2,24 +2,36 @@ import React = require("react");
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { action, computed, observable } from "mobx";
import { observer } from "mobx-react";
-import { Doc, DocListCast, DocCastAsync } from "../../../fields/Doc";
+import { Doc, DocListCast, DocCastAsync, WidthSym } from "../../../fields/Doc";
import { InkTool } from "../../../fields/InkField";
-import { BoolCast, Cast, NumCast, StrCast } from "../../../fields/Types";
-import { returnFalse, returnOne } from "../../../Utils";
+import { BoolCast, Cast, NumCast, StrCast, ScriptCast } from "../../../fields/Types";
+import { returnFalse, returnOne, numberRange, returnTrue } from "../../../Utils";
import { documentSchema } from "../../../fields/documentSchemas";
import { DocumentManager } from "../../util/DocumentManager";
import { undoBatch } from "../../util/UndoManager";
-import { CollectionDockingView } from "../collections/CollectionDockingView";
+import { CollectionDockingView, DockedFrameRenderer } from "../collections/CollectionDockingView";
import { CollectionView, CollectionViewType } from "../collections/CollectionView";
import { FieldView, FieldViewProps } from './FieldView';
+import { DocumentType } from "../../documents/DocumentTypes";
import "./PresBox.scss";
import { ViewBoxBaseComponent } from "../DocComponent";
-import { makeInterface } from "../../../fields/Schema";
-import { Docs } from "../../documents/Documents";
+import { makeInterface, listSpec } from "../../../fields/Schema";
+import { Docs, DocUtils } from "../../documents/Documents";
import { PrefetchProxy } from "../../../fields/Proxy";
import { ScriptField } from "../../../fields/ScriptField";
import { Scripting } from "../../util/Scripting";
import { InkingStroke } from "../InkingStroke";
+import { HighlightSpanKind } from "typescript";
+import { SearchUtil } from "../../util/SearchUtil";
+import { CollectionFreeFormDocumentView } from "./CollectionFreeFormDocumentView";
+import { child } from "serializr";
+import { List } from "../../../fields/List";
+import { Tooltip } from "@material-ui/core";
+import { CollectionFreeFormViewChrome } from "../collections/CollectionMenu";
+import { conformsTo } from "lodash";
+import { translate } from "googleapis/build/src/apis/translate";
+import { DragManager, dropActionType } from "../../util/DragManager";
+import { actionAsync } from "mobx-utils";
type PresBoxSchema = makeInterface<[typeof documentSchema]>;
const PresBoxDocument = makeInterface(documentSchema);
@@ -27,20 +39,23 @@ const PresBoxDocument = makeInterface(documentSchema);
@observer
export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>(PresBoxDocument) {
public static LayoutString(fieldKey: string) { return FieldView.LayoutString(PresBox, fieldKey); }
+ private treedropDisposer?: DragManager.DragDropDisposer;
+ static Instance: PresBox;
@observable _isChildActive = false;
@computed get childDocs() { return DocListCast(this.dataDoc[this.fieldKey]); }
@computed get itemIndex() { return NumCast(this.rootDoc._itemIndex); }
@computed get presElement() { return Cast(Doc.UserDoc().presElement, Doc, null); }
constructor(props: any) {
super(props);
+ PresBox.Instance = this;
if (!this.presElement) { // create exactly one presElmentBox template to use by any and all presentations.
Doc.UserDoc().presElement = new PrefetchProxy(Docs.Create.PresElementBoxDocument({
- title: "pres element template", backgroundColor: "transparent", _xMargin: 5, _height: 46, isTemplateDoc: true, isTemplateForField: "data"
+ title: "pres element template", backgroundColor: "transparent", _xMargin: 0, isTemplateDoc: true, isTemplateForField: "data"
}));
// this script will be called by each presElement to get rendering-specific info that the PresBox knows about but which isn't written to the PresElement
// this is a design choice -- we could write this data to the presElements which would require a reaction to keep it up to date, and it would prevent
// the preselement docs from being part of multiple presentations since they would all have the same field, or we'd have to keep per-presentation data
- // stored on each pres element.
+ // stored on each pres element.
(this.presElement as Doc).lookupField = ScriptField.MakeFunction("lookupPresBoxField(container, field, data)",
{ field: "string", data: Doc.name, container: Doc.name });
}
@@ -51,8 +66,26 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
this.rootDoc.presBox = this.rootDoc;
this.rootDoc._forceRenderEngine = "timeline";
this.rootDoc._replacedChrome = "replaced";
+ this.layoutDoc.presStatus = "edit";
+ this.layoutDoc._gridGap = 5;
+ // document.addEventListener("keydown", this.keyEvents, false);
+ }
+
+ componentWillUnmount() {
+ this.treedropDisposer?.();
+ }
+
+ onPointerOver = () => {
+ document.addEventListener("keydown", this.keyEvents, true);
+ }
+
+ onPointerLeave = () => {
+ document.removeEventListener("keydown", this.keyEvents, true);
+ }
+
+ updateCurrentPresentation = () => {
+ Doc.UserDoc().activePresentation = this.rootDoc;
}
- updateCurrentPresentation = () => Doc.UserDoc().activePresentation = this.rootDoc;
@undoBatch
@action
@@ -61,22 +94,18 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
const presTargetDoc = Cast(this.childDocs[this.itemIndex].presentationTargetDoc, Doc, null);
const lastFrame = Cast(presTargetDoc.lastFrame, "number", null);
const curFrame = NumCast(presTargetDoc.currentFrame);
- if (lastFrame !== undefined && curFrame < lastFrame) {
+ let internalFrames: boolean = false;
+ if (presTargetDoc.presProgressivize || presTargetDoc.zoomProgressivize || presTargetDoc.scrollProgressivize) internalFrames = true;
+ // Case 1: There are still other frames and should go through all frames before going to next slide
+ if (internalFrames && lastFrame !== undefined && curFrame < lastFrame) {
presTargetDoc._viewTransition = "all 1s";
setTimeout(() => presTargetDoc._viewTransition = undefined, 1010);
presTargetDoc.currentFrame = curFrame + 1;
- }
- else if (this.childDocs[this.itemIndex + 1] !== undefined) {
- let nextSelected = this.itemIndex + 1;
+ if (presTargetDoc.zoomProgressivize) this.zoomProgressivizeNext(presTargetDoc);
+ // Case 2: No more frames in current doc and next slide is defined, therefore move to next slide
+ } else if (this.childDocs[this.itemIndex + 1] !== undefined) {
+ const nextSelected = this.itemIndex + 1;
this.gotoDocument(nextSelected, this.itemIndex);
-
- for (nextSelected = nextSelected + 1; nextSelected < this.childDocs.length; nextSelected++) {
- if (!this.childDocs[nextSelected].groupButton) {
- break;
- } else {
- this.gotoDocument(nextSelected, this.itemIndex);
- }
- }
}
}
@@ -90,54 +119,132 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
//If so making sure to zoom out, which goes back to state before zooming action
let prevSelected = this.itemIndex;
let didZoom = docAtCurrent.zoomButton;
- for (; !didZoom && prevSelected > 0 && this.childDocs[prevSelected].groupButton; prevSelected--) {
- didZoom = this.childDocs[prevSelected].zoomButton;
- }
+ // for (; !didZoom && prevSelected > 0 && this.childDocs[prevSelected].groupButton; prevSelected--) {
+ // didZoom = this.childDocs[prevSelected].zoomButton;
+ // }
prevSelected = Math.max(0, prevSelected - 1);
this.gotoDocument(prevSelected, this.itemIndex);
}
}
+ zoomProgressivizeNext = (presTargetDoc: Doc) => {
+ const srcContext = Cast(presTargetDoc.context, Doc, null);
+ const docView = DocumentManager.Instance.getDocumentView(presTargetDoc);
+ const vfLeft: number = this.checkList(presTargetDoc, presTargetDoc["viewfinder-left-indexed"]);
+ const vfWidth: number = this.checkList(presTargetDoc, presTargetDoc["viewfinder-width-indexed"]);
+ const vfTop: number = this.checkList(presTargetDoc, presTargetDoc["viewfinder-top-indexed"]);
+ const vfHeight: number = this.checkList(presTargetDoc, presTargetDoc["viewfinder-height-indexed"]);
+ // Case 1: document that is not a Golden Layout tab
+ if (srcContext) {
+ console.log("CASE 1");
+ const srcDocView = DocumentManager.Instance.getDocumentView(srcContext);
+ if (srcDocView) {
+ const layoutdoc = Doc.Layout(presTargetDoc);
+ const panelWidth: number = srcDocView.props.PanelWidth();
+ const panelHeight: number = srcDocView.props.PanelHeight();
+ console.log("srcDocView: " + srcDocView.props.PanelWidth());
+ // console.log("layoutdoc._width: " + layoutdoc._width);
+ // console.log("srcContext._width: " + srcContext._width);
+ const newPanX = NumCast(presTargetDoc.x) + NumCast(layoutdoc._width) / 2;
+ const newPanY = NumCast(presTargetDoc.y) + NumCast(layoutdoc._height) / 2;
+ // const newPanX = NumCast(presTargetDoc.x) + panelWidth / 2;
+ // const newPanY = NumCast(presTargetDoc.y) + panelHeight / 2;
+ let newScale = 0.9 * Math.min(Number(panelWidth) / vfWidth, Number(panelHeight) / vfHeight);
+ // srcContext._panX = newPanX + (NumCast(presTargetDoc._viewScale) * this.checkList(presTargetDoc, presTargetDoc["viewfinder-left-indexed"]) + NumCast(presTargetDoc._panX) + (this.checkList(presTargetDoc, presTargetDoc["viewfinder-width-indexed"]) / 2));
+ // srcContext._panY = newPanY + (NumCast(presTargetDoc._viewScale) * this.checkList(presTargetDoc, presTargetDoc["viewfinder-top-indexed"]) + NumCast(presTargetDoc._panY) + (this.checkList(presTargetDoc, presTargetDoc["viewfinder-height-indexed"]) / 2));
+ srcContext._panX = newPanX + (vfLeft + (vfWidth / 2));
+ srcContext._panY = newPanY + (vfTop + (vfHeight / 2));
+ // srcContext._panX = newPanX
+ // srcContext._panY = newPanY
+ srcContext._viewScale = newScale;
+ console.log("X: " + srcContext._panX + ", Y: " + srcContext._panY + ", Scale: " + srcContext._viewScale);
+ }
+ }
+ // Case 2: document is the containing collection
+ if (docView && !srcContext) {
+ console.log("CASE 2");
+ const panelWidth: number = docView.props.PanelWidth();
+ const panelHeight: number = docView.props.PanelHeight();
+ let newScale = 0.9 * Math.min(Number(panelWidth) / vfWidth, Number(panelHeight) / vfHeight);
+ presTargetDoc._panX = vfLeft + (vfWidth / 2);
+ presTargetDoc._panY = vfTop + (vfWidth / 2);
+ presTargetDoc._viewScale = newScale;
+ }
+ const resize = document.getElementById('resizable');
+ if (resize) {
+ resize.style.width = vfWidth + 'px';
+ resize.style.height = vfHeight + 'px';
+ resize.style.top = vfTop + 'px';
+ resize.style.left = vfLeft + 'px';
+ }
+ }
+
+
+ @action
+ onHideDocumentUntilPressClick = () => {
+ this.childDocs.forEach((doc, index) => {
+ const curDoc = Cast(doc, Doc, null);
+ const tagDoc = Cast(curDoc.presentationTargetDoc, Doc, null);
+ if (tagDoc.presEffect === 'None' || !tagDoc.presEffect) {
+ tagDoc.opacity = 1;
+ } else {
+ if (index <= this.itemIndex) {
+ tagDoc.opacity = 1;
+ } else {
+ tagDoc.opacity = 0;
+ }
+ }
+ });
+ }
+
/**
* This is the method that checks for the actions that need to be performed
- * after the document has been presented, which involves 3 button options:
+ * before the document has been presented, which involves 3 button options:
* Hide Until Presented, Hide After Presented, Fade After Presented
*/
- showAfterPresented = (index: number) => {
+ @action
+ hideDocumentInPres = () => {
this.updateCurrentPresentation();
- this.childDocs.forEach((doc, ind) => {
- const presTargetDoc = doc.presentationTargetDoc as Doc;
- //the order of cases is aligned based on priority
- if (doc.presHideTillShownButton && ind <= index) {
- presTargetDoc.opacity = 1;
- }
- if (doc.presHideAfterButton && ind < index) {
- presTargetDoc.opacity = 0;
+ this.childDocs.forEach((doc, i) => {
+ const tagDoc = Cast(doc.presentationTargetDoc, Doc, null);
+ console.log("HB: " + doc.presHideTillShownButton);
+ console.log("HA: " + doc.presHideAfterButton);
+ if (doc.presHideTillShownButton) {
+ if (i < this.itemIndex) {
+ console.log(i + 1 + "hide before");
+ tagDoc.opacity = 0;
+ console.log(tagDoc.opacity);
+ } else {
+ tagDoc.opacity = 1;
+ }
}
- if (doc.presFadeButton && ind < index) {
- presTargetDoc.opacity = 0.5;
+ if (doc.presHideAfterButton) {
+ if (i > this.itemIndex) {
+ console.log(i + 1 + "hide after");
+ tagDoc.opacity = 0;
+ console.log(tagDoc.opacity);
+ } else {
+ tagDoc.opacity = 1;
+ }
}
});
}
/**
* This is the method that checks for the actions that need to be performed
- * before the document has been presented, which involves 3 button options:
+ * after the document has been presented, which involves 3 button options:
* Hide Until Presented, Hide After Presented, Fade After Presented
*/
- hideIfNotPresented = (index: number) => {
+ showAfterPresented = (index: number) => {
this.updateCurrentPresentation();
- this.childDocs.forEach((key, ind) => {
+ this.childDocs.forEach((doc, ind) => {
+ const presTargetDoc = doc.presentationTargetDoc as Doc;
//the order of cases is aligned based on priority
- const presTargetDoc = key.presentationTargetDoc as Doc;
- if (key.hideAfterButton && ind >= index) {
- presTargetDoc.opacity = 1;
- }
- if (key.fadeButton && ind >= index) {
+ if (doc.presHideTillShownButton && ind <= index) {
presTargetDoc.opacity = 1;
}
- if (key.hideTillShownButton && ind > index) {
+ if (doc.presHideAfterButton && ind < index) {
presTargetDoc.opacity = 0;
}
});
@@ -146,50 +253,50 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
/**
* This method makes sure that cursor navigates to the element that
* has the option open and last in the group. If not in the group, and it has
- * te option open, navigates to that element.
+ * the option open, navigates to that element.
*/
- navigateToElement = async (curDoc: Doc, fromDocIndex: number) => {
- this.updateCurrentPresentation();
- let docToJump = curDoc;
- let willZoom = false;
-
- const presDocs = DocListCast(this.dataDoc[this.props.fieldKey]);
- let nextSelected = presDocs.indexOf(curDoc);
- const currentDocGroups: Doc[] = [];
- for (; nextSelected < presDocs.length - 1; nextSelected++) {
- if (!presDocs[nextSelected + 1].groupButton) {
- break;
- }
- currentDocGroups.push(presDocs[nextSelected]);
+ navigateToElement = async (curDoc: Doc) => {
+ const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null);
+ const targetDoc = Cast(activeItem.presentationTargetDoc, Doc, null);
+ const srcContext = await DocCastAsync(targetDoc.context);
+ const presCollection = Cast(this.layoutDoc.presCollection, Doc, null);
+ const collectionDocView = presCollection ? DocumentManager.Instance.getDocumentView(presCollection) : undefined;
+ if (this.itemIndex >= 0) {
+ if (targetDoc) {
+ if (srcContext) this.layoutDoc.presCollection = srcContext;
+ } else if (targetDoc) this.layoutDoc.presCollection = targetDoc;
}
-
- currentDocGroups.forEach((doc: Doc, index: number) => {
- if (doc.presNavButton) {
- docToJump = doc;
- willZoom = false;
- }
- if (doc.presZoomButton) {
- docToJump = doc;
- willZoom = true;
+ if (srcContext) console.log("NC: " + srcContext.title);
+ if (presCollection) console.log("PC: " + presCollection.title);
+ if (collectionDocView) {
+ if (srcContext && srcContext !== presCollection) {
+ console.log("Case 1: new srcContext inside of current collection so add a new tab to the current pres collection");
+ console.log(collectionDocView);
+ collectionDocView.props.addDocTab(srcContext, "inPlace");
}
- });
+ } else if (srcContext) {
+ console.log("Case 2: srcContext - not open and collection containing this document exists, so open collection that contains it and then await zooming in on document");
+ this.props.addDocTab(srcContext, "onRight");
+ } else if (!srcContext) {
+ console.log("Case 3: !srcContext - no collection containing this document, therefore open document itself on right");
+ this.props.addDocTab(targetDoc, "onRight");
+ }
+ this.updateCurrentPresentation();
+ const docToJump = curDoc;
+ const willZoom = false;
//docToJump stayed same meaning, it was not in the group or was the last element in the group
- const aliasOf = await DocCastAsync(docToJump.aliasOf);
- const srcContext = aliasOf && await DocCastAsync(aliasOf.context);
if (docToJump === curDoc) {
//checking if curDoc has navigation open
- const target = (await DocCastAsync(curDoc.presentationTargetDoc)) || curDoc;
- if (curDoc.presNavButton && target) {
- DocumentManager.Instance.jumpToDocument(target, false, undefined, srcContext);
- } else if (curDoc.presZoomButton && target) {
+ if (curDoc.presNavButton && targetDoc) {
+ await DocumentManager.Instance.jumpToDocument(targetDoc, false, undefined, srcContext);
+ } else if (curDoc.presZoomButton && targetDoc) {
//awaiting jump so that new scale can be found, since jumping is async
- await DocumentManager.Instance.jumpToDocument(target, true, undefined, srcContext);
+ await DocumentManager.Instance.jumpToDocument(targetDoc, true, undefined, srcContext);
}
} else {
//awaiting jump so that new scale can be found, since jumping is async
- const presTargetDoc = await DocCastAsync(docToJump.presentationTargetDoc);
- presTargetDoc && await DocumentManager.Instance.jumpToDocument(presTargetDoc, willZoom, undefined, srcContext);
+ targetDoc && await DocumentManager.Instance.jumpToDocument(targetDoc, willZoom, undefined, srcContext);
}
}
@@ -201,30 +308,41 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
if (index >= 0 && index < this.childDocs.length) {
this.rootDoc._itemIndex = index;
const presTargetDoc = Cast(this.childDocs[this.itemIndex].presentationTargetDoc, Doc, null);
- if (presTargetDoc.lastFrame !== undefined) {
+ if (presTargetDoc?.lastFrame !== undefined) {
presTargetDoc.currentFrame = 0;
}
-
- if (!this.layoutDoc.presStatus) {
- this.layoutDoc.presStatus = true;
- this.startPresentation(index);
- }
-
- this.navigateToElement(this.childDocs[index], fromDoc);
- this.hideIfNotPresented(index);
- this.showAfterPresented(index);
+ this.navigateToElement(this.childDocs[index]);
+ this._selectedArray = [this.childDocs[index]];
+ // this.hideIfNotPresented(index);
+ // this.showAfterPresented(index);
+ // this.hideDocumentInPres();
+ this.onHideDocumentUntilPressClick();
}
});
+
+ @observable _presTimer!: NodeJS.Timeout;
+
//The function that starts or resets presentaton functionally, depending on status flag.
- startOrResetPres = () => {
+ @action
+ startOrResetPres = (startSlide: number) => {
this.updateCurrentPresentation();
- if (this.layoutDoc.presStatus) {
- this.resetPresentation();
+ const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null);
+ const targetDoc = Cast(activeItem.presentationTargetDoc, Doc, null);
+ if (this.layoutDoc.presStatus === "auto") {
+ if (this._presTimer) clearInterval(this._presTimer);
+ this.layoutDoc.presStatus = "manual";
} else {
- this.layoutDoc.presStatus = true;
- this.startPresentation(0);
- this.gotoDocument(0, this.itemIndex);
+ this.layoutDoc.presStatus = "auto";
+ this.startPresentation(startSlide);
+ this.gotoDocument(startSlide, this.itemIndex);
+ this._presTimer = setInterval(() => {
+ if (this.itemIndex + 1 < this.childDocs.length) this.next();
+ else {
+ clearInterval(this._presTimer);
+ this.layoutDoc.presStatus = "manual";
+ }
+ }, targetDoc.presDuration ? NumCast(targetDoc.presDuration) + NumCast(targetDoc.presTransition) : 2000);
}
}
@@ -234,7 +352,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
this.updateCurrentPresentation();
this.childDocs.forEach(doc => (doc.presentationTargetDoc as Doc).opacity = 1);
this.rootDoc._itemIndex = 0;
- this.layoutDoc.presStatus = false;
+ // this.layoutDoc.presStatus = false;
}
//The function that starts the presentation, also checking if actions should be applied
@@ -255,76 +373,1337 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
});
}
- updateMinimize = action((e: React.ChangeEvent, mode: CollectionViewType) => {
- if (BoolCast(this.layoutDoc.inOverlay) !== (mode === CollectionViewType.Invalid)) {
- if (this.layoutDoc.inOverlay) {
- Doc.RemoveDocFromList((Doc.UserDoc().myOverlayDocuments as Doc), undefined, this.rootDoc);
+ updateMinimize = () => {
+ const srcContext = Cast(this.rootDoc.presCollection, Doc, null);
+ if (srcContext) {
+ if (srcContext.miniPres) {
+ document.removeEventListener("keydown", this.keyEvents, false);
+ srcContext.miniPres = false;
+ // Doc.RemoveDocFromList((Doc.UserDoc().myOverlayDocuments as Doc), undefined, this.rootDoc);
CollectionDockingView.AddRightSplit(this.rootDoc);
- this.layoutDoc.inOverlay = false;
+ // this.layoutDoc.inOverlay = false;
} else {
- const pt = this.props.ScreenToLocalTransform().inverse().transformPoint(0, 0);
- this.rootDoc.x = pt[0];// 500;//e.clientX + 25;
- this.rootDoc.y = pt[1];////e.clientY - 25;
+ document.addEventListener("keydown", this.keyEvents, false);
+ srcContext.miniPres = true;
this.props.addDocTab?.(this.rootDoc, "close");
- Doc.AddDocToList((Doc.UserDoc().myOverlayDocuments as Doc), undefined, this.rootDoc);
+ // Doc.AddDocToList((Doc.UserDoc().myOverlayDocuments as Doc), undefined, this.rootDoc);
}
}
- });
+ // if (srcContext) {
+ // Doc.RemoveDocFromList((Doc.UserDoc().myOverlayDocuments as Doc), undefined, this.rootDoc);
+ // CollectionDockingView.AddRightSplit(this.rootDoc);
+ // this.layoutDoc.inOverlay = false;
+ // }
+ // else {
+ // const pt = this.props.ScreenToLocalTransform().inverse().transformPoint(0, 0);
+ // this.rootDoc.x = pt[0];// 500;//e.clientX + 25;
+ // this.rootDoc.y = pt[1];////e.clientY - 25;
+ // this.props.addDocTab?.(this.rootDoc, "close");
+ // Doc.AddDocToList((Doc.UserDoc().myOverlayDocuments as Doc), undefined, this.rootDoc);
+ // }
+ // }
+ }
@undoBatch
viewChanged = action((e: React.ChangeEvent) => {
//@ts-ignore
const viewType = e.target.selectedOptions[0].value as CollectionViewType;
viewType === CollectionViewType.Stacking && (this.rootDoc._pivotField = undefined); // pivot field may be set by the user in timeline view (or some other way) -- need to reset it here
- this.updateMinimize(e, this.rootDoc._viewType = viewType);
+ // this.updateMinimize(this.rootDoc._viewType = viewType);
+ if (viewType === CollectionViewType.Stacking) this.layoutDoc._gridGap = 5;
+ });
+
+ @undoBatch
+ movementChanged = action((movement: string) => {
+ const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null);
+ const targetDoc = Cast(activeItem.presentationTargetDoc, Doc, null);
+ if (movement === 'zoom') {
+ activeItem.presZoomButton = !activeItem.presZoomButton;
+ if (activeItem.presZoomButton) activeItem.presMovement = 'Zoom';
+ else activeItem.presMovement = 'None';
+ activeItem.presNavButton = false;
+ } else if (movement === 'nav') {
+ activeItem.presZoomButton = false;
+ activeItem.presNavButton = !activeItem.presNavButton;
+ if (activeItem.presNavButton) activeItem.presMovement = 'Pan';
+ else activeItem.presMovement = 'None';
+ } else if (movement === 'switch') {
+ targetDoc.presTransition = 0;
+ activeItem.presSwitchButton = !activeItem.presSwitchButton;
+ if (activeItem.presSwitchButton) activeItem.presMovement = 'Switch';
+ else activeItem.presMovement = 'None';
+ } else {
+ activeItem.presMovement = 'None';
+ activeItem.presZoomButton = false;
+ activeItem.presNavButton = false;
+ activeItem.presSwitchButton = false;
+ }
});
whenActiveChanged = action((isActive: boolean) => this.props.whenActiveChanged(this._isChildActive = isActive));
addDocumentFilter = (doc: Doc | Doc[]) => {
const docs = doc instanceof Doc ? [doc] : doc;
- docs.forEach(doc => {
- doc.aliasOf instanceof Doc && (doc.presentationTargetDoc = doc.aliasOf);
- !this.childDocs.includes(doc) && (doc.presZoomButton = true);
+ docs.forEach((doc, i) => {
+ if (this.childDocs.includes(doc)) {
+ console.log(docs.length);
+ console.log(i + 1);
+ if (docs.length === i + 1) return false;
+ } else {
+ doc.aliasOf instanceof Doc && (doc.presentationTargetDoc = doc.aliasOf);
+ !this.childDocs.includes(doc) && (doc.presZoomButton = true);
+ }
});
return true;
}
childLayoutTemplate = () => this.rootDoc._viewType !== CollectionViewType.Stacking ? undefined : this.presElement;
removeDocument = (doc: Doc) => Doc.RemoveDocFromList(this.dataDoc, this.fieldKey, doc);
- selectElement = (doc: Doc) => this.gotoDocument(this.childDocs.indexOf(doc), NumCast(this.itemIndex));
- getTransform = () => this.props.ScreenToLocalTransform().translate(-5, -65);// listBox padding-left and pres-box-cont minHeight
- panelHeight = () => this.props.PanelHeight() - 20;
+ getTransform = () => this.props.ScreenToLocalTransform();// listBox padding-left and pres-box-cont minHeight - .translate(-5, -65)
+ panelHeight = () => this.props.PanelHeight() - 40;
active = (outsideReaction?: boolean) => ((Doc.GetSelectedTool() === InkTool.None && !this.layoutDoc.isBackground) &&
(this.layoutDoc.forceActive || this.props.isSelected(outsideReaction) || this._isChildActive || this.props.renderDepth === 0) ? true : false)
- render() {
- // const presOrderedDocs = DocListCast(this.rootDoc.presOrderedDocs);
- // if (presOrderedDocs.length != this.childDocs.length || presOrderedDocs.some((pd, i) => pd !== this.childDocs[i])) {
- // this.rootDoc.presOrderedDocs = new List<Doc>(this.childDocs.slice());
+ // KEYS
+ @observable _selectedArray: Doc[] = [];
+ @observable _sortedSelectedArray: Doc[] = [];
+ @observable _eleArray: HTMLElement[] = [];
+ @observable _dragArray: HTMLElement[] = [];
+
+ //TODO: Update to radix / quick sort
+ @action
+ sortArray = (): Doc[] => {
+ const sort: Doc[] = this._selectedArray;
+ this.childDocs.forEach((doc, i) => {
+ if (this._selectedArray.includes(doc)) {
+ sort.push(doc);
+ }
+ });
+ return sort;
+ }
+
+ @computed get listOfSelected() {
+ const list = this._selectedArray.map((doc: Doc, index: any) => {
+ const activeItem = Cast(doc, Doc, null);
+ const targetDoc = Cast(activeItem.presentationTargetDoc, Doc, null);
+ return (
+ <div className="selectedList-items">{index + 1}. {targetDoc.title}</div>
+ );
+ });
+ return list;
+ }
+
+ //Regular click
+ @action
+ selectElement = (doc: Doc) => {
+ // this._selectedArray = [];
+ this.gotoDocument(this.childDocs.indexOf(doc), NumCast(this.itemIndex));
+ // this._selectedArray.push(this.childDocs[this.childDocs.indexOf(doc)]);
+ // console.log(this._selectedArray);
+ }
+
+ //Command click
+ @action
+ multiSelect = (doc: Doc, ref: HTMLElement) => {
+ this._selectedArray.push(this.childDocs[this.childDocs.indexOf(doc)]);
+ const ele = ref.getElementsByClassName("stacking");
+ this._eleArray.push(ref);
+ }
+
+ //Shift click
+ @action
+ shiftSelect = (doc: Doc, ref: HTMLElement) => {
+ this._selectedArray = [];
+ const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null);
+ if (activeItem) {
+ for (let i = Math.min(this.itemIndex, this.childDocs.indexOf(doc)); i <= Math.max(this.itemIndex, this.childDocs.indexOf(doc)); i++) {
+ this._selectedArray.push(this.childDocs[i]);
+ this._eleArray.push(ref);
+ }
+ }
+ }
+
+
+
+ //Esc click
+ @action
+ keyEvents = (e: KeyboardEvent) => {
+ e.stopPropagation();
+ e.preventDefault();
+ // switch(e.keyCode) {
+ // case 27: console.log("escape");
+ // case 65 && (e.metaKey || e.altKey):
+ // }
+ // Escape key
+ if (e.keyCode === 27) {
+ if (this.layoutDoc.presStatus === "edit") this._selectedArray = [];
+ else this.layoutDoc.presStatus = "edit";
+ // Ctrl-A to select all
+ } if ((e.metaKey || e.altKey) && e.keyCode === 65) {
+ if (this.layoutDoc.presStatus === "edit") this._selectedArray = this.childDocs;
+ // left(37) / a(65) / up(38) to go back
+ } if (e.keyCode === 37) {
+ if (this.layoutDoc.presStatus !== "edit") this.back();
+ // right (39) / d(68) / down(40) to go to next
+ } if (e.keyCode === 39) {
+ if (this.layoutDoc.presStatus !== "edit") this.next();
+ // spacebar to 'present' or go to next slide
+ } if (e.keyCode === 32) {
+ if (this.layoutDoc.presStatus !== "edit") this.next();
+ else this.layoutDoc.presStatus = "manual";
+ }
+ }
+
+ @observable private transitionTools: boolean = false;
+ @observable private newDocumentTools: boolean = false;
+ @observable private progressivizeTools: boolean = false;
+ @observable private moreInfoTools: boolean = false;
+ @observable private playTools: boolean = false;
+ @observable private presentTools: boolean = false;
+ @observable private pathBoolean: boolean = false;
+ @observable private expandBoolean: boolean = false;
+
+ // For toggling transition toolbar
+ @action toggleTransitionTools = () => {
+ this.transitionTools = !this.transitionTools;
+ this.newDocumentTools = false;
+ this.progressivizeTools = false;
+ this.moreInfoTools = false;
+ this.playTools = false;
+ }
+ // For toggling the add new document dropdown
+ @action toggleNewDocument = () => {
+ this.newDocumentTools = !this.newDocumentTools;
+ this.transitionTools = false;
+ this.progressivizeTools = false;
+ this.moreInfoTools = false;
+ this.playTools = false;
+ }
+ // For toggling the tools for progressivize
+ @action toggleProgressivize = () => {
+ this.progressivizeTools = !this.progressivizeTools;
+ const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null);
+ const targetDoc = Cast(activeItem.presentationTargetDoc, Doc, null);
+ targetDoc.editZoomProgressivize = false;
+ targetDoc.editProgressivize = false;
+ this.transitionTools = false;
+ this.newDocumentTools = false;
+ this.moreInfoTools = false;
+ this.playTools = false;
+ }
+ // For toggling the tools for more info
+ @action toggleMoreInfo = () => {
+ this.moreInfoTools = !this.moreInfoTools;
+ this.transitionTools = false;
+ this.newDocumentTools = false;
+ this.progressivizeTools = false;
+ this.playTools = false;
+ }
+ // For toggling the options when the user wants to select play
+ @action togglePlay = () => {
+ this.playTools = !this.playTools;
+ this.transitionTools = false;
+ this.newDocumentTools = false;
+ this.progressivizeTools = false;
+ this.moreInfoTools = false;
+ }
+
+ // For toggling the options when the user wants to select play
+ @action togglePresent = () => {
+ this.presentTools = !this.presentTools;
+ this.playTools = false;
+ this.transitionTools = false;
+ this.newDocumentTools = false;
+ this.progressivizeTools = false;
+ this.moreInfoTools = false;
+ }
+
+ @action toggleAllDropdowns() {
+ this.transitionTools = false;
+ this.newDocumentTools = false;
+ this.progressivizeTools = false;
+ this.moreInfoTools = false;
+ this.playTools = false;
+ }
+
+ @undoBatch
+ @action
+ viewPaths = async () => {
+ const srcContext = Cast(this.rootDoc.presCollection, Doc, null);
+ if (this.pathBoolean) {
+ console.log("true");
+ if (srcContext) {
+ this.togglePath();
+ srcContext._fitToBox = false;
+ srcContext._viewType = "freeform";
+ srcContext.presPathView = false;
+ }
+ } else {
+ console.log("false");
+ if (srcContext) {
+ this.togglePath();
+ srcContext._fitToBox = true;
+ srcContext._viewType = "freeform";
+ srcContext.presPathView = true;
+ }
+ }
+ console.log("view paths");
+ const viewType = srcContext?._viewType;
+ const fit = srcContext?._fitToBox;
+
+ // if (!DocumentManager.Instance.getDocumentView(curPres)) {
+ // CollectionDockingView.AddRightSplit(curPres);
// }
- this.childDocs.slice(); // needed to insure that the childDocs are loaded for looking up fields
+ }
+
+ @computed get order() {
+ const order: JSX.Element[] = [];
+ this.childDocs.forEach((doc, index) => {
+ const targetDoc = Cast(doc.presentationTargetDoc, Doc, null);
+ const srcContext = Cast(targetDoc.context, Doc, null);
+ if (this.rootDoc.presCollection === srcContext) {
+ order.push(
+ <div className="pathOrder" style={{ top: NumCast(targetDoc.y), left: NumCast(targetDoc.x) }}>
+ <div className="pathOrder-frame">{index + 1}</div>
+ </div>);
+ } else {
+ order.push(
+ <div className="pathOrder" style={{ top: 0, left: 0 }}>
+ <div className="pathOrder-frame">{index + 1}</div>
+ </div>);
+ }
+ });
+ return order;
+ }
+
+ @computed get paths() {
+ let pathPoints = "";
+ console.log(this.childDocs.length - 1);
+ this.childDocs.forEach((doc, index) => {
+ const targetDoc = Cast(doc.presentationTargetDoc, Doc, null);
+ const srcContext = Cast(targetDoc.context, Doc, null);
+ if (targetDoc && this.rootDoc.presCollection === srcContext) {
+ const n1x = NumCast(targetDoc.x) + (NumCast(targetDoc._width) / 2);
+ const n1y = NumCast(targetDoc.y) + (NumCast(targetDoc._height) / 2);
+ if (index = 0) pathPoints = n1x + "," + n1y;
+ else pathPoints = pathPoints + " " + n1x + "," + n1y;
+ } else {
+ if (index = 0) pathPoints = 0 + "," + 0;
+ else pathPoints = pathPoints + " " + 0 + "," + 0;
+ }
+ });
+ console.log(pathPoints);
+ return (<polyline
+ points={pathPoints}
+ style={{
+ opacity: 1,
+ stroke: "#69a6db",
+ strokeWidth: 5,
+ strokeDasharray: '10 5',
+ }}
+ fill="none"
+ markerStart="url(#markerSquare)"
+ markerMid="url(#markerSquare)"
+ markerEnd="url(#markerArrow)"
+ />);
+ }
+
+ @action togglePath = () => this.pathBoolean = !this.pathBoolean;
+ @action toggleExpand = () => this.expandBoolean = !this.expandBoolean;
+
+ /**
+ * The function that is called on click to turn fading document after presented option on/off.
+ * It also makes sure that the option swithches from hide-after to this one, since both
+ * can't coexist.
+ */
+ @action
+ onFadeDocumentAfterPresentedClick = (e: React.MouseEvent) => {
+ e.stopPropagation();
+ const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null);
+ const targetDoc = Cast(activeItem.presentationTargetDoc, Doc, null);
+ activeItem.presFadeButton = !activeItem.presFadeButton;
+ if (!activeItem.presFadeButton) {
+ if (targetDoc) {
+ targetDoc.opacity = 1;
+ }
+ } else {
+ activeItem.presHideAfterButton = false;
+ if (this.rootDoc.presStatus !== "edit" && targetDoc) {
+ targetDoc.opacity = 0.5;
+ }
+ }
+ }
+
+ @action
+ dropdownToggle = (menu: string) => {
+ console.log('presBox' + menu + 'Dropdown');
+ const dropMenu = document.getElementById('presBox' + menu + 'Dropdown');
+ console.log(dropMenu);
+ console.log(dropMenu?.style.display);
+ if (dropMenu) dropMenu.style.display === 'none' ? dropMenu.style.display = 'block' : dropMenu.style.display = 'none';
+ }
+
+ setTransitionTime = (number: String) => {
+ const timeInMS = Number(number) * 1000;
+ const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null);
+ const targetDoc = Cast(activeItem.presentationTargetDoc, Doc, null);
+ if (targetDoc) targetDoc.presTransition = timeInMS;
+ }
+
+ setDurationTime = (number: String) => {
+ const timeInMS = Number(number) * 1000;
+ const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null);
+ const targetDoc = Cast(activeItem.presentationTargetDoc, Doc, null);
+ if (targetDoc) targetDoc.presDuration = timeInMS;
+ }
+
+ @computed get transitionDropdown() {
+ const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null);
+ const targetDoc = Cast(activeItem?.presentationTargetDoc, Doc, null);
+ if (activeItem && targetDoc) {
+ const transitionSpeed = targetDoc.presTransition ? String(Number(targetDoc.presTransition) / 1000) : 0.5;
+ const duration = targetDoc.presDuration ? String(Number(targetDoc.presDuration) / 1000) : 2;
+ const transitionThumbLocation = String(-9.48 * Number(transitionSpeed) + 93);
+ const durationThumbLocation = String(9.48 * Number(duration));
+ const effect = targetDoc.presEffect ? targetDoc.presEffect : 'None';
+ activeItem.presMovement = activeItem.presMovement ? activeItem.presMovement : 'Zoom';
+ return (
+ <div className={`presBox-ribbon ${this.transitionTools && this.layoutDoc.presStatus === "edit" ? "active" : ""}`} onClick={e => e.stopPropagation()} onPointerUp={e => e.stopPropagation()} onPointerDown={e => e.stopPropagation()}>
+ <div className="ribbon-box">
+ Movement
+ <div className="presBox-dropdown"
+ onPointerDown={e => e.stopPropagation()}
+ // onClick={() => this.dropdownToggle('Movement')}
+ >
+ {activeItem.presMovement}
+ <FontAwesomeIcon className='presBox-dropdownIcon' style={{ gridColumn: 2 }} icon={"angle-down"} />
+ <div className={'presBox-dropdownOptions'} id={'presBoxMovementDropdown'} onClick={e => e.stopPropagation()}>
+ <div className={`presBox-dropdownOption ${activeItem.presMovement === 'None' ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.movementChanged('none')}>None</div>
+ <div className={`presBox-dropdownOption ${activeItem.presMovement === 'Zoom' ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.movementChanged('zoom')}>Pan and Zoom</div>
+ <div className={`presBox-dropdownOption ${activeItem.presMovement === 'Pan' ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.movementChanged('nav')}>Pan</div>
+ <div className={`presBox-dropdownOption ${activeItem.presMovement === 'Switch' ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.movementChanged('switch')}>Switch</div>
+ </div>
+ </div>
+ <input type="range" step="0.1" min="0.1" max="10" value={transitionSpeed} className={`toolbar-slider ${activeItem.presMovement === 'Pan' || activeItem.presMovement === 'Zoom' ? "" : "none"}`} id="toolbar-slider" onChange={(e: React.ChangeEvent<HTMLInputElement>) => { e.stopPropagation(); this.setTransitionTime(e.target.value); }} />
+ <div className={`slider-headers ${activeItem.presMovement === 'Pan' || activeItem.presMovement === 'Zoom' ? "" : "none"}`}>
+ <div className={`slider-value ${activeItem.presZoomButton || activeItem.presNavButton ? "" : "none"}`} style={{ left: transitionThumbLocation + '%' }}>{transitionSpeed}s</div>
+ <div className="slider-text">Slow</div>
+ <div className="slider-text"></div>
+ <div className="slider-text">Fast</div>
+ </div>
+ </div>
+ <div className="ribbon-box">
+ Visibility
+ <div className="ribbon-doubleButton">
+ <Tooltip title={<><div className="dash-tooltip">{"Hide before presented"}</div></>}><div className={`ribbon-button ${activeItem.presHideTillShownButton ? "active" : ""}`} onClick={() => activeItem.presHideTillShownButton = !activeItem.presHideTillShownButton}>HB</div></Tooltip>
+ <Tooltip title={<><div className="dash-tooltip">{"Hide after presented"}</div></>}><div className={`ribbon-button ${activeItem.presHideAfterButton ? "active" : ""}`} onClick={() => activeItem.presHideAfterButton = !activeItem.presHideAfterButton}>HA</div></Tooltip>
+ </div>
+ <input type="range" step="0.1" min="0.1" max="10" value={duration} style={{ transform: 'rotate(0deg)' }} className={"toolbar-slider"} id="duration-slider" onChange={(e: React.ChangeEvent<HTMLInputElement>) => { e.stopPropagation(); this.setDurationTime(e.target.value); }} />
+ <div className={"slider-headers"}>
+ <div className={"slider-value"} style={{ left: durationThumbLocation + '%' }}>{duration}s</div>
+ <div className="slider-text">Short</div>
+ <div className="slider-text"></div>
+ <div className="slider-text">Long</div>
+ </div>
+ </div>
+ <div className="ribbon-box">
+ Effects
+ <div className="presBox-dropdown"
+ onPointerDown={e => e.stopPropagation()}
+ >
+ {effect}
+ <FontAwesomeIcon className='presBox-dropdownIcon' style={{ gridColumn: 2 }} icon={"angle-down"} />
+ <div className={'presBox-dropdownOptions'} id={'presBoxMovementDropdown'} onClick={e => e.stopPropagation()}>
+ <div className={'presBox-dropdownOption'} onPointerDown={e => e.stopPropagation()} onClick={() => targetDoc.presEffect = 'None'}>None</div>
+ <div className={'presBox-dropdownOption'} onPointerDown={e => e.stopPropagation()} onClick={() => targetDoc.presEffect = 'Fade'}>Fade In</div>
+ <div className={'presBox-dropdownOption'} onPointerDown={e => e.stopPropagation()} onClick={() => targetDoc.presEffect = 'Flip'}>Flip</div>
+ <div className={'presBox-dropdownOption'} onPointerDown={e => e.stopPropagation()} onClick={() => targetDoc.presEffect = 'Rotate'}>Rotate</div>
+ <div className={'presBox-dropdownOption'} onPointerDown={e => e.stopPropagation()} onClick={() => targetDoc.presEffect = 'Bounce'}>Bounce</div>
+ <div className={'presBox-dropdownOption'} onPointerDown={e => e.stopPropagation()} onClick={() => targetDoc.presEffect = 'Roll'}>Roll</div>
+ </div>
+ </div>
+ <div className="effectDirection" style={{ display: effect === 'None' ? "none" : "grid" }}>
+ <Tooltip title={<><div className="dash-tooltip">{"Enter from left"}</div></>}><div style={{ gridColumn: 1, gridRow: 2, justifySelf: 'center', color: targetDoc.presEffectDirection === "left" ? "#5a9edd" : "black" }} onClick={() => targetDoc.presEffectDirection = 'left'}><FontAwesomeIcon icon={"angle-right"} /></div></Tooltip>
+ <Tooltip title={<><div className="dash-tooltip">{"Enter from right"}</div></>}><div style={{ gridColumn: 3, gridRow: 2, justifySelf: 'center', color: targetDoc.presEffectDirection === "right" ? "#5a9edd" : "black" }} onClick={() => targetDoc.presEffectDirection = 'right'}><FontAwesomeIcon icon={"angle-left"} /></div></Tooltip>
+ <Tooltip title={<><div className="dash-tooltip">{"Enter from top"}</div></>}><div style={{ gridColumn: 2, gridRow: 1, justifySelf: 'center', color: targetDoc.presEffectDirection === "top" ? "#5a9edd" : "black" }} onClick={() => targetDoc.presEffectDirection = 'top'}><FontAwesomeIcon icon={"angle-down"} /></div></Tooltip>
+ <Tooltip title={<><div className="dash-tooltip">{"Enter from bottom"}</div></>}><div style={{ gridColumn: 2, gridRow: 3, justifySelf: 'center', color: targetDoc.presEffectDirection === "bottom" ? "#5a9edd" : "black" }} onClick={() => targetDoc.presEffectDirection = 'bottom'}><FontAwesomeIcon icon={"angle-up"} /></div></Tooltip>
+ <Tooltip title={<><div className="dash-tooltip">{"Enter from center"}</div></>}><div style={{ gridColumn: 2, gridRow: 2, width: 10, height: 10, alignSelf: 'center', justifySelf: 'center', border: targetDoc.presEffectDirection ? "solid 2px black" : "solid 2px #5a9edd", borderRadius: "100%" }} onClick={() => targetDoc.presEffectDirection = false}></div></Tooltip>
+ </div>
+ </div>
+ <div className="ribbon-final-box">
+ {this._selectedArray.length} selected
+ <div className="selectedList">
+ {this.listOfSelected}
+ </div>
+ </div>
+ <div className="ribbon-final-box">
+ <div className={this._selectedArray.length === 0 ? "ribbon-final-button" : "ribbon-final-button-hidden"} onClick={() => this.applyTo(this._selectedArray)}>
+ Apply to selected
+ </div>
+ <div className="ribbon-final-button-hidden" onClick={() => this.applyTo(this.childDocs)}>
+ Apply to all
+ </div>
+ </div>
+ </div>
+ );
+ }
+ }
+
+ applyTo = (array: Doc[]) => {
+ const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null);
+ const targetDoc = Cast(activeItem?.presentationTargetDoc, Doc, null);
+ array.forEach((doc, index) => {
+ const curDoc = Cast(doc, Doc, null);
+ const tagDoc = Cast(curDoc.presentationTargetDoc, Doc, null);
+ if (tagDoc && targetDoc) {
+ tagDoc.presTransition = targetDoc.presTransition;
+ tagDoc.presDuration = targetDoc.presDuration;
+ tagDoc.presEffect = targetDoc.presEffect;
+ }
+ });
+ }
+
+ public inputRef = React.createRef<HTMLInputElement>();
+
+
+ createNewSlide = (title: string, type: string) => {
+ let doc = null;
+ if (type === "text") {
+ doc = Docs.Create.TextDocument("", { _nativeWidth: 400, _width: 400, title: title });
+ const data = Cast(this.rootDoc.data, listSpec(Doc));
+ if (data) data.push(doc);
+ } else {
+ doc = Docs.Create.FreeformDocument([], { _nativeWidth: 400, _width: 400, title: title });
+ const data = Cast(this.rootDoc.data, listSpec(Doc));
+ if (data) data.push(doc);
+ }
+ }
+
+ @computed get newDocumentDropdown() {
+ let type = "";
+ let title = "";
+ return (
+ <div>
+ <div className={`presBox-ribbon ${this.newDocumentTools && this.layoutDoc.presStatus === "edit" ? "active" : ""}`} onClick={e => e.stopPropagation()} onPointerUp={e => e.stopPropagation()} onPointerDown={e => e.stopPropagation()}>
+ <div className="ribbon-box">
+ Slide Title: <br></br>
+ {/* <div className="dropdown-textInput"> */}
+ <input className="ribbon-textInput" placeholder="..." type="text" name="fname" ref={this.inputRef} onChange={(e) => {
+ e.stopPropagation();
+ title = e.target.value;
+ }}></input>
+ {/* </div> */}
+ </div>
+ <div className="ribbon-box">
+ Choose type:
+ <div style={{ display: 'block', alignSelf: 'center' }}>
+ <div title="Text" className={'ribbon-button'} style={{ background: type === 'text' ? "#000000" : "#f6f6f6" }} onClick={action(() => { type = "text"; })}>Text</div>
+ <div title="Freeform" className={'ribbon-button'} style={{ background: type === 'freeform' ? "#000000" : "#f6f6f6" }} onClick={action(() => { type = "freeform"; })}>Freeform</div>
+ </div>
+ </div>
+ <div className="ribbon-box">
+ Preset layouts:
+ <div className="layout-container">
+ <div className="layout">
+ <div className="header">HEADER</div>
+ <div className="subheader">Content goes here</div>
+ </div>
+ <div className="layout">
+ <div className="header" style={{ gridColumn: 1 / 2, gridRow: 1 }}>HEADER</div>
+ <div className="subheader" style={{ gridColumn: 1, gridRow: 2 }}>Some content</div>
+ <div className="subheader" style={{ gridColumn: 2, gridRow: 2 }}>Some more content</div>
+ </div>
+ <div className="layout">
+ <div className="header">HEADER</div>
+ <div className="subheader">Content goes here</div>
+ </div>
+ </div>
+ </div>
+ <div className="ribbon-final-box">
+ <div className="ribbon-final-button" onClick={() => this.createNewSlide(title, type)}>
+ Create New Slide
+ </div>
+ </div>
+ </div>
+ </div >
+ );
+ }
+
+ @computed get playDropdown() {
+ return (
+ <div className={`dropdown-play ${this.playTools ? "active" : ""}`} onClick={e => e.stopPropagation()} onPointerUp={e => e.stopPropagation()} onPointerDown={e => e.stopPropagation()}>
+ <div className="dropdown-play-button" onClick={() => this.startOrResetPres(this.itemIndex)}>
+ Present from current slide
+ </div>
+ <div className="dropdown-play-button" onClick={() => this.startOrResetPres(0)}>
+ Present from first slide
+ </div>
+ </div>
+ );
+ }
+
+ @computed get presentDropdown() {
+ return (
+ <div className={`dropdown-play ${this.presentTools ? "active" : ""}`} onClick={e => e.stopPropagation()} onPointerUp={e => e.stopPropagation()} onPointerDown={e => e.stopPropagation()}>
+ <div className="dropdown-play-button" onClick={this.updateMinimize}>
+ Minimize
+ </div>
+ <div className="dropdown-play-button" onClick={() => this.startOrResetPres(0)}>
+ Sidebar view
+ </div>
+ </div>
+ );
+ }
+
+ // progressivizeOptions = (viewType: string) => {
+ // const buttons = [];
+ // buttons.push(<div className="ribbon-button" onClick={this.progressivize}>Child documents</div>);
+ // buttons.push(<div className="ribbon-button" onClick={() => console.log("hide after")}>Internal zoom</div>);
+ // buttons.push(<div className="ribbon-button" onClick={() => console.log("hide after")}>Bullet points</div>);
+ // if (viewType === "rtf") {
+ // buttons.push(<div className="ribbon-button" title="Progressivize bullet points" onClick={() => console.log("hide after")}>Bullet points</div>);
+ // }
+ // return buttons;
+ // }
+
+ @undoBatch
+ @action
+ nextKeyframe = (tagDoc: Doc): void => {
+ const childDocs = DocListCast(tagDoc[Doc.LayoutFieldKey(tagDoc)]);
+ const currentFrame = Cast(tagDoc.currentFrame, "number", null);
+ if (currentFrame === undefined) {
+ tagDoc.currentFrame = 0;
+ CollectionFreeFormDocumentView.setupScroll(tagDoc, 0);
+ CollectionFreeFormDocumentView.setupKeyframes(childDocs, 0);
+ }
+ let lastFrame: number = 0;
+ childDocs.forEach((doc) => {
+ if (NumCast(doc.appearFrame) > lastFrame) lastFrame = NumCast(doc.appearFrame);
+ });
+ CollectionFreeFormDocumentView.updateScrollframe(tagDoc, currentFrame);
+ CollectionFreeFormDocumentView.updateKeyframe(childDocs, currentFrame || 0);
+ tagDoc.currentFrame = Math.max(0, (currentFrame || 0) + 1);
+ tagDoc.lastFrame = Math.max(NumCast(tagDoc.currentFrame), lastFrame);
+ if (tagDoc.zoomProgressivize) {
+ const resize = document.getElementById('resizable');
+ if (resize) {
+ resize.style.width = this.checkList(tagDoc, tagDoc["viewfinder-width-indexed"]) + 'px';
+ resize.style.height = this.checkList(tagDoc, tagDoc["viewfinder-height-indexed"]) + 'px';
+ resize.style.top = this.checkList(tagDoc, tagDoc["viewfinder-top-indexed"]) + 'px';
+ resize.style.left = this.checkList(tagDoc, tagDoc["viewfinder-left-indexed"]) + 'px';
+ }
+ }
+ }
+
+ @undoBatch
+ @action
+ prevKeyframe = (tagDoc: Doc): void => {
+ const childDocs = DocListCast(tagDoc[Doc.LayoutFieldKey(tagDoc)]);
+ const currentFrame = Cast(tagDoc.currentFrame, "number", null);
+ if (currentFrame === undefined) {
+ tagDoc.currentFrame = 0;
+ CollectionFreeFormDocumentView.setupKeyframes(childDocs, 0);
+ }
+ CollectionFreeFormDocumentView.gotoKeyframe(childDocs.slice());
+ tagDoc.currentFrame = Math.max(0, (currentFrame || 0) - 1);
+ if (tagDoc.zoomProgressivize) {
+ const resize = document.getElementById('resizable');
+ if (resize) {
+ resize.style.width = this.checkList(tagDoc, tagDoc["viewfinder-width-indexed"]) + 'px';
+ resize.style.height = this.checkList(tagDoc, tagDoc["viewfinder-height-indexed"]) + 'px';
+ resize.style.top = this.checkList(tagDoc, tagDoc["viewfinder-top-indexed"]) + 'px';
+ resize.style.left = this.checkList(tagDoc, tagDoc["viewfinder-left-indexed"]) + 'px';
+ }
+ }
+ }
+
+ @computed get progressivizeDropdown() {
+ const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null);
+ const targetDoc = Cast(activeItem?.presentationTargetDoc, Doc, null);
+
+ if (activeItem && targetDoc) {
+ return (
+ <div>
+ <div className={`presBox-ribbon ${this.progressivizeTools && this.layoutDoc.presStatus === "edit" ? "active" : ""}`} onClick={e => e.stopPropagation()} onPointerUp={e => e.stopPropagation()} onPointerDown={e => e.stopPropagation()}>
+ <div className="ribbon-box">
+ {targetDoc.type} selected
+ <div className="selectedList" style={{ height: 'max-content' }}>
+ <div className="selectedList-items">{targetDoc.title}</div>
+ </div>
+ <div className="ribbon-doubleButton">
+ <div className="ribbon-frameSelector">
+ <div key="back" title="back frame" className="backKeyframe" onClick={e => { e.stopPropagation(); this.prevKeyframe(targetDoc); }}>
+ <FontAwesomeIcon icon={"caret-left"} size={"lg"} />
+ </div>
+ <div key="num" title="toggle view all" className="numKeyframe" style={{ backgroundColor: targetDoc.editing ? "#5a9edd" : "#5a9edd" }}
+ onClick={action(() => targetDoc.editing = !targetDoc.editing)} >
+ {NumCast(targetDoc.currentFrame)}
+ </div>
+ <div key="fwd" title="forward frame" className="fwdKeyframe" onClick={e => { e.stopPropagation(); this.nextKeyframe(targetDoc); }}>
+ <FontAwesomeIcon icon={"caret-right"} size={"lg"} />
+ </div>
+ </div>
+ <Tooltip title={<><div className="dash-tooltip">{"Last frame"}</div></>}><div style={{ fontWeight: 600, marginTop: 0, marginLeft: 3 }} className="ribbon-button">{NumCast(targetDoc.lastFrame)}</div></Tooltip>
+ </div>
+ </div>
+ <div className="ribbon-final-box">
+ <div className="ribbon-doubleButton" style={{ display: targetDoc.type === DocumentType.COL ? "inline-flex" : "none" }}>
+ <div className="ribbon-button" style={{ backgroundColor: activeItem.presProgressivize ? "#aedef8" : "" }} onClick={this.progressivizeChild}>Child documents</div>
+ <div className="ribbon-button" style={{ display: activeItem.presProgressivize ? "flex" : "none", backgroundColor: targetDoc.editProgressivize ? "#aedef8" : "" }} onClick={this.editProgressivize}>Edit</div>
+ </div>
+ <div className="ribbon-doubleButton" style={{ display: targetDoc.type === DocumentType.COL || targetDoc.type === "image" ? "inline-flex" : "none" }}>
+ <div className="ribbon-button" style={{ backgroundColor: activeItem.zoomProgressivize ? "#aedef8" : "" }} onClick={this.progressivizeZoom}>Internal zoom</div>
+ <div className="ribbon-button" style={{ display: activeItem.zoomProgressivize ? "flex" : "none", backgroundColor: targetDoc.editZoomProgressivize ? "#aedef8" : "" }} onClick={this.editZoomProgressivize}>Viewfinder</div>
+ <div className="ribbon-button" style={{ display: activeItem.zoomProgressivize ? "flex" : "none", backgroundColor: targetDoc.editSnapZoomProgressivize ? "#aedef8" : "" }} onClick={this.editSnapZoomProgressivize}>Snapshot</div>
+ </div>
+ <div className="ribbon-doubleButton" style={{ display: targetDoc.type === DocumentType.RTF ? "inline-flex" : "none" }}>
+ <div className="ribbon-button" onClick={this.progressivizeText}>Text progressivize</div>
+ <div className="ribbon-button" style={{ display: activeItem.textProgressivize ? "flex" : "none", backgroundColor: targetDoc.editTextProgressivize ? "#aedef8" : "" }} onClick={this.editTextProgressivize}>Edit</div>
+ </div>
+ <div className="ribbon-doubleButton" style={{ display: targetDoc.type === "pdf" ? "inline-flex" : "none" }}>
+ <div className="ribbon-button" style={{ backgroundColor: activeItem.scrollProgressivize ? "#aedef8" : "" }} onClick={this.progressivizeScroll}>Scroll progressivize</div>
+ <div className="ribbon-button" style={{ display: activeItem.scrollProgressivize ? "flex" : "none", backgroundColor: targetDoc.editScrollProgressivize ? "#aedef8" : "" }} onClick={this.editScrollProgressivize}>Edit</div>
+ </div>
+ </div>
+ </div>
+ </div>
+ );
+ }
+ }
+
+ //Toggle whether the user edits or not
+ @action
+ editSnapZoomProgressivize = (e: React.MouseEvent) => {
+ const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null);
+ const targetDoc = Cast(activeItem.presentationTargetDoc, Doc, null);
+ if (!targetDoc.editSnapZoomProgressivize) {
+ targetDoc.editSnapZoomProgressivize = true;
+ } else {
+ targetDoc.editSnapZoomProgressivize = false;
+ }
+
+ }
+
+ //Toggle whether the user edits or not
+ @action
+ editZoomProgressivize = (e: React.MouseEvent) => {
+ const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null);
+ const targetDoc = Cast(activeItem.presentationTargetDoc, Doc, null);
+ if (!targetDoc.editZoomProgressivize) {
+ targetDoc.editZoomProgressivize = true;
+ } else {
+ targetDoc.editZoomProgressivize = false;
+ }
+ }
+
+ //Toggle whether the user edits or not
+ @action
+ editScrollProgressivize = (e: React.MouseEvent) => {
+ const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null);
+ const targetDoc = Cast(activeItem.presentationTargetDoc, Doc, null);
+ if (!targetDoc.editScrollProgressivize) {
+ targetDoc.editScrollProgressivize = true;
+ } else {
+ targetDoc.editScrollProgressivize = false;
+ }
+ }
+
+ //Progressivize Zoom
+ @action
+ progressivizeScroll = (e: React.MouseEvent) => {
+ e.stopPropagation();
+ const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null);
+ activeItem.scrollProgressivize = !activeItem.scrollProgressivize;
+ const targetDoc = Cast(activeItem.presentationTargetDoc, Doc, null);
+ targetDoc.scrollProgressivize = !targetDoc.zoomProgressivize;
+ CollectionFreeFormDocumentView.setupScroll(targetDoc, NumCast(targetDoc.currentFrame), true);
+ if (targetDoc.editScrollProgressivize) {
+ targetDoc.editScrollProgressivize = false;
+ targetDoc.currentFrame = 0;
+ targetDoc.lastFrame = 0;
+ }
+ }
+
+ //Progressivize Zoom
+ @action
+ progressivizeZoom = (e: React.MouseEvent) => {
+ e.stopPropagation();
+ const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null);
+ activeItem.zoomProgressivize = !activeItem.zoomProgressivize;
+ const targetDoc = Cast(activeItem.presentationTargetDoc, Doc, null);
+ targetDoc.zoomProgressivize = !targetDoc.zoomProgressivize;
+ CollectionFreeFormDocumentView.setupZoom(targetDoc, true);
+ if (targetDoc.editZoomProgressivize) {
+ targetDoc.editZoomProgressivize = false;
+ targetDoc.currentFrame = 0;
+ targetDoc.lastFrame = 0;
+ }
+ }
+
+ //Progressivize Text nodes
+ @action
+ editTextProgressivize = (e: React.MouseEvent) => {
+ const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null);
+ const targetDoc = Cast(activeItem.presentationTargetDoc, Doc, null);
+ targetDoc.currentFrame = targetDoc.lastFrame;
+ if (targetDoc?.editTextProgressivize) {
+ targetDoc.editTextProgressivize = false;
+ } else {
+ targetDoc.editTextProgressivize = true;
+ }
+ }
+
+ @action
+ progressivizeText = (e: React.MouseEvent) => {
+ e.stopPropagation();
+ const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null);
+ activeItem.presProgressivize = !activeItem.presProgressivize;
+ const targetDoc = Cast(activeItem.presentationTargetDoc, Doc, null);
+ const docs = DocListCast(targetDoc[Doc.LayoutFieldKey(targetDoc)]);
+ targetDoc.presProgressivize = !targetDoc.presProgressivize;
+ console.log(targetDoc.presProgressivize);
+ if (activeItem.presProgressivize) {
+ console.log("progressivize");
+ targetDoc.currentFrame = 0;
+ CollectionFreeFormDocumentView.setupKeyframes(docs, docs.length, true);
+ targetDoc.lastFrame = docs.length - 1;
+ }
+ }
+
+ //Progressivize Child Docs
+ @action
+ editProgressivize = (e: React.MouseEvent) => {
+ const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null);
+ const targetDoc = Cast(activeItem.presentationTargetDoc, Doc, null);
+ targetDoc.currentFrame = targetDoc.lastFrame;
+ if (targetDoc?.editProgressivize) {
+ targetDoc.editProgressivize = false;
+ } else {
+ targetDoc.editProgressivize = true;
+ }
+ }
+
+ @action
+ progressivizeChild = (e: React.MouseEvent) => {
+ e.stopPropagation();
+ const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null);
+ const targetDoc = Cast(activeItem.presentationTargetDoc, Doc, null);
+ const docs = DocListCast(targetDoc[Doc.LayoutFieldKey(targetDoc)]);
+ if (!activeItem.presProgressivize) {
+ activeItem.presProgressivize = true;
+ targetDoc.presProgressivize = true;
+ targetDoc.currentFrame = 0;
+ CollectionFreeFormDocumentView.setupKeyframes(docs, docs.length, true);
+ targetDoc.lastFrame = docs.length - 1;
+ } else {
+ targetDoc.editProgressivize = false;
+ activeItem.presProgressivize = false;
+ targetDoc.presProgressivize = false;
+ // docs.forEach((doc, index) => {
+ // doc.appearFrame = 0;
+ // });
+ targetDoc.currentFrame = 0;
+ targetDoc.lastFrame = 0;
+ }
+ }
+
+ @action
+ checkMovementLists = (doc: Doc, xlist: any, ylist: any) => {
+ const x: List<number> = xlist;
+ const y: List<number> = ylist;
+ const tags: JSX.Element[] = [];
+ let pathPoints = ""; //List of all of the pathpoints that need to be added
+ // console.log(x);
+ // console.log(x.length);
+ // console.log(x[0]);
+ for (let i = 0; i < x.length - 1; i++) {
+ if (y[i] || x[i]) {
+ if (i === 0) pathPoints = (x[i] - 11) + "," + (y[i] + 33);
+ else pathPoints = pathPoints + " " + (x[i] - 11) + "," + (y[i] + 33);
+ tags.push(<div className="progressivizeMove-frame" style={{ position: 'absolute', top: y[i], left: x[i] }}>{i}</div>);
+ }
+ }
+ tags.push(<svg style={{ overflow: 'visible', position: 'absolute' }}><polyline
+ points={pathPoints}
+ style={{
+ position: 'absolute',
+ opacity: 1,
+ stroke: "#000000",
+ strokeWidth: 2,
+ strokeDasharray: '10 5',
+ }}
+ fill="none"
+ /></svg>);
+ return tags;
+ }
+
+ @observable
+ toggleDisplayMovement = (doc: Doc) => {
+ if (doc.displayMovement) doc.displayMovement = false;
+ else doc.displayMovement = true;
+ }
+
+ private _isDraggingTL = false;
+ private _isDraggingTR = false;
+ private _isDraggingBR = false;
+ private _isDraggingBL = false;
+ private _isDragging = false;
+ // private _drag = "";
+
+ // onPointerDown = (e: React.PointerEvent): void => {
+ // e.stopPropagation();
+ // e.preventDefault();
+ // if (e.button === 0) {
+ // this._drag = e.currentTarget.id;
+ // console.log(this._drag);
+ // }
+ // document.removeEventListener("pointermove", this.onPointerMove);
+ // document.addEventListener("pointermove", this.onPointerMove);
+ // document.removeEventListener("pointerup", this.onPointerUp);
+ // document.addEventListener("pointerup", this.onPointerUp);
+ // }
+
+
+ //Adds event listener so knows pointer is down and moving
+ onPointerMid = (e: React.PointerEvent): void => {
+ e.stopPropagation();
+ e.preventDefault();
+ this._isDragging = true;
+ document.removeEventListener("pointermove", this.onPointerMove);
+ document.addEventListener("pointermove", this.onPointerMove);
+ document.removeEventListener("pointerup", this.onPointerUp);
+ document.addEventListener("pointerup", this.onPointerUp);
+ }
+
+ //Adds event listener so knows pointer is down and moving
+ onPointerBR = (e: React.PointerEvent): void => {
+ e.stopPropagation();
+ e.preventDefault();
+ this._isDraggingBR = true;
+ document.removeEventListener("pointermove", this.onPointerMove);
+ document.addEventListener("pointermove", this.onPointerMove);
+ document.removeEventListener("pointerup", this.onPointerUp);
+ document.addEventListener("pointerup", this.onPointerUp);
+ }
+
+ //Adds event listener so knows pointer is down and moving
+ onPointerBL = (e: React.PointerEvent): void => {
+ e.stopPropagation();
+ e.preventDefault();
+ this._isDraggingBL = true;
+ document.removeEventListener("pointermove", this.onPointerMove);
+ document.addEventListener("pointermove", this.onPointerMove);
+ document.removeEventListener("pointerup", this.onPointerUp);
+ document.addEventListener("pointerup", this.onPointerUp);
+ }
+
+ //Adds event listener so knows pointer is down and moving
+ onPointerTR = (e: React.PointerEvent): void => {
+ e.stopPropagation();
+ e.preventDefault();
+ this._isDraggingTR = true;
+ document.removeEventListener("pointermove", this.onPointerMove);
+ document.addEventListener("pointermove", this.onPointerMove);
+ document.removeEventListener("pointerup", this.onPointerUp);
+ document.addEventListener("pointerup", this.onPointerUp);
+ }
+
+ //Adds event listener so knows pointer is down and moving
+ onPointerTL = (e: React.PointerEvent): void => {
+ e.stopPropagation();
+ e.preventDefault();
+ this._isDraggingTL = true;
+ document.removeEventListener("pointermove", this.onPointerMove);
+ document.addEventListener("pointermove", this.onPointerMove);
+ document.removeEventListener("pointerup", this.onPointerUp);
+ document.addEventListener("pointerup", this.onPointerUp);
+ }
+
+ //Removes all event listeners
+ onPointerUp = (e: PointerEvent): void => {
+ e.stopPropagation();
+ e.preventDefault();
+ this._isDraggingTL = false;
+ this._isDraggingTR = false;
+ this._isDraggingBL = false;
+ this._isDraggingBR = false;
+ this._isDragging = false;
+ document.removeEventListener("pointermove", this.onPointerMove);
+ document.removeEventListener("pointerup", this.onPointerUp);
+ }
+
+ //Adjusts the value in NodeStore
+ onPointerMove = (e: PointerEvent): void => {
+ const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null);
+ const targetDoc = Cast(activeItem?.presentationTargetDoc, Doc, null);
+ const tagDocView = DocumentManager.Instance.getDocumentView(targetDoc);
+ e.stopPropagation();
+ e.preventDefault();
+ const doc = document.getElementById('resizable');
+ if (doc && tagDocView) {
+
+ const scale = tagDocView.childScaling();
+ console.log("childScaling: " + scale);
+ const scale2 = tagDocView.props.ScreenToLocalTransform().Scale;
+ console.log("ScreenToLocal...Scale: " + scale2);
+ let height = doc.offsetHeight;
+ let width = doc.offsetWidth;
+ let top = doc.offsetTop;
+ let left = doc.offsetLeft;
+ // const newHeightB = height += (e.movementY * NumCast(targetDoc._viewScale));
+ // const newHeightT = height -= (e.movementY * NumCast(targetDoc._viewScale));
+ // const newWidthR = width += (e.movementX * NumCast(targetDoc._viewScale));
+ // const newWidthL = width -= (e.movementX * NumCast(targetDoc._viewScale));
+ // const newLeft = left += (e.movementX * NumCast(targetDoc._viewScale));
+ // const newTop = top += (e.movementY * NumCast(targetDoc._viewScale));
+ // switch (this._drag) {
+ // case "": break;
+ // case "resizer-br":
+ // doc.style.height = newHeightB + 'px';
+ // doc.style.width = newWidthR + 'px';
+ // break;
+ // case "resizer-bl":
+ // doc.style.height = newHeightB + 'px';
+ // doc.style.width = newWidthL + 'px';
+ // doc.style.left = newLeft + 'px';
+ // break;
+ // case "resizer-tr":
+ // doc.style.width = newWidthR + 'px';
+ // doc.style.height = newHeightT + 'px';
+ // doc.style.top = newTop + 'px';
+ // case "resizer-tl":
+ // doc.style.width = newWidthL + 'px';
+ // doc.style.height = newHeightT + 'px';
+ // doc.style.top = newTop + 'px';
+ // doc.style.left = newLeft + 'px';
+ // case "resizable":
+ // doc.style.top = newTop + 'px';
+ // doc.style.left = newLeft + 'px';
+ // }
+ //Bottom right
+ if (this._isDraggingBR) {
+ const newHeight = height += (e.movementY * scale2);
+ doc.style.height = newHeight + 'px';
+ const newWidth = width += (e.movementX * scale2);
+ doc.style.width = newWidth + 'px';
+ // Bottom left
+ } else if (this._isDraggingBL) {
+ const newHeight = height += (e.movementY * scale);
+ doc.style.height = newHeight + 'px';
+ const newWidth = width -= (e.movementX * scale);
+ doc.style.width = newWidth + 'px';
+ const newLeft = left += (e.movementX * scale);
+ doc.style.left = newLeft + 'px';
+ // Top right
+ } else if (this._isDraggingTR) {
+ const newWidth = width += (e.movementX * tagDocView.props.ScreenToLocalTransform().Scale);
+ doc.style.width = newWidth + 'px';
+ const newHeight = height -= (e.movementY * tagDocView.props.ScreenToLocalTransform().Scale);
+ doc.style.height = newHeight + 'px';
+ const newTop = top += (e.movementY * tagDocView.props.ScreenToLocalTransform().Scale);
+ doc.style.top = newTop + 'px';
+ // Top left
+ } else if (this._isDraggingTL) {
+ const newWidth = width -= (e.movementX * tagDocView.props.ScreenToLocalTransform().Scale);
+ doc.style.width = newWidth + 'px';
+ const newHeight = height -= (e.movementY * tagDocView.props.ScreenToLocalTransform().Scale);
+ doc.style.height = newHeight + 'px';
+ const newTop = top += (e.movementY * tagDocView.props.ScreenToLocalTransform().Scale);
+ doc.style.top = newTop + 'px';
+ const newLeft = left += (e.movementX * tagDocView.props.ScreenToLocalTransform().Scale);
+ doc.style.left = newLeft + 'px';
+ } else if (this._isDragging) {
+ const newTop = top += (e.movementY * tagDocView.props.ScreenToLocalTransform().Scale);
+ doc.style.top = newTop + 'px';
+ const newLeft = left += (e.movementX * tagDocView.props.ScreenToLocalTransform().Scale);
+ doc.style.left = newLeft + 'px';
+ }
+ this.updateList(targetDoc, targetDoc["viewfinder-width-indexed"], width);
+ this.updateList(targetDoc, targetDoc["viewfinder-height-indexed"], height);
+ this.updateList(targetDoc, targetDoc["viewfinder-top-indexed"], top);
+ this.updateList(targetDoc, targetDoc["viewfinder-left-indexed"], left);
+ }
+ }
+
+ @action
+ checkList = (doc: Doc, list: any): number => {
+ const x: List<number> = list;
+ if (x && x.length >= NumCast(doc.currentFrame) + 1) {
+ return x[NumCast(doc.currentFrame)];
+ } else {
+ x.length = NumCast(doc.currentFrame) + 1;
+ x[NumCast(doc.currentFrame)] = x[NumCast(doc.currentFrame) - 1];
+ return x[NumCast(doc.currentFrame)];
+ }
+
+ }
+
+ @action
+ updateList = (doc: Doc, list: any, val: number) => {
+ const x: List<number> = list;
+ if (x && x.length >= NumCast(doc.currentFrame) + 1) {
+ x[NumCast(doc.currentFrame)] = val;
+ list = x;
+ } else {
+ x.length = NumCast(doc.currentFrame) + 1;
+ x[NumCast(doc.currentFrame)] = val;
+ list = x;
+ }
+ }
+
+ // scale: NumCast(targetDoc._viewScale),
+ @computed get zoomProgressivizeContainer() {
+ const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null);
+ const targetDoc = Cast(activeItem?.presentationTargetDoc, Doc, null);
+ if (targetDoc.editZoomProgressivize) {
+ return (
+ <>
+ <div id="resizable" className="resizable" onPointerDown={this.onPointerMid} style={{ width: this.checkList(targetDoc, targetDoc["viewfinder-width-indexed"]), height: this.checkList(targetDoc, targetDoc["viewfinder-height-indexed"]), top: this.checkList(targetDoc, targetDoc["viewfinder-top-indexed"]), left: this.checkList(targetDoc, targetDoc["viewfinder-left-indexed"]), position: 'absolute' }}>
+ <div className='resizers'>
+ <div id="resizer-tl" className='resizer top-left' onPointerDown={this.onPointerTL}></div>
+ <div id="resizer-tr" className='resizer top-right' onPointerDown={this.onPointerTR}></div>
+ <div id="resizer-bl" className='resizer bottom-left' onPointerDown={this.onPointerBL}></div>
+ <div id="resizer-br" className='resizer bottom-right' onPointerDown={this.onPointerBR}></div>
+ </div>
+ </div>
+ </>
+ );
+ } else return null;
+ }
+
+ @computed get progressivizeChildDocs() {
+ const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null);
+ const targetDoc = Cast(activeItem?.presentationTargetDoc, Doc, null);
+ const docs = DocListCast(targetDoc[Doc.LayoutFieldKey(targetDoc)]);
+ const tags: JSX.Element[] = [];
+ docs.forEach((doc, index) => {
+ if (doc["x-indexed"] && doc["y-indexed"]) {
+ tags.push(<div style={{ position: 'absolute', display: doc.displayMovement ? "block" : "none" }}>{this.checkMovementLists(doc, doc["x-indexed"], doc["y-indexed"])}</div>);
+ }
+ tags.push(
+ <div className="progressivizeButton" onPointerLeave={() => { if (NumCast(targetDoc.currentFrame) < NumCast(doc.appearFrame)) doc.opacity = 0; }} onPointerOver={() => { if (NumCast(targetDoc.currentFrame) < NumCast(doc.appearFrame)) doc.opacity = 0.5; }} onClick={e => { this.toggleDisplayMovement(doc); e.stopPropagation(); }} style={{ backgroundColor: doc.displayMovement ? "#aedff8" : "#c8c8c8", top: NumCast(doc.y), left: NumCast(doc.x) }}>
+ <div className="progressivizeButton-prev"><FontAwesomeIcon icon={"caret-left"} size={"lg"} onClick={e => { e.stopPropagation(); this.prevAppearFrame(doc, index); }} /></div>
+ <div className="progressivizeButton-frame">{doc.appearFrame}</div>
+ <div className="progressivizeButton-next"><FontAwesomeIcon icon={"caret-right"} size={"lg"} onClick={e => { e.stopPropagation(); this.nextAppearFrame(doc, index); }} /></div>
+ </div>);
+ });
+ return tags;
+ }
+
+ @undoBatch
+ @action
+ nextAppearFrame = (doc: Doc, i: number): void => {
+ console.log("next");
+ const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null);
+ const targetDoc = Cast(activeItem?.presentationTargetDoc, Doc, null);
+ const appearFrame = Cast(doc.appearFrame, "number", null);
+ if (appearFrame === undefined) {
+ doc.appearFrame = 0;
+ }
+ doc.appearFrame = appearFrame + 1;
+ const olist = new List<number>(numberRange(NumCast(targetDoc.lastFrame)).map(t => targetDoc.presProgressivize && t < (doc.appearFrame ? doc.appearFrame : i) ? 0 : 1));
+ doc["opacity-indexed"] = olist;
+ console.log(doc.appearFrame);
+ }
+
+ @undoBatch
+ @action
+ prevAppearFrame = (doc: Doc, i: number): void => {
+ console.log("prev");
+ const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null);
+ const targetDoc = Cast(activeItem?.presentationTargetDoc, Doc, null);
+ const appearFrame = Cast(doc.appearFrame, "number", null);
+ if (appearFrame === undefined) {
+ doc.appearFrame = 0;
+ }
+ doc.appearFrame = Math.max(0, appearFrame - 1);
+ const olist = new List<number>(numberRange(NumCast(targetDoc.lastFrame)).map(t => targetDoc.presProgressivize && t < (doc.appearFrame ? doc.appearFrame : i) ? 0 : 1));
+ doc["opacity-indexed"] = olist;
+ console.log(doc.appearFrame);
+ }
+
+ @computed get moreInfoDropdown() {
+ return (<div></div>);
+ }
+
+ @computed
+ get toolbarWidth(): number {
+ const width = this.props.PanelWidth();
+ return width;
+ }
+
+
+ @computed get toolbar() {
+ const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null);
+ if (activeItem) {
+ return (
+ <>
+ <Tooltip title={<><div className="dash-tooltip">{"Add new slide"}</div></>}><div className={`toolbar-button ${this.newDocumentTools ? "active" : ""}`} onClick={this.toggleNewDocument}><FontAwesomeIcon icon={"plus"} />
+ <FontAwesomeIcon className={`dropdown ${this.newDocumentTools ? "active" : ""}`} icon={"angle-down"} />
+ </div></Tooltip>
+ <div className="toolbar-divider" />
+ <Tooltip title={<><div className="dash-tooltip">{"View paths"}</div></>}><div className={`toolbar-button ${this.pathBoolean ? "active" : ""}`}>
+ <FontAwesomeIcon icon={"exchange-alt"} onClick={this.viewPaths} />
+ </div></Tooltip>
+ <Tooltip title={<><div className="dash-tooltip">{this.expandBoolean ? "Minimize all" : "Expand all"}</div></>}>
+ <div className={`toolbar-button ${this.expandBoolean ? "active" : ""}`} onClick={() => { this.toggleExpand(); this.childDocs.forEach((doc, ind) => { if (this.expandBoolean) doc.presExpandInlineButton = true; else doc.presExpandInlineButton = false; }); }}>
+ <FontAwesomeIcon icon={"eye"} />
+ </div>
+ </Tooltip>
+ {/* <div className="toolbar-button"><FontAwesomeIcon title={"Portal"} icon={"eye"} onClick={this.toolbarTest} /></div> */}
+ <div className="toolbar-divider" />
+ <Tooltip title={<><div className="dash-tooltip">{"Transitions"}</div></>}><div className={`toolbar-button ${this.transitionTools ? "active" : ""}`} onClick={this.toggleTransitionTools}>
+ <FontAwesomeIcon icon={"rocket"} />
+ <div style={{ display: this.props.PanelWidth() > 430 ? "block" : "none" }} className="toolbar-buttonText">&nbsp; Transitions</div>
+ <FontAwesomeIcon className={`dropdown ${this.transitionTools ? "active" : ""}`} icon={"angle-down"} />
+ </div></Tooltip>
+ <div className="toolbar-divider" />
+ <Tooltip title={<><div className="dash-tooltip">{"Progressivize"}</div></>}><div className={`toolbar-button ${this.progressivizeTools ? "active" : ""}`} onClick={this.toggleProgressivize}>
+ <FontAwesomeIcon icon={"tasks"} />
+ <div style={{ display: this.props.PanelWidth() > 430 ? "block" : "none" }} className="toolbar-buttonText">&nbsp; Progressivize</div>
+ <FontAwesomeIcon className={`dropdown ${this.progressivizeTools ? "active" : ""}`} icon={"angle-down"} />
+ </div></Tooltip>
+ <div className="toolbar-divider" />
+ <div className="toolbar-button" style={{ position: 'absolute', right: 23, transform: 'rotate(45deg)', fontSize: 16 }}>
+ <FontAwesomeIcon className={"toolbar-thumbtack"} icon={"thumbtack"} />
+ </div>
+ <div className={`toolbar-button ${this.moreInfoTools ? "active" : ""}`} onClick={this.toggleMoreInfo}>
+ <div className={`toolbar-moreInfo ${this.moreInfoTools ? "active" : ""}`}>
+ <div className="toolbar-moreInfoBall" />
+ <div className="toolbar-moreInfoBall" />
+ <div className="toolbar-moreInfoBall" />
+ </div>
+ </div>
+ </>
+ );
+ } else {
+ return (
+ <>
+ <Tooltip title={<><div className="dash-tooltip">{"Add new slide"}</div></>}><div className={`toolbar-button ${this.newDocumentTools ? "active" : ""}`} onClick={this.toggleNewDocument}><FontAwesomeIcon icon={"plus"} />
+ <FontAwesomeIcon className={`dropdown ${this.newDocumentTools ? "active" : ""}`} icon={"angle-down"} />
+ </div></Tooltip>
+ <div className="toolbar-button" style={{ position: 'absolute', right: 23, transform: 'rotate(45deg)', fontSize: 16 }}>
+ <FontAwesomeIcon className={"toolbar-thumbtack"} icon={"thumbtack"} />
+ </div>
+ <div className={`toolbar-button ${this.moreInfoTools ? "active" : ""}`} onClick={this.toggleMoreInfo}>
+ <div className={`toolbar-moreInfo ${this.moreInfoTools ? "active" : ""}`}>
+ <div className="toolbar-moreInfoBall" />
+ <div className="toolbar-moreInfoBall" />
+ <div className="toolbar-moreInfoBall" />
+ </div>
+ </div>
+ </>
+ );
+ }
+ }
+
+ private _itemRef: React.RefObject<HTMLDivElement> = React.createRef();
+
+
+ // protected createPresDropTarget = (ele: HTMLDivElement) => {
+ // console.log("created?");
+ // this.treedropDisposer?.();
+ // ele && (this.treedropDisposer = DragManager.MakeDropTarget(ele, this.onInternalDrop.bind(this), this.layoutDoc, this.onInternalPreDrop.bind(this)));
+ // if (ele) {
+ // console.log("ele: " + ele.className)
+ // }
+ // }
+
+ // protected onInternalPreDrop(e: Event, de: DragManager.DropEvent, targetAction: dropActionType) {
+ // console.log("preDrop?")
+ // if (de.complete.docDragData) {
+ // // if targetDropAction is, say 'alias', but we're just dragging within a collection, we want to ignore the targetAction.
+ // // otherwise, the targetAction should become the actual action (which can still be overridden by the userDropAction -eg, shift/ctrl keys)
+ // if (targetAction && !de.complete.docDragData.draggedDocuments.some(d => d.context === this.props.Document && this.childDocs.includes(d))) {
+ // de.complete.docDragData.dropAction = targetAction;
+ // }
+ // e.stopPropagation();
+ // }
+ // }
+
+ // @action
+ // protected onInternalDrop(e: Event, de: DragManager.DropEvent): boolean {
+ // console.log("drop in pres")
+ // const docDragData = de.complete.docDragData;
+ // ScriptCast(this.props.Document.dropConverter)?.script.run({ dragData: docDragData });
+ // if (docDragData && this.props.addDocument) {
+ // console.log("docDragData && this.props.addDocument");
+ // let added = false;
+ // const dropaction = docDragData.dropAction || docDragData.userDropAction;
+ // if (dropaction && dropaction !== "move") {
+ // console.log("dropaction && dropaction !== move");
+ // added = this.props.addDocument(docDragData.droppedDocuments);
+ // } else if (docDragData.moveDocument) {
+ // console.log("docDragData.moveDocument");
+ // const movedDocs = docDragData.droppedDocuments.filter((d, i) => docDragData.draggedDocuments[i] === d);
+ // const addedDocs = docDragData.droppedDocuments.filter((d, i) => docDragData.draggedDocuments[i] !== d);
+ // const res = addedDocs.length ? this.props.addDocument(addedDocs) : true;
+ // if (movedDocs.length) {
+ // const canAdd = this.props.Document._viewType === CollectionViewType.Pile || de.embedKey ||
+ // Doc.AreProtosEqual(Cast(movedDocs[0].annotationOn, Doc, null), this.props.Document);
+ // added = docDragData.moveDocument(movedDocs, this.props.Document, canAdd ? this.props.addDocument : returnFalse);
+ // } else added = res;
+ // } else {
+ // console.log("else");
+ // added = this.props.addDocument(docDragData.droppedDocuments);
+ // }
+ // added && e.stopPropagation();
+ // return added;
+ // }
+ // return false;
+ // }
+
+ render() {
+ this.childDocs.slice(); // needed to insure that the childDocs are loaded for looking up fields
const mode = StrCast(this.rootDoc._viewType) as CollectionViewType;
- return <div className="presBox-cont" style={{ minWidth: this.layoutDoc.inOverlay ? 240 : undefined }} >
+ // const addDocument = (doc: Doc | Doc[], relativeTo?: Doc, before?: boolean) => {
+ // return add(doc, relativeTo ? relativeTo : docs[i], before !== undefined ? before : false);
+ // };
+ return <div onPointerOver={this.onPointerOver} onPointerLeave={this.onPointerLeave} className="presBox-cont" style={{ minWidth: this.layoutDoc.inOverlay ? 240 : undefined }} >
<div className="presBox-buttons" style={{ display: this.rootDoc._chromeStatus === "disabled" ? "none" : undefined }}>
<select className="presBox-viewPicker"
onPointerDown={e => e.stopPropagation()}
onChange={this.viewChanged}
value={mode}>
- <option onPointerDown={e => e.stopPropagation()} value={CollectionViewType.Invalid}>Min</option>
+ {/* <option onPointerDown={e => e.stopPropagation()} value={CollectionViewType.Invalid}>Min</option> */}
<option onPointerDown={e => e.stopPropagation()} value={CollectionViewType.Stacking}>List</option>
- <option onPointerDown={e => e.stopPropagation()} value={CollectionViewType.Time}>Time</option>
+ {/* <option onPointerDown={e => e.stopPropagation()} value={CollectionViewType.Time}>Time</option> */}
<option onPointerDown={e => e.stopPropagation()} value={CollectionViewType.Carousel}>Slides</option>
</select>
- <div className="presBox-button" title="Back" style={{ gridColumn: 2 }} onClick={this.back}>
- <FontAwesomeIcon icon={"arrow-left"} />
- </div>
- <div className="presBox-button" title={"Reset Presentation" + this.layoutDoc.presStatus ? "" : " From Start"} style={{ gridColumn: 3 }} onClick={this.startOrResetPres}>
- <FontAwesomeIcon icon={this.layoutDoc.presStatus ? "stop" : "play"} />
- </div>
- <div className="presBox-button" title="Next" style={{ gridColumn: 4 }} onClick={this.next}>
- <FontAwesomeIcon icon={"arrow-right"} />
+ <div className="presBox-presentPanel">
+ <span className={`presBox-button ${this.layoutDoc.presStatus !== "edit" ? "active" : ""}`} title={"Reset Presentation" + this.layoutDoc.presStatus ? "" : " From Start"} style={{ minWidth: 60, gridColumn: 2 }}>
+ <div className="presBox-button-left" onClick={() => this.startOrResetPres(0)}>
+ <FontAwesomeIcon icon={"clock"} /> &nbsp;
+ <FontAwesomeIcon icon={this.layoutDoc.presStatus === "auto" ? "pause" : "play"} />
+ </div>
+ <div className={`presBox-button-right ${this.playTools ? "active" : ""}`} onClick={e => { e.stopPropagation; this.togglePlay(); }}>
+ <FontAwesomeIcon className="dropdown" style={{ margin: 0, transform: this.playTools ? 'rotate(180deg)' : 'rotate(0deg)' }} icon={"angle-down"} />
+ {this.playDropdown}
+ </div>
+ </span>
+ <span className={`presBox-button ${this.layoutDoc.presStatus === "edit" ? "present" : ""}`} title="Present">
+ <div className="presBox-button-left" onClick={() => this.layoutDoc.presStatus = "manual"}><FontAwesomeIcon icon={"play-circle"} /> &nbsp; Present </div>
+ <div className={`presBox-button-right ${this.presentTools ? "active" : ""}`} onClick={e => { e.stopPropagation; this.togglePresent(); }}>
+ <FontAwesomeIcon className="dropdown" style={{ margin: 0, transform: this.presentTools ? 'rotate(180deg)' : 'rotate(0deg)' }} icon={"angle-down"} />
+ {this.presentDropdown}
+ </div>
+ </span>
+ <div className={`presBox-button ${this.layoutDoc.presStatus !== "edit" ? "active" : ""}`} title="Back" onClick={this.back}>
+ <FontAwesomeIcon icon={"arrow-left"} />
+ </div>
+ <div className={`presBox-button ${this.layoutDoc.presStatus !== "edit" ? "active" : ""}`} title="Next" onClick={this.next}>
+ <FontAwesomeIcon icon={"arrow-right"} />
+ </div>
+ <div className={`presBox-button ${this.layoutDoc.presStatus !== "edit" ? "edit" : ""}`} title="Next" onClick={() => this.layoutDoc.presStatus = "edit"}>
+ <FontAwesomeIcon icon={"times"} />
+ </div>
</div>
</div>
- <div className="presBox-listCont" >
+ <div id="toolbarContainer" className={`presBox-toolbar ${this.layoutDoc.presStatus === "edit" ? "active" : ""}`}> {this.toolbar} </div>
+ {this.newDocumentDropdown}
+ {this.moreInfoDropdown}
+ {this.transitionDropdown}
+ {this.progressivizeDropdown}
+ <div className="presBox-listCont">
+ {/* ref={this.createPresDropTarget}> */}
{mode !== CollectionViewType.Invalid ?
<CollectionView {...this.props}
ContainingCollectionDoc={this.props.Document}
@@ -337,6 +1716,8 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
removeDocument={returnFalse}
dontRegisterView={true}
focus={this.selectElement}
+ // presMultiSelect={this.multiSelect}
+ // ScreenToLocalTransform={Transform.Identity} />
ScreenToLocalTransform={this.getTransform} />
: (null)
}
@@ -346,9 +1727,19 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
}
Scripting.addGlobal(function lookupPresBoxField(container: Doc, field: string, data: Doc) {
if (field === 'indexInPres') return DocListCast(container[StrCast(container.presentationFieldKey)]).indexOf(data);
- if (field === 'presCollapsedHeight') return container._viewType === CollectionViewType.Stacking ? 50 : 46;
+ if (field === 'presCollapsedHeight') return container._viewType === CollectionViewType.Stacking ? 30 : 26;
if (field === 'presStatus') return container.presStatus;
if (field === '_itemIndex') return container._itemIndex;
if (field === 'presBox') return container;
return undefined;
});
+
+
+
+// console.log("render = " + this.layoutDoc.title + " " + this.layoutDoc.presStatus);
+// const presOrderedDocs = DocListCast(activeItem.presOrderedDocs);
+// if (presOrderedDocs.length != this.childDocs.length || presOrderedDocs.some((pd, i) => pd !== this.childDocs[i])) {
+// this.rootDoc.presOrderedDocs = new List<Doc>(this.childDocs.slice());
+// }
+
+
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index 5a43a076b..192a6300a 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -9,8 +9,8 @@ import { documentSchema } from "../../../fields/documentSchemas";
import { Id } from "../../../fields/FieldSymbols";
import { InkTool } from "../../../fields/InkField";
import { List } from "../../../fields/List";
-import { createSchema, makeInterface } from "../../../fields/Schema";
-import { ScriptField } from "../../../fields/ScriptField";
+import { createSchema, makeInterface, listSpec } from "../../../fields/Schema";
+import { ScriptField, ComputedField } from "../../../fields/ScriptField";
import { Cast, NumCast } from "../../../fields/Types";
import { PdfField } from "../../../fields/URLField";
import { TraceMobx, GetEffectiveAcl } from "../../../fields/util";
@@ -344,6 +344,11 @@ export class PDFViewer extends ViewBoxAnnotatableComponent<IViewerProps, PdfDocu
}
@action
+ scrollToFrame = (duration: number, top: number) => {
+ this._mainCont.current && smoothScroll(duration, this._mainCont.current, top);
+ }
+
+ @action
scrollToAnnotation = (scrollToAnnotation: Doc) => {
if (scrollToAnnotation) {
const offset = this.visibleHeight() / 2;
diff --git a/src/client/views/presentationview/PresElementBox.scss b/src/client/views/presentationview/PresElementBox.scss
index dbe6b0d4f..159cb5f8a 100644
--- a/src/client/views/presentationview/PresElementBox.scss
+++ b/src/client/views/presentationview/PresElementBox.scss
@@ -1,11 +1,13 @@
.presElementBox-item {
- display: inline-block;
- background-color: #eeeeee;
+ display: grid;
+ grid-template-columns: max-content max-content max-content;
+ background-color: #d5dce2;
+ // box-shadow: 0px 2px 3px rgba(0, 0, 0, 0.25);
+ position: relative;
pointer-events: all;
width: 100%;
height: 100%;
- outline-color: maroon;
- outline-style: dashed;
+ font-weight: 400;
border-radius: 6px;
-webkit-touch-callout: none;
-webkit-user-select: none;
@@ -13,10 +15,19 @@
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
- transition: all .1s;
+ transition: all .3s;
padding: 0px;
padding-bottom: 3px;
+ .presElementBox-highlight {
+ position: absolute;
+ transform: translate(-100px, -6px);
+ z-index: -1;
+ width: calc(100% + 200px);
+ height: calc(100% + 12px);
+ background-color: #AEDDF8;
+ }
+
.documentView-node {
position: absolute;
z-index: 1;
@@ -33,62 +44,79 @@
.presElementBox-item:hover {
transition: all .1s;
- background: #AAAAAA;
+ background: #98b7da;
border-radius: 6px;
}
.presElementBox-active {
- background: gray;
color: black;
border-radius: 6px;
- box-shadow: black 2px 2px 5px;
+ border: solid 2px #5B9FDD;
}
-.presElementBox-closeIcon {
- border-radius: 20px;
- transform: scale(0.7);
- position: absolute;
- right: 0;
- top: 0;
- padding: 8px;
-}
-
-
.presElementBox-buttons {
- display: flow-root;
- position: relative;
+ display: grid;
+ grid-template-rows: 15px;
+ top: 15px;
+ left: -20;
+ position: absolute;
width: 100%;
height: auto;
.presElementBox-interaction {
- color: gray;
- float: left;
- padding: 0px;
- width: 20px;
- height: 20px;
+ display: none;
}
.presElementBox-interaction-selected {
- color: white;
+ color: grey;
+ background-color: rgba(0, 0, 0, 0);
float: left;
padding: 0px;
width: 20px;
height: 20px;
- border: solid 1px darkgray;
}
}
-.presElementBox-name {
+.presElementBox-number {
font-size: 12px;
+ font-weight: 700;
+ left: -15;
position: absolute;
display: inline-block;
- width: calc(100% - 45px);
+ overflow: hidden;
+}
+
+.presElementBox-name {
+ align-self: center;
+ font-size: 13px;
+ font-family: Roboto;
+ font-weight: 500;
+ position: relative;
+ top: 1px;
+ padding-left: 10px;
+ padding-right: 10px;
+ letter-spacing: normal;
+ max-width: max-content;
text-overflow: ellipsis;
overflow: hidden;
white-space: pre;
}
+.presElementBox-time {
+ align-self: center;
+ position: relative;
+ top: 2px;
+ padding-right: 10px;
+ font-size: 10;
+ font-weight: 300;
+ font-family: Roboto;
+ /* font-style: italic; */
+ letter-spacing: normal;
+ /* left: 10px; */
+}
+
.presElementBox-embedded {
+ grid-column: 1/8;
position: relative;
display: flex;
width: auto;
@@ -100,51 +128,56 @@
width: 100%;
height: 100%;
position: absolute;
- left: 0;
+ border-radius: 3px;
top: 0;
- background: transparent;
- z-index: 2;
+ left: 0;
+ z-index: 1;
+ overflow: hidden;
}
-@media only screen and (max-device-width: 480px) {
- .presElementBox-buttons {
- display: inline-flex;
- position: absolute;
- top: 0;
- right: 0;
- z-index: 3;
- width: 50%;
-
- .presElementBox-interaction {
- width: 50;
- height: 50;
- }
-
- .presElementBox-interaction-selected {
- width: 50;
- height: 50;
- }
- }
-
- .presElementBox-item {
- display: inline-flex;
- overflow: hidden;
- }
-
- .presElementBox-closeIcon {
- transform: scale(1.5);
- right: 10;
- top: 10;
- }
+.presElementBox-closeIcon {
+ position: absolute;
+ border-radius: 100%;
+ z-index: 300;
+ right: 3px;
+ top: 3px;
+ width: 20px;
+ height: 20px;
+ display: flex;
+ font-size: 75%;
+ background-color: black;
+ color: white;
+ justify-content: center;
+ align-items: center;
+}
- .presElementBox-name {
- font-size: 30px;
- top: 10px;
- z-index: 3;
- width: 50%;
- }
+.presElementBox-expand {
+ position: absolute;
+ border-radius: 100%;
+ z-index: 300;
+ right: 26px;
+ top: 3px;
+ width: 20px;
+ height: 20px;
+ display: flex;
+ font-size: 75%;
+ background-color: black;
+ color: white;
+ justify-content: center;
+ align-items: center;
+}
- .presElementBox-embedded {
- transform: translate(0, 90px) scale(1.5);
- }
+.presElementBox-expand-selected {
+ position: absolute;
+ border-radius: 100%;
+ right: 3px;
+ bottom: 3px;
+ width: 20px;
+ height: 20px;
+ z-index: 200;
+ display: flex;
+ background-color: black;
+ color: white;
+ justify-content: center;
+ align-items: center;
} \ No newline at end of file
diff --git a/src/client/views/presentationview/PresElementBox.tsx b/src/client/views/presentationview/PresElementBox.tsx
index 4c0972736..a27d5ef16 100644
--- a/src/client/views/presentationview/PresElementBox.tsx
+++ b/src/client/views/presentationview/PresElementBox.tsx
@@ -5,8 +5,8 @@ import { Doc, DataSym, DocListCast } from "../../../fields/Doc";
import { documentSchema } from '../../../fields/documentSchemas';
import { Id } from "../../../fields/FieldSymbols";
import { createSchema, makeInterface, listSpec } from '../../../fields/Schema';
-import { Cast, NumCast, BoolCast, ScriptCast } from "../../../fields/Types";
-import { emptyFunction, emptyPath, returnFalse, returnTrue, returnOne, returnZero, numberRange } from "../../../Utils";
+import { Cast, NumCast, BoolCast, ScriptCast, StrCast } from "../../../fields/Types";
+import { emptyFunction, emptyPath, returnFalse, returnTrue, returnOne, returnZero, numberRange, setupMoveUpEvents } from "../../../Utils";
import { Transform } from "../../util/Transform";
import { CollectionViewType } from '../collections/CollectionView';
import { ViewBoxBaseComponent } from '../DocComponent';
@@ -15,7 +15,10 @@ import { FieldView, FieldViewProps } from '../nodes/FieldView';
import "./PresElementBox.scss";
import React = require("react");
import { CollectionFreeFormDocumentView } from "../nodes/CollectionFreeFormDocumentView";
+import { PresBox } from "../nodes/PresBox";
import { DocumentType } from "../../documents/DocumentTypes";
+import { Tooltip } from "@material-ui/core";
+import { DragManager } from "../../util/DragManager";
export const presSchema = createSchema({
presentationTargetDoc: Doc,
@@ -38,19 +41,18 @@ const PresDocument = makeInterface(presSchema, documentSchema);
@observer
export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps, PresDocument>(PresDocument) {
public static LayoutString(fieldKey: string) { return FieldView.LayoutString(PresElementBox, fieldKey); }
-
_heightDisposer: IReactionDisposer | undefined;
// these fields are conditionally computed fields on the layout document that take this document as a parameter
@computed get indexInPres() { return Number(this.lookupField("indexInPres")); } // the index field is where this document is in the presBox display list (since this value is different for each presentation element, the value can't be stored on the layout template which is used by all display elements)
- @computed get collapsedHeight() { return Number(this.lookupField("presCollapsedHeight")); } // the collapsed height changes depending on the state of the presBox. We could store this on the presentation elemnt template if it's used by only one presentation - but if it's shared by multiple, then this value must be looked up
- @computed get presStatus() { return BoolCast(this.lookupField("presStatus")); }
+ @computed get collapsedHeight() { return Number(this.lookupField("presCollapsedHeight")); } // the collapsed height changes depending on the state of the presBox. We could store this on the presentation element template if it's used by only one presentation - but if it's shared by multiple, then this value must be looked up
+ @computed get presStatus() { return StrCast(this.lookupField("presStatus")); }
@computed get itemIndex() { return NumCast(this.lookupField("_itemIndex")); }
@computed get presBox() { return Cast(this.lookupField("presBox"), Doc, null); }
@computed get targetDoc() { return Cast(this.rootDoc.presentationTargetDoc, Doc, null) || this.rootDoc; }
componentDidMount() {
this._heightDisposer = reaction(() => [this.rootDoc.presExpandInlineButton, this.collapsedHeight],
- params => this.layoutDoc._height = NumCast(params[1]) + (Number(params[0]) ? 200 : 0), { fireImmediately: true });
+ params => this.layoutDoc._height = NumCast(params[1]) + (Number(params[0]) ? 100 : 0), { fireImmediately: true });
}
componentWillUnmount() {
this._heightDisposer?.();
@@ -69,7 +71,7 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps, PresDoc
this.targetDoc.opacity = 1;
}
} else {
- if (this.presStatus && this.indexInPres > this.itemIndex && this.targetDoc) {
+ if (this.presStatus !== "edit" && this.indexInPres > this.itemIndex && this.targetDoc) {
this.targetDoc.opacity = 0;
}
}
@@ -90,7 +92,7 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps, PresDoc
}
} else {
if (this.rootDoc.presFadeButton) this.rootDoc.presFadeButton = false;
- if (this.presStatus && this.indexInPres < this.itemIndex && this.targetDoc) {
+ if (this.presStatus !== "edit" && this.indexInPres < this.itemIndex && this.targetDoc) {
this.targetDoc.opacity = 0;
}
}
@@ -125,7 +127,7 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps, PresDoc
}
} else {
this.rootDoc.presHideAfterButton = false;
- if (this.presStatus && (this.indexInPres < this.itemIndex) && this.targetDoc) {
+ if (this.presStatus !== "edit" && (this.indexInPres < this.itemIndex) && this.targetDoc) {
this.targetDoc.opacity = 0.5;
}
}
@@ -166,10 +168,17 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps, PresDoc
*/
ScreenToLocalListTransform = (xCord: number, yCord: number) => [xCord, yCord];
- embedHeight = () => Math.min(this.props.PanelWidth() - 20, this.props.PanelHeight() - this.collapsedHeight);
+ @action
+ presExpandDocumentClick = () => {
+ this.rootDoc.presExpandInlineButton = !this.rootDoc.presExpandInlineButton;
+ }
+
+ embedHeight = () => 100;
+ // embedWidth = () => this.props.PanelWidth();
+ // embedHeight = () => Math.min(this.props.PanelWidth() - 20, this.props.PanelHeight() - this.collapsedHeight);
embedWidth = () => this.props.PanelWidth() - 20;
/**
- * The function that is responsible for rendering the a preview or not for this
+ * The function that is responsible for rendering a preview or not for this
* presentation element.
*/
@computed get renderEmbeddedInline() {
@@ -180,7 +189,7 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps, PresDoc
DataDoc={this.targetDoc[DataSym] !== this.targetDoc && this.targetDoc[DataSym]}
LibraryPath={emptyPath}
fitToBox={true}
- backgroundColor={this.props.backgroundColor}
+ backgroundColor={() => "darkgrey"}
rootSelected={returnTrue}
addDocument={returnFalse}
removeDocument={returnFalse}
@@ -207,36 +216,114 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps, PresDoc
</div>;
}
+ @computed get duration() {
+ let durationInS: number;
+ if (this.targetDoc.presDuration) durationInS = NumCast(this.targetDoc.presDuration) / 1000;
+ else durationInS = 2;
+ return "V: " + durationInS + "s";
+ }
+
+ @computed get transition() {
+ let transitionInS: number;
+ if (this.targetDoc.presTransition) transitionInS = NumCast(this.targetDoc.presTransition) / 1000;
+ else transitionInS = 0.5;
+ return "M: " + transitionInS + "s";
+ }
+
+ private _itemRef: React.RefObject<HTMLDivElement> = React.createRef();
+
+ headerDown = (e: React.PointerEvent<HTMLDivElement>) => {
+ const element = document.elementFromPoint(e.clientX, e.clientY)?.parentElement;
+ e.stopPropagation();
+ e.preventDefault();
+ if (element) {
+ console.log(element.className);
+ if (PresBox.Instance._eleArray.includes(element)) {
+ setupMoveUpEvents(this, e, this.startDrag, emptyFunction, emptyFunction);
+ }
+ }
+ }
+
+ startDrag = (e: PointerEvent, down: number[], delta: number[]) => {
+ // const ele: HTMLElement[] = PresBox.Instance._eleArray.map(doc => doc);
+ const activeItem = this.rootDoc;
+ const dragData = new DragManager.DocumentDragData(PresBox.Instance.sortArray().map(doc => doc));
+ // let value = this.getValue(this._heading);
+ // value = typeof value === "string" ? `"${value}"` : value;
+ if (activeItem) {
+ DragManager.StartDocumentDrag(PresBox.Instance._eleArray.map(ele => ele), dragData, e.clientX, e.clientY);
+ activeItem.dragging = true;
+ return true;
+ }
+ return false;
+ }
+
+
+
render() {
const treecontainer = this.props.ContainingCollectionDoc?._viewType === CollectionViewType.Tree;
const className = "presElementBox-item" + (this.itemIndex === this.indexInPres ? " presElementBox-active" : "");
const pbi = "presElementBox-interaction";
return !(this.rootDoc instanceof Doc) || this.targetDoc instanceof Promise ? (null) : (
<div className={className} key={this.props.Document[Id] + this.indexInPres}
+ ref={this._itemRef}
style={{ outlineWidth: Doc.IsBrushed(this.targetDoc) ? `1px` : "0px", }}
- onClick={e => { this.props.focus(this.rootDoc); e.stopPropagation(); }}>
- {treecontainer ? (null) : <>
- <strong className="presElementBox-name">
- {`${this.indexInPres + 1}. ${this.targetDoc?.title}`}
- </strong>
- <button className="presElementBox-closeIcon" onPointerDown={e => e.stopPropagation()} onClick={e => {
- this.props.removeDocument?.(this.rootDoc);
- e.stopPropagation();
- }}>X</button>
- <br />
- </>}
- <div className="presElementBox-buttons">
+ onClick={e => {
+ if (e.ctrlKey || e.metaKey) {
+ PresBox.Instance.multiSelect(this.rootDoc, this._itemRef.current!);
+ console.log("cmmd click");
+ } else if (e.shiftKey) {
+ PresBox.Instance.shiftSelect(this.rootDoc, this._itemRef.current!);
+ } else {
+ this.props.focus(this.rootDoc); e.stopPropagation();
+ PresBox.Instance._eleArray = [];
+ PresBox.Instance._eleArray.push(this._itemRef.current!);
+ console.log("normal click");
+ }
+ }}
+ // onClick={e => {
+ // if (this.props.active(true)) {
+ // e.stopPropagation();
+ // e.preventDefault();
+ // }
+ // }}
+ onPointerDown={this.headerDown}
+ >
+ <>
+ <div className="presElementBox-number">
+ {`${this.indexInPres + 1}.`}
+ </div>
+ <div className="presElementBox-name">
+ {`${this.targetDoc?.title}`}
+ </div>
+ <Tooltip title={<><div className="dash-tooltip">{"Movement speed"}</div></>}><div className="presElementBox-time" style={{ display: PresBox.Instance.toolbarWidth > 300 ? "block" : "none" }}>{this.transition}</div></Tooltip>
+ <Tooltip title={<><div className="dash-tooltip">{"Duration of visibility"}</div></>}><div className="presElementBox-time" style={{ display: PresBox.Instance.toolbarWidth > 300 ? "block" : "none" }}>{this.duration}</div></Tooltip>
+ <Tooltip title={<><div className="dash-tooltip">{"Remove from presentation"}</div></>}><div
+ className="presElementBox-closeIcon"
+ // onPointerDown={e => e.stopPropagation()}
+ onClick={e => {
+ this.props.removeDocument?.(this.rootDoc);
+ e.stopPropagation();
+ }}>
+ <FontAwesomeIcon icon={"trash"} onPointerDown={e => e.stopPropagation()} />
+ </div></Tooltip>
+ <Tooltip title={<><div className="dash-tooltip">{this.rootDoc.presExpandInlineButton ? "Minimize" : "Expand"}</div></>}><div className={"presElementBox-expand" + (this.rootDoc.presExpandInlineButton ? "-selected" : "")} onClick={e => { e.stopPropagation(); this.presExpandDocumentClick(); }}>
+ <FontAwesomeIcon icon={(this.rootDoc.presExpandInlineButton ? "angle-up" : "angle-down")} onPointerDown={e => e.stopPropagation()} />
+ </div></Tooltip>
+ </>
+ <div className="presElementBox-highlight" style={{ display: PresBox.Instance._selectedArray.includes(this.rootDoc) ? "block" : "none" }} />
+ <div className="presElementBox-buttons" style={{ display: this.rootDoc.presExpandInlineButton ? "grid" : "none" }}>
<button title="Zoom" className={pbi + (this.rootDoc.presZoomButton ? "-selected" : "")} onClick={this.onZoomDocumentClick}><FontAwesomeIcon icon={"search"} onPointerDown={e => e.stopPropagation()} /></button>
<button title="Navigate" className={pbi + (this.rootDoc.presNavButton ? "-selected" : "")} onClick={this.onNavigateDocumentClick}><FontAwesomeIcon icon={"location-arrow"} onPointerDown={e => e.stopPropagation()} /></button>
<button title="Hide Before" className={pbi + (this.rootDoc.presHideTillShownButton ? "-selected" : "")} onClick={this.onHideDocumentUntilPressClick}><FontAwesomeIcon icon={"file"} onPointerDown={e => e.stopPropagation()} /></button>
- <button title="Fade After" className={pbi + (this.rootDoc.presFadeButton ? "-selected" : "")} onClick={this.onFadeDocumentAfterPresentedClick}><FontAwesomeIcon icon={"file-download"} onPointerDown={e => e.stopPropagation()} /></button>
<button title="Hide After" className={pbi + (this.rootDoc.presHideAfterButton ? "-selected" : "")} onClick={this.onHideDocumentAfterPresentedClick}><FontAwesomeIcon icon={"file-download"} onPointerDown={e => e.stopPropagation()} /></button>
- <button title="Group With Up" className={pbi + (this.rootDoc.presGroupButton ? "-selected" : "")} onClick={e => { e.stopPropagation(); this.rootDoc.presGroupButton = !this.rootDoc.presGroupButton; }}><FontAwesomeIcon icon={"arrow-up"} onPointerDown={e => e.stopPropagation()} /></button>
- <button title="Progressivize" className={pbi + (this.rootDoc.pres ? "-selected" : "")} onClick={this.progressivize}><FontAwesomeIcon icon={"tasks"} onPointerDown={e => e.stopPropagation()} /></button>
- <button title="Expand Inline" className={pbi + (this.rootDoc.presExpandInlineButton ? "-selected" : "")} onClick={e => { e.stopPropagation(); this.rootDoc.presExpandInlineButton = !this.rootDoc.presExpandInlineButton; }}><FontAwesomeIcon icon={"arrow-down"} onPointerDown={e => e.stopPropagation()} /></button>
+ <button title="Progressivize" className={pbi + (this.rootDoc.presProgressivize ? "-selected" : "")} onClick={this.progressivize}><FontAwesomeIcon icon={"tasks"} onPointerDown={e => e.stopPropagation()} /></button>
+ <button title="Effect" className={pbi + (this.rootDoc.presEffect ? "-selected" : "")}>E</button>
</div>
{this.renderEmbeddedInline}
</div>
);
}
-} \ No newline at end of file
+}
+
+// this.layoutDoc.title !== "pres element template" \ No newline at end of file
diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts
index a1acc7060..43e74ff61 100644
--- a/src/fields/Doc.ts
+++ b/src/fields/Doc.ts
@@ -627,7 +627,7 @@ export namespace Doc {
var zip = new JSZip();
- zip.file("doc.json", docString);
+ zip.file(doc.title + ".json", docString);
// // Generate a directory within the Zip file structure
// var img = zip.folder("images");
@@ -639,7 +639,7 @@ export namespace Doc {
zip.generateAsync({ type: "blob" })
.then((content: any) => {
// Force down of the Zip file
- saveAs(content, "download.zip");
+ saveAs(content, doc.title + ".zip"); // glr: Possibly change the name of the document to match the title?
});
}
//
diff --git a/src/typings/index.d.ts b/src/typings/index.d.ts
index 452882e09..24b70057a 100644
--- a/src/typings/index.d.ts
+++ b/src/typings/index.d.ts
@@ -6,8 +6,11 @@ declare module 'cors';
declare module 'webrtc-adapter';
declare module 'bezier-curve';
-declare module 'fit-curve'
-
+declare module 'fit-curve';
+declare module 'reveal';
+declare module 'react-reveal';
+declare module 'react-reveal/makeCarousel';
+declare module 'react-resizable-rotatable-draggable';
declare module '@react-pdf/renderer' {
import * as React from 'react';