Add a popover with a list of diagnostics to the diagnostics toolbar buttons

This commit is contained in:
Neil Brommer 2023-08-02 16:30:24 -07:00
parent 92695b8361
commit 7610ffaf38
10 changed files with 769 additions and 42 deletions

View file

@ -0,0 +1,96 @@
using System;
using System.Collections;
using System.Collections.Generic;
using AppKit;
using Foundation;
namespace Cauldron.Macos.SourceList
{
public class SourceListDataSource : NSOutlineViewDataSource
{
#region Private Variables
private SourceListView _controller;
#endregion
#region Public Variables
public List<SourceListItem> Items = new();
#endregion
#region Constructors
public SourceListDataSource(SourceListView controller)
{
// Initialize
this._controller = controller;
}
#endregion
#region Override Properties
public override nint GetChildrenCount(NSOutlineView outlineView, Foundation.NSObject item)
{
if (item == null)
{
return Items.Count;
}
else
{
return ((SourceListItem)item).Count;
}
}
public override bool ItemExpandable(NSOutlineView outlineView, Foundation.NSObject item)
{
return ((SourceListItem)item).HasChildren;
}
public override NSObject GetChild(NSOutlineView outlineView, nint childIndex, Foundation.NSObject item)
{
if (item == null)
{
return Items[(int)childIndex];
}
else
{
return ((SourceListItem)item)[(int)childIndex];
}
}
public override NSObject GetObjectValue(NSOutlineView outlineView, NSTableColumn tableColumn, NSObject item)
{
return new NSString(((SourceListItem)item).Title);
}
#endregion
#region Internal Methods
internal SourceListItem ItemForRow(int row)
{
int index = 0;
// Look at each group
foreach (SourceListItem item in Items)
{
// Is the row inside this group?
if (row >= index && row <= (index + item.Count))
{
return item[row - index - 1];
}
// Move index
index += item.Count + 1;
}
// Not found
return null;
}
#endregion
}
}

View file

@ -0,0 +1,112 @@
using AppKit;
using CoreGraphics;
using Foundation;
namespace Cauldron.Macos.SourceList
{
public class SourceListDelegate : NSOutlineViewDelegate
{
#region Private variables
private SourceListView _controller;
#endregion
#region Constructors
public SourceListDelegate(SourceListView controller)
{
this._controller = controller;
}
#endregion
#region Override Methods
public override bool ShouldEditTableColumn(NSOutlineView outlineView,
NSTableColumn tableColumn, NSObject item)
{
return false;
}
public override NSCell GetCell(NSOutlineView outlineView, NSTableColumn tableColumn,
NSObject item)
{
nint row = outlineView.RowForItem(item);
return tableColumn.DataCellForRow(row);
}
public override bool IsGroupItem(NSOutlineView outlineView, NSObject item)
{
return ((SourceListItem)item).HasChildren;
}
public override NSView GetView(NSOutlineView outlineView, NSTableColumn tableColumn,
NSObject item)
{
NSTableCellView view;
// Is this a group item?
if (((SourceListItem)item).IsHeader)
{
view = (NSTableCellView)outlineView.MakeView("HeaderCell", this);
}
else
{
view = (NSTableCellView)outlineView.MakeView("DataCell", this);
view.ImageView.Image = ((SourceListItem)item).Icon;
view.TextField.LineBreakMode = NSLineBreakMode.CharWrapping;
view.TextField.UsesSingleLineMode = false;
view.TextField.MaximumNumberOfLines = 0;
}
view.TextField.StringValue = ((SourceListItem)item).Title;
view.TextField.SetBoundsSize(CalculateTextFieldHeight(view));
return view;
}
public override bool ShouldSelectItem(NSOutlineView outlineView, NSObject item)
{
return (outlineView.GetParent(item) != null);
}
public override void SelectionDidChange(NSNotification notification)
{
NSIndexSet selectedIndexes = _controller.SelectedRows;
// More than one item selected?
if (selectedIndexes.Count > 1)
{
// Not handling this case
}
else
{
// Grab the item
var item = _controller.Data.ItemForRow((int)selectedIndexes.FirstIndex);
// Was an item found?
if (item != null)
{
// Fire the clicked event for the item
item.RaiseClickedEvent();
// Inform caller of selection
_controller.RaiseItemSelected(item);
}
}
}
private static CGSize CalculateTextFieldHeight(NSTableCellView cell)
{
CGRect rect = new(0, 0, cell.TextField.Bounds.Width, double.MaxValue);
NSString str = new(cell.TextField.StringValue);
CGRect bounds = str.BoundingRectWithSize(rect.Size, 0,
new NSDictionary(NSStringAttributeKey.Font, cell.TextField.Font));
return new CGSize(cell.TextField.Bounds.Width, bounds.Size.Height);
}
#endregion
}
}

View file

@ -0,0 +1,241 @@
using System;
using System.Collections;
using System.Collections.Generic;
using AppKit;
using Foundation;
namespace Cauldron.Macos.SourceList
{
public class SourceListItem : NSObject, IEnumerator, IEnumerable
{
#region Private Properties
private string _title;
private NSImage _icon;
private string _tag;
private bool _isHeader = false;
private List<SourceListItem> _items = new();
#endregion
#region Computed Properties
public string Title
{
get { return _title; }
set { _title = value; }
}
public NSImage Icon
{
get { return _icon; }
set { _icon = value; }
}
public string Tag
{
get { return _tag; }
set { _tag = value; }
}
public bool IsHeader
{
get => this._isHeader;
set => this._isHeader = value;
}
#endregion
#region Indexer
public SourceListItem this[int index]
{
get
{
return _items[index];
}
set
{
_items[index] = value;
}
}
public int Count
{
get { return _items.Count; }
}
public bool HasChildren
{
get { return (Count > 0); }
}
#endregion
#region Enumerable Routines
private int _position = -1;
public IEnumerator GetEnumerator()
{
_position = -1;
return (IEnumerator)this;
}
public bool MoveNext()
{
_position++;
return (_position < _items.Count);
}
public void Reset()
{ _position = -1; }
public object Current
{
get
{
try
{
return _items[_position];
}
catch (IndexOutOfRangeException)
{
throw new InvalidOperationException();
}
}
}
#endregion
#region Constructors
public SourceListItem() { }
public SourceListItem(string title)
{
this._title = title;
}
public SourceListItem(string title, string icon)
{
this._title = title;
this._icon = NSImage.ImageNamed(icon);
}
public SourceListItem(string title, string icon, ClickedDelegate clicked)
{
this._title = title;
this._icon = NSImage.ImageNamed(icon);
this.Clicked = clicked;
}
public SourceListItem(string title, NSImage icon)
{
this._title = title;
this._icon = icon;
}
public SourceListItem(string title, NSImage icon, ClickedDelegate clicked)
{
this._title = title;
this._icon = icon;
this.Clicked = clicked;
}
public SourceListItem(string title, NSImage icon, string tag)
{
this._title = title;
this._icon = icon;
this._tag = tag;
}
public SourceListItem(string title, NSImage icon, string tag, ClickedDelegate clicked)
{
this._title = title;
this._icon = icon;
this._tag = tag;
this.Clicked = clicked;
}
#endregion
#region Public Methods
public void AddItem(SourceListItem item)
{
_items.Add(item);
}
public void AddItem(string title)
{
_items.Add(new SourceListItem(title));
}
public void AddItem(string title, string icon)
{
_items.Add(new SourceListItem(title, icon));
}
public void AddItem(string title, string icon, ClickedDelegate clicked)
{
_items.Add(new SourceListItem(title, icon, clicked));
}
public void AddItem(string title, NSImage icon)
{
_items.Add(new SourceListItem(title, icon));
}
public void AddItem(string title, NSImage icon, ClickedDelegate clicked)
{
_items.Add(new SourceListItem(title, icon, clicked));
}
public void AddItem(string title, NSImage icon, string tag)
{
_items.Add(new SourceListItem(title, icon, tag));
}
public void AddItem(string title, NSImage icon, string tag, ClickedDelegate clicked)
{
_items.Add(new SourceListItem(title, icon, tag, clicked));
}
public void Insert(int n, SourceListItem item)
{
_items.Insert(n, item);
}
public void RemoveItem(SourceListItem item)
{
_items.Remove(item);
}
public void RemoveItem(int n)
{
_items.RemoveAt(n);
}
public void Clear()
{
_items.Clear();
}
#endregion
#region Events
public delegate void ClickedDelegate();
public event ClickedDelegate Clicked;
internal void RaiseClickedEvent()
{
this.Clicked?.Invoke();
}
#endregion
}
}

View file

@ -0,0 +1,69 @@
using System;
using AppKit;
using Foundation;
namespace Cauldron.Macos.SourceList
{
[Register("SourceListView")]
public class SourceListView : NSOutlineView
{
#region Computed Properties
public SourceListDataSource Data
{
get { return (SourceListDataSource)this.DataSource; }
}
#endregion
#region Constructors
public SourceListView() { }
public SourceListView(IntPtr handle) : base(handle) { }
public SourceListView(NSCoder coder) : base(coder) { }
public SourceListView(NSObjectFlag t) : base(t) { }
public SourceListView(ObjCRuntime.NativeHandle handle) : base(handle) { }
#endregion
#region Override Methods
public override void AwakeFromNib()
{
base.AwakeFromNib();
}
#endregion
#region Public Methods
public void Initialize()
{
this.DataSource = new SourceListDataSource(this);
this.Delegate = new SourceListDelegate(this);
}
public void AddItem(SourceListItem item)
{
Data?.Items.Add(item);
}
#endregion
#region Events
public delegate void ItemSelectedDelegate(SourceListItem item);
public event ItemSelectedDelegate ItemSelected;
internal void RaiseItemSelected(SourceListItem item)
{
this.ItemSelected?.Invoke(item);
}
#endregion
}
}