public void DrawBackground(Graphics Gfx, Rectangle Bounds) { Color FillColor = SystemColors.ControlLightLight; ProgressionSample Sample = ProgressionSamples[ProgressionSamples.Count - 1]; if (Sample.State >= EProgressionState.RemoteDisconnected) { FillColor = SystemColors.ControlLight; } Gfx.Clear(FillColor); }
/* * Advance all active timers */ public bool Tick() { bool Invalidate = false; foreach (Progression MachineProgression in MachineProgressions.Values) { List <ProgressionSample> Samples = MachineProgression.ProgressionSamples; ProgressionSample Sample = Samples[Samples.Count - 1]; if (Sample.State < EProgressionState.RemoteDisconnected) { Sample.AddTimestamp(DateTime.UtcNow); Invalidate = true; } } return(Invalidate); }
private void MouseMoveHandler(object sender, MouseEventArgs e) { Point GridClientPos = this.VisualiserGridView.PointToClient(MousePosition); DataGridView.HitTestInfo HitInfo = this.VisualiserGridView.HitTest(GridClientPos.X, GridClientPos.Y); bool bShowingToolTip = false; if (HitInfo.Type == DataGridViewHitTestType.ColumnHeader && HitInfo.ColumnIndex == 1) { float Timestamp = GridClientPos.X - HitInfo.ColumnX; Timestamp /= AgentApplication.Options.VisualiserZoomLevel; Point AgentClientPos = PointToClient(MousePosition); string ToolTipText = String.Format("Time: {0:g4} seconds", Timestamp); BarToolTip.Show(ToolTipText, this, AgentClientPos.X, AgentClientPos.Y, 60000); bShowingToolTip = true; } else if (HitInfo.Type == DataGridViewHitTestType.Cell && HitInfo.ColumnIndex == 1) { DataGridViewCell cell = this.VisualiserGridView.Rows[HitInfo.RowIndex].Cells[1]; string Machine = ( string )VisualiserGridView.Rows[HitInfo.RowIndex].Cells[0].Value; Progression MachineProgression = null; if (ProgressionData.MachineProgressions.TryGetValue(Machine, out MachineProgression)) { for (int BarIndex = 1; BarIndex < MachineProgression.ProgressionSamples.Count; BarIndex++) { ProgressionSample Sample = MachineProgression.ProgressionSamples[BarIndex]; if (Sample.Bounds.Contains(GridClientPos)) { Point AgentClientPos = PointToClient(MousePosition); string BarName = BarNames[Sample.State.ToString()]; string ToolTipText = String.Format("{0} ({1:g4} seconds)", BarName, Sample.Duration); BarToolTip.Show(ToolTipText, this, AgentClientPos.X, AgentClientPos.Y, 60000); bShowingToolTip = true; break; } } } } if (!bShowingToolTip) { BarToolTip.Hide(this); } }
/* * Process a state change timing event */ public bool ProcessEvent(ProgressionEvent Event) { // Overall progress info if (Event.State < EProgressionState.Idle) { switch (Event.State) { case EProgressionState.TaskTotal: NumTasks = Event.ThreadNum; break; case EProgressionState.TasksCompleted: NumRetiredTasks = Event.ThreadNum; break; case EProgressionState.TasksInProgress: NumRunningTasks = Event.ThreadNum; break; } return(true); } // Handle per machine stats Progression MachineProgression = null; if (!MachineProgressions.TryGetValue(Event.Machine, out MachineProgression)) { MachineProgressions.Add(Event.Machine, new Progression()); MachineProgressions.TryGetValue(Event.Machine, out MachineProgression); } List <ProgressionSample> Samples = MachineProgression.ProgressionSamples; ProgressionSample LastSample = Samples[Samples.Count - 1]; // If this machine has disconnected, ignore any further messages if (LastSample.State >= EProgressionState.RemoteDisconnected) { return(true); } // Coarse tracking on a per machine basis bool bCreateNewSample = (LastSample.State != Event.State) || (Event.ThreadNum >= 0 && LastSample.ThreadSamples == null) || (Event.ThreadNum < 0 && LastSample.ThreadSamples != null); if (bCreateNewSample == false) { // Just updating the same event, add timestamp LastSample.AddTimestamp(Event.Time); } else { // If the previous sample have proper Start and End timestamps, add one if (LastSample.NumTimestamps <= 1) { LastSample.AddTimestamp(Event.Time); } // If the previous sample has individual thread samples, make sure they're all ended if ((LastSample.ThreadSamples != null) && (LastSample.ThreadSamples.Count > 0)) { foreach (ProgressionThreadSample NextThreadSample in LastSample.ThreadSamples) { if (NextThreadSample.NumTimestamps <= 1) { NextThreadSample.AddTimestamp(Event.Time); } } } } if (Event.ThreadNum < 0) { if (bCreateNewSample) { Samples.Add(new ProgressionSample(Event.State, Event.Time)); } } else if (Event.ThreadNum >= 0) { if (bCreateNewSample) { // Previous sample was of a different kind, so create a new per-thread instance. LastSample = new ProgressionSample(Event.State, Event.Time); LastSample.ThreadSamples = new List <ProgressionThreadSample>(); Samples.Add(LastSample); } // Optional more detailed per thread tracking while (LastSample.ThreadSamples.Count <= Event.ThreadNum) { List <ProgressionThreadSample> ThreadSamples = new List <ProgressionThreadSample>(); ProgressionThreadSample ThreadSample = new ProgressionThreadSample(Event.State); LastSample.ThreadSamples.Add(ThreadSample); } LastSample.ThreadSamples[Event.ThreadNum].AddTimestamp(Event.Time); } // If we've had a disconnect message, make sure all progressions are terminated if (Event.State == EProgressionState.InstigatorDisconnected) { Samples.Add(new ProgressionSample(Event.State, Event.Time)); // Make sure all progress bars stop as there will be no more messages foreach (Progression ProgressionMachine in MachineProgressions.Values) { List <ProgressionSample> ProgressionSamples = ProgressionMachine.ProgressionSamples; LastSample = ProgressionSamples[ProgressionSamples.Count - 1]; if (LastSample.State < EProgressionState.RemoteDisconnected) { ProgressionSamples.Add(new ProgressionSample(EProgressionState.RemoteDisconnected, Event.Time)); } } return(true); } return(bCreateNewSample); }
public int Draw(DateTime Start, float ZoomLevel, Graphics Gfx, Rectangle Bounds) { int Rightmost = 0; int Offset = BarBorder + Bounds.Left; // Work out initial offset so all the bars are on the same time rule ProgressionSample LastSample = ProgressionSamples[ProgressionSamples.Count - 1]; int Top = Bounds.Top + BarBorder; int Height = Bounds.Height - (BarBorder * 2); for (int BarIndex = 1; BarIndex < ProgressionSamples.Count; BarIndex++) { ProgressionSample NewSample = ProgressionSamples[BarIndex]; // Render progress bars if (NewSample.ThreadSamples == null) { int Left = ( int )((NewSample.StartTime - Start).TotalSeconds * ZoomLevel); int Right = ( int )((NewSample.EndTime - Start).TotalSeconds * ZoomLevel); if (Right - Left > 2) { DrawFilledBar(Gfx, NewSample.State, Left + Offset, Top, Right - Left, Height); NewSample.Bounds = new Rectangle(Left + Offset, Top, Right - Left, Height); NewSample.Duration = (NewSample.EndTime - NewSample.StartTime).TotalSeconds; if (Right > Rightmost) { Rightmost = Right; } } } else { // Render a line per thread with ticks for new jobs int HeightPerThread = Math.Max(Height / NewSample.ThreadSamples.Count, 2); int ThreadTop = Top; int AccumulatedThreadHeight = 0; int BarThreadLeft = 0; int BarThreadRight = 0; int BarThreadLeftMost = Int32.MaxValue; int BarThreadRightMost = 0; foreach (ProgressionThreadSample ThreadSample in NewSample.ThreadSamples) { if (AccumulatedThreadHeight < Height) { // Draw the thread line BarThreadLeft = (int)(ZoomLevel * (ThreadSample.StartTime - Start).TotalSeconds); if (BarIndex < (ProgressionSamples.Count - 1) || ThreadSample.StartTime != ThreadSample.EndTime) { BarThreadRight = (int)(ZoomLevel * (ThreadSample.EndTime - Start).TotalSeconds); } else if (LastSample.State >= EProgressionState.RemoteDisconnected) { BarThreadRight = (int)(ZoomLevel * (LastSample.StartTime - Start).TotalSeconds); } else { BarThreadRight = (int)(ZoomLevel * (DateTime.UtcNow - Start).TotalSeconds); } // Make sure each bar is at least 1 unit wide, and maintain extrema. if (BarThreadRight <= BarThreadLeft) { BarThreadRight = BarThreadLeft + 1; } if (BarThreadLeft < BarThreadLeftMost) { BarThreadLeftMost = BarThreadLeft; } if (BarThreadRight > BarThreadRightMost) { BarThreadRightMost = BarThreadRight; } Rectangle ThreadBar = new Rectangle(BarThreadLeft + Offset, ThreadTop + 1, BarThreadRight - BarThreadLeft, HeightPerThread - 1); BarColour ThreadBarColor = BarColours[ThreadSample.State.ToString()]; Gfx.FillRectangle(ThreadBarColor.FillBrush, ThreadBar); ThreadTop += HeightPerThread; AccumulatedThreadHeight += HeightPerThread; } } // Add a border NewSample.Bounds = new Rectangle(BarThreadLeftMost + Offset, Top, BarThreadRightMost - BarThreadLeftMost, Height); NewSample.Duration = NewSample.Bounds.Width / ZoomLevel; Gfx.DrawRectangle(Pens.Black, NewSample.Bounds); if (BarThreadRightMost > Rightmost) { Rightmost = BarThreadRightMost; } } } ProgressTotalWidth = Rightmost; return(Rightmost); }
/* * Process a state change timing event */ public bool ProcessEvent( ProgressionEvent Event ) { // Overall progress info if( Event.State < EProgressionState.Idle ) { switch( Event.State ) { case EProgressionState.TaskTotal: NumTasks = Event.ThreadNum; break; case EProgressionState.TasksCompleted: NumRetiredTasks = Event.ThreadNum; break; case EProgressionState.TasksInProgress: NumRunningTasks = Event.ThreadNum; break; } return ( true ); } // Handle per machine stats Progression MachineProgression = null; if( !MachineProgressions.TryGetValue( Event.Machine, out MachineProgression ) ) { MachineProgressions.Add( Event.Machine, new Progression() ); MachineProgressions.TryGetValue( Event.Machine, out MachineProgression ); } List<ProgressionSample> Samples = MachineProgression.ProgressionSamples; ProgressionSample LastSample = Samples[Samples.Count - 1]; // If this machine has disconnected, ignore any further messages if( LastSample.State >= EProgressionState.RemoteDisconnected ) { return ( true ); } // Coarse tracking on a per machine basis bool bCreateNewSample = (LastSample.State != Event.State) || (Event.ThreadNum >= 0 && LastSample.ThreadSamples == null) || (Event.ThreadNum < 0 && LastSample.ThreadSamples != null); if( bCreateNewSample == false ) { // Just updating the same event, add timestamp LastSample.AddTimestamp( Event.Time ); } else { // If the previous sample have proper Start and End timestamps, add one if( LastSample.NumTimestamps <= 1 ) { LastSample.AddTimestamp( Event.Time ); } // If the previous sample has individual thread samples, make sure they're all ended if( ( LastSample.ThreadSamples != null ) && ( LastSample.ThreadSamples.Count > 0 ) ) { foreach( ProgressionThreadSample NextThreadSample in LastSample.ThreadSamples ) { if( NextThreadSample.NumTimestamps <= 1 ) { NextThreadSample.AddTimestamp( Event.Time ); } } } } if( Event.ThreadNum < 0 ) { if ( bCreateNewSample ) { Samples.Add( new ProgressionSample( Event.State, Event.Time ) ); } } else if( Event.ThreadNum >= 0 ) { if ( bCreateNewSample ) { // Previous sample was of a different kind, so create a new per-thread instance. LastSample = new ProgressionSample( Event.State, Event.Time ); LastSample.ThreadSamples = new List<ProgressionThreadSample>(); Samples.Add( LastSample ); } // Optional more detailed per thread tracking while( LastSample.ThreadSamples.Count <= Event.ThreadNum ) { List<ProgressionThreadSample> ThreadSamples = new List<ProgressionThreadSample>(); ProgressionThreadSample ThreadSample = new ProgressionThreadSample( Event.State ); LastSample.ThreadSamples.Add( ThreadSample ); } LastSample.ThreadSamples[Event.ThreadNum].AddTimestamp( Event.Time ); } // If we've had a disconnect message, make sure all progressions are terminated if( Event.State == EProgressionState.InstigatorDisconnected ) { Samples.Add( new ProgressionSample( Event.State, Event.Time ) ); // Make sure all progress bars stop as there will be no more messages foreach( Progression ProgressionMachine in MachineProgressions.Values ) { List<ProgressionSample> ProgressionSamples = ProgressionMachine.ProgressionSamples; LastSample = ProgressionSamples[ProgressionSamples.Count - 1]; if( LastSample.State < EProgressionState.RemoteDisconnected ) { ProgressionSamples.Add( new ProgressionSample( EProgressionState.RemoteDisconnected, Event.Time ) ); } } return ( true ); } return ( bCreateNewSample ); }