Files
2026-07-13 13:13:17 +08:00

127 lines
4.4 KiB
C#

using System.Numerics;
using ImGuiNET;
namespace SilkWindows.Implementations.FileManager.ItemDrawers;
// todo: child class (DirectoryDrawer) being referenced in the base class is UGLY
public abstract class FileSystemDrawer
{
private protected readonly IFileManager FileManager;
private protected FileSystemDrawer(IFileManager fileManager, DirectoryDrawer? parent)
{
FileManager = fileManager;
ParentDirectoryDrawer = parent;
}
internal abstract DirectoryDrawer RootDirectory { get; }
public abstract bool IsReadOnly { get; }
internal abstract bool IsDirectory { get; }
internal abstract string DisplayName { get; }
internal abstract string Path { get; }
internal DirectoryDrawer? ParentDirectoryDrawer { get; }
protected abstract void DrawTooltipContents(ImFonts fonts);
protected internal abstract FileSystemInfo FileSystemInfo { get; }
protected virtual ImGuiHoveredFlags HoverFlags => ImGuiHoveredFlags.None;
protected internal bool Expanded { get; set; }
protected bool IsHovered() => ImGui.IsItemHovered(HoverFlags);
const ImGuiHoveredFlags FileDragHoverFlags = ImGuiHoveredFlags.DelayNone
| ImGuiHoveredFlags.AllowWhenBlockedByActiveItem;
protected bool HoveredByFileDrag(ImGuiHoveredFlags flags = FileDragHoverFlags) =>
FileManager.IsDraggingPaths && ImGui.IsItemHovered(flags);
protected abstract void DrawSelectable(ImFonts fonts, bool isSelected);
protected abstract void CompleteDraw(ImFonts fonts, bool hovered, bool isSelected);
public void Draw(ImFonts fonts, bool forceDeselected = false)
{
bool isSelected = FileManager.IsSelected(this);
var fileInfo = FileSystemInfo;
fileInfo.Refresh();
var missing = !fileInfo.Exists;
if (missing)
{
ImGui.PushStyleColor(ImGuiCol.Text, new Vector4(1f, 0.2f, 0.2f, 1f));
}
DrawSelectable(fonts, isSelected && !forceDeselected);
var hovered = IsHovered();
var hoveredByFileDrag = HoveredByFileDrag();
if (hovered)
{
if (ImGui.IsMouseClicked(ImGuiMouseButton.Left))
{
FileManager.ItemClicked(this);
}
if (ImGui.IsMouseDragging(ImGuiMouseButton.Left, lock_threshold: 2f)) // lock threshold is required distance of dragging (in pixels maybe??)
{
FileManager.BeginDragOn(this);
}
if (FileManager.HasDroppedFiles)
{
FileManager.ConsumeDroppedFiles(this);
}
if (ImGui.IsMouseDoubleClicked(0))
{
OnDoubleClicked();
}
}
if (hoveredByFileDrag && FileManager.IsDropTarget(this, out var targetDirDrawer))
{
var imTheTarget = targetDirDrawer == this;
if(imTheTarget)
ImGui.Indent();
ImGui.SeparatorText($"Drop in \"{targetDirDrawer.DisplayName}\"");
if(imTheTarget)
ImGui.Unindent();
}
else if (!missing)
{
if (ImGui.BeginPopupContextItem())
{
DrawContextMenuContents(fonts);
ImGui.EndPopup();
}
// check for root directory drawer since we treat it specially. it should probably be its own class but here we are for now
// the root directory has its own tooltip that this would mess up
if (!FileManager.IsDraggingPaths && hovered && this is not DirectoryDrawer { IsRoot: true })
{
if (ImGui.BeginTooltip())
{
DrawTooltipContents(fonts);
ImGui.EndTooltip();
}
}
}
if (missing)
{
ImGui.PopStyleColor();
ParentDirectoryDrawer?.MarkNeedsRescan();
}
else
{
CompleteDraw(fonts, hovered, isSelected);
}
}
protected abstract void DrawContextMenuContents(ImFonts fonts);
protected abstract void OnDoubleClicked();
}