</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugType>full</DebugType>
- <DefineConstants>$(DefineConstants);DEBUG;TRACE;MEASURE_TIME;_DEBUG_DISPOSE;_DEBUG_BINDING;_DEBUG_CLIP_RECTANGLE;_DEBUG_FOCUS;DEBUG_DRAGNDROP;_DEBUG_LOG</DefineConstants>
+ <DefineConstants>$(DefineConstants);DEBUG_LOG;DEBUG;TRACE;DEBUG_LAYOUTING;DEBUG_DISPOSE;_DEBUG_BINDING;_DEBUG_CLIP_RECTANGLE</DefineConstants>
<CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>
</PropertyGroup>
<ItemGroup Condition="$(TargetFramework.StartsWith('netstandard'))">
#endif
iface = _iface;
sourcePath = srcPath;
- #if DEBUG_LOAD
- Stopwatch loadingTime = Stopwatch.StartNew ();
- #endif
+#if DEBUG_LOG
+ DbgEvent de = DbgLogger.StartEvent (DbgEvtType.CreateITor, sourcePath);
+#endif
try {
using (XmlReader itr = XmlReader.Create (stream)) {
parseIML (itr);
throw new InstantiatorException(sourcePath, ex);
} finally {
stream?.Dispose ();
-#if DEBUG_LOAD
- loadingTime.Stop ();
- using (StreamWriter sw = new StreamWriter ("loading.log", true)) {
- sw.WriteLine ($"ITOR;{sourcePath,-50};{loadingTime.ElapsedTicks,8};{loadingTime.ElapsedMilliseconds,8}");
- }
+#if DEBUG_LOG
+ DbgLogger.EndEvent (DbgEvtType.CreateITor, de);
#endif
}
}
/// </summary>
/// <returns>The new graphic object instance</returns>
public Widget CreateInstance(){
-#if DEBUG_LOAD
- Stopwatch loadingTime = Stopwatch.StartNew ();
- GraphicObject o = loader (iface) as GraphicObject;
- loadingTime.Stop ();
- using (StreamWriter sw = new StreamWriter ("loading.log", true)) {
- sw.WriteLine ($"NEW ;{sourcePath,-50};{loadingTime.ElapsedTicks,8};{loadingTime.ElapsedMilliseconds,8}");
- }
- return o;
-#else
return loader (iface) as Widget;
-#endif
}
/// <summary>
/// Creates a new instance of T compiled in the instantiator
/// </summary>
/// <returns>The new T instance</returns>
public T CreateInstance<T>(){
-#if DEBUG_LOAD
- Stopwatch loadingTime = Stopwatch.StartNew ();
- T i = (T)loader (iface);
- loadingTime.Stop ();
- using (StreamWriter sw = new StreamWriter ("loading.log", true)) {
- sw.WriteLine ($"NEW ;{sourcePath,-50};{loadingTime.ElapsedTicks,8};{loadingTime.ElapsedMilliseconds,8}");
- }
- return i;
-#else
return (T)loader (iface);
-#endif
}
List<DynamicMethod> dsValueChangedDynMeths = new List<DynamicMethod>();
List<Delegate> cachedDelegates = new List<Delegate>();
lock (ClippingMutex) {
if (g.IsQueueForClipping)
return;
- #if DEBUG_LOG
- DbgLogger.AddEvent(DbgEvtType.GOEnqueueForRepaint, g);
- #endif
+#if DEBUG_LOG
+ DbgLogger.StartEvent (DbgEvtType.GOEnqueueForRepaint, g);
+#endif
ClippingQueue.Enqueue (g);
g.IsQueueForClipping = true;
+#if DEBUG_LOG
+ DbgLogger.EndEvent (DbgEvtType.GOEnqueueForRepaint);
+#endif
}
}
/// <summary>Main Update loop, executed in this interface thread, protected by the UpdateMutex
return;
#if DEBUG_LOG
- DbgLogger.StartEvent (DbgEvtType.IFaceUpdate);
+ DbgLogger.StartEvent (DbgEvtType.Update);
#endif
processLayouting ();
processDrawing (ctx);
#if DEBUG_LOG
- DbgLogger.EndEvent (DbgEvtType.IFaceUpdate, true);
+ DbgLogger.EndEvent (DbgEvtType.Update, true);
#endif
Monitor.Exit (UpdateMutex);
protected virtual void processLayouting(){
if (Monitor.TryEnter (LayoutMutex)) {
#if DEBUG_LOG
- DbgLogger.StartEvent (DbgEvtType.IFaceLayouting);
+ DbgLogger.StartEvent (DbgEvtType.Layouting);
#endif
DiscardQueue = new Queue<LayoutingQueueItem> ();
//Debug.WriteLine ("======= Layouting queue start =======");
}
LayoutingQueue = DiscardQueue;
#if DEBUG_LOG
- DbgLogger.EndEvent (DbgEvtType.IFaceLayouting, true);
+ DbgLogger.EndEvent (DbgEvtType.Layouting, true);
#endif
Monitor.Exit (LayoutMutex);
DiscardQueue = null;
/// operation to known if it should go down in the tree for further graphic updates and repaints</summary>
void clippingRegistration(){
#if DEBUG_LOG
- DbgLogger.StartEvent (DbgEvtType.IFaceClipping);
+ DbgLogger.StartEvent (DbgEvtType.Clipping);
#endif
Widget g = null;
while (ClippingQueue.Count > 0) {
g.ClippingRegistration ();
}
#if DEBUG_LOG
- DbgLogger.EndEvent (DbgEvtType.IFaceClipping, true);
+ DbgLogger.EndEvent (DbgEvtType.Clipping, 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 DEBUG_LOG
- DbgLogger.StartEvent (DbgEvtType.IFaceDrawing);
+ DbgLogger.StartEvent (DbgEvtType.Drawing);
#endif
if (DragImage != null)
clipping.UnionRectangle(new Rectangle (DragImageX, DragImageY, DragImageWidth, DragImageHeight));
}
#if DEBUG_LOG
- DbgLogger.EndEvent (DbgEvtType.IFaceDrawing, true);
+ DbgLogger.EndEvent (DbgEvtType.Drawing, true);
#endif
}
#endregion
g.Dispose ();
}
}
- #if DEBUG_LAYOUTING
- LQIsTries = new List<LQIList>();
- curLQIsTries = new LQIList();
- LQIs = new List<LQIList>();
- curLQIs = new LQIList();
- #endif
}
/// <summary> Put widget on top of other root widgets</summary>
public void PutOnTop(Widget g, bool isOverlay = false)
}
public Rectangle getSlot () { return ClientRectangle; }
#endregion
-
-
-#if DEBUG_LAYOUTING
- public List<LQIList> LQIsTries = new List<LQIList>();
- public LQIList curLQIsTries = new LQIList();
- public List<LQIList> LQIs = new List<LQIList>();
- public LQIList curLQIs = new LQIList();
- // public static LayoutingQueueItem[] MultipleRunsLQIs {
- // get { return curUpdateLQIs.Where(l=>l.LayoutingTries>2 || l.DiscardCount > 0).ToArray(); }
- // }
- public LayoutingQueueItem currentLQI;
-#else
- public List<LQIList> LQIs = null;//still create the var for CrowIDE
-#endif
}
}
/// <summary> Unsuccessfull UpdateLayout and requeueing count </summary>
public int LayoutingTries, DiscardCount;
- #if DEBUG_LOG
+
public enum Result : byte {
Unknown,
Register,
Discarded,
Deleted,
}
+#if DEBUG_LOG
public Result result;
public Widget graphicObject {
get { return Layoutable as Widget; }
return;
}
#if DEBUG_LOG
- DbgLogger.DbgEvent dbgEvt = DbgLogger.StartEvent (DbgEvtType.GOProcessLayouting, this);
+ DbgLogger.StartEvent (DbgEvtType.GOProcessLayouting, this);
#endif
LayoutingTries++;
if (!Layoutable.UpdateLayout (LayoutType)) {
else{
result = Result.Success;
}
- DbgLogger.EndEvent (DbgEvtType.GOProcessLayouting).data = this;
+ Slot = graphicObject.LastSlots;
+ NewSlot = graphicObject.Slot;
+ (DbgLogger.EndEvent (DbgEvtType.GOProcessLayouting) as DbgLayoutEvent).SetLQI (this);
#endif
go.parentRWLock.ExitReadLock ();
}
return lqi.LayoutType;
}
public override string ToString ()
- {
- #if DEBUG_LAYOUTING
- return string.Format ("{2};{3} {1}->{0}", LayoutType,Layoutable.ToString(),
- LayoutingTries,DiscardCount);
- #else
- return string.Format ("{2};{3} {1}->{0}", LayoutType,Layoutable.ToString(),
- LayoutingTries, DiscardCount);
- #endif
- }
- }
- public class LQIList : List<LayoutingQueueItem>{
-// #if DEBUG_LAYOUTING
-// public List<LayoutingQueueItem> GetRootLQIs(){
-// return this.Where (lqi => lqi.wasTriggeredBy == null).ToList ();
-// }
-// #endif
+ => $"{LayoutType};{Layoutable.ToString ()};{LayoutingTries};{DiscardCount}";
}
}
if (newW != stretchedGO.Slot.Width) {
stretchedGO.Slot.Width = newW;
stretchedGO.IsDirty = true;
-#if DEBUG_LAYOUTING
- LOG ($"width: {stretchedGO.ToString()}");
-#endif
stretchedGO.LayoutChanged -= OnChildLayoutChanges;
stretchedGO.OnLayoutChanges (LayoutingType.Width);
stretchedGO.LayoutChanged += OnChildLayoutChanges;
if (newH != stretchedGO.Slot.Height) {
stretchedGO.Slot.Height = newH;
stretchedGO.IsDirty = true;
-#if DEBUG_LAYOUTING
- LOG ($"height: {stretchedGO.ToString ()}");
-#endif
stretchedGO.LayoutChanged -= OnChildLayoutChanges;
stretchedGO.OnLayoutChanges (LayoutingType.Height);
stretchedGO.LayoutChanged += OnChildLayoutChanges;
set { _multiSelect = value; }
}
public virtual void AddChild(Widget g){
-#if DEBUG
+#if DEBUG_LOG
if (disposed) {
- System.Diagnostics.Debug.WriteLine ($"AddChild ({g}) in disposed Widget: {this}\n{System.Environment.StackTrace}");
+ DbgLogger.AddEvent (DbgEvtType.AlreadyDisposed | DbgEvtType.GOAddChild);
return;
}
#endif
child.Dispose ();
}
public virtual void InsertChild (int idx, Widget g) {
-#if DEBUG
+#if DEBUG_LOG
if (disposed) {
- System.Diagnostics.Debug.WriteLine ($"InsertChild ({idx},{g}) in disposed Widget: {this}\n{System.Environment.StackTrace}");
+ DbgLogger.AddEvent (DbgEvtType.AlreadyDisposed | DbgEvtType.GOAddChild);
return;
}
#endif
{
Widget g = sender as Widget;
-#if DEBUG_LAYOUTING
- LOG ($"{arg.LayoutType}:{g}->{g.Slot}");
-#endif
-
switch (arg.LayoutType) {
case LayoutingType.Width:
if (Width != Measure.Fit)
}
void searchLargestChild (bool forceMeasure = false)
{
- #if DEBUG_LAYOUTING
- LOG (this.ToString());
- #endif
+#if DEBUG_LOG
+ DbgLogger.StartEvent (DbgEvtType.GOSearchLargestChild, this);
+#endif
largestChild = null;
contentSize.Width = 0;
for (int i = 0; i < Children.Count; i++) {
largestChild = Children [i];
}
}
+#if DEBUG_LOG
+ DbgLogger.EndEvent (DbgEvtType.GOSearchLargestChild);
+#endif
}
void searchTallestChild (bool forceMeasure = false)
{
- #if DEBUG_LAYOUTING
- LOG (this.ToString());
- #endif
+#if DEBUG_LOG
+ DbgLogger.StartEvent (DbgEvtType.GOSearchTallestChild, this);
+#endif
tallestChild = null;
contentSize.Height = 0;
for (int i = 0; i < Children.Count; i++) {
tallestChild = Children [i];
}
}
+#if DEBUG_LOG
+ DbgLogger.EndEvent (DbgEvtType.GOSearchTallestChild);
+#endif
}
}
public override void onMouseClick (object sender, MouseButtonEventArgs e)
{
-#if DEBUG_FOCUS
- System.Diagnostics.Debug.WriteLine ("MENU CLICK => " + this.ToString ());
-#endif
if (command != null) {
command.Execute ();
closeMenu ();
public virtual void OnChildLayoutChanges (object sender, LayoutingEventArgs arg)
{
Widget g = sender as Widget;
-#if DEBUG_LAYOUTING
- LOG ($"{arg.LayoutType}:{g}->{child.Slot}");
-#endif
if (arg.LayoutType == LayoutingType.Width) {
contentSize.Width = g.Slot.Width;
if (Width != Measure.Fit)
//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, or never added to main tree
public int treeIndex;
+ public int instanceIndex;//index in the GraphicObjects list
public int yIndex;//absolute index in the graphic tree for debug draw
public int xLevel;//x increment for debug draw
#endif
}
protected virtual void Dispose(bool disposing){
if (disposed){
- #if DEBUG_DISPOSE
- Debug.WriteLine ("Trying to dispose already disposed obj: {0}", this.ToString());
- #endif
+#if DEBUG_LOG
+ DbgLogger.AddEvent (DbgEvtType.AlreadyDisposed, this);
+#endif
return;
}
+#if DEBUG_LOG
+ DbgLogger.StartEvent (DbgEvtType.Disposing, this);
+#endif
if (disposing) {
- #if DEBUG_DISPOSE
- System.Diagnostics.Debug.WriteLine ("Disposing: {0}", this.ToString());
- //if ()
- //throw new Exception("Trying to dispose an object queued for Redraw: " + this.ToString());
- #endif
unshownPostActions ();
parentRWLock.EnterWriteLock();
parent = null;
parentRWLock.ExitWriteLock();
- } else
- Debug.WriteLine ("!!! Finalized by GC: {0}", this.ToString ());
+ }
+#if DEBUG_LOG
+ else
+ DbgLogger.AddEvent (DbgEvtType.DisposedByGC, this);
+#endif
Clipping?.Dispose ();
bmp?.Dispose ();
disposed = true;
- }
+#if DEBUG_LOG
+ DbgLogger.EndEvent (DbgEvtType.Disposing);
+#endif
+ }
#endregion
- #if DEBUG_LOG
+#if DEBUG_LOG
internal static List<Widget> GraphicObjects = new List<Widget>();
#endif
/// </summary>
protected Widget () {
Clipping = new Region ();
- #if DEBUG_LOG
+#if DEBUG_LOG
+ instanceIndex = GraphicObjects.Count;
GraphicObjects.Add (this);
DbgLogger.AddEvent(DbgEvtType.GOClassCreation, this);
- #endif
+#endif
}
/// <summary>
/// This constructor **must** be used when creating widget from code.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void RegisterForGraphicUpdate ()
{
-#if DEBUG
+#if DEBUG_LOG
if (disposed) {
-// System.Diagnostics.Debug.WriteLine ($"RegisterForGraphicUpdate for disposed Widget: {this}\n{System.Environment.StackTrace}");
+ DbgLogger.AddEvent (DbgEvtType.GORegisterForGraphicUpdate | DbgEvtType.AlreadyDisposed, this);
return;
}
#endif
{
#if DEBUG
if (disposed) {
- System.Diagnostics.Debug.WriteLine ($"RegisterForRedraw for disposed Widget: {this}\n{System.Environment.StackTrace}");
+ DbgLogger.AddEvent (DbgEvtType.GORegisterForRedraw | DbgEvtType.AlreadyDisposed, this);
return;
}
#endif
}
public virtual void onMouseDown(object sender, MouseButtonEventArgs e){
-#if DEBUG_FOCUS
- Debug.WriteLine("MOUSE DOWN => " + this.ToString());
-#endif
if (Focusable) {
IFace.FocusedWidget = this;
e.Handled = true;
FocusParent?.onMouseDown (sender, e);
}
public virtual void onMouseUp(object sender, MouseButtonEventArgs e){
-#if DEBUG_FOCUS
- Debug.WriteLine("MOUSE UP => " + this.ToString());
-#endif
if (IFace.DragAndDropOperation != null){
if (IFace.DragAndDropOperation.DragSource == this) {
FocusParent?.onMouseUp (sender, e);
}
public virtual void onMouseClick(object sender, MouseButtonEventArgs e){
-#if DEBUG_FOCUS
- Debug.WriteLine("CLICK => " + this.ToString());
-#endif
if (MouseClick != null)
MouseClick.Invoke (this, e);
else if (!e.Handled)
FocusParent?.onMouseClick (sender, e);
}
public virtual void onMouseDoubleClick(object sender, MouseButtonEventArgs e){
-#if DEBUG_FOCUS
- Debug.WriteLine("DOUBLE CLICK => " + this.ToString());
-#endif
if (MouseDoubleClick != null)
MouseDoubleClick.Invoke (this, e);
else if (!e.Handled)
}
public virtual void onMouseEnter(object sender, MouseMoveEventArgs e)
{
- #if DEBUG_FOCUS
- Debug.WriteLine("MouseEnter => " + this.ToString());
- #endif
-
IFace.MouseCursor = MouseCursor;
if (IFace.DragAndDropOperation != null) {
}
public virtual void onMouseLeave(object sender, MouseMoveEventArgs e)
{
- #if DEBUG_FOCUS
- Debug.WriteLine("MouseLeave => " + this.ToString());
- #endif
-
MouseLeave.Raise (this, e);
}
Disabled.Raise (this, e);
}
protected virtual void onParentChanged(object sender, DataSourceChangeEventArgs e) {
+#if DEBUG_LOG
+ DbgLogger.AddEvent (DbgEvtType.GONewParent, this, e);
+#endif
ParentChanged.Raise (this, e);
if (logicalParent == null)
LogicalParentChanged.Raise (this, e);
}
protected virtual void onLogicalParentChanged(object sender, DataSourceChangeEventArgs e) {
+#if DEBUG_LOG
+ DbgLogger.AddEvent (DbgEvtType.GONewLogicalParent, this, e);
+#endif
LogicalParentChanged.Raise (this, e);
}
internal void ClearTemplateBinding(){
- #if DEBUG_UPDATE
+#if DEBUG_UPDATE
Debug.WriteLine (string.Format("ClearTemplateBinding: {0}", this.ToString()));
- #endif
+#endif
if (ValueChanged == null)
return;
EventInfo eiEvt = this.GetType().GetEvent ("ValueChanged");
}
public override void OnLayoutChanges (LayoutingType layoutType)
{
-#if DEBUG_LAYOUTING
- LOG ($"{layoutType}: {LastSlots}->{Slot}");
-#endif
switch (layoutType) {
case LayoutingType.Width:
foreach (Widget c in Children) {
-//
-// DbgEventTypeColors.cs
+// Copyright (c) 2013-2020 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
//
-// 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.
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+
using System;
using Crow.Cairo;
using System.Linq;
namespace Crow
{
- #if DEBUG_LOG
public class DbgEventTypeColors : Widget
{
protected override void onDraw (Context gr)
}
}
}
- #endif
}
using System.Threading.Tasks;
using Crow.Cairo;
-#if DEBUG_LOG
namespace Crow
{
public class DbgLogViewer : ScrollingObject
public static Configuration colorsConf = new Configuration ("dbgcolor.conf");//, Interface.GetStreamFromPath("#Crow.dbgcolor.conf"));
- #region debug viewer private classes
- public class DbgLayoutEvent : DbgWidgetEvent
- {
- public LayoutingType layouting;
- public LayoutingQueueItem.Result result;
- 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 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() {}
-
- public static DbgEvent Parse (string str) {
- if (str == null)
- return null;
- string[] tmp = str.Trim().Split(';');
-
- 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 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}";
- }
- 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;
- //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>();//flattened event list of this widget
-
- 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
-
public static void reloadColors () {
colors = new Dictionary<DbgEvtType, Color>();
foreach (string n in colorsConf.Names) {
double xScale = 1.0/512.0, yScale = 1.0, leftMargin, topMargin = 0.0;
string logFile;
- DbgGo curWidget;
+ DbgWidgetRecord curWidget;
DbgEvent curEvent;
List<DbgEvent> events;
- List<DbgGo> objs;
+ List<DbgWidgetRecord> objs;
public List<DbgEvent> Events => events;
- public List<DbgGo> Widgets => objs;
+ public List<DbgWidgetRecord> Widgets => objs;
long currentTick = 0, selStart = -1, selEnd = -1, minTicks = 0, maxTicks = 0, visibleTicks = 0;
}
}
- public DbgGo CurrentWidget {
+ public DbgWidgetRecord CurrentWidget {
get => curWidget;
internal set {
if (curWidget == value)
internal set {
if (curEvent == value)
return;
+
+ if (curEvent != null)
+ curEvent.IsSelected = false;
curEvent = value;
+ if (curEvent != null) {
+ curEvent.IsSelected = true;
+ curEvent.IsExpanded = true;
+ }
+
NotifyValueChanged (nameof (CurrentEvent), curEvent);
}
}
if (evt.begin - minTicks > ScrollX + visibleTicks)
break;
double penY = topMargin + ClientRectangle.Top;
- if (evt.type.HasFlag (DbgEvtType.GraphicObject)) {
+ if (evt.type.HasFlag (DbgEvtType.Widget)) {
DbgWidgetEvent eW = evt as DbgWidgetEvent;
- int lIdx = eW.widgetInstanceId - ScrollY;
+ int lIdx = eW.InstanceIndex - ScrollY;
if (lIdx < 0 || lIdx > visibleLines)
continue;
penY += (lIdx) * fe.Height;
ctx.ShowText (s);
}
- drawEvents (ctx, evt.events);
+ drawEvents (ctx, evt.Events);
}
}
for (int i = 0; i < visibleLines; i++) {
if (i + ScrollY >= objs.Count)
break;
- DbgGo g = objs [i + ScrollY];
+ int gIdx = i + ScrollY;
+ DbgWidgetRecord g = objs [gIdx];
penY += fe.Height;
Foreground.SetAsSource (gr);
gr.MoveTo (penX, penY - gr.FontExtents.Descent);
- gr.ShowText (g.name + g.instanceNum);
+ gr.ShowText (g.name + gIdx);
gr.SetSource (Crow.Colors.White);
gr.MoveTo (cb.X, penY - gr.FontExtents.Descent);
base.onMouseDown (sender, e);
if (e.Button == Glfw.MouseButton.Left) {
+ CurrentWidget = (currentLine < 0 || currentLine >= objs.Count) ? null : objs [currentLine];
+ CurrentEvent = curWidget?.Events.FirstOrDefault (ev => ev.begin <= currentTick && ev.end >= currentTick);
selStart = currentTick;
selEnd = -1;
}
return;
events = new List<DbgEvent> ();
- objs = new List<DbgGo> ();
+ objs = new List<DbgWidgetRecord> ();
minTicks = maxTicks = 0;
leftMargin = topMargin = 0.0;
string l = s.ReadLine ();
if (l == "[Events]")
break;
- DbgGo o = DbgGo.Parse (l);
+ DbgWidgetRecord o = DbgWidgetRecord.Parse (l);
objs.Add (o);
double nameWidth = gr.TextExtents (o.name).Width + 5.0 * o.xLevel;
if (nameWidth > maxNameWidth)
}
}
startedEvents.Push (evt);
- if (evt.type.HasFlag(DbgEvtType.GraphicObject))
- objs [(evt as DbgWidgetEvent).widgetInstanceId].events.Add (evt);
+ if (evt.type.HasFlag(DbgEvtType.Widget))
+ objs [(evt as DbgWidgetEvent).InstanceIndex].Events.Add (evt);
}
if (events.Count > 0)
minTicks = events [0].begin;
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;
}
}
}
-#endif
+
using System.Linq;
using System.Threading;
-#if DEBUG_LOG
+
namespace Crow
{
- /*public class LayoutingEvent : DbgEvent {
- public List<LayoutingQueueItem> lqis = new List<LayoutingQueueItem>();
-
- }*/
[Flags]
public enum DbgEvtType {
////9 nth bit set for iface event
IFace = 0x10000,
- IFaceFocus = 0x20000,
- GraphicObject = 0x00100,
- GOLayouting = 0x00200,
- Drawing = 0x00400,
- GOLock = 0x00800,
- IFaceLayouting = IFace | 0x01,
- IFaceClipping = IFace | 0x02,
- IFaceDrawing = IFace | 0x03,
- IFaceUpdate = IFace | 0x04,
+ Focus = 0x20000,
+ Override = 0x40000,
+ Widget = 0x00100,
+ //GOLayouting = 0x00200,
+ //Drawing = 0x00400,
+ Lock = 0x00800,
+ Layouting = IFace | 0x01000,
+ Clipping = IFace | 0x02000,
+ Drawing = IFace | 0x04000,
+ Update = IFace | 0x08000,
IFaceLoad = IFace | 0x05,
IFaceInit = IFace | 0x06,
+ CreateITor = IFace | 0x07,
- HoverWidget = IFaceFocus | 0x01,
- FocusedWidget = IFaceFocus | 0x02,
- ActiveWidget = IFaceFocus | 0x03,
+ HoverWidget = Focus | 0x01,
+ FocusedWidget = Focus | 0x02,
+ ActiveWidget = Focus | 0x03,
//10 nth bit set for graphic obj
- Warning = 0x4000,
- Error = 0x8000,
- GOClassCreation = GraphicObject | 0x01,
- GOInitialization = GraphicObject | 0x02,
- GOClippingRegistration = GraphicObject | 0x03,
- GORegisterClip = GraphicObject | 0x04,
- GORegisterForGraphicUpdate = GraphicObject | 0x05,
- GOEnqueueForRepaint = GraphicObject | 0x06,
- GONewDataSource = GraphicObject | 0x07,
TemplatedGroup = 0x1000,
- GORegisterLayouting = GraphicObject | GOLayouting | 0x01,
- GOProcessLayouting = GraphicObject | GOLayouting | 0x02,
- GOProcessLayoutingWithNoParent = Warning | GraphicObject | GOLayouting | 0x01,
- GODraw = GraphicObject | Drawing | 0x01,
- GORecreateCache = GraphicObject | Drawing | 0x02,
- GOUpdateCache = GraphicObject | Drawing | 0x03,
- GOPaint = GraphicObject | Drawing | 0x04,
-
- GOLockUpdate = GraphicObject | GOLock | 0x01,
- GOLockClipping = GraphicObject | GOLock | 0x02,
- GOLockRender = GraphicObject | GOLock | 0x03,
- GOLockLayouting = GraphicObject | GOLock | 0x04,
-
- TGLoadingThread = GraphicObject | TemplatedGroup | 0x01,
- TGCancelLoadingThread = GraphicObject | TemplatedGroup | 0x02,
+ Dispose = 0x2000,
+ Warning = 0x4000,
+ Error = 0x8000,
+ GOClassCreation = Widget | 0x01,
+ GOInitialization = Widget | 0x02,
+ GORegisterForGraphicUpdate = Widget | 0x03,
+ GOEnqueueForRepaint = Widget | 0x04,
+ GONewDataSource = Widget | 0x05,
+ GONewParent = Widget | 0x06,
+ GONewLogicalParent = Widget | 0x07,
+ GOAddChild = Widget | 0x08,
+
+ GOSearchLargestChild = Widget | 0x09,
+ GOSearchTallestChild = Widget | 0x10,
+ GORegisterForRedraw = Widget | 0x11,
+
+ AlreadyDisposed = Dispose | Widget | Error | 0x01,
+ DisposedByGC = Dispose | Widget | Error | 0x02,
+ Disposing = Dispose | Widget | 0x01,
+
+ GOClippingRegistration = Clipping | Widget | 0x01,
+ GORegisterClip = Clipping | Widget | 0x02,
+ GORegisterLayouting = Layouting | Widget | 0x01,
+ GOProcessLayouting = Layouting | Widget | 0x02,
+ GOProcessLayoutingWithNoParent = Layouting | Widget | Warning | 0x01,
+ GODraw = Drawing | Widget | 0x01,
+ GORecreateCache = Drawing | Widget | 0x02,
+ GOUpdateCache = Drawing | Widget | 0x03,
+ GOPaint = Drawing | Widget | 0x04,
+
+ GOLockUpdate = Widget | Lock | 0x01,
+ GOLockClipping = Widget | Lock | 0x02,
+ GOLockRender = Widget | Lock | 0x03,
+ GOLockLayouting = Widget | Lock | 0x04,
+
+ TGLoadingThread = Widget | TemplatedGroup | 0x01,
+ TGCancelLoadingThread = Widget | TemplatedGroup | 0x02,
All = 0x0FFFFFFF
}
-
-
-
+#if DEBUG_LOG
public static class DbgLogger
{
public static DbgEvtType IncludeEvents = DbgEvtType.All;
- public static DbgEvtType DiscardEvents = DbgEvtType.IFaceFocus;
+ public static DbgEvtType DiscardEvents = DbgEvtType.Focus;
static bool logevt (DbgEvtType evtType)
- {
- return (evtType & DiscardEvents) == 0 && (evtType & IncludeEvents) != 0;
- }
+ => (evtType & DiscardEvents) == 0 && (evtType & IncludeEvents) != 0;
- /// <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 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 ()}";
+ static object logMutex = new object ();
+ static Stopwatch chrono = Stopwatch.StartNew ();
+ static List<DbgEvent> events = new List<DbgEvent> ();
+ //started events per thread
+ static Dictionary<int, Stack<DbgEvent>> startedEvents = new Dictionary<int, Stack<DbgEvent>> ();
+ //helper for fetching current event list to add next event to while recording
+ static List<DbgEvent> curEventList {
+ get {
+ if (startedEvents.ContainsKey (Thread.CurrentThread.ManagedThreadId)) {
+ if (startedEvents [Thread.CurrentThread.ManagedThreadId].Count == 0)
+ return events;
+ DbgEvent e = startedEvents [Thread.CurrentThread.ManagedThreadId].Peek ();
+ if (e.Events == null)
+ e.Events = new List<DbgEvent> ();
+ return e.Events;
}
- return tmp;
+ return events;
}
}
- public static Stopwatch chrono = Stopwatch.StartNew();
-
- 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)
+ public static DbgEvent StartEvent (DbgEvtType evtType, params object[] data)
{
if (!logevt (evtType))
return null;
lock (logMutex) {
chrono.Stop ();
- DbgEvent evt = new DbgEvent (chrono.ElapsedTicks, evtType, data);
- curEventList.Add (evt);
+ DbgEvent evt = addEventInternal (evtType, data);
if (!startedEvents.ContainsKey (Thread.CurrentThread.ManagedThreadId))
startedEvents [Thread.CurrentThread.ManagedThreadId] = new Stack<DbgEvent> ();
startedEvents [Thread.CurrentThread.ManagedThreadId].Push (evt);
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)
+ if (discardIfNoChildEvents && (e.Events == null || e.Events.Count == 0))
curEventList.Remove (e);
else
e.end = chrono.ElapsedTicks;
return e;
}
}
- public static DbgEvent AddEvent (DbgEvtType evtType, object data = null) {
+ /// <summary>
+ /// End event by reference to cancel unended events on failure
+ /// </summary>
+ public static DbgEvent EndEvent (DbgEvtType evtType, DbgEvent evt)
+ {
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))
+ throw new Exception ("Current thread has no event started");
+ DbgEvent e = startedEvents [Thread.CurrentThread.ManagedThreadId].Pop ();
+ while (e != evt)
+ e = startedEvents [Thread.CurrentThread.ManagedThreadId].Pop ();
+ e.end = chrono.ElapsedTicks;
+ chrono.Start ();
+ return e;
+ }
+ }
+
+ public static DbgEvent AddEvent (DbgEvtType evtType, params object [] data) {
+ if (!logevt (evtType))
+ return null;
+
+ lock (logMutex) {
+ chrono.Stop ();
+ DbgEvent evt = addEventInternal (evtType, data);
chrono.Start ();
return evt;
}
}
- static int y, level;
+ static DbgEvent addEventInternal (DbgEvtType evtType, params object [] data)
+ {
+ DbgEvent evt = null;
+ if (data == null || data.Length == 0)
+ evt = new DbgEvent (chrono.ElapsedTicks, evtType);
+ else if (data [0] is Widget w)
+ evt = new DbgWidgetEvent (chrono.ElapsedTicks, evtType, w);
+ else if (data [0] is LayoutingQueueItem lqi)
+ evt = new DbgLayoutEvent (chrono.ElapsedTicks, evtType, lqi);
+ else
+ evt = new DbgEvent (chrono.ElapsedTicks, evtType);
+
+ curEventList.Add (evt);
+ return evt;
+ }
- static void parseTree (Widget go) {
+ static void parseTree (Widget go, int level = 0, int y = 1) {
if (go == null)
return;
- go.yIndex = y++;
- go.xLevel = level++;
+ go.yIndex = y;
+ go.xLevel = level;
Group gr = go as Group;
if (gr != null) {
- foreach (Widget g in gr.Children) {
- parseTree (g);
- }
+ foreach (Widget g in gr.Children)
+ parseTree (g, level + 1, y + 1);
+
} else {
PrivateContainer pc = go as PrivateContainer;
if (pc != null)
- parseTree (pc.getTemplateRoot);
+ parseTree (pc.getTemplateRoot, level + 1, y + 1);
}
- level--;
}
+ /// <summary>
+ /// Clear all recorded events from logger.
+ /// </summary>
public static void Reset ()
{
lock (logMutex) {
chrono.Restart ();
}
}
- public static void save(Interface iface) {
+ /// <summary>
+ /// Save recorded events to disk
+ /// </summary>
+ /// <param name="iface">Iface.</param>
+ public static void save(Interface iface, string dbgLogFilePath = "debug.log") {
lock (logMutex) {
- y = 1;
- level = 0;
foreach (Widget go in iface.GraphicTree)
parseTree (go);
- using (StreamWriter s = new StreamWriter ("debug.log")) {
+ using (StreamWriter s = new StreamWriter (dbgLogFilePath)) {
s.WriteLine ("[GraphicObjects]");
lock (Widget.GraphicObjects) {
- Widget.GraphicObjects = Widget.GraphicObjects.OrderBy (o => o.yIndex).ToList ();
+ //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 ($"{g.GetType ().Name};{g.yIndex};{g.xLevel}");
}
}
s.WriteLine ("[Events]");
}
}
- static void saveEventList (StreamWriter s, List<DbgEvent> events, int level = 0)
+ static void saveEventList (StreamWriter s, List<DbgEvent> evts, int level = 0)
{
- foreach (DbgEvent e in events) {
+ foreach (DbgEvent e in evts) {
if (e == null)
continue;
- s.WriteLine (new string ('\t', level) + e.ToString ());
- saveEventList (s, e.Events, level + 1);
+ s.WriteLine (new string ('\t', level) + e);
+ if (e.Events != null)
+ saveEventList (s, e.Events, level + 1);
}
}
}
-}
#endif
+}
+
<?xml version="1.0" encoding="UTF-8"?>
<HorizontalStack>
- <TreeView Width="20%" Data="{../dbv.Events}">
- <ItemTemplate Data="events">
- <Expandable Caption="{type}" MouseDoubleClick="/onClickForExpand" CacheEnabled="true">
+ <TreeView Width="20%" Data="{../dbv.Events}" SelectedItemChanged="onSelectedItemChanged">
+ <ItemTemplate Data="Events">
+ <Expandable Caption="{type}" MouseDoubleClick="/onClickForExpand" CacheEnabled="true" IsExpanded="{²IsExpanded}">
<Template>
<VerticalStack>
<Border CornerRadius="2" Margin="0" Height="Fit" MouseDoubleClick="./onClickForExpand"
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>
+ <DbgEventWidget Event="{}" Tooltip="{/HoverEvent}" TicksPerPixel="200" Width="Fit" Height="5"/>
+ </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>
+ <ItemTemplate Data="Events" DataType="DbgWidgetEvent">
+ <Expandable Caption="{type}" MouseDoubleClick="/onClickForExpand" CacheEnabled="true" IsExpanded="{²IsExpanded}">
+ <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"/>
+ <Label Text="{InstanceIndex}" Width="40" Font="mono, 8" TextAlignment="Center" Background="DimGrey"/>
+ <DbgEventWidget Event="{}" Tooltip="{/HoverEvent}" TicksPerPixel="200" Width="Fit" Height="5"/>
</HorizontalStack>
</Border>
<Container Name="Content" Visible="false"/>
</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}"/>
+ <DbgLogViewer Visible="true" 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="{yIndex}"/>
<Label Text="{xLevel}"/>
</HorizontalStack>
- <DbgEventWidget Height="20" Width="Stretched" Event="{../../dbv.CurrentEvent}"/>
+ <ListBox Data="{RootEvents}" Height="100" DataSource="{../../dbv.CurrentWidget}">
+ <ItemTemplate>
+ <DbgEventWidget Height="10" Width="Fit" Event="{}" Tooltip="{/HoverEvent}" TicksPerPixel="100"/>
+ </ItemTemplate>
+ <Template>
+ <Wrapper Name="ItemsContainer" Spacing="2" Background="DarkGrey"/>
+ </Template>
+ </ListBox>
+ <!--<DbgEventWidget Height="20" Width="Stretched" Event="{../../dbv.CurrentEvent}"/>-->
<VerticalStack DataSource="{../../dbv.CurrentEvent}">
<HorizontalStack>
<Label Text="{type}"/>
<DbgEventWidget Height="20" Width="Stretched" Event="{}"/>
</ItemTemplate>
</ListBox>
- </VerticalStack>-->
+ </VerticalStack>
</VerticalStack>
</HorizontalStack>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0"?>
+<Window Width="400" Height="240">
+ <Template>
+ <Group >
+ <Shape StrokeWidth="1" Foreground="0.1,0.3,0.7,0.7" KeepProportions="false" Size="100,60" Path="M 5.5,15 L 15,5 L 95.5,5.5 L 95.5,50 L 70,55.5 L 5.5,55.5 Z g O 1,1,1,1 S 0.25 G"/>
+
+ </Group>
+ </Template>
+</Window>
\ No newline at end of file
<?xml version="1.0"?>
<Menu>
- <MenuItem Caption="File">
- <MenuItem Caption="New"/>
- <MenuItem Caption="Open"/>
- <MenuItem Caption="Save"/>
- <MenuItem Caption="Quit"/>
- </MenuItem>
+ <MenuItem Caption="File" Fit="true">
+ <MenuItem Caption="New">
+ <Template>
+<Popper Font="{./Font}" Caption="{./Caption}" Background="{./Background}" PopDirection="{./PopDirection}"
+ Foreground = "{./Foreground}" CanPop="{./HasChildren}"
+ IsPopped="{²./IsOpened}" PopWidth="{./PopWidth}" PopHeight="{./PopHeight}">
+ <Template>
+ <CheckBox IsChecked="{²./IsPopped}" Caption="{./Caption}" Background="{./Background}" Foreground="{./Foreground}">
+ <Template>
+ <Border Name="border1"
+ MinimumSize = "60,0"
+ Foreground="Transparent"
+ Background="{./Background}">
+ <Label Text="{./Caption}"
+ Foreground="{./Foreground}"
+ Margin="2" HorizontalAlignment="Left"
+ Font="{./Font}" />
+ </Border>
+ </Template>
+ </CheckBox>
+ </Template>
+ <Border Foreground="DimGrey" Width="{../PopWidth}" Height="{../PopHeight}" Background="${MenuBackground}">
+ <VerticalStack Name="ItemsContainer"/>
+ </Border>
+</Popper>
+ </Template>
+ </MenuItem>
+ </MenuItem>
</Menu>
--- /dev/null
+<?xml version="1.0"?>
+<Menu>
+ <MenuItem Caption="File" >
+ <MenuItem Caption="New">
+ <Template>
+ <Popper Font="{./Font}" Caption="{./Caption}" Background="{./Background}" PopDirection="{./PopDirection}"
+ Foreground = "{./Foreground}" CanPop="{./HasChildren}"
+ IsPopped="{²./IsOpened}" PopWidth="{./PopWidth}" PopHeight="{./PopHeight}">
+ <Template>
+ <CheckBox IsChecked="{²./IsPopped}" Caption="{./Caption}" Background="{./Background}" Foreground="{./Foreground}">
+ <Template>
+ <Label Text="{./Caption}"
+ Foreground="{./Foreground}"
+ Margin="2" HorizontalAlignment="Left"
+ Font="{./Font}" />
+ </Template>
+ </CheckBox>
+ </Template>
+ <Border Foreground="DimGrey" Height="{../PopHeight}" Background="FireBrick" Margin="3">
+ <VerticalStack Name="ItemsContainer"/>
+ </Border>
+ </Popper>
+ </Template>
+ </MenuItem>
+ </MenuItem>
+</Menu>
<?xml version="1.0"?>
-<VerticalStack Width="60%" Height="60%" Spacing="10" Background="DimGrey" Margin="20" ClipToClientRect="false" CornerRadius="10">
+<VerticalStack Width="60%" Height="60%" Spacing="10" Background="DarkGrey" Margin="20" ClipToClientRect="false" CornerRadius="10">
<Label Background="Jet" Text="{TestList3SelProp1}"/>
<ComboBox Data="{TestList3Props1}">
</ComboBox>