From 87c05720cef6aea452cca2e905b7f4e74ed967c3 Mon Sep 17 00:00:00 2001 From: lacvet Date: Sun, 5 Apr 2026 20:50:51 +0900 Subject: [PATCH] =?UTF-8?q?AX=20Agent=20=EC=BB=A8=ED=85=8D=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=ED=86=A0=ED=81=B0=20hover=20=EB=9D=BC=EB=B2=A8=20?= =?UTF-8?q?=EB=8B=AB=ED=9E=98=20=EB=B0=8F=20=EC=A0=95=EB=B3=B4=20=ED=91=9C?= =?UTF-8?q?=EC=8B=9C=20=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 하단 컨텍스트 토큰 popup 닫힘 판정을 IsMouseOver 중심에서 실제 마우스 좌표 기준으로 보강 - 마우스를 떼었는데도 hover 라벨이 남아 있던 문제를 줄이도록 card/popup 경계 검사 로직 정리 - popup 내용에서 모델명 및 오늘 사용량 줄을 제거하고 현재 사용량과 자동 압축 기준만 남겨 정보 밀도 단순화 - README 및 DEVELOPMENT 문서에 2026-04-05 23:38 (KST) 기준 변경 이력 반영 검증 - dotnet build src/AxCopilot/AxCopilot.csproj -c Release -v minimal -p:OutputPath=bin\\verify\\ -p:IntermediateOutputPath=obj\\verify\\ - 경고 0 / 오류 0 확인 --- README.md | 2 ++ docs/DEVELOPMENT.md | 3 ++ src/AxCopilot/Views/ChatWindow.xaml.cs | 48 ++++++++++++-------------- 3 files changed, 27 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index 147d508..389ac3d 100644 --- a/README.md +++ b/README.md @@ -1057,3 +1057,5 @@ MIT License - AX Agent 작업 폴더 선택 팝업의 최근 항목 스타일을 레퍼런스처럼 더 단정한 라운드 row 구조로 정리했다. 각 최근 폴더 항목은 개별 카드형 hover/선택 상태를 가지도록 바꾸고, `다른 폴더 선택`도 같은 시각 언어로 맞췄다. 팝업 외곽 radius, 그림자, 여백, 체크 위치, 텍스트 계층도 함께 조정해 더 자연스럽게 보이게 했다. - 업데이트: 2026-04-05 23:33 (KST) - AX Agent 빈 상태 상단 심볼과 작업 유형/대화 주제 프리셋 카드 아이콘 비율을 다시 맞췄다. 프리셋 카드 내부 아이콘과 `프리셋 추가` 심볼은 한 단계 줄이고, 상단 중앙 심볼과 제목도 같은 밀도로 재조정해 화면 균형을 정리했다. +- 업데이트: 2026-04-05 23:38 (KST) + - 하단 컨텍스트 토큰 hover 라벨이 마우스를 떼어도 남아 있던 문제를 보정했다. 닫힘 판정을 단순 `IsMouseOver` 대신 실제 마우스 좌표 기준으로 바꾸고, 팝업 내용도 `현재 사용량 + 자동 압축 기준`만 남기도록 단순화했다. diff --git a/docs/DEVELOPMENT.md b/docs/DEVELOPMENT.md index 9b75fe5..7c17faa 100644 --- a/docs/DEVELOPMENT.md +++ b/docs/DEVELOPMENT.md @@ -4807,3 +4807,6 @@ ow + toggle ?쒓컖 ?몄뼱濡??ㅼ떆 ?뺣젹?덈떎. - 업데이트: 2026-04-05 23:33 (KST) - [ChatWindow.xaml](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Views/ChatWindow.xaml) 의 빈 상태 상단 심볼 크기를 42 기준으로 다시 맞추고, 제목/설명 폰트도 함께 미세 조정했다. - [ChatWindow.xaml.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Views/ChatWindow.xaml.cs) 의 `BuildTopicButtons()`에서 프리셋 카드 아이콘 원형 배경과 아이콘 크기, `기타`/`프리셋 추가` 카드 심볼 크기를 함께 줄여 프리셋 아이콘이 과하게 커 보이지 않도록 균형을 맞췄다. +- 업데이트: 2026-04-05 23:38 (KST) + - [ChatWindow.xaml.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Views/ChatWindow.xaml.cs) 의 하단 컨텍스트 토큰 hover 팝업을 더 단순하게 정리했다. 모델명/오늘 사용량 줄은 제거하고 `현재 사용량`과 `자동 압축 시작 기준`만 남겼다. + - 같은 파일의 토큰 팝업 닫힘 판정도 `IsMouseOver`만 보던 방식에서 실제 마우스 좌표 기반으로 바꿔, 마우스를 떼었는데도 라벨이 남아 있는 경우를 줄였다. diff --git a/src/AxCopilot/Views/ChatWindow.xaml.cs b/src/AxCopilot/Views/ChatWindow.xaml.cs index 3f47f83..889da23 100644 --- a/src/AxCopilot/Views/ChatWindow.xaml.cs +++ b/src/AxCopilot/Views/ChatWindow.xaml.cs @@ -18939,19 +18939,9 @@ private static (string icon, string label, string bgHex, string fgHex) GetDecisi TokenUsageArc.Stroke = progressBrush; TokenUsageThresholdMarker.Fill = progressBrush; var percentText = $"{Math.Round(usageRatio * 100):0}%"; - var (currentService, currentModel) = _llm.GetCurrentModelInfo(); - var todayUsage = Services.UsageStatisticsService.GetTodaySnapshot(); - var currentModelUsageKey = BuildUsageModelKey(currentService, currentModel); - var currentModelPromptTokens = GetUsageValue(todayUsage.ModelPromptTokens, currentModelUsageKey); - var currentModelCompletionTokens = GetUsageValue(todayUsage.ModelCompletionTokens, currentModelUsageKey); - var currentModelTotalTokens = currentModelPromptTokens + currentModelCompletionTokens; TokenUsagePercentText.Text = percentText; TokenUsageSummaryText.Text = $"컨텍스트 {percentText}"; - TokenUsageHintText.Text = - $"{Services.TokenEstimator.Format(currentTokens)} / {Services.TokenEstimator.Format(maxContextTokens)}" + - (currentModelTotalTokens > 0 - ? $" · 오늘 {FormatTokenCount(currentModelTotalTokens)}" - : ""); + TokenUsageHintText.Text = $"{Services.TokenEstimator.Format(currentTokens)} / {Services.TokenEstimator.Format(maxContextTokens)}"; CompactNowLabel.Text = compactLabel; if (TokenUsagePopupTitle != null) @@ -18960,24 +18950,13 @@ private static (string icon, string label, string bgHex, string fgHex) GetDecisi TokenUsagePopupUsage.Text = $"{Services.TokenEstimator.Format(currentTokens)}/{Services.TokenEstimator.Format(maxContextTokens)}"; if (TokenUsagePopupDetail != null) { - var usageLine = currentModelTotalTokens > 0 - ? $"{currentService} · {currentModel} 오늘 {FormatTokenCount(currentModelTotalTokens)}" - : $"{summary} · 오늘 모델 사용량 없음"; - var compactLine = _pendingPostCompaction + TokenUsagePopupDetail.Text = _pendingPostCompaction ? "compact 후 첫 응답 대기 중" : $"자동 압축 시작 {triggerPercent}%"; - TokenUsagePopupDetail.Text = $"{usageLine}\n{compactLine}"; } if (TokenUsagePopupCompact != null) { - var compactText = compactLabel switch - { - "지금 압축" => "지금 압축이 필요합니다", - "압축 권장" => "곧 자동 압축이 시작됩니다", - "미리 압축" => "여유가 있을 때 먼저 압축할 수 있습니다", - _ => "AX Agent가 컨텍스트를 자동으로 관리합니다", - }; - TokenUsagePopupCompact.Text = compactText; + TokenUsagePopupCompact.Text = "AX Agent가 컨텍스트를 자동으로 관리합니다"; } TokenUsageCard.ToolTip = null; @@ -19016,12 +18995,29 @@ private static (string icon, string label, string bgHex, string fgHex) GetDecisi if (TokenUsagePopup == null) return; - var cardHovered = TokenUsageCard?.IsMouseOver ?? false; - var popupHovered = TokenUsagePopup.Child is FrameworkElement popupChild && popupChild.IsMouseOver; + var cardHovered = IsMouseInsideElement(TokenUsageCard); + var popupHovered = TokenUsagePopup.Child is FrameworkElement popupChild && IsMouseInsideElement(popupChild); if (!cardHovered && !popupHovered) TokenUsagePopup.IsOpen = false; } + private static bool IsMouseInsideElement(FrameworkElement? element) + { + if (element == null || !element.IsVisible || element.ActualWidth <= 0 || element.ActualHeight <= 0) + return false; + + try + { + var mouse = System.Windows.Forms.Control.MousePosition; + var point = element.PointFromScreen(new Point(mouse.X, mouse.Y)); + return point.X >= 0 && point.Y >= 0 && point.X <= element.ActualWidth && point.Y <= element.ActualHeight; + } + catch + { + return element.IsMouseOver; + } + } + private static string BuildUsageModelKey(string? service, string? model) { var normalizedService = (service ?? "").Trim().ToLowerInvariant();