using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.ComponentModel;
using System.Collections.ObjectModel;
using BuzzGUI.Interfaces;
using BuzzGUI.Common;
using System.Windows.Threading;
using PropertyChanged;
namespace BuzzGUI.MachineView.CPUMonitor
{
///
/// Interaction logic for CPUMonitorWindow.xaml
///
public partial class CPUMonitorWindow : Window
{
IMachineGraph machineGraph;
public IMachineGraph MachineGraph
{
get { return machineGraph; }
set
{
if (machineGraph != null)
{
machineGraph.MachineAdded -= new Action(machineGraph_MachineAdded);
machineGraph.MachineRemoved -= new Action(machineGraph_MachineRemoved);
ClearMachines();
}
machineGraph = value;
if (machineGraph != null)
{
machineGraph.MachineAdded += new Action(machineGraph_MachineAdded);
machineGraph.MachineRemoved += new Action(machineGraph_MachineRemoved);
AddAllMachines();
}
}
}
[DoNotNotify]
public class MachineVM : INotifyPropertyChanged
{
MachinePerformanceData perfData;
public IMachine Machine { get; private set; }
public string Name { get { return Machine.Name; } }
public double CPUUsage { get; private set; }
public string CPUUsageString { get; private set; }
public long CCPerSample { get; private set; }
public long MaxLockTime { get; private set; }
public MachineVM(IMachine m)
{
Machine = m;
Machine.PropertyChanged += Machine_PropertyChanged;
}
public void Release()
{
Machine.PropertyChanged -= Machine_PropertyChanged;
}
void Machine_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "Name")
PropertyChanged.Raise(this, "Name");
}
internal void Update(long dt)
{
if (perfData == null)
{
perfData = Machine.PerformanceData;
return;
}
var newpd = Machine.PerformanceData;
if (dt > 0)
{
long dpc = newpd.PerformanceCount - perfData.PerformanceCount;
CPUUsage = 100.0 * dpc / dt;
CPUUsageString = string.Format("{0:F1}%", CPUUsage);
PropertyChanged.Raise(this, "CPUUsage");
PropertyChanged.Raise(this, "CPUUsageString");
}
long ds = newpd.SampleCount - perfData.SampleCount;
if (ds > 0)
{
long dcc = newpd.CycleCount - perfData.CycleCount;
CCPerSample = dcc / ds;
PropertyChanged.Raise(this, "CCPerSample");
}
if (perfData.MaxEngineLockTime > MaxLockTime)
{
MaxLockTime = perfData.MaxEngineLockTime;
PropertyChanged.Raise(this, "MaxLockTime");
}
perfData = newpd;
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
#endregion
}
ObservableCollection machines = new ObservableCollection();
void AddAllMachines()
{
foreach (var m in machineGraph.Machines)
machines.Add(new MachineVM(m));
}
void ClearMachines()
{
machines.Clear();
}
void machineGraph_MachineAdded(IMachine m)
{
machines.Add(new MachineVM(m));
}
void machineGraph_MachineRemoved(IMachine m)
{
var mvm = machines.First(vm => vm.Machine == m);
mvm.Release();
machines.Remove(mvm);
}
DispatcherTimer timer;
BuzzPerformanceData buzzPerfData;
public CPUMonitorWindow()
{
this.DataContext = this;
InitializeComponent();
listView.ItemsSource = machines;
this.Loaded += (sender, e) =>
{
SetSortColumn((listView.View as GridView).Columns[0].Header as GridViewColumnHeader);
};
this.IsVisibleChanged += (sender, e) =>
{
if (IsVisible && timer == null)
{
SetTimer();
}
else if (!IsVisible && timer != null)
{
timer.Stop();
timer = null;
}
};
}
void SetTimer()
{
timer = new DispatcherTimer();
timer.Interval = TimeSpan.FromMilliseconds(250);
timer.Tick += (sender, e) =>
{
if (machineGraph == null) return;
machineGraph.Buzz.TakePerformanceDataSnapshot();
if (buzzPerfData == null)
{
buzzPerfData = machineGraph.Buzz.PerformanceData;
foreach (var m in machines)
m.Update(0);
return;
}
var newpd = machineGraph.Buzz.PerformanceData;
long dt = newpd.PerformanceCount - buzzPerfData.PerformanceCount;
foreach (var m in machines)
m.Update(dt);
if (dt > 0)
{
long det = newpd.EnginePerformanceCount - buzzPerfData.EnginePerformanceCount;
double total = 100.0 * det / dt;
totalText.Text = string.Format("Total: {0:F1}%", total);
double overhead = total - machines.Sum(m => m.CPUUsage);
overheadText.Text = string.Format("Overhead: {0:F1}%", overhead);
}
buzzPerfData = newpd;
};
timer.Start();
}
#region Sorting
SortAdorner sortAdorner;
GridViewColumnHeader sortColumn;
private void SortClick(object sender, RoutedEventArgs e)
{
SetSortColumn(sender as GridViewColumnHeader);
}
void SetSortColumn(GridViewColumnHeader column)
{
var field = column.Tag as string;
if (sortColumn != null)
{
AdornerLayer.GetAdornerLayer(sortColumn).Remove(sortAdorner);
listView.Items.SortDescriptions.Clear();
}
var newDir = ListSortDirection.Ascending;
if (sortColumn == column && sortAdorner.Direction == newDir)
newDir = ListSortDirection.Descending;
sortColumn = column;
sortAdorner = new SortAdorner(sortColumn, newDir);
AdornerLayer.GetAdornerLayer(sortColumn).Add(sortAdorner);
listView.Items.SortDescriptions.Add(new SortDescription(field, newDir));
}
public class SortAdorner : Adorner
{
private readonly static Geometry _AscGeometry = Geometry.Parse("M 0,5 L 10,5 L 5,0 Z");
private readonly static Geometry _DescGeometry = Geometry.Parse("M 0,0 L 10,0 L 5,5 Z");
public ListSortDirection Direction { get; private set; }
public SortAdorner(UIElement element, ListSortDirection dir) : base(element) { Direction = dir; }
protected override void OnRender(DrawingContext drawingContext)
{
base.OnRender(drawingContext);
if (AdornedElement.RenderSize.Width < 20) return;
drawingContext.PushTransform(new TranslateTransform(AdornedElement.RenderSize.Width - 15, (AdornedElement.RenderSize.Height - 5) / 2));
drawingContext.DrawGeometry(this.GetValue(Control.ForegroundProperty) as Brush, null, Direction == ListSortDirection.Ascending ? _AscGeometry : _DescGeometry);
drawingContext.Pop();
}
}
#endregion
public TextFormattingMode TextFormattingMode { get { return Global.GeneralSettings.WPFIdealFontMetrics ? TextFormattingMode.Ideal : TextFormattingMode.Display; } }
}
}