Penumbra/Penumbra/UI/ConfigWindow.ModPanel.Header.cs

209 lines
No EOL
7.9 KiB
C#

using System;
using System.Diagnostics;
using System.Numerics;
using Dalamud.Interface;
using Dalamud.Interface.GameFonts;
using ImGuiNET;
using OtterGui;
using OtterGui.Raii;
using Penumbra.UI.Classes;
namespace Penumbra.UI;
public partial class ConfigWindow
{
private partial class ModPanel
{
// We use a big, nice game font for the title.
private readonly GameFontHandle _nameFont =
Dalamud.PluginInterface.UiBuilder.GetGameFontHandle( new GameFontStyle( GameFontFamilyAndSize.Jupiter23 ) );
// Header data.
private string _modName = string.Empty;
private string _modAuthor = string.Empty;
private string _modVersion = string.Empty;
private string _modWebsite = string.Empty;
private string _modWebsiteButton = string.Empty;
private bool _websiteValid;
private float _modNameWidth;
private float _modAuthorWidth;
private float _modVersionWidth;
private float _modWebsiteButtonWidth;
private float _secondRowWidth;
// Draw the header for the current mod,
// consisting of its name, version, author and website, if they exist.
private void DrawModHeader()
{
var offset = DrawModName();
DrawVersion( offset );
DrawSecondRow( offset );
}
// Draw the mod name in the game font with a 2px border, centered,
// with at least the width of the version space to each side.
private float DrawModName()
{
var decidingWidth = Math.Max( _secondRowWidth, ImGui.GetWindowWidth() );
var offsetWidth = ( decidingWidth - _modNameWidth ) / 2;
var offsetVersion = _modVersion.Length > 0
? _modVersionWidth + ImGui.GetStyle().ItemSpacing.X + ImGui.GetStyle().WindowPadding.X
: 0;
var offset = Math.Max( offsetWidth, offsetVersion );
if( offset > 0 )
{
ImGui.SetCursorPosX( offset );
}
using var color = ImRaii.PushColor( ImGuiCol.Border, Colors.MetaInfoText );
using var style = ImRaii.PushStyle( ImGuiStyleVar.FrameBorderSize, 2 * ImGuiHelpers.GlobalScale );
using var font = ImRaii.PushFont( _nameFont.ImFont, _nameFont.Available );
ImGuiUtil.DrawTextButton( _modName, Vector2.Zero, 0 );
return offset;
}
// Draw the version in the top-right corner.
private void DrawVersion( float offset )
{
var oldPos = ImGui.GetCursorPos();
ImGui.SetCursorPos( new Vector2( 2 * offset + _modNameWidth - _modVersionWidth - ImGui.GetStyle().WindowPadding.X,
ImGui.GetStyle().FramePadding.Y ) );
ImGuiUtil.TextColored( Colors.MetaInfoText, _modVersion );
ImGui.SetCursorPos( oldPos );
}
// Draw author and website if they exist. The website is a button if it is valid.
// Usually, author begins at the left boundary of the name,
// and website ends at the right boundary of the name.
// If their combined width is larger than the name, they are combined-centered.
private void DrawSecondRow( float offset )
{
if( _modAuthor.Length == 0 )
{
if( _modWebsiteButton.Length == 0 )
{
ImGui.NewLine();
return;
}
offset += ( _modNameWidth - _modWebsiteButtonWidth ) / 2;
ImGui.SetCursorPosX( offset );
DrawWebsite();
}
else if( _modWebsiteButton.Length == 0 )
{
offset += ( _modNameWidth - _modAuthorWidth ) / 2;
ImGui.SetCursorPosX( offset );
DrawAuthor();
}
else if( _secondRowWidth < _modNameWidth )
{
ImGui.SetCursorPosX( offset );
DrawAuthor();
ImGui.SameLine( offset + _modNameWidth - _modWebsiteButtonWidth );
DrawWebsite();
}
else
{
offset -= ( _secondRowWidth - _modNameWidth ) / 2;
if( offset > 0 )
{
ImGui.SetCursorPosX( offset );
}
DrawAuthor();
ImGui.SameLine();
DrawWebsite();
}
}
// Draw the author text.
private void DrawAuthor()
{
using var style = ImRaii.PushStyle( ImGuiStyleVar.ItemSpacing, Vector2.Zero );
ImGuiUtil.TextColored( Colors.MetaInfoText, "by " );
ImGui.SameLine();
style.Pop();
ImGui.TextUnformatted( _mod.Author );
}
// Draw either a website button if the source is a valid website address,
// or a source text if it is not.
private void DrawWebsite()
{
if( _websiteValid )
{
if( ImGui.SmallButton( _modWebsiteButton ) )
{
try
{
var process = new ProcessStartInfo( _modWebsite )
{
UseShellExecute = true,
};
Process.Start( process );
}
catch
{
// ignored
}
}
ImGuiUtil.HoverTooltip( _modWebsite );
}
else
{
using var style = ImRaii.PushStyle( ImGuiStyleVar.ItemSpacing, Vector2.Zero );
ImGuiUtil.TextColored( Colors.MetaInfoText, "from " );
ImGui.SameLine();
style.Pop();
ImGui.TextUnformatted( _mod.Website );
}
}
// Update all mod header data. Should someone change frame padding or item spacing,
// or his default font, this will break, but he will just have to select a different mod to restore.
private void UpdateModData()
{
// Name
var name = $" {_mod.Name} ";
if( name != _modName )
{
using var font = ImRaii.PushFont( _nameFont.ImFont, _nameFont.Available );
_modName = name;
_modNameWidth = ImGui.CalcTextSize( name ).X + 2 * ( ImGui.GetStyle().FramePadding.X + 2 * ImGuiHelpers.GlobalScale );
}
// Author
var author = _mod.Author.IsEmpty ? string.Empty : $"by {_mod.Author}";
if( author != _modAuthor )
{
_modAuthor = author;
_modAuthorWidth = ImGui.CalcTextSize( author ).X;
_secondRowWidth = _modAuthorWidth + _modWebsiteButtonWidth + ImGui.GetStyle().ItemSpacing.X;
}
// Version
var version = _mod.Version.Length > 0 ? $"({_mod.Version})" : string.Empty;
if( version != _modVersion )
{
_modVersion = version;
_modVersionWidth = ImGui.CalcTextSize( version ).X;
}
// Website
if( _modWebsite != _mod.Website )
{
_modWebsite = _mod.Website;
_websiteValid = Uri.TryCreate( _modWebsite, UriKind.Absolute, out var uriResult )
&& ( uriResult.Scheme == Uri.UriSchemeHttps || uriResult.Scheme == Uri.UriSchemeHttp );
_modWebsiteButton = _websiteValid ? "Open Website" : _modWebsite.Length == 0 ? string.Empty : $"from {_modWebsite}";
_modWebsiteButtonWidth = _websiteValid
? ImGui.CalcTextSize( _modWebsiteButton ).X + 2 * ImGui.GetStyle().FramePadding.X
: ImGui.CalcTextSize( _modWebsiteButton ).X;
_secondRowWidth = _modAuthorWidth + _modWebsiteButtonWidth + ImGui.GetStyle().ItemSpacing.X;
}
}
}
}