feat: Add configurable Padding and display nodes without RFID in gray
MapNode.cs: - Padding 속성 추가 (기본값 8px, 텍스트 주변 여백) - Clone 메서드에 Padding 복사 추가 NodePropertyWrapper.cs: - LabelNodePropertyWrapper에 Padding 속성 추가 - PropertyGrid에서 0~50px 범위로 조정 가능 UnifiedAGVCanvas.Events.cs: - DrawLabelNode: 하드코딩된 패딩을 node.Padding 사용 - GetNodeBrush: RFID 없는 노드를 회색 계통으로 표시 * Normal: Blue → LightGray * Rotation: Orange → DarkGray * Docking: Green → Gray * Charging: Red → Silver UnifiedAGVCanvas.Mouse.cs: - HandleLabelNodeDoubleClick: node.Name → node.LabelText 사용 이제 라벨 노드 패딩을 속성창에서 조정 가능하고, RFID 미할당 노드를 시각적으로 쉽게 구분 가능 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -45,6 +45,8 @@ namespace AGVMapEditor.Controls
|
||||
this.DoubleBuffered = true;
|
||||
this.BackColor = Color.White;
|
||||
this.AutoScroll = true;
|
||||
|
||||
|
||||
}
|
||||
|
||||
#region Properties
|
||||
|
||||
@@ -25,6 +25,11 @@ namespace AGVMapEditor.Forms
|
||||
{
|
||||
LoadImageFromNode(imageNode);
|
||||
}
|
||||
|
||||
this.KeyPreview = true;
|
||||
this.KeyDown += (s1, e1) => {
|
||||
if (e1.KeyCode == Keys.Escape) this.Close();
|
||||
};
|
||||
}
|
||||
|
||||
private void SetupUI()
|
||||
|
||||
@@ -154,6 +154,19 @@ namespace AGVMapEditor.Models
|
||||
}
|
||||
}
|
||||
|
||||
[Category("라벨")]
|
||||
[DisplayName("패딩")]
|
||||
[Description("텍스트 주변 여백 (픽셀 단위)")]
|
||||
public int Padding
|
||||
{
|
||||
get => _node.Padding;
|
||||
set
|
||||
{
|
||||
_node.Padding = Math.Max(0, Math.Min(50, value));
|
||||
_node.ModifiedDate = DateTime.Now;
|
||||
}
|
||||
}
|
||||
|
||||
[Category("위치")]
|
||||
[DisplayName("X 좌표")]
|
||||
[Description("맵에서의 X 좌표")]
|
||||
|
||||
@@ -743,10 +743,10 @@ namespace AGVNavigationCore.Controls
|
||||
{
|
||||
var backgroundBrush = new SolidBrush(node.BackColor);
|
||||
var backgroundRect = new Rectangle(
|
||||
textPoint.X - 2,
|
||||
textPoint.Y - 2,
|
||||
(int)textSize.Width + 4,
|
||||
(int)textSize.Height + 4
|
||||
textPoint.X - node.Padding,
|
||||
textPoint.Y - node.Padding,
|
||||
(int)textSize.Width + (node.Padding * 2),
|
||||
(int)textSize.Height + (node.Padding * 2)
|
||||
);
|
||||
g.FillRectangle(backgroundBrush, backgroundRect);
|
||||
g.DrawRectangle(Pens.Black, backgroundRect);
|
||||
@@ -759,11 +759,12 @@ namespace AGVNavigationCore.Controls
|
||||
// 선택된 노드 강조
|
||||
if (node == _selectedNode)
|
||||
{
|
||||
var selectionPadding = node.Padding + 2;
|
||||
var selectionRect = new Rectangle(
|
||||
textPoint.X - 4,
|
||||
textPoint.Y - 4,
|
||||
(int)textSize.Width + 8,
|
||||
(int)textSize.Height + 8
|
||||
textPoint.X - selectionPadding,
|
||||
textPoint.Y - selectionPadding,
|
||||
(int)textSize.Width + (selectionPadding * 2),
|
||||
(int)textSize.Height + (selectionPadding * 2)
|
||||
);
|
||||
g.DrawRectangle(_selectedNodePen, selectionRect);
|
||||
}
|
||||
@@ -771,11 +772,12 @@ namespace AGVNavigationCore.Controls
|
||||
// 호버된 노드 강조
|
||||
if (node == _hoveredNode)
|
||||
{
|
||||
var hoverPadding = node.Padding + 4;
|
||||
var hoverRect = new Rectangle(
|
||||
textPoint.X - 6,
|
||||
textPoint.Y - 6,
|
||||
(int)textSize.Width + 12,
|
||||
(int)textSize.Height + 12
|
||||
textPoint.X - hoverPadding,
|
||||
textPoint.Y - hoverPadding,
|
||||
(int)textSize.Width + (hoverPadding * 2),
|
||||
(int)textSize.Height + (hoverPadding * 2)
|
||||
);
|
||||
g.DrawRectangle(new Pen(Color.Orange, 2), hoverRect);
|
||||
}
|
||||
@@ -908,22 +910,25 @@ namespace AGVNavigationCore.Controls
|
||||
|
||||
private Brush GetNodeBrush(MapNode node)
|
||||
{
|
||||
// RFID가 없는 노드는 회색 계통으로 표시
|
||||
bool hasRfid = node.HasRfid();
|
||||
|
||||
switch (node.Type)
|
||||
{
|
||||
case NodeType.Normal:
|
||||
return _normalNodeBrush;
|
||||
return hasRfid ? _normalNodeBrush : new SolidBrush(Color.LightGray);
|
||||
case NodeType.Rotation:
|
||||
return _rotationNodeBrush;
|
||||
return hasRfid ? _rotationNodeBrush : new SolidBrush(Color.DarkGray);
|
||||
case NodeType.Docking:
|
||||
return _dockingNodeBrush;
|
||||
return hasRfid ? _dockingNodeBrush : new SolidBrush(Color.Gray);
|
||||
case NodeType.Charging:
|
||||
return _chargingNodeBrush;
|
||||
return hasRfid ? _chargingNodeBrush : new SolidBrush(Color.Silver);
|
||||
case NodeType.Label:
|
||||
return new SolidBrush(Color.Purple);
|
||||
case NodeType.Image:
|
||||
return new SolidBrush(Color.Brown);
|
||||
default:
|
||||
return _normalNodeBrush;
|
||||
return hasRfid ? _normalNodeBrush : new SolidBrush(Color.LightGray);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -105,7 +105,7 @@ namespace AGVNavigationCore.Controls
|
||||
private void HandleLabelNodeDoubleClick(MapNode node)
|
||||
{
|
||||
// 라벨 텍스트 입력창 표시
|
||||
string currentText = node.Name ?? "새 라벨";
|
||||
string currentText = node.LabelText ?? "새 라벨";
|
||||
string newText = Microsoft.VisualBasic.Interaction.InputBox(
|
||||
"라벨 텍스트를 입력하세요:",
|
||||
"라벨 편집",
|
||||
@@ -113,7 +113,7 @@ namespace AGVNavigationCore.Controls
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(newText) && newText != currentText)
|
||||
{
|
||||
node.Name = newText.Trim();
|
||||
node.LabelText = newText.Trim();
|
||||
MapChanged?.Invoke(this, EventArgs.Empty);
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
@@ -138,6 +138,11 @@ namespace AGVNavigationCore.Models
|
||||
/// </summary>
|
||||
public bool ShowBackground { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 라벨 패딩 (NodeType.Label인 경우 사용, 픽셀 단위)
|
||||
/// </summary>
|
||||
public int Padding { get; set; } = 8;
|
||||
|
||||
/// <summary>
|
||||
/// 이미지 파일 경로 (편집용, 저장시엔 사용되지 않음)
|
||||
/// </summary>
|
||||
@@ -343,6 +348,7 @@ namespace AGVNavigationCore.Models
|
||||
ForeColor = ForeColor,
|
||||
BackColor = BackColor,
|
||||
ShowBackground = ShowBackground,
|
||||
Padding = Padding,
|
||||
ImagePath = ImagePath,
|
||||
ImageBase64 = ImageBase64,
|
||||
Scale = Scale,
|
||||
|
||||
Reference in New Issue
Block a user