qamp/Qrakhen.TilingFrames/Models/TilingHost.cs

75 lines
2.7 KiB
C#

using CopaData.FileInspector.GUI.Models;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
namespace Qrakhen.TilingFrames.Models;
/// <summary>
/// Host node that by paradigm is located only at the very end of the tree's branches.<br/>
/// Hosts may contain at least one central control, or multiple tabs of controls.<br/>
/// Note that tab contents must _not_ be any tiling controls, as that would break hierarchy and branching logic.<br/>
/// Everything above a <see cref="TilingHost"/> will be a <see cref="TilingPanel"/> by definition.
/// </summary>
public class TilingHost : TilingNode
{
public ObservableCollection<HostFrame> Frames { get; } = [];
private HostFrame? _activeFrame;
public HostFrame? ActiveFrame {
get => _activeFrame;
set => SetField(ref _activeFrame, value);
}
public bool ShowTabs => Frames.Count > 1;
public bool IsEmpty => Frames.Count == 0;
public TilingHost(params HostFrame[] frames)
{
if (frames != null && frames.Length > 0) {
Frames = new ObservableCollection<HostFrame>(frames);
ActiveFrame = Frames[^1];
}
Frames.CollectionChanged += OnTabsChanged;
}
private void OnTabsChanged(object? sender, NotifyCollectionChangedEventArgs e)
{
if (e.NewItems != null && e.NewItems.Count > 0) {
// Make the last item active
ActiveFrame = e.NewItems[^1] as HostFrame;
} else if (e.OldItems != null && e.OldItems.Count > 0) {
if (ActiveFrame != null && !Frames.Contains(ActiveFrame)) {
// Previous active tab got removed, revert back to the most recent tab or set ActiveTab to null if tabs are empty.
if (Frames.Count > 0) {
ActiveFrame = Frames[^1];
} else {
ActiveFrame = null;
}
}
}
}
/// <summary>
/// Inserts <paramref name="newHost"/> into <paramref name="targetHost"/> as a new tab
/// after being dropped in the center region by the user.<br/>
/// If the previous host only had one frame inside it, it will be detached from its parent.
/// Otherwise, only the frame will be removed and inserted into <paramref name="targetHost"/>'s frames.
/// </summary>
public static void InsertHost(TilingPanel rootPanel, TilingHost targetHost, TilingHost newHost)
{
HostFrame? frame = newHost.ActiveFrame;
if (frame == null) {
throw new InvalidOperationException($"No active frame to be inserted could be found within {newHost}'s frames.");
}
if (newHost.Frames.Count == 1) {
TilingPanel.Detach(rootPanel, newHost);
} else {
newHost.Frames.Remove(frame);
}
targetHost.Frames.Add(frame);
}
}