Initial commit: AetherBags + KamiToolKit for FC Gitea
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,109 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using KamiToolKit.Nodes;
|
||||
using Lumina.Text.ReadOnly;
|
||||
|
||||
namespace KamiToolKit.Premade.Widgets;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a search element that has a searchbar, and a dropdown for reordering elements.
|
||||
/// </summary>
|
||||
public unsafe class SearchWidget : SimpleComponentNode {
|
||||
public readonly TextInputNode InputNode;
|
||||
public readonly TextDropDownNode SortOrderDropDown;
|
||||
public readonly CircleButtonNode ReverseButtonNode;
|
||||
|
||||
public bool IsReversed { get; private set; }
|
||||
public string SearchText { get; private set; } = string.Empty;
|
||||
public string SortMode { get; private set; } = string.Empty;
|
||||
|
||||
public delegate void SearchUpdated(string searchString);
|
||||
public delegate void SortUpdated(string sortingString, bool reversed);
|
||||
|
||||
public SearchWidget() {
|
||||
InputNode = new TextInputNode {
|
||||
PlaceholderString = "Search . . .",
|
||||
String = SearchText,
|
||||
OnInputReceived = SearchTextChanged,
|
||||
};
|
||||
InputNode.AttachNode(this);
|
||||
|
||||
SortOrderDropDown = new TextDropDownNode {
|
||||
MaxListOptions = 0,
|
||||
Options = [],
|
||||
IsVisible = false,
|
||||
SelectedOption = SortMode == string.Empty ? null : SortMode,
|
||||
OnOptionSelected = DropDownChanged,
|
||||
};
|
||||
SortOrderDropDown.AttachNode(this);
|
||||
|
||||
ReverseButtonNode = new CircleButtonNode {
|
||||
Icon = ButtonIcon.Sort,
|
||||
OnClick = OnReverseButtonClicked,
|
||||
TextTooltip = "Reverse Sort Direction",
|
||||
IsVisible = false,
|
||||
};
|
||||
ReverseButtonNode.AttachNode(this);
|
||||
|
||||
ResNode->SetHeight(38);
|
||||
}
|
||||
|
||||
public required SortUpdated OnSortOrderChanged { get; set; }
|
||||
|
||||
private void OnReverseButtonClicked() {
|
||||
IsReversed = !IsReversed;
|
||||
OnSortOrderChanged(SortMode, IsReversed);
|
||||
}
|
||||
|
||||
private void DropDownChanged(string newOption) {
|
||||
SortMode = newOption;
|
||||
OnSortOrderChanged(SortMode, IsReversed);
|
||||
}
|
||||
|
||||
public required SearchUpdated OnSearchUpdated { get; set; }
|
||||
|
||||
private void SearchTextChanged(ReadOnlySeString newSearchString) {
|
||||
SearchText = newSearchString.ToString();
|
||||
OnSearchUpdated(SearchText);
|
||||
}
|
||||
|
||||
protected override void OnSizeChanged() {
|
||||
base.OnSizeChanged();
|
||||
|
||||
InputNode.Size = new Vector2(Width - 10.0f, 28.0f);
|
||||
InputNode.Position = new Vector2(5.0f, 5.0f);
|
||||
|
||||
ReverseButtonNode.Size = new Vector2(28.0f, 28.0f);
|
||||
ReverseButtonNode.Position = new Vector2(Width - 5.0f - ReverseButtonNode.Width, InputNode.Height + 8.0f);
|
||||
|
||||
SortOrderDropDown.Size = new Vector2(Width - 5.0f - ReverseButtonNode.Width - 5.0f - 5.0f, 28.0f);
|
||||
SortOrderDropDown.Position = new Vector2(5.0f, InputNode.Height + 8.0f);
|
||||
}
|
||||
|
||||
// Disallow modifying the height of this element.
|
||||
public override float Height { get => base.Height; set { } }
|
||||
|
||||
public int MaxDropdownOptions {
|
||||
get => SortOrderDropDown.MaxListOptions;
|
||||
set => SortOrderDropDown.MaxListOptions = value;
|
||||
}
|
||||
|
||||
public List<string> SortingOptions {
|
||||
get => SortOrderDropDown.Options ?? [];
|
||||
set {
|
||||
SortOrderDropDown.Options = value;
|
||||
SortOrderDropDown.MaxListOptions = value.Count / 2 + 1;
|
||||
SortOrderDropDown.IsVisible = value.Count > 0;
|
||||
ReverseButtonNode.IsVisible = value.Count > 0;
|
||||
|
||||
ResNode->SetHeight((ushort)(value.Count > 0 ? 69 : 38));
|
||||
|
||||
if (SortingOptions.Count > 0) {
|
||||
SortMode = value.First();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public string? SelectedOption => SortOrderDropDown.SelectedOption;
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
using System;
|
||||
using System.Numerics;
|
||||
using FFXIVClientStructs.FFXIV.Component.GUI;
|
||||
using KamiToolKit.Classes;
|
||||
using KamiToolKit.Nodes;
|
||||
|
||||
namespace KamiToolKit.Premade.Widgets;
|
||||
|
||||
public class Vector2EditWidget : SimpleComponentNode {
|
||||
public readonly GridNode GridNode;
|
||||
public readonly TextNode WidthTextNode;
|
||||
public readonly TextNode HeightTextNode;
|
||||
public readonly NumericInputNode WidthInputNode;
|
||||
public readonly NumericInputNode HeightInputNode;
|
||||
|
||||
public Vector2EditWidget() {
|
||||
GridNode = new GridNode {
|
||||
GridSize = new GridSize(2, 2),
|
||||
};
|
||||
GridNode.AttachNode(this);
|
||||
|
||||
WidthTextNode = new TextNode {
|
||||
AlignmentType = AlignmentType.Bottom,
|
||||
FontType = FontType.Axis,
|
||||
FontSize = 14,
|
||||
LineSpacing = 14,
|
||||
TextColor = ColorHelper.GetColor(8),
|
||||
TextOutlineColor = ColorHelper.GetColor(7),
|
||||
TextFlags = TextFlags.Edge | TextFlags.AutoAdjustNodeSize,
|
||||
String = XLabel ?? "Width",
|
||||
};
|
||||
WidthTextNode.AttachNode(GridNode[0, 0]);
|
||||
|
||||
HeightTextNode = new TextNode {
|
||||
AlignmentType = AlignmentType.Bottom,
|
||||
FontType = FontType.Axis,
|
||||
FontSize = 14,
|
||||
LineSpacing = 14,
|
||||
TextColor = ColorHelper.GetColor(8),
|
||||
TextOutlineColor = ColorHelper.GetColor(7),
|
||||
TextFlags = TextFlags.Edge | TextFlags.AutoAdjustNodeSize,
|
||||
String = YLabel ?? "Height",
|
||||
};
|
||||
HeightTextNode.AttachNode(GridNode[1, 0]);
|
||||
|
||||
WidthInputNode = new NumericInputNode {
|
||||
Position = new Vector2(2.0f, 2.0f),
|
||||
OnValueUpdate = OnXValueUpdated,
|
||||
};
|
||||
WidthInputNode.AttachNode(GridNode[0, 1]);
|
||||
|
||||
HeightInputNode = new NumericInputNode {
|
||||
Position = new Vector2(2.0f, 2.0f),
|
||||
OnValueUpdate = OnYValueUpdated,
|
||||
};
|
||||
HeightInputNode.AttachNode(GridNode[1, 1]);
|
||||
}
|
||||
|
||||
protected override void OnSizeChanged() {
|
||||
base.OnSizeChanged();
|
||||
|
||||
GridNode.Size = Size;
|
||||
|
||||
WidthTextNode.Size = GridNode[0, 0].Size;
|
||||
HeightTextNode.Size = GridNode[1, 0].Size;
|
||||
|
||||
WidthInputNode.Size = GridNode[0, 1].Size;
|
||||
HeightInputNode.Size = GridNode[1, 1].Size;
|
||||
}
|
||||
|
||||
private void OnXValueUpdated(int newValue) {
|
||||
Value = Value with { X = newValue };
|
||||
OnValueChanged?.Invoke(Value);
|
||||
}
|
||||
|
||||
private void OnYValueUpdated(int newValue) {
|
||||
Value = Value with { Y = newValue };
|
||||
OnValueChanged?.Invoke(Value);
|
||||
}
|
||||
|
||||
public Vector2 Value {
|
||||
get;
|
||||
set {
|
||||
field = value;
|
||||
WidthInputNode.Value = (int) value.X;
|
||||
HeightInputNode.Value = (int) value.Y;
|
||||
}
|
||||
}
|
||||
|
||||
public Action<Vector2>? OnValueChanged { get; set; }
|
||||
|
||||
public string? XLabel { get; set; }
|
||||
public string? YLabel { get; set; }
|
||||
}
|
||||
Reference in New Issue
Block a user