Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Moder.Core/App.axaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ private static HostApplicationBuilder CreateHostBuilder()
var settings = new HostApplicationBuilderSettings
{
Args = Environment.GetCommandLineArgs(),
ApplicationName = "Moder"
ApplicationName = "Moder",
};

#if DEBUG
Expand All @@ -141,6 +141,7 @@ private static HostApplicationBuilder CreateHostBuilder()
builder.Services.AddViewSingleton<SideBarControlView, SideBarControlViewModel>();
builder.Services.AddViewSingleton<WorkSpaceControlView, WorkSpaceControlViewModel>();
builder.Services.AddViewTransient<CharacterEditorControlView, CharacterEditorControlViewModel>();
builder.Services.AddViewTransient<FocusTreeEditorControlView, FoucsTreeEditorControlViewModel>();
builder.Services.AddViewTransient<AppSettingsView, AppSettingsViewModel>();
builder.Services.AddViewSingleton<StatusBarControlView, StatusBarControlViewModel>();
builder.Services.AddTransient<TraitSelectionWindowViewModel>();
Expand Down
138 changes: 138 additions & 0 deletions Moder.Core/Graph/Controls/FocusTreeImage.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
using System.Diagnostics;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Data;
using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.Media;
using Avalonia.Skia;
using Avalonia.Threading;
using Moder.Core.Graph.Data;
using Moder.Core.Graph.Drawer;
using Moder.Core.Graph.DrawHelper;
using SkiaSharp;

namespace Moder.Core.Graph.Controls;

public class FocusTreeImage : Control
{
public FocusTree? FocusTree { get; set; }
private bool DoDragGraph { get; set; }
private Point DragStartPoint { get; set; }
private SKColor SkForeColor { get; set; } = SKColors.White;
private SKColor SkBackColor { get; set; } = SKColors.SkyBlue;

public bool ShowEmptyGrid
{
get => GetValue(ShowEmptyGridProperty);
set => SetValue(ShowEmptyGridProperty, value);
}
public static readonly StyledProperty<bool> ShowEmptyGridProperty = AvaloniaProperty.Register<
FocusTreeImage,
bool
>(nameof(ShowEmptyGrid), false, false, BindingMode.TwoWay);

public Color ForeColor
{
get => GetValue(ForeColorProperty);
set => SetValue(ForeColorProperty, value);
}
public static readonly StyledProperty<Color> ForeColorProperty = AvaloniaProperty.Register<
FocusTreeImage,
Color
>(nameof(ForeColor), Colors.White);

public Color BackColor
{
get => GetValue(BackColorProperty);
set => SetValue(BackColorProperty, value);
}
public static readonly StyledProperty<Color> BackColorProperty = AvaloniaProperty.Register<
FocusTreeImage,
Color
>(nameof(BackColor), Colors.SkyBlue);

protected override void OnPointerPressed(PointerPressedEventArgs e)
{
base.OnPointerPressed(e);
DoDragGraph = true;
var position = e.GetPosition(this);
DragStartPoint = position;
}

protected override void OnPointerReleased(PointerReleasedEventArgs e)
{
base.OnPointerReleased(e);
DoDragGraph = false;
}

protected override void OnPointerExited(PointerEventArgs e)
{
base.OnPointerExited(e);
if (FocusTree != null)
{
GridTransform.SetSelectPoint(FocusTree, null);
}
}

protected override void OnPointerMoved(PointerEventArgs e)
{
base.OnPointerMoved(e);
if (FocusTree == null)
{
return;
}
var position = e.GetPosition(this);
GridTransform.SetSelectPoint(FocusTree, position);
if (DoDragGraph)
{
var offset = position - DragStartPoint;
DragStartPoint = position;
GridTransform.OffsetOrigin(FocusTree, offset.ToSKPoint());
}
else
{
// GridData.SelectPoint = position.ToSKPoint();
// TODO: for test
var cell = new Cell();
cell.SetRealPoint(FocusTree, position.ToSKPoint());
Debug.WriteLine(cell);
// InvalidateVisual();
// GridDrawer.DrawSelect(Bounds.Size, BackColor, e.Location);
}
}

protected override void OnPointerWheelChanged(PointerWheelEventArgs e)
{
base.OnPointerWheelChanged(e);
if (FocusTree == null)
{
return;
}
var position = e.GetPosition(this);
var rect = new Rect(Bounds.Size);
var diffInWidth = position.X - rect.Width / 2;
var diffInHeight = position.Y - rect.Height / 2;
var dX = diffInWidth / CellData.EdgeLength * rect.Width / 200;
var dY = diffInHeight / CellData.EdgeLength * rect.Height / 200;
CellData.EdgeLength += (int)Math.Round(e.Delta.Y / 10 * Math.Max(rect.Width, rect.Height) / 200);
GridTransform.OffsetOrigin(FocusTree, new SKPoint((float)dX, (float)dY));
}

public override void Render(DrawingContext context)
{
base.Render(context);
if (FocusTree is null)
{
return;
}
using var drawer = new FocusTreeDrawer(
new Rect(Bounds.Size),
ForeColor.ToSKColor(),
BackColor.ToSKColor(),
FocusTree
);
context.Custom(drawer);
Dispatcher.UIThread.Post(InvalidateVisual, DispatcherPriority.Background);
}
}
27 changes: 27 additions & 0 deletions Moder.Core/Graph/Data/FocusNode.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using Avalonia;
using Avalonia.Media;
using Moder.Core.Graph.Tools;

namespace Moder.Core.Graph.Data;

public class FocusNode : IRosterItem<PixelPoint>
{
public PixelPoint Site { get; set; }

public PixelPoint Signature => Site;
public NodeType Type { get; set; }

public static NodeColorSelector Colors { get; } = new();

public Color Color => Colors[Type];
public static FocusNode Default { get; } = new();

public FocusNode(PixelPoint site, NodeType type)
{
Site = site;
Type = type;
}

public FocusNode()
: this(new PixelPoint(), NodeType.None) { }
}
47 changes: 47 additions & 0 deletions Moder.Core/Graph/Data/FocusTree.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
using Avalonia;
using Moder.Core.Graph.Tools;

namespace Moder.Core.Graph.Data;

public sealed class FocusTree
{
public Roster<PixelPoint, FocusNode> FocusNodes { get; set; } = [];

public PixelSize Size { get; set; }

public int Width => Size.Width;

public int Height => Size.Height;

public FocusNode this[PixelPoint site]
{
get
{
if (FocusNodes.TryGetValue(site, out var sourceLand))
{
return sourceLand;
}
return new FocusNode(site, NodeType.None);
}
}

public PixelPoint SetPointWithin(PixelPoint point)
{
return SetPointWithin(point, Size);
}

private static PixelPoint SetPointWithin(PixelPoint point, PixelSize range)
{
var x = point.X % range.Width;
if (x < 0)
{
x += range.Width;
}
var y = point.Y % range.Height;
if (y < 0)
{
y += range.Height;
}
return new(x, y);
}
}
19 changes: 19 additions & 0 deletions Moder.Core/Graph/Data/NodeColorSelector.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using Avalonia.Media;

namespace Moder.Core.Graph.Data;

public class NodeColorSelector
{
public Color this[NodeType type] => ColorCollection[type];

public void SetColor(NodeType type, string colorName)
{
if (Color.TryParse(colorName, out var color))
{
ColorCollection[type] = color;
}
}

private Dictionary<NodeType, Color> ColorCollection { get; set; } =
new() { [NodeType.None] = Colors.White, [NodeType.Normal] = Colors.DarkSlateGray };
}
7 changes: 7 additions & 0 deletions Moder.Core/Graph/Data/NodeType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace Moder.Core.Graph.Data;

public enum NodeType : byte
{
None,
Normal,
}
Loading