mirror of
https://github.com/goatcorp/Dalamud.git
synced 2025-12-14 04:34:16 +01:00
Make notifications minimizable, remove interactable
This commit is contained in:
parent
e96089f8b2
commit
0040f61125
12 changed files with 688 additions and 424 deletions
|
|
@ -1,7 +1,5 @@
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
||||||
using Dalamud.Interface.Internal.Notifications;
|
|
||||||
|
|
||||||
namespace Dalamud.Interface.ImGuiNotification;
|
namespace Dalamud.Interface.ImGuiNotification;
|
||||||
|
|
||||||
/// <summary>Represents an active notification.</summary>
|
/// <summary>Represents an active notification.</summary>
|
||||||
|
|
@ -17,7 +15,6 @@ public interface IActiveNotification : INotification
|
||||||
|
|
||||||
/// <summary>Invoked upon clicking on the notification.</summary>
|
/// <summary>Invoked upon clicking on the notification.</summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// This event is not applicable when <see cref="INotification.Interactable"/> is set to <c>false</c>.
|
|
||||||
/// Note that this function may be called even after <see cref="Dismiss"/> has been invoked.
|
/// Note that this function may be called even after <see cref="Dismiss"/> has been invoked.
|
||||||
/// Refer to <see cref="IsDismissed"/>.
|
/// Refer to <see cref="IsDismissed"/>.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
|
|
@ -25,7 +22,6 @@ public interface IActiveNotification : INotification
|
||||||
|
|
||||||
/// <summary>Invoked when the mouse enters the notification window.</summary>
|
/// <summary>Invoked when the mouse enters the notification window.</summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// This event is applicable regardless of <see cref="INotification.Interactable"/>.
|
|
||||||
/// Note that this function may be called even after <see cref="Dismiss"/> has been invoked.
|
/// Note that this function may be called even after <see cref="Dismiss"/> has been invoked.
|
||||||
/// Refer to <see cref="IsDismissed"/>.
|
/// Refer to <see cref="IsDismissed"/>.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
|
|
@ -33,7 +29,6 @@ public interface IActiveNotification : INotification
|
||||||
|
|
||||||
/// <summary>Invoked when the mouse leaves the notification window.</summary>
|
/// <summary>Invoked when the mouse leaves the notification window.</summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// This event is applicable regardless of <see cref="INotification.Interactable"/>.
|
|
||||||
/// Note that this function may be called even after <see cref="Dismiss"/> has been invoked.
|
/// Note that this function may be called even after <see cref="Dismiss"/> has been invoked.
|
||||||
/// Refer to <see cref="IsDismissed"/>.
|
/// Refer to <see cref="IsDismissed"/>.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
|
|
@ -41,42 +36,18 @@ public interface IActiveNotification : INotification
|
||||||
|
|
||||||
/// <summary>Invoked upon drawing the action bar of the notification.</summary>
|
/// <summary>Invoked upon drawing the action bar of the notification.</summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// This event is applicable regardless of <see cref="INotification.Interactable"/>.
|
|
||||||
/// Note that this function may be called even after <see cref="Dismiss"/> has been invoked.
|
/// Note that this function may be called even after <see cref="Dismiss"/> has been invoked.
|
||||||
/// Refer to <see cref="IsDismissed"/>.
|
/// Refer to <see cref="IsDismissed"/>.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
event Action<IActiveNotification> DrawActions;
|
event Action<IActiveNotification> DrawActions;
|
||||||
|
|
||||||
/// <inheritdoc cref="INotification.Content"/>
|
|
||||||
new string Content { get; set; }
|
|
||||||
|
|
||||||
/// <inheritdoc cref="INotification.Title"/>
|
|
||||||
new string? Title { get; set; }
|
|
||||||
|
|
||||||
/// <inheritdoc cref="INotification.Type"/>
|
|
||||||
new NotificationType Type { get; set; }
|
|
||||||
|
|
||||||
/// <inheritdoc cref="INotification.Expiry"/>
|
|
||||||
new DateTime Expiry { get; set; }
|
|
||||||
|
|
||||||
/// <inheritdoc cref="INotification.ShowIndeterminateIfNoExpiry"/>
|
|
||||||
new bool ShowIndeterminateIfNoExpiry { get; set; }
|
|
||||||
|
|
||||||
/// <inheritdoc cref="INotification.Interactable"/>
|
|
||||||
new bool Interactable { get; set; }
|
|
||||||
|
|
||||||
/// <inheritdoc cref="INotification.UserDismissable"/>
|
|
||||||
new bool UserDismissable { get; set; }
|
|
||||||
|
|
||||||
/// <inheritdoc cref="INotification.HoverExtendDuration"/>
|
|
||||||
new TimeSpan HoverExtendDuration { get; set; }
|
|
||||||
|
|
||||||
/// <inheritdoc cref="INotification.Progress"/>
|
|
||||||
new float Progress { get; set; }
|
|
||||||
|
|
||||||
/// <summary>Gets the ID of this notification.</summary>
|
/// <summary>Gets the ID of this notification.</summary>
|
||||||
long Id { get; }
|
long Id { get; }
|
||||||
|
|
||||||
|
/// <summary>Gets the effective expiry time.</summary>
|
||||||
|
/// <remarks>Contains <see cref="DateTime.MaxValue"/> if the notification does not expire.</remarks>
|
||||||
|
DateTime EffectiveExpiry { get; }
|
||||||
|
|
||||||
/// <summary>Gets a value indicating whether the mouse cursor is on the notification window.</summary>
|
/// <summary>Gets a value indicating whether the mouse cursor is on the notification window.</summary>
|
||||||
bool IsMouseHovered { get; }
|
bool IsMouseHovered { get; }
|
||||||
|
|
||||||
|
|
@ -87,16 +58,15 @@ public interface IActiveNotification : INotification
|
||||||
/// <summary>Dismisses this notification.</summary>
|
/// <summary>Dismisses this notification.</summary>
|
||||||
void DismissNow();
|
void DismissNow();
|
||||||
|
|
||||||
|
/// <summary>Extends this notifiation.</summary>
|
||||||
|
/// <param name="extension">The extension time.</param>
|
||||||
|
/// <remarks>This does not override <see cref="INotification.HardExpiry"/>.</remarks>
|
||||||
|
void ExtendBy(TimeSpan extension);
|
||||||
|
|
||||||
/// <summary>Loads the icon again using the same <see cref="INotification.IconSource"/>.</summary>
|
/// <summary>Loads the icon again using the same <see cref="INotification.IconSource"/>.</summary>
|
||||||
/// <remarks>If <see cref="IsDismissed"/> is <c>true</c>, then this function is a no-op.</remarks>
|
/// <remarks>If <see cref="IsDismissed"/> is <c>true</c>, then this function is a no-op.</remarks>
|
||||||
void UpdateIcon();
|
void UpdateIcon();
|
||||||
|
|
||||||
/// <summary>Disposes the previous icon source, take ownership of the new icon source,
|
|
||||||
/// and calls <see cref="UpdateIcon"/>.</summary>
|
|
||||||
/// <param name="newIconSource">Thew new icon source.</param>
|
|
||||||
/// <remarks>If <see cref="IsDismissed"/> is <c>true</c>, then this function is a no-op.</remarks>
|
|
||||||
void UpdateIconSource(INotificationIconSource? newIconSource);
|
|
||||||
|
|
||||||
/// <summary>Generates a new value to use for <see cref="Id"/>.</summary>
|
/// <summary>Generates a new value to use for <see cref="Id"/>.</summary>
|
||||||
/// <returns>The new value.</returns>
|
/// <returns>The new value.</returns>
|
||||||
internal static long CreateNewId() => Interlocked.Increment(ref idCounter);
|
internal static long CreateNewId() => Interlocked.Increment(ref idCounter);
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
using Dalamud.Interface.ImGuiNotification.Internal.IconSource;
|
|
||||||
using Dalamud.Interface.Internal.Notifications;
|
using Dalamud.Interface.Internal.Notifications;
|
||||||
|
|
||||||
namespace Dalamud.Interface.ImGuiNotification;
|
namespace Dalamud.Interface.ImGuiNotification;
|
||||||
|
|
@ -6,63 +5,69 @@ namespace Dalamud.Interface.ImGuiNotification;
|
||||||
/// <summary>Represents a notification.</summary>
|
/// <summary>Represents a notification.</summary>
|
||||||
public interface INotification : IDisposable
|
public interface INotification : IDisposable
|
||||||
{
|
{
|
||||||
/// <summary>Gets the content body of the notification.</summary>
|
/// <summary>Gets or sets the content body of the notification.</summary>
|
||||||
string Content { get; }
|
string Content { get; set; }
|
||||||
|
|
||||||
/// <summary>Gets the title of the notification.</summary>
|
/// <summary>Gets or sets the title of the notification.</summary>
|
||||||
string? Title { get; }
|
string? Title { get; set; }
|
||||||
|
|
||||||
/// <summary>Gets the type of the notification.</summary>
|
/// <summary>Gets or sets the text to display when the notification is minimized.</summary>
|
||||||
NotificationType Type { get; }
|
string? MinimizedText { get; set; }
|
||||||
|
|
||||||
/// <summary>Gets the icon source.</summary>
|
/// <summary>Gets or sets the type of the notification.</summary>
|
||||||
|
NotificationType Type { get; set; }
|
||||||
|
|
||||||
|
/// <summary>Gets or sets the icon source.</summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// The assigned value will be disposed upon the <see cref="IDisposable.Dispose"/> call on this instance of
|
/// <para>Assigning a new value that does not equal to the previous value will dispose the old value. The ownership
|
||||||
/// <see cref="INotification"/>.<br />
|
/// of the new value is transferred to this <see cref="INotification"/>. <b>Even if the assignment throws an
|
||||||
/// <br />
|
/// exception</b>, the ownership is transferred, causing the value to be disposed. Assignment should not throw an
|
||||||
/// The following icon sources are currently available.<br />
|
/// exception though, so wrapping the assignment in try...catch block is not required.</para>
|
||||||
/// <ul>
|
/// <para>The assigned value will be disposed upon the <see cref="IDisposable.Dispose"/> call on this instance of
|
||||||
/// <li><see cref="SeIconCharIconSource"/></li>
|
/// <see cref="INotification"/>, unless the same value is assigned, in which case it will do nothing.</para>
|
||||||
/// <li><see cref="FontAwesomeIconIconSource"/></li>
|
/// <para>If this <see cref="INotification"/> is an <see cref="IActiveNotification"/>, then updating this property
|
||||||
/// <li><see cref="TextureWrapIconSource"/></li>
|
/// will change the icon being displayed (calls <see cref="IActiveNotification.UpdateIcon"/>), unless
|
||||||
/// <li><see cref="TextureWrapTaskIconSource"/></li>
|
/// <see cref="IActiveNotification.IsDismissed"/> is <c>true</c>.</para>
|
||||||
/// <li><see cref="GamePathIconSource"/></li>
|
|
||||||
/// <li><see cref="FilePathIconSource"/></li>
|
|
||||||
/// </ul>
|
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
INotificationIconSource? IconSource { get; }
|
INotificationIconSource? IconSource { get; set; }
|
||||||
|
|
||||||
/// <summary>Gets the expiry.</summary>
|
/// <summary>Gets or sets the hard expiry.</summary>
|
||||||
/// <remarks>Set to <see cref="DateTime.MaxValue"/> to make the notification not have an expiry time
|
|
||||||
/// (sticky, indeterminate, permanent, or persistent).</remarks>
|
|
||||||
DateTime Expiry { get; }
|
|
||||||
|
|
||||||
/// <summary>Gets a value indicating whether to show an indeterminate expiration animation if <see cref="Expiry"/>
|
|
||||||
/// is set to <see cref="DateTime.MaxValue"/>.</summary>
|
|
||||||
bool ShowIndeterminateIfNoExpiry { get; }
|
|
||||||
|
|
||||||
/// <summary>Gets a value indicating whether this notification may be interacted.</summary>
|
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// Set this value to <c>true</c> if you want to respond to user inputs from
|
/// Setting this value will override <see cref="InitialDuration"/> and <see cref="HoverExtendDuration"/>, in that
|
||||||
/// <see cref="IActiveNotification.DrawActions"/>.
|
/// the notification will be dismissed when this expiry expires.<br />
|
||||||
/// Note that the close buttons for notifications are always provided and interactable.
|
/// Set to <see cref="DateTime.MaxValue"/> to make only <see cref="InitialDuration"/> take effect.<br />
|
||||||
/// If set to <c>true</c>, then clicking on the notification itself will be interpreted as user-initiated dismissal,
|
/// If neither <see cref="HardExpiry"/> nor <see cref="InitialDuration"/> is not MaxValue, then the notification
|
||||||
/// unless <see cref="IActiveNotification.Click"/> is set or <see cref="UserDismissable"/> is unset.
|
/// will not expire after a set time. It must be explicitly dismissed by the user of via calling
|
||||||
|
/// <see cref="IActiveNotification.DismissNow"/>.<br />
|
||||||
|
/// Updating this value will reset the dismiss timer.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
bool Interactable { get; }
|
DateTime HardExpiry { get; set; }
|
||||||
|
|
||||||
/// <summary>Gets a value indicating whether the user can dismiss the notification by themselves.</summary>
|
/// <summary>Gets or sets the initial duration.</summary>
|
||||||
|
/// <remarks>Set to <see cref="TimeSpan.MaxValue"/> to make only <see cref="HardExpiry"/> take effect.</remarks>
|
||||||
|
/// <remarks>Updating this value will reset the dismiss timer.</remarks>
|
||||||
|
TimeSpan InitialDuration { get; set; }
|
||||||
|
|
||||||
|
/// <summary>Gets or sets the new duration for this notification once the mouse cursor leaves the window.</summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// If set to <see cref="TimeSpan.Zero"/> or less, then this feature is turned off, and hovering the mouse on the
|
||||||
|
/// notification will not make the notification stay.<br />
|
||||||
|
/// Updating this value will reset the dismiss timer.
|
||||||
|
/// </remarks>
|
||||||
|
TimeSpan HoverExtendDuration { get; set; }
|
||||||
|
|
||||||
|
/// <summary>Gets or sets a value indicating whether to show an indeterminate expiration animation if
|
||||||
|
/// <see cref="HardExpiry"/> is set to <see cref="DateTime.MaxValue"/>.</summary>
|
||||||
|
bool ShowIndeterminateIfNoExpiry { get; set; }
|
||||||
|
|
||||||
|
/// <summary>Gets or sets a value indicating whether the notification has been minimized.</summary>
|
||||||
|
bool Minimized { get; set; }
|
||||||
|
|
||||||
|
/// <summary>Gets or sets a value indicating whether the user can dismiss the notification by themselves.</summary>
|
||||||
/// <remarks>Consider adding a cancel button to <see cref="IActiveNotification.DrawActions"/>.</remarks>
|
/// <remarks>Consider adding a cancel button to <see cref="IActiveNotification.DrawActions"/>.</remarks>
|
||||||
bool UserDismissable { get; }
|
bool UserDismissable { get; set; }
|
||||||
|
|
||||||
/// <summary>Gets the new duration for this notification if mouse cursor is on the notification window.</summary>
|
/// <summary>Gets or sets the progress for the background progress bar of the notification.</summary>
|
||||||
/// <remarks>
|
|
||||||
/// If set to <see cref="TimeSpan.Zero"/> or less, then this feature is turned off.
|
|
||||||
/// This property is applicable regardless of <see cref="Interactable"/>.
|
|
||||||
/// </remarks>
|
|
||||||
TimeSpan HoverExtendDuration { get; }
|
|
||||||
|
|
||||||
/// <summary>Gets the progress for the background progress bar of the notification.</summary>
|
|
||||||
/// <remarks>The progress should be in the range between 0 and 1.</remarks>
|
/// <remarks>The progress should be in the range between 0 and 1.</remarks>
|
||||||
float Progress { get; }
|
float Progress { get; set; }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ internal sealed class ActiveNotification : IActiveNotification
|
||||||
private readonly Easing showEasing;
|
private readonly Easing showEasing;
|
||||||
private readonly Easing hideEasing;
|
private readonly Easing hideEasing;
|
||||||
private readonly Easing progressEasing;
|
private readonly Easing progressEasing;
|
||||||
|
private readonly Easing expandoEasing;
|
||||||
|
|
||||||
/// <summary>The progress before for the progress bar animation with <see cref="progressEasing"/>.</summary>
|
/// <summary>The progress before for the progress bar animation with <see cref="progressEasing"/>.</summary>
|
||||||
private float progressBefore;
|
private float progressBefore;
|
||||||
|
|
@ -38,6 +39,9 @@ internal sealed class ActiveNotification : IActiveNotification
|
||||||
/// <summary>New progress value to be updated on next call to <see cref="UpdateAnimations"/>.</summary>
|
/// <summary>New progress value to be updated on next call to <see cref="UpdateAnimations"/>.</summary>
|
||||||
private float? newProgress;
|
private float? newProgress;
|
||||||
|
|
||||||
|
/// <summary>New minimized value to be updated on next call to <see cref="UpdateAnimations"/>.</summary>
|
||||||
|
private bool? newMinimized;
|
||||||
|
|
||||||
/// <summary>Initializes a new instance of the <see cref="ActiveNotification"/> class.</summary>
|
/// <summary>Initializes a new instance of the <see cref="ActiveNotification"/> class.</summary>
|
||||||
/// <param name="underlyingNotification">The underlying notification.</param>
|
/// <param name="underlyingNotification">The underlying notification.</param>
|
||||||
/// <param name="initiatorPlugin">The initiator plugin. Use <c>null</c> if originated by Dalamud.</param>
|
/// <param name="initiatorPlugin">The initiator plugin. Use <c>null</c> if originated by Dalamud.</param>
|
||||||
|
|
@ -51,6 +55,7 @@ internal sealed class ActiveNotification : IActiveNotification
|
||||||
this.showEasing = new InCubic(NotificationConstants.ShowAnimationDuration);
|
this.showEasing = new InCubic(NotificationConstants.ShowAnimationDuration);
|
||||||
this.hideEasing = new OutCubic(NotificationConstants.HideAnimationDuration);
|
this.hideEasing = new OutCubic(NotificationConstants.HideAnimationDuration);
|
||||||
this.progressEasing = new InOutCubic(NotificationConstants.ProgressChangeAnimationDuration);
|
this.progressEasing = new InOutCubic(NotificationConstants.ProgressChangeAnimationDuration);
|
||||||
|
this.expandoEasing = new InOutCubic(NotificationConstants.ExpandoAnimationDuration);
|
||||||
|
|
||||||
this.showEasing.Start();
|
this.showEasing.Start();
|
||||||
this.progressEasing.Start();
|
this.progressEasing.Start();
|
||||||
|
|
@ -88,9 +93,12 @@ internal sealed class ActiveNotification : IActiveNotification
|
||||||
public DateTime CreatedAt { get; } = DateTime.Now;
|
public DateTime CreatedAt { get; } = DateTime.Now;
|
||||||
|
|
||||||
/// <summary>Gets the time of starting to count the timer for the expiration.</summary>
|
/// <summary>Gets the time of starting to count the timer for the expiration.</summary>
|
||||||
public DateTime ExpiryRelativeToTime { get; private set; } = DateTime.Now;
|
public DateTime HoverRelativeToTime { get; private set; } = DateTime.Now;
|
||||||
|
|
||||||
/// <inheritdoc cref="IActiveNotification.Content"/>
|
/// <summary>Gets the extended expiration time from <see cref="ExtendBy"/>.</summary>
|
||||||
|
public DateTime ExtendedExpiry { get; private set; } = DateTime.Now;
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
public string Content
|
public string Content
|
||||||
{
|
{
|
||||||
get => this.underlyingNotification.Content;
|
get => this.underlyingNotification.Content;
|
||||||
|
|
@ -102,7 +110,7 @@ internal sealed class ActiveNotification : IActiveNotification
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc cref="IActiveNotification.Title"/>
|
/// <inheritdoc/>
|
||||||
public string? Title
|
public string? Title
|
||||||
{
|
{
|
||||||
get => this.underlyingNotification.Title;
|
get => this.underlyingNotification.Title;
|
||||||
|
|
@ -114,7 +122,19 @@ internal sealed class ActiveNotification : IActiveNotification
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc cref="IActiveNotification.Type"/>
|
/// <inheritdoc/>
|
||||||
|
public string? MinimizedText
|
||||||
|
{
|
||||||
|
get => this.underlyingNotification.MinimizedText;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (this.IsDismissed)
|
||||||
|
return;
|
||||||
|
this.underlyingNotification.MinimizedText = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
public NotificationType Type
|
public NotificationType Type
|
||||||
{
|
{
|
||||||
get => this.underlyingNotification.Type;
|
get => this.underlyingNotification.Type;
|
||||||
|
|
@ -127,22 +147,98 @@ internal sealed class ActiveNotification : IActiveNotification
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public INotificationIconSource? IconSource => this.underlyingNotification.IconSource;
|
public INotificationIconSource? IconSource
|
||||||
|
|
||||||
/// <inheritdoc cref="IActiveNotification.Expiry"/>
|
|
||||||
public DateTime Expiry
|
|
||||||
{
|
{
|
||||||
get => this.underlyingNotification.Expiry;
|
get => this.underlyingNotification.IconSource;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (this.underlyingNotification.Expiry == value || this.IsDismissed)
|
if (this.IsDismissed)
|
||||||
|
{
|
||||||
|
value?.Dispose();
|
||||||
return;
|
return;
|
||||||
this.underlyingNotification.Expiry = value;
|
}
|
||||||
this.ExpiryRelativeToTime = DateTime.Now;
|
|
||||||
|
this.underlyingNotification.IconSource = value;
|
||||||
|
this.UpdateIcon();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc cref="IActiveNotification.ShowIndeterminateIfNoExpiry"/>
|
/// <inheritdoc/>
|
||||||
|
public DateTime HardExpiry
|
||||||
|
{
|
||||||
|
get => this.underlyingNotification.HardExpiry;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (this.underlyingNotification.HardExpiry == value || this.IsDismissed)
|
||||||
|
return;
|
||||||
|
this.underlyingNotification.HardExpiry = value;
|
||||||
|
this.HoverRelativeToTime = DateTime.Now;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public TimeSpan InitialDuration
|
||||||
|
{
|
||||||
|
get => this.underlyingNotification.InitialDuration;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (this.IsDismissed)
|
||||||
|
return;
|
||||||
|
this.underlyingNotification.InitialDuration = value;
|
||||||
|
this.HoverRelativeToTime = DateTime.Now;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public TimeSpan HoverExtendDuration
|
||||||
|
{
|
||||||
|
get => this.underlyingNotification.HoverExtendDuration;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (this.IsDismissed)
|
||||||
|
return;
|
||||||
|
this.underlyingNotification.HoverExtendDuration = value;
|
||||||
|
this.HoverRelativeToTime = DateTime.Now;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public DateTime EffectiveExpiry
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var initialDuration = this.InitialDuration;
|
||||||
|
var expiryInitial =
|
||||||
|
initialDuration == TimeSpan.MaxValue
|
||||||
|
? DateTime.MaxValue
|
||||||
|
: this.CreatedAt + initialDuration;
|
||||||
|
|
||||||
|
DateTime expiry;
|
||||||
|
var hoverExtendDuration = this.HoverExtendDuration;
|
||||||
|
if (hoverExtendDuration > TimeSpan.Zero && this.IsMouseHovered)
|
||||||
|
{
|
||||||
|
expiry = DateTime.MaxValue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var expiryExtend =
|
||||||
|
hoverExtendDuration == TimeSpan.MaxValue
|
||||||
|
? DateTime.MaxValue
|
||||||
|
: this.HoverRelativeToTime + hoverExtendDuration;
|
||||||
|
|
||||||
|
expiry = expiryInitial > expiryExtend ? expiryInitial : expiryExtend;
|
||||||
|
if (expiry < this.ExtendedExpiry)
|
||||||
|
expiry = this.ExtendedExpiry;
|
||||||
|
}
|
||||||
|
|
||||||
|
var he = this.HardExpiry;
|
||||||
|
if (he < expiry)
|
||||||
|
expiry = he;
|
||||||
|
return expiry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
public bool ShowIndeterminateIfNoExpiry
|
public bool ShowIndeterminateIfNoExpiry
|
||||||
{
|
{
|
||||||
get => this.underlyingNotification.ShowIndeterminateIfNoExpiry;
|
get => this.underlyingNotification.ShowIndeterminateIfNoExpiry;
|
||||||
|
|
@ -154,19 +250,19 @@ internal sealed class ActiveNotification : IActiveNotification
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc cref="IActiveNotification.Interactable"/>
|
/// <inheritdoc/>
|
||||||
public bool Interactable
|
public bool Minimized
|
||||||
{
|
{
|
||||||
get => this.underlyingNotification.Interactable;
|
get => this.newMinimized ?? this.underlyingNotification.Minimized;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (this.IsDismissed)
|
if (this.IsDismissed)
|
||||||
return;
|
return;
|
||||||
this.underlyingNotification.Interactable = value;
|
this.newMinimized = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc cref="IActiveNotification.UserDismissable"/>
|
/// <inheritdoc/>
|
||||||
public bool UserDismissable
|
public bool UserDismissable
|
||||||
{
|
{
|
||||||
get => this.underlyingNotification.UserDismissable;
|
get => this.underlyingNotification.UserDismissable;
|
||||||
|
|
@ -178,19 +274,7 @@ internal sealed class ActiveNotification : IActiveNotification
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc cref="IActiveNotification.HoverExtendDuration"/>
|
/// <inheritdoc/>
|
||||||
public TimeSpan HoverExtendDuration
|
|
||||||
{
|
|
||||||
get => this.underlyingNotification.HoverExtendDuration;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (this.IsDismissed)
|
|
||||||
return;
|
|
||||||
this.underlyingNotification.HoverExtendDuration = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc cref="IActiveNotification.Progress"/>
|
|
||||||
public float Progress
|
public float Progress
|
||||||
{
|
{
|
||||||
get => this.newProgress ?? this.underlyingNotification.Progress;
|
get => this.newProgress ?? this.underlyingNotification.Progress;
|
||||||
|
|
@ -198,7 +282,6 @@ internal sealed class ActiveNotification : IActiveNotification
|
||||||
{
|
{
|
||||||
if (this.IsDismissed)
|
if (this.IsDismissed)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this.newProgress = value;
|
this.newProgress = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -244,13 +327,13 @@ internal sealed class ActiveNotification : IActiveNotification
|
||||||
};
|
};
|
||||||
|
|
||||||
/// <summary>Gets the default icon of the notification.</summary>
|
/// <summary>Gets the default icon of the notification.</summary>
|
||||||
private string? DefaultIconString => this.Type switch
|
private char? DefaultIconChar => this.Type switch
|
||||||
{
|
{
|
||||||
NotificationType.None => null,
|
NotificationType.None => null,
|
||||||
NotificationType.Success => FontAwesomeIcon.CheckCircle.ToIconString(),
|
NotificationType.Success => FontAwesomeIcon.CheckCircle.ToIconChar(),
|
||||||
NotificationType.Warning => FontAwesomeIcon.ExclamationCircle.ToIconString(),
|
NotificationType.Warning => FontAwesomeIcon.ExclamationCircle.ToIconChar(),
|
||||||
NotificationType.Error => FontAwesomeIcon.TimesCircle.ToIconString(),
|
NotificationType.Error => FontAwesomeIcon.TimesCircle.ToIconChar(),
|
||||||
NotificationType.Info => FontAwesomeIcon.InfoCircle.ToIconString(),
|
NotificationType.Info => FontAwesomeIcon.InfoCircle.ToIconChar(),
|
||||||
_ => null,
|
_ => null,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -273,6 +356,9 @@ internal sealed class ActiveNotification : IActiveNotification
|
||||||
? NotificationConstants.UnloadedInitiatorNameFormat.Format(initiatorPlugin.Name)
|
? NotificationConstants.UnloadedInitiatorNameFormat.Format(initiatorPlugin.Name)
|
||||||
: initiatorPlugin.Name;
|
: initiatorPlugin.Name;
|
||||||
|
|
||||||
|
/// <summary>Gets the effective text to display when minimized.</summary>
|
||||||
|
private string EffectiveMinimizedText => (this.MinimizedText ?? this.Content).ReplaceLineEndings(" ");
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
|
|
@ -314,16 +400,38 @@ internal sealed class ActiveNotification : IActiveNotification
|
||||||
this.showEasing.Update();
|
this.showEasing.Update();
|
||||||
this.hideEasing.Update();
|
this.hideEasing.Update();
|
||||||
this.progressEasing.Update();
|
this.progressEasing.Update();
|
||||||
|
if (this.expandoEasing.IsRunning)
|
||||||
|
{
|
||||||
|
this.expandoEasing.Update();
|
||||||
|
if (this.expandoEasing.IsDone)
|
||||||
|
this.expandoEasing.Stop();
|
||||||
|
}
|
||||||
|
|
||||||
if (this.newProgress is { } p)
|
if (this.newProgress is { } newProgressValue)
|
||||||
|
{
|
||||||
|
if (Math.Abs(this.underlyingNotification.Progress - newProgressValue) > float.Epsilon)
|
||||||
{
|
{
|
||||||
this.progressBefore = this.ProgressEased;
|
this.progressBefore = this.ProgressEased;
|
||||||
this.underlyingNotification.Progress = p;
|
this.underlyingNotification.Progress = newProgressValue;
|
||||||
this.progressEasing.Restart();
|
this.progressEasing.Restart();
|
||||||
this.progressEasing.Update();
|
this.progressEasing.Update();
|
||||||
|
}
|
||||||
|
|
||||||
this.newProgress = null;
|
this.newProgress = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.newMinimized is { } newMinimizedValue)
|
||||||
|
{
|
||||||
|
if (this.underlyingNotification.Minimized != newMinimizedValue)
|
||||||
|
{
|
||||||
|
this.underlyingNotification.Minimized = newMinimizedValue;
|
||||||
|
this.expandoEasing.Restart();
|
||||||
|
this.expandoEasing.Update();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.newMinimized = null;
|
||||||
|
}
|
||||||
|
|
||||||
return this.hideEasing.IsRunning && this.hideEasing.IsDone;
|
return this.hideEasing.IsRunning && this.hideEasing.IsDone;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -333,12 +441,9 @@ internal sealed class ActiveNotification : IActiveNotification
|
||||||
/// <returns>The height of the notification.</returns>
|
/// <returns>The height of the notification.</returns>
|
||||||
public float Draw(float maxWidth, float offsetY)
|
public float Draw(float maxWidth, float offsetY)
|
||||||
{
|
{
|
||||||
if (!this.IsDismissed
|
var effectiveExpiry = this.EffectiveExpiry;
|
||||||
&& DateTime.Now > this.Expiry
|
if (!this.IsDismissed && DateTime.Now > effectiveExpiry)
|
||||||
&& (this.HoverExtendDuration <= TimeSpan.Zero || !this.IsMouseHovered))
|
|
||||||
{
|
|
||||||
this.DismissNow(NotificationDismissReason.Timeout);
|
this.DismissNow(NotificationDismissReason.Timeout);
|
||||||
}
|
|
||||||
|
|
||||||
var opacity =
|
var opacity =
|
||||||
Math.Clamp(
|
Math.Clamp(
|
||||||
|
|
@ -375,6 +480,12 @@ internal sealed class ActiveNotification : IActiveNotification
|
||||||
unboundedWidth += NotificationConstants.ScaledWindowPadding * 3;
|
unboundedWidth += NotificationConstants.ScaledWindowPadding * 3;
|
||||||
unboundedWidth += NotificationConstants.ScaledIconSize;
|
unboundedWidth += NotificationConstants.ScaledIconSize;
|
||||||
|
|
||||||
|
var actionWindowHeight =
|
||||||
|
// Content
|
||||||
|
ImGui.GetTextLineHeight() +
|
||||||
|
// Top and bottom padding
|
||||||
|
(NotificationConstants.ScaledWindowPadding * 2);
|
||||||
|
|
||||||
var width = Math.Min(maxWidth, unboundedWidth);
|
var width = Math.Min(maxWidth, unboundedWidth);
|
||||||
|
|
||||||
var viewport = ImGuiHelpers.MainViewport;
|
var viewport = ImGuiHelpers.MainViewport;
|
||||||
|
|
@ -384,6 +495,7 @@ internal sealed class ActiveNotification : IActiveNotification
|
||||||
ImGui.PushID(this.Id.GetHashCode());
|
ImGui.PushID(this.Id.GetHashCode());
|
||||||
ImGui.PushStyleVar(ImGuiStyleVar.Alpha, opacity);
|
ImGui.PushStyleVar(ImGuiStyleVar.Alpha, opacity);
|
||||||
ImGui.PushStyleVar(ImGuiStyleVar.WindowRounding, 0f);
|
ImGui.PushStyleVar(ImGuiStyleVar.WindowRounding, 0f);
|
||||||
|
ImGui.PushStyleVar(ImGuiStyleVar.WindowPadding, new Vector2(NotificationConstants.ScaledWindowPadding));
|
||||||
unsafe
|
unsafe
|
||||||
{
|
{
|
||||||
ImGui.PushStyleColor(
|
ImGui.PushStyleColor(
|
||||||
|
|
@ -402,67 +514,63 @@ internal sealed class ActiveNotification : IActiveNotification
|
||||||
new Vector2(0, offsetY),
|
new Vector2(0, offsetY),
|
||||||
ImGuiCond.Always,
|
ImGuiCond.Always,
|
||||||
Vector2.One);
|
Vector2.One);
|
||||||
ImGui.SetNextWindowSizeConstraints(new(width, 0), new(width, float.MaxValue));
|
ImGui.SetNextWindowSizeConstraints(
|
||||||
ImGui.PushStyleVar(
|
new(width, actionWindowHeight),
|
||||||
ImGuiStyleVar.WindowPadding,
|
new(
|
||||||
new Vector2(NotificationConstants.ScaledWindowPadding, 0));
|
width,
|
||||||
|
!this.underlyingNotification.Minimized || this.expandoEasing.IsRunning
|
||||||
|
? float.MaxValue
|
||||||
|
: actionWindowHeight));
|
||||||
ImGui.Begin(
|
ImGui.Begin(
|
||||||
$"##NotifyMainWindow{this.Id}",
|
$"##NotifyMainWindow{this.Id}",
|
||||||
ImGuiWindowFlags.AlwaysAutoResize |
|
ImGuiWindowFlags.AlwaysAutoResize |
|
||||||
ImGuiWindowFlags.NoDecoration |
|
ImGuiWindowFlags.NoDecoration |
|
||||||
(this.Interactable
|
|
||||||
? ImGuiWindowFlags.None
|
|
||||||
: ImGuiWindowFlags.NoInputs | ImGuiWindowFlags.NoBringToFrontOnFocus) |
|
|
||||||
ImGuiWindowFlags.NoNav |
|
ImGuiWindowFlags.NoNav |
|
||||||
ImGuiWindowFlags.NoMove |
|
ImGuiWindowFlags.NoMove |
|
||||||
ImGuiWindowFlags.NoFocusOnAppearing |
|
ImGuiWindowFlags.NoFocusOnAppearing |
|
||||||
ImGuiWindowFlags.NoDocking);
|
ImGuiWindowFlags.NoDocking);
|
||||||
|
|
||||||
this.DrawWindowBackgroundProgressBar();
|
this.DrawWindowBackgroundProgressBar();
|
||||||
this.DrawNotificationMainWindowContent(width);
|
this.DrawTopBar(interfaceManager, width, actionWindowHeight);
|
||||||
|
if (!this.underlyingNotification.Minimized && !this.expandoEasing.IsRunning)
|
||||||
|
{
|
||||||
|
this.DrawContentArea(width, actionWindowHeight);
|
||||||
|
}
|
||||||
|
else if (this.expandoEasing.IsRunning)
|
||||||
|
{
|
||||||
|
if (this.underlyingNotification.Minimized)
|
||||||
|
ImGui.PushStyleVar(ImGuiStyleVar.Alpha, opacity * (1f - (float)this.expandoEasing.Value));
|
||||||
|
else
|
||||||
|
ImGui.PushStyleVar(ImGuiStyleVar.Alpha, opacity * (float)this.expandoEasing.Value);
|
||||||
|
this.DrawContentArea(width, actionWindowHeight);
|
||||||
|
ImGui.PopStyleVar();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.DrawExpiryBar(effectiveExpiry);
|
||||||
|
|
||||||
var windowPos = ImGui.GetWindowPos();
|
var windowPos = ImGui.GetWindowPos();
|
||||||
var windowSize = ImGui.GetWindowSize();
|
var windowSize = ImGui.GetWindowSize();
|
||||||
var hovered = ImGui.IsWindowHovered();
|
var hovered = ImGui.IsWindowHovered();
|
||||||
|
|
||||||
ImGui.End();
|
ImGui.End();
|
||||||
ImGui.PopStyleVar();
|
|
||||||
|
|
||||||
offsetY += windowSize.Y;
|
|
||||||
|
|
||||||
var actionWindowHeight =
|
|
||||||
// Content
|
|
||||||
ImGui.GetTextLineHeight() +
|
|
||||||
// Top and bottom padding
|
|
||||||
(NotificationConstants.ScaledWindowPadding * 2);
|
|
||||||
ImGuiHelpers.ForceNextWindowMainViewport();
|
|
||||||
ImGui.SetNextWindowPos(
|
|
||||||
(viewportPos + viewportSize) -
|
|
||||||
new Vector2(NotificationConstants.ScaledViewportEdgeMargin) -
|
|
||||||
new Vector2(0, offsetY),
|
|
||||||
ImGuiCond.Always,
|
|
||||||
Vector2.One);
|
|
||||||
ImGui.SetNextWindowSizeConstraints(new(width, actionWindowHeight), new(width, actionWindowHeight));
|
|
||||||
ImGui.PushStyleVar(ImGuiStyleVar.WindowPadding, Vector2.Zero);
|
|
||||||
ImGui.Begin(
|
|
||||||
$"##NotifyActionWindow{this.Id}",
|
|
||||||
ImGuiWindowFlags.NoDecoration |
|
|
||||||
ImGuiWindowFlags.NoNav |
|
|
||||||
ImGuiWindowFlags.NoFocusOnAppearing |
|
|
||||||
ImGuiWindowFlags.NoDocking);
|
|
||||||
|
|
||||||
this.DrawWindowBackgroundProgressBar();
|
|
||||||
this.DrawNotificationActionWindowContent(interfaceManager, width);
|
|
||||||
windowSize.Y += actionWindowHeight;
|
|
||||||
windowPos.Y -= actionWindowHeight;
|
|
||||||
hovered |= ImGui.IsWindowHovered();
|
|
||||||
|
|
||||||
ImGui.End();
|
|
||||||
ImGui.PopStyleVar();
|
|
||||||
|
|
||||||
ImGui.PopStyleColor();
|
ImGui.PopStyleColor();
|
||||||
ImGui.PopStyleVar(2);
|
ImGui.PopStyleVar(3);
|
||||||
ImGui.PopID();
|
ImGui.PopID();
|
||||||
|
|
||||||
|
if (windowPos.X <= ImGui.GetIO().MousePos.X
|
||||||
|
&& windowPos.Y <= ImGui.GetIO().MousePos.Y
|
||||||
|
&& ImGui.GetIO().MousePos.X < windowPos.X + windowSize.X
|
||||||
|
&& ImGui.GetIO().MousePos.Y < windowPos.Y + windowSize.Y)
|
||||||
|
{
|
||||||
|
if (!this.IsMouseHovered)
|
||||||
|
{
|
||||||
|
this.IsMouseHovered = true;
|
||||||
|
this.MouseEnter.InvokeSafely(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.HoverExtendDuration > TimeSpan.Zero)
|
||||||
|
this.HoverRelativeToTime = DateTime.Now;
|
||||||
|
|
||||||
if (hovered)
|
if (hovered)
|
||||||
{
|
{
|
||||||
if (this.Click is null)
|
if (this.Click is null)
|
||||||
|
|
@ -478,30 +586,9 @@ internal sealed class ActiveNotification : IActiveNotification
|
||||||
this.Click.InvokeSafely(this);
|
this.Click.InvokeSafely(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (windowPos.X <= ImGui.GetIO().MousePos.X
|
|
||||||
&& windowPos.Y <= ImGui.GetIO().MousePos.Y
|
|
||||||
&& ImGui.GetIO().MousePos.X < windowPos.X + windowSize.X
|
|
||||||
&& ImGui.GetIO().MousePos.Y < windowPos.Y + windowSize.Y)
|
|
||||||
{
|
|
||||||
if (!this.IsMouseHovered)
|
|
||||||
{
|
|
||||||
this.IsMouseHovered = true;
|
|
||||||
this.MouseEnter.InvokeSafely(this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (this.IsMouseHovered)
|
else if (this.IsMouseHovered)
|
||||||
{
|
{
|
||||||
if (this.HoverExtendDuration > TimeSpan.Zero)
|
|
||||||
{
|
|
||||||
var newExpiry = DateTime.Now + this.HoverExtendDuration;
|
|
||||||
if (newExpiry > this.Expiry)
|
|
||||||
{
|
|
||||||
this.underlyingNotification.Expiry = newExpiry;
|
|
||||||
this.ExpiryRelativeToTime = DateTime.Now;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.IsMouseHovered = false;
|
this.IsMouseHovered = false;
|
||||||
this.MouseLeave.InvokeSafely(this);
|
this.MouseLeave.InvokeSafely(this);
|
||||||
}
|
}
|
||||||
|
|
@ -509,6 +596,14 @@ internal sealed class ActiveNotification : IActiveNotification
|
||||||
return windowSize.Y;
|
return windowSize.Y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public void ExtendBy(TimeSpan extension)
|
||||||
|
{
|
||||||
|
var newExpiry = DateTime.Now + extension;
|
||||||
|
if (this.ExtendedExpiry < newExpiry)
|
||||||
|
this.ExtendedExpiry = newExpiry;
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public void UpdateIcon()
|
public void UpdateIcon()
|
||||||
{
|
{
|
||||||
|
|
@ -518,17 +613,6 @@ internal sealed class ActiveNotification : IActiveNotification
|
||||||
this.MaterializedIcon = (this.IconSource as INotificationIconSource.IInternal)?.Materialize();
|
this.MaterializedIcon = (this.IconSource as INotificationIconSource.IInternal)?.Materialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public void UpdateIconSource(INotificationIconSource? newIconSource)
|
|
||||||
{
|
|
||||||
if (this.IsDismissed || this.underlyingNotification.IconSource == newIconSource)
|
|
||||||
return;
|
|
||||||
|
|
||||||
this.underlyingNotification.IconSource?.Dispose();
|
|
||||||
this.underlyingNotification.IconSource = newIconSource;
|
|
||||||
this.UpdateIcon();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>Removes non-Dalamud invocation targets from events.</summary>
|
/// <summary>Removes non-Dalamud invocation targets from events.</summary>
|
||||||
public void RemoveNonDalamudInvocations()
|
public void RemoveNonDalamudInvocations()
|
||||||
{
|
{
|
||||||
|
|
@ -539,14 +623,13 @@ internal sealed class ActiveNotification : IActiveNotification
|
||||||
this.MouseEnter = RemoveNonDalamudInvocationsCore(this.MouseEnter);
|
this.MouseEnter = RemoveNonDalamudInvocationsCore(this.MouseEnter);
|
||||||
this.MouseLeave = RemoveNonDalamudInvocationsCore(this.MouseLeave);
|
this.MouseLeave = RemoveNonDalamudInvocationsCore(this.MouseLeave);
|
||||||
|
|
||||||
this.Interactable = true;
|
|
||||||
this.IsInitiatorUnloaded = true;
|
this.IsInitiatorUnloaded = true;
|
||||||
this.UserDismissable = true;
|
this.UserDismissable = true;
|
||||||
this.HoverExtendDuration = NotificationConstants.DefaultHoverExtendDuration;
|
this.HoverExtendDuration = NotificationConstants.DefaultHoverExtendDuration;
|
||||||
|
|
||||||
var newMaxExpiry = DateTime.Now + NotificationConstants.DefaultDisplayDuration;
|
var newMaxExpiry = DateTime.Now + NotificationConstants.DefaultDisplayDuration;
|
||||||
if (this.Expiry > newMaxExpiry)
|
if (this.EffectiveExpiry > newMaxExpiry)
|
||||||
this.Expiry = newMaxExpiry;
|
this.HardExpiry = newMaxExpiry;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
@ -617,23 +700,209 @@ internal sealed class ActiveNotification : IActiveNotification
|
||||||
ImGui.PopClipRect();
|
ImGui.PopClipRect();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawNotificationMainWindowContent(float width)
|
private void DrawTopBar(InterfaceManager interfaceManager, float width, float height)
|
||||||
{
|
{
|
||||||
var basePos = ImGui.GetCursorPos();
|
var windowPos = ImGui.GetWindowPos();
|
||||||
|
var windowSize = ImGui.GetWindowSize();
|
||||||
|
|
||||||
|
var rtOffset = new Vector2(width, 0);
|
||||||
|
using (interfaceManager.IconFontHandle?.Push())
|
||||||
|
{
|
||||||
|
ImGui.PushClipRect(windowPos, windowPos + windowSize with { Y = height }, false);
|
||||||
|
if (this.UserDismissable)
|
||||||
|
{
|
||||||
|
if (this.DrawIconButton(FontAwesomeIcon.Times, rtOffset, height))
|
||||||
|
this.DismissNow(NotificationDismissReason.Manual);
|
||||||
|
rtOffset.X -= height;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.underlyingNotification.Minimized)
|
||||||
|
{
|
||||||
|
if (this.DrawIconButton(FontAwesomeIcon.ChevronDown, rtOffset, height))
|
||||||
|
this.Minimized = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (this.DrawIconButton(FontAwesomeIcon.ChevronUp, rtOffset, height))
|
||||||
|
this.Minimized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
rtOffset.X -= height;
|
||||||
|
ImGui.PopClipRect();
|
||||||
|
}
|
||||||
|
|
||||||
|
float relativeOpacity;
|
||||||
|
if (this.expandoEasing.IsRunning)
|
||||||
|
{
|
||||||
|
relativeOpacity =
|
||||||
|
this.underlyingNotification.Minimized
|
||||||
|
? 1f - (float)this.expandoEasing.Value
|
||||||
|
: (float)this.expandoEasing.Value;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
relativeOpacity = this.underlyingNotification.Minimized ? 0f : 1f;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.IsMouseHovered)
|
||||||
|
ImGui.PushClipRect(windowPos, windowPos + rtOffset with { Y = height }, false);
|
||||||
|
else
|
||||||
|
ImGui.PushClipRect(windowPos, windowPos + windowSize with { Y = height }, false);
|
||||||
|
|
||||||
|
if (relativeOpacity > 0)
|
||||||
|
{
|
||||||
|
ImGui.PushStyleVar(ImGuiStyleVar.Alpha, ImGui.GetStyle().Alpha * relativeOpacity);
|
||||||
|
ImGui.SetCursorPos(new(NotificationConstants.ScaledWindowPadding));
|
||||||
|
ImGui.PushStyleColor(ImGuiCol.Text, NotificationConstants.WhenTextColor);
|
||||||
|
ImGui.TextUnformatted(
|
||||||
|
this.IsMouseHovered
|
||||||
|
? this.CreatedAt.FormatAbsoluteDateTime()
|
||||||
|
: this.CreatedAt.FormatRelativeDateTime());
|
||||||
|
ImGui.PopStyleColor();
|
||||||
|
ImGui.PopStyleVar();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (relativeOpacity < 1)
|
||||||
|
{
|
||||||
|
rtOffset = new(width - NotificationConstants.ScaledWindowPadding, 0);
|
||||||
|
ImGui.PushStyleVar(ImGuiStyleVar.Alpha, ImGui.GetStyle().Alpha * (1f - relativeOpacity));
|
||||||
|
|
||||||
|
var ltOffset = new Vector2(NotificationConstants.ScaledWindowPadding);
|
||||||
|
this.DrawIcon(ltOffset, new(height - (2 * NotificationConstants.ScaledWindowPadding)));
|
||||||
|
|
||||||
|
ltOffset.X = height;
|
||||||
|
|
||||||
|
var agoText = this.CreatedAt.FormatRelativeDateTimeShort();
|
||||||
|
var agoSize = ImGui.CalcTextSize(agoText);
|
||||||
|
rtOffset.X -= agoSize.X;
|
||||||
|
ImGui.SetCursorPos(rtOffset with { Y = NotificationConstants.ScaledWindowPadding });
|
||||||
|
ImGui.PushStyleColor(ImGuiCol.Text, NotificationConstants.WhenTextColor);
|
||||||
|
ImGui.TextUnformatted(agoText);
|
||||||
|
ImGui.PopStyleColor();
|
||||||
|
|
||||||
|
rtOffset.X -= NotificationConstants.ScaledWindowPadding;
|
||||||
|
|
||||||
|
ImGui.PushClipRect(
|
||||||
|
windowPos + ltOffset with { Y = 0 },
|
||||||
|
windowPos + rtOffset with { Y = height },
|
||||||
|
true);
|
||||||
|
ImGui.SetCursorPos(ltOffset with { Y = NotificationConstants.ScaledWindowPadding });
|
||||||
|
ImGui.TextUnformatted(this.EffectiveMinimizedText);
|
||||||
|
ImGui.PopClipRect();
|
||||||
|
|
||||||
|
ImGui.PopStyleVar();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.PopClipRect();
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool DrawIconButton(FontAwesomeIcon icon, Vector2 rt, float size)
|
||||||
|
{
|
||||||
|
ImGui.PushStyleVar(ImGuiStyleVar.FramePadding, Vector2.Zero);
|
||||||
|
if (!this.IsMouseHovered)
|
||||||
|
ImGui.PushStyleVar(ImGuiStyleVar.Alpha, 0f);
|
||||||
|
ImGui.PushStyleColor(ImGuiCol.Button, 0);
|
||||||
|
ImGui.PushStyleColor(ImGuiCol.Text, NotificationConstants.CloseTextColor);
|
||||||
|
|
||||||
|
ImGui.SetCursorPos(rt - new Vector2(size, 0));
|
||||||
|
var r = ImGui.Button(icon.ToIconString(), new(size));
|
||||||
|
|
||||||
|
ImGui.PopStyleColor(2);
|
||||||
|
if (!this.IsMouseHovered)
|
||||||
|
ImGui.PopStyleVar();
|
||||||
|
ImGui.PopStyleVar();
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DrawContentArea(float width, float actionWindowHeight)
|
||||||
|
{
|
||||||
|
var textColumnX = (NotificationConstants.ScaledWindowPadding * 2) + NotificationConstants.ScaledIconSize;
|
||||||
|
var textColumnWidth = width - textColumnX - NotificationConstants.ScaledWindowPadding;
|
||||||
|
var textColumnOffset = new Vector2(textColumnX, actionWindowHeight);
|
||||||
|
|
||||||
this.DrawIcon(
|
this.DrawIcon(
|
||||||
basePos,
|
new(NotificationConstants.ScaledWindowPadding, actionWindowHeight),
|
||||||
basePos + new Vector2(NotificationConstants.ScaledIconSize));
|
new(NotificationConstants.ScaledIconSize));
|
||||||
basePos.X += NotificationConstants.ScaledIconSize + NotificationConstants.ScaledWindowPadding;
|
|
||||||
width -= NotificationConstants.ScaledIconSize + (NotificationConstants.ScaledWindowPadding * 2);
|
|
||||||
this.DrawTitle(basePos, basePos + new Vector2(width, 0));
|
|
||||||
basePos.Y = ImGui.GetCursorPosY();
|
|
||||||
this.DrawContentBody(basePos, basePos + new Vector2(width, 0));
|
|
||||||
|
|
||||||
// Intention was to have left, right, and bottom have the window padding and top have the component gap,
|
textColumnOffset.Y += this.DrawTitle(textColumnOffset, textColumnWidth);
|
||||||
// but as ImGui only allows horz/vert padding, we add the extra bottom padding.
|
textColumnOffset.Y += NotificationConstants.ScaledComponentGap;
|
||||||
// Top padding is zero, as the action window will add the padding.
|
|
||||||
ImGui.Dummy(new(NotificationConstants.ScaledWindowPadding));
|
|
||||||
|
|
||||||
|
this.DrawContentBody(textColumnOffset, textColumnWidth);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DrawIcon(Vector2 minCoord, Vector2 size)
|
||||||
|
{
|
||||||
|
var maxCoord = minCoord + size;
|
||||||
|
if (this.MaterializedIcon is not null)
|
||||||
|
{
|
||||||
|
this.MaterializedIcon.DrawIcon(minCoord, maxCoord, this.DefaultIconColor, this.InitiatorPlugin);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var defaultIconChar = this.DefaultIconChar;
|
||||||
|
if (defaultIconChar is not null)
|
||||||
|
{
|
||||||
|
NotificationUtilities.DrawIconString(
|
||||||
|
Service<NotificationManager>.Get().IconFontAwesomeFontHandle,
|
||||||
|
defaultIconChar.Value,
|
||||||
|
minCoord,
|
||||||
|
maxCoord,
|
||||||
|
this.DefaultIconColor);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
TextureWrapTaskIconSource.DefaultMaterializedIcon.DrawIcon(
|
||||||
|
minCoord,
|
||||||
|
maxCoord,
|
||||||
|
this.DefaultIconColor,
|
||||||
|
this.InitiatorPlugin);
|
||||||
|
}
|
||||||
|
|
||||||
|
private float DrawTitle(Vector2 minCoord, float width)
|
||||||
|
{
|
||||||
|
ImGui.PushTextWrapPos(minCoord.X + width);
|
||||||
|
|
||||||
|
ImGui.SetCursorPos(minCoord);
|
||||||
|
if ((this.Title ?? this.DefaultTitle) is { } title)
|
||||||
|
{
|
||||||
|
ImGui.PushStyleColor(ImGuiCol.Text, NotificationConstants.TitleTextColor);
|
||||||
|
ImGui.TextUnformatted(title);
|
||||||
|
ImGui.PopStyleColor();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.PushStyleColor(ImGuiCol.Text, NotificationConstants.BlameTextColor);
|
||||||
|
ImGui.SetCursorPos(minCoord with { Y = ImGui.GetCursorPosY() });
|
||||||
|
ImGui.TextUnformatted(this.InitiatorString);
|
||||||
|
ImGui.PopStyleColor();
|
||||||
|
|
||||||
|
ImGui.PopTextWrapPos();
|
||||||
|
return ImGui.GetCursorPosY() - minCoord.Y;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DrawContentBody(Vector2 minCoord, float width)
|
||||||
|
{
|
||||||
|
ImGui.SetCursorPos(minCoord);
|
||||||
|
ImGui.PushTextWrapPos(minCoord.X + width);
|
||||||
|
ImGui.PushStyleColor(ImGuiCol.Text, NotificationConstants.BodyTextColor);
|
||||||
|
ImGui.TextUnformatted(this.Content);
|
||||||
|
ImGui.PopStyleColor();
|
||||||
|
ImGui.PopTextWrapPos();
|
||||||
|
if (this.DrawActions is not null)
|
||||||
|
{
|
||||||
|
ImGui.SetCursorPosY(ImGui.GetCursorPosY() + NotificationConstants.ScaledComponentGap);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
this.DrawActions.Invoke(this);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DrawExpiryBar(DateTime effectiveExpiry)
|
||||||
|
{
|
||||||
float barL, barR;
|
float barL, barR;
|
||||||
if (this.IsDismissed)
|
if (this.IsDismissed)
|
||||||
{
|
{
|
||||||
|
|
@ -643,7 +912,14 @@ internal sealed class ActiveNotification : IActiveNotification
|
||||||
barL = midpoint - (length * v);
|
barL = midpoint - (length * v);
|
||||||
barR = midpoint + (length * v);
|
barR = midpoint + (length * v);
|
||||||
}
|
}
|
||||||
else if (this.Expiry == DateTime.MaxValue)
|
else if (this.HoverExtendDuration > TimeSpan.Zero && this.IsMouseHovered)
|
||||||
|
{
|
||||||
|
barL = 0f;
|
||||||
|
barR = 1f;
|
||||||
|
this.prevProgressL = barL;
|
||||||
|
this.prevProgressR = barR;
|
||||||
|
}
|
||||||
|
else if (effectiveExpiry == DateTime.MaxValue)
|
||||||
{
|
{
|
||||||
if (this.ShowIndeterminateIfNoExpiry)
|
if (this.ShowIndeterminateIfNoExpiry)
|
||||||
{
|
{
|
||||||
|
|
@ -663,17 +939,10 @@ internal sealed class ActiveNotification : IActiveNotification
|
||||||
this.prevProgressR = barR = 1f;
|
this.prevProgressR = barR = 1f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (this.HoverExtendDuration > TimeSpan.Zero && this.IsMouseHovered)
|
|
||||||
{
|
|
||||||
barL = 0f;
|
|
||||||
barR = 1f;
|
|
||||||
this.prevProgressL = barL;
|
|
||||||
this.prevProgressR = barR;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
barL = 1f - (float)((this.Expiry - DateTime.Now).TotalMilliseconds /
|
barL = 1f - (float)((effectiveExpiry - DateTime.Now).TotalMilliseconds /
|
||||||
(this.Expiry - this.ExpiryRelativeToTime).TotalMilliseconds);
|
(effectiveExpiry - this.HoverRelativeToTime).TotalMilliseconds);
|
||||||
barR = 1f;
|
barR = 1f;
|
||||||
this.prevProgressL = barL;
|
this.prevProgressL = barL;
|
||||||
this.prevProgressR = barR;
|
this.prevProgressR = barR;
|
||||||
|
|
@ -692,112 +961,4 @@ internal sealed class ActiveNotification : IActiveNotification
|
||||||
ImGui.GetColorU32(this.DefaultIconColor));
|
ImGui.GetColorU32(this.DefaultIconColor));
|
||||||
ImGui.PopClipRect();
|
ImGui.PopClipRect();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawIcon(Vector2 minCoord, Vector2 maxCoord)
|
|
||||||
{
|
|
||||||
if (this.MaterializedIcon is not null)
|
|
||||||
{
|
|
||||||
this.MaterializedIcon.DrawIcon(minCoord, maxCoord, this.DefaultIconColor, this.InitiatorPlugin);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var defaultIconString = this.DefaultIconString;
|
|
||||||
if (!string.IsNullOrWhiteSpace(defaultIconString))
|
|
||||||
{
|
|
||||||
FontAwesomeIconIconSource.DrawIconStatic(defaultIconString, minCoord, maxCoord, this.DefaultIconColor);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
TextureWrapTaskIconSource.DefaultMaterializedIcon.DrawIcon(
|
|
||||||
minCoord,
|
|
||||||
maxCoord,
|
|
||||||
this.DefaultIconColor,
|
|
||||||
this.InitiatorPlugin);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DrawTitle(Vector2 minCoord, Vector2 maxCoord)
|
|
||||||
{
|
|
||||||
ImGui.PushTextWrapPos(maxCoord.X);
|
|
||||||
|
|
||||||
ImGui.SetCursorPos(minCoord);
|
|
||||||
if ((this.Title ?? this.DefaultTitle) is { } title)
|
|
||||||
{
|
|
||||||
ImGui.PushStyleColor(ImGuiCol.Text, NotificationConstants.TitleTextColor);
|
|
||||||
ImGui.TextUnformatted(title);
|
|
||||||
ImGui.PopStyleColor();
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui.PushStyleColor(ImGuiCol.Text, NotificationConstants.BlameTextColor);
|
|
||||||
ImGui.SetCursorPos(minCoord with { Y = ImGui.GetCursorPosY() });
|
|
||||||
ImGui.TextUnformatted(this.InitiatorString);
|
|
||||||
ImGui.PopStyleColor();
|
|
||||||
|
|
||||||
ImGui.PopTextWrapPos();
|
|
||||||
ImGui.SetCursorPosY(ImGui.GetCursorPosY() + NotificationConstants.ScaledComponentGap);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DrawContentBody(Vector2 minCoord, Vector2 maxCoord)
|
|
||||||
{
|
|
||||||
ImGui.SetCursorPos(minCoord);
|
|
||||||
ImGui.PushTextWrapPos(maxCoord.X);
|
|
||||||
ImGui.PushStyleColor(ImGuiCol.Text, NotificationConstants.BodyTextColor);
|
|
||||||
ImGui.TextUnformatted(this.Content);
|
|
||||||
ImGui.PopStyleColor();
|
|
||||||
ImGui.PopTextWrapPos();
|
|
||||||
if (this.DrawActions is not null)
|
|
||||||
{
|
|
||||||
ImGui.SetCursorPosY(ImGui.GetCursorPosY() + NotificationConstants.ScaledComponentGap);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
this.DrawActions.Invoke(this);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
// ignore
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DrawNotificationActionWindowContent(InterfaceManager interfaceManager, float width)
|
|
||||||
{
|
|
||||||
ImGui.SetCursorPos(new(NotificationConstants.ScaledWindowPadding));
|
|
||||||
ImGui.PushStyleColor(ImGuiCol.Text, NotificationConstants.WhenTextColor);
|
|
||||||
ImGui.TextUnformatted(
|
|
||||||
this.IsMouseHovered
|
|
||||||
? this.CreatedAt.FormatAbsoluteDateTime()
|
|
||||||
: this.CreatedAt.FormatRelativeDateTime());
|
|
||||||
ImGui.PopStyleColor();
|
|
||||||
|
|
||||||
this.DrawCloseButton(
|
|
||||||
interfaceManager,
|
|
||||||
new(width - NotificationConstants.ScaledWindowPadding, NotificationConstants.ScaledWindowPadding),
|
|
||||||
NotificationConstants.ScaledWindowPadding);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DrawCloseButton(InterfaceManager interfaceManager, Vector2 rt, float pad)
|
|
||||||
{
|
|
||||||
if (!this.UserDismissable)
|
|
||||||
return;
|
|
||||||
|
|
||||||
using (interfaceManager.IconFontHandle?.Push())
|
|
||||||
{
|
|
||||||
var str = FontAwesomeIcon.Times.ToIconString();
|
|
||||||
var textSize = ImGui.CalcTextSize(str);
|
|
||||||
var size = Math.Max(textSize.X, textSize.Y);
|
|
||||||
ImGui.PushStyleVar(ImGuiStyleVar.FramePadding, Vector2.Zero);
|
|
||||||
if (!this.IsMouseHovered)
|
|
||||||
ImGui.PushStyleVar(ImGuiStyleVar.Alpha, 0f);
|
|
||||||
ImGui.PushStyleColor(ImGuiCol.Button, 0);
|
|
||||||
ImGui.PushStyleColor(ImGuiCol.Text, NotificationConstants.CloseTextColor);
|
|
||||||
|
|
||||||
ImGui.SetCursorPos(rt - new Vector2(size, 0) - new Vector2(pad));
|
|
||||||
if (ImGui.Button(str, new(size + (pad * 2))))
|
|
||||||
this.DismissNow(NotificationDismissReason.Manual);
|
|
||||||
|
|
||||||
ImGui.PopStyleColor(2);
|
|
||||||
if (!this.IsMouseHovered)
|
|
||||||
ImGui.PopStyleVar();
|
|
||||||
ImGui.PopStyleVar();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,6 @@ using System.Numerics;
|
||||||
|
|
||||||
using Dalamud.Plugin.Internal.Types;
|
using Dalamud.Plugin.Internal.Types;
|
||||||
|
|
||||||
using ImGuiNET;
|
|
||||||
|
|
||||||
namespace Dalamud.Interface.ImGuiNotification.Internal.IconSource;
|
namespace Dalamud.Interface.ImGuiNotification.Internal.IconSource;
|
||||||
|
|
||||||
/// <summary>Represents the use of <see cref="FontAwesomeIcon"/> as the icon of a notification.</summary>
|
/// <summary>Represents the use of <see cref="FontAwesomeIcon"/> as the icon of a notification.</summary>
|
||||||
|
|
@ -27,35 +25,22 @@ internal class FontAwesomeIconIconSource : INotificationIconSource.IInternal
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public INotificationMaterializedIcon Materialize() => new MaterializedIcon(this.IconChar);
|
public INotificationMaterializedIcon Materialize() => new MaterializedIcon(this.IconChar);
|
||||||
|
|
||||||
/// <summary>Draws the icon.</summary>
|
|
||||||
/// <param name="iconString">The icon string.</param>
|
|
||||||
/// <param name="minCoord">The coordinates of the top left of the icon area.</param>
|
|
||||||
/// <param name="maxCoord">The coordinates of the bottom right of the icon area.</param>
|
|
||||||
/// <param name="color">The foreground color.</param>
|
|
||||||
internal static void DrawIconStatic(string iconString, Vector2 minCoord, Vector2 maxCoord, Vector4 color)
|
|
||||||
{
|
|
||||||
using (Service<NotificationManager>.Get().IconFontAwesomeFontHandle.Push())
|
|
||||||
{
|
|
||||||
var size = ImGui.CalcTextSize(iconString);
|
|
||||||
var pos = ((minCoord + maxCoord) - size) / 2;
|
|
||||||
ImGui.SetCursorPos(pos);
|
|
||||||
ImGui.PushStyleColor(ImGuiCol.Text, color);
|
|
||||||
ImGui.TextUnformatted(iconString);
|
|
||||||
ImGui.PopStyleColor();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private sealed class MaterializedIcon : INotificationMaterializedIcon
|
private sealed class MaterializedIcon : INotificationMaterializedIcon
|
||||||
{
|
{
|
||||||
private readonly string iconString;
|
private readonly char iconChar;
|
||||||
|
|
||||||
public MaterializedIcon(FontAwesomeIcon c) => this.iconString = c.ToIconString();
|
public MaterializedIcon(FontAwesomeIcon c) => this.iconChar = c.ToIconChar();
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DrawIcon(Vector2 minCoord, Vector2 maxCoord, Vector4 color, LocalPlugin? initiatorPlugin) =>
|
public void DrawIcon(Vector2 minCoord, Vector2 maxCoord, Vector4 color, LocalPlugin? initiatorPlugin) =>
|
||||||
DrawIconStatic(this.iconString, minCoord, maxCoord, color);
|
NotificationUtilities.DrawIconString(
|
||||||
|
Service<NotificationManager>.Get().IconFontAwesomeFontHandle,
|
||||||
|
this.iconChar,
|
||||||
|
minCoord,
|
||||||
|
maxCoord,
|
||||||
|
color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,6 @@ using System.Numerics;
|
||||||
using Dalamud.Game.Text;
|
using Dalamud.Game.Text;
|
||||||
using Dalamud.Plugin.Internal.Types;
|
using Dalamud.Plugin.Internal.Types;
|
||||||
|
|
||||||
using ImGuiNET;
|
|
||||||
|
|
||||||
namespace Dalamud.Interface.ImGuiNotification.Internal.IconSource;
|
namespace Dalamud.Interface.ImGuiNotification.Internal.IconSource;
|
||||||
|
|
||||||
/// <summary>Represents the use of <see cref="SeIconChar"/> as the icon of a notification.</summary>
|
/// <summary>Represents the use of <see cref="SeIconChar"/> as the icon of a notification.</summary>
|
||||||
|
|
@ -30,25 +28,20 @@ internal class SeIconCharIconSource : INotificationIconSource.IInternal
|
||||||
|
|
||||||
private sealed class MaterializedIcon : INotificationMaterializedIcon
|
private sealed class MaterializedIcon : INotificationMaterializedIcon
|
||||||
{
|
{
|
||||||
private readonly string iconString;
|
private readonly char iconChar;
|
||||||
|
|
||||||
public MaterializedIcon(SeIconChar c) => this.iconString = c.ToIconString();
|
public MaterializedIcon(SeIconChar c) => this.iconChar = c.ToIconChar();
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DrawIcon(Vector2 minCoord, Vector2 maxCoord, Vector4 color, LocalPlugin? initiatorPlugin)
|
public void DrawIcon(Vector2 minCoord, Vector2 maxCoord, Vector4 color, LocalPlugin? initiatorPlugin) =>
|
||||||
{
|
NotificationUtilities.DrawIconString(
|
||||||
using (Service<NotificationManager>.Get().IconAxisFontHandle.Push())
|
Service<NotificationManager>.Get().IconAxisFontHandle,
|
||||||
{
|
this.iconChar,
|
||||||
var size = ImGui.CalcTextSize(this.iconString);
|
minCoord,
|
||||||
var pos = ((minCoord + maxCoord) - size) / 2;
|
maxCoord,
|
||||||
ImGui.SetCursorPos(pos);
|
color);
|
||||||
ImGui.PushStyleColor(ImGuiCol.Text, color);
|
|
||||||
ImGui.TextUnformatted(this.iconString);
|
|
||||||
ImGui.PopStyleColor();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -106,7 +106,8 @@ internal class NotificationManager : INotificationManager, IServiceType, IDispos
|
||||||
|
|
||||||
var maxWidth = Math.Max(320 * ImGuiHelpers.GlobalScale, viewportSize.X / 3);
|
var maxWidth = Math.Max(320 * ImGuiHelpers.GlobalScale, viewportSize.X / 3);
|
||||||
|
|
||||||
this.notifications.RemoveAll(static x =>
|
this.notifications.RemoveAll(
|
||||||
|
static x =>
|
||||||
{
|
{
|
||||||
if (!x.UpdateAnimations())
|
if (!x.UpdateAnimations())
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
using Dalamud.Interface.Internal.Notifications;
|
using Dalamud.Interface.Internal.Notifications;
|
||||||
|
|
||||||
namespace Dalamud.Interface.ImGuiNotification;
|
namespace Dalamud.Interface.ImGuiNotification;
|
||||||
|
|
@ -5,40 +7,88 @@ namespace Dalamud.Interface.ImGuiNotification;
|
||||||
/// <summary>Represents a blueprint for a notification.</summary>
|
/// <summary>Represents a blueprint for a notification.</summary>
|
||||||
public sealed record Notification : INotification
|
public sealed record Notification : INotification
|
||||||
{
|
{
|
||||||
|
private INotificationIconSource? iconSource;
|
||||||
|
|
||||||
|
/// <summary>Initializes a new instance of the <see cref="Notification"/> class.</summary>
|
||||||
|
public Notification()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Initializes a new instance of the <see cref="Notification"/> class.</summary>
|
||||||
|
/// <param name="notification">The instance of <see cref="INotification"/> to copy from.</param>
|
||||||
|
public Notification(INotification notification) => this.CopyValuesFrom(notification);
|
||||||
|
|
||||||
|
/// <summary>Initializes a new instance of the <see cref="Notification"/> class.</summary>
|
||||||
|
/// <param name="notification">The instance of <see cref="Notification"/> to copy from.</param>
|
||||||
|
public Notification(Notification notification) => this.CopyValuesFrom(notification);
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public string Content { get; set; } = string.Empty;
|
public string Content { get; set; } = string.Empty;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public string? Title { get; set; }
|
public string? Title { get; set; }
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public string? MinimizedText { get; set; }
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public NotificationType Type { get; set; } = NotificationType.None;
|
public NotificationType Type { get; set; } = NotificationType.None;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public INotificationIconSource? IconSource { get; set; }
|
public INotificationIconSource? IconSource
|
||||||
|
{
|
||||||
|
get => this.iconSource;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
var prevSource = Interlocked.Exchange(ref this.iconSource, value);
|
||||||
|
if (prevSource != value)
|
||||||
|
prevSource?.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public DateTime Expiry { get; set; } = DateTime.Now + NotificationConstants.DefaultDisplayDuration;
|
public DateTime HardExpiry { get; set; } = DateTime.MaxValue;
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public TimeSpan InitialDuration { get; set; } = NotificationConstants.DefaultDisplayDuration;
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public TimeSpan HoverExtendDuration { get; set; } = NotificationConstants.DefaultHoverExtendDuration;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public bool ShowIndeterminateIfNoExpiry { get; set; } = true;
|
public bool ShowIndeterminateIfNoExpiry { get; set; } = true;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public bool Interactable { get; set; } = true;
|
public bool Minimized { get; set; } = true;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public bool UserDismissable { get; set; } = true;
|
public bool UserDismissable { get; set; } = true;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public TimeSpan HoverExtendDuration { get; set; } = NotificationConstants.DefaultHoverExtendDuration;
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public float Progress { get; set; } = 1f;
|
public float Progress { get; set; } = 1f;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
this.IconSource?.Dispose();
|
// Assign to the property; it will take care of disposing
|
||||||
this.IconSource = null;
|
this.IconSource = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Copy values from the given instance of <see cref="INotification"/>.</summary>
|
||||||
|
/// <param name="copyFrom">The instance of <see cref="INotification"/> to copy from.</param>
|
||||||
|
private void CopyValuesFrom(INotification copyFrom)
|
||||||
|
{
|
||||||
|
this.Content = copyFrom.Content;
|
||||||
|
this.Title = copyFrom.Title;
|
||||||
|
this.MinimizedText = copyFrom.MinimizedText;
|
||||||
|
this.Type = copyFrom.Type;
|
||||||
|
this.IconSource = copyFrom.IconSource?.Clone();
|
||||||
|
this.HardExpiry = copyFrom.HardExpiry;
|
||||||
|
this.InitialDuration = copyFrom.InitialDuration;
|
||||||
|
this.HoverExtendDuration = copyFrom.HoverExtendDuration;
|
||||||
|
this.ShowIndeterminateIfNoExpiry = copyFrom.ShowIndeterminateIfNoExpiry;
|
||||||
|
this.Minimized = copyFrom.Minimized;
|
||||||
|
this.UserDismissable = copyFrom.UserDismissable;
|
||||||
|
this.Progress = copyFrom.Progress;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
using System.Diagnostics;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
|
||||||
using Dalamud.Interface.Utility;
|
using Dalamud.Interface.Utility;
|
||||||
|
|
@ -56,6 +57,9 @@ public static class NotificationConstants
|
||||||
/// <summary>Duration of progress change animation.</summary>
|
/// <summary>Duration of progress change animation.</summary>
|
||||||
internal static readonly TimeSpan ProgressChangeAnimationDuration = TimeSpan.FromMilliseconds(200);
|
internal static readonly TimeSpan ProgressChangeAnimationDuration = TimeSpan.FromMilliseconds(200);
|
||||||
|
|
||||||
|
/// <summary>Duration of expando animation.</summary>
|
||||||
|
internal static readonly TimeSpan ExpandoAnimationDuration = TimeSpan.FromMilliseconds(300);
|
||||||
|
|
||||||
/// <summary>Text color for the when.</summary>
|
/// <summary>Text color for the when.</summary>
|
||||||
internal static readonly Vector4 WhenTextColor = new(0.8f, 0.8f, 0.8f, 1f);
|
internal static readonly Vector4 WhenTextColor = new(0.8f, 0.8f, 0.8f, 1f);
|
||||||
|
|
||||||
|
|
@ -92,6 +96,16 @@ public static class NotificationConstants
|
||||||
(TimeSpan.MinValue, "just now"),
|
(TimeSpan.MinValue, "just now"),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// <summary>Gets the relative time format strings.</summary>
|
||||||
|
private static readonly (TimeSpan MinSpan, string FormatString)[] RelativeFormatStringsShort =
|
||||||
|
{
|
||||||
|
(TimeSpan.FromDays(1), "{0:%d}d"),
|
||||||
|
(TimeSpan.FromHours(1), "{0:%h}h"),
|
||||||
|
(TimeSpan.FromMinutes(1), "{0:%m}m"),
|
||||||
|
(TimeSpan.FromSeconds(1), "{0:%s}s"),
|
||||||
|
(TimeSpan.MinValue, "now"),
|
||||||
|
};
|
||||||
|
|
||||||
/// <summary>Gets the scaled padding of the window (dot(.) in the above diagram).</summary>
|
/// <summary>Gets the scaled padding of the window (dot(.) in the above diagram).</summary>
|
||||||
internal static float ScaledWindowPadding => MathF.Round(16 * ImGuiHelpers.GlobalScale);
|
internal static float ScaledWindowPadding => MathF.Round(16 * ImGuiHelpers.GlobalScale);
|
||||||
|
|
||||||
|
|
@ -137,4 +151,21 @@ public static class NotificationConstants
|
||||||
/// <param name="when">When.</param>
|
/// <param name="when">When.</param>
|
||||||
/// <returns>The formatted string.</returns>
|
/// <returns>The formatted string.</returns>
|
||||||
internal static string FormatAbsoluteDateTime(this DateTime when) => $"{when:G}";
|
internal static string FormatAbsoluteDateTime(this DateTime when) => $"{when:G}";
|
||||||
|
|
||||||
|
/// <summary>Formats an instance of <see cref="DateTime"/> as a relative time.</summary>
|
||||||
|
/// <param name="when">When.</param>
|
||||||
|
/// <returns>The formatted string.</returns>
|
||||||
|
internal static string FormatRelativeDateTimeShort(this DateTime when)
|
||||||
|
{
|
||||||
|
var ts = DateTime.Now - when;
|
||||||
|
foreach (var (minSpan, formatString) in RelativeFormatStringsShort)
|
||||||
|
{
|
||||||
|
if (ts < minSpan)
|
||||||
|
continue;
|
||||||
|
return string.Format(formatString, ts);
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug.Assert(false, "must not reach here");
|
||||||
|
return "???";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ namespace Dalamud.Interface.ImGuiNotification;
|
||||||
/// <summary>Specifies the reason of dismissal for a notification.</summary>
|
/// <summary>Specifies the reason of dismissal for a notification.</summary>
|
||||||
public enum NotificationDismissReason
|
public enum NotificationDismissReason
|
||||||
{
|
{
|
||||||
/// <summary>The notification is dismissed because the expiry specified from <see cref="INotification.Expiry"/> is
|
/// <summary>The notification is dismissed because the expiry specified from <see cref="INotification.HardExpiry"/> is
|
||||||
/// met.</summary>
|
/// met.</summary>
|
||||||
Timeout = 1,
|
Timeout = 1,
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,8 @@ using System.Runtime.CompilerServices;
|
||||||
using Dalamud.Game.Text;
|
using Dalamud.Game.Text;
|
||||||
using Dalamud.Interface.Internal;
|
using Dalamud.Interface.Internal;
|
||||||
using Dalamud.Interface.Internal.Windows;
|
using Dalamud.Interface.Internal.Windows;
|
||||||
|
using Dalamud.Interface.ManagedFontAtlas;
|
||||||
|
using Dalamud.Interface.Utility;
|
||||||
using Dalamud.Plugin.Internal.Types;
|
using Dalamud.Plugin.Internal.Types;
|
||||||
using Dalamud.Storage.Assets;
|
using Dalamud.Storage.Assets;
|
||||||
|
|
||||||
|
|
@ -35,6 +37,40 @@ public static class NotificationUtilities
|
||||||
public static INotificationIconSource ToIconSource(this FileInfo fileInfo) =>
|
public static INotificationIconSource ToIconSource(this FileInfo fileInfo) =>
|
||||||
INotificationIconSource.FromFile(fileInfo.FullName);
|
INotificationIconSource.FromFile(fileInfo.FullName);
|
||||||
|
|
||||||
|
/// <summary>Draws an icon string.</summary>
|
||||||
|
/// <param name="fontHandleLarge">The font handle to use.</param>
|
||||||
|
/// <param name="c">The icon character.</param>
|
||||||
|
/// <param name="minCoord">The coordinates of the top left of the icon area.</param>
|
||||||
|
/// <param name="maxCoord">The coordinates of the bottom right of the icon area.</param>
|
||||||
|
/// <param name="color">The foreground color.</param>
|
||||||
|
internal static unsafe void DrawIconString(
|
||||||
|
IFontHandle fontHandleLarge,
|
||||||
|
char c,
|
||||||
|
Vector2 minCoord,
|
||||||
|
Vector2 maxCoord,
|
||||||
|
Vector4 color)
|
||||||
|
{
|
||||||
|
var smallerDim = Math.Max(maxCoord.Y - minCoord.Y, maxCoord.X - minCoord.X);
|
||||||
|
using (fontHandleLarge.Push())
|
||||||
|
{
|
||||||
|
var font = ImGui.GetFont();
|
||||||
|
ref readonly var glyph = ref *(ImGuiHelpers.ImFontGlyphReal*)font.FindGlyph(c).NativePtr;
|
||||||
|
var size = glyph.XY1 - glyph.XY0;
|
||||||
|
var smallerSizeDim = Math.Min(size.X, size.Y);
|
||||||
|
var scale = smallerSizeDim > smallerDim ? smallerDim / smallerSizeDim : 1f;
|
||||||
|
size *= scale;
|
||||||
|
var pos = ((minCoord + maxCoord) - size) / 2;
|
||||||
|
pos += ImGui.GetWindowPos();
|
||||||
|
ImGui.GetWindowDrawList().AddImage(
|
||||||
|
font.ContainerAtlas.Textures[glyph.TextureIndex].TexID,
|
||||||
|
pos,
|
||||||
|
pos + size,
|
||||||
|
glyph.UV0,
|
||||||
|
glyph.UV1,
|
||||||
|
ImGui.GetColorU32(color with { W = color.W * ImGui.GetStyle().Alpha }));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>Draws the given texture, or the icon of the plugin if texture is <c>null</c>.</summary>
|
/// <summary>Draws the given texture, or the icon of the plugin if texture is <c>null</c>.</summary>
|
||||||
/// <param name="texture">The texture.</param>
|
/// <param name="texture">The texture.</param>
|
||||||
/// <param name="minCoord">The coordinates of the top left of the icon area.</param>
|
/// <param name="minCoord">The coordinates of the top left of the icon area.</param>
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ using System.Threading.Tasks;
|
||||||
using Dalamud.Game.Text;
|
using Dalamud.Game.Text;
|
||||||
using Dalamud.Interface.ImGuiNotification;
|
using Dalamud.Interface.ImGuiNotification;
|
||||||
using Dalamud.Interface.ImGuiNotification.Internal;
|
using Dalamud.Interface.ImGuiNotification.Internal;
|
||||||
using Dalamud.Interface.ImGuiNotification.Internal.IconSource;
|
|
||||||
using Dalamud.Interface.Internal.Notifications;
|
using Dalamud.Interface.Internal.Notifications;
|
||||||
using Dalamud.Interface.Windowing;
|
using Dalamud.Interface.Windowing;
|
||||||
using Dalamud.Storage.Assets;
|
using Dalamud.Storage.Assets;
|
||||||
|
|
@ -64,6 +63,10 @@ internal class ImGuiWidget : IDataWindowWidget
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
ImGui.InputText("Title##title", ref this.notificationTemplate.Title, 255);
|
ImGui.InputText("Title##title", ref this.notificationTemplate.Title, 255);
|
||||||
|
|
||||||
|
ImGui.Checkbox("##manualMinimizedText", ref this.notificationTemplate.ManualMinimizedText);
|
||||||
|
ImGui.SameLine();
|
||||||
|
ImGui.InputText("MinimizedText##minimizedText", ref this.notificationTemplate.MinimizedText, 255);
|
||||||
|
|
||||||
ImGui.Checkbox("##manualType", ref this.notificationTemplate.ManualType);
|
ImGui.Checkbox("##manualType", ref this.notificationTemplate.ManualType);
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
ImGui.Combo(
|
ImGui.Combo(
|
||||||
|
|
@ -107,10 +110,16 @@ internal class ImGuiWidget : IDataWindowWidget
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui.Combo(
|
ImGui.Combo(
|
||||||
"Duration",
|
"Initial Duration",
|
||||||
ref this.notificationTemplate.DurationInt,
|
ref this.notificationTemplate.InitialDurationInt,
|
||||||
NotificationTemplate.DurationTitles,
|
NotificationTemplate.InitialDurationTitles,
|
||||||
NotificationTemplate.DurationTitles.Length);
|
NotificationTemplate.InitialDurationTitles.Length);
|
||||||
|
|
||||||
|
ImGui.Combo(
|
||||||
|
"Hover Extend Duration",
|
||||||
|
ref this.notificationTemplate.HoverExtendDurationInt,
|
||||||
|
NotificationTemplate.HoverExtendDurationTitles,
|
||||||
|
NotificationTemplate.HoverExtendDurationTitles.Length);
|
||||||
|
|
||||||
ImGui.Combo(
|
ImGui.Combo(
|
||||||
"Progress",
|
"Progress",
|
||||||
|
|
@ -118,7 +127,7 @@ internal class ImGuiWidget : IDataWindowWidget
|
||||||
NotificationTemplate.ProgressModeTitles,
|
NotificationTemplate.ProgressModeTitles,
|
||||||
NotificationTemplate.ProgressModeTitles.Length);
|
NotificationTemplate.ProgressModeTitles.Length);
|
||||||
|
|
||||||
ImGui.Checkbox("Interactable", ref this.notificationTemplate.Interactable);
|
ImGui.Checkbox("Minimized", ref this.notificationTemplate.Minimized);
|
||||||
|
|
||||||
ImGui.Checkbox("Show Indeterminate If No Expiry", ref this.notificationTemplate.ShowIndeterminateIfNoExpiry);
|
ImGui.Checkbox("Show Indeterminate If No Expiry", ref this.notificationTemplate.ShowIndeterminateIfNoExpiry);
|
||||||
|
|
||||||
|
|
@ -141,18 +150,26 @@ internal class ImGuiWidget : IDataWindowWidget
|
||||||
if (this.notificationTemplate.ManualType)
|
if (this.notificationTemplate.ManualType)
|
||||||
type = (NotificationType)this.notificationTemplate.TypeInt;
|
type = (NotificationType)this.notificationTemplate.TypeInt;
|
||||||
|
|
||||||
var duration = NotificationTemplate.Durations[this.notificationTemplate.DurationInt];
|
|
||||||
|
|
||||||
var n = notifications.AddNotification(
|
var n = notifications.AddNotification(
|
||||||
new()
|
new()
|
||||||
{
|
{
|
||||||
Content = text,
|
Content = text,
|
||||||
Title = title,
|
Title = title,
|
||||||
|
MinimizedText = this.notificationTemplate.ManualMinimizedText
|
||||||
|
? this.notificationTemplate.MinimizedText
|
||||||
|
: null,
|
||||||
Type = type,
|
Type = type,
|
||||||
ShowIndeterminateIfNoExpiry = this.notificationTemplate.ShowIndeterminateIfNoExpiry,
|
ShowIndeterminateIfNoExpiry = this.notificationTemplate.ShowIndeterminateIfNoExpiry,
|
||||||
Interactable = this.notificationTemplate.Interactable,
|
Minimized = this.notificationTemplate.Minimized,
|
||||||
UserDismissable = this.notificationTemplate.UserDismissable,
|
UserDismissable = this.notificationTemplate.UserDismissable,
|
||||||
Expiry = duration == TimeSpan.MaxValue ? DateTime.MaxValue : DateTime.Now + duration,
|
InitialDuration =
|
||||||
|
this.notificationTemplate.InitialDurationInt == 0
|
||||||
|
? TimeSpan.MaxValue
|
||||||
|
: NotificationTemplate.Durations[this.notificationTemplate.InitialDurationInt],
|
||||||
|
HoverExtendDuration =
|
||||||
|
this.notificationTemplate.HoverExtendDurationInt == 0
|
||||||
|
? TimeSpan.Zero
|
||||||
|
: NotificationTemplate.Durations[this.notificationTemplate.HoverExtendDurationInt],
|
||||||
Progress = this.notificationTemplate.ProgressMode switch
|
Progress = this.notificationTemplate.ProgressMode switch
|
||||||
{
|
{
|
||||||
0 => 1f,
|
0 => 1f,
|
||||||
|
|
@ -220,7 +237,8 @@ internal class ImGuiWidget : IDataWindowWidget
|
||||||
n.Progress = i / 10f;
|
n.Progress = i / 10f;
|
||||||
}
|
}
|
||||||
|
|
||||||
n.Expiry = DateTime.Now + NotificationConstants.DefaultDisplayDuration;
|
n.ExtendBy(NotificationConstants.DefaultDisplayDuration);
|
||||||
|
n.InitialDuration = NotificationConstants.DefaultDisplayDuration;
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -324,7 +342,7 @@ internal class ImGuiWidget : IDataWindowWidget
|
||||||
nameof(NotificationType.Info),
|
nameof(NotificationType.Info),
|
||||||
};
|
};
|
||||||
|
|
||||||
public static readonly string[] DurationTitles =
|
public static readonly string[] InitialDurationTitles =
|
||||||
{
|
{
|
||||||
"Infinite",
|
"Infinite",
|
||||||
"1 seconds",
|
"1 seconds",
|
||||||
|
|
@ -332,9 +350,17 @@ internal class ImGuiWidget : IDataWindowWidget
|
||||||
"10 seconds",
|
"10 seconds",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
public static readonly string[] HoverExtendDurationTitles =
|
||||||
|
{
|
||||||
|
"Disable",
|
||||||
|
"1 seconds",
|
||||||
|
"3 seconds (default)",
|
||||||
|
"10 seconds",
|
||||||
|
};
|
||||||
|
|
||||||
public static readonly TimeSpan[] Durations =
|
public static readonly TimeSpan[] Durations =
|
||||||
{
|
{
|
||||||
TimeSpan.MaxValue,
|
TimeSpan.Zero,
|
||||||
TimeSpan.FromSeconds(1),
|
TimeSpan.FromSeconds(1),
|
||||||
NotificationConstants.DefaultDisplayDuration,
|
NotificationConstants.DefaultDisplayDuration,
|
||||||
TimeSpan.FromSeconds(10),
|
TimeSpan.FromSeconds(10),
|
||||||
|
|
@ -344,14 +370,17 @@ internal class ImGuiWidget : IDataWindowWidget
|
||||||
public string Content;
|
public string Content;
|
||||||
public bool ManualTitle;
|
public bool ManualTitle;
|
||||||
public string Title;
|
public string Title;
|
||||||
|
public bool ManualMinimizedText;
|
||||||
|
public string MinimizedText;
|
||||||
public int IconSourceInt;
|
public int IconSourceInt;
|
||||||
public string IconSourceText;
|
public string IconSourceText;
|
||||||
public int IconSourceAssetInt;
|
public int IconSourceAssetInt;
|
||||||
public bool ManualType;
|
public bool ManualType;
|
||||||
public int TypeInt;
|
public int TypeInt;
|
||||||
public int DurationInt;
|
public int InitialDurationInt;
|
||||||
|
public int HoverExtendDurationInt;
|
||||||
public bool ShowIndeterminateIfNoExpiry;
|
public bool ShowIndeterminateIfNoExpiry;
|
||||||
public bool Interactable;
|
public bool Minimized;
|
||||||
public bool UserDismissable;
|
public bool UserDismissable;
|
||||||
public bool ActionBar;
|
public bool ActionBar;
|
||||||
public int ProgressMode;
|
public int ProgressMode;
|
||||||
|
|
@ -362,14 +391,17 @@ internal class ImGuiWidget : IDataWindowWidget
|
||||||
this.Content = string.Empty;
|
this.Content = string.Empty;
|
||||||
this.ManualTitle = false;
|
this.ManualTitle = false;
|
||||||
this.Title = string.Empty;
|
this.Title = string.Empty;
|
||||||
|
this.ManualMinimizedText = false;
|
||||||
|
this.MinimizedText = string.Empty;
|
||||||
this.IconSourceInt = 0;
|
this.IconSourceInt = 0;
|
||||||
this.IconSourceText = "ui/icon/000000/000004_hr1.tex";
|
this.IconSourceText = "ui/icon/000000/000004_hr1.tex";
|
||||||
this.IconSourceAssetInt = 0;
|
this.IconSourceAssetInt = 0;
|
||||||
this.ManualType = false;
|
this.ManualType = false;
|
||||||
this.TypeInt = (int)NotificationType.None;
|
this.TypeInt = (int)NotificationType.None;
|
||||||
this.DurationInt = 2;
|
this.InitialDurationInt = 2;
|
||||||
|
this.HoverExtendDurationInt = 2;
|
||||||
this.ShowIndeterminateIfNoExpiry = true;
|
this.ShowIndeterminateIfNoExpiry = true;
|
||||||
this.Interactable = true;
|
this.Minimized = true;
|
||||||
this.UserDismissable = true;
|
this.UserDismissable = true;
|
||||||
this.ActionBar = true;
|
this.ActionBar = true;
|
||||||
this.ProgressMode = 0;
|
this.ProgressMode = 0;
|
||||||
|
|
|
||||||
|
|
@ -579,7 +579,7 @@ public sealed class UiBuilder : IDisposable
|
||||||
Content = content,
|
Content = content,
|
||||||
Title = title,
|
Title = title,
|
||||||
Type = type,
|
Type = type,
|
||||||
Expiry = DateTime.Now + TimeSpan.FromMilliseconds(msDelay),
|
InitialDuration = TimeSpan.FromMilliseconds(msDelay),
|
||||||
},
|
},
|
||||||
true,
|
true,
|
||||||
this.localPlugin);
|
this.localPlugin);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue