Fix graph crash on reload, even out depth sizes

This commit is contained in:
sarah committed 2026-10-09 10:00:15 +02:00
1 parent 0372a73dd2
commit d616361c2f
3 files changed
+27 -13

No files matched your search

+18 -9
View File
@@ -220,8 +220,11 @@ class Layout:
# Directories go down the heading colours by depth (h1 Mauve, h2 Blue, ...), # Directories go down the heading colours by depth (h1 Mauve, h2 Blue, ...),
# starting again after Red. Files are White. # starting again after Red. Files are White.
DepthColours = ["Mauve", "Blue", "Green", "Yellow", "Peach", "Red"] DepthColours = ["Mauve", "Blue", "Green", "Yellow", "Peach", "Red"]
ShrinkPerDepth = 0.8 # with GraphShrinkByDepth, each level's directory dots are this much smaller # With GraphShrinkByDepth, directory dots shrink in even steps from their
SmallestDirectory = 3 # ...but never smaller than a file's dot # usual size to a file dot's size (a file with one link) at this depth (the
# red ones), and stay that size below it.
ShrinkDepth = 5
FileDotRadius = 3.8
def DirectoryColour(Depth: int) -> str: def DirectoryColour(Depth: int) -> str:
@@ -370,17 +373,22 @@ class GraphView(ft.Container):
self.Status.value = "Nothing to show here." self.Status.value = "Nothing to show here."
self.Status.update() self.Status.update()
return return
self.Layout = Layout(Graph) # This thread keeps its own Layout: a Reload meanwhile (the graph
# opening, or the scope changing) clears self.Layout for its own thread.
Settling = Layout(Graph)
Base = len(Path.split("/")) if Path else 0 Base = len(Path.split("/")) if Path else 0
self.Depths = np.array([(len(Node["Id"].split("/")) if Node["Id"] else 0) - Base for Node in self.Layout.Nodes]) Depths = np.array([(len(Node["Id"].split("/")) if Node["Id"] else 0) - Base for Node in Settling.Nodes])
self.Colours = [(DirectoryColour(int(Depth)) if self.ColourByDepth else Palette.Mauve) if Node["IsDirectory"] Colours = [(DirectoryColour(int(Depth)) if self.ColourByDepth else Palette.Mauve) if Node["IsDirectory"]
else Palette.White for Node, Depth in zip(self.Layout.Nodes, self.Depths)] else Palette.White for Node, Depth in zip(Settling.Nodes, Depths)]
if Generation != self.Generation or self.Closed:
return
self.Layout, self.Depths, self.Colours = Settling, Depths, Colours
self.StatusBox.visible = False self.StatusBox.visible = False
self.StatusBox.update() self.StatusBox.update()
# Settle in steps, drawing as it goes, like the web view's animation. # Settle in steps, drawing as it goes, like the web view's animation.
while not self.Layout.Settled: while not Settling.Settled:
for _ in range(TicksPerDraw): for _ in range(TicksPerDraw):
self.Layout.Tick() Settling.Tick()
if Generation != self.Generation or self.Closed: if Generation != self.Generation or self.Closed:
return return
self._Draw() self._Draw()
@@ -403,7 +411,8 @@ class GraphView(ft.Container):
Degree = np.sqrt(self.Layout.Degree) Degree = np.sqrt(self.Layout.Degree)
DirectoryRadius = 5 + Degree * 1.6 DirectoryRadius = 5 + Degree * 1.6
if self.ShrinkByDepth: if self.ShrinkByDepth:
DirectoryRadius = np.maximum(SmallestDirectory, DirectoryRadius * ShrinkPerDepth ** self.Depths) Step = np.minimum(self.Depths, ShrinkDepth) / ShrinkDepth
DirectoryRadius = DirectoryRadius + (FileDotRadius - DirectoryRadius) * Step
self.Radius = np.maximum(2, np.where(IsDirectory, DirectoryRadius, 3 + Degree * 0.8) * Zoom) self.Radius = np.maximum(2, np.where(IsDirectory, DirectoryRadius, 3 + Degree * 0.8) * Zoom)
def _Label(self, Number: int, Colour: str) -> cv.Text: def _Label(self, Number: int, Colour: str) -> cv.Text:
+7 -3
View File
@@ -20,8 +20,11 @@ const LabelZoom = 0.7; // below this, only hovered labels are drawn
const ClickSlop = 4; // pixels a click may wander and still count as a click const ClickSlop = 4; // pixels a click may wander and still count as a click
// Directories by depth, like the headings: h1 Purple, h2 Blue, ... // Directories by depth, like the headings: h1 Purple, h2 Blue, ...
const DepthRoles = ["Purple", "Blue", "Green", "Yellow", "Orange", "Red"]; const DepthRoles = ["Purple", "Blue", "Green", "Yellow", "Orange", "Red"];
const ShrinkPerDepth = 0.8; // with ShrinkByDepth, each level's directory dots are this much smaller // With ShrinkByDepth, directory dots shrink in even steps from their usual
const SmallestDirectory = 3; // ...but never smaller than a file's dot // size to a file dot's size (a file with one link) at this depth (the red
// ones), and stay that size below it.
const ShrinkDepth = 5;
const FileDotRadius = 3.8;
function ReadRole(Name) { function ReadRole(Name) {
return getComputedStyle(document.documentElement).getPropertyValue(`--${Name}`).trim(); return getComputedStyle(document.documentElement).getPropertyValue(`--${Name}`).trim();
@@ -206,7 +209,8 @@ export default function GraphPane({
} }
Node.Colour = ColourByDepth ? DepthColours[Depth % DepthColours.length] : Colours.Directory; Node.Colour = ColourByDepth ? DepthColours[Depth % DepthColours.length] : Colours.Directory;
if (ShrinkByDepth) { if (ShrinkByDepth) {
Node.Radius = Math.max(SmallestDirectory, Node.Radius * Math.pow(ShrinkPerDepth, Depth)); const Step = Math.min(Depth, ShrinkDepth) / ShrinkDepth;
Node.Radius += (FileDotRadius - Node.Radius) * Step;
} }
} }
// Anything but "Left" (including an old "Middle") pans with Right. // Anything but "Left" (including an old "Middle") pans with Right.
+2 -1
View File
@@ -306,7 +306,8 @@ links, scroll to zoom. One mouse button pans and the other opens the dot
you click: right-drag pans and left-click opens by default, or the other way you click: right-drag pans and left-click opens by default, or the other way
round in Settings > Graph. That's also where directories can be hidden round in Settings > Graph. That's also where directories can be hidden
(leaving only files and the links between them), all made purple instead (leaving only files and the links between them), all made purple instead
of coloured by depth, or made smaller the deeper they are. of coloured by depth, or made smaller the deeper they are (down to a
file dot's size at depth 5, the red ones).
Rename takes a `/` to move, like the web view (`../Archive/Notes.md`). Rename takes a `/` to move, like the web view (`../Archive/Notes.md`).
Shortcuts: Enter opens, Backspace goes up, F2 renames, Delete deletes, Shortcuts: Enter opens, Backspace goes up, F2 renames, Delete deletes,