diff options
| author | Jean-Philippe Bruyère <jp_bruyere@hotmail.com> | 2018-11-24 10:48:34 +0100 |
|---|---|---|
| committer | Jean-Philippe Bruyère <jp_bruyere@hotmail.com> | 2018-11-24 10:48:34 +0100 |
| commit | 98eada369aa50115e677a1b337662fee9f0ca011 (patch) | |
| tree | 6855bc602c4da5f6a13c90276452b438172c1d3d /src/debug | |
| parent | 4db409fdff013e3e4249d567e4d6fdb0ee877256 (diff) | |
debug log viewer, X backends
Diffstat (limited to 'src/debug')
| -rw-r--r-- | src/debug/DbgLogViewer.cs | 327 | ||||
| -rw-r--r-- | src/debug/DebugLogger.cs | 113 |
2 files changed, 387 insertions, 53 deletions
diff --git a/src/debug/DbgLogViewer.cs b/src/debug/DbgLogViewer.cs new file mode 100644 index 00000000..b020df4b --- /dev/null +++ b/src/debug/DbgLogViewer.cs @@ -0,0 +1,327 @@ +// +// DbgLogViewer.cs +// +// Author: +// Jean-Philippe Bruyère <jp_bruyere@hotmail.com> +// +// Copyright (c) 2013-2017 Jean-Philippe Bruyère +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; + +#if DEBUG_LOG +namespace Crow +{ + public class DbgLogViewer : ScrollingObject + { + #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; + string logFile; + long currentTick = 0, selStart = -1, selEnd = -1, minTicks = 0, maxTicks = 0; + + public string LogFile { + get { return logFile; } + set { + if (logFile == value) + return; + logFile = value; + NotifyValueChanged ("LogFile", logFile); + loaded = false; + RegisterForGraphicUpdate (); + } + } + public double XScale { + get { return xScale; } + set { + if (xScale == value) + return; + xScale = value; + NotifyValueChanged ("XScale", xScale); + RegisterForGraphicUpdate (); + } + } + public double YScale { + get { return yScale; } + set { + if (yScale == value) + return; + yScale = value; + NotifyValueChanged ("YScale", yScale); + RegisterForGraphicUpdate (); + } + } + List<DbgEvent> events; + List<DbgGo> objs; + + protected override void onDraw (Cairo.Context gr) + { + base.onDraw (gr); + + if (!loaded) { + if (!File.Exists (logFile)) + return; + events = new List<DbgEvent>(); + objs = new List<DbgGo> (); + + 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)); + } + while (!s.EndOfStream) + events.Add (DbgEvent.Parse (s.ReadLine ())); + } + 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; + + Foreground.SetAsSource (gr); + + leftMargin = 0.0; + + foreach (DbgGo g in objs) { + if (g.yIndex == 0) + continue; + double penX = r.X + g.xLevel * 5.0, penY = (g.yIndex - ScrollY) * lineHeight - gr.FontExtents.Descent; + gr.MoveTo (penX, penY); + Cairo.TextExtents te = gr.TextExtents (g.name); + if (te.Width + penX > leftMargin) + leftMargin = te.Width + penX; + gr.ShowText (g.name); + } + + leftMargin += 2.5; + r.Left += (int)leftMargin; + gr.LineWidth = 1.0; + gr.MoveTo (leftMargin, r.Top); + gr.LineTo (leftMargin, r.Bottom); + gr.Stroke (); + + MaxScrollX = (int)(maxTicks - minTicks) - r.Width; + + 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(4.0, 10.0 * xScale), (double)(evt.end - evt.begin) * xScale); + + if (x < r.Left || x > r.Right) + continue; + + 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; + } + }else + gr.SetSourceColor (Crow.Color.Bisque); + }else if (evt.type == DbgEvtType.GOInitialization) + gr.SetSourceColor (Crow.Color.Cyan); + + gr.Rectangle (x, y, w, lineHeight); + gr.Fill (); + } else { + gr.SetSourceColor (Crow.Color.Black); + 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.White); + gr.ShowText (s); + } + } + + } + 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); + + ctx.Rectangle (cb); + ctx.SetSourceColor (Color.CornflowerBlue); + ctx.Fill(); + + ctx.MoveTo (cb.X, cb.Y + lineHeight); + ctx.ShowText (currentTick.ToString ()); + + if (selStart < 0) + 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; + + if (selStartX < selEndX) { + cb.X = (int)selStartX; + cb.Width = (int)(selEndX - selStartX); + } else { + cb.X = (int)selEndX; + cb.Width = (int)(selStartX - selEndX); + } + ctx.Operator = Cairo.Operator.Multiply; + cb.Width = Math.Max (1, cb.Width); + ctx.Rectangle (cb); + ctx.SetSourceColor (Color.LightYellow); + ctx.Fill(); + ctx.Operator = Cairo.Operator.Over; + + } + public override void OnLayoutChanges (LayoutingType layoutType) + { + base.OnLayoutChanges (layoutType); + switch (layoutType) { + case LayoutingType.Width: + RegisterForLayouting (LayoutingType.X); + break; + case LayoutingType.Height: + if (!loaded) + break; + MaxScrollY = objs.Count - (int)Math.Ceiling((double)ClientRectangle.Height / lineHeight); + break; + } + } + Point mousePos; + void updateMouseLocalPos(Point mPos){ + Rectangle r = ScreenCoordinates (Slot); + Rectangle cb = ClientRectangle; + cb.Left += (int)leftMargin; + mousePos = mPos - r.Position; + + mousePos.X = Math.Max(cb.X, mousePos.X); + mousePos.X = Math.Min(cb.Right, mousePos.X); + 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; + } + public override void onMouseMove (object sender, MouseMoveEventArgs e) + { + base.onMouseMove (sender, e); + updateMouseLocalPos (e.Position); + + if (selStart >= 0 && IFace.Mouse.IsButtonDown(MouseButton.Left)) + selEnd = currentTick; + + RegisterForRedraw (); + } + public override void onMouseDown (object sender, MouseButtonEventArgs e) + { + base.onMouseDown (sender, e); + + selStart = currentTick; + selEnd = -1; + + RegisterForRedraw (); + } + public override void onMouseUp (object sender, MouseButtonEventArgs e) + { + base.onMouseUp (sender, e); + if (selStart == currentTick) { + selStart = -1; + selEnd = -1; + }else + selEnd = currentTick; + RegisterForRedraw (); + } + + /// <summary> Process scrolling vertically, or if shift is down, vertically </summary> + public override void onMouseWheel (object sender, MouseWheelEventArgs e) + { + //base.onMouseWheel (sender, e); + + if (IFace.Keyboard.Shift) + ScrollX -= (int)((double)(e.Delta * MouseWheelSpeed) / xScale); + else if (IFace.Keyboard.Ctrl) { + if (e.Delta > 0) { + XScale *= 2.0; + } else { + XScale *= 0.5; + } + int cbx = ClientRectangle.X + (int)leftMargin; + ScrollX = (int)(currentTick - (int)((double)Math.Max(0, mousePos.X - cbx) / xScale) - minTicks); + }else + ScrollY -= e.Delta * MouseWheelSpeed; + } + + public override void onKeyDown (object sender, KeyEventArgs e) + { + base.onKeyDown (sender, e); + + if (e.Key == Key.F3) { + if (selEnd < 0) + return; + if (selEnd < selStart) + zoom (selEnd, selStart); + else + zoom (selStart, selEnd); + selEnd = selStart = -1; + } + } + + void zoom (long start, long end) { + ScrollX = (int)(start - minTicks); + XScale = (ClientRectangle.Width - leftMargin)/(end - start); + } + } +} +#endif + diff --git a/src/debug/DebugLogger.cs b/src/debug/DebugLogger.cs index 0599a6a1..161d742c 100644 --- a/src/debug/DebugLogger.cs +++ b/src/debug/DebugLogger.cs @@ -27,7 +27,6 @@ using System; using Cairo; using System.Collections.Generic; using System.Diagnostics; -using System.Runtime.Serialization.Formatters.Binary; using System.IO; #if DEBUG_LOG @@ -47,28 +46,41 @@ namespace Crow IFaceEndClipping = 0x0104, IFaceStartDrawing = 0x0105, IFaceEndDrawing = 0x0106, + IFaceUpdate = 0x0107, //10 nth bit set for graphic obj GraphicObject = 0x0200, GOClassCreation = 0x0201, - GOInitialized = 0x0202, + GOInitialization = 0x0202, GOClippingRegistration = 0x0203, GORegisterClip = 0x0204, GORegisterForGraphicUpdate = 0x0205, GOEnqueueForRepaint = 0x0206, - GORegisterLayouting = 0x0207, - GOProcessLayoutingWithNoParent = 0x0208, - GOProcessLayouting = 0x0209, + GOLayouting = 0x0400, + GORegisterLayouting = 0x0607, + GOProcessLayoutingWithNoParent = 0x0608, + GOProcessLayouting = 0x0609, GODraw = 0x020a, GORecreateCache = 0x020b, GOUpdateCacheAndPaintOnCTX = 0x020c, GOPaint = 0x020d, GONewDataSource = 0x020e, } + public class DbgData { + public int obj; + public LayoutingType layout; + public LayoutingQueueItem.Result result; + + public DbgData (int _obj) { + obj = _obj; + } + } public class DbgEvent { public long begin, end; public DbgEvtType type; public object data = null; + public DbgEvent() {} + public DbgEvent(long timeStamp, DbgEvtType evt, object _data = null) { data = _data; type = evt; @@ -79,13 +91,13 @@ namespace Crow { GraphicObject go = data as GraphicObject; if (go != null) - return string.Format ("{0};{1};{2}", begin, type, GraphicObject.GraphicObjects.IndexOf(go).ToString()); + return string.Format ("{0};{1};{2};{3}", begin, end, type, GraphicObject.GraphicObjects.IndexOf(go).ToString()); if (!(data is LayoutingQueueItem)) - return string.Format ("{0};{1}", begin, type); + return string.Format ("{0};{1};{2}", begin, end, type); LayoutingQueueItem lqi = (LayoutingQueueItem)data; if (type == DbgEvtType.GOProcessLayouting) - return string.Format ("{0};{1};{2};{3};{4};{5}", begin, type, GraphicObject.GraphicObjects.IndexOf(lqi.graphicObject).ToString(), lqi.LayoutType.ToString(), lqi.result.ToString(), end); - return string.Format ("{0};{1};{2};{3}", begin, type, GraphicObject.GraphicObjects.IndexOf(lqi.graphicObject).ToString(), lqi.LayoutType.ToString()); + return string.Format ("{0};{1};{2};{3};{4};{5}", begin, end, type, GraphicObject.GraphicObjects.IndexOf(lqi.graphicObject).ToString(), lqi.LayoutType.ToString(), lqi.result.ToString()); + return string.Format ("{0};{1};{2};{3};{4}", begin, end, type, GraphicObject.GraphicObjects.IndexOf(lqi.graphicObject).ToString(), lqi.LayoutType.ToString()); } @@ -94,13 +106,42 @@ namespace Crow return null; string[] tmp = str.Trim().Split(';'); - long timeStamp = long.Parse (tmp [0]); - DbgEvtType type = (DbgEvtType)Enum.Parse (typeof(DbgEvtType), tmp [1]); - if (type.HasFlag (DbgEvtType.GraphicObject)) { + 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)) { + DbgData data = new DbgData (int.Parse (tmp [3])); + if (evt.type.HasFlag (DbgEvtType.GOLayouting)) { + data.layout = (LayoutingType)Enum.Parse (typeof(LayoutingType), tmp [4]); + if (evt.type == DbgEvtType.GOProcessLayouting) + data.result = (LayoutingQueueItem.Result)Enum.Parse (typeof(LayoutingQueueItem.Result), tmp [5]); + } + evt.data = data; } - return null; + return evt; + } + } + public class DbgGo { + public int index; + public string name; + public int yIndex; + public int xLevel; + + public static DbgGo Parse (string str) { + DbgGo g = new DbgGo (); + if (str == null) + return null; + string[] tmp = str.Trim().Split(';'); + g.index = int.Parse (tmp [0]); + g.name = tmp [1]; + g.yIndex = int.Parse (tmp [2]); + g.xLevel = int.Parse (tmp [3]); + return g; } + } public static class DebugLog { @@ -123,24 +164,6 @@ namespace Crow return evt; } - static DebugLog () - { - surf = new ImageSurface (Format.Argb32, bounds.Width, bounds.Height); - ctx = new Context (surf); - - ctx.Antialias = Antialias.Subpixel; - ctx.FontOptions = Interface.FontRenderingOptions; - ctx.Antialias = Interface.Antialias; - - ctx.Rectangle (bounds); - ctx.SetSourceColor (Crow.Color.WhiteSmoke); - ctx.Fill (); - - ctx.SelectFontFace ("mono", FontSlant.Normal, FontWeight.Normal); - ctx.SetFontSize (8.0); - ySpacing = ctx.FontExtents.Height; - } - static int y, level; static void parseTree (GraphicObject go) { @@ -170,19 +193,18 @@ namespace Crow foreach (GraphicObject go in iface.GraphicTree) parseTree (go); - using (StreamWriter s = new StreamWriter("debug.bin")){ + using (StreamWriter s = new StreamWriter("debug.log")){ s.WriteLine ("[GraphicObjects]"); for (int i=0; i<GraphicObject.GraphicObjects.Count; i++) { GraphicObject g = GraphicObject.GraphicObjects [i]; s.WriteLine ("{0};{1};{2};{3}", i, g.GetType().Name, g.yIndex, g.xLevel); } s.WriteLine ("[Events]"); - foreach (DbgEvent e in events) { - s.WriteLine (e.ToString ()); - } + foreach (DbgEvent e in events) + s.WriteLine (e.ToString ()); } - + /* List<GraphicObject> drawn = new List<GraphicObject> (); @@ -213,27 +235,12 @@ namespace Crow //penX = xPenStart + xResolution * lqi.begin; //ctx.Rectangle (penX, penY, Math.Max(1.0, (lqi.end - lqi.begin) * xResolution), ySpacing); - switch (lqi.result) { - case LayoutingQueueItem.Result.Success: - ctx.SetSourceColor (Crow.Color.Green); - break; - case LayoutingQueueItem.Result.Deleted: - ctx.SetSourceColor (Crow.Color.Red); - break; - case LayoutingQueueItem.Result.Discarded: - ctx.SetSourceColor (Crow.Color.DarkOrange); - break; - case LayoutingQueueItem.Result.Requeued: - ctx.SetSourceColor (Crow.Color.GreenYellow); - break; - case LayoutingQueueItem.Result.Register: - ctx.SetSourceColor (Crow.Color.Blue); - break; - } + ctx.Fill (); } surf.WriteToPng ("debug.png"); + */ } } } |