Beispiel #1
0
        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();
        }
Beispiel #2
0
        /// <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);
        }
Beispiel #3
0
        public void ExitModelContext(NavigationContext oldContext, NavigationContext newContext)
        {
            NavigationData navigationData = GetNavigationData(oldContext, false);

            navigationData.Dispose();
            ReleaseModelData();
        }
Beispiel #4
0
        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();
        }
Beispiel #5
0
        public void EnterModelContext(NavigationContext oldContext, NavigationContext newContext)
        {
            PrepareState(newContext);
            NavigationData navigationData = GetNavigationData(newContext, false);

            navigationData.Enable();
        }
Beispiel #6
0
        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;
            }
        }
Beispiel #7
0
 /// <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);
        }
Beispiel #11
0
        protected IEnumerable <MediaItem> GetMediaItemsFromCurrentView()
        {
            NavigationData navigationData = NavigationData;

            if (navigationData == null)
            {
                yield break;
            }
            foreach (MediaItem mediaItem in navigationData.CurrentScreenData.GetAllMediaItems())
            {
                yield return(mediaItem);
            }
        }
Beispiel #12
0
        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;
    }
Beispiel #15
0
        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;
        }
Beispiel #16
0
        /// <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();
        }
Beispiel #17
0
 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();
     }
 }
Beispiel #18
0
        /// <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);
        }
Beispiel #20
0
 // 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();
        }
Beispiel #22
0
        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;
 }
Beispiel #26
0
        /// <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
            });
        }
Beispiel #30
0
 protected static void SetNavigationData(NavigationData navigationData, NavigationContext navigationContext)
 {
     navigationContext.SetContextVariable(Consts.KEY_NAVIGATION_DATA, navigationData);
 }
Beispiel #31
0
 /// <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) { }
Beispiel #32
0
 // 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();
 }
Beispiel #33
0
 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
     });
 }
Beispiel #34
0
 /// <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;
 }
Beispiel #35
0
 /// <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;
    }