diff options
Diffstat (limited to 'src/client/views/collections')
-rw-r--r-- | src/client/views/collections/CollectionDockingView.scss | 98 | ||||
-rw-r--r-- | src/client/views/collections/CollectionDockingView.tsx | 2 | ||||
-rw-r--r-- | src/client/views/collections/TabDocView.scss | 59 | ||||
-rw-r--r-- | src/client/views/collections/TabDocView.tsx | 107 |
4 files changed, 199 insertions, 67 deletions
diff --git a/src/client/views/collections/CollectionDockingView.scss b/src/client/views/collections/CollectionDockingView.scss index a054f0ae1..b8180fe24 100644 --- a/src/client/views/collections/CollectionDockingView.scss +++ b/src/client/views/collections/CollectionDockingView.scss @@ -1,40 +1,46 @@ -@import "../../views/global/globalCssVariables.scss"; +@import "../global/globalCssVariables.scss"; .lm_title { - margin-top: 3px; - border-radius: 5px; - border: solid 0px dimgray; - border-width: 2px 2px 0px; - height: 20px; - transform: translate(0px, -3px); + -webkit-appearance: none; + display: inline-block; + align-self: center; + align-items: center; + height: 100%; + overflow: hidden; + text-overflow: ellipsis; + background: transparent; + border: solid 0px transparent; cursor: grab; + color: $black; } .lm_title.focus-visible { + -webkit-appearance: none; cursor: text; } .lm_title_wrap { overflow: hidden; - height: 19px; - margin-top: -2px; - display: inline-block; + align-items: center; + align-self: center; + background: transparent; + width: max-content; + height: 100%; + display: flex; } .lm_active .lm_title { - border: solid 1px lightgray; -} - -.lm_header .lm_tab .lm_close_tab { - position: absolute; - text-align: center; + -webkit-appearance: none; + // font-weight: 700; } .lm_header .lm_tab { - padding-right: 20px; - margin-top: -1px; - border-bottom: 1px black; + padding: 0px; + opacity: 0.7; + box-shadow: none; + height: 19px; + // border-bottom: 1px black; .collectionDockingView-gear { display: none; @@ -42,9 +48,13 @@ } .lm_header .lm_tab.lm_active { - padding-right: 20px; - margin-top: 1px; - border-bottom: unset; + padding: 0; + opacity: 1; + margin: 0; + box-shadow: none; + height: 22px; + margin-right: 2px; + // border-bottom: unset; .collectionDockingView-gear { display: inline-block; @@ -55,6 +65,41 @@ display: inline; } +.lm_drag_tab { + padding: 0; + width: 15px !important; + height: 15px !important; + position: relative !important; + display: inline-flex !important; + align-items: center; + top: 0 !important; + right: unset !important; + left: 0 !important; +} + +.lm_close_tab { + padding: 0; + align-self: center; + margin-right: 5px; + background-color: black; + border-radius: 3px; + opacity: 1 !important; + width: 15px !important; + height: 15px !important; + position: relative !important; + display: inline-flex !important; + align-items: center; + top: 0 !important; + right: unset !important; + left: 0 !important; +} + +.lm_tab, +.lm_tab_active { + display: flex !important; + padding-right: 0 !important; +} + .collectiondockingview-container { width: 100%; height: 100%; @@ -82,16 +127,17 @@ } .lm_content { - background: white; + background: $white; } .lm_controls>li { - opacity: 0.6; - transform: scale(1.2); + opacity: 1; + transform: scale(1); } .lm_controls .lm_popout { - background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAUCAAAAABHICnvAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QAAKqNIzIAAAAHdElNRQfkCBsXMgbrEyzaAAAAT0lEQVQY02NgIAcIu8tgEW3/u4IDQ5B14/8LQlhFhckVFfCJjIyIOfP/QWpEZGSQJFS05s9fIPj3/z+YmseCTxS7CZS7DI+PsYcOjpAkDAA6H0KZxzDzlgAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAyMC0wOC0yN1QyMzo1MDowNi0wNDowMDvgVpQAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMjAtMDgtMjdUMjM6NTA6MDYtMDQ6MDBKve4oAAAAAElFTkSuQmCC) + transform: rotate(45deg); + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAQUlEQVR4nHXOQQ4AMAgCQeT/f6aXpsGK3jSTuCVJAAr7iBdoAwCKd0nwfaAdHbYERw5b44+E8JoBjEYGMBq5gAYP3usUDu2IvoUAAAAASUVORK5CYII=); } .lm_maximised .lm_controls .lm_maximise { diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 388f9a909..a8471f8e2 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -445,4 +445,4 @@ Scripting.addGlobal(function openInLightbox(doc: any) { LightboxView.AddDocTab(d "opens up document in a lightbox", "(doc: any)"); Scripting.addGlobal(function openOnRight(doc: any) { return CollectionDockingView.AddSplit(doc, "right"); }, "opens up document in tab on right side of the screen", "(doc: any)"); -Scripting.addGlobal(function useRightSplit(doc: any, shiftKey?: boolean) { CollectionDockingView.ReplaceTab(doc, "right", undefined, shiftKey); }); +Scripting.addGlobal(function useRightSplit(doc: any, shiftKey?: boolean) { CollectionDockingView.ReplaceTab(doc, "right", undefined, shiftKey); });
\ No newline at end of file diff --git a/src/client/views/collections/TabDocView.scss b/src/client/views/collections/TabDocView.scss index 9acbc4f85..a963f1cb9 100644 --- a/src/client/views/collections/TabDocView.scss +++ b/src/client/views/collections/TabDocView.scss @@ -1,19 +1,62 @@ input.lm_title:focus, -input.lm_title -{ +input.lm_title { max-width: unset !important; + outline: none; transition-delay: unset; - width: 100%; + width: max-content; cursor: text; } + input.lm_title { transition-delay: 0.35s; - width: 100px; + width: max-content; cursor: pointer; } -.tabDocView-drag { - margin: auto; + +.lm_iconWrap { + display: flex; + color: black; + width: 15px; + height: 15px; + align-items: center; + align-self: center; + justify-content: center; + margin: 3px; + border-radius: 20%; + + .moreInfoDot { + background-color: white; + border-radius: 100%; + width: 3px; + height: 3px; + margin: 0.5px; + } +} + +.ffMenu { + display: grid; + grid-auto-rows: 35px; + grid-auto-columns: auto auto auto auto auto; + right: 10px; + bottom: 50px; + position: absolute; + min-height: 35px; + height: max-content; + border: solid 2px black; + border-radius: 5px; + background-color: #bddbe6; + width: max-content; + min-width: 35px; + + .ffMenuButton { + display: flex; + width: 35px; + height: 35px; + align-items: center; + justify-content: center; + } } + .miniMap-hidden, .miniMap { position: absolute; @@ -37,6 +80,7 @@ input.lm_title { } } } + .miniMap-hidden { position: absolute; bottom: 0; @@ -46,7 +90,8 @@ input.lm_title { transform: translate(20px, 20px) rotate(45deg); border-radius: 30px; padding: 2px; - > svg { + + >svg { margin-top: 3px; transform: translate(0px, 7px); } diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx index 7e2f7811e..0e67bebd8 100644 --- a/src/client/views/collections/TabDocView.tsx +++ b/src/client/views/collections/TabDocView.tsx @@ -1,3 +1,4 @@ +import { IconProp } from '@fortawesome/fontawesome-svg-core'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Tooltip } from '@material-ui/core'; import 'golden-layout/src/css/goldenlayout-base.css'; @@ -9,9 +10,9 @@ import * as ReactDOM from 'react-dom'; import { DataSym, Doc, DocListCast, DocListCastAsync, HeightSym, Opt, WidthSym } from "../../../fields/Doc"; import { Id } from '../../../fields/FieldSymbols'; import { FieldId } from "../../../fields/RefField"; -import { Cast, NumCast, StrCast, BoolCast } from "../../../fields/Types"; +import { BoolCast, Cast, NumCast, StrCast } from "../../../fields/Types"; import { TraceMobx } from '../../../fields/util'; -import { emptyFunction, returnEmptyDoclist, returnFalse, returnTrue, setupMoveUpEvents, Utils } from "../../../Utils"; +import { emptyFunction, lightOrDark, returnEmptyDoclist, returnFalse, returnTrue, setupMoveUpEvents, Utils } from "../../../Utils"; import { DocServer } from "../../DocServer"; import { DocUtils } from '../../documents/Documents'; import { DocumentType } from '../../documents/DocumentTypes'; @@ -24,15 +25,15 @@ import { Transform } from '../../util/Transform'; import { undoBatch, UndoManager } from "../../util/UndoManager"; import { LightboxView } from '../LightboxView'; import { DocFocusOptions, DocumentView, DocumentViewProps } from "../nodes/DocumentView"; -import { FieldViewProps } from '../nodes/FieldView'; -import { PinProps, PresBox, PresMovement } from '../nodes/PresBox'; +import { PresBox, PinProps, PresMovement } from '../nodes/PresBox'; import { DefaultLayerProvider, DefaultStyleProvider, StyleLayers, StyleProp } from '../StyleProvider'; import { CollectionDockingView } from './CollectionDockingView'; import { CollectionDockingViewMenu } from './CollectionDockingViewMenu'; import { CollectionFreeFormView } from './collectionFreeForm/CollectionFreeFormView'; -import { CollectionViewType, CollectionView } from './CollectionView'; +import { CollectionView, CollectionViewType } from './CollectionView'; import "./TabDocView.scss"; import React = require("react"); +import Color = require('color'); const _global = (window /* browser */ || global /* node */) as any; interface TabDocViewProps { @@ -52,6 +53,14 @@ export class TabDocView extends React.Component<TabDocViewProps> { @computed get layoutDoc() { return this._document && Doc.Layout(this._document); } @computed get tabColor() { return StrCast(this._document?._backgroundColor, StrCast(this._document?.backgroundColor, DefaultStyleProvider(this._document, undefined, StyleProp.BackgroundColor))); } + @computed get tabTextColor() { return this._document?.type === DocumentType.PRES ? "black" : StrCast(this._document?._color, StrCast(this._document?.color, DefaultStyleProvider(this._document, undefined, StyleProp.Color))); } + // @computed get renderBounds() { + // const bounds = this._document ? Cast(this._document._renderContentBounds, listSpec("number"), [0, 0, this.returnMiniSize(), this.returnMiniSize()]) : [0, 0, 0, 0]; + // const xbounds = bounds[2] - bounds[0]; + // const ybounds = bounds[3] - bounds[1]; + // const dim = Math.max(xbounds, ybounds); + // return { l: bounds[0] + xbounds / 2 - dim / 2, t: bounds[1] + ybounds / 2 - dim / 2, cx: bounds[0] + xbounds / 2, cy: bounds[1] + ybounds / 2, dim }; + // } get stack() { return (this.props as any).glContainer.parent.parent; } get tab() { return (this.props as any).glContainer.tab; } @@ -65,15 +74,25 @@ export class TabDocView extends React.Component<TabDocViewProps> { tab.contentItem.config.fixed && (tab.contentItem.parent.config.fixed = true); tab.DashDoc = doc; CollectionDockingView.Instance.tabMap.add(tab); - + const iconType: IconProp = Doc.toIcon(doc); // setup the title element and set its size according to the # of chars in the title. Show the full title when clicked. const titleEle = tab.titleElement[0]; + const iconWrap = document.createElement("div"); + const closeWrap = document.createElement("div"); + + titleEle.size = StrCast(doc.title).length + 3; titleEle.value = doc.title; titleEle.onchange = undoBatch(action((e: any) => { titleEle.size = e.currentTarget.value.length + 3; Doc.GetProto(doc).title = e.currentTarget.value; })); + + const dragBtnDown = (e: React.PointerEvent) => { + setupMoveUpEvents(this, e, e => !e.defaultPrevented && DragManager.StartDocumentDrag([iconWrap], new DragManager.DocumentDragData([doc], doc.dropAction as dropActionType), e.clientX, e.clientY), returnFalse, emptyFunction); + }; + + if (tab.element[0].children[1].children.length === 1) { const toggle = document.createElement("div"); toggle.style.width = "10px"; @@ -83,18 +102,42 @@ export class TabDocView extends React.Component<TabDocViewProps> { toggle.style.borderTopRightRadius = "7px"; toggle.style.position = "relative"; toggle.style.display = "inline-block"; - toggle.style.background = "gray"; - toggle.style.borderLeft = "solid 1px black"; + toggle.style.background = "transparent"; toggle.onclick = (e: MouseEvent) => { if (tab.contentItem === tab.header.parent.getActiveContentItem()) { tab.DashDoc.activeLayer = tab.DashDoc.activeLayer ? undefined : StyleLayers.Background; } }; - tab.element[0].style.borderTopRightRadius = "8px"; - tab.element[0].children[1].appendChild(toggle); - tab._disposers.layerDisposer = reaction(() => - ({ layer: tab.DashDoc.activeLayer, color: this.tabColor }), - ({ layer, color }) => toggle.style.background = !layer ? color : "dimgrey", { fireImmediately: true }); + iconWrap.className = "lm_iconWrap"; + iconWrap.id = "lm_iconWrap"; + closeWrap.className = "lm_iconWrap"; + closeWrap.id = "lm_closeWrap"; + closeWrap.onclick = (e: MouseEvent) => { + tab.header.parent.contentItem.remove(); + Doc.AddDocToList(CurrentUserUtils.MyRecentlyClosed, "data", tab.DashDoc, undefined, true, true); + }; + const docIcon = <FontAwesomeIcon onPointerDown={dragBtnDown} icon={iconType} />; + const closeIcon = <FontAwesomeIcon icon={"times"} />; + ReactDOM.render(docIcon, iconWrap); + ReactDOM.render(closeIcon, closeWrap); + // tab.element[0].append(closeWrap); + tab.element[0].prepend(iconWrap); + tab._disposers.layerDisposer = reaction(() => ({ layer: tab.DashDoc.activeLayer, color: this.tabColor }), + ({ layer, color }) => { + const textColor = lightOrDark(this.tabColor); //not working with StyleProp.Color + titleEle.style.color = textColor; + titleEle.style.backgroundColor = "transparent"; + iconWrap.style.color = textColor; + closeWrap.style.color = textColor; + moreInfoDrag.style.backgroundColor = textColor; + tab.element[0].style.background = !layer ? color : "dimgrey"; + }, { fireImmediately: true }); + // TODO:glr fix + // tab.element[0].style.borderTopRightRadius = "8px"; + // tab.element[0].children[1].appendChild(toggle); + // tab._disposers.layerDisposer = reaction(() => + // ({ layer: tab.DashDoc.activeLayer, color: this.tabColor }), + // ({ layer, color }) => toggle.style.background = !layer ? color : "dimgrey", { fireImmediately: true }); } // shifts the focus to this tab when another tab is dragged over it tab.element[0].onmouseenter = (e: MouseEvent) => { @@ -103,13 +146,11 @@ export class TabDocView extends React.Component<TabDocViewProps> { tab.setActive(true); } }; - const dragBtnDown = (e: React.PointerEvent) => { - setupMoveUpEvents(this, e, e => !e.defaultPrevented && DragManager.StartDocumentDrag([dragHdl], new DragManager.DocumentDragData([doc], doc.dropAction as dropActionType), e.clientX, e.clientY), returnFalse, emptyFunction); - }; + // select the tab document when the tab is directly clicked and activate the tab whenver the tab document is selected titleEle.onpointerdown = action((e: any) => { - if (e.target.className !== "lm_close_tab") { + if (e.target.className !== "lm_iconWrap") { if (this.view) SelectionManager.SelectView(this.view, false); else this._activated = true; if (Date.now() - titleEle.lastClick < 1000) titleEle.select(); @@ -123,25 +164,25 @@ export class TabDocView extends React.Component<TabDocViewProps> { const toggle = tab.element[0].children[1].children[0] as HTMLInputElement; selected && tab.contentItem !== tab.header.parent.getActiveContentItem() && UndoManager.RunInBatch(() => tab.header.parent.setActiveContentItem(tab.contentItem), "tab switch"); - toggle.style.fontWeight = selected ? "bold" : ""; - toggle.style.textTransform = selected ? "uppercase" : ""; + // toggle.style.fontWeight = selected ? "bold" : ""; + // toggle.style.textTransform = selected ? "uppercase" : ""; })); //attach the selection doc buttons menu to the drag handle const stack = tab.contentItem.parent; - const dragHdl = document.createElement("div"); - dragHdl.className = "lm_drag_tab"; + const moreInfoDrag = document.createElement("div"); + moreInfoDrag.className = "lm_iconWrap"; tab._disposers.buttonDisposer = reaction(() => this.view, view => - view && [ReactDOM.render(<span className="tabDocView-drag" onPointerDown={dragBtnDown}><CollectionDockingViewMenu views={() => [view]} Stack={stack} /></span>, dragHdl), tab._disposers.buttonDisposer?.()], + view && [ReactDOM.render(<span><CollectionDockingViewMenu views={() => [view]} Stack={stack} /></span>, moreInfoDrag), tab._disposers.buttonDisposer?.()], { fireImmediately: true }); - tab.reactComponents = [dragHdl]; - tab.closeElement.before(dragHdl); + // tab.reactComponents = [moreInfoDrag]; + // tab.element[0].children[3].before(moreInfoDrag); // highlight the tab when the tab document is brushed in any part of the UI tab._disposers.reactionDisposer = reaction(() => ({ title: doc.title, degree: Doc.IsBrushedDegree(doc) }), ({ title, degree }) => { titleEle.value = title; - titleEle.style.padding = degree ? 0 : 2; - titleEle.style.border = `${["gray", "gray", "gray"][degree]} ${["none", "dashed", "solid"][degree]} 2px`; + // titleEle.style.padding = degree ? 0 : 2; + // titleEle.style.border = `${["gray", "gray", "gray"][degree]} ${["none", "dashed", "solid"][degree]} 2px`; }, { fireImmediately: true }); // clean up the tab when it is closed @@ -221,9 +262,9 @@ export class TabDocView extends React.Component<TabDocViewProps> { })).observe(this.props.glContainer._element[0]); this.props.glContainer.layoutManager.on("activeContentItemChanged", this.onActiveContentItemChanged); this.props.glContainer.tab?.isActive && this.onActiveContentItemChanged(undefined); - this._tabReaction = reaction(() => ({ selected: this.active(), title: this.tab?.titleElement[0] }), - ({ selected, title }) => title && (title.style.backgroundColor = selected ? "white" : ""), - { fireImmediately: true }); + // this._tabReaction = reaction(() => ({ selected: this.active(), title: this.tab?.titleElement[0] }), + // ({ selected, title }) => title && (title.style.backgroundColor = selected ? "white" : ""), + // { fireImmediately: true }); } componentWillUnmount() { @@ -243,10 +284,10 @@ export class TabDocView extends React.Component<TabDocViewProps> { } // adds a tab to the layout based on the locaiton parameter which can be: - // close[:{left,right,top,bottom}] - e.g., "close" will close the tab, "close:left" will close the left tab, + // close[:{left,right,top,bottom}] - e.g., "close" will close the tab, "close:left" will close the left tab, // add[:{left,right,top,bottom}] - e.g., "add" will add a tab to the current stack, "add:right" will add a tab on the right - // replace[:{left,right,top,bottom,<any string>}] - e.g., "replace" will replace the current stack contents, - // "replace:right" - will replace the stack on the right named "right" if it exists, or create a stack on the right with that name, + // replace[:{left,right,top,bottom,<any string>}] - e.g., "replace" will replace the current stack contents, + // "replace:right" - will replace the stack on the right named "right" if it exists, or create a stack on the right with that name, // "replace:monkeys" - will replace any tab that has the label 'monkeys', or a tab with that label will be created by default on the right // inPlace - will add the document to any collection along the path from the document to the docking view that has a field isInPlaceContainer. if none is found, inPlace adds a tab to current stack addDocTab = (doc: Doc, location: string) => { @@ -460,4 +501,4 @@ export class TabMinimapView extends React.Component<TabMinimapViewProps> { </div> </div>; } -}
\ No newline at end of file +} |