mirror of
https://github.com/BentoBoxWorld/Level.git
synced 2024-11-22 10:36:08 +01:00
Implement feature that allows to sort items in detail panel. (#259)
Apparently, because it is 2 years old request, it got in a state -> implement or drop. Fixes #192
This commit is contained in:
parent
fcf6e76599
commit
4948689fe8
@ -63,6 +63,7 @@ public class DetailsPanel
|
||||
|
||||
// By default no-filters are active.
|
||||
this.activeTab = Tab.ALL_BLOCKS;
|
||||
this.activeFilter = Filter.NAME;
|
||||
this.materialCountList = new ArrayList<>(Material.values().length);
|
||||
|
||||
this.updateFilters();
|
||||
@ -101,6 +102,8 @@ public class DetailsPanel
|
||||
panelBuilder.registerTypeBuilder("PREVIOUS", this::createPreviousButton);
|
||||
panelBuilder.registerTypeBuilder("BLOCK", this::createMaterialButton);
|
||||
|
||||
panelBuilder.registerTypeBuilder("FILTER", this::createFilterButton);
|
||||
|
||||
// Register tabs
|
||||
panelBuilder.registerTypeBuilder("TAB", this::createTabButton);
|
||||
|
||||
@ -152,6 +155,61 @@ public class DetailsPanel
|
||||
}
|
||||
}
|
||||
|
||||
Comparator<Pair<Material, Integer>> sorter;
|
||||
|
||||
switch (this.activeFilter)
|
||||
{
|
||||
case COUNT ->
|
||||
{
|
||||
sorter = (o1, o2) ->
|
||||
{
|
||||
if (o1.getValue().equals(o2.getValue()))
|
||||
{
|
||||
String o1Name = DetailsPanel.prettifyObject(o1.getKey(), this.user);
|
||||
String o2Name = DetailsPanel.prettifyObject(o2.getKey(), this.user);
|
||||
|
||||
return String.CASE_INSENSITIVE_ORDER.compare(o1Name, o2Name);
|
||||
}
|
||||
else
|
||||
{
|
||||
return Integer.compare(o2.getValue(), o1.getValue());
|
||||
}
|
||||
};
|
||||
}
|
||||
case VALUE ->
|
||||
{
|
||||
sorter = (o1, o2) ->
|
||||
{
|
||||
int o1Value = this.addon.getBlockConfig().getBlockValues().getOrDefault(o1.getKey(), 0);
|
||||
int o2Value = this.addon.getBlockConfig().getBlockValues().getOrDefault(o2.getKey(), 0);
|
||||
|
||||
if (o1Value == o2Value)
|
||||
{
|
||||
String o1Name = DetailsPanel.prettifyObject(o1.getKey(), this.user);
|
||||
String o2Name = DetailsPanel.prettifyObject(o2.getKey(), this.user);
|
||||
|
||||
return String.CASE_INSENSITIVE_ORDER.compare(o1Name, o2Name);
|
||||
}
|
||||
else
|
||||
{
|
||||
return Integer.compare(o2Value, o1Value);
|
||||
}
|
||||
};
|
||||
}
|
||||
default ->
|
||||
{
|
||||
sorter = (o1, o2) ->
|
||||
{
|
||||
String o1Name = DetailsPanel.prettifyObject(o1.getKey(), this.user);
|
||||
String o2Name = DetailsPanel.prettifyObject(o2.getKey(), this.user);
|
||||
|
||||
return String.CASE_INSENSITIVE_ORDER.compare(o1Name, o2Name);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
this.materialCountList.sort(sorter);
|
||||
|
||||
this.pageIndex = 0;
|
||||
}
|
||||
|
||||
@ -240,6 +298,117 @@ public class DetailsPanel
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create next button panel item.
|
||||
*
|
||||
* @param template the template
|
||||
* @param slot the slot
|
||||
* @return the panel item
|
||||
*/
|
||||
private PanelItem createFilterButton(ItemTemplateRecord template, TemplatedPanel.ItemSlot slot)
|
||||
{
|
||||
PanelItemBuilder builder = new PanelItemBuilder();
|
||||
|
||||
if (template.icon() != null)
|
||||
{
|
||||
// Set icon
|
||||
builder.icon(template.icon().clone());
|
||||
}
|
||||
|
||||
Filter filter;
|
||||
|
||||
if (slot.amountMap().getOrDefault("FILTER", 0) > 1)
|
||||
{
|
||||
filter = Enums.getIfPresent(Filter.class, String.valueOf(template.dataMap().get("filter"))).or(Filter.NAME);
|
||||
}
|
||||
else
|
||||
{
|
||||
filter = this.activeFilter;
|
||||
}
|
||||
|
||||
final String reference = "level.gui.buttons.filters.";
|
||||
|
||||
if (template.title() != null)
|
||||
{
|
||||
// Set title
|
||||
builder.name(this.user.getTranslation(this.world, template.title().replace("[filter]", filter.name().toLowerCase())));
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.name(this.user.getTranslation(this.world, reference + filter.name().toLowerCase() + ".name"));
|
||||
}
|
||||
|
||||
if (template.description() != null)
|
||||
{
|
||||
// Set description
|
||||
builder.description(this.user.getTranslation(this.world, template.description().replace("[filter]", filter.name().toLowerCase())));
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.name(this.user.getTranslation(this.world, reference + filter.name().toLowerCase() + ".description"));
|
||||
}
|
||||
|
||||
// Get only possible actions, by removing all inactive ones.
|
||||
List<ItemTemplateRecord.ActionRecords> activeActions = new ArrayList<>(template.actions());
|
||||
|
||||
// Add Click handler
|
||||
builder.clickHandler((panel, user, clickType, i) ->
|
||||
{
|
||||
for (ItemTemplateRecord.ActionRecords action : activeActions)
|
||||
{
|
||||
if (clickType == action.clickType() || ClickType.UNKNOWN.equals(action.clickType()))
|
||||
{
|
||||
if ("UP".equalsIgnoreCase(action.actionType()))
|
||||
{
|
||||
this.activeFilter = Utils.getNextValue(Filter.values(), filter);
|
||||
|
||||
// Update filters.
|
||||
this.updateFilters();
|
||||
this.build();
|
||||
}
|
||||
else if ("DOWN".equalsIgnoreCase(action.actionType()))
|
||||
{
|
||||
this.activeFilter = Utils.getPreviousValue(Filter.values(), filter);
|
||||
|
||||
// Update filters.
|
||||
this.updateFilters();
|
||||
this.build();
|
||||
}
|
||||
else if ("SELECT".equalsIgnoreCase(action.actionType()))
|
||||
{
|
||||
this.activeFilter = filter;
|
||||
|
||||
// Update filters.
|
||||
this.updateFilters();
|
||||
this.build();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
// Collect tooltips.
|
||||
List<String> tooltips = activeActions.stream().
|
||||
filter(action -> action.tooltip() != null).
|
||||
map(action -> this.user.getTranslation(this.world, action.tooltip())).
|
||||
filter(text -> !text.isBlank()).
|
||||
collect(Collectors.toCollection(() -> new ArrayList<>(template.actions().size())));
|
||||
|
||||
// Add tooltips.
|
||||
if (!tooltips.isEmpty())
|
||||
{
|
||||
// Empty line and tooltips.
|
||||
builder.description("");
|
||||
builder.description(tooltips);
|
||||
}
|
||||
|
||||
builder.glow(this.activeFilter == filter);
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Section: Create common buttons
|
||||
// ---------------------------------------------------------------------
|
||||
@ -646,6 +815,26 @@ public class DetailsPanel
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sorting order of blocks.
|
||||
*/
|
||||
private enum Filter
|
||||
{
|
||||
/**
|
||||
* By name
|
||||
*/
|
||||
NAME,
|
||||
/**
|
||||
* By value
|
||||
*/
|
||||
VALUE,
|
||||
/**
|
||||
* By number
|
||||
*/
|
||||
COUNT
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Section: Variables
|
||||
// ---------------------------------------------------------------------
|
||||
@ -689,4 +878,9 @@ public class DetailsPanel
|
||||
* This variable stores which tab currently is active.
|
||||
*/
|
||||
private Tab activeTab;
|
||||
|
||||
/**
|
||||
* This variable stores active filter for items.
|
||||
*/
|
||||
private Filter activeFilter;
|
||||
}
|
||||
|
@ -73,4 +73,62 @@ public class Utils
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method allows to get next value from array list after given value.
|
||||
*
|
||||
* @param values Array that should be searched for given value.
|
||||
* @param currentValue Value which next element should be found.
|
||||
* @param <T> Instance of given object.
|
||||
* @return Next value after currentValue in values array.
|
||||
*/
|
||||
public static <T> T getNextValue(T[] values, T currentValue)
|
||||
{
|
||||
for (int i = 0; i < values.length; i++)
|
||||
{
|
||||
if (values[i].equals(currentValue))
|
||||
{
|
||||
if (i + 1 == values.length)
|
||||
{
|
||||
return values[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
return values[i + 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return currentValue;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method allows to get previous value from array list after given value.
|
||||
*
|
||||
* @param values Array that should be searched for given value.
|
||||
* @param currentValue Value which previous element should be found.
|
||||
* @param <T> Instance of given object.
|
||||
* @return Previous value before currentValue in values array.
|
||||
*/
|
||||
public static <T> T getPreviousValue(T[] values, T currentValue)
|
||||
{
|
||||
for (int i = 0; i < values.length; i++)
|
||||
{
|
||||
if (values[i].equals(currentValue))
|
||||
{
|
||||
if (i > 0)
|
||||
{
|
||||
return values[i - 1];
|
||||
}
|
||||
else
|
||||
{
|
||||
return values[values.length - 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return currentValue;
|
||||
}
|
||||
}
|
||||
|
@ -123,6 +123,19 @@ level:
|
||||
name: "&f&l Spawners"
|
||||
description: |-
|
||||
&7 Display only spawners.
|
||||
filters:
|
||||
name:
|
||||
name: "&f&l Sort by Name"
|
||||
description: |-
|
||||
&7 Sort all blocks by name.
|
||||
value:
|
||||
name: "&f&l Sort by Value"
|
||||
description: |-
|
||||
&7 Sort all blocks by their value.
|
||||
count:
|
||||
name: "&f&l Sort by Count"
|
||||
description: |-
|
||||
&7 Sort all blocks by their amount.
|
||||
# Button that is used in multi-page GUIs which allows to return to previous page.
|
||||
previous:
|
||||
name: "&f&l Previous Page"
|
||||
@ -137,6 +150,9 @@ level:
|
||||
click-to-view: "&e Click &7 to view."
|
||||
click-to-previous: "&e Click &7 to view previous page."
|
||||
click-to-next: "&e Click &7 to view next page."
|
||||
click-to-select: "&e Click &7 to select."
|
||||
left-click-to-cycle-up: "&e Left Click &7 to cycle up."
|
||||
right-click-to-cycle-down: "&e Right Click &7 to cycle down."
|
||||
conversations:
|
||||
# Prefix for messages that are send from server.
|
||||
prefix: "&l&6 [BentoBox]: &r"
|
||||
|
@ -19,7 +19,7 @@ detail_panel:
|
||||
tab: ALL_BLOCKS
|
||||
actions:
|
||||
view:
|
||||
click-type: unknwon
|
||||
click-type: unknown
|
||||
tooltip: level.gui.tips.click-to-view
|
||||
3:
|
||||
icon: GRASS_BLOCK
|
||||
@ -30,7 +30,7 @@ detail_panel:
|
||||
tab: ABOVE_SEA_LEVEL
|
||||
actions:
|
||||
view:
|
||||
click-type: unknwon
|
||||
click-type: unknown
|
||||
tooltip: level.gui.tips.click-to-view
|
||||
4:
|
||||
icon: WATER_BUCKET
|
||||
@ -41,7 +41,7 @@ detail_panel:
|
||||
tab: UNDERWATER
|
||||
actions:
|
||||
view:
|
||||
click-type: unknwon
|
||||
click-type: unknown
|
||||
tooltip: level.gui.tips.click-to-view
|
||||
5:
|
||||
icon: SPAWNER
|
||||
@ -52,8 +52,29 @@ detail_panel:
|
||||
tab: SPAWNER
|
||||
actions:
|
||||
view:
|
||||
click-type: unknwon
|
||||
click-type: unknown
|
||||
tooltip: level.gui.tips.click-to-view
|
||||
9:
|
||||
# You can create multiple buttons. By default it is one.
|
||||
icon: IRON_TRAPDOOR
|
||||
# [filter] is placeholder for different filter types. It will be replaced with name, value, count.
|
||||
title: level.gui.buttons.filters.[filter].name
|
||||
description: level.gui.buttons.filters.[filter].description
|
||||
data:
|
||||
type: FILTER
|
||||
# the value of filter button. Suggestion is to leave fist value to name if you use single button.
|
||||
filter: NAME
|
||||
actions:
|
||||
up:
|
||||
click-type: left
|
||||
tooltip: level.gui.tips.left-click-to-cycle-up
|
||||
down:
|
||||
click-type: right
|
||||
tooltip: level.gui.tips.right-click-to-cycle-down
|
||||
# There is also select action. With it you can create multiple filter buttons.
|
||||
# select:
|
||||
# click-type: unknown
|
||||
# tooltip: level.gui.tips.click-to-select
|
||||
2:
|
||||
2: material_button
|
||||
3: material_button
|
||||
|
@ -11,7 +11,7 @@ top_panel:
|
||||
content:
|
||||
2:
|
||||
5:
|
||||
icon: PLAYER_HEAD
|
||||
#icon: PLAYER_HEAD
|
||||
title: level.gui.buttons.island.name
|
||||
description: level.gui.buttons.island.description
|
||||
data:
|
||||
@ -22,7 +22,7 @@ top_panel:
|
||||
title: level.gui.buttons.island.empty
|
||||
3:
|
||||
4:
|
||||
icon: PLAYER_HEAD
|
||||
#icon: PLAYER_HEAD
|
||||
title: level.gui.buttons.island.name
|
||||
description: level.gui.buttons.island.description
|
||||
data:
|
||||
@ -32,7 +32,7 @@ top_panel:
|
||||
icon: LIME_STAINED_GLASS_PANE
|
||||
title: level.gui.buttons.island.empty
|
||||
6:
|
||||
icon: PLAYER_HEAD
|
||||
#icon: PLAYER_HEAD
|
||||
title: level.gui.buttons.island.name
|
||||
description: level.gui.buttons.island.description
|
||||
data:
|
||||
@ -43,7 +43,7 @@ top_panel:
|
||||
title: level.gui.buttons.island.empty
|
||||
4:
|
||||
2:
|
||||
icon: PLAYER_HEAD
|
||||
#icon: PLAYER_HEAD
|
||||
title: level.gui.buttons.island.name
|
||||
description: level.gui.buttons.island.description
|
||||
data:
|
||||
@ -53,7 +53,7 @@ top_panel:
|
||||
icon: LIME_STAINED_GLASS_PANE
|
||||
title: level.gui.buttons.island.empty
|
||||
3:
|
||||
icon: PLAYER_HEAD
|
||||
#icon: PLAYER_HEAD
|
||||
title: level.gui.buttons.island.name
|
||||
description: level.gui.buttons.island.description
|
||||
data:
|
||||
@ -63,7 +63,7 @@ top_panel:
|
||||
icon: LIME_STAINED_GLASS_PANE
|
||||
title: level.gui.buttons.island.empty
|
||||
4:
|
||||
icon: PLAYER_HEAD
|
||||
#icon: PLAYER_HEAD
|
||||
title: level.gui.buttons.island.name
|
||||
description: level.gui.buttons.island.description
|
||||
data:
|
||||
@ -73,7 +73,7 @@ top_panel:
|
||||
icon: LIME_STAINED_GLASS_PANE
|
||||
title: level.gui.buttons.island.empty
|
||||
5:
|
||||
icon: PLAYER_HEAD
|
||||
#icon: PLAYER_HEAD
|
||||
title: level.gui.buttons.island.name
|
||||
description: level.gui.buttons.island.description
|
||||
data:
|
||||
@ -83,7 +83,7 @@ top_panel:
|
||||
icon: LIME_STAINED_GLASS_PANE
|
||||
title: level.gui.buttons.island.empty
|
||||
6:
|
||||
icon: PLAYER_HEAD
|
||||
#icon: PLAYER_HEAD
|
||||
title: level.gui.buttons.island.name
|
||||
description: level.gui.buttons.island.description
|
||||
data:
|
||||
@ -93,7 +93,7 @@ top_panel:
|
||||
icon: LIME_STAINED_GLASS_PANE
|
||||
title: level.gui.buttons.island.empty
|
||||
7:
|
||||
icon: PLAYER_HEAD
|
||||
#icon: PLAYER_HEAD
|
||||
title: level.gui.buttons.island.name
|
||||
description: level.gui.buttons.island.description
|
||||
data:
|
||||
@ -103,7 +103,7 @@ top_panel:
|
||||
icon: LIME_STAINED_GLASS_PANE
|
||||
title: level.gui.buttons.island.empty
|
||||
8:
|
||||
icon: PLAYER_HEAD
|
||||
#icon: PLAYER_HEAD
|
||||
title: level.gui.buttons.island.name
|
||||
description: level.gui.buttons.island.description
|
||||
data:
|
||||
@ -114,7 +114,7 @@ top_panel:
|
||||
title: level.gui.buttons.island.empty
|
||||
6:
|
||||
5:
|
||||
icon: PLAYER_HEAD
|
||||
#icon: PLAYER_HEAD
|
||||
title: level.gui.buttons.island.name
|
||||
description: level.gui.buttons.island.description
|
||||
data:
|
||||
|
Loading…
Reference in New Issue
Block a user