protected void UpdateFiltersList() { _filterItemsList.Clear(); NavigationData navigationData = GetCurrentNavigationData(); IList <WorkflowAction> actions = navigationData.GetWorkflowActions(); if (actions == null) { return; } string currentScreenTitle = LocalizationHelper.CreateResourceString(navigationData.CurrentScreenData?.MenuItemLabel)?.Evaluate(); foreach (WorkflowAction action in actions) { WorkflowAction actionCopy = action; ListItem screenItem = new ListItem(Consts.KEY_NAME, action.DisplayTitle) { Command = new MethodDelegateCommand(actionCopy.Execute), Selected = currentScreenTitle == action.DisplayTitle?.Evaluate() }; screenItem.AdditionalProperties[Consts.KEY_FILTER] = actionCopy; _filterItemsList.Add(screenItem); } _filterItemsList.FireChange(); }
/// <summary> /// Enters a new media navigation context by inheriting all currently available screens. This is used for /// presenting the contents of a media items or filter group, where the current menu should remain available. /// Only the currently visible screen can be exchanged to configure another presentation mode for the group to /// be stepped-in. /// </summary> /// <remarks> /// Actually, we mix two different concerns in this method: /// <list type="number"> /// <item>The setting that the new navigation context will be subordinated, i.e. it will be removed/exchanged by a filter action</item> /// <item>The setting that all menu actions will be adopted from the parent navigation context</item> /// </list> /// But in fact, filter actions are only used together with the concept that there exist two different kind of navigation contexts; /// autonomous contexts and subordinated contexts. /// If there are no filter actions present (like in the browse media navigation modes), the only difference between the methods /// <see cref="StackSubordinateNavigationContext"/> and <see cref="StackAutonomousNavigationContext"/> is the inheritance of the menu. /// </remarks> /// <param name="subViewSpecification">Specification for the sub view to be shown in the new navigation context.</param> /// <param name="visibleScreen">Screen which should be visible in the new navigation context.</param> /// <param name="navbarDisplayLabel">Display label to be shown in the navigation bar for the new navigation context.</param> /// <returns>Newly created navigation data.</returns> public NavigationData StackSubordinateNavigationContext(ViewSpecification subViewSpecification, AbstractScreenData visibleScreen, string navbarDisplayLabel) { WorkflowState newState = WorkflowState.CreateTransientState( "View: " + subViewSpecification.ViewDisplayName, subViewSpecification.ViewDisplayName, false, null, true, WorkflowType.Workflow); ScreenConfig nextScreenConfig; LoadLayoutSettings(visibleScreen.ToString(), out nextScreenConfig); Sorting.Sorting nextSortingMode = AvailableSortings.FirstOrDefault( sorting => sorting.GetType().ToString() == nextScreenConfig.Sorting && sorting.IsAvailable(visibleScreen)) ?? _currentSorting; Sorting.Sorting nextGroupingMode = string.IsNullOrEmpty(nextScreenConfig.Grouping) ? null : AvailableGroupings.FirstOrDefault( grouping => grouping.GetType().ToString() == nextScreenConfig.Grouping && grouping.IsAvailable(visibleScreen)) ?? _currentGrouping; NavigationData newNavigationData = new NavigationData(this, subViewSpecification.ViewDisplayName, _baseWorkflowStateId, newState.StateId, subViewSpecification, visibleScreen, _availableScreens, nextSortingMode, nextGroupingMode, true) { LayoutType = nextScreenConfig.LayoutType, LayoutSize = nextScreenConfig.LayoutSize }; PushNewNavigationWorkflowState(newState, navbarDisplayLabel, newNavigationData); return(newNavigationData); }
public void ExitModelContext(NavigationContext oldContext, NavigationContext newContext) { NavigationData navigationData = GetNavigationData(oldContext, false); navigationData.Dispose(); ReleaseModelData(); }
protected void UpdateGroupingsList() { _groupingItemsList.Clear(); NavigationData navigationData = GetCurrentNavigationData(); ICollection <Sorting.Sorting> groupings = navigationData.AvailableGroupings; if (groupings == null) { return; } ListItem groupingItem = new ListItem(Consts.KEY_NAME, Consts.RES_NO_GROUPING) { Command = new MethodDelegateCommand(() => navigationData.CurrentGrouping = null), Selected = navigationData.CurrentGrouping == null }; groupingItem.AdditionalProperties[Consts.KEY_GROUPING] = null; _groupingItemsList.Add(groupingItem); foreach (Sorting.Sorting grouping in groupings.Where(g => g.IsAvailable(navigationData.CurrentScreenData))) { Sorting.Sorting groupingCopy = grouping; groupingItem = new ListItem(Consts.KEY_NAME, grouping.GroupByDisplayName) { Command = new MethodDelegateCommand(() => navigationData.CurrentGrouping = groupingCopy), Selected = navigationData.CurrentGrouping == groupingCopy }; groupingItem.AdditionalProperties[Consts.KEY_GROUPING] = groupingCopy; _groupingItemsList.Add(groupingItem); } _groupingItemsList.FireChange(); }
public void EnterModelContext(NavigationContext oldContext, NavigationContext newContext) { PrepareState(newContext); NavigationData navigationData = GetNavigationData(newContext, false); navigationData.Enable(); }
protected void AddCurrentViewToPlaylistInternal() { NavigationData navigationData = NavigationData; if (navigationData == null || !navigationData.IsEnabled) { ServiceRegistration.Get <ILogger>().Error("MediaNavigationModel: Cannot add current view to playlist - There is no enabled navigation data available"); } string mode = Mode; switch (mode) { case MediaNavigationMode.Audio: PlayItemsModel.CheckQueryPlayAction(GetMediaItemsFromCurrentView, AVType.Audio); break; case MediaNavigationMode.Movies: case MediaNavigationMode.Series: case MediaNavigationMode.Videos: case MediaNavigationMode.Images: PlayItemsModel.CheckQueryPlayAction(GetMediaItemsFromCurrentView, AVType.Video); break; case MediaNavigationMode.BrowseLocalMedia: case MediaNavigationMode.BrowseMediaLibrary: PlayItemsModel.CheckQueryPlayAction(GetMediaItemsFromCurrentView); break; } }
/// <summary> /// Creates a new navigation data structure for a new media navigation step. /// </summary> /// <param name="parent">Parent navigation data, this navigation data is derived from.</param> /// <param name="navigationContextName">Name, which is used for the corresponding workflow navigation context.</param> /// <param name="currentWorkflowStateId">Id of the workflow state which corresponds to the new media navigation step.</param> /// <param name="parentWorkflowStateId">Id of the workflow state to which the workflow navigation should be reverted when /// another filter is choosen.</param> /// <param name="baseViewSpecification">View specification for the media items of the new media navigation step.</param> /// <param name="defaultScreen">Screen which should present the new navigation step by default.</param> /// <param name="availableScreens">Available set of screen descriptions which can present the new media navigation step.</param> /// <param name="currentSorting">Denotes the current sorting for the items to be shown. If this is set to <c>null</c>, /// default sorting will be applied.</param> /// <param name="currentGrouping">Denotes the current grouping for the items to be shown.</param> public NavigationData(NavigationData parent, string navigationContextName, Guid parentWorkflowStateId, Guid currentWorkflowStateId, ViewSpecification baseViewSpecification, AbstractScreenData defaultScreen, ICollection <AbstractScreenData> availableScreens, Sorting.Sorting currentSorting, Sorting.Sorting currentGrouping) : this(parent, navigationContextName, parentWorkflowStateId, currentWorkflowStateId, baseViewSpecification, defaultScreen, availableScreens, currentSorting, currentGrouping, false) { }
protected void AddCurrentViewToPlaylistInternal(MediaItem selectedMediaItem) { NavigationData navigationData = NavigationData; if (navigationData == null || !navigationData.IsEnabled) { ServiceRegistration.Get <ILogger>().Error("MediaNavigationModel: Cannot add current view to playlist - There is no enabled navigation data available"); } AddMediaItemstoPlaylist(() => GetMediaItemsFromCurrentView(selectedMediaItem)); }
protected void SetGrouping(Sorting.Sorting grouping) { NavigationData navigationData = GetCurrentNavigationData(); if (navigationData == null) { return; } navigationData.CurrentGrouping = grouping; }
/// <summary> /// Enters a new media navigation context by inheriting all currently available screens. This is used for /// presenting the contents of a media items or filter group, where the current menu should remain available. /// Only the currently visible screen can be exchanged to configure another presentation mode for the group to /// be stepped-in. /// </summary> /// <remarks> /// Actually, we mix two different concerns in this method: /// <list type="number"> /// <item>The setting that the new navigation context will be subordinated, i.e. it will be removed/exchanged by a filter action</item> /// <item>The setting that all menu actions will be adopted from the parent navigation context</item> /// </list> /// But in fact, filter actions are only used together with the concept that there exist two different kind of navigation contexts; /// autonomous contexts and subordinated contexts. /// If there are no filter actions present (like in the browse media navigation modes), the only difference between the methods /// <see cref="StackSubordinateNavigationContext"/> and <see cref="StackAutonomousNavigationContext"/> is the inheritance of the menu. /// </remarks> /// <param name="subViewSpecification">Specification for the sub view to be shown in the new navigation context.</param> /// <param name="visibleScreen">Screen which should be visible in the new navigation context.</param> /// <param name="navbarDisplayLabel">Display label to be shown in the navigation bar for the new navigation context.</param> /// <returns>Newly created navigation data.</returns> public NavigationData StackSubordinateNavigationContext(ViewSpecification subViewSpecification, AbstractScreenData visibleScreen, string navbarDisplayLabel) { WorkflowState newState = WorkflowState.CreateTransientState( "View: " + subViewSpecification.ViewDisplayName, subViewSpecification.ViewDisplayName, false, null, true, WorkflowType.Workflow); NavigationData newNavigationData = new NavigationData(this, subViewSpecification.ViewDisplayName, _baseWorkflowStateId, newState.StateId, subViewSpecification, visibleScreen, _availableScreens, _currentSorting, true); PushNewNavigationWorkflowState(newState, navbarDisplayLabel, newNavigationData); return(newNavigationData); }
protected IEnumerable <MediaItem> GetMediaItemsFromCurrentView() { NavigationData navigationData = NavigationData; if (navigationData == null) { yield break; } foreach (MediaItem mediaItem in navigationData.CurrentScreenData.GetAllMediaItems()) { yield return(mediaItem); } }
public void Update() { MediaNavigationModel model = MediaNavigationModel.GetCurrentInstance(); NavigationData navigationData = model.NavigationData; if (navigationData == null) { return; } LayoutType = navigationData.LayoutType; LayoutSize = navigationData.LayoutSize; }
/// <summary> /// Enters a new media navigation context by modifying the list of available screens. This is used for /// presenting the result of a filter, where the menu must be changed. /// </summary> /// <param name="subViewSpecification">Specification for the sub view to be shown in the new navigation context.</param> /// <param name="remainingScreens">New collection of remaining available screens.</param> /// <param name="navbarDisplayLabel">Display label to be shown in the navigation bar for the new navigation context.</param> /// <returns>Newly created navigation data.</returns> public NavigationData StackAutonomousNavigationContext(ViewSpecification subViewSpecification, ICollection <AbstractScreenData> remainingScreens, string navbarDisplayLabel) { WorkflowState newState = WorkflowState.CreateTransientState( "View: " + subViewSpecification.ViewDisplayName, subViewSpecification.ViewDisplayName, false, null, false, WorkflowType.Workflow); NavigationData newNavigationData = new NavigationData(this, subViewSpecification.ViewDisplayName, newState.StateId, newState.StateId, subViewSpecification, remainingScreens.FirstOrDefault(), remainingScreens, _currentSorting); PushNewNavigationWorkflowState(newState, navbarDisplayLabel, newNavigationData); return(newNavigationData); }
public void InitMediaNavigation(out string mediaNavigationMode, out NavigationData navigationData) { IEnumerable<Guid> skinDependentOptionalMIATypeIDs = MediaNavigationModel.GetMediaSkinOptionalMIATypes(MediaNavigationMode); AbstractItemsScreenData.PlayableItemCreatorDelegate picd = mi => new VideoItem(mi) { Command = new MethodDelegateCommand(() => PlayItemsModel.CheckQueryPlayAction(mi)) }; ViewSpecification rootViewSpecification = new MediaLibraryQueryViewSpecification(SlimTvConsts.RES_RECORDINGS_VIEW_NAME, null, SlimTvConsts.NECESSARY_RECORDING_MIAS, skinDependentOptionalMIATypeIDs, true) { MaxNumItems = Consts.MAX_NUM_ITEMS_VISIBLE }; AbstractScreenData defaultScreen = new RecordingFilterByNameScreenData(); ICollection<AbstractScreenData> availableScreens = new List<AbstractScreenData> { // C# doesn't like it to have an assignment inside a collection initializer defaultScreen, new VideosShowItemsScreenData(picd), new RecordingsFilterByChannelScreenData(), new VideosFilterByActorScreenData(), new VideosFilterByDirectorScreenData(), new VideosFilterByWriterScreenData(), new VideosFilterByGenreScreenData(), new VideosFilterByYearScreenData(), new VideosFilterBySystemScreenData(), new VideosSimpleSearchScreenData(picd), }; Sorting defaultSorting = new SortByRecordingDateDesc(); ICollection<Sorting> availableSortings = new List<Sorting> { defaultSorting, new SortByTitle(), new VideoSortByFirstGenre(), new VideoSortByDuration(), new VideoSortByFirstActor(), new VideoSortByFirstDirector(), new VideoSortByFirstWriter(), new VideoSortBySize(), new VideoSortByAspectRatio(), new SortBySystem(), }; navigationData = new NavigationData(null, Consts.RES_MOVIES_VIEW_NAME, MediaNavigationRootState, MediaNavigationRootState, rootViewSpecification, defaultScreen, availableScreens, defaultSorting) { AvailableSortings = availableSortings }; mediaNavigationMode = MediaNavigationMode; }
protected void SetViewMode(LayoutType layoutType, LayoutSize layoutSize) { LayoutType = layoutType; LayoutSize = layoutSize; MediaNavigationModel model = MediaNavigationModel.GetCurrentInstance(); NavigationData navigationData = model.NavigationData; if (navigationData == null) { return; } navigationData.LayoutType = layoutType; navigationData.LayoutSize = layoutSize; }
/// <summary> /// Adds the current view to the playlist of the current player. /// </summary> /// <remarks> /// This action can be called from outside when there is an enabled navigation data present (<see cref="IsNavigationDataEnabled"/>. /// </remarks> public static void AddCurrentViewToPlaylist() { MediaNavigationModel model = GetCurrentInstance(); NavigationData navigationData = model.NavigationData; if (navigationData == null || !navigationData.IsEnabled) { ServiceRegistration.Get <ILogger>().Error("MediaNavigationModel.AddCurrentViewToPlaylist: No enabled navigation data present"); return; } if (navigationData.CurrentScreenData.IsItemsEmpty) { ServiceRegistration.Get <IDialogManager>().ShowDialog(Consts.RES_NO_ITEMS_TO_ADD_HEADER, Consts.RES_NO_ITEMS_TO_ADD_TEXT, DialogType.OkDialog, false, DialogButtonType.Ok); return; } model.AddCurrentViewToPlaylistInternal(); }
public void ChangeModelContext(NavigationContext oldContext, NavigationContext newContext, bool push) { PrepareState(newContext); if (push) { NavigationData navigationData = GetNavigationData(oldContext, false); navigationData.Disable(); navigationData = GetNavigationData(newContext, false); navigationData.Enable(); } else { NavigationData navigationData = GetNavigationData(oldContext, false); navigationData.Dispose(); navigationData = GetNavigationData(newContext, false); navigationData.Enable(); } }
/// <summary> /// Prepares the given workflow navigation <paramref name="context"/>, i.e. prepares the view data and the /// available filter criteria to be used in the menu. /// </summary> protected void PrepareState(NavigationContext context) { _currentNavigationContext = context; NavigationData navigationData = GetNavigationData(context, false); if (navigationData != null) { return; } // Initialize root media navigation state. We will set up all sub processes for each media model "part", i.e. // audio, videos, images, browse local media and browse media library. IDictionary <string, object> contextVariables = PrepareRootState(context.WorkflowState.StateId); foreach (KeyValuePair <string, object> variable in contextVariables) { context.SetContextVariable(variable.Key, variable.Value); } }
/// <summary> /// Enters a new media navigation context by modifying the list of available screens. This is used for /// presenting the result of a filter, where the menu must be changed. /// </summary> /// <param name="subViewSpecification">Specification for the sub view to be shown in the new navigation context.</param> /// <param name="currentMenuItemLabel">Current menu item label needed for distinction of available screens.</param> /// <param name="navbarDisplayLabel">Display label to be shown in the navigation bar for the new navigation context.</param> /// <returns>Newly created navigation data.</returns> public NavigationData StackAutonomousNavigationContext(ViewSpecification subViewSpecification, string currentMenuItemLabel, string navbarDisplayLabel) { AbstractScreenData currentScreen = AvailableScreens.FirstOrDefault(screen => screen.MenuItemLabel == currentMenuItemLabel); ICollection <AbstractScreenData> remainingScreens = new List <AbstractScreenData>(AvailableScreens.Where(screen => screen != currentScreen)); WorkflowState newState = WorkflowState.CreateTransientState( "View: " + subViewSpecification.ViewDisplayName, subViewSpecification.ViewDisplayName, false, null, false, WorkflowType.Workflow, null); string nextScreenName; AbstractScreenData nextScreen = null; // Try to load the prefered next screen from settings. if (LoadScreenHierarchy(CurrentScreenData.GetType().ToString(), out nextScreenName)) { nextScreen = remainingScreens.FirstOrDefault(s => s.GetType().ToString() == nextScreenName); } // Default way: always take the first of the available screens. if (nextScreen == null) { nextScreen = remainingScreens.First(s => s != currentScreen); } ScreenConfig nextScreenConfig; LoadLayoutSettings(nextScreen.GetType().ToString(), out nextScreenConfig); Sorting.Sorting nextSortingMode = AvailableSortings.FirstOrDefault( sorting => sorting.GetType().ToString() == nextScreenConfig.Sorting && sorting.IsAvailable(nextScreen)) ?? _currentSorting; Sorting.Sorting nextGroupingMode = String.IsNullOrEmpty(nextScreenConfig.Grouping) ? null : AvailableGroupings.FirstOrDefault( grouping => grouping.GetType().ToString() == nextScreenConfig.Grouping && grouping.IsAvailable(nextScreen)) ?? _currentGrouping; NavigationData newNavigationData = new NavigationData(this, subViewSpecification.ViewDisplayName, newState.StateId, newState.StateId, subViewSpecification, nextScreen, remainingScreens, nextSortingMode, nextGroupingMode) { LayoutType = nextScreenConfig.LayoutType, LayoutSize = nextScreenConfig.LayoutSize }; PushNewNavigationWorkflowState(newState, navbarDisplayLabel, newNavigationData); return(newNavigationData); }
// If the suppressActions parameter is set to <c>true</c>, no actions will be built. Instead, they will be inherited from // the parent navigation step. That is used for subview navigation where the navigation step doesn't produce own // workflow actions. protected NavigationData(NavigationData parent, string navigationContextName, Guid parentWorkflowStateId, Guid currentWorkflowStateId, ViewSpecification baseViewSpecification, AbstractScreenData defaultScreen, ICollection <AbstractScreenData> availableScreens, Sorting.Sorting currentSorting, bool suppressActions) { _parent = parent; _navigationContextName = navigationContextName; _currentWorkflowStateId = currentWorkflowStateId; _baseWorkflowStateId = parentWorkflowStateId; _baseViewSpecification = baseViewSpecification; _currentScreenData = defaultScreen; _availableScreens = availableScreens ?? new List <AbstractScreenData>(); _currentSorting = currentSorting; if (suppressActions) { _dynamicWorkflowActions = null; } else { BuildWorkflowActions(); } }
protected void UpdateSortingsList() { _sortingItemsList.Clear(); NavigationData navigationData = GetCurrentNavigationData(); ICollection <Sorting.Sorting> sortings = navigationData.AvailableSortings; if (sortings == null) { return; } foreach (Sorting.Sorting sorting in sortings) { Sorting.Sorting sortingCopy = sorting; ListItem sortingItem = new ListItem(Consts.KEY_NAME, sorting.DisplayName) { Command = new MethodDelegateCommand(() => navigationData.CurrentSorting = sortingCopy) }; sortingItem.AdditionalProperties[Consts.KEY_SORTING] = sortingCopy; _sortingItemsList.Add(sortingItem); } _sortingItemsList.FireChange(); }
protected void UpdateFiltersList() { _filterItemsList.Clear(); NavigationData navigationData = GetCurrentNavigationData(); IList <WorkflowAction> actions = navigationData.GetWorkflowActions(); if (actions == null) { return; } foreach (WorkflowAction action in actions) { WorkflowAction actionCopy = action; ListItem screenItem = new ListItem(Consts.KEY_NAME, action.DisplayTitle) { Command = new MethodDelegateCommand(actionCopy.Execute) }; screenItem.AdditionalProperties[Consts.KEY_FILTER] = actionCopy; _filterItemsList.Add(screenItem); } _filterItemsList.FireChange(); }
public void ChangeModelContext(NavigationContext oldContext, NavigationContext newContext, bool push) { PrepareState(newContext); if (push) { NavigationData navigationData = GetNavigationData(oldContext, false); navigationData.Disable(); SaveUIState(oldContext); navigationData = GetNavigationData(newContext, false); navigationData.Enable(); if (navigationData.CurrentScreenData.SkipForSingleItem && navigationData.CurrentScreenData.Items.Count == 1) { var command = navigationData.CurrentScreenData.Items.FirstOrDefault()?.Command; if (command != null) { newContext.SetContextVariable(WorkflowManager.KEY_NAVIGATION_SKIP_ACTION, command); } } } else { NavigationData navigationData = GetNavigationData(oldContext, false); navigationData.Dispose(); navigationData = GetNavigationData(newContext, false); navigationData.Enable(); if (navigationData.CurrentScreenData.SkipForSingleItem && navigationData.CurrentScreenData.Items.Count == 1) { newContext.SetContextVariable(WorkflowManager.KEY_NAVIGATION_SKIP_ACTION, new MethodDelegateCommand(() => { var wfManager = ServiceRegistration.Get <IWorkflowManager>(false); wfManager?.NavigatePop(1); })); } } }
protected static void SetNavigationData(NavigationData navigationData, NavigationContext navigationContext) { navigationContext.SetContextVariable(Consts.KEY_NAVIGATION_DATA, navigationData); }
/// <summary> /// Returns context variables to be set for the given workflow state id. /// </summary> /// <param name="workflowStateId">Workflow state which determines the root media navigation state.</param> /// <returns>Mapping of context variable keys to values.</returns> protected static IDictionary<string, object> PrepareRootState(Guid workflowStateId) { IDictionary<string, object> result = new Dictionary<string, object>(); // The initial state ID determines the media model "part" to initialize: Browse local media, browse media library, audio, videos or images. // The media model part determines the media navigation mode and the view contents to be set. NavigationData navigationData; string mode; if (_initializers.ContainsKey(workflowStateId)) { // Use the IMediaNavigationInitializer that is associated with our root workflow state. IMediaNavigationInitializer initializer = _initializers[workflowStateId]; initializer.InitMediaNavigation(out mode, out navigationData); } else { // If we were called with a supported root state, we should be either in state WF_STATE_ID_LOCAL_MEDIA_NAVIGATION_ROOT // or WF_STATE_ID_MEDIA_BROWSE_NAVIGATION_ROOT here if (workflowStateId != Consts.WF_STATE_ID_LOCAL_MEDIA_NAVIGATION_ROOT && workflowStateId != Consts.WF_STATE_ID_BROWSE_MEDIA_NAVIGATION_ROOT) { // Error case: We cannot handle the given state ServiceRegistration.Get<ILogger>().Warn("MediaNavigationModel: Unknown root workflow state with ID '{0}', initializing local media navigation", workflowStateId); // We simply use the local media mode as fallback for this case, so we go on workflowStateId = Consts.WF_STATE_ID_LOCAL_MEDIA_NAVIGATION_ROOT; } mode = workflowStateId == Consts.WF_STATE_ID_LOCAL_MEDIA_NAVIGATION_ROOT ? MediaNavigationMode.BrowseLocalMedia : MediaNavigationMode.BrowseMediaLibrary; IEnumerable<Guid> skinDependentOptionalMIATypeIDs = GetMediaSkinOptionalMIATypes(mode); AbstractItemsScreenData.PlayableItemCreatorDelegate picd = mi => { if (mi.Aspects.ContainsKey(AudioAspect.ASPECT_ID)) return new AudioItem(mi) { Command = new MethodDelegateCommand(() => PlayItemsModel.CheckQueryPlayAction(mi)) }; if (mi.Aspects.ContainsKey(VideoAspect.ASPECT_ID)) return new VideoItem(mi) { Command = new MethodDelegateCommand(() => PlayItemsModel.CheckQueryPlayAction(mi)) }; if (mi.Aspects.ContainsKey(ImageAspect.ASPECT_ID)) return new ImageItem(mi) { Command = new MethodDelegateCommand(() => PlayItemsModel.CheckQueryPlayAction(mi)) }; return null; }; IEnumerable<Guid> necessaryMIATypeIDs = new Guid[] { ProviderResourceAspect.ASPECT_ID, MediaAspect.ASPECT_ID, }; IEnumerable<Guid> optionalMIATypeIDs = new Guid[] { AudioAspect.ASPECT_ID, VideoAspect.ASPECT_ID, ImageAspect.ASPECT_ID, }.Union(skinDependentOptionalMIATypeIDs); string viewName = workflowStateId == Consts.WF_STATE_ID_LOCAL_MEDIA_NAVIGATION_ROOT ? Consts.RES_LOCAL_MEDIA_ROOT_VIEW_NAME : Consts.RES_BROWSE_MEDIA_ROOT_VIEW_NAME; ViewSpecification rootViewSpecification = workflowStateId == Consts.WF_STATE_ID_LOCAL_MEDIA_NAVIGATION_ROOT ? new AddedRemovableMediaViewSpecificationFacade(new LocalMediaRootProxyViewSpecification(viewName, necessaryMIATypeIDs, optionalMIATypeIDs)) : new AddedRemovableMediaViewSpecificationFacade(new BrowseMediaRootProxyViewSpecification(viewName, necessaryMIATypeIDs, optionalMIATypeIDs)); // Dynamic screens remain null - browse media states don't provide dynamic filters AbstractScreenData screenData = workflowStateId == Consts.WF_STATE_ID_LOCAL_MEDIA_NAVIGATION_ROOT ? (AbstractScreenData) new LocalMediaNavigationScreenData(picd) : new BrowseMediaNavigationScreenData(picd); Sorting.Sorting browseDefaultSorting = new BrowseDefaultSorting(); ICollection<Sorting.Sorting> availableSortings = new List<Sorting.Sorting> { browseDefaultSorting, new SortByTitle(), new SortByDate(), // We could offer sortings here which are specific for one media item type but which will cope with all three item types (and sort items of the three types in a defined order) }; navigationData = new NavigationData(null, viewName, workflowStateId, workflowStateId, rootViewSpecification, screenData, null, browseDefaultSorting) { AvailableSortings = availableSortings }; } result.Add(Consts.KEY_NAVIGATION_MODE, mode); result.Add(Consts.KEY_NAVIGATION_DATA, navigationData); return result; }
/// <summary> /// Returns context variables to be set for the given workflow state id. /// </summary> /// <param name="workflowStateId">Workflow state which determines the root media navigation state.</param> /// <returns>Mapping of context variable keys to values.</returns> protected static IDictionary <string, object> PrepareRootState(Guid workflowStateId) { IDictionary <string, object> result = new Dictionary <string, object>(); // The initial state ID determines the media model "part" to initialize: Browse local media, browse media library, audio, videos or images. // The media model part determines the media navigation mode and the view contents to be set. NavigationData navigationData; string mode; if (_initializers.ContainsKey(workflowStateId)) { // Use the IMediaNavigationInitializer that is associated with our root workflow state. IMediaNavigationInitializer initializer = _initializers[workflowStateId]; initializer.InitMediaNavigation(out mode, out navigationData); } else { // If we were called with a supported root state, we should be either in state WF_STATE_ID_LOCAL_MEDIA_NAVIGATION_ROOT // or WF_STATE_ID_MEDIA_BROWSE_NAVIGATION_ROOT here if (workflowStateId != Consts.WF_STATE_ID_LOCAL_MEDIA_NAVIGATION_ROOT && workflowStateId != Consts.WF_STATE_ID_BROWSE_MEDIA_NAVIGATION_ROOT) { // Error case: We cannot handle the given state ServiceRegistration.Get <ILogger>().Warn("MediaNavigationModel: Unknown root workflow state with ID '{0}', initializing local media navigation", workflowStateId); // We simply use the local media mode as fallback for this case, so we go on workflowStateId = Consts.WF_STATE_ID_LOCAL_MEDIA_NAVIGATION_ROOT; } mode = workflowStateId == Consts.WF_STATE_ID_LOCAL_MEDIA_NAVIGATION_ROOT ? MediaNavigationMode.BrowseLocalMedia : MediaNavigationMode.BrowseMediaLibrary; IEnumerable <Guid> skinDependentOptionalMIATypeIDs = GetMediaSkinOptionalMIATypes(mode); AbstractItemsScreenData.PlayableItemCreatorDelegate picd = mi => { if (mi.Aspects.ContainsKey(AudioAspect.ASPECT_ID)) { return new AudioItem(mi) { Command = new MethodDelegateCommand(() => PlayItemsModel.CheckQueryPlayAction(mi)) } } ; if (mi.Aspects.ContainsKey(VideoAspect.ASPECT_ID)) { return new VideoItem(mi) { Command = new MethodDelegateCommand(() => PlayItemsModel.CheckQueryPlayAction(mi)) } } ; if (mi.Aspects.ContainsKey(ImageAspect.ASPECT_ID)) { return new ImageItem(mi) { Command = new MethodDelegateCommand(() => PlayItemsModel.CheckQueryPlayAction(mi)) } } ; return(null); }; IEnumerable <Guid> necessaryMIATypeIDs = new Guid[] { ProviderResourceAspect.ASPECT_ID, MediaAspect.ASPECT_ID, }; IEnumerable <Guid> optionalMIATypeIDs = new Guid[] { AudioAspect.ASPECT_ID, VideoAspect.ASPECT_ID, ImageAspect.ASPECT_ID, }.Union(skinDependentOptionalMIATypeIDs); string viewName = workflowStateId == Consts.WF_STATE_ID_LOCAL_MEDIA_NAVIGATION_ROOT ? Consts.RES_LOCAL_MEDIA_ROOT_VIEW_NAME : Consts.RES_BROWSE_MEDIA_ROOT_VIEW_NAME; ViewSpecification rootViewSpecification = workflowStateId == Consts.WF_STATE_ID_LOCAL_MEDIA_NAVIGATION_ROOT ? new AddedRemovableMediaViewSpecificationFacade(new LocalMediaRootProxyViewSpecification(viewName, necessaryMIATypeIDs, optionalMIATypeIDs)) : new AddedRemovableMediaViewSpecificationFacade(new BrowseMediaRootProxyViewSpecification(viewName, necessaryMIATypeIDs, optionalMIATypeIDs)); // Dynamic screens remain null - browse media states don't provide dynamic filters AbstractScreenData screenData = workflowStateId == Consts.WF_STATE_ID_LOCAL_MEDIA_NAVIGATION_ROOT ? (AbstractScreenData) new LocalMediaNavigationScreenData(picd) : new BrowseMediaNavigationScreenData(picd); Sorting.Sorting browseDefaultSorting = new BrowseDefaultSorting(); ICollection <Sorting.Sorting> availableSortings = new List <Sorting.Sorting> { browseDefaultSorting, new SortByTitle(), new SortByDate(), // We could offer sortings here which are specific for one media item type but which will cope with all three item types (and sort items of the three types in a defined order) }; navigationData = new NavigationData(null, viewName, workflowStateId, workflowStateId, rootViewSpecification, screenData, null, browseDefaultSorting) { AvailableSortings = availableSortings }; } result.Add(Consts.KEY_NAVIGATION_MODE, mode); result.Add(Consts.KEY_NAVIGATION_DATA, navigationData); return(result); }
/// <summary> /// Returns context variables to be set for the given workflow state id. /// </summary> /// <param name="workflowStateId">Workflow state which determines the root media navigation state.</param> /// <returns>Mapping of context variable keys to values.</returns> protected static IDictionary <string, object> PrepareRootState(Guid workflowStateId) { IDictionary <string, object> result = new Dictionary <string, object>(); // The initial state ID determines the media model "part" to initialize: Browse local media, browse media library, audio, videos or images. // The media model part determines the media navigation mode and the view contents to be set. NavigationData navigationData; MediaNavigationMode mode; if (workflowStateId == Consts.WF_STATE_ID_AUDIO_NAVIGATION_ROOT) { mode = MediaNavigationMode.Audio; IEnumerable <Guid> skinDependentOptionalMIATypeIDs = GetMediaSkinOptionalMIATypes(mode); AbstractItemsScreenData.PlayableItemCreatorDelegate picd = mi => new AudioItem(mi) { Command = new MethodDelegateCommand(() => PlayItemsModel.CheckQueryPlayAction(mi)) }; ViewSpecification rootViewSpecification = new MediaLibraryQueryViewSpecification(Consts.RES_AUDIO_VIEW_NAME, null, Consts.NECESSARY_AUDIO_MIAS, skinDependentOptionalMIATypeIDs, true) { MaxNumItems = Consts.MAX_NUM_ITEMS_VISIBLE }; AbstractScreenData filterByAlbum = new AudioFilterByAlbumScreenData(); ICollection <AbstractScreenData> availableScreens = new List <AbstractScreenData> { new AudioShowItemsScreenData(picd), new AudioFilterByArtistScreenData(), filterByAlbum, // C# doesn't like it to have an assignment inside a collection initializer new AudioFilterByGenreScreenData(), new AudioFilterByDecadeScreenData(), new AudioFilterBySystemScreenData(), new AudioSimpleSearchScreenData(picd), }; Sorting.Sorting sortByAlbumTrack = new AudioSortByAlbumTrack(); ICollection <Sorting.Sorting> availableSortings = new List <Sorting.Sorting> { sortByAlbumTrack, new SortByTitle(), new AudioSortByFirstGenre(), new AudioSortByFirstArtist(), new AudioSortByAlbum(), new AudioSortByTrack(), new SortByYear(), new SortBySystem(), }; navigationData = new NavigationData(null, Consts.RES_AUDIO_VIEW_NAME, workflowStateId, workflowStateId, rootViewSpecification, filterByAlbum, availableScreens, sortByAlbumTrack) { AvailableSortings = availableSortings }; } else if (workflowStateId == Consts.WF_STATE_ID_VIDEOS_NAVIGATION_ROOT) { mode = MediaNavigationMode.Videos; IEnumerable <Guid> skinDependentOptionalMIATypeIDs = GetMediaSkinOptionalMIATypes(mode); AbstractItemsScreenData.PlayableItemCreatorDelegate picd = mi => new VideoItem(mi) { Command = new MethodDelegateCommand(() => PlayItemsModel.CheckQueryPlayAction(mi)) }; ViewSpecification rootViewSpecification = new MediaLibraryQueryViewSpecification(Consts.RES_VIDEOS_VIEW_NAME, null, Consts.NECESSARY_VIDEO_MIAS, skinDependentOptionalMIATypeIDs, true) { MaxNumItems = Consts.MAX_NUM_ITEMS_VISIBLE }; AbstractScreenData filterByGenre = new VideosFilterByGenreScreenData(); ICollection <AbstractScreenData> availableScreens = new List <AbstractScreenData> { new VideosShowItemsScreenData(picd), new VideosFilterByLanguageScreenData(), new VideosFilterByActorScreenData(), filterByGenre, // C# doesn't like it to have an assignment inside a collection initializer new VideosFilterByYearScreenData(), new VideosFilterBySystemScreenData(), new VideosSimpleSearchScreenData(picd), }; Sorting.Sorting sortByTitle = new SortByTitle(); ICollection <Sorting.Sorting> availableSortings = new List <Sorting.Sorting> { sortByTitle, new SortByYear(), new VideoSortByFirstGenre(), new VideoSortByDuration(), new VideoSortByDirector(), new VideoSortByFirstActor(), new VideoSortBySize(), new VideoSortByAspectRatio(), new SortBySystem(), }; navigationData = new NavigationData(null, Consts.RES_VIDEOS_VIEW_NAME, workflowStateId, workflowStateId, rootViewSpecification, filterByGenre, availableScreens, sortByTitle) { AvailableSortings = availableSortings }; } else if (workflowStateId == Consts.WF_STATE_ID_SERIES_NAVIGATION_ROOT) { mode = MediaNavigationMode.Videos; IEnumerable <Guid> skinDependentOptionalMIATypeIDs = GetMediaSkinOptionalMIATypes(mode); AbstractItemsScreenData.PlayableItemCreatorDelegate picd = mi => new SeriesItem(mi) { Command = new MethodDelegateCommand(() => PlayItemsModel.CheckQueryPlayAction(mi)) }; ViewSpecification rootViewSpecification = new MediaLibraryQueryViewSpecification(Consts.RES_SERIES_VIEW_NAME, null, Consts.NECESSARY_SERIES_MIAS, skinDependentOptionalMIATypeIDs, true) { MaxNumItems = Consts.MAX_NUM_ITEMS_VISIBLE }; AbstractScreenData filterBySeries = new SeriesFilterByNameScreenData(); ICollection <AbstractScreenData> availableScreens = new List <AbstractScreenData> { new SeriesShowItemsScreenData(picd), filterBySeries, // C# doesn't like it to have an assignment inside a collection initializer new VideosFilterByLanguageScreenData(), new SeriesFilterBySeasonScreenData(), new VideosFilterByGenreScreenData(), new VideosSimpleSearchScreenData(picd), }; Sorting.Sorting sortByEpisode = new SeriesSortByEpisode(); ICollection <Sorting.Sorting> availableSortings = new List <Sorting.Sorting> { sortByEpisode, new SortByTitle(), new SortByDate(), new SortBySystem(), }; navigationData = new NavigationData(null, Consts.RES_SERIES_VIEW_NAME, workflowStateId, workflowStateId, rootViewSpecification, filterBySeries, availableScreens, sortByEpisode) { AvailableSortings = availableSortings }; } else if (workflowStateId == Consts.WF_STATE_ID_MOVIES_NAVIGATION_ROOT) { mode = MediaNavigationMode.Movies; IEnumerable <Guid> skinDependentOptionalMIATypeIDs = GetMediaSkinOptionalMIATypes(mode); AbstractItemsScreenData.PlayableItemCreatorDelegate picd = mi => new MovieItem(mi) { Command = new MethodDelegateCommand(() => PlayItemsModel.CheckQueryPlayAction(mi)) }; ViewSpecification rootViewSpecification = new MediaLibraryQueryViewSpecification(Consts.RES_MOVIES_VIEW_NAME, null, Consts.NECESSARY_MOVIES_MIAS, skinDependentOptionalMIATypeIDs, true) { MaxNumItems = Consts.MAX_NUM_ITEMS_VISIBLE }; AbstractScreenData filterByGenre = new VideosFilterByGenreScreenData(); ICollection <AbstractScreenData> availableScreens = new List <AbstractScreenData> { new MoviesShowItemsScreenData(picd), new VideosFilterByActorScreenData(), filterByGenre, // C# doesn't like it to have an assignment inside a collection initializer new VideosFilterByYearScreenData(), new VideosFilterBySystemScreenData(), new VideosSimpleSearchScreenData(picd), }; Sorting.Sorting sortByTitle = new SortByTitle(); ICollection <Sorting.Sorting> availableSortings = new List <Sorting.Sorting> { sortByTitle, new SortByYear(), new VideoSortByFirstGenre(), new VideoSortByDuration(), new VideoSortByDirector(), new VideoSortByFirstActor(), new VideoSortBySize(), new VideoSortByAspectRatio(), new SortBySystem(), }; navigationData = new NavigationData(null, Consts.RES_MOVIES_VIEW_NAME, workflowStateId, workflowStateId, rootViewSpecification, filterByGenre, availableScreens, sortByTitle) { AvailableSortings = availableSortings }; } else if (workflowStateId == Consts.WF_STATE_ID_IMAGES_NAVIGATION_ROOT) { mode = MediaNavigationMode.Images; IEnumerable <Guid> skinDependentOptionalMIATypeIDs = GetMediaSkinOptionalMIATypes(mode); AbstractItemsScreenData.PlayableItemCreatorDelegate picd = mi => new ImageItem(mi) { Command = new MethodDelegateCommand(() => PlayItemsModel.CheckQueryPlayAction(mi)) }; ViewSpecification rootViewSpecification = new MediaLibraryQueryViewSpecification(Consts.RES_IMAGES_VIEW_NAME, null, Consts.NECESSARY_IMAGE_MIAS, skinDependentOptionalMIATypeIDs, true) { MaxNumItems = Consts.MAX_NUM_ITEMS_VISIBLE }; AbstractScreenData filterByYear = new ImagesFilterByYearScreenData(); ICollection <AbstractScreenData> availableScreens = new List <AbstractScreenData> { new ImagesShowItemsScreenData(picd), filterByYear, // C# doesn't like it to have an assignment inside a collection initializer new ImagesFilterBySizeScreenData(), new ImagesFilterBySystemScreenData(), new ImagesSimpleSearchScreenData(picd), }; Sorting.Sorting sortByYear = new SortByYear(); ICollection <Sorting.Sorting> availableSortings = new List <Sorting.Sorting> { new SortByYear(), new SortByTitle(), new ImageSortBySize(), new SortBySystem(), }; navigationData = new NavigationData(null, Consts.RES_IMAGES_VIEW_NAME, workflowStateId, workflowStateId, rootViewSpecification, filterByYear, availableScreens, sortByYear) { AvailableSortings = availableSortings }; } else { // If we were called with a supported root state, we should be either in state WF_STATE_ID_LOCAL_MEDIA_NAVIGATION_ROOT // or WF_STATE_ID_MEDIA_BROWSE_NAVIGATION_ROOT here if (workflowStateId != Consts.WF_STATE_ID_LOCAL_MEDIA_NAVIGATION_ROOT && workflowStateId != Consts.WF_STATE_ID_BROWSE_MEDIA_NAVIGATION_ROOT) { // Error case: We cannot handle the given state ServiceRegistration.Get <ILogger>().Warn("MediaNavigationModel: Unknown root workflow state with ID '{0}', initializing local media navigation", workflowStateId); // We simply use the local media mode as fallback for this case, so we go on workflowStateId = Consts.WF_STATE_ID_LOCAL_MEDIA_NAVIGATION_ROOT; } mode = workflowStateId == Consts.WF_STATE_ID_LOCAL_MEDIA_NAVIGATION_ROOT ? MediaNavigationMode.BrowseLocalMedia : MediaNavigationMode.BrowseMediaLibrary; IEnumerable <Guid> skinDependentOptionalMIATypeIDs = GetMediaSkinOptionalMIATypes(mode); AbstractItemsScreenData.PlayableItemCreatorDelegate picd = mi => { if (mi.Aspects.ContainsKey(AudioAspect.ASPECT_ID)) { return new AudioItem(mi) { Command = new MethodDelegateCommand(() => PlayItemsModel.CheckQueryPlayAction(mi)) } } ; if (mi.Aspects.ContainsKey(VideoAspect.ASPECT_ID)) { return new VideoItem(mi) { Command = new MethodDelegateCommand(() => PlayItemsModel.CheckQueryPlayAction(mi)) } } ; if (mi.Aspects.ContainsKey(ImageAspect.ASPECT_ID)) { return new ImageItem(mi) { Command = new MethodDelegateCommand(() => PlayItemsModel.CheckQueryPlayAction(mi)) } } ; return(null); }; IEnumerable <Guid> necessaryMIATypeIDs = new Guid[] { ProviderResourceAspect.ASPECT_ID, MediaAspect.ASPECT_ID, }; IEnumerable <Guid> optionalMIATypeIDs = new Guid[] { AudioAspect.ASPECT_ID, VideoAspect.ASPECT_ID, ImageAspect.ASPECT_ID, }.Union(skinDependentOptionalMIATypeIDs); string viewName = workflowStateId == Consts.WF_STATE_ID_LOCAL_MEDIA_NAVIGATION_ROOT ? Consts.RES_LOCAL_MEDIA_ROOT_VIEW_NAME : Consts.RES_BROWSE_MEDIA_ROOT_VIEW_NAME; ViewSpecification rootViewSpecification = workflowStateId == Consts.WF_STATE_ID_LOCAL_MEDIA_NAVIGATION_ROOT ? new AddedRemovableMediaViewSpecificationFacade(new LocalMediaRootProxyViewSpecification(viewName, necessaryMIATypeIDs, optionalMIATypeIDs)) : new AddedRemovableMediaViewSpecificationFacade(new BrowseMediaRootProxyViewSpecification(viewName, necessaryMIATypeIDs, optionalMIATypeIDs)); // Dynamic screens remain null - browse media states don't provide dynamic filters AbstractScreenData screenData = workflowStateId == Consts.WF_STATE_ID_LOCAL_MEDIA_NAVIGATION_ROOT ? (AbstractScreenData) new LocalMediaNavigationScreenData(picd) : new BrowseMediaNavigationScreenData(picd); Sorting.Sorting browseDefaultSorting = new BrowseDefaultSorting(); ICollection <Sorting.Sorting> availableSortings = new List <Sorting.Sorting> { browseDefaultSorting, new SortByTitle(), new SortByDate(), // We could offer sortings here which are specific for one media item type but which will cope with all three item types (and sort items of the three types in a defined order) }; navigationData = new NavigationData(null, viewName, workflowStateId, workflowStateId, rootViewSpecification, screenData, null, browseDefaultSorting) { AvailableSortings = availableSortings }; } result.Add(Consts.KEY_NAVIGATION_MODE, mode); result.Add(Consts.KEY_NAVIGATION_DATA, navigationData); return(result); }
/// <summary> /// Returns context variables to be set for the given workflow state id. /// </summary> /// <param name="workflowStateId">Workflow state which determines the root media navigation state.</param> /// <returns>Mapping of context variable keys to values.</returns> protected static IDictionary<string, object> PrepareRootState(Guid workflowStateId) { IDictionary<string, object> result = new Dictionary<string, object>(); // The initial state ID determines the media model "part" to initialize: Browse local media, browse media library, audio, videos or images. // The media model part determines the media navigation mode and the view contents to be set. NavigationData navigationData; MediaNavigationMode mode; if (workflowStateId == Consts.WF_STATE_ID_AUDIO_NAVIGATION_ROOT) { mode = MediaNavigationMode.Audio; IEnumerable<Guid> skinDependentOptionalMIATypeIDs = GetMediaSkinOptionalMIATypes(mode); AbstractItemsScreenData.PlayableItemCreatorDelegate picd = mi => new AudioItem(mi) { Command = new MethodDelegateCommand(() => PlayItemsModel.CheckQueryPlayAction(mi)) }; ViewSpecification rootViewSpecification = new MediaLibraryQueryViewSpecification(Consts.RES_AUDIO_VIEW_NAME, null, Consts.NECESSARY_AUDIO_MIAS, skinDependentOptionalMIATypeIDs, true) { MaxNumItems = Consts.MAX_NUM_ITEMS_VISIBLE }; AbstractScreenData filterByAlbum = new AudioFilterByAlbumScreenData(); ICollection<AbstractScreenData> availableScreens = new List<AbstractScreenData> { new AudioShowItemsScreenData(picd), new AudioFilterByArtistScreenData(), filterByAlbum, // C# doesn't like it to have an assignment inside a collection initializer new AudioFilterByGenreScreenData(), new AudioFilterByDecadeScreenData(), new AudioFilterBySystemScreenData(), new AudioSimpleSearchScreenData(picd), }; Sorting.Sorting sortByAlbumTrack = new AudioSortByAlbumTrack(); ICollection<Sorting.Sorting> availableSortings = new List<Sorting.Sorting> { sortByAlbumTrack, new SortByTitle(), new AudioSortByFirstGenre(), new AudioSortByFirstArtist(), new AudioSortByAlbum(), new AudioSortByTrack(), new SortByYear(), new SortBySystem(), }; navigationData = new NavigationData(null, Consts.RES_AUDIO_VIEW_NAME, workflowStateId, workflowStateId, rootViewSpecification, filterByAlbum, availableScreens, sortByAlbumTrack) { AvailableSortings = availableSortings }; } else if (workflowStateId == Consts.WF_STATE_ID_VIDEOS_NAVIGATION_ROOT) { mode = MediaNavigationMode.Videos; IEnumerable<Guid> skinDependentOptionalMIATypeIDs = GetMediaSkinOptionalMIATypes(mode); AbstractItemsScreenData.PlayableItemCreatorDelegate picd = mi => new VideoItem(mi) { Command = new MethodDelegateCommand(() => PlayItemsModel.CheckQueryPlayAction(mi)) }; ViewSpecification rootViewSpecification = new MediaLibraryQueryViewSpecification(Consts.RES_VIDEOS_VIEW_NAME, null, Consts.NECESSARY_VIDEO_MIAS, skinDependentOptionalMIATypeIDs, true) { MaxNumItems = Consts.MAX_NUM_ITEMS_VISIBLE }; AbstractScreenData filterByGenre = new VideosFilterByGenreScreenData(); ICollection<AbstractScreenData> availableScreens = new List<AbstractScreenData> { new VideosShowItemsScreenData(picd), new VideosFilterByLanguageScreenData(), new VideosFilterByActorScreenData(), filterByGenre, // C# doesn't like it to have an assignment inside a collection initializer new VideosFilterByYearScreenData(), new VideosFilterBySystemScreenData(), new VideosSimpleSearchScreenData(picd), }; Sorting.Sorting sortByTitle = new SortByTitle(); ICollection<Sorting.Sorting> availableSortings = new List<Sorting.Sorting> { sortByTitle, new SortByYear(), new VideoSortByFirstGenre(), new VideoSortByDuration(), new VideoSortByDirector(), new VideoSortByFirstActor(), new VideoSortBySize(), new VideoSortByAspectRatio(), new SortBySystem(), }; navigationData = new NavigationData(null, Consts.RES_VIDEOS_VIEW_NAME, workflowStateId, workflowStateId, rootViewSpecification, filterByGenre, availableScreens, sortByTitle) { AvailableSortings = availableSortings }; } else if (workflowStateId == Consts.WF_STATE_ID_SERIES_NAVIGATION_ROOT) { mode = MediaNavigationMode.Videos; IEnumerable<Guid> skinDependentOptionalMIATypeIDs = GetMediaSkinOptionalMIATypes(mode); AbstractItemsScreenData.PlayableItemCreatorDelegate picd = mi => new SeriesItem(mi) { Command = new MethodDelegateCommand(() => PlayItemsModel.CheckQueryPlayAction(mi)) }; ViewSpecification rootViewSpecification = new MediaLibraryQueryViewSpecification(Consts.RES_SERIES_VIEW_NAME, null, Consts.NECESSARY_SERIES_MIAS, skinDependentOptionalMIATypeIDs, true) { MaxNumItems = Consts.MAX_NUM_ITEMS_VISIBLE }; AbstractScreenData filterBySeries = new SeriesFilterByNameScreenData(); ICollection<AbstractScreenData> availableScreens = new List<AbstractScreenData> { new SeriesShowItemsScreenData(picd), filterBySeries, // C# doesn't like it to have an assignment inside a collection initializer new VideosFilterByLanguageScreenData(), new SeriesFilterBySeasonScreenData(), new VideosFilterByGenreScreenData(), new VideosSimpleSearchScreenData(picd), }; Sorting.Sorting sortByEpisode = new SeriesSortByEpisode(); ICollection<Sorting.Sorting> availableSortings = new List<Sorting.Sorting> { sortByEpisode, new SortByTitle(), new SortByDate(), new SortBySystem(), }; navigationData = new NavigationData(null, Consts.RES_SERIES_VIEW_NAME, workflowStateId, workflowStateId, rootViewSpecification, filterBySeries, availableScreens, sortByEpisode) { AvailableSortings = availableSortings }; } else if (workflowStateId == Consts.WF_STATE_ID_MOVIES_NAVIGATION_ROOT) { mode = MediaNavigationMode.Movies; IEnumerable<Guid> skinDependentOptionalMIATypeIDs = GetMediaSkinOptionalMIATypes(mode); AbstractItemsScreenData.PlayableItemCreatorDelegate picd = mi => new MovieItem(mi) { Command = new MethodDelegateCommand(() => PlayItemsModel.CheckQueryPlayAction(mi)) }; ViewSpecification rootViewSpecification = new MediaLibraryQueryViewSpecification(Consts.RES_MOVIES_VIEW_NAME, null, Consts.NECESSARY_MOVIES_MIAS, skinDependentOptionalMIATypeIDs, true) { MaxNumItems = Consts.MAX_NUM_ITEMS_VISIBLE }; AbstractScreenData filterByGenre = new VideosFilterByGenreScreenData(); ICollection<AbstractScreenData> availableScreens = new List<AbstractScreenData> { new MoviesShowItemsScreenData(picd), new VideosFilterByActorScreenData(), filterByGenre, // C# doesn't like it to have an assignment inside a collection initializer new VideosFilterByYearScreenData(), new VideosFilterBySystemScreenData(), new VideosSimpleSearchScreenData(picd), }; Sorting.Sorting sortByTitle = new SortByTitle(); ICollection<Sorting.Sorting> availableSortings = new List<Sorting.Sorting> { sortByTitle, new SortByYear(), new VideoSortByFirstGenre(), new VideoSortByDuration(), new VideoSortByDirector(), new VideoSortByFirstActor(), new VideoSortBySize(), new VideoSortByAspectRatio(), new SortBySystem(), }; navigationData = new NavigationData(null, Consts.RES_MOVIES_VIEW_NAME, workflowStateId, workflowStateId, rootViewSpecification, filterByGenre, availableScreens, sortByTitle) { AvailableSortings = availableSortings }; } else if (workflowStateId == Consts.WF_STATE_ID_IMAGES_NAVIGATION_ROOT) { mode = MediaNavigationMode.Images; IEnumerable<Guid> skinDependentOptionalMIATypeIDs = GetMediaSkinOptionalMIATypes(mode); AbstractItemsScreenData.PlayableItemCreatorDelegate picd = mi => new ImageItem(mi) { Command = new MethodDelegateCommand(() => PlayItemsModel.CheckQueryPlayAction(mi)) }; ViewSpecification rootViewSpecification = new MediaLibraryQueryViewSpecification(Consts.RES_IMAGES_VIEW_NAME, null, Consts.NECESSARY_IMAGE_MIAS, skinDependentOptionalMIATypeIDs, true) { MaxNumItems = Consts.MAX_NUM_ITEMS_VISIBLE }; AbstractScreenData filterByYear = new ImagesFilterByYearScreenData(); ICollection<AbstractScreenData> availableScreens = new List<AbstractScreenData> { new ImagesShowItemsScreenData(picd), filterByYear, // C# doesn't like it to have an assignment inside a collection initializer new ImagesFilterBySizeScreenData(), new ImagesFilterBySystemScreenData(), new ImagesSimpleSearchScreenData(picd), }; Sorting.Sorting sortByYear = new SortByYear(); ICollection<Sorting.Sorting> availableSortings = new List<Sorting.Sorting> { new SortByYear(), new SortByTitle(), new ImageSortBySize(), new SortBySystem(), }; navigationData = new NavigationData(null, Consts.RES_IMAGES_VIEW_NAME, workflowStateId, workflowStateId, rootViewSpecification, filterByYear, availableScreens, sortByYear) { AvailableSortings = availableSortings }; } else { // If we were called with a supported root state, we should be either in state WF_STATE_ID_LOCAL_MEDIA_NAVIGATION_ROOT // or WF_STATE_ID_MEDIA_BROWSE_NAVIGATION_ROOT here if (workflowStateId != Consts.WF_STATE_ID_LOCAL_MEDIA_NAVIGATION_ROOT && workflowStateId != Consts.WF_STATE_ID_BROWSE_MEDIA_NAVIGATION_ROOT) { // Error case: We cannot handle the given state ServiceRegistration.Get<ILogger>().Warn("MediaNavigationModel: Unknown root workflow state with ID '{0}', initializing local media navigation", workflowStateId); // We simply use the local media mode as fallback for this case, so we go on workflowStateId = Consts.WF_STATE_ID_LOCAL_MEDIA_NAVIGATION_ROOT; } mode = workflowStateId == Consts.WF_STATE_ID_LOCAL_MEDIA_NAVIGATION_ROOT ? MediaNavigationMode.BrowseLocalMedia : MediaNavigationMode.BrowseMediaLibrary; IEnumerable<Guid> skinDependentOptionalMIATypeIDs = GetMediaSkinOptionalMIATypes(mode); AbstractItemsScreenData.PlayableItemCreatorDelegate picd = mi => { if (mi.Aspects.ContainsKey(AudioAspect.ASPECT_ID)) return new AudioItem(mi) { Command = new MethodDelegateCommand(() => PlayItemsModel.CheckQueryPlayAction(mi)) }; if (mi.Aspects.ContainsKey(VideoAspect.ASPECT_ID)) return new VideoItem(mi) { Command = new MethodDelegateCommand(() => PlayItemsModel.CheckQueryPlayAction(mi)) }; if (mi.Aspects.ContainsKey(ImageAspect.ASPECT_ID)) return new ImageItem(mi) { Command = new MethodDelegateCommand(() => PlayItemsModel.CheckQueryPlayAction(mi)) }; return null; }; IEnumerable<Guid> necessaryMIATypeIDs = new Guid[] { ProviderResourceAspect.ASPECT_ID, MediaAspect.ASPECT_ID, }; IEnumerable<Guid> optionalMIATypeIDs = new Guid[] { AudioAspect.ASPECT_ID, VideoAspect.ASPECT_ID, ImageAspect.ASPECT_ID, }.Union(skinDependentOptionalMIATypeIDs); string viewName = workflowStateId == Consts.WF_STATE_ID_LOCAL_MEDIA_NAVIGATION_ROOT ? Consts.RES_LOCAL_MEDIA_ROOT_VIEW_NAME : Consts.RES_BROWSE_MEDIA_ROOT_VIEW_NAME; ViewSpecification rootViewSpecification = workflowStateId == Consts.WF_STATE_ID_LOCAL_MEDIA_NAVIGATION_ROOT ? new AddedRemovableMediaViewSpecificationFacade(new LocalMediaRootProxyViewSpecification(viewName, necessaryMIATypeIDs, optionalMIATypeIDs)) : new AddedRemovableMediaViewSpecificationFacade(new BrowseMediaRootProxyViewSpecification(viewName, necessaryMIATypeIDs, optionalMIATypeIDs)); // Dynamic screens remain null - browse media states don't provide dynamic filters AbstractScreenData screenData = workflowStateId == Consts.WF_STATE_ID_LOCAL_MEDIA_NAVIGATION_ROOT ? (AbstractScreenData) new LocalMediaNavigationScreenData(picd) : new BrowseMediaNavigationScreenData(picd); Sorting.Sorting browseDefaultSorting = new BrowseDefaultSorting(); ICollection<Sorting.Sorting> availableSortings = new List<Sorting.Sorting> { browseDefaultSorting, new SortByTitle(), new SortByDate(), // We could offer sortings here which are specific for one media item type but which will cope with all three item types (and sort items of the three types in a defined order) }; navigationData = new NavigationData(null, viewName, workflowStateId, workflowStateId, rootViewSpecification, screenData, null, browseDefaultSorting) { AvailableSortings = availableSortings }; } result.Add(Consts.KEY_NAVIGATION_MODE, mode); result.Add(Consts.KEY_NAVIGATION_DATA, navigationData); return result; }
protected static void PushNewNavigationWorkflowState(WorkflowState newState, string navbarDisplayLabel, NavigationData newNavigationData) { IWorkflowManager workflowManager = ServiceRegistration.Get <IWorkflowManager>(); workflowManager.NavigatePushTransient(newState, new NavigationContextConfig { AdditionalContextVariables = new Dictionary <string, object> { { Consts.KEY_NAVIGATION_DATA, newNavigationData } }, NavigationContextDisplayLabel = navbarDisplayLabel }); }
/// <summary> /// Creates a new navigation data structure for a new media navigation step. /// </summary> /// <param name="parent">Parent navigation data, this navigation data is derived from.</param> /// <param name="navigationContextName">Name, which is used for the corresponding workflow navigation context.</param> /// <param name="currentWorkflowStateId">Id of the workflow state which corresponds to the new media navigation step.</param> /// <param name="parentWorkflowStateId">Id of the workflow state to which the workflow navigation should be reverted when /// another filter is choosen.</param> /// <param name="baseViewSpecification">View specification for the media items of the new media navigation step.</param> /// <param name="defaultScreen">Screen which should present the new navigation step by default.</param> /// <param name="availableScreens">Available set of screen descriptions which can present the new media navigation step.</param> /// <param name="currentSorting">Denotes the current sorting for the items to be shown. If this is set to <c>null</c>, /// default sorting will be applied.</param> public NavigationData(NavigationData parent, string navigationContextName, Guid parentWorkflowStateId, Guid currentWorkflowStateId, ViewSpecification baseViewSpecification, AbstractScreenData defaultScreen, ICollection<AbstractScreenData> availableScreens, Sorting.Sorting currentSorting) : this(parent, navigationContextName, parentWorkflowStateId, currentWorkflowStateId, baseViewSpecification, defaultScreen, availableScreens, currentSorting, false) { }
// If the suppressActions parameter is set to <c>true</c>, no actions will be built. Instead, they will be inherited from // the parent navigation step. That is used for subview navigation where the navigation step doesn't produce own // workflow actions. protected NavigationData(NavigationData parent, string navigationContextName, Guid parentWorkflowStateId, Guid currentWorkflowStateId, ViewSpecification baseViewSpecification, AbstractScreenData defaultScreen, ICollection<AbstractScreenData> availableScreens, Sorting.Sorting currentSorting, bool suppressActions) { _parent = parent; _navigationContextName = navigationContextName; _currentWorkflowStateId = currentWorkflowStateId; _baseWorkflowStateId = parentWorkflowStateId; _baseViewSpecification = baseViewSpecification; _currentScreenData = defaultScreen; _availableScreens = availableScreens ?? new List<AbstractScreenData>(); _currentSorting = currentSorting; if (suppressActions) _dynamicWorkflowActions = null; else BuildWorkflowActions(); }
protected static void PushNewNavigationWorkflowState(WorkflowState newState, string navbarDisplayLabel, NavigationData newNavigationData) { IWorkflowManager workflowManager = ServiceRegistration.Get<IWorkflowManager>(); workflowManager.NavigatePushTransient(newState, new NavigationContextConfig { AdditionalContextVariables = new Dictionary<string, object> { {Consts.KEY_NAVIGATION_DATA, newNavigationData} }, NavigationContextDisplayLabel = navbarDisplayLabel }); }
/// <summary> /// Enters a new media navigation context by modifying the list of available screens. This is used for /// presenting the result of a filter, where the menu must be changed. /// </summary> /// <param name="subViewSpecification">Specification for the sub view to be shown in the new navigation context.</param> /// <param name="remainingScreens">New collection of remaining available screens.</param> /// <param name="navbarDisplayLabel">Display label to be shown in the navigation bar for the new navigation context.</param> /// <returns>Newly created navigation data.</returns> public NavigationData StackAutonomousNavigationContext(ViewSpecification subViewSpecification, ICollection<AbstractScreenData> remainingScreens, string navbarDisplayLabel) { WorkflowState newState = WorkflowState.CreateTransientState( "View: " + subViewSpecification.ViewDisplayName, subViewSpecification.ViewDisplayName, false, null, false, WorkflowType.Workflow); NavigationData newNavigationData = new NavigationData(this, subViewSpecification.ViewDisplayName, newState.StateId, newState.StateId, subViewSpecification, remainingScreens.FirstOrDefault(), remainingScreens, _currentSorting); PushNewNavigationWorkflowState(newState, navbarDisplayLabel, newNavigationData); return newNavigationData; }
/// <summary> /// Enters a new media navigation context by inheriting all currently available screens. This is used for /// presenting the contents of a media items or filter group, where the current menu should remain available. /// Only the currently visible screen can be exchanged to configure another presentation mode for the group to /// be stepped-in. /// </summary> /// <remarks> /// Actually, we mix two different concerns in this method: /// <list type="number"> /// <item>The setting that the new navigation context will be subordinated, i.e. it will be removed/exchanged by a filter action</item> /// <item>The setting that all menu actions will be adopted from the parent navigation context</item> /// </list> /// But in fact, filter actions are only used together with the concept that there exist two different kind of navigation contexts; /// autonomous contexts and subordinated contexts. /// If there are no filter actions present (like in the browse media navigation modes), the only difference between the methods /// <see cref="StackSubordinateNavigationContext"/> and <see cref="StackAutonomousNavigationContext"/> is the inheritance of the menu. /// </remarks> /// <param name="subViewSpecification">Specification for the sub view to be shown in the new navigation context.</param> /// <param name="visibleScreen">Screen which should be visible in the new navigation context.</param> /// <param name="navbarDisplayLabel">Display label to be shown in the navigation bar for the new navigation context.</param> /// <returns>Newly created navigation data.</returns> public NavigationData StackSubordinateNavigationContext(ViewSpecification subViewSpecification, AbstractScreenData visibleScreen, string navbarDisplayLabel) { WorkflowState newState = WorkflowState.CreateTransientState( "View: " + subViewSpecification.ViewDisplayName, subViewSpecification.ViewDisplayName, false, null, true, WorkflowType.Workflow); NavigationData newNavigationData = new NavigationData(this, subViewSpecification.ViewDisplayName, _baseWorkflowStateId, newState.StateId, subViewSpecification, visibleScreen, _availableScreens, _currentSorting, true); PushNewNavigationWorkflowState(newState, navbarDisplayLabel, newNavigationData); return newNavigationData; }
/// <summary> /// Enters a new media navigation context by modifying the list of available screens. This is used for /// presenting the result of a filter, where the menu must be changed. /// </summary> /// <param name="subViewSpecification">Specification for the sub view to be shown in the new navigation context.</param> /// <param name="currentMenuItemLabel">Current menu item label needed for distinction of available screens.</param> /// <param name="navbarDisplayLabel">Display label to be shown in the navigation bar for the new navigation context.</param> /// <returns>Newly created navigation data.</returns> public NavigationData StackAutonomousNavigationContext(ViewSpecification subViewSpecification, string currentMenuItemLabel, string navbarDisplayLabel) { AbstractScreenData currentScreen = AvailableScreens.FirstOrDefault(screen => screen.MenuItemLabel == currentMenuItemLabel); ICollection<AbstractScreenData> remainingScreens = new List<AbstractScreenData>(AvailableScreens.Where(screen => screen != currentScreen)); WorkflowState newState = WorkflowState.CreateTransientState( "View: " + subViewSpecification.ViewDisplayName, subViewSpecification.ViewDisplayName, false, null, false, WorkflowType.Workflow); string nextScreenName; AbstractScreenData nextScreen = null; // Try to load the prefered next screen from settings. if (LoadScreenHierarchy(CurrentScreenData.GetType().ToString(), out nextScreenName)) nextScreen = remainingScreens.FirstOrDefault(s => s.GetType().ToString() == nextScreenName); // Default way: always take the first of the available screens. if (nextScreen == null) nextScreen = remainingScreens.First(s => s != currentScreen); ScreenConfig nextScreenConfig; LoadLayoutSettings(nextScreen.GetType().ToString(), out nextScreenConfig); Sorting.Sorting nextSortingMode = AvailableSortings.FirstOrDefault(sorting => sorting.GetType().ToString() == nextScreenConfig.Sorting) ?? _currentSorting; NavigationData newNavigationData = new NavigationData(this, subViewSpecification.ViewDisplayName, newState.StateId, newState.StateId, subViewSpecification, nextScreen, remainingScreens, nextSortingMode) { LayoutType = nextScreenConfig.LayoutType, LayoutSize = nextScreenConfig.LayoutSize }; PushNewNavigationWorkflowState(newState, navbarDisplayLabel, newNavigationData); return newNavigationData; }
/// <summary> /// Enters a new media navigation context by inheriting all currently available screens. This is used for /// presenting the contents of a media items or filter group, where the current menu should remain available. /// Only the currently visible screen can be exchanged to configure another presentation mode for the group to /// be stepped-in. /// </summary> /// <remarks> /// Actually, we mix two different concerns in this method: /// <list type="number"> /// <item>The setting that the new navigation context will be subordinated, i.e. it will be removed/exchanged by a filter action</item> /// <item>The setting that all menu actions will be adopted from the parent navigation context</item> /// </list> /// But in fact, filter actions are only used together with the concept that there exist two different kind of navigation contexts; /// autonomous contexts and subordinated contexts. /// If there are no filter actions present (like in the browse media navigation modes), the only difference between the methods /// <see cref="StackSubordinateNavigationContext"/> and <see cref="StackAutonomousNavigationContext"/> is the inheritance of the menu. /// </remarks> /// <param name="subViewSpecification">Specification for the sub view to be shown in the new navigation context.</param> /// <param name="visibleScreen">Screen which should be visible in the new navigation context.</param> /// <param name="navbarDisplayLabel">Display label to be shown in the navigation bar for the new navigation context.</param> /// <returns>Newly created navigation data.</returns> public NavigationData StackSubordinateNavigationContext(ViewSpecification subViewSpecification, AbstractScreenData visibleScreen, string navbarDisplayLabel) { WorkflowState newState = WorkflowState.CreateTransientState( "View: " + subViewSpecification.ViewDisplayName, subViewSpecification.ViewDisplayName, false, null, true, WorkflowType.Workflow); ScreenConfig nextScreenConfig; LoadLayoutSettings(visibleScreen.ToString(), out nextScreenConfig); Sorting.Sorting nextSortingMode = AvailableSortings.FirstOrDefault(sorting => sorting.GetType().ToString() == nextScreenConfig.Sorting) ?? _currentSorting; NavigationData newNavigationData = new NavigationData(this, subViewSpecification.ViewDisplayName, _baseWorkflowStateId, newState.StateId, subViewSpecification, visibleScreen, _availableScreens, nextSortingMode, true) { LayoutType = nextScreenConfig.LayoutType, LayoutSize = nextScreenConfig.LayoutSize }; PushNewNavigationWorkflowState(newState, navbarDisplayLabel, newNavigationData); return newNavigationData; }