fix(ui): clickable channel pill, auto-seed channel, kill outer scrollbar
Three smoke bugs from the second in-game test: 1. The channel pill was draw-list only, so it didn't react to clicks and there was no way to switch channels inside a tab. The pill now has a hit area on top and opens a popup that lists every ChatType in tab.SelectedChannels with a ToInputChannel mapping; selecting one writes through CurrentChannel.SetChannel. 2. Switching to Allgemein / Gruppe / Linkshell still showed "—" because tab.CurrentChannel.Channel stayed at Invalid until somebody set it. The sidebar now seeds CurrentChannel on tab activation by walking SelectedChannels for the first key with a valid mapping, so every tab opens with its own real channel instead of inheriting the FC default. 3. MainWindow still surfaced an outer scrollbar next to the message list's own scroll. Adding NoScrollbar + NoScrollWithMouse to the window flags strips the second bar — the body child owns scroll on its own. Plus the system-icon path: System / BattleSystem / GatheringSystem / Error / Notice / LootNotice all map to fa-cog now, so the System tab renders the gear instead of falling back to the generic comment.
This commit is contained in:
@@ -110,8 +110,43 @@ internal sealed class InputBar
|
||||
dl.AddRectFilled(origin, max, pillAbgr, 6f);
|
||||
dl.AddText(origin + new Vector2(PillPaddingX, 3f), textAbgr, label);
|
||||
|
||||
// Reserve the layout slot so SameLine after the pill knows the width.
|
||||
ImGui.Dummy(new Vector2(width, PillHeight));
|
||||
// Hit area over the rendered pill so a click opens the channel
|
||||
// picker. InvisibleButton both reserves the layout slot and gives
|
||||
// the popup a stable anchor item.
|
||||
ImGui.InvisibleButton("##hellion-pill", new Vector2(width, PillHeight));
|
||||
if (ImGui.IsItemClicked() && tab is not null)
|
||||
ImGui.OpenPopup("##hellion-channel-picker");
|
||||
|
||||
DrawChannelPickerPopup(tab);
|
||||
}
|
||||
|
||||
private static void DrawChannelPickerPopup(Tab? tab)
|
||||
{
|
||||
if (!ImGui.BeginPopup("##hellion-channel-picker"))
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
if (tab is null || tab.SelectedChannels.Count == 0)
|
||||
{
|
||||
ImGui.TextDisabled("No channels");
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var chatType in tab.SelectedChannels.Keys)
|
||||
{
|
||||
if (chatType.ToInputChannel() is not { } input)
|
||||
continue;
|
||||
|
||||
var isCurrent = tab.CurrentChannel.Channel == input;
|
||||
if (ImGui.Selectable(input.ToChatType().Name(), isCurrent))
|
||||
tab.CurrentChannel.SetChannel(input);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
ImGui.EndPopup();
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawInputField(Tab? activeTab)
|
||||
|
||||
@@ -117,7 +117,10 @@ internal sealed class Sidebar
|
||||
ImGui.InvisibleButton("row", new Vector2(tabHitWidth, RowHeight));
|
||||
var rowHovered = ImGui.IsItemHovered();
|
||||
if (ImGui.IsItemClicked())
|
||||
{
|
||||
activeTab = tab;
|
||||
EnsureCurrentChannel(tab);
|
||||
}
|
||||
|
||||
dl.DrawHoverSheen(
|
||||
origin,
|
||||
@@ -209,11 +212,36 @@ internal sealed class Sidebar
|
||||
ChatType.NoviceNetwork or ChatType.NoviceNetworkSystem => FontAwesomeIcon.Users,
|
||||
ChatType.PvpTeam or ChatType.PvpTeamAnnouncement or ChatType.PvpTeamLoginLogout =>
|
||||
FontAwesomeIcon.Users,
|
||||
ChatType.System or ChatType.Echo => FontAwesomeIcon.Cog,
|
||||
ChatType.System
|
||||
or ChatType.BattleSystem
|
||||
or ChatType.GatheringSystem
|
||||
or ChatType.Error
|
||||
or ChatType.Notice
|
||||
or ChatType.LootNotice
|
||||
or ChatType.Echo => FontAwesomeIcon.Cog,
|
||||
ChatType.CustomEmote or ChatType.StandardEmote => FontAwesomeIcon.Comments,
|
||||
_ => FontAwesomeIcon.Comment,
|
||||
};
|
||||
|
||||
// Pick a sensible input channel for the tab if it has none yet —
|
||||
// walking SelectedChannels for the first key with a ToInputChannel
|
||||
// mapping lets the channel pill render the tab's actual channel
|
||||
// instead of falling back to "—" on first activation.
|
||||
private static void EnsureCurrentChannel(Tab tab)
|
||||
{
|
||||
if (tab.CurrentChannel.Channel != InputChannel.Invalid)
|
||||
return;
|
||||
|
||||
foreach (var chatType in tab.SelectedChannels.Keys)
|
||||
{
|
||||
if (chatType.ToInputChannel() is { } input)
|
||||
{
|
||||
tab.CurrentChannel.SetChannel(input);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void LogPopOutStub(Tab tab)
|
||||
{
|
||||
// The channel-popout pool is built in a later cycle; logging here
|
||||
|
||||
@@ -51,6 +51,9 @@ internal sealed class MainWindow : Window
|
||||
MinimumSize = new Vector2(MinWidth, MinHeight),
|
||||
MaximumSize = new Vector2(float.MaxValue, float.MaxValue),
|
||||
};
|
||||
// The message list owns its own scroll inside the body child;
|
||||
// the outer window must not show a second scrollbar.
|
||||
Flags = ImGuiWindowFlags.NoScrollbar | ImGuiWindowFlags.NoScrollWithMouse;
|
||||
IsOpen = Plugin.Config.MainWindowOpen;
|
||||
RespectCloseHotkey = false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user