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.DoubleBuffered = true;
|
||||||
this.BackColor = Color.White;
|
this.BackColor = Color.White;
|
||||||
this.AutoScroll = true;
|
this.AutoScroll = true;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Properties
|
#region Properties
|
||||||
|
|||||||
@@ -25,6 +25,11 @@ namespace AGVMapEditor.Forms
|
|||||||
{
|
{
|
||||||
LoadImageFromNode(imageNode);
|
LoadImageFromNode(imageNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.KeyPreview = true;
|
||||||
|
this.KeyDown += (s1, e1) => {
|
||||||
|
if (e1.KeyCode == Keys.Escape) this.Close();
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetupUI()
|
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("위치")]
|
[Category("위치")]
|
||||||
[DisplayName("X 좌표")]
|
[DisplayName("X 좌표")]
|
||||||
[Description("맵에서의 X 좌표")]
|
[Description("맵에서의 X 좌표")]
|
||||||
|
|||||||
@@ -743,10 +743,10 @@ namespace AGVNavigationCore.Controls
|
|||||||
{
|
{
|
||||||
var backgroundBrush = new SolidBrush(node.BackColor);
|
var backgroundBrush = new SolidBrush(node.BackColor);
|
||||||
var backgroundRect = new Rectangle(
|
var backgroundRect = new Rectangle(
|
||||||
textPoint.X - 2,
|
textPoint.X - node.Padding,
|
||||||
textPoint.Y - 2,
|
textPoint.Y - node.Padding,
|
||||||
(int)textSize.Width + 4,
|
(int)textSize.Width + (node.Padding * 2),
|
||||||
(int)textSize.Height + 4
|
(int)textSize.Height + (node.Padding * 2)
|
||||||
);
|
);
|
||||||
g.FillRectangle(backgroundBrush, backgroundRect);
|
g.FillRectangle(backgroundBrush, backgroundRect);
|
||||||
g.DrawRectangle(Pens.Black, backgroundRect);
|
g.DrawRectangle(Pens.Black, backgroundRect);
|
||||||
@@ -759,11 +759,12 @@ namespace AGVNavigationCore.Controls
|
|||||||
// 선택된 노드 강조
|
// 선택된 노드 강조
|
||||||
if (node == _selectedNode)
|
if (node == _selectedNode)
|
||||||
{
|
{
|
||||||
|
var selectionPadding = node.Padding + 2;
|
||||||
var selectionRect = new Rectangle(
|
var selectionRect = new Rectangle(
|
||||||
textPoint.X - 4,
|
textPoint.X - selectionPadding,
|
||||||
textPoint.Y - 4,
|
textPoint.Y - selectionPadding,
|
||||||
(int)textSize.Width + 8,
|
(int)textSize.Width + (selectionPadding * 2),
|
||||||
(int)textSize.Height + 8
|
(int)textSize.Height + (selectionPadding * 2)
|
||||||
);
|
);
|
||||||
g.DrawRectangle(_selectedNodePen, selectionRect);
|
g.DrawRectangle(_selectedNodePen, selectionRect);
|
||||||
}
|
}
|
||||||
@@ -771,11 +772,12 @@ namespace AGVNavigationCore.Controls
|
|||||||
// 호버된 노드 강조
|
// 호버된 노드 강조
|
||||||
if (node == _hoveredNode)
|
if (node == _hoveredNode)
|
||||||
{
|
{
|
||||||
|
var hoverPadding = node.Padding + 4;
|
||||||
var hoverRect = new Rectangle(
|
var hoverRect = new Rectangle(
|
||||||
textPoint.X - 6,
|
textPoint.X - hoverPadding,
|
||||||
textPoint.Y - 6,
|
textPoint.Y - hoverPadding,
|
||||||
(int)textSize.Width + 12,
|
(int)textSize.Width + (hoverPadding * 2),
|
||||||
(int)textSize.Height + 12
|
(int)textSize.Height + (hoverPadding * 2)
|
||||||
);
|
);
|
||||||
g.DrawRectangle(new Pen(Color.Orange, 2), hoverRect);
|
g.DrawRectangle(new Pen(Color.Orange, 2), hoverRect);
|
||||||
}
|
}
|
||||||
@@ -908,22 +910,25 @@ namespace AGVNavigationCore.Controls
|
|||||||
|
|
||||||
private Brush GetNodeBrush(MapNode node)
|
private Brush GetNodeBrush(MapNode node)
|
||||||
{
|
{
|
||||||
|
// RFID가 없는 노드는 회색 계통으로 표시
|
||||||
|
bool hasRfid = node.HasRfid();
|
||||||
|
|
||||||
switch (node.Type)
|
switch (node.Type)
|
||||||
{
|
{
|
||||||
case NodeType.Normal:
|
case NodeType.Normal:
|
||||||
return _normalNodeBrush;
|
return hasRfid ? _normalNodeBrush : new SolidBrush(Color.LightGray);
|
||||||
case NodeType.Rotation:
|
case NodeType.Rotation:
|
||||||
return _rotationNodeBrush;
|
return hasRfid ? _rotationNodeBrush : new SolidBrush(Color.DarkGray);
|
||||||
case NodeType.Docking:
|
case NodeType.Docking:
|
||||||
return _dockingNodeBrush;
|
return hasRfid ? _dockingNodeBrush : new SolidBrush(Color.Gray);
|
||||||
case NodeType.Charging:
|
case NodeType.Charging:
|
||||||
return _chargingNodeBrush;
|
return hasRfid ? _chargingNodeBrush : new SolidBrush(Color.Silver);
|
||||||
case NodeType.Label:
|
case NodeType.Label:
|
||||||
return new SolidBrush(Color.Purple);
|
return new SolidBrush(Color.Purple);
|
||||||
case NodeType.Image:
|
case NodeType.Image:
|
||||||
return new SolidBrush(Color.Brown);
|
return new SolidBrush(Color.Brown);
|
||||||
default:
|
default:
|
||||||
return _normalNodeBrush;
|
return hasRfid ? _normalNodeBrush : new SolidBrush(Color.LightGray);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ namespace AGVNavigationCore.Controls
|
|||||||
private void HandleLabelNodeDoubleClick(MapNode node)
|
private void HandleLabelNodeDoubleClick(MapNode node)
|
||||||
{
|
{
|
||||||
// 라벨 텍스트 입력창 표시
|
// 라벨 텍스트 입력창 표시
|
||||||
string currentText = node.Name ?? "새 라벨";
|
string currentText = node.LabelText ?? "새 라벨";
|
||||||
string newText = Microsoft.VisualBasic.Interaction.InputBox(
|
string newText = Microsoft.VisualBasic.Interaction.InputBox(
|
||||||
"라벨 텍스트를 입력하세요:",
|
"라벨 텍스트를 입력하세요:",
|
||||||
"라벨 편집",
|
"라벨 편집",
|
||||||
@@ -113,7 +113,7 @@ namespace AGVNavigationCore.Controls
|
|||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(newText) && newText != currentText)
|
if (!string.IsNullOrWhiteSpace(newText) && newText != currentText)
|
||||||
{
|
{
|
||||||
node.Name = newText.Trim();
|
node.LabelText = newText.Trim();
|
||||||
MapChanged?.Invoke(this, EventArgs.Empty);
|
MapChanged?.Invoke(this, EventArgs.Empty);
|
||||||
Invalidate();
|
Invalidate();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -138,6 +138,11 @@ namespace AGVNavigationCore.Models
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public bool ShowBackground { get; set; } = false;
|
public bool ShowBackground { get; set; } = false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 라벨 패딩 (NodeType.Label인 경우 사용, 픽셀 단위)
|
||||||
|
/// </summary>
|
||||||
|
public int Padding { get; set; } = 8;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 이미지 파일 경로 (편집용, 저장시엔 사용되지 않음)
|
/// 이미지 파일 경로 (편집용, 저장시엔 사용되지 않음)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -343,6 +348,7 @@ namespace AGVNavigationCore.Models
|
|||||||
ForeColor = ForeColor,
|
ForeColor = ForeColor,
|
||||||
BackColor = BackColor,
|
BackColor = BackColor,
|
||||||
ShowBackground = ShowBackground,
|
ShowBackground = ShowBackground,
|
||||||
|
Padding = Padding,
|
||||||
ImagePath = ImagePath,
|
ImagePath = ImagePath,
|
||||||
ImageBase64 = ImageBase64,
|
ImageBase64 = ImageBase64,
|
||||||
Scale = Scale,
|
Scale = Scale,
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user