Vibe search feature
This commit is contained in:
@@ -27,4 +27,6 @@ public sealed class MapNode
|
||||
}
|
||||
|
||||
public bool IsSelected { get; set; }
|
||||
|
||||
public bool IsHighlighted { get; set; }
|
||||
}
|
||||
|
||||
@@ -58,11 +58,18 @@ public sealed class MapDrawable : IDrawable
|
||||
canvas.FillColor = ColorForKind(node.Doc.Kind);
|
||||
canvas.FillCircle(center, radius);
|
||||
|
||||
if (node.IsHighlighted)
|
||||
{
|
||||
canvas.StrokeColor = Color.FromArgb("#FFD700");
|
||||
canvas.StrokeSize = 3;
|
||||
canvas.DrawCircle(center, radius + 4);
|
||||
}
|
||||
|
||||
if (node.IsSelected)
|
||||
{
|
||||
canvas.StrokeColor = Colors.White;
|
||||
canvas.StrokeSize = 3;
|
||||
canvas.DrawCircle(center, radius + 6);
|
||||
canvas.DrawCircle(center, node.IsHighlighted ? radius + 8 : radius + 6);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,11 @@
|
||||
<Button Text="+" WidthRequest="44" Clicked="OnZoomInClicked" />
|
||||
<Button Text="−" WidthRequest="44" Clicked="OnZoomOutClicked" />
|
||||
<Button Text="Reset View" Clicked="OnResetViewClicked" />
|
||||
<SearchBar x:Name="SearchControl"
|
||||
Placeholder="Search systems..."
|
||||
WidthRequest="220"
|
||||
TextChanged="OnSearchTextChanged"
|
||||
SearchButtonPressed="OnSearchButtonPressed" />
|
||||
<Label x:Name="StatusLabel"
|
||||
Text="No folder loaded."
|
||||
VerticalOptions="Center"
|
||||
|
||||
@@ -82,6 +82,84 @@ public partial class MapEditorPage : ContentPage
|
||||
FitView();
|
||||
}
|
||||
|
||||
private void CenterOnNode(MapNode node)
|
||||
{
|
||||
var width = MapView.Width;
|
||||
var height = MapView.Height;
|
||||
if (width > 0 && height > 0)
|
||||
{
|
||||
_drawable.OffsetX = width / 2 - node.X * _drawable.Scale;
|
||||
_drawable.OffsetY = height / 2 - node.Y * _drawable.Scale;
|
||||
MapView.Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
// ----- search -----
|
||||
|
||||
private void OnSearchTextChanged(object? sender, TextChangedEventArgs e) => ApplySearch(e.NewTextValue);
|
||||
|
||||
private void OnSearchButtonPressed(object? sender, EventArgs e)
|
||||
{
|
||||
ApplySearch(SearchControl.Text);
|
||||
FocusFirstMatch();
|
||||
}
|
||||
|
||||
private void ApplySearch(string? query)
|
||||
{
|
||||
var trimmed = query?.Trim();
|
||||
if (string.IsNullOrEmpty(trimmed))
|
||||
{
|
||||
foreach (var node in _nodes)
|
||||
{
|
||||
node.IsHighlighted = false;
|
||||
}
|
||||
|
||||
if (_folder is not null)
|
||||
{
|
||||
StatusLabel.Text = $"{_nodes.Count} systems loaded from {_folder}.";
|
||||
}
|
||||
else
|
||||
{
|
||||
StatusLabel.Text = "No folder loaded.";
|
||||
}
|
||||
|
||||
MapView.Invalidate();
|
||||
return;
|
||||
}
|
||||
|
||||
var matchCount = 0;
|
||||
foreach (var node in _nodes)
|
||||
{
|
||||
var isMatch = node.Doc.Name.Contains(trimmed, StringComparison.OrdinalIgnoreCase);
|
||||
node.IsHighlighted = isMatch;
|
||||
if (isMatch)
|
||||
{
|
||||
matchCount++;
|
||||
}
|
||||
}
|
||||
|
||||
if (matchCount == 0)
|
||||
{
|
||||
StatusLabel.Text = $"No systems matching '{trimmed}'.";
|
||||
}
|
||||
else
|
||||
{
|
||||
StatusLabel.Text = $"Found {matchCount} matching system{(matchCount == 1 ? string.Empty : "s")}.";
|
||||
}
|
||||
|
||||
MapView.Invalidate();
|
||||
}
|
||||
|
||||
private void FocusFirstMatch()
|
||||
{
|
||||
var match = _nodes.FirstOrDefault(static n => n.IsHighlighted);
|
||||
if (match is not null)
|
||||
{
|
||||
Select(match);
|
||||
CenterOnNode(match);
|
||||
}
|
||||
}
|
||||
|
||||
// ----- pointer interaction -----
|
||||
|
||||
private MapNode? HitTest(Point screen)
|
||||
@@ -321,7 +399,15 @@ public partial class MapEditorPage : ContentPage
|
||||
FitView();
|
||||
Preferences.Set("MapEditorFolder", folder);
|
||||
UpdateDirtyState();
|
||||
StatusLabel.Text = $"{_nodes.Count} systems loaded from {folder}.";
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(SearchControl.Text))
|
||||
{
|
||||
ApplySearch(SearchControl.Text);
|
||||
}
|
||||
else
|
||||
{
|
||||
StatusLabel.Text = $"{_nodes.Count} systems loaded from {folder}.";
|
||||
}
|
||||
}
|
||||
|
||||
private async void OnOpenFolderClicked(object? sender, EventArgs e)
|
||||
|
||||
Reference in New Issue
Block a user