diff options
Diffstat (limited to 'src/debug/DbgLogViewer.cs')
| -rw-r--r-- | src/debug/DbgLogViewer.cs | 579 |
1 files changed, 417 insertions, 162 deletions
diff --git a/src/debug/DbgLogViewer.cs b/src/debug/DbgLogViewer.cs index eca502fb..7c8a1bdf 100644 --- a/src/debug/DbgLogViewer.cs +++ b/src/debug/DbgLogViewer.cs @@ -27,21 +27,94 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; +using Cairo; #if DEBUG_LOG namespace Crow { public class DbgLogViewer : ScrollingObject { + #region debug viewer private classes + class DbgData { + public int objInstanceNum; + public LayoutingType layout; + public LayoutingQueueItem.Result result; + + public DbgData (int _obj) { + objInstanceNum = _obj; + } + } + class DbgEvent { + public long begin, end; + public DbgEvtType type; + public DbgData data = null; + + public DbgEvent() {} + + public static DbgEvent Parse (string str) { + if (str == null) + return null; + string[] tmp = str.Trim().Split(';'); + + DbgEvent evt = new DbgEvent (); + evt.begin = long.Parse (tmp [0]); + evt.end = long.Parse (tmp [1]); + evt.type = (DbgEvtType)Enum.Parse (typeof(DbgEvtType), tmp [2]); + + if (evt.type.HasFlag (DbgEvtType.GraphicObject)) { + evt.data = new DbgData (int.Parse (tmp [3])); + if (evt.type.HasFlag (DbgEvtType.GOLayouting)) { + evt.data.layout = (LayoutingType)Enum.Parse (typeof(LayoutingType), tmp [4]); + if (evt.type == DbgEvtType.GOProcessLayouting) + evt.data.result = (LayoutingQueueItem.Result)Enum.Parse (typeof(LayoutingQueueItem.Result), tmp [5]); + } + } + return evt; + } + } + class DbgGo { + public int listIndex;//prevent doing an IndexOf on list for each event to know y pos on screen + public int instanceNum;//class instantiation order, used to bind events to objs + public string name; + //0 is the main graphic tree, for other obj tree not added to main tree, it range from 1->n + //useful to track events for obj shown later, not on start + public int treeIndex; + public int yIndex;//index in parenting, the whole main graphic tree is one continuous suite + public int xLevel;//depth + + public List<DbgEvent> events = new List<DbgEvent>(); + + public static DbgGo Parse (string str) { + DbgGo g = new DbgGo (); + if (str == null) + return null; + string[] tmp = str.Trim().Split(';'); + g.instanceNum = int.Parse (tmp [0]); + g.name = tmp [1]; + g.yIndex = int.Parse (tmp [2]); + g.xLevel = int.Parse (tmp [3]); + return g; + } + + } + #endregion + #region CTOR protected DbgLogViewer () : base(){} public DbgLogViewer (Interface iface) : base(iface){} #endregion - bool loaded = false; - double xScale = 0.125, yScale = 1.0, lineHeight = 0.0, leftMargin; + FontExtents fe; + + double xScale = 1.0/512.0, yScale = 1.0, leftMargin, topMargin = 0.0; string logFile; - long currentTick = 0, selStart = -1, selEnd = -1, minTicks = 0, maxTicks = 0; + + List<DbgEvent> events;//global events + List<DbgGo> objs; + + long currentTick = 0, selStart = -1, selEnd = -1, minTicks = 0, maxTicks = 0, visibleTicks = 0; + int currentLine = -1; + int visibleLines; public string LogFile { get { return logFile; } @@ -49,8 +122,11 @@ namespace Crow if (logFile == value) return; logFile = value; + + loadDebugFile (); + + NotifyValueChanged ("LogFile", logFile); - loaded = false; RegisterForGraphicUpdate (); } } @@ -61,6 +137,7 @@ namespace Crow return; xScale = value; NotifyValueChanged ("XScale", xScale); + updateVisibleTicks (); RegisterForGraphicUpdate (); } } @@ -74,8 +151,188 @@ namespace Crow RegisterForGraphicUpdate (); } } - List<DbgEvent> events; - List<DbgGo> objs; + + + void storeEvent (DbgEvent evt) { + if (evt.data == null)//global events + events.Add (evt); + else + objs.Where (o => o.instanceNum == evt.data.objInstanceNum).FirstOrDefault ().events.Add (evt); + } + + void loadDebugFile() { + if (!File.Exists (logFile)) + return; + + events = new List<DbgEvent>(); + objs = new List<DbgGo> (); + minTicks = maxTicks = 0; + leftMargin = topMargin = 0.0; + + using (ImageSurface img = new ImageSurface (Format.Argb32, 1, 1)) { + using (Context gr = new Context (img)) { + double maxNameWidth = 0.0; + + gr.SelectFontFace (Font.Name, Font.Slant, Font.Wheight); + gr.SetFontSize (Font.Size); + + using (StreamReader s = new StreamReader (logFile)) { + if (s.ReadLine () != "[GraphicObjects]") + return; + while (!s.EndOfStream) { + string l = s.ReadLine (); + if (l == "[Events]") + break; + DbgGo o = DbgGo.Parse (l); + objs.Add (o); + double nameWidth = gr.TextExtents (o.name).Width + 5.0 * o.xLevel; + if (nameWidth > maxNameWidth) + maxNameWidth = nameWidth; + } + if (!s.EndOfStream) { + DbgEvent firstEvt = DbgEvent.Parse (s.ReadLine ()); + storeEvent (firstEvt); + minTicks = firstEvt.begin; + } + + if (!s.EndOfStream) { + while (true) { + DbgLogViewer.DbgEvent evt = DbgEvent.Parse (s.ReadLine ()); + storeEvent (evt); + if (s.EndOfStream) { + maxTicks = evt.end; + break; + } + } + } + } + + leftMargin = 2.5 + maxNameWidth; + + fe = gr.FontExtents; + + topMargin = 2.0 * fe.Height; + + updateVisibleLines (); + updateVisibleTicks (); + } + } + + } + void updateVisibleLines(){ + visibleLines = (int)Math.Floor (((double)ClientRectangle.Height - topMargin) / fe.Height); + NotifyValueChanged ("VisibleLines", visibleLines); + updateMaxScrollY (); + } + void updateVisibleTicks() { + visibleTicks = Math.Max (0, (long)((double)(ClientRectangle.Width - leftMargin) / XScale)); + NotifyValueChanged ("VisibleTicks", visibleTicks); + updateMaxScrollX (); + } + /* + void updateVisibleColumns(){ + visibleColumns = (int)Math.Floor ((double)(ClientRectangle.Width - leftMargin)/ fe.MaxXAdvance); + NotifyValueChanged ("VisibleColumns", visibleColumns); + updateMaxScrollX (); + } + void updateMaxScrollX () { + MaxScrollX = Math.Max (0, buffer.longestLineCharCount - visibleColumns); + if (buffer.longestLineCharCount > 0) + NotifyValueChanged ("ChildWidthRatio", Slot.Width * visibleColumns / buffer.longestLineCharCount); + }*/ + + void updateMaxScrollX () { + if (objs == null) + MaxScrollX = 0; + else + MaxScrollX = (int)Math.Max(0L, maxTicks - minTicks - visibleTicks); + } + void updateMaxScrollY () { + if (objs == null) + MaxScrollY = 0; + else + MaxScrollY = Math.Max(0, objs.Count - visibleLines); + } + + + public override Font Font { + get { return base.Font; } + set { + base.Font = value; + loadDebugFile (); + } + } + + public override int ScrollY { + get { + return base.ScrollY; + } + set { + base.ScrollY = value; + + if (objs == null) + return; + + Rectangle cb = ClientRectangle; + cb.Left += (int)leftMargin; + cb.Width -= (int)leftMargin; + cb.Y += (int)topMargin; + cb.Height -= (int)topMargin; + + if (mousePos.Y < cb.Top || mousePos.Y > cb.Bottom) + currentLine = -1; + else + currentLine = (int)((double)(mousePos.Y - cb.Top) / fe.Height) + ScrollY; + + NotifyValueChanged ("CurrentLine", currentLine); + + } + } + + Crow.Color getObjEventColor (DbgEvent evt) { + if (evt.type.HasFlag (DbgEvtType.GOLayouting)) { + if (evt.type == DbgEvtType.GOProcessLayouting) { + switch (evt.data.result) { + case LayoutingQueueItem.Result.Success: + return Crow.Color.Green; + case LayoutingQueueItem.Result.Deleted: + return Crow.Color.Red; + case LayoutingQueueItem.Result.Discarded: + return Crow.Color.DarkRed; + case LayoutingQueueItem.Result.Requeued: + return Crow.Color.Orange; + } + } else if (evt.type == DbgEvtType.GOProcessLayoutingWithNoParent) + return Color.IndianRed; + else + return Crow.Color.Blue; + } + switch (evt.type) { + case DbgEvtType.GOClassCreation: + return Color.GhostWhite; + case DbgEvtType.GOInitialization: + return Color.Cyan; + case DbgEvtType.GOClippingRegistration: + return Color.Cyan; + case DbgEvtType.GORegisterClip: + return Color.Cyan; + case DbgEvtType.GORegisterForGraphicUpdate: + return Color.Cyan; + case DbgEvtType.GOEnqueueForRepaint: + return Color.Cyan; + case DbgEvtType.GODraw: + return Color.Cyan; + case DbgEvtType.GORecreateCache: + return Color.Cyan; + case DbgEvtType.GOUpdateCacheAndPaintOnCTX: + return Color.Cyan; + case DbgEvtType.GOPaint: + return Color.Cyan; + case DbgEvtType.GONewDataSource: + return Color.Cyan; + } + return Crow.Color.RebeccaPurple; + } protected override void onDraw (Cairo.Context gr) { @@ -86,167 +343,132 @@ namespace Crow gr.FontOptions = Interface.FontRenderingOptions; gr.Antialias = Interface.Antialias; - if (!loaded) { - if (!File.Exists (logFile)) - return; - events = new List<DbgEvent>(); - objs = new List<DbgGo> (); + if (objs == null) + return; - using (StreamReader s = new StreamReader (logFile)) { - if (s.ReadLine () != "[GraphicObjects]") { - loaded = false; - return; - } - while (!s.EndOfStream) { - string l = s.ReadLine (); - if (l == "[Events]") - break; - objs.Add (DbgGo.Parse (l)); + gr.LineWidth = 1.0; + + Rectangle cb = ClientRectangle; + + double penY = topMargin + ClientRectangle.Top; + + for (int i = 0; i < visibleLines; i++) { + DbgGo g = objs [i + ScrollY]; + + foreach (DbgEvent evt in g.events) { + if (evt.end - minTicks <= ScrollX) + continue; + if (evt.begin - minTicks > ScrollX + visibleTicks) + break; + double x = xScale * (evt.begin - minTicks - ScrollX) ; + double w = Math.Max (Math.Max(2.0, 2.0 * xScale), (double)(evt.end - evt.begin) * xScale); + if (x < 0.0) { + w += x; + x = 0.0; } - while (!s.EndOfStream) - events.Add (DbgEvent.Parse (s.ReadLine ())); + x += leftMargin + cb.Left; + double rightDiff = x + w - cb.Right; + if (rightDiff > 0) + w -= rightDiff; + //if (x + w > cb.Right) + // continue; + + gr.SetSourceColor (getObjEventColor (evt)); + + gr.Rectangle (x, penY, w, fe.Height); + gr.Fill (); + } - loaded = true; - lineHeight = gr.FontExtents.Height; - if (events.Count > 0) { - minTicks = events [0].begin; - maxTicks = events [events.Count - 1].begin; - } else - minTicks = maxTicks = 0; - - MaxScrollY = Math.Max(0, objs.Count - (int)Math.Ceiling((double)ClientRectangle.Height / lineHeight)); - } - Rectangle r = ClientRectangle; + penY += fe.Height; - gr.LineWidth = 1.0; + gr.SetSourceColor (Crow.Color.Jet); + gr.MoveTo (cb.X, penY - 0.5); + gr.LineTo (cb.Right, penY - 0.5); + gr.Stroke (); - leftMargin = 0.0; + double penX = 5.0 * g.xLevel + cb.Left; - foreach (DbgGo g in objs) { if (g.yIndex == 0) - continue; - double penX = r.X + g.xLevel * 5.0; - Cairo.TextExtents te = gr.TextExtents (g.name); - if (te.Width + penX > leftMargin) - leftMargin = te.Width + penX; - double penY = (g.yIndex - ScrollY) * lineHeight + r.Top; - if (penY < r.Top || penY > r.Bottom + lineHeight) - continue; - - Foreground.SetAsSource (gr); + gr.SetSourceColor (Crow.Color.LightSalmon); + else + Foreground.SetAsSource (gr); + gr.MoveTo (penX, penY - gr.FontExtents.Descent); gr.ShowText (g.name); - gr.SetSourceColor (Crow.Color.Jet); - gr.MoveTo (r.X, penY - 0.5); - gr.LineTo (r.Right, penY - 0.5); - gr.Stroke (); + + gr.SetSourceColor (Crow.Color.White); + gr.MoveTo (cb.X, penY - gr.FontExtents.Descent); + gr.ShowText ((i+ ScrollY).ToString()); + } - leftMargin += 2.5; - r.Left += (int)leftMargin; - gr.MoveTo (leftMargin, r.Top); - gr.LineTo (leftMargin, r.Bottom); - Foreground.SetAsSource (gr); - gr.Stroke (); - MaxScrollX = (int)(maxTicks - minTicks) - r.Width; + gr.MoveTo (cb.Left, topMargin - 0.5 + cb.Top); + gr.LineTo (cb.Right, topMargin - 0.5 + cb.Top); - gr.SetFontSize (8); + gr.MoveTo (leftMargin + cb.Left, cb.Top); + gr.LineTo (leftMargin + cb.Left, cb.Bottom); + gr.SetSourceColor (Crow.Color.Grey); - gr.Save (); - gr.Rectangle (r); - gr.Clip (); + penY = topMargin + ClientRectangle.Top; - foreach (DbgEvent evt in events) { - double x = (int)((double)(evt.begin - minTicks - ScrollX) * xScale) ; - x += (double)r.Left + 0.5; - double w = Math.Max (Math.Max(2.0, 2.0 * xScale), (double)(evt.end - evt.begin) * xScale); + //graduation + int largeGrad = int.Parse ("1" + new string ('0', visibleTicks.ToString ().Length - 1)); + int smallGrad = Math.Max (1, largeGrad / 10); - if (x + w < r.Left || x > r.Right) - continue; + long firstVisibleTicks = minTicks + ScrollX; + long curGrad = firstVisibleTicks - firstVisibleTicks % smallGrad + smallGrad; - if (evt.type.HasFlag (DbgEvtType.GraphicObject)) { - gr.SetSourceColor (Crow.Color.DarkSlateBlue); - DbgData data = (DbgData)evt.data; - double y = (objs.Where(o=>o.index == data.obj).FirstOrDefault().yIndex - ScrollY - 1) * lineHeight; - if (evt.type.HasFlag (DbgEvtType.GOLayouting)) { - if (evt.type == DbgEvtType.GOProcessLayouting) { - switch (data.result) { - case LayoutingQueueItem.Result.Success: - gr.SetSourceColor (Crow.Color.Green); - break; - case LayoutingQueueItem.Result.Deleted: - gr.SetSourceColor (Crow.Color.Red); - break; - case LayoutingQueueItem.Result.Discarded: - gr.SetSourceColor (Crow.Color.DarkOrange); - break; - case LayoutingQueueItem.Result.Requeued: - gr.SetSourceColor (Crow.Color.GreenYellow); - break; - case LayoutingQueueItem.Result.Register: - gr.SetSourceColor (Crow.Color.Blue); - break; - } + long gg = curGrad - ScrollX - minTicks; + while (gg < visibleTicks ) { + double x = (double)gg * xScale + leftMargin + cb.Left; - }else - gr.SetSourceColor (Crow.Color.Bisque); - - }else if (evt.type == DbgEvtType.GOInitialization) - gr.SetSourceColor (Crow.Color.Cyan); - else if (evt.type == DbgEvtType.GOClippingRegistration) - gr.SetSourceColor (Crow.Color.BlueViolet); - else if (evt.type == DbgEvtType.GORegisterClip) - gr.SetSourceColor (Crow.Color.Orange); - else if (evt.type == DbgEvtType.GODraw) - gr.SetSourceColor (Crow.Color.Pink); - else if (evt.type == DbgEvtType.GORecreateCache) - gr.SetSourceColor (Crow.Color.YellowGreen); - - gr.Rectangle (x, y, w, lineHeight); - gr.Fill (); + gr.MoveTo (x, penY - 0.5); + if (curGrad % largeGrad == 0) { + gr.LineTo (x, penY - 8.5); + string str = curGrad.ToString (); + TextExtents te = gr.TextExtents (str); + gr.RelMoveTo (-0.5 * te.Width, -2.0); + gr.ShowText (str); + }else + gr.LineTo (x, penY - 2.5); - if (evt.type.HasFlag (DbgEvtType.GOLayouting)) { - gr.SetSourceColor (Crow.Color.Black); - switch (data.layout) { - case LayoutingType.Height: - gr.MoveTo (x + w * 0.5, y + 1); - gr.LineTo (x + w * 0.5, y + lineHeight - 2); - gr.Stroke (); - break; - case LayoutingType.Width: - gr.MoveTo (x + 0.5, y + lineHeight * 0.5); - gr.LineTo (x + w - 1.0, y + lineHeight * 0.5); - gr.Stroke (); - break; - default: - break; - } - } - } else { - gr.SetSourceColor (Crow.Color.Yellow); - gr.MoveTo (x, r.Top); - gr.LineTo (x, r.Bottom); - gr.Stroke (); - string s = evt.type.ToString () [10].ToString (); - Cairo.TextExtents te = gr.TextExtents (s); - gr.Rectangle (x, r.Top, te.Width, lineHeight); - gr.Fill (); - gr.MoveTo (x, r.Top + gr.FontExtents.Ascent); - gr.SetSourceColor (Crow.Color.Jet); - gr.ShowText (s); - } + curGrad += smallGrad; + gg = curGrad - ScrollX - minTicks; + } + + gr.Stroke (); + + //global events + foreach (DbgEvent evt in events) { + if (evt.begin - minTicks <= ScrollX) + continue; + double x = xScale * (evt.begin - minTicks - ScrollX) ; + x += leftMargin + cb.Left; + + gr.SetSourceColor (Crow.Color.Yellow); + gr.MoveTo (x, penY); + gr.LineTo (x, cb.Bottom); + gr.Stroke (); + string s = evt.type.ToString () [10].ToString (); + Cairo.TextExtents te = gr.TextExtents (s); + gr.Rectangle (x - 0.5 * te.Width , penY - te.Height, te.Width, te.Height); + gr.Fill (); + gr.MoveTo (x- 0.5 * te.Width, penY - gr.FontExtents.Descent); + gr.SetSourceColor (Crow.Color.Jet); + gr.ShowText (s); } - gr.Restore (); } public override void Paint (ref Cairo.Context ctx) { base.Paint (ref ctx); + Rectangle r = new Rectangle(mousePos.X, 0, 1, Slot.Height); - Rectangle cb = ContextCoordinates (r); + Rectangle ctxR = ContextCoordinates (r); + Rectangle cb = ClientRectangle; - ctx.Rectangle (cb); + ctx.Rectangle (ctxR); ctx.SetSourceColor (Color.CornflowerBlue); ctx.Fill(); @@ -255,25 +477,38 @@ namespace Crow ctx.FontOptions = Interface.FontRenderingOptions; ctx.Antialias = Interface.Antialias; - ctx.MoveTo (cb.X, cb.Y + lineHeight); + ctx.MoveTo (ctxR.X, ctxR.Y + fe.Height); ctx.ShowText (currentTick.ToString ()); - if (selStart < 0) + ctx.Operator = Cairo.Operator.Add; + + if (currentLine >= 0) { + r = new Rectangle (cb.Left, (currentLine + 2 - ScrollY) * (int)fe.Height + cb.Top, cb.Width, (int)fe.Height); + + ctx.Operator = Cairo.Operator.Add; + ctx.SetSourceRGBA (0.1, 0.1, 0.1, 0.4); + ctx.Rectangle (ContextCoordinates (r)); + ctx.Fill (); + } + + if (selStart < 0) { + ctx.Operator = Cairo.Operator.Over; return; - double selStartX = (double)(selStart - ScrollX - minTicks) * xScale + leftMargin; - double selEndX = (selEnd >= 0) ? (double)(selEnd - ScrollX - minTicks) * xScale + leftMargin : - (double)(currentTick - ScrollX - minTicks) * xScale + leftMargin; + } + double selStartX = (double)(selStart - ScrollX - minTicks) * xScale + leftMargin + cb.Left; + double selEndX = (selEnd >= 0) ? (double)(selEnd - ScrollX - minTicks) * xScale + leftMargin + cb.Left : + (double)(currentTick - ScrollX - minTicks) * xScale + leftMargin + cb.Left; if (selStartX < selEndX) { - cb.X = (int)selStartX; - cb.Width = (int)(selEndX - selStartX); + ctxR.X = (int)selStartX; + ctxR.Width = (int)(selEndX - selStartX); } else { - cb.X = (int)selEndX; - cb.Width = (int)(selStartX - selEndX); + ctxR.X = (int)selEndX; + ctxR.Width = (int)(selStartX - selEndX); } - ctx.Operator = Cairo.Operator.Add; - cb.Width = Math.Max (1, cb.Width); - ctx.Rectangle (cb); + + ctxR.Width = Math.Max (1, ctxR.Width); + ctx.Rectangle (ctxR); //ctx.SetSourceColor (Color.LightYellow); ctx.SetSourceColor (Color.Jet); ctx.Fill(); @@ -285,28 +520,46 @@ namespace Crow base.OnLayoutChanges (layoutType); switch (layoutType) { case LayoutingType.Width: - + updateVisibleTicks (); break; case LayoutingType.Height: - if (!loaded) - break; - MaxScrollY = objs.Count - (int)Math.Ceiling((double)ClientRectangle.Height / lineHeight); + updateVisibleLines (); break; } } + Point mousePos; void updateMouseLocalPos(Point mPos){ Rectangle r = ScreenCoordinates (Slot); Rectangle cb = ClientRectangle; cb.Left += (int)leftMargin; + cb.Width -= (int)leftMargin; + cb.Y += (int)topMargin; + cb.Height -= (int)topMargin; + mousePos = mPos - r.Position; mousePos.X = Math.Max(cb.X, mousePos.X); mousePos.X = Math.Min(cb.Right, mousePos.X); + + if (mousePos.Y < cb.Top || mousePos.Y > cb.Bottom) + currentLine = -1; + else + currentLine = (int)((double)(mousePos.Y - cb.Top) / fe.Height) + ScrollY; + + NotifyValueChanged ("CurrentLine", currentLine); + mousePos.Y = Math.Max(cb.Y, mousePos.Y); mousePos.Y = Math.Min(cb.Bottom, mousePos.Y); - currentTick = (int)((double)Math.Max(0, mousePos.X - cb.X) / xScale) + minTicks + ScrollX; + currentTick = (int)((double)(mousePos.X - cb.X) / xScale) + minTicks + ScrollX; + + } + public override void onMouseLeave (object sender, MouseMoveEventArgs e) + { + base.onMouseLeave (sender, e); + currentLine = -1; + currentTick = 0; } public override void onMouseMove (object sender, MouseMoveEventArgs e) { @@ -349,10 +602,10 @@ namespace Crow if (e.Delta > 0) { XScale *= 2.0; } else { - XScale *= 0.5; + if (MaxScrollX > 0) + XScale *= 0.5; } - int cbx = ClientRectangle.X + (int)leftMargin; - ScrollX = (int)(currentTick - (int)((double)Math.Max(0, mousePos.X - cbx) / xScale) - minTicks); + ScrollX = (int)(currentTick - (int)((double)Math.Max(0, mousePos.X - (int)leftMargin) / xScale) - minTicks); }else ScrollY -= e.Delta * MouseWheelSpeed; } @@ -372,9 +625,11 @@ namespace Crow } } - void zoom (long start, long end) { + void zoom (long start, long end) { + //Rectangle cb = ClientRectangle; + //cb.X += (int)leftMargin; + XScale = ((double)ClientRectangle.Width - leftMargin)/(end - start); ScrollX = (int)(start - minTicks); - XScale = (ClientRectangle.Width - leftMargin)/(end - start); } } } |