using Dalamud.Bindings.ImGui; using Dalamud.Interface; using Dalamud.Interface.Colors; using Dalamud.Interface.Utility.Raii; using Dalamud.Utility; using MareSynchronos.MareConfiguration; using MareSynchronos.Services; using MareSynchronos.Services.Events; using MareSynchronos.Services.Mediator; using Microsoft.Extensions.Logging; using System.Diagnostics; using System.Globalization; using System.Numerics; namespace MareSynchronos.UI; internal class EventViewerUI : WindowMediatorSubscriberBase { private readonly EventAggregator _eventAggregator; private readonly UiSharedService _uiSharedService; private readonly MareConfigService _configService; private List _currentEvents = new(); private Lazy> _filteredEvents; private string _filterFreeText = string.Empty; private bool _isPaused = false; private List CurrentEvents { get { return _currentEvents; } set { _currentEvents = value; _filteredEvents = RecreateFilter(); } } public EventViewerUI(ILogger logger, MareMediator mediator, EventAggregator eventAggregator, UiSharedService uiSharedService, MareConfigService configService, PerformanceCollectorService performanceCollectorService) : base(logger, mediator, "Event Viewer", performanceCollectorService) { _eventAggregator = eventAggregator; _uiSharedService = uiSharedService; _configService = configService; SizeConstraints = new() { MinimumSize = new(700, 400) }; _filteredEvents = RecreateFilter(); } private Lazy> RecreateFilter() { return new(() => CurrentEvents.Where(f => string.IsNullOrEmpty(_filterFreeText) || (f.EventSource.Contains(_filterFreeText, StringComparison.OrdinalIgnoreCase) || f.Character.Contains(_filterFreeText, StringComparison.OrdinalIgnoreCase) || f.UID.Contains(_filterFreeText, StringComparison.OrdinalIgnoreCase) || f.Message.Contains(_filterFreeText, StringComparison.OrdinalIgnoreCase) ) ).ToList()); } private void ClearFilters() { _filterFreeText = string.Empty; _filteredEvents = RecreateFilter(); } public override void OnOpen() { CurrentEvents = _eventAggregator.EventList.Value.OrderByDescending(f => f.EventTime).ToList(); ClearFilters(); } protected override void DrawInternal() { var newEventsAvailable = _eventAggregator.NewEventsAvailable; var freezeSize = _uiSharedService.GetIconTextButtonSize(FontAwesomeIcon.PlayCircle, "Unfreeze View"); if (_isPaused) { using (ImRaii.PushColor(ImGuiCol.Text, ImGuiColors.DalamudYellow, newEventsAvailable)) { if (_uiSharedService.IconTextButton(FontAwesomeIcon.PlayCircle, "Unfreeze View")) _isPaused = false; if (newEventsAvailable) UiSharedService.AttachToolTip("New events are available. Click to resume updating."); } } else { if (_uiSharedService.IconTextButton(FontAwesomeIcon.PauseCircle, "Freeze View")) _isPaused = true; } if (newEventsAvailable && !_isPaused) CurrentEvents = _eventAggregator.EventList.Value.OrderByDescending(f => f.EventTime).ToList(); ImGui.SameLine(freezeSize + ImGui.GetStyle().ItemSpacing.X * 2); bool changedFilter = false; ImGui.SetNextItemWidth(200); changedFilter |= ImGui.InputText("Filter lines", ref _filterFreeText, 50); if (changedFilter) _filteredEvents = RecreateFilter(); using (ImRaii.Disabled(_filterFreeText.IsNullOrEmpty())) { ImGui.SameLine(); if (_uiSharedService.IconButton(FontAwesomeIcon.Ban)) { _filterFreeText = string.Empty; _filteredEvents = RecreateFilter(); } } if (_configService.Current.LogEvents) { var buttonSize = _uiSharedService.GetIconTextButtonSize(FontAwesomeIcon.FolderOpen, "Open EventLog Folder"); var dist = ImGui.GetWindowContentRegionMax().X - buttonSize; ImGui.SameLine(dist); if (_uiSharedService.IconTextButton(FontAwesomeIcon.FolderOpen, "Open EventLog folder")) { ProcessStartInfo ps = new() { FileName = _eventAggregator.EventLogFolder, UseShellExecute = true, WindowStyle = ProcessWindowStyle.Normal }; Process.Start(ps); } } var cursorPos = ImGui.GetCursorPosY(); var max = ImGui.GetWindowContentRegionMax(); var min = ImGui.GetWindowContentRegionMin(); var width = max.X - min.X; var height = max.Y - cursorPos; using var table = ImRaii.Table("eventTable", 6, ImGuiTableFlags.SizingFixedFit | ImGuiTableFlags.ScrollY | ImGuiTableFlags.RowBg, new Vector2(width, height)); float timeColWidth = ImGui.CalcTextSize("88:88:88 PM").X; float sourceColWidth = ImGui.CalcTextSize("PairManager").X; float uidColWidth = ImGui.CalcTextSize("WWWWWWW").X; float characterColWidth = ImGui.CalcTextSize("Wwwwww Wwwwww").X; if (table) { ImGui.TableSetupScrollFreeze(0, 1); ImGui.TableSetupColumn(string.Empty, ImGuiTableColumnFlags.NoSort); ImGui.TableSetupColumn("Time", ImGuiTableColumnFlags.None, timeColWidth); ImGui.TableSetupColumn("Source", ImGuiTableColumnFlags.None, sourceColWidth); ImGui.TableSetupColumn("UID", ImGuiTableColumnFlags.None, uidColWidth); ImGui.TableSetupColumn("Character", ImGuiTableColumnFlags.None, characterColWidth); ImGui.TableSetupColumn("Event", ImGuiTableColumnFlags.None); ImGui.TableHeadersRow(); int i = 0; foreach (var ev in _filteredEvents.Value) { ++i; var icon = ev.EventSeverity switch { EventSeverity.Informational => FontAwesomeIcon.InfoCircle, EventSeverity.Warning => FontAwesomeIcon.ExclamationTriangle, EventSeverity.Error => FontAwesomeIcon.Cross, _ => FontAwesomeIcon.QuestionCircle }; var iconColor = ev.EventSeverity switch { EventSeverity.Informational => new Vector4(), EventSeverity.Warning => ImGuiColors.DalamudYellow, EventSeverity.Error => ImGuiColors.DalamudRed, _ => new Vector4() }; ImGui.TableNextColumn(); _uiSharedService.IconText(icon, iconColor == new Vector4() ? null : iconColor); UiSharedService.AttachToolTip(ev.EventSeverity.ToString()); ImGui.TableNextColumn(); ImGui.AlignTextToFramePadding(); ImGui.TextUnformatted(ev.EventTime.ToString("T", CultureInfo.CurrentCulture)); ImGui.TableNextColumn(); ImGui.AlignTextToFramePadding(); ImGui.TextUnformatted(ev.EventSource); ImGui.TableNextColumn(); ImGui.AlignTextToFramePadding(); if (!string.IsNullOrEmpty(ev.UID)) { if (ImGui.Selectable(ev.UID + $"##{i}")) { _filterFreeText = ev.UID; _filteredEvents = RecreateFilter(); } } else { ImGui.TextUnformatted("--"); } ImGui.TableNextColumn(); ImGui.AlignTextToFramePadding(); if (!string.IsNullOrEmpty(ev.Character)) { if (ImGui.Selectable(ev.Character + $"##{i}")) { _filterFreeText = ev.Character; _filteredEvents = RecreateFilter(); } } else { ImGui.TextUnformatted("--"); } ImGui.TableNextColumn(); ImGui.AlignTextToFramePadding(); var posX = ImGui.GetCursorPosX(); var maxTextLength = ImGui.GetWindowContentRegionMax().X - posX; var textSize = ImGui.CalcTextSize(ev.Message).X; var msg = ev.Message; while (textSize > maxTextLength) { msg = msg[..^5] + "..."; textSize = ImGui.CalcTextSize(msg).X; } ImGui.TextUnformatted(msg); if (!string.Equals(msg, ev.Message, StringComparison.Ordinal)) { UiSharedService.AttachToolTip(ev.Message); } } } } }