Support drag & drop to redorder lists
This commit is contained in:
parent
44f44bce8a
commit
9d7f2a9b56
@ -1,6 +1,6 @@
|
|||||||
<Project Sdk="Dalamud.NET.Sdk/9.0.2">
|
<Project Sdk="Dalamud.NET.Sdk/9.0.2">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Version>5.1</Version>
|
<Version>5.2</Version>
|
||||||
<OutputPath>dist</OutputPath>
|
<OutputPath>dist</OutputPath>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
@ -125,7 +125,6 @@ internal sealed class Configuration : IPluginConfiguration
|
|||||||
public bool ShowVentureListContents { get; set; } = true;
|
public bool ShowVentureListContents { get; set; } = true;
|
||||||
public bool CheckGatheredItemsPerCharacter { get; set; }
|
public bool CheckGatheredItemsPerCharacter { get; set; }
|
||||||
public bool OnlyShowMissingGatheredItems { get; set; }
|
public bool OnlyShowMissingGatheredItems { get; set; }
|
||||||
public bool WrapAroundWhenReordering { get; set; }
|
|
||||||
public bool ShowAssignmentChatMessages { get; set; } = true;
|
public bool ShowAssignmentChatMessages { get; set; } = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -57,15 +57,5 @@ internal sealed class MiscTab : ITab
|
|||||||
_configuration.ConfigUiOptions.ShowVentureListContents = showContents;
|
_configuration.ConfigUiOptions.ShowVentureListContents = showContents;
|
||||||
_configWindow.ShouldSave();
|
_configWindow.ShouldSave();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wrapAroundWhenReordering = _configuration.ConfigUiOptions.WrapAroundWhenReordering;
|
|
||||||
if (ImGui.Checkbox("Allow sorting with up/down arrows to wrap around", ref wrapAroundWhenReordering))
|
|
||||||
{
|
|
||||||
_configuration.ConfigUiOptions.WrapAroundWhenReordering = wrapAroundWhenReordering;
|
|
||||||
_configWindow.ShouldSave();
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGuiComponents.HelpMarker(
|
|
||||||
"When enabled:\n- Clicking the Up-Arrow for the first item in a list, that item will be moved to the bottom.\n- Clicking the Down-Arrow for the last item in the list, that item will be moved to the top.");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Numerics;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using ARControl.External;
|
using ARControl.External;
|
||||||
@ -15,7 +16,6 @@ using Dalamud.Interface.Utility.Raii;
|
|||||||
using Dalamud.Plugin.Services;
|
using Dalamud.Plugin.Services;
|
||||||
using ECommons;
|
using ECommons;
|
||||||
using ECommons.ImGuiMethods;
|
using ECommons.ImGuiMethods;
|
||||||
using FFXIVClientStructs.FFXIV.Common.Math;
|
|
||||||
using ImGuiNET;
|
using ImGuiNET;
|
||||||
using LLib;
|
using LLib;
|
||||||
|
|
||||||
@ -37,7 +37,9 @@ internal sealed class VentureListTab : ITab
|
|||||||
private readonly IconCache _iconCache;
|
private readonly IconCache _iconCache;
|
||||||
private readonly DiscardHelperIpc _discardHelperIpc;
|
private readonly DiscardHelperIpc _discardHelperIpc;
|
||||||
private readonly IPluginLog _pluginLog;
|
private readonly IPluginLog _pluginLog;
|
||||||
|
|
||||||
private string _searchString = string.Empty;
|
private string _searchString = string.Empty;
|
||||||
|
private (Guid, Guid)? _draggedItem;
|
||||||
|
|
||||||
private readonly Dictionary<Guid, TemporaryConfig> _currentEditPopups = new();
|
private readonly Dictionary<Guid, TemporaryConfig> _currentEditPopups = new();
|
||||||
|
|
||||||
@ -189,9 +191,14 @@ internal sealed class VentureListTab : ITab
|
|||||||
Configuration.QueuedItem? itemToAdd = null;
|
Configuration.QueuedItem? itemToAdd = null;
|
||||||
int indexToAdd = 0;
|
int indexToAdd = 0;
|
||||||
|
|
||||||
var dragDropData = _configWindow.CalculateDragDropData(list.Items.Count);
|
float width = ImGui.GetContentRegionAvail().X;
|
||||||
|
List<(Vector2 TopLeft, Vector2 BottomRight)> itemPositions = [];
|
||||||
|
|
||||||
for (int i = 0; i < list.Items.Count; ++i)
|
for (int i = 0; i < list.Items.Count; ++i)
|
||||||
{
|
{
|
||||||
|
Vector2 topLeft = ImGui.GetCursorScreenPos() +
|
||||||
|
new Vector2(-_configWindow.MainIndentSize, -ImGui.GetStyle().ItemSpacing.Y / 2);
|
||||||
|
|
||||||
var item = list.Items[i];
|
var item = list.Items[i];
|
||||||
ImGui.PushID($"QueueItem{item.InternalId}");
|
ImGui.PushID($"QueueItem{item.InternalId}");
|
||||||
var ventures = _gameCache.Ventures.Where(x => x.ItemId == item.ItemId).ToList();
|
var ventures = _gameCache.Ventures.Where(x => x.ItemId == item.ItemId).ToList();
|
||||||
@ -238,18 +245,16 @@ internal sealed class VentureListTab : ITab
|
|||||||
ImGui.GetStyle().ItemSpacing.X);
|
ImGui.GetStyle().ItemSpacing.X);
|
||||||
ImGui.PopFont();
|
ImGui.PopFont();
|
||||||
|
|
||||||
|
if (_draggedItem != null && _draggedItem.Value.Item1 == list.Id && _draggedItem.Value.Item2 == item.InternalId)
|
||||||
|
{
|
||||||
|
ImGuiComponents.IconButton("##Move", FontAwesomeIcon.ArrowsUpDown,
|
||||||
|
ImGui.ColorConvertU32ToFloat4(ImGui.GetColorU32(ImGuiCol.ButtonActive)));
|
||||||
|
}
|
||||||
|
else
|
||||||
ImGuiComponents.IconButton("##Move", FontAwesomeIcon.ArrowsUpDown);
|
ImGuiComponents.IconButton("##Move", FontAwesomeIcon.ArrowsUpDown);
|
||||||
|
|
||||||
if (ImGui.IsItemActive() && ImGui.IsMouseDragging(ImGuiMouseButton.Left))
|
if (_draggedItem == null && ImGui.IsItemActive() && ImGui.IsMouseDragging(ImGuiMouseButton.Left))
|
||||||
{
|
_draggedItem = (list.Id, item.InternalId);
|
||||||
int newIndex = dragDropData.ItemPositions.FindIndex(x =>
|
|
||||||
ImGui.IsMouseHoveringRect(x.TopLeft, x.BottomRight, true));
|
|
||||||
if (newIndex != i && newIndex >= 0)
|
|
||||||
{
|
|
||||||
indexToAdd = newIndex;
|
|
||||||
itemToAdd = item;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
}
|
}
|
||||||
@ -268,6 +273,31 @@ internal sealed class VentureListTab : ITab
|
|||||||
itemToRemove = item;
|
itemToRemove = item;
|
||||||
|
|
||||||
ImGui.PopID();
|
ImGui.PopID();
|
||||||
|
|
||||||
|
Vector2 bottomRight = new Vector2(topLeft.X + width + _configWindow.MainIndentSize,
|
||||||
|
ImGui.GetCursorScreenPos().Y - ImGui.GetStyle().ItemSpacing.Y + 2);
|
||||||
|
//ImGui.GetWindowDrawList().AddRect(topLeft, bottomRight, ImGui.GetColorU32(i % 2 == 0 ? ImGuiColors.DalamudRed : ImGuiColors.HealerGreen));
|
||||||
|
itemPositions.Add((topLeft, bottomRight));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ImGui.IsMouseDragging(ImGuiMouseButton.Left))
|
||||||
|
_draggedItem = null;
|
||||||
|
else if (_draggedItem != null && _draggedItem.Value.Item1 == list.Id)
|
||||||
|
{
|
||||||
|
var draggedItem = list.Items.Single(x => x.InternalId == _draggedItem.Value.Item2);
|
||||||
|
int oldIndex = list.Items.IndexOf(draggedItem);
|
||||||
|
|
||||||
|
var (topLeft, bottomRight) = itemPositions[oldIndex];
|
||||||
|
if (!itemsToDiscard.Contains(draggedItem.ItemId))
|
||||||
|
topLeft += new Vector2(_configWindow.MainIndentSize, 0);
|
||||||
|
ImGui.GetWindowDrawList().AddRect(topLeft, bottomRight, ImGui.GetColorU32(ImGuiColors.DalamudGrey), 3f, ImDrawFlags.RoundCornersAll);
|
||||||
|
|
||||||
|
int newIndex = itemPositions.IndexOf(x => ImGui.IsMouseHoveringRect(x.TopLeft, x.BottomRight, true));
|
||||||
|
if (newIndex >= 0 && oldIndex != newIndex)
|
||||||
|
{
|
||||||
|
itemToAdd = list.Items.Single(x => x.InternalId == _draggedItem.Value.Item2);
|
||||||
|
indexToAdd = newIndex;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (itemToRemove != null)
|
if (itemToRemove != null)
|
||||||
|
@ -1,10 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using System.Text;
|
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
using ARControl.External;
|
using ARControl.External;
|
||||||
using ARControl.GameData;
|
using ARControl.GameData;
|
||||||
using ARControl.Windows.Config;
|
using ARControl.Windows.Config;
|
||||||
@ -12,13 +9,10 @@ using Dalamud.Game.Text;
|
|||||||
using Dalamud.Interface;
|
using Dalamud.Interface;
|
||||||
using Dalamud.Interface.Colors;
|
using Dalamud.Interface.Colors;
|
||||||
using Dalamud.Interface.Components;
|
using Dalamud.Interface.Components;
|
||||||
using Dalamud.Interface.Textures.TextureWraps;
|
|
||||||
using Dalamud.Interface.Utility;
|
|
||||||
using Dalamud.Interface.Utility.Raii;
|
using Dalamud.Interface.Utility.Raii;
|
||||||
using Dalamud.Plugin;
|
using Dalamud.Plugin;
|
||||||
using Dalamud.Plugin.Services;
|
using Dalamud.Plugin.Services;
|
||||||
using ECommons;
|
using ECommons;
|
||||||
using ECommons.ImGuiMethods;
|
|
||||||
using ImGuiNET;
|
using ImGuiNET;
|
||||||
using LLib;
|
using LLib;
|
||||||
using LLib.ImGui;
|
using LLib.ImGui;
|
||||||
@ -37,6 +31,7 @@ internal sealed class ConfigWindow : LWindow
|
|||||||
private readonly List<ITab> _tabs;
|
private readonly List<ITab> _tabs;
|
||||||
|
|
||||||
private bool _shouldSave;
|
private bool _shouldSave;
|
||||||
|
private (string, int)? _draggedItem;
|
||||||
|
|
||||||
public ConfigWindow(
|
public ConfigWindow(
|
||||||
IDalamudPluginInterface pluginInterface,
|
IDalamudPluginInterface pluginInterface,
|
||||||
@ -113,18 +108,24 @@ internal sealed class ConfigWindow : LWindow
|
|||||||
int? itemToRemove = null;
|
int? itemToRemove = null;
|
||||||
int? itemToAdd = null;
|
int? itemToAdd = null;
|
||||||
int indexToAdd = 0;
|
int indexToAdd = 0;
|
||||||
|
|
||||||
|
float width = ImGui.GetContentRegionAvail().X;
|
||||||
|
List<(Vector2 TopLeft, Vector2 BottomRight)> itemPositions = [];
|
||||||
|
|
||||||
for (int i = 0; i < selectedLists.Count; ++i)
|
for (int i = 0; i < selectedLists.Count; ++i)
|
||||||
{
|
{
|
||||||
|
Vector2 topLeft = ImGui.GetCursorScreenPos() +
|
||||||
|
new Vector2(-MainIndentSize, -ImGui.GetStyle().ItemSpacing.Y / 2);
|
||||||
|
|
||||||
ImGui.PushID($"##{id}_Item{i}");
|
ImGui.PushID($"##{id}_Item{i}");
|
||||||
var listId = selectedLists[i];
|
var listId = selectedLists[i];
|
||||||
var listIndex = itemLists.FindIndex(x => x.Id == listId);
|
var listIndex = itemLists.FindIndex(x => x.Id == listId);
|
||||||
|
|
||||||
ImGui.PushFont(UiBuilder.IconFont);
|
ImGui.PushFont(UiBuilder.IconFont);
|
||||||
ImGui.SetNextItemWidth(ImGui.GetContentRegionAvail().X -
|
ImGui.SetNextItemWidth(ImGui.GetContentRegionAvail().X -
|
||||||
ImGui.CalcTextSize(FontAwesomeIcon.ArrowUp.ToIconString()).X -
|
ImGui.CalcTextSize(FontAwesomeIcon.ArrowsUpDown.ToIconString()).X -
|
||||||
ImGui.CalcTextSize(FontAwesomeIcon.ArrowDown.ToIconString()).X -
|
|
||||||
ImGui.CalcTextSize(FontAwesomeIcon.Times.ToIconString()).X -
|
ImGui.CalcTextSize(FontAwesomeIcon.Times.ToIconString()).X -
|
||||||
ImGui.GetStyle().FramePadding.X * 6 -
|
ImGui.GetStyle().FramePadding.X * 4 -
|
||||||
ImGui.GetStyle().ItemSpacing.X * 2);
|
ImGui.GetStyle().ItemSpacing.X * 2);
|
||||||
ImGui.PopFont();
|
ImGui.PopFont();
|
||||||
if (ImGui.Combo("", ref listIndex, itemLists.Select(x => x.Name).ToArray(), itemLists.Count))
|
if (ImGui.Combo("", ref listIndex, itemLists.Select(x => x.Name).ToArray(), itemLists.Count))
|
||||||
@ -135,33 +136,19 @@ internal sealed class ConfigWindow : LWindow
|
|||||||
|
|
||||||
if (selectedLists.Count > 1)
|
if (selectedLists.Count > 1)
|
||||||
{
|
{
|
||||||
bool wrap = _configuration.ConfigUiOptions.WrapAroundWhenReordering;
|
|
||||||
|
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
ImGui.BeginDisabled(i == 0 && !wrap);
|
|
||||||
if (ImGuiComponents.IconButton($"##Up{i}", FontAwesomeIcon.ArrowUp))
|
if (_draggedItem != null && _draggedItem.Value.Item1 == id && _draggedItem.Value.Item2 == i)
|
||||||
{
|
{
|
||||||
itemToAdd = i;
|
ImGuiComponents.IconButton("##Move", FontAwesomeIcon.ArrowsUpDown,
|
||||||
if (i > 0)
|
ImGui.ColorConvertU32ToFloat4(ImGui.GetColorU32(ImGuiCol.ButtonActive)));
|
||||||
indexToAdd = i - 1;
|
|
||||||
else
|
|
||||||
indexToAdd = selectedLists.Count - 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui.EndDisabled();
|
|
||||||
|
|
||||||
ImGui.SameLine(0, 0);
|
|
||||||
ImGui.BeginDisabled(i == selectedLists.Count - 1 && !wrap);
|
|
||||||
if (ImGuiComponents.IconButton($"##Down{i}", FontAwesomeIcon.ArrowDown))
|
|
||||||
{
|
|
||||||
itemToAdd = i;
|
|
||||||
if (i < selectedLists.Count - 1)
|
|
||||||
indexToAdd = i + 1;
|
|
||||||
else
|
else
|
||||||
indexToAdd = 0;
|
ImGuiComponents.IconButton("##Move", FontAwesomeIcon.ArrowsUpDown);
|
||||||
}
|
|
||||||
|
if (_draggedItem == null && ImGui.IsItemActive() && ImGui.IsMouseDragging(ImGuiMouseButton.Left))
|
||||||
|
_draggedItem = (id, i);
|
||||||
|
|
||||||
ImGui.EndDisabled();
|
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -199,6 +186,32 @@ internal sealed class ConfigWindow : LWindow
|
|||||||
}
|
}
|
||||||
|
|
||||||
ImGui.PopID();
|
ImGui.PopID();
|
||||||
|
|
||||||
|
Vector2 bottomRight = new Vector2(topLeft.X + width + MainIndentSize,
|
||||||
|
ImGui.GetCursorScreenPos().Y - ImGui.GetStyle().ItemSpacing.Y + 2);
|
||||||
|
//ImGui.GetWindowDrawList().AddRect(topLeft, bottomRight, ImGui.GetColorU32(i % 2 == 0 ? ImGuiColors.DalamudRed : ImGuiColors.HealerGreen));
|
||||||
|
itemPositions.Add((topLeft, bottomRight));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ImGui.IsMouseDragging(ImGuiMouseButton.Left))
|
||||||
|
_draggedItem = null;
|
||||||
|
else if (_draggedItem != null && _draggedItem.Value.Item1 == id)
|
||||||
|
{
|
||||||
|
int oldIndex = _draggedItem.Value.Item2;
|
||||||
|
var draggedItem = selectedLists[oldIndex];
|
||||||
|
|
||||||
|
var (topLeft, bottomRight) = itemPositions[oldIndex];
|
||||||
|
topLeft += new Vector2(MainIndentSize, 0);
|
||||||
|
ImGui.GetWindowDrawList().AddRect(topLeft, bottomRight, ImGui.GetColorU32(ImGuiColors.DalamudGrey), 3f, ImDrawFlags.RoundCornersAll);
|
||||||
|
|
||||||
|
int newIndex = itemPositions.IndexOf(x => ImGui.IsMouseHoveringRect(x.TopLeft, x.BottomRight, true));
|
||||||
|
if (newIndex >= 0 && oldIndex != newIndex)
|
||||||
|
{
|
||||||
|
itemToAdd = _draggedItem.Value.Item2;
|
||||||
|
indexToAdd = newIndex;
|
||||||
|
|
||||||
|
_draggedItem = (_draggedItem.Value.Item1, newIndex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (itemToRemove != null)
|
if (itemToRemove != null)
|
||||||
@ -246,29 +259,4 @@ internal sealed class ConfigWindow : LWindow
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void ShouldSave() => _shouldSave = true;
|
public void ShouldSave() => _shouldSave = true;
|
||||||
|
|
||||||
internal DragDropData CalculateDragDropData(int itemCount)
|
|
||||||
{
|
|
||||||
float yDelta = ImGui.GetFrameHeight() + ImGui.GetStyle().ItemSpacing.Y;
|
|
||||||
var firstCursorPos = ImGui.GetCursorScreenPos() +
|
|
||||||
new Vector2(-MainIndentSize, -ImGui.GetStyle().ItemSpacing.Y / 2);
|
|
||||||
var lastCursorPos = new Vector2(
|
|
||||||
firstCursorPos.X + MainIndentSize + ImGui.GetContentRegionAvail().X,
|
|
||||||
firstCursorPos.Y + yDelta * itemCount);
|
|
||||||
|
|
||||||
List<(Vector2 TopLeft, Vector2 BottomRight)> itemPositions = [];
|
|
||||||
for (int i = 0; i < itemCount; ++i)
|
|
||||||
{
|
|
||||||
Vector2 left = firstCursorPos;
|
|
||||||
Vector2 right = lastCursorPos with { Y = firstCursorPos.Y + yDelta - 1 };
|
|
||||||
itemPositions.Add((left, right));
|
|
||||||
|
|
||||||
firstCursorPos.Y += yDelta;
|
|
||||||
lastCursorPos.Y += yDelta;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new DragDropData(itemPositions);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal sealed record DragDropData(List<(Vector2 TopLeft, Vector2 BottomRight)> ItemPositions);
|
|
||||||
}
|
}
|
||||||
|
2
LLib
2
LLib
@ -1 +1 @@
|
|||||||
Subproject commit 93fac6efb01a1272192d929fd863328271512ea4
|
Subproject commit fa3d19dde18bfd00237e66ea1eb48a60caa01b8a
|
Loading…
Reference in New Issue
Block a user