From 82819bbe9412325148848ba118b546019292153a Mon Sep 17 00:00:00 2001 From: sawka Date: Mon, 10 Oct 2022 12:45:57 -0700 Subject: [PATCH] updating selectedline will now scroll the window --- src/main.tsx | 112 +++++++++++++++++++++++++++++++++++++++++++-------- src/model.ts | 6 +++ src/sh2.less | 4 +- src/sh2.ts | 9 +++-- 4 files changed, 108 insertions(+), 23 deletions(-) diff --git a/src/main.tsx b/src/main.tsx index 16c066d1e..817bf0a71 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -1636,12 +1636,11 @@ class LinesView extends React.Component<{sw : ScreenWindow, width : number, line rszObs : any; linesRef : React.RefObject; staticRender : OV = mobx.observable.box(true); - anchorLine : number = 0; - anchorOffset : number = 0; lastOffsetHeight : number = 0; lastOffsetWidth : number = 0; ignoreNextScroll : boolean = false; visibleMap : Map>; // lineid => OV + lastSelectedLine : number = 0; computeAnchorLine_throttled : () => void; computeVisibleMap_debounced : () => void; @@ -1649,8 +1648,6 @@ class LinesView extends React.Component<{sw : ScreenWindow, width : number, line constructor(props) { super(props); this.linesRef = React.createRef(); - this.anchorLine = props.lines[props.lines.length-1].linenum; - this.anchorOffset = 0; this.computeAnchorLine_throttled = throttle(100, this.computeAnchorLine.bind(this), {noLeading: true, noTrailing: false}); this.visibleMap = new Map(); this.computeVisibleMap_debounced = debounce(1000, this.computeVisibleMap.bind(this)); @@ -1668,16 +1665,17 @@ class LinesView extends React.Component<{sw : ScreenWindow, width : number, line } computeAnchorLine() : void { + let {sw} = this.props; let linesElem = this.linesRef.current; if (linesElem == null) { - this.anchorLine = null; - this.anchorOffset = 0; + sw.anchorLine = null; + sw.anchorOffset = 0; return; } let lineElemArr = linesElem.querySelectorAll(".line"); if (lineElemArr == null) { - this.anchorLine = null; - this.anchorOffset = 0; + sw.anchorLine = null; + sw.anchorOffset = 0; return; } let scrollTop = linesElem.scrollTop; @@ -1694,8 +1692,8 @@ class LinesView extends React.Component<{sw : ScreenWindow, width : number, line if (anchorElem == null) { anchorElem = lineElemArr[0]; } - this.anchorLine = parseInt(anchorElem.dataset.linenum); - this.anchorOffset = containerBottom - (anchorElem.offsetTop + anchorElem.offsetHeight); + sw.anchorLine = parseInt(anchorElem.dataset.linenum); + sw.anchorOffset = containerBottom - (anchorElem.offsetTop + anchorElem.offsetHeight); // console.log("anchor", this.anchorLine, this.anchorOffset); } @@ -1710,7 +1708,6 @@ class LinesView extends React.Component<{sw : ScreenWindow, width : number, line } let containerTop = linesElem.scrollTop - LinesVisiblePadding; let containerBot = linesElem.scrollTop + linesElem.clientHeight + LinesVisiblePadding; - console.log("container", containerTop, containerBot); let newMap = new Map(); for (let i=0; i", newScrollTop); linesElem.scrollTop = newScrollTop; @@ -1765,7 +1763,14 @@ class LinesView extends React.Component<{sw : ScreenWindow, width : number, line } componentDidMount() : void { - this.computeAnchorLine(); + let {sw} = this.props; + if (sw.anchorLine == null) { + this.computeAnchorLine(); + } + else { + this.restoreAnchorOffset("re-mount"); + } + this.lastSelectedLine = sw.selectedLine.get(); let linesElem = this.linesRef.current; if (linesElem != null) { @@ -1781,6 +1786,80 @@ class LinesView extends React.Component<{sw : ScreenWindow, width : number, line })(); } + getLineElem(lineNum : number) : HTMLElement { + let linesElem = this.linesRef.current; + if (linesElem == null) { + return null; + } + let elem = linesElem.querySelector(sprintf(".line[data-linenum=\"%d\"]", lineNum)); + return elem; + } + + getLineViewInfo(lineNum : number) : {height: number, topOffset: number, botOffset: number} { + let linesElem = this.linesRef.current; + if (linesElem == null) { + return null; + } + let lineElem = this.getLineElem(lineNum); + if (lineElem == null) { + return null; + } + let rtn = { + height: lineElem.offsetHeight, + topOffset: 0, + botOffset: 0, + }; + let containerTop = linesElem.scrollTop; + let containerBot = linesElem.scrollTop + linesElem.clientHeight; + let lineTop = lineElem.offsetTop; + let lineBot = lineElem.offsetTop + lineElem.offsetHeight; + if (lineTop < containerTop) { + rtn.topOffset = lineTop - containerTop; + } + else if (lineTop > containerBot) { + rtn.topOffset = lineTop - containerBot; + } + if (lineBot < containerTop) { + rtn.botOffset = lineBot - containerTop; + } + else if (lineBot > containerBot) { + rtn.botOffset = lineBot - containerBot; + } + return rtn; + } + + updateSelectedLine() : void { + let {sw, lines} = this.props; + let linesElem = this.linesRef.current; + if (linesElem == null) { + return null; + } + let newLine = sw.selectedLine.get(); + if (newLine == sw.anchorLine) { + return; + } + let viewInfo = this.getLineViewInfo(newLine); + if (viewInfo == null) { + return; + } + let isFirst = (newLine == lines[0].linenum); + let isLast = (newLine == lines[lines.length-1].linenum); + if (viewInfo.botOffset > 0) { + linesElem.scrollTop = linesElem.scrollTop + viewInfo.botOffset + (isLast ? 10 : 0); + } + else if (viewInfo.topOffset < 0) { + linesElem.scrollTop = linesElem.scrollTop + viewInfo.topOffset + (isFirst ? -10 : 0); + } + } + + componentDidUpdate(prevProps, prevState, snapshot) : void { + let {sw} = this.props; + if (sw.selectedLine.get() != this.lastSelectedLine) { + this.updateSelectedLine(); + this.lastSelectedLine = sw.selectedLine.get(); + } + } + componentWillUnmount() : void { if (this.rszObs != null) { this.rszObs.disconnect(); @@ -1813,6 +1892,7 @@ class LinesView extends React.Component<{sw : ScreenWindow, width : number, line render() { let {sw, width, lines} = this.props; + let selectedLine = sw.selectedLine.get(); // for re-rendering let line : LineType = null; let idx : number = 0; for (let i=0; i; shouldFollow : OV = mobx.observable.box(true); focusType : OV<"input"|"lines"> = mobx.observable.box("input"); + anchorLine : number = null; + anchorOffset : number = 0; // cmdid => TermWrap terms : Record = {}; @@ -281,6 +283,10 @@ class ScreenWindow { this.selectedLine = mobx.observable.box(swdata.selectedline == 0 ? null : swdata.selectedline); this.scrollTop = mobx.observable.box(swdata.scrolltop); this.setScrollTop_debounced = debounce(1000, this.setScrollTop.bind(this)); + if (swdata.selectedline != 0) { + this.anchorLine = swdata.selectedline; + this.anchorOffset = 0; + } } updateSelf(swdata : ScreenWindowType) { diff --git a/src/sh2.less b/src/sh2.less index 72b141a04..8fba66b36 100644 --- a/src/sh2.less +++ b/src/sh2.less @@ -641,9 +641,7 @@ body .xterm .xterm-viewport { flex-direction: column; height: 80vh; overflow-y: scroll; - padding-bottom: 10px; - padding-top: 10px; - padding-right: 0px; + padding: 10px 0 10px 0; flex-grow: 1; position: relative; diff --git a/src/sh2.ts b/src/sh2.ts index e0283dddc..37e57d775 100644 --- a/src/sh2.ts +++ b/src/sh2.ts @@ -15,10 +15,11 @@ let jbmFontNormal = new FontFace("JetBrains Mono", "url('static/fonts/jetbrains- let jbmFont200 = new FontFace("JetBrains Mono", "url('static/fonts/jetbrains-mono-v13-latin-200.woff2')", {style: "normal", weight: "200"}); let jbmFont700 = new FontFace("JetBrains Mono", "url('static/fonts/jetbrains-mono-v13-latin-700.woff2')", {style: "normal", weight: "700"}); let faFont = new FontFace("FontAwesome", "url(static/fonts/fontawesome-webfont-4.7.woff2)", {style: "normal", weight: "normal"}); -document.fonts.add(jbmFontNormal); -document.fonts.add(jbmFont200); -document.fonts.add(jbmFont700); -document.fonts.add(faFont); +let docFonts : any = document.fonts; // work around ts typing issue +docFonts.add(jbmFontNormal); +docFonts.add(jbmFont200); +docFonts.add(jbmFont700); +docFonts.add(faFont); jbmFontNormal.load(); jbmFont200.load(); jbmFont700.load();