/// <summary> /// Pushes the <see cref="TargetState"/> onto the workflow navigation context stack. /// </summary> public override void Execute() { IWorkflowManager workflowManager = ServiceRegistration.Get <IWorkflowManager>(); NavigationContextConfig config = new NavigationContextConfig { NavigationContextDisplayLabel = _displayLabel, AdditionalContextVariables = _workflowNavigationContextVariables }; workflowManager.NavigatePushTransient(_transientState, config); }
private void ShowSingleChannelGuide(IChannel channel) { if (channel == null || CurrentChannelGroup == null) return; int channelId = channel.ChannelId; int groupId = CurrentChannelGroup.ChannelGroupId; IWorkflowManager workflowManager = ServiceRegistration.Get<IWorkflowManager>(); NavigationContextConfig navigationContextConfig = new NavigationContextConfig(); navigationContextConfig.AdditionalContextVariables = new Dictionary<string, object>(); navigationContextConfig.AdditionalContextVariables[SlimTvClientModel.KEY_CHANNEL_ID] = channelId; navigationContextConfig.AdditionalContextVariables[SlimTvClientModel.KEY_GROUP_ID] = groupId; Guid stateId = new Guid("A40F05BB-022E-4247-8BEE-16EB3E0B39C5"); if (workflowManager.IsAnyStateContainedInNavigationStack(new Guid[] { stateId })) workflowManager.NavigatePopToState(stateId, false); else workflowManager.NavigatePush(stateId, navigationContextConfig); }
// Maybe called asynchronously. protected void NavigatePushInternal(Guid stateId, NavigationContextConfig config) { EnterWriteLock("NavigatePush"); try { WorkflowState state; if (!_states.TryGetValue(stateId, out state)) throw new ArgumentException(string.Format("WorkflowManager: Workflow state '{0}' is not available", stateId)); try { if (DoPushNavigationContext(state, config)) UpdateScreen_NeedsLock(true, true); WorkflowManagerMessaging.SendNavigationCompleteMessage(); } catch (Exception e) { ServiceRegistration.Get<ILogger>().Error("WorkflowManager.NavigatePushInternal: Error in workflow model or screen", e); NavigatePopInternal(1); } } finally { ExitWriteLock(); } }
// Maybe called asynchronously. protected void NavigatePushTransientInternal(WorkflowState state, NavigationContextConfig config) { EnterWriteLock("NavigatePushTransient"); try { try { if (DoPushNavigationContext(state, config)) UpdateScreen_NeedsLock(true, true); WorkflowManagerMessaging.SendNavigationCompleteMessage(); } catch (Exception e) { ServiceRegistration.Get<ILogger>().Error("WorkflowManager.NavigatePushTransientInternal: Error in workflow model or screen", e); NavigatePopInternal(1); } } finally { ExitWriteLock(); } }
public void NavigatePushTransientAsync(WorkflowState state, NavigationContextConfig config) { IThreadPool threadPool = ServiceRegistration.Get<IThreadPool>(); threadPool.Add(() => NavigatePushTransientInternal(state, config)); }
/// <summary> /// Synchronous method which pushes the given workflow <paramref name="state"/> onto the navigation stack. /// </summary> /// <remarks> /// This method rethrows all exceptions which are thrown by workflow models. In case an exception is thrown, /// the internal state is still valid but the caller must pop the current navigation context from the workflow stack. /// </remarks> /// <param name="state">Workflow state to push.</param> /// <param name="config">Additional navigation context configuration.</param> /// <returns><c>true</c> if the push action was successful, else <c>false</c>.</returns> protected bool DoPushNavigationContext(WorkflowState state, NavigationContextConfig config) { if (config == null) config = EMPTY_NAVIGATION_CONTEXT_CONFIG; EnterWriteLock("DoPushNavigationContext"); try { ILogger logger = ServiceRegistration.Get<ILogger>(); NavigationContext current = CurrentNavigationContext; if (current != null && current.WorkflowState.IsTemporary && state.WorkflowType == WorkflowType.Workflow) { logger.Info("Current workflow state '{0}' is temporary, popping it from navigation stack", current.WorkflowState.Name); // The next statement can throw an exception - don't catch it - our caller should pop the current navigation context bool workflowStatePopped; DoPopNavigationContext(1, out workflowStatePopped); } NavigationContext predecessor = CurrentNavigationContext; logger.Info("WorkflowManager: Pushing workflow state '{0}' (id='{1}') onto the navigation stack...", state.Name, state.StateId); // Find non-transient state. If new state is transient, search for last non-transient state on stack. WorkflowState nonTransientState = state.IsTransient ? FindLastNonTransientState() : state; if (nonTransientState == null) { logger.Error("WorkflowManager: No non-transient state found on workflow context stack to be used as reference state. Workflow state to be pushed is '{0}' (id: '{1}')", state.Name, state.StateId); return false; } // Initialize workflow model Guid? workflowModelId = nonTransientState.WorkflowModelId; IWorkflowModel workflowModel = null; if (workflowModelId.HasValue) { object model = GetOrLoadModel(workflowModelId.Value); if (model is IWorkflowModel) { logger.Debug("WorkflowManager: Using workflow model with id '{0}' for new workflow state '{1}'", workflowModelId.Value, state.StateId); workflowModel = (IWorkflowModel) model; } else logger.Error("WorkflowManager: Model with id '{0}', which is used as workflow model in state '{1}', doesn't implement the interface '{2}'", workflowModelId.Value, state.StateId, typeof(IWorkflowModel).Name); } // Create new workflow context NavigationContext newContext = new NavigationContext(state, config.NavigationContextDisplayLabel, predecessor, workflowModel); if (config.AdditionalContextVariables != null) lock (newContext.SyncRoot) CollectionUtils.AddAll(newContext.ContextVariables, config.AdditionalContextVariables); // Check if state change is accepted bool canEnter = true; if (workflowModel != null) try { canEnter = workflowModel.CanEnterState(predecessor, newContext); } catch (Exception e) { logger.Error("WorkflowManager: Error checking if workflow model '{0}' can enter workflow state '{1}'", e, workflowModel.ModelId, newContext.WorkflowState.StateId); canEnter = false; } if (!canEnter) { logger.Debug("WorkflowManager: Workflow model with id '{0}' doesn't accept the state being pushed onto the workflow context stack. Reverting to old workflow state.", workflowModelId); return false; } // Store model exceptions IList<Exception> delayedExceptions = new List<Exception>(); // Push new context logger.Debug("WorkflowManager: Entering workflow state '{0}'", state.Name); _navigationContextStack.Push(newContext); Guid? predecessorModelId = predecessor == null ? null : predecessor.WorkflowModelId; // Communicate context change to models bool modelChange = workflowModelId != predecessorModelId; // - Handle predecessor workflow model IWorkflowModel predecessorWorkflowModel = predecessorModelId.HasValue ? GetOrLoadModel(predecessorModelId.Value) as IWorkflowModel : null; if (predecessorWorkflowModel != null) if (modelChange) { logger.Debug("WorkflowManager: Deactivating predecessor workflow model '{0}'", predecessorModelId.Value); try { predecessorWorkflowModel.Deactivate(predecessor, newContext); } catch (Exception e) { logger.Error("WorkflowManager: Error deactivating workflow model '{0}'", e, predecessorWorkflowModel.ModelId); delayedExceptions.Add(e); } } // else: same model is currently active - model context change will be handled in the next block // - Handle new workflow model if (workflowModel != null) if (modelChange) { if (predecessor == null) logger.Debug("WorkflowManager: Starting first model context with workflow state '{0}' in workflow model '{1}'", newContext.WorkflowState.StateId, workflowModelId.Value); else logger.Debug("WorkflowManager: Entering model context with workflow state '{0}' (old state was '{1}') in new workflow model '{2}'", newContext.WorkflowState.StateId, predecessor.WorkflowState.StateId, workflowModelId.Value); try { workflowModel.EnterModelContext(predecessor, newContext); } catch (Exception e) { logger.Error("WorkflowManager: Error entering model context of workflow model '{0}' for workflow state '{1}'", e, workflowModel.ModelId, newContext.WorkflowState.StateId); delayedExceptions.Add(e); } } else { logger.Debug("WorkflowManager: Changing model context to workflow state '{0}' (old state was '{1}') in workflow model '{2}'", newContext.WorkflowState.StateId, predecessor == null ? null : predecessor.WorkflowState.StateId.ToString(), workflowModelId.Value); try { workflowModel.ChangeModelContext(predecessor, newContext, true); } catch (Exception e) { logger.Error("WorkflowManager: Error changing model context of workflow model '{0}' from workflow state '{1}' to workflow state '{2}'", e, workflowModel.ModelId, predecessor.WorkflowState.StateId, newContext.WorkflowState.StateId); delayedExceptions.Add(e); } } if (state.WorkflowType == WorkflowType.Workflow) { // Compile menu actions logger.Debug("WorkflowManager: Compiling menu actions for workflow state '{0}'", state.Name); IDictionary<Guid, WorkflowAction> menuActions = new Dictionary<Guid, WorkflowAction>(); foreach (WorkflowAction action in FilterActionsBySourceState(state.StateId, _menuActions.Values)) menuActions.Add(action.ActionId, action); if (workflowModel != null) try { workflowModel.UpdateMenuActions(newContext, menuActions); } catch (Exception e) { logger.Error("WorkflowManager: Error updating menu actions in workflow model '{0}' for workflow state '{1}'", e, workflowModel.ModelId, newContext.WorkflowState.StateId); delayedExceptions.Add(e); } newContext.SetMenuActions(menuActions.Values); } if (delayedExceptions.Count > 0) throw delayedExceptions.First(); WorkflowManagerMessaging.SendStatePushedMessage(newContext); return true; } finally { ExitWriteLock(); IterateCache_NoLock(); } }
public void NavigatePushAsync(Guid stateId, NavigationContextConfig config) { IThreadPool threadPool = ServiceRegistration.Get<IThreadPool>(); threadPool.Add(() => NavigatePushInternal(stateId, config)); }
public void NavigatePushTransient(WorkflowState state, NavigationContextConfig config) { NavigatePushTransientInternal(state, config); }
public void NavigatePush(Guid stateId, NavigationContextConfig config) { NavigatePushInternal(stateId, config); }
/// <summary> /// Pushes the <see cref="TargetState"/> onto the workflow navigation context stack. /// </summary> public override void Execute() { IWorkflowManager workflowManager = ServiceRegistration.Get<IWorkflowManager>(); NavigationContextConfig config = new NavigationContextConfig { NavigationContextDisplayLabel = _displayLabel, AdditionalContextVariables = _workflowNavigationContextVariables }; workflowManager.NavigatePushTransient(_transientState, config); }
private static void Show(NavigationContextConfig context) { IWorkflowManager workflowManager = ServiceRegistration.Get<IWorkflowManager>(); Guid stateId = new Guid("3C6081CB-88DC-44A7-9E17-8D7BFE006EE5"); if (workflowManager.IsAnyStateContainedInNavigationStack(new Guid[] { stateId })) workflowManager.NavigatePopToState(stateId, false); else workflowManager.NavigatePush(stateId, context); }
public static void Show(IProgram program) { NavigationContextConfig navigationContextConfig = new NavigationContextConfig(); navigationContextConfig.AdditionalContextVariables = new Dictionary<string, object>(); navigationContextConfig.AdditionalContextVariables[SlimTvClientModel.KEY_PROGRAM] = program; navigationContextConfig.AdditionalContextVariables[SlimTvClientModel.KEY_MODE] = false; Show(navigationContextConfig); }
public static void Show(ISchedule schedule) { NavigationContextConfig navigationContextConfig = new NavigationContextConfig(); navigationContextConfig.AdditionalContextVariables = new Dictionary<string, object>(); navigationContextConfig.AdditionalContextVariables[SlimTvClientModel.KEY_SCHEDULE] = schedule; navigationContextConfig.AdditionalContextVariables[SlimTvClientModel.KEY_MODE] = true; Show(navigationContextConfig); }