Skip to content

Commit

Permalink
Add font property to various controls;
Browse files Browse the repository at this point in the history
Optimize most components to reflect new wiki;
Bump to 1.2.0;
  • Loading branch information
onepiecefreak3 committed Oct 11, 2024
1 parent 026dc7e commit 9fcdbc3
Show file tree
Hide file tree
Showing 44 changed files with 728 additions and 768 deletions.
11 changes: 8 additions & 3 deletions ImGui.Forms/Controls/ArrowButton.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Numerics;
using ImGui.Forms.Controls.Base;
using ImGui.Forms.Models;
using ImGui.Forms.Models.IO;
Expand All @@ -18,6 +19,8 @@ public class ArrowButton : Component

public ImGuiDir Direction { get; set; }

public Vector2 Padding { get; set; } = new(4, 3);

#endregion

#region Events
Expand All @@ -33,15 +36,15 @@ public ArrowButton(ImGuiDir direction = ImGuiDir.None)

public override Size GetSize()
{
var padding = ImGuiNET.ImGui.GetStyle().FramePadding;

return new Size((int)Math.Ceiling(ButtonSizeX_ + padding.X * 2), (int)Math.Ceiling(ButtonSizeY_ + padding.Y * 2));
return new Size((int)Math.Ceiling(ButtonSizeX_ + Padding.X * 2), (int)Math.Ceiling(ButtonSizeY_ + Padding.Y * 2));
}

protected override void UpdateInternal(Rectangle contentRect)
{
var enabled = Enabled;

ImGuiNET.ImGui.PushStyleVar(ImGuiStyleVar.FramePadding, Padding);

if (!enabled)
{
ImGuiNET.ImGui.PushStyleColor(ImGuiCol.Button, ImGuiNET.ImGui.GetColorU32(ImGuiCol.TextDisabled));
Expand All @@ -54,6 +57,8 @@ protected override void UpdateInternal(Rectangle contentRect)

if (!enabled)
ImGuiNET.ImGui.PopStyleColor(3);

ImGuiNET.ImGui.PopStyleVar();
}

private void OnClicked()
Expand Down
24 changes: 15 additions & 9 deletions ImGui.Forms/Controls/Base/Component.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@

namespace ImGui.Forms.Controls.Base
{
// TODO: Due to executive inconsistency, remove ApplyStyles/RemoveStyles methods and apply styles in Update/Size methods directly
public abstract class Component
{
private bool _tabInactive;

#region Properties

/// <summary>
/// The Id for this component.
/// </summary>
Expand All @@ -40,6 +41,8 @@ public abstract class Component
/// </summary>
public bool ShowBorder { get; set; }

#endregion

#region Events

/// <summary>
Expand Down Expand Up @@ -119,51 +122,54 @@ protected bool IsTabInactiveCore()
/// Gets the finalized width of this component.
/// </summary>
/// <param name="parentWidth">The width of the parent component.</param>
/// <param name="parentHeight">The height of the parent component.</param>
/// <param name="layoutCorrection">A correctional value for layouts.</param>
/// <returns>The finalized width of this component.</returns>
public int GetWidth(int parentWidth, float layoutCorrection = 1f)
public int GetWidth(int parentWidth, int parentHeight, float layoutCorrection = 1f)
{
var width = GetSize().Width;
return width.IsContentAligned ?
GetContentWidth(parentWidth, layoutCorrection) :
GetContentWidth(parentWidth, parentHeight, layoutCorrection) :
GetDimension(width, parentWidth, layoutCorrection);
}

/// <summary>
/// Gets the width of this component, if it's content aligned.
/// </summary>
/// <param name="parentWidth">The width of the parent component.</param>
/// <param name="parentHeight">The height of the parent component.</param>
/// <param name="layoutCorrection">A correctional value for layouts.</param>
/// <returns>The content width of this component.</returns>
protected virtual int GetContentWidth(int parentWidth, float layoutCorrection = 1f) => 0;
protected virtual int GetContentWidth(int parentWidth, int parentHeight, float layoutCorrection = 1f) => 0;

/// <summary>
/// Gets the finalized height of this component.
/// </summary>
/// <param name="parentWidth">The width of the parent component.</param>
/// <param name="parentHeight">The height of the parent component.</param>
/// <param name="layoutCorrection">A correctional value for layouts.</param>
/// <returns>The finalized height of this component.</returns>
public int GetHeight(int parentHeight, float layoutCorrection = 1f)
public int GetHeight(int parentWidth, int parentHeight, float layoutCorrection = 1f)
{
var height = GetSize().Height;
return height.IsContentAligned ?
GetContentHeight(parentHeight, layoutCorrection) :
GetContentHeight(parentWidth, parentHeight, layoutCorrection) :
GetDimension(height, parentHeight, layoutCorrection);
}

/// <summary>
/// Gets the height of this component, if it's content aligned.
/// </summary>
/// <param name="parentWidth">The width of the parent component.</param>
/// <param name="parentHeight">The height of the parent component.</param>
/// <param name="layoutCorrection">A correctional value for layouts.</param>
/// <returns>The content height of this component.</returns>
protected virtual int GetContentHeight(int parentHeight, float layoutCorrection = 1f) => 0;
protected virtual int GetContentHeight(int parentWidth, int parentHeight, float layoutCorrection = 1f) => 0;

/// <summary>
/// Gets the absolute or relative size of the component. Use <see cref="GetWidth"/> or <see cref="GetHeight"/> to get the finalized size.
/// </summary>
/// <returns>The absolute or relative size of this component.</returns>
/// TODO: Make gettable property, default value Size.Content
public abstract Size GetSize();

/// <summary>
Expand Down Expand Up @@ -243,7 +249,7 @@ private void OnDragDrop(DragDropEvent[] events)
/// <param name="maxDimensionValue">The maximum to calculate relative <see cref="SizeValue"/>s against.</param>
/// <param name="correction">The corrective value to calculate relative <see cref="SizeValue"/>s against.</param>
/// <returns></returns>
internal static int GetDimension(SizeValue dimensionValue, int maxDimensionValue, float correction = 1f)
protected internal static int GetDimension(SizeValue dimensionValue, int maxDimensionValue, float correction = 1f)
{
if (dimensionValue.IsAbsolute)
return (int)Math.Min(dimensionValue.Value, maxDimensionValue);
Expand Down
7 changes: 3 additions & 4 deletions ImGui.Forms/Controls/Button.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,14 @@ public class Button : Component

public LocalizedString Text { get; set; }
public LocalizedString Tooltip { get; set; }
public FontResource Font { get; set; }

public KeyCommand KeyAction { get; set; }

public Vector2 Padding { get; set; } = new(2, 2);

public SizeValue Width { get; set; } = SizeValue.Content;

public FontResource Font { get; set; }

#endregion

#region Events
Expand Down Expand Up @@ -58,7 +57,7 @@ protected override void UpdateInternal(Rectangle contentRect)

ApplyStyles(enabled, font);

if ((ImGuiNET.ImGui.Button(EscapeText(), new Vector2(contentRect.Width, contentRect.Height)) || IsKeyDown(KeyAction)) && Enabled)
if ((ImGuiNET.ImGui.Button(EscapeText(), contentRect.Size) || IsKeyDown(KeyAction)) && Enabled)
OnClicked();

if (Tooltip is { IsEmpty: false } && IsHoveredCore())
Expand Down Expand Up @@ -100,7 +99,7 @@ private void RemoveStyles(bool enabled, FontResource font)

protected void OnClicked()
{
Clicked?.Invoke(this, new EventArgs());
Clicked?.Invoke(this, EventArgs.Empty);
}

protected string EscapeText()
Expand Down
32 changes: 23 additions & 9 deletions ImGui.Forms/Controls/CheckBox.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ public class CheckBox : Component
#region Properties

public LocalizedString Text { get; set; }

public LocalizedString Tooltip { get; set; }
public FontResource Font { get; set; }

public bool Checked
{
get=> _checked;
get => _checked;
set
{
_checked = value;
Expand All @@ -43,30 +43,37 @@ public CheckBox(LocalizedString text = default)

public override Size GetSize()
{
ApplyStyles(Enabled, Font);

var size = TextMeasurer.MeasureText(Text);
return new Size((int)(Math.Ceiling(size.X) + 21 + ImGuiNET.ImGui.GetStyle().ItemInnerSpacing.X), (int)Math.Max(Math.Ceiling(size.Y), 21));
var width = (int)(Math.Ceiling(size.X) + 21 + ImGuiNET.ImGui.GetStyle().ItemInnerSpacing.X);
var height = (int)Math.Max(Math.Ceiling(size.Y), 21);

RemoveStyles(Enabled, Font);

return new Size(width, height);
}

protected override void UpdateInternal(Rectangle contentRect)
{
// TODO: Draw checkbox manually, when disabled, to work around checkmark flickering
ImGuiNET.ImGui.SetNextItemWidth(contentRect.Width);

var check = Checked;
var enabled = Enabled;
var font = Font;

ApplyStyles(enabled);
ApplyStyles(enabled, font);

if (IsHovering(contentRect) && !string.IsNullOrEmpty(Tooltip))
ImGuiNET.ImGui.SetTooltip(Tooltip);

if (ImGuiNET.ImGui.Checkbox(Text, ref check) && Enabled)
Checked = check;

RemoveStyles(enabled);
RemoveStyles(enabled, font);
}

private void ApplyStyles(bool enabled)
private void ApplyStyles(bool enabled, FontResource font)
{
if (!enabled)
{
Expand All @@ -75,10 +82,17 @@ private void ApplyStyles(bool enabled)
ImGuiNET.ImGui.PushStyleColor(ImGuiCol.FrameBgActive, ImGuiNET.ImGui.GetColorU32(ImGuiCol.TextDisabled));
ImGuiNET.ImGui.PushStyleColor(ImGuiCol.FrameBgHovered, ImGuiNET.ImGui.GetColorU32(ImGuiCol.TextDisabled));
}

ImFontPtr? fontPtr = font?.GetPointer();
if (fontPtr != null)
ImGuiNET.ImGui.PushFont(fontPtr.Value);
}

private void RemoveStyles(bool enabled)
private void RemoveStyles(bool enabled, FontResource font)
{
if (font?.GetPointer() != null)
ImGuiNET.ImGui.PopFont();

if (!enabled)
ImGuiNET.ImGui.PopStyleColor(4);
}
Expand All @@ -90,7 +104,7 @@ private bool IsHovering(Rectangle contentRect)

private void OnCheckChanged()
{
CheckChanged?.Invoke(this, new EventArgs());
CheckChanged?.Invoke(this, EventArgs.Empty);
}
}
}
44 changes: 36 additions & 8 deletions ImGui.Forms/Controls/ComboBox.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Numerics;
using System.Runtime.InteropServices;
using ImGui.Forms.Controls.Base;
using ImGui.Forms.Localization;
using ImGui.Forms.Models;
using ImGui.Forms.Resources;
using ImGuiNET;
Expand All @@ -15,13 +16,24 @@ namespace ImGui.Forms.Controls
{
public class ComboBox<TItem> : Component
{
private const int ButtonSizeX_ = 11;

private string _input = string.Empty;
private DropDownItem<TItem> _selected;

#region Properties

public IList<ComboBoxItem<TItem>> Items { get; } = new List<ComboBoxItem<TItem>>();
public IList<DropDownItem<TItem>> Items { get; } = new List<DropDownItem<TItem>>();

public ComboBoxItem<TItem> SelectedItem { get; set; }
public DropDownItem<TItem> SelectedItem
{
get => _selected;
set
{
_selected = value;
_input = value.Name;
}
}

public SizeValue Width { get; set; } = SizeValue.Content;

Expand All @@ -46,7 +58,7 @@ public class ComboBox<TItem> : Component
public override Size GetSize()
{
var maxWidth = Items.Select(x => TextMeasurer.GetCurrentLineWidth(x.Name)).DefaultIfEmpty(0).Max() + (int)ImGuiNET.ImGui.GetStyle().ItemInnerSpacing.X * 2;
var arrowWidth = 20;
int arrowWidth = (int)(ButtonSizeX_ + ImGuiNET.ImGui.GetStyle().FramePadding.X * 2);

SizeValue width = Width.IsContentAligned ? maxWidth + arrowWidth : Width;
var height = TextMeasurer.GetCurrentLineHeight() + (int)ImGuiNET.ImGui.GetStyle().ItemInnerSpacing.Y * 2;
Expand All @@ -63,10 +75,13 @@ protected override unsafe void UpdateInternal(Rectangle contentRect)

ImGuiNET.ImGui.PushID(Id);

var arrowWidth = ButtonSizeX_ + ImGuiNET.ImGui.GetStyle().FramePadding.X * 2;
ImGuiNET.ImGui.SetNextItemWidth(contentRect.Width - arrowWidth);

bool isFinal = ImGuiNET.ImGui.InputText("##in", ref _input, MaxCharacters, ImGuiInputTextFlags.CallbackAlways | ImGuiInputTextFlags.EnterReturnsTrue, Propose);
if (isFinal)
{
ComboBoxItem<TItem> selectedItem = Items.FirstOrDefault(i => i.Name == _input);
DropDownItem<TItem> selectedItem = Items.FirstOrDefault(i => i.Name == _input);
if (SelectedItem != selectedItem)
{
SelectedItem = selectedItem;
Expand All @@ -92,9 +107,7 @@ protected override unsafe void UpdateInternal(Rectangle contentRect)
ImGuiNET.ImGui.SetNextWindowSize(size);
if (ImGuiNET.ImGui.BeginPopup("combobox", ImGuiWindowFlags.NoMove))
{
ImGuiNET.ImGui.Text("Select an item");
ImGuiNET.ImGui.Separator();
foreach (ComboBoxItem<TItem> item in Items)
foreach (DropDownItem<TItem> item in Items)
{
if (!ImGuiNET.ImGui.Selectable(item.Name))
continue;
Expand Down Expand Up @@ -159,7 +172,7 @@ private unsafe int Propose(ImGuiInputTextCallbackData* data)
int prevDiff = -1;
string? itemName = null;

Check warning on line 173 in ImGui.Forms/Controls/ComboBox.cs

View workflow job for this annotation

GitHub Actions / build

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

foreach (ComboBoxItem<TItem> item in Items)
foreach (DropDownItem<TItem> item in Items)
{
if (!Identical(bufferString, item.Name, out int diff))
continue;
Expand Down Expand Up @@ -215,4 +228,19 @@ private bool Identical(string buf, string item, out int diff)
return true;
}
}

public class DropDownItem<TItem>
{
public TItem Content { get; }

public LocalizedString Name { get; }

public DropDownItem(TItem content, LocalizedString name = default)
{
Content = content;
Name = name.IsEmpty ? (LocalizedString)content.ToString() : name;
}

public static implicit operator DropDownItem<TItem>(TItem o) => new(o);
}
}
Loading

0 comments on commit 9fcdbc3

Please sign in to comment.