aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/StyleProvider.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/StyleProvider.tsx')
-rw-r--r--src/client/views/StyleProvider.tsx137
1 files changed, 66 insertions, 71 deletions
diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx
index c1a088b36..d4ef73557 100644
--- a/src/client/views/StyleProvider.tsx
+++ b/src/client/views/StyleProvider.tsx
@@ -3,13 +3,15 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import 'golden-layout/src/css/goldenlayout-base.css';
import 'golden-layout/src/css/goldenlayout-dark-theme.css';
import { action, runInAction } from 'mobx';
+import { extname } from 'path';
import { Doc, Opt, StrListCast } from "../../fields/Doc";
import { List } from '../../fields/List';
import { listSpec } from '../../fields/Schema';
-import { BoolCast, Cast, NumCast, StrCast } from "../../fields/Types";
+import { BoolCast, Cast, ImageCast, NumCast, StrCast } from "../../fields/Types";
import { DashColor, lightOrDark } from '../../Utils';
import { DocumentType } from '../documents/DocumentTypes';
import { CurrentUserUtils } from '../util/CurrentUserUtils';
+import { DocFocusOrOpen } from '../util/DocumentManager';
import { ColorScheme } from '../util/SettingsManager';
import { SnappingManager } from '../util/SnappingManager';
import { undoBatch, UndoManager } from '../util/UndoManager';
@@ -21,13 +23,12 @@ import { FieldViewProps } from './nodes/FieldView';
import { SliderBox } from './nodes/SliderBox';
import "./StyleProvider.scss";
import React = require("react");
-
-export enum StyleLayers {
- Background = "background"
-}
+import { InkingStroke } from './InkingStroke';
+import { TreeSort } from './collections/TreeView';
export enum StyleProp {
TreeViewIcon = "treeViewIcon",
+ TreeViewSortings = "treeViewSortings",// options for how to sort tree view items
DocContents = "docContents", // when specified, the JSX returned will replace the normal rendering of the document view
Opacity = "opacity", // opacity of the document view
Hidden = "hidden", // whether the document view should not be isplayed
@@ -51,14 +52,10 @@ export enum StyleProp {
function darkScheme() { return CurrentUserUtils.ActiveDashboard?.colorScheme === ColorScheme.Dark; }
-function toggleBackground(doc: Doc) {
+function toggleLockedPosition(doc: Doc) {
UndoManager.RunInBatch(() => runInAction(() => {
- const layers = StrListCast(doc._layerTags);
- if (!layers.includes(StyleLayers.Background)) {
- if (!layers.length) doc._layerTags = new List<string>([StyleLayers.Background]);
- else layers.push(StyleLayers.Background);
- }
- else layers.splice(layers.indexOf(StyleLayers.Background), 1);
+ doc._lockedPosition = !doc._lockedPosition;
+ doc._pointerEvents = doc._lockedPosition ? "none" : undefined;
}), "toggleBackground");
}
@@ -73,21 +70,37 @@ export function wavyBorderPath(pw: number, ph: number, inset: number = 0.05) {
// a preliminary implementation of a dash style sheet for setting rendering properties of documents nested within a Tab
//
export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps>, property: string): any {
+ const remoteDocHeader = "author;creationDate;noMargin";
const docProps = testDocProps(props) ? props : undefined;
const selected = property.includes(":selected");
const isCaption = property.includes(":caption");
const isAnchor = property.includes(":anchor");
const isAnnotated = property.includes(":annotated");
const isOpen = property.includes(":open");
- const fieldKey = (props as any)?.fieldKey ? (props as any).fieldKey + "-" : isCaption ? "caption-" : "";
+ const fieldKey = props?.fieldKey ? props.fieldKey + "-" : isCaption ? "caption-" : "";
const comicStyle = () => doc && !Doc.IsSystem(doc) && Doc.UserDoc().renderStyle === "comic";
- const isBackground = () => StrListCast(doc?._layerTags).includes(StyleLayers.Background);
+ const isBackground = () => doc && BoolCast(doc._lockedPosition);
const backgroundCol = () => props?.styleProvider?.(doc, props, StyleProp.BackgroundColor);
const opacity = () => props?.styleProvider?.(doc, props, StyleProp.Opacity);
const showTitle = () => props?.styleProvider?.(doc, props, StyleProp.ShowTitle);
const random = (min: number, max: number, x: number, y: number) => /* min should not be equal to max */ min + ((Math.abs(x * y) * 9301 + 49297) % 233280 / 233280) * (max - min);
switch (property.split(":")[0]) {
- case StyleProp.TreeViewIcon: return Doc.toIcon(doc, isOpen);
+ case StyleProp.TreeViewIcon:
+ const img = ImageCast(doc?.icon, ImageCast(doc?.data));
+ if (img) {
+ const ext = extname(img.url.href);
+ const url = doc?.icon ? img.url.href : img.url.href.replace(ext, "_s" + ext);
+ return <img src={url} width={20} height={15} style={{ margin: "auto", display: "block", objectFit: "contain" }} />;
+ }
+ return Doc.toIcon(doc, isOpen);
+
+ case StyleProp.TreeViewSortings:
+ const allSorts: { [key: string]: { color: string, label: string } | undefined } = {};
+ allSorts[TreeSort.Down] = { color: "blue", label: "↓" };
+ allSorts[TreeSort.Up] = { color: "crimson", label: "↑" };
+ if (doc?._viewType === CollectionViewType.Freeform) allSorts[TreeSort.Zindex] = { color: "green", label: "z" };
+ allSorts[TreeSort.None] = { color: "darkgray", label: '\u00A0\u00A0\u00A0' };
+ return allSorts;
case StyleProp.DocContents: return undefined;
case StyleProp.WidgetColor: return isAnnotated ? Colors.LIGHT_BLUE : darkScheme() ? "lightgrey" : "dimgrey";
// return doc = dragManager.dragDocument ? props.dragEffects.opacity??CastofOpacityonline94 : Cast())
@@ -99,36 +112,40 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
case StyleProp.ShowTitle: return (doc && !doc.presentationTargetDoc &&
StrCast(doc._showTitle,
props?.showTitle?.() ||
- (!Doc.IsSystem(doc) && [DocumentType.COL, DocumentType.RTF, DocumentType.IMG, DocumentType.VID].includes(doc.type as any) ?
+ (!Doc.IsSystem(doc) && [DocumentType.COL, DocumentType.LABEL, DocumentType.RTF, DocumentType.IMG, DocumentType.VID].includes(doc.type as any) ?
(doc.author === Doc.CurrentUserEmail ? StrCast(Doc.UserDoc().showTitle) :
- "author;creationDate") : "")) || "");
+ remoteDocHeader) : "")) || "");
case StyleProp.Color:
if (MainView.Instance.LastButton === doc) return Colors.DARK_GRAY;
const docColor: Opt<string> = StrCast(doc?.[fieldKey + "color"], StrCast(doc?._color));
if (docColor) return docColor;
- const backColor = backgroundCol();
+ const docView = props?.DocumentView?.();
+ const backColor = backgroundCol() || docView?.props.styleProvider?.(docView.props.treeViewDoc, docView.props, "backgroundColor");
if (!backColor) return undefined;
return lightOrDark(backColor);
- case StyleProp.Hidden: return BoolCast(doc?._hidden);
- case StyleProp.BorderRounding: return StrCast(doc?.[fieldKey + "borderRounding"], doc?._viewType === CollectionViewType.Pile ? "50%" : "");
+ case StyleProp.Hidden: return BoolCast(doc?.hidden);
+ case StyleProp.BorderRounding: return StrCast(doc?.[fieldKey + "borderRounding"], StrCast(doc?.borderRounding, doc?._viewType === CollectionViewType.Pile ? "50%" : ""));
case StyleProp.TitleHeight: return 15;
case StyleProp.BorderPath: return comicStyle() && props?.renderDepth && doc?.type !== DocumentType.INK ? { path: wavyBorderPath(props?.PanelWidth?.() || 0, props?.PanelHeight?.() || 0), fill: wavyBorderPath(props?.PanelWidth?.() || 0, props?.PanelHeight?.() || 0, .08), width: 3 } : { path: undefined, width: 0 };
case StyleProp.JitterRotation: return comicStyle() ? random(-1, 1, NumCast(doc?.x), NumCast(doc?.y)) * ((props?.PanelWidth() || 0) > (props?.PanelHeight() || 0) ? 5 : 10) : 0;
case StyleProp.HeaderMargin: return ([CollectionViewType.Stacking, CollectionViewType.NoteTaking, CollectionViewType.Masonry, CollectionViewType.Tree].includes(doc?._viewType as any) ||
- doc?.type === DocumentType.RTF) && showTitle() && !StrCast(doc?.showTitle).includes(":hover") ? 15 : 0;
+ (doc?.type === DocumentType.RTF && !showTitle()?.includes("noMargin")) || doc?.type === DocumentType.LABEL) && showTitle() && !StrCast(doc?.showTitle).includes(":hover") ? 15 : 0;
case StyleProp.BackgroundColor: {
if (MainView.Instance.LastButton === doc) return Colors.LIGHT_GRAY;
- let docColor: Opt<string> = StrCast(doc?.[fieldKey + "backgroundColor"], StrCast(doc?._backgroundColor, isCaption ? "rgba(0,0,0,0.4)" : ""));
+ let docColor: Opt<string> =
+ StrCast(doc?.[fieldKey + "backgroundColor"],
+ StrCast(doc?._backgroundColor,
+ StrCast(props?.Document.backgroundColor, isCaption ? "rgba(0,0,0,0.4)" : "")));
switch (doc?.type) {
case DocumentType.PRESELEMENT: docColor = docColor || (darkScheme() ? "" : ""); break;
- case DocumentType.PRES: docColor = docColor || (darkScheme() ? Colors.DARK_GRAY : Colors.WHITE); break;
+ case DocumentType.PRES: docColor = docColor || (darkScheme() ? "transparent" : "transparent"); break;
case DocumentType.FONTICON: docColor = docColor || Colors.DARK_GRAY; break;
case DocumentType.RTF: docColor = docColor || (darkScheme() ? Colors.DARK_GRAY : Colors.LIGHT_GRAY); break;
case DocumentType.FILTER: docColor = docColor || (darkScheme() ? Colors.DARK_GRAY : "rgba(105, 105, 105, 0.432)"); break;
case DocumentType.INK: docColor = doc?.isInkMask ? "rgba(0,0,0,0.7)" : undefined; break;
case DocumentType.SLIDER: break;
case DocumentType.EQUATION: docColor = docColor || "transparent"; break;
- case DocumentType.LABEL: docColor = docColor || (doc.annotationOn !== undefined ? "rgba(128, 128, 128, 0.18)" : undefined); break;
+ case DocumentType.LABEL: docColor = docColor || (doc.annotationOn !== undefined ? "rgba(128, 128, 128, 0.18)" : undefined) || (darkScheme() ? Colors.DARK_GRAY : Colors.LIGHT_GRAY); break;
case DocumentType.BUTTON: docColor = docColor || (darkScheme() ? Colors.DARK_GRAY : Colors.LIGHT_GRAY); break;
case DocumentType.LINKANCHOR: docColor = isAnchor ? Colors.LIGHT_BLUE : "transparent"; break;
case DocumentType.LINK: docColor = (isAnchor ? docColor : "") || "transparent"; break;
@@ -141,18 +158,20 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
case DocumentType.COL:
if (StrCast(Doc.LayoutField(doc)).includes(SliderBox.name)) break;
docColor = docColor ||
- (doc?._isGroup ? "#00000004" : // very faint highlight to show bounds of group
- (doc?._viewType === CollectionViewType.Pile || Doc.IsSystem(doc) ? (darkScheme() ? Colors.DARK_GRAY : Colors.LIGHT_GRAY) : // system docs (seen in treeView) get a grayish background
- isBackground() ? "cyan" : // ?? is there a good default for a background collection
- doc.annotationOn ? "#00000015" : // faint interior for collections on PDFs, images, etc
- StrCast((props?.renderDepth || 0) > 0 ?
- Doc.UserDoc().activeCollectionNestedBackground :
- Doc.UserDoc().activeCollectionBackground ?? (darkScheme() ? Colors.BLACK : Colors.WHITE))));
+ (doc?._viewType === CollectionViewType.Pile || Doc.IsSystem(doc) ? (darkScheme() ? Colors.DARK_GRAY : Colors.LIGHT_GRAY) : // system docs (seen in treeView) get a grayish background
+ doc.annotationOn ? "#00000015" : // faint interior for collections on PDFs, images, etc
+ (doc?._isGroup ? undefined :
+ Cast((props?.renderDepth || 0) > 0 ?
+ Doc.UserDoc().activeCollectionNestedBackground :
+ Doc.UserDoc().activeCollectionBackground, "string") ?? (darkScheme() ?
+ Colors.BLACK :
+ "linear-gradient(#065fff, #85c1f9)"))
+ );
break;
//if (doc._viewType !== CollectionViewType.Freeform && doc._viewType !== CollectionViewType.Time) return "rgb(62,62,62)";
default: docColor = docColor || (darkScheme() ? Colors.DARK_GRAY : Colors.WHITE); break;
}
- if (docColor && (!doc || props?.layerProvider?.(doc) === false)) docColor = DashColor(docColor).fade(0.5).toString();
+ if (docColor && !doc) docColor = DashColor(docColor).fade(0.5).toString();
return docColor;
}
case StyleProp.BoxShadow: {
@@ -178,18 +197,17 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
}
}
case StyleProp.PointerEvents:
- if (doc?.type === DocumentType.MARKER) return "none";
- if (props?.pointerEvents === "none") return "none";
- const layer = doc && props?.layerProvider?.(doc);
- if (opacity() === 0 || (doc?.type === DocumentType.INK && !docProps?.treeViewDoc) || doc?.isInkMask) return "none";
- if (layer === false && !selected && !SnappingManager.GetIsDragging()) return "none";
- if (doc?.type !== DocumentType.INK && layer === true) return "all";
+ if (doc?.pointerEvents) return StrCast(doc.pointerEvents);
+ if (props?.pointerEvents?.() === "none") return "none";
+ const isInk = doc && StrCast(Doc.Layout(doc).layout).includes(InkingStroke.name);
+ if (opacity() === 0 || (isInk && !docProps?.treeViewDoc) || doc?.isInkMask) return "none";
+ if (!isInk) return "all";
return undefined;
case StyleProp.Decorations:
- if (props?.ContainingCollectionDoc?._viewType === CollectionViewType.Freeform) {
- return doc && (isBackground() || selected) && (props?.renderDepth || 0) > 0 &&
+ if (props?.ContainingCollectionDoc?._viewType === CollectionViewType.Freeform || doc?.x !== undefined || doc?.y !== undefined) {
+ return doc && (isBackground() || selected) && !Doc.IsSystem(doc) && (props?.renderDepth || 0) > 0 &&
((doc.type === DocumentType.COL && doc._viewType !== CollectionViewType.Pile) || [DocumentType.RTF, DocumentType.IMG, DocumentType.INK].includes(doc.type as DocumentType)) ?
- <div className="styleProvider-lock" onClick={() => toggleBackground(doc)}>
+ <div className="styleProvider-lock" onClick={() => toggleLockedPosition(doc)}>
<FontAwesomeIcon icon={isBackground() ? "lock" : "unlock"} style={{ color: isBackground() ? "red" : undefined }} size="lg" />
</div>
: (null);
@@ -198,7 +216,7 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
}
export function DashboardToggleButton(doc: Doc, field: string, onIcon: IconProp, offIcon: IconProp, clickFunc?: () => void) {
- return <div className={`styleProvider-treeView-icon${doc[field] ? "-active" : ""}`}
+ return <div title={field} className={`styleProvider-treeView-icon${doc[field] ? "-active" : ""}`}
onClick={undoBatch(action((e: React.MouseEvent) => {
e.stopPropagation();
clickFunc ? clickFunc() : (doc[field] = doc[field] ? undefined : true);
@@ -214,36 +232,13 @@ export function DashboardStyleProvider(doc: Opt<Doc>, props: Opt<FieldViewProps
if (doc && property.split(":")[0] === StyleProp.Decorations) {
return doc._viewType === CollectionViewType.Docking ? (null) :
<>
- {DashboardToggleButton(doc, "hidden", "eye-slash", "eye")}
- {DashboardToggleButton(doc, "lockedPosition", "lock", "unlock")}
+ {DashboardToggleButton(doc, "hidden", "eye-slash", "eye", () => {
+ doc.hidden = doc.hidden ? undefined : true;
+ if (!doc.hidden) {
+ DocFocusOrOpen(doc, props?.ContainingCollectionDoc);
+ }
+ })}
</>;
}
return DefaultStyleProvider(doc, props, property);
}
-
-//
-// a preliminary semantic-"layering/grouping" mechanism for determining interactive properties of documents
-// currently, the provider tests whether the docuemnt's layer field matches the activeLayer field of the tab.
-// if it matches, then the document gets pointer events, otherwise it does not.
-//
-export function DefaultLayerProvider(thisDoc: Doc) {
- return (doc: Doc, assign?: boolean) => {
- if (doc.z) return true;
- if (assign) {
- const activeLayer = StrCast(thisDoc?.activeLayer);
- if (activeLayer) {
- const layers = Cast(doc._layerTags, listSpec("string"), []);
- if (layers.length && !layers.includes(activeLayer)) layers.push(activeLayer);
- else if (!layers.length) doc._layerTags = new List<string>([activeLayer]);
- if (activeLayer === "red" || activeLayer === "green" || activeLayer === "blue") doc._backgroundColor = activeLayer;
- }
- return true;
- } else {
- if (Doc.AreProtosEqual(doc, thisDoc)) return true;
- const layers = StrListCast(doc._layerTags);
- if (!layers.length && !thisDoc?.activeLayer) return true;
- if (layers.includes(StrCast(thisDoc?.activeLayer))) return true;
- return false;
- }
- };
-} \ No newline at end of file