};
t.Start ();
}
-
-#if MEASURE_TIME
- PerfMeasures.Add (updateMeasure);
- PerfMeasures.Add (drawingMeasure);
- PerfMeasures.Add (layoutingMeasure);
- PerfMeasures.Add (clippingMeasure);
-#endif
}
#endregion
while (!Glfw3.WindowShouldClose (hWin)) {
Update ();
Thread.Sleep (UPDATE_INTERVAL);
-#if MEASURE_TIME
- foreach (PerformanceMeasure m in PerfMeasures)
- m.NotifyChanges ();
-#endif
}
}
protected virtual void OnInitialized ()
{
- try {
+ /*try {
Load ("#main.crow").DataSource = this;
- } catch { }
+ } catch { }*/
Initialized.Raise (this, null);
}
/// <summary>
/// load styling, init default tooltips and context menus, load main.crow resource if exists.
/// </summary>
public void Init () {
+#if DEBUG_LOG
+ DbgLogger.StartEvent (DbgEvtType.IFaceInit);
+#endif
loadStyling ();
initTooltip ();
initContextMenus ();
OnInitialized ();
+#if DEBUG_LOG
+ DbgLogger.EndEvent (DbgEvtType.IFaceInit);
+#endif
}
/// <summary>
/// call Init() then enter the running loop performing ProcessEvents until running==false.
public Widget Load (string path)
{
lock (UpdateMutex) {
+ #if DEBUG_LOG
+ DbgLogger.StartEvent (DbgEvtType.IFaceLoad);
+ #endif
Widget tmp = CreateInstance (path);
AddWidget (tmp);
+ #if DEBUG_LOG
+ DbgLogger.EndEvent (DbgEvtType.IFaceLoad);
+ #endif
return tmp;
}
}
_activeWidget = value;
- #if DEBUG_FOCUS
+#if DEBUG_LOG
NotifyValueChanged("ActiveWidget", _activeWidget);
- #endif
+ DbgLogger.AddEvent (DbgEvtType.ActiveWidget, _activeWidget);
+#endif
if (_activeWidget != null)
- {
_activeWidget.IsActive = true;
- #if DEBUG_FOCUS
- NotifyValueChanged("ActiveWidget", _activeWidget);
- Debug.WriteLine("Active => " + _activeWidget.ToString());
- }else
- Debug.WriteLine("Active => null");
- #else
- }
- #endif
}
}
/// <summary>Pointer is over the widget</summary>
_hoverWidget = value;
- #if DEBUG_FOCUS
+#if DEBUG_LOG
NotifyValueChanged("HoverWidget", _hoverWidget);
- #endif
+ DbgLogger.AddEvent (DbgEvtType.HoverWidget, _hoverWidget);
+#endif
if (DragAndDropOperation == null && FOCUS_ON_HOVER) {
Widget w = _hoverWidget;
}
if (_hoverWidget != null)
- {
_hoverWidget.IsHover = true;
-#if DEBUG_FOCUS
- Debug.WriteLine("Hover => " + _hoverWidget.ToString());
- }else
- Debug.WriteLine("Hover => null");
-#else
- }
-#endif
}
}
/// <summary>Widget has the keyboard or mouse focus</summary>
if (_focusedWidget != null)
_focusedWidget.HasFocus = false;
_focusedWidget = value;
- #if DEBUG_FOCUS
+#if DEBUG_LOG
NotifyValueChanged("FocusedWidget", _focusedWidget);
- #endif
+ DbgLogger.AddEvent (DbgEvtType.FocusedWidget, _focusedWidget);
+#endif
if (_focusedWidget != null)
- {
_focusedWidget.HasFocus = true;
-#if DEBUG_FOCUS
- Debug.WriteLine ("Focus => " + _hoverWidget.ToString ());
- } else
- Debug.WriteLine ("Focus => null");
-#else
- }
-#endif
}
}
#endregion
if (g.IsQueueForClipping)
return;
#if DEBUG_LOG
- DebugLog.AddEvent(DbgEvtType.GOEnqueueForRepaint, g);
+ DbgLogger.AddEvent(DbgEvtType.GOEnqueueForRepaint, g);
#endif
ClippingQueue.Enqueue (g);
g.IsQueueForClipping = true;
if (!Monitor.TryEnter (UpdateMutex))
return;
-
- #if MEASURE_TIME
- updateMeasure.StartCycle();
- #endif
-
- /*#if DEBUG_LOG
- DebugLog.AddEvent (DbgEvtType.IFaceUpdate);
- #endif*/
+
+#if DEBUG_LOG
+ DbgLogger.StartEvent (DbgEvtType.IFaceUpdate);
+#endif
processLayouting ();
}else
processDrawing (ctx);
-#if MEASURE_TIME
- updateMeasure.StopCycle();
+#if DEBUG_LOG
+ DbgLogger.EndEvent (DbgEvtType.IFaceUpdate, true);
#endif
Monitor.Exit (UpdateMutex);
/// Layouting queue items. Failing LQI's are requeued in this cycle until MaxTry is reached which
/// trigger an enqueue for the next Update Cycle</summary>
protected virtual void processLayouting(){
- #if MEASURE_TIME
- layoutingMeasure.StartCycle();
- #endif
if (Monitor.TryEnter (LayoutMutex)) {
- #if DEBUG_LOG
- if (LayoutingQueue.Count > 0)
- DebugLog.AddEvent (DbgEvtType.IFaceStartLayouting);
- #endif
+#if DEBUG_LOG
+ DbgLogger.StartEvent (DbgEvtType.IFaceLayouting);
+#endif
DiscardQueue = new Queue<LayoutingQueueItem> ();
//Debug.WriteLine ("======= Layouting queue start =======");
LayoutingQueueItem lqi;
lqi.ProcessLayouting ();
}
LayoutingQueue = DiscardQueue;
+#if DEBUG_LOG
+ DbgLogger.EndEvent (DbgEvtType.IFaceLayouting, true);
+#endif
Monitor.Exit (LayoutMutex);
DiscardQueue = null;
}
- /*#if DEBUG_LOG
- DebugLog.AddEvent (DbgEvtType.IFaceStartLayouting);
- #endif*/
- #if MEASURE_TIME
- layoutingMeasure.StopCycle();
- #endif
}
/// <summary>Degueue Widget to clip from DrawingQueue and register the last painted slot and the new one
/// Clipping rectangles are added at each level of the tree from leef to root, that's the way for the painting
/// operation to known if it should go down in the tree for further graphic updates and repaints</summary>
void clippingRegistration(){
- #if MEASURE_TIME
- clippingMeasure.StartCycle();
- #endif
- #if DEBUG_LOG
- if (ClippingQueue.Count > 0)
- DebugLog.AddEvent (DbgEvtType.IFaceStartClipping);
- #endif
+#if DEBUG_LOG
+ DbgLogger.StartEvent (DbgEvtType.IFaceClipping);
+#endif
Widget g = null;
while (ClippingQueue.Count > 0) {
lock (ClippingMutex) {
}
g.ClippingRegistration ();
}
- /*#if DEBUG_LOG
- DebugLog.AddEvent (DbgEvtType.IFaceEndClipping);
- #endif*/
- #if MEASURE_TIME
- clippingMeasure.StopCycle();
- #endif
+#if DEBUG_LOG
+ DbgLogger.EndEvent (DbgEvtType.IFaceClipping, true);
+#endif
}
/// <summary>Clipping Rectangles drive the drawing process. For compositing, each object under a clip rectangle should be
/// repainted. If it contains also clip rectangles, its cache will be update, or if not cached a full redraw will take place</summary>
void processDrawing(Context ctx){
- #if MEASURE_TIME
- drawingMeasure.StartCycle();
- #endif
- #if DEBUG_LOG
- if (!clipping.IsEmpty)
- DebugLog.AddEvent (DbgEvtType.IFaceStartDrawing);
- #endif
+#if DEBUG_LOG
+ DbgLogger.StartEvent (DbgEvtType.IFaceDrawing);
+#endif
if (DragImage != null)
clipping.UnionRectangle(new Rectangle (DragImageX, DragImageY, DragImageWidth, DragImageHeight));
if (!clipping.IsEmpty) {
clipping = new Region ();
}
- /*#if DEBUG_LOG
- DebugLog.AddEvent (DbgEvtType.IFaceEndDrawing);
- #endif*/
- #if MEASURE_TIME
- drawingMeasure.StopCycle();
- #endif
+#if DEBUG_LOG
+ DbgLogger.EndEvent (DbgEvtType.IFaceDrawing, true);
+#endif
}
#endregion
public Rectangle getSlot () { return ClientRectangle; }
#endregion
-#if MEASURE_TIME
- public PerformanceMeasure clippingMeasure = new PerformanceMeasure ("Clipping", 1);
- public PerformanceMeasure layoutingMeasure = new PerformanceMeasure ("Layouting", 1);
- public PerformanceMeasure updateMeasure = new PerformanceMeasure ("Update", 1);
- public PerformanceMeasure drawingMeasure = new PerformanceMeasure ("Drawing", 1);
- public List<PerformanceMeasure> PerfMeasures = new List<PerformanceMeasure> ();
-#endif
+
#if DEBUG_LAYOUTING
public List<LQIList> LQIsTries = new List<LQIList>();
public LQIList curLQIsTries = new LQIList();
Slot = Rectangle.Zero;
NewSlot = Rectangle.Zero;
result = Result.Register;
- DebugLog.AddEvent (DbgEvtType.GORegisterLayouting, this);
+ DbgLogger.AddEvent (DbgEvtType.GORegisterLayouting, this);
#endif
}
#endregion
//cancel layouting for object without parent, maybe some were in queue when
//removed from a listbox
#if DEBUG_LOG
- DebugLog.AddEvent (DbgEvtType.GOProcessLayoutingWithNoParent, this);
+ DbgLogger.AddEvent (DbgEvtType.GOProcessLayoutingWithNoParent, this);
#endif
go.parentRWLock.ExitReadLock ();
return;
}
#if DEBUG_LOG
- DbgEvent dbgEvt = DebugLog.AddEvent (DbgEvtType.GOProcessLayouting, this);
+ DbgLogger.DbgEvent dbgEvt = DbgLogger.StartEvent (DbgEvtType.GOProcessLayouting, this);
#endif
LayoutingTries++;
if (!Layoutable.UpdateLayout (LayoutType)) {
- #if DEBUG_LOG
- dbgEvt.end = DebugLog.chrono.ElapsedTicks;
- #endif
if (LayoutingTries < Interface.MaxLayoutingTries) {
Layoutable.RegisteredLayoutings |= LayoutType;
(Layoutable as Widget).IFace.LayoutingQueue.Enqueue (this);
else{
result = Result.Success;
}
- dbgEvt.data = this;
+ DbgLogger.EndEvent (DbgEvtType.GOProcessLayouting).data = this;
#endif
go.parentRWLock.ExitReadLock ();
}
/// Items loading thread
/// </summary>
void loading(){
+#if DEBUG_LOG
+ DbgLogger.StartEvent (DbgEvtType.TGLoadingThread, this);
+#endif
try {
loadPage (data, items, dataTest);
} catch (Exception ex) {
Monitor.Exit (IFace.LayoutMutex);
System.Diagnostics.Debug.WriteLine ("loading thread aborted: " + ex.ToString());
}
-
+#if DEBUG_LOG
+ DbgLogger.EndEvent (DbgEvtType.TGLoadingThread);
+#endif
}
-// //if (!ItemTemplates.ContainsKey ("default"))
-// // ItemTemplates ["default"] = Interface.GetItemTemplate (ItemTemplate);
-//
-// for (int i = 1; i <= (data.Count / itemPerPage) + 1; i++) {
-// if ((bool)loadingThread?.cancelRequested) {
-// this.Dispose ();
-// return;
-// }
-// loadPage (i);
-// Thread.Sleep (1);
-// }
-// }
+ // //if (!ItemTemplates.ContainsKey ("default"))
+ // // ItemTemplates ["default"] = Interface.GetItemTemplate (ItemTemplate);
+ //
+ // for (int i = 1; i <= (data.Count / itemPerPage) + 1; i++) {
+ // if ((bool)loadingThread?.cancelRequested) {
+ // this.Dispose ();
+ // return;
+ // }
+ // loadPage (i);
+ // Thread.Sleep (1);
+ // }
+ // }
void cancelLoadingThread(){
if (loadingThread == null)
return;
bool layoutMx = Monitor.IsEntered (IFace.LayoutMutex);
#if DEBUG_LOG
- DebugLog.AddEvent (DbgEvtType.TGCancelLoadingThread, this);
+ DbgLogger.AddEvent (DbgEvtType.TGCancelLoadingThread, this);
#endif
if (layoutMx)
Clipping = new Region ();
#if DEBUG_LOG
GraphicObjects.Add (this);
- DebugLog.AddEvent(DbgEvtType.GOClassCreation, this);
+ DbgLogger.AddEvent(DbgEvtType.GOClassCreation, this);
#endif
}
/// <summary>
/// If enabled, resulting bitmap of graphic object is cached
/// speeding up rendering of complex object. Default is enabled.
/// </summary>
- [DesignCategory ("Behavior")][DefaultValue(true)]
+ [DesignCategory ("Behavior")][DefaultValue(false)]
public virtual bool CacheEnabled {
get { return cacheEnabled; }
set {
rootDataLevel = true;
#if DEBUG_LOG
- DbgEvent dbgEvt = DebugLog.AddEvent(DbgEvtType.GOLockUpdate, this);
+ DbgLogger.StartEvent(DbgEvtType.GOLockUpdate, this);
#endif
lock (IFace.UpdateMutex) {
OnDataSourceChanged (this, dse);
NotifyValueChangedAuto (DataSource);
}
#if DEBUG_LOG
- dbgEvt.end = DebugLog.chrono.ElapsedTicks;
+ DbgLogger.EndEvent (DbgEvtType.GOLockUpdate);
#endif
}
get {
public virtual void OnDataSourceChanged(object sender, DataSourceChangeEventArgs e){
DataSourceChanged.Raise (this, e);
#if DEBUG_LOG
- DebugLog.AddEvent(DbgEvtType.GONewDataSource, this);
+ DbgLogger.AddEvent(DbgEvtType.GONewDataSource, this);
#endif
#if DEBUG_BINDING
public void loadDefaultValues()
{
#if DEBUG_LOG
- DbgEvent dbgEvt = DebugLog.AddEvent(DbgEvtType.GOInitialization, this);
+ DbgLogger.StartEvent (DbgEvtType.GOInitialization, this);
#endif
Type thisType = this.GetType ();
/*} catch (Exception ex) {
throw new Exception ("Error applying style <" + styleKey + ">:", ex);
}*/
-
- #if DEBUG_LOG
- dbgEvt.end = DebugLog.chrono.ElapsedTicks;
- #endif
-
onInitialized (this, null);
}
void setDefaultValue (ILGenerator il, PropertyInfo pi, ref List<Style> styling)
protected virtual void onInitialized (object sender, EventArgs e){
Initialized.Raise(sender, e);
+ #if DEBUG_LOG
+ DbgLogger.EndEvent (DbgEvtType.GOInitialization);
+ #endif
}
bool getDefaultEvent(EventInfo ei, List<Style> styling,
out string expression){
/// </summary>
public virtual void ClippingRegistration(){
#if DEBUG_LOG
- DbgEvent dbgEvt = DebugLog.AddEvent(DbgEvtType.GOClippingRegistration, this);
+ DbgLogger.StartEvent (DbgEvtType.GOClippingRegistration, this);
#endif
parentRWLock.EnterReadLock ();
if (parent != null) {
}
parentRWLock.ExitReadLock ();
#if DEBUG_LOG
- dbgEvt.end = DebugLog.chrono.ElapsedTicks;
+ DbgLogger.EndEvent (DbgEvtType.GOClippingRegistration);
#endif
}
/// <summary>
return;
}
#if DEBUG_LOG
- DbgEvent dbgEvt = DebugLog.AddEvent(DbgEvtType.GORegisterClip, this);
+ DbgLogger.StartEvent(DbgEvtType.GORegisterClip, this);
#endif
Rectangle cb = ClientRectangle;
Rectangle r = clip + cb.Position;
r.Height -= r.Bottom - cb.Bottom;
if (r.Width < 0 || r.Height < 0) {
//Debug.WriteLine ($"Invalid clip: {clip}:{r} hnd:{this}");//\n{Environment.StackTrace}");
- return;
+ #if DEBUG_LOG
+ DbgLogger.EndEvent (DbgEvtType.GORegisterClip);
+ #endif
+ return;
}
if (cacheEnabled && !IsDirty)
Clipping.UnionRectangle (r);
- if (Parent == null)
+ if (Parent == null) {
+ #if DEBUG_LOG
+ DbgLogger.EndEvent (DbgEvtType.GORegisterClip);
+ #endif
return;
+ }
Widget p = Parent as Widget;
- if (p?.IsDirty == true && p?.CacheEnabled == true)
+ if (p?.IsDirty == true && p?.CacheEnabled == true) {
+ #if DEBUG_LOG
+ DbgLogger.EndEvent (DbgEvtType.GORegisterClip);
+ #endif
return;
+ }
Parent.RegisterClip (r + Slot.Position);
#if DEBUG_LOG
- dbgEvt.end = DebugLog.chrono.ElapsedTicks;
+ DbgLogger.EndEvent (DbgEvtType.GORegisterClip);
#endif
}
/// <summary> Full update, if width or height is 'Fit' a layouting is requested, and a redraw is done in any case. </summary>
return;
}
#endif
-
IsDirty = true;
if (RegisteredLayoutings == LayoutingType.None)
IFace.EnqueueForRepaint (this);
#endif
if (Parent == null)
return;
-#if DEBUG_LOG
- DbgEvent dbgEvt = DebugLog.AddEvent (DbgEvtType.GOLockLayouting, this);
-#endif
+ #if DEBUG_LOG
+ DbgLogger.StartEvent (DbgEvtType.GOLockLayouting, this);
+ #endif
lock (IFace.LayoutMutex) {
//prevent queueing same LayoutingType for this
layoutType &= (~RegisteredLayoutings);
- if (layoutType == LayoutingType.None)
+ if (layoutType == LayoutingType.None) {
+ #if DEBUG_LOG
+ DbgLogger.EndEvent (DbgEvtType.GOLockLayouting);
+ #endif
return;
+ }
//dont set position for stretched item
if (Width == Measure.Stretched)
layoutType &= (~LayoutingType.X);
// //prevent queueing same LayoutingType for this
layoutType &= (~RegisteredLayoutings);
- if (layoutType == LayoutingType.None)
+ if (layoutType == LayoutingType.None) {
+ #if DEBUG_LOG
+ DbgLogger.EndEvent (DbgEvtType.GOLockLayouting);
+ #endif
return;
+ }
//enqueue LQI LayoutingTypes separately
if (layoutType.HasFlag (LayoutingType.Width))
if (layoutType.HasFlag (LayoutingType.ArrangeChildren))
IFace.LayoutingQueue.Enqueue (new LayoutingQueueItem (LayoutingType.ArrangeChildren, this));
}
-#if DEBUG_LOG
- dbgEvt.end = DebugLog.chrono.ElapsedTicks;
-#endif
+ #if DEBUG_LOG
+ DbgLogger.EndEvent (DbgEvtType.GOLockLayouting);
+ #endif
}
/// <summary> trigger dependant sizing component update </summary>
protected virtual void onDraw(Context gr)
{
#if DEBUG_LOG
- DbgEvent dbgEvt = DebugLog.AddEvent(DbgEvtType.GODraw, this);
+ DbgLogger.StartEvent(DbgEvtType.GODraw, this);
#endif
Rectangle rBack = new Rectangle (Slot.Size);
gr.Fill ();
#if DEBUG_LOG
- dbgEvt.end = DebugLog.chrono.ElapsedTicks;
+ DbgLogger.EndEvent (DbgEvtType.GODraw);
#endif
}
protected virtual void RecreateCache ()
{
#if DEBUG_LOG
- DbgEvent dbgEvt = DebugLog.AddEvent(DbgEvtType.GORecreateCache, this);
+ DbgLogger.StartEvent (DbgEvtType.GORecreateCache, this);
#endif
/*if (bmp == null)
IsDirty = false;
#if DEBUG_LOG
- dbgEvt.end = DebugLog.chrono.ElapsedTicks;
+ DbgLogger.EndEvent (DbgEvtType.GORecreateCache);
#endif
}
protected virtual void UpdateCache(Context ctx){
#if DEBUG_LOG
- DbgEvent dbgEvt = DebugLog.AddEvent(DbgEvtType.GOUpdateCacheAndPaintOnCTX, this);
+ DbgLogger.StartEvent(DbgEvtType.GOUpdateCache, this);
#endif
Rectangle rb = Slot + Parent.ClientRectangle.Position;
Clipping.Dispose ();
Clipping = new Region ();
#if DEBUG_LOG
- dbgEvt.end = DebugLog.chrono.ElapsedTicks;
+ DbgLogger.EndEvent (DbgEvtType.GOUpdateCache);
#endif
}
/// <summary> Chained painting routine on the parent context of the actual cached version
public virtual void Paint (ref Context ctx)
{
#if DEBUG_LOG
- DebugLog.AddEvent(DbgEvtType.GOPaint, this);
+ DbgLogger.AddEvent(DbgEvtType.GOPaint, this);
#endif
//TODO:this test should not be necessary
using System.Collections.Generic;
using System.IO;
using System.Linq;
+using System.Threading.Tasks;
using Crow.Cairo;
#if DEBUG_LOG
{
public class DbgLogViewer : ScrollingObject
{
- public static Dictionary<DbgEvtType,Color> colors;
+ public static Dictionary<DbgEvtType, Color> colors;
- public static Configuration colorsConf = new Configuration("dbgcolor.conf");
+ public static Configuration colorsConf = new Configuration ("dbgcolor.conf");//, Interface.GetStreamFromPath("#Crow.dbgcolor.conf"));
#region debug viewer private classes
- public class DbgData {
- public int objInstanceNum;
- public LayoutingType layout;
+ public class DbgLayoutEvent : DbgWidgetEvent
+ {
+ public LayoutingType layouting;
public LayoutingQueueItem.Result result;
-
- public DbgData (int _obj) {
- objInstanceNum = _obj;
+ public override Color Color {
+ get {
+ if (type == DbgEvtType.GORegisterLayouting)
+ return Colors.GreenYellow;
+ if (type == DbgEvtType.GOProcessLayoutingWithNoParent)
+ return Colors.DarkRed;
+ switch (result) {
+ case LayoutingQueueItem.Result.Success:
+ return Colors.Green;
+ case LayoutingQueueItem.Result.Deleted:
+ return Colors.Red;
+ case LayoutingQueueItem.Result.Discarded:
+ return Colors.OrangeRed;
+ default:
+ return Colors.Orange;
+ }
+ }
+ }
+ }
+ public class DbgWidgetEvent : DbgEvent
+ {
+ public int widgetInstanceId;
+ public override Color Color {
+ get {
+ switch (type) {
+ case DbgEvtType.GOClassCreation:
+ return Colors.DarkSlateGrey;
+ case DbgEvtType.GOInitialization:
+ return Colors.DarkOliveGreen;
+ case DbgEvtType.GOClippingRegistration:
+ return Colors.MediumTurquoise;
+ case DbgEvtType.GORegisterClip:
+ return Colors.Turquoise;
+ case DbgEvtType.GORegisterForGraphicUpdate:
+ return Colors.LightPink;
+ case DbgEvtType.GOEnqueueForRepaint:
+ return Colors.LightSalmon;
+ case DbgEvtType.GONewDataSource:
+ return Colors.MediumVioletRed;
+ case DbgEvtType.GODraw:
+ return Colors.SteelBlue;
+ case DbgEvtType.GORecreateCache:
+ return Colors.CornflowerBlue;
+ case DbgEvtType.GOUpdateCache:
+ return Colors.SteelBlue;
+ case DbgEvtType.GOPaint:
+ return Colors.RoyalBlue;
+ case DbgEvtType.GOLockUpdate:
+ return Colors.SaddleBrown;
+ case DbgEvtType.GOLockClipping:
+ return Colors.Sienna;
+ case DbgEvtType.GOLockRender:
+ return Colors.BurlyWood;
+ case DbgEvtType.GOLockLayouting:
+ return Colors.GoldenRod;
+ case DbgEvtType.TGCancelLoadingThread:
+ return Colors.Maroon;
+ default:
+ return Colors.Crimson;
+ }
+ if (type.HasFlag (DbgEvtType.GOLock))
+ return Colors.DarkMagenta;
+ return Colors.White;
+ }
}
}
public class DbgEvent {
public long begin, end;
+ public int threadId;
public DbgEvtType type;
- public DbgData data = null;
+ public DbgEvent parentEvent;
+ public List<DbgEvent> events;
+ public bool HasChildEvents => events != null && events.Count > 0;
+ public long Duration => end - begin;
+
+ public virtual Color Color {
+ get {
+ switch (type) {
+ case DbgEvtType.IFaceLayouting:
+ return Colors.Yellow;
+ case DbgEvtType.IFaceClipping:
+ return Colors.DarkTurquoise;
+ case DbgEvtType.IFaceDrawing:
+ return Colors.MidnightBlue;
+ case DbgEvtType.IFaceUpdate:
+ return Colors.Grey;
+ case DbgEvtType.IFaceLoad:
+ return Colors.Teal;
+ default:
+ return Colors.White;
+ }
+
+ }
+ }
+
+ public void AddEvent (DbgEvent evt)
+ {
+ if (events == null)
+ events = new List<DbgEvent> () { evt };
+ else
+ events.Add (evt);
+ evt.parentEvent = this;
+ }
public DbgEvent() {}
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]);
- }
+ DbgEvtType evtType = (DbgEvtType)Enum.Parse (typeof (DbgEvtType), tmp [3]);
+
+ if (evtType.HasFlag (DbgEvtType.GraphicObject)) {
+ if (evtType.HasFlag (DbgEvtType.GOLayouting))
+ return new DbgLayoutEvent () {
+ begin = long.Parse (tmp [0]),
+ end = long.Parse (tmp [1]),
+ threadId = int.Parse (tmp [2]),
+ type = evtType,
+ widgetInstanceId = int.Parse (tmp [4]),
+ layouting = (LayoutingType)Enum.Parse (typeof (LayoutingType), tmp [5]),
+ result = evtType == DbgEvtType.GOProcessLayouting ?
+ (LayoutingQueueItem.Result)Enum.Parse (typeof (LayoutingQueueItem.Result), tmp [6])
+ : LayoutingQueueItem.Result.Unknown
+ };
+ return new DbgWidgetEvent () {
+ begin = long.Parse (tmp [0]),
+ end = long.Parse (tmp [1]),
+ threadId = int.Parse (tmp [2]),
+ type = evtType,
+ widgetInstanceId = int.Parse (tmp [4]),
+ };
}
- return evt;
+ return new DbgEvent () {
+ begin = long.Parse (tmp [0]),
+ end = long.Parse (tmp [1]),
+ threadId = int.Parse (tmp [2]),
+ type = evtType,
+ };
}
+ public override string ToString ()
+ => $"{begin}:{end}:{type}";
}
- class DbgGo {
+ public 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;
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 List<DbgEvent> events = new List<DbgEvent>();//flattened event list of this widget
public static DbgGo Parse (string str) {
DbgGo g = new DbgGo ();
reloadColors ();
}
protected DbgLogViewer () : base(){}
- public DbgLogViewer (Interface iface) : base(iface){}
+ public DbgLogViewer (Interface iface, string style = null) : base(iface, style){}
#endregion
FontExtents fe;
double xScale = 1.0/512.0, yScale = 1.0, leftMargin, topMargin = 0.0;
string logFile;
+ DbgGo curWidget;
+ DbgEvent curEvent;
- List<DbgEvent> events;//global events
+ List<DbgEvent> events;
List<DbgGo> objs;
+ public List<DbgEvent> Events => events;
+ public List<DbgGo> Widgets => objs;
+
+
long currentTick = 0, selStart = -1, selEnd = -1, minTicks = 0, maxTicks = 0, visibleTicks = 0;
int currentLine = -1;
int visibleLines = 1;
+ Point mousePos;
public string LogFile {
get { return logFile; }
return;
logFile = value;
+ Console.WriteLine ("before load");
loadDebugFile ();
+ Console.WriteLine ("after load");
NotifyValueChanged ("LogFile", logFile);
RegisterForGraphicUpdate ();
}
}
public double YScale {
- get { return yScale; }
+ get => yScale;
set {
if (yScale == value)
return;
RegisterForGraphicUpdate ();
}
}
-
-
- void storeEvent (DbgEvent evt) {
- if (evt.data == null)//global events
- events.Add (evt);
- else {
- DbgGo go = objs.Where (o => o.instanceNum == evt.data.objInstanceNum).FirstOrDefault ();
- if (go == null)
- System.Diagnostics.Debug.WriteLine ("Unknown instance: " + evt.data.objInstanceNum);
- else
- go.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;
-
- topMargin = 2.0 * fe.Height;
-
- updateVisibleLines ();
- updateVisibleTicks ();
- }
- }
-
- }
- void updateVisibleLines(){
- visibleLines = fe.Height < 1 ? 1 : (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 {
}
}
public override int ScrollY {
- get {
- return base.ScrollY;
- }
+ get => base.ScrollY;
set {
base.ScrollY = value;
if (objs == null)
return;
-
+
Rectangle cb = ClientRectangle;
cb.Left += (int)leftMargin;
cb.Width -= (int)leftMargin;
currentLine = (int)((double)(mousePos.Y - cb.Top) / fe.Height) + ScrollY;
NotifyValueChanged ("CurrentLine", currentLine);
+ }
+ }
+ public DbgGo CurrentWidget {
+ get => curWidget;
+ internal set {
+ if (curWidget == value)
+ return;
+ curWidget = value;
+ NotifyValueChanged (nameof (CurrentWidget), curWidget);
+ }
+ }
+ public DbgEvent CurrentEvent {
+ get => curEvent;
+ internal set {
+ if (curEvent == value)
+ return;
+ curEvent = value;
+ NotifyValueChanged (nameof (CurrentEvent), curEvent);
}
}
+ void drawEvents (Context ctx, List<DbgEvent> evts)
+ {
+ if (evts == null || evts.Count == 0)
+ return;
+ Rectangle cb = ClientRectangle;
+
+ foreach (DbgEvent evt in evts) {
+ if (evt.end - minTicks <= ScrollX)
+ continue;
+ if (evt.begin - minTicks > ScrollX + visibleTicks)
+ break;
+ double penY = topMargin + ClientRectangle.Top;
+ if (evt.type.HasFlag (DbgEvtType.GraphicObject)) {
+ DbgWidgetEvent eW = evt as DbgWidgetEvent;
+ int lIdx = eW.widgetInstanceId - ScrollY;
+ if (lIdx < 0 || lIdx > visibleLines)
+ continue;
+ penY += (lIdx) * fe.Height;
+
+ ctx.SetSource (evt.Color);
+
+ 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;
+ }
+ x += leftMargin + cb.Left;
+ double rightDiff = x + w - cb.Right;
+ if (rightDiff > 0)
+ w -= rightDiff;
+
+ ctx.Rectangle (x, penY, w, fe.Height);
+ ctx.Fill ();
+ } else {
+ double x = xScale * (evt.begin - minTicks - ScrollX);
+ x += leftMargin + cb.Left;
+
+ double trunc = Math.Truncate (x);
+ if (x - trunc > 0.5)
+ x = trunc + 0.5;
+ else
+ x = trunc - 0.5;
+
+
+ ctx.SetSource (Colors.Yellow);
+ ctx.MoveTo (x, penY);
+ ctx.LineTo (x, cb.Bottom);
+ ctx.Stroke ();
+ string s = evt.type.ToString () [5].ToString ();
+ TextExtents te = ctx.TextExtents (s);
+ ctx.Rectangle (x - 0.5 * te.Width, penY - te.Height, te.Width, te.Height);
+ ctx.Fill ();
+ ctx.MoveTo (x - 0.5 * te.Width, penY - ctx.FontExtents.Descent);
+ ctx.SetSource (Colors.Jet);
+ ctx.ShowText (s);
+
+ }
+ drawEvents (ctx, evt.events);
+ }
+ }
protected override void onDraw (Cairo.Context gr)
{
break;
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;
- }
- x += leftMargin + cb.Left;
- double rightDiff = x + w - cb.Right;
- if (rightDiff > 0)
- w -= rightDiff;
- //if (x + w > cb.Right)
- // continue;
-
- Color c = Colors.Black;
-
- if (evt.type == DbgEvtType.GOProcessLayouting) {
- switch (evt.data.result) {
- case LayoutingQueueItem.Result.Success:
- c = Crow.Colors.Green;
- break;
- case LayoutingQueueItem.Result.Deleted:
- c = Crow.Colors.Red;
- break;
- case LayoutingQueueItem.Result.Discarded:
- c = Crow.Colors.OrangeRed;
- break;
- case LayoutingQueueItem.Result.Requeued:
- c = Crow.Colors.Orange;
- break;
- }
- } else if (evt.type.HasFlag (DbgEvtType.GOLock))
- c = Colors.BlueViolet;
- else if (colors.ContainsKey (evt.type))
- c = colors [evt.type];
- //else
- // System.Diagnostics.Debugger.Break ();
- c = c.AdjustAlpha (0.2);
- gr.SetSource (c);
-
- gr.Rectangle (x, penY, w, fe.Height);
- gr.Fill ();
- }
-
penY += fe.Height;
gr.SetSource (Crow.Colors.Jet);
Foreground.SetAsSource (gr);
gr.MoveTo (penX, penY - gr.FontExtents.Descent);
- gr.ShowText (g.name);
+ gr.ShowText (g.name + g.instanceNum);
gr.SetSource (Crow.Colors.White);
gr.MoveTo (cb.X, penY - gr.FontExtents.Descent);
- gr.ShowText ((i+ ScrollY).ToString());
-
+ gr.ShowText ((i + ScrollY).ToString ());
}
+ drawEvents (gr, events);
+ /*
+ for (int i = 0; i < visibleLines; i++) {
+ foreach (DbgEvent evt in events) {
+ if (evt.end - minTicks <= ScrollX)
+ continue;
+ if (evt.begin - minTicks > ScrollX + visibleTicks)
+ break;
+
+
+ }
+
+
+ }
+ */
gr.MoveTo (cb.Left, topMargin - 0.5 + cb.Top);
gr.LineTo (cb.Right, topMargin - 0.5 + cb.Top);
gr.Stroke ();
//global events
- foreach (DbgEvent evt in events) {
+/* foreach (DbgEvent evt in events) {
if (evt.begin - minTicks <= ScrollX)
continue;
double x = xScale * (evt.begin - minTicks - ScrollX) ;
x += leftMargin + cb.Left;
- gr.SetSource (Crow.Colors.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.SetSource (Crow.Colors.Jet);
- gr.ShowText (s);
- }
+ }*/
}
public override void Paint (ref Cairo.Context ctx)
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);
+ double y = fe.Height * (currentLine - ScrollY) + topMargin + cb.Top;
+ r = new Rectangle (cb.Left, (int)y, cb.Width, (int)fe.Height);
ctx.Operator = Cairo.Operator.Add;
ctx.SetSourceRGBA (0.1, 0.1, 0.1, 0.4);
ctx.Fill ();
}
- if (selStart < 0) {
+ if (selStart < 0 || selEnd < 0) {
ctx.Operator = Cairo.Operator.Over;
return;
}
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;
+ double selEndX = (double)(selEnd - ScrollX - minTicks) * xScale + leftMargin + cb.Left;
if (selStartX < selEndX) {
ctxR.X = (int)selStartX;
}
}
- 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)(mousePos.X - cb.X) / xScale) + minTicks + ScrollX;
-
- }
public override void onMouseLeave (object sender, MouseMoveEventArgs e)
{
base.onMouseLeave (sender, e);
public override void onMouseMove (object sender, MouseMoveEventArgs e)
{
base.onMouseMove (sender, e);
+
+ long lastTick = currentTick;
updateMouseLocalPos (e.Position);
- if (selStart >= 0 && IFace.IsDown (Glfw.MouseButton.Left))
+ if (IFace.IsDown (Glfw.MouseButton.Left) && selStart >= 0)
selEnd = currentTick;
+ else if (IFace.IsDown(Glfw.MouseButton.Right)) {
+ ScrollX += (int)(lastTick - currentTick);
+ updateMouseLocalPos (e.Position);
+ }
if (RegisteredLayoutings == LayoutingType.None && !IsDirty)
IFace.EnqueueForRepaint (this);
{
base.onMouseDown (sender, e);
- selStart = currentTick;
- selEnd = -1;
+ if (e.Button == Glfw.MouseButton.Left) {
+ 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;
+
+ selStart = -1;
+ selEnd = -1;
+
RegisterForRedraw ();
}
selEnd = selStart = -1;
}
}
+ async void loadDebugFile ()
+ {
+ await loadDebugFileAsync ();
+ }
+
+
+
+ async Task loadDebugFileAsync ()
+ {
+ if (!File.Exists (logFile))
+ return;
+
+ events = new List<DbgEvent> ();
+ objs = new List<DbgGo> ();
+ minTicks = maxTicks = 0;
+ leftMargin = topMargin = 0.0;
+ using (Context gr = new Context (IFace.surf)) {
+ 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;
+ }
+
+ Stack<DbgEvent> startedEvents = new Stack<DbgEvent> ();
+
+ if (!s.EndOfStream) {
+ while (!s.EndOfStream) {
+ int level = 0;
+ while (s.Peek () == (int)'\t') {
+ s.Read ();
+ level++;
+ }
+ DbgEvent evt = DbgEvent.Parse (s.ReadLine ());
+ if (evt.end > maxTicks)
+ maxTicks = evt.end;
+ if (level == 0) {
+ startedEvents.Clear ();
+ events.Add (evt);
+ } else {
+ int levelDiff = level - startedEvents.Count + 1;
+ if (levelDiff > 0) {
+ if (levelDiff > 1)
+ System.Diagnostics.Debugger.Break ();
+ startedEvents.Peek ().AddEvent (evt);
+ } else {
+ startedEvents.Pop ();
+ if (-levelDiff > startedEvents.Count)
+ System.Diagnostics.Debugger.Break ();
+ while (startedEvents.Count > level)
+ startedEvents.Pop ();
+ startedEvents.Peek ().AddEvent (evt);
+ }
+ }
+ startedEvents.Push (evt);
+ if (evt.type.HasFlag(DbgEvtType.GraphicObject))
+ objs [(evt as DbgWidgetEvent).widgetInstanceId].events.Add (evt);
+ }
+ if (events.Count > 0)
+ minTicks = events [0].begin;
+ }
+ }
+
+ leftMargin = 2.5 + maxNameWidth;
+ topMargin = 2.0 * fe.Height;
+
+ updateVisibleLines ();
+ updateVisibleTicks ();
+ }
+ NotifyValueChanged ("Widgets", Widgets);
+ NotifyValueChanged ("Events", Events);
+ }
+
+ void updateVisibleLines ()
+ {
+ visibleLines = fe.Height < 1 ? 1 : (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 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);
+ }
+
+ 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)(mousePos.X - cb.X) / xScale) + minTicks + ScrollX;
+ CurrentWidget = (currentLine < 0 || currentLine >= objs.Count) ? null : objs [currentLine];
+ CurrentEvent = curWidget?.events.FirstOrDefault (e => e.begin <= currentTick && e.end >= currentTick);
+ }
void zoom (long start, long end) {
//Rectangle cb = ClientRectangle;
//cb.X += (int)leftMargin;
using System.Diagnostics;
using System.IO;
using System.Linq;
+using System.Threading;
#if DEBUG_LOG
namespace Crow
[Flags]
public enum DbgEvtType {
////9 nth bit set for iface event
- IFace = 0x0100,
- IFaceStartLayouting = 0x0101,
- IFaceEndLayouting = 0x0102,
- IFaceStartClipping = 0x0103,
- IFaceEndClipping = 0x0104,
- IFaceStartDrawing = 0x0105,
- IFaceEndDrawing = 0x0106,
- IFaceUpdate = 0x0107,
+ IFace = 0x10000,
+ IFaceFocus = 0x20000,
+ GraphicObject = 0x00100,
+ GOLayouting = 0x00200,
+ Drawing = 0x00400,
+ GOLock = 0x00800,
+ IFaceLayouting = IFace | 0x01,
+ IFaceClipping = IFace | 0x02,
+ IFaceDrawing = IFace | 0x03,
+ IFaceUpdate = IFace | 0x04,
+ IFaceLoad = IFace | 0x05,
+ IFaceInit = IFace | 0x06,
+
+ HoverWidget = IFaceFocus | 0x01,
+ FocusedWidget = IFaceFocus | 0x02,
+ ActiveWidget = IFaceFocus | 0x03,
+
//10 nth bit set for graphic obj
- GraphicObject = 0x0100,
- Warning = 0x4000,
+ Warning = 0x4000,
Error = 0x8000,
GOClassCreation = GraphicObject | 0x01,
GOInitialization = GraphicObject | 0x02,
GORegisterForGraphicUpdate = GraphicObject | 0x05,
GOEnqueueForRepaint = GraphicObject | 0x06,
GONewDataSource = GraphicObject | 0x07,
- GOLayouting = 0x0200,
- Drawing = 0x0400,
- GOLock = 0x0800,
TemplatedGroup = 0x1000,
GORegisterLayouting = GraphicObject | GOLayouting | 0x01,
GOProcessLayouting = GraphicObject | GOLayouting | 0x02,
GOProcessLayoutingWithNoParent = Warning | GraphicObject | GOLayouting | 0x01,
GODraw = GraphicObject | Drawing | 0x01,
GORecreateCache = GraphicObject | Drawing | 0x02,
- GOUpdateCacheAndPaintOnCTX = GraphicObject | Drawing | 0x03,
+ GOUpdateCache = GraphicObject | Drawing | 0x03,
GOPaint = GraphicObject | Drawing | 0x04,
GOLockUpdate = GraphicObject | GOLock | 0x01,
GOLockRender = GraphicObject | GOLock | 0x03,
GOLockLayouting = GraphicObject | GOLock | 0x04,
- TGCancelLoadingThread = GraphicObject | TemplatedGroup | 0x01,
+ TGLoadingThread = GraphicObject | TemplatedGroup | 0x01,
+ TGCancelLoadingThread = GraphicObject | TemplatedGroup | 0x02,
+
+ All = 0x0FFFFFFF
}
- /// <summary>
- /// debug events as recorded, another class is used in the viewer
- /// </summary>
- 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;
- begin = timeStamp;
- end = timeStamp;
+
+
+ public static class DbgLogger
+ {
+ public static DbgEvtType IncludeEvents = DbgEvtType.All;
+ public static DbgEvtType DiscardEvents = DbgEvtType.IFaceFocus;
+
+ static bool logevt (DbgEvtType evtType)
+ {
+ return (evtType & DiscardEvents) == 0 && (evtType & IncludeEvents) != 0;
}
- public override string ToString ()
+ /// <summary>
+ /// debug events as recorded, another class is used in the viewer
+ /// </summary>
+ public class DbgEvent
{
- Widget go = data as Widget;
- if (go != null)
- return string.Format ("{0};{1};{2};{3}", begin, end, type, Widget.GraphicObjects.IndexOf(go).ToString());
- if (!(data is LayoutingQueueItem))
- 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, end, type, Widget.GraphicObjects.IndexOf(lqi.graphicObject).ToString(), lqi.LayoutType.ToString(), lqi.result.ToString());
- return string.Format ("{0};{1};{2};{3};{4}", begin, end, type, Widget.GraphicObjects.IndexOf(lqi.graphicObject).ToString(), lqi.LayoutType.ToString());
-
+ public long begin, end;
+ public DbgEvtType type;
+ public object data = null;
+ public int threadId;
+ public List<DbgEvent> Events = new List<DbgEvent> ();
+
+ public DbgEvent () { }
+
+ public DbgEvent (long timeStamp, DbgEvtType evt, object _data = null)
+ {
+ data = _data;
+ type = evt;
+ begin = timeStamp;
+ end = timeStamp;
+ threadId = Thread.CurrentThread.ManagedThreadId;
+ }
+
+ public override string ToString ()
+ {
+ string tmp = $"{begin};{end};{threadId};{type}";
+ if (type.HasFlag (DbgEvtType.GraphicObject)) {
+ if (type.HasFlag (DbgEvtType.GOLayouting)) {
+ LayoutingQueueItem lqi = (LayoutingQueueItem)data;
+ tmp += $";{Widget.GraphicObjects.IndexOf (lqi.graphicObject).ToString ()};{lqi.LayoutType}";
+ if (type == DbgEvtType.GOProcessLayouting)
+ tmp += $";{lqi.result}";
+ } else
+ tmp += $";{Widget.GraphicObjects.IndexOf (data as Widget).ToString ()}";
+ }
+ return tmp;
+ }
}
- }
- public static class DebugLog
- {
- static Surface surf;
- static Context ctx;
-
- static Crow.Rectangle bounds = new Crow.Rectangle(0,0,8182,4096);
- static double penX = 1.0;
- static double ySpacing = 10.0;
- static double xPenStart = 250.0;
- static double xResolution = 0.001; //per tick
public static Stopwatch chrono = Stopwatch.StartNew();
- public static List<DbgEvent> events = new List<DbgEvent>();
- public static DbgEvent currentEvent = null;
+ static List<DbgEvent> events = new List<DbgEvent>();
+ static Dictionary<int, Stack<DbgEvent>> startedEvents = new Dictionary<int, Stack<DbgEvent>> ();
+
+ static object logMutex = new object ();
+
+
+ static List<DbgEvent> curEventList =>
+ startedEvents.ContainsKey(Thread.CurrentThread.ManagedThreadId) ?
+ startedEvents[Thread.CurrentThread.ManagedThreadId].Count == 0 ? events : startedEvents[Thread.CurrentThread.ManagedThreadId].Peek ().Events : events;
+ public static DbgEvent StartEvent (DbgEvtType evtType, object data = null)
+ {
+ if (!logevt (evtType))
+ return null;
+ lock (logMutex) {
+ chrono.Stop ();
+ DbgEvent evt = new DbgEvent (chrono.ElapsedTicks, evtType, data);
+ curEventList.Add (evt);
+ if (!startedEvents.ContainsKey (Thread.CurrentThread.ManagedThreadId))
+ startedEvents [Thread.CurrentThread.ManagedThreadId] = new Stack<DbgEvent> ();
+ startedEvents [Thread.CurrentThread.ManagedThreadId].Push (evt);
+ chrono.Start ();
+ return evt;
+ }
+ }
+ public static DbgEvent EndEvent (DbgEvtType evtType, bool discardIfNoChildEvents = false)
+ {
+ if (!logevt (evtType))
+ return null;
+
+ lock (logMutex) {
+ chrono.Stop ();
+ if (!startedEvents.ContainsKey (Thread.CurrentThread.ManagedThreadId))
+ throw new Exception ("Current thread has no event started");
+ DbgEvent e = startedEvents [Thread.CurrentThread.ManagedThreadId].Pop ();
+ if (e.type != evtType)
+ throw new Exception ($"Begin/end event logging mismatch: {e.type}/{evtType}");
+ if (discardIfNoChildEvents && e.Events.Count == 0)
+ curEventList.Remove (e);
+ else
+ e.end = chrono.ElapsedTicks;
+ chrono.Start ();
+ return e;
+ }
+ }
public static DbgEvent AddEvent (DbgEvtType evtType, object data = null) {
- DbgEvent evt = new DbgEvent(chrono.ElapsedTicks, evtType, data);
- events.Add (evt);
- return evt;
+ if (!logevt (evtType))
+ return null;
+
+ lock (logMutex) {
+ chrono.Stop ();
+ DbgEvent evt = new DbgEvent (chrono.ElapsedTicks, evtType, data);
+ curEventList.Add (evt);
+ chrono.Start ();
+ return evt;
+ }
}
static int y, level;
if (go == null)
return;
-
go.yIndex = y++;
go.xLevel = level++;
}
level--;
}
-
+ public static void Reset ()
+ {
+ lock (logMutex) {
+ startedEvents.Clear ();
+ events.Clear ();
+ chrono.Restart ();
+ }
+ }
public static void save(Interface iface) {
- y = 1;
- level = 0;
-
- foreach (Widget go in iface.GraphicTree)
- parseTree (go);
-
- using (StreamWriter s = new StreamWriter("debug.log")){
- s.WriteLine ("[GraphicObjects]");
- lock (Widget.GraphicObjects) {
- Widget.GraphicObjects = Widget.GraphicObjects.OrderBy (o => o.yIndex).ToList();
- for (int i = 0; i < Widget.GraphicObjects.Count; i++) {
- Widget g = Widget.GraphicObjects [i];
- s.WriteLine ("{0};{1};{2};{3}", i, g.GetType ().Name, g.yIndex, g.xLevel);
+ lock (logMutex) {
+ y = 1;
+ level = 0;
+
+ foreach (Widget go in iface.GraphicTree)
+ parseTree (go);
+
+ using (StreamWriter s = new StreamWriter ("debug.log")) {
+ s.WriteLine ("[GraphicObjects]");
+ lock (Widget.GraphicObjects) {
+ Widget.GraphicObjects = Widget.GraphicObjects.OrderBy (o => o.yIndex).ToList ();
+ for (int i = 0; i < Widget.GraphicObjects.Count; i++) {
+ Widget g = Widget.GraphicObjects [i];
+ s.WriteLine ("{0};{1};{2};{3}", i, g.GetType ().Name, g.yIndex, g.xLevel);
+ }
}
+ s.WriteLine ("[Events]");
+ saveEventList (s, events);
}
- s.WriteLine ("[Events]");
+ }
+ }
- foreach (DbgEvent e in events)
- if (e != null)
- s.WriteLine (e.ToString ());
+ static void saveEventList (StreamWriter s, List<DbgEvent> events, int level = 0)
+ {
+ foreach (DbgEvent e in events) {
+ if (e == null)
+ continue;
+ s.WriteLine (new string ('\t', level) + e.ToString ());
+ saveEventList (s, e.Events, level + 1);
}
}
+
}
}
#endif
</HorizontalStack>
<HorizontalStack>
<Scroller Name="scroller1" Background="White"
- Margin="2" ScrollY="{../scrollbar1.Value}"
- ValueChanged="./_scroller_ValueChanged">
+ Margin="2" ScrollY="{../scrollbar1.Value}">
<TextBox VerticalAlignment="Top"
Text="{²Source}" Multiline="true" TextAlignment="TopLeft"
Font="mono 10"/>
--- /dev/null
+<?xml version="1.0"?>
+<Window Width="80%" Height="90%">
+<ListBox Name="ColorList" Data="{TestList}" Margin="5">
+ <Template>
+ <Wrapper Name="ItemsContainer" Orientation="Horizontal"/>
+ </Template>
+ <ItemTemplate>
+ <Group Background="{}" Width="Fit" Height="Fit" >
+ <Label Text="{}" TextAlignment="Center" Font="mono, 9" Foreground="Black" Left="2" Top="2" Margin="10" Width="100"/>
+ <Label Text="{}" TextAlignment="Center" Font="mono, 9" Left="1" Top="1" Margin="10" Width="100"/>
+ </Group>
+ </ItemTemplate>
+
+</ListBox>
+</Window>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<HorizontalStack>
+ <TreeView Width="20%" Data="{../dbv.Events}">
+ <ItemTemplate Data="events">
+ <Expandable Caption="{type}" MouseDoubleClick="/onClickForExpand" CacheEnabled="true">
+ <Template>
+ <VerticalStack>
+ <Border CornerRadius="2" Margin="0" Height="Fit" MouseDoubleClick="./onClickForExpand"
+ Foreground="Transparent"
+ MouseEnter="{Foreground=DimGrey}"
+ MouseLeave="{Foreground=Transparent}">
+ <HorizontalStack Spacing="2" Background="Onyx">
+ <Image Margin="1" Width="9" Height="9" Focusable="true" MouseDown="./onClickForExpand"
+ Path="{./Image}"
+ Visible="{HasChildEvents}"
+ SvgSub="{./IsExpanded}"
+ MouseEnter="{Background=LightGrey}"
+ MouseLeave="{Background=Transparent}"/>
+ <Label Text="{./Caption}" Width="80" Font="mono, 8" />
+ <Label Text="{Duration}" Width="40" Font="mono, 8" TextAlignment="Center" Background="DimGrey"/>
+ <Group Height="5">
+ <DbgEventWidget Event="{}" />
+ </Group>
+ </HorizontalStack>
+ </Border>
+ <Container Name="Content" Visible="false"/>
+ </VerticalStack>
+ </Template>
+ <HorizontalStack Height="Fit">
+ <Widget Width="12" Height="10"/>
+ <VerticalStack Height="Fit" Name="ItemsContainer"/>
+ </HorizontalStack>
+ </Expandable>
+ </ItemTemplate>
+ </TreeView>
+ <Splitter/>
+ <VerticalStack>
+ <DbgLogViewer Visible="false" Name="dbv" LogFile="debug.log" MouseWheelSpeed="10" Font="mono, 8"/>
+ <!--<ScrollBar Style="HScrollBar" Maximum="{../dbv.MaxScrollX}" Value="{²../dbv.ScrollX}"/>
+ <HorizontalStack Height="Fit" DataSource="{../../dbv.CurrentWidget}">
+ <Label Text="{name}"/>
+ <Label Text="{listIndex}"/>
+ <Label Text="{instanceNum}"/>
+ <Label Text="{treeIndex}"/>
+ <Label Text="{yIndex}"/>
+ <Label Text="{xLevel}"/>
+ </HorizontalStack>
+ <DbgEventWidget Height="20" Width="Stretched" Event="{../../dbv.CurrentEvent}"/>
+ <VerticalStack DataSource="{../../dbv.CurrentEvent}">
+ <HorizontalStack>
+ <Label Text="{type}"/>
+ <Label Text="{begin}"/>
+ <Label Text="{end}"/>
+ <Label Text="{Duration}"/>
+ </HorizontalStack>
+ <ListBox Data="{events}" Height="100">
+ <ItemTemplate>
+ <DbgEventWidget Height="20" Width="Stretched" Event="{}"/>
+ </ItemTemplate>
+ </ListBox>
+ </VerticalStack>-->
+ </VerticalStack>
+</HorizontalStack>
\ No newline at end of file