Skip to content

Commit 8e9a5bd

Browse files
authored
Merge pull request #60 from Supheria/focus_tree
2 parents 9d028d2 + 6e84686 commit 8e9a5bd

25 files changed

+997
-15
lines changed

Moder.Core/App.axaml.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ private static HostApplicationBuilder CreateHostBuilder()
119119
var settings = new HostApplicationBuilderSettings
120120
{
121121
Args = Environment.GetCommandLineArgs(),
122-
ApplicationName = "Moder"
122+
ApplicationName = "Moder",
123123
};
124124

125125
#if DEBUG
@@ -141,6 +141,7 @@ private static HostApplicationBuilder CreateHostBuilder()
141141
builder.Services.AddViewSingleton<SideBarControlView, SideBarControlViewModel>();
142142
builder.Services.AddViewSingleton<WorkSpaceControlView, WorkSpaceControlViewModel>();
143143
builder.Services.AddViewTransient<CharacterEditorControlView, CharacterEditorControlViewModel>();
144+
builder.Services.AddViewTransient<FocusTreeEditorControlView, FoucsTreeEditorControlViewModel>();
144145
builder.Services.AddViewTransient<AppSettingsView, AppSettingsViewModel>();
145146
builder.Services.AddViewSingleton<StatusBarControlView, StatusBarControlViewModel>();
146147
builder.Services.AddTransient<TraitSelectionWindowViewModel>();
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
using System.Diagnostics;
2+
using Avalonia;
3+
using Avalonia.Controls;
4+
using Avalonia.Data;
5+
using Avalonia.Input;
6+
using Avalonia.Interactivity;
7+
using Avalonia.Media;
8+
using Avalonia.Skia;
9+
using Avalonia.Threading;
10+
using Moder.Core.Graph.Data;
11+
using Moder.Core.Graph.Drawer;
12+
using Moder.Core.Graph.DrawHelper;
13+
using SkiaSharp;
14+
15+
namespace Moder.Core.Graph.Controls;
16+
17+
public class FocusTreeImage : Control
18+
{
19+
public FocusTree? FocusTree { get; set; }
20+
private bool DoDragGraph { get; set; }
21+
private Point DragStartPoint { get; set; }
22+
private SKColor SkForeColor { get; set; } = SKColors.White;
23+
private SKColor SkBackColor { get; set; } = SKColors.SkyBlue;
24+
25+
public bool ShowEmptyGrid
26+
{
27+
get => GetValue(ShowEmptyGridProperty);
28+
set => SetValue(ShowEmptyGridProperty, value);
29+
}
30+
public static readonly StyledProperty<bool> ShowEmptyGridProperty = AvaloniaProperty.Register<
31+
FocusTreeImage,
32+
bool
33+
>(nameof(ShowEmptyGrid), false, false, BindingMode.TwoWay);
34+
35+
public Color ForeColor
36+
{
37+
get => GetValue(ForeColorProperty);
38+
set => SetValue(ForeColorProperty, value);
39+
}
40+
public static readonly StyledProperty<Color> ForeColorProperty = AvaloniaProperty.Register<
41+
FocusTreeImage,
42+
Color
43+
>(nameof(ForeColor), Colors.White);
44+
45+
public Color BackColor
46+
{
47+
get => GetValue(BackColorProperty);
48+
set => SetValue(BackColorProperty, value);
49+
}
50+
public static readonly StyledProperty<Color> BackColorProperty = AvaloniaProperty.Register<
51+
FocusTreeImage,
52+
Color
53+
>(nameof(BackColor), Colors.SkyBlue);
54+
55+
protected override void OnPointerPressed(PointerPressedEventArgs e)
56+
{
57+
base.OnPointerPressed(e);
58+
DoDragGraph = true;
59+
var position = e.GetPosition(this);
60+
DragStartPoint = position;
61+
}
62+
63+
protected override void OnPointerReleased(PointerReleasedEventArgs e)
64+
{
65+
base.OnPointerReleased(e);
66+
DoDragGraph = false;
67+
}
68+
69+
protected override void OnPointerExited(PointerEventArgs e)
70+
{
71+
base.OnPointerExited(e);
72+
if (FocusTree != null)
73+
{
74+
GridTransform.SetSelectPoint(FocusTree, null);
75+
}
76+
}
77+
78+
protected override void OnPointerMoved(PointerEventArgs e)
79+
{
80+
base.OnPointerMoved(e);
81+
if (FocusTree == null)
82+
{
83+
return;
84+
}
85+
var position = e.GetPosition(this);
86+
GridTransform.SetSelectPoint(FocusTree, position);
87+
if (DoDragGraph)
88+
{
89+
var offset = position - DragStartPoint;
90+
DragStartPoint = position;
91+
GridTransform.OffsetOrigin(FocusTree, offset.ToSKPoint());
92+
}
93+
else
94+
{
95+
// GridData.SelectPoint = position.ToSKPoint();
96+
// TODO: for test
97+
var cell = new Cell();
98+
cell.SetRealPoint(FocusTree, position.ToSKPoint());
99+
Debug.WriteLine(cell);
100+
// InvalidateVisual();
101+
// GridDrawer.DrawSelect(Bounds.Size, BackColor, e.Location);
102+
}
103+
}
104+
105+
protected override void OnPointerWheelChanged(PointerWheelEventArgs e)
106+
{
107+
base.OnPointerWheelChanged(e);
108+
if (FocusTree == null)
109+
{
110+
return;
111+
}
112+
var position = e.GetPosition(this);
113+
var rect = new Rect(Bounds.Size);
114+
var diffInWidth = position.X - rect.Width / 2;
115+
var diffInHeight = position.Y - rect.Height / 2;
116+
var dX = diffInWidth / CellData.EdgeLength * rect.Width / 200;
117+
var dY = diffInHeight / CellData.EdgeLength * rect.Height / 200;
118+
CellData.EdgeLength += (int)Math.Round(e.Delta.Y / 10 * Math.Max(rect.Width, rect.Height) / 200);
119+
GridTransform.OffsetOrigin(FocusTree, new SKPoint((float)dX, (float)dY));
120+
}
121+
122+
public override void Render(DrawingContext context)
123+
{
124+
base.Render(context);
125+
if (FocusTree is null)
126+
{
127+
return;
128+
}
129+
using var drawer = new FocusTreeDrawer(
130+
new Rect(Bounds.Size),
131+
ForeColor.ToSKColor(),
132+
BackColor.ToSKColor(),
133+
FocusTree
134+
);
135+
context.Custom(drawer);
136+
Dispatcher.UIThread.Post(InvalidateVisual, DispatcherPriority.Background);
137+
}
138+
}

Moder.Core/Graph/Data/FocusNode.cs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
using Avalonia;
2+
using Avalonia.Media;
3+
using Moder.Core.Graph.Tools;
4+
5+
namespace Moder.Core.Graph.Data;
6+
7+
public class FocusNode : IRosterItem<PixelPoint>
8+
{
9+
public PixelPoint Site { get; set; }
10+
11+
public PixelPoint Signature => Site;
12+
public NodeType Type { get; set; }
13+
14+
public static NodeColorSelector Colors { get; } = new();
15+
16+
public Color Color => Colors[Type];
17+
public static FocusNode Default { get; } = new();
18+
19+
public FocusNode(PixelPoint site, NodeType type)
20+
{
21+
Site = site;
22+
Type = type;
23+
}
24+
25+
public FocusNode()
26+
: this(new PixelPoint(), NodeType.None) { }
27+
}

Moder.Core/Graph/Data/FocusTree.cs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
using Avalonia;
2+
using Moder.Core.Graph.Tools;
3+
4+
namespace Moder.Core.Graph.Data;
5+
6+
public sealed class FocusTree
7+
{
8+
public Roster<PixelPoint, FocusNode> FocusNodes { get; set; } = [];
9+
10+
public PixelSize Size { get; set; }
11+
12+
public int Width => Size.Width;
13+
14+
public int Height => Size.Height;
15+
16+
public FocusNode this[PixelPoint site]
17+
{
18+
get
19+
{
20+
if (FocusNodes.TryGetValue(site, out var sourceLand))
21+
{
22+
return sourceLand;
23+
}
24+
return new FocusNode(site, NodeType.None);
25+
}
26+
}
27+
28+
public PixelPoint SetPointWithin(PixelPoint point)
29+
{
30+
return SetPointWithin(point, Size);
31+
}
32+
33+
private static PixelPoint SetPointWithin(PixelPoint point, PixelSize range)
34+
{
35+
var x = point.X % range.Width;
36+
if (x < 0)
37+
{
38+
x += range.Width;
39+
}
40+
var y = point.Y % range.Height;
41+
if (y < 0)
42+
{
43+
y += range.Height;
44+
}
45+
return new(x, y);
46+
}
47+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
using Avalonia.Media;
2+
3+
namespace Moder.Core.Graph.Data;
4+
5+
public class NodeColorSelector
6+
{
7+
public Color this[NodeType type] => ColorCollection[type];
8+
9+
public void SetColor(NodeType type, string colorName)
10+
{
11+
if (Color.TryParse(colorName, out var color))
12+
{
13+
ColorCollection[type] = color;
14+
}
15+
}
16+
17+
private Dictionary<NodeType, Color> ColorCollection { get; set; } =
18+
new() { [NodeType.None] = Colors.White, [NodeType.Normal] = Colors.DarkSlateGray };
19+
}

Moder.Core/Graph/Data/NodeType.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
namespace Moder.Core.Graph.Data;
2+
3+
public enum NodeType : byte
4+
{
5+
None,
6+
Normal,
7+
}

0 commit comments

Comments
 (0)