--- /dev/null
+using Dali;
+using System;
+using System.Runtime.InteropServices;
+using System.Collections.Generic;
+
+namespace FirstScreen
+{
+ public class FirstScreenApp
+ {
+ private int _currentPostersContainerID;
+ private int _totalPostersContainers;
+
+ private Application _application;
+ private Stage _stage;
+ private Vector2 _stageSize;
+
+ private List<ScrollContainer> _postersContainer;
+
+ private ScrollContainer _menuContainer;
+ private Vector3 _menuItemSize;
+
+ private Layer _bottomClipLayer;
+ private Layer _topClipLayer;
+ private View _topContainer;
+ private View _bottomContainer;
+
+ private EdenEffect _edenEffect;
+ private string _imagePath;
+
+ private ImageView _keyboardFocusIndicator;
+ private ImageView _launcherSeparator;
+ private ImageView[] launcherIcon;
+ private Animation _showBottomContainerAnimation;
+ private Animation _hideBottomContainerAnimation;
+
+ public FirstScreenApp(Application application)
+ {
+ _application = application;
+ _application.Initialized += OnInitialize;
+ }
+
+ public static void Run()
+ {
+ FirstScreenApp tVApp = new FirstScreenApp(Application.NewApplication());
+ tVApp.MainLoop();
+ }
+
+ public void MainLoop()
+ {
+ _application.MainLoop();
+ }
+
+ // Create Items for Poster ScrollContainer
+ private void CreatePosters()
+ {
+ for (int j = 0; j < _totalPostersContainers; j++)
+ {
+ View posterContainer = _postersContainer[j].Container;
+ for (int i = 0; i < Constants.PostersItemsCount; i++)
+ {
+ if (j % _totalPostersContainers == 0)
+ {
+ View item = new ImageView(_imagePath + "/poster"+j+"/"+ (i % 6)+ ".jpg");
+ item.SetName ("poster-item-" + _postersContainer[j].ItemCount);
+ _postersContainer[j].AddItem(item);
+ }
+ else
+ {
+ View item = new ImageView(_imagePath + "/poster"+j+"/"+ (i % 6)+ ".jpg");
+ item.SetName ("poster-item-" + _postersContainer[j].ItemCount);
+ _postersContainer[j].AddItem(item);
+ }
+ }
+
+ if (j == 0)
+ {
+ _postersContainer[j].Show();
+ }
+ else
+ {
+ _postersContainer[j].Hide();
+ }
+
+ _postersContainer[j].SetFocused(false);
+ }
+
+ _currentPostersContainerID = 0;
+ }
+
+ // Create Items for Menu ScrollContainer
+ private void CreateMenu()
+ {
+ View menuContainer = _menuContainer.Container;
+ menuContainer.Position = new Vector3(Constants.LauncherWidth, 0.0f, 0.0f);
+
+ for(int i = 0; i < Constants.MenuItemsCount; i++)
+ {
+ View menuItem = new ImageView(_imagePath + "/menu/" + i % 7 + ".png");
+ menuItem.SetName("menu-item-" + _menuContainer.ItemCount);
+ _menuContainer.AddItem(menuItem);
+ }
+ }
+
+ private Actor OnKeyboardPreFocusChangeSignal(object source, KeyboardFocusManager.PreFocusChangeEventArgs e)
+ {
+ Actor actor = _menuContainer.ItemRoot;
+
+ if (e.Direction == View.KeyboardFocus.Direction.UP)
+ {
+ // Move the Focus to Poster ScrollContainer and hide Bottom Container (Menu ScrollContainer)
+ if (_menuContainer.IsFocused)
+ {
+ actor = _postersContainer[_currentPostersContainerID].GetCurrentFocusedActor();
+ _menuContainer.SetFocused(false);
+ _postersContainer[_currentPostersContainerID].SetFocused(true);
+ HideBottomContainer();
+
+ // Also apply Focus animation on Focused item on Poster ScrollContainer
+ _postersContainer[_currentPostersContainerID].FocusAnimation(_edenEffect, EdenEffectDirection.BottomToTop);
+ }
+ }
+ else if (e.Direction == View.KeyboardFocus.Direction.DOWN)
+ {
+ // Show Bottom Container (Menu ScrollContainer) and move the Focus to it
+ if (!_menuContainer.IsFocused)
+ {
+ ShowBottomContainer();
+ actor = _menuContainer.GetCurrentFocusedActor();
+ _postersContainer[_currentPostersContainerID].SetFocused(false);
+ _menuContainer.SetFocused(true);
+
+ // Also apply Focus animation on Focused item on Menu ScrollContainer
+ _menuContainer.FocusAnimation(_edenEffect, EdenEffectDirection.TopToBottom);
+ }
+ }
+ else if (e.Direction == View.KeyboardFocus.Direction.LEFT)
+ {
+ if (_menuContainer.IsFocused)
+ {
+ // Move the Focus to the left item/image of currently focused item on Menu ScrollContainer
+ actor = _menuContainer.FocusPrevious();
+
+ int id = _menuContainer.FocusedItemID % _totalPostersContainers;
+ if (id != _currentPostersContainerID)
+ {
+ _postersContainer[_currentPostersContainerID].Hide();
+ _currentPostersContainerID = id;
+
+ _postersContainer[_currentPostersContainerID].Show();
+ }
+ }
+ else
+ {
+ // Move the Focus to the left item/image of currently focused item on Poster ScrollContainer
+ actor = _postersContainer[_currentPostersContainerID].FocusPrevious();
+ }
+ }
+ else if (e.Direction == View.KeyboardFocus.Direction.RIGHT)
+ {
+ if (_menuContainer.IsFocused)
+ {
+ // Move the Focus to the right item/image of currently focused item on Menu ScrollContainer
+ actor = _menuContainer.FocusNext();
+
+ int id = _menuContainer.FocusedItemID % _totalPostersContainers;
+ if (id != _currentPostersContainerID)
+ {
+ _postersContainer[_currentPostersContainerID].Hide();
+ _currentPostersContainerID = id;
+ _postersContainer[_currentPostersContainerID].Show();
+ }
+ }
+ else
+ {
+ // Move the Focus to the right item/image of currently focused item on Poster ScrollContainer
+ actor = _postersContainer[_currentPostersContainerID].FocusNext();
+ }
+ }
+
+ return actor;
+ }
+
+ // Hide Bottom Container (Menu ScrollContainer) when it is not focused
+ private void HideBottomContainer()
+ {
+ _topClipLayer.ClippingBox = new RectInteger(0,
+ Convert.ToInt32(_stageSize.height * Constants.TopContainerPositionFactor),
+ Convert.ToInt32((_stageSize.width)),
+ Convert.ToInt32((_stageSize.height * Constants.TopClipLayerExpandHeightFactor))); // X, Y, Width, Height
+
+ _hideBottomContainerAnimation.AnimateTo(new Property(_bottomContainer, Actor.Property.POSITION),
+ new Property.Value(new Vector3(0.0f, _stageSize.height * Constants.BottomContainerHidePositionFactor, 0.0f)),
+ new AlphaFunction(AlphaFunction.BuiltinFunction.EASE_OUT_SINE));
+ _hideBottomContainerAnimation.Play();
+ }
+
+ // Show (unhide) Bottom Container (Menu ScrollContainer) when it is focused
+ private void ShowBottomContainer()
+ {
+ _topClipLayer.ClippingBox = new RectInteger(0,
+ Convert.ToInt32(_stageSize.height * Constants.TopContainerPositionFactor),
+ Convert.ToInt32((_stageSize.width)),
+ Convert.ToInt32((_stageSize.height * Constants.TopClipLayerHeightFactor))); // X, Y, Width, Height
+
+ _showBottomContainerAnimation.AnimateTo(new Property(_bottomContainer, Actor.Property.POSITION),
+ new Property.Value(new Vector3(0.0f, _stageSize.height * Constants.BottomContainerShowPositionFactor, 0.0f)),
+ new AlphaFunction(AlphaFunction.BuiltinFunction.EASE_OUT_SINE));
+ _showBottomContainerAnimation.Play();
+ }
+
+ // First screen demo Application initialisation
+ private void OnInitialize(object source, AUIApplicationInitEventArgs e)
+ {
+ _stage = Stage.GetCurrent();
+ _stageSize = _stage.GetSize();
+// _stage.SetBackgroundColor(NDalic.TRANSPARENT);
+
+ _totalPostersContainers = Constants.TotalPostersContainers;
+ _imagePath = "./images/"; // Desktop
+// _imagePath = "/home/owner/apps_rw/org.tizen.firstscreen/res/images/"; // Target
+
+ _postersContainer = new List<ScrollContainer> ();
+ _menuContainer = new ScrollContainer ();
+
+ _hideBottomContainerAnimation = new Animation(0.25f);
+ _showBottomContainerAnimation = new Animation(0.25f);
+
+ // Create a Top Container for poster items
+ _topContainer = new View();
+ _topContainer.Size = new Vector3(_stageSize.width, _stageSize.height * Constants.TopContainerHeightFactor, 0.0f);
+ _topContainer.Position = new Vector3(0.0f, _stageSize.y * Constants.TopContainerPositionFactor, 0.0f);
+ _topContainer.ParentOrigin = NDalic.ParentOriginTopLeft;
+ _topContainer.AnchorPoint = NDalic.AnchorPointTopLeft;
+
+ // Add a background to Top container
+ Property.Map visual = new Property.Map();
+ visual.Insert(NDalic.VISUAL_PROPERTY_TYPE, new Property.Value((int)VisualType.IMAGE));
+ visual.Insert(NDalic.IMAGE_VISUAL_URL, new Property.Value(_imagePath + "/background.png"));
+ _topContainer.Background = visual;
+ _topContainer.Name = "TopControl";
+
+ // Create a Bottom Container
+ _bottomContainer = new View();
+ _bottomContainer.Size = new Vector3(_stageSize.width, _stageSize.height * Constants.BottomContainerHeightFactor, 0.0f);
+ _bottomContainer.Position = new Vector3(0.0f, _stageSize.height * Constants.BottomContainerHidePositionFactor, 0.0f);
+ _bottomContainer.ParentOrigin = NDalic.ParentOriginTopLeft;
+ _bottomContainer.AnchorPoint = NDalic.AnchorPointTopLeft;
+
+ // Add a background to Bottom Container
+ visual = new Property.Map();
+ visual.Insert(NDalic.VISUAL_PROPERTY_TYPE, new Property.Value((int)VisualType.IMAGE));
+ visual.Insert(NDalic.IMAGE_VISUAL_URL, new Property.Value(_imagePath + "/background.png"));
+ _bottomContainer.Background = visual;
+ _bottomContainer.Name = "BottomControl";
+
+ // Add both Top and Bottom Containers to Stage
+ _stage.Add(_topContainer);
+ _stage.Add(_bottomContainer);
+
+ // Add a clip layer to Top Container
+ _topClipLayer = new Layer();
+ _topClipLayer.AnchorPoint = NDalic.AnchorPointBottomCenter;
+ _topClipLayer.ParentOrigin = NDalic.ParentOriginBottomCenter;
+ _topClipLayer.ClippingEnable = true;
+ _topClipLayer.ClippingBox = new RectInteger(0,
+ Convert.ToInt32(_stageSize.height * Constants.TopContainerPositionFactor),
+ Convert.ToInt32((_stageSize.width)),
+ Convert.ToInt32((_stageSize.height * Constants.TopClipLayerHeightFactor))); // X, Y, Width, Height
+ _topContainer.Add(_topClipLayer);
+
+ // Create a SpotLight for items / images of both Poster and Menu ScrollContainers
+ ImageView spotLight = new ImageView(_imagePath + "/highlight_spot.png");
+ spotLight.WidthResizePolicy = "USE_NATURAL_SIZE";
+ spotLight.HeightResizePolicy = "USE_NATURAL_SIZE";
+ spotLight.ParentOrigin = NDalic.ParentOriginCenter;
+ spotLight.AnchorPoint = NDalic.AnchorPointCenter;
+ spotLight.Name = "spotLight";
+
+ // Create a shadowBorder for items / images of Poster ScrollContainers
+ ImageView shadowBorder = new ImageView(_imagePath + "/thumbnail_shadow.9.png");
+ shadowBorder.ParentOrigin = NDalic.ParentOriginCenter;
+ shadowBorder.AnchorPoint = NDalic.AnchorPointCenter;
+ shadowBorder.WidthResizePolicy = "SIZE_FIXED_OFFSET_FROM_PARENT";
+ shadowBorder.HeightResizePolicy = "SIZE_FIXED_OFFSET_FROM_PARENT";
+ shadowBorder.SetSizeModeFactor(new Vector3(32.0f, 41.0f, 0.0f));
+ shadowBorder.Name = "poster shadowBorder";
+
+ // Create Poster Containers and add them to Top Clip layer
+ for (int i = 0; i < _totalPostersContainers; i++)
+ {
+ _postersContainer.Add(new ScrollContainer());
+ _postersContainer[i].Container.Name = "poster" + i;
+ if (i == 0)
+ {
+ _postersContainer[i].ItemSize = new Vector3((_stageSize.width * Constants.Poster0ItemWidthFactor) - Constants.PostersContainerPadding,
+ _stageSize.height * Constants.PostersItemHeightFactor, 0.0f);
+ }
+ else
+ {
+ _postersContainer[i].ItemSize = new Vector3(_stageSize.width * Constants.Poster1ItemWidthFactor,
+ _stageSize.height * Constants.PostersItemHeightFactor, 0.0f);
+ }
+ _postersContainer[i].Padding = Constants.PostersContainerPadding;
+ _postersContainer[i].MarginX = Constants.PostersContainerMargin;
+ _postersContainer[i].OffsetY = Constants.PostersContainerOffsetYFactor;
+ _postersContainer[i].Width = _stageSize.width;
+ _postersContainer[i].Height = _stageSize.height * Constants.PostersContainerHeightFactor;
+ _postersContainer[i].ShadowBorder = shadowBorder;
+ _postersContainer[i].ShadowBorder.Position = new Vector3(0.0f, 4.0f, 0.0f);
+ _postersContainer[i].SpotLight = spotLight;
+ _topClipLayer.Add(_postersContainer[i].Container);
+ }
+
+ // Add a clip layer to Bottom Container
+ _bottomClipLayer = new Layer();
+ _bottomClipLayer.AnchorPoint = NDalic.AnchorPointBottomCenter;
+ _bottomClipLayer.ParentOrigin = NDalic.ParentOriginBottomCenter;
+ _bottomClipLayer.ClippingEnable = true;
+ _bottomClipLayer.ClippingBox = new RectInteger(Convert.ToInt32(Constants.LauncherWidth),
+ Convert.ToInt32(_stageSize.height * Constants.BottomContainerShowPositionFactor),
+ Convert.ToInt32((_stageSize.width)),
+ Convert.ToInt32((_stageSize.height - (_stageSize.height * Constants.BottomClipLayerHeightFactor)))); // X, Y, Width, Height
+ _bottomContainer.Add(_bottomClipLayer);
+
+ // Add Launcher items to Bottom Container. Launcher is used to display three images on left of Menu ScrollContainer
+ launcherIcon = new ImageView[Convert.ToInt32(Constants.LauncherItemsCount)];
+ for (int launcherIndex = 0; launcherIndex < Constants.LauncherItemsCount; launcherIndex++)
+ {
+ launcherIcon[launcherIndex] = new ImageView(_imagePath + "/" + launcherIndex + "-normal.png");
+ launcherIcon[launcherIndex].Name = "launcherIcon" + launcherIndex;
+ launcherIcon[launcherIndex].WidthResizePolicy = "USE_NATURAL_SIZE";
+ launcherIcon[launcherIndex].HeightResizePolicy = "USE_NATURAL_SIZE";
+ launcherIcon[launcherIndex].ParentOrigin = NDalic.ParentOriginCenterLeft;
+ launcherIcon[launcherIndex].AnchorPoint = NDalic.AnchorPointCenterLeft;
+ launcherIcon[launcherIndex].Position = new Vector3(Constants.LauncherIconWidth * launcherIndex + Constants.LauncherLeftMargin, 0.0f, 0.0f);
+ _bottomContainer.Add(launcherIcon[launcherIndex]);
+ }
+
+ // Add a shadow seperator image between last Launcher icon and Menu ScrollContainer
+ _launcherSeparator = new ImageView(_imagePath + "/eden_launcher_shadow_n.png");
+ _launcherSeparator.Name = "launcherSeparator";
+ _launcherSeparator.WidthResizePolicy = "USE_NATURAL_SIZE";
+ _launcherSeparator.HeightResizePolicy = "FILL_TO_PARENT";
+ _launcherSeparator.ParentOrigin = NDalic.ParentOriginCenterLeft;
+ _launcherSeparator.AnchorPoint = NDalic.AnchorPointCenterLeft;
+ _launcherSeparator.Position = new Vector3(Constants.LauncherIconWidth * Constants.LauncherItemsCount + Constants.LauncherLeftMargin, 0.0f, 0.0f);
+ _bottomContainer.Add(_launcherSeparator);
+
+ // Create Menu Container and add it to Bottom Clip Layer
+ _menuItemSize = new Vector3((_stageSize.width * Constants.MenuItemWidthFactor) - Constants.MenuContainerPadding,
+ _stageSize.height * Constants.MenuItemHeightFactor, 0.0f);
+ _menuContainer.Container.Name = "menu";
+ _menuContainer.ItemSize = _menuItemSize;
+ _menuContainer.Padding = Constants.MenuContainerPadding;
+ _menuContainer.MarginX = Constants.MenuContainerMargin;
+ _menuContainer.OffsetY = Constants.MenuContainerOffsetYFactor;
+ _menuContainer.OffsetX = Constants.LauncherWidth;
+ _menuContainer.Width = _stageSize.width - Constants.LauncherWidth;
+ _menuContainer.Height = _stageSize.height * Constants.MenuContainerHeightFactor;
+ _menuContainer.ShadowBorder = new ImageView(_imagePath + "/eden_launcher_shadow.9.png");
+ _menuContainer.ShadowBorder.Name = "_menuContainer.ShadowBorder";
+ _menuContainer.ShadowBorder.Size = new Vector3(_menuContainer.ItemSize.width + 40.0f, _menuContainer.ItemSize.height + 50.0f, 0.0f);
+ _menuContainer.ShadowBorder.Position = new Vector3(0.0f, 5.0f, 0.0f);
+ _menuContainer.ShadowBorder.ParentOrigin = NDalic.ParentOriginCenter;
+ _menuContainer.ShadowBorder.AnchorPoint = NDalic.AnchorPointCenter;
+ _menuContainer.SpotLight = spotLight;
+ _bottomClipLayer.Add(_menuContainer.Container);
+
+ CreatePosters(); // Create Items for Poster ScrollContainer
+ CreateMenu(); // Create Items for Menu ScrollContainer
+
+ // Initialize PreFocusChange event of KeyboardFocusManager
+ KeyboardFocusManager keyboardFocusManager = KeyboardFocusManager.Get();
+ keyboardFocusManager.PreFocusChange += OnKeyboardPreFocusChangeSignal;
+
+ _keyboardFocusIndicator = new ImageView(_imagePath + "/highlight_stroke.9.png");
+ _keyboardFocusIndicator.ParentOrigin = NDalic.ParentOriginCenter;
+ _keyboardFocusIndicator.AnchorPoint = NDalic.AnchorPointCenter;
+ _keyboardFocusIndicator.WidthResizePolicy = "FILL_TO_PARENT";
+ _keyboardFocusIndicator.HeightResizePolicy = "FILL_TO_PARENT";
+
+ keyboardFocusManager.SetFocusIndicatorActor(_keyboardFocusIndicator);
+
+ _edenEffect = new EdenEffect();
+
+ // Move Fcous to Bottom Container (Menu ScrollContainer)
+ ShowBottomContainer();
+ _menuContainer.SetFocused(true);
+ }
+ }
+}
+
--- /dev/null
+using System;
+
+namespace FirstScreen
+{
+ public class Constants
+ {
+ public const int TotalPostersContainers = 2; // Number of Poster ScrollContainers to be added on Top Container
+
+ public const float TopContainerHeightFactor = 0.38f; // Height Factor of stage height used for Top Container total height
+ public const float TopContainerPositionFactor = 0.50f; // Position Factor of stage height used for Top Container position
+ public const float TopClipLayerHeightFactor = 0.34f; // Height Factor of stage height used for Top Clip layer height
+ public const float TopClipLayerExpandHeightFactor = 0.36f; // Expanded Height Factor of stage height used for Top Clip layer height (used when Bottom container is hidden)
+ public const float PostersContainerHeightFactor = 0.32f; // Height Factor of stage height used for Poster ScrollContainers
+ public const float PostersContainerPadding = 2.0f; // Padding size used between items / images in Poster ScrollContainer
+ public const float PostersContainerMargin = 60.0f; // Extra margin Padding size used between items / images in Poster ScrollContainer when item / image is focused
+ public const float PostersContainerOffsetYFactor = 0.17f; // Position Factor of Poster item height used for Poster items / images position
+
+ public const float BottomContainerHeightFactor = 0.16f; // Height Factor of stage height used for Bottom Container total height
+ public const float BottomContainerHidePositionFactor = 0.88f; // Position Factor of stage height used for Bottom Container position when bottom container is hidden (not focused)
+ public const float BottomContainerShowPositionFactor = 0.84f; // Position Factor of stage height used for Bottom Container position when bottom container is not hidden (focused)
+ public const float MenuContainerHeightFactor = 0.16f; // Height Factor of stage height used for Bottom ScrollContainers
+ public const float BottomClipLayerHeightFactor = 0.84f; // Height Factor of stage height used for Bottom Clip layer height
+ public const float MenuContainerPadding = 10.0f; // Padding size used between items / images in Menu ScrollContainer
+ public const float MenuContainerMargin = 25.0f; // Extra margin Padding size used between items / images in Menu ScrollContainer when item / image is focused
+ public const float MenuContainerOffsetYFactor = 0.35f; // Position Factor of Poster item height used for Menu items / images position
+
+ public const float MenuItemWidthFactor = 0.125f; // Width Factor (1/8) of stage Width used for Menu items / images Width
+ public const float MenuItemHeightFactor = 0.10f; // Height Factor of stage height used for Menu items / images Height
+ public const float MenuItemsCount = 14; // Number of Menu items / images used in a Menu ScrollContainer
+
+ public const float Poster0ItemWidthFactor = 0.25f; // Width Factor (1/4) of stage Width used for Poster items / images Width in a Poster ScrollContainer 0
+ public const float Poster1ItemWidthFactor = 0.24f; // Width Factor of stage Width used for Poster items / images Width in a Poster ScrollContainer 1
+ public const float PostersItemHeightFactor = 0.24f; // Height Factor of stage height used for Poster items / images Height
+ public const float PostersItemsCount = 24; // Number of Menu items / images used in a Poster ScrollContainer
+
+ public const float LauncherWidth = 280.0f; // Width of Launcher. Launcher is used to display three images on left of Menu ScrollContainer
+ public const float LauncherLeftMargin = 40.0f; // Extra Spaces to the left of first Launcher item / image
+ public const float LauncherSeparatorWidth = 20.0f; // Extra area / space to the left of Menu ScrollContainer used for a speration shadow image
+ public const float LauncherItemsCount = 3.0f; // Total number of Launcher items / images
+ public const float LauncherIconWidth = (LauncherWidth - LauncherLeftMargin - LauncherSeparatorWidth) / LauncherItemsCount; // Width of each Launcher item / image
+ }
+}
+
--- /dev/null
+using Dali;
+using System;
+
+namespace FirstScreen
+{
+ public class EdenData
+ {
+ private string _name; // Name used for EdenData object (mainly to differentiate key frame animation )
+ private string _imageName; // Image File Name (to be loaded from disk) used for ImageView used in key frame animation
+ private Vector3 _parentOrigin; // ParentOrigin applied to ImageView
+ private Vector3 _initSize; // InitSize used for key frame animation
+ private Vector3 _targetSize; // TargetSize used for key frame animation
+ private float _keyFrameStart; // KeyFrameStart used for key frame animation
+ private float _keyFrameEnd; // KeyFrameEnd used for key frame animation
+ private Direction _direction; // Direction used for key frame animation
+ private ImageView _imageFocus; // ImageView used in key frame animation
+
+ // Initialize EdenData used for key frame animation
+ public EdenData(string name, string imageName, Direction direction, Vector3 parentOrigin, Vector3 initSize,
+ Vector3 targetSize, float keyFrameStart, float keyFrameEnd)
+ {
+ _name = name;
+ _imageName = imageName;
+ _parentOrigin = parentOrigin;
+ _initSize = initSize;
+ _targetSize = targetSize;
+ _keyFrameStart = keyFrameStart;
+ _keyFrameEnd = keyFrameEnd;
+ _direction = direction;
+
+ _imageFocus = new ImageView("./images/edeneffect/" + _imageName); // Desktop
+// _imageFocus = new ImageView("/home/owner/apps_rw/org.tizen.firstscreen/res/images/edeneffect/" + _imageName); // Target
+
+ _imageFocus.ParentOrigin = _parentOrigin;
+ _imageFocus.AnchorPoint = NDalic.AnchorPointCenter;
+ _imageFocus.Name = _name;
+ }
+
+ public enum Direction
+ {
+ Horizontal,
+ Vertical
+ };
+
+ public Direction EdenDirection
+ {
+ get {return _direction;}
+ set {_direction = value;}
+ }
+
+ public string Name
+ {
+ get {return _name;}
+ set {_name = value;}
+ }
+
+ public string ImageName
+ {
+ get {return _imageName;}
+ set {_imageName = value;}
+ }
+
+ public Vector3 ParentOrigin
+ {
+ get
+ {
+ return _parentOrigin;
+ }
+ set
+ {
+ _parentOrigin = value;
+ _imageFocus.ParentOrigin = _parentOrigin;
+ }
+ }
+
+ public Vector3 InitSize
+ {
+ get {return _initSize;}
+ set {_initSize = value;}
+ }
+
+ public Vector3 TargetSize
+ {
+ get {return _targetSize;}
+ set {_targetSize = value;}
+ }
+
+ public float KeyFrameStart
+ {
+ get {return _keyFrameStart;}
+ set {_keyFrameStart = value;}
+ }
+
+ public float KeyFrameEnd
+ {
+ get {return _keyFrameEnd;}
+ set {_keyFrameEnd = value;}
+ }
+
+ public ImageView ImageItem
+ {
+ get {return _imageFocus;}
+ }
+ }
+}
+
--- /dev/null
+using Dali;
+using System;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+
+namespace FirstScreen
+{
+ public class EdenEffect : IEdenEffect
+ {
+ private float _frameThickness;
+ private EdenData[] _edenFocusData; // Each EdenData is used for one key frame animation (total 6 key frame animations needed for EddenEffect)
+ private Animation _animation; // Animation used to apply all six key frame animations
+
+ public EdenEffect()
+ {
+ _frameThickness = 10.0f;
+ float _bottomFrameTime = 0.6f; // complete the halo/bottom animation 60% of the way through
+ float _sideFrameTime = 0.8f; // Start the side frame animation after the bottom animation and complete at 80% of the way through
+ float _topFrameTime = 1.0f; // start the top frame animation after the side frame animation and complete at 100% way through
+
+ // Six key frame animations (EdenData objects) needed for EddenEffect
+ // Two key frame animations for top horizontal effect
+ // Two key frame animations for bottom horizontal effect
+ // Two key frame animations for vertical horizontal effect
+ _edenFocusData = new EdenData[6];
+
+ EdenData edenData = new EdenData("halo", "halo.png", EdenData.Direction.Horizontal, NDalic.ParentOriginTopCenter,
+ new Vector3(50,20,0), new Vector3(0.0f, 100.0f , 0.0f), 0.0f, _bottomFrameTime);
+ _edenFocusData[0] = edenData;
+
+ edenData = new EdenData("bottom", "horizontalFrame.png", EdenData.Direction.Horizontal, NDalic.ParentOriginTopCenter,
+ new Vector3(0.0f, 0.0f, 0.0f), new Vector3(0.0f, _frameThickness, 0.0f), 0.0f, _bottomFrameTime);
+ _edenFocusData[1] = edenData;
+
+ edenData = new EdenData("left", "verticalFrame.png", EdenData.Direction.Vertical, NDalic.ParentOriginBottomLeft,
+ new Vector3(0.0f, 0.0f, 0.0f), new Vector3(_frameThickness, 0.0f, 0.0f), _bottomFrameTime, _sideFrameTime);
+ _edenFocusData[2] = edenData;
+
+ edenData = new EdenData("right", "verticalFrame.png", EdenData.Direction.Vertical, NDalic.ParentOriginBottomRight,
+ new Vector3(0.0f, 0.0f, 0.0f), new Vector3(_frameThickness, 0.0f, 0.0f), _bottomFrameTime, _sideFrameTime);
+ _edenFocusData[3] = edenData;
+
+ edenData = new EdenData("top-left", "horizontalFrame.png", EdenData.Direction.Horizontal, NDalic.ParentOriginBottomLeft,
+ new Vector3(0.0f, 0.0f, 0.0f), new Vector3(0.0f ,_frameThickness, 0.0f), _sideFrameTime, _topFrameTime);
+ _edenFocusData[4] = edenData;
+
+ edenData = new EdenData("top-right", "horizontalFrame.png", EdenData.Direction.Horizontal, NDalic.ParentOriginBottomRight,
+ new Vector3(0.0f, 0.0f, 0.0f), new Vector3(0.0f, _frameThickness, 0.0f), _sideFrameTime, _topFrameTime);
+ _edenFocusData[5] = edenData;
+ }
+
+ public void FocusAnimation(View parentItem, Vector3 itemSize, float duration, EdenEffectDirection direction)
+ {
+ var itemWidth = itemSize.x + _frameThickness / 2;
+ var itemHeight = itemSize.y + _frameThickness / 3;
+
+ if (_animation)
+ {
+ _animation.Clear();
+ _animation.Reset();
+ }
+ _animation = new Animation(duration);
+
+ if (direction == EdenEffectDirection.BottomToTop)
+ {
+ _edenFocusData[0].ParentOrigin = NDalic.ParentOriginBottomCenter;
+ _edenFocusData[1].ParentOrigin = NDalic.ParentOriginBottomCenter;
+ _edenFocusData[2].ParentOrigin = NDalic.ParentOriginBottomLeft;
+ _edenFocusData[3].ParentOrigin = NDalic.ParentOriginBottomRight;
+ _edenFocusData[4].ParentOrigin = NDalic.ParentOriginTopLeft;
+ _edenFocusData[5].ParentOrigin = NDalic.ParentOriginTopRight;
+ }
+ else
+ {
+ _edenFocusData[0].ParentOrigin = NDalic.ParentOriginTopCenter;
+ _edenFocusData[1].ParentOrigin = NDalic.ParentOriginTopCenter;
+ _edenFocusData[2].ParentOrigin = NDalic.ParentOriginBottomLeft;
+ _edenFocusData[3].ParentOrigin = NDalic.ParentOriginBottomRight;
+ _edenFocusData[4].ParentOrigin = NDalic.ParentOriginBottomLeft;
+ _edenFocusData[5].ParentOrigin = NDalic.ParentOriginBottomRight;
+ }
+
+ foreach (EdenData edenData in _edenFocusData)
+ {
+ var currentParent = edenData.ImageItem.GetParent();
+
+ // first parent the controls
+ if (parentItem != currentParent)
+ {
+ parentItem.Add(edenData.ImageItem);
+ }
+
+ edenData.ImageItem.Size = new Vector3(100.0f,100.0f, 0.0f);
+ parentItem.Add(edenData.ImageItem);
+
+ Vector3 targetSize = edenData.TargetSize;
+ Vector3 initSize = edenData.InitSize;
+
+ if (edenData.EdenDirection == EdenData.Direction.Horizontal)
+ {
+ // adjust the width to match the parent
+ targetSize.x = itemWidth;
+ }
+ else // vertical frame
+ {
+ // adjust the height to match the parent
+ targetSize.y = itemHeight;
+ }
+
+ // half the size for the top frame as we come out from both left / right sides
+ if (edenData.Name == "top-right" || edenData.Name == "top-left")
+ {
+ targetSize.x = itemWidth - _frameThickness;
+ }
+
+ KeyFrames keyFrames = new KeyFrames();
+
+ keyFrames.Add(0.0f, new Property.Value(initSize));
+ keyFrames.Add(edenData.KeyFrameStart, new Property.Value(initSize));
+ keyFrames.Add(edenData.KeyFrameEnd, new Property.Value(targetSize));
+
+ // for halo add an extra keyframe to shrink it ( in 20% of time after it has finished)
+ if (edenData.Name =="halo")
+ {
+ keyFrames.Add(edenData.KeyFrameEnd + 0.2f, new Property.Value(initSize));
+ }
+
+ _animation.AnimateBetween(new Property(edenData.ImageItem, Actor.Property.SIZE), keyFrames,
+ new AlphaFunction(AlphaFunction.BuiltinFunction.EASE_OUT_SINE));
+
+ // Simulate the vertical frame growing from the top.
+ // Vertical items are anchored to the bottom of the parent... so when they grow
+ // we need to move them to the middle of the parent ( otherwise they stick out the bottom)
+ if (edenData.EdenDirection == EdenData.Direction.Vertical)
+ {
+ //animate position as well so it looks like animation is coming from bottom
+ KeyFrames keyFramesV = new KeyFrames();
+
+ if (direction == EdenEffectDirection.BottomToTop)
+ {
+ keyFramesV.Add(0.0f, new Property.Value(0.0f));
+ keyFramesV.Add(edenData.KeyFrameStart, new Property.Value(0.0f));
+ }
+ else
+ {
+ keyFramesV.Add(0.0f, new Property.Value(-itemHeight));
+ keyFramesV.Add(edenData.KeyFrameStart, new Property.Value(-itemHeight));
+ }
+
+ keyFramesV.Add(edenData.KeyFrameEnd, new Property.Value(-itemHeight / 2)); // animate to halfway up the control
+
+ _animation.AnimateBetween(new Property(edenData.ImageItem, Actor.Property.POSITION_Y), keyFramesV,
+ new AlphaFunction(AlphaFunction.BuiltinFunction.EASE_OUT_SINE));
+ }
+
+ // Simulate the top frame growing from the sides.
+ if (edenData.Name == "top-left")
+ {
+ KeyFrames keyFramesTL = new KeyFrames();
+
+ keyFramesTL.Add(0.0f, new Property.Value(0.0f));
+ keyFramesTL.Add(edenData.KeyFrameStart, new Property.Value(0.0f));
+ keyFramesTL.Add(edenData.KeyFrameEnd, new Property.Value(itemWidth / 2)); // animate to halfway up the control
+
+ // grow these from the left or right
+ _animation.AnimateBetween(new Property(edenData.ImageItem, Actor.Property.POSITION_X), keyFramesTL,
+ new AlphaFunction(AlphaFunction.BuiltinFunction.EASE_OUT_SINE));
+ }
+
+ if (edenData.Name == "top-right")
+ {
+ KeyFrames keyFramesTR = new KeyFrames();
+
+ keyFramesTR.Add(0.0f, new Property.Value(0.0f));
+ keyFramesTR.Add(edenData.KeyFrameStart, new Property.Value(0.0f));
+ keyFramesTR.Add(edenData.KeyFrameEnd, new Property.Value(-itemWidth / 2)); // animate to halfway up the control
+
+ // grow these from the left or right
+ _animation.AnimateBetween(new Property(edenData.ImageItem, Actor.Property.POSITION_X), keyFramesTR,
+ new AlphaFunction(AlphaFunction.BuiltinFunction.EASE_OUT_SINE));
+ }
+
+ _animation.Finished += OnAnimationFinished;
+
+ _animation.Play();
+ }
+ }
+
+ private void OnAnimationFinished(object source, Animation.FinishedEventArgs e)
+ {
+ foreach (EdenData edenData in _edenFocusData)
+ {
+ var currentParent = edenData.ImageItem.GetParent();
+
+ if (currentParent)
+ {
+ currentParent.Remove(edenData.ImageItem);
+ }
+ }
+ }
+ }
+}
+
--- /dev/null
+using Dali;
+using System;
+
+namespace FirstScreen
+{
+ public enum EdenEffectDirection
+ {
+ TopToBottom,
+ BottomToTop
+ };
+
+ public interface IEdenEffect
+ {
+ void FocusAnimation(View parentItem, Vector3 itemSize, float duration, EdenEffectDirection direction);
+ }
+}
+
--- /dev/null
+using System;
+
+namespace FirstScreen
+{
+ public class MainClass
+ {
+ [STAThread]
+ static void Main(string[] args)
+ {
+ FirstScreenApp.Run();
+ }
+ }
+}
+
--- /dev/null
+using Dali;
+using System;
+using System.Runtime.InteropServices;
+using System.Collections.Generic;
+
+
+namespace FirstScreen
+{
+ public class ScrollContainer
+ {
+ private View _container;
+ private Actor _itemRoot;
+ private Vector3 _itemSize;
+ private List<View> _itemList;
+ private int _itemCount;
+ private int _focusedItem;
+ private PanGestureDetector _panGestureDetector;
+ private float _scrollDisplacement;
+ private float _currentScrollPosition;
+ private float _padding;
+ private float _width;
+ private float _height;
+ private bool _isFocused;
+ private float _marginX;
+ private float _marginY;
+ private float _offsetY;
+ private float _offsetX;
+ private Stage _stage;
+ private Vector2 _stageSize;
+ private ImageView _shadowBorder;
+ private ImageView _spotLight;
+ private Animation _spotLightAnimation;
+ private Animation _showAnimation;
+ private Animation _hideAnimation;
+ private Animation _focusAnimation;
+ private Animation _scrollAnimation;
+ private Animation _focusTransitionAnimation;
+ private Path _circularPath;
+ private bool _shouldHide;
+
+ public ScrollContainer()
+ {
+ _itemSize = new Vector3(0.0f, 0.0f, 0.0f);
+ _padding = 0.0f;
+ _width = 0.0f;
+ _height = 0.0f;
+ _currentScrollPosition = 0.0f;
+ _itemCount = 0;
+ _focusedItem = -1;
+ _isFocused = false;
+ _marginX = 50.0f;
+ _marginY = 0.0f;
+ _offsetY = 0.0f;
+ _offsetX = 0.0f;
+
+ _shouldHide = true;
+
+ _container = new View();
+ _itemRoot = new Actor();
+ _container.Add(_itemRoot);
+
+ _itemList = new List<View>();
+
+ if (_panGestureDetector == null)
+ {
+ _panGestureDetector = new PanGestureDetector();
+ _panGestureDetector.Attach(_container);
+
+ _panGestureDetector.Detected += OnPan;
+ }
+
+ _container.ParentOrigin = NDalic.ParentOriginTopLeft;
+ _container.AnchorPoint = NDalic.AnchorPointTopLeft;
+ _itemRoot.ParentOrigin = NDalic.ParentOriginTopLeft;
+ _itemRoot.AnchorPoint = NDalic.AnchorPointTopLeft;
+
+ _container.WidthResizePolicy = "FILL_TO_PARENT";
+ _container.HeightResizePolicy = "FILL_TO_PARENT";
+ _itemRoot.WidthResizePolicy = "FILL_TO_PARENT";
+ _itemRoot.HeightResizePolicy = "FILL_TO_PARENT";
+
+ _stage = Stage.GetCurrent();
+ _stageSize = _stage.GetSize();
+
+ _spotLightAnimation = new Animation(5.0f);
+ _focusTransitionAnimation = new Animation (0.35f);
+ _focusAnimation = new Animation (0.35f);
+ _focusAnimation.SetEndAction(Animation.EndAction.BakeFinal);
+ _scrollAnimation = new Animation (0.35f);
+ _scrollAnimation.SetEndAction(Animation.EndAction.BakeFinal);
+ }
+
+ public bool IsFocused
+ {
+ get
+ {
+ return _isFocused;
+ }
+ }
+
+ public Dali.View Container
+ {
+ get
+ {
+ return _container;
+ }
+ }
+
+ public int ItemCount
+ {
+ get
+ {
+ return _itemCount;
+ }
+ }
+
+ public Actor ItemRoot
+ {
+ get
+ {
+ return _itemRoot;
+ }
+ }
+
+ public Vector3 ItemSize
+ {
+ get
+ {
+ return _itemSize;
+ }
+
+ set
+ {
+ _itemSize = value;
+
+ Vector3 topLeft = new Vector3(-0.25f * _itemSize.width, -0.25f * _itemSize.height, 0.0f);
+ Vector3 topRight = new Vector3(0.25f * _itemSize.width, -0.25f * _itemSize.height, 0.0f);
+ Vector3 bottomRight = new Vector3(0.25f * _itemSize.width, 0.25f * _itemSize.height, 0.0f);
+ Vector3 bottomLeft = new Vector3(-0.25f * _itemSize.width, 0.25f * _itemSize.height, 0.0f);
+
+ _circularPath = new Path();
+ _circularPath.AddPoint(topLeft);
+ _circularPath.AddPoint(topRight);
+ _circularPath.AddPoint(bottomRight);
+ _circularPath.AddPoint(bottomLeft);
+ _circularPath.AddPoint(topLeft);
+ _circularPath.GenerateControlPoints(0.5f);
+ }
+ }
+
+ public float Padding
+ {
+ get
+ {
+ return _padding;
+ }
+
+ set
+ {
+ _padding = value;
+ }
+ }
+
+ public float MarginX
+ {
+ get
+ {
+ return _marginX;
+ }
+
+ set
+ {
+ _marginX = value;
+ }
+ }
+
+ public float OffsetY
+ {
+ get
+ {
+ return _offsetY;
+ }
+
+ set
+ {
+ _offsetY = value;
+ }
+ }
+
+ public float OffsetX
+ {
+ get
+ {
+ return _offsetX;
+ }
+
+ set
+ {
+ _offsetX = value;
+ }
+ }
+
+ public float MarginY
+ {
+ get
+ {
+ return _marginY;
+ }
+
+ set
+ {
+ _marginY = value;
+ }
+ }
+
+ public float Width
+ {
+ get
+ {
+ return _width;
+ }
+
+ set
+ {
+ _width = value;
+ }
+ }
+
+ public float Height
+ {
+ get
+ {
+ return _height;
+ }
+
+ set
+ {
+ _height = value;
+ }
+ }
+
+ public ImageView ShadowBorder
+ {
+ get
+ {
+ return _shadowBorder;
+ }
+
+ set
+ {
+ _shadowBorder = value;
+ }
+ }
+
+ public ImageView SpotLight
+ {
+ get
+ {
+ return _spotLight;
+ }
+
+ set
+ {
+ _spotLight = value;
+ }
+ }
+
+ public int FocusedItemID
+ {
+ get
+ {
+ if (_focusedItem < 0)
+ {
+ _focusedItem = 0;
+ }
+
+ return _focusedItem;
+ }
+ }
+
+ public Actor GetCurrentFocusedActor()
+ {
+ if (_focusedItem < 0)
+ {
+ _focusedItem = 0;
+ }
+
+ return _itemList[_focusedItem];
+ }
+
+ public void AddItem(View item)
+ {
+ item.AnchorPoint = NDalic.AnchorPointBottomCenter;
+ item.ParentOrigin = NDalic.ParentOriginBottomCenter;
+
+ item.Size = _itemSize;
+ item.SetKeyboardFocusable(true);
+ item.Position = GetItemPosition(_itemCount, _currentScrollPosition);
+
+ item.Name = _itemCount.ToString();
+
+// item.ClippingMode = "CLIP_CHILDREN";
+
+ _itemRoot.Add(item);
+ _itemList.Add(item);
+ _panGestureDetector.Attach(item);
+ _itemCount++;
+ }
+
+ // Perform Show animation on ScrollContainer (used only for Poster Container)
+ public void Show()
+ {
+ Container.Add(ItemRoot);
+
+ _shouldHide = false;
+ _showAnimation = new Animation (0.35f);
+
+ _showAnimation.AnimateTo(new Property(_container, Actor.Property.COLOR_ALPHA), new Property.Value(1.0f));
+
+ _container.PositionY = _container.Position.y + 200.0f;
+ float targetPositionY = _container.Position.y - 200.0f;
+ _showAnimation.AnimateTo(new Property(_container, Actor.Property.POSITION_Y), new Property.Value(targetPositionY),
+ new AlphaFunction(AlphaFunction.BuiltinFunction.LINEAR));
+
+ _showAnimation.Play();
+ }
+
+ // Perform Hide animation on ScrollContainer (used only for Poster Container)
+ public void Hide()
+ {
+ if (_hideAnimation)
+ {
+ _hideAnimation.Clear();
+ _hideAnimation.Reset();
+ }
+
+ float duration = 0.35f;
+ _hideAnimation = new Animation(duration);
+
+ _hideAnimation.AnimateTo(new Property(_container, Actor.Property.COLOR_ALPHA), new Property.Value(0.0f),
+ new AlphaFunction(AlphaFunction.BuiltinFunction.LINEAR), new TimePeriod(0.0f, duration * 0.75f));
+
+ _hideAnimation.Finished += OnHideAnimationFinished;
+
+ _shouldHide = true;
+ _hideAnimation.Play();
+ }
+
+ public View Focus(int itemId)
+ {
+ if (itemId < 0)
+ {
+ itemId = 0;
+ }
+ else if (itemId >= _itemList.Count)
+ {
+ itemId = _itemList.Count - 1;
+ }
+
+ _itemList[itemId].Add(_shadowBorder);
+ _itemList[itemId].Add(_spotLight);
+
+ // Perform Spot Light animation
+ if(_focusedItem != itemId && _spotLight != null)
+ {
+ _spotLightAnimation.Clear();
+ _spotLightAnimation.Animate( _spotLight, _circularPath, new Vector3(0.0f, 0.0f, 0.0f) );
+ _spotLightAnimation.SetLooping(true);
+ _spotLightAnimation.Play();
+ }
+
+ _focusedItem = itemId;
+
+ Vector3 itemPosition = GetItemPosition(_focusedItem, _currentScrollPosition);
+
+ _focusAnimation.Clear();
+
+ float relativeItemPositionX = itemPosition.x - _itemSize.width * 0.5f + (_stageSize.width * 0.5f) + _offsetX;
+ if (relativeItemPositionX < _marginX + _offsetX + _padding)
+ {
+ float amount = _marginX + _offsetX + _padding - relativeItemPositionX;
+ Scroll(amount, itemId + 1); // Perform Scroll animation
+ }
+ else if (relativeItemPositionX + _itemSize.width + _padding + _marginX > _stageSize.width)
+ {
+ float amount = relativeItemPositionX + _marginX + _padding + _itemSize.width - _stageSize.width;
+ Scroll(-amount, itemId - 1); // Perform Scroll animation
+ }
+ else
+ {
+ for (int i = 0; i < _itemList.Count; ++i)
+ {
+ Vector3 targetPosition = GetItemPosition(i, _currentScrollPosition);
+ _focusAnimation.AnimateTo(new Property(_itemList[i], Actor.Property.POSITION),
+ new Property.Value(targetPosition),
+ new AlphaFunction(AlphaFunction.BuiltinFunction.EASE_OUT_SINE));
+ }
+ }
+
+ for (int i = 0; i < _itemList.Count; ++i)
+ {
+ SetupItemRenderer(_itemList[i], false);
+
+ // Perform Focus animation
+ if (i == _focusedItem)
+ {
+ _focusAnimation.AnimateTo(new Property(_itemList[i], Actor.Property.SCALE),
+ new Property.Value(new Vector3(1.2f, 1.2f, 1.2f)),
+ new AlphaFunction(AlphaFunction.BuiltinFunction.EASE_OUT_SINE));
+ }
+ else
+ {
+ _focusAnimation.AnimateTo(new Property(_itemList[i], Actor.Property.SCALE),
+ new Property.Value(new Vector3(1.0f, 1.0f, 1.0f)),
+ new AlphaFunction(AlphaFunction.BuiltinFunction.EASE_OUT_SINE));
+ }
+ }
+
+ _focusAnimation.Play();
+
+ if (_isFocused && _focusedItem >= 0)
+ {
+ SetupItemRenderer(_itemList[_focusedItem], true);
+ SetupSpotLightRenderer();
+ }
+
+ return _itemList[_focusedItem];
+ }
+
+ // Perform EddenEffect animation on Focused Item specified
+ public void FocusAnimation(EdenEffect edenEffect, EdenEffectDirection direction)
+ {
+ edenEffect.FocusAnimation(_itemList[_focusedItem], _itemSize, 1.0f, direction);
+ }
+
+ public void SetFocused(bool focused)
+ {
+ _isFocused = focused;
+
+ // Perform Focus animation if the ScrollContainer is not focused already
+ if (!_isFocused)
+ {
+ Actor parent = _shadowBorder.GetParent();
+ if (parent)
+ {
+ parent.Remove(_shadowBorder);
+ }
+
+ parent = _spotLight.GetParent();
+ if (parent)
+ {
+ parent.Remove(_spotLight);
+ }
+
+ _focusTransitionAnimation.Clear();
+
+ for (int i = 0; i < _itemList.Count; ++i)
+ {
+ SetupItemRenderer(_itemList[i], false);
+
+ Vector3 targetPosition = GetItemPosition(i, _currentScrollPosition);
+ _focusTransitionAnimation.AnimateTo(new Property(_itemList[i], Actor.Property.POSITION),
+ new Property.Value(targetPosition),
+ new AlphaFunction(AlphaFunction.BuiltinFunction.EASE_OUT_SINE));
+
+ _focusTransitionAnimation.AnimateTo(new Property(_itemList[i], Actor.Property.SCALE),
+ new Property.Value(new Vector3(1.0f, 1.0f, 1.0f)),
+ new AlphaFunction(AlphaFunction.BuiltinFunction.EASE_OUT_SINE));
+ }
+
+ _focusTransitionAnimation.Play();
+ }
+ else
+ {
+ Focus(_focusedItem);
+ }
+ }
+
+ // Obtain ID of first visible item/image on the screen of the ScrollContainer
+ public int GetFirstVisibleItemId()
+ {
+ int firstItemId = -1;
+
+ if (_isFocused)
+ {
+ firstItemId = (int)Math.Floor((-1.0 * _currentScrollPosition + _marginX * 2.0f) / (_itemSize.x + _padding));
+ }
+ else
+ {
+ firstItemId = (int)Math.Floor(-1.0 * _currentScrollPosition / (_itemSize.x + _padding));
+ }
+
+ if (firstItemId < 0)
+ {
+ firstItemId = 0;
+ }
+
+ return firstItemId;
+ }
+
+ // Obtain ID of last visible item/image on the screen of the ScrollContainer
+ public int GetLastVisibleItemId()
+ {
+ int lastItemId = -1;
+
+ if (_isFocused)
+ {
+ lastItemId = (int)Math.Ceiling(((_width - _currentScrollPosition - _marginX * 2.0f) / _itemSize.x) - 1);
+ }
+ else
+ {
+ lastItemId = (int)Math.Ceiling(((_width - _currentScrollPosition) / _itemSize.x) - 1);
+ }
+
+ if (lastItemId >= _itemList.Count)
+ {
+
+ lastItemId = _itemList.Count - 1;
+ }
+
+ return lastItemId;
+ }
+
+ // Obtain Next item/image (Right of the currently focused item) of the ScrollContainer
+ public Actor FocusNext()
+ {
+ int nextItem = -1;
+
+ if (_focusedItem < GetFirstVisibleItemId() || _focusedItem > GetLastVisibleItemId())
+ {
+ nextItem = GetFirstVisibleItemId();
+ }
+ else
+ {
+ nextItem = _focusedItem + 1;
+ }
+
+ return Focus(nextItem);
+ }
+
+ // Obtain Previous item/image (left of the currently focused item) of the ScrollContainer
+ public Actor FocusPrevious()
+ {
+ int previousItem = -1;
+
+ if (_focusedItem < GetFirstVisibleItemId() || _focusedItem > GetLastVisibleItemId())
+ {
+ previousItem = GetFirstVisibleItemId();
+ }
+ else
+ {
+ previousItem = _focusedItem - 1;
+ }
+
+ return Focus(previousItem);
+ }
+
+ private void OnHideAnimationFinished(object source, Animation.FinishedEventArgs e)
+ {
+ var currentParent = ItemRoot.GetParent();
+ if (_shouldHide && currentParent != null)
+ {
+ Container.Remove(ItemRoot);
+ }
+ }
+
+ private void OnPan(object source, PanGestureDetector.DetectedEventArgs e)
+ {
+ switch (e.PanGesture.state)
+ {
+ case Gesture.State.Started:
+ _scrollDisplacement = 0.0f;
+ break;
+
+ case Gesture.State.Continuing:
+ _scrollDisplacement = e.PanGesture.displacement.x;
+ break;
+
+ case Gesture.State.Finished:
+ case Gesture.State.Cancelled:
+ float absScrollDistance = _scrollDisplacement;
+ if (absScrollDistance < 0.0f)
+ absScrollDistance = 0.0f - absScrollDistance;
+
+ float scrollSpeed = e.PanGesture.velocity.x * e.PanGesture.velocity.x + e.PanGesture.velocity.y * e.PanGesture.velocity.y;
+ float maxScrollSpeed = 40.0f; // TBD
+ if (scrollSpeed > maxScrollSpeed)
+ scrollSpeed = maxScrollSpeed;
+
+ if (absScrollDistance > 1.0f && scrollSpeed > 0.05f) // Threshold TBD
+ {
+ if (_scrollDisplacement > 0.0f) // scroll constant distance in constant speed.
+ {
+ Scroll((_itemSize.x + _padding) * 2, GetFirstVisibleItemId());
+ }
+ else
+ {
+ Scroll(-(_itemSize.x + _padding) * 2, GetFirstVisibleItemId());
+ }
+ }
+ break;
+ }
+ }
+
+ // Perform ScrollAnimation on each item
+ private void Scroll(float amount, int baseItem)
+ {
+ float tagetScrollPosition = _currentScrollPosition + amount;
+ float totalItemSize = _itemList.Count * (_itemSize.width + _padding) + _padding + (_marginX * 2.0f);
+
+ float maxScrollPosition = _width - totalItemSize;
+
+ if (tagetScrollPosition < maxScrollPosition)
+ {
+ tagetScrollPosition = maxScrollPosition;
+ }
+ if (tagetScrollPosition > 0.0f)
+ {
+ tagetScrollPosition = 0.0f;
+ }
+
+ _scrollAnimation.Clear();
+
+ for (int i = 0; i < _itemList.Count; ++i)
+ {
+ Vector3 targetPosition = GetItemPosition(i, tagetScrollPosition);
+ _scrollAnimation.AnimateTo(new Property(_itemList[i], Actor.Property.POSITION),
+ new Property.Value(targetPosition),
+ new AlphaFunction(AlphaFunction.BuiltinFunction.EASE_OUT_SINE));
+ }
+
+ _currentScrollPosition = tagetScrollPosition;
+ _scrollAnimation.Play();
+ }
+
+ // Calculate Position of any item/image of ScrollContainer
+ private Vector3 GetItemPosition(int itemId, float scrollPosition)
+ {
+ if (_isFocused)
+ {
+ // used (_itemSize.width * 0.5f) because of AnchorPointCenter
+ // used (_stageSize.width * 0.5f) because of ParentOriginCenter
+ if (_focusedItem > itemId)
+ {
+ float positionX = (_itemSize.width * itemId) + (_padding * (itemId + 1)) + scrollPosition + (_itemSize.width * 0.5f) - (_stageSize.width * 0.5f);
+ return new Vector3(positionX, -_itemSize.height * _offsetY, 0.0f);
+ }
+ else if (_focusedItem == itemId)
+ {
+ float positionX = (_itemSize.width * itemId) + (_padding * (itemId + 1)) + scrollPosition + _marginX + (_itemSize.width * 0.5f) - (_stageSize.width * 0.5f);
+ return new Vector3(positionX, -_itemSize.height * _offsetY, 0.0f);
+ }
+ else
+ {
+ float positionX = (_itemSize.width * itemId) + (_padding * (itemId + 1)) + scrollPosition + _marginX * 2.0f + (_itemSize.width * 0.5f) - (_stageSize.width * 0.5f);
+ return new Vector3(positionX, -_itemSize.height * _offsetY, 0.0f);
+ }
+ }
+ else
+ {
+ float positionX = (_itemSize.width * itemId) + (_padding * (itemId + 1)) + scrollPosition + (_itemSize.width * 0.5f) - (_stageSize.width * 0.5f);
+ return new Vector3(positionX, -_itemSize.height * _offsetY, 0.0f);
+ }
+ }
+
+ // Used for SpotLight animation with clipping
+ private void SetupItemRenderer(Actor actor, bool stencilOn)
+ {
+ if (actor)
+ {
+ Renderer renderer = actor.GetRendererAt(0);
+
+ if (renderer)
+ {
+ // Setup the renderer properties:
+ // The stencil plane is only for stencilling, so disable writing to color buffer.
+
+ // Enable stencil. Draw to the stencil buffer (only).
+ if (stencilOn)
+ {
+ renderer.RenderMode = (int)RenderModeType.COLOR_STENCIL;
+ }
+ else
+ {
+ renderer.RenderMode = (int)RenderModeType.COLOR;
+ }
+ renderer.StencilFunction = (int)StencilFunctionType.ALWAYS;
+ renderer.StencilFunctionReference = 1;
+ renderer.StencilFunctionMask = 0xFF;
+ renderer.StencilOperationOnFail = (int)StencilOperationType.KEEP;
+ renderer.StencilOperationOnZFail = (int)StencilOperationType.KEEP;
+ renderer.StencilOperationOnZPass = (int)StencilOperationType.REPLACE;
+ renderer.StencilMask = 0xFF;
+
+ // We don't want to write to the depth buffer.
+ renderer.DepthWriteMode = (int)DepthWriteModeType.OFF;
+ // We don't beed to test the depth buffer.
+ renderer.DepthTestMode = (int)DepthTestModeType.OFF;
+
+ // This object must be rendered 1st.
+ renderer.DepthIndex = 10;
+ }
+ }
+ }
+
+ // Used for SpotLight animation with clipping
+ private void SetupSpotLightRenderer()
+ {
+ if (_spotLight)
+ {
+ Renderer renderer = _spotLight.GetRendererAt(0);
+
+ if (renderer)
+ {
+ // Setup the renderer properties:
+ // Write to color buffer so soptlight is visible
+
+ // We use blending to blend the spotlight with the poster image.
+ renderer.BlendMode = (int)BlendModeType.ON;
+ renderer.BlendEquationRgb = (int)BlendEquationType.ADD;
+ renderer.BlendEquationAlpha = (int)BlendEquationType.ADD;
+ renderer.BlendFactorDestRgb = (int)BlendFactorType.ONE;
+
+ // Enable stencil. Here we only draw to areas within the stencil.
+ renderer.RenderMode = (int)RenderModeType.COLOR_STENCIL;
+ renderer.StencilFunction = (int)StencilFunctionType.EQUAL;
+ renderer.StencilFunctionReference = 1;
+ renderer.StencilFunctionMask = 0xFF;
+ // Don't write to the stencil.
+ renderer.StencilMask = 0x00;
+
+ // We don't need to write to the depth buffer.
+ renderer.DepthWriteMode = (int)DepthWriteModeType.OFF;
+ // We don't need to test the depth buffer.
+ renderer.DepthTestMode = (int)DepthTestModeType.OFF;
+
+ // This object must be rendered last.
+ renderer.DepthIndex = 20;
+ }
+ }
+ }
+ }
+}
+