825 lines
24 KiB
C#
825 lines
24 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.Drawing;
|
|
using System.Drawing.Design;
|
|
using AGVNavigationCore.Models;
|
|
using AGVNavigationCore.Controls;
|
|
|
|
namespace AGVMapEditor.Models
|
|
{
|
|
/// <summary>
|
|
/// 노드 타입에 따른 PropertyWrapper 팩토리
|
|
/// </summary>
|
|
public static class NodePropertyWrapperFactory
|
|
{
|
|
public static object CreateWrapper(MapNode node, List<MapNode> mapNodes)
|
|
{
|
|
switch (node.Type)
|
|
{
|
|
case NodeType.Label:
|
|
return new LabelNodePropertyWrapper(node, mapNodes);
|
|
case NodeType.Image:
|
|
return new ImageNodePropertyWrapper(node, mapNodes);
|
|
default:
|
|
return new NodePropertyWrapper(node, mapNodes);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 라벨 노드 전용 PropertyWrapper
|
|
/// </summary>
|
|
public class LabelNodePropertyWrapper
|
|
{
|
|
private MapNode _node;
|
|
private List<MapNode> _mapNodes;
|
|
|
|
public LabelNodePropertyWrapper(MapNode node, List<MapNode> mapNodes)
|
|
{
|
|
_node = node;
|
|
_mapNodes = mapNodes;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 래핑된 MapNode 인스턴스 접근
|
|
/// </summary>
|
|
public MapNode WrappedNode => _node;
|
|
|
|
[Category("기본 정보")]
|
|
[DisplayName("노드 ID")]
|
|
[Description("노드의 고유 식별자")]
|
|
[ReadOnly(true)]
|
|
public string NodeId
|
|
{
|
|
get => _node.NodeId;
|
|
}
|
|
|
|
[Category("기본 정보")]
|
|
[DisplayName("노드 타입")]
|
|
[Description("노드의 타입")]
|
|
[ReadOnly(true)]
|
|
public NodeType Type
|
|
{
|
|
get => _node.Type;
|
|
}
|
|
|
|
[Category("라벨")]
|
|
[DisplayName("텍스트")]
|
|
[Description("표시할 텍스트")]
|
|
public string LabelText
|
|
{
|
|
get => _node.LabelText;
|
|
set
|
|
{
|
|
_node.LabelText = value ?? "";
|
|
_node.ModifiedDate = DateTime.Now;
|
|
}
|
|
}
|
|
|
|
[Category("라벨")]
|
|
[DisplayName("폰트 패밀리")]
|
|
[Description("폰트 패밀리")]
|
|
public string FontFamily
|
|
{
|
|
get => _node.FontFamily;
|
|
set
|
|
{
|
|
_node.FontFamily = value ?? "Arial";
|
|
_node.ModifiedDate = DateTime.Now;
|
|
}
|
|
}
|
|
|
|
[Category("라벨")]
|
|
[DisplayName("폰트 크기")]
|
|
[Description("폰트 크기")]
|
|
public float FontSize
|
|
{
|
|
get => _node.FontSize;
|
|
set
|
|
{
|
|
_node.FontSize = Math.Max(6, Math.Min(72, value));
|
|
_node.ModifiedDate = DateTime.Now;
|
|
}
|
|
}
|
|
|
|
[Category("라벨")]
|
|
[DisplayName("폰트 스타일")]
|
|
[Description("폰트 스타일")]
|
|
public FontStyle FontStyle
|
|
{
|
|
get => _node.FontStyle;
|
|
set
|
|
{
|
|
_node.FontStyle = value;
|
|
_node.ModifiedDate = DateTime.Now;
|
|
}
|
|
}
|
|
|
|
[Category("라벨")]
|
|
[DisplayName("전경색")]
|
|
[Description("텍스트 색상")]
|
|
public Color ForeColor
|
|
{
|
|
get => _node.ForeColor;
|
|
set
|
|
{
|
|
_node.ForeColor = value;
|
|
_node.ModifiedDate = DateTime.Now;
|
|
}
|
|
}
|
|
|
|
[Category("라벨")]
|
|
[DisplayName("배경색")]
|
|
[Description("배경 색상")]
|
|
public Color BackColor
|
|
{
|
|
get => _node.BackColor;
|
|
set
|
|
{
|
|
_node.BackColor = value;
|
|
_node.ModifiedDate = DateTime.Now;
|
|
}
|
|
}
|
|
|
|
[Category("라벨")]
|
|
[DisplayName("배경 표시")]
|
|
[Description("배경을 표시할지 여부")]
|
|
public bool ShowBackground
|
|
{
|
|
get => _node.ShowBackground;
|
|
set
|
|
{
|
|
_node.ShowBackground = value;
|
|
_node.ModifiedDate = DateTime.Now;
|
|
}
|
|
}
|
|
|
|
[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 좌표")]
|
|
public int PositionX
|
|
{
|
|
get => _node.Position.X;
|
|
set
|
|
{
|
|
_node.Position = new Point(value, _node.Position.Y);
|
|
_node.ModifiedDate = DateTime.Now;
|
|
}
|
|
}
|
|
|
|
[Category("위치")]
|
|
[DisplayName("Y 좌표")]
|
|
[Description("맵에서의 Y 좌표")]
|
|
public int PositionY
|
|
{
|
|
get => _node.Position.Y;
|
|
set
|
|
{
|
|
_node.Position = new Point(_node.Position.X, value);
|
|
_node.ModifiedDate = DateTime.Now;
|
|
}
|
|
}
|
|
|
|
[Category("정보")]
|
|
[DisplayName("생성 일시")]
|
|
[Description("노드가 생성된 일시")]
|
|
[ReadOnly(true)]
|
|
public DateTime CreatedDate
|
|
{
|
|
get => _node.CreatedDate;
|
|
}
|
|
|
|
[Category("정보")]
|
|
[DisplayName("수정 일시")]
|
|
[Description("노드가 마지막으로 수정된 일시")]
|
|
[ReadOnly(true)]
|
|
public DateTime ModifiedDate
|
|
{
|
|
get => _node.ModifiedDate;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 이미지 노드 전용 PropertyWrapper
|
|
/// </summary>
|
|
public class ImageNodePropertyWrapper
|
|
{
|
|
private MapNode _node;
|
|
private List<MapNode> _mapNodes;
|
|
|
|
public ImageNodePropertyWrapper(MapNode node, List<MapNode> mapNodes)
|
|
{
|
|
_node = node;
|
|
_mapNodes = mapNodes;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 래핑된 MapNode 인스턴스 접근
|
|
/// </summary>
|
|
public MapNode WrappedNode => _node;
|
|
|
|
[Category("기본 정보")]
|
|
[DisplayName("노드 ID")]
|
|
[Description("노드의 고유 식별자")]
|
|
[ReadOnly(true)]
|
|
public string NodeId
|
|
{
|
|
get => _node.NodeId;
|
|
}
|
|
|
|
[Category("기본 정보")]
|
|
[DisplayName("노드 타입")]
|
|
[Description("노드의 타입")]
|
|
[ReadOnly(true)]
|
|
public NodeType Type
|
|
{
|
|
get => _node.Type;
|
|
}
|
|
|
|
[Category("이미지")]
|
|
[DisplayName("이미지 경로")]
|
|
[Description("이미지 파일 경로 (... 버튼으로 파일 선택)")]
|
|
[Editor(typeof(ImagePathEditor), typeof(UITypeEditor))]
|
|
public string ImagePath
|
|
{
|
|
get => _node.ImagePath;
|
|
set
|
|
{
|
|
if (string.IsNullOrEmpty(value))
|
|
{
|
|
_node.ImagePath = "";
|
|
return;
|
|
}
|
|
|
|
// 파일이 존재하면 Base64로 변환하여 저장
|
|
if (System.IO.File.Exists(value))
|
|
{
|
|
_node.ConvertImageToBase64(value);
|
|
_node.LoadImage(); // 이미지 다시 로드
|
|
}
|
|
else
|
|
{
|
|
_node.ImagePath = value;
|
|
}
|
|
|
|
_node.ModifiedDate = DateTime.Now;
|
|
}
|
|
}
|
|
|
|
[Category("이미지")]
|
|
[DisplayName("가로 배율")]
|
|
[Description("가로 배율 (1.0 = 원본 크기)")]
|
|
public float ScaleWidth
|
|
{
|
|
get => _node.Scale.Width;
|
|
set
|
|
{
|
|
_node.Scale = new SizeF(Math.Max(0.1f, Math.Min(5.0f, value)), _node.Scale.Height);
|
|
_node.ModifiedDate = DateTime.Now;
|
|
}
|
|
}
|
|
|
|
[Category("이미지")]
|
|
[DisplayName("세로 배율")]
|
|
[Description("세로 배율 (1.0 = 원본 크기)")]
|
|
public float ScaleHeight
|
|
{
|
|
get => _node.Scale.Height;
|
|
set
|
|
{
|
|
_node.Scale = new SizeF(_node.Scale.Width, Math.Max(0.1f, Math.Min(5.0f, value)));
|
|
_node.ModifiedDate = DateTime.Now;
|
|
}
|
|
}
|
|
|
|
[Category("이미지")]
|
|
[DisplayName("투명도")]
|
|
[Description("투명도 (0.0 = 투명, 1.0 = 불투명)")]
|
|
public float Opacity
|
|
{
|
|
get => _node.Opacity;
|
|
set
|
|
{
|
|
_node.Opacity = Math.Max(0.0f, Math.Min(1.0f, value));
|
|
_node.ModifiedDate = DateTime.Now;
|
|
}
|
|
}
|
|
|
|
[Category("이미지")]
|
|
[DisplayName("회전각도")]
|
|
[Description("회전 각도 (도 단위)")]
|
|
public float Rotation
|
|
{
|
|
get => _node.Rotation;
|
|
set
|
|
{
|
|
_node.Rotation = value % 360;
|
|
_node.ModifiedDate = DateTime.Now;
|
|
}
|
|
}
|
|
|
|
[Category("위치")]
|
|
[DisplayName("X 좌표")]
|
|
[Description("맵에서의 X 좌표")]
|
|
public int PositionX
|
|
{
|
|
get => _node.Position.X;
|
|
set
|
|
{
|
|
_node.Position = new Point(value, _node.Position.Y);
|
|
_node.ModifiedDate = DateTime.Now;
|
|
}
|
|
}
|
|
|
|
[Category("위치")]
|
|
[DisplayName("Y 좌표")]
|
|
[Description("맵에서의 Y 좌표")]
|
|
public int PositionY
|
|
{
|
|
get => _node.Position.Y;
|
|
set
|
|
{
|
|
_node.Position = new Point(_node.Position.X, value);
|
|
_node.ModifiedDate = DateTime.Now;
|
|
}
|
|
}
|
|
|
|
[Category("정보")]
|
|
[DisplayName("생성 일시")]
|
|
[Description("노드가 생성된 일시")]
|
|
[ReadOnly(true)]
|
|
public DateTime CreatedDate
|
|
{
|
|
get => _node.CreatedDate;
|
|
}
|
|
|
|
[Category("정보")]
|
|
[DisplayName("수정 일시")]
|
|
[Description("노드가 마지막으로 수정된 일시")]
|
|
[ReadOnly(true)]
|
|
public DateTime ModifiedDate
|
|
{
|
|
get => _node.ModifiedDate;
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// PropertyGrid에서 사용할 노드 속성 래퍼 클래스
|
|
/// </summary>
|
|
public class NodePropertyWrapper
|
|
{
|
|
private MapNode _node;
|
|
private List<MapNode> _mapNodes;
|
|
|
|
public NodePropertyWrapper(MapNode node, List<MapNode> mapNodes)
|
|
{
|
|
_node = node;
|
|
_mapNodes = mapNodes;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 래핑된 MapNode 인스턴스 접근
|
|
/// </summary>
|
|
public MapNode WrappedNode => _node;
|
|
|
|
[Category("기본 정보")]
|
|
[DisplayName("노드 ID")]
|
|
[Description("노드의 고유 식별자")]
|
|
[ReadOnly(true)]
|
|
public string NodeId
|
|
{
|
|
get => _node.NodeId;
|
|
set => _node.NodeId = value;
|
|
}
|
|
|
|
[Category("기본 정보")]
|
|
[DisplayName("노드 이름")]
|
|
[Description("노드의 표시 이름")]
|
|
public string Name
|
|
{
|
|
get => _node.Name;
|
|
set
|
|
{
|
|
_node.Name = value;
|
|
_node.ModifiedDate = DateTime.Now;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
[Category("기본 정보")]
|
|
[DisplayName("노드 타입")]
|
|
[Description("노드의 타입 (Normal, Rotation, Docking, Charging)")]
|
|
public NodeType Type
|
|
{
|
|
get => _node.Type;
|
|
set
|
|
{
|
|
_node.Type = value;
|
|
_node.CanRotate = value == NodeType.Rotation;
|
|
_node.SetDefaultColorByType(value);
|
|
_node.ModifiedDate = DateTime.Now;
|
|
}
|
|
}
|
|
|
|
[Category("기본 정보")]
|
|
[DisplayName("도킹 방향")]
|
|
[Description("도킹이 필요한 노드의 경우 AGV 진입 방향 (DontCare: 방향 무관, Forward: 전진 도킹, Backward: 후진 도킹)")]
|
|
public DockingDirection DockDirection
|
|
{
|
|
get => _node.DockDirection;
|
|
set
|
|
{
|
|
_node.DockDirection = value;
|
|
_node.ModifiedDate = DateTime.Now;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
[Category("위치")]
|
|
[DisplayName("X 좌표")]
|
|
[Description("맵에서의 X 좌표")]
|
|
public int PositionX
|
|
{
|
|
get => _node.Position.X;
|
|
set
|
|
{
|
|
_node.Position = new Point(value, _node.Position.Y);
|
|
_node.ModifiedDate = DateTime.Now;
|
|
}
|
|
}
|
|
|
|
[Category("위치")]
|
|
[DisplayName("Y 좌표")]
|
|
[Description("맵에서의 Y 좌표")]
|
|
public int PositionY
|
|
{
|
|
get => _node.Position.Y;
|
|
set
|
|
{
|
|
_node.Position = new Point(_node.Position.X, value);
|
|
_node.ModifiedDate = DateTime.Now;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
[Category("고급")]
|
|
[DisplayName("회전 가능")]
|
|
[Description("이 노드에서 AGV가 회전할 수 있는지 여부")]
|
|
public bool CanRotate
|
|
{
|
|
get => _node.CanRotate;
|
|
set
|
|
{
|
|
_node.CanRotate = value;
|
|
_node.ModifiedDate = DateTime.Now;
|
|
}
|
|
}
|
|
|
|
[Category("고급")]
|
|
[DisplayName("RFID")]
|
|
[Description("RFID ID")]
|
|
public string RFID
|
|
{
|
|
get => _node.RfidId;
|
|
set
|
|
{
|
|
_node.RfidId = value;
|
|
_node.ModifiedDate = DateTime.Now;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
[Category("고급")]
|
|
[DisplayName("활성화")]
|
|
[Description("노드 활성화 여부")]
|
|
public bool IsActive
|
|
{
|
|
get => _node.IsActive;
|
|
set
|
|
{
|
|
_node.IsActive = value;
|
|
_node.ModifiedDate = DateTime.Now;
|
|
}
|
|
}
|
|
|
|
[Category("표시")]
|
|
[DisplayName("노드 배경색")]
|
|
[Description("노드 배경 색상")]
|
|
public Color DisplayColor
|
|
{
|
|
get => _node.DisplayColor;
|
|
set
|
|
{
|
|
_node.DisplayColor = value;
|
|
_node.ModifiedDate = DateTime.Now;
|
|
}
|
|
}
|
|
|
|
[Category("표시")]
|
|
[DisplayName("글자 색상")]
|
|
[Description("노드 텍스트 색상 (NodeId, Name 등)")]
|
|
public Color ForeColor
|
|
{
|
|
get => _node.ForeColor;
|
|
set
|
|
{
|
|
_node.ForeColor = value;
|
|
_node.ModifiedDate = DateTime.Now;
|
|
}
|
|
}
|
|
|
|
[Category("표시")]
|
|
[DisplayName("글자 크기")]
|
|
[Description("노드 텍스트 크기 (픽셀)")]
|
|
public float TextFontSize
|
|
{
|
|
get => _node.TextFontSize;
|
|
set
|
|
{
|
|
_node.TextFontSize = Math.Max(5.0f, Math.Min(20.0f, value));
|
|
_node.ModifiedDate = DateTime.Now;
|
|
}
|
|
}
|
|
|
|
[Category("표시")]
|
|
[DisplayName("글자 굵게")]
|
|
[Description("노드 텍스트 볼드 표시")]
|
|
public bool TextFontBold
|
|
{
|
|
get => _node.TextFontBold;
|
|
set
|
|
{
|
|
_node.TextFontBold = value;
|
|
_node.ModifiedDate = DateTime.Now;
|
|
}
|
|
}
|
|
|
|
[Category("표시")]
|
|
[DisplayName("이름 말풍선 배경색")]
|
|
[Description("노드 이름 말풍선(하단 표시) 배경색")]
|
|
public Color NameBubbleBackColor
|
|
{
|
|
get => _node.NameBubbleBackColor;
|
|
set
|
|
{
|
|
_node.NameBubbleBackColor = value;
|
|
_node.ModifiedDate = DateTime.Now;
|
|
}
|
|
}
|
|
|
|
[Category("표시")]
|
|
[DisplayName("이름 말풍선 글자색")]
|
|
[Description("노드 이름 말풍선(하단 표시) 글자색")]
|
|
public Color NameBubbleForeColor
|
|
{
|
|
get => _node.NameBubbleForeColor;
|
|
set
|
|
{
|
|
_node.NameBubbleForeColor = value;
|
|
_node.ModifiedDate = DateTime.Now;
|
|
}
|
|
}
|
|
|
|
[Category("정보")]
|
|
[DisplayName("생성 일시")]
|
|
[Description("노드가 생성된 일시")]
|
|
[ReadOnly(true)]
|
|
public DateTime CreatedDate
|
|
{
|
|
get => _node.CreatedDate;
|
|
}
|
|
|
|
[Category("정보")]
|
|
[DisplayName("수정 일시")]
|
|
[Description("노드가 마지막으로 수정된 일시")]
|
|
[ReadOnly(true)]
|
|
public DateTime ModifiedDate
|
|
{
|
|
get => _node.ModifiedDate;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 다중 노드 선택 시 공통 속성 편집용 래퍼
|
|
/// </summary>
|
|
public class MultiNodePropertyWrapper
|
|
{
|
|
private List<MapNode> _nodes;
|
|
|
|
public MultiNodePropertyWrapper(List<MapNode> nodes)
|
|
{
|
|
_nodes = nodes ?? new List<MapNode>();
|
|
}
|
|
|
|
[Category("다중 선택")]
|
|
[DisplayName("선택된 노드 수")]
|
|
[Description("현재 선택된 노드의 개수")]
|
|
[ReadOnly(true)]
|
|
public int SelectedCount => _nodes.Count;
|
|
|
|
[Category("표시")]
|
|
[DisplayName("노드 배경색")]
|
|
[Description("선택된 모든 노드의 배경색을 일괄 변경")]
|
|
public Color DisplayColor
|
|
{
|
|
get => _nodes.Count > 0 ? _nodes[0].DisplayColor : Color.Blue;
|
|
set
|
|
{
|
|
foreach (var node in _nodes)
|
|
{
|
|
node.DisplayColor = value;
|
|
node.ModifiedDate = DateTime.Now;
|
|
}
|
|
}
|
|
}
|
|
|
|
[Category("표시")]
|
|
[DisplayName("글자 색상")]
|
|
[Description("선택된 모든 노드의 글자 색상을 일괄 변경")]
|
|
public Color ForeColor
|
|
{
|
|
get => _nodes.Count > 0 ? _nodes[0].ForeColor : Color.Black;
|
|
set
|
|
{
|
|
foreach (var node in _nodes)
|
|
{
|
|
node.ForeColor = value;
|
|
node.ModifiedDate = DateTime.Now;
|
|
}
|
|
}
|
|
}
|
|
|
|
[Category("표시")]
|
|
[DisplayName("글자 크기")]
|
|
[Description("선택된 모든 노드의 글자 크기를 일괄 변경 (5~20 픽셀)")]
|
|
public float TextFontSize
|
|
{
|
|
get => _nodes.Count > 0 ? _nodes[0].TextFontSize : 7.0f;
|
|
set
|
|
{
|
|
var validValue = Math.Max(5.0f, Math.Min(20.0f, value));
|
|
System.Diagnostics.Debug.WriteLine($"[MultiNode] TextFontSize 변경 시작: {validValue}, 노드 수: {_nodes.Count}");
|
|
|
|
foreach (var node in _nodes)
|
|
{
|
|
System.Diagnostics.Debug.WriteLine($" - 노드 {node.NodeId}: {node.TextFontSize} → {validValue}");
|
|
node.TextFontSize = validValue;
|
|
node.ModifiedDate = DateTime.Now;
|
|
System.Diagnostics.Debug.WriteLine($" - 변경 후: {node.TextFontSize}");
|
|
}
|
|
|
|
System.Diagnostics.Debug.WriteLine($"[MultiNode] TextFontSize 변경 완료");
|
|
}
|
|
}
|
|
|
|
[Category("표시")]
|
|
[DisplayName("글자 굵게")]
|
|
[Description("선택된 모든 노드의 글자 굵기를 일괄 변경")]
|
|
public bool TextFontBold
|
|
{
|
|
get
|
|
{
|
|
var result = _nodes.Count > 0 ? _nodes[0].TextFontBold : true;
|
|
System.Diagnostics.Debug.WriteLine($"[MultiNode] TextFontBold GET: {result}");
|
|
return result;
|
|
}
|
|
set
|
|
{
|
|
System.Diagnostics.Debug.WriteLine($"[MultiNode] TextFontBold 변경 시작: {value}, 노드 수: {_nodes.Count}");
|
|
|
|
foreach (var node in _nodes)
|
|
{
|
|
System.Diagnostics.Debug.WriteLine($" - 노드 {node.NodeId}: {node.TextFontBold} → {value}");
|
|
node.TextFontBold = value;
|
|
node.ModifiedDate = DateTime.Now;
|
|
System.Diagnostics.Debug.WriteLine($" - 변경 후: {node.TextFontBold}");
|
|
}
|
|
|
|
System.Diagnostics.Debug.WriteLine($"[MultiNode] TextFontBold 변경 완료");
|
|
}
|
|
}
|
|
|
|
[Category("표시")]
|
|
[DisplayName("이름 말풍선 배경색")]
|
|
[Description("선택된 모든 노드의 이름 말풍선(하단 표시) 배경색을 일괄 변경")]
|
|
public Color NameBubbleBackColor
|
|
{
|
|
get => _nodes.Count > 0 ? _nodes[0].NameBubbleBackColor : Color.Gold;
|
|
set
|
|
{
|
|
foreach (var node in _nodes)
|
|
{
|
|
node.NameBubbleBackColor = value;
|
|
node.ModifiedDate = DateTime.Now;
|
|
}
|
|
}
|
|
}
|
|
|
|
[Category("표시")]
|
|
[DisplayName("이름 말풍선 글자색")]
|
|
[Description("선택된 모든 노드의 이름 말풍선(하단 표시) 글자색을 일괄 변경")]
|
|
public Color NameBubbleForeColor
|
|
{
|
|
get => _nodes.Count > 0 ? _nodes[0].NameBubbleForeColor : Color.Black;
|
|
set
|
|
{
|
|
foreach (var node in _nodes)
|
|
{
|
|
node.NameBubbleForeColor = value;
|
|
node.ModifiedDate = DateTime.Now;
|
|
}
|
|
}
|
|
}
|
|
|
|
[Category("고급")]
|
|
[DisplayName("활성화")]
|
|
[Description("선택된 모든 노드의 활성화 상태를 일괄 변경")]
|
|
public bool IsActive
|
|
{
|
|
get => _nodes.Count > 0 ? _nodes[0].IsActive : true;
|
|
set
|
|
{
|
|
foreach (var node in _nodes)
|
|
{
|
|
node.IsActive = value;
|
|
node.ModifiedDate = DateTime.Now;
|
|
}
|
|
}
|
|
}
|
|
|
|
[Category("정보")]
|
|
[DisplayName("안내")]
|
|
[Description("다중 선택 시 공통 속성만 변경할 수 있습니다")]
|
|
[ReadOnly(true)]
|
|
public string HelpText => "위 속성을 변경하면 선택된 모든 노드에 일괄 적용됩니다.";
|
|
}
|
|
|
|
/// <summary>
|
|
/// 캔버스 속성 래퍼 (배경색 등 캔버스 전체 속성 편집)
|
|
/// </summary>
|
|
public class CanvasPropertyWrapper
|
|
{
|
|
private UnifiedAGVCanvas _canvas;
|
|
|
|
public CanvasPropertyWrapper(UnifiedAGVCanvas canvas)
|
|
{
|
|
_canvas = canvas;
|
|
}
|
|
|
|
[Category("배경")]
|
|
[DisplayName("배경색")]
|
|
[Description("맵 캔버스 배경색")]
|
|
public Color BackgroundColor
|
|
{
|
|
get => _canvas.BackColor;
|
|
set
|
|
{
|
|
_canvas.BackColor = value;
|
|
_canvas.Invalidate();
|
|
}
|
|
}
|
|
|
|
[Category("그리드")]
|
|
[DisplayName("그리드 표시")]
|
|
[Description("그리드 표시 여부")]
|
|
public bool ShowGrid
|
|
{
|
|
get => _canvas.ShowGrid;
|
|
set
|
|
{
|
|
_canvas.ShowGrid = value;
|
|
_canvas.Invalidate();
|
|
}
|
|
}
|
|
|
|
[Category("정보")]
|
|
[DisplayName("설명")]
|
|
[Description("맵 캔버스 전체 속성")]
|
|
[ReadOnly(true)]
|
|
public string Description
|
|
{
|
|
get => "빈 공간을 클릭하면 캔버스 전체 속성을 편집할 수 있습니다.";
|
|
}
|
|
}
|
|
|
|
} |