diff --git a/Client/Graph.py b/Client/Graph.py index 2c57325..4f87c73 100644 --- a/Client/Graph.py +++ b/Client/Graph.py @@ -220,8 +220,11 @@ class Layout: # Directories go down the heading colours by depth (h1 Mauve, h2 Blue, ...), # starting again after Red. Files are White. DepthColours = ["Mauve", "Blue", "Green", "Yellow", "Peach", "Red"] -ShrinkPerDepth = 0.8 # with GraphShrinkByDepth, each level's directory dots are this much smaller -SmallestDirectory = 3 # ...but never smaller than a file's dot +# With GraphShrinkByDepth, directory dots shrink in even steps from their +# 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: @@ -370,17 +373,22 @@ class GraphView(ft.Container): self.Status.value = "Nothing to show here." self.Status.update() 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 - self.Depths = np.array([(len(Node["Id"].split("/")) if Node["Id"] else 0) - Base for Node in self.Layout.Nodes]) - self.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)] + Depths = np.array([(len(Node["Id"].split("/")) if Node["Id"] else 0) - Base for Node in Settling.Nodes]) + Colours = [(DirectoryColour(int(Depth)) if self.ColourByDepth else Palette.Mauve) if Node["IsDirectory"] + 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.update() # 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): - self.Layout.Tick() + Settling.Tick() if Generation != self.Generation or self.Closed: return self._Draw() @@ -403,7 +411,8 @@ class GraphView(ft.Container): Degree = np.sqrt(self.Layout.Degree) DirectoryRadius = 5 + Degree * 1.6 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) def _Label(self, Number: int, Colour: str) -> cv.Text: diff --git a/Frontend/src/Components/GraphPane.jsx b/Frontend/src/Components/GraphPane.jsx index b518c12..948b548 100644 --- a/Frontend/src/Components/GraphPane.jsx +++ b/Frontend/src/Components/GraphPane.jsx @@ -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 // Directories by depth, like the headings: h1 Purple, h2 Blue, ... const DepthRoles = ["Purple", "Blue", "Green", "Yellow", "Orange", "Red"]; -const ShrinkPerDepth = 0.8; // with ShrinkByDepth, each level's directory dots are this much smaller -const SmallestDirectory = 3; // ...but never smaller than a file's dot +// With ShrinkByDepth, directory dots shrink in even steps from their 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. +const ShrinkDepth = 5; +const FileDotRadius = 3.8; function ReadRole(Name) { return getComputedStyle(document.documentElement).getPropertyValue(`--${Name}`).trim(); @@ -206,7 +209,8 @@ export default function GraphPane({ } Node.Colour = ColourByDepth ? DepthColours[Depth % DepthColours.length] : Colours.Directory; 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. diff --git a/README.md b/README.md index 0a90c7e..9acf9dd 100644 --- a/README.md +++ b/README.md @@ -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 round in Settings > Graph. That's also where directories can be hidden (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`). Shortcuts: Enter opens, Backspace goes up, F2 renames, Delete deletes,