From cdef57cbf5f07aaebfb18d6b772375b4a465e5b4 Mon Sep 17 00:00:00 2001 From: ChulSeung Kim Date: Wed, 21 Jun 2017 09:50:28 +0900 Subject: [PATCH] TVHome Refactoring - Seperate MainPageViewModel to severals - Make a connection based on status(AppState, PanelState, PanelButtonState) - Make it use event notification to change GUI Change-Id: I7ccd85d15cc56410d9d64720cde1d25325abaf4e --- .../Models/AppShortcutController.cs | 2 +- LibTVRefCommonPortable/Utils/IStatePublisher.cs | 11 +- LibTVRefCommonTizen/Ports/PackageManagerPort.cs | 7 +- LibTVRefCommonTizen/Ports/WindowPort.cs | 5 +- TVApps/TVApps.TizenTV/TVApps.TizenTV.cs | 5 +- TVApps/TVApps/Controls/AppListView.xaml.cs | 5 +- TVHome/TVHome.TizenTV/TVHome.TizenTV.cs | 19 +- TVHome/TVHome/Controls/MainPanelButton.xaml.cs | 19 +- TVHome/TVHome/Controls/PanelButton.cs | 168 ++++++- .../TVHome/Controls/SubPanelAllAppsButton.xaml.cs | 19 +- TVHome/TVHome/Controls/SubPanelButton.xaml.cs | 156 +++--- .../TVHome/Controls/SubPanelSettingButton.xaml.cs | 20 +- .../Controls/SubPanelThumbnailButton.xaml.cs | 108 ++-- TVHome/TVHome/TVHome.cs | 3 +- TVHome/TVHome/TVHome.csproj | 5 +- TVHome/TVHome/ViewModels/AppListViewModel.cs | 259 ++++++++++ TVHome/TVHome/ViewModels/IHomeViewModel.cs | 37 -- TVHome/TVHome/ViewModels/MainPageViewModel.cs | 557 ++------------------- TVHome/TVHome/ViewModels/MainPanelViewModel.cs | 270 ++++++++++ TVHome/TVHome/ViewModels/RecentListViewModel.cs | 205 ++++++++ TVHome/TVHome/ViewModels/SettingsViewModel.cs | 234 +++++++++ TVHome/TVHome/Views/MainPage.xaml | 17 +- TVHome/TVHome/Views/MainPage.xaml.cs | 207 +++----- TVHome/TVHome/Views/MainPanel.xaml.cs | 144 ++++-- TVHome/TVHome/Views/Panel.cs | 183 +++++-- TVHome/TVHome/Views/SubPanel.xaml.cs | 369 ++++++++------ TVHome/TVHome/Views/SubThumbnailPanel.xaml | 5 +- TVHome/TVHome/Views/SubThumbnailPanel.xaml.cs | 251 ++++++---- 28 files changed, 2022 insertions(+), 1268 deletions(-) create mode 100644 TVHome/TVHome/ViewModels/AppListViewModel.cs delete mode 100755 TVHome/TVHome/ViewModels/IHomeViewModel.cs create mode 100644 TVHome/TVHome/ViewModels/MainPanelViewModel.cs create mode 100644 TVHome/TVHome/ViewModels/RecentListViewModel.cs create mode 100644 TVHome/TVHome/ViewModels/SettingsViewModel.cs diff --git a/LibTVRefCommonPortable/Models/AppShortcutController.cs b/LibTVRefCommonPortable/Models/AppShortcutController.cs index 37df5c0..7ec06fd 100755 --- a/LibTVRefCommonPortable/Models/AppShortcutController.cs +++ b/LibTVRefCommonPortable/Models/AppShortcutController.cs @@ -346,7 +346,7 @@ namespace LibTVRefCommonPortable.Models } else { - DebuggingUtils.Dbg("AppShortcutStorage Instance is NULL"); + DebuggingUtils.Err("AppShortcutStorage Instance is NULL"); } } } diff --git a/LibTVRefCommonPortable/Utils/IStatePublisher.cs b/LibTVRefCommonPortable/Utils/IStatePublisher.cs index 4600c1a..0c3605d 100644 --- a/LibTVRefCommonPortable/Utils/IStatePublisher.cs +++ b/LibTVRefCommonPortable/Utils/IStatePublisher.cs @@ -24,8 +24,17 @@ namespace LibTVRefCommonPortable.Utils { public enum AppState { - + HomeMainPanelRecentFocused, + HomeMainPanelAppsFocused, + HomeMainPanelSettingsFocused, + HomeSubPanelRecentFocused, + HomeSubPanelAppsFocused, + HomeSubPanelSettingsFocused, + HomeShowOptions, + HomeMove, + HomeIconified, } + public interface IStatePublisher { AppState CurrentState diff --git a/LibTVRefCommonTizen/Ports/PackageManagerPort.cs b/LibTVRefCommonTizen/Ports/PackageManagerPort.cs index a8719b7..dff72d8 100644 --- a/LibTVRefCommonTizen/Ports/PackageManagerPort.cs +++ b/LibTVRefCommonTizen/Ports/PackageManagerPort.cs @@ -92,10 +92,7 @@ namespace LibTVRefCommonTizen.Ports { if (e.State == PackageEventState.Completed) { - if (Notification != null) - { - Notification.OnAppInstalled(e.PackageId); - } + Notification?.OnAppInstalled(e.PackageId); } } @@ -120,7 +117,7 @@ namespace LibTVRefCommonTizen.Ports result = new string[3]; var itemLabel = "No Name"; - if (item.Label != null && item.Label.Length > 0) + if (!string.IsNullOrEmpty(item.Label)) { itemLabel = item.Label; } diff --git a/LibTVRefCommonTizen/Ports/WindowPort.cs b/LibTVRefCommonTizen/Ports/WindowPort.cs index 3829121..f2213d3 100644 --- a/LibTVRefCommonTizen/Ports/WindowPort.cs +++ b/LibTVRefCommonTizen/Ports/WindowPort.cs @@ -97,10 +97,7 @@ namespace LibTVRefCommonTizen.Ports /// public void Active() { - if (mainWindow != null) - { - mainWindow.Active(); - } + mainWindow?.Active(); } } } diff --git a/TVApps/TVApps.TizenTV/TVApps.TizenTV.cs b/TVApps/TVApps.TizenTV/TVApps.TizenTV.cs index 72abdc5..067aef0 100755 --- a/TVApps/TVApps.TizenTV/TVApps.TizenTV.cs +++ b/TVApps/TVApps.TizenTV/TVApps.TizenTV.cs @@ -77,10 +77,7 @@ namespace TVApps.TizenTV if (args.KeyName.CompareTo(ElmSharp.EvasKeyEventArgs.PlatformMenuButtonName) == 0 || args.KeyName.CompareTo("XF86Info") == 0) { - if (notification != null) - { - notification.OnMenuKeyPressed(); - } + notification?.OnMenuKeyPressed(); } } diff --git a/TVApps/TVApps/Controls/AppListView.xaml.cs b/TVApps/TVApps/Controls/AppListView.xaml.cs index 7dade6d..09bd061 100755 --- a/TVApps/TVApps/Controls/AppListView.xaml.cs +++ b/TVApps/TVApps/Controls/AppListView.xaml.cs @@ -214,10 +214,7 @@ namespace TVApps.Controls NoContentsView.IsVisible = true; } - if (OnChangeFocusChainingCommand != null) - { - OnChangeFocusChainingCommand.Execute(""); - } + OnChangeFocusChainingCommand?.Execute(""); } /// diff --git a/TVHome/TVHome.TizenTV/TVHome.TizenTV.cs b/TVHome/TVHome.TizenTV/TVHome.TizenTV.cs index c83c2c7..78845d8 100755 --- a/TVHome/TVHome.TizenTV/TVHome.TizenTV.cs +++ b/TVHome/TVHome.TizenTV/TVHome.TizenTV.cs @@ -120,25 +120,16 @@ namespace TVHome.TizenTV DbgPort.D("Key Pressed :" + e.KeyName); if (e.KeyName.CompareTo(ElmSharp.EvasKeyEventArgs.PlatformHomeButtonName) == 0) { - if (notification != null) - { - notification.OnHomeKeyPressed(); - } + notification?.OnHomeKeyPressed(); } else if (e.KeyName.CompareTo(ElmSharp.EvasKeyEventArgs.PlatformMenuButtonName) == 0 || e.KeyName.CompareTo("XF86Info") == 0) { - if (notification != null) - { - notification.OnMenuKeyPressed(); - } + notification?.OnMenuKeyPressed(); } else if (e.KeyName.Equals("Up") || e.KeyName.Equals("Down") || e.KeyName.Equals("Left") || e.KeyName.Equals("Right")) { - if (notification != null) - { - notification.OnNavigationKeyPressed(e.KeyName); - } + notification?.OnNavigationKeyPressed(e.KeyName); } } @@ -172,11 +163,11 @@ namespace TVHome.TizenTV string pinnedApp; if (e.ReceivedAppControl.ExtraData.TryGet(AppControlPort.KeyAddedAppID, out pinnedApp)) { - notification.OnAppPinnedNotificationReceived(pinnedApp); + notification?.OnAppPinnedNotificationReceived(pinnedApp); } else { - notification.OnAppPinnedNotificationReceived(""); + notification?.OnAppPinnedNotificationReceived(""); } } } diff --git a/TVHome/TVHome/Controls/MainPanelButton.xaml.cs b/TVHome/TVHome/Controls/MainPanelButton.xaml.cs index e7418e0..0d731aa 100755 --- a/TVHome/TVHome/Controls/MainPanelButton.xaml.cs +++ b/TVHome/TVHome/Controls/MainPanelButton.xaml.cs @@ -107,10 +107,7 @@ namespace TVHome.Controls /// The event that is occurred when button is focused public override void OnFocused(object sender, FocusEventArgs e) { - if (OnFocusedCommand != null) - { - OnFocusedCommand.Execute(""); - } + OnFocusedCommand?.Execute(""); } /// @@ -129,18 +126,18 @@ namespace TVHome.Controls /// The event that is occurred when button is clicked public override void OnClicked(object sender, EventArgs e) { - if (OnClickedCommand != null) - { - OnClickedCommand.Execute(""); - } + OnClickedCommand?.Execute(""); + } + + public override void OnMoveStarting() + { } /// /// A method for handling the button when button is changed to move mode /// - /// A flag indicates whether the button is move mode or not - /// A flag indicates whether this method is called by ChangeToDefaultMode method - public override void ChangeMoveMode(bool isMoveMode, bool isDefault) + /// A flag indicates whether moving is canceled or not + public override void OnMoveFinishing(bool isMoveCanceled) { } diff --git a/TVHome/TVHome/Controls/PanelButton.cs b/TVHome/TVHome/Controls/PanelButton.cs index efc0162..35e735d 100755 --- a/TVHome/TVHome/Controls/PanelButton.cs +++ b/TVHome/TVHome/Controls/PanelButton.cs @@ -14,23 +14,98 @@ * limitations under the License. */ +using LibTVRefCommonPortable.Utils; using System; +using System.ComponentModel; using System.Windows.Input; +using Tizen.Xamarin.Forms.Extension; using Xamarin.Forms; namespace TVHome.Controls { /// + /// Definition of enumerations which to use for recognizing a state of the PanelButton. + /// + public enum PanelButtonState + { + /// + /// Panel button is showing. But not focused. + /// + Show, + /// + /// Panel button is focusing. + /// + Focused, + /// + /// Panel button is now showing. + /// + Hide, + /// + /// Panel button is ready to move. + /// + Move, + /// + /// Panel button is moving with a animation. + /// + Moving, + /// + /// Panel button moving is canceled. + /// + MoveCanceled, + /// + /// Panel button is showing a option menu. + /// + ShowingOption, + } + + + /// /// TVHome has two panels, MainPanel and SubPanel. The panels have several panel buttons. /// The class for handling panel button's events /// public abstract class PanelButton : RelativeLayout { - public bool isMoveMode; - public bool isFocused; - public bool isShowOptions; - public bool rightMoving; - public bool leftMoving; + protected ContextPopup popup; + + private PanelButtonState previousPanelState = PanelButtonState.Hide; + + public static readonly BindableProperty PanelButtonStateProperty = BindableProperty.Create("PanelButtonState", + typeof(PanelButtonState), typeof(PanelButton), PanelButtonState.Hide, BindingMode.TwoWay); + + public PanelButtonState PanelButtonState + { + get { return (PanelButtonState)GetValue(PanelButtonStateProperty); } + set { SetValue(PanelButtonStateProperty, value); } + } + + + public bool IsButtonFocused + { + get + { + return PanelButtonState == PanelButtonState.Focused; + } + } + + public bool IsButtonMoving + { + get + { + return (PanelButtonState == PanelButtonState.Move || + PanelButtonState == PanelButtonState.Moving); + } + } + + public bool IsOptionsShowing + { + get + { + return PanelButtonState == PanelButtonState.ShowingOption; + } + } + + public EventHandler OnPanelButtonStateChanged; + /// /// A Command will be executed the button is focused. /// @@ -49,7 +124,7 @@ namespace TVHome.Controls /// /// A Command will be executed when the button moving is finished /// - public ICommand OnMoveFinishedCommand { get; set; } + public ICommand OnMoveToggleCommand { get; set; } /// /// A Command will be executed the button is unpinned. @@ -71,10 +146,6 @@ namespace TVHome.Controls /// public ICommand OnDefaultModeCommand { get; set; } - /// - /// A Command will be executed the option menus are showed. - /// - public ICommand OnShowOptionsCommand { get; set; } /// /// Handles Button Focused event @@ -97,22 +168,87 @@ namespace TVHome.Controls /// The event that is occurred when button is clicked public abstract void OnClicked(object sender, EventArgs e); + public abstract void OnMoveStarting(); + /// /// A method for handling the button when button is changed to move mode /// - /// A flag indicates whether the button is move mode or not - /// A flag indicates whether this method is called by ChangeToDefaultMode method - public abstract void ChangeMoveMode(bool isMoveMode, bool isDefault); + /// A flag indicates whether moving is canceled or not + public abstract void OnMoveFinishing(bool isMoveCanceled = false); /// - /// A method for showing context popup + /// A method for showing context pop-up /// public abstract void ShowContextPopup(); /// - /// A method for changing context popup mode + /// A method for changing context pop-up mode /// - /// Options for change context popup mode + /// Options for change context pop-up mode public abstract void ChangeShowOptionsMode(bool showOptions); + + + public PanelButton() + { + PropertyChanged += OnPropertyChanged; + } + + /// + /// An event handler for handling property changed event + /// + /// A source of event + /// The event that is occurred when property is changed + private void OnPropertyChanged(object sender, PropertyChangedEventArgs e) + { + if (e.PropertyName == "PanelButtonState") + { + if (PanelButtonState == previousPanelState) + { + DebuggingUtils.Dbg("[PanelButtonState] " + previousPanelState + " => " + PanelButtonState); + return; + } + + DebuggingUtils.Dbg("[PanelButtonState] " + previousPanelState + " => " + PanelButtonState); + switch (PanelButtonState) + { + case PanelButtonState.Move: + if (previousPanelState != PanelButtonState.Moving) + { + OnMoveStarting(); + } + + break; + + case PanelButtonState.ShowingOption: + ShowContextPopup(); + ChangeShowOptionsMode(true); + break; + } + + OnPanelButtonStateChanged?.Invoke(this, PanelButtonState); + + + switch (previousPanelState) + { + case PanelButtonState.ShowingOption: + popup?.Dismiss(); + break; + + case PanelButtonState.Move: + if (PanelButtonState != PanelButtonState.Moving) + { + OnMoveFinishing(); + } + + break; + + case PanelButtonState.MoveCanceled: + OnMoveFinishing(true); + break; + } + + previousPanelState = PanelButtonState; + } + } } } diff --git a/TVHome/TVHome/Controls/SubPanelAllAppsButton.xaml.cs b/TVHome/TVHome/Controls/SubPanelAllAppsButton.xaml.cs index 17004d1..f7c0804 100755 --- a/TVHome/TVHome/Controls/SubPanelAllAppsButton.xaml.cs +++ b/TVHome/TVHome/Controls/SubPanelAllAppsButton.xaml.cs @@ -51,10 +51,7 @@ namespace TVHome.Controls /// The event that is occurred when button is clicked public override async void OnClicked(object sender, EventArgs e) { - if (OnClickedCommand != null) - { - OnClickedCommand.Execute(""); - } + OnClickedCommand?.Execute(""); await this.FadeTo(0.99, 300); } @@ -66,10 +63,7 @@ namespace TVHome.Controls /// The event that is occurred when button is focused public override async void OnFocused(object sender, FocusEventArgs e) { - if (OnFocusedCommand != null) - { - OnFocusedCommand.Execute(""); - } + OnFocusedCommand?.Execute(""); #pragma warning disable CS4014 ButtonTitle.On().SetFontWeight(FontWeight.Medium); @@ -96,12 +90,15 @@ namespace TVHome.Controls ButtonDimmedImage.Scale = 1.0; } + public override void OnMoveStarting() + { + + } /// /// A method for handling the button when button is changed to move mode /// - /// A flag indicates whether the button is move mode or not - /// A flag indicates whether this method is called by ChangeToDefaultMode method - public override void ChangeMoveMode(bool isMoveMode, bool isDefault) + /// A flag indicates whether moving is canceled or not + public override void OnMoveFinishing(bool isMoveCanceled = false) { } diff --git a/TVHome/TVHome/Controls/SubPanelButton.xaml.cs b/TVHome/TVHome/Controls/SubPanelButton.xaml.cs index ce84884..a94d57f 100755 --- a/TVHome/TVHome/Controls/SubPanelButton.xaml.cs +++ b/TVHome/TVHome/Controls/SubPanelButton.xaml.cs @@ -49,88 +49,77 @@ namespace TVHome.Controls ButtonTitle.FontSize = SizeUtils.GetFontSize(26); ButtonTitle.On().SetFontWeight(FontWeight.Normal); + // TODO : make this subscribe when it is in the move mode. MessagingCenter.Subscribe(this, "NavigationKeyPressed", (sender, e) => { - if (isMoveMode && IsEnabled) + if (IsButtonMoving) { OnMoveCommand?.Execute(e); } }); - //InitializeLongTapGesture(); } - /* - private void InitializeLongTapGesture() - { - var longTapGesture = new LongTapGestureRecognizer - { - Timeout = 0.5 - }; - longTapGesture.TapCompleted += (sender, args) => - { - ShowContextPopup(); - }; - - View.GestureRecognizers.Add(longTapGesture); - } - */ /// /// A method for showing Context popup /// public override void ShowContextPopup() { - if (isShowOptions) + if (popup != null) { return; } - ContextPopup popup = new ContextPopup + popup = new ContextPopup { IsAutoHidingEnabled = true, Orientation = ContextPopupOrientation.Vertical, DirectionPriorities = new ContextPopupDirectionPriorities(ContextPopupDirection.Down, ContextPopupDirection.Up, ContextPopupDirection.Right, ContextPopupDirection.Left) }; + PanelButtonState = PanelButtonState.ShowingOption; + popup.Items.Add(new ContextPopupItem("MOVE")); popup.Items.Add(new ContextPopupItem("UNPIN")); popup.SelectedIndexChanged += (sender, args) => { var ctxPopup = sender as ContextPopup; - if (ctxPopup.SelectedIndex == 0) - { - OnMoveFinishedCommand.Execute(""); - } - else if (ctxPopup.SelectedIndex == 1) + DebuggingUtils.Dbg("popup SelectedIndexChanged = " + ctxPopup.SelectedIndex); + switch (ctxPopup.SelectedIndex) { - OnUnpinCommand.Execute(""); - } + case 0: + OnMoveToggleCommand.Execute(""); + ctxPopup.Dismiss(); + break; - popup.Dismiss(); + case 1: + OnUnpinCommand.Execute(""); + ctxPopup.Dismiss(); + break; + } }; popup.Dismissed += (sender, args) => { + DebuggingUtils.Dbg("popup dismissed, " + PanelButtonState); var ctxPopup = sender as ContextPopup; - isShowOptions = false; - if (ctxPopup.SelectedIndex == -1) { - OnDefaultModeCommand.Execute(""); + OnDefaultModeCommand.Execute(string.Empty); } - else if (ctxPopup.SelectedIndex == 1) + + popup = null; + if (!IsButtonMoving) { - OnShowOptionsCommand?.Execute(isShowOptions); + PanelButtonState = PanelButtonState.Focused; } }; popup.Show(this, Width / 2, Height - (moveTransitionHeight + selectTransitionHeight)); ButtonTitle.FadeTo(0, 300); - isShowOptions = true; } - /// /// Handles Button Clicked event /// @@ -138,59 +127,56 @@ namespace TVHome.Controls /// The event that is occurred when button is clicked public override async void OnClicked(object sender, EventArgs e) { - if (!isMoveMode) + DebuggingUtils.Dbg("OnClicked, moving = " + IsButtonMoving); + if (!IsButtonMoving) { - if (OnClickedCommand != null) - { - OnClickedCommand.Execute(""); - } + OnClickedCommand?.Execute(""); await this.FadeTo(0.99, 300); } else { - OnMoveFinishedCommand.Execute(""); + OnMoveToggleCommand.Execute(""); } } + public override async void OnMoveStarting() + { + DebuggingUtils.Dbg("OnMoveStarting"); + +#pragma warning disable CS4014 + ButtonTitle.FadeTo(0, 300); + + for (int i = 0; i < 2; i++) + { + LeftBtnImg.FadeTo(1, 300); + await RightBtnImg.FadeTo(1, 300); + LeftBtnImg.FadeTo(0, 300); + await RightBtnImg.FadeTo(0, 300); + } +#pragma warning restore CS4014 + } + /// /// A method for handling the button when button is changed to move mode /// - /// A flag indicates whether the button is move mode or not - /// A flag indicates whether this method is called by ChangeToDefaultMode method - public override async void ChangeMoveMode(bool moveMode, bool isDefault) + /// A flag indicates whether moving is canceled or not + public override async void OnMoveFinishing(bool isMoveCanceled = false) { - isMoveMode = moveMode; + DebuggingUtils.Dbg($"OnMoveFinishing, isMoveCanceled = {isMoveCanceled}"); #pragma warning disable CS4014 - if (moveMode) + if (!isMoveCanceled) { - ButtonTitle.FadeTo(0, 300); - - for (int i = 0; i < 2; i++) - { - LeftBtnImg.FadeTo(1, 300); - await RightBtnImg.FadeTo(1, 300); - LeftBtnImg.FadeTo(0, 300); - await RightBtnImg.FadeTo(0, 300); - } + await this.TranslateTo(SizeUtils.GetWidthSize((int)TranslationX), 0, 300); } else { - if (!isDefault) - { - await this.TranslateTo(SizeUtils.GetWidthSize((int)TranslationX), 0, 300); - } - else - { - await this.TranslateTo(0, SizeUtils.GetHeightSize((int)TranslationY), 0); - await this.TranslateTo(0, 0, 300); - } - - OnFocused(null, null); + await this.TranslateTo(0, SizeUtils.GetHeightSize((int)TranslationY), 0); + await this.TranslateTo(0, 0, 300); } - OnShowOptionsCommand?.Execute(moveMode); + OnFocused(null, null); #pragma warning restore CS4014 } @@ -200,6 +186,8 @@ namespace TVHome.Controls /// Options for change context popup mode public override async void ChangeShowOptionsMode(bool showOptions) { + DebuggingUtils.Dbg("ChangeShowOptionsMode, showOptions = " + showOptions); + if (showOptions) { #pragma warning disable CS4014 @@ -212,8 +200,6 @@ namespace TVHome.Controls await this.TranslateTo(0, 0, 300); OnFocused(null, null); } - - OnShowOptionsCommand?.Execute(showOptions); } /// @@ -223,16 +209,17 @@ namespace TVHome.Controls /// The event that is occurred when button is focused public override async void OnFocused(object sender, FocusEventArgs e) { - isFocused = true; - if (isMoveMode || isShowOptions) + DebuggingUtils.Dbg("SubPanelButton " + ButtonTitle.Text + " - OnFocused"); + + if (IsOptionsShowing || IsButtonMoving) { + DebuggingUtils.Dbg("SubPanelButton " + ButtonTitle.Text + " - OnFocused - IGNORE"); return; } - if (OnFocusedCommand != null) - { - OnFocusedCommand.Execute(""); - } + PanelButtonState = PanelButtonState.Focused; + + OnFocusedCommand?.Execute(""); #pragma warning disable CS4014 ButtonTitle.On().SetFontWeight(FontWeight.Medium); @@ -250,18 +237,23 @@ namespace TVHome.Controls /// The event that is occurred when button is unfocused public override async void OnUnfocused(object sender, FocusEventArgs e) { - isFocused = false; + DebuggingUtils.Dbg("SubPanelButton " + ButtonTitle.Text + " - OnUnfocused"); - if (!isMoveMode && !isShowOptions) + if (IsOptionsShowing || IsButtonMoving) { + DebuggingUtils.Dbg("SubPanelButton " + ButtonTitle.Text + " - OnUnfocused - IGNORE"); + return; + } + + PanelButtonState = PanelButtonState.Show; + #pragma warning disable CS4014 - ButtonTitle.On().SetFontWeight(FontWeight.Normal); - ButtonTitle.FadeTo(0.6, 300); - ButtonTitle.TranslateTo(0, 0, 300); + ButtonTitle.On().SetFontWeight(FontWeight.Normal); + ButtonTitle.FadeTo(0.6, 300); + ButtonTitle.TranslateTo(0, 0, 300); #pragma warning restore CS4014 - await ButtonImage.ScaleTo(1, 300); - ButtonDimmedImage.Scale = 1.0; - } + await ButtonImage.ScaleTo(1, 300); + ButtonDimmedImage.Scale = 1.0; } } } \ No newline at end of file diff --git a/TVHome/TVHome/Controls/SubPanelSettingButton.xaml.cs b/TVHome/TVHome/Controls/SubPanelSettingButton.xaml.cs index 5d63ae3..f5c6eff 100755 --- a/TVHome/TVHome/Controls/SubPanelSettingButton.xaml.cs +++ b/TVHome/TVHome/Controls/SubPanelSettingButton.xaml.cs @@ -51,10 +51,7 @@ namespace TVHome.Controls /// The event that is occurred when button is clicked public override async void OnClicked(object sender, EventArgs e) { - if (OnClickedCommand != null) - { - OnClickedCommand.Execute(""); - } + OnClickedCommand?.Execute(""); await this.FadeTo(0.99, 300); } @@ -66,10 +63,7 @@ namespace TVHome.Controls /// The event that is occurred when button is focused public override async void OnFocused(object sender, FocusEventArgs e) { - if (OnFocusedCommand != null) - { - OnFocusedCommand.Execute(""); - } + OnFocusedCommand?.Execute(""); #pragma warning disable CS4014 ButtonTitle.On().SetFontWeight(FontWeight.Medium); @@ -96,14 +90,16 @@ namespace TVHome.Controls ButtonDimmedImage.Scale = 1; } + public override void OnMoveStarting() + { + } + /// /// A method for handling the button when button is changed to move mode /// - /// A flag indicates whether the button is move mode or not - /// A flag indicates whether this method is called by ChangeToDefaultMode method - public override void ChangeMoveMode(bool isMoveMode, bool isDefault) + /// A flag indicates whether moving is canceled or not + public override void OnMoveFinishing(bool isMoveCanceled) { - } /// diff --git a/TVHome/TVHome/Controls/SubPanelThumbnailButton.xaml.cs b/TVHome/TVHome/Controls/SubPanelThumbnailButton.xaml.cs index 9e4aeb6..e3c76e1 100755 --- a/TVHome/TVHome/Controls/SubPanelThumbnailButton.xaml.cs +++ b/TVHome/TVHome/Controls/SubPanelThumbnailButton.xaml.cs @@ -27,11 +27,6 @@ namespace TVHome.Controls public partial class SubPanelThumbnailButton : PanelButton { /// - /// A flag which will enable showing a popup. - /// - private bool isPopupShowing = false; - - /// /// Constructor /// public SubPanelThumbnailButton() @@ -43,49 +38,7 @@ namespace TVHome.Controls ThumbnailTitle.FontSize = SizeUtils.GetFontSize(26); ThumbnailTitle.On().SetFontWeight(FontWeight.Normal); - //InitializeLongTapGesture(); - } - - /* - private void InitializeLongTapGesture() - { - var longTapGesture = new LongTapGestureRecognizer - { - Timeout = 0.5 - }; - - var tapGesture = new TapGestureRecognizer - { - NumberOfTapsRequired = 1 - }; - - tapGesture.Tapped += (sender, args) => - { - if (!isMoveMode) - { - if (OnClickedCommand != null) - { - OnClickedCommand.Execute(""); - } - - View.FadeTo(0.99, 300); - } - else - { - OnMoveFinishedCommand.Execute(""); - } - }; - - longTapGesture.TapCompleted += (sender, args) => - { - ShowContextPopup(); - //OnMoveFinishedCommand.Execute(""); - }; - - View.GestureRecognizers.Add(longTapGesture); - //View.GestureRecognizers.Add(tapGesture); } - */ /// /// Handles Button Clicked event @@ -94,10 +47,7 @@ namespace TVHome.Controls /// The event that is occurred when button is clicked public override async void OnClicked(object sender, EventArgs e) { - if (OnClickedCommand != null) - { - OnClickedCommand.Execute(""); - } + OnClickedCommand?.Execute(""); await this.FadeTo(0.9, 300); } @@ -109,12 +59,11 @@ namespace TVHome.Controls /// The event that is occurred when button is focused public override async void OnFocused(object sender, FocusEventArgs e) { - isFocused = true; + DebuggingUtils.Dbg("SubPanelThumbnailButton " + ThumbnailTitle.Text + " - OnFocused"); - if (OnFocusedCommand != null) - { - OnFocusedCommand.Execute(""); - } + PanelButtonState = PanelButtonState.Focused; + + OnFocusedCommand?.Execute(""); #pragma warning disable CS4014 ThumbnailGradient.Source = "ic_list_thumbnail_gradient_focused.9.png"; @@ -131,7 +80,13 @@ namespace TVHome.Controls /// The event that is occurred when button is unfocused public override async void OnUnfocused(object sender, FocusEventArgs e) { - isFocused = false; + DebuggingUtils.Dbg("SubPanelThumbnailButton " + ThumbnailTitle.Text + " - OnUnfocused"); + + if (!IsOptionsShowing) + { + PanelButtonState = PanelButtonState.Show; + } + #pragma warning disable CS4014 //ThumbnailTitle.FadeTo(0.3, 300); ThumbnailGradient.Source = "ic_list_thumbnail_gradient_normal.9.png"; @@ -140,12 +95,16 @@ namespace TVHome.Controls await this.ScaleTo(1.0, 300); } + public override void OnMoveStarting() + { + + } + /// /// A method for handling the button when button is changed to move mode /// - /// A flag indicates whether the button is move mode or not - /// A flag indicates whether this method is called by ChangeToDefaultMode method - public override void ChangeMoveMode(bool isMoveMode, bool isDefault) + /// A flag indicates whether moving is canceled or not + public override void OnMoveFinishing(bool isMoveCanceled) { } @@ -155,43 +114,48 @@ namespace TVHome.Controls /// public override void ShowContextPopup() { - if (isPopupShowing) + if (popup != null) { return; } - ContextPopup popup = new ContextPopup + popup = new ContextPopup { IsAutoHidingEnabled = true, Orientation = ContextPopupOrientation.Vertical, DirectionPriorities = new ContextPopupDirectionPriorities(ContextPopupDirection.Down, ContextPopupDirection.Up, ContextPopupDirection.Right, ContextPopupDirection.Left) }; + PanelButtonState = PanelButtonState.ShowingOption; + popup.Items.Add(new ContextPopupItem("REMOVE")); popup.Items.Add(new ContextPopupItem("CLEAR ALL")); popup.SelectedIndexChanged += (sender, args) => { var ctxPopup = sender as ContextPopup; - if (ctxPopup.SelectedIndex == 0) + switch (ctxPopup.SelectedIndex) { - OnClearCommand.Execute(""); - ctxPopup.Dismiss(); - } - else if (ctxPopup.SelectedIndex == 1) - { - OnClearAllCommand.Execute(""); - ctxPopup.Dismiss(); + case 0: + OnClearCommand.Execute(""); + ctxPopup.Dismiss(); + break; + + case 1: + OnClearAllCommand.Execute(""); + ctxPopup.Dismiss(); + break; } }; popup.Dismissed += (sender, args) => { - isPopupShowing = false; + popup = null; }; + DebuggingUtils.Dbg("auto hiding = " + popup.IsAutoHidingEnabled); + popup.Show(this); - isPopupShowing = true; } /// diff --git a/TVHome/TVHome/TVHome.cs b/TVHome/TVHome/TVHome.cs index 717e365..642d83e 100755 --- a/TVHome/TVHome/TVHome.cs +++ b/TVHome/TVHome/TVHome.cs @@ -200,6 +200,7 @@ namespace TVHome public void OnNavigationKeyPressed(string keyName) { + DebuggingUtils.Dbg("OnNavigationKeyPressed, " + keyName); MessagingCenter.Send(this, "NavigationKeyPressed", keyName); } @@ -244,7 +245,7 @@ namespace TVHome public void OnAppPinnedNotificationReceived(String appID) { DebuggingUtils.Dbg("[[[ App Pinned ]]] " + appID); - AppPinnedNotificationListener.Invoke(this, new TVHomeEventArgs() + AppPinnedNotificationListener?.Invoke(this, new TVHomeEventArgs() { arg = appID, }); diff --git a/TVHome/TVHome/TVHome.csproj b/TVHome/TVHome/TVHome.csproj index 60b177e..23f1885 100755 --- a/TVHome/TVHome/TVHome.csproj +++ b/TVHome/TVHome/TVHome.csproj @@ -55,7 +55,10 @@ - + + + + MainPage.xaml diff --git a/TVHome/TVHome/ViewModels/AppListViewModel.cs b/TVHome/TVHome/ViewModels/AppListViewModel.cs new file mode 100644 index 0000000..509c659 --- /dev/null +++ b/TVHome/TVHome/ViewModels/AppListViewModel.cs @@ -0,0 +1,259 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * 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 LibTVRefCommonPortable.DataModels; +using LibTVRefCommonPortable.Utils; +using Xamarin.Forms; +using LibTVRefCommonPortable.Models; +using TVHome.Views; + +namespace TVHome.ViewModels +{ + + /// + /// A class for ViewModel of TV Home Recent Menu List + /// + public class AppListViewModel : INotifyPropertyChanged, IStateSubscriber + { + private static readonly Lazy instance = new Lazy(() => new AppListViewModel()); + + public static AppListViewModel Instance + { + get + { + return instance.Value; + } + } + + private PanelState appsSubPanelState; + public PanelState AppsSubPanelState + { + set + { + if (appsSubPanelState == value) + { + return; + } + + DebuggingUtils.Dbg("AppsSubPanelState, set - " + value); + + switch (value) + { + case PanelState.Focused: + MainPageViewModel.Publisher.CurrentState = AppState.HomeSubPanelAppsFocused; + break; + + case PanelState.ShowingOption: + MainPageViewModel.Publisher.CurrentState = AppState.HomeShowOptions; + break; + + case PanelState.Moving: + MainPageViewModel.Publisher.CurrentState = AppState.HomeMove; + break; + + case PanelState.Iconified: + MainPageViewModel.Publisher.CurrentState = AppState.HomeIconified; + break; + } + + + + appsSubPanelState = value; + OnPropertyChanged("AppsSubPanelState"); + } + + get + { + return appsSubPanelState; + } + } + + /// + /// Gets or set AppList for Apps SubPanel + /// + public IEnumerable AppList { get; set; } + + /// + /// A command for moving item in sub panel + /// + public Command OnMoveCommand { get; set; } + + /// + /// A command for unpin item in sub panel + /// + public Command OnUnpinCommand { get; set; } + + private AppListViewModel() + { + DebuggingUtils.Dbg("AppListViewModel"); + + MainPageViewModel.Instance.RegisterStateSubscriber(this); + + UpdateAppList(null, null); + TVHomeImpl.GetInstance.AppShortcutControllerInstance.AddFileSystemChangedListener(UpdateAppList); + + OnMoveCommand = new Command>((moveList) => + { + DebuggingUtils.Dbg("OnMoveCommand"); + MoveAppShortcutInfo(moveList); + }); + + OnUnpinCommand = new Command((appId) => + { + DebuggingUtils.Dbg("OnUnpinCommand "); + UnpinAppShortcutInfo(appId); + }); + + + } + + /// + /// Gets the AppList for displaying items and updates the list to Apps SubPanel + /// + /// The source of event + /// The event that is occurred pinned app file is changed + private async void UpdateAppList(object sender, EventArgs e) + { + DebuggingUtils.Dbg("UpdateAppList"); + AppList = await TVHomeImpl.GetInstance.AppShortcutControllerInstance.GetPinnedAppsWithDefaultShortcuts(); + OnPropertyChanged("AppList"); + } + + /// + /// A method for updating reordered list + /// + /// A list of reordered views + private void MoveAppShortcutInfo(List moveList) + { + DebuggingUtils.Dbg("MoveAppShortcutInfo"); + List pinnedAppList = new List(); + AppShortcutInfo appShortcut; + + foreach (var item in moveList) + { + appShortcut = (AppShortcutInfo)item.BindingContext; + if (!string.IsNullOrEmpty(appShortcut.AppID)) + { + pinnedAppList.Add(new AppShortcutInfo() + { + AppID = appShortcut.AppID, + }); + } + } + + TVHomeImpl.GetInstance.AppShortcutControllerInstance.UpdatePinnedApps(pinnedAppList); + } + + + /// + /// A method for unpin application + /// + /// An application ID for unpin + private void UnpinAppShortcutInfo(string appId) + { + RemovePinnedApp(appId); + } + + + + /// + /// A method for updating pinned applications + /// + /// A list of pinned application + private void UpdatePinnedApps(Dictionary pinnedApps) + { + List pinnedAppList = new List(); + foreach (var item in pinnedApps) + { + pinnedAppList.Add(new AppShortcutInfo() + { + AppID = item.Key, + }); + } + + TVHomeImpl.GetInstance.AppShortcutControllerInstance.UpdatePinnedApps(pinnedAppList); + } + + + /// + /// A method for remove pinned application + /// + /// An ID of application for removing from pinned application list + private async void RemovePinnedApp(string appID) + { + Dictionary PinnedApps = await TVHomeImpl.GetInstance.AppShortcutControllerInstance.GetPinnedAppsAppIDs(); + if (PinnedApps.ContainsKey(appID)) + { + PinnedApps.Remove(appID); + UpdatePinnedApps(PinnedApps); + return; + } + } + + /// + /// An event that is occurred when property of MainPageViewModel is changed + /// + public event PropertyChangedEventHandler PropertyChanged; + + /// + /// A method for invoking PropertyChanged event + /// + /// The name of property + public void OnPropertyChanged(string name) + { + PropertyChangedEventHandler handler = PropertyChanged; + if (handler != null) + { + handler(this, new PropertyChangedEventArgs(name)); + } + } + + public void OnStateChanged(AppState state) + { + //DebuggingUtils.Dbg("AppPanel OnStateChanged " + state); + + switch (state) + { + case AppState.HomeMainPanelAppsFocused: + AppsSubPanelState = PanelState.Show; + break; + + case AppState.HomeSubPanelAppsFocused: + AppsSubPanelState = PanelState.Focused; + break; + + case AppState.HomeShowOptions: + case AppState.HomeMove: + break; + + case AppState.HomeIconified: + AppsSubPanelState = PanelState.Iconified; + break; + + default: + AppsSubPanelState = PanelState.Hide; + break; + + } + } + + + } +} diff --git a/TVHome/TVHome/ViewModels/IHomeViewModel.cs b/TVHome/TVHome/ViewModels/IHomeViewModel.cs deleted file mode 100755 index d6d374f..0000000 --- a/TVHome/TVHome/ViewModels/IHomeViewModel.cs +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2017 Samsung Electronics Co., Ltd - * - * Licensed under the Flora License, Version 1.1 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://floralicense.org/license/ - * - * 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. - */ - -namespace TVHome.ViewModels -{ - /// - /// An interface for TV Home MainPageViewModel - /// - interface IHomeViewModel - { - /// - /// A method for invoking PropertyChanged event - /// - /// The name of property - void OnPropertyChanged(string name); - - /// - /// A method changes CurrentStatus according to parameter - /// - /// The next status name - /// A flag indicates whether CurrentStatus to be changed or not - void ChangeCurrentStatus(HomeStatus newStatus, bool isForceUpdate); - } -} diff --git a/TVHome/TVHome/ViewModels/MainPageViewModel.cs b/TVHome/TVHome/ViewModels/MainPageViewModel.cs index 31be243..11452ee 100755 --- a/TVHome/TVHome/ViewModels/MainPageViewModel.cs +++ b/TVHome/TVHome/ViewModels/MainPageViewModel.cs @@ -26,18 +26,6 @@ using LibTVRefCommonPortable.Models; namespace TVHome.ViewModels { /// - /// A HomeStatus type enumeration - /// - public enum HomeStatus - { - MainPanelFocused = 0, - SubPanelFocused, - ShowOptions, - Move, - Iconified - }; - - /// /// A HomeMenuItem type enumeration /// public enum HomeMenuItem @@ -51,399 +39,85 @@ namespace TVHome.ViewModels /// /// A class for ViewModel of TV Home /// - public class MainPageViewModel : INotifyPropertyChanged, IHomeViewModel + public class MainPageViewModel : INotifyPropertyChanged, IStatePublisher { - /// - /// Gets or set CurrentStatus of HomeStatus - /// - public HomeStatus CurrentStatus { get; private set; } + private static readonly Lazy instance = new Lazy(); - private HomeMenuItem selectedMenuName = HomeMenuItem.Apps; - /// - /// Gets or set SelectedMenuName of HomeMenuItem - /// - public HomeMenuItem SelectedMenuName + public static MainPageViewModel Instance { get { - return selectedMenuName; + return instance.Value; } + } - set + public static IStatePublisher Publisher + { + get { - if (selectedMenuName != value) - { - selectedMenuName = value; - ChangeSelectedPanelName(value, true); - } + return instance.Value; } } - /// - /// Gets or set MainList for MainPanel - /// - public IEnumerable MainList { get; set; } - /// - /// Gets or set RecentList for Recent SubPanel - /// - public IEnumerable RecentList { get; set; } + private AppState currentState; - /// - /// Gets or set AppList for Apps SubPanel - /// - public IEnumerable AppList { get; set; } - - /// - /// Gets or set SettingsList for Settings SubPanel - /// - public IEnumerable SettingsList { get; set; } - - /// - /// A command for executing when MainPanel is focused. - /// - public Command ChangeStatusCommand { get; set; } - - /// - /// A command for executing when SubPanel is focused. - /// - public Command SubPanelFocusedCommand { get; set; } - - /// - /// A command for changing the status to Move status - /// - public Command SetMoveStatusCommand { get; set; } - - /// - /// A command for changing the status to Unpin status - /// - public Command SetUnpinStatusCommand { get; set; } - - /// - /// A command for moving item in sub panel - /// - public Command OnMoveCommand { get; set; } - - /// - /// A command for unpin item in sub panel - /// - public Command OnUnpinCommand { get; set; } - - /// - /// A command for delete a recent item - /// - public Command OnClearCommand { get; set; } - - /// - /// A command for delete all recent items - /// - public Command OnClearAllCommand { get; set; } - - /// - /// A flag indicates whether "No recent info" in Recent SubPanel to be displayed or not - /// - public bool IsShowNoRecentContents { get; set; } - - /// - /// An event that is occurred when property of MainPageViewModel is changed - /// - public event PropertyChangedEventHandler PropertyChanged; - - - /// - /// Constructor - /// Initialize MainPanel, SubPanel, Command and EventListeners - /// - public MainPageViewModel() + public AppState CurrentState { - // Init sequence - // MainPage ( MainPageViewModel -> MainPanel -> SubPanel ) - MakeMainMenuItems(); - InitStatus(); - InitCommands(); - MakeSettingsButtons(); - - UpdateAppList(null, null); - - TVHomeImpl.GetInstance.AppShortcutControllerInstance.AddFileSystemChangedListener(UpdateAppList); - - App.SetAppPinnedNotificationListener((s, e) => + get { - // TODO : Make this for Move a pinned app/Show pinned apps(scroll to last) - ChangeSelectedPanelName(HomeMenuItem.Apps); - if (e.arg.Length > 0) - { - DebuggingUtils.Dbg("Move, AppID : " + e.arg); - } - else - { - DebuggingUtils.Dbg("Show, Pinned Apps"); - } - }); + return currentState; + } - MessagingCenter.Subscribe(this, App.AppStatus, (sender, arg) => + set { - switch (arg) + if (value == currentState) { - case TVHomeStatus.OnResume: - MakeRecentButtons(); - break; - case TVHomeStatus.OnSleep: - ChangeCurrentStatus(HomeStatus.MainPanelFocused, true); - break; + return; } - }); - PropertyChanged += MainPageViewModelPropertyChanged; - } - private void MainPageViewModelPropertyChanged(object sender, PropertyChangedEventArgs e) - { - DebuggingUtils.Dbg(e.PropertyName); - } - - /// - /// A method for initializing HomeStatus to Default - /// - private void InitStatus() - { - ChangeSelectedPanelName(HomeMenuItem.Apps, true); - ChangeCurrentStatus(HomeStatus.MainPanelFocused, true); - } - - /// - /// A method for initializing commands - /// - private void InitCommands() - { - ChangeStatusCommand = new Command((status) => - { - ChangeCurrentStatus(status); - }); + DebuggingUtils.Dbg("----------------------------------"); + DebuggingUtils.Dbg("MPVM state = " + currentState + " ==> " + value); + DebuggingUtils.Dbg("----------------------------------"); - OnMoveCommand = new Command>((moveList) => - { - MoveAppShortcutInfo(moveList); - }); + currentState = value; - OnUnpinCommand = new Command((appId) => - { - UnpinAppShortcutInfo(appId); - }); - - OnClearCommand = new Command((appId) => - { - RemoveRecentApplication(appId); - }); - - OnClearAllCommand = new Command(() => - { - ClearAllRecentApplications(); - }); - } - - /// - /// A method for making MainMenu items and display in MainPanel - /// - private void MakeMainMenuItems() - { - string[] AppName = { "Recent", "Apps", "Settings" }; - string[] AppControlID = { ManagedApps.TVAppsAppID, ManagedApps.TVAppsAppID, ManagedApps.SettingsAppID }; - string[] AppIconPath = + // TODO : asynchronously + foreach (var sub in stateSubscriber) { - "ic_home_menu_{0}_normal.png", - "ic_home_menu_{0}_focused.png", - "ic_home_menu_{0}_selected.png", - "ic_home_menu_{0}_unselected.png" - }; - - List TempList = new List(); - for (int i = 0; i < AppName.Length; i++) - { - AppControlAction appControlAction = new AppControlAction() - { - AppID = AppControlID[i] - }; + sub.OnStateChanged(currentState); + } - ShortcutInfo shortcutInfo = new HomeMenuAppShortcutInfo() - { - StateDescriptions = - { - { - "default", - new StateDescription - { - Label = AppName[i], - IconPath = String.Format(AppIconPath[0], AppName[i].ToLower()), - Action = appControlAction, - } - }, - { - "focused", - new StateDescription - { - Label = AppName[i], - IconPath = String.Format(AppIconPath[1], AppName[i].ToLower()), - Action = appControlAction, - } - }, - { - "selected", - new StateDescription - { - Label = AppName[i], - IconPath = String.Format(AppIconPath[2], AppName[i].ToLower()), - Action = appControlAction, - } - }, - { - "unselect", - new StateDescription - { - Label = AppName[i], - IconPath = String.Format(AppIconPath[3], AppName[i].ToLower()), - Action = appControlAction, - } - }, - }, - }; - shortcutInfo.UpdateState(); - TempList.Add(shortcutInfo); } - - MainList = TempList; - OnPropertyChanged("MainList"); } - /// - /// Gets the AppList for displaying items and updates the list to Apps SubPanel - /// - /// The source of event - /// The event that is occurred pinned app file is changed - private async void UpdateAppList(object sender, EventArgs e) - { - AppList = await TVHomeImpl.GetInstance.AppShortcutControllerInstance.GetPinnedAppsWithDefaultShortcuts(); - OnPropertyChanged("AppList"); - } + private List stateSubscriber = new List(); - /// - /// Gets the SettingsList for displaying items and updates the list to Settings SubPanel - /// - private void MakeSettingsButtons() + public void RegisterStateSubscriber(IStateSubscriber subscriber) { - string[] ShortCutLabel = { "Brightness", "Contrast", "Color", "Tint" }; - - List TempList = new List(); - - ShortcutInfo Settings = new SettingShortcutInfo() - { - StateDescriptions = - { - { - "default", - new StateDescription - { - Label = "All Settings", - IconPath = "ic_home_settings_all_138.png", - Action = new AppControlAction() - { - AppID = "org.tizen.settings" - } - } - }, - { - "focused", - new StateDescription - { - Label = "All Settings", - IconPath = "ic_home_settings_all_182.png", - Action = new AppControlAction() - { - AppID = "org.tizen.settings" - } - } - }, - } - }; - Settings.UpdateState(); - TempList.Add(Settings); - - for (int i = 0; i < ShortCutLabel.Length; i++) - { - AppControlAction appControlAction = new AppControlAction() - { - AppID = "org.tizen.settings", - }; - appControlAction.ExtraData.Add("subview", ShortCutLabel[i].ToLower()); - - ShortcutInfo shortcutInfo = new SettingShortcutInfo() - { - StateDescriptions = - { - { - "default", - new StateDescription - { - Label = ShortCutLabel[i], - IconPath = "ic_home_settings_" + ShortCutLabel[i].ToLower() + "_138.png", - Action = appControlAction, - } - }, - { - "focused", - new StateDescription - { - Label = ShortCutLabel[i], - IconPath = "ic_home_settings_" + ShortCutLabel[i].ToLower() + "_182.png", - Action = appControlAction, - } - }, - }, - }; - shortcutInfo.UpdateState(); - TempList.Add(shortcutInfo); - } - - SettingsList = TempList; - OnPropertyChanged("SettingsList"); + stateSubscriber.Add(subscriber); } - /// - /// Gets the RecentList for displaying items and updates the list to Recent SubPanel - /// - private void MakeRecentButtons() - { - RecentList = TVHomeImpl.GetInstance.RecentShortcutControllerInstance.GetList(); - if (RecentList.Count() > 0) - { - IsShowNoRecentContents = false; - OnPropertyChanged("RecentList"); - } - else - { - IsShowNoRecentContents = true; - } - - OnPropertyChanged("IsShowNoRecentContents"); - } /// - /// Clears all recent applications and updates the list to Recent SubPanel + /// Constructor + /// Initialize MainPanel, SubPanel, Command and EventListeners /// - private void ClearAllRecentApplications() + public MainPageViewModel() { - TVHomeImpl.GetInstance.RecentShortcutControllerInstance.RemoveAll(); - MakeRecentButtons(); + // Init sequence + // MainPage ( MainPageViewModel -> MainPanel -> SubPanel ) + + App.SetAppPinnedNotificationListener((s, e) => + { + DebuggingUtils.Dbg("Show, Pinned Apps"); + }); } /// - /// Removes specified recent application and updates the list to Recent SubPanel + /// An event that is occurred when property of MainPageViewModel is changed /// - /// An application ID - private void RemoveRecentApplication(string appId) - { - TVHomeImpl.GetInstance.RecentShortcutControllerInstance.Remove(appId); - MakeRecentButtons(); - } + public event PropertyChangedEventHandler PropertyChanged; /// /// A method for invoking PropertyChanged event @@ -458,156 +132,5 @@ namespace TVHome.ViewModels } } - /// - /// A method for changing CurrentStatus according to parameter - /// - /// The next status name - /// A flag indicates whether CurrentStatus to be changed or not - public void ChangeCurrentStatus(HomeStatus newStatus, bool isForceUpdate = false) - { - if (isForceUpdate || - CurrentStatus.CompareTo(newStatus) != 0) - { - CurrentStatus = newStatus; - if (CurrentStatus.CompareTo(HomeStatus.MainPanelFocused) == 0) - { - HomeMenuItem index = HomeMenuItem.Recent; - foreach (HomeMenuAppShortcutInfo item in MainList) - { - if (index == SelectedMenuName) - { - DebuggingUtils.Dbg(index.ToString() + " To Focused"); - item.ChangeStatus("focused"); - } - else - { - DebuggingUtils.Dbg(index.ToString() + " To Default"); - item.ChangeStatus("default"); - } - - index++; - } - } - else if (CurrentStatus.CompareTo(HomeStatus.SubPanelFocused) == 0) - { - HomeMenuItem index = HomeMenuItem.Recent; - foreach (HomeMenuAppShortcutInfo item in MainList) - { - if (index == SelectedMenuName) - { - DebuggingUtils.Dbg(index.ToString() + " To be selected"); - item.ChangeStatus("selected"); - } - else - { - DebuggingUtils.Dbg(index.ToString() + " To be unselect"); - item.ChangeStatus("unselect"); - } - - index++; - } - } - - OnPropertyChanged("CurrentStatus"); - } - } - - /// - /// A method for changing selected HomeMenuItem according to parameter - /// - /// Selected menu name in MainPanel - /// A flag indicates whether selected menu name to be changed or not - public void ChangeSelectedPanelName(HomeMenuItem panelName, bool isForceUpdate = false) - { - if (isForceUpdate || - SelectedMenuName.CompareTo(panelName) != 0) - { - SelectedMenuName = panelName; - HomeMenuItem index = HomeMenuItem.Recent; - foreach (HomeMenuAppShortcutInfo item in MainList) - { - if (index == panelName) - { - //DebuggingUtils.Dbg(index.ToString() + " To Focused"); - item.ChangeStatus("focused"); - } - else - { - //DebuggingUtils.Dbg(index.ToString() + " To Default"); - item.ChangeStatus("default"); - } - - index++; - } - - OnPropertyChanged("SelectedMenuName"); - } - } - - /// - /// A method for unpin application - /// - /// An application ID for unpin - private void UnpinAppShortcutInfo(string appId) - { - RemovePinnedApp(appId); - } - - /// - /// A method for updating pinned applications - /// - /// A list of pinned application - private void UpdatePinnedApps(Dictionary pinnedApps) - { - List pinnedAppList = new List(); - foreach (var item in pinnedApps) - { - pinnedAppList.Add(new AppShortcutInfo() - { - AppID = item.Key, - }); - } - - TVHomeImpl.GetInstance.AppShortcutControllerInstance.UpdatePinnedApps(pinnedAppList); - } - - /// - /// A method for remove pinned application - /// - /// An ID of application for removing from pinned application list - private async void RemovePinnedApp(string appID) - { - Dictionary PinnedApps = await TVHomeImpl.GetInstance.AppShortcutControllerInstance.GetPinnedAppsAppIDs(); - if (PinnedApps.ContainsKey(appID)) - { - PinnedApps.Remove(appID); - UpdatePinnedApps(PinnedApps); - return; - } - } - - /// - /// A method for updating reordered list - /// - /// A list of reordered views - private void MoveAppShortcutInfo(List moveList) - { - List pinnedAppList = new List(); - AppShortcutInfo appShortcut; - - foreach (var item in moveList) - { - appShortcut = (AppShortcutInfo)item.BindingContext; - if (appShortcut.AppID != null && appShortcut.AppID.Length > 0) - { - pinnedAppList.Add(new AppShortcutInfo() - { - AppID = appShortcut.AppID, - }); - } - } - - TVHomeImpl.GetInstance.AppShortcutControllerInstance.UpdatePinnedApps(pinnedAppList); - } } } diff --git a/TVHome/TVHome/ViewModels/MainPanelViewModel.cs b/TVHome/TVHome/ViewModels/MainPanelViewModel.cs new file mode 100644 index 0000000..43bd322 --- /dev/null +++ b/TVHome/TVHome/ViewModels/MainPanelViewModel.cs @@ -0,0 +1,270 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * 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 LibTVRefCommonPortable.DataModels; +using LibTVRefCommonPortable.Utils; +using Xamarin.Forms; +using LibTVRefCommonPortable.Models; +using TVHome.Views; + +namespace TVHome.ViewModels +{ + + /// + /// A class for ViewModel of TV Home Recent Menu List + /// + public class MainPanelViewModel : INotifyPropertyChanged, IStateSubscriber + { + private static readonly Lazy instance = new Lazy(() => new MainPanelViewModel()); + + public static MainPanelViewModel Instance + { + get + { + return instance.Value; + } + } + + private PanelState mainPanelState; + public PanelState MainPanelState + { + get + { + return mainPanelState; + } + + set + { + if (mainPanelState == value) + { + return; + } + + DebuggingUtils.Dbg("MainPanelState, set - " + value); + mainPanelState = value; + + OnPropertyChanged("MainPanelState"); + } + } + + private int focusedItemIndex; + public int FocusedItemIndex + { + get + { + return focusedItemIndex; + } + + set + { + /* + if (focusedItemIndex == value) + { + return; + } + */ + focusedItemIndex = value; + DebuggingUtils.Dbg("FocusedItemIndex => " + value); + + switch (focusedItemIndex) + { + case 0: + MainPageViewModel.Publisher.CurrentState = AppState.HomeMainPanelRecentFocused; + return; + case 1: + MainPageViewModel.Publisher.CurrentState = AppState.HomeMainPanelAppsFocused; + return; + case 2: + MainPageViewModel.Publisher.CurrentState = AppState.HomeMainPanelSettingsFocused; + return; + } + + OnPropertyChanged("FocusedItemIndex"); + } + } + + + /// + /// Gets or set MainList for MainPanel + /// + public IEnumerable MainList { get; set; } + + + + private MainPanelViewModel() + { + DebuggingUtils.Dbg("MainPanelViewModel"); + + MakeMainMenuItems(); + + //FocusedItemIndex = 1; + + MainPageViewModel.Instance.RegisterStateSubscriber(this); + } + + + /// + /// A method for making MainMenu items and display in MainPanel + /// + private void MakeMainMenuItems() + { + string[] AppName = { "Recent", "Apps", "Settings" }; + string[] AppControlID = { ManagedApps.TVAppsAppID, ManagedApps.TVAppsAppID, ManagedApps.SettingsAppID }; + string[] AppIconPath = + { + "ic_home_menu_{0}_normal.png", + "ic_home_menu_{0}_focused.png", + "ic_home_menu_{0}_selected.png", + "ic_home_menu_{0}_unselected.png" + }; + + List TempList = new List(); + for (int i = 0; i < AppName.Length; i++) + { + AppControlAction appControlAction = new AppControlAction() + { + AppID = AppControlID[i] + }; + + ShortcutInfo shortcutInfo = new HomeMenuAppShortcutInfo() + { + StateDescriptions = + { + { + "default", + new StateDescription + { + Label = AppName[i], + IconPath = String.Format(AppIconPath[0], AppName[i].ToLower()), + Action = appControlAction, + } + }, + { + "focused", + new StateDescription + { + Label = AppName[i], + IconPath = String.Format(AppIconPath[1], AppName[i].ToLower()), + Action = appControlAction, + } + }, + { + "selected", + new StateDescription + { + Label = AppName[i], + IconPath = String.Format(AppIconPath[2], AppName[i].ToLower()), + Action = appControlAction, + } + }, + { + "unselect", + new StateDescription + { + Label = AppName[i], + IconPath = String.Format(AppIconPath[3], AppName[i].ToLower()), + Action = appControlAction, + } + }, + }, + }; + shortcutInfo.UpdateState(); + TempList.Add(shortcutInfo); + } + + MainList = TempList; + OnPropertyChanged("MainList"); + } + + + /// + /// An event that is occurred when property of MainPageViewModel is changed + /// + public event PropertyChangedEventHandler PropertyChanged; + + /// + /// A method for invoking PropertyChanged event + /// + /// The name of property + public void OnPropertyChanged(string name) + { + PropertyChangedEventHandler handler = PropertyChanged; + if (handler != null) + { + handler(this, new PropertyChangedEventArgs(name)); + } + } + + public void OnStateChanged(AppState state) + { + //DebuggingUtils.Dbg("MainPanel OnStateChanged " + state); + + switch (state) + { + case AppState.HomeMainPanelAppsFocused: + case AppState.HomeMainPanelRecentFocused: + case AppState.HomeMainPanelSettingsFocused: + MainPanelState = PanelState.Focused; + + foreach (var menuItem in MainList) + { + HomeMenuAppShortcutInfo homeMenuItem = menuItem as HomeMenuAppShortcutInfo; + homeMenuItem.ChangeStatus("default"); + } + + (MainList.ElementAt(FocusedItemIndex) as HomeMenuAppShortcutInfo)?.ChangeStatus("focused"); + OnPropertyChanged("MainList"); + break; + + case AppState.HomeSubPanelRecentFocused: + case AppState.HomeSubPanelAppsFocused: + case AppState.HomeSubPanelSettingsFocused: + foreach (var menuItem in MainList) + { + HomeMenuAppShortcutInfo homeMenuItem = menuItem as HomeMenuAppShortcutInfo; + homeMenuItem.ChangeStatus("unselect"); + } + + (MainList.ElementAt(FocusedItemIndex) as HomeMenuAppShortcutInfo)?.ChangeStatus("selected"); + OnPropertyChanged("MainList"); + MainPanelState = PanelState.Show; + + + break; + + case AppState.HomeShowOptions: + MainPanelState = PanelState.ShowingOption; + break; + + case AppState.HomeMove: + MainPanelState = PanelState.Moving; + break; + + case AppState.HomeIconified: + MainPanelState = PanelState.Iconified; + break; + + default: + MainPanelState = PanelState.Hide; + break; + } + } + } +} diff --git a/TVHome/TVHome/ViewModels/RecentListViewModel.cs b/TVHome/TVHome/ViewModels/RecentListViewModel.cs new file mode 100644 index 0000000..c9150ad --- /dev/null +++ b/TVHome/TVHome/ViewModels/RecentListViewModel.cs @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * 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 LibTVRefCommonPortable.DataModels; +using LibTVRefCommonPortable.Utils; +using Xamarin.Forms; +using LibTVRefCommonPortable.Models; +using TVHome.Views; + +namespace TVHome.ViewModels +{ + + /// + /// A class for ViewModel of TV Home Recent Menu List + /// + public class RecentListViewModel : INotifyPropertyChanged, IStateSubscriber + { + private static readonly Lazy instance = new Lazy(() => new RecentListViewModel()); + + public static RecentListViewModel Instance + { + get + { + return instance.Value; + } + } + + private PanelState recentSubPanelState; + public PanelState RecentSubPanelState + { + set + { + if (recentSubPanelState == value) + { + return; + } + + DebuggingUtils.Dbg("RecentSubPanelState, set - " + value); + + switch (value) + { + case PanelState.Focused: + if (MainPageViewModel.Publisher.CurrentState == AppState.HomeMainPanelRecentFocused) + { + MainPageViewModel.Publisher.CurrentState = AppState.HomeSubPanelRecentFocused; + } + + break; + + case PanelState.Iconified: + MainPageViewModel.Publisher.CurrentState = AppState.HomeIconified; + break; + } + + recentSubPanelState = value; + OnPropertyChanged("RecentSubPanelState"); + } + + get + { + return recentSubPanelState; + } + } + + + + /// + /// Gets or set RecentList for Recent SubPanel + /// + public IEnumerable RecentList { get; set; } + + + /// + /// A command for delete a recent item + /// + public Command OnClearCommand { get; set; } + + /// + /// A command for delete all recent items + /// + public Command OnClearAllCommand { get; set; } + + private RecentListViewModel() + { + DebuggingUtils.Dbg("RecentListViewModel"); + + MakeRecentButtons(); + + MainPageViewModel.Instance.RegisterStateSubscriber(this); + + OnClearCommand = new Command((appId) => + { + RemoveRecentApplication(appId); + }); + + OnClearAllCommand = new Command(() => + { + ClearAllRecentApplications(); + }); + + MessagingCenter.Subscribe(this, App.AppStatus, (sender, arg) => + { + switch (arg) + { + case TVHomeStatus.OnResume: + MakeRecentButtons(); + break; + } + }); + } + + /// + /// Gets the RecentList for displaying items and updates the list to Recent SubPanel + /// + private void MakeRecentButtons() + { + RecentList = TVHomeImpl.GetInstance.RecentShortcutControllerInstance.GetList(); + OnPropertyChanged("RecentList"); + } + + /// + /// Clears all recent applications and updates the list to Recent SubPanel + /// + private void ClearAllRecentApplications() + { + TVHomeImpl.GetInstance.RecentShortcutControllerInstance.RemoveAll(); + MakeRecentButtons(); + } + + /// + /// Removes specified recent application and updates the list to Recent SubPanel + /// + /// An application ID + private void RemoveRecentApplication(string appId) + { + TVHomeImpl.GetInstance.RecentShortcutControllerInstance.Remove(appId); + MakeRecentButtons(); + } + + /// + /// An event that is occurred when property of MainPageViewModel is changed + /// + public event PropertyChangedEventHandler PropertyChanged; + + /// + /// A method for invoking PropertyChanged event + /// + /// The name of property + public void OnPropertyChanged(string name) + { + DebuggingUtils.Dbg("RecentListViewModel OnPropertyChanged " + name); + PropertyChangedEventHandler handler = PropertyChanged; + if (handler != null) + { + handler(this, new PropertyChangedEventArgs(name)); + } + } + + public void OnStateChanged(AppState state) + { + DebuggingUtils.Dbg("RecentListViewModel OnStateChanged " + state); + + switch (state) + { + case AppState.HomeMainPanelRecentFocused: + RecentSubPanelState = PanelState.Show; + break; + + case AppState.HomeSubPanelRecentFocused: + RecentSubPanelState = PanelState.Focused; + break; + + case AppState.HomeShowOptions: + case AppState.HomeMove: + break; + + case AppState.HomeIconified: + RecentSubPanelState = PanelState.Iconified; + break; + + default: + RecentSubPanelState = PanelState.Hide; + break; + + } + } + } +} diff --git a/TVHome/TVHome/ViewModels/SettingsViewModel.cs b/TVHome/TVHome/ViewModels/SettingsViewModel.cs new file mode 100644 index 0000000..fd30bbd --- /dev/null +++ b/TVHome/TVHome/ViewModels/SettingsViewModel.cs @@ -0,0 +1,234 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * 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 LibTVRefCommonPortable.DataModels; +using LibTVRefCommonPortable.Utils; +using Xamarin.Forms; +using LibTVRefCommonPortable.Models; +using TVHome.Views; + +namespace TVHome.ViewModels +{ + + /// + /// A class for ViewModel of TV Home Recent Menu List + /// + public class SettingsViewModel : INotifyPropertyChanged, IStateSubscriber + { + private static readonly Lazy instance = new Lazy(() => new SettingsViewModel()); + + public static SettingsViewModel Instance + { + get + { + return instance.Value; + } + } + + + private PanelState settingsSubPanelState; + public PanelState SettingsSubPanelState + { + set + { + if (settingsSubPanelState == value) + { + return; + } + + DebuggingUtils.Dbg("SettingsSubPanelState, set - " + value); + + switch (value) + { + case PanelState.Focused: + if (settingsSubPanelState != PanelState.Focused) + { + MainPageViewModel.Publisher.CurrentState = AppState.HomeSubPanelSettingsFocused; + } + + break; + + case PanelState.Iconified: + MainPageViewModel.Publisher.CurrentState = AppState.HomeIconified; + break; + } + + settingsSubPanelState = value; + OnPropertyChanged("SettingsSubPanelState"); + } + + get + { + return settingsSubPanelState; + } + } + + + /// + /// Gets or set SettingsList for Settings SubPanel + /// + public IEnumerable SettingsList { get; set; } + + + private SettingsViewModel() + { + DebuggingUtils.Dbg("SettingsViewModel"); + + MakeSettingsButtons(); + + MainPageViewModel.Instance.RegisterStateSubscriber(this); + + } + + + + /// + /// Gets the SettingsList for displaying items and updates the list to Settings SubPanel + /// + private void MakeSettingsButtons() + { + string[] ShortCutLabel = { "Brightness", "Contrast", "Color", "Tint" }; + + List TempList = new List(); + + ShortcutInfo Settings = new SettingShortcutInfo() + { + StateDescriptions = + { + { + "default", + new StateDescription + { + Label = "All Settings", + IconPath = "ic_home_settings_all_138.png", + Action = new AppControlAction() + { + AppID = "org.tizen.settings" + } + } + }, + { + "focused", + new StateDescription + { + Label = "All Settings", + IconPath = "ic_home_settings_all_182.png", + Action = new AppControlAction() + { + AppID = "org.tizen.settings" + } + } + }, + } + }; + Settings.UpdateState(); + TempList.Add(Settings); + + for (int i = 0; i < ShortCutLabel.Length; i++) + { + AppControlAction appControlAction = new AppControlAction() + { + AppID = "org.tizen.settings", + }; + appControlAction.ExtraData.Add("subview", ShortCutLabel[i].ToLower()); + + ShortcutInfo shortcutInfo = new SettingShortcutInfo() + { + StateDescriptions = + { + { + "default", + new StateDescription + { + Label = ShortCutLabel[i], + IconPath = "ic_home_settings_" + ShortCutLabel[i].ToLower() + "_138.png", + Action = appControlAction, + } + }, + { + "focused", + new StateDescription + { + Label = ShortCutLabel[i], + IconPath = "ic_home_settings_" + ShortCutLabel[i].ToLower() + "_182.png", + Action = appControlAction, + } + }, + }, + }; + shortcutInfo.UpdateState(); + TempList.Add(shortcutInfo); + } + + SettingsList = TempList; + OnPropertyChanged("SettingsList"); + } + + + + + /// + /// An event that is occurred when property of MainPageViewModel is changed + /// + public event PropertyChangedEventHandler PropertyChanged; + + /// + /// A method for invoking PropertyChanged event + /// + /// The name of property + public void OnPropertyChanged(string name) + { + DebuggingUtils.Dbg("OnPropertyChanged - " + name); + PropertyChangedEventHandler handler = PropertyChanged; + if (handler != null) + { + handler(this, new PropertyChangedEventArgs(name)); + } + } + + public void OnStateChanged(AppState state) + { + //DebuggingUtils.Dbg("SettingsSubPanel OnStateChanged " + state); + + switch (state) + { + case AppState.HomeMainPanelSettingsFocused: + SettingsSubPanelState = PanelState.Show; + break; + + case AppState.HomeSubPanelSettingsFocused: + SettingsSubPanelState = PanelState.Focused; + break; + + case AppState.HomeShowOptions: + case AppState.HomeMove: + break; + + case AppState.HomeIconified: + SettingsSubPanelState = PanelState.Iconified; + break; + + default: + SettingsSubPanelState = PanelState.Hide; + break; + } + } + } +} diff --git a/TVHome/TVHome/Views/MainPage.xaml b/TVHome/TVHome/Views/MainPage.xaml index dd41bbe..cd3d409 100755 --- a/TVHome/TVHome/Views/MainPage.xaml +++ b/TVHome/TVHome/Views/MainPage.xaml @@ -5,11 +5,8 @@ xmlns:Views="clr-namespace:TVHome.Views" xmlns:ViewModels="clr-namespace:TVHome.ViewModels" xmlns:Controls="clr-namespace:TVHome.Controls" - CurrentStatus="{Binding CurrentStatus}" + CurrentState="{Binding CurrentState}" SelectedMenuName="{Binding SelectedMenuName}"> - - - + ItemsSource="{Binding RecentList}" /> @@ -53,7 +50,7 @@ RelativeLayout.HeightConstraint="{ConstraintExpression Type=RelativeToParent, Property=Height, Factor=0.2370}" RelativeLayout.WidthConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=1}" RelativeLayout.YConstraint="{ConstraintExpression Type=RelativeToParent, Property=Height, Factor=0.8833}" - ChangeStatusCommand="{Binding ChangeStatusCommand}" + PanelState="{Binding SettingsSubPanelState}" ItemsSource="{Binding SettingsList}" /> diff --git a/TVHome/TVHome/Views/MainPage.xaml.cs b/TVHome/TVHome/Views/MainPage.xaml.cs index 9daf994..c67c9b6 100755 --- a/TVHome/TVHome/Views/MainPage.xaml.cs +++ b/TVHome/TVHome/Views/MainPage.xaml.cs @@ -29,17 +29,18 @@ namespace TVHome.Views public partial class MainPage : ContentPage { /// - /// Identifies the CurrentStatus bindable property + /// Identifies the CurrentState bindable property /// - public static readonly BindableProperty CurrentStatusProperty = BindableProperty.Create("CurrentStatus", typeof(HomeStatus), typeof(MainPage), default(HomeStatus)); + public static readonly BindableProperty CurrentStateProperty = BindableProperty.Create("CurrentState", typeof(AppState), typeof(MainPage), default(AppState), BindingMode.TwoWay); /// /// Gets or sets current status of MainPage /// - public HomeStatus CurrentStatus + // TODO : modify name to CurrentState + public AppState CurrentState { - get { return (HomeStatus)GetValue(CurrentStatusProperty); } - set { SetValue(CurrentStatusProperty, value); } + get { return (AppState)GetValue(CurrentStateProperty); } + set { SetValue(CurrentStateProperty, value); } } /// @@ -66,7 +67,7 @@ namespace TVHome.Views /// private async void Iconified() { - SubPanelDictionary[SelectedMenuName]?.ForceHidePanel(); + //SubPanelDictionary[SelectedMenuName]?.ForceHidePanel(); #pragma warning disable CS4014 SubPanelDictionary[SelectedMenuName]?.TranslateTo(0.0, SizeUtils.GetHeightSize(100), 150); SubPanelDictionary[SelectedMenuName]?.FadeTo(0, 150); @@ -101,10 +102,13 @@ namespace TVHome.Views { PageMainPanel.InitialFocusing(); Uniconified(); + PageMainPanel.InitialFocusing(); } else { + CurrentState = AppState.HomeIconified; Iconified(); + //CurrentState = AppState.HomeMainPanelAppsFocused; } } @@ -117,20 +121,28 @@ namespace TVHome.Views public MainPage() { InitializeComponent(); + + BindingContext = MainPageViewModel.Instance; + SubPanelDictionary = new Dictionary(); SubPanelDictionary.Add(HomeMenuItem.Recent, RecentSubPanel); SubPanelDictionary.Add(HomeMenuItem.Apps, AppsSubPanel); SubPanelDictionary.Add(HomeMenuItem.Settings, SettingsSubPanel); - RecentSubPanel.HidePanel(); - AppsSubPanel.ShowPanel(); - SettingsSubPanel.HidePanel(); + RecentSubPanel.OnPanelHiding(); + RecentSubPanel.BindingContext = RecentListViewModel.Instance; + + AppsSubPanel.OnPanelShowing(); + AppsSubPanel.BindingContext = AppListViewModel.Instance; + + SettingsSubPanel.OnPanelHiding(); + SettingsSubPanel.BindingContext = SettingsViewModel.Instance; PropertyChanged += MainPage_PropertyChanged; App.SetHomeKeyListener((e, arg) => { - if (AppsSubPanel.isMoveMode) + if (AppsSubPanel.PanelState == PanelState.Moving) { AppsSubPanel.ChangeToDefaultMode(); } @@ -140,36 +152,16 @@ namespace TVHome.Views App.SetMenuKeyListener((e, arg) => { - if (AppsSubPanel.isFocused) + foreach (var subPanel in SubPanelDictionary.Values) { - AppsSubPanel.MenuKeyPressed(); - } - else if (RecentSubPanel.isFocused) - { - RecentSubPanel.MenuKeyPressed(); + if (subPanel.PanelState == PanelState.Focused) + { + subPanel.MenuKeyPressed(); + break; + } } }); - AppsSubPanel.OnShowOptionsCommand = new Command((isShowOptions) => - { - var bounds = AppsSubPanel.Bounds; - if (isShowOptions) - { - PageMainPanel.FadeTo(0, 300); - PageMainPanel.IsVisible = false; - bounds.Height += 300; - bounds.Y -= 300; - } - else - { - PageMainPanel.FadeTo(1, 300); - bounds.Height -= 300; - bounds.Y += 300; - PageMainPanel.IsVisible = true; - } - - AppsSubPanel.LayoutTo(bounds, 0); - }); MessagingCenter.Subscribe(this, App.AppStatus, (sender, arg) => { @@ -183,45 +175,6 @@ namespace TVHome.Views break; } }); - PageMainPanel.OnItemFocusedHandler += (selectedItem) => - { - SelectedMenuName = selectedItem; - DebuggingUtils.Dbg("test" + SelectedMenuName); - }; - - PageMainPanel.OnItemSelectedHandler += (selectedItem) => - { - switch (selectedItem) - { - case HomeMenuItem.Recent: - RecentSubPanel.FocusPanel(); - AppsSubPanel.HidePanel(); - SettingsSubPanel.HidePanel(); - break; - case HomeMenuItem.Apps: - RecentSubPanel.HidePanel(); - AppsSubPanel.FocusPanel(); - SettingsSubPanel.HidePanel(); - break; - case HomeMenuItem.Settings: - RecentSubPanel.HidePanel(); - AppsSubPanel.HidePanel(); - SettingsSubPanel.FocusPanel(); - break; - } - }; - AppsSubPanel.OnItemClickEventHandler += () => - { - ToggleIconified(); - }; - RecentSubPanel.OnItemClickEventHandler += () => - { - ToggleIconified(); - }; - SettingsSubPanel.OnItemClickEventHandler += () => - { - ToggleIconified(); - }; } /// @@ -234,7 +187,10 @@ namespace TVHome.Views AppsSubPanel.ItemSourceChanged += (s, e) => { - InitializeAppsSubPanelButtonFocusChain(); + if (CurrentState != AppState.HomeMove) + { + InitializeAppsSubPanelButtonFocusChain(); + } }; InitializeMainPanelButtonFocusChain(); @@ -265,7 +221,7 @@ namespace TVHome.Views /// private void InitializeRecentSubPanelButtonFocusChain() { - List recentSubPanelButtons = new List(RecentSubPanel.GetSubPanelButtons()); + List recentSubPanelButtons = new List(RecentSubPanel.GetSubPanelButtons); Button recentMainPanelButton = PageMainPanel.GetButtonToFocusing(0); if (recentSubPanelButtons.Count > 1) @@ -297,8 +253,8 @@ namespace TVHome.Views /// private void InitializeAppsSubPanelButtonFocusChain() { - List appsSubPanelButtons = new List(AppsSubPanel.GetSubPanelButtons()); - DebuggingUtils.Dbg("test" + appsSubPanelButtons.Count); + List appsSubPanelButtons = new List(AppsSubPanel.SubPanelButtons); + DebuggingUtils.Dbg("InitializeAppsSubPanelButtonFocusChain, buttons = " + appsSubPanelButtons.Count); Button appsMainPanelButton = PageMainPanel.GetButtonToFocusing(1); if (appsSubPanelButtons.Count > 2) @@ -330,7 +286,7 @@ namespace TVHome.Views /// private void InitializeSettingsSubPanelButtonFocusChain() { - List settingSubPanelButtons = new List(SettingsSubPanel.GetSubPanelButtons()); + List settingSubPanelButtons = new List(SettingsSubPanel.SubPanelButtons); Button settingMainPanelButton = PageMainPanel.GetButtonToFocusing(2); if (settingSubPanelButtons.Count > 2) @@ -351,77 +307,52 @@ namespace TVHome.Views /// The event that is occurred when property is changed private void MainPage_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) { - if (e.PropertyName.CompareTo("CurrentStatus") == 0) - { - SetCurrentStatus(CurrentStatus); - } - else if (e.PropertyName.CompareTo("SelectedMenuName") == 0) + DebuggingUtils.Dbg("MainPage_PropertyChanged, status = " + CurrentState + ", - " + e.PropertyName); + if (e.PropertyName.CompareTo("CurrentState") == 0) { - SelectMenu(SelectedMenuName); + switch (CurrentState) + { + case AppState.HomeIconified: + ToggleIconified(); + break; + } } } /// - /// A method sets current status according to parameter + /// A task for handling BackKey event /// - /// The next status name - private void SetCurrentStatus(HomeStatus status) + /// Always returns true + protected override bool OnBackButtonPressed() { - switch (status) + DebuggingUtils.Dbg("OnBackButtonPressed"); + + switch (CurrentState) { - case HomeStatus.MainPanelFocused: - PageMainPanel.FocusPanel(); - SelectMenu(SelectedMenuName); + case AppState.HomeMove: + case AppState.HomeShowOptions: + AppsSubPanel.ChangeToDefaultMode(); + // TODO : set panel focused for focused panel. break; - case HomeStatus.SubPanelFocused: - PageMainPanel.SelectPanel(); + + case AppState.HomeMainPanelAppsFocused: + // TODO : remove dependency of MainPanel + PageMainPanel.SetButtonFocus(1); break; - } - } - /// - /// A method sets selected HomeMenuItem according to parameter - /// - /// Selected HomeMenuItem - private void SelectMenu(HomeMenuItem panelName) - { - foreach (var panelItem in SubPanelDictionary) - { - panelItem.Value.HidePanel(); - } + case AppState.HomeMainPanelRecentFocused: + // TODO : + PageMainPanel.SetButtonFocus(0); + break; - if (panelName == HomeMenuItem.NotSelected) - { - return; - } + case AppState.HomeMainPanelSettingsFocused: + // TODO : + PageMainPanel.SetButtonFocus(2); + break; - SubPanelDictionary[panelName].ShowPanel(); - } - /// - /// A task for handling BackKey event - /// - /// Always returns true - protected override bool OnBackButtonPressed() - { - if (AppsSubPanel.isMoveMode || AppsSubPanel.isShowOptions) - { - AppsSubPanel.ChangeToDefaultMode(); - } - else if (AppsSubPanel.isFocused) - { - PageMainPanel.SetButtonFocus(1); - } - else if (RecentSubPanel.isFocused) - { - PageMainPanel.SetButtonFocus(0); - } - else if (SettingsSubPanel.isFocused) - { - PageMainPanel.SetButtonFocus(2); - } - else - { - ToggleIconified(); + default: + ToggleIconified(); + break; } return true; diff --git a/TVHome/TVHome/Views/MainPanel.xaml.cs b/TVHome/TVHome/Views/MainPanel.xaml.cs index e0306dd..41003c7 100755 --- a/TVHome/TVHome/Views/MainPanel.xaml.cs +++ b/TVHome/TVHome/Views/MainPanel.xaml.cs @@ -20,6 +20,7 @@ using LibTVRefCommonPortable.DataModels; using TVHome.ViewModels; using Xamarin.Forms; using LibTVRefCommonPortable.Utils; +using System; namespace TVHome.Views { @@ -28,18 +29,13 @@ namespace TVHome.Views /// public partial class MainPanel : Panel { - public delegate void FocusEventHandler(HomeMenuItem item); - public delegate void SelectEventHandler(HomeMenuItem item); + public static readonly BindableProperty FocusedItemIndexProperty = BindableProperty.Create("FocusedItemIndex", typeof(int), typeof(MainPanel), default(int), BindingMode.TwoWay); - /// - /// A EventHandler for Item focused event - /// - public FocusEventHandler OnItemFocusedHandler; - - /// - /// A EventHandler for Item selected event - /// - public SelectEventHandler OnItemSelectedHandler; + public int FocusedItemIndex + { + get { return (int)GetValue(FocusedItemIndexProperty); } + set { SetValue(FocusedItemIndexProperty, value); } + } /// /// Main panel icon's width @@ -61,9 +57,10 @@ namespace TVHome.Views /// public MainPanel() { + BindingContext = MainPanelViewModel.Instance; InitializeComponent(); InitializeSize(); - PropertyChanged += OnItemsSourcePropertyChanged; + PropertyChanged += OnPropertyChanged; } private void InitializeSize() @@ -84,39 +81,61 @@ namespace TVHome.Views /// /// The source of the event /// The event that is occurred when property is changed - private void OnItemsSourcePropertyChanged(object sender, PropertyChangedEventArgs e) + private void OnPropertyChanged(object sender, PropertyChangedEventArgs e) { - if (e.PropertyName != "ItemsSource") + if (e.PropertyName == "ItemsSource") { - return; - } - HomeMenuItem menuIndex = HomeMenuItem.Recent; - var index = 1; - PanelButtonGrid.Children.Clear(); - foreach (ShortcutInfo item in ItemsSource) - { - var button = new MainPanelButton(); - button.BindingContext = item; - HomeMenuItem ItemName = menuIndex; - button.OnFocusedCommand = new Command(() => - { - ChangeStatusCommand?.Execute(HomeStatus.MainPanelFocused); - OnItemFocusedHandler?.Invoke(ItemName); - FocusPanel(); - }); - button.OnClickedCommand = new Command(() => - { - OnItemSelectedHandler?.Invoke(ItemName); - //item.DoAction(); - }); - PanelButtonGrid.Children.Add(button, index, 0); + HomeMenuItem menuIndex = HomeMenuItem.Recent; + var index = 0; + PanelButtonGrid.Children.Clear(); - index++; - menuIndex++; + foreach (ShortcutInfo item in ItemsSource) + { + int buttonIndex = index; + var button = new MainPanelButton(); + + button.BindingContext = item; + HomeMenuItem ItemName = menuIndex; + var thisButtonInfo = item as HomeMenuAppShortcutInfo; + button.OnFocusedCommand = new Command(() => + { + DebuggingUtils.Dbg("FocusedItemIndex = " + FocusedItemIndex); + DebuggingUtils.Dbg("New FocusedItemIndex = " + buttonIndex); + // TODO : fix + if (FocusedItemIndex == buttonIndex) + { + FocusedItemIndex = 999; + } + + SelectedItem = item; + FocusedItemIndex = buttonIndex; + + DebuggingUtils.Dbg(ItemName + " focused"); + + foreach (var info in ItemsSource) + { + var homeButtonInfo = info as HomeMenuAppShortcutInfo; + homeButtonInfo.ChangeStatus("default"); + } + + thisButtonInfo.ChangeStatus("focused"); + PanelState = PanelState.Focused; + DebuggingUtils.Dbg("End callback........."); + }); + button.OnClickedCommand = new Command(() => + { + DebuggingUtils.Dbg(ItemName + " clicked"); + thisButtonInfo.ChangeStatus("selected"); + }); + PanelButtonGrid.Children.Add(button, index + 1, 0); + + index++; + menuIndex++; + } + + PanelButtonGrid.ForceLayout(); } - - PanelButtonGrid.ForceLayout(); } /// @@ -124,6 +143,13 @@ namespace TVHome.Views /// public void InitialFocusing() { + DebuggingUtils.Dbg("InitialFocusing"); + if (PanelButtonGrid.Children.Count < 2) + { + DebuggingUtils.Dbg("InitialFocusing, ignored"); + return; + } + var button = PanelButtonGrid.Children[1]; button.FindByName /// A source of event /// The event that is occurred when property is changed - private void OnItemsSourcePropertyChanged(object sender, PropertyChangedEventArgs e) + private void OnPropertyChanged(object sender, PropertyChangedEventArgs e) { - if (e.PropertyName == "ShowNoContentsInfo") - { - if (ShowNoContentsInfo) - { - PanelScrollView.IsVisible = false; - NoContentInfo.IsVisible = true; - HidePanel(); - return; - } - else - { - PanelScrollView.IsVisible = true; - NoContentInfo.IsVisible = false; - } - } - else if (e.PropertyName == "ItemsSource") + if (e.PropertyName == "ItemsSource") { + DebuggingUtils.Dbg("SubThumbnailPanel view OnPropertyChanged, ItemSource "); + + isShowNoContentsInfo = true; PanelButtonStack.Children.Clear(); ButtonList.Clear(); + foreach (RecentShortcutInfo item in ItemsSource) { PanelButton button = new SubPanelThumbnailButton(); button.BindingContext = item; + + button.OnPanelButtonStateChanged += PanelButtonStateEventHandler; button.OnFocusedCommand = new Command(() => { - ChangeStatusCommand?.Execute(HomeStatus.SubPanelFocused); - FocusPanel(); + DebuggingUtils.Dbg("SubThumbnailPanel Focused"); + PanelState = PanelState.Focused; + SelectedItem = item; + if (SizeUtils.GetWidthSize((int)button.X) - SizeUtils.GetWidthSize((int)PanelScrollView.ScrollX) < 0) { ScrollToLeft(); @@ -152,16 +182,20 @@ namespace TVHome.Views }); PanelButtonStack.Children.Add(button); ButtonList.Add(button); + + isShowNoContentsInfo = false; } - if (!isFocused) + SetPanelDisplay(); + + if (PanelState == PanelState.Hide || + PanelState == PanelState.Iconified) { - HidePanel(); + OnPanelHiding(); } else { - isFocused = false; - FocusPanel(); + OnPanelFocusing(); } } } @@ -187,97 +221,89 @@ namespace TVHome.Views } /// - /// A method for getting Panel Buttons - /// - /// A list of panel button views - public IList GetSubPanelButtons() - { - return PanelButtonStack.Children; - } - - /// /// A method for hiding the panel /// - public override void HidePanel() + public override void OnPanelHiding() { - if (NoContentInfo.IsVisible) + if (isShowNoContentsInfo) { TranslationY = 0; Opacity = 0; + return; } - else - { - isFocused = false; - foreach (var item in PanelButtonStack.Children) - { - item.IsEnabled = false; - } - PanelScrollView.ScrollToAsync(0, 0, true); - AnimationExtensions.AbortAnimation(this, "PanelAnimation"); - var currentTranslationY = TranslationY; - var diff = selectTransitionHeight - currentTranslationY; - var currentOpacity = Opacity; - Animation animation = new Animation(); - Animation translateAnimation = new Animation(v => TranslationY = (currentTranslationY + diff * v)); - Animation fadeAnimation = new Animation(v => Opacity = currentOpacity * (1 - v)); - animation.Add(0, 1, translateAnimation); - animation.Add(0, 1, fadeAnimation); - animation.Commit(this, "PanelAnimation", length: 300); + foreach (var item in PanelButtonStack.Children) + { + item.IsEnabled = false; } + + AnimationExtensions.AbortAnimation(this, "PanelAnimation"); + var currentTranslationY = TranslationY; + var diff = selectTransitionHeight - currentTranslationY; + var currentOpacity = Opacity; + Animation animation = new Animation(); + Animation translateAnimation = new Animation(v => TranslationY = (currentTranslationY + diff * v)); + Animation fadeAnimation = new Animation(v => Opacity = currentOpacity * (1 - v)); + animation.Add(0, 1, translateAnimation); + animation.Add(0, 1, fadeAnimation); + animation.Commit(this, "PanelAnimation", length: 300, finished: (percentage, cancel) => + { + PanelScrollView.ScrollToAsync(0, 0, true); + }); } /// /// A method for showing the panel /// - public override void ShowPanel() + public override void OnPanelShowing() { - if (NoContentInfo.IsVisible) + if (isShowNoContentsInfo) { - NoContentInfo.IsEnabled = false; + TranslationY = 0; Opacity = 1; + return; } - else - { - isFocused = false; - foreach (var item in PanelButtonStack.Children) - { - item.IsEnabled = true; - item.FindByName("ThumnailDimLayer").Opacity = 1; - } - AnimationExtensions.AbortAnimation(this, "PanelAnimation"); - var currentTranslationY = TranslationY; - var currentOpacity = Opacity; - var diff = 1 - currentOpacity; - Animation animation = new Animation(); - Animation translateAnimation = new Animation(v => TranslationY = (currentTranslationY * (1 - v))); - Animation fadeAnimation = new Animation(v => Opacity = currentOpacity + diff * v); - animation.Add(0, 1, translateAnimation); - animation.Add(0, 1, fadeAnimation); - animation.Commit(this, "PanelAnimation", length: 300); + foreach (var item in PanelButtonStack.Children) + { + item.IsEnabled = true; + item.FindByName("ThumnailDimLayer").Opacity = 1; } + + AnimationExtensions.AbortAnimation(this, "PanelAnimation"); + var currentTranslationY = TranslationY; + var currentOpacity = Opacity; + var diff = 1 - currentOpacity; + Animation animation = new Animation(); + Animation translateAnimation = new Animation(v => TranslationY = (currentTranslationY * (1 - v))); + Animation fadeAnimation = new Animation(v => Opacity = currentOpacity + diff * v); + animation.Add(0, 1, translateAnimation); + animation.Add(0, 1, fadeAnimation); + animation.Commit(this, "PanelAnimation", length: 300); + } /// /// A method for handling panel focused event /// - public override void FocusPanel() + /// If this flag is true, the first item should be focused. + public override void OnPanelFocusing(bool shouldBeFirstItemFocused = true) { - if (isFocused || ShowNoContentsInfo) + if (isShowNoContentsInfo) { return; } - isFocused = true; - foreach (var item in PanelButtonStack.Children) { item.FindByName("ThumnailDimLayer").Opacity = 0; } - var button = PanelButtonStack.Children[0]; - button.FindByName