diff --git a/src/Ursa.Themes.Semi/Controls/Anchor.axaml b/src/Ursa.Themes.Semi/Controls/Anchor.axaml
index 098f292..108f37b 100644
--- a/src/Ursa.Themes.Semi/Controls/Anchor.axaml
+++ b/src/Ursa.Themes.Semi/Controls/Anchor.axaml
@@ -6,11 +6,14 @@
xmlns:u="https://irihi.tech/ursa">
+
+
@@ -21,23 +24,30 @@
+
-
+
+
-
-
+
@@ -53,8 +63,24 @@
-
+
+
+
+
+
diff --git a/src/Ursa.Themes.Semi/Themes/Shared/Anchor.axaml b/src/Ursa.Themes.Semi/Themes/Shared/Anchor.axaml
index 3f22c22..cffb17e 100644
--- a/src/Ursa.Themes.Semi/Themes/Shared/Anchor.axaml
+++ b/src/Ursa.Themes.Semi/Themes/Shared/Anchor.axaml
@@ -1,4 +1,6 @@
12
+ 20
+ 16
diff --git a/src/Ursa/Controls/Anchor/Anchor.cs b/src/Ursa/Controls/Anchor/Anchor.cs
index 7a75b93..2ecf018 100644
--- a/src/Ursa/Controls/Anchor/Anchor.cs
+++ b/src/Ursa/Controls/Anchor/Anchor.cs
@@ -11,15 +11,27 @@ using Ursa.Common;
namespace Ursa.Controls;
///
-/// Some basic assumptions: This should not be a regular SelectingItemsControl, because it does not support multiple selections.
-/// Selection should not be exposed to the user, it is only used to determine which item is currently selected.
-/// The manipulation of container selection should be simplified.
-/// Scroll event of TargetContainer also triggers selection change.
+/// Some basic assumptions: This should not be a regular SelectingItemsControl, because it does not support multiple
+/// selections.
+/// Selection should not be exposed to the user, it is only used to determine which item is currently selected.
+/// The manipulation of container selection should be simplified.
+/// Scroll event of TargetContainer also triggers selection change.
///
-public class Anchor: ItemsControl
+public class Anchor : ItemsControl
{
- public static readonly StyledProperty TargetContainerProperty = AvaloniaProperty.Register(
- nameof(TargetContainer));
+ public static readonly StyledProperty TargetContainerProperty =
+ AvaloniaProperty.Register(
+ nameof(TargetContainer));
+
+ public static readonly AttachedProperty AnchorIdProperty =
+ AvaloniaProperty.RegisterAttached("AnchorId");
+
+ private CancellationTokenSource _cts = new();
+
+ private List<(string, double)> _positions = [];
+ private bool _scrollingFromSelection;
+
+ private AnchorItem? _selectedContainer;
public ScrollViewer? TargetContainer
{
@@ -27,12 +39,16 @@ public class Anchor: ItemsControl
set => SetValue(TargetContainerProperty, value);
}
- public static readonly AttachedProperty AnchorIdProperty =
- AvaloniaProperty.RegisterAttached("AnchorId");
+ public static void SetAnchorId(Visual obj, string? value)
+ {
+ obj.SetValue(AnchorIdProperty, value);
+ }
+
+ public static string? GetAnchorId(Visual obj)
+ {
+ return obj.GetValue(AnchorIdProperty);
+ }
- public static void SetAnchorId(Visual obj, string? value) => obj.SetValue(AnchorIdProperty, value);
- public static string? GetAnchorId(Visual obj) => obj.GetValue(AnchorIdProperty);
-
protected override bool NeedsContainerOverride(object? item, int index, out object? recycleKey)
{
@@ -45,80 +61,65 @@ public class Anchor: ItemsControl
return i;
}
- private CancellationTokenSource _cts = new();
- private bool _scrollingFromSelection;
-
private void ScrollToAnchor(Visual target)
{
if (TargetContainer is null)
return;
-
+
var targetPosition = target.TranslatePoint(new Point(0, 0), TargetContainer);
if (targetPosition.HasValue)
{
var from = TargetContainer.Offset.Y;
var to = TargetContainer.Offset.Y + targetPosition.Value.Y;
- if(to > TargetContainer.Extent.Height - TargetContainer.Bounds.Height)
- {
+ if (to > TargetContainer.Extent.Height - TargetContainer.Bounds.Height)
to = TargetContainer.Extent.Height - TargetContainer.Bounds.Height;
- }
if (from == to) return;
- Animation animation = new Animation()
+ var animation = new Animation
{
Duration = TimeSpan.FromSeconds(0.3),
Easing = new QuadraticEaseOut(),
Children =
{
- new KeyFrame(){
- Setters =
- {
- new Setter(ScrollViewer.OffsetProperty, new Vector(0, from)),
- },
+ new KeyFrame
+ {
+ Setters = { new Setter(ScrollViewer.OffsetProperty, new Vector(0, from)) },
Cue = new Cue(0.0)
},
- new KeyFrame()
+ new KeyFrame
{
- Setters =
- {
- new Setter(ScrollViewer.OffsetProperty, new Vector(0, to))
- },
+ Setters = { new Setter(ScrollViewer.OffsetProperty, new Vector(0, to)) },
Cue = new Cue(1.0)
}
-
}
};
_cts.Cancel();
_cts = new CancellationTokenSource();
- var token = _cts.Token;
+ var token = _cts.Token;
token.Register(_ => _scrollingFromSelection = false, null);
_scrollingFromSelection = true;
animation.RunAsync(TargetContainer, token).ContinueWith(_ => _scrollingFromSelection = false, token);
}
}
-
+
public void InvalidatePositions()
{
InvalidateAnchorPositions();
MarkSelectedContainerByPosition();
}
- private List<(string, double)> _positions = [];
-
internal void InvalidateAnchorPositions()
{
if (TargetContainer is null) return;
var items = TargetContainer.GetVisualDescendants().Where(a => GetAnchorId(a) is not null);
- List<(string, double)> positions = new List<(string, double)>();
+ var positions = new List<(string, double)>();
foreach (var item in items)
{
var anchorId = GetAnchorId(item);
if (anchorId is null) continue;
var position = item.TransformToVisual(TargetContainer)?.M32 + TargetContainer.Offset.Y;
- if (position.HasValue)
- {
- positions.Add((anchorId, position.Value));
- }
+ if (position.HasValue) positions.Add((anchorId, position.Value));
}
+
positions.Sort((a, b) => a.Item2.CompareTo(b.Item2));
_positions = positions;
}
@@ -126,14 +127,11 @@ public class Anchor: ItemsControl
protected override void OnLoaded(RoutedEventArgs e)
{
base.OnLoaded(e);
- var target = this.TargetContainer;
+ var target = TargetContainer;
if (target is null) return;
TargetContainer?.AddHandler(ScrollViewer.ScrollChangedEvent, OnScrollChanged);
TargetContainer?.AddHandler(LoadedEvent, OnTargetContainerLoaded);
- if (TargetContainer?.IsLoaded == true)
- {
- InvalidateAnchorPositions();
- }
+ if (TargetContainer?.IsLoaded == true) InvalidateAnchorPositions();
MarkSelectedContainerByPosition();
}
@@ -150,24 +148,24 @@ public class Anchor: ItemsControl
if (source is null) return;
MarkSelectedContainer(source);
var target = TargetContainer?.GetVisualDescendants()
- .FirstOrDefault(a => Anchor.GetAnchorId(a) == source.AnchorId);
+ .FirstOrDefault(a => GetAnchorId(a) == source.AnchorId);
if (target is null) return;
ScrollToAnchor(target);
}
///
- /// This method is used to expose the protected CreateContainerForItemOverride method to the AnchorItem class.
+ /// This method is used to expose the protected CreateContainerForItemOverride method to the AnchorItem class.
///
internal Control CreateContainerForItemOverride_INTERNAL(object? item, int index, object? recycleKey)
{
return CreateContainerForItemOverride(item, index, recycleKey);
}
-
+
internal bool NeedsContainerOverride_INTERNAL(object? item, int index, out object? recycleKey)
{
return NeedsContainerOverride(item, index, out recycleKey);
}
-
+
internal void PrepareContainerForItemOverride_INTERNAL(Control container, object? item, int index)
{
PrepareContainerForItemOverride(container, item, index);
@@ -178,8 +176,6 @@ public class Anchor: ItemsControl
ContainerForItemPreparedOverride(container, item, index);
}
- private AnchorItem? _selectedContainer;
-
internal void MarkSelectedContainer(AnchorItem? item)
{
var oldValue = _selectedContainer;
@@ -197,7 +193,7 @@ public class Anchor: ItemsControl
var topAnchorId = _positions.LastOrDefault(a => a.Item2 <= top).Item1;
if (topAnchorId is null) return;
var item = this.GetVisualDescendants().OfType()
- .FirstOrDefault(a => a.AnchorId == topAnchorId);
+ .FirstOrDefault(a => a.AnchorId == topAnchorId);
if (item is null) return;
MarkSelectedContainer(item);
}
diff --git a/src/Ursa/Controls/Anchor/AnchorItem.cs b/src/Ursa/Controls/Anchor/AnchorItem.cs
index 6986d6f..17f6917 100644
--- a/src/Ursa/Controls/Anchor/AnchorItem.cs
+++ b/src/Ursa/Controls/Anchor/AnchorItem.cs
@@ -31,7 +31,7 @@ public class AnchorItem : HeaderedItemsControl, ISelectable
{
SelectableMixin.Attach(IsSelectedProperty);
PressedMixin.Attach();
- ItemsPanelProperty.OverrideDefaultValue(DefaultPanel);
+ ItemsPanelProperty.OverrideDefaultValue(DefaultPanel);
}
public int Level