<CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>
<Optimize>false</Optimize>
<OutputPath>$(SolutionDir)build\Debug</OutputPath>
- <DefineConstants>DESIGN_MODE;DEBUG_LAYOUTING;DEBUG_UPDATE0;DEBUG_FOCUS0;DEBUG_DISPOSE0;TRACE0;DEBUG;MEASURE_TIME;DEBUG_LOAD0;DEBUG_BINDING0;DEBUG_CLIP_RECTANGLE0</DefineConstants>
+ <DefineConstants>DESIGN_MODE;DBG_EVENTS;DEBUG_LAYOUTING0;DEBUG_UPDATE0;DEBUG_FOCUS0;DEBUG_DISPOSE0;TRACE0;DEBUG;MEASURE_TIME;DEBUG_LOAD0;DEBUG_BINDING0;DEBUG_CLIP_RECTANGLE0</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<Optimize>true</Optimize>
<Compile Include="src\ParsingException.cs" />
<Compile Include="src\IMLAttributes.cs" />
<Compile Include="src\GraphicObjects\DockStack.cs" />
+ <Compile Include="src\DebugEvents\DebugEvent.cs" />
</ItemGroup>
<ItemGroup>
<Reference Include="System" />
<Folder Include="src\rsvg\" />
<Folder Include="src\IML\" />
<Folder Include="Icons\" />
+ <Folder Include="src\DebugEvents\" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Images\Icons\updown.svg" />
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
- <DefineConstants>DEBUG;</DefineConstants>
+ <DefineConstants>DEBUG;DBG_EVENTS</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<ConsolePause>false</ConsolePause>
protected override void processLayouting ()
{
- #if MEASURE_TIME
- layoutingMeasure.StartCycle();
+ #if DBG_EVENTS
+ DbgStartSubEvt(DbgEvtType.IFaceLayouting);
#endif
if (Monitor.TryEnter (LayoutMutex)) {
LayoutingQueueItem lqi;
while (LayoutingQueue.Count > 0) {
lqi = LayoutingQueue.Dequeue ();
- //Console.WriteLine (lqi.ToString ());
- #if DEBUG_LAYOUTING
- currentLQI = lqi;
- curLQIsTries.Add(currentLQI);
+ #if DBG_EVENTS
+ DbgStartSubEvt (new LayoutingDebugEvent(lqi.LayoutType,lqi.Layoutable as GraphicObject));
#endif
lqi.ProcessLayouting ();
+ #if DBG_EVENTS
+ DbgEndSubEvt();
+ #endif
}
LayoutingQueue = DiscardQueue;
Monitor.Exit (LayoutMutex);
DiscardQueue = null;
}
- #if MEASURE_TIME
- layoutingMeasure.StopCycle();
+ #if DBG_EVENTS
+ DbgEndSubEvt();
#endif
}
}
);
#endif
- Thread t = new Thread (interfaceThread);
- t.IsBackground = true;
- t.Start ();
+ CrowInterface.StartThread ();
initGL ();
}
#endregion
- void interfaceThread()
- {
- while (CrowInterface.ClientRectangle.Size.Width == 0)
- Thread.Sleep (5);
-
- while (true) {
- CrowInterface.Update ();
- Thread.Sleep (2);
- }
- }
#region Mouse And Keyboard handling
public virtual void ProcessResize(Rectangle newSize){
--- /dev/null
+//
+// DebugEvent.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.Diagnostics;
+using System.Collections.Generic;
+using System.Threading;
+
+namespace Crow
+{
+ #if DBG_EVENTS
+ public enum DbgEvtType {
+ Clipping = 8,
+ Interface = 0x10,
+ IfaceStart = 0x11,
+ IFaceUpdate = 0x12,
+ IFaceClipping = 0x13,
+ IFaceDrawing = 0x14,
+ Drawnig = 0x20,
+ OnDraw = 0x21,
+ Paint = 0x22,
+ UpdateCache = 0x23,
+ RecreateCache = 0x24,
+ IFaceLayouting = 0x80,
+ UpdateLayout = 0x81,
+ RegisterLayouting= 0x82,
+ }
+
+ public class DebugEvent
+ {
+ public DebugEvent (DbgEvtType type, string message = "")
+ {
+ EventType = type;
+ ThreadId = Thread.CurrentThread.ManagedThreadId;
+ }
+
+ public int ThreadId;
+ public DbgEvtType EventType;
+ public Stopwatch Time;
+ public string Message;
+
+ public DebugEvent Parent;
+ public List<DebugEvent> ChildEvents = new List<DebugEvent>();
+
+ public virtual void Start () {
+ Time = Stopwatch.StartNew();
+ }
+ public virtual void Finished () {
+ Time.Stop();
+ }
+ }
+ public class WidgetDebugEvent : DebugEvent {
+ public GraphicObject Target;
+ public LayoutingType RegisteredLayoutings;
+ public LayoutingType RequestedLayoutings;
+ public Rectangle Slot;
+ public Measure Width;
+ public Measure Height;
+
+ public WidgetDebugEvent (DbgEvtType type, GraphicObject go, string message = "") : base(type, message)
+ {
+ Target = go;
+ saveTargetState ();
+ }
+ protected virtual void saveTargetState () {
+ RegisteredLayoutings = Target.registeredLayoutings;
+ RequestedLayoutings = Target.requestedLayoutings;
+ Width = Target.Width;
+ Height = Target.Height;
+ Slot = Target.Slot;
+ }
+ public override void Finished ()
+ {
+ base.Finished ();
+ saveTargetState ();
+ }
+ }
+ public class LayoutingDebugEvent : WidgetDebugEvent
+ {
+ public enum Result {
+ Ok,
+ Requeued,
+ Discarded,
+ Deleted,
+ }
+ public LayoutingDebugEvent (LayoutingType layoutingType, GraphicObject go) : base(DbgEvtType.IFaceLayouting, go)
+ {
+ LayoutingType = layoutingType;
+ Target = go;
+ }
+ public LayoutingType LayoutingType;
+ public Rectangle PreviousSlot;
+ public Result EndResult;
+ public override void Finished ()
+ {
+ base.Finished ();
+ saveTargetState ();
+ PreviousSlot = Target.LastSlots;
+ }
+ }
+ #endif
+}
+
/// </remarks>
public class Interface : ILayoutable
{
+ #if DBG_EVENTS
+ const int MAX_THREAD = 20;
+
+ public DebugEvent[] PerThreadCurDbgEvt = new DebugEvent[MAX_THREAD];
+ public DebugEvent CurDbgEvt {
+ get { return PerThreadCurDbgEvt [Thread.CurrentThread.ManagedThreadId]; }
+ set { PerThreadCurDbgEvt [Thread.CurrentThread.ManagedThreadId] = value; }
+ }
+ public void DbgLogEvent (DebugEvent de) {
+ if (CurDbgEvt == null)
+ CurDbgEvt = new DebugEvent(DbgEvtType.IfaceStart) ;
+ de.Parent = CurDbgEvt;
+ if (CurDbgEvt != null)
+ CurDbgEvt.ChildEvents.Add(de);
+ }
+ public DebugEvent DbgStartSubEvt (DbgEvtType dbgType){
+ DebugEvent de = new DebugEvent(dbgType);
+ DbgStartSubEvt(de);
+ return de;
+ }
+ public void DbgStartSubEvt (DebugEvent de){
+ if (CurDbgEvt == null)
+ CurDbgEvt = new DebugEvent(DbgEvtType.IfaceStart) ;
+ de.Parent = CurDbgEvt;
+ CurDbgEvt.ChildEvents.Add(de);
+ CurDbgEvt = de;
+ CurDbgEvt.Start ();
+ }
+ public void DbgEndSubEvt () {
+ CurDbgEvt.Finished ();
+ CurDbgEvt = CurDbgEvt.Parent;
+ }
+ #endif
+
#region CTOR
static Interface(){
if (Type.GetType ("Mono.Runtime") == null) {
}
#endregion
+ public void StartThread () {
+ Thread t = new Thread (interfaceThread);
+ t.IsBackground = true;
+ t.Start ();
+ }
+ void interfaceThread()
+ {
+ #if DBG_EVENTS
+ CurDbgEvt = new DebugEvent(DbgEvtType.IfaceStart);
+ #endif
+
+ while (ClientRectangle.Size.Width == 0)
+ Thread.Sleep (5);
+
+ while (true) {
+ Update ();
+ Thread.Sleep (2);
+ }
+ }
public void Init () {
CurrentInterface = this;
loadCursors ();
public const int MaxCacheSize = 2048;
/// <summary> Above this count, the layouting is discard from the current
/// update cycle and requeued for the next</summary>
- public const int MaxLayoutingTries = 30;
+ public const int MaxLayoutingTries = 20;
/// <summary> Above this count, the layouting is discard for the widget and it
/// will not be rendered on screen </summary>
public const int MaxDiscardCount = 3;
/// Result: the Interface bitmap is drawn in memory (byte[] bmp) and a dirtyRect and bitmap are available
/// </summary>
public void Update(){
+ #if DBG_EVENTS
+ DbgStartSubEvt(DbgEvtType.IFaceUpdate);
+ #endif
+
if (armedClickSender != null && clickTimer.ElapsedMilliseconds >= Interface.DoubleClick) {
armedClickSender.onMouseClick (armedClickSender, armedClickEvtArgs);
armedClickSender = null;
if (!Monitor.TryEnter (UpdateMutex))
return;
- #if MEASURE_TIME
- updateMeasure.StartCycle();
- #endif
-
processLayouting ();
- #if DEBUG_LAYOUTING
- if (curLQIsTries.Count > 0){
- LQIsTries.Add(curLQIsTries);
- curLQIsTries = new LQIList();
- LQIs.Add(curLQIs);
- curLQIs = new LQIList();
- }
- #endif
-
clippingRegistration ();
processDrawing ();
- #if MEASURE_TIME
- updateMeasure.StopCycle();
- #endif
-
Monitor.Exit (UpdateMutex);
+
+ #if DBG_EVENTS
+ DbgEndSubEvt ();
+ #endif
}
#if DEBUG_LAYOUTING
public string BreakingName;
/// 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();
+ #if DBG_EVENTS
+ DbgStartSubEvt(DbgEvtType.IFaceLayouting);
#endif
if (Monitor.TryEnter (LayoutMutex)) {
DiscardQueue = new Queue<LayoutingQueueItem> ();
- //Debug.WriteLine ("======= Layouting queue start =======");
LayoutingQueueItem lqi;
while (LayoutingQueue.Count > 0) {
lqi = LayoutingQueue.Dequeue ();
- #if DEBUG_LAYOUTING
- currentLQI = lqi;
- curLQIsTries.Add(currentLQI);
- if (lqi.graphicObject.Name == BreakingName)
- Debugger.Break();
+ #if DBG_EVENTS
+ DbgStartSubEvt (new LayoutingDebugEvent(lqi.LayoutType,lqi.Layoutable as GraphicObject));
#endif
lqi.ProcessLayouting ();
+ #if DBG_EVENTS
+ DbgEndSubEvt();
+ #endif
}
LayoutingQueue = DiscardQueue;
Monitor.Exit (LayoutMutex);
DiscardQueue = null;
}
- #if MEASURE_TIME
- layoutingMeasure.StopCycle();
+ #if DBG_EVENTS
+ DbgEndSubEvt();
#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();
+ #if DBG_EVENTS
+ DbgStartSubEvt(DbgEvtType.IFaceClipping);
#endif
GraphicObject g = null;
while (ClippingQueue.Count > 0) {
g.ClippingRegistration ();
}
- #if MEASURE_TIME
- clippingMeasure.StopCycle();
+ #if DBG_EVENTS
+ DbgEndSubEvt();
#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(){
- #if MEASURE_TIME
- drawingMeasure.StartCycle();
+ #if DBG_EVENTS
+ DbgStartSubEvt(DbgEvtType.IFaceDrawing);
#endif
if (DragImage != null)
clipping.UnionRectangle(new Rectangle (DragImageX, DragImageY, DragImageWidth, DragImageHeight));
//surf.WriteToPng (@"/mnt/data/test.png");
}
}
- #if MEASURE_TIME
- drawingMeasure.StopCycle();
+ #if DBG_EVENTS
+ DbgEndSubEvt ();
#endif
}
#endregion
/// <summary> Unsuccessfull UpdateLayout and requeueing count </summary>
public int LayoutingTries, DiscardCount;
- #if DEBUG_LAYOUTING
- public Stopwatch LQITime;
- public GraphicObject graphicObject {
- get { return Layoutable as GraphicObject; }
- }
- public string Name {
- get { return graphicObject.Name; }
- }
- public string FullName {
- get { return graphicObject.ToString(); }
- }
- public Measure Width {
- get { return graphicObject.Width; }
- }
- public Measure Height {
- get { return graphicObject.Height; }
- }
- public Rectangle Slot, NewSlot;
- #endif
-
#region CTOR
public LayoutingQueueItem (LayoutingType _layoutType, ILayoutable _graphicObject)
{
Layoutable.RegisteredLayoutings |= LayoutType;
LayoutingTries = 0;
DiscardCount = 0;
- #if DEBUG_LAYOUTING
- LQITime = new Stopwatch();
- Slot = Rectangle.Empty;
- NewSlot = Rectangle.Empty;
- Debug.WriteLine ("\tRegister => " + this.ToString ());
- #endif
}
#endregion
-
public void ProcessLayouting()
{
GraphicObject go = Layoutable as GraphicObject;
if (go.Parent == null) {//TODO:improve this
go.registeredLayoutings &= (~LayoutType);
go.requestedLayoutings |= LayoutType;
- //cancel layouting for object without parent, maybe some were in queue when
- //removed from a listbox
- #if DEBUG_UPDATE || DEBUG_LAYOUTING
- Debug.WriteLine ("ERROR: processLayouting, no parent for: " + this.ToString ());
- #endif
go.parentRWLock.ExitReadLock ();
+ #if DBG_EVENTS
+ (go.IFace.CurDbgEvt as LayoutingDebugEvent).EndResult = LayoutingDebugEvent.Result.Deleted;
+ go.IFace.CurDbgEvt.Message = "Parent is null";
+ #endif
return;
}
- #if DEBUG_LAYOUTING
- LQITime.Start();
- Debug.WriteLine ("=> " + this.ToString ());
- #endif
LayoutingTries++;
if (!Layoutable.UpdateLayout (LayoutType)) {
- #if DEBUG_LAYOUTING
- Debug.WriteLine ("\t\tRequeued");
- #endif
if (LayoutingTries < Interface.MaxLayoutingTries) {
Layoutable.RegisteredLayoutings |= LayoutType;
+
+ #if DBG_EVENTS
+ (go.IFace.CurDbgEvt as LayoutingDebugEvent).EndResult = LayoutingDebugEvent.Result.Requeued;
+ #endif
+
(Layoutable as GraphicObject).IFace.LayoutingQueue.Enqueue (this);
} else if (DiscardCount < Interface.MaxDiscardCount) {
- #if DEBUG_LAYOUTING
- Debug.WriteLine ("\t\tDiscarded");
+ #if DBG_EVENTS
+ (go.IFace.CurDbgEvt as LayoutingDebugEvent).EndResult = LayoutingDebugEvent.Result.Discarded;
#endif
go.LayoutingDiscardCheck (LayoutType);
LayoutingTries = 0;
Layoutable.RegisteredLayoutings |= LayoutType;
(Layoutable as GraphicObject).IFace.DiscardQueue.Enqueue (this);
}
- //#if DEBUG_LAYOUTING
+ #if DBG_EVENTS
else
- Debug.WriteLine ("\tDELETED => " + this.ToString ());
- //#endif
- }
-
- else{
- if (LayoutingTries > 2 || DiscardCount > 0)
- Debug.WriteLine (this.ToString ());
+ (go.IFace.CurDbgEvt as LayoutingDebugEvent).EndResult = LayoutingDebugEvent.Result.Deleted;
+ #endif
}
- #if DEBUG_LAYOUTING
- LQITime.Stop();
+ #if DBG_EVENTS
+ else
+ (go.IFace.CurDbgEvt as LayoutingDebugEvent).EndResult = LayoutingDebugEvent.Result.Ok;
#endif
+
go.parentRWLock.ExitReadLock ();
}