75 lines
2.7 KiB
C#
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);
|
|
}
|
|
}
|