/// <summary> /// 요소를 스택에 추가 /// </summary> /// <param name="item">추가할 요소</param> public virtual void Push(T item) { if (IsDebugEnabled) { log.Debug("Stack에 요소를 추가합니다. item=[{0}]", item); } lock (_syncLock) { InnerStack.Push(item); Monitor.Pulse(_syncLock); } }
private T FindFirstOfType <T>() where T : InnerStack <TViewModel> { for (int index = _innerStacks.Count - 1; index >= 0; index--) { InnerStack <TViewModel> stack = _innerStacks[index]; if (stack is T result) { return(result); } } return(null); }
private static UIViewController AsViewController(InnerStack item) { switch (item) { case SimpleControllerInnerStack simpleControllerInnerStack: return(simpleControllerInnerStack.Controller); case ModalControllerInnerStack modalControllerInnerStack: return(AsViewController(modalControllerInnerStack.Modal)); default: throw new NotSupportedException($"Unsupported type of {item.GetType().Name}"); } }
/// <summary> /// 스택에서 요소를 꺼냄, 꺼낼 요소가 없으면 기다립니다. /// </summary> /// <returns>요소</returns> public virtual T Pop() { if (IsDebugEnabled) { log.Debug("Stack에서 요소를 꺼냅니다. 꺼낼 요소가 없으면 기다립니다..."); } lock (_syncLock) { while (InnerStack.Count == 0) { Monitor.Wait(_syncLock); } return(InnerStack.Pop()); } }
/// <summary> /// Stack에서 최상위 요소를 조회합니다. Stack이 비었으면 default(T)를 반환합니다. /// </summary> /// <returns>요소</returns> public virtual T Peek() { if (IsDebugEnabled) { log.Debug("Stack에서 최상위 요소를 조회합니다. Stack이 비었으면 기다리지 않고, default(T)를 반환합니다."); } lock (_syncLock) { if (InnerStack.Count == 0) { return(default(T)); } return(InnerStack.Peek()); } }
/// <summary> /// 스텍에서 요소를 꺼내본다. 꺼낼 요소가 없으면 False를 반환하고, item 은 default(T)가 설정된다. /// </summary> /// <param name="item">꺼낼 요소</param> /// <returns>꺼낼 요소가 없으면 False를 반환하고, item 은 default(T)가 설정된다.</returns> public virtual bool TryPop(out T item) { if (IsDebugEnabled) { log.Debug("스텍에서 요소를 꺼내본다. 꺼낼 요소가 없으면 기다리지 않고, False를 반환하고, item 은 default(T)가 설정된다."); } lock (_syncLock) { if (InnerStack.Count > 0) { item = InnerStack.Pop(); return(true); } item = default(T); return(false); } }
private List <PushOperation> Push(List <PushInformation <TViewModel> > pushInformations) { List <PushOperation> pushOperations = new List <PushOperation>(); InnerStack <TViewModel> top = null; if (_innerStacks.Count > 0) { top = _innerStacks[_innerStacks.Count - 1]; } foreach (var pushInformation in pushInformations) { if (pushInformation.Factory is ActivityViewFactory activityViewFactory) { var activityInnerStack = new ActivityInnerStack <TViewModel>(this, activityViewFactory.ActivityType, activityIsOnlyAFragmentContainer: false, shouldClearHistory: activityViewFactory.ShouldClearHistory); pushOperations.Add(new ActivityPushOperation <TViewModel>(activityInnerStack, pushInformation.Instance.ViewModelInstance)); top = activityInnerStack; _innerStacks.Add(top); } else if (pushInformation.Factory is DialogFragmentViewFactory dialogFragmentViewFactory) { var host = top.GetActivityInnerStack(); if (host == null) { //need to push the activity first var activityInnerStack = new ActivityInnerStack <TViewModel>(this, dialogFragmentViewFactory.HostActivityType, activityIsOnlyAFragmentContainer: true, shouldClearHistory: dialogFragmentViewFactory.ShouldClearHistory); pushOperations.Add(new ActivityPushOperation <TViewModel>(activityInnerStack, viewModel: null)); top = host = activityInnerStack; _innerStacks.Add(top); } var fragment = dialogFragmentViewFactory.Creator(); //we set screeninformation to the fragment can retrieve its viewmodel if (fragment is IScreenView screenView) { screenView.ScreenRoute = pushInformation.Instance.ToString(); _viewModelLocatorService.AddViewModel(pushInformation.Instance.ToString(), pushInformation.Instance.ViewModelInstance); } var dialogFragmentInnerStack = new DialogFragmentInnerStack <TViewModel>(this, host, fragment); pushOperations.Add(new FragmentPushOperation <TViewModel>(host) { FragmentStacksToPush = { dialogFragmentInnerStack } }); top = dialogFragmentInnerStack; _innerStacks.Add(top); } else if (pushInformation.Factory is FragmentViewFactory fragmentViewFactory) { var activityHost = top.GetActivityInnerStack(); if (activityHost == null) { //need to push the activity first var activityInnerStack = new ActivityInnerStack <TViewModel>(this, fragmentViewFactory.HostActivityType, activityIsOnlyAFragmentContainer: true, shouldClearHistory: fragmentViewFactory.ShouldClearHistory); pushOperations.Add(new ActivityPushOperation <TViewModel>(activityInnerStack, viewModel: null)); top = activityHost = activityInnerStack; _innerStacks.Add(top); } var fragment = fragmentViewFactory.Creator(); //we set screeninformation to the fragment can retrieve its viewmodel if (fragment is IScreenView screenView) { screenView.ScreenRoute = pushInformation.Instance.ToString(); _viewModelLocatorService.AddViewModel(pushInformation.Instance.ToString(), pushInformation.Instance.ViewModelInstance); } var fragmentInnerStack = new FragmentInnerStack <TViewModel>(this, activityHost, fragment); pushOperations.Add(new FragmentPushOperation <TViewModel>(activityHost) { FragmentStacksToPush = { fragmentInnerStack } }); activityHost.FragmentStack.Add(fragmentInnerStack); } else { throw new InvalidOperationException("This kind of factory is not supported..."); } } //simplify list of pop operations int insertIndex = 0; for (int i = 1; i < pushOperations.Count; i++) { if (TryMerge(pushOperations[insertIndex], pushOperations[i], out PushOperation op)) { pushOperations[insertIndex] = op; } else { insertIndex++; if (insertIndex != i) { pushOperations[insertIndex] = pushOperations[i]; } } } if (insertIndex < pushOperations.Count - 1) { int firstIndexToRemove = insertIndex + 1; pushOperations.RemoveRange(firstIndexToRemove, pushOperations.Count - firstIndexToRemove); } return(pushOperations); }