Skip to content

Instantly share code, notes, and snippets.

@kornman00
Created August 29, 2022 05:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kornman00/629c47dcfe10d6d9aedcfcf505c3a830 to your computer and use it in GitHub Desktop.
Save kornman00/629c47dcfe10d6d9aedcfcf505c3a830 to your computer and use it in GitHub Desktop.
TraceListViewModel for Gemini PR #328
using System.ComponentModel;
using System.ComponentModel.Composition;
using System.Threading;
using System.Threading.Tasks;
using Caliburn.Micro;
using Gemini.Framework;
using Gemini.Framework.Services;
using Gemini.Modules.Inspector;
namespace SomeRedactedAppName.Modules.TraceList
{
[Export(typeof(ITraceList))]
[PartCreationPolicy(CreationPolicy.Shared)]
public sealed class TraceListViewModel
: Tool
, ITraceList
, IHandle<TracedItemEventArgs>
{
public override PaneLocation PreferredLocation => PaneLocation.Bottom;
#region Imports
private readonly IEventAggregator mEventAggregator;
private readonly IInspectorTool mInspectorTool;
private readonly SomeRedactedAppNameUserSettings mSomeRedactedAppNameUserSettings;
[ImportingConstructor]
public TraceListViewModel(
IEventAggregator eventAggregator,
IInspectorTool inspectorTool,
SomeRedactedAppNameUserSettings userSettings)
{
mEventAggregator = eventAggregator;
mInspectorTool = inspectorTool;
mSomeRedactedAppNameUserSettings = userSettings;
PostConstruction();
}
#endregion
private int mItemNumber;
BindableCollection<TraceListItem> mItems;
public IObservableCollection<TraceListItem> Items => mItems;
public ICollectionView ItemsView { get; private set; }
#region PauseTracing
bool mPauseTracing;
public bool PauseTracing
{
get { return mPauseTracing; }
set { this.SetFieldVal(ref mPauseTracing, value); }
}
#endregion
#region TotalNumberOfTraces
int mTotalNumberOfTraces;
public int TotalNumberOfTraces
{
get { return mTotalNumberOfTraces; }
set { this.SetFieldVal(ref mTotalNumberOfTraces, value); }
}
#endregion
#region ShowCritical
bool mShowCritical = true;
public bool ShowCritical
{
get { return mShowCritical; }
set
{
if (this.SetFieldVal(ref mShowCritical, value))
{
OnShowFiltersChanged();
}
}
}
#endregion
#region ShowError
bool mShowError = true;
public bool ShowError
{
get { return mShowError; }
set
{
if (this.SetFieldVal(ref mShowError, value))
{
OnShowFiltersChanged();
}
}
}
#endregion
#region ShowWarning
bool mShowWarning = true;
public bool ShowWarning
{
get { return mShowWarning; }
set
{
if (this.SetFieldVal(ref mShowWarning, value))
{
OnShowFiltersChanged();
}
}
}
#endregion
#region ShowInformation
bool mShowInformation = true;
public bool ShowInformation
{
get { return mShowInformation; }
set
{
if (this.SetFieldVal(ref mShowInformation, value))
{
OnShowFiltersChanged();
}
}
}
#endregion
#region ShowVerbose
bool mShowVerbose = Constants.IsDebugBuild;
public bool ShowVerbose
{
get { return mShowVerbose; }
set
{
if (this.SetFieldVal(ref mShowVerbose, value))
{
OnShowFiltersChanged();
}
}
}
#endregion
#region ShowStart
bool mShowStart = Constants.IsDebugBuild;
public bool ShowStart
{
get { return mShowStart; }
set
{
if (this.SetFieldVal(ref mShowStart, value))
{
OnShowFiltersChanged();
}
}
}
#endregion
#region ShowStop
bool mShowStop = Constants.IsDebugBuild;
public bool ShowStop
{
get { return mShowStop; }
set
{
if (this.SetFieldVal(ref mShowStop, value))
{
OnShowFiltersChanged();
}
}
}
#endregion
#region ShowSuspend
bool mShowSuspend = true;
public bool ShowSuspend
{
get { return mShowSuspend; }
set
{
if (this.SetFieldVal(ref mShowSuspend, value))
{
OnShowFiltersChanged();
}
}
}
#endregion
#region ShowResume
bool mShowResume = true;
public bool ShowResume
{
get { return mShowResume; }
set
{
if (this.SetFieldVal(ref mShowResume, value))
{
OnShowFiltersChanged();
}
}
}
#endregion
#region ShowTransfer
bool mShowTransfer = true;
public bool ShowTransfer
{
get { return mShowTransfer; }
set
{
if (this.SetFieldVal(ref mShowTransfer, value))
{
OnShowFiltersChanged();
}
}
}
#endregion
#region TailTraces
bool mTailTraces = true;
[Description("When enabled, UI will snap to new traces as they come in")]
public bool TailTraces
{
get { return mTailTraces; }
set { this.SetFieldVal(ref mTailTraces, value); }
}
#endregion
private void PostConstruction()
{
DisplayName = "Trace List";
ToolBarDefinition = ToolBarDefinitions.TraceListToolBar;
mItems = new BindableCollection<TraceListItem>();
ItemsView = System.Windows.Data.CollectionViewSource.GetDefaultView(Items);
}
protected override async Task OnActivateAsync(
CancellationToken cancellationToken)
{
await base.OnActivateAsync(cancellationToken)
.ConfigureAwait(false);
mEventAggregator.SubscribeOnUIThread(this);
}
protected override async Task OnDeactivateAsync(
bool close,
CancellationToken cancellationToken)
{
await base.OnDeactivateAsync(close, cancellationToken)
.ConfigureAwait(false);
mEventAggregator.Unsubscribe(this);
}
public void OnMainModuleClosing()
{
PauseTracing = true;
IsNotifying = false; // we still attempt to track TotalNumberOfTraces even when paused
}
private void OnShowFiltersChanged()
=> ItemsView.Refresh();
Task IHandle<TracedItemEventArgs>.HandleAsync(
TracedItemEventArgs message,
CancellationToken cancellationToken)
{
AddItem(message.Type, message.TimeStamp, message.SourceName, message.Message, message.Data, message.OnClickAction);
return Task.CompletedTask;
}
public void AddItem(
TraceListItemType type,
long timeStamp,
string sourceName,
string message,
object[] data = null,
System.Action onClick = null)
{
if (PauseTracing)
{
// #NOTE I think I still want to track the total number of would-be traces
++mItemNumber;
TotalNumberOfTraces = mItemNumber;
return;
}
SomeRedactedAppNameUserSettings settings = mSomeRedactedAppNameUserSettings;
TraceSourceSettings traceSettings = settings.TraceSourceOptions;
if (traceSettings != null)
{
if (traceSettings.MaxTraceListItems.IsNotNone())
{
int surplus_count = Items.Count;
surplus_count += 1; // we're adding one
surplus_count -= traceSettings.MaxTraceListItems;
while (surplus_count-- > 0)
{
Items.RemoveAt(0);
}
}
}
var item = new TraceListItem
{
ItemType = type,
Number = ++mItemNumber,
TimeStamp = timeStamp,
SourceName = sourceName,
Message = message,
Data = data,
OnClick = onClick,
};
Items.Add(item);
TotalNumberOfTraces = mItemNumber;
}
public void ClearAll() => Items.Clear();
public void OnSelectedItemChanged(
TraceListItem selectedItem)
{
if (mInspectorTool == null)
return;
if (selectedItem == null)
{
mInspectorTool.SelectedObject = null;
return;
}
var item_inspector = new InspectableObjectBuilder()
.WithObjectProperties(selectedItem, TraceListItemPropertyFilter);
if (selectedItem.HasData)
{
_ = item_inspector
#pragma warning disable CA2000 // Dispose objects before losing scope
.WithEditor(selectedItem, x => x.Data, new Inspectors.TraceDataEditorViewModel());
#pragma warning restore CA2000 // Dispose objects before losing scope
}
mInspectorTool.SelectedObject = item_inspector.ToInspectableObject();
}
private static bool TraceListItemPropertyFilter(
PropertyDescriptor pd)
{
switch (pd.Name)
{
case nameof(TraceListItem.SourceName):
case nameof(TraceListItem.Message):
return true;
default:
return false;
}
}
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment