Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Structure width fix #752

Merged
merged 1 commit into from
May 27, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/editor/codemirror/structure-highlighting/theme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export const baseTheme = EditorView.baseTheme({
position: "absolute",
top: 0,
height: "100%",
width: "100%",
// Width is set in code.
zIndex: -1,
},
".cm-cs--block, .cm-cs--indent": {
Expand Down
54 changes: 39 additions & 15 deletions src/editor/codemirror/structure-highlighting/view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,35 @@ const grammarInfo = {
]),
};

interface Measure {
blocks: VisualBlock[];
class Measure {
constructor(
readonly width: number,
readonly left: number,
readonly blocks: VisualBlock[]
) {}
eq(other: Measure) {
if (this.width !== other.width) {
return false;
}
if (this.left !== other.left) {
return false;
}
const blocksChanged =
other.blocks.length !== this.blocks.length ||
other.blocks.some((b, i) => !b.eq(this.blocks[i]));
if (blocksChanged) {
return false;
}
return true;
}
}

export const codeStructureView = (option: "full" | "simple") =>
ViewPlugin.fromClass(
class {
measureReq: { read: () => Measure; write: (value: Measure) => void };
overlayLayer: HTMLElement;
blocks: VisualBlock[] = [];
lastMeasure: Measure = new Measure(0, 0, []);

constructor(readonly view: EditorView) {
this.measureReq = {
Expand All @@ -59,6 +78,12 @@ export const codeStructureView = (option: "full" | "simple") =>
const view = this.view;
const { state } = view;

const contentDOMRect = view.contentDOM.getBoundingClientRect();
// The gutter is awkward as its position fixed in the scroller.
const gutterWidth =
view.scrollDOM.firstElementChild!.getBoundingClientRect().width;
const width = contentDOMRect.width;

let cursorFound = false;

const positionsForNode = (
Expand All @@ -67,11 +92,8 @@ export const codeStructureView = (option: "full" | "simple") =>
end: number,
depth: number,
body: boolean
) => {
): Positions | undefined => {
const diagnostics = state.field(lintState, false)?.diagnostics;
const leftEdge =
view.contentDOM.getBoundingClientRect().left -
view.scrollDOM.getBoundingClientRect().left;
const indentWidth =
state.facet(indentUnit).length * view.defaultCharacterWidth;

Expand Down Expand Up @@ -106,7 +128,7 @@ export const codeStructureView = (option: "full" | "simple") =>
const bottom = bottomLine.bottom;
const height = bottom - top;
const leftIndent = depth * indentWidth;
const left = leftEdge + leftIndent;
const left = leftIndent;
const mainCursor = state.selection.main.head;
const cursorActive =
!cursorFound &&
Expand Down Expand Up @@ -170,6 +192,7 @@ export const codeStructureView = (option: "full" | "simple") =>
blocks.push(
new VisualBlock(
bodyPullBack,
width,
parentPositions,
bodyPositions
)
Expand All @@ -191,15 +214,16 @@ export const codeStructureView = (option: "full" | "simple") =>
},
});
}
return { blocks: blocks.reverse() };
return new Measure(width, gutterWidth, blocks.reverse());
}

drawBlocks({ blocks }: Measure) {
const blocksChanged =
blocks.length !== this.blocks.length ||
blocks.some((b, i) => !b.eq(this.blocks[i]));
if (blocksChanged) {
this.blocks = blocks;
drawBlocks(measure: Measure) {
if (!measure.eq(this.lastMeasure)) {
this.lastMeasure = measure;
const { blocks, left, width } = measure;

this.overlayLayer.style.width = width + "px";
this.overlayLayer.style.left = left + "px";

// Should be able to adjust old elements here if it's a performance win.
this.overlayLayer.textContent = "";
Expand Down
11 changes: 8 additions & 3 deletions src/editor/codemirror/structure-highlighting/visual-block.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export class Positions {
export class VisualBlock {
constructor(
readonly bodyPullBack: boolean,
readonly width: number,
readonly parent?: Positions,
readonly body?: Positions
) {}
Expand Down Expand Up @@ -73,7 +74,7 @@ export class VisualBlock {
parent.style.left = this.parent.left + "px";
parent.style.top = this.parent.top + "px";
parent.style.height = this.parent.height + "px";
parent.style.width = `calc(100% - ${this.parent.left}px)`;
parent.style.width = this.width - this.parent.left + "px";
}

// Optionally allows nested compound statements some breathing space
Expand All @@ -82,7 +83,7 @@ export class VisualBlock {
body.style.left = this.body.left - bodyPullBack + "px";
body.style.top = this.body.top + "px";
body.style.height = this.body.height + "px";
body.style.width = `calc(100% - ${this.body.left - bodyPullBack}px)`;
body.style.width = this.width - this.body.left + bodyPullBack + "px";
}

if (this.parent && parent && this.body && body && indent) {
Expand All @@ -95,7 +96,11 @@ export class VisualBlock {
}

eq(other: VisualBlock) {
return equals(this.body, other.body) && equals(this.parent, other.parent);
return (
equals(this.body, other.body) &&
equals(this.parent, other.parent) &&
this.width === other.width
);
}
}

Expand Down