aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbobzel <zzzman@gmail.com>2022-04-29 13:57:42 -0400
committerbobzel <zzzman@gmail.com>2022-04-29 13:57:42 -0400
commit7b08cb4fd86a7e7048e14c05ab980f5b008d18d8 (patch)
treed1b66246de9bc25ac596c728ef0e9ece89f13a16
parent15bc17cbbe3816ab78ce653105ddff06bce18c59 (diff)
cleaned up creation of icon templates. fixed labelBox to support padding and to work with multiple lines and min font sizes.
-rw-r--r--src/client/util/CurrentUserUtils.ts141
-rw-r--r--src/client/util/DropConverter.ts5
-rw-r--r--src/client/views/nodes/LabelBigText.js7
-rw-r--r--src/client/views/nodes/LabelBox.tsx46
4 files changed, 105 insertions, 94 deletions
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index c7309d15e..7948aa70b 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -9,7 +9,7 @@ import { RichTextField } from "../../fields/RichTextField";
import { listSpec } from "../../fields/Schema";
import { ComputedField, ScriptField } from "../../fields/ScriptField";
import { BoolCast, Cast, DateCast, NumCast, PromiseValue, StrCast } from "../../fields/Types";
-import { ImageField, nullAudio } from "../../fields/URLField";
+import { nullAudio } from "../../fields/URLField";
import { SharingPermissions } from "../../fields/util";
import { Utils } from "../../Utils";
import { DocServer } from "../DocServer";
@@ -22,11 +22,10 @@ import { Colors } from "../views/global/globalEnums";
import { MainView } from "../views/MainView";
import { ButtonType, NumButtonType } from "../views/nodes/button/FontIconBox";
import { FormattedTextBox } from "../views/nodes/formattedText/FormattedTextBox";
-import { LabelBox } from "../views/nodes/LabelBox";
import { OverlayView } from "../views/OverlayView";
import { DocumentManager } from "./DocumentManager";
import { DragManager } from "./DragManager";
-import { makeTemplate } from "./DropConverter";
+import { makeTemplate, MakeTemplate } from "./DropConverter";
import { HistoryUtil } from "./History";
import { LinkManager } from "./LinkManager";
import { ScriptingGlobals } from "./ScriptingGlobals";
@@ -289,82 +288,68 @@ export class CurrentUserUtils {
// setup templates for different document types when they are iconified from Document Decorations
static setupDefaultIconTemplates(doc: Doc) {
- if (doc["template-icon-view"] === undefined) {
- const iconView = Docs.Create.LabelDocument({
- title: "icon", textTransform: "unset", letterSpacing: "unset", layout: LabelBox.LayoutString("title"), _backgroundColor: "dimgray",
- _width: 150, _height: 70, _xPadding: 10, _yPadding: 10, isTemplateDoc: true, onClick: ScriptField.MakeScript("deiconifyView(documentView)", { documentView: "any" }), system: true
- });
- // Docs.Create.TextDocument("", {
- // title: "icon", _width: 150, _height: 30, isTemplateDoc: true, onDoubleClick: ScriptField.MakeScript("deiconifyView(documentView)", { documentView: "any" })
- // });
- // Doc.GetProto(iconView).icon = new RichTextField('{"doc":{"type":"doc","content":[{"type":"paragraph","attrs":{"align":null,"color":null,"id":null,"indent":null,"inset":null,"lineSpacing":null,"paddingBottom":null,"paddingTop":null},"content":[{"type":"dashField","attrs":{"fieldKey":"title","docid":""}}]}]},"selection":{"type":"text","anchor":2,"head":2},"storedMarks":[]}', "");
- iconView.isTemplateDoc = makeTemplate(iconView);
- doc["template-icon-view"] = new PrefetchProxy(iconView);
- }
- if (doc["template-icon-view-rtf"] === undefined) {
- const iconRtfView = Docs.Create.LabelDocument({
- title: "icon_" + DocumentType.RTF, _showTitle: "creationDate", textTransform: "unset", letterSpacing: "unset", layout: LabelBox.LayoutString("text"),
- _singleLine: false, _minFontSize: 18, _maxFontSize: 24,
- _width: 150, _height: 70, _xPadding: 10, _yPadding: 10, isTemplateDoc: true, onClick: ScriptField.MakeScript("deiconifyView(documentView)", { documentView: "any" }), system: true
- });
- iconRtfView.isTemplateDoc = makeTemplate(iconRtfView, true, "icon_" + DocumentType.RTF);
- doc["template-icon-view-rtf"] = new PrefetchProxy(iconRtfView);
- }
- if (doc["template-icon-view-button"] === undefined) {
- const iconBtnView = Docs.Create.FontIconDocument({
- title: "icon_" + DocumentType.BUTTON, _nativeHeight: 30, _nativeWidth: 30,
- _width: 30, _height: 30, isTemplateDoc: true, onDoubleClick: ScriptField.MakeScript("deiconifyView(documentView)", { documentView: "any" }), system: true
- });
- iconBtnView.isTemplateDoc = makeTemplate(iconBtnView, true, "icon_" + DocumentType.BUTTON);
- doc["template-icon-view-button"] = new PrefetchProxy(iconBtnView);
- }
- if (doc["template-icon-view-img"] === undefined) {
- const iconImageView = Docs.Create.ImageDocument("http://www.cs.brown.edu/~bcz/face.gif", {
- title: "data", _width: 150, isTemplateDoc: true, _showTitle: "title", onClick: ScriptField.MakeScript("deiconifyView(documentView)", { documentView: "any" }), system: true
- });
- iconImageView.isTemplateDoc = makeTemplate(iconImageView, true, "icon_" + DocumentType.IMG);
- doc["template-icon-view-img"] = new PrefetchProxy(iconImageView);
- }
- if (doc["template-icon-view-col"] === undefined) {
- const iconColView = Docs.Create.ImageDocument("", { title: "icon", _showTitle: "title", _width: 360 / 4, _height: 270 / 4, onClick: ScriptField.MakeScript("deiconifyView(documentView)", { documentView: "any" }), system: true });
- iconColView.isTemplateDoc = makeTemplate(iconColView, true, "icon_" + DocumentType.COL);
- const proto = iconColView.proto as Doc;
- proto["icon-nativeWidth"] = 360 / 4;
- proto["icon-nativeHeight"] = 270 / 4;
- proto.icon = new ImageField("http://www.cs.brown.edu/~bcz/noImage.png");
- doc["template-icon-view-col"] = new PrefetchProxy(iconColView);
- }
- if (doc["template-icon-view-video"] === undefined) {
- const iconVidView = Docs.Create.ImageDocument("", { title: "icon", _width: 360 / 4, _height: 270 / 4, _showTitle: "title", onClick: ScriptField.MakeScript("deiconifyView(documentView)", { documentView: "any" }), system: true });
- iconVidView.isTemplateDoc = makeTemplate(iconVidView, true, "icon_" + DocumentType.VID);
- const proto = iconVidView.proto as Doc;
- proto["icon-nativeWidth"] = 360 / 4;
- proto["icon-nativeHeight"] = 270 / 4;
- proto.icon = new ImageField("http://www.cs.brown.edu/~bcz/noImage.png");
- doc["template-icon-view-video"] = new PrefetchProxy(iconVidView);
- }
- if (doc["template-icon-view-pdf"] === undefined) {
- const iconPdfView = Docs.Create.ImageDocument("", { title: "icon", _width: 360 / 4, _height: 270 / 4, _showTitle: "title", onClick: ScriptField.MakeScript("deiconifyView(documentView)", { documentView: "any" }), system: true });
- iconPdfView.isTemplateDoc = makeTemplate(iconPdfView, true, "icon_" + DocumentType.PDF);
- const proto = iconPdfView.proto as Doc;
- proto["icon-nativeWidth"] = 360 / 4;
- proto["icon-nativeHeight"] = 270 / 4;
- proto.icon = new ImageField("http://www.cs.brown.edu/~bcz/noImage.png");
- doc["template-icon-view-pdf"] = new PrefetchProxy(iconPdfView);
- }
- if (doc["template-icons"] === undefined) {
- doc["template-icons"] = new PrefetchProxy(Docs.Create.TreeDocument([doc["template-icon-view"] as Doc, doc["template-icon-view-img"] as Doc, doc["template-icon-view-button"] as Doc,
- doc["template-icon-view-col"] as Doc, doc["template-icon-view-rtf"] as Doc, doc["template-icon-view-video"] as Doc, doc["template-icon-view-pdf"] as Doc], { title: "icon templates", _height: 75, system: true }));
- } else {
- const templateIconsDoc = Cast(doc["template-icons"], Doc, null);
- const requiredTypes = [doc["template-icon-view"] as Doc, doc["template-icon-view-img"] as Doc, doc["template-icon-view-button"] as Doc,
- doc["template-icon-view-col"] as Doc, doc["template-icon-view-rtf"] as Doc];
- DocListCastAsync(templateIconsDoc.data).then(async curIcons => {
- curIcons && await Promise.all(curIcons);
- requiredTypes.map(ntype => Doc.AddDocToList(templateIconsDoc, "data", ntype));
- });
+ const templateIconsDoc = Cast(doc["template-icons"], Doc, null);
+
+ const makeIconTemplate = (type: DocumentType | undefined, templateField: string, iconTemplate: () => Doc, finalize: (icon: Doc) => Doc = (doc: Doc) => doc) => {
+ const iconFieldName = type ? "icon_" + type : "icon";
+ if (templateIconsDoc?.[iconFieldName] === undefined) {
+ const template = finalize(MakeTemplate(iconTemplate(), true, iconFieldName, templateField));
+ if (templateIconsDoc) {
+ templateIconsDoc[iconFieldName] = new PrefetchProxy(template);
+ Doc.AddDocToList(templateIconsDoc, "data", template);
+ }
+ return template;
+ }
+ return templateIconsDoc[iconFieldName] as Doc;
+ };
+ const finalizeIconTemplate = (icon: Doc) => {
+ const iconProto = Doc.GetProto(icon);
+ iconProto["icon-nativeWidth"] = iconProto.width;
+ iconProto["icon-nativeHeight"] = iconProto.height;
+ return icon;
+ };
+ const iconList = [
+ makeIconTemplate(undefined, "title", () => Docs.Create.LabelDocument({
+ textTransform: "unset", letterSpacing: "unset", _backgroundColor: "dimgray", _singleLine: false, _minFontSize: 14, _maxFontSize: 24, borderRounding: "5px",
+ _width: 150, _height: 70, _xPadding: 10, _yPadding: 10,
+ onClick: ScriptField.MakeScript("deiconifyView(documentView)", { documentView: "any" }), system: true
+ })),
+ makeIconTemplate(DocumentType.AUDIO, "title", () => Docs.Create.LabelDocument({
+ textTransform: "unset", letterSpacing: "unset", _backgroundColor: "lightgreen", _singleLine: false, _minFontSize: 14, _maxFontSize: 24, borderRounding: "5px",
+ _width: 150, _height: 70, _xPadding: 10, _yPadding: 10,
+ onClick: ScriptField.MakeScript("deiconifyView(documentView)", { documentView: "any" }), system: true
+ })),
+ makeIconTemplate(DocumentType.RTF, "text", () => Docs.Create.LabelDocument({
+ _showTitle: "creationDate", textTransform: "unset", letterSpacing: "unset", _singleLine: false, _minFontSize: 14, _maxFontSize: 24, borderRounding: "5px",
+ _width: 150, _height: 70, _xPadding: 10, _yPadding: 10,
+ onClick: ScriptField.MakeScript("deiconifyView(documentView)", { documentView: "any" }), system: true
+ })),
+ makeIconTemplate(DocumentType.PDF, "title", () => Docs.Create.LabelDocument({
+ textTransform: "unset", letterSpacing: "unset", _backgroundColor: "pink", _singleLine: false, _minFontSize: 10, _maxFontSize: 24, borderRounding: "5px",
+ _width: 75, _height: 125, _xPadding: 10, _yPadding: 10,
+ onClick: ScriptField.MakeScript("deiconifyView(documentView)", { documentView: "any" }), system: true
+ })),
+ makeIconTemplate(DocumentType.BUTTON, "data", () => Docs.Create.FontIconDocument({
+ _nativeHeight: 30, _nativeWidth: 30, _width: 30, _height: 30,
+ onDoubleClick: ScriptField.MakeScript("deiconifyView(documentView)", { documentView: "any" }), system: true
+ })),
+ makeIconTemplate(DocumentType.IMG, "data", () => Docs.Create.ImageDocument("", {
+ _width: 150, _showTitle: "title", onClick: ScriptField.MakeScript("deiconifyView(documentView)", { documentView: "any" }), system: true
+ })),
+ makeIconTemplate(DocumentType.COL, "icon", () => Docs.Create.ImageDocument("http://www.cs.brown.edu/~bcz/noImage.png", {
+ _width: 360 / 4, _height: 270 / 4, _showTitle: "title", onClick: ScriptField.MakeScript("deiconifyView(documentView)", { documentView: "any" }), system: true
+ }), finalizeIconTemplate),
+ makeIconTemplate(DocumentType.VID, "icon", () => Docs.Create.ImageDocument("http://www.cs.brown.edu/~bcz/noImage.png", {
+ _width: 360 / 4, _height: 270 / 4, _showTitle: "title", onClick: ScriptField.MakeScript("deiconifyView(documentView)", { documentView: "any" }), system: true
+ }), finalizeIconTemplate),
+ // makeIconTemplate(DocumentType.PDF, "data", () => Docs.Create.ImageDocument("http://www.cs.brown.edu/~bcz/noImage.png", {
+ // _width: 360 / 4, _height: 270 / 4, _showTitle: "title", onClick: ScriptField.MakeScript("deiconifyView(documentView)", { documentView: "any" }), system: true
+ // }), setIconProtoFields)
+ ];
+ if (!templateIconsDoc) {
+ doc["template-icons"] = Docs.Create.TreeDocument(iconList, { title: "icon templates", _height: 75, system: true });
+ iconList.map(ntype => (doc["template-icons"] as Doc)[StrCast(ntype.title)] = new PrefetchProxy(ntype));
}
- return doc["template-icons"] as Doc;
}
static creatorBtnDescriptors(doc: Doc): {
diff --git a/src/client/util/DropConverter.ts b/src/client/util/DropConverter.ts
index 082b6d8bd..076afd3a0 100644
--- a/src/client/util/DropConverter.ts
+++ b/src/client/util/DropConverter.ts
@@ -10,6 +10,11 @@ import { ImageField } from "../../fields/URLField";
import { ScriptingGlobals } from "./ScriptingGlobals";
import { listSpec } from "../../fields/Schema";
+export function MakeTemplate(doc: Doc, first: boolean = true, rename: Opt<string> = undefined, templateField: string = "") {
+ if (templateField) Doc.GetProto(doc).title = templateField; /// the title determines which field is being templated
+ doc.isTemplateDoc = makeTemplate(doc, first, rename);
+ return doc;
+}
//
// converts 'doc' into a template that can be used to render other documents.
// the title of doc is used to determine which field is being templated, so
diff --git a/src/client/views/nodes/LabelBigText.js b/src/client/views/nodes/LabelBigText.js
index 02c36c4bc..6a212d9ea 100644
--- a/src/client/views/nodes/LabelBigText.js
+++ b/src/client/views/nodes/LabelBigText.js
@@ -193,11 +193,12 @@ export default function BigText(element, options) {
if (fontSize < options.minimumFontSize) {
parentStyle.display = "flex";
parentStyle.alignItems = "center";
- style.whiteSpace = "pre-wrap";
style.textAlign = "center";
style.visibility = "";
- style.fontSize = "18px";
- style.lineHeight = "20px";
+ style.fontSize = options.minimumFontSize + "px";
+ style.lineHeight = "";
+ style.overflow = "hidden";
+ style.textOverflow = "ellipsis";
style.top = "";
style.left = "";
style.margin = "";
diff --git a/src/client/views/nodes/LabelBox.tsx b/src/client/views/nodes/LabelBox.tsx
index d539ca9b8..dfff59005 100644
--- a/src/client/views/nodes/LabelBox.tsx
+++ b/src/client/views/nodes/LabelBox.tsx
@@ -27,14 +27,19 @@ export class LabelBox extends ViewBoxBaseComponent<(FieldViewProps & LabelBoxPro
return `<${fieldType.name} fieldKey={'${fieldStr}'} label={'${label}'} {...props} />`; //e.g., "<ImageBox {...props} fieldKey={"data} />"
}
private dropDisposer?: DragManager.DragDropDisposer;
-
+ private _timeout: any;
componentDidMount() {
this.props.setContentView?.(this);
}
+ componentWillUnMount() {
+ this._timeout && clearTimeout(this._timeout);
+ }
getTitle() {
- return this.rootDoc["title-custom"] ? StrCast(this.rootDoc.title) : this.props.label ? this.props.label :
- typeof this.rootDoc[this.fieldKey] === "string" ? StrCast(this.rootDoc[this.fieldKey]) : StrCast(this.rootDoc.title);
+ return this.rootDoc["title-custom"] ? StrCast(this.rootDoc.title) :
+ this.props.label ? this.props.label :
+ typeof this.rootDoc[this.fieldKey] === "string" ? StrCast(this.rootDoc[this.fieldKey]) :
+ StrCast(this.rootDoc.title);
}
protected createDropTarget = (ele: HTMLDivElement) => {
@@ -73,8 +78,8 @@ export class LabelBox extends ViewBoxBaseComponent<(FieldViewProps & LabelBoxPro
@observable _mouseOver = false;
@computed get hoverColor() { return this._mouseOver ? StrCast(this.layoutDoc._hoverBackgroundColor) : "unset"; }
- fitTextToBox = (r: any) => {
- BigText(r, {
+ fitTextToBox = (r: any): any => {
+ const params = {
rotateText: null,
fontSizeFactor: 1,
minimumFontSize: NumCast(this.layoutDoc._minFontSize),
@@ -83,11 +88,25 @@ export class LabelBox extends ViewBoxBaseComponent<(FieldViewProps & LabelBoxPro
horizontalAlign: "center",
verticalAlign: "center",
textAlign: "center",
- whiteSpace: "nowrap"
- });
+ whiteSpace: this.layoutDoc._singleLine ? "nowrap" : "pre-wrap"
+ };
+ this._timeout = undefined;
+ if (!r) return params;
+ if (!r.offsetHeight || !r.offsetWidth) return this._timeout = setTimeout(() => this.fitTextToBox(r));
+ const parent = r.parentNode;
+ const parentStyle = parent.style;
+ parentStyle.display = "";
+ parentStyle.alignItems = "";
+ r.setAttribute("style", "");
+ r.style.width = this.layoutDoc._singleLine ? "" : "100%";
+
+ r.style.textOverflow = "ellipsis";
+ r.style.overflow = "hidden";
+ BigText(r, params);
}
// (!missingParams || !missingParams.length ? "" : "(" + missingParams.map(m => m + ":").join(" ") + ")")
render() {
+ this.fitTextToBox(null);// this causes mobx to trigger re-render when data changes
const params = Cast(this.paramsDoc["onClick-paramFieldKeys"], listSpec("string"), []);
const missingParams = params?.filter(p => !this.paramsDoc[p]);
params?.map(p => DocListCast(this.paramsDoc[p])); // bcz: really hacky form of prefetching ...
@@ -104,16 +123,17 @@ export class LabelBox extends ViewBoxBaseComponent<(FieldViewProps & LabelBoxPro
fontFamily: StrCast(this.layoutDoc._fontFamily) || "inherit",
letterSpacing: StrCast(this.layoutDoc.letterSpacing),
textTransform: StrCast(this.layoutDoc.textTransform) as any,
+ paddingLeft: NumCast(this.rootDoc._xPadding),
+ paddingRight: NumCast(this.rootDoc._xPadding),
+ paddingTop: NumCast(this.rootDoc._yPadding),
+ paddingBottom: NumCast(this.rootDoc._yPadding),
width: this.props.PanelWidth(),
height: this.props.PanelHeight(),
whiteSpace: this.layoutDoc._singleLine ? "pre" : "pre-wrap"
}} >
- <span ref={r => {
- if (r) {
- if (!r.offsetWidth || !r.offsetHeight) setTimeout(() => this.fitTextToBox(r));
- else this.fitTextToBox(r);
- }
- }}>{label.startsWith("#") ? (null) : label}</span>
+ <span ref={action((r: any) => this.fitTextToBox(r))}>
+ {label.startsWith("#") ? (null) : label}
+ </span>
</div>
<div className="labelBox-fieldKeyParams" >
{!missingParams?.length ? (null) : missingParams.map(m => <div key={m} className="labelBox-missingParam">{m}</div>)}