aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes/PresBox.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/nodes/PresBox.tsx')
-rw-r--r--src/client/views/nodes/PresBox.tsx765
1 files changed, 732 insertions, 33 deletions
diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx
index 8818d375e..fc5e73c81 100644
--- a/src/client/views/nodes/PresBox.tsx
+++ b/src/client/views/nodes/PresBox.tsx
@@ -9,17 +9,23 @@ import { returnFalse, returnOne } 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 "./PresBox.scss";
import { ViewBoxBaseComponent } from "../DocComponent";
-import { makeInterface } from "../../../fields/Schema";
+import { makeInterface, listSpec } from "../../../fields/Schema";
import { Docs } 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 { Zoom, Fade, Flip, Rotate, Bounce, Roll, LightSpeed } from 'react-reveal';
+
type PresBoxSchema = makeInterface<[typeof documentSchema]>;
const PresBoxDocument = makeInterface(documentSchema);
@@ -27,15 +33,17 @@ const PresBoxDocument = makeInterface(documentSchema);
@observer
export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>(PresBoxDocument) {
public static LayoutString(fieldKey: string) { return FieldView.LayoutString(PresBox, fieldKey); }
+ 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
@@ -51,7 +59,14 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
this.rootDoc.presBox = this.rootDoc;
this.rootDoc._forceRenderEngine = "timeline";
this.rootDoc._replacedChrome = "replaced";
+ this.layoutDoc.presStatus = "edit";
+ document.addEventListener("keydown", this.keyEvents, false);
+ }
+
+ componentWillUnmount() {
+ document.removeEventListener("keydown", this.keyEvents, false);
}
+
updateCurrentPresentation = () => Doc.UserDoc().activePresentation = this.rootDoc;
@undoBatch
@@ -146,7 +161,7 @@ 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();
@@ -201,31 +216,59 @@ 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);
- }
-
+ // if (this.layoutDoc.presStatus === "edit") {
+ // this.layoutDoc.presStatus = true;
+ // this.startPresentation(index);
+ // }
this.navigateToElement(this.childDocs[index], fromDoc);
this.hideIfNotPresented(index);
this.showAfterPresented(index);
+ 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._presTimer && this.layoutDoc.presStatus === "auto") {
+ 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);
+ // for (let i = this.itemIndex + 1; i <= this.childDocs.length; i++) {
+ // if (this.itemIndex + 1 === this.childDocs.length) {
+ // clearTimeout(this._presTimer);
+ // this.layoutDoc.presStatus = "manual";
+ // } else timer = setTimeout(() => { console.log(i); this.next(); }, i * 2000);
+ // }
+
}
+
+ // if (this.layoutDoc.presStatus) {
+ // this.resetPresentation();
+ // } else {
+ // this.layoutDoc.presStatus = true;
+ // this.startPresentation(0);
+ // this.gotoDocument(0, this.itemIndex);
+ // }
}
//The function that resets the presentation by removing every action done by it. It also
@@ -234,7 +277,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
@@ -279,6 +322,42 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
this.updateMinimize(e, this.rootDoc._viewType = viewType);
});
+ @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;
+ activeItem.presNavButton = false;
+ } else if (movement === 'nav') {
+ activeItem.presZoomButton = false;
+ activeItem.presNavButton = !activeItem.presNavButton;
+ } else if (movement === 'swap') {
+ targetDoc.presTransition = 0;
+ } else {
+ activeItem.presZoomButton = false;
+ activeItem.presNavButton = false;
+ }
+ });
+
+ @undoBatch
+ visibilityChanged = action((visibility: string) => {
+ const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null);
+ if (visibility === 'fade') {
+ activeItem.presFadeButton = !activeItem.presFadeButton;
+ } else if (visibility === 'hideBefore') {
+ activeItem.presHideTillShownButton = !activeItem.presHideTillShownButton;
+ activeItem.presHideAfterButton = false;
+ } else if (visibility === 'hideAfter') {
+ activeItem.presHideAfterButton = !activeItem.presHideAfterButton;
+ activeItem.presHideAfterButton = false;
+ } else {
+ activeItem.presHideAfterButton = false;
+ activeItem.presHideTillShownButton = false;
+ activeItem.presFadeButton = false;
+ }
+ });
+
whenActiveChanged = action((isActive: boolean) => this.props.whenActiveChanged(this._isChildActive = isActive));
addDocumentFilter = (doc: Doc | Doc[]) => {
const docs = doc instanceof Doc ? [doc] : doc;
@@ -290,18 +369,612 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
}
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;
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() {
- // console.log("render = " + this.layoutDoc.title + " " + this.layoutDoc.presStatus);
- // 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[] = [];
+
+ @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) => {
+ this._selectedArray.push(this.childDocs[this.childDocs.indexOf(doc)]);
+ console.log(this._selectedArray);
+ }
+
+ //Shift click
+ @action
+ shiftSelect = (doc: Doc) => {
+ 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]);
+ }
+ }
+ console.log(this._selectedArray);
+ }
+
+
+
+ //Esc click
+ @action
+ keyEvents = (e: KeyboardEvent) => {
+ e.stopPropagation;
+ // 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
+ } else if ((e.metaKey || e.altKey) && e.keyCode === 65) {
+ if (this.layoutDoc.presStatus === "edit") this._selectedArray = this.childDocs;
+ // left / a / up to go back
+ } else if (e.keyCode === 37 || 65 || 38) {
+ if (this.layoutDoc.presStatus !== "edit") this.back();
+ // right / d / down to go to next
+ } else if (e.keyCode === 39 || 68 || 40) {
+ if (this.layoutDoc.presStatus !== "edit") this.next();
+ // spacebar to 'present' or go to next slide
+ } else if (e.keyCode === 32) {
+ if (this.layoutDoc.presStatus !== "edit") this.next();
+ else this.layoutDoc.presStatus = "manual";
+ }
+ }
+
+ @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;
+ }
+ }
+ });
+ }
+
+
+ @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 pathBoolean: 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;
+ 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;
+ }
+
+ @action toggleAllDropdowns() {
+ this.transitionTools = false;
+ this.newDocumentTools = false;
+ this.progressivizeTools = false;
+ this.moreInfoTools = false;
+ this.playTools = false;
+ }
+
+ @undoBatch
+ @action
+ toolbarTest = () => {
+ const presTargetDoc = Cast(this.childDocs[this.itemIndex].presentationTargetDoc, Doc, null);
+ console.log("title: " + presTargetDoc.title);
+ console.log("index: " + this.itemIndex);
+ }
+
+ @undoBatch
+ @action
+ viewPaths = async () => {
+ const docToJump = this.childDocs[0];
+ const aliasOf = await DocCastAsync(docToJump.aliasOf);
+ const srcContext = aliasOf && await DocCastAsync(aliasOf.context);
+ 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);
+ // }
+ }
+
+ @computed get paths() {
+ const paths = []; //List of all of the paths that need to be added
+ console.log(this.childDocs.length - 1);
+ for (let i = 0; i <= this.childDocs.length - 1; i++) {
+ const targetDoc = Cast(this.childDocs[i].presentationTargetDoc, Doc, null);
+ if (this.childDocs[i + 1] && targetDoc) {
+ const nextTargetDoc = Cast(this.childDocs[i + 1].presentationTargetDoc, Doc, null);
+ const n1x = NumCast(targetDoc.x) + (NumCast(targetDoc._width) / 2);
+ const n1y = NumCast(targetDoc.y) + (NumCast(targetDoc._height) / 2);
+ const n2x = NumCast(nextTargetDoc.x) + (NumCast(targetDoc._width) / 2);
+ const n2y = NumCast(nextTargetDoc.y) + (NumCast(targetDoc._height) / 2);
+ const pathPoints = n1x + "," + n1y + " " + n2x + "," + n2y;
+ paths.push(<polyline
+ points={pathPoints}
+ style={{
+ opacity: 0.7,
+ stroke: "#69a6db",
+ strokeWidth: 5,
+ }}
+ markerStart="url(#square)"
+ markerEnd="url(#arrow)" />);
+ }
+ }
+ return paths;
+ }
+
+ @action togglePath = () => this.pathBoolean = !this.pathBoolean;
+
+ /**
+ * 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);
+
+ if (activeItem) {
+ const targetDoc = Cast(activeItem.presentationTargetDoc, Doc, null);
+ 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 movement = activeItem.presZoomButton ? 'Zoom' : activeItem.presNavbutton ? 'Navigate' : 'None';
+ const effect = targetDoc.presEffect ? targetDoc.presEffect : 'None';
+ const visibility = activeItem.presFadeButton ? 'Fade' : activeItem.presHideTillShownButton ? 'Hide till shown' : activeItem.presHideAfter ? 'Hide on exit' : 'None';
+ 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')}
+ >
+ {movement}
+ <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.presZoomButton && !activeItem.presNavButton ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.movementChanged('none')}>None</div>
+ <div className={`presBox-dropdownOption ${activeItem.presZoomButton ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.movementChanged('zoom')}>Pan and Zoom</div>
+ <div className={`presBox-dropdownOption ${activeItem.presNavButton ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.movementChanged('nav')}>Pan</div>
+ <div className={`presBox-dropdownOption ${activeItem.presNavButton ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.movementChanged('swap')}>Swap</div>
+ </div>
+ </div>
+ <input type="range" step="0.1" min="0.1" max="10" value={transitionSpeed} className={`toolbar-slider ${activeItem.presZoomButton || activeItem.presNavButton ? "" : "none"}`} id="toolbar-slider" onChange={(e: React.ChangeEvent<HTMLInputElement>) => { e.stopPropagation(); this.setTransitionTime(e.target.value); }} />
+ <div className={`slider-headers ${activeItem.presZoomButton || activeItem.presNavButton ? "" : "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">Medium</div>
+ <div className="slider-text">Fast</div>
+ </div>
+ </div>
+ <div className="ribbon-box">
+ Duration
+ <div className="presBox-dropdown"
+ onPointerDown={e => e.stopPropagation()}
+ >
+ {duration} seconds
+ </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 title="Fade After" className={`ribbon-button ${activeItem.presFadeButton ? "active" : ""}`} onClick={this.onFadeDocumentAfterPresentedClick}>Fade After</div> */}
+ {/* <div title="Hide After" className={`ribbon-button ${activeItem.presHideTillShownButton ? "active" : ""}`} onClick={() => console.log("hide before")}>Hide Before</div> */}
+ {/* <div title="Hide Before" className={`ribbon-button ${activeItem.presHideAfterButton ? "active" : ""}`} onClick={() => console.log("hide after")}>Hide After</div> */}
+ </div>
+ <div className="ribbon-box">
+ Effects
+ <div className="presBox-dropdown"
+ onPointerDown={e => e.stopPropagation()}
+ // onClick={() => this.dropdownToggle('Movement')}
+ >
+ {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">
+ <div style={{ gridColumn: 1, gridRow: 2, justifySelf: 'center', color: targetDoc.presEffectDirection === "left" ? "#5a9edd" : "black" }} onClick={() => targetDoc.presEffectDirection = 'left'}><FontAwesomeIcon icon={"angle-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>
+ <div style={{ gridColumn: 2, gridRow: 1, justifySelf: 'center', color: targetDoc.presEffectDirection === "top" ? "#5a9edd" : "black" }} onClick={() => targetDoc.presEffectDirection = 'top'}><FontAwesomeIcon icon={"angle-down"} /></div>
+ <div style={{ gridColumn: 2, gridRow: 3, justifySelf: 'center', color: targetDoc.presEffectDirection === "bottom" ? "#5a9edd" : "black" }} onClick={() => targetDoc.presEffectDirection = 'bottom'}><FontAwesomeIcon icon={"angle-up"} /></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>
+ </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: "flex", alignSelf: "center" }}>
+ <div title="Text" className={`ribbon-button ${type === "text" ? "active" : ""}`} onClick={() => { type = "text"; }}>Text</div>
+ <div title="Freeform" className={`ribbon-button ${type === "freeform" ? "active" : ""}`} onClick={() => { type = "freeform"; }}>Freeform</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)}>
+ Start from current slide
+ </div>
+ <div className="dropdown-play-button" onClick={() => this.startOrResetPres(0)}>
+ Start from first slide
+ </div>
+ </div>
+ );
+ }
+
+ progressivizeOptions = (viewType: string) => {
+ const buttons = [];
+ buttons.push(<div className="ribbon-button" title="Progressivize child documents" onClick={this.progressivize}>Progressivize child documents</div>);
+ buttons.push(<div className="ribbon-button" title="Internal navigation" onClick={() => console.log("hide after")}>Internal navigation</div>);
+ if (viewType === "rtf") {
+ buttons.push(<div className="ribbon-button" title="Progressivize bullet points" onClick={() => console.log("hide after")}>Bullet points</div>);
+ }
+ return buttons;
+ }
+
+
+
+ @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">
+ <div className="selectedList-items">1. {targetDoc.title}</div>
+ </div>
+ </div>
+ <div className="ribbon-final-box">
+ <div className="progressivizeEdit">
+ <div className="ribbon-button" style={{ backgroundColor: activeItem.presProgressivize ? "#aedef8" : "" }} title="Progressivize child documents" onClick={this.progressivize}>Progressivize child documents</div>
+ <div className="ribbon-button" style={{ display: activeItem.presProgressivize ? "block" : "none", backgroundColor: targetDoc.editProgressivize ? "#aedef8" : "" }} title="Edit progresivize" onClick={this.editProgressivize}>Edit</div>
+ </div>
+ <div className="ribbon-button" title="Internal navigation" onClick={() => console.log("hide after")}>Internal navigation</div>
+ </div>
+ </div>
+ </div>
+ );
+ }
+ }
+
+ @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
+ progressivize = (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;
+ }
+ }
+
+ @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) => {
+ tags.push(
+ <div className="progressivizeButton" style={{ top: NumCast(doc.y), left: NumCast(doc.x) }}>{doc.appearFrame}</div>
+ );
+ });
+ return tags;
+ }
+
+
+
+ @computed get moreInfoDropdown() {
+ return (<div></div>);
+ }
+
+ @computed get effectOpenBracket() {
+ const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null);
+ const targetDoc = Cast(activeItem.presentationTargetDoc, Doc, null);
+ if (targetDoc.presEffect && this.itemIndex) {
+ return ("<" + targetDoc.presEffect + "when=" + this.layoutDoc === PresBox.Instance.childDocs[this.itemIndex].presentationTargetDoc + ">");
+ } else return;
+ }
+
+ @computed get effectCloseBracket() {
+ const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null);
+ const targetDoc = Cast(activeItem.presentationTargetDoc, Doc, null);
+ if (targetDoc.presEffect && this.itemIndex) {
+ return ("</" + targetDoc.presEffect + ">");
+ } else return;
+ }
+
+ @computed get toolbar() {
+ const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null);
+
+ if (activeItem) {
+ return (
+ <>
+ <div className={`toolbar-button ${this.newDocumentTools ? "active" : ""}`} onClick={this.toggleNewDocument}><FontAwesomeIcon icon={"plus"} />
+ <FontAwesomeIcon className={`dropdown ${this.newDocumentTools ? "active" : ""}`} icon={"angle-down"} />
+ </div>
+ <div className="toolbar-divider" />
+ <div className={`toolbar-button ${this.pathBoolean ? "active" : ""}`}><FontAwesomeIcon title={"View Paths"} icon={"object-group"} onClick={this.viewPaths} /></div>
+ {/* <div className="toolbar-button"><FontAwesomeIcon title={"Portal"} icon={"eye"} onClick={this.toolbarTest} /></div> */}
+ <div className="toolbar-divider" />
+ <div className={`toolbar-button ${this.transitionTools ? "active" : ""}`} onClick={this.toggleTransitionTools}>
+ <FontAwesomeIcon icon={"rocket"} />
+ <div className="toolbar-buttonText">&nbsp; Transitions</div>
+ <FontAwesomeIcon className={`dropdown ${this.transitionTools ? "active" : ""}`} icon={"angle-down"} />
+ </div>
+ <div className="toolbar-divider" />
+ <div className={`toolbar-button ${this.progressivizeTools ? "active" : ""}`} onClick={this.toggleProgressivize}>
+ <FontAwesomeIcon icon={"tasks"} />
+ <div className="toolbar-buttonText">&nbsp; Progressivize</div>
+ <FontAwesomeIcon className={`dropdown ${this.progressivizeTools ? "active" : ""}`} icon={"angle-down"} />
+ </div>
+ <div className="toolbar-divider" />
+ <div className="toolbar-button">
+ <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 (
+ <>
+ <div className="toolbar-button"><FontAwesomeIcon icon={"plus"} onClick={this.toggleNewDocument} />
+ <FontAwesomeIcon className={`dropdown ${this.newDocumentTools ? "active" : ""}`} icon={"angle-down"} />
+ </div>
+ <div className="toolbar-button">
+ <FontAwesomeIcon className={"toolbar-thumbtack"} icon={"thumbtack"} />
+ </div>
+ <Fade left when={this.moreInfoTools}>
+ <h1>uppercase</h1>
+ </Fade>
+ <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>
+ </>
+ );
+ }
+ }
+
+ 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 }} >
@@ -315,16 +988,33 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
<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">
+ <div className={`presBox-button ${this.layoutDoc.presStatus !== "edit" ? "active" : ""}`} title={"Reset Presentation" + this.layoutDoc.presStatus ? "" : " From Start"} style={{ gridColumn: 2 }} onClick={() => this.startOrResetPres(0)}>
+ <FontAwesomeIcon icon={"clock"} /> &nbsp;
+ <FontAwesomeIcon icon={this.layoutDoc.presStatus === "auto" ? "pause" : "play"} />
+ <div className="toolbar-divider" style={{ marginLeft: 5 }} />
+ <FontAwesomeIcon onClick={e => { e.stopPropagation; this.togglePlay(); }} className="dropdown" icon={"angle-down"} />
+ {this.playDropdown}
+ </div>
+ <div className={`presBox-button ${this.layoutDoc.presStatus === "edit" ? "present" : ""}`} title="Present" onClick={() => this.layoutDoc.presStatus = "manual"}>
+ <FontAwesomeIcon className="present-icon" icon={"play-circle"} /> Present
+ </div>
+ <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-toolbar ${this.layoutDoc.presStatus === "edit" ? "active" : ""}`}> {this.toolbar} </div>
+ {this.newDocumentDropdown}
+ {this.moreInfoDropdown}
+ {this.transitionDropdown}
+ {this.progressivizeDropdown}
<div className="presBox-listCont" >
{mode !== CollectionViewType.Invalid ?
<CollectionView {...this.props}
@@ -334,10 +1024,11 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
moveDocument={returnFalse}
childOpacity={returnOne}
childLayoutTemplate={this.childLayoutTemplate}
- filterAddDocument={this.addDocumentFilter}
+ filterAddDocument={returnFalse}
removeDocument={returnFalse}
dontRegisterView={true}
focus={this.selectElement}
+ presMultiSelect={this.multiSelect}
ScreenToLocalTransform={this.getTransform} />
: (null)
}
@@ -353,3 +1044,11 @@ Scripting.addGlobal(function lookupPresBoxField(container: Doc, field: string, d
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());
+ // } \ No newline at end of file