/Sources/Applications/Observatory/Monitor/ReactRT.Observatory.Monitor.TimelineControl/TimelineViewModel.cs
C# | 349 lines | 266 code | 80 blank | 3 comment | 19 complexity | 4a9d9e1e5f8bd9b81f0a770d64c5523b MD5 | raw file
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Collections.ObjectModel;
- using ReactRT.Observatory.Monitor.Domain;
- using GalaSoft.MvvmLight;
- using System.ComponentModel;
- using GalaSoft.MvvmLight.Command;
- using System.Windows.Input;
- using System.Collections.Specialized;
- using System.Windows.Media;
- using System.Windows;
-
- namespace ReactRT.Observatory.Monitor.TimelineControl {
- /// <summary>
- /// This is the main view-model of the timeline control.
- /// </summary>
- public class TimelineViewModel : ViewModelBase, ITimelinePositionTracker, ISessionInformationProvider {
-
- #region Private fields
-
- private Session _session;
-
- private readonly TimeConverter _timeConverter = new TimeConverter();
-
- private double _currentPosition = 0;
-
- #endregion
-
-
- public TimelineViewModel() {
-
- _timeConverter.PixelsPerMillisecond = 6;
- ZeroPointOffset = 1500;
- JumpToNewReactions = false;
- IsLiveTraceMode = false;
-
- ProgressIndicator = new ProgressIndicatorViewModel();
-
- Axis = new AxisViewModel(this, _timeConverter);
- }
-
-
- #region Events
-
- public event EventHandler<TimelinePositionChangedEventArgs> TimelinePositionChanged = delegate { };
-
- public event EventHandler<SessionDurationChangedEventArgs> SessionDurationChanged = delegate { };
-
- #endregion
-
-
- #region Properties
-
- public AxisViewModel Axis { get; private set; }
-
- public ProgressIndicatorViewModel ProgressIndicator { get; private set; }
-
- public ObservableCollection<StateMachineViewModel> StateMachines { get; private set; }
-
- public ObservableSortedSet<ReactionViewModel> AllReactions { get; private set; }
-
- public double ZeroPointOffset { get; private set; }
-
- public DateTime StartTime { get; private set; }
-
- public DateTime EndTime { get; private set; }
-
- public bool JumpToNewReactions { get; set; }
-
- private bool _hasReactions = false;
- public bool HasReactions {
- get {
- return _hasReactions;
- }
- private set {
- _hasReactions = value;
- RaisePropertyChanged("HasReactions");
- }
- }
-
- public Session ActiveSession {
- get {
- return _session;
- }
- set {
- ActivateNewSession(value);
- }
- }
-
- private bool _isLiveTraceActive = false;
- public bool IsLiveTraceActive {
- get {
- return _isLiveTraceActive;
- }
- set {
- _isLiveTraceActive = value;
- RaisePropertyChanged("IsLiveTraceActive");
- RaisePropertyChanged("LiveTraceStateMessage");
- RaisePropertyChanged("JumpToNewReactions");
- }
- }
-
- public string LiveTraceStateMessage {
- get {
- if (IsLiveTraceActive) {
- return "Live Trace in progress";
- } else {
- return "Live Trace stopped";
- }
- }
- }
-
- private bool _isLiveTraceMode = false;
- public bool IsLiveTraceMode {
- get {
- return _isLiveTraceMode;
- }
- set {
- _isLiveTraceMode = value;
- RaisePropertyChanged("IsLiveTraceMode");
- RaisePropertyChanged("SessionTypeMessage");
- }
- }
-
- public string SessionTypeMessage {
- get {
- if (_session == null) {
- return "";
- } else {
- if (IsLiveTraceMode) {
- return "Live Trace Session";
- } else {
- return "Replay Session";
- }
- }
- }
- }
-
-
- public TimeSpan SessionDuration {
- get {
- if (HasReactions) {
- return _timeConverter.ToRelativeTime(EndTime);
- } else {
- return TimeSpan.FromTicks(0);
- }
- }
- }
-
- public double SessionWidth {
- get {
- return _timeConverter.ToPixels(SessionDuration);
- }
- }
-
- public double CurrentPositionFraction {
- get {
- if (SessionDuration.Ticks > 0) {
- return Convert.ToDouble(CurrentTime.Ticks) / Convert.ToDouble(SessionDuration.Ticks);
- }
- return 0;
- }
- set {
- CurrentTime = TimeSpan.FromTicks(Convert.ToInt64(SessionDuration.Ticks * value));
- }
- }
-
- public double CurrentPosition {
- get {
- return _currentPosition;
- }
- set {
- _currentPosition = value;
- RaiseCurrentPositionChanged();
- }
- }
-
- public double CurrentScrollPosition {
- get {
- return CurrentPosition + ZeroPointOffset;
- }
- set {
- CurrentPosition = value - ZeroPointOffset;
- }
- }
-
- public TimeSpan CurrentTime {
- get {
- TimeSpan current = _timeConverter.ToTimeSpan(CurrentPosition);
- if (current < TimeSpan.FromTicks(0)) {
- return TimeSpan.FromTicks(0);
- }
- return current;
- }
- set {
- CurrentPosition = _timeConverter.ToPixels(value);
- }
- }
-
- #endregion
-
-
- #region Commands
-
- public RelayCommand NextCommand {
- get {
- return new RelayCommand(SkipToNextReaction);
- }
- }
-
- public RelayCommand PreviousCommand {
- get {
- return new RelayCommand(SkipToPreviousReaction);
- }
- }
-
- public RelayCommand StopLiveTracingCommand {
- get {
- return new RelayCommand(StopLiveTracing, () => IsLiveTraceActive);
- }
- }
-
- #endregion
-
-
- #region Public Methods
-
- public void OnLoaded() {
- CurrentTime = TimeSpan.FromTicks(0);
- }
-
- public void StopLiveTracing() {
- if (IsLiveTraceActive) {
- _session.RawEventLogProvider.Stop();
- IsLiveTraceActive = false;
- }
- }
-
- #endregion
-
-
- #region Helper Methods
-
- private void ActivateNewSession(Session newSession) {
- Reset();
-
- _session = newSession;
-
- ProgressIndicator.SetSession(_session);
-
- IsLiveTraceMode = !_session.IsReplaySession;
- IsLiveTraceActive = !_session.IsReplaySession;
-
- _session.StateMachines.ForEach(CreateStateMachineViewModel);
- }
-
- private void Reset() {
- HasReactions = false;
- JumpToNewReactions = false;
- _timeConverter.Reset();
- CurrentTime = TimeSpan.FromTicks(0);
-
- StateMachines = new ObservableCollection<StateMachineViewModel>();
- AllReactions = new ObservableSortedSet<ReactionViewModel>();
- RaisePropertyChanged("StateMachines");
- RaisePropertyChanged("AllReactions");
- RaiseSessionDurationChanged();
- }
-
- private void CreateStateMachineViewModel(StateMachine stateMachine) {
- StateMachineViewModel smvm = new StateMachineViewModel(stateMachine, this, _timeConverter);
- StateMachines.Add(smvm);
-
- smvm.ReactionViewModelCreated += (object sender, ReactionViewModelCreatedEventArgs e) => HandleReactionViewModelCreated(e.Reaction);
- }
-
- private void EstablishSessionStartReference(ReactionViewModel firstReaction) {
- StartTime = firstReaction.AbsoluteStartTime;
- EndTime = firstReaction.AbsoluteEndTime;
-
- _timeConverter.SetStartReference(StartTime);
-
- HasReactions = true;
-
- RaisePropertyChanged("StartTime");
- RaiseSessionDurationChanged();
-
- CurrentTime = TimeSpan.FromTicks(0);
- }
-
- private void HandleReactionViewModelCreated(ReactionViewModel rvm) {
- AllReactions.Add(rvm);
-
- if (!HasReactions) {
- EstablishSessionStartReference(rvm);
- }
-
- if (EndTime < rvm.AbsoluteEndTime) {
- EndTime = rvm.AbsoluteEndTime;
- RaiseSessionDurationChanged();
- }
-
- if (JumpToNewReactions) {
- CurrentPosition = rvm.Offset;
- }
- }
-
- private void SkipToNextReaction() {
- Func<ReactionViewModel, bool> laterThanCurrent = (ReactionViewModel rvm) => rvm.StartTime > CurrentTime + TimeSpan.FromMilliseconds(1);
-
- if (AllReactions.Count(laterThanCurrent) > 0) {
- CurrentTime = AllReactions.FirstOrDefault(laterThanCurrent).StartTime;
- } else {
- CurrentTime = SessionDuration;
- }
- }
-
- private void SkipToPreviousReaction() {
- Func<ReactionViewModel, bool> earlierThanCurrent = (ReactionViewModel rvm) => rvm.StartTime < CurrentTime - TimeSpan.FromMilliseconds(1);
-
- if (AllReactions.Count(earlierThanCurrent) > 0) {
- CurrentTime = AllReactions.LastOrDefault(earlierThanCurrent).StartTime;
- } else {
- CurrentTime = TimeSpan.FromTicks(0);
- }
- }
-
- private void RaiseSessionDurationChanged() {
- RaisePropertyChanged("EndTime");
- RaisePropertyChanged("SessionDuration");
- RaisePropertyChanged("SessionWidth");
-
- SessionDurationChanged(this, new SessionDurationChangedEventArgs(SessionDuration));
- }
-
- private void RaiseCurrentPositionChanged() {
- RaisePropertyChanged("CurrentPosition");
- RaisePropertyChanged("CurrentScrollPosition");
- RaisePropertyChanged("CurrentPositionFraction");
- RaisePropertyChanged("CurrentTime");
-
- TimelinePositionChanged(this, new TimelinePositionChangedEventArgs(CurrentPosition, CurrentTime));
- }
-
- #endregion
- }
- }