"Amélioration de l'UI AutoDetect Syncshell : ajout de paramètres récurrents, plages horaires et gestion des fuseaux horaires. Refactorisation des méthodes de dessin et introduction de boutons centrés pour une meilleure ergonomie. Mise à jour des fichiers de configuration et du projet avec des optimisations diverses."
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -3,6 +3,7 @@
|
||||
##
|
||||
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
|
||||
.idea
|
||||
qodana.yaml
|
||||
# User-specific files
|
||||
*.rsuser
|
||||
*.suo
|
||||
@@ -13,6 +14,8 @@
|
||||
MareSynchronos/.DS_Store
|
||||
*.zip
|
||||
UmbraServer_extracted/
|
||||
NuGet.config
|
||||
Directory.Build.props
|
||||
|
||||
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||
*.userprefs
|
||||
|
||||
2
MareAPI
2
MareAPI
Submodule MareAPI updated: deb911cb0a...f75f16fb13
@@ -50,6 +50,8 @@
|
||||
<PropertyGroup>
|
||||
<SourceRevisionId>build$([System.DateTime]::UtcNow.ToString("yyyy-MM-ddTHH:mm:ss:fffZ"))</SourceRevisionId>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<DisablePackageVulnerabilityAnalysis>true</DisablePackageVulnerabilityAnalysis>
|
||||
<NoWarn>$(NoWarn);NU1900</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -73,6 +73,13 @@ public sealed class SyncshellDiscoveryService : IHostedService, IMediatorSubscri
|
||||
}
|
||||
|
||||
public async Task<bool> SetVisibilityAsync(string gid, bool visible, CancellationToken ct)
|
||||
{
|
||||
return await SetVisibilityAsync(gid, visible, null, null, null, null, null, ct).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public async Task<bool> SetVisibilityAsync(string gid, bool visible, int? displayDurationHours,
|
||||
int[]? activeWeekdays, TimeSpan? timeStartLocal, TimeSpan? timeEndLocal, string? timeZone,
|
||||
CancellationToken ct)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -80,6 +87,11 @@ public sealed class SyncshellDiscoveryService : IHostedService, IMediatorSubscri
|
||||
{
|
||||
GID = gid,
|
||||
AutoDetectVisible = visible,
|
||||
DisplayDurationHours = displayDurationHours,
|
||||
ActiveWeekdays = activeWeekdays,
|
||||
TimeStartLocal = timeStartLocal.HasValue ? new DateTime(timeStartLocal.Value.Ticks).ToString("HH:mm") : null,
|
||||
TimeEndLocal = timeEndLocal.HasValue ? new DateTime(timeEndLocal.Value.Ticks).ToString("HH:mm") : null,
|
||||
TimeZone = timeZone,
|
||||
};
|
||||
var success = await _apiController.SyncshellDiscoverySetVisibility(request).ConfigureAwait(false);
|
||||
if (!success) return false;
|
||||
|
||||
@@ -79,6 +79,8 @@ public class DrawGroupPair : DrawPairBase
|
||||
width += _uiSharedService.GetIconButtonSize(FontAwesomeIcon.Plus).X + spacing;
|
||||
}
|
||||
|
||||
width += spacing * 1.2f;
|
||||
|
||||
return width;
|
||||
}
|
||||
|
||||
@@ -215,6 +217,7 @@ public class DrawGroupPair : DrawPairBase
|
||||
var pauseIcon = _fullInfoDto.GroupUserPermissions.IsPaused() ? FontAwesomeIcon.Play : FontAwesomeIcon.Pause;
|
||||
var pauseButtonWidth = _uiSharedService.GetIconButtonSize(pauseIcon).X;
|
||||
var barButtonWidth = _uiSharedService.GetIconButtonSize(FontAwesomeIcon.Bars).X;
|
||||
var rightEdgeGap = spacing * 1.2f;
|
||||
|
||||
float totalWidth = 0f;
|
||||
void Accumulate(bool condition, float width)
|
||||
@@ -242,7 +245,7 @@ public class DrawGroupPair : DrawPairBase
|
||||
float cardPaddingX = UiSharedService.GetCardContentPaddingX();
|
||||
float rightMargin = cardPaddingX + 6f * ImGuiHelpers.GlobalScale;
|
||||
float baseX = MathF.Max(ImGui.GetCursorPosX(),
|
||||
ImGui.GetWindowContentRegionMin().X + UiSharedService.GetWindowContentRegionWidth() - rightMargin - totalWidth);
|
||||
ImGui.GetWindowContentRegionMin().X + UiSharedService.GetWindowContentRegionWidth() - rightMargin - rightEdgeGap - totalWidth);
|
||||
float currentX = baseX;
|
||||
|
||||
ImGui.SameLine();
|
||||
@@ -266,6 +269,16 @@ public class DrawGroupPair : DrawPairBase
|
||||
|
||||
if (showInfo && infoIconWidth > 0f)
|
||||
{
|
||||
bool centerWarning = permIcon == FontAwesomeIcon.ExclamationTriangle && showPause && showBars && !showShared && !showPlus;
|
||||
if (centerWarning)
|
||||
{
|
||||
float barsClusterWidth = showBars ? (barButtonWidth + spacing * 0.5f) : 0f;
|
||||
float leftAreaWidth = MathF.Max(totalWidth - pauseButtonWidth - barsClusterWidth, 0f);
|
||||
float warningX = baseX + MathF.Max((leftAreaWidth - infoIconWidth) / 2f, 0f);
|
||||
currentX = warningX;
|
||||
ImGui.SetCursorPosX(currentX);
|
||||
}
|
||||
|
||||
ImGui.SetCursorPosY(textPosY);
|
||||
if (individualAnimDisabled || individualSoundsDisabled || individualVFXDisabled)
|
||||
{
|
||||
@@ -359,7 +372,7 @@ public class DrawGroupPair : DrawPairBase
|
||||
{
|
||||
ImGui.SetCursorPosY(originalY);
|
||||
|
||||
if (_uiSharedService.IconButton(FontAwesomeIcon.Plus))
|
||||
if (_uiSharedService.IconPlusButtonCentered())
|
||||
{
|
||||
var targetUid = _pair.UserData.UID;
|
||||
if (!string.IsNullOrEmpty(targetUid))
|
||||
@@ -376,7 +389,7 @@ public class DrawGroupPair : DrawPairBase
|
||||
{
|
||||
float gapToBars = showBars ? spacing * 0.5f : spacing;
|
||||
ImGui.SetCursorPosY(originalY);
|
||||
if (_uiSharedService.IconButton(pauseIcon))
|
||||
if (pauseIcon == FontAwesomeIcon.Pause ? _uiSharedService.IconPauseButtonCentered() : _uiSharedService.IconButtonCentered(pauseIcon))
|
||||
{
|
||||
var newPermissions = _fullInfoDto.GroupUserPermissions ^ GroupUserPermissions.Paused;
|
||||
_fullInfoDto.GroupUserPermissions = newPermissions;
|
||||
@@ -391,7 +404,7 @@ public class DrawGroupPair : DrawPairBase
|
||||
if (showBars)
|
||||
{
|
||||
ImGui.SetCursorPosY(originalY);
|
||||
if (_uiSharedService.IconButton(FontAwesomeIcon.Bars))
|
||||
if (_uiSharedService.IconButtonCentered(FontAwesomeIcon.Bars))
|
||||
{
|
||||
ImGui.OpenPopup("Syncshell Flyout Menu");
|
||||
}
|
||||
|
||||
@@ -42,8 +42,8 @@ public abstract class DrawPairBase
|
||||
var menuButtonSize = _uiSharedService.GetIconButtonSize(FontAwesomeIcon.Bars);
|
||||
|
||||
float pauseClusterWidth = Math.Max(pauseButtonSize.X, playButtonSize.X);
|
||||
float pauseClusterHeight = Math.Max(pauseButtonSize.Y, playButtonSize.Y);
|
||||
float reservedSpacing = style.ItemSpacing.X * 2.4f;
|
||||
float pauseClusterHeight = Math.Max(Math.Max(pauseButtonSize.Y, playButtonSize.Y), ImGui.GetFrameHeight());
|
||||
float reservedSpacing = style.ItemSpacing.X * 1.6f;
|
||||
float rightButtonWidth =
|
||||
menuButtonSize.X +
|
||||
pauseClusterWidth +
|
||||
@@ -84,11 +84,15 @@ public abstract class DrawPairBase
|
||||
|
||||
ImGui.SetCursorPos(new Vector2(rowStartCursor.X + padding.X, iconTop));
|
||||
DrawLeftSide(iconTop, iconTop);
|
||||
ImGui.SameLine();
|
||||
ImGui.SetCursorPosY(textTop);
|
||||
var posX = ImGui.GetCursorPosX();
|
||||
|
||||
float leftReserved = GetLeftSideReservedWidth();
|
||||
float nameStartX = rowStartCursor.X + padding.X + leftReserved;
|
||||
|
||||
var rightSide = DrawRightSide(buttonTop, buttonTop);
|
||||
DrawName(textTop + padding.Y * 0.15f, posX, rightSide);
|
||||
|
||||
ImGui.SameLine(nameStartX);
|
||||
ImGui.SetCursorPosY(textTop);
|
||||
DrawName(textTop + padding.Y * 0.15f, nameStartX, rightSide);
|
||||
|
||||
ImGui.SetCursorPos(new Vector2(rowStartCursor.X, rowStartCursor.Y + totalHeight));
|
||||
ImGui.SetCursorPosX(rowStartCursor.X);
|
||||
@@ -100,6 +104,8 @@ public abstract class DrawPairBase
|
||||
|
||||
protected virtual float GetRightSideExtraWidth() => 0f;
|
||||
|
||||
protected virtual float GetLeftSideReservedWidth() => UiSharedService.GetIconSize(FontAwesomeIcon.Moon).X * 2f + ImGui.GetStyle().ItemSpacing.X * 1.5f;
|
||||
|
||||
private void DrawName(float originalY, float leftSide, float rightSide)
|
||||
{
|
||||
_displayHandler.DrawPairText(_id, _pair, leftSide, originalY, () => rightSide - leftSide);
|
||||
|
||||
@@ -60,9 +60,29 @@ public class DrawUserPair : DrawPairBase
|
||||
width += _uiSharedService.GetIconButtonSize(FontAwesomeIcon.Running).X + spacingX * 0.5f;
|
||||
}
|
||||
|
||||
width += spacingX * 1.2f;
|
||||
return width;
|
||||
}
|
||||
|
||||
protected override float GetLeftSideReservedWidth()
|
||||
{
|
||||
var style = ImGui.GetStyle();
|
||||
float spacing = style.ItemSpacing.X;
|
||||
float iconW = UiSharedService.GetIconSize(FontAwesomeIcon.Moon).X;
|
||||
|
||||
int icons = 1;
|
||||
if (!(_pair.UserPair!.OwnPermissions.IsPaired() && _pair.UserPair!.OtherPermissions.IsPaired()))
|
||||
icons++;
|
||||
else if (_pair.UserPair!.OwnPermissions.IsPaused() || _pair.UserPair!.OtherPermissions.IsPaused())
|
||||
icons++;
|
||||
if (_pair.IsOnline && _pair.IsVisible)
|
||||
icons++;
|
||||
|
||||
float iconsTotal = icons * iconW + Math.Max(0, icons - 1) * spacing;
|
||||
float cushion = spacing * 0.6f;
|
||||
return iconsTotal + cushion;
|
||||
}
|
||||
|
||||
protected override void DrawLeftSide(float textPosY, float originalY)
|
||||
{
|
||||
var online = _pair.IsOnline;
|
||||
@@ -133,7 +153,8 @@ public class DrawUserPair : DrawPairBase
|
||||
var entryUID = _pair.UserData.AliasOrUID;
|
||||
var spacingX = ImGui.GetStyle().ItemSpacing.X;
|
||||
var edgePadding = UiSharedService.GetCardContentPaddingX() + 6f * ImGuiHelpers.GlobalScale;
|
||||
var windowEndX = ImGui.GetWindowContentRegionMin().X + UiSharedService.GetWindowContentRegionWidth() - edgePadding;
|
||||
var rightEdgeGap = spacingX * 1.2f;
|
||||
var windowEndX = ImGui.GetWindowContentRegionMin().X + UiSharedService.GetWindowContentRegionWidth() - edgePadding - rightEdgeGap;
|
||||
var rightSidePos = windowEndX - barButtonSize.X;
|
||||
|
||||
// Flyout Menu
|
||||
@@ -150,13 +171,12 @@ public class DrawUserPair : DrawPairBase
|
||||
ImGui.EndPopup();
|
||||
}
|
||||
|
||||
// Pause (mutual pairs only)
|
||||
if (_pair.UserPair!.OwnPermissions.IsPaired() && _pair.UserPair!.OtherPermissions.IsPaired())
|
||||
{
|
||||
rightSidePos -= pauseIconSize.X + spacingX;
|
||||
ImGui.SameLine(rightSidePos);
|
||||
ImGui.SetCursorPosY(originalY);
|
||||
if (_uiSharedService.IconButton(pauseIcon))
|
||||
if (pauseIcon == FontAwesomeIcon.Pause ? _uiSharedService.IconPauseButtonCentered() : _uiSharedService.IconButtonCentered(pauseIcon))
|
||||
{
|
||||
var perm = _pair.UserPair!.OwnPermissions;
|
||||
perm.SetPaused(!perm.IsPaused());
|
||||
|
||||
@@ -42,6 +42,16 @@ public class SyncshellAdminUI : WindowMediatorSubscriberBase
|
||||
private bool _autoDetectPasswordDisabled;
|
||||
private string? _autoDetectMessage;
|
||||
|
||||
private bool _autoDetectDesiredVisibility;
|
||||
private int _adDurationHours = 2;
|
||||
private bool _adRecurring = false;
|
||||
private readonly bool[] _adWeekdays = new bool[7];
|
||||
private int _adStartHour = 21;
|
||||
private int _adStartMinute = 0;
|
||||
private int _adEndHour = 23;
|
||||
private int _adEndMinute = 0;
|
||||
private const string AutoDetectTimeZone = "Europe/Paris";
|
||||
|
||||
public SyncshellAdminUI(ILogger<SyncshellAdminUI> logger, MareMediator mediator, ApiController apiController,
|
||||
UiSharedService uiSharedService, PairManager pairManager, SyncshellDiscoveryService syncshellDiscoveryService,
|
||||
GroupFullInfoDto groupFullInfo, PerformanceCollectorService performanceCollectorService)
|
||||
@@ -58,6 +68,7 @@ public class SyncshellAdminUI : WindowMediatorSubscriberBase
|
||||
_multiInvites = 30;
|
||||
_pwChangeSuccess = true;
|
||||
_autoDetectVisible = groupFullInfo.AutoDetectVisible;
|
||||
_autoDetectDesiredVisibility = _autoDetectVisible;
|
||||
_autoDetectPasswordDisabled = groupFullInfo.PasswordTemporarilyDisabled;
|
||||
Mediator.Subscribe<SyncshellAutoDetectStateChanged>(this, OnSyncshellAutoDetectStateChanged);
|
||||
IsOpen = true;
|
||||
@@ -89,6 +100,9 @@ public class SyncshellAdminUI : WindowMediatorSubscriberBase
|
||||
ImGui.Separator();
|
||||
var perm = GroupFullInfo.GroupPermissions;
|
||||
|
||||
using var tabColor = ImRaii.PushColor(ImGuiCol.Tab, UiSharedService.AccentColor);
|
||||
using var tabHoverColor = ImRaii.PushColor(ImGuiCol.TabHovered, UiSharedService.AccentHoverColor);
|
||||
using var tabActiveColor = ImRaii.PushColor(ImGuiCol.TabActive, UiSharedService.AccentActiveColor);
|
||||
using var tabbar = ImRaii.TabBar("syncshell_tab_" + GroupFullInfo.GID);
|
||||
|
||||
if (tabbar)
|
||||
@@ -498,26 +512,93 @@ public class SyncshellAdminUI : WindowMediatorSubscriberBase
|
||||
UiSharedService.ColorTextWrapped(_autoDetectMessage!, ImGuiColors.DalamudYellow);
|
||||
}
|
||||
|
||||
bool desiredVisibility = _autoDetectVisible;
|
||||
using (ImRaii.Disabled(_autoDetectToggleInFlight || _autoDetectStateLoading))
|
||||
{
|
||||
if (ImGui.Checkbox("Afficher cette Syncshell dans l'AutoDetect", ref desiredVisibility))
|
||||
if (ImGui.Checkbox("Afficher cette Syncshell dans l'AutoDetect", ref _autoDetectDesiredVisibility))
|
||||
{
|
||||
_ = ToggleAutoDetectAsync(desiredVisibility);
|
||||
// Only change local desired state; sending is done via the validate button
|
||||
}
|
||||
}
|
||||
_uiSharedService.DrawHelpText("Quand cette option est activée, le mot de passe devient inactif tant que la visibilité est maintenue.");
|
||||
|
||||
if (_autoDetectDesiredVisibility)
|
||||
{
|
||||
ImGuiHelpers.ScaledDummy(4);
|
||||
ImGui.TextUnformatted("Options d'affichage AutoDetect");
|
||||
ImGui.Separator();
|
||||
|
||||
// Recurring toggle first
|
||||
ImGui.Checkbox("Affichage récurrent", ref _adRecurring);
|
||||
_uiSharedService.DrawHelpText("Si activé, vous pouvez choisir les jours et une plage horaire récurrents. Si désactivé, seule la durée sera prise en compte.");
|
||||
|
||||
// Duration in hours (only when NOT recurring)
|
||||
if (!_adRecurring)
|
||||
{
|
||||
ImGuiHelpers.ScaledDummy(4);
|
||||
int duration = _adDurationHours;
|
||||
ImGui.PushItemWidth(120 * ImGuiHelpers.GlobalScale);
|
||||
if (ImGui.InputInt("Durée (heures)", ref duration))
|
||||
{
|
||||
_adDurationHours = Math.Clamp(duration, 1, 240);
|
||||
}
|
||||
ImGui.PopItemWidth();
|
||||
_uiSharedService.DrawHelpText("Combien de temps la Syncshell doit rester visible, en heures.");
|
||||
}
|
||||
|
||||
ImGuiHelpers.ScaledDummy(4);
|
||||
if (_adRecurring)
|
||||
{
|
||||
ImGuiHelpers.ScaledDummy(4);
|
||||
ImGui.TextUnformatted("Jours de la semaine actifs :");
|
||||
string[] daysFr = new[] { "Lun", "Mar", "Mer", "Jeu", "Ven", "Sam", "Dim" };
|
||||
for (int i = 0; i < 7; i++)
|
||||
{
|
||||
ImGui.SameLine(i == 0 ? 0 : 0);
|
||||
bool v = _adWeekdays[i];
|
||||
if (ImGui.Checkbox($"##adwd{i}", ref v)) _adWeekdays[i] = v;
|
||||
ImGui.SameLine();
|
||||
ImGui.TextUnformatted(daysFr[i]);
|
||||
if (i < 6) ImGui.SameLine();
|
||||
}
|
||||
ImGui.NewLine();
|
||||
_uiSharedService.DrawHelpText("Sélectionnez les jours où l'affichage est autorisé (ex: jeudi et dimanche).");
|
||||
|
||||
ImGuiHelpers.ScaledDummy(4);
|
||||
ImGui.TextUnformatted("Plage horaire (heure locale Europe/Paris) :");
|
||||
ImGui.PushItemWidth(60 * ImGuiHelpers.GlobalScale);
|
||||
ImGui.InputInt("Début heure", ref _adStartHour); ImGui.SameLine();
|
||||
ImGui.InputInt("min", ref _adStartMinute);
|
||||
_adStartHour = Math.Clamp(_adStartHour, 0, 23);
|
||||
_adStartMinute = Math.Clamp(_adStartMinute, 0, 59);
|
||||
ImGui.SameLine();
|
||||
ImGui.TextUnformatted("→"); ImGui.SameLine();
|
||||
ImGui.InputInt("Fin heure", ref _adEndHour); ImGui.SameLine();
|
||||
ImGui.InputInt("min ", ref _adEndMinute);
|
||||
_adEndHour = Math.Clamp(_adEndHour, 0, 23);
|
||||
_adEndMinute = Math.Clamp(_adEndMinute, 0, 59);
|
||||
ImGui.PopItemWidth();
|
||||
_uiSharedService.DrawHelpText("Exemple : de 21h00 à 23h00. Le fuseau utilisé est Europe/Paris (avec changements été/hiver).");
|
||||
}
|
||||
}
|
||||
|
||||
if (_autoDetectPasswordDisabled && _autoDetectVisible)
|
||||
{
|
||||
UiSharedService.ColorTextWrapped("Le mot de passe est actuellement désactivé pendant la visibilité AutoDetect.", ImGuiColors.DalamudYellow);
|
||||
}
|
||||
|
||||
ImGuiHelpers.ScaledDummy(6);
|
||||
if (ImGui.Button("Recharger l'état"))
|
||||
using (ImRaii.Disabled(_autoDetectToggleInFlight || _autoDetectStateLoading))
|
||||
{
|
||||
_autoDetectStateLoading = true;
|
||||
_ = EnsureAutoDetectStateAsync(true);
|
||||
if (ImGui.Button("Valider et envoyer"))
|
||||
{
|
||||
_ = SubmitAutoDetectAsync();
|
||||
}
|
||||
ImGui.SameLine();
|
||||
if (ImGui.Button("Recharger l'état"))
|
||||
{
|
||||
_autoDetectStateLoading = true;
|
||||
_ = EnsureAutoDetectStateAsync(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -580,6 +661,67 @@ public class SyncshellAdminUI : WindowMediatorSubscriberBase
|
||||
}
|
||||
}
|
||||
|
||||
private async Task SubmitAutoDetectAsync()
|
||||
{
|
||||
if (_autoDetectToggleInFlight)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_autoDetectToggleInFlight = true;
|
||||
_autoDetectMessage = null;
|
||||
|
||||
try
|
||||
{
|
||||
// Duration always used when visible
|
||||
int? duration = _autoDetectDesiredVisibility ? _adDurationHours : null;
|
||||
|
||||
// Scheduling fields only if recurring is enabled
|
||||
int[]? weekdaysArr = null;
|
||||
TimeSpan? start = null;
|
||||
TimeSpan? end = null;
|
||||
string? tz = null;
|
||||
if (_autoDetectDesiredVisibility && _adRecurring)
|
||||
{
|
||||
List<int> weekdays = new();
|
||||
for (int i = 0; i < 7; i++) if (_adWeekdays[i]) weekdays.Add(i);
|
||||
weekdaysArr = weekdays.Count > 0 ? weekdays.ToArray() : Array.Empty<int>();
|
||||
start = new TimeSpan(_adStartHour, _adStartMinute, 0);
|
||||
end = new TimeSpan(_adEndHour, _adEndMinute, 0);
|
||||
tz = AutoDetectTimeZone;
|
||||
}
|
||||
|
||||
var ok = await _syncshellDiscoveryService.SetVisibilityAsync(
|
||||
GroupFullInfo.GID,
|
||||
_autoDetectDesiredVisibility,
|
||||
duration,
|
||||
weekdaysArr,
|
||||
start,
|
||||
end,
|
||||
tz,
|
||||
CancellationToken.None).ConfigureAwait(false);
|
||||
|
||||
if (!ok)
|
||||
{
|
||||
_autoDetectMessage = "Impossible d'envoyer les paramètres AutoDetect.";
|
||||
return;
|
||||
}
|
||||
|
||||
await EnsureAutoDetectStateAsync(true).ConfigureAwait(false);
|
||||
_autoDetectMessage = _autoDetectDesiredVisibility
|
||||
? "Paramètres AutoDetect envoyés. La Syncshell sera visible selon le planning défini."
|
||||
: "La Syncshell n'est plus visible dans AutoDetect.";
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_autoDetectMessage = $"Erreur lors de l'envoi des paramètres AutoDetect : {ex.Message}";
|
||||
}
|
||||
finally
|
||||
{
|
||||
_autoDetectToggleInFlight = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyAutoDetectState(bool visible, bool passwordDisabled, bool fromServer)
|
||||
{
|
||||
_autoDetectVisible = visible;
|
||||
|
||||
@@ -542,6 +542,100 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase
|
||||
return result;
|
||||
}
|
||||
|
||||
public bool IconButtonCentered(FontAwesomeIcon icon, float? height = null, float xOffset = 0f, float yOffset = 0f, bool square = false)
|
||||
{
|
||||
string text = icon.ToIconString();
|
||||
|
||||
ImGui.PushID($"centered-{text}");
|
||||
Vector2 glyphSize;
|
||||
using (IconFont.Push())
|
||||
glyphSize = ImGui.CalcTextSize(text);
|
||||
ImDrawListPtr drawList = ImGui.GetWindowDrawList();
|
||||
Vector2 cursorScreenPos = ImGui.GetCursorScreenPos();
|
||||
float frameHeight = height ?? ImGui.GetFrameHeight();
|
||||
float buttonWidth = square ? frameHeight : glyphSize.X + ImGui.GetStyle().FramePadding.X * 2f;
|
||||
using var hoverColor = ImRaii.PushColor(ImGuiCol.ButtonHovered, AccentHoverColor);
|
||||
using var activeColor = ImRaii.PushColor(ImGuiCol.ButtonActive, AccentActiveColor);
|
||||
bool clicked = ImGui.Button(string.Empty, new Vector2(buttonWidth, frameHeight));
|
||||
Vector2 pos = new Vector2(
|
||||
cursorScreenPos.X + (buttonWidth - glyphSize.X) / 2f + xOffset,
|
||||
cursorScreenPos.Y + frameHeight / 2f - glyphSize.Y / 2f + yOffset);
|
||||
using (IconFont.Push())
|
||||
drawList.AddText(pos, ImGui.GetColorU32(ImGuiCol.Text), text);
|
||||
ImGui.PopID();
|
||||
|
||||
return clicked;
|
||||
}
|
||||
public bool IconPauseButtonCentered(float? height = null)
|
||||
{
|
||||
ImGui.PushID("centered-pause-custom");
|
||||
Vector2 glyphSize;
|
||||
using (IconFont.Push())
|
||||
glyphSize = ImGui.CalcTextSize(FontAwesomeIcon.Pause.ToIconString());
|
||||
float frameHeight = height ?? ImGui.GetFrameHeight();
|
||||
float buttonWidth = glyphSize.X + ImGui.GetStyle().FramePadding.X * 2f;
|
||||
|
||||
using var hoverColor = ImRaii.PushColor(ImGuiCol.ButtonHovered, AccentHoverColor);
|
||||
using var activeColor = ImRaii.PushColor(ImGuiCol.ButtonActive, AccentActiveColor);
|
||||
|
||||
var drawList = ImGui.GetWindowDrawList();
|
||||
var buttonTopLeft = ImGui.GetCursorScreenPos();
|
||||
bool clicked = ImGui.Button(string.Empty, new Vector2(buttonWidth, frameHeight));
|
||||
|
||||
var textColor = ImGui.GetColorU32(ImGuiCol.Text);
|
||||
|
||||
float h = frameHeight * 0.55f; // bar height
|
||||
float w = MathF.Max(1f, frameHeight * 0.16f); // bar width
|
||||
float gap = MathF.Max(1f, w * 0.9f); // gap between bars
|
||||
float total = 2f * w + gap;
|
||||
|
||||
float startX = buttonTopLeft.X + (buttonWidth - total) / 2f;
|
||||
float startY = buttonTopLeft.Y + (frameHeight - h) / 2f;
|
||||
float rounding = w * 0.35f;
|
||||
|
||||
drawList.AddRectFilled(new Vector2(startX, startY), new Vector2(startX + w, startY + h), textColor, rounding);
|
||||
float rightX = startX + w + gap;
|
||||
drawList.AddRectFilled(new Vector2(rightX, startY), new Vector2(rightX + w, startY + h), textColor, rounding);
|
||||
|
||||
ImGui.PopID();
|
||||
return clicked;
|
||||
}
|
||||
|
||||
public bool IconPlusButtonCentered(float? height = null)
|
||||
{
|
||||
ImGui.PushID("centered-plus-custom");
|
||||
Vector2 glyphSize;
|
||||
using (IconFont.Push())
|
||||
glyphSize = ImGui.CalcTextSize(FontAwesomeIcon.Plus.ToIconString());
|
||||
float frameHeight = height ?? ImGui.GetFrameHeight();
|
||||
float buttonWidth = glyphSize.X + ImGui.GetStyle().FramePadding.X * 2f;
|
||||
|
||||
using var hoverColor = ImRaii.PushColor(ImGuiCol.ButtonHovered, AccentHoverColor);
|
||||
using var activeColor = ImRaii.PushColor(ImGuiCol.ButtonActive, AccentActiveColor);
|
||||
|
||||
var drawList = ImGui.GetWindowDrawList();
|
||||
var buttonTopLeft = ImGui.GetCursorScreenPos();
|
||||
bool clicked = ImGui.Button(string.Empty, new Vector2(buttonWidth, frameHeight));
|
||||
|
||||
var color = ImGui.GetColorU32(ImGuiCol.Text);
|
||||
|
||||
float armThickness = MathF.Max(1f, frameHeight * 0.14f);
|
||||
float crossSize = frameHeight * 0.55f; // total length of vertical/horizontal arms
|
||||
float startX = buttonTopLeft.X + (buttonWidth - crossSize) / 2f;
|
||||
float startY = buttonTopLeft.Y + (frameHeight - crossSize) / 2f;
|
||||
float endX = startX + crossSize;
|
||||
float endY = startY + crossSize;
|
||||
float r = armThickness * 0.35f;
|
||||
|
||||
float hY1 = startY + (crossSize - armThickness) / 2f;
|
||||
drawList.AddRectFilled(new Vector2(startX, hY1), new Vector2(endX, hY1 + armThickness), color, r);
|
||||
float vX1 = startX + (crossSize - armThickness) / 2f;
|
||||
drawList.AddRectFilled(new Vector2(vX1, startY), new Vector2(vX1 + armThickness, endY), color, r);
|
||||
|
||||
ImGui.PopID();
|
||||
return clicked;
|
||||
}
|
||||
|
||||
private bool IconTextButtonInternal(FontAwesomeIcon icon, string text, Vector4? defaultColor = null, float? width = null, bool useAccentHover = true)
|
||||
{
|
||||
int colorsPushed = 0;
|
||||
|
||||
Reference in New Issue
Block a user