Vibe search feature
This commit is contained in:
@@ -4,7 +4,7 @@ sessionId: session-260928-112553-atgt
|
||||
|
||||
# Delivery Steps
|
||||
|
||||
### * Step 1: Implementation
|
||||
### ✓ Step 1: Implementation
|
||||
<plan_session_history>
|
||||
History processor: During the current session, you have worked on the following `<previous_issue>`.
|
||||
The `<issue_description>` usually continues or extends your previous work. Consider all `<previous_issue>` and `<issue_description>` together.
|
||||
@@ -59,6 +59,18 @@ System.TypeLoadException: Method 'get_HasExplicitSafeAreaEdges' in type 'Microso
|
||||
tool name: submit
|
||||
tool parameters:
|
||||
</previous_issue_solution>
|
||||
<previous_issue>
|
||||
## Orchestrated Plan Task
|
||||
implement according to the plan
|
||||
</previous_issue>
|
||||
<previous_issue>
|
||||
## Plan Task
|
||||
Add a search feature to the editor that will highlight matching nodes in the ZeroSpace.MapEditor
|
||||
</previous_issue>
|
||||
<previous_issue_solution>
|
||||
tool name: submit
|
||||
tool parameters:
|
||||
</previous_issue_solution>
|
||||
</plan_session_history>
|
||||
|
||||
<plan_task>
|
||||
|
||||
-61660
File diff suppressed because one or more lines are too long
@@ -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,8 +399,16 @@ public partial class MapEditorPage : ContentPage
|
||||
FitView();
|
||||
Preferences.Set("MapEditorFolder", folder);
|
||||
UpdateDirtyState();
|
||||
|
||||
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