From b388b1917d6ac26c1db5cb96ef478ca00e2fdd0c Mon Sep 17 00:00:00 2001 From: backuppc Date: Wed, 4 Feb 2026 15:23:45 +0900 Subject: [PATCH] feat(AGVCanvas): blink error msg, debug info, setview --- .../Controls/UnifiedAGVCanvas.Events.cs | 62 +++++++++++++++++-- .../Controls/UnifiedAGVCanvas.cs | 57 +++++++++++++++++ 2 files changed, 114 insertions(+), 5 deletions(-) diff --git a/AGVLogic/AGVNavigationCore/Controls/UnifiedAGVCanvas.Events.cs b/AGVLogic/AGVNavigationCore/Controls/UnifiedAGVCanvas.Events.cs index 5420472..8d87a4f 100644 --- a/AGVLogic/AGVNavigationCore/Controls/UnifiedAGVCanvas.Events.cs +++ b/AGVLogic/AGVNavigationCore/Controls/UnifiedAGVCanvas.Events.cs @@ -90,7 +90,7 @@ namespace AGVNavigationCore.Controls } // UI 정보 그리기 (변환 없이) - if (_showGrid) + //if (_showGrid) DrawUIInfo(g); // 동기화 화면 그리기 (변환 없이, 최상위) @@ -209,13 +209,57 @@ namespace AGVNavigationCore.Controls void DrawAlertMessage(Graphics g) { - if (showalert == false) return; + if (!showalert || String.IsNullOrEmpty(this._alertmesage)) return; - //상단에 경고 메세지를 추가한다 - if (String.IsNullOrEmpty(this._alertmesage)) return; + // 상단 중앙에 반투명 빨간색 배경 바 표시 + int barHeight = 40; + int barWidth = Math.Min(600, this.Width - 40); // 최대 600px, 좌우 여백 20px + int barX = (this.Width - barWidth) / 2; + int barY = 20; + // 둥근 사각형 배경 + using (var path = new GraphicsPath()) + { + int radius = 10; + path.AddArc(barX, barY, radius * 2, radius * 2, 180, 90); + path.AddArc(barX + barWidth - radius * 2, barY, radius * 2, radius * 2, 270, 90); + path.AddArc(barX + barWidth - radius * 2, barY + barHeight - radius * 2, radius * 2, radius * 2, 0, 90); + path.AddArc(barX, barY + barHeight - radius * 2, radius * 2, radius * 2, 90, 90); + path.CloseFigure(); - g.DrawString(this._alertmesage, this.Font, Brushes.Gold, 10, 10); + using (var brush = new SolidBrush(Color.FromArgb(200, 255, 69, 58))) // 진한 붉은색 (Apple Red 계열) + { + g.FillPath(brush, path); + } + + using (var pen = new Pen(Color.FromArgb(255, 255, 255), 2)) + { + g.DrawPath(pen, path); + } + } + + // 텍스트 깜박임 효과 (배경은 유지하고 텍스트만 깜박임) + if (_isAlertBlinkOn) + { + using (var font = new Font("Malgun Gothic", 12, FontStyle.Bold)) + using (var brush = new SolidBrush(Color.White)) + { + var textSize = g.MeasureString(_alertmesage, font); + g.DrawString(_alertmesage, font, brush, + barX + (barWidth - textSize.Width) / 2, + barY + (barHeight - textSize.Height) / 2); + } + + // 경고 아이콘 그리기 (왼쪽) + // 간단한 느낌표 아이콘 + int iconX = barX + 15; + int iconY = barY + barHeight / 2; + using (var brush = new SolidBrush(Color.White)) + { + g.FillEllipse(brush, iconX - 2, iconY - 8, 4, 16); // body + g.FillEllipse(brush, iconX - 2, iconY + 10, 4, 4); // dot + } + } } private void DrawSyncScreen(Graphics g) @@ -2396,6 +2440,14 @@ namespace AGVNavigationCore.Controls g.FillRectangle(bgBrush, scaleRect); g.DrawRectangle(Pens.Gray, scaleRect.X, scaleRect.Y, scaleRect.Width, scaleRect.Height); g.DrawString(scaleText, font, Brushes.Black, scaleRect.X + 5, scaleRect.Y + 2); + + // 팬 정보 (스케일 정보 위에) + var panText = $"Pan: {_panOffset.X:F1}, {_panOffset.Y:F1}"; + var panSize = g.MeasureString(panText, font); + var panRect = new RectangleF(10, Height - zoomSize.Height - scaleSize.Height - panSize.Height - 35, panSize.Width + 10, panSize.Height + 5); + g.FillRectangle(bgBrush, panRect); + g.DrawRectangle(Pens.Gray, panRect.X, panRect.Y, panRect.Width, panRect.Height); + g.DrawString(panText, font, Brushes.Black, panRect.X + 5, panRect.Y + 2); } diff --git a/AGVLogic/AGVNavigationCore/Controls/UnifiedAGVCanvas.cs b/AGVLogic/AGVNavigationCore/Controls/UnifiedAGVCanvas.cs index 9136863..fd30f2f 100644 --- a/AGVLogic/AGVNavigationCore/Controls/UnifiedAGVCanvas.cs +++ b/AGVLogic/AGVNavigationCore/Controls/UnifiedAGVCanvas.cs @@ -137,10 +137,42 @@ namespace AGVNavigationCore.Controls string _alertmesage = ""; bool showalert = false; + + // 깜박임 효과를 위한 타이머 및 상태 + private Timer _alertBlinkTimer; + private bool _isAlertBlinkOn = true; + public void SetAlertMessage(string m) { _alertmesage = m; showalert = !string.IsNullOrEmpty(m); + + //if (showalert) + //{ + // if (_alertBlinkTimer == null) + // { + // _alertBlinkTimer = new Timer(); + // _alertBlinkTimer.Interval = 500; // 0.5초 간격 + // _alertBlinkTimer.Tick += _alertBlinkTimer_Tick; + // } + // _alertBlinkTimer.Start(); + // _isAlertBlinkOn = true; + //} + //else + //{ + // if (_alertBlinkTimer != null) + // { + // _alertBlinkTimer.Stop(); + // } + // _isAlertBlinkOn = false; + //} + //Invalidate(); // 즉시 갱신 + } + + private void _alertBlinkTimer_Tick(object sender, EventArgs e) + { + //_isAlertBlinkOn = !_isAlertBlinkOn; + //Invalidate(); } @@ -292,6 +324,23 @@ namespace AGVNavigationCore.Controls } } + /// + /// 외부에서 Pan(X,Y) 및 Zoom 값을 설정합니다. + /// + /// Pan X 좌표 + /// Pan Y 좌표 + /// Zoom Level (0.1 ~ 5.0) + public void SetView(float panX, float panY, float zoom) + { + // Zoom 값 범위 제한 + float newZoom = Math.Max(0.1f, Math.Min(5.0f, zoom)); + + _panOffset = new PointF(panX, panY); + _zoomFactor = newZoom; + + Invalidate(); + } + /// /// 그리드 표시 여부 /// @@ -886,6 +935,14 @@ namespace AGVNavigationCore.Controls // 이미지 정리 _companyLogo?.Dispose(); + + // 타이머 정리 + if (_alertBlinkTimer != null) + { + _alertBlinkTimer.Stop(); + _alertBlinkTimer.Dispose(); + _alertBlinkTimer = null; + } } base.Dispose(disposing);