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.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Profiler.Data;
using System.Windows.Media;
using System.Windows.Controls.Primitives;
using System.Globalization;
using System.Threading;
using System.ComponentModel;
using Profiler.DirectX;
using System.Windows.Threading;
using System.Diagnostics;
using Profiler.Controls;
using System.Threading.Tasks;
namespace Profiler.Controls
{
///
/// Interaction logic for ThreadView.xaml
///
public partial class ThreadViewControl : UserControl
{
public ThreadScroll Scroll { get; set; } = new ThreadScroll();
private List Rows = new List();
private SolidColorBrush _optickBackground;
public SolidColorBrush OptickBackground { get { if (_optickBackground == null) _optickBackground = FindResource("OptickBackground") as SolidColorBrush; return _optickBackground; } }
private SolidColorBrush _optickAlternativeBackground;
public SolidColorBrush OptickAlternativeBackground { get { if (_optickAlternativeBackground == null) _optickAlternativeBackground = FindResource("OptickAlternative") as SolidColorBrush; return _optickAlternativeBackground; } }
private SolidColorBrush _frameSelection;
public SolidColorBrush FrameSelection { get { if (_frameSelection == null) _frameSelection = FindResource("OptickFrameSelection") as SolidColorBrush; return _frameSelection; } }
private SolidColorBrush _frameHover;
public SolidColorBrush FrameHover { get { if (_frameHover == null) _frameHover = FindResource("OptickFrameHover") as SolidColorBrush; return _frameHover; } }
Color MeasureBackground;
Color HoverBackground;
void InitColors()
{
MeasureBackground = Color.FromArgb(100, 0, 0, 0);
HoverBackground = Color.FromArgb(170, 0, 0, 0);
}
public bool ShowThreadHeaders { get; set; } = true;
public bool ShowFrameLines { get; set; } = true;
Mesh BackgroundMesh { get; set; }
Mesh ForegroundMesh { get; set; }
public delegate void HighlightFrameEventHandler(object sender, HighlightFrameEventArgs e);
public static readonly RoutedEvent HighlightFrameEvent = EventManager.RegisterRoutedEvent("HighlightFrameEvent", RoutingStrategy.Bubble, typeof(HighlightFrameEventHandler), typeof(ThreadViewControl));
public void UpdateRows()
{
ThreadList.Children.Clear();
ThreadList.RowDefinitions.Clear();
ThreadList.Margin = new Thickness(0, 0, 3, 0);
double offset = 0.0;
bool isAlternative = false;
int rowCount = 0;
for (int threadIndex = 0; threadIndex < Rows.Count; ++threadIndex)
{
ThreadRow row = Rows[threadIndex];
row.Offset = offset;
if (!row.IsVisible)
continue;
if (ShowThreadHeaders)
{
ThreadList.RowDefinitions.Add(new RowDefinition());
Border border = new Border()
{
Height = row.Height / RenderSettings.dpiScaleY,
};
FrameworkElement header = row.Header;
if (header != null && header.Parent != null && (header.Parent is Border))
(header.Parent as Border).Child = null;
border.Child = row.Header;
border.Background = isAlternative ? OptickAlternativeBackground : OptickBackground;
Grid.SetRow(border, rowCount);
ThreadList.Children.Add(border);
}
isAlternative = !isAlternative;
offset += row.Height;
rowCount += 1;
}
Scroll.Height = offset;
double controlHeight = offset / RenderSettings.dpiScaleY;
surface.Height = controlHeight;
surface.MaxHeight = controlHeight;
InitBackgroundMesh();
}
public void InitRows(List rows, IDurable timeslice)
{
Rows = rows;
if (rows.Count > 0)
{
Scroll.TimeSlice = new Durable(timeslice.Start, timeslice.Finish);
Scroll.Width = surface.ActualWidth * RenderSettings.dpiScaleX;
rows.ForEach(row => row.BuildMesh(surface, Scroll));
rows.ForEach(row => row.ExpandChanged += Row_ExpandChanged);
rows.ForEach(row => row.VisibilityChanged += Row_VisibilityChanged);
}
UpdateRows();
}
public void ReinitRows(List rows)
{
rows.ForEach(row => row.BuildMesh(surface, Scroll));
UpdateRowsAsync();
}
private void Row_ExpandChanged(ThreadRow row)
{
//Task.Run(()=>
//{
row.BuildMesh(surface, Scroll);
UpdateRowsAsync();
//});
}
private void UpdateRowsAsync()
{
Application.Current.Dispatcher.BeginInvoke(new Action(() => UpdateRows()));
}
private void Row_VisibilityChanged(ThreadRow row)
{
//throw new NotImplementedException();
}
private void InitBackgroundMesh()
{
if (BackgroundMesh != null)
BackgroundMesh.Dispose();
DynamicMesh backgroundBuilder = surface.CreateMesh();
backgroundBuilder.Projection = Mesh.ProjectionType.Pixel;
double offset = 0.0;
bool isAlternative = false;
for (int threadIndex = 0; threadIndex < Rows.Count; ++threadIndex)
{
ThreadRow row = Rows[threadIndex];
if (!row.IsVisible)
continue;
backgroundBuilder.AddRect(new Rect(0.0, offset, Scroll.Width, row.Height), isAlternative ? OptickAlternativeBackground.Color : OptickBackground.Color);
isAlternative = !isAlternative;
offset += row.Height;
}
BackgroundMesh = backgroundBuilder.Freeze(surface.RenderDevice);
}
public void InitForegroundLines(List lines)
{
if (ForegroundMesh != null)
ForegroundMesh.Dispose();
DynamicMesh builder = surface.CreateMesh();
builder.Geometry = Mesh.GeometryType.Lines;
// Adding Frame separators
if (lines != null)
{
foreach (ITick line in lines)
{
double x = Scroll.TimeToUnit(line);
builder.AddLine(new Point(x, 0.0), new Point(x, 1.0), OptickAlternativeBackground.Color);
}
}
ForegroundMesh = builder.Freeze(surface.RenderDevice);
}
DynamicMesh SelectionMesh;
DynamicMesh HoverMesh;
DynamicMesh HoverLines;
DynamicMesh MeasureMesh;
public TooltipInfo ToolTipPanel { get; set; }
public class TooltipInfo
{
public String Text;
public Rect Rect;
public void Reset()
{
Text = String.Empty;
Rect = new Rect();
}
}
const double DefaultFrameZoom = 1.10;
public void Highlight(IEnumerable items, bool focus = true)
{
SelectionList = new List(items);
if (focus)
{
foreach (Selection s in items)
{
Interval interval = Scroll.TimeToUnit(s.Focus != null ? s.Focus : (IDurable)s.Frame);
if (!Scroll.ViewUnit.IsValid || (!Scroll.ViewUnit.Contains(interval) && !interval.Contains(Scroll.ViewUnit)))
{
Scroll.ViewUnit.Width = interval.Width * DefaultFrameZoom;
Scroll.ViewUnit.Left = interval.Left - (Scroll.ViewUnit.Width - interval.Width) * 0.5;
Scroll.ViewUnit.Normalize();
UpdateBar();
}
}
}
UpdateSurface();
}
public ThreadViewControl()
{
InitializeComponent();
surface.SizeChanged += new SizeChangedEventHandler(ThreadView_SizeChanged);
surface.OnDraw += OnDraw;
InitInputEvent();
InitColors();
SelectionMesh = surface.CreateMesh();
SelectionMesh.Projection = Mesh.ProjectionType.Pixel;
SelectionMesh.Geometry = Mesh.GeometryType.Lines;
HoverLines = surface.CreateMesh();
HoverLines.Projection = Mesh.ProjectionType.Pixel;
HoverLines.Geometry = Mesh.GeometryType.Lines;
HoverMesh = surface.CreateMesh();
HoverMesh.Projection = Mesh.ProjectionType.Pixel;
HoverMesh.Geometry = Mesh.GeometryType.Polygons;
HoverMesh.UseAlpha = true;
MeasureMesh = surface.CreateMesh();
MeasureMesh.Projection = Mesh.ProjectionType.Pixel;
MeasureMesh.UseAlpha = true;
}
class InputState
{
public bool IsDrag { get; set; }
public bool IsSelect { get; set; }
public bool IsMeasure { get; set; }
public Durable MeasureInterval { get; set; }
public System.Drawing.Point SelectStartPosition { get; set; }
public System.Drawing.Point DragPosition { get; set; }
public System.Drawing.Point MousePosition { get; set; }
public InputState()
{
MeasureInterval = new Durable();
}
}
InputState Input = new InputState();
private void InitInputEvent()
{
surface.RenderCanvas.MouseWheel += RenderCanvas_MouseWheel;
surface.RenderCanvas.MouseDown += RenderCanvas_MouseDown;
surface.RenderCanvas.MouseUp += RenderCanvas_MouseUp;
surface.RenderCanvas.MouseMove += RenderCanvas_MouseMove;
surface.RenderCanvas.MouseLeave += RenderCanvas_MouseLeave;
scrollBar.Scroll += ScrollBar_Scroll;
}
private void RenderCanvas_MouseLeave(object sender, EventArgs e)
{
Mouse.OverrideCursor = null;
Input.IsDrag = false;
Input.IsSelect = false;
ToolTipPanel?.Reset();
UpdateSurface();
}
public delegate void OnShowPopupHandler(List