첨부 실행 코드는 나눔고딕코딩 폰트를 사용합니다.
728x90
반응형
728x170

TestProject.zip
다운로드

▶ MainWindow.xaml

<Window x:Class="TestProject.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Width="800"
    Height="600"
    Title="지오메트리 디자이너 사용하기"
    FontFamily="나눔고딕코딩"
    FontSize="16">
    <Grid>
        <!-- 화면 가로 영역을 3개로 분할한다 -->
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="210"  />
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="*"    />
        </Grid.ColumnDefinitions>
        <!-- 좌측 화면 영역 -->
        <Grid Grid.Column="0"
            Background="LightGray">
            <!-- 좌측 화면 세로 영역을 3개로 분할한다 -->
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto" />
                <RowDefinition Height="*"    />
                <RowDefinition Height="Auto" />
            </Grid.RowDefinitions>
            <!-- 좌측 화면 상단 영역 -->
            <Border Grid.Row="0"
                Margin="1 1 0 0"
                BorderBrush="Black"
                BorderThickness="1"
                Background="LightYellow">
                <Grid Margin="10">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto" />
                        <RowDefinition Height="Auto" />
                        <RowDefinition Height="Auto" />
                    </Grid.RowDefinitions>
                    <Label Content="단계 1 :" Grid.Row="0"
                        Margin="0 0 0 10"
                        FontWeight="Bold" />
                    <Label Content="지오메트리 타입 선택" Grid.Row="1"
                        Margin="0 0 0 10" />
                    <ComboBox Name="geometryTypeComboBox" Grid.Row="2"
                        HorizontalAlignment="Left"
                        Margin="10 0 0 0"
                        Width="100">
                        <ComboBoxItem>Line</ComboBoxItem>
                        <ComboBoxItem>Ellipse</ComboBoxItem>
                        <ComboBoxItem>Rectangle</ComboBoxItem>
                        <ComboBoxItem>Arc</ComboBoxItem>
                        <ComboBoxItem>Bezier</ComboBoxItem>
                    </ComboBox>
                </Grid>
            </Border>
            <!-- 좌측 화면 중단 영역 -->
            <Border Grid.Row="1"
                Margin="1 1 0 0"
                BorderBrush="Black"
                BorderThickness="1"
                Background="LightYellow">
                <Grid Name="controlPointGrid">
                    <!-- 선 컨트롤 포인트 그리드 -->
                    <Grid Name="lineControlPointGrid"
                        ClipToBounds="True"
                        Visibility="Visible">
                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto" />
                            <RowDefinition Height="Auto" />
                            <RowDefinition Height="Auto" />
                        </Grid.RowDefinitions>
                        <Label Content="단계 2 :" Grid.Row="0"
                            Margin="10 10 0 10"
                            FontWeight="Bold" />
                        <Label Content="선 설정" Grid.Row="1"
                            Margin="10 0 0 10" />
                        <Grid Grid.Row="2">
                            <Grid.RowDefinitions>
                                <RowDefinition Height="Auto" />
                                <RowDefinition Height="Auto" />
                                <RowDefinition Height="Auto" />
                            </Grid.RowDefinitions>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="Auto" />
                                <ColumnDefinition Width="Auto" />
                            </Grid.ColumnDefinitions>
                            <Label Content="시작점" Grid.Row="0" Grid.Column="0"
                                Margin="10 0 0 10" />
                            <TextBox Name="lineStartPointTextBox" Grid.Row="0" Grid.Column="1"
                                Margin="0 0 0 10"
                                Width="100"
                                Height="25"
                                AcceptsTab="False"
                                VerticalContentAlignment="Center" />
                            <Label Content="종료점" Grid.Row="1" Grid.Column="0"
                                Margin="10 0 0 10" />
                            <TextBox Name="lineEndPointTextBox" Grid.Row="1" Grid.Column="1"
                                Margin="0 0 0 10"
                                Width="100"
                                Height="25"
                                AcceptsTab="False"
                                VerticalContentAlignment="Center" />
                            <Button Content="추가" Grid.Row="2" Grid.Column="1"
                                Width="100"
                                Height="30"
                                Click="insertButton_Click" />
                        </Grid>
                    </Grid>
                    <!-- 타원 컨트롤 포인트 그리드 -->
                    <Grid Name="ellipseControlPointGrid"
                        ClipToBounds="True"
                        Visibility="Collapsed">
                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto" />
                            <RowDefinition Height="Auto" />
                            <RowDefinition Height="Auto" />
                        </Grid.RowDefinitions>
                        <Label Content="단계 2 :" Grid.Row="0"
                            Margin="10 10 0 10"
                            FontWeight="Bold" />
                        <Label Content="타원 설정" Grid.Row="1"
                            Margin="10 0 0 10" />
                        <Grid Grid.Row="2">
                            <Grid.RowDefinitions>
                                <RowDefinition Height="Auto" />
                                <RowDefinition Height="Auto" />
                                <RowDefinition Height="Auto" />
                                <RowDefinition Height="Auto" />
                            </Grid.RowDefinitions>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="Auto" />
                                <ColumnDefinition Width="Auto" />
                            </Grid.ColumnDefinitions>
                            <Label Content="중심점" Grid.Row="0" Grid.Column="0"
                                Margin="10 0 0 10" />
                            <TextBox Name="ellipseCenterPointTextBox" Grid.Row="0" Grid.Column="1"
                                Margin="0 0 0 10"
                                Width="100"
                                Height="25"
                                AcceptsTab="False"
                                VerticalContentAlignment="Center" />
                            <Label Content="반경 X" Grid.Row="1" Grid.Column="0"
                                Margin="10 0 0 10" />
                            <TextBox Name="ellipseRadiusXTextBox" Grid.Row="1" Grid.Column="1"
                                Margin="0 0 0 10"
                                Width="100"
                                Height="25"
                                VerticalContentAlignment="Center" />
                            <Label Content="반경 Y" Grid.Row="2" Grid.Column="0"
                                Margin="10 0 0 10" />
                            <TextBox Name="ellipseRadiusYTextBox" Grid.Row="2" Grid.Column="1"
                                Margin="0 0 0 10"
                                Width="100"
                                Height="25"
                                VerticalContentAlignment="Center" />
                            <Button Content="추가" Grid.Row="3" Grid.Column="1"
                                Width="100"
                                Height="30"
                                Click="insertButton_Click" />
                        </Grid>
                    </Grid>
                    <!-- 사각형 컨트롤 포인트 그리드 -->
                    <Grid Name="rectangleControlPointGrid"
                        ClipToBounds="True"
                        Visibility="Collapsed">
                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto" />
                            <RowDefinition Height="Auto" />
                            <RowDefinition Height="Auto" />
                        </Grid.RowDefinitions>
                        <Label Content="단계 2 :" Grid.Row="0"
                            Margin="10 10 0 10"
                            FontWeight="Bold" />
                        <Label Content="사각형 설정" Grid.Row="1"
                            Margin="10 0 0 10" />
                        <Grid Grid.Row="2">
                            <Grid.RowDefinitions>
                                <RowDefinition Height="Auto" />
                                <RowDefinition Height="Auto" />
                                <RowDefinition Height="Auto" />
                                <RowDefinition Height="Auto" />
                                <RowDefinition Height="Auto" />
                                <RowDefinition Height="Auto" />
                            </Grid.RowDefinitions>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="Auto" />
                                <ColumnDefinition Width="Auto" />
                            </Grid.ColumnDefinitions>
                            <Label Content="좌상단점" Grid.Row="0" Grid.Column="0"
                                Margin="10 0 0 10" />
                            <TextBox Name="rectangleTopLeftPointTextBox" Grid.Row="0" Grid.Column="1"
                                Margin="0 0 0 10"
                                Width="100"
                                Height="25"
                                VerticalContentAlignment="Center" />
                            <Label Content="너비" Grid.Row="1" Grid.Column="0"
                                Margin="10 0 0 10" />
                            <TextBox Name="rectangleWidthTextBox" Grid.Row="1" Grid.Column="1"
                                Margin="0 0 0 10"
                                Width="100"
                                Height="25"
                                VerticalContentAlignment="Center" />
                            <Label Content="높이" Grid.Row="2" Grid.Column="0"
                                Margin="10 0 0 10" />
                            <TextBox Name="rectangleHeightTextBox" Grid.Row="2" Grid.Column="1"
                                Margin="0 0 0 10"
                                Width="100"
                                Height="25"
                                VerticalContentAlignment="Center" />
                            <Label Content="반경 X" Grid.Row="3" Grid.Column="0"
                                Margin="10 0 0 10" />
                            <TextBox Name="rectangleRadiusXTextBox" Grid.Row="3" Grid.Column="1"
                                Margin="0 0 0 10"
                                Width="100"
                                Height="25"
                                VerticalContentAlignment="Center" />
                            <Label Content="반경 Y" Grid.Row="4" Grid.Column="0"
                                Margin="10 0 0 10" />
                            <TextBox Name="rectangleRadiusYTextBox" Grid.Row="4" Grid.Column="1"
                                Margin="0 0 0 10"
                                Width="100"
                                Height="25"
                                VerticalContentAlignment="Center" />
                            <Button Content="추가" Grid.Row="5" Grid.Column="1"
                                Width="100"
                                Height="30"
                                Click="insertButton_Click" />
                        </Grid>
                    </Grid>
                    <!-- 베지어 컨트롤 포인트 그리드 -->
                    <Grid Name="bezierControlPointGrid"
                        ClipToBounds="True"
                        Visibility="Collapsed">
                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto" />
                            <RowDefinition Height="Auto" />
                            <RowDefinition Height="Auto" />
                        </Grid.RowDefinitions>
                        <Label Content="단계 2 :" Grid.Row="0"
                            Margin="10 10 0 10"
                            FontWeight="Bold" />
                        <Label Content="베지어 곡선 설정" Grid.Row="1"
                            Margin="10 0 0 10" />
                        <Grid Grid.Row="2">
                            <Grid.RowDefinitions>
                                <RowDefinition Height="Auto" />
                                <RowDefinition Height="Auto" />
                                <RowDefinition Height="Auto" />
                                <RowDefinition Height="Auto" />
                                <RowDefinition Height="Auto" />
                            </Grid.RowDefinitions>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="Auto" />
                                <ColumnDefinition Width="Auto" />
                            </Grid.ColumnDefinitions>
                            <Label Content="시작점" Grid.Row="0" Grid.Column="0"
                                Margin="10 0 0 10" />
                            <TextBox Name="bezierStartPointTextBox" Grid.Row="0" Grid.Column="1"
                                Margin="0 0 0 10"
                                Width="100"
                                Height="25"
                                VerticalContentAlignment="Center" />
                            <Label Content="점 1" Grid.Row="1" Grid.Column="0"
                                Margin="10 0 0 10" />
                            <TextBox Name="bezierPoint1TextBox" Grid.Row="1" Grid.Column="1"
                                Margin="0 0 0 10"
                                Width="100"
                                Height="25"
                                VerticalContentAlignment="Center" />
                            <Label Content="점 2" Grid.Row="2" Grid.Column="0"
                                Margin="10 0 0 10" />
                            <TextBox Name="bezierPoint2TextBox" Grid.Row="2" Grid.Column="1"
                                Margin="0 0 0 10"
                                Width="100"
                                Height="25"
                                VerticalContentAlignment="Center" />
                            <Label Content="점 3" Grid.Row="3" Grid.Column="0"
                                Margin="10 0 0 10" />
                            <TextBox Name="bezierPoint3TextBox" Grid.Row="3" Grid.Column="1"
                                Margin="0 0 0 10"
                                Width="100"
                                Height="25"
                                VerticalContentAlignment="Center" />
                            <Button Content="추가" Grid.Row="4" Grid.Column="1"
                                Width="100"
                                Height="30"
                                Click="insertButton_Click" />
                        </Grid>
                    </Grid>
                    <!-- 호 컨트롤 포인트 그리드 -->
                    <Grid Name="arcControlPointGrid"
                        ClipToBounds="True"
                        Visibility="Collapsed">
                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto" />
                            <RowDefinition Height="Auto" />
                            <RowDefinition Height="Auto" />
                        </Grid.RowDefinitions>
                        <Label Content="단계 2 :" Grid.Row="0"
                            Margin="10 10 0 10"
                            FontWeight="Bold" />
                        <Label Content="호 설정" Grid.Row="1"
                            Margin="10 0 0 10" />
                        <Grid Grid.Row="2">
                            <Grid.RowDefinitions>
                                <RowDefinition Height="Auto" />
                                <RowDefinition Height="Auto" />
                                <RowDefinition Height="Auto" />
                                <RowDefinition Height="Auto" />
                                <RowDefinition Height="Auto" />
                                <RowDefinition Height="Auto" />
                                <RowDefinition Height="Auto" />
                            </Grid.RowDefinitions>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="Auto" />
                                <ColumnDefinition Width="Auto" />
                            </Grid.ColumnDefinitions>
                            <Label Content="시작점" Grid.Row="0" Grid.Column="0"
                                Margin="10 0 0 10" />
                            <TextBox Name="arcStartPointTextBox" Grid.Row="0" Grid.Column="1"
                                Margin="0 0 0 10"
                                Width="100"
                                Height="25"
                                VerticalContentAlignment="Center" />
                            <Label Content="점" Grid.Row="1" Grid.Column="0"
                                Margin="10 0 0 10" />
                            <TextBox Name="arcPointTextBox" Grid.Row="1" Grid.Column="1"
                                Margin="0 0 0 10"
                                Width="100"
                                Height="25"
                                VerticalContentAlignment="Center" />
                            <Label Content="크기" Grid.Row="2" Grid.Column="0"
                                Margin="10 0 0 10" />
                            <TextBox Name="arcSizeTextBox" Grid.Row="2" Grid.Column="1"
                                Margin="0 0 0 10"
                                Width="100"
                                Height="25"
                                VerticalContentAlignment="Center" />
                            <Label Content="X 회전" Grid.Row="3" Grid.Column="0"
                                Margin="10 0 0 10" />
                            <TextBox Name="arcXRotationTextBox" Grid.Row="3" Grid.Column="1"
                                Margin="0 0 0 10"
                                Width="100"
                                Height="25"
                                VerticalContentAlignment="Center" />
                            <Label Content="큰 호" Grid.Row="4" Grid.Column="0"
                                Margin="10 0 0 10" />
                            <ComboBox Name="arcLargeArcComboBox" Grid.Row="4" Grid.Column="1"
                                Margin="0 0 0 10"
                                Width="100"
                                Height="25"
                                SelectedIndex="0">
                                <ComboBoxItem>TRUE</ComboBoxItem>
                                <ComboBoxItem>FALSE</ComboBoxItem>
                            </ComboBox>
                            <Label Content="스윕 방향" Grid.Row="5" Grid.Column="0"
                                Margin="10 0 0 10" />
                            <ComboBox Name="arcSweepArcComboBox" Grid.Row="5" Grid.Column="1"
                                Margin="0 0 0 10"
                                Width="100"
                                Height="25"
                                SelectedIndex="0">
                                <ComboBoxItem>Clockwise</ComboBoxItem>
                                <ComboBoxItem>Counterclockwise</ComboBoxItem>
                            </ComboBox>
                            <Button Content="추가" Grid.Row="6" Grid.Column="1"
                                Width="100"
                                Height="30"
                                Click="insertButton_Click" />
                        </Grid>
                    </Grid>
                </Grid>
            </Border>
            <!-- 좌측 화면 하단 영역 -->
            <Border Grid.Row="2"
                Margin="1 1 0 1"
                BorderBrush="Black"
                BorderThickness="1"
                Background="LightYellow">
                <Grid Margin="10">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto" />
                        <RowDefinition Height="Auto" />
                    </Grid.RowDefinitions>
                    <StackPanel Grid.Row="0"
                        Orientation="Horizontal">
                        <Label Content="단계 3 :"
                            FontWeight="Bold" />
                        <Label Content="XAML 생성" />
                    </StackPanel>
                    <Button Name="showXAMLButton" Grid.Row="1"
                        Margin="0 10 0 0"
                        Width="150"
                        Height="30"
                        Content="XAML 보여주기" />
                </Grid>
            </Border>
        </Grid>
        <!-- 가운데 화면 영역 -->
        <GridSplitter Grid.Column="1"
            HorizontalAlignment="Center"
            VerticalAlignment="Stretch"
            Width="5" />
        <!-- 우측 화면 영역 -->
        <Canvas Name="designerCanvas" Grid.Column="2"
            ClipToBounds="True">
            <Canvas Canvas.Left="0" Canvas.Top="0"
                Width="1000"
                Height="1000">
                <Canvas.Background>
                    <VisualBrush x:Name="LogoBrush"
                        TileMode="Tile"
                        Viewport="0 0 0.3 0.1">
                        <VisualBrush.Visual>
                            <Border Background="Transparent">
                                <TextBlock x:Name="geoText"
                                    Margin="5 5 10 5"
                                    Foreground="LightGray"
                                    FontFamily="Comic Sans MS"
                                    FontSize="14pt"
                                    Text="Geometry Designer" />
                            </Border>
                        </VisualBrush.Visual>
                    </VisualBrush>
                </Canvas.Background>
                <Rectangle
                    Width="{Binding ElementName=designerCanvas, Path=ActualWidth}" 
                    Height="{Binding ElementName=designerCanvas, Path=ActualHeight}">
                    <Rectangle.Fill>
                        <DrawingBrush x:Name="GridBrush"
                            Viewport="0 0 10 10"
                            ViewportUnits="Absolute"
                            TileMode="Tile"
                            Opacity="0">
                            <DrawingBrush.Drawing>
                                <DrawingGroup>
                                    <GeometryDrawing Brush="#ccccff">
                                        <GeometryDrawing.Geometry>
                                            <RectangleGeometry Rect="0 0 10 1" />
                                        </GeometryDrawing.Geometry>
                                    </GeometryDrawing>
                                    <GeometryDrawing Brush="#ccccff">
                                        <GeometryDrawing.Geometry>
                                            <RectangleGeometry Rect="0 0 1 10" />
                                        </GeometryDrawing.Geometry>
                                    </GeometryDrawing>
                                </DrawingGroup>
                            </DrawingBrush.Drawing>
                        </DrawingBrush>
                    </Rectangle.Fill>
                </Rectangle>
                <Canvas Name="drawingCanvas" Canvas.Left="0" Canvas.Top="0"
                    Width="1000"
                    Height="1000">
                </Canvas>
                <Canvas.Triggers>
                    <EventTrigger RoutedEvent="Canvas.Loaded">
                        <BeginStoryboard>
                            <Storyboard>
                                <DoubleAnimation
                                     Storyboard.TargetName="LogoBrush"
                                     Storyboard.TargetProperty="Opacity"
                                     From="1"
                                     To="0"
                                     Duration="0:0:3" />
                                <DoubleAnimation
                                    Storyboard.TargetName="GridBrush"
                                    Storyboard.TargetProperty="Opacity"
                                    From="0"
                                    To="1"
                                    Duration="0:0:3" />
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger>
                </Canvas.Triggers>
            </Canvas>
            <DockPanel Name="xamlDockPanel"
                Width="0"
                Height="0">
                <TextBox Name="xamlTextBox"
                    VerticalAlignment="Stretch"
                    AcceptsReturn="True"
                    AcceptsTab="False"
                    Background="LightYellow"
                    TextWrapping="Wrap" />
            </DockPanel>
        </Canvas>
    </Grid>
</Window>

 

728x90

 

▶ MainWindow.xaml.cs

using System;
using System.Collections;
using System.Globalization;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace TestProject
{
    /// <summary>
    /// 메인 윈도우
    /// </summary>
    public partial class MainWindow : Window
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Class
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region 베이스 정보 - BaseInfo

        /// <summary>
        /// 베이스 정보
        /// </summary>
        public abstract class BaseInfo
        {
            //////////////////////////////////////////////////////////////////////////////////////////////////// Field
            ////////////////////////////////////////////////////////////////////////////////////////// Public

            #region Field

            /// <summary>
            /// 지오메트리 타입
            /// </summary>
            public string GeometryType;

            /// <summary>
            /// 컨트롤 포인트 배열 리스트
            /// </summary>
            public ArrayList ControlPointArrayList;

            #endregion

            ////////////////////////////////////////////////////////////////////////////////////////// Protected

            #region Field

            /// <summary>
            /// 부모 그리드
            /// </summary>
            protected Grid parentGrid;

            #endregion

            //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
            ////////////////////////////////////////////////////////////////////////////////////////// Public

            #region 생성자 - BaseInfo(parentGrid)

            /// <summary>
            /// 생성자
            /// </summary>
            /// <param name="parentGrid">부모 그리드</param>
            public BaseInfo(Grid parentGrid)
            {
                this.parentGrid = parentGrid;
            }

            #endregion

            //////////////////////////////////////////////////////////////////////////////////////////////////// Method
            ////////////////////////////////////////////////////////////////////////////////////////// Public

            #region 파싱하기 - Parse()

            /// <summary>
            /// 파싱하기
            /// </summary>
            public abstract void Parse();

            #endregion
            #region 지오메트리 구하기 - GetGeometry()

            /// <summary>
            /// 지오메트리 구하기
            /// </summary>
            /// <returns>지오메트리</returns>
            public abstract Geometry GetGeometry();

            #endregion

            ////////////////////////////////////////////////////////////////////////////////////////// Protected

            #region 실수 파싱하기 - ParseDouble(source)

            /// <summary>
            /// 실수 파싱하기
            /// </summary>
            /// <param name="source">소스 문자열</param>
            /// <returns>실수</returns>
            protected double ParseDouble(string source)
            {
                return double.Parse(source);
            }

            #endregion
            #region 포인트 파싱하기 - ParsePoint(source)

            /// <summary>
            /// 포인트 파싱하기
            /// </summary>
            /// <param name="source">소스 문자열</param>
            /// <returns>포인트</returns>
            protected Point ParsePoint(string source)
            {
                try
                {
                    return Point.Parse(source);
                }
                catch(Exception exception)
                {
                    MessageBox.Show(exception.ToString());

                    throw new ApplicationException("에러 : 콤마나 공백으로 구분되는 2개 숫자 값을 입력해 주시기 바랍니다.");
                }
            }

            #endregion
            #region 크기 파싱하기 - ParseSize(source)

            /// <summary>
            /// 크기 파싱하기
            /// </summary>
            /// <param name="source">소스 문자열</param>
            /// <returns>크기</returns>
            protected Size ParseSize(string source)
            {
                Size size = new Size();

                string[] sizeString = source.Split(new char[] { ' ', ',', ';' });

                if(sizeString.Length == 0 || sizeString.Length != 2)
                {
                    throw new ApplicationException("에러 : 콤마나 공백으로 구분되는 2개 숫자 값을 입력해 주시기 바랍니다.");
                }

                try
                {
                    double width  = Convert.ToDouble(sizeString[0], CultureInfo.InvariantCulture);
                    double height = Convert.ToDouble(sizeString[1], CultureInfo.InvariantCulture);

                    size.Width  = width;
                    size.Height = height;
                }
                catch(Exception exception)
                {
                    MessageBox.Show(exception.ToString());

                    throw new ApplicationException("에러 : 콤마나 공백으로 구분되는 2개 숫자 값을 입력해 주시기 바랍니다.");
                }

                return size;
            }

            #endregion
        }

        #endregion
        #region 선 정보 - LineInfo

        /// <summary>
        /// 선 정보
        /// </summary>
        public class LineInfo : BaseInfo
        {
            //////////////////////////////////////////////////////////////////////////////////////////////////// Field
            ////////////////////////////////////////////////////////////////////////////////////////// Private

            #region Field

            /// <summary>
            /// 시작점
            /// </summary>
            private Point startPoint;

            /// <summary>
            /// 종료점
            /// </summary>
            private Point endPoint;

            #endregion

            //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
            ////////////////////////////////////////////////////////////////////////////////////////// Public

            #region 생성자 - LineInfo(parentGrid)

            /// <summary>
            /// 생성자
            /// </summary>
            /// <param name="parentGrid">부모 그리드</param>
            public LineInfo(Grid parentGrid) : base(parentGrid)
            {
                GeometryType          = "Line";
                ControlPointArrayList = new ArrayList();

                Parse(); 
            }

            #endregion

            //////////////////////////////////////////////////////////////////////////////////////////////////// Method
            ////////////////////////////////////////////////////////////////////////////////////////// Public

            #region 파싱하기 - Parse()

            /// <summary>
            /// 파싱하기
            /// </summary>
            public override void Parse()
            {
                TextBox lineStartPointTextBox = LogicalTreeHelper.FindLogicalNode(parentGrid, "lineStartPointTextBox") as TextBox;
                TextBox lineEndPointTextBox   = LogicalTreeHelper.FindLogicalNode(parentGrid, "lineEndPointTextBox"  ) as TextBox;

                this.startPoint = ParsePoint(lineStartPointTextBox.Text);
                this.endPoint   = ParsePoint(lineEndPointTextBox.Text);

                ControlPointArrayList.Add(this.startPoint);
                ControlPointArrayList.Add(this.endPoint  );
            }

            #endregion
            #region 지오메트리 구하기 - GetGeometry()

            /// <summary>
            /// 지오메트리 구하기
            /// </summary>
            /// <returns>지오메트리</returns>
            public override Geometry GetGeometry()
            {
                LineGeometry lineGeometry = new LineGeometry(this.startPoint, this.endPoint);

                return lineGeometry;
            }

            #endregion
        }

        #endregion
        #region 타원 정보 - EllipseInfo

        /// <summary>
        /// 타원 정보
        /// </summary>
        public class EllipseInfo : BaseInfo
        {
            //////////////////////////////////////////////////////////////////////////////////////////////////// Field
            ////////////////////////////////////////////////////////////////////////////////////////// Private

            #region Field

            /// <summary>
            /// 중심점
            /// </summary>
            private Point centerPoint;

            /// <summary>
            /// 반경 X
            /// </summary>
            private double radiusX;

            /// <summary>
            /// 반경 Y
            /// </summary>
            private double radiusY;

            #endregion

            //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
            ////////////////////////////////////////////////////////////////////////////////////////// Public

            #region 생성자 - EllipseInfo(parentGrid)

            /// <summary>
            /// 생성자
            /// </summary>
            /// <param name="parentGrid">부모 그리드</param>
            public EllipseInfo(Grid parentGrid) : base(parentGrid)
            {
                GeometryType          = "Ellipse";
                ControlPointArrayList = new ArrayList();

                Parse();
            }

            #endregion

            //////////////////////////////////////////////////////////////////////////////////////////////////// Method
            ////////////////////////////////////////////////////////////////////////////////////////// Public

            #region 파싱하기 - Parse()

            /// <summary>
            /// 파싱하기
            /// </summary>
            public override void Parse()
            {
                TextBox centerPointTextBox = LogicalTreeHelper.FindLogicalNode(parentGrid, "ellipseCenterPointTextBox") as TextBox;
                TextBox radiusXTextBox     = LogicalTreeHelper.FindLogicalNode(parentGrid, "ellipseRadiusXTextBox"    ) as TextBox;
                TextBox radiusYTextBox     = LogicalTreeHelper.FindLogicalNode(parentGrid, "ellipseRadiusYTextBox"    ) as TextBox;

                this.centerPoint  = ParsePoint (centerPointTextBox.Text);
                this.radiusX = ParseDouble(radiusXTextBox.Text    );
                this.radiusY = ParseDouble(radiusYTextBox.Text    );

                ControlPointArrayList.Add(centerPoint);

                // 좌상단
                ControlPointArrayList.Add(new Point(centerPoint.X - radiusX , centerPoint.Y));

                // 중상단
                ControlPointArrayList.Add(new Point(centerPoint.X , centerPoint.Y - radiusY));

                // 우상단
                ControlPointArrayList.Add(new Point(centerPoint.X + radiusX, centerPoint.Y));

                // 중하단
                ControlPointArrayList.Add(new Point(centerPoint.X , centerPoint.Y + radiusY));
            }

            #endregion
            #region 지오메트리 구하기 - GetGeometry()

            /// <summary>
            /// 지오메트리 구하기
            /// </summary>
            /// <returns>지오메트리</returns>
            public override Geometry GetGeometry()
            {
                EllipseGeometry ellipseGeometry = new EllipseGeometry
                (
                    this.centerPoint,
                    this.radiusX,
                    this.radiusY
                );

                return ellipseGeometry;
            }

            #endregion
        }

        #endregion
        #region 사각형 정보 - RectanlgeInfo

        /// <summary>
        /// 사각형 정보
        /// </summary>
        public class RectanlgeInfo : BaseInfo
        {
            //////////////////////////////////////////////////////////////////////////////////////////////////// Method
            ////////////////////////////////////////////////////////////////////////////////////////// Private

            #region Field

            /// <summary>
            /// 좌상단점
            /// </summary>
            private Point topLeftPoint;

            /// <summary>
            /// 너비
            /// </summary>
            private double width;

            /// <summary>
            /// 높이
            /// </summary>
            private double height;

            /// <summary>
            /// 반경 X
            /// </summary>
            private double radiusX;

            /// <summary>
            /// 반경 Y
            /// </summary>
            private double radiusY;

            #endregion

            //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
            ////////////////////////////////////////////////////////////////////////////////////////// Public

            #region 생성자 - RectanlgeInfo(parentGrid)

            /// <summary>
            /// 생성자
            /// </summary>
            /// <param name="parentGrid">부모 그리드</param>
            public RectanlgeInfo(Grid parentGrid) : base(parentGrid)
            {
                GeometryType          = "Rectangle";
                ControlPointArrayList = new ArrayList();

                Parse();
            }

            #endregion

            //////////////////////////////////////////////////////////////////////////////////////////////////// Method
            ////////////////////////////////////////////////////////////////////////////////////////// Public

            #region 파싱하기 - Parse()

            /// <summary>
            /// 파싱하기
            /// </summary>
            public override void Parse()
            {
                TextBox topLeftPointTextBox = LogicalTreeHelper.FindLogicalNode(parentGrid, "rectangleTopLeftPointTextBox") as TextBox;
                TextBox radiusXTextBox      = LogicalTreeHelper.FindLogicalNode(parentGrid, "rectangleRadiusXTextBox"     ) as TextBox;
                TextBox radiusYTextBox      = LogicalTreeHelper.FindLogicalNode(parentGrid, "rectangleRadiusYTextBox"     ) as TextBox;
                TextBox widthTextBox        = LogicalTreeHelper.FindLogicalNode(parentGrid, "rectangleWidthTextBox"       ) as TextBox;
                TextBox heightTextBox       = LogicalTreeHelper.FindLogicalNode(parentGrid, "rectangleHeightTextBox"      ) as TextBox;

                this.topLeftPoint = ParsePoint (topLeftPointTextBox.Text);
                this.radiusX      = ParseDouble(radiusXTextBox.Text     );
                this.radiusY      = ParseDouble(radiusYTextBox.Text     );
                this.width        = ParseDouble(widthTextBox.Text       );
                this.height       = ParseDouble(heightTextBox.Text      );

                ControlPointArrayList.Add(topLeftPoint);

                // 우상단
                ControlPointArrayList.Add(new Point(topLeftPoint.X + width, topLeftPoint.Y));

                // 좌하단
                ControlPointArrayList.Add(new Point(topLeftPoint.X, topLeftPoint.Y + height));

                // 우하단
                ControlPointArrayList.Add(new Point(topLeftPoint.X + width, topLeftPoint.Y + height));

                if(radiusX != 0 && radiusY != 0)
                {
                    ControlPointArrayList.Add(new Point(topLeftPoint.X + radiusX, topLeftPoint.Y + radiusY));
                }
            }

            #endregion
            #region 지오메트리 구하기 - GetGeometry()

            /// <summary>
            /// 지오메트리 구하기
            /// </summary>
            /// <returns>지오메트리</returns>
            public override Geometry GetGeometry()
            {
                RectangleGeometry rectangleGeometry = new RectangleGeometry
                (
                    new Rect
                    (
                        topLeftPoint.X,
                        topLeftPoint.Y,
                        width,
                        height
                    ),
                    radiusX,
                    radiusY
                );
                
                return rectangleGeometry;
            }

            #endregion
        }

        #endregion
        #region 베지어 곡선 정보 - BezierCurveInfo

        /// <summary>
        /// 베지어 곡선 정보
        /// </summary>
        public class BezierCurveInfo : BaseInfo
        {
            //////////////////////////////////////////////////////////////////////////////////////////////////// Field
            ////////////////////////////////////////////////////////////////////////////////////////// Private

            #region Field

            /// <summary>
            /// 시작점
            /// </summary>
            private Point startpoint;
            
            /// <summary>
            /// 포인트 1
            /// </summary>
            private Point point1;
            
            /// <summary>
            /// 포인트 2
            /// </summary>
            private Point point2;
            
            /// <summary>
            /// 포인트 3
            /// </summary>
            private Point point3;

            #endregion

            //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
            ////////////////////////////////////////////////////////////////////////////////////////// Public

            #region 생성자 - BezierCurveInfo(parentGrid)

            /// <summary>
            /// 생성자
            /// </summary>
            /// <param name="parentGrid">부모 그리드</param>
            public BezierCurveInfo(Grid parentGrid) : base(parentGrid)
            {
                GeometryType          = "Bezier";
                ControlPointArrayList = new ArrayList();

                Parse();
            }

            #endregion

            //////////////////////////////////////////////////////////////////////////////////////////////////// Method
            ////////////////////////////////////////////////////////////////////////////////////////// Public

            #region 파싱하기 - Parse()

            /// <summary>
            /// 파싱하기
            /// </summary>
            public override void Parse()
            {
                TextBox sartPointTextBox = LogicalTreeHelper.FindLogicalNode(parentGrid, "bezierStartPointTextBox") as TextBox;
                TextBox point1TextBox    = LogicalTreeHelper.FindLogicalNode(parentGrid, "bezierPoint1TextBox"    ) as TextBox;
                TextBox point2TextBox    = LogicalTreeHelper.FindLogicalNode(parentGrid, "bezierPoint2TextBox"    ) as TextBox;
                TextBox point3TextBox    = LogicalTreeHelper.FindLogicalNode(parentGrid, "bezierPoint31TextBox"   ) as TextBox;

                this.startpoint = ParsePoint(sartPointTextBox.Text);
                this.point1     = ParsePoint(point1TextBox.Text   );
                this.point2     = ParsePoint(point2TextBox.Text   );
                this.point3     = ParsePoint(point3TextBox.Text   );

                ControlPointArrayList.Add(startpoint);
                ControlPointArrayList.Add(point1);
                ControlPointArrayList.Add(point2);
                ControlPointArrayList.Add(point3);
            }

            #endregion
            #region 지오메트리 구하기 - GetGeometry()

            /// <summary>
            /// 지오메트리 구하기
            /// </summary>
            /// <returns>지오메트리</returns>
            public override Geometry GetGeometry()
            {
                PathGeometry pathGeometry = new PathGeometry();

                PathFigure pathFigure = new PathFigure();

                pathFigure.StartPoint = startpoint;

                pathFigure.Segments.Add(new BezierSegment(point1, point2, point3, true));

                pathGeometry.Figures.Add(pathFigure);

                return pathGeometry;
            }

            #endregion
        }

        #endregion
        #region 호 정보 - ArcInfo

        /// <summary>
        /// 호 정보
        /// </summary>
        public class ArcInfo : BaseInfo
        {
            //////////////////////////////////////////////////////////////////////////////////////////////////// Field
            ////////////////////////////////////////////////////////////////////////////////////////// Private

            #region Field

            /// <summary>
            /// 시작점
            /// </summary>
            private Point startPoint;
            
            /// <summary>
            /// 포인트
            /// </summary>
            private Point point;

            /// <summary>
            /// 크기
            /// </summary>
            private Size size;

            /// <summary>
            /// 큰 호 여부
            /// </summary>
            private bool largeArc;

            /// <summary>
            /// 스윕 방향
            /// </summary>
            private SweepDirection sweepDirection;

            /// <summary>
            /// X 회전
            /// </summary>
            private double xRotation;

            #endregion

            //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
            ////////////////////////////////////////////////////////////////////////////////////////// Public

            #region 생성자 - ArcInfo(parentGrid)

            /// <summary>
            /// 생성자
            /// </summary>
            /// <param name="parentGrid">부모 그리드</param>
            public ArcInfo(Grid parentGrid) : base(parentGrid)
            {
                GeometryType          = "Arc";
                ControlPointArrayList = new ArrayList();

                Parse();
            }

            #endregion

            //////////////////////////////////////////////////////////////////////////////////////////////////// Method
            ////////////////////////////////////////////////////////////////////////////////////////// Public

            #region 파싱하기 - Parse()

            /// <summary>
            /// 파싱하기
            /// </summary>
            public override void Parse()
            {
                TextBox  startPointTextBox = LogicalTreeHelper.FindLogicalNode(parentGrid, "arcStartPointTextBox") as TextBox;
                TextBox  pointTextBox      = LogicalTreeHelper.FindLogicalNode(parentGrid, "arcPointTextBox"     ) as TextBox;
                TextBox  sizeTextBox       = LogicalTreeHelper.FindLogicalNode(parentGrid, "arcSizeTextBox"      ) as TextBox;
                TextBox  xRotationTextBox  = LogicalTreeHelper.FindLogicalNode(parentGrid, "arcXRotationTextBox" ) as TextBox;
                ComboBox largeArcComboBox  = LogicalTreeHelper.FindLogicalNode(parentGrid, "arcLargeArcComboBox" ) as ComboBox;
                ComboBox sweepArcComboBox  = LogicalTreeHelper.FindLogicalNode(parentGrid, "arcSweepArcComboBox" ) as ComboBox;

                this.startPoint     = ParsePoint (startPointTextBox.Text);
                this.point          = ParsePoint (pointTextBox.Text     );
                this.size           = ParseSize  (sizeTextBox.Text      );
                this.xRotation      = ParseDouble(xRotationTextBox.Text );
                this.largeArc       = bool.Parse(((string)((ComboBoxItem)largeArcComboBox.SelectedItem).Content));
                this.sweepDirection = (SweepDirection)Enum.Parse
                (
                    typeof(SweepDirection), 
                    ((string)((ComboBoxItem)sweepArcComboBox.SelectedItem).Content)
                );

                ControlPointArrayList.Add(startPoint);
                ControlPointArrayList.Add(point     );
            }

            #endregion
            #region 지오메트리 구하기 - GetGeometry()

            /// <summary>
            /// 지오메트리 구하기
            /// </summary>
            /// <returns>지오메트리</returns>
            public override Geometry GetGeometry()
            {
                PathGeometry pathGeometry = new PathGeometry();

                PathFigure pathFigure = new PathFigure();

                pathFigure.StartPoint = startPoint;

                pathFigure.Segments.Add(new ArcSegment(point, size, xRotation, largeArc, sweepDirection, true));

                pathGeometry.Figures.Add(pathFigure);

                return pathGeometry;
            }

            #endregion
        }

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Field
        ////////////////////////////////////////////////////////////////////////////////////////// Static
        //////////////////////////////////////////////////////////////////////////////// Private

        #region Field

        /// <summary>
        /// 컨트롤 포인트 마커 너비
        /// </summary>
        private static double CONTROL_POINT_MARKER_WIDTH = 20;

        /// <summary>
        /// 컨트롤 포인트 마커 높이
        /// </summary>
        private static double CONTROL_POINT_MARKER_HEIGHT = 20;

        #endregion

        ////////////////////////////////////////////////////////////////////////////////////////// Private

        #region Field

        /// <summary>
        /// 초기 선택
        /// </summary>
        private bool initialSelection = true;

        /// <summary>
        /// 선 카운트
        /// </summary>
        private int lineCount = 1;

        /// <summary>
        /// 타원 카운트
        /// </summary>
        private int elliipseCount = 1;

        /// <summary>
        /// 사각형 카운트
        /// </summary>
        private int rectangleCount = 1;

        /// <summary>
        /// 베지어 카운트
        /// </summary>
        private int bezierCount = 1;

        /// <summary>
        /// 호 카운트
        /// </summary>
        private int arcCount = 1;

        /// <summary>
        /// 현재 패스
        /// </summary>
        private Path currentPath = null;

        /// <summary>
        /// 추가 여부
        /// </summary>
        private bool isInsert = true;

        /// <summary>
        /// XAML 표시 여부
        /// </summary>
        private bool isXAMLShow = false;

        /// <summary>
        /// 타원 이동 여부
        /// </summary>
        private bool isEllipseMoving = false;

        /// <summary>
        /// 타원 이동 마지막 포인트
        /// </summary>
        private Point ellipseMovingLastPoint;

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region 생성자 - MainWindow()

        /// <summary>
        /// 생성자
        /// </summary>
        public MainWindow()
        {
            InitializeComponent();

            ContentRendered                            += Window_ContentRendered;
            this.geometryTypeComboBox.SelectionChanged += geometryTypeComboBox_SelectionChanged;
            this.showXAMLButton.Click                  += showXAMLButton_Click;

            this.geometryTypeComboBox.SelectedIndex = 0;
        }

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method
        ////////////////////////////////////////////////////////////////////////////////////////// Private
        //////////////////////////////////////////////////////////////////////////////// Event

        #region 윈도우 컨텐트 렌더링 후 처리하기 - Window_ContentRendered(sender, e)

        /// <summary>
        /// 윈도우 컨텐트 렌더링 후 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void Window_ContentRendered(object sender, EventArgs e)
        {
            SizeChanged                    += Window_SizeChanged;
            this.designerCanvas.MouseLeave += designerCanvas_MouseLeave;
        }

        #endregion
        #region 윈도우 크기 변경시 처리하기 - Window_SizeChanged(sender, e)

        /// <summary>
        /// 윈도우 크기 변경시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void Window_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            this.xamlDockPanel.BeginAnimation(Canvas.TopProperty, null);

            if(this.isXAMLShow)
            {
                this.xamlDockPanel.SetValue(Canvas.TopProperty, e.NewSize.Height - 70);
            }
            else
            {
                this.xamlDockPanel.SetValue(Canvas.TopProperty, e.NewSize.Height);
            }

            this.xamlDockPanel.Width = e.NewSize.Width - 215;
        }

        #endregion
        #region 지오메트리 타입 콤보 박스 선택 변경시 처리하기 - geometryTypeComboBox_SelectionChanged(sender, e)

        /// <summary>
        /// 지오메트리 타입 콤보 박스 선택 변경시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void geometryTypeComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            ComboBox comboBox = sender as ComboBox;

            if(this.initialSelection)
            {
                this.initialSelection = !this.initialSelection;
            }
            else
            {
                ComboBoxItem item = (ComboBoxItem)comboBox.SelectedItem;

                string geometryType = item.Content as string;

                ChangeControlPointGrid(geometryType, true);
            }
        }

        #endregion
        #region 추가 버튼 클릭시 처리하기 - insertButton_Click(sender, e)

        /// <summary>
        /// 추가 버튼 클릭시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void insertButton_Click(object sender, RoutedEventArgs e)
        {
            Button button = sender as Button;

            Grid controlPointGrid = (button.Parent as Grid).Parent as Grid;

            try
            {
                if(this.isInsert)
                {
                    Path path = new Path();

                    path.Stroke          = Brushes.Black;
                    path.StrokeThickness = 2;

                    BaseInfo baseInfo = GetBaseInfo(controlPointGrid);

                    switch(baseInfo.GeometryType)
                    {
                        case "Line" :

                            path.Name = "Line" + this.lineCount;

                            AddControlPoint(baseInfo.ControlPointArrayList, "Line");

                            this.lineCount++;

                            break;

                        case "Rectangle" :

                            path.Name = "Rectangle" + this.rectangleCount;

                            AddControlPoint(baseInfo.ControlPointArrayList, "Rectangle");

                            this.rectangleCount++;                            

                            break;

                        case "Ellipse" :

                            path.Name = "Ellipse" + this.elliipseCount;

                            AddControlPoint(baseInfo.ControlPointArrayList, "Ellipse");

                            this.elliipseCount++;

                            break;

                        case "Arc" :

                            path.Name = "Arc" + this.arcCount;

                            AddControlPoint(baseInfo.ControlPointArrayList, "Arc");

                            this.arcCount++;

                            break;

                        case "Bezier" :

                            path.Name = "Bezier" + this.bezierCount;

                            AddControlPoint(baseInfo.ControlPointArrayList, "Bezier");

                            this.bezierCount++;

                            break;

                        default :

                            throw new ApplicationException("에러 : 부정확한 지오메트리 타입");
                    }

                    path.Data = baseInfo.GetGeometry();

                    path.MouseEnter += path_MouseEnter;

                    this.currentPath = path;

                    this.drawingCanvas.Children.Add(path);

                    button.Content = "갱신";

                    this.isInsert = !this.isInsert;
                }
                else
                {
                    BaseInfo baseInfo = GetBaseInfo(controlPointGrid);

                    this.currentPath.Data = baseInfo.GetGeometry();

                    UpdateControlPoint(baseInfo.ControlPointArrayList);
                }
            }
            catch(ApplicationException exception)
            {
                MessageBox.Show(exception.Message);
            }
        }

        #endregion
        #region XAML 보여주기 버튼 클릭시 처리하기 - showXAMLButton_Click(sender, e)

        /// <summary>
        /// XAML 보여주기 버튼 클릭시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void showXAMLButton_Click(object sender, RoutedEventArgs e)
        {
            Button button = sender as Button;

            string xaml = XamlWriter.Save(drawingCanvas);

            this.xamlTextBox.Text = xaml;

            if(!this.isXAMLShow)
            {
                this.isXAMLShow = !this.isXAMLShow;

                this.xamlDockPanel.Width  = this.ActualWidth - 215;
                this.xamlDockPanel.Height = 50;

                double locationY = this.designerCanvas.ActualHeight;

                this.xamlDockPanel.SetValue(Canvas.LeftProperty, this.designerCanvas.GetValue(Canvas.LeftProperty));

                this.xamlDockPanel.SetValue(Canvas.TopProperty, locationY);

                button.Content = "XAML 숨기기";

                DoubleAnimation doubleAnimation = new DoubleAnimation();

                doubleAnimation.FillBehavior = FillBehavior.HoldEnd;
                doubleAnimation.To           = locationY - 50;
                doubleAnimation.Duration     = TimeSpan.FromMilliseconds(500);

                this.xamlDockPanel.BeginAnimation(Canvas.TopProperty, doubleAnimation);
            }
            else
            {
                this.isXAMLShow = !this.isXAMLShow;

                button.Content = "XAML 보여주기";

                DoubleAnimation doubleAnimation = new DoubleAnimation();

                doubleAnimation.FillBehavior = FillBehavior.HoldEnd;
                doubleAnimation.From         = this.designerCanvas.ActualHeight - 50;
                doubleAnimation.To           = this.designerCanvas.ActualHeight;
                doubleAnimation.Duration     = TimeSpan.FromMilliseconds(500);

                this.xamlDockPanel.BeginAnimation(Canvas.TopProperty, doubleAnimation);
            }
        }

        #endregion

        #region 디자이너 캔버스 마우스 이탈시 처리하기 - designerCanvas_MouseLeave(sender, e)

        /// <summary>
        /// 디자이너 캔버스 마우스 이탈시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void designerCanvas_MouseLeave(object sender, MouseEventArgs e)
        {
            foreach(object element in designerCanvas.Children)
            {
                if(element is Ellipse)
                {
                    ((Ellipse)element).Visibility = Visibility.Hidden;
                }
            }
        }

        #endregion
        #region 패스 마우스 진입시 처리하기 - path_MouseEnter(sender, e)

        /// <summary>
        /// 패스 마우스 진입시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void path_MouseEnter(object sender, MouseEventArgs e)
        {
            Path path = sender as Path;

            string pathID = path.Name;

            foreach(object element in this.designerCanvas.Children)
            {
                if(element is Ellipse ellipse)
                {
                    if(ellipse.Name.Contains(pathID))
                    {
                        ellipse.Visibility = Visibility.Visible;
                    }
                    else 
                    {
                        ellipse.Visibility = Visibility.Hidden;
                    }
                }
            }
        }

        #endregion
        #region 타원 마우스 왼쪽 버튼 DOWN 처리하기 - ellipse_MouseLeftButtonDown(sender, e)

        /// <summary>
        /// 타원 마우스 왼쪽 버튼 DOWN 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void ellipse_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            Ellipse ellipse = sender as Ellipse;

            ellipse.Cursor = Cursors.Hand;

            this.isEllipseMoving = true;

            this.ellipseMovingLastPoint = e.GetPosition(this.drawingCanvas);
        }

        #endregion
        #region 타원 마우스 이동시 처리하기 - ellipse_MouseMove(sender, e)

        /// <summary>
        /// 타원 마우스 이동시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void ellipse_MouseMove(object sender, MouseEventArgs e)
        {
            Ellipse ellipse = sender as Ellipse;

            Point mousePoint;

            if(this.isEllipseMoving)
            {
                mousePoint = e.GetPosition(this.drawingCanvas);

                Canvas.SetLeft(ellipse, mousePoint.X - ellipse.Width  / 2);
                Canvas.SetTop (ellipse, mousePoint.Y - ellipse.Height / 2);
                
                UpdatePath(mousePoint, ellipse.Name);

                this.ellipseMovingLastPoint = mousePoint;
            }
        }

        #endregion
        #region 타원 마우스 왼쪽 버튼 UP 처리하기 - ellipse_MouseLeftButtonUp(sender, e)

        /// <summary>
        /// 타원 마우스 왼쪽 버튼 UP 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void ellipse_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            Ellipse ellipse = sender as Ellipse;

            ellipse.Cursor = Cursors.Arrow;

            this.isEllipseMoving = false;
        }

        #endregion

        //////////////////////////////////////////////////////////////////////////////// Function

        #region 컨트롤 포인트 그리드명 구하기 - GetControlPointGridName(geometryType)

        /// <summary>
        /// 컨트롤 포인트 그리드명 구하기
        /// </summary>
        /// <param name="geometryType">지오메트리 타입</param>
        /// <returns>컨트롤 포인트 그리드명</returns>
        private string GetControlPointGridName(string geometryType)
        {
            switch(geometryType)
            {
                case "Line"      : return "lineControlPointGrid";
                case "Ellipse"   : return "ellipseControlPointGrid";
                case "Rectangle" : return "rectangleControlPointGrid";
                case "Bezier"    : return "bezierControlPointGrid";
                case "Arc"       : return "arcControlPointGrid";
            }

            return null;
        }

        #endregion
        #region 컨트롤 포인트 그리드 변경하기 - ChangeControlPointGrid(geometryType, allowInsert)

        /// <summary>
        /// 컨트롤 포인트 그리드 변경하기
        /// </summary>
        /// <param name="geometryType">지오메트리 타입</param>
        /// <param name="allowInsert">추가 허용 여부</param>
        private void ChangeControlPointGrid(string geometryType, bool allowInsert)
        {
            string gridName = GetControlPointGridName(geometryType);

            foreach(Grid grid in this.controlPointGrid.Children)
            {
                Grid containerGrid = grid.Children[2] as Grid;

                if(string.Compare(grid.Name, gridName, false, CultureInfo.InvariantCulture) == 0)
                {
                    grid.Visibility = Visibility.Visible;

                    if(allowInsert)
                    {
                        foreach(object child in containerGrid.Children)
                        {
                            if(child is TextBox)
                            {
                                ((TextBox)child).Text = string.Empty;

                                continue;
                            }

                            if
                            (
                                child is Button                   &&
                                ((Button)child).Content is string &&
                                ((string)((Button)child).Content == "추가" || (string)((Button)child).Content == "갱신")
                            )
                            {
                                ((Button)child).IsEnabled = true;

                                ((Button)child).Content = "추가";

                                this.isInsert = true;
                            }
                        }
                    }
                    else
                    {
                        foreach(object child in containerGrid.Children)
                        {
                            if
                            (
                                child is Button                   &&
                                ((Button)child).Content is string &&
                                (string)((Button)child).Content == "추가"
                            )
                            {
                                ((Button)child).IsEnabled = false;
                            }
                        }
                    }
                }
                else
                {
                    grid.Visibility = Visibility.Collapsed;
                }
            }
        }

        #endregion
        #region 베이스 정보 구하기 - GetBaseInfo(parentGrid)

        /// <summary>
        /// 베이스 정보 구하기
        /// </summary>
        /// <param name="parentGrid">부모 그리드</param>
        /// <returns>베이스 정보</returns>
        private BaseInfo GetBaseInfo(Grid parentGrid)
        {
            switch(parentGrid.Name.Remove(parentGrid.Name.LastIndexOf("ControlPointGrid")))
            {
                case "line"      : return new LineInfo(parentGrid);
                case "ellipse"   : return new EllipseInfo(parentGrid);
                case "rectangle" : return new RectanlgeInfo(parentGrid);
                case "bezier"    : return new BezierCurveInfo(parentGrid);
                case "arc"       : return new ArcInfo(parentGrid);
                default          : throw  new ApplicationException("에러 : 부정확한 부모 그리드명");
            }
        }

        #endregion

        #region 선 컨트롤 포인트 추가하기 - AddLineControlPoint(controlPointArrayList)

        /// <summary>
        /// 선 컨트롤 포인트 추가하기
        /// </summary>
        /// <param name="controlPointArrayList">컨트롤 포인트 배열 리스트</param>
        private void AddLineControlPoint(ArrayList controlPointArrayList)
        {
            if(controlPointArrayList.Count != 2)
            {
                throw new ApplicationException("에러 : 부정확한 컨트롤 포인트 수");
            }

            for(int i = 0; i < controlPointArrayList.Count; i++)
            {
                Ellipse ellipse = new Ellipse();

                ellipse.Width           = 3;
                ellipse.Height          = 3;
                ellipse.Stroke          = Brushes.Black;
                ellipse.StrokeThickness = 1;
                ellipse.Fill            = Brushes.White;
                ellipse.Opacity         = 0.5;
                ellipse.Visibility      = Visibility.Hidden;

                if(i == 0)
                {
                    ellipse.Name = "Line" + this.lineCount + "_StartPoint";
                }
                else
                {
                    ellipse.Name = "Line" + this.lineCount + "_EndPoint";
                }

                ellipse.Width  = CONTROL_POINT_MARKER_WIDTH;
                ellipse.Height = CONTROL_POINT_MARKER_HEIGHT;

                Canvas.SetLeft(ellipse, ((Point)controlPointArrayList[i]).X - ellipse.Width  / 2); 
                Canvas.SetTop (ellipse, ((Point)controlPointArrayList[i]).Y - ellipse.Height / 2);

                ellipse.MouseLeftButtonDown += ellipse_MouseLeftButtonDown;
                ellipse.MouseLeftButtonUp   += ellipse_MouseLeftButtonUp;
                ellipse.MouseMove           += ellipse_MouseMove;

                this.designerCanvas.Children.Insert(this.designerCanvas.Children.Count - 1, ellipse);
            }
        }

        #endregion
        #region 타원 컨트롤 포인트 추가하기 - AddEllipseControlPoint(controlPoints)

        /// <summary>
        /// 타원 컨트롤 포인트 추가하기
        /// </summary>
        /// <param name="controlPointArrayList">컨트롤 포인트 배열 리스트</param>
        private void AddEllipseControlPoint(ArrayList controlPointArrayList)
        {
            if(controlPointArrayList.Count != 5)
            {
                throw new System.ApplicationException("에러 : 부정확한 컨트롤 포인트 수");
            }

            for(int i = 0; i < controlPointArrayList.Count; i++)
            {
                Ellipse ellipse = new Ellipse();

                ellipse.Width           = 3;
                ellipse.Height          = 3;
                ellipse.Stroke          = Brushes.Black;
                ellipse.StrokeThickness = 1;
                ellipse.Fill            = Brushes.White;
                ellipse.Opacity         = 0.5;
                ellipse.Visibility      = Visibility.Hidden;

                switch(i)
                {
                    case 0  : ellipse.Name = "Ellipse" + this.elliipseCount + "_Center";       break;
                    case 1  : ellipse.Name = "Ellipse" + this.elliipseCount + "_TopLeft";      break;
                    case 2  : ellipse.Name = "Ellipse" + this.elliipseCount + "_TopMiddle";    break;
                    case 3  : ellipse.Name = "Ellipse" + this.elliipseCount + "_TopRight";     break;
                    case 4  : ellipse.Name = "Ellipse" + this.elliipseCount + "_BottomMiddle"; break;
                    default : throw new ApplicationException("에러 : 부정확한 컨트롤 포인트");
                }

                ellipse.Width  = CONTROL_POINT_MARKER_WIDTH;
                ellipse.Height = CONTROL_POINT_MARKER_HEIGHT;

                Canvas.SetLeft(ellipse, ((Point)controlPointArrayList[i]).X - ellipse.Width  / 2);
                Canvas.SetTop (ellipse, ((Point)controlPointArrayList[i]).Y - ellipse.Height / 2);
      
                ellipse.MouseLeftButtonDown += ellipse_MouseLeftButtonDown;
                ellipse.MouseLeftButtonUp   += ellipse_MouseLeftButtonUp;
                ellipse.MouseMove           += ellipse_MouseMove;

                this.designerCanvas.Children.Insert(this.designerCanvas.Children.Count - 1, ellipse);
            }
        }

        #endregion
        #region 사각형 컨트롤 포인트 추가하기 - AddRectangleControlPoint(controlPointArrayList)

        /// <summary>
        /// 사각형 컨트롤 포인트 추가하기
        /// </summary>
        /// <param name="controlPointArrayList">컨트롤 포인트 배열 리스트</param>
        private void AddRectangleControlPoint(ArrayList controlPointArrayList)
        {
            if(controlPointArrayList.Count != 5 && controlPointArrayList.Count != 4)
            {
                throw new ApplicationException("에러 : 부정확한 컨트롤 포인트 수");
            }

            for(int i = 0; i < controlPointArrayList.Count; i++)
            {
                Ellipse ellipse = new Ellipse();

                ellipse.Width           = 3;
                ellipse.Height          = 3;
                ellipse.Stroke          = Brushes.Black;
                ellipse.StrokeThickness = 1;
                ellipse.Fill            = Brushes.White;
                ellipse.Opacity         = 0.5;
                ellipse.Visibility      = Visibility.Hidden;

                switch(i)
                {
                    case 0  : ellipse.Name = "Rectangle" + this.rectangleCount + "_TopLeft";     break;
                    case 1  : ellipse.Name = "Rectangle" + this.rectangleCount + "_TopRight";    break;
                    case 2  : ellipse.Name = "Rectangle" + this.rectangleCount + "_BottomLeft";  break;
                    case 3  : ellipse.Name = "Rectangle" + this.rectangleCount + "_BottomRight"; break;
                    case 4  : ellipse.Name = "Rectangle" + this.rectangleCount + "_Corner";      break;
                    default : throw new ApplicationException("에러 : 부정확한 컨트롤 포인트");
                }

                ellipse.Width  = CONTROL_POINT_MARKER_WIDTH;
                ellipse.Height = CONTROL_POINT_MARKER_HEIGHT;

                Canvas.SetLeft(ellipse, ((Point)controlPointArrayList[i]).X - ellipse.Width  / 2);
                Canvas.SetTop (ellipse, ((Point)controlPointArrayList[i]).Y - ellipse.Height / 2);

                ellipse.MouseLeftButtonDown += ellipse_MouseLeftButtonDown;
                ellipse.MouseLeftButtonUp   += ellipse_MouseLeftButtonUp;
                ellipse.MouseMove           += ellipse_MouseMove;

                this.designerCanvas.Children.Insert(this.designerCanvas.Children.Count - 1, ellipse);
            }
        }

        #endregion
        #region 베지어 곡선 컨트롤 포인트 추가하기 - AddBezierCurveControlPoint(controlPointArrayList)

        /// <summary>
        /// 베지어 곡선 컨트롤 포인트 추가하기
        /// </summary>
        /// <param name="controlPointArrayList">컨트롤 포인트 배열 리스트</param>
        private void AddBezierCurveControlPoint(ArrayList controlPointArrayList)
        {
            if(controlPointArrayList.Count != 4)
            {
                throw new ApplicationException("에러 : 부정확한 컨트롤 포인트 수");
            }

            for(int i = 0; i < controlPointArrayList.Count; i++)
            {
                Ellipse ellipse = new Ellipse();

                ellipse.Width           = 3;
                ellipse.Height          = 3;
                ellipse.Stroke          = Brushes.Black;
                ellipse.StrokeThickness = 1;
                ellipse.Fill            = Brushes.White;
                ellipse.Opacity         = 0.5;
                ellipse.Visibility      = Visibility.Hidden;

                switch(i)
                {
                    case 0  : ellipse.Name = "Bezier" + this.bezierCount + "_StartPoint"; break;
                    case 1  : ellipse.Name = "Bezier" + this.bezierCount + "_Point1";     break;
                    case 2  : ellipse.Name = "Bezier" + this.bezierCount + "_Point2";     break;
                    case 3  : ellipse.Name = "Bezier" + this.bezierCount + "_Point3";     break;
                    default : throw new ApplicationException("에러 : 부정확한 컨트롤 포인트");
                }

                ellipse.Width  = CONTROL_POINT_MARKER_WIDTH;
                ellipse.Height = CONTROL_POINT_MARKER_HEIGHT;

                Canvas.SetLeft(ellipse, ((Point)controlPointArrayList[i]).X - ellipse.Width  / 2);
                Canvas.SetTop (ellipse, ((Point)controlPointArrayList[i]).Y - ellipse.Height / 2);

                ellipse.MouseLeftButtonDown += ellipse_MouseLeftButtonDown;
                ellipse.MouseLeftButtonUp   += ellipse_MouseLeftButtonUp;
                ellipse.MouseMove           += ellipse_MouseMove;

                this.designerCanvas.Children.Insert(this.designerCanvas.Children.Count - 1, ellipse);
            }
        }

        #endregion
        #region 호 컨트롤 포인트 추가하기 - AddArcControlPoint(controlPointArrayList)

        /// <summary>
        /// 호 컨트롤 포인트 추가하기
        /// </summary>
        /// <param name="controlPointArrayList">컨트롤 포인트 배열 리스트</param>
        private void AddArcControlPoint(ArrayList controlPointArrayList)
        {
            if(controlPointArrayList.Count != 2)
            {
                throw new ApplicationException("에러 : 부정확한 컨트롤 포인트 수");
            }

            for(int i = 0; i < controlPointArrayList.Count; i++)
            {
                Ellipse ellipse = new Ellipse();

                ellipse.Width           = 3;
                ellipse.Height          = 3;
                ellipse.Stroke          = Brushes.Black;
                ellipse.StrokeThickness = 1;
                ellipse.Fill            = Brushes.White;
                ellipse.Opacity         = 0.5;
                ellipse.Visibility      = Visibility.Hidden;

                switch(i)
                {
                    case 0  : ellipse.Name = "Arc" + this.arcCount + "_StartPoint"; break;
                    case 1  : ellipse.Name = "Arc" + this.arcCount + "_Point";      break;
                    default : throw new System.ApplicationException("에러 : 부정확한 컨트롤 포인트");
                }

                ellipse.Width  = CONTROL_POINT_MARKER_WIDTH;
                ellipse.Height = CONTROL_POINT_MARKER_HEIGHT;

                Canvas.SetLeft(ellipse, ((Point)controlPointArrayList[i]).X - ellipse.Width  / 2);
                Canvas.SetTop (ellipse, ((Point)controlPointArrayList[i]).Y - ellipse.Height / 2);
                
                ellipse.MouseLeftButtonDown += ellipse_MouseLeftButtonDown;
                ellipse.MouseLeftButtonUp   += ellipse_MouseLeftButtonUp;
                ellipse.MouseMove           += ellipse_MouseMove;
                
                this.designerCanvas.Children.Insert(this.designerCanvas.Children.Count - 1, ellipse);
            }
        }

        #endregion
        #region 컨트롤 포인트 추가하기 - AddControlPoint(controlPointArrayList, geometryType)

        /// <summary>
        /// 컨트롤 포인트 추가하기
        /// </summary>
        /// <param name="controlPointArrayList">컨트롤 포인트 배열 리스트</param>
        /// <param name="geometryType">지오메트리 타입</param>
        private void AddControlPoint(ArrayList controlPointArrayList, string geometryType)
        {
            switch(geometryType)
            {
                case "Line"      : AddLineControlPoint       (controlPointArrayList); break;
                case "Ellipse"   : AddEllipseControlPoint    (controlPointArrayList); break;
                case "Rectangle" : AddRectangleControlPoint  (controlPointArrayList); break;
                case "Bezier"    : AddBezierCurveControlPoint(controlPointArrayList); break;
                case "Arc"       : AddArcControlPoint        (controlPointArrayList); break;
                default          : throw new ApplicationException("에러 : 부정확한 지오메트리 타입");
            }
        }

        #endregion
        #region 지오메트리 타입 구하기 - GetGeometryType(id)

        /// <summary>
        /// 지오메트리 타입 구하기
        /// </summary>
        /// <param name="id">ID</param>
        /// <returns>지오메트리 타입</returns>
        private string GetGeometryType(string id)
        {
            string[] tokenArray = id.Split('_');

            if(tokenArray[0].Contains("Line"))
            {
                return "Line";
            }
            else
            {
                if(tokenArray[0].Contains("Ellipse"))
                {
                    return "Ellipse";
                }
                else
                {
                    if(tokenArray[0].Contains("Rectangle"))
                    {
                        return "Rectangle";
                    }
                    else
                    {
                        if(tokenArray[0].Contains("Bezier"))
                        {
                            return "Bezier";
                        }
                        else
                        {
                            return "Arc";
                        }
                    }
                }
            }
        }

        #endregion

        #region 패스 구하기 - GetPath(pathName)

        /// <summary>
        /// 패스 구하기
        /// </summary>
        /// <param name="pathName">패스명</param>
        /// <returns>패스</returns>
        private Path GetPath(string pathName)
        {
            foreach(object element in this.drawingCanvas.Children)
            {
                if(element is Path && ((Path)element).Name == pathName)
                {
                    return element as Path;
                }
            }

            return null;
        }

        #endregion
        #region 선 패스 갱신하기 - UpdateLinePath(mousePoint, id)

        /// <summary>
        /// 선 패스 갱신하기
        /// </summary>
        /// <param name="mousePoint">마우스 포인트</param>
        /// <param name="id">ID</param>
        private void UpdateLinePath(Point mousePoint, string id)
        {
            string[] tokenArray       = id.Split('_');
            string   pathName         = tokenArray[0];
            string   controlPointType = tokenArray[1];

            Path path = GetPath(pathName);

            if(path == null)
            {
                throw new ApplicationException("에러 : 부정확한 지오메트리 ID");
            }

            this.currentPath = path;

            LineGeometry lineGeometry = path.Data as LineGeometry;

            switch(controlPointType)
            {
                case "StartPoint" :

                    this.lineStartPointTextBox.Text = mousePoint.X + " " + mousePoint.Y;

                    lineGeometry.StartPoint = mousePoint;
                    
                    break;

                case "EndPoint" :

                    this.lineEndPointTextBox.Text = mousePoint.X + " " + mousePoint.Y;

                    lineGeometry.EndPoint = mousePoint;
                    
                    break;

                default :

                    throw new ApplicationException($"에러 : 부정확한 컨트롤 포인트 타입({controlPointType}");
            }
        }

        #endregion
        #region 타원 패스 갱신하기 - UpdateEllipsePath(mousePoint, id)

        /// <summary>
        /// 타원 패스 갱신하기
        /// </summary>
        /// <param name="mousePoint">마우스 포인트</param>
        /// <param name="id">ID</param>
        private void UpdateEllipsePath(Point mousePoint, string id)
        {
            string[] tokenArray       = id.Split('_');
            string   pathName         = tokenArray[0];
            string   controlPointType = tokenArray[1];

            Path path = GetPath(pathName);

            if(path == null)
            {
                throw new ApplicationException("에러 : 부정확한 지오메트리 ID");
            }

            this.currentPath = path;

            EllipseGeometry ellipseGeometry = path.Data.Clone() as EllipseGeometry;

            double deltaX = mousePoint.X - ellipseGeometry.Center.X;
            double deltaY = mousePoint.Y - ellipseGeometry.Center.Y;

            double radian = Math.Atan2(deltaY, deltaX);
            double angle  = radian * (180 / Math.PI);

            switch(controlPointType)
            {
                case "Center" :
                {
                    ellipseGeometry.Center = mousePoint;

                    if(ellipseGeometry.Transform != null && ellipseGeometry.Transform is RotateTransform)
                    {
                        RotateTransform transform = ellipseGeometry.Transform as RotateTransform;

                        transform.CenterX = ellipseGeometry.Center.X;
                        transform.CenterY = ellipseGeometry.Center.Y;
                    }

                    foreach(object element in this.designerCanvas.Children)
                    {
                        if
                        (
                            element is Ellipse                              &&
                            ((Ellipse)element).Name.Contains(tokenArray[0]) &&
                            ((Ellipse)element).Name != tokenArray[0]
                        )
                        {
                            Canvas.SetLeft(((Ellipse)element), Canvas.GetLeft(((Ellipse)element)) + deltaX);
                            Canvas.SetTop (((Ellipse)element), Canvas.GetTop (((Ellipse)element)) + deltaY);
                        }
                    }

                    path.Data = ellipseGeometry;

                    this.ellipseCenterPointTextBox.Text = ellipseGeometry.Center.X + " " + ellipseGeometry.Center.Y;

                    break;
                }  
                case "TopLeft" :
                {
                    Vector deltaVector = new Vector(deltaX, deltaY);

                    RotateTransform transform = new RotateTransform
                    (
                        angle + 180,
                        ellipseGeometry.Center.X,
                        ellipseGeometry.Center.Y
                    );

                    ellipseGeometry.Transform = transform;
                    ellipseGeometry.RadiusX   = deltaVector.Length;

                    this.ellipseRadiusXTextBox.Text = deltaVector.Length.ToString();

                    path.Data = ellipseGeometry;

                    Ellipse topRightEllipse = (Ellipse)LogicalTreeHelper.FindLogicalNode
                    (
                        this.designerCanvas,
                        tokenArray[0] + "_TopRight"
                    );

                    Canvas.SetLeft
                    (
                        topRightEllipse,
                        (ellipseGeometry.Center.X - deltaX) - topRightEllipse.Width / 2
                    );

                    Canvas.SetTop
                    (
                        topRightEllipse,
                        (ellipseGeometry.Center.Y - deltaY) - topRightEllipse.Height / 2
                    );

                    Ellipse topMiddleEllipse = (Ellipse)LogicalTreeHelper.FindLogicalNode
                    (
                        this.designerCanvas,
                        tokenArray[0] + "_TopMiddle"
                    );

                    Canvas.SetLeft
                    (
                        topMiddleEllipse,
                        (ellipseGeometry.Center.X - deltaY * ellipseGeometry.RadiusY / deltaVector.Length) -
                            topMiddleEllipse.Width / 2
                    );

                    Canvas.SetTop
                    (
                        topMiddleEllipse,
                        (ellipseGeometry.Center.Y + deltaX * ellipseGeometry.RadiusY / deltaVector.Length) -
                            topMiddleEllipse.Height / 2
                    );

                    Ellipse bottomMiddleEllipse = (Ellipse)LogicalTreeHelper.FindLogicalNode
                    (
                        this.designerCanvas,
                        tokenArray[0] + "_BottomMiddle"
                    );

                    Canvas.SetLeft
                    (
                        bottomMiddleEllipse,
                        (ellipseGeometry.Center.X + deltaY * ellipseGeometry.RadiusY / deltaVector.Length) -
                            bottomMiddleEllipse.Width / 2
                    );

                    Canvas.SetTop
                    (
                        bottomMiddleEllipse,
                        (ellipseGeometry.Center.Y - deltaX * ellipseGeometry.RadiusY / deltaVector.Length) -
                            bottomMiddleEllipse.Height / 2
                    );

                    break;
                }
                case "TopMiddle" :
                {
                    Vector deltaVector = new Vector(deltaX, deltaY);

                    RotateTransform transform = new RotateTransform
                    (
                        angle + 90,
                        ellipseGeometry.Center.X,
                        ellipseGeometry.Center.Y
                    );

                    ellipseGeometry.Transform = transform;
                    ellipseGeometry.RadiusY   = deltaVector.Length;

                    this.ellipseRadiusYTextBox.Text = deltaVector.Length.ToString();

                    path.Data = ellipseGeometry;

                    Ellipse topLeftEllipse = (Ellipse)LogicalTreeHelper.FindLogicalNode
                    (
                        this.designerCanvas,
                        tokenArray[0] + "_TopLeft"
                    );

                    Canvas.SetLeft
                    (
                        topLeftEllipse,
                        (ellipseGeometry.Center.X + deltaY * ellipseGeometry.RadiusX / deltaVector.Length) -
                            topLeftEllipse.Width / 2
                    );

                    Canvas.SetTop
                    (
                        topLeftEllipse,
                        (ellipseGeometry.Center.Y - deltaX * ellipseGeometry.RadiusX / deltaVector.Length) -
                            topLeftEllipse.Height /2
                    );

                    Ellipse topRightEllipse = (Ellipse)LogicalTreeHelper.FindLogicalNode
                    (
                        this.designerCanvas,
                        tokenArray[0] + "_TopRight"
                    );

                    Canvas.SetLeft
                    (
                        topRightEllipse,
                        (ellipseGeometry.Center.X - deltaY * ellipseGeometry.RadiusX / deltaVector.Length) -
                            topRightEllipse.Width / 2
                    );

                    Canvas.SetTop
                    (
                        topRightEllipse,
                        (ellipseGeometry.Center.Y + deltaX * ellipseGeometry.RadiusX / deltaVector.Length) -
                            topRightEllipse.Height / 2
                    );

                    Ellipse bottomMiddleEllipse = (Ellipse)LogicalTreeHelper.FindLogicalNode
                    (
                        this.designerCanvas,
                        tokenArray[0] + "_BottomMiddle"
                    );

                    Canvas.SetLeft
                    (
                        bottomMiddleEllipse,
                        (ellipseGeometry.Center.X - deltaX) - bottomMiddleEllipse.Width / 2
                    );

                    Canvas.SetTop
                    (
                        bottomMiddleEllipse,
                        (ellipseGeometry.Center.Y - deltaY) - bottomMiddleEllipse.Height / 2
                    );

                    break;
                }
                case "TopRight" :
                {
                    Vector deltaVector = new Vector(deltaX, deltaY);

                    RotateTransform transform = new RotateTransform
                    (
                        angle,
                        ellipseGeometry.Center.X,
                        ellipseGeometry.Center.Y
                    );

                    ellipseGeometry.Transform = transform;
                    ellipseGeometry.RadiusX   = deltaVector.Length;

                    this.ellipseRadiusXTextBox.Text = deltaVector.Length.ToString();

                    path.Data = ellipseGeometry;

                    Ellipse topLeftEllipse = (Ellipse)LogicalTreeHelper.FindLogicalNode
                    (
                        this.designerCanvas,
                        tokenArray[0] + "_TopLeft"
                    );

                    Canvas.SetLeft
                    (
                        topLeftEllipse,
                        (ellipseGeometry.Center.X - deltaX) - topLeftEllipse.Width / 2
                    );

                    Canvas.SetTop
                    (
                        topLeftEllipse,
                        (ellipseGeometry.Center.Y - deltaY) - topLeftEllipse.Height / 2
                    );

                    Ellipse topMiddleEllipse = (Ellipse)LogicalTreeHelper.FindLogicalNode
                    (
                        this.designerCanvas,
                        tokenArray[0] + "_TopMiddle"
                    );

                    Canvas.SetLeft
                    (
                        topMiddleEllipse,
                        (ellipseGeometry.Center.X + deltaY * ellipseGeometry.RadiusY / deltaVector.Length) -
                            topMiddleEllipse.Width / 2
                    );

                    Canvas.SetTop
                    (
                        topMiddleEllipse,
                        (ellipseGeometry.Center.Y - deltaX * ellipseGeometry.RadiusY / deltaVector.Length) -
                            topMiddleEllipse.Height / 2
                    );

                    Ellipse bottomMiddleEllipse = (Ellipse)LogicalTreeHelper.FindLogicalNode
                    (
                        this.designerCanvas,
                        tokenArray[0] + "_BottomMiddle"
                    );

                    Canvas.SetLeft
                    (
                        bottomMiddleEllipse,
                        (ellipseGeometry.Center.X - deltaY * ellipseGeometry.RadiusY / deltaVector.Length) -
                            bottomMiddleEllipse.Width / 2
                    );

                    Canvas.SetTop
                    (
                        bottomMiddleEllipse,
                        (ellipseGeometry.Center.Y + deltaX * ellipseGeometry.RadiusY / deltaVector.Length) -
                            bottomMiddleEllipse.Height / 2
                    );

                    break;
                }  
                case "BottomMiddle" :
                {
                    Vector deltaVector = new Vector(deltaX, deltaY);

                    RotateTransform transform = new RotateTransform
                    (
                        angle - 90,
                        ellipseGeometry.Center.X,
                        ellipseGeometry.Center.Y
                    );

                    ellipseGeometry.Transform = transform;
                    ellipseGeometry.RadiusY   = deltaVector.Length;

                    this.ellipseRadiusYTextBox.Text = deltaVector.Length.ToString();

                    path.Data = ellipseGeometry;

                    Ellipse topLeftEllipse = (Ellipse)LogicalTreeHelper.FindLogicalNode
                    (
                        this.designerCanvas,
                        tokenArray[0] + "_TopLeft"
                    );

                    Canvas.SetLeft
                    (
                        topLeftEllipse,
                        (ellipseGeometry.Center.X - deltaY * ellipseGeometry.RadiusX / deltaVector.Length) -
                            topLeftEllipse.Width / 2
                    );

                    Canvas.SetTop
                    (
                        topLeftEllipse,
                        (ellipseGeometry.Center.Y + deltaX * ellipseGeometry.RadiusX / deltaVector.Length) -
                            topLeftEllipse.Height / 2
                    );

                    Ellipse topRightEllipse = (Ellipse)LogicalTreeHelper.FindLogicalNode
                    (
                        this.designerCanvas,
                        tokenArray[0] + "_TopRight"
                    );

                    Canvas.SetLeft
                    (
                        topRightEllipse,
                        (ellipseGeometry.Center.X + deltaY * ellipseGeometry.RadiusX / deltaVector.Length) -
                            topRightEllipse.Width / 2
                    );

                    Canvas.SetTop
                    (
                        topRightEllipse,
                        (ellipseGeometry.Center.Y - deltaX * ellipseGeometry.RadiusX / deltaVector.Length) -
                            topRightEllipse.Height / 2
                    );

                    Ellipse topMiddleEllipse = (Ellipse)LogicalTreeHelper.FindLogicalNode
                    (
                        this.designerCanvas,
                        tokenArray[0] + "_TopMiddle"
                    );

                    Canvas.SetLeft
                    (
                        topMiddleEllipse,
                        (ellipseGeometry.Center.X - deltaX) - topMiddleEllipse.Width / 2
                    );

                    Canvas.SetTop
                    (
                        topMiddleEllipse,
                        (ellipseGeometry.Center.Y - deltaY) - topMiddleEllipse.Height / 2
                    );

                    break;
                }   
                default :
                {
                    throw new ApplicationException($"에러 : 부정확한 컨트롤 포인트 타입({controlPointType}");
                }
            }
        }

        #endregion
        #region 사각형 패스 갱신하기 - UpdateRectanglePath(mousePoint, id)

        /// <summary>
        /// 사각형 패스 갱신하기
        /// </summary>
        /// <param name="mousePoint">마우스 포인트</param>
        /// <param name="id">id</param>
        private void UpdateRectanglePath(Point mousePoint, string id)
        {
            double width;
            double height;

            string[] tokenArray       = id.Split('_');
            string   pathName         = tokenArray[0];
            string   controlPointType = tokenArray[1];

            Path path = GetPath(pathName);

            if(path == null)
            {
                throw new ApplicationException("에러 : 부정확한 지오메트리 ID");
            }

            this.currentPath = path;

            RectangleGeometry rectangleGeometry = path.Data as RectangleGeometry;

            Ellipse topLeftEllipse = (Ellipse)LogicalTreeHelper.FindLogicalNode
            (
                this.designerCanvas,
                tokenArray[0] + "_TopLeft"
            );

            Ellipse topRightEllipse = (Ellipse)LogicalTreeHelper.FindLogicalNode
            (
                this.designerCanvas,
                tokenArray[0] + "_TopRight"
            );

            Ellipse bottomLeftEllipse = (Ellipse)LogicalTreeHelper.FindLogicalNode
            (
                this.designerCanvas,
                tokenArray[0] + "_BottomLeft"
            );

            Ellipse bottomRightEllipse = (Ellipse)LogicalTreeHelper.FindLogicalNode
            (
                this.designerCanvas,
                tokenArray[0] + "_BottomRight"
            );

            Ellipse cornerEllipse = (Ellipse)LogicalTreeHelper.FindLogicalNode
            (
                this.designerCanvas,
                tokenArray[0] + "_Corner"
            );

            switch(controlPointType)
            {
                case "TopLeft" :
                {
                    width  = rectangleGeometry.Rect.Width  + (rectangleGeometry.Rect.X - mousePoint.X);
                    height = rectangleGeometry.Rect.Height + (rectangleGeometry.Rect.Y - mousePoint.Y);

                    this.rectangleWidthTextBox.Text  = width.ToString();
                    this.rectangleHeightTextBox.Text = height.ToString();

                    rectangleGeometry.Rect = new Rect(mousePoint.X, mousePoint.Y, width, height);

                    Canvas.SetLeft
                    (
                        topRightEllipse,
                        (mousePoint.X + width) - topRightEllipse.Width / 2
                    );

                    Canvas.SetTop
                    (
                        topRightEllipse,
                        (mousePoint.Y) - topRightEllipse.Height / 2
                    );

                    Canvas.SetLeft
                    (
                        bottomLeftEllipse,
                        mousePoint.X - bottomLeftEllipse.Width / 2
                    );

                    if(cornerEllipse != null)
                    {
                        Canvas.SetLeft
                        (
                            cornerEllipse,
                            mousePoint.X + rectangleGeometry.RadiusX - cornerEllipse.Width / 2
                        );

                        Canvas.SetTop
                        (
                            cornerEllipse,
                            mousePoint.Y + rectangleGeometry.RadiusY - cornerEllipse.Height / 2
                        );
                    }
                    
                    this.rectangleTopLeftPointTextBox.Text = mousePoint.X + " " + mousePoint.Y;

                    break;
                }
                case "TopRight" :
                {
                    width  = mousePoint.X - rectangleGeometry.Rect.X;
                    height = (rectangleGeometry.Rect.Y + rectangleGeometry.Rect.Height) - mousePoint.Y;

                    this.rectangleWidthTextBox.Text  = width.ToString();
                    this.rectangleHeightTextBox.Text = height.ToString();

                    Canvas.SetTop
                    (
                        topLeftEllipse,
                        mousePoint.Y - topLeftEllipse.Height / 2
                    );

                    Canvas.SetLeft
                    (
                        bottomRightEllipse,
                        mousePoint.X - bottomRightEllipse.Width / 2
                    );
                    
                    if(cornerEllipse != null)
                    {
                        Canvas.SetTop
                        (
                            cornerEllipse,
                            Canvas.GetTop(cornerEllipse) + (mousePoint.Y - rectangleGeometry.Rect.Y) -
                                cornerEllipse.Height / 2
                        );
                    }

                    rectangleGeometry.Rect = new Rect
                    (
                        Canvas.GetLeft(topLeftEllipse) + topLeftEllipse.Width  / 2,
                        Canvas.GetTop (topLeftEllipse) + topLeftEllipse.Height / 2,
                        width,
                        height
                    );

                    this.rectangleTopLeftPointTextBox.Text = mousePoint.X + " " + mousePoint.Y;

                    break;
                }
                case "BottomLeft" :
                {
                    width  = rectangleGeometry.Rect.Width + (rectangleGeometry.Rect.X - mousePoint.X);
                    height = mousePoint.Y - rectangleGeometry.Rect.Y;

                    this.rectangleWidthTextBox.Text  = width.ToString();
                    this.rectangleHeightTextBox.Text = height.ToString();

                    Canvas.SetLeft
                    (
                        topLeftEllipse,
                        mousePoint.X - topLeftEllipse.Width / 2
                    );

                    Canvas.SetLeft
                    (
                        bottomRightEllipse,
                        mousePoint.X + width - bottomRightEllipse.Width / 2
                    );

                    Canvas.SetTop
                    (
                        bottomRightEllipse,
                        mousePoint.Y - bottomRightEllipse.Height / 2
                    );
                    
                    if(cornerEllipse != null)
                    {
                        Canvas.SetLeft
                        (
                            cornerEllipse,
                            mousePoint.X + rectangleGeometry.RadiusX - cornerEllipse.Width / 2
                        );
                    }

                    this.rectangleTopLeftPointTextBox.Text = Canvas.GetLeft(topLeftEllipse) +
                                                             topLeftEllipse.Width  / 2      +
                                                             " "                            +
                                                             Canvas.GetTop (topLeftEllipse) +
                                                             topLeftEllipse.Height / 2;

                    rectangleGeometry.Rect = new Rect
                    (
                        Canvas.GetLeft(topLeftEllipse) + topLeftEllipse.Width  / 2,
                        Canvas.GetTop (topLeftEllipse) + topLeftEllipse.Height / 2,
                        width,
                        height
                    );
                    
                    break;
                }                   
                case "BottomRight" :
                {
                    width  = mousePoint.X - rectangleGeometry.Rect.X;
                    height = mousePoint.Y - rectangleGeometry.Rect.Y;

                    this.rectangleWidthTextBox.Text  = width.ToString();
                    this.rectangleHeightTextBox.Text = height.ToString();

                    Canvas.SetLeft
                    (
                        topRightEllipse,
                        mousePoint.X - topRightEllipse.Width / 2
                    );

                    Canvas.SetTop
                    (
                        bottomLeftEllipse,
                        mousePoint.Y - bottomLeftEllipse.Height / 2
                    );

                    rectangleGeometry.Rect = new Rect
                    (
                        Canvas.GetLeft(topLeftEllipse) + topLeftEllipse.Width  / 2,
                        Canvas.GetTop (topLeftEllipse) + topLeftEllipse.Height / 2,
                        width,
                        height
                    );

                    path.Data = rectangleGeometry;

                    break;
                }
                case "Corner" :
                {
                    double radiusX = mousePoint.X - rectangleGeometry.Rect.X;
                    double radiusY = mousePoint.Y - rectangleGeometry.Rect.Y;

                    if(radiusX <= 0)
                    {
                        Canvas.SetLeft
                        (
                            cornerEllipse,
                            rectangleGeometry.Rect.X + 0.1 - cornerEllipse.Width
                        );

                        radiusX = 0.1;
                    }

                    if(radiusY <= 0)
                    {
                        Canvas.SetTop
                        (
                            cornerEllipse,
                            rectangleGeometry.Rect.Y + 0.1 - cornerEllipse.Height / 2
                        );

                        radiusY = 0.1;
                    }

                    this.rectangleWidthTextBox.Text  = radiusX.ToString();
                    this.rectangleHeightTextBox.Text = radiusY.ToString();

                    rectangleGeometry.RadiusX = radiusX;
                    rectangleGeometry.RadiusY = radiusY;

                    path.Data = rectangleGeometry;

                    break;
                }
                default :
                {
                    throw new ApplicationException($"에러 : 부정확한 컨트롤 포인트 타입({controlPointType}");
                }
            }
        }

        #endregion
        #region 베지어 패스 갱신하기 - UpdateBezierPath(mousePoint, id)

        /// <summary>
        /// 베지어 패스 갱신하기
        /// </summary>
        /// <param name="mousePoint">마우스 포인트</param>
        /// <param name="id">id</param>
        private void UpdateBezierPath(Point mousePoint, string id)
        {
            string[] tokenArray       = id.Split('_');
            string   pathName         = tokenArray[0];
            string   controlPointType = tokenArray[1];

            Path path = GetPath(pathName);

            if(path == null)
            {
                throw new ApplicationException("에러 : 부정확한 지오메트리 ID");
            }

            this.currentPath = path;

            PathGeometry pathGeometry = path.Data.Clone() as PathGeometry;

            PathFigure pathFigure = pathGeometry.Figures[0];

            switch(controlPointType)
            {
                case "StartPoint" :
                {
                    pathFigure.StartPoint = mousePoint;

                    this.bezierStartPointTextBox.Text = mousePoint.X + " " + mousePoint.Y;

                    break;
                }
                case "Point1" :
                {
                    this.bezierPoint1TextBox.Text = mousePoint.X + " " + mousePoint.Y;

                    ((BezierSegment)pathFigure.Segments[0]).Point1 = mousePoint;

                    break;
                }
                case "Point2" :
                {
                    this.bezierPoint2TextBox.Text = mousePoint.X + " " + mousePoint.Y;

                    ((BezierSegment)pathFigure.Segments[0]).Point2 = mousePoint;

                    break;
                }
                case "Point3" :
                {
                    this.bezierPoint3TextBox.Text = mousePoint.X + " " + mousePoint.Y;

                    ((BezierSegment)pathFigure.Segments[0]).Point3 = mousePoint;

                    break;
                }
                default :
                {
                    throw new ApplicationException($"에러 : 부정확한 컨트롤 포인트 타입({controlPointType}");
                }
            }

            path.Data = pathGeometry;
        }

        #endregion
        #region 호 패스 갱신하기 - UpdateArcPath(mousePoint, id)

        /// <summary>
        /// 호 패스 갱신하기
        /// </summary>
        /// <param name="mousePoint">마우스 포인트</param>
        /// <param name="id">ID</param>
        private void UpdateArcPath(Point mousePoint, string id)
        {
            string[] tokenArray       = id.Split('_');
            string   pathName         = tokenArray[0];
            string   controlPointType = tokenArray[1];

            Path path = GetPath(pathName);

            if(path == null)
            {
                throw new ApplicationException("에러 : 부정확한 지오메트리 ID");
            }

            this.currentPath = path;

            PathGeometry pathGeometry = path.Data as PathGeometry;

            PathFigure pathFigure = pathGeometry.Figures[0];

            switch(controlPointType)
            {
                case "StartPoint" :
                {
                    pathFigure.StartPoint = mousePoint;

                    this.arcStartPointTextBox.Text = mousePoint.X + " " + mousePoint.Y;

                    break;
                }
                case "Point" :
                {
                    ((ArcSegment)pathFigure.Segments[0]).Point = mousePoint;

                    this.arcPointTextBox.Text = mousePoint.X + " " + mousePoint.Y;

                    break;
                }
                default :
                {
                    throw new ApplicationException($"에러 : 부정확한 컨트롤 포인트 타입({controlPointType}");
                }
            }

            path.Data = pathGeometry;
        }

        #endregion
        #region 패스 갱신하기 - UpdatePath(mousePoint, id)

        /// <summary>
        /// 패스 갱신하기
        /// </summary>
        /// <param name="mousePoint">마우스 포인트</param>
        /// <param name="id">ID</param>
        private void UpdatePath(Point mousePoint, string id)
        {
            string GeometryType = GetGeometryType(id);

            ChangeControlPointGrid(GeometryType, false);

            switch(GeometryType)
            {
                case "Line"      : UpdateLinePath     (mousePoint, id); break;
                case "Ellipse"   : UpdateEllipsePath  (mousePoint, id); break;
                case "Rectangle" : UpdateRectanglePath(mousePoint, id); break;
                case "Bezier"    : UpdateBezierPath   (mousePoint, id); break;
                case "Arc"       : UpdateArcPath      (mousePoint, id); break;
                default          : throw new ApplicationException("에러 : 부정확한 지오메트리 타입");
            }
        }

        #endregion

        #region 선 컨트롤 포인트 갱신하기 - UpdateLineControlPoint(controlPointArrayList)

        /// <summary>
        /// 선 컨트롤 포인트 갱신하기
        /// </summary>
        /// <param name="controlPointArrayList">컨트롤 포인트 배열 리스트</param>
        private void UpdateLineControlPoint(ArrayList controlPointArrayList)
        {
            if(controlPointArrayList.Count != 2)
            {
                throw new ApplicationException("에러 : 부정확한 컨트롤 포인트 수");
            }

            for(int i = 0; i < controlPointArrayList.Count; i++)
            {
                switch(i)
                {
                    case 0 :

                        Ellipse startPointEllipse = LogicalTreeHelper.FindLogicalNode
                        (
                            this.designerCanvas,
                            this.currentPath.Name + "_StartPoint"
                        ) as Ellipse;

                        Canvas.SetLeft
                        (
                            startPointEllipse,
                            ((Point)controlPointArrayList[i]).X - startPointEllipse.Width / 2
                        );

                        Canvas.SetTop
                        (
                            startPointEllipse,
                            ((Point)controlPointArrayList[i]).Y - startPointEllipse.Height / 2
                        );

                        break;

                    case 1 :

                        Ellipse endPointEllipse = LogicalTreeHelper.FindLogicalNode
                        (
                            this.designerCanvas,
                            this.currentPath.Name + "_EndPoint"
                        ) as Ellipse;

                        Canvas.SetLeft
                        (
                            endPointEllipse,
                            ((Point)controlPointArrayList[i]).X - endPointEllipse.Width / 2
                        );

                        Canvas.SetTop
                        (
                            endPointEllipse,
                            ((Point)controlPointArrayList[i]).Y - endPointEllipse.Height / 2
                        );

                        break;

                    default :

                        throw new ApplicationException("에러 : 부정확한 컨트롤 포인트 수");
                }
            }
        }

        #endregion
        #region 타원 컨트롤 포인트 갱신하기 - UpdateEllipseControlPoint(controlPointArrayList)

        /// <summary>
        /// 타원 컨트롤 포인트 갱신하기
        /// </summary>
        /// <param name="controlPointArrayList">컨트롤 포인트 배열 리스트</param>
        private void UpdateEllipseControlPoint(ArrayList controlPointArrayList)
        {
            if(controlPointArrayList.Count != 5)
            {
                throw new ApplicationException("에러 : 부정확한 컨트롤 포인트 수");
            }

            for(int i = 0; i < controlPointArrayList.Count; i++)
            {
                switch (i)
                {
                    case 0 :

                        Ellipse centerEllipse = LogicalTreeHelper.FindLogicalNode
                        (
                            this.designerCanvas,
                            this.currentPath.Name + "_Center"
                        ) as Ellipse;

                        Canvas.SetLeft
                        (
                            centerEllipse,
                            ((Point)controlPointArrayList[i]).X - centerEllipse.Width / 2
                        );

                        Canvas.SetTop
                        (
                            centerEllipse,
                            ((Point)controlPointArrayList[i]).Y - centerEllipse.Height / 2
                        );

                        break;

                    case 1 :

                        Ellipse topLeftEllipse = LogicalTreeHelper.FindLogicalNode
                        (
                            this.designerCanvas,
                            this.currentPath.Name + "_TopLeft"
                        ) as Ellipse;

                        Canvas.SetLeft
                        (
                            topLeftEllipse,
                            ((Point)controlPointArrayList[i]).X - topLeftEllipse.Width / 2
                        );

                        Canvas.SetTop
                        (
                            topLeftEllipse,
                            ((Point)controlPointArrayList[i]).Y - topLeftEllipse.Height / 2
                        );

                        break;

                    case 2 :

                        Ellipse topMiddleEllipse = LogicalTreeHelper.FindLogicalNode
                        (
                            this.designerCanvas,
                            this.currentPath.Name + "_TopMiddle"
                        ) as Ellipse;

                        Canvas.SetLeft
                        (
                            topMiddleEllipse,
                            ((Point)controlPointArrayList[i]).X - topMiddleEllipse.Width / 2
                        );

                        Canvas.SetTop
                        (
                            topMiddleEllipse,
                            ((Point)controlPointArrayList[i]).Y - topMiddleEllipse.Height / 2
                        );

                        break;

                    case 3 :

                        Ellipse topRightEllipse = LogicalTreeHelper.FindLogicalNode
                        (
                            this.designerCanvas,
                            this.currentPath.Name + "_TopRight"
                        ) as Ellipse;

                        Canvas.SetLeft
                        (
                            topRightEllipse,
                            ((Point)controlPointArrayList[i]).X - topRightEllipse.Width / 2
                        );

                        Canvas.SetTop
                        (
                            topRightEllipse,
                            ((Point)controlPointArrayList[i]).Y - topRightEllipse.Height / 2
                        );

                        break;

                    case 4 :

                        Ellipse bottomMiddleEllipse = LogicalTreeHelper.FindLogicalNode
                        (
                            this.designerCanvas,
                            this.currentPath.Name + "_BottomMiddle"
                        ) as Ellipse;

                        Canvas.SetLeft
                        (
                            bottomMiddleEllipse,
                            ((Point)controlPointArrayList[i]).X - bottomMiddleEllipse.Width / 2
                        );

                        Canvas.SetTop
                        (
                            bottomMiddleEllipse,
                            ((Point)controlPointArrayList[i]).Y - bottomMiddleEllipse.Height / 2
                        );

                        break;

                    default :

                        throw new ApplicationException("에러 : 부정확한 컨트롤 포인트 수");
                }
            }
        }

        #endregion
        #region 사각형 컨트롤 포인트 갱신하기 - UpdateRectangleControlPoint(controlPointArrayList)

        /// <summary>
        /// 사각형 컨트롤 포인트 갱신하기
        /// </summary>
        /// <param name="controlPointArrayList">컨트롤 포인트 배열 리스트</param>
        private void UpdateRectangleControlPoint(ArrayList controlPointArrayList)
        {
            if(controlPointArrayList.Count != 5 && controlPointArrayList.Count != 4)
            {
                throw new ApplicationException("에러 : 부정확한 컨트롤 포인트 수");
            }

            for(int i = 0; i < controlPointArrayList.Count; i++)
            {
                switch(i)
                {
                    case 0 :

                        Ellipse topLeftEllipse = LogicalTreeHelper.FindLogicalNode
                        (
                            this.designerCanvas,
                            this.currentPath.Name + "_TopLeft"
                        ) as Ellipse;

                        Canvas.SetLeft
                        (
                            topLeftEllipse,
                            ((Point)controlPointArrayList[i]).X - topLeftEllipse.Width / 2
                        );

                        Canvas.SetTop
                        (
                            topLeftEllipse,
                            ((Point)controlPointArrayList[i]).Y - topLeftEllipse.Height / 2
                        );

                        break;

                    case 1 :

                        Ellipse topRightEllipse = LogicalTreeHelper.FindLogicalNode
                        (
                            this.designerCanvas,
                            this.currentPath.Name + "_TopRight"
                        ) as Ellipse;

                        Canvas.SetLeft
                        (
                            topRightEllipse,
                            ((Point)controlPointArrayList[i]).X - topRightEllipse.Width / 2
                        );

                        Canvas.SetTop
                        (
                            topRightEllipse,
                            ((Point)controlPointArrayList[i]).Y - topRightEllipse.Height / 2
                        );

                        break;

                    case 2 :

                        Ellipse bottomLeftEllipse = LogicalTreeHelper.FindLogicalNode
                        (
                            this.designerCanvas,
                            this.currentPath.Name + "_BottomLeft"
                        ) as Ellipse;

                        Canvas.SetLeft
                        (
                            bottomLeftEllipse,
                            ((Point)controlPointArrayList[i]).X - bottomLeftEllipse.Width / 2
                        );

                        Canvas.SetTop
                        (
                            bottomLeftEllipse,
                            ((Point)controlPointArrayList[i]).Y - bottomLeftEllipse.Height / 2
                        );

                        break;

                    case 3 :

                        Ellipse bottomRightEllipse = LogicalTreeHelper.FindLogicalNode
                        (
                            this.designerCanvas,
                            this.currentPath.Name + "_BottomRight"
                        ) as Ellipse;

                        Canvas.SetLeft
                        (
                            bottomRightEllipse,
                            ((Point)controlPointArrayList[i]).X - bottomRightEllipse.Width / 2
                        );

                        Canvas.SetTop
                        (
                            bottomRightEllipse,
                            ((Point)controlPointArrayList[i]).Y - bottomRightEllipse.Height / 2
                        );

                        break;

                    case 4 :

                        Ellipse cornerEllipse = LogicalTreeHelper.FindLogicalNode
                        (
                            this.designerCanvas,
                            this.currentPath.Name + "_Corner"
                        ) as Ellipse;

                        Canvas.SetLeft
                        (
                            cornerEllipse,
                            ((Point)controlPointArrayList[i]).X - cornerEllipse.Width / 2
                        );

                        Canvas.SetTop
                        (
                            cornerEllipse,
                            ((Point)controlPointArrayList[i]).Y - cornerEllipse.Height / 2
                        );

                        break;

                    default :

                        throw new ApplicationException("에러 : 부정확한 컨트롤 포인트 수");
                }
            }
        }

        #endregion
        #region 베지어 곡선 컨트롤 포인트 갱신하기 - UpdateBezierCurveControlPoint(controlPointArrayList)

        /// <summary>
        /// 베지어 곡선 컨트롤 포인트 갱신하기
        /// </summary>
        /// <param name="controlPointArrayList">컨트롤 포인트 배열 리스트</param>
        private void UpdateBezierCurveControlPoint(ArrayList controlPointArrayList)
        {
            if(controlPointArrayList.Count != 4)
            {
                throw new ApplicationException("에러 : 부정확한 컨트롤 포인트 수");
            }

            for(int i = 0; i < controlPointArrayList.Count; i++)
            {
                switch(i)
                {
                    case 0 :

                        Ellipse startPointEllipse = LogicalTreeHelper.FindLogicalNode
                        (
                            this.designerCanvas,
                            this.currentPath.Name + "_StartPoint"
                        ) as Ellipse;

                        Canvas.SetLeft
                        (
                            startPointEllipse,
                            ((Point)controlPointArrayList[i]).X - startPointEllipse.Width / 2
                        );

                        Canvas.SetTop
                        (
                            startPointEllipse,
                            ((Point)controlPointArrayList[i]).Y - startPointEllipse.Height / 2
                        );

                        break;

                    case 1 :

                        Ellipse point1Ellipse = LogicalTreeHelper.FindLogicalNode
                        (
                            this.designerCanvas,
                            this.currentPath.Name + "_Point1"
                        ) as Ellipse;

                        Canvas.SetLeft
                        (
                            point1Ellipse,
                            ((Point)controlPointArrayList[i]).X - point1Ellipse.Width  / 2
                        );

                        Canvas.SetTop
                        (
                            point1Ellipse,
                            ((Point)controlPointArrayList[i]).Y - point1Ellipse.Height / 2
                        );
  
                        break;

                    case 2 :

                        Ellipse point2Ellipse = LogicalTreeHelper.FindLogicalNode
                        (
                            this.designerCanvas,
                            this.currentPath.Name + "_Point2"
                        ) as Ellipse;

                        Canvas.SetLeft
                        (
                            point2Ellipse,
                            ((Point)controlPointArrayList[i]).X - point2Ellipse.Width / 2
                        );

                        Canvas.SetTop
                        (
                            point2Ellipse,
                            ((Point)controlPointArrayList[i]).Y - point2Ellipse.Height / 2
                        );

                        break;

                    case 3 :

                        Ellipse point3Ellipse = LogicalTreeHelper.FindLogicalNode
                        (
                            this.designerCanvas,
                            this.currentPath.Name + "_Point3"
                        ) as Ellipse;

                        Canvas.SetLeft
                        (
                            point3Ellipse,
                            ((Point)controlPointArrayList[i]).X - point3Ellipse.Width / 2
                        );

                        Canvas.SetTop
                        (
                            point3Ellipse,
                            ((Point)controlPointArrayList[i]).Y - point3Ellipse.Height / 2
                        );

                        break;

                    default :
                        throw new ApplicationException("에러 : 부정확한 컨트롤 포인트 수");
                }
            }
        }

        #endregion
        #region 호 컨트롤 포인트 갱신하기 - UpdateArcControlPoint(controlPointArrayList)

        /// <summary>
        /// 호 컨트롤 포인트 갱신하기
        /// </summary>
        /// <param name="controlPointArrayList">컨트롤 포인트 배열 리스트</param>
        private void UpdateArcControlPoint(ArrayList controlPointArrayList)
        {
            if(controlPointArrayList.Count != 2)
            {
                throw new ApplicationException("에러 : 부정확한 컨트롤 포인트 수");
            }

            for(int i = 0; i < controlPointArrayList.Count; i++)
            {
                switch(i)
                {
                    case 0 :

                        Ellipse startPointEllipse = LogicalTreeHelper.FindLogicalNode
                        (
                            this.designerCanvas,
                            this.currentPath.Name + "_StartPoint"
                        ) as Ellipse;

                        Canvas.SetLeft
                        (
                            startPointEllipse,
                            ((Point)controlPointArrayList[i]).X - startPointEllipse.Width / 2
                        );

                        Canvas.SetTop
                        (
                            startPointEllipse,
                            ((Point)controlPointArrayList[i]).Y - startPointEllipse.Height / 2
                        );

                        break;

                    case 1 :

                        Ellipse point1Ellipse = LogicalTreeHelper.FindLogicalNode
                        (
                            this.designerCanvas,
                            this.currentPath.Name + "_Point"
                        ) as Ellipse;

                        Canvas.SetLeft
                        (
                            point1Ellipse,
                            ((Point)controlPointArrayList[i]).X - point1Ellipse.Width / 2
                        );

                        Canvas.SetTop
                        (
                            point1Ellipse,
                            ((Point)controlPointArrayList[i]).Y - point1Ellipse.Height / 2
                        );

                        break;

                    default :

                        throw new ApplicationException("에러 : 부정확한 컨트롤 포인트 수");
                }
            }
        }

        #endregion
        #region 컨트롤 포인트 갱신하기 - UpdateControlPoint(controlPointArrayList)

        /// <summary>
        /// 컨트롤 포인트 갱신하기
        /// </summary>
        /// <param name="controlPointArrayList">컨트롤 포인트 배열 리스트</param>
        private void UpdateControlPoint(ArrayList controlPointArrayList)
        {
            string geometryType = GetGeometryType(this.currentPath.Name);

            switch(geometryType)
            {
                case "Line"      : UpdateLineControlPoint       (controlPointArrayList); break;
                case "Ellipse"   : UpdateEllipseControlPoint    (controlPointArrayList); break;
                case "Rectangle" : UpdateRectangleControlPoint  (controlPointArrayList); break;
                case "Bezier"    : UpdateBezierCurveControlPoint(controlPointArrayList); break;
                case "Arc"       : UpdateArcControlPoint        (controlPointArrayList); break;
                default          : throw new ApplicationException("에러 : 부정확한 지오메트리 타입");
            }
        }

        #endregion
    }
}
728x90
반응형
그리드형(광고전용)
Posted by icodebroker

댓글을 달아 주세요