f185a225ee8995518b5e676bcdb5044190afaa6b
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI / src / public / Window / DefaultBorder.cs
1 /*
2  * Copyright(c) 2022 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 using System;
19 using System.ComponentModel;
20 using Tizen.NUI.BaseComponents;
21 using Tizen.NUI.Binding;
22
23 namespace Tizen.NUI
24 {
25     /// <summary>
26     /// This class creates a border UI.
27     /// </summary>
28     [EditorBrowsable(EditorBrowsableState.Never)]
29     public class DefaultBorder : BindableObject, IDisposable, IBorderInterface
30     {
31         #region Constant Fields
32         private static readonly string ResourcePath = FrameworkInformation.ResourcePath;
33         private static readonly string MinimalizeIcon = ResourcePath + "minimalize.png";
34         private static readonly string MaximalizeIcon = ResourcePath + "maximalize.png";
35         private static readonly string CloseIcon = ResourcePath + "close.png";
36         private static readonly string LeftCornerIcon = ResourcePath + "leftCorner.png";
37         private static readonly string RightCornerIcon = ResourcePath + "rightCorner.png";
38
39         private static readonly string DarkMinimalizeIcon = ResourcePath + "dark_minimalize.png";
40         private static readonly string DarkPreviousIcon = ResourcePath + "dark_smallwindow.png";
41         private static readonly string DarkCloseIcon = ResourcePath + "dark_close.png";
42         private static readonly string DarkLeftCornerIcon = ResourcePath + "dark_leftCorner.png";
43         private static readonly string DarkRightCornerIcon = ResourcePath + "dark_rightCorner.png";
44
45
46         private const float DefaultHeight = 50;
47         private const uint DefaultLineThickness = 5;
48         private const uint DefaultTouchThickness = 0;
49         private static readonly Color DefaultBackgroundColor = new Color(1, 1, 1, 0.3f);
50         private static readonly Color DefaultClickedBackgroundColor = new Color(1, 1, 1, 0.4f);
51         private static readonly Size2D DefaultMinSize = new Size2D(100, 0);
52         #endregion //Constant Fields
53
54
55         #region Fields
56         private bool disposed = false;
57         private Color backgroundColor;
58         private View borderView;
59
60         private ImageView minimalizeIcon;
61         private ImageView maximalizeIcon;
62         private ImageView closeIcon;
63         private ImageView leftCornerIcon;
64         private ImageView rightCornerIcon;
65
66         private Window.BorderDirection direction = Window.BorderDirection.None;
67         private float preScale = 0;
68
69         private View windowView = null;
70         private bool isWinGestures = false;
71         private Timer timer;
72         private Timer overlayTimer;
73
74         private CurrentGesture currentGesture = CurrentGesture.None;
75
76         private uint borderLineThickness;
77         private Size2D minSize;
78         private Size2D maxSize;
79         private Window.BorderResizePolicyType resizePolicy;
80
81         #endregion //Fields
82
83         #region Events
84         private PanGestureDetector borderPanGestureDetector;
85         #endregion //Events
86
87         #region Enums
88         private enum CurrentGesture
89         {
90           None = 0,
91           TapGesture = 1,
92           PanGesture = 2,
93           PinchGesture = 3,
94         }
95         #endregion //Enums
96
97         #region Methods
98
99         [EditorBrowsable(EditorBrowsableState.Never)]
100         public static readonly BindableProperty BorderLineThicknessProperty = BindableProperty.Create(nameof(BorderLineThickness), typeof(uint), typeof(DefaultBorder), default(uint), propertyChanged: (bindable, oldValue, newValue) =>
101         {
102             var instance = (DefaultBorder)bindable;
103             if (newValue != null)
104             {
105                 instance.borderLineThickness = (uint)newValue;
106                 instance.UpdateProperty();
107             }
108         },
109         defaultValueCreator: (bindable) =>
110         {
111             var instance = (DefaultBorder)bindable;
112             return instance.borderLineThickness;
113         });
114
115         [EditorBrowsable(EditorBrowsableState.Never)]
116         public static readonly BindableProperty MinSizeProperty = BindableProperty.Create(nameof(MinSize), typeof(Size2D), typeof(DefaultBorder), default(Size2D), propertyChanged: (bindable, oldValue, newValue) =>
117         {
118             var instance = (DefaultBorder)bindable;
119             if (newValue != null)
120             {
121                 instance.minSize = (Size2D)newValue;
122                 instance.UpdateProperty();
123             }
124         },
125         defaultValueCreator: (bindable) =>
126         {
127             var instance = (DefaultBorder)bindable;
128             return instance.minSize;
129         });
130
131         [EditorBrowsable(EditorBrowsableState.Never)]
132         public static readonly BindableProperty MaxSizeProperty = BindableProperty.Create(nameof(MaxSize), typeof(Size2D), typeof(DefaultBorder), default(Size2D), propertyChanged: (bindable, oldValue, newValue) =>
133         {
134             var instance = (DefaultBorder)bindable;
135             if (newValue != null)
136             {
137                 instance.maxSize = (Size2D)newValue;
138                 instance.UpdateProperty();
139             }
140         },
141         defaultValueCreator: (bindable) =>
142         {
143             var instance = (DefaultBorder)bindable;
144             return instance.maxSize;
145         });
146
147         [EditorBrowsable(EditorBrowsableState.Never)]
148         public static readonly BindableProperty ResizePolicyProperty = BindableProperty.Create(nameof(ResizePolicy), typeof(Window.BorderResizePolicyType), typeof(DefaultBorder), default(Window.BorderResizePolicyType), propertyChanged: (bindable, oldValue, newValue) =>
149         {
150             var instance = (DefaultBorder)bindable;
151             if (newValue != null)
152             {
153                 instance.resizePolicy = (Window.BorderResizePolicyType)newValue;
154                 instance.UpdateProperty();
155             }
156         },
157         defaultValueCreator: (bindable) =>
158         {
159             var instance = (DefaultBorder)bindable;
160             return instance.resizePolicy;
161         });
162         
163
164         /// <summary>
165         /// The thickness of the border.
166         /// </summary>
167         [EditorBrowsable(EditorBrowsableState.Never)]
168         public uint BorderLineThickness 
169         {
170             get
171             {
172                 return (uint)GetValue(BorderLineThicknessProperty);
173             }
174             set
175             {
176                 SetValue(BorderLineThicknessProperty, value);
177             }
178         }
179
180         /// <summary>
181         /// The thickness of the border's touch area.
182         /// </summary>
183         [EditorBrowsable(EditorBrowsableState.Never)]
184         public uint TouchThickness {get; set;}
185
186         /// <summary>
187         /// The height of the border.
188         /// This value is the initial value used when creating borders.
189         /// </summary>
190         [EditorBrowsable(EditorBrowsableState.Never)]
191         public float BorderHeight {get; set;}
192
193         /// <summary>
194         /// The minimum size by which the window will small.
195         /// </summary>
196         [EditorBrowsable(EditorBrowsableState.Never)]
197         public Size2D MinSize
198         {
199             get
200             {
201                 return (Size2D)GetValue(MinSizeProperty);
202             }
203             set
204             {
205                 SetValue(MinSizeProperty, value);
206             }
207         }
208
209         /// <summary>
210         /// The maximum size by which the window will big.
211         /// </summary>
212         [EditorBrowsable(EditorBrowsableState.Never)]
213         public Size2D MaxSize
214         {
215             get
216             {
217                 return (Size2D)GetValue(MaxSizeProperty);
218             }
219             set
220             {
221                 SetValue(MaxSizeProperty, value);
222             }
223         }
224
225         /// <summary>
226         /// The window with borders added.
227         /// </summary>
228         [EditorBrowsable(EditorBrowsableState.Never)]
229         public Window BorderWindow {get; set;}
230
231         /// <summary>
232         /// Whether overlay mode.
233         /// If overlay mode is true, the border area is hidden when the window is maximized.
234         /// And if you touched at screen, the border area is shown on the screen.
235         /// Default value is false;
236         /// </summary>
237         [EditorBrowsable(EditorBrowsableState.Never)]
238         public bool OverlayMode {get; set;}
239
240         /// <summary>
241         /// Set the window resizing policy.
242         /// Default value is BorderResizePolicyType.Free;
243         /// </summary>
244         [EditorBrowsable(EditorBrowsableState.Never)]
245         public Window.BorderResizePolicyType ResizePolicy
246         {
247             get
248             {
249                 return (Window.BorderResizePolicyType)GetValue(ResizePolicyProperty);
250             }
251             set
252             {
253                 SetValue(ResizePolicyProperty, value);
254             }
255         }
256
257         /// <summary>
258         /// Update properties
259         /// </summary>
260         [EditorBrowsable(EditorBrowsableState.Never)]
261         public void UpdateProperty()
262         {
263             BorderWindow?.UpdateProperty();
264         }
265
266         /// <summary>
267         /// Creates a default border
268         /// </summary>
269         [EditorBrowsable(EditorBrowsableState.Never)]
270         public DefaultBorder() : base()
271         {
272             BorderLineThickness = DefaultLineThickness;
273             TouchThickness = DefaultTouchThickness;
274             BorderHeight = DefaultHeight;
275             MinSize = DefaultMinSize;
276             OverlayMode = false;
277             ResizePolicy = Window.BorderResizePolicyType.Free;
278         }
279
280         /// <summary>
281         /// Create top border UI. User can override this method to draw top border UI.
282         /// </summary>
283         /// <param name="topView">The top view on which the border.</param>
284         [EditorBrowsable(EditorBrowsableState.Never)]
285         public virtual bool CreateTopBorderView(View topView)
286         {
287             return false;
288         }
289
290         /// <summary>
291         /// Create bottom border UI. User can override this method to draw bottom border UI.
292         /// </summary>
293         /// <param name="bottomView">The bottom view on which the border.</param>
294         [EditorBrowsable(EditorBrowsableState.Never)]
295         public virtual bool CreateBottomBorderView(View bottomView)
296         {
297             if (bottomView == null)
298             {
299                 return false;
300             }
301             bottomView.Layout = new RelativeLayout();
302
303             minimalizeIcon = new ImageView()
304             {
305                 Focusable = true,
306                 ResourceUrl = MinimalizeIcon,
307                 AccessibilityHighlightable = true,
308             };
309
310             maximalizeIcon = new ImageView()
311             {
312                 Focusable = true,
313                 ResourceUrl = MaximalizeIcon,
314                 AccessibilityHighlightable = true,
315             };
316
317             closeIcon = new ImageView()
318             {
319                 Focusable = true,
320                 ResourceUrl = CloseIcon,
321                 AccessibilityHighlightable = true,
322             };
323
324             leftCornerIcon = new ImageView()
325             {
326                 Focusable = true,
327                 ResourceUrl = LeftCornerIcon,
328                 AccessibilityHighlightable = true,
329             };
330
331             rightCornerIcon = new ImageView()
332             {
333                 Focusable = true,
334                 ResourceUrl = RightCornerIcon,
335                 AccessibilityHighlightable = true,
336             };
337
338             RelativeLayout.SetRightTarget(minimalizeIcon, maximalizeIcon);
339             RelativeLayout.SetRightRelativeOffset(minimalizeIcon, 0.0f);
340             RelativeLayout.SetHorizontalAlignment(minimalizeIcon, RelativeLayout.Alignment.End);
341             RelativeLayout.SetRightTarget(maximalizeIcon, closeIcon);
342             RelativeLayout.SetRightRelativeOffset(maximalizeIcon, 0.0f);
343             RelativeLayout.SetHorizontalAlignment(maximalizeIcon, RelativeLayout.Alignment.End);
344             RelativeLayout.SetRightTarget(closeIcon, rightCornerIcon);
345             RelativeLayout.SetRightRelativeOffset(closeIcon, 0.0f);
346             RelativeLayout.SetHorizontalAlignment(closeIcon, RelativeLayout.Alignment.End);
347             RelativeLayout.SetRightRelativeOffset(rightCornerIcon, 1.0f);
348             RelativeLayout.SetHorizontalAlignment(rightCornerIcon, RelativeLayout.Alignment.End);
349             bottomView.Add(leftCornerIcon);
350             bottomView.Add(minimalizeIcon);
351             bottomView.Add(maximalizeIcon);
352             bottomView.Add(closeIcon);
353             bottomView.Add(rightCornerIcon);
354
355
356             minimalizeIcon.TouchEvent += OnMinimizeIconTouched;
357             maximalizeIcon.TouchEvent += OnMaximizeIconTouched;
358             closeIcon.TouchEvent += OnCloseIconTouched;
359             leftCornerIcon.TouchEvent += OnLeftBottomCornerIconTouched;
360             rightCornerIcon.TouchEvent += OnRightBottomCornerIconTouched;
361
362             minimalizeIcon.AccessibilityActivated += (s, e) =>
363             {
364                 MinimizeBorderWindow();
365             };
366             maximalizeIcon.AccessibilityActivated += (s, e) =>
367             {
368                 MaximizeBorderWindow();
369             };
370             closeIcon.AccessibilityActivated += (s, e) =>
371             {
372                 CloseBorderWindow();
373             };
374
375             minimalizeIcon.AccessibilityNameRequested += (s, e) =>
376             {
377                 e.Name = "Minimize";
378             };
379             maximalizeIcon.AccessibilityNameRequested += (s, e) =>
380             {
381                 e.Name = "Maximize";
382             };
383             closeIcon.AccessibilityNameRequested += (s, e) =>
384             {
385                 e.Name = "Close";
386             };
387             leftCornerIcon.AccessibilityNameRequested += (s, e) =>
388             {
389                 e.Name = "Resize";
390             };
391             rightCornerIcon.AccessibilityNameRequested += (s, e) =>
392             {
393                 e.Name = "Resize";
394             };
395
396             minimalizeIcon.SetAccessibilityReadingInfoTypes(Tizen.NUI.BaseComponents.AccessibilityReadingInfoTypes.Name);
397             maximalizeIcon.SetAccessibilityReadingInfoTypes(Tizen.NUI.BaseComponents.AccessibilityReadingInfoTypes.Name);
398             closeIcon.SetAccessibilityReadingInfoTypes(Tizen.NUI.BaseComponents.AccessibilityReadingInfoTypes.Name);
399             leftCornerIcon.SetAccessibilityReadingInfoTypes(Tizen.NUI.BaseComponents.AccessibilityReadingInfoTypes.Name);
400             rightCornerIcon.SetAccessibilityReadingInfoTypes(Tizen.NUI.BaseComponents.AccessibilityReadingInfoTypes.Name);
401
402             return true;
403         }
404
405
406         /// <summary>
407         /// Create border UI. User can override this method to draw border UI.
408         /// A top border and a bottom border are added to this view.
409         /// </summary>
410         /// <param name="borderView">The root view on which the border.</param>
411         [EditorBrowsable(EditorBrowsableState.Never)]
412         public virtual void CreateBorderView(View borderView)
413         {
414             if (borderView == null)
415             {
416                 return;
417             }
418
419             if (string.IsNullOrEmpty(borderView.BackgroundImage))
420             {
421                 borderView.BackgroundColor = DefaultBackgroundColor;
422             }
423             borderView.BorderlineColor = new Color(0.5f, 0.5f, 0.5f, 0.3f);
424             borderView.BorderlineWidth = 1.0f;
425             borderView.BorderlineOffset = -1f;
426             borderView.CornerRadius = new Vector4(0.03f, 0.03f, 0.03f, 0.03f);
427             borderView.CornerRadiusPolicy = VisualTransformPolicyType.Relative;
428
429             // Register touch event for effect when border is touched.
430             borderView.LeaveRequired = true;
431             borderView.TouchEvent += OnBorderViewTouched;
432             this.borderView = borderView;
433         }
434
435         private bool OnBorderViewTouched(object sender, View.TouchEventArgs e)
436         {
437             if (string.IsNullOrEmpty(borderView.BackgroundImage))
438             {
439                 if (e.Touch.GetState(0) == PointStateType.Started)
440                 {
441                     backgroundColor = new Color(borderView.BackgroundColor);
442                     borderView.BackgroundColor = DefaultClickedBackgroundColor;
443                 }
444                 else if (e.Touch.GetState(0) == PointStateType.Finished ||
445                         e.Touch.GetState(0) == PointStateType.Leave ||
446                         e.Touch.GetState(0) == PointStateType.Interrupted)
447                 {
448                     borderView.BackgroundColor = backgroundColor;
449                 }
450             }
451             return true;
452         }
453
454         /// Determines the behavior of pinch gesture.
455         private void OnPinchGestureDetected(object source, PinchGestureDetector.DetectedEventArgs e)
456         {
457             if (e == null)
458             {
459                 return;
460             }
461             if (e.PinchGesture.State == Gesture.StateType.Started)
462             {
463                 preScale = e.PinchGesture.Scale;
464             }
465             else if (e.PinchGesture.State == Gesture.StateType.Finished || e.PinchGesture.State == Gesture.StateType.Cancelled)
466             {
467                 if (preScale > e.PinchGesture.Scale)
468                 {
469                     if (BorderWindow.IsMaximized())
470                     {
471                         BorderWindow.Maximize(false);
472                     }
473                     else
474                     {
475                         BorderWindow.Minimize(true);
476                         OnMinimize(true);
477                     }
478                 }
479                 else
480                 {
481                     BorderWindow.Maximize(true);
482                 }
483             }
484         }
485
486         /// Determines the behavior of borders.
487         private void OnPanGestureDetected(object source, PanGestureDetector.DetectedEventArgs e)
488         {
489             if (e == null)
490             {
491                 return;
492             }
493             PanGesture panGesture = e.PanGesture;
494
495             if (panGesture.State == Gesture.StateType.Started && panGesture.Position != null)
496             {
497                 direction = BorderWindow.GetDirection(panGesture.Position.X, panGesture.Position.Y);
498
499                 if (direction == Window.BorderDirection.Move)
500                 {
501                     if (BorderWindow.IsMaximized() == true)
502                     {
503                         BorderWindow.Maximize(false);
504                     }
505                     else
506                     {
507                         OnRequestMove();
508                         BorderWindow.RequestMoveToServer();
509                     }
510                 }
511                 else if (direction != Window.BorderDirection.None && ResizePolicy != Window.BorderResizePolicyType.Fixed)
512                 {
513                     OnRequestResize();
514                     BorderWindow.RequestResizeToServer((Window.ResizeDirection)direction);
515                 }
516             }
517             else if (panGesture.State == Gesture.StateType.Finished || panGesture.State == Gesture.StateType.Cancelled)
518             {
519                 direction = Window.BorderDirection.None;
520             }
521         }
522
523         /// <summary>
524         /// This is an event callback when the left top corner icon is touched.
525         /// </summary>
526         [EditorBrowsable(EditorBrowsableState.Never)]
527         public virtual bool OnLeftTopCornerIconTouched(object sender, View.TouchEventArgs e)
528         {
529             SetDispatchParentGestureEvents(sender as View, false);
530             if (e != null && e.Touch.GetState(0) == PointStateType.Down)
531             {
532               if (ResizePolicy != Window.BorderResizePolicyType.Fixed)
533               {
534                 OnRequestResize();
535                 BorderWindow.RequestResizeToServer(Window.ResizeDirection.TopLeft);
536               }
537             }
538             return true;
539         }
540
541         /// <summary>
542         ///This is an event callback when the right bottom corner icon is touched.
543         /// </summary>
544         [EditorBrowsable(EditorBrowsableState.Never)]
545         public virtual bool OnRightTopCornerIconTouched(object sender, View.TouchEventArgs e)
546         {
547             SetDispatchParentGestureEvents(sender as View, false);
548             if (e != null && e.Touch.GetState(0) == PointStateType.Down)
549             {
550               if (ResizePolicy != Window.BorderResizePolicyType.Fixed)
551               {
552                 OnRequestResize();
553                 BorderWindow.RequestResizeToServer(Window.ResizeDirection.TopRight);
554               }
555             }
556             return true;
557         }
558
559
560         /// <summary>
561         /// This is an event callback when the left bottom corner icon is touched.
562         /// </summary>
563         [EditorBrowsable(EditorBrowsableState.Never)]
564         public virtual bool OnLeftBottomCornerIconTouched(object sender, View.TouchEventArgs e)
565         {
566             SetDispatchParentGestureEvents(sender as View, false);
567             if (e != null && e.Touch.GetState(0) == PointStateType.Down)
568             {
569               if (ResizePolicy != Window.BorderResizePolicyType.Fixed)
570               {
571                 OnRequestResize();
572                 BorderWindow.RequestResizeToServer(Window.ResizeDirection.BottomLeft);
573               }
574             }
575             return true;
576         }
577
578         /// <summary>
579         ///This is an event callback when the right bottom corner icon is touched.
580         /// </summary>
581         [EditorBrowsable(EditorBrowsableState.Never)]
582         public virtual bool OnRightBottomCornerIconTouched(object sender, View.TouchEventArgs e)
583         {
584             SetDispatchParentGestureEvents(sender as View, false);
585             if (e != null && e.Touch.GetState(0) == PointStateType.Down)
586             {
587               if (ResizePolicy != Window.BorderResizePolicyType.Fixed)
588               {
589                 OnRequestResize();
590                 BorderWindow.RequestResizeToServer(Window.ResizeDirection.BottomRight);
591               }
592             }
593             return true;
594         }
595
596
597         /// <summary>
598         /// Minimize border window.
599         /// </summary>
600         [EditorBrowsable(EditorBrowsableState.Never)]
601         protected void MinimizeBorderWindow()
602         {
603             BorderWindow.Minimize(true);
604             OnMinimize(true);
605         }
606
607         /// <summary>
608         /// This is an event callback when the minimize icon is touched.
609         /// </summary>
610         [EditorBrowsable(EditorBrowsableState.Never)]
611         public virtual bool OnMinimizeIconTouched(object sender, View.TouchEventArgs e)
612         {
613             SetDispatchParentGestureEvents(sender as View, false);
614             if (e != null && e.Touch.GetState(0) == PointStateType.Up)
615             {
616                 MinimizeBorderWindow();
617             }
618             return true;
619         }
620
621         /// <summary>
622         /// Maximize border window.
623         /// </summary>
624         [EditorBrowsable(EditorBrowsableState.Never)]
625         protected void MaximizeBorderWindow()
626         {
627             if (BorderWindow.IsMaximized())
628             {
629               BorderWindow.Maximize(false);
630             }
631             else
632             {
633               BorderWindow.Maximize(true);
634             }
635         }
636
637         /// <summary>
638         /// This is an event callback when the maximum icon is touched.
639         /// </summary>
640         [EditorBrowsable(EditorBrowsableState.Never)]
641         public virtual bool OnMaximizeIconTouched(object sender, View.TouchEventArgs e)
642         {
643             SetDispatchParentGestureEvents(sender as View, false);
644             if (e != null && e.Touch.GetState(0) == PointStateType.Up)
645             {
646                 MaximizeBorderWindow();
647             }
648             return true;
649         }
650
651         /// <summary>
652         /// Close border window.
653         /// </summary>
654         [EditorBrowsable(EditorBrowsableState.Never)]
655         protected void CloseBorderWindow()
656         {
657             BorderWindow.BorderDestroy();
658         }
659
660         /// <summary>
661         /// This is an event callback when the close icon is touched.
662         /// </summary>
663         [EditorBrowsable(EditorBrowsableState.Never)]
664         public virtual bool OnCloseIconTouched(object sender, View.TouchEventArgs e)
665         {
666             SetDispatchParentGestureEvents(sender as View, false);
667             if (e != null && e.Touch.GetState(0) == PointStateType.Up)
668             {
669                 CloseBorderWindow();
670             }
671             return true;
672         }
673
674         private void SetDispatchParentGestureEvents(View view, bool dispatch)
675         {
676             if (view != null)
677             {
678                 // If this is set, my parents will not receive gesture events.
679                 // This is to prevent the move action by PanGesture when the icon is touched.
680                 view.DispatchParentGestureEvents = dispatch;
681             }
682         }
683
684
685         private void UpdateIcons()
686         {
687             if (BorderWindow != null && borderView != null)
688             {
689                 if (BorderWindow.IsMaximized() == true)
690                 {
691                     if (maximalizeIcon != null)
692                     {
693                         maximalizeIcon.ResourceUrl = DarkPreviousIcon;
694                     }
695                     if (minimalizeIcon != null)
696                     {
697                         minimalizeIcon.ResourceUrl = DarkMinimalizeIcon;
698                     }
699                     if (closeIcon != null)
700                     {
701                         closeIcon.ResourceUrl = DarkCloseIcon;
702                     }
703                     if (leftCornerIcon != null)
704                     {
705                         leftCornerIcon.ResourceUrl = DarkLeftCornerIcon;
706                     }
707                     if (rightCornerIcon != null)
708                     {
709                         rightCornerIcon.ResourceUrl = DarkRightCornerIcon;
710                     }
711                     borderView.CornerRadius = new Vector4(0, 0, 0, 0);
712                     borderView.CornerRadiusPolicy = VisualTransformPolicyType.Relative;
713                 }
714                 else
715                 {
716                     if (maximalizeIcon != null)
717                     {
718                         maximalizeIcon.ResourceUrl = MaximalizeIcon;
719                     }
720                     if (minimalizeIcon != null)
721                     {
722                         minimalizeIcon.ResourceUrl = MinimalizeIcon;
723                     }
724                     if (closeIcon != null)
725                     {
726                         closeIcon.ResourceUrl = CloseIcon;
727                     }
728                     if (leftCornerIcon != null)
729                     {
730                         leftCornerIcon.ResourceUrl = LeftCornerIcon;
731                     }
732                     if (rightCornerIcon != null)
733                     {
734                         rightCornerIcon.ResourceUrl = RightCornerIcon;
735                     }
736                     borderView.CornerRadius = new Vector4(0.03f, 0.03f, 0.03f, 0.03f);
737                     borderView.CornerRadiusPolicy = VisualTransformPolicyType.Relative;
738                 }
739             }
740         }
741
742         /// <summary>
743         /// Called after the border UI is created.
744         /// </summary>
745         /// <param name="borderView">The border view on which the border.</param>
746         [EditorBrowsable(EditorBrowsableState.Never)]
747         public virtual void OnCreated(View borderView)
748         {
749             if (borderView == null)
750             {
751                 return;
752             }
753             this.borderView = borderView;
754
755             BorderWindow.BackgroundColor = Color.Transparent;
756
757             // Register to resize and move through pan gestures.
758             borderPanGestureDetector = new PanGestureDetector();
759             borderPanGestureDetector.Attach(borderView);
760             borderPanGestureDetector.Detected += OnPanGestureDetected;
761
762             UpdateIcons();
763         }
764
765         /// <summary>
766         /// Called when requesting a resize
767         /// </summary>
768         [EditorBrowsable(EditorBrowsableState.Never)]
769         public virtual void OnRequestResize() {}
770
771         /// <summary>
772         /// Called when the window is resized.
773         /// </summary>
774         /// <param name="width">The width of the resized window</param>
775         /// <param name="height">The height of the resized window</param>
776         [EditorBrowsable(EditorBrowsableState.Never)]
777         public virtual void OnResized(int width, int height)
778         {
779             if (overlayTimer != null)
780             {
781                 overlayTimer.Stop();
782                 overlayTimer.Dispose();
783                 overlayTimer = null;
784             }
785             UpdateIcons();
786         }
787
788         /// <summary>
789         /// Called when requesting a move
790         /// </summary>
791         [EditorBrowsable(EditorBrowsableState.Never)]
792         public virtual void OnRequestMove() {}
793
794         /// <summary>
795         /// Called when the window is moved.
796         /// </summary>
797         /// <param name="x">The x of the moved window</param>
798         /// <param name="y">The y of the moved window</param>
799         [EditorBrowsable(EditorBrowsableState.Never)]
800         public virtual void OnMoved(int x, int y) {}
801
802         /// <summary>
803         /// Called when the window is maximized.
804         /// </summary>
805         /// <param name="isMaximized">If window is maximized or unmaximized.</param>
806         [EditorBrowsable(EditorBrowsableState.Never)]
807         public virtual void OnMaximize(bool isMaximized)
808         {
809             Tizen.Log.Info("NUI", $"OnMaximize {isMaximized}\n");
810             if (BorderWindow.IsMaximized() == true)
811             {
812                 BorderWindow.SetTransparency(false);
813             }
814             else
815             {
816                 BorderWindow.SetTransparency(true);
817             }
818
819         }
820
821         /// <summary>
822         /// Called when the window is minimized.
823         /// </summary>
824         /// <param name="isMinimized">If window is mnimized or unminimized.</param>
825         [EditorBrowsable(EditorBrowsableState.Never)]
826         public virtual void OnMinimize(bool isMinimized)
827         {
828             UpdateIcons();
829         }
830
831         /// <summary>
832         /// Called when there is a change in overlay mode.
833         /// </summary>
834         /// <param name="enabled">If true, borderView has entered overlayMode.</param>
835         [EditorBrowsable(EditorBrowsableState.Never)]
836         public virtual void OnOverlayMode(bool enabled)
837         {
838             if (borderView != null && OverlayMode == true)
839             {
840                 Tizen.Log.Info("NUI", $"OnOverlayMode {enabled}\n");
841                 if (enabled == true)
842                 {
843                     backgroundColor = new Color(borderView.BackgroundColor);
844                     if (string.IsNullOrEmpty(borderView.BackgroundImage))
845                     {
846                         borderView.BackgroundColor = Color.Transparent;
847                     }
848                     borderView.Hide();
849                 }
850                 else
851                 {
852                     if (string.IsNullOrEmpty(borderView.BackgroundImage))
853                     {
854                         borderView.BackgroundColor = backgroundColor;
855                     }
856                     borderView.Show();
857                 }
858             }
859         }
860
861         /// <summary>
862         /// Show the border when OverlayMode is true and the window is now Maximize.
863         /// </summary>
864         /// <param name="time">Time(ms) for borders to disappear again</param>
865         /// <returns>True if border became show, false otherwise</returns>
866         [EditorBrowsable(EditorBrowsableState.Never)]
867         public virtual bool OverlayBorderShow(uint time = 3000)
868         {
869             if (BorderWindow != null && BorderWindow.IsMaximized())
870             {
871                 if (overlayTimer == null)
872                 {
873                     overlayTimer = new Timer(time);
874                     overlayTimer.Tick += (s, e) =>
875                     {
876                         borderView?.Hide();
877                         overlayTimer?.Stop();
878                         overlayTimer?.Dispose();
879                         overlayTimer = null;
880                         return false;
881                     };
882                     overlayTimer.Start();
883                     borderView?.Show();
884                 }
885                 else
886                 {
887                     overlayTimer.Start();
888                 }
889                 return true;
890             }
891             return false;
892         }
893
894         /// <summary>
895         /// Hide the border when OverlayMode is true and the window is now Maximize.
896         /// </summary>
897         /// <returns>True if border became hide, false otherwise</returns>
898         [EditorBrowsable(EditorBrowsableState.Never)]
899         public virtual bool OverlayBorderHide()
900         {
901             if (BorderWindow != null && BorderWindow.IsMaximized())
902             {
903                 borderView?.Hide();
904                 overlayTimer?.Stop();
905                 overlayTimer?.Dispose();
906                 overlayTimer = null;
907                 return true;
908             }
909             return false;
910         }
911
912         [EditorBrowsable(EditorBrowsableState.Never)]
913         public void Dispose()
914         {
915             Dispose(true);
916             global::System.GC.SuppressFinalize(this);
917         }
918
919         protected virtual void Dispose(bool disposing)
920         {
921             if (disposed)
922             {
923                 return;
924             }
925
926             if (disposing)
927             {
928                 borderView?.Dispose();
929                 windowView?.Dispose();
930                 borderPanGestureDetector?.Dispose();
931                 backgroundColor?.Dispose();
932                 minimalizeIcon?.Dispose();
933                 maximalizeIcon?.Dispose();
934                 closeIcon?.Dispose();
935                 leftCornerIcon?.Dispose();
936                 rightCornerIcon?.Dispose();
937                 timer?.Dispose();
938                 overlayTimer?.Dispose();
939             }
940             disposed = true;
941         }
942
943         #endregion //Methods
944
945     }
946 }