mirror of
https://git.srhtnin.garden/sarah/SaraView.git
synced 2026-10-14 18:38:11 +02:00
Graph: options for depth colours and dot sizes
This commit is contained in:
1 parent
cc7d624a57
commit
0372a73dd2
8 files changed
+78
-11
No files matched your search
@@ -53,6 +53,10 @@ DefaultSettings: dict[str, Any] = {
|
||||
# other one opens a dot).
|
||||
"GraphShowDirectories": True,
|
||||
"GraphPanButton": "Right",
|
||||
# Directory dots: heading colours by depth (off: all Purple), and smaller
|
||||
# the deeper they are.
|
||||
"GraphColourByDepth": True,
|
||||
"GraphShrinkByDepth": False,
|
||||
}
|
||||
|
||||
DefaultThemesDirectory = ApplicationDirectory / "DefaultThemes"
|
||||
|
||||
@@ -172,6 +172,10 @@ class AppConfig:
|
||||
# other one opens a dot).
|
||||
GraphShowDirectories: bool = True
|
||||
GraphPanButton: str = "Right"
|
||||
# Directory dots: heading colours by depth (off: all Mauve), and smaller
|
||||
# the deeper they are.
|
||||
GraphColourByDepth: bool = True
|
||||
GraphShrinkByDepth: bool = False
|
||||
# Double-click on a file: True opens it in SaraView's own viewer, False
|
||||
# hands it to the system's default program. The menu always offers the other.
|
||||
OpenFilesInApp: bool = True
|
||||
|
||||
+15
-4
@@ -220,6 +220,8 @@ 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
|
||||
|
||||
|
||||
def DirectoryColour(Depth: int) -> str:
|
||||
@@ -251,6 +253,9 @@ class GraphView(ft.Container):
|
||||
self.PanButton = "Left" if TheApp.Config.GraphPanButton == "Left" else "Right"
|
||||
self.OpenButton = "Right" if self.PanButton == "Left" else "Left"
|
||||
self.ShowDirectories = TheApp.Config.GraphShowDirectories
|
||||
self.ColourByDepth = TheApp.Config.GraphColourByDepth
|
||||
self.ShrinkByDepth = TheApp.Config.GraphShrinkByDepth
|
||||
self.Depths = np.zeros(0) # each dot's depth below the graph's directory
|
||||
self.Layout: Optional[Layout] = None
|
||||
self.ScopePath = ""
|
||||
self.Size = (800.0, 600.0)
|
||||
@@ -276,7 +281,9 @@ class GraphView(ft.Container):
|
||||
)
|
||||
self.CountText = ft.Text("", size=12, color=Palette.Overlay0)
|
||||
LegendItems: list[ft.Control] = []
|
||||
if self.ShowDirectories:
|
||||
if self.ShowDirectories and not self.ColourByDepth:
|
||||
LegendItems += [ft.Text("●", color=Palette.Mauve), ft.Text("Directory", size=12, color=Palette.Overlay0)]
|
||||
elif self.ShowDirectories:
|
||||
LegendItems += [ft.Text("●", color=Palette.Mauve), ft.Text("●", color=Palette.Blue), ft.Text("●", color=Palette.Green),
|
||||
ft.Text("Directories by depth", size=12, color=Palette.Overlay0)]
|
||||
LegendItems += [ft.Text("●", color=Palette.White), ft.Text("File", size=12, color=Palette.Overlay0),
|
||||
@@ -365,8 +372,9 @@ class GraphView(ft.Container):
|
||||
return
|
||||
self.Layout = Layout(Graph)
|
||||
Base = len(Path.split("/")) if Path else 0
|
||||
self.Colours = [DirectoryColour((len(Node["Id"].split("/")) if Node["Id"] else 0) - Base) if Node["IsDirectory"]
|
||||
else Palette.White for Node in self.Layout.Nodes]
|
||||
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)]
|
||||
self.StatusBox.visible = False
|
||||
self.StatusBox.update()
|
||||
# Settle in steps, drawing as it goes, like the web view's animation.
|
||||
@@ -393,7 +401,10 @@ class GraphView(ft.Container):
|
||||
Zoom = math.sqrt(Scale)
|
||||
IsDirectory = np.array([Node["IsDirectory"] for Node in self.Layout.Nodes])
|
||||
Degree = np.sqrt(self.Layout.Degree)
|
||||
self.Radius = np.maximum(2, np.where(IsDirectory, 5 + Degree * 1.6, 3 + Degree * 0.8) * Zoom)
|
||||
DirectoryRadius = 5 + Degree * 1.6
|
||||
if self.ShrinkByDepth:
|
||||
DirectoryRadius = np.maximum(SmallestDirectory, DirectoryRadius * ShrinkPerDepth ** self.Depths)
|
||||
self.Radius = np.maximum(2, np.where(IsDirectory, DirectoryRadius, 3 + Degree * 0.8) * Zoom)
|
||||
|
||||
def _Label(self, Number: int, Colour: str) -> cv.Text:
|
||||
X, Y = self.Screen[Number]
|
||||
|
||||
+9
-1
@@ -120,6 +120,10 @@ def ShowSettingsDialog(TheApp: App, OnSaved: Callable[[bool], None], StartCatego
|
||||
# Graph.
|
||||
GraphDirectoriesSwitch = ft.Switch(label="Show directories (off: only files and the links between them)",
|
||||
value=Config.GraphShowDirectories)
|
||||
ColourByDepthSwitch = ft.Switch(label="Colour directories by depth (off: all purple)",
|
||||
value=Config.GraphColourByDepth)
|
||||
ShrinkByDepthSwitch = ft.Switch(label="Smaller directory dots the deeper they are",
|
||||
value=Config.GraphShrinkByDepth)
|
||||
PanButtonPicker = ft.RadioGroup(
|
||||
ft.Column([
|
||||
ft.Radio(value="Right", label="Right (left-click opens a dot)"),
|
||||
@@ -217,9 +221,11 @@ def ShowSettingsDialog(TheApp: App, OnSaved: Callable[[bool], None], StartCatego
|
||||
OwnAppearance,
|
||||
], spacing=12, scroll=ft.ScrollMode.AUTO),
|
||||
"Graph": ft.Column([
|
||||
_Note("The graph view (Ctrl+G): directories in the heading colours by depth, files white, "
|
||||
_Note("The graph view (Ctrl+G): directories purple or in the heading colours by depth, files white, "
|
||||
"joined to their directory and to the files that reference them."),
|
||||
GraphDirectoriesSwitch,
|
||||
ColourByDepthSwitch,
|
||||
ShrinkByDepthSwitch,
|
||||
ft.Divider(height=1, color=Palette.Surface1),
|
||||
ft.Text("Pan with mouse button"),
|
||||
PanButtonPicker,
|
||||
@@ -261,6 +267,8 @@ def ShowSettingsDialog(TheApp: App, OnSaved: Callable[[bool], None], StartCatego
|
||||
Config.ShowFilesInTree = TreeFilesSwitch.value
|
||||
Config.MarkdownEditing = MarkdownEditingPicker.value or Config.MarkdownEditing
|
||||
Config.GraphShowDirectories = GraphDirectoriesSwitch.value
|
||||
Config.GraphColourByDepth = ColourByDepthSwitch.value
|
||||
Config.GraphShrinkByDepth = ShrinkByDepthSwitch.value
|
||||
Config.GraphPanButton = PanButtonPicker.value or Config.GraphPanButton
|
||||
Config.FontSize = _ReadInt(FontSizeField, Config.FontSize, 8, 32)
|
||||
Config.Mode = ModePicker.value or Config.Mode
|
||||
|
||||
@@ -384,6 +384,8 @@ export default function App() {
|
||||
DirectoryPath={CurrentDirectoryPath}
|
||||
ShowDirectories={Settings ? Settings.GraphShowDirectories : true}
|
||||
PanButton={Settings ? Settings.GraphPanButton : "Right"}
|
||||
ColourByDepth={Settings ? Settings.GraphColourByDepth : true}
|
||||
ShrinkByDepth={Settings ? Settings.GraphShrinkByDepth : false}
|
||||
OnOpenNode={HandleOpenGraphNode}
|
||||
OnClose={() => SetIsGraphOpen(false)}
|
||||
/>
|
||||
|
||||
@@ -20,6 +20,8 @@ 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
|
||||
|
||||
function ReadRole(Name) {
|
||||
return getComputedStyle(document.documentElement).getPropertyValue(`--${Name}`).trim();
|
||||
@@ -132,7 +134,16 @@ function Tick(Nodes, Links, Alpha) {
|
||||
}
|
||||
}
|
||||
|
||||
export default function GraphPane({ RootName, DirectoryPath, ShowDirectories, PanButton, OnOpenNode, OnClose }) {
|
||||
export default function GraphPane({
|
||||
RootName,
|
||||
DirectoryPath,
|
||||
ShowDirectories,
|
||||
PanButton,
|
||||
ColourByDepth,
|
||||
ShrinkByDepth,
|
||||
OnOpenNode,
|
||||
OnClose,
|
||||
}) {
|
||||
const [Scope, SetScope] = useState("Root");
|
||||
const [Graph, SetGraph] = useState(null);
|
||||
const [Error, SetError] = useState(null);
|
||||
@@ -189,7 +200,14 @@ export default function GraphPane({ RootName, DirectoryPath, ShowDirectories, Pa
|
||||
const BaseDepth = Graph.Path ? Graph.Path.split("/").length : 0;
|
||||
for (const Node of Nodes) {
|
||||
const Depth = (Node.Id ? Node.Id.split("/").length : 0) - BaseDepth;
|
||||
Node.Colour = Node.IsDirectory ? DepthColours[Depth % DepthColours.length] : Colours.File;
|
||||
if (!Node.IsDirectory) {
|
||||
Node.Colour = Colours.File;
|
||||
continue;
|
||||
}
|
||||
Node.Colour = ColourByDepth ? DepthColours[Depth % DepthColours.length] : Colours.Directory;
|
||||
if (ShrinkByDepth) {
|
||||
Node.Radius = Math.max(SmallestDirectory, Node.Radius * Math.pow(ShrinkPerDepth, Depth));
|
||||
}
|
||||
}
|
||||
// Anything but "Left" (including an old "Middle") pans with Right.
|
||||
const PanNumber = PanButton === "Left" ? 0 : 2;
|
||||
@@ -394,7 +412,7 @@ export default function GraphPane({ RootName, DirectoryPath, ShowDirectories, Pa
|
||||
Canvas.removeEventListener("contextmenu", OnContextMenu);
|
||||
Canvas.removeEventListener("wheel", OnWheel);
|
||||
};
|
||||
}, [Graph, ShowDirectories, PanButton]);
|
||||
}, [Graph, ShowDirectories, PanButton, ColourByDepth, ShrinkByDepth]);
|
||||
|
||||
const FileCount = Graph ? Graph.Nodes.filter((Node) => !Node.IsDirectory).length : 0;
|
||||
const DirectoryCount = Graph ? Graph.Nodes.length - FileCount : 0;
|
||||
@@ -410,7 +428,12 @@ export default function GraphPane({ RootName, DirectoryPath, ShowDirectories, Pa
|
||||
</option>
|
||||
</select>
|
||||
<span className="GraphLegend">
|
||||
{ShowDirectories && (
|
||||
{ShowDirectories && !ColourByDepth && (
|
||||
<>
|
||||
<span className="GraphLegendDirectory">●</span> Directory
|
||||
</>
|
||||
)}
|
||||
{ShowDirectories && ColourByDepth && (
|
||||
<>
|
||||
<span className="GraphLegendDirectory">●</span>
|
||||
<span className="GraphLegendDepth1">●</span>
|
||||
|
||||
@@ -410,6 +410,20 @@ export default function SettingsPanel({
|
||||
OnChange={(Event) => UpdateField("GraphShowDirectories", Event.target.checked)}
|
||||
/>
|
||||
</div>
|
||||
<div className="SettingsRowInline">
|
||||
<label className="SettingsLabel">Colour directories by depth (off: all purple)</label>
|
||||
<Switch
|
||||
Checked={Settings.GraphColourByDepth}
|
||||
OnChange={(Event) => UpdateField("GraphColourByDepth", Event.target.checked)}
|
||||
/>
|
||||
</div>
|
||||
<div className="SettingsRowInline">
|
||||
<label className="SettingsLabel">Smaller directory dots the deeper they are</label>
|
||||
<Switch
|
||||
Checked={Settings.GraphShrinkByDepth}
|
||||
OnChange={(Event) => UpdateField("GraphShrinkByDepth", Event.target.checked)}
|
||||
/>
|
||||
</div>
|
||||
<div className="SettingsRow">
|
||||
<label className="SettingsLabel">Pan with mouse button</label>
|
||||
<select
|
||||
|
||||
@@ -304,8 +304,9 @@ joined to its parent directory and to the files that reference it (Markdown
|
||||
links and images, `[[wiki links]]` and portals). Hover a dot to light up its
|
||||
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, which can also hide directories, leaving only
|
||||
files and the links between them.
|
||||
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.
|
||||
|
||||
Rename takes a `/` to move, like the web view (`../Archive/Notes.md`).
|
||||
Shortcuts: Enter opens, Backspace goes up, F2 renames, Delete deletes,
|
||||
|
||||
Reference in new issue
Block a user