프로젝트

일반

사용자정보

통계
| 브랜치(Branch): | 개정판:

markus / MarkupToPDF / Controls / Etc / SymControl.cs @ 5a223b60

이력 | 보기 | 이력해설 | 다운로드 (23.2 KB)

1
using System;
2
using System.Net;
3
using System.Windows;
4
using System.Windows.Controls;
5
using System.Windows.Documents;
6
using System.Windows.Ink;
7
using System.Windows.Input;
8
using System.Windows.Media;
9
using System.Windows.Media.Animation;
10
using System.Windows.Shapes;
11
using System.ComponentModel;
12
using System.Collections.Generic;
13
using MarkupToPDF.Controls.Common;
14
using MarkupToPDF.Common;
15
using MarkupToPDF.Serialize.Core;
16
using MarkupToPDF.Serialize.S_Control;
17
using System.Linq;
18
using MarkupToPDF.Controls.Shape;
19
using System.Windows.Markup;
20

    
21
namespace MarkupToPDF.Controls.Etc
22
{
23
    [TemplatePart(Name = "PART_SymPath", Type = typeof(Path))]
24
    [TemplatePart(Name = "PART_ViewBox", Type = typeof(Viewbox))]
25

    
26
    public class SymControl : CommentUserInfo, IDisposable, INotifyPropertyChanged, IPath, IViewBox, IMarkupCommonData
27
    {
28
        #region 초기선언
29
        public enum SymStyleSet { None, Fill };
30
        private const string PART_ViewBox = "PART_ViewBox";
31
        private const string PART_SymPath = "PART_SymPath";
32
        public Viewbox Base_ViewBox = null;
33
        public Path Base_SymPath = null;
34
        #endregion
35

    
36
        static SymControl()
37
        {
38
            DefaultStyleKeyProperty.OverrideMetadata(typeof(SymControl), new FrameworkPropertyMetadata(typeof(SymControl)));
39
            //Application.Current.Resources.MergedDictionaries.Add(Application.LoadComponent(new Uri("/MarkupToPDF;Component/Themes/generic.xaml")) as ResourceDictionary);
40
            //ResourceDictionary dictionary = new ResourceDictionary();
41
            //dictionary.Source = new Uri("/MarkupToPDF;component/themes/generic.xaml", UriKind.RelativeOrAbsolute);
42
            //Application.Current.Resources.MergedDictionaries.Add(dictionary);
43
            //System.Diagnostics.Debug.WriteLine("resource Count :" + Application.Current.Resources.MergedDictionaries.Count);
44
        }
45
        public override void Copy(CommentUserInfo lhs)
46
        {
47
            if(lhs is SymControl symControl)
48
            {
49
                this.LineSize = symControl.LineSize;
50
                this.PointSet = symControl.PointSet.ConvertAll(x => new System.Windows.Point(x.X, x.Y));
51
                this.Paint = symControl.Paint;
52
                this.StartPoint = new System.Windows.Point(symControl.StartPoint.X, symControl.StartPoint.Y);
53
                this.EndPoint = new System.Windows.Point(symControl.EndPoint.X, symControl.EndPoint.Y);
54
                this.LeftBottomPoint = new System.Windows.Point(symControl.LeftBottomPoint.X, symControl.LeftBottomPoint.Y);
55
                this.TopRightPoint = new System.Windows.Point(symControl.TopRightPoint.X, symControl.TopRightPoint.Y);
56
                this.StrokeColor = symControl.StrokeColor;
57
                this.CommentAngle = symControl.CommentAngle;
58
                this.UserID = symControl.UserID;
59

    
60
                this.PathData = symControl.PathData.Clone();
61
                this.Opacity = symControl.Opacity;
62
                this.Memo = symControl.Memo;
63
                this.ZIndex = symControl.ZIndex;
64
            }
65
        }
66

    
67
        public override CommentUserInfo Clone()
68
        {
69
            var clone = new SymControl();
70
            clone.Copy(this);
71
            return clone;
72
        }
73

    
74
        public void Dispose()
75
        {
76
            //GC.Collect();
77
            ////GC.SuppressFinalize(this);
78
            this.Base_SymPath = null;
79
            this.Base_ViewBox = null;
80
        }
81
        public event PropertyChangedEventHandler PropertyChanged;
82
        protected void RaisePropertyChanged(string propName)
83
        {
84
            if (PropertyChanged != null)
85
                PropertyChanged(this, new PropertyChangedEventArgs(propName));
86
        }
87
        #region Dependency Properties
88
        public static readonly DependencyProperty UserIDProperty = DependencyProperty.Register(
89
                "UserID", typeof(string), typeof(SymControl), new PropertyMetadata(null));
90
        public static readonly DependencyProperty LineSizeProperty = DependencyProperty.Register(
91
                "LineSize", typeof(double), typeof(SymControl), new PropertyMetadata((Double)1));
92
        public static readonly DependencyProperty StrokeColorProperty = DependencyProperty.Register(
93
                "StrokeColor", typeof(SolidColorBrush), typeof(SymControl), new PropertyMetadata(new SolidColorBrush(Colors.Red)));
94
        public static readonly DependencyProperty PathDataProperty = DependencyProperty.Register(
95
                "PathData", typeof(Geometry), typeof(SymControl), null);
96
        public static readonly DependencyProperty EndPointProperty = DependencyProperty.Register(
97
                "EndPoint", typeof(Point), typeof(SymControl), new PropertyMetadata(new Point(0, 0), PointValueChanged));
98
        public static readonly DependencyProperty StartPointProperty = DependencyProperty.Register(
99
                "StartPoint", typeof(Point), typeof(SymControl), new PropertyMetadata(new Point(0, 0), PointValueChanged));
100
        public static readonly DependencyProperty TopRightPointProperty = DependencyProperty.Register(
101
                "TopRightPoint", typeof(Point), typeof(SymControl), new PropertyMetadata(new Point(0, 0), TRPointValueChanged));
102
        public static readonly DependencyProperty LeftBottomPointProperty = DependencyProperty.Register(
103
                 "LeftBottomPoint", typeof(Point), typeof(SymControl), new PropertyMetadata(new Point(0, 0), LBPointValueChanged));
104
        public static readonly DependencyProperty PointSetProperty = DependencyProperty.Register(
105
                 "PointSet", typeof(List<Point>), typeof(SymControl), new PropertyMetadata(new List<Point>()));
106
        public static readonly DependencyProperty AngleProperty = DependencyProperty.Register("Angle", typeof(double), typeof(SymControl),
107
            new PropertyMetadata((double)0.0, new PropertyChangedCallback(AngleValueChanged)));
108
        public static readonly DependencyProperty CenterXProperty = DependencyProperty.Register("CenterX", typeof(double), typeof(SymControl),
109
            new PropertyMetadata((double)0, OnCenterXYChanged));
110
        public static readonly DependencyProperty CenterYProperty = DependencyProperty.Register("CenterY", typeof(double), typeof(SymControl),
111
            new PropertyMetadata((double)0, OnCenterXYChanged));
112
        public static readonly DependencyProperty PaintProperty = DependencyProperty.Register(
113
                "Paint", typeof(PaintSet), typeof(SymControl), new PropertyMetadata(PaintSet.None));
114

    
115
        public static readonly DependencyProperty IsSelectedProperty =
116
     DependencyProperty.Register("IsSelected", typeof(bool), typeof(SymControl), new FrameworkPropertyMetadata(false, IsSelectedChanged));
117

    
118
        public static readonly DependencyProperty ControlTypeProperty =
119
            DependencyProperty.Register("ControlType", typeof(ControlType), typeof(SymControl), new FrameworkPropertyMetadata(ControlType.Symbol));
120
        #endregion
121
        #region PropertyChanged Method
122
        public static void PointValueChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
123
        {
124
            var instance = (SymControl)sender;
125
            if (e.OldValue != e.NewValue && instance.Base_SymPath != null)
126
            {
127
                instance.SetValue(e.Property, e.NewValue);
128
                instance.SetSymPath();
129
            }
130
        }
131

    
132
        public static void TRPointValueChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
133
        {
134
            var instance = (SymControl)sender;
135
            if (e.OldValue != e.NewValue && instance.Base_SymPath != null)
136
            {
137
                instance.SetValue(e.Property, e.NewValue);
138
                instance.SetSymPath();
139
            }
140
        }
141
        public static void IsSelectedChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
142
        {
143

    
144
        }
145
        public static void OnCenterXYChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
146
        {
147
            var instance = (SymControl)sender;
148
            if (e.OldValue != e.NewValue && instance.Base_SymPath != null)
149
            {
150
                instance.SetValue(e.Property, e.NewValue);
151
                instance.SetSymPath();
152
            }
153
        }
154

    
155
        public static void LBPointValueChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
156
        {
157
            var instance = (SymControl)sender;
158
            if (e.OldValue != e.NewValue && instance.Base_SymPath != null)
159
            {
160
                instance.SetValue(e.Property, e.NewValue);
161
                //instance.EndPoint = new Point(instance.EndPoint.X, ((Point)e.NewValue).Y);
162
                //instance.StartPoint = new Point(((Point)e.NewValue).X, instance.StartPoint.Y);
163
                ////instance.PointSet[0] = instance.StartPoint;
164
                ////instance.PointSet[2] = instance.EndPoint;
165
                instance.SetSymPath();
166
            }
167
        }
168

    
169
        public static void AngleValueChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
170
        {
171
            var instance = (SymControl)sender;
172
            if (e.OldValue != e.NewValue && instance.Base_SymPath != null)
173
            {
174
                instance.SetValue(e.Property, e.NewValue);
175
                instance.SetSymPath();
176
            }
177
        }
178
        #endregion
179
        #region Properties
180
        public string UserID
181
        {
182
            get { return (string)GetValue(UserIDProperty); }
183
            set
184
            {
185
                if (this.UserID != value)
186
                {
187
                    SetValue(UserIDProperty, value);
188
                    RaisePropertyChanged("UserID");
189
                }
190
            }
191
        }
192
        public Double LineSize
193
        {
194
            get { return (Double)GetValue(LineSizeProperty); }
195
            set
196
            {
197
                if (this.LineSize != value)
198
                {
199
                    SetValue(LineSizeProperty, value);
200
                }
201
            }
202
        }
203
        public PaintSet Paint
204
        {
205
            get { return (PaintSet)GetValue(PaintProperty); }
206
            set
207
            {
208
                if (this.Paint != value)
209
                {
210
                    SetValue(PaintProperty, value);
211
                }
212
            }
213
        }
214
        public List<Point> PointSet
215
        {
216
            get { return (List<Point>)GetValue(PointSetProperty); }
217
            set { SetValue(PointSetProperty, value); }
218
        }
219

    
220
        public override double CommentAngle
221
        {
222
            get { return (double)GetValue(AngleProperty); }
223
            set
224
            {
225
                if (this.CommentAngle != value)
226
                {
227
                    SetValue(AngleProperty, value);
228
                }
229
            }
230
        }
231
        public SolidColorBrush StrokeColor
232
        {
233
            get { return (SolidColorBrush)GetValue(StrokeColorProperty); }
234
            set
235
            {
236
                if (this.StrokeColor != value)
237
                {
238
                    SetValue(StrokeColorProperty, value);
239
                }
240
            }
241
        }
242
        public Geometry PathData
243
        {
244
            get { return (Geometry)GetValue(PathDataProperty); }
245
            set
246
            {
247
                SetValue(PathDataProperty, value);
248
                RaisePropertyChanged("PathData");
249
            }
250
        }
251
        public Point TopRightPoint
252
        {
253
            get { return (Point)GetValue(TopRightPointProperty); }
254
            set
255
            {
256
                SetValue(TopRightPointProperty, value);
257
                RaisePropertyChanged("TopRightPoint");
258
            }
259
        }
260
        public Point LeftBottomPoint
261
        {
262
            get { return (Point)GetValue(LeftBottomPointProperty); }
263
            set
264
            {
265
                SetValue(LeftBottomPointProperty, value);
266
                RaisePropertyChanged("LeftBottomPoint");
267
            }
268
        }
269
        public Point EndPoint
270
        {
271
            get { return (Point)GetValue(EndPointProperty); }
272
            set
273
            {
274
                SetValue(EndPointProperty, value);
275
                RaisePropertyChanged("EndPoint");
276
            }
277
        }
278
        public Point StartPoint
279
        {
280
            get { return (Point)GetValue(StartPointProperty); }
281
            set
282
            {
283
                SetValue(StartPointProperty, value);
284
                RaisePropertyChanged("StartPoint");
285
            }
286
        }
287
        public double CenterX
288
        {
289
            get { return (double)GetValue(CenterXProperty); }
290
            set { SetValue(CenterXProperty, value); }
291
        }
292
        public double CenterY
293
        {
294
            get { return (double)GetValue(CenterYProperty); }
295
            set { SetValue(CenterYProperty, value); }
296
        }
297
        public double AngleValue
298
        {
299
            get { return (double)GetValue(AngleProperty); }
300
            set { SetValue(AngleProperty, value); }
301
        }
302
        public override bool IsSelected
303
        {
304
            get
305
            {
306
                return (bool)GetValue(IsSelectedProperty);
307
            }
308
            set
309
            {
310
                SetValue(IsSelectedProperty, value);
311
            }
312
        }
313

    
314
        public override ControlType ControlType
315
        {
316
            set
317
            {
318
                SetValue(ControlTypeProperty, value);
319
            }
320
            get
321
            {
322
                return (ControlType)GetValue(ControlTypeProperty);
323
            }
324
        }
325

    
326
        #endregion
327
        public override void OnApplyTemplate()
328
        {
329
            base.OnApplyTemplate();
330
            Base_ViewBox = GetTemplateChild(PART_ViewBox) as Viewbox;
331
            Base_SymPath = GetTemplateChild(PART_SymPath) as Path;
332
            SetSymPath();
333
        }
334

    
335
        private void SetSymPath()
336
        {
337
            this.ApplyTemplate();
338
            switch (this.Paint)
339
            {
340
                case PaintSet.None:
341
                    Base_SymPath.Fill = null;
342
                    break;
343
                case PaintSet.Fill:
344
                    Base_SymPath.Fill = this.StrokeColor;
345
                    break;
346
                default:
347
                    break;
348
            }
349

    
350
            Point mid = MathSet.FindCentroid(new List<Point>()
351
            {
352
                this.StartPoint,
353
                this.LeftBottomPoint,
354
                this.EndPoint,
355
                this.TopRightPoint,
356
            });
357

    
358
            double AngleData = this.CommentAngle * -1;
359

    
360
            PathFigure pathFigure = new PathFigure();
361
            pathFigure.StartPoint = MathSet.RotateAbout(mid, this.StartPoint, AngleData);
362

    
363
            LineSegment lineSegment0 = new LineSegment();
364
            lineSegment0.Point = MathSet.RotateAbout(mid, this.StartPoint, AngleData);
365
            pathFigure.Segments.Add(lineSegment0);
366

    
367
            LineSegment lineSegment1 = new LineSegment();
368
            lineSegment1.Point = MathSet.RotateAbout(mid, this.LeftBottomPoint, AngleData);
369
            pathFigure.Segments.Add(lineSegment1);
370

    
371
            LineSegment lineSegment2 = new LineSegment();
372
            lineSegment2.Point = MathSet.RotateAbout(mid, this.EndPoint, AngleData);
373
            pathFigure.Segments.Add(lineSegment2);
374

    
375
            LineSegment lineSegment3 = new LineSegment();
376
            lineSegment3.Point = MathSet.RotateAbout(mid, this.TopRightPoint, AngleData);
377
            pathFigure.Segments.Add(lineSegment3);
378

    
379
            PathGeometry pathGeometry = new PathGeometry();
380
            pathGeometry.Figures = new PathFigureCollection();
381
            pathFigure.IsClosed = true;
382
            pathGeometry.Figures.Add(pathFigure);
383
            this.Base_ViewBox.Width = pathGeometry.Bounds.Width;
384
            this.Base_ViewBox.Height = pathGeometry.Bounds.Height;
385
            this.Tag = pathGeometry;
386

    
387
            Canvas.SetLeft(this, MathSet.RotateAbout(mid, mid, AngleData).X - this.Base_ViewBox.Width / 2);
388
            Canvas.SetTop(this, MathSet.RotateAbout(mid, mid, AngleData).Y - this.Base_ViewBox.Height / 2);
389

    
390
        }
391

    
392
        public override void UpdateControl()
393
        {
394
            this.StartPoint = new Point(this.PointSet[0].X, this.PointSet[0].Y);
395
            this.LeftBottomPoint = new Point(this.PointSet[1].X, this.PointSet[1].Y);
396
            this.EndPoint = new Point(this.PointSet[2].X, this.PointSet[2].Y);
397
            this.TopRightPoint = new Point(this.PointSet[3].X, this.PointSet[3].Y);
398
            this.SetSymPath();
399
        }
400

    
401

    
402
        public void ChangePaint(PaintSet state)
403
        {
404
            this.Paint = state;
405
            this.SetSymPath();
406
        }
407

    
408
        /// <summary>
409
        /// call when mouse is moving while drawing control
410
        /// </summary>
411
        /// <author>humkyung</author>
412
        /// <param name="pt"></param>
413
        /// <param name="bAxisLocked"></param>
414
        public override void OnCreatingMouseMove(Point pt, bool bAxisLocked)
415
        {
416
            if (bAxisLocked)
417
            {
418
                double _dx = pt.X - this.StartPoint.X;
419
                double _dy = pt.Y - this.StartPoint.Y;
420
                double dist = Math.Max(Math.Abs(_dx), Math.Abs(_dy));
421
                var dir = new Vector(_dx, _dy);
422
                dir.Normalize();
423

    
424
                this.LeftBottomPoint = new Point(this.StartPoint.X, this.StartPoint.Y + (dir.Y > 0 ? 1 : -1) * dist);
425
                this.TopRightPoint = new Point(this.StartPoint.X + (dir.X > 0 ? 1 : -1) * dist, this.StartPoint.Y);
426
                this.EndPoint = new Point(this.TopRightPoint.X, this.LeftBottomPoint.Y);
427
            }
428
            else
429
            {
430
                this.EndPoint = pt;
431
                this.LeftBottomPoint = new Point(this.StartPoint.X, this.EndPoint.Y);
432
                this.TopRightPoint = new Point(this.EndPoint.X, this.StartPoint.Y);
433
            }
434
            
435
            this.StrokeColor = new SolidColorBrush(Colors.Red);
436

    
437
            if (this.StartPoint != this.EndPoint)
438
            {
439
                if (this.PathData == null)
440
                {
441
                    using (StringToPathConverter Convert = new StringToPathConverter())
442
                    {
443
                        this.PathData = Convert.Convert("M-5,5L0,0L20,30L40,-20 ");
444
                    }
445
                }
446
            }
447

    
448
            this.PointSet = new List<Point>
449
            {
450
                this.StartPoint,
451
                this.LeftBottomPoint,
452
                this.EndPoint,
453
                this.TopRightPoint,
454
            };
455
        }
456

    
457
        /// <summary>
458
        /// move control point has same location of given pt along given delta
459
        /// </summary>
460
        /// <author>humkyung</author>
461
        /// <date>2019.06.20</date>
462
        /// <param name="pt"></param>
463
        /// <param name="dx"></param>
464
        /// <param name="dy"></param>
465
        public override void OnMoveCtrlPoint(Point pt, double dx, double dy, bool bAxisLocked = false)
466
        {
467
            IPath path = (this as IPath);
468

    
469
            Point selected = MathSet.getNearPoint(path.PointSet, pt);
470
            selected.X += dx;
471
            selected.Y += dy;
472
            int i = 0;
473
            for (i = 0; i < (this as IPath).PointSet.Count; i++)
474
            {
475
                if (pt.Equals((this as IPath).PointSet[i]))
476
                {
477
                    path.PointSet[i] = selected;
478
                    break;
479
                }
480
            }
481

    
482
            var ReverseP = (i + path.PointSet.Count / 2) % path.PointSet.Count;
483
            var PreviousP = (i + (path.PointSet.Count - 1)) % path.PointSet.Count;
484
            var NextP = (i + 1) % path.PointSet.Count;
485

    
486
            var distance = MathSet.DistanceTo(path.PointSet[ReverseP], path.PointSet[i]);
487

    
488
            var PreviousV = MathSet.GetNormVectorBetween(path.PointSet[ReverseP], path.PointSet[PreviousP]);
489
            var l = MathSet.DotProduct(PreviousV.X, PreviousV.Y, path.PointSet[i].X - path.PointSet[ReverseP].X,
490
                path.PointSet[i].Y - path.PointSet[ReverseP].Y);
491
            path.PointSet[PreviousP] = new Point(path.PointSet[ReverseP].X + PreviousV.X * l, path.PointSet[ReverseP].Y + PreviousV.Y * l);
492

    
493
            var NextV = MathSet.GetNormVectorBetween(path.PointSet[ReverseP], path.PointSet[NextP]);
494
            l = MathSet.DotProduct(NextV.X, NextV.Y, path.PointSet[i].X - path.PointSet[ReverseP].X, path.PointSet
495
                [i].Y - path.PointSet[ReverseP].Y);
496
            path.PointSet[NextP] = new Point(path.PointSet[ReverseP].X + NextV.X * l, path.PointSet[ReverseP].Y + NextV.Y * l);
497

    
498
            this.UpdateControl();
499
        }
500

    
501
        /// <summary>
502
        /// return SymControl's area
503
        /// </summary>
504
        /// <author>humkyung</author>
505
        /// <date>2019.06.13</date>
506
        public override Rect ItemRect
507
        {
508
            get
509
            {
510
                double dMinX = Math.Min(this.StartPoint.X, this.EndPoint.X);
511
                double dMinY = Math.Min(this.StartPoint.Y, this.EndPoint.Y);
512
                double dMaxX = Math.Max(this.StartPoint.X, this.EndPoint.X);
513
                double dMaxY = Math.Max(this.StartPoint.Y, this.EndPoint.Y);
514

    
515
                return new Rect(new Point(dMinX, dMinY), new Point(dMaxX, dMaxY));
516
            }
517
        }
518

    
519
        /// <summary>
520
        /// Serialize this
521
        /// </summary>
522
        /// <param name="sUserId"></param>
523
        /// <returns></returns>
524
        public override string Serialize()
525
        {
526
            using (S_SymControl ctrl = new S_SymControl())
527
            {
528
                ctrl.TransformPoint = "0|0";
529
                ctrl.PointSet = this.PointSet;
530
                ctrl.UserID = this.UserID;
531
                ctrl.SizeSet = String.Format("{0}", this.LineSize.ToString());
532
                ctrl.PaintState = this.Paint;
533
                ctrl.PathInfo = this.PathData.ToString();
534
                ctrl.StrokeColor = this.StrokeColor.Color.ToString();
535
                ctrl.StartPoint = this.StartPoint;
536
                ctrl.Angle = this.CommentAngle;
537
                ctrl.EndPoint = this.EndPoint;
538
                ctrl.LB = this.LeftBottomPoint;
539
                ctrl.TR = this.TopRightPoint;
540
                ctrl.Opac = this.Opacity;
541
                ctrl.Name = this.GetType().Name.ToString();
542
                ctrl.ZIndex = this.ZIndex;
543

    
544
                return "|DZ|" + JsonSerializerHelper.CompressString((ctrl.JsonSerialize()));
545
            }
546
        }
547

    
548
        /// <summary>
549
        /// create a symcontrol from given string
550
        /// </summary>
551
        /// <param name="str"></param>
552
        /// <returns></returns>
553
        public static SymControl FromString(string str, SolidColorBrush brush, string sProjectNo)
554
        {
555
            SymControl instance = null;
556
            using (S_SymControl s = JsonSerializerHelper.JsonDeserialize<S_SymControl>(str))
557
            {
558
                string[] data2 = s.SizeSet.Split(delimiterChars2, StringSplitOptions.RemoveEmptyEntries);
559
                Common.StringToPathConverter sm = new Common.StringToPathConverter();
560
                instance = new SymControl
561
                {
562
                    LineSize = Convert.ToDouble(data2.First()),
563
                    PointSet = s.PointSet,
564
                    Paint = s.PaintState,
565
                    StartPoint = s.StartPoint,
566
                    StrokeColor = brush,
567
                    EndPoint = s.EndPoint,
568
                    CommentAngle = s.Angle,
569
                    UserID = s.UserID,
570
                    LeftBottomPoint = s.LB,
571
                    TopRightPoint = s.TR,
572
                    PathData = sm.Convert(s.PathInfo.ToString()),
573
                    Opacity = s.Opac,
574
                    Memo = s.Memo,
575
                    ZIndex = s.ZIndex
576
                };
577
            }
578

    
579
            return instance;
580
        }
581
    }
582
}
클립보드 이미지 추가 (최대 크기: 500 MB)