private static string currentLoadedXaml = null;
/// <summary>
+ /// The border window
+ /// </summary>
+ private bool borderEnabled = false;
+ private IBorderInterface borderInterface = null;
+
+ /// <summary>
/// Xaml loaded delegate.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
}
/// <summary>
+ /// The constructor with a stylesheet, window mode, size, position, theme option and boderInterface
+ /// It is the only way to create an IME window.
+ /// </summary>
+ /// <param name="styleSheet">The styleSheet URL.</param>
+ /// <param name="windowMode">The windowMode.</param>
+ /// <param name="windowSize">The window size.</param>
+ /// <param name="windowPosition">The window position.</param>
+ /// <param name="borderInterface"><see cref="Tizen.NUI.IBorderInterface"/>If borderInterface is null, defaultBorder is enabled.</param>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public NUIApplication(string styleSheet, Size2D windowSize, Position2D windowPosition, IBorderInterface borderInterface, WindowMode windowMode = WindowMode.Opaque) : base(new NUICoreBackend(styleSheet, windowMode, windowSize, windowPosition))
+ {
+ borderEnabled = true;
+ this.borderInterface = borderInterface;
+ }
+
+ /// <summary>
/// Occurs whenever the application is resumed.
/// </summary>
/// <since_tizen> 4 </since_tizen>
/// <since_tizen> 3 </since_tizen>
protected virtual void OnPreCreate()
{
+ if (borderEnabled)
+ {
+ GetDefaultWindow().EnableBorder(borderInterface);
+ }
}
/// <summary>
if (parentChildren != null)
{
int currentIdx = parentChildren.IndexOf(this);
+ int idx = window.IsBorderEnabled ? 1 : 0;
- if (currentIdx > 0 && currentIdx < parentChildren.Count)
+ if (currentIdx > idx && currentIdx < parentChildren.Count)
{
var low = parentChildren[currentIdx - 1];
LowerBelow(low);
parentChildren.Insert(0, this);
Interop.Layer.LowerToBottom(SwigCPtr);
+
+ if (window.IsBorderEnabled)
+ {
+ Layer bottomLayer = window.GetBorderWindowBottomLayer();
+ parentChildren.Remove(bottomLayer);
+ parentChildren.Insert(0, bottomLayer);
+ Interop.Layer.LowerToBottom(Layer.getCPtr(bottomLayer));
+ }
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
}
}
if (value < 0) throw new global::System.ArgumentOutOfRangeException(nameof(LayoutCount), "LayoutCount(" + LayoutCount + ") should not be less than zero");
- int diff = value - layoutCount;
- layoutCount = value;
-
if (window != null)
{
- window.LayoutController.LayoutCount += diff;
+ if (value == 0)
+ {
+ window.LayoutController.LayoutCount = 0;
+ }
+ else
+ {
+ int diff = value - layoutCount;
+ window.LayoutController.LayoutCount += diff;
+ }
}
+ layoutCount = value;
}
}
--- /dev/null
+/*
+ * Copyright(c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Threading;
+using Tizen.NUI.BaseComponents;
+
+namespace Tizen.NUI
+{
+ public partial class Window
+ {
+ #region Constant Fields
+ #endregion //Constant Fields
+
+ #region Fields
+ private IBorderInterface borderInterface = null;
+ private Layer borderWindowRootLayer = null;
+ private Layer borderWindowBottomLayer = null;
+ private bool isBorderWindow = false;
+ private bool isInterceptTouch = false;
+
+ private Timer overlayTimer;
+
+ // for border area
+ private View rootView = null;
+ #endregion //Fields
+
+ #region Constructors
+ #endregion //Constructors
+
+ #region Distructors
+ #endregion //Distructors
+
+ #region Delegates
+ #endregion //Delegates
+
+ #region Events
+ #endregion //Events
+
+ #region Enums
+ /// <summary>
+ /// This is an enum for the resize direction or move value when the border area is touched.
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public enum BorderDirection
+ {
+ None = ResizeDirection.None,
+ TopLeft = ResizeDirection.TopLeft,
+ Top = ResizeDirection.Top,
+ TopRight = ResizeDirection.TopRight,
+ Left = ResizeDirection.Left,
+ Right = ResizeDirection.Right,
+ BottomLeft = ResizeDirection.BottomLeft,
+ Bottom = ResizeDirection.Bottom,
+ BottomRight = ResizeDirection.BottomRight,
+ Move,
+ }
+ #endregion //Enums
+
+ #region Interfaces
+ #endregion //Interfaces
+
+ #region Properties
+ /// <summary>
+ /// Whether the border is enabled.
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public bool IsBorderEnabled => isBorderWindow;
+ #endregion //Properties
+
+ #region Indexers
+ #endregion //Indexers
+
+ #region Methods
+ /// <summary>
+ /// Enable the border window with IBorderInterface.
+ /// This adds a border area to the Window.
+ /// The border's UI is configured using IBorderInterface.
+ /// Users can reisze and move by touching the border area.
+ /// </summary>
+ /// <param name="borderInterface">The IBorderInterface.</param>
+ /// <returns>Whether the border window is enabled</returns>
+ internal bool EnableBorder(IBorderInterface borderInterface = null)
+ {
+ if (isBorderWindow == true)
+ {
+ Tizen.Log.Error("NUI", $"Already EnableBorderWindow\n");
+ return false;
+ }
+
+ if (borderInterface == null)
+ {
+ borderInterface = new DefaultBorder();
+ }
+ this.borderInterface = borderInterface;
+
+ GetDefaultLayer().Name = "OriginalRootLayer";
+
+ Resized += OnBorderWindowResized;
+
+ isBorderWindow = true;
+
+ // The current window is as below
+ // *****
+ // *****
+ // Increase the window size as much as the border area.
+ // +++++++
+ // +*****+
+ // +*****+
+ // +=====+
+ // +=====+
+ // '+' is BorderLineThickness
+ // '=' is BorderHeight
+ WindowSize += new Size2D((int)borderInterface.GetBorderLineThickness() * 2, (int)(borderInterface.GetBorderHeight() + borderInterface.GetBorderLineThickness()));
+
+ if (CreateBorder() == false)
+ {
+ WindowSize -= new Size2D((int)borderInterface.GetBorderLineThickness() * 2, (int)(borderInterface.GetBorderHeight() + borderInterface.GetBorderLineThickness()));
+ Resized -= OnBorderWindowResized;
+ isBorderWindow = false;
+ this.borderInterface = null;
+ return false;
+ }
+
+
+ SetTransparency(true);
+ BackgroundColor = Color.Transparent;
+ borderInterface.SetWindow(this);
+
+ EnableFloatingMode(true);
+
+ borderInterface.OnCreated(rootView);
+
+ return true;
+ }
+
+ /// Create the border UI.
+ private bool CreateBorder()
+ {
+ rootView = new View()
+ {
+ WidthResizePolicy = ResizePolicyType.FillToParent,
+ HeightResizePolicy = ResizePolicyType.FillToParent,
+ BackgroundColor = Color.Transparent,
+ };
+
+ // Gets the Border's UI.
+ borderInterface.CreateBorderView(rootView);
+ if (rootView == null)
+ {
+ return false;
+ }
+ else
+ {
+ if (borderInterface.IsOverlayMode() == true)
+ {
+ rootView.InterceptTouchEvent += OverlayInterceptTouch;
+ }
+ // Add a view to the border layer.
+ GetBorderWindowBottomLayer().Add(rootView);
+
+ return true;
+ }
+ }
+
+ /// <summary>
+ /// Calculates which direction to resize or to move.
+ /// </summary>
+ /// <param name="xPosition">The X position.</param>
+ /// <param name="yPosition">The Y position.</param>
+ /// <returns>The BorderDirection</returns>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public BorderDirection GetDirection(float xPosition, float yPosition)
+ {
+ BorderDirection direction = BorderDirection.None;
+
+ // check bottom left corner
+ if (xPosition < borderInterface.GetTouchThickness() && yPosition > WindowSize.Height + borderInterface.GetBorderHeight() - borderInterface.GetTouchThickness())
+ {
+ direction = BorderDirection.BottomLeft;
+ }
+ // check bottom right corner
+ else if (xPosition > WindowSize.Width + borderInterface.GetBorderLineThickness()*2 - borderInterface.GetTouchThickness() && yPosition > WindowSize.Height + borderInterface.GetBorderHeight() - borderInterface.GetTouchThickness())
+ {
+ direction = BorderDirection.BottomRight;
+ }
+ // check top left corner
+ else if (xPosition < borderInterface.GetTouchThickness() && yPosition < borderInterface.GetTouchThickness())
+ {
+ direction = BorderDirection.TopLeft;
+ }
+ // check top right corner
+ else if (xPosition > WindowSize.Width + borderInterface.GetBorderLineThickness()*2 - borderInterface.GetTouchThickness() && yPosition < borderInterface.GetTouchThickness())
+ {
+ direction = BorderDirection.TopRight;
+ }
+ // check left side
+ else if (xPosition < borderInterface.GetTouchThickness())
+ {
+ direction = BorderDirection.Left;
+ }
+ // check right side
+ else if (xPosition > WindowSize.Width + borderInterface.GetBorderLineThickness()*2 - borderInterface.GetTouchThickness())
+ {
+ direction = BorderDirection.Right;
+ }
+ // check bottom side
+ else if (yPosition > WindowSize.Height + borderInterface.GetBorderHeight() + borderInterface.GetBorderLineThickness() - borderInterface.GetTouchThickness())
+ {
+ direction = BorderDirection.Bottom;
+ }
+ // check top side
+ else if (yPosition < borderInterface.GetTouchThickness())
+ {
+ direction = BorderDirection.Top;
+ }
+ // check move
+ else if (yPosition > WindowSize.Height)
+ {
+ direction = BorderDirection.Move;
+ }
+
+ return direction;
+ }
+
+
+ private bool OverlayInterceptTouch(object sender, View.TouchEventArgs e)
+ {
+ if (isInterceptTouch == true && overlayTimer != null)
+ {
+ overlayTimer.Start();
+ }
+ return false;
+ }
+
+ private bool OnTick(object o, Timer.TickEventArgs e)
+ {
+ GetBorderWindowBottomLayer().LowerToBottom();
+ if (rootView != null)
+ {
+ rootView.Hide();
+ }
+ isInterceptTouch = false;
+
+ overlayTimer.Stop();
+ overlayTimer.Dispose();
+ overlayTimer = null;
+ return false;
+ }
+
+ // Intercept touch on window.
+ private bool OnWinInterceptTouch(object sender, Window.TouchEventArgs e)
+ {
+ if (e.Touch.GetState(0) == PointStateType.Up)
+ {
+ if (isInterceptTouch == false && overlayTimer == null)
+ {
+ overlayTimer = new Timer(3000);
+ overlayTimer.Tick += OnTick;
+ overlayTimer.Start();
+ GetBorderWindowBottomLayer().RaiseToTop();
+ if (rootView != null)
+ {
+ rootView.Show();
+ }
+ isInterceptTouch = true;
+ }
+ }
+ return false;
+ }
+
+ private void OverlayMode(bool enable)
+ {
+ if (borderInterface.IsOverlayMode() == true)
+ {
+ if (enable == true)
+ {
+ InterceptTouchEvent += OnWinInterceptTouch;
+ if (rootView != null)
+ {
+ rootView.Hide();
+ }
+ }
+ else
+ {
+ if (overlayTimer != null)
+ {
+ overlayTimer.Stop();
+ overlayTimer.Dispose();
+ overlayTimer = null;
+ }
+ isInterceptTouch = false;
+ InterceptTouchEvent -= OnWinInterceptTouch;
+ GetBorderWindowBottomLayer().LowerToBottom();
+ if (rootView != null)
+ {
+ rootView.Show();
+ }
+ }
+ }
+ }
+
+
+ // Called when the window size has changed.
+ private void OnBorderWindowResized(object sender, Window.ResizedEventArgs e)
+ {
+ Tizen.Log.Info("NUI", $"OnBorderWindowResized {e.WindowSize.Width},{e.WindowSize.Height}\n");
+ int resizeWidth = e.WindowSize.Width;
+ int resizeHeight = e.WindowSize.Height;
+ if (borderInterface.GetMinSize() != null)
+ {
+ resizeWidth = borderInterface.GetMinSize().Width > resizeWidth ? (int)borderInterface.GetMinSize().Width : resizeWidth;
+ resizeHeight = borderInterface.GetMinSize().Height > resizeHeight ? (int)borderInterface.GetMinSize().Height : resizeHeight;
+ }
+
+ if (borderInterface.GetMaxSize() != null)
+ {
+ resizeWidth = borderInterface.GetMaxSize().Width < resizeWidth ? (int)borderInterface.GetMaxSize().Width : resizeWidth;
+ resizeHeight = borderInterface.GetMaxSize().Height < resizeHeight ? (int)borderInterface.GetMaxSize().Height : resizeHeight;
+ }
+
+ if (resizeWidth != e.WindowSize.Width || resizeHeight != e.WindowSize.Height)
+ {
+ WindowSize = new Size2D(resizeWidth, resizeHeight);
+ }
+
+ if (borderInterface.IsOverlayMode() == true && IsMaximized() == true)
+ {
+ Interop.ActorInternal.SetSize(GetBorderWindowRootLayer().SwigCPtr, resizeWidth, resizeHeight);
+ Interop.ActorInternal.SetSize(GetBorderWindowBottomLayer().SwigCPtr, resizeWidth, resizeHeight);
+ OverlayMode(true);
+ }
+ else
+ {
+ Interop.ActorInternal.SetSize(GetBorderWindowRootLayer().SwigCPtr, resizeWidth, resizeHeight);
+ Interop.ActorInternal.SetSize(GetBorderWindowBottomLayer().SwigCPtr, resizeWidth + borderInterface.GetBorderLineThickness() * 2, resizeHeight+borderInterface.GetBorderHeight() + borderInterface.GetBorderLineThickness());
+ OverlayMode(false);
+ }
+
+ borderInterface.OnResized(resizeWidth, resizeHeight);
+
+ if (NDalicPINVOKE.SWIGPendingException.Pending) { throw NDalicPINVOKE.SWIGPendingException.Retrieve(); }
+ }
+
+ internal Layer GetBorderWindowBottomLayer()
+ {
+ if (borderWindowBottomLayer == null)
+ {
+ borderWindowBottomLayer = new Layer();
+ borderWindowBottomLayer.Name = "BorderWindowBottomLayer";
+ Interop.ActorInternal.SetParentOrigin(borderWindowBottomLayer.SwigCPtr, Tizen.NUI.ParentOrigin.TopCenter.SwigCPtr);
+ Interop.Actor.SetAnchorPoint(borderWindowBottomLayer.SwigCPtr, Tizen.NUI.PivotPoint.TopCenter.SwigCPtr);
+ Interop.Actor.Add(rootLayer.SwigCPtr, borderWindowBottomLayer.SwigCPtr);
+ Interop.ActorInternal.SetSize(borderWindowBottomLayer.SwigCPtr, WindowSize.Width+borderInterface.GetBorderLineThickness()*2, WindowSize.Height+borderInterface.GetBorderLineThickness());
+ borderWindowBottomLayer.SetWindow(this);
+ borderWindowBottomLayer.LowerToBottom();
+
+ if (NDalicPINVOKE.SWIGPendingException.Pending) { throw NDalicPINVOKE.SWIGPendingException.Retrieve(); }
+ }
+ return borderWindowBottomLayer;
+ }
+
+ internal Layer GetBorderWindowRootLayer()
+ {
+ if (borderWindowRootLayer == null)
+ {
+ borderWindowRootLayer = new Layer();
+ borderWindowRootLayer.Name = "RootLayer";
+ Interop.ActorInternal.SetParentOrigin(borderWindowRootLayer.SwigCPtr, Tizen.NUI.ParentOrigin.TopCenter.SwigCPtr);
+ Interop.Actor.SetAnchorPoint(borderWindowRootLayer.SwigCPtr, Tizen.NUI.PivotPoint.TopCenter.SwigCPtr);
+ Interop.Actor.Add(rootLayer.SwigCPtr, borderWindowRootLayer.SwigCPtr);
+ Interop.ActorInternal.SetSize(borderWindowRootLayer.SwigCPtr, WindowSize.Width, WindowSize.Height-borderInterface.GetBorderHeight()-borderInterface.GetBorderLineThickness());
+ Interop.ActorInternal.SetPosition(borderWindowRootLayer.SwigCPtr, 0, borderInterface.GetBorderLineThickness());
+ Tizen.NUI.Object.SetProperty(borderWindowRootLayer.SwigCPtr, Tizen.NUI.BaseComponents.View.Property.ClippingMode, new Tizen.NUI.PropertyValue((int)Tizen.NUI.ClippingModeType.ClipToBoundingBox));
+
+ if (NDalicPINVOKE.SWIGPendingException.Pending) { throw NDalicPINVOKE.SWIGPendingException.Retrieve(); }
+ }
+
+ return borderWindowRootLayer;
+ }
+
+ internal void DisposeBorder()
+ {
+ Resized -= OnBorderWindowResized;
+ if (borderInterface.IsOverlayMode() == true && rootView != null)
+ {
+ rootView.InterceptTouchEvent -= OverlayInterceptTouch;
+ }
+ borderInterface.Dispose();
+ GetBorderWindowBottomLayer().Dispose();
+ }
+
+ private void convertBorderWindowSizeToRealWindowSize(Uint16Pair size)
+ {
+ if (isBorderWindow == true)
+ {
+ var height = (ushort)(size.GetHeight() + borderInterface.GetBorderHeight()+borderInterface.GetBorderLineThickness());
+ var width = (ushort)(size.GetWidth() + borderInterface.GetBorderLineThickness()*2);
+ size.SetHeight(height);
+ size.SetWidth(width);
+ }
+ }
+
+ private void convertRealWindowSizeToBorderWindowSize(Uint16Pair size)
+ {
+ if (isBorderWindow == true && !(borderInterface.IsOverlayMode() == true && IsMaximized() == true))
+ {
+ var height = (ushort)(size.GetHeight() - borderInterface.GetBorderHeight()-borderInterface.GetBorderLineThickness());
+ var width = (ushort)(size.GetWidth() - borderInterface.GetBorderLineThickness()*2);
+ size.SetHeight(height);
+ size.SetWidth(width);
+ }
+ }
+ #endregion //Methods
+
+ #region Structs
+ #endregion //Structs
+
+ #region Classes
+ #endregion //Classes
+ }
+
+
+
+}
--- /dev/null
+/*
+ * Copyright(c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+using System;
+using System.ComponentModel;
+using Tizen.NUI.BaseComponents;
+
+namespace Tizen.NUI
+{
+ /// <summary>
+ /// This class creates a border UI.
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public class DefaultBorder : IBorderInterface
+ {
+ #region Constant Fields
+ private static readonly string ResourcePath = FrameworkInformation.ResourcePath;
+ private static readonly string MinimalizeIcon = ResourcePath + "minimalize.png";
+ private static readonly string MaximalizeIcon = ResourcePath + "maximalize.png";
+ private static readonly string PreviousIcon = ResourcePath + "smallwindow.png";
+ private static readonly string CloseIcon = ResourcePath + "close.png";
+ private static readonly string LeftCornerIcon = ResourcePath + "leftCorner.png";
+ private static readonly string RightCornerIcon = ResourcePath + "rightCorner.png";
+
+ private static readonly string DarkMinimalizeIcon = ResourcePath + "dark_minimalize.png";
+ private static readonly string DarkMaximalizeIcon = ResourcePath + "dark_maximalize.png";
+ private static readonly string DarkPreviousIcon = ResourcePath + "dark_smallwindow.png";
+ private static readonly string DarkCloseIcon = ResourcePath + "dark_close.png";
+ private static readonly string DarkLeftCornerIcon = ResourcePath + "dark_leftCorner.png";
+ private static readonly string DarkRightCornerIcon = ResourcePath + "dark_rightCorner.png";
+
+
+ private static readonly uint DefaultHeight = 50;
+ private static readonly uint DefaultLineThickness = 5;
+ private static readonly uint DefaultTouchThickness = 20;
+ private static readonly Color DefaultBackgroundColor = new Color(1, 1, 1, 0.3f);
+ private static readonly Color DefaultClickedBackgroundColor = new Color(1, 1, 1, 0.4f);
+ private static readonly Size2D DefaultMinSize = new Size2D(500, 0);
+ #endregion //Constant Fields
+
+
+ #region Fields
+ private Color backgroundColor;
+ private View rootView;
+ private Window window = null;
+
+ private ImageView minimalizeIcon;
+ private ImageView maximalizeIcon;
+ private ImageView closeIcon;
+ private ImageView leftCornerIcon;
+ private ImageView rightCornerIcon;
+
+ private Window.BorderDirection direction = Window.BorderDirection.None;
+ private float preScale = 0;
+
+ private View windowView = null;
+ private bool isWinGestures = false;
+ private Timer timer;
+
+ private CurrentGesture currentGesture = CurrentGesture.None;
+ #endregion //Fields
+
+ #region Events
+ private PanGestureDetector borderPanGestureDetector;
+ private PinchGestureDetector borderPinchGestureDetector;
+ private PanGestureDetector winPanGestureDetector;
+ private TapGestureDetector winTapGestureDetector;
+ #endregion //Events
+
+ #region Enums
+ private enum CurrentGesture
+ {
+ None = 0,
+ TapGesture = 1,
+ PanGesture = 2,
+ PinchGesture = 3,
+ }
+ #endregion //Enums
+
+ #region Methods
+
+ /// <summary>
+ /// Sets the window which the border is enabled.
+ /// </summary>
+ /// <param name="window">The window in which the border is enabled.</param>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public virtual void SetWindow(Window window)
+ {
+ this.window = window;
+ }
+
+ /// <summary>
+ /// Returns the window which borders is enabled.
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public virtual Window GetWindow()
+ {
+ return window;
+ }
+
+ /// <summary>
+ /// Create border UI. Users can override this method to draw border UI.
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public virtual void CreateBorderView(View rootView)
+ {
+ this.rootView = rootView;
+ rootView.BackgroundColor = DefaultBackgroundColor;
+ rootView.CornerRadius = new Vector4(0.03f, 0.03f, 0.03f, 0.03f);
+ rootView.CornerRadiusPolicy = VisualTransformPolicyType.Relative;
+
+ View borderView = new View()
+ {
+ Layout = new LinearLayout()
+ {
+ LinearAlignment = LinearLayout.Alignment.End,
+ LinearOrientation = LinearLayout.Orientation.Horizontal,
+ },
+ WidthSpecification = LayoutParamPolicies.MatchParent,
+ HeightSpecification = LayoutParamPolicies.MatchParent,
+ };
+
+ minimalizeIcon = new ImageView()
+ {
+ ResourceUrl = MinimalizeIcon,
+ PositionUsesPivotPoint = true,
+ PivotPoint = PivotPoint.BottomLeft,
+ ParentOrigin = ParentOrigin.BottomLeft,
+ };
+
+ maximalizeIcon = new ImageView()
+ {
+ ResourceUrl = MaximalizeIcon,
+ PositionUsesPivotPoint = true,
+ PivotPoint = PivotPoint.BottomLeft,
+ ParentOrigin = ParentOrigin.BottomLeft,
+ };
+
+ closeIcon = new ImageView()
+ {
+ ResourceUrl = CloseIcon,
+ PositionUsesPivotPoint = true,
+ PivotPoint = PivotPoint.BottomLeft,
+ ParentOrigin = ParentOrigin.BottomLeft,
+ };
+
+ leftCornerIcon = new ImageView()
+ {
+ ResourceUrl = LeftCornerIcon,
+ PositionUsesPivotPoint = true,
+ PivotPoint = PivotPoint.BottomLeft,
+ ParentOrigin = ParentOrigin.BottomLeft,
+ };
+
+ rightCornerIcon = new ImageView()
+ {
+ ResourceUrl = RightCornerIcon,
+ PositionUsesPivotPoint = true,
+ PivotPoint = PivotPoint.BottomLeft,
+ ParentOrigin = ParentOrigin.BottomLeft,
+ };
+
+ rootView.Add(leftCornerIcon);
+ borderView.Add(minimalizeIcon);
+ borderView.Add(maximalizeIcon);
+ borderView.Add(closeIcon);
+ borderView.Add(rightCornerIcon);
+ rootView.Add(borderView);
+
+ minimalizeIcon.TouchEvent += OnMinimizeIconTouched;
+ maximalizeIcon.TouchEvent += OnMaximizeIconTouched;
+ closeIcon.TouchEvent += OnCloseIconTouched;
+ leftCornerIcon.TouchEvent += OnLeftCornerIconTouched;
+ rightCornerIcon.TouchEvent += OnRightCornerIconTouched;
+ }
+
+ /// Determines the behavior of pinch gesture.
+ private void OnPinchGestureDetected(object source, PinchGestureDetector.DetectedEventArgs e)
+ {
+ if (e.PinchGesture.State == Gesture.StateType.Started)
+ {
+ preScale = e.PinchGesture.Scale;
+ }
+ else if (e.PinchGesture.State == Gesture.StateType.Finished || e.PinchGesture.State == Gesture.StateType.Cancelled)
+ {
+ if (preScale > e.PinchGesture.Scale)
+ {
+ if (window.IsMaximized())
+ {
+ window.Maximize(false);
+ }
+ else
+ {
+ window.Minimize(true);
+ }
+ }
+ else
+ {
+ window.Maximize(true);
+ }
+ }
+ }
+
+ /// Determines the behavior of borders.
+ private void OnPanGestureDetected(object source, PanGestureDetector.DetectedEventArgs e)
+ {
+ PanGesture panGesture = e.PanGesture;
+
+ if (panGesture.State == Gesture.StateType.Started)
+ {
+ direction = window.GetDirection(panGesture.Position.X, panGesture.Position.Y);
+ if (direction == Window.BorderDirection.Move)
+ {
+ if (window.IsMaximized() == true)
+ {
+ window.Maximize(false);
+ }
+ else
+ {
+ window.RequestMoveToServer();
+ }
+ }
+ else if (direction != Window.BorderDirection.None)
+ {
+ window.RequestResizeToServer((Window.ResizeDirection)direction);
+ }
+ }
+ else if (panGesture.State == Gesture.StateType.Continuing)
+ {
+ if (direction == Window.BorderDirection.BottomLeft || direction == Window.BorderDirection.BottomRight || direction == Window.BorderDirection.TopLeft || direction == Window.BorderDirection.TopRight)
+ {
+ window.WindowSize += new Size2D((int)panGesture.ScreenDisplacement.X, (int)panGesture.ScreenDisplacement.Y);
+ }
+ else if (direction == Window.BorderDirection.Left || direction == Window.BorderDirection.Right)
+ {
+ window.WindowSize += new Size2D((int)panGesture.ScreenDisplacement.X, 0);
+ }
+ else if (direction == Window.BorderDirection.Bottom || direction == Window.BorderDirection.Top)
+ {
+ window.WindowSize += new Size2D(0, (int)panGesture.ScreenDisplacement.Y);
+ }
+ else if (direction == Window.BorderDirection.Move)
+ {
+ window.WindowPosition += new Position2D((int)panGesture.ScreenDisplacement.X, (int)panGesture.ScreenDisplacement.Y);
+ }
+ }
+ else if (panGesture.State == Gesture.StateType.Finished || panGesture.State == Gesture.StateType.Cancelled)
+ {
+ direction = Window.BorderDirection.None;
+ ClearWindowGesture();
+ }
+ }
+
+
+ /// <summary>
+ /// This is an event callback when the left corner icon is touched.
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public virtual bool OnLeftCornerIconTouched(object sender, View.TouchEventArgs e)
+ {
+ if (e.Touch.GetState(0) == PointStateType.Down)
+ {
+ ClearWindowGesture();
+ if(window.IsMinimized() == true)
+ {
+ window.RequestResizeToServer(Window.ResizeDirection.TopLeft);
+ }
+ else
+ {
+ window.RequestResizeToServer(Window.ResizeDirection.BottomLeft);
+ }
+ }
+ return true;
+ }
+
+ /// <summary>
+ ///This is an event callback when the right corner icon is touched.
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public virtual bool OnRightCornerIconTouched(object sender, View.TouchEventArgs e)
+ {
+ if (e.Touch.GetState(0) == PointStateType.Down)
+ {
+ ClearWindowGesture();
+ if(window.IsMinimized() == true)
+ {
+ window.RequestResizeToServer(Window.ResizeDirection.TopRight);
+ }
+ else
+ {
+ window.RequestResizeToServer(Window.ResizeDirection.BottomRight);
+ }
+ }
+ return true;
+ }
+
+
+ /// <summary>
+ /// This is an event callback when the minimize button is touched.
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public virtual bool OnMinimizeIconTouched(object sender, View.TouchEventArgs e)
+ {
+ if (e.Touch.GetState(0) == PointStateType.Up)
+ {
+ ClearWindowGesture();
+ window.Minimize(true);
+ }
+ return true;
+ }
+
+ /// <summary>
+ /// This is an event callback when the maximum button is touched.
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public virtual bool OnMaximizeIconTouched(object sender, View.TouchEventArgs e)
+ {
+ if (e.Touch.GetState(0) == PointStateType.Up)
+ {
+ ClearWindowGesture();
+ if (window.IsMaximized())
+ {
+ window.Maximize(false);
+ }
+ else
+ {
+ window.Maximize(true);
+ }
+ }
+ return true;
+ }
+
+ /// <summary>
+ /// This is an event callback when the close button is touched.
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public virtual bool OnCloseIconTouched(object sender, View.TouchEventArgs e)
+ {
+ if (e.Touch.GetState(0) == PointStateType.Up)
+ {
+ window.Destroy();
+ window = null;
+ }
+ return true;
+ }
+
+
+ private void UpdateIcons()
+ {
+ if (window != null && rootView != null)
+ {
+ if (window.IsMaximized() == true)
+ {
+ if (maximalizeIcon != null)
+ {
+ maximalizeIcon.ResourceUrl = DarkPreviousIcon;
+ }
+ if (minimalizeIcon != null)
+ {
+ minimalizeIcon.ResourceUrl = DarkMinimalizeIcon;
+ }
+ if (closeIcon != null)
+ {
+ closeIcon.ResourceUrl = DarkCloseIcon;
+ }
+ if (leftCornerIcon != null)
+ {
+ leftCornerIcon.ResourceUrl = DarkLeftCornerIcon;
+ }
+ if (rightCornerIcon != null)
+ {
+ rightCornerIcon.ResourceUrl = DarkRightCornerIcon;
+ }
+ rootView.CornerRadius = new Vector4(0, 0, 0, 0);
+ rootView.CornerRadiusPolicy = VisualTransformPolicyType.Relative;
+ window.SetTransparency(false);
+ }
+ else
+ {
+ if (maximalizeIcon != null)
+ {
+ maximalizeIcon.ResourceUrl = MaximalizeIcon;
+ }
+ if (minimalizeIcon != null)
+ {
+ minimalizeIcon.ResourceUrl = MinimalizeIcon;
+ }
+ if (closeIcon != null)
+ {
+ closeIcon.ResourceUrl = CloseIcon;
+ }
+ if (leftCornerIcon != null)
+ {
+ leftCornerIcon.ResourceUrl = LeftCornerIcon;
+ }
+ if (rightCornerIcon != null)
+ {
+ rightCornerIcon.ResourceUrl = RightCornerIcon;
+ }
+ rootView.CornerRadius = new Vector4(0.03f, 0.03f, 0.03f, 0.03f);
+ rootView.CornerRadiusPolicy = VisualTransformPolicyType.Relative;
+ window.SetTransparency(true);
+ }
+ }
+ }
+
+
+ /// <summary>
+ /// Called after the border UI is created.
+ /// </summary>
+ /// <param name="rootView">The root view on which the border.</param>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public virtual void OnCreated(View rootView)
+ {
+ // Register to resize and move through pan gestures.
+ borderPanGestureDetector = new PanGestureDetector();
+ borderPanGestureDetector.Attach(rootView);
+ borderPanGestureDetector.Detected += OnPanGestureDetected;
+
+ // Register touch event for effect when border is touched.
+ rootView.LeaveRequired = true;
+ rootView.TouchEvent += (s, e) =>
+ {
+ if (e.Touch.GetState(0) == PointStateType.Started)
+ {
+ backgroundColor = new Color(rootView.BackgroundColor);
+ rootView.BackgroundColor = DefaultClickedBackgroundColor;
+ }
+ else if (e.Touch.GetState(0) == PointStateType.Finished ||
+ e.Touch.GetState(0) == PointStateType.Leave ||
+ e.Touch.GetState(0) == PointStateType.Interrupted)
+ {
+ rootView.BackgroundColor = backgroundColor;
+ }
+ return true;
+ };
+
+ borderPinchGestureDetector = new PinchGestureDetector();
+ borderPinchGestureDetector.Attach(rootView);
+ borderPinchGestureDetector.Detected += OnPinchGestureDetected;
+
+ AddInterceptGesture();
+ }
+
+
+ // Register an intercept touch event on the window.
+ private void AddInterceptGesture()
+ {
+ isWinGestures = false;
+ window.InterceptTouchEvent += OnWinInterceptedTouch;
+ }
+
+ // Intercept touch on window.
+ private bool OnWinInterceptedTouch(object sender, Window.TouchEventArgs e)
+ {
+ if (e.Touch.GetState(0) == PointStateType.Stationary && e.Touch.GetPointCount() == 2)
+ {
+ if (isWinGestures == false && timer == null)
+ {
+ timer = new Timer(300);
+ timer.Tick += OnTick;
+ timer.Start();
+ }
+ }
+ else
+ {
+ currentGesture = CurrentGesture.None;
+ if (timer != null)
+ {
+ timer.Stop();
+ timer.Dispose();
+ }
+ }
+ return false;
+ }
+
+ // If two finger long press is done, create a windowView.
+ // then, Register a gesture on the windowView to do a resize or move.
+ private bool OnTick(object o, Timer.TickEventArgs e)
+ {
+ windowView = new View()
+ {
+ WidthResizePolicy = ResizePolicyType.FillToParent,
+ HeightResizePolicy = ResizePolicyType.FillToParent,
+ BackgroundColor = new Vector4(1, 1, 1, 0.5f),
+ };
+ windowView.TouchEvent += (s, e) =>
+ {
+ return true;
+ };
+ window.Add(windowView);
+
+ winTapGestureDetector = new TapGestureDetector();
+ winTapGestureDetector.Attach(windowView);
+ winTapGestureDetector.SetMaximumTapsRequired(3);
+ winTapGestureDetector.Detected += OnWinTapGestureDetected;
+
+ winPanGestureDetector = new PanGestureDetector();
+ winPanGestureDetector.Attach(windowView);
+ winPanGestureDetector.Detected += OnWinPanGestureDetected;
+
+ window.InterceptTouchEvent -= OnWinInterceptedTouch;
+ isWinGestures = true;
+ return false;
+ }
+
+ // Behavior when the window is tapped.
+ private void OnWinTapGestureDetected(object source, TapGestureDetector.DetectedEventArgs e)
+ {
+ if (currentGesture <= CurrentGesture.TapGesture)
+ {
+ currentGesture = CurrentGesture.TapGesture;
+ if (e.TapGesture.NumberOfTaps == 2)
+ {
+ if (window.IsMaximized() == false)
+ {
+ window.Maximize(true);
+ }
+ else
+ {
+ window.Maximize(false);
+ }
+ }
+ else
+ {
+ ClearWindowGesture();
+ }
+ }
+ }
+
+ // Window moves through pan gestures.
+ private void OnWinPanGestureDetected(object source, PanGestureDetector.DetectedEventArgs e)
+ {
+ if (currentGesture <= CurrentGesture.PanGesture /*&& panGesture.NumberOfTouches == 1*/)
+ {
+ PanGesture panGesture = e.PanGesture;
+
+ if (panGesture.State == Gesture.StateType.Started)
+ {
+ currentGesture = CurrentGesture.PanGesture;
+ if (window.IsMaximized() == true)
+ {
+ window.Maximize(false);
+ }
+ else
+ {
+ window.RequestMoveToServer();
+ }
+ }
+ else if (panGesture.State == Gesture.StateType.Finished || panGesture.State == Gesture.StateType.Cancelled)
+ {
+ currentGesture = CurrentGesture.None;
+ ClearWindowGesture();
+ }
+ }
+ }
+
+ private void ClearWindowGesture()
+ {
+ if (isWinGestures)
+ {
+ winPanGestureDetector.Dispose();
+ winTapGestureDetector.Dispose();
+
+ isWinGestures = false;
+ window.Remove(windowView);
+ window.InterceptTouchEvent += OnWinInterceptedTouch;
+ }
+ }
+
+ /// <summary>
+ /// Called when the window is resized.
+ /// </summary>
+ /// <param name="width">The width of the resized window</param>
+ /// <param name="height">The height of the resized window</param>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public virtual void OnResized(int width, int height)
+ {
+ UpdateIcons();
+ }
+
+ /// <summary>
+ /// Returns the thickness of the border.
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public virtual uint GetBorderLineThickness()
+ {
+ return DefaultLineThickness;
+ }
+
+ /// <summary>
+ /// Returns the thickness of the border's touch area.
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public virtual uint GetTouchThickness()
+ {
+ return DefaultTouchThickness;
+ }
+
+ /// <summary>
+ /// Returns the height of the border.
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public virtual uint GetBorderHeight()
+ {
+ return DefaultHeight;
+ }
+
+ /// <summary>
+ /// Returns the minimum size by which the window will small.
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public virtual Size2D GetMinSize()
+ {
+ return DefaultMinSize;
+ }
+
+ /// <summary>
+ /// Returns the maximum size by which the window will big.
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public virtual Size2D GetMaxSize()
+ {
+ return null;
+ }
+
+ /// <summary>
+ /// Returns whether overlay mode is present.
+ /// If overlay mode is true, the border area is hidden when the window is maximized.
+ /// And if you touched at screen, the border area is shown on the screen.
+ /// Default value is false;
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public virtual bool IsOverlayMode()
+ {
+ return false;
+ }
+
+ /// <summary>
+ /// Dispose
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public virtual void Dispose()
+ {
+ ClearWindowGesture();
+ window.InterceptTouchEvent -= OnWinInterceptedTouch;
+ borderPanGestureDetector.Dispose();
+ borderPinchGestureDetector.Dispose();
+ if (windowView != null)
+ {
+ windowView.Dispose();
+ }
+ if (rootView != null)
+ {
+ rootView.Dispose();
+ }
+ }
+ #endregion //Methods
+
+ }
+}
--- /dev/null
+/*
+ * Copyright(c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+using System;
+using System.ComponentModel;
+using Tizen.NUI.BaseComponents;
+
+namespace Tizen.NUI
+{
+ /// <summary>
+ /// This is the interface used to draw the border UI.
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public interface IBorderInterface
+ {
+ /// <summary>
+ /// Create border UI. User can override this method to draw border UI.
+ /// </summary>
+ /// <param name="rootView">The root view on which the border.</param>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public void CreateBorderView(View rootView);
+
+
+ /// <summary>
+ /// Called after the border UI is created.
+ /// </summary>
+ /// <param name="rootView">The root view on which the border.</param>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public void OnCreated(View rootView);
+
+ /// <summary>
+ /// Called when the window is resized.
+ /// </summary>
+ /// <param name="width">The width of the resized window</param>
+ /// <param name="height">The height of the resized window</param>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public void OnResized(int width, int height);
+
+ /// <summary>
+ /// Returns the thickness of the border.
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public uint GetBorderLineThickness();
+
+ /// <summary>
+ /// Returns the thickness of the border's touch area.
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public uint GetTouchThickness();
+
+ /// <summary>
+ /// Returns the height of the border.
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public uint GetBorderHeight();
+
+ /// <summary>
+ /// Returns the minimum size by which the window will small.
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public Size2D GetMinSize();
+
+ /// <summary>
+ /// Returns the maximum size by which the window will big.
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public Size2D GetMaxSize();
+
+ /// <summary>
+ /// Sets The window to which the border is added.
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public void SetWindow(Window window);
+
+ /// <summary>
+ /// Returns the window with borders added.
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public Window GetWindow();
+
+ /// <summary>
+ /// Returns whether overlay mode is present.
+ /// If overlay mode is true, the border area is hidden when the window is maximized.
+ /// And if you touched at screen, the border area is shown on the screen.
+ /// Default value is false;
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public bool IsOverlayMode();
+
+ /// <summary>
+ /// Dispose
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public void Dispose();
+ }
+}
{
private HandleRef stageCPtr;
private Layer rootLayer;
+ private Layer borderLayer;
private string windowTitle;
private List<Layer> childLayers = new List<Layer>();
private LayoutController localController;
}
/// <summary>
+ /// Creates a new Window with a specific name.<br />
+ /// This creates an extra window in addition to the default main window<br />
+ /// </summary>
+ /// <param name="name">The name for extra window. </param>
+ /// <param name="borderInterface"><see cref="Tizen.NUI.IBorderInterface"/>If borderInterface is null, defaultBorder is enabled.</param>
+ /// <param name="windowPosition">The position and size of the Window.</param>
+ /// <param name="isTranslucent">Whether Window is translucent.</param>
+ /// <returns>A new Window.</returns>
+ /// <feature> http://tizen.org/feature/opengles.surfaceless_context </feature>
+ /// <exception cref="NotSupportedException">The required feature is not supported.</exception>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public Window(string name, IBorderInterface borderInterface, Rectangle windowPosition = null, bool isTranslucent = false) : this(Interop.Window.New(Rectangle.getCPtr(windowPosition), name, isTranslucent), true)
+ {
+ if (IsSupportedMultiWindow() == false)
+ {
+ NUILog.Error("This device does not support surfaceless_context. So Window cannot be created. ");
+ }
+ this.windowTitle = name;
+ this.EnableBorder(borderInterface);
+ if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+ }
+
+
+ /// <summary>
/// Enumeration for orientation of the window is the way in which a rectangular page is oriented for normal viewing.
/// </summary>
/// <since_tizen> 3 </since_tizen>
public enum ResizeDirection
{
/// <summary>
+ /// None type.
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ None = 0,
+ /// <summary>
/// Start resizing window to the top-left edge.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
{
throw new ArgumentNullException(nameof(layer));
}
- Interop.Window.Add(SwigCPtr, Layer.getCPtr(layer));
- if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+
+ if (isBorderWindow)
+ {
+ Interop.Actor.Add(GetBorderWindowRootLayer().SwigCPtr, layer.SwigCPtr);
+ if (NDalicPINVOKE.SWIGPendingException.Pending) { throw NDalicPINVOKE.SWIGPendingException.Retrieve(); }
+ }
+ else
+ {
+ Interop.Window.Add(SwigCPtr, Layer.getCPtr(layer));
+ if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+ }
LayersChildren?.Add(layer);
layer.SetWindow(this);
internal Vector2 GetSize()
{
var val = new Uint16Pair(Interop.Window.GetSize(SwigCPtr), true);
+
+ convertRealWindowSizeToBorderWindowSize(val);
+
Vector2 ret = new Vector2(val.GetWidth(), val.GetHeight());
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
val.Dispose();
internal Layer GetRootLayer()
{
- // Window.IsInstalled() is actually true only when called from event thread and
- // Core has been initialized, not when Stage is ready.
- if (rootLayer == null && Window.IsInstalled())
+ if (isBorderWindow)
{
- rootLayer = new Layer(Interop.Window.GetRootLayer(SwigCPtr), true);
- if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
- LayersChildren?.Add(rootLayer);
- rootLayer.SetWindow(this);
+ if(borderLayer == null)
+ {
+ borderLayer = GetBorderWindowRootLayer();
+ LayersChildren?.Add(borderLayer);
+ borderLayer.SetWindow(this);
+ }
+ return borderLayer;
+ }
+ else
+ {
+ // Window.IsInstalled() is actually true only when called from event thread and
+ // Core has been initialized, not when Stage is ready.
+ if (rootLayer == null && Window.IsInstalled())
+ {
+ rootLayer = new Layer(Interop.Window.GetRootLayer(SwigCPtr), true);
+ if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+ LayersChildren?.Add(rootLayer);
+ rootLayer.SetWindow(this);
+ }
+ return rootLayer;
}
- return rootLayer;
}
internal void SetBackgroundColor(Vector4 color)
throw new ArgumentNullException(nameof(size));
}
var val = new Uint16Pair((uint)size.Width, (uint)size.Height);
+
+ convertBorderWindowSizeToRealWindowSize(val);
+
Interop.Window.SetSize(SwigCPtr, Uint16Pair.getCPtr(val));
val.Dispose();
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
internal Size2D GetWindowSize()
{
var val = new Uint16Pair(Interop.Window.GetSize(SwigCPtr), true);
+
+ convertRealWindowSizeToBorderWindowSize(val);
+
Size2D ret = new Size2D(val.GetWidth(), val.GetHeight());
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
val.Dispose();
internal void SetPositionSize(Rectangle positionSize)
{
+ if (positionSize == null)
+ {
+ throw new ArgumentNullException(nameof(positionSize));
+ }
+ var val = new Uint16Pair((uint)positionSize.Width, (uint)positionSize.Height);
+
+ convertBorderWindowSizeToRealWindowSize(val);
+
+ positionSize.Width = val.GetX();
+ positionSize.Height = val.GetY();
+
Interop.Window.SetPositionSize(SwigCPtr, Rectangle.getCPtr(positionSize));
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
//Release your own managed resources here.
//You should release all of your own disposable objects here.
+ if (IsBorderEnabled)
+ {
+ DisposeBorder();
+ }
+
if (rootLayer != null)
{
rootLayer.Dispose();
{
private WindowFocusChangedEventCallbackType windowFocusChangedEventCallback;
private RootLayerTouchDataCallbackType rootLayerTouchDataCallback;
+ private RootLayerTouchDataCallbackType rootLayerInterceptTouchDataCallback;
private WheelEventCallbackType wheelEventCallback;
private EventCallbackDelegateType1 stageKeyCallbackDelegate;
private EventCallbackDelegateType0 stageEventProcessingFinishedEventCallbackDelegate;
private VoidSignal contextLostSignal;
private VoidSignal contextRegainedSignal;
private AuxiliaryMessageEventCallbackType auxiliaryMessageEventCallback;
+ private TouchDataSignal interceptTouchDataSignal;
+ private TouchSignal interceptTouchSignal;
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void WindowFocusChangedEventCallbackType(IntPtr window, bool focusGained);
}
/// <summary>
+ /// An event for the touched signal which can be used to subscribe or unsubscribe the event handler provided by the user.<br />
+ /// The touched signal is emitted when the touch input is received.<br />
+ /// This can receive touch events before child. <br />
+ /// If it returns false, the child can receive the touch event. If it returns true, the touch event is intercepted. So child cannot receive touch event.<br />
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public event ReturnTypeEventHandler<object, TouchEventArgs, bool> InterceptTouchEvent
+ {
+ add
+ {
+ if (rootLayerInterceptTouchDataEventHandler == null)
+ {
+ rootLayerInterceptTouchDataCallback = OnWindowInterceptTouch;
+ interceptTouchDataSignal = this.InterceptTouchDataSignal();
+ interceptTouchDataSignal?.Connect(rootLayerInterceptTouchDataCallback);
+ }
+ rootLayerInterceptTouchDataEventHandler += value;
+ }
+ remove
+ {
+ rootLayerInterceptTouchDataEventHandler -= value;
+ interceptTouchSignal = TouchSignal();
+ if (rootLayerInterceptTouchDataEventHandler == null && interceptTouchSignal?.Empty() == false && rootLayerInterceptTouchDataCallback != null)
+ {
+ interceptTouchDataSignal?.Disconnect(rootLayerInterceptTouchDataCallback);
+ if (interceptTouchDataSignal?.Empty() == true)
+ {
+ rootLayerInterceptTouchDataCallback = null;
+ }
+ }
+ }
+ }
+
+ /// <summary>
/// Emits the event when the wheel event is received.
/// </summary>
/// <since_tizen> 3 </since_tizen>
public event EventHandler ViewAdded;
private event EventHandler<FocusChangedEventArgs> windowFocusChangedEventHandler;
private event EventHandler<TouchEventArgs> rootLayerTouchDataEventHandler;
+ private ReturnTypeEventHandler<object, TouchEventArgs, bool> rootLayerInterceptTouchDataEventHandler;
private event EventHandler<WheelEventArgs> stageWheelHandler;
private event EventHandler<KeyEventArgs> stageKeyHandler;
private event EventHandler stageEventProcessingFinishedEventHandler;
return ret;
}
+ internal TouchDataSignal InterceptTouchDataSignal()
+ {
+ TouchDataSignal ret = new TouchDataSignal(Interop.ActorSignal.ActorInterceptTouchSignal(Layer.getCPtr(GetRootLayer())), false);
+ if (NDalicPINVOKE.SWIGPendingException.Pending)
+ throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+ return ret;
+ }
+
+
internal VoidSignal ContextLostSignal()
{
VoidSignal ret = new VoidSignal(Interop.StageSignal.ContextLostSignal(stageCPtr), false);
rootLayerTouchDataCallback = null;
}
+ if (rootLayerInterceptTouchDataCallback != null)
+ {
+ interceptTouchDataSignal?.Disconnect(rootLayerInterceptTouchDataCallback);
+ rootLayerInterceptTouchDataCallback = null;
+ }
+
if (wheelEventCallback != null)
{
wheelSignal?.Disconnect(wheelEventCallback);
return false;
}
+ private bool OnWindowInterceptTouch(IntPtr view, IntPtr touchData)
+ {
+ if (touchData == global::System.IntPtr.Zero)
+ {
+ NUILog.Error("touchData should not be null!");
+ return true;
+ }
+
+ bool consumed = false;
+ if (rootLayerInterceptTouchDataEventHandler != null)
+ {
+ TouchEventArgs e = new TouchEventArgs();
+ e.Touch = Tizen.NUI.Touch.GetTouchFromPtr(touchData);
+ consumed = rootLayerInterceptTouchDataEventHandler(this, e);
+ }
+ return consumed;
+ }
+
private bool OnStageWheel(IntPtr rootLayer, IntPtr wheelEvent)
{
if (wheelEvent == global::System.IntPtr.Zero)
--- /dev/null
+
+using System;
+using Tizen.NUI;
+using Tizen.NUI.BaseComponents;
+using Tizen.NUI.Components;
+using System.Collections.Generic;
+
+
+namespace Tizen.NUI.Samples
+{
+ public class BorderWindowTest : IExample
+ {
+ private Window win;
+ private Window subWindowOne = null;
+ private Window subWindowTwo = null;
+ private static readonly string imagePath = Tizen.Applications.Application.Current.DirectoryInfo.Resource + "/images/Dali/CubeTransitionEffect/";
+
+
+ class CustomBorder : DefaultBorder
+ {
+ private int width = 500;
+ private bool hide = false;
+ private View rootView;
+ private View borderView;
+ private TextLabel title;
+
+ public CustomBorder() : base()
+ {
+ }
+
+
+ public override void CreateBorderView(View rootView)
+ {
+ this.rootView = rootView;
+ // rootView.BackgroundColor = new Color(1, 1, 1, 0.3f);
+ rootView.CornerRadius = new Vector4(0.03f, 0.03f, 0.03f, 0.03f);
+ rootView.CornerRadiusPolicy = VisualTransformPolicyType.Relative;
+
+ borderView = new View()
+ {
+ Layout = new LinearLayout()
+ {
+ LinearAlignment = LinearLayout.Alignment.End,
+ LinearOrientation = LinearLayout.Orientation.Horizontal,
+ },
+ WidthSpecification = LayoutParamPolicies.MatchParent,
+ HeightSpecification = LayoutParamPolicies.MatchParent,
+ };
+ title = new TextLabel()
+ {
+ Text = "CustomBorder",
+ Size = new Size(300, 50),
+ Position = new Position(60, 0),
+ PositionUsesPivotPoint = true,
+ PivotPoint = PivotPoint.BottomLeft,
+ ParentOrigin = ParentOrigin.BottomLeft,
+ };
+
+ var minimalizeIcon = new Button()
+ {
+ Text = "m",
+ PositionUsesPivotPoint = true,
+ PivotPoint = PivotPoint.BottomLeft,
+ ParentOrigin = ParentOrigin.BottomLeft,
+ Size = new Size(50, 50),
+ };
+
+ var maximalizeIcon = new Button()
+ {
+ Text = "M",
+ PositionUsesPivotPoint = true,
+ PivotPoint = PivotPoint.BottomLeft,
+ ParentOrigin = ParentOrigin.BottomLeft,
+ Size = new Size(50, 50),
+ };
+
+ var closeIcon = new Button()
+ {
+ Text = "C",
+ PositionUsesPivotPoint = true,
+ PivotPoint = PivotPoint.BottomLeft,
+ ParentOrigin = ParentOrigin.BottomLeft,
+ Size = new Size(50, 50),
+ };
+
+
+ var leftPadding = new View()
+ {
+ PositionUsesPivotPoint = true,
+ PivotPoint = PivotPoint.BottomLeft,
+ ParentOrigin = ParentOrigin.BottomLeft,
+ Size = new Size(50, 50),
+ };
+
+ var rightPadding = new View()
+ {
+ PositionUsesPivotPoint = true,
+ PivotPoint = PivotPoint.BottomLeft,
+ ParentOrigin = ParentOrigin.BottomLeft,
+ Size = new Size(50, 50),
+ };
+
+ rootView.Add(leftPadding);
+ rootView.Add(title);
+ borderView.Add(minimalizeIcon);
+ borderView.Add(maximalizeIcon);
+ borderView.Add(closeIcon);
+ borderView.Add(rightPadding);
+ rootView.Add(borderView);
+
+ minimalizeIcon.TouchEvent += OnMinimizeIconTouched;
+ maximalizeIcon.TouchEvent += OnMaximizeIconTouched;
+ closeIcon.TouchEvent += OnCloseIconTouched;
+ leftPadding.TouchEvent += OnLeftCornerIconTouched;
+ rightPadding.TouchEvent += OnRightCornerIconTouched;
+ }
+
+ public override void OnCreated(View rootView)
+ {
+ base.OnCreated(rootView);
+ }
+
+ public override bool OnCloseIconTouched(object sender, View.TouchEventArgs e)
+ {
+ base.OnCloseIconTouched(sender, e);
+ return true;
+ }
+
+ public override bool OnMinimizeIconTouched(object sender, View.TouchEventArgs e)
+ {
+ base.OnMinimizeIconTouched(sender, e);
+ return true;
+ }
+
+ public override void OnResized(int width, int height)
+ {
+ if (rootView != null)
+ {
+ if (this.width > width && hide == false)
+ {
+ title.Hide();
+ hide = true;
+ }
+ else if (this.width < width && hide == true)
+ {
+ title.Show();
+ hide = false;
+ }
+ base.OnResized(width, height);
+ }
+ }
+
+ public override uint GetBorderLineThickness()
+ {
+ return base.GetBorderLineThickness();
+ }
+
+ public override uint GetTouchThickness()
+ {
+ return base.GetTouchThickness();
+ }
+
+ public override uint GetBorderHeight()
+ {
+ return base.GetBorderHeight();
+ }
+
+ public override Size2D GetMinSize()
+ {
+ return base.GetMinSize();
+ }
+
+ public override Size2D GetMaxSize()
+ {
+ return base.GetMaxSize();
+ }
+
+ public override void SetWindow(Window window)
+ {
+ base.SetWindow(window);
+ }
+
+ public override Window GetWindow()
+ {
+ return base.GetWindow();
+ }
+
+ public override void Dispose()
+ {
+ base.Dispose();
+ }
+
+ public override bool IsOverlayMode()
+ {
+ return true;
+ }
+
+
+ }
+
+ void CreateSubWindowOne()
+ {
+ if (subWindowOne == null)
+ {
+ subWindowOne = new Window("subwin1", null, new Rectangle(20, 20, 800, 800), false);
+
+ var root = new ImageView()
+ {
+ WidthResizePolicy = ResizePolicyType.FillToParent,
+ HeightResizePolicy = ResizePolicyType.FillToParent,
+ ResourceUrl = imagePath + "gallery-large-9.jpg",
+ CornerRadius = new Vector4(0.03f, 0.03f, 0.03f, 0.03f),
+ CornerRadiusPolicy = VisualTransformPolicyType.Relative,
+ };
+ subWindowOne.Add(root);
+
+ TextLabel text = new TextLabel("Hello Tizen NUI World");
+ text.HorizontalAlignment = HorizontalAlignment.Center;
+ text.VerticalAlignment = VerticalAlignment.Center;
+ text.TextColor = Color.CornflowerBlue;
+ text.HeightResizePolicy = ResizePolicyType.FillToParent;
+ text.WidthResizePolicy = ResizePolicyType.FillToParent;
+ root.Add(text);
+
+ Animation animation = new Animation(2000);
+ animation.AnimateTo(text, "Orientation", new Rotation(new Radian(new Degree(180.0f)), PositionAxis.X), 0, 500);
+ animation.AnimateTo(text, "Orientation", new Rotation(new Radian(new Degree(0.0f)), PositionAxis.X), 500, 1000);
+ animation.Looping = true;
+ animation.Play();
+ }
+ else
+ {
+ subWindowOne.Minimize(false);
+ }
+ }
+
+ void CreateSubWindowTwo()
+ {
+ if (subWindowTwo == null)
+ {
+ IBorderInterface customBorder = new CustomBorder();
+ subWindowTwo = new Window("subwin1", customBorder, new Rectangle(60, 20, 800, 800), false);
+
+ subWindowTwo.BackgroundColor = Color.Red;
+
+ var root = new View(){
+ Layout = new LinearLayout()
+ {
+ LinearAlignment = LinearLayout.Alignment.CenterHorizontal,
+ },
+ WidthResizePolicy = ResizePolicyType.FillToParent,
+ HeightResizePolicy = ResizePolicyType.FillToParent,
+ BackgroundColor = Color.Yellow,
+ };
+
+ var image = new ImageView()
+ {
+ Size = new Size(300, 300),
+ ResourceUrl = imagePath + "gallery-large-5.jpg",
+ CornerRadius = new Vector4(0.03f, 0.03f, 0, 0),
+ CornerRadiusPolicy = VisualTransformPolicyType.Relative,
+ };
+ root.Add(image);
+ subWindowTwo.Add(root);
+ }
+ else
+ {
+ subWindowTwo.Minimize(false);
+ }
+ }
+
+
+
+ void Initialize()
+ {
+ win = NUIApplication.GetDefaultWindow();
+
+ List<Window.WindowOrientation> list = new List<Window.WindowOrientation>();
+ list.Add(Window.WindowOrientation.Landscape);
+ list.Add(Window.WindowOrientation.LandscapeInverse);
+ list.Add(Window.WindowOrientation.NoOrientationPreference);
+ list.Add(Window.WindowOrientation.Portrait);
+ list.Add(Window.WindowOrientation.PortraitInverse);
+ win.SetAvailableOrientations(list);
+
+ var root = new ImageView()
+ {
+ WidthResizePolicy = ResizePolicyType.FillToParent,
+ HeightResizePolicy = ResizePolicyType.FillToParent,
+ ResourceUrl = imagePath + "gallery-large-14.jpg",
+ Layout = new LinearLayout()
+ {
+ LinearAlignment = LinearLayout.Alignment.CenterHorizontal,
+ LinearOrientation = LinearLayout.Orientation.Horizontal,
+ CellPadding = new Size(10, 10),
+ }
+
+
+ };
+ win.Add(root);
+
+ var imageViewA = new ImageView()
+ {
+ PositionUsesPivotPoint = true,
+ PivotPoint = PivotPoint.BottomLeft,
+ ParentOrigin = ParentOrigin.BottomLeft,
+ Size = new Size(150, 150),
+ ResourceUrl = imagePath + "gallery-large-9.jpg",
+ CornerRadius = 0.3f,
+ CornerRadiusPolicy = VisualTransformPolicyType.Relative,
+ };
+ root.Add(imageViewA);
+ imageViewA.TouchEvent += (s, e) =>
+ {
+ if (e.Touch.GetState(0) == PointStateType.Up)
+ {
+ CreateSubWindowOne();
+ }
+ return true;
+ };
+
+ var imageViewB = new ImageView()
+ {
+ PositionUsesPivotPoint = true,
+ PivotPoint = PivotPoint.BottomLeft,
+ ParentOrigin = ParentOrigin.BottomLeft,
+ Size = new Size(150, 150),
+ ResourceUrl = imagePath + "gallery-large-5.jpg",
+ CornerRadius = 0.3f,
+ CornerRadiusPolicy = VisualTransformPolicyType.Relative,
+ };
+ root.Add(imageViewB);
+ imageViewB.TouchEvent += (s, e) =>
+ {
+ if (e.Touch.GetState(0) == PointStateType.Up)
+ {
+ CreateSubWindowTwo();
+ }
+ return true;
+ };
+ }
+
+ public void Activate()
+ {
+ Initialize();
+ }
+
+ public void Deactivate()
+ {
+ }
+
+
+ }
+}