ClothConfigScreen.java 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467
  1. package me.shedaniel.clothconfig2.gui;
  2. import com.google.common.collect.Lists;
  3. import com.google.common.collect.Maps;
  4. import com.google.common.util.concurrent.AtomicDouble;
  5. import com.mojang.blaze3d.platform.GlStateManager;
  6. import com.mojang.blaze3d.platform.GlStateManager.DestFactor;
  7. import com.mojang.blaze3d.platform.GlStateManager.SourceFactor;
  8. import it.unimi.dsi.fastutil.booleans.BooleanConsumer;
  9. import me.shedaniel.clothconfig2.api.AbstractConfigEntry;
  10. import me.shedaniel.clothconfig2.api.AbstractConfigListEntry;
  11. import me.shedaniel.clothconfig2.api.QueuedTooltip;
  12. import me.shedaniel.clothconfig2.gui.widget.DynamicElementListWidget;
  13. import me.shedaniel.math.api.Rectangle;
  14. import net.minecraft.client.MinecraftClient;
  15. import net.minecraft.client.font.TextRenderer;
  16. import net.minecraft.client.gui.DrawableHelper;
  17. import net.minecraft.client.gui.Element;
  18. import net.minecraft.client.gui.screen.ConfirmScreen;
  19. import net.minecraft.client.gui.screen.Screen;
  20. import net.minecraft.client.gui.widget.AbstractButtonWidget;
  21. import net.minecraft.client.gui.widget.AbstractPressableButtonWidget;
  22. import net.minecraft.client.gui.widget.ButtonWidget;
  23. import net.minecraft.client.render.BufferBuilder;
  24. import net.minecraft.client.render.Tessellator;
  25. import net.minecraft.client.render.VertexFormats;
  26. import net.minecraft.client.resource.language.I18n;
  27. import net.minecraft.text.LiteralText;
  28. import net.minecraft.text.TranslatableText;
  29. import net.minecraft.util.Identifier;
  30. import net.minecraft.util.Pair;
  31. import net.minecraft.util.Tickable;
  32. import net.minecraft.util.math.MathHelper;
  33. import java.util.LinkedHashMap;
  34. import java.util.List;
  35. import java.util.Map;
  36. import java.util.Optional;
  37. import java.util.stream.Collectors;
  38. public abstract class ClothConfigScreen extends Screen {
  39. private static final Identifier CONFIG_TEX = new Identifier("cloth-config2", "textures/gui/cloth_config.png");
  40. private final List<QueuedTooltip> queuedTooltips = Lists.newArrayList();
  41. public int nextTabIndex;
  42. public int selectedTabIndex;
  43. public double tabsScrollVelocity = 0d;
  44. public double tabsScrollProgress = 0d;
  45. public ListWidget listWidget;
  46. private Screen parent;
  47. private LinkedHashMap<String, List<AbstractConfigEntry>> tabbedEntries;
  48. private List<Pair<String, Integer>> tabs;
  49. private boolean edited;
  50. private boolean requiresRestart;
  51. private boolean confirmSave;
  52. private AbstractButtonWidget buttonQuit;
  53. private AbstractButtonWidget buttonSave;
  54. private AbstractButtonWidget buttonLeftTab;
  55. private AbstractButtonWidget buttonRightTab;
  56. private Rectangle tabsBounds, tabsLeftBounds, tabsRightBounds;
  57. private String title;
  58. private double tabsMaximumScrolled = -1d;
  59. private boolean displayErrors;
  60. private List<ClothConfigTabButton> tabButtons;
  61. private boolean smoothScrollingTabs = true;
  62. private boolean smoothScrollingList = true;
  63. private Identifier defaultBackgroundLocation;
  64. private Map<String, Identifier> categoryBackgroundLocation;
  65. public ClothConfigScreen(Screen parent, String title, Map<String, List<Pair<String, Object>>> o) {
  66. this(parent, title, o, true, true);
  67. }
  68. public ClothConfigScreen(Screen parent, String title, Map<String, List<Pair<String, Object>>> o, boolean confirmSave, boolean displayErrors) {
  69. this(parent, title, o, confirmSave, displayErrors, true, DrawableHelper.BACKGROUND_LOCATION);
  70. }
  71. public ClothConfigScreen(Screen parent, String title, Map<String, List<Pair<String, Object>>> o, boolean confirmSave, boolean displayErrors, boolean smoothScrollingList, Identifier defaultBackgroundLocation) {
  72. this(parent, title, o, confirmSave, displayErrors, smoothScrollingList, defaultBackgroundLocation, Maps.newHashMap());
  73. }
  74. @SuppressWarnings("deprecation")
  75. public ClothConfigScreen(Screen parent, String title, Map<String, List<Pair<String, Object>>> o, boolean confirmSave, boolean displayErrors, boolean smoothScrollingList, Identifier defaultBackgroundLocation, Map<String, Identifier> categoryBackgroundLocation) {
  76. super(new LiteralText(""));
  77. this.parent = parent;
  78. this.title = title;
  79. this.tabbedEntries = Maps.newLinkedHashMap();
  80. this.smoothScrollingList = smoothScrollingList;
  81. this.defaultBackgroundLocation = defaultBackgroundLocation;
  82. o.forEach((tab, pairs) -> {
  83. List<AbstractConfigEntry> list = Lists.newArrayList();
  84. for(Pair<String, Object> pair : pairs) {
  85. if (pair.getRight() instanceof AbstractConfigListEntry) {
  86. list.add((AbstractConfigListEntry) pair.getRight());
  87. } else {
  88. throw new IllegalArgumentException("Unsupported Type (" + pair.getLeft() + "): " + pair.getRight().getClass().getSimpleName());
  89. }
  90. }
  91. list.forEach(entry -> entry.setScreen(this));
  92. tabbedEntries.put(tab, list);
  93. });
  94. this.nextTabIndex = 0;
  95. this.selectedTabIndex = 0;
  96. this.confirmSave = confirmSave;
  97. this.edited = false;
  98. this.requiresRestart = false;
  99. TextRenderer textRenderer = MinecraftClient.getInstance().textRenderer;
  100. this.tabs = tabbedEntries.keySet().stream().map(s -> new Pair<>(s, textRenderer.getStringWidth(I18n.translate(s)) + 8)).collect(Collectors.toList());
  101. this.tabsScrollProgress = 0d;
  102. this.tabButtons = Lists.newArrayList();
  103. this.displayErrors = displayErrors;
  104. this.categoryBackgroundLocation = categoryBackgroundLocation;
  105. }
  106. @Override
  107. public void tick() {
  108. super.tick();
  109. for(Element child : children())
  110. if (child instanceof Tickable)
  111. ((Tickable) child).tick();
  112. }
  113. public Identifier getBackgroundLocation() {
  114. if (categoryBackgroundLocation.containsKey(Lists.newArrayList(tabbedEntries.keySet()).get(selectedTabIndex)))
  115. return categoryBackgroundLocation.get(Lists.newArrayList(tabbedEntries.keySet()).get(selectedTabIndex));
  116. return defaultBackgroundLocation;
  117. }
  118. public boolean isSmoothScrollingList() {
  119. return smoothScrollingList;
  120. }
  121. public void setSmoothScrollingList(boolean smoothScrollingList) {
  122. this.smoothScrollingList = smoothScrollingList;
  123. }
  124. public boolean isSmoothScrollingTabs() {
  125. return smoothScrollingTabs;
  126. }
  127. public void setSmoothScrollingTabs(boolean smoothScrolling) {
  128. this.smoothScrollingTabs = smoothScrolling;
  129. }
  130. public boolean isEdited() {
  131. return edited;
  132. }
  133. @Deprecated
  134. public void setEdited(boolean edited) {
  135. this.edited = edited;
  136. buttonQuit.setMessage(edited ? I18n.translate("text.cloth-config.cancel_discard") : I18n.translate("gui.cancel"));
  137. buttonSave.active = edited;
  138. }
  139. @SuppressWarnings("deprecation")
  140. public void setEdited(boolean edited, boolean requiresRestart) {
  141. setEdited(edited);
  142. if (!this.requiresRestart && requiresRestart)
  143. this.requiresRestart = requiresRestart;
  144. }
  145. @Override
  146. protected void init() {
  147. super.init();
  148. this.children.clear();
  149. this.tabButtons.clear();
  150. if (listWidget != null)
  151. tabbedEntries.put(tabs.get(selectedTabIndex).getLeft(), listWidget.children());
  152. selectedTabIndex = nextTabIndex;
  153. children.add(listWidget = new ListWidget(minecraft, width, height, 70, height - 32, getBackgroundLocation()));
  154. listWidget.setSmoothScrolling(this.smoothScrollingList);
  155. if (tabbedEntries.size() > selectedTabIndex)
  156. Lists.newArrayList(tabbedEntries.values()).get(selectedTabIndex).forEach(entry -> listWidget.children().add(entry));
  157. addButton(buttonQuit = new ButtonWidget(width / 2 - 154, height - 26, 150, 20, edited ? I18n.translate("text.cloth-config.cancel_discard") : I18n.translate("gui.cancel"), widget -> {
  158. if (confirmSave && edited)
  159. minecraft.openScreen(new ConfirmScreen(new QuitSaveConsumer(), new TranslatableText("text.cloth-config.quit_config"), new TranslatableText("text.cloth-config.quit_config_sure"), I18n.translate("text.cloth-config.quit_discard"), I18n.translate("gui.cancel")));
  160. else
  161. minecraft.openScreen(parent);
  162. }));
  163. addButton(buttonSave = new AbstractPressableButtonWidget(width / 2 + 4, height - 26, 150, 20, "") {
  164. @Override
  165. public void onPress() {
  166. Map<String, List<Pair<String, Object>>> map = Maps.newLinkedHashMap();
  167. tabbedEntries.forEach((s, abstractListEntries) -> {
  168. List list = abstractListEntries.stream().map(entry -> new Pair(entry.getFieldName(), entry.getValue())).collect(Collectors.toList());
  169. map.put(s, list);
  170. });
  171. for(List<AbstractConfigEntry> entries : Lists.newArrayList(tabbedEntries.values()))
  172. for(AbstractConfigEntry entry : entries)
  173. entry.save();
  174. onSave(map);
  175. if (requiresRestart)
  176. ClothConfigScreen.this.minecraft.openScreen(new ClothRequiresRestartScreen(parent));
  177. else
  178. ClothConfigScreen.this.minecraft.openScreen(parent);
  179. }
  180. @Override
  181. public void render(int int_1, int int_2, float float_1) {
  182. boolean hasErrors = false;
  183. if (displayErrors)
  184. for(List<AbstractConfigEntry> entries : Lists.newArrayList(tabbedEntries.values())) {
  185. for(AbstractConfigEntry entry : entries)
  186. if (entry.getConfigError().isPresent()) {
  187. hasErrors = true;
  188. break;
  189. }
  190. if (hasErrors)
  191. break;
  192. }
  193. active = edited && !hasErrors;
  194. setMessage(displayErrors && hasErrors ? I18n.translate("text.cloth-config.error_cannot_save") : I18n.translate("text.cloth-config.save_and_done"));
  195. super.render(int_1, int_2, float_1);
  196. }
  197. });
  198. buttonSave.active = edited;
  199. tabsBounds = new Rectangle(0, 41, width, 24);
  200. tabsLeftBounds = new Rectangle(0, 41, 18, 24);
  201. tabsRightBounds = new Rectangle(width - 18, 41, 18, 24);
  202. children.add(buttonLeftTab = new AbstractPressableButtonWidget(4, 44, 12, 18, "") {
  203. @Override
  204. public void onPress() {
  205. tabsScrollProgress = Integer.MIN_VALUE;
  206. tabsScrollVelocity = 0d;
  207. clampTabsScrolled();
  208. }
  209. @Override
  210. public void renderButton(int int_1, int int_2, float float_1) {
  211. minecraft.getTextureManager().bindTexture(CONFIG_TEX);
  212. GlStateManager.color4f(1.0F, 1.0F, 1.0F, this.alpha);
  213. int int_3 = this.getYImage(this.isHovered());
  214. GlStateManager.enableBlend();
  215. GlStateManager.blendFuncSeparate(SourceFactor.SRC_ALPHA, DestFactor.ONE_MINUS_SRC_ALPHA, SourceFactor.ONE, DestFactor.ZERO);
  216. GlStateManager.blendFunc(SourceFactor.SRC_ALPHA, DestFactor.ONE_MINUS_SRC_ALPHA);
  217. this.blit(x, y, 12, 18 * int_3, width, height);
  218. }
  219. });
  220. int j = 0;
  221. for(Pair<String, Integer> tab : tabs) {
  222. tabButtons.add(new ClothConfigTabButton(this, j, -100, 43, tab.getRight(), 20, I18n.translate(tab.getLeft())));
  223. j++;
  224. }
  225. tabButtons.forEach(children::add);
  226. children.add(buttonRightTab = new AbstractPressableButtonWidget(width - 16, 44, 12, 18, "") {
  227. @Override
  228. public void onPress() {
  229. tabsScrollProgress = Integer.MAX_VALUE;
  230. tabsScrollVelocity = 0d;
  231. clampTabsScrolled();
  232. }
  233. @Override
  234. public void renderButton(int int_1, int int_2, float float_1) {
  235. minecraft.getTextureManager().bindTexture(CONFIG_TEX);
  236. GlStateManager.color4f(1.0F, 1.0F, 1.0F, this.alpha);
  237. int int_3 = this.getYImage(this.isHovered());
  238. GlStateManager.enableBlend();
  239. GlStateManager.blendFuncSeparate(SourceFactor.SRC_ALPHA, DestFactor.ONE_MINUS_SRC_ALPHA, SourceFactor.ONE, DestFactor.ZERO);
  240. GlStateManager.blendFunc(SourceFactor.SRC_ALPHA, DestFactor.ONE_MINUS_SRC_ALPHA);
  241. this.blit(x, y, 0, 18 * int_3, width, height);
  242. }
  243. });
  244. }
  245. @Override
  246. public boolean mouseScrolled(double double_1, double double_2, double double_3) {
  247. if (tabsBounds.contains(double_1, double_2) && !tabsLeftBounds.contains(double_1, double_2) && !tabsRightBounds.contains(double_1, double_2) && double_3 != 0d) {
  248. if (double_3 < 0)
  249. tabsScrollVelocity += 16;
  250. if (double_3 > 0)
  251. tabsScrollVelocity -= 16;
  252. return true;
  253. }
  254. return super.mouseScrolled(double_1, double_2, double_3);
  255. }
  256. public double getTabsMaximumScrolled() {
  257. if (tabsMaximumScrolled == -1d) {
  258. AtomicDouble d = new AtomicDouble();
  259. tabs.forEach(pair -> d.addAndGet(pair.getRight() + 2));
  260. tabsMaximumScrolled = d.get();
  261. }
  262. return tabsMaximumScrolled;
  263. }
  264. public void resetTabsMaximumScrolled() {
  265. tabsMaximumScrolled = -1d;
  266. tabsScrollVelocity = 0f;
  267. }
  268. public void clampTabsScrolled() {
  269. int xx = 0;
  270. for(ClothConfigTabButton tabButton : tabButtons)
  271. xx += tabButton.getWidth() + 2;
  272. if (xx > width - 40)
  273. tabsScrollProgress = MathHelper.clamp(tabsScrollProgress, 0, getTabsMaximumScrolled() - width + 40);
  274. else
  275. tabsScrollProgress = 0d;
  276. }
  277. @Override
  278. public void render(int int_1, int int_2, float float_1) {
  279. if (smoothScrollingTabs) {
  280. double change = tabsScrollVelocity * 0.2f;
  281. if (change != 0) {
  282. if (change > 0 && change < .2)
  283. change = .2;
  284. else if (change < 0 && change > -.2)
  285. change = -.2;
  286. tabsScrollProgress += change;
  287. tabsScrollVelocity -= change;
  288. if (change > 0 == tabsScrollVelocity < 0)
  289. tabsScrollVelocity = 0f;
  290. clampTabsScrolled();
  291. }
  292. } else {
  293. tabsScrollProgress += tabsScrollVelocity;
  294. tabsScrollVelocity = 0d;
  295. clampTabsScrolled();
  296. }
  297. int xx = 20 - (int) tabsScrollProgress;
  298. for(ClothConfigTabButton tabButton : tabButtons) {
  299. tabButton.x = xx;
  300. xx += tabButton.getWidth() + 2;
  301. }
  302. buttonLeftTab.active = tabsScrollProgress > 0d;
  303. buttonRightTab.active = tabsScrollProgress < getTabsMaximumScrolled() - width + 40;
  304. renderDirtBackground(0);
  305. listWidget.render(int_1, int_2, float_1);
  306. overlayBackground(tabsBounds, 32, 32, 32, 255, 255);
  307. drawCenteredString(minecraft.textRenderer, title, width / 2, 18, -1);
  308. tabButtons.forEach(widget -> widget.render(int_1, int_2, float_1));
  309. overlayBackground(tabsLeftBounds, 64, 64, 64, 255, 255);
  310. overlayBackground(tabsRightBounds, 64, 64, 64, 255, 255);
  311. drawShades();
  312. buttonLeftTab.render(int_1, int_2, float_1);
  313. buttonRightTab.render(int_1, int_2, float_1);
  314. if (displayErrors && isEditable()) {
  315. List<String> errors = Lists.newArrayList();
  316. for(List<AbstractConfigEntry> entries : Lists.newArrayList(tabbedEntries.values()))
  317. for(AbstractConfigEntry entry : entries)
  318. if (entry.getConfigError().isPresent())
  319. errors.add(((Optional<String>) entry.getConfigError()).get());
  320. if (errors.size() > 0) {
  321. minecraft.getTextureManager().bindTexture(CONFIG_TEX);
  322. GlStateManager.color4f(1.0F, 1.0F, 1.0F, 1.0F);
  323. blit(10, 10, 0, 54, 3, 11);
  324. if (errors.size() == 1)
  325. drawString(minecraft.textRenderer, "§c" + errors.get(0), 18, 12, -1);
  326. else
  327. drawString(minecraft.textRenderer, "§c" + I18n.translate("text.cloth-config.multi_error"), 18, 12, -1);
  328. }
  329. } else if (!isEditable()) {
  330. minecraft.getTextureManager().bindTexture(CONFIG_TEX);
  331. GlStateManager.color4f(1.0F, 1.0F, 1.0F, 1.0F);
  332. blit(10, 10, 0, 54, 3, 11);
  333. drawString(minecraft.textRenderer, "§c" + I18n.translate("text.cloth-config.not_editable"), 18, 12, -1);
  334. }
  335. super.render(int_1, int_2, float_1);
  336. queuedTooltips.forEach(queuedTooltip -> renderTooltip(queuedTooltip.getText(), queuedTooltip.getX(), queuedTooltip.getY()));
  337. queuedTooltips.clear();
  338. }
  339. public void queueTooltip(QueuedTooltip queuedTooltip) {
  340. queuedTooltips.add(queuedTooltip);
  341. }
  342. private void drawShades() {
  343. GlStateManager.enableBlend();
  344. GlStateManager.blendFuncSeparate(SourceFactor.SRC_ALPHA, DestFactor.ONE_MINUS_SRC_ALPHA, SourceFactor.ZERO, DestFactor.ONE);
  345. GlStateManager.disableAlphaTest();
  346. GlStateManager.shadeModel(7425);
  347. GlStateManager.disableTexture();
  348. Tessellator tessellator = Tessellator.getInstance();
  349. BufferBuilder buffer = tessellator.getBufferBuilder();
  350. buffer.begin(7, VertexFormats.POSITION_UV_COLOR);
  351. buffer.vertex(tabsBounds.getMinX() + 20, tabsBounds.getMinY() + 4, 0.0D).texture(0.0D, 1.0D).color(0, 0, 0, 0).next();
  352. buffer.vertex(tabsBounds.getMaxX() - 20, tabsBounds.getMinY() + 4, 0.0D).texture(1.0D, 1.0D).color(0, 0, 0, 0).next();
  353. buffer.vertex(tabsBounds.getMaxX() - 20, tabsBounds.getMinY(), 0.0D).texture(1.0D, 0.0D).color(0, 0, 0, 255).next();
  354. buffer.vertex(tabsBounds.getMinX() + 20, tabsBounds.getMinY(), 0.0D).texture(0.0D, 0.0D).color(0, 0, 0, 255).next();
  355. tessellator.draw();
  356. buffer.begin(7, VertexFormats.POSITION_UV_COLOR);
  357. buffer.vertex(tabsBounds.getMinX() + 20, tabsBounds.getMaxY(), 0.0D).texture(0.0D, 1.0D).color(0, 0, 0, 255).next();
  358. buffer.vertex(tabsBounds.getMaxX() - 20, tabsBounds.getMaxY(), 0.0D).texture(1.0D, 1.0D).color(0, 0, 0, 255).next();
  359. buffer.vertex(tabsBounds.getMaxX() - 20, tabsBounds.getMaxY() - 4, 0.0D).texture(1.0D, 0.0D).color(0, 0, 0, 0).next();
  360. buffer.vertex(tabsBounds.getMinX() + 20, tabsBounds.getMaxY() - 4, 0.0D).texture(0.0D, 0.0D).color(0, 0, 0, 0).next();
  361. tessellator.draw();
  362. GlStateManager.enableTexture();
  363. GlStateManager.shadeModel(7424);
  364. GlStateManager.enableAlphaTest();
  365. GlStateManager.disableBlend();
  366. }
  367. protected void overlayBackground(Rectangle rect, int red, int green, int blue, int startAlpha, int endAlpha) {
  368. Tessellator tessellator = Tessellator.getInstance();
  369. BufferBuilder buffer = tessellator.getBufferBuilder();
  370. minecraft.getTextureManager().bindTexture(getBackgroundLocation());
  371. GlStateManager.color4f(1.0F, 1.0F, 1.0F, 1.0F);
  372. float f = 32.0F;
  373. buffer.begin(7, VertexFormats.POSITION_UV_COLOR);
  374. buffer.vertex(rect.getMinX(), rect.getMaxY(), 0.0D).texture(rect.getMinX() / 32.0D, rect.getMaxY() / 32.0D).color(red, green, blue, endAlpha).next();
  375. buffer.vertex(rect.getMaxX(), rect.getMaxY(), 0.0D).texture(rect.getMaxX() / 32.0D, rect.getMaxY() / 32.0D).color(red, green, blue, endAlpha).next();
  376. buffer.vertex(rect.getMaxX(), rect.getMinY(), 0.0D).texture(rect.getMaxX() / 32.0D, rect.getMinY() / 32.0D).color(red, green, blue, startAlpha).next();
  377. buffer.vertex(rect.getMinX(), rect.getMinY(), 0.0D).texture(rect.getMinX() / 32.0D, rect.getMinY() / 32.0D).color(red, green, blue, startAlpha).next();
  378. tessellator.draw();
  379. }
  380. @Override
  381. public boolean keyPressed(int int_1, int int_2, int int_3) {
  382. if (int_1 == 256 && this.shouldCloseOnEsc()) {
  383. if (confirmSave && edited)
  384. minecraft.openScreen(new ConfirmScreen(new QuitSaveConsumer(), new TranslatableText("text.cloth-config.quit_config"), new TranslatableText("text.cloth-config.quit_config_sure"), I18n.translate("text.cloth-config.quit_discard"), I18n.translate("gui.cancel")));
  385. else
  386. minecraft.openScreen(parent);
  387. return true;
  388. }
  389. return super.keyPressed(int_1, int_2, int_3);
  390. }
  391. public abstract void onSave(Map<String, List<Pair<String, Object>>> o);
  392. public boolean isEditable() {
  393. return true;
  394. }
  395. private class QuitSaveConsumer implements BooleanConsumer {
  396. @Override
  397. public void accept(boolean t) {
  398. if (!t)
  399. minecraft.openScreen(ClothConfigScreen.this);
  400. else
  401. minecraft.openScreen(parent);
  402. return;
  403. }
  404. }
  405. public class ListWidget extends DynamicElementListWidget {
  406. public ListWidget(MinecraftClient client, int width, int height, int top, int bottom, Identifier backgroundLocation) {
  407. super(client, width, height, top, bottom, backgroundLocation);
  408. visible = false;
  409. }
  410. @Override
  411. public int getItemWidth() {
  412. return width - 80;
  413. }
  414. public ClothConfigScreen getScreen() {
  415. return ClothConfigScreen.this;
  416. }
  417. @Override
  418. protected int getScrollbarPosition() {
  419. return width - 36;
  420. }
  421. protected final void clearStuff() {
  422. this.clearItems();
  423. }
  424. }
  425. }