put static values for font size, re-render entire window when font size changes

This commit is contained in:
sawka 2023-02-25 23:16:58 -08:00
parent 5e68c6b2f7
commit c66bee7657
5 changed files with 73 additions and 34 deletions

View File

@ -12,13 +12,15 @@ class ImageRendererModel {
htmlImg : any;
termOpts : TermOptsType;
dataBuf : PtyDataBuffer;
fontSize : number;
constructor(imgDivElem : any, context : RendererContext, termOpts : TermOptsType, isDone : boolean) {
constructor(imgDivElem : any, context : RendererContext, termOpts : TermOptsType, isDone : boolean, fontSize : number) {
this.dataBuf = new PtyDataBuffer();
this.htmlImgDivElem = imgDivElem;
this.termOpts = termOpts;
this.context = context;
this.isDone = mobx.observable.box(isDone, {name: "isDone"});
this.fontSize = fontSize;
this.reload(0);
}
@ -39,8 +41,8 @@ class ImageRendererModel {
let blob = new Blob([this.dataBuf.getData()], {type: "image/jpeg"});
this.htmlImg = new Image();
this.htmlImg.src = URL.createObjectURL(blob);
this.htmlImg.style.maxHeight = termHeightFromRows(this.termOpts.rows) + "px";
this.htmlImg.style.maxWidth = termWidthFromCols(this.termOpts.cols) + "px";
this.htmlImg.style.maxHeight = termHeightFromRows(this.termOpts.rows, this.fontSize) + "px";
this.htmlImg.style.maxWidth = termWidthFromCols(this.termOpts.cols, this.fontSize) + "px";
this.htmlImgDivElem.replaceChildren(this.htmlImg);
}

View File

@ -483,7 +483,7 @@ class TerminalRenderer extends React.Component<{sw : ScreenWindow, line : LineTy
}, {name: "computed-isFocused"}).get();
let cmd = GlobalModel.getCmd(line); // will not be null
let usedRows = sw.getUsedRows(line, cmd, width);
let termHeight = termHeightFromRows(usedRows);
let termHeight = termHeightFromRows(usedRows, GlobalModel.termFontSize.get());
let termLoaded = this.termLoaded.get();
return (
<div ref={this.elemRef} key="term-wrap" className={cn("terminal-wrapper", {"focus": isFocused}, {"cmd-done": !cmd.isRunning()}, {"zero-height": (termHeight == 0)}, {"collapsed": collapsed})}>
@ -707,12 +707,11 @@ class LineCmd extends React.Component<{sw : ScreenWindow, line : LineType, width
// header is 36px tall, padding+border = 6px
// zero-terminal is 0px
// terminal-wrapper overhead is 11px (margin/padding)
// each terminal line 16px
// inner-height, if zero-lines => 42
// else: 53+(lines*16)
// else: 53+(lines*lineheight)
let height = 42; // height of zero height terminal
if (usedRows > 0) {
height = 53 + termHeightFromRows(usedRows);
height = 53 + termHeightFromRows(usedRows, GlobalModel.termFontSize.get());
}
return (
<div className={mainDivCn} id={this.getLineDomId()} ref={this.lineRef} data-lineid={line.lineid} data-linenum={line.linenum} data-windowid={line.windowid} style={{height: height}}>
@ -1396,6 +1395,7 @@ class InfoRemoteShow extends React.Component<{}, {}> {
</>
);
}
let termFontSize = GlobalModel.termFontSize.get();
return (
<>
<div key="info" className="info-remote">
@ -1441,14 +1441,14 @@ class InfoRemoteShow extends React.Component<{}, {}> {
</div>
</If>
</div>
<div key="term" className={cn("terminal-wrapper", {"focus": isTermFocused}, (remote != null ? "status-" + remote.status : null))} style={{display: (ptyRemoteId == null ? "none" : "block"), width: termWidthFromCols(RemotePtyCols)}}>
<div key="term" className={cn("terminal-wrapper", {"focus": isTermFocused}, (remote != null ? "status-" + remote.status : null))} style={{display: (ptyRemoteId == null ? "none" : "block"), width: termWidthFromCols(RemotePtyCols, termFontSize)}}>
<If condition={!isTermFocused}>
<div key="termblock" className="term-block" onClick={this.clickTermBlock}></div>
</If>
<If condition={inputModel.showNoInputMsg.get()}>
<div key="termtag" className="term-tag">input is only allowed while status is 'connecting'</div>
</If>
<div key="terminal" className="terminal-connectelem" id="term-remote" data-remoteid={ptyRemoteId} style={{height: termHeightFromRows(RemotePtyRows)}}></div>
<div key="terminal" className="terminal-connectelem" id="term-remote" data-remoteid={ptyRemoteId} style={{height: termHeightFromRows(RemotePtyRows, termFontSize)}}></div>
</div>
</>
);
@ -2604,8 +2604,8 @@ class ScreenWindowView extends React.Component<{sw : ScreenWindow}, {}> {
this.width.set(width);
this.height.set(height);
let {sw} = this.props;
let cols = windowWidthToCols(width);
let rows = windowHeightToRows(height);
let cols = windowWidthToCols(width, GlobalModel.termFontSize.get());
let rows = windowHeightToRows(height, GlobalModel.termFontSize.get());
if (sw == null || cols == 0 || rows == 0) {
return;
}
@ -2720,9 +2720,11 @@ class ScreenView extends React.Component<{screen : Screen}, {}> {
</div>
);
}
let fontSize = GlobalModel.termFontSize.get();
let swKey = sw.windowId + "-fs" + fontSize;
return (
<div className="screen-view" data-screenid={sw.screenId}>
<ScreenWindowView key={sw.windowId} sw={sw}/>
<ScreenWindowView key={swKey} sw={sw}/>
</div>
);
}

View File

@ -8,11 +8,9 @@ import {v4 as uuidv4} from "uuid";
import type {SessionDataType, WindowDataType, LineType, RemoteType, HistoryItem, RemoteInstanceType, RemotePtrType, CmdDataType, FeCmdPacketType, TermOptsType, RemoteStateType, ScreenDataType, ScreenWindowType, ScreenOptsType, LayoutType, PtyDataUpdateType, ModelUpdateType, UpdateMessage, InfoType, CmdLineUpdateType, UIContextType, HistoryInfoType, HistoryQueryOpts, FeInputPacketType, TermWinSize, RemoteInputPacketType, FeStateType, ContextMenuOpts, RendererContext, RendererModel, PtyDataType, BookmarkType} from "./types";
import {WSControl} from "./ws";
import {ImageRendererModel} from "./imagerenderer";
import {measureText} from "./textmeasure";
import {measureText, getMonoFontSize} from "./textmeasure";
var GlobalUser = "sawka";
const DefaultCellWidth = 7.203125;
const DefaultCellHeight = 16;
const RemotePtyRows = 8; // also in main.tsx
const RemotePtyCols = 80;
const MinTermCols = 10;
@ -21,6 +19,9 @@ const ProdServerEndpoint = "http://localhost:1619";
const ProdServerWsEndpoint = "ws://localhost:1623";
const DevServerEndpoint = "http://localhost:8090";
const DevServerWsEndpoint = "ws://localhost:8091";
const DefaultTermFontSize = 12;
const MinFontSize = 8;
const MaxFontSize = 15;
// @ts-ignore
const VERSION = __PROMPT_VERSION__;
@ -34,26 +35,30 @@ type SWLinePtr = {
sw : ScreenWindow,
};
function windowWidthToCols(width : number) : number {
let cols = Math.trunc((width - 50) / DefaultCellWidth) - 1;
function windowWidthToCols(width : number, fontSize : number) : number {
let dr = getMonoFontSize(fontSize);
let cols = Math.trunc((width - 50) / dr.width) - 1;
cols = boundInt(cols, MinTermCols, MaxTermCols);
return cols;
}
function windowHeightToRows(height : number) : number {
let rows = Math.floor((height - 80)/DefaultCellHeight) - 1;
function windowHeightToRows(height : number, fontSize : number) : number {
let dr = getMonoFontSize(fontSize);
let rows = Math.floor((height - 80) / dr.height) - 1;
if (rows <= 0) {
rows = 1;
}
return rows;
}
function termWidthFromCols(cols : number) : number {
return Math.ceil(DefaultCellWidth*cols) + 15;
function termWidthFromCols(cols : number, fontSize : number) : number {
let dr = getMonoFontSize(fontSize);
return Math.ceil(dr.width*cols) + 15;
}
function termHeightFromRows(rows : number) : number {
return Math.ceil(DefaultCellHeight*rows);
function termHeightFromRows(rows : number, fontSize : number) : number {
let dr = getMonoFontSize(fontSize);
return Math.ceil(dr.height*rows);
}
function cmdStatusIsRunning(status : string) : boolean {
@ -559,7 +564,7 @@ class ScreenWindow {
loadImageRenderer(imageDivElem : any, line : LineType, cmd : Cmd) : ImageRendererModel {
let cmdId = cmd.cmdId;
let context = {sessionId: this.sessionId, screenId: this.screenId, windowId: this.windowId, cmdId: cmdId, lineId : line.lineid, lineNum: line.linenum};
let imageModel = new ImageRendererModel(imageDivElem, context, cmd.getTermOpts(), !cmd.isRunning());
let imageModel = new ImageRendererModel(imageDivElem, context, cmd.getTermOpts(), !cmd.isRunning(), GlobalModel.termFontSize.get());
this.renderers[cmdId] = imageModel;
return imageModel;
}
@ -571,7 +576,7 @@ class ScreenWindow {
console.log("term-wrap already exists for", this.screenId, this.windowId, cmdId);
return;
}
let cols = windowWidthToCols(width);
let cols = windowWidthToCols(width, GlobalModel.termFontSize.get());
let usedRows = GlobalModel.getTUR(this.sessionId, cmdId, cols);
if (line.contentheight != null && line.contentheight != -1) {
usedRows = line.contentheight;
@ -586,6 +591,7 @@ class ScreenWindow {
focusHandler: (focus : boolean) => this.setTermFocus(line.linenum, focus),
isRunning: cmd.isRunning(),
customKeyHandler: this.termCustomKeyHandler.bind(this),
fontSize: GlobalModel.termFontSize.get(),
});
this.renderers[cmdId] = termWrap;
if ((this.focusType.get() == "cmd" || this.focusType.get() == "cmd-fg") && this.selectedLine.get() == line.linenum) {
@ -612,7 +618,7 @@ class ScreenWindow {
}
let termWrap = this.getRenderer(cmd.cmdId);
if (termWrap == null) {
let cols = windowWidthToCols(width);
let cols = windowWidthToCols(width, GlobalModel.termFontSize.get());
let usedRows = GlobalModel.getTUR(this.sessionId, cmd.cmdId, cols);
if (usedRows != null) {
return usedRows;
@ -1535,6 +1541,7 @@ class InputModel {
keyHandler: (e, termWrap) => { this.termKeyHandler(remoteId, e, termWrap)},
focusHandler: this.setRemoteTermWrapFocus.bind(this),
isRunning: true,
fontSize: GlobalModel.termFontSize.get(),
});
}
}
@ -1827,6 +1834,7 @@ class Model {
authKey : string;
isDev : boolean;
activeMainView : OV<"session" | "history" | "bookmarks"> = mobx.observable.box("session", {name: "activeMainView"});
termFontSize : OV<number> = mobx.observable.box(DefaultTermFontSize, {name: "termFontSize"});
inputModel : InputModel;
bookmarksModel : BookmarksModel;
@ -1863,6 +1871,18 @@ class Model {
return ProdServerEndpoint;
}
setTermFontSize(fontSize : number) {
if (fontSize < MinFontSize) {
fontSize = MinFontSize;
}
if (fontSize > MaxFontSize) {
fontSize = MaxFontSize;
}
mobx.action(() => {
this.termFontSize.set(fontSize);
})();
}
getBaseWsHostPort() : string {
if (this.isDev) {
return DevServerWsEndpoint;
@ -2749,12 +2769,11 @@ let GlobalCommandRunner : CommandRunner = null;
if ((window as any).GlobalModel == null) {
(window as any).GlobalModel = new Model();
(window as any).GlobalCommandRunner = new CommandRunner();
(window as any).getMonoFontSize = getMonoFontSize;
}
GlobalModel = (window as any).GlobalModel;
GlobalCommandRunner = (window as any).GlobalCommandRunner;
window.measureText = measureText;
export {Model, Session, Window, GlobalModel, GlobalCommandRunner, Cmd, Screen, ScreenWindow, riToRPtr, windowWidthToCols, windowHeightToRows, termWidthFromCols, termHeightFromRows, getPtyData, getRemotePtyData};

View File

@ -29,6 +29,7 @@ type TermWrapOpts = {
dataHandler? : (data : string, termWrap : TermWrap) => void,
isRunning : boolean,
customKeyHandler? : (event : any, termWrap : TermWrap) => boolean,
fontSize: number,
};
// cmd-instance
@ -48,6 +49,7 @@ class TermWrap {
termSize : TermWinSize;
focusHandler : (focus : boolean) => void;
isRunning : boolean;
fontSize : number;
constructor(elem : Element, opts : TermWrapOpts) {
opts = opts ?? ({} as any);
@ -57,6 +59,7 @@ class TermWrap {
this.winSize = opts.winSize;
this.focusHandler = opts.focusHandler;
this.isRunning = opts.isRunning;
this.fontSize = opts.fontSize;
if (this.flexRows) {
this.atRowMax = false;
this.usedRows = mobx.observable.box(opts.usedRows ?? (opts.isRunning ? 1 : 0), {name: "term-usedrows"});
@ -69,13 +72,13 @@ class TermWrap {
this.termSize = {rows: opts.termOpts.rows, cols: opts.termOpts.cols};
}
else {
let cols = windowWidthToCols(opts.winSize.width);
let cols = windowWidthToCols(opts.winSize.width, opts.fontSize);
this.termSize = {rows: opts.termOpts.rows, cols: cols};
}
let theme = {
foreground: "#d3d7cf",
};
this.terminal = new Terminal({rows: this.termSize.rows, cols: this.termSize.cols, fontSize: 12, fontFamily: "JetBrains Mono", theme: theme});
this.terminal = new Terminal({rows: this.termSize.rows, cols: this.termSize.cols, fontSize: opts.fontSize, fontFamily: "JetBrains Mono", theme: theme});
this.terminal._core._inputHandler._parser.setErrorHandler((state) => {
this.numParseErrors++;
return state;
@ -238,8 +241,8 @@ class TermWrap {
}
resizeWindow(size : WindowSize) : void {
let cols = windowWidthToCols(size.width);
let rows = windowHeightToRows(size.height);
let cols = windowWidthToCols(size.width, this.fontSize);
let rows = windowHeightToRows(size.height, this.fontSize);
this.resize({rows, cols});
}

View File

@ -1,4 +1,17 @@
let canvasElem = document.createElement("canvas");
let MonoFontSizes : {height : number, width : number}[] = [];
MonoFontSizes[8] = {height: 11, width: 4.797};
MonoFontSizes[9] = {height: 12, width: 5.398};
MonoFontSizes[10] = {height: 13, width: 6};
MonoFontSizes[11] = {height: 15, width: 6.602};
MonoFontSizes[12] = {height: 16, width: 7.203};
MonoFontSizes[13] = {height: 18, width: 7.797};
MonoFontSizes[14] = {height: 19, width: 8.398};
MonoFontSizes[15] = {height: 20, width: 9};
function getMonoFontSize(fontSize : number) : {height : number, width : number} {
return MonoFontSizes[fontSize];
}
function measureText(text : string, textOpts? : {pre? : boolean, mono? : boolean, fontSize? : number|string}) : DOMRect {
if (textOpts == null) {
@ -28,4 +41,4 @@ function measureText(text : string, textOpts? : {pre? : boolean, mono? : boolean
return measureDiv.getBoundingClientRect()
}
export {measureText};
export {measureText, getMonoFontSize};