컨텍스트 사용량 링 정렬 회귀 수정
원인: 하단 컨텍스트 사용량 트랙은 22x22 원형인데 arc는 center=15, radius=11 하드코딩으로 더 크게 그려져 오른쪽으로 밀려 보였습니다. 수정: TokenUsageTrack과 TokenUsageArc를 같은 크기와 가운데 정렬로 맞추고, 실제 트랙 지름과 스트로크 두께를 기준으로 중심점·반지름을 계산하는 helper를 추가했습니다. 크기 변경 시에도 arc가 다시 그려지도록 캐시 조건도 보강했습니다. 검증: dotnet build src/AxCopilot/AxCopilot.csproj -c Release -v minimal -p:OutputPath=bin\verify_token_ring_alignment\ -p:IntermediateOutputPath=obj\verify_token_ring_alignment\ (경고 0 / 오류 0), dotnet test src/AxCopilot.Tests/AxCopilot.Tests.csproj -c Release -v minimal --filter ChatWindowSlashPolicyTests -p:OutputPath=bin\verify_token_ring_alignment_tests\ -p:IntermediateOutputPath=obj\verify_token_ring_alignment_tests\ (통과 53)
This commit is contained in:
@@ -1,5 +1,9 @@
|
||||
# AX Commander
|
||||
|
||||
- 업데이트: 2026-04-15 20:12 (KST)
|
||||
- AX Agent 하단 컨텍스트 사용량 링이 트랙보다 오른쪽으로 밀려 보이던 정렬 문제를 수정했습니다. `src/AxCopilot/Views/ChatWindow.xaml`은 진행 arc를 트랙과 같은 `22x22` 기준으로 가운데 정렬하고, `src/AxCopilot/Views/ChatWindow.ContextUsagePresentation.cs`는 실제 트랙 지름 기준으로 중심점과 반지름을 계산해 그리도록 바뀌었습니다.
|
||||
- `src/AxCopilot/Views/ChatWindow.xaml.cs`에 링 중심/반지름 계산 helper를 추가했고, `src/AxCopilot.Tests/Views/ChatWindowSlashPolicyTests.cs`에 지름·스트로크 두께별 계산 회귀 테스트를 넣었습니다.
|
||||
|
||||
- 업데이트: 2026-04-15 20:06 (KST)
|
||||
- 빠른 로컬 테스트용 Windows 빌드 스크립트 [build-quick.ps1](/E:/AX%20Copilot%20-%20Codex/build-quick.ps1)를 추가했습니다. 인스톨러/`dist` 패키징 없이 `src/AxCopilot/AxCopilot.csproj`만 `dotnet build -c Release -r win-x64`로 빌드합니다.
|
||||
- 기본 출력 경로는 `src\AxCopilot\bin\Release\net8.0-windows10.0.17763.0\win-x64`이며, 기본 실행은 `--no-restore` 경로를 우선 사용해 반복 테스트 속도를 줄였습니다. 첫 실행이나 패키지 변경 시에는 `-Restore`, 실행 중 잠금이 있으면 `-StopRunningApp` 옵션을 사용할 수 있습니다.
|
||||
|
||||
@@ -1533,3 +1533,9 @@ UI ?遺우쁽????域뱀뮆???귐뗫솯?醫딆춦 ???袁る퓮 ?臾믩씜 ??疫
|
||||
- 빠른 로컬 테스트 전용 Windows 스크립트 `build-quick.ps1`를 루트에 추가했습니다. 목적은 인스톨러 빌드와 `dist` 패키징을 건너뛰고 `src/AxCopilot/AxCopilot.csproj`만 직접 `Release + win-x64`로 빌드해 `src\\AxCopilot\\bin\\Release\\net8.0-windows10.0.17763.0\\win-x64` 출력물을 빠르게 갱신하는 것입니다.
|
||||
- 스크립트는 기본적으로 `dotnet build --no-restore` 경로를 사용하고, `obj\\project.assets.json`이 없거나 사용자가 `-Restore`를 준 경우에만 restore를 수행합니다. 잠금 문제를 줄이기 위해 `-StopRunningApp`, 출력물 정리를 원할 때 `-Clean` 옵션도 함께 지원합니다.
|
||||
- 검증: `powershell -ExecutionPolicy Bypass -File .\\build-quick.ps1` 실행으로 빠른 빌드 스크립트가 정상 완료되고 출력 경로가 갱신되는 것을 확인했습니다.
|
||||
업데이트: 2026-04-15 20:12 (KST)
|
||||
- AX Agent 하단 컨텍스트 사용량 링이 트랙보다 오른쪽으로 밀려 보이던 시각 회귀를 수정했습니다. 원인은 `src/AxCopilot/Views/ChatWindow.ContextUsagePresentation.cs`가 `22x22` 트랙 위에 arc를 `center=15`, `radius=11` 하드코딩으로 그려 실제 트랙 중심선보다 크게 렌더링하던 점이었습니다.
|
||||
- `src/AxCopilot/Views/ChatWindow.xaml`에서 `TokenUsageTrack`을 명시적으로 분리하고, `TokenUsageArc`를 트랙과 같은 크기/가운데 정렬/`Stretch=None`으로 맞췄습니다. `src/AxCopilot/Views/ChatWindow.ContextUsagePresentation.cs`는 실제 트랙 지름을 읽어 arc 크기를 맞추고, `src/AxCopilot/Views/ChatWindow.xaml.cs`의 `CalculateCircularRingMetrics(...)` helper로 중심점과 반지름을 계산하도록 변경했습니다.
|
||||
- `src/AxCopilot.Tests/Views/ChatWindowSlashPolicyTests.cs`에 `CalculateCircularRingMetrics_ShouldAlignCenterlineToTrack`를 추가해 지름과 스트로크 두께에 따른 계산 회귀를 고정했습니다.
|
||||
- 검증: `dotnet build src/AxCopilot/AxCopilot.csproj -c Release -v minimal -p:OutputPath=bin\\verify_token_ring_alignment\\ -p:IntermediateOutputPath=obj\\verify_token_ring_alignment\\` 경고 0 / 오류 0
|
||||
- 검증: `dotnet test src/AxCopilot.Tests/AxCopilot.Tests.csproj -c Release -v minimal --filter "ChatWindowSlashPolicyTests" -p:OutputPath=bin\\verify_token_ring_alignment_tests\\ -p:IntermediateOutputPath=obj\\verify_token_ring_alignment_tests\\` 통과 53
|
||||
|
||||
@@ -198,4 +198,21 @@ public class ChatWindowSlashPolicyTests
|
||||
var result = method!.Invoke(null, new object?[] { runTab });
|
||||
result.Should().Be(expected);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(22, 2, 11, 10)]
|
||||
[InlineData(28, 2, 14, 13)]
|
||||
[InlineData(22, 0, 11, 11)]
|
||||
[InlineData(0, 2, 0, 0)]
|
||||
public void CalculateCircularRingMetrics_ShouldAlignCenterlineToTrack(
|
||||
double diameter,
|
||||
double strokeThickness,
|
||||
double expectedCenter,
|
||||
double expectedRadius)
|
||||
{
|
||||
var (center, radius) = ChatWindow.CalculateCircularRingMetrics(diameter, strokeThickness);
|
||||
|
||||
center.Should().Be(expectedCenter);
|
||||
radius.Should().Be(expectedRadius);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,7 +138,24 @@ public partial class ChatWindow
|
||||
|
||||
TokenUsageCard.ToolTip = null;
|
||||
|
||||
UpdateCircularUsageArc(TokenUsageArc, usageRatio, 15, 15, 11);
|
||||
var ringDiameter = ResolveTokenUsageRingDiameter();
|
||||
TokenUsageArc.Width = ringDiameter;
|
||||
TokenUsageArc.Height = ringDiameter;
|
||||
var (center, radius) = CalculateCircularRingMetrics(ringDiameter, TokenUsageArc.StrokeThickness);
|
||||
UpdateCircularUsageArc(TokenUsageArc, usageRatio, center, center, radius);
|
||||
}
|
||||
|
||||
private double ResolveTokenUsageRingDiameter()
|
||||
{
|
||||
var actual = TokenUsageTrack?.ActualWidth ?? 0;
|
||||
if (actual > 0)
|
||||
return actual;
|
||||
|
||||
var declared = TokenUsageTrack?.Width ?? 0;
|
||||
if (declared > 0)
|
||||
return declared;
|
||||
|
||||
return TokenUsageArc?.Width > 0 ? TokenUsageArc.Width : 22;
|
||||
}
|
||||
|
||||
private void TokenUsageCard_MouseEnter(object sender, MouseEventArgs e)
|
||||
|
||||
@@ -2673,7 +2673,8 @@
|
||||
MouseLeave="TokenUsageCard_MouseLeave">
|
||||
<Grid Width="28" Height="28">
|
||||
<!-- Ring track (subtle background ring) -->
|
||||
<Ellipse Width="22" Height="22"
|
||||
<Ellipse x:Name="TokenUsageTrack"
|
||||
Width="22" Height="22"
|
||||
Stroke="{DynamicResource BorderColor}"
|
||||
StrokeThickness="2"
|
||||
Opacity="0.45"
|
||||
@@ -2681,10 +2682,16 @@
|
||||
VerticalAlignment="Center"/>
|
||||
<!-- Usage arc (progress) -->
|
||||
<Path x:Name="TokenUsageArc"
|
||||
Width="22"
|
||||
Height="22"
|
||||
Stroke="{DynamicResource AccentColor}"
|
||||
StrokeThickness="2"
|
||||
StrokeStartLineCap="Round"
|
||||
StrokeEndLineCap="Round"/>
|
||||
StrokeEndLineCap="Round"
|
||||
Stretch="None"
|
||||
SnapsToDevicePixels="True"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"/>
|
||||
<!-- Hidden data elements (referenced in code) -->
|
||||
<StackPanel Visibility="Collapsed">
|
||||
<TextBlock x:Name="TokenUsagePercentText"
|
||||
|
||||
@@ -7347,16 +7347,32 @@ public partial class ChatWindow : Window
|
||||
return value.ToString("N0");
|
||||
}
|
||||
|
||||
internal static (double Center, double Radius) CalculateCircularRingMetrics(double diameter, double strokeThickness)
|
||||
{
|
||||
var safeDiameter = Math.Max(0, diameter);
|
||||
var safeStrokeThickness = Math.Max(0, strokeThickness);
|
||||
var center = safeDiameter / 2;
|
||||
var radius = Math.Max(0, center - (safeStrokeThickness / 2));
|
||||
return (center, radius);
|
||||
}
|
||||
|
||||
private double _lastArcRatio = -1;
|
||||
private double _lastArcDiameter = -1;
|
||||
private double _lastArcStrokeThickness = -1;
|
||||
|
||||
private void UpdateCircularUsageArc(System.Windows.Shapes.Path path, double ratio, double centerX, double centerY, double radius)
|
||||
{
|
||||
ratio = Math.Clamp(ratio, 0, 0.9999);
|
||||
var effectiveDiameter = Math.Max(0, radius * 2 + path.StrokeThickness);
|
||||
|
||||
// 비율 변화가 1% 미만이면 렌더링 생략 (250ms마다 호출되므로 불필요한 재생성 방지)
|
||||
if (Math.Abs(ratio - _lastArcRatio) < 0.01)
|
||||
// 비율 변화가 1% 미만이어도 크기나 두께가 바뀌면 다시 그립니다.
|
||||
if (Math.Abs(ratio - _lastArcRatio) < 0.01
|
||||
&& Math.Abs(effectiveDiameter - _lastArcDiameter) < 0.01
|
||||
&& Math.Abs(path.StrokeThickness - _lastArcStrokeThickness) < 0.01)
|
||||
return;
|
||||
_lastArcRatio = ratio;
|
||||
_lastArcDiameter = effectiveDiameter;
|
||||
_lastArcStrokeThickness = path.StrokeThickness;
|
||||
|
||||
if (ratio <= 0)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user