namespace AIStudio.Tools; /// /// The shared state of one drop zone scope, meaning one page, one assistant, or one dialog. /// /// /// A scope is the area whose drops end up at its default target whenever the cursor is not over a /// more specific zone. That is what users are used to: a file dropped anywhere in the chat hangs /// itself on the composer. This object connects the two sides -- the scope cascades it inwards, and /// the zone which wants to be the default target claims it here. /// /// The ID of the element the scope renders. public sealed class DropZoneScopeState(string scopeId) { /// /// The ID of the element the scope renders. The hit test reports it for every point inside the /// area which no more specific zone covers. /// public string ScopeId { get; } = scopeId; private object? defaultZone; /// /// Makes the given zone the default target of this scope, unless another zone was there first. /// /// /// Zones initialize in render order, so the first one in the markup wins. Two zones asking for /// the same area is a mistake in the markup rather than a state worth resolving, and taking the /// first one is at least a rule which can be stated and logged. Asking twice is no mistake, /// though: a zone whose parameters are set anew has to keep the role it already holds. /// /// The zone that wants to be the default target. /// True if the zone is the default target of this scope from now on. public bool TryBecomeDefaultZone(object zone) { if (this.defaultZone is not null && !ReferenceEquals(this.defaultZone, zone)) return false; this.defaultZone = zone; return true; } /// /// Gives the role of the default target up again so that another zone can take it. /// /// /// Every zone that took the role has to do this when it is disposed. Without it, an area would /// lose its default target for good as soon as the zone holding it is created anew -- which is /// what happens on every navigation and every time a dialog is opened again. /// /// The zone that gives the role up. public void ReleaseDefaultZone(object zone) { if (ReferenceEquals(this.defaultZone, zone)) this.defaultZone = null; } }