TextFieldWidget.java 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605
  1. package me.shedaniel.rei.gui.widget;
  2. import com.google.common.base.Predicates;
  3. import com.mojang.blaze3d.platform.GlStateManager;
  4. import net.minecraft.SharedConstants;
  5. import net.minecraft.client.MinecraftClient;
  6. import net.minecraft.client.font.FontRenderer;
  7. import net.minecraft.client.gui.Drawable;
  8. import net.minecraft.client.gui.Gui;
  9. import net.minecraft.client.render.BufferBuilder;
  10. import net.minecraft.client.render.Tessellator;
  11. import net.minecraft.client.render.VertexFormats;
  12. import net.minecraft.util.math.MathHelper;
  13. import java.awt.*;
  14. import java.util.ArrayList;
  15. import java.util.List;
  16. import java.util.function.BiFunction;
  17. import java.util.function.Consumer;
  18. import java.util.function.Predicate;
  19. public class TextFieldWidget extends Drawable implements IWidget {
  20. private final FontRenderer fontRenderer;
  21. private int width;
  22. private int height;
  23. private int x;
  24. private int y;
  25. private String text;
  26. private int maxLength;
  27. private int focusedTicks;
  28. private boolean hasBorder;
  29. private boolean field_2096;
  30. private boolean focused;
  31. private boolean editable;
  32. private boolean field_17037;
  33. private int field_2103;
  34. private int cursorMax;
  35. private int cursorMin;
  36. private int field_2100;
  37. private int field_2098;
  38. private boolean visible;
  39. private String suggestion;
  40. private Consumer<String> changedListener;
  41. private Predicate<String> textPredicate;
  42. private BiFunction<String, Integer, String> field_2099;
  43. public TextFieldWidget(Rectangle rectangle) {
  44. this(rectangle.x, rectangle.y, rectangle.width, rectangle.height);
  45. }
  46. public TextFieldWidget(int x, int y, int width, int height) {
  47. this.text = "";
  48. this.maxLength = 32;
  49. this.hasBorder = true;
  50. this.field_2096 = true;
  51. this.editable = true;
  52. this.field_2100 = 14737632;
  53. this.field_2098 = 7368816;
  54. this.visible = true;
  55. this.textPredicate = Predicates.alwaysTrue();
  56. this.field_2099 = (string_1, integer_1) -> {
  57. return string_1;
  58. };
  59. this.fontRenderer = MinecraftClient.getInstance().fontRenderer;
  60. this.x = x;
  61. this.y = y;
  62. this.width = width;
  63. this.height = height;
  64. }
  65. public Rectangle getBounds() {
  66. return new Rectangle(x, y, width, height);
  67. }
  68. public void setBounds(Rectangle rectangle) {
  69. this.x = rectangle.x;
  70. this.y = rectangle.y;
  71. this.width = rectangle.width;
  72. this.height = rectangle.height;
  73. }
  74. public void setChangedListener(Consumer<String> biConsumer_1) {
  75. this.changedListener = biConsumer_1;
  76. }
  77. public void method_1854(BiFunction<String, Integer, String> biFunction_1) {
  78. this.field_2099 = biFunction_1;
  79. }
  80. public void tick() {
  81. ++this.focusedTicks;
  82. }
  83. public String getText() {
  84. return this.text;
  85. }
  86. public void setText(String string_1) {
  87. if (this.textPredicate.test(string_1)) {
  88. if (string_1.length() > this.maxLength) {
  89. this.text = string_1.substring(0, this.maxLength);
  90. } else {
  91. this.text = string_1;
  92. }
  93. this.onChanged(string_1);
  94. this.method_1872();
  95. }
  96. }
  97. public String getSelectedText() {
  98. int int_1 = this.cursorMax < this.cursorMin ? this.cursorMax : this.cursorMin;
  99. int int_2 = this.cursorMax < this.cursorMin ? this.cursorMin : this.cursorMax;
  100. return this.text.substring(int_1, int_2);
  101. }
  102. public void method_1890(Predicate<String> predicate_1) {
  103. this.textPredicate = predicate_1;
  104. }
  105. public void addText(String string_1) {
  106. String string_2 = "";
  107. String string_3 = SharedConstants.stripInvalidChars(string_1);
  108. int int_1 = this.cursorMax < this.cursorMin ? this.cursorMax : this.cursorMin;
  109. int int_2 = this.cursorMax < this.cursorMin ? this.cursorMin : this.cursorMax;
  110. int int_3 = this.maxLength - this.text.length() - (int_1 - int_2);
  111. if (!this.text.isEmpty()) {
  112. string_2 = string_2 + this.text.substring(0, int_1);
  113. }
  114. int int_5;
  115. if (int_3 < string_3.length()) {
  116. string_2 = string_2 + string_3.substring(0, int_3);
  117. int_5 = int_3;
  118. } else {
  119. string_2 = string_2 + string_3;
  120. int_5 = string_3.length();
  121. }
  122. if (!this.text.isEmpty() && int_2 < this.text.length()) {
  123. string_2 = string_2 + this.text.substring(int_2);
  124. }
  125. if (this.textPredicate.test(string_2)) {
  126. this.text = string_2;
  127. this.setCursor(int_1 + int_5);
  128. this.method_1884(this.cursorMax);
  129. this.onChanged(this.text);
  130. }
  131. }
  132. public void onChanged(String string_1) {
  133. if (this.changedListener != null) {
  134. this.changedListener.accept(string_1);
  135. }
  136. }
  137. private void method_16873(int int_1) {
  138. if (Gui.isControlPressed()) {
  139. this.method_1877(int_1);
  140. } else {
  141. this.method_1878(int_1);
  142. }
  143. }
  144. public void method_1877(int int_1) {
  145. if (!this.text.isEmpty()) {
  146. if (this.cursorMin != this.cursorMax) {
  147. this.addText("");
  148. } else {
  149. this.method_1878(this.method_1853(int_1) - this.cursorMax);
  150. }
  151. }
  152. }
  153. public void method_1878(int int_1) {
  154. if (!this.text.isEmpty()) {
  155. if (this.cursorMin != this.cursorMax) {
  156. this.addText("");
  157. } else {
  158. boolean boolean_1 = int_1 < 0;
  159. int int_2 = boolean_1 ? this.cursorMax + int_1 : this.cursorMax;
  160. int int_3 = boolean_1 ? this.cursorMax : this.cursorMax + int_1;
  161. String string_1 = "";
  162. if (int_2 >= 0) {
  163. string_1 = this.text.substring(0, int_2);
  164. }
  165. if (int_3 < this.text.length()) {
  166. string_1 = string_1 + this.text.substring(int_3);
  167. }
  168. if (this.textPredicate.test(string_1)) {
  169. this.text = string_1;
  170. if (boolean_1) {
  171. this.moveCursor(int_1);
  172. }
  173. this.onChanged(this.text);
  174. }
  175. }
  176. }
  177. }
  178. public int method_1853(int int_1) {
  179. return this.method_1869(int_1, this.getCursor());
  180. }
  181. public int method_1869(int int_1, int int_2) {
  182. return this.method_1864(int_1, int_2, true);
  183. }
  184. public int method_1864(int int_1, int int_2, boolean boolean_1) {
  185. int int_3 = int_2;
  186. boolean boolean_2 = int_1 < 0;
  187. int int_4 = Math.abs(int_1);
  188. for(int int_5 = 0; int_5 < int_4; ++int_5) {
  189. if (!boolean_2) {
  190. int int_6 = this.text.length();
  191. int_3 = this.text.indexOf(32, int_3);
  192. if (int_3 == -1) {
  193. int_3 = int_6;
  194. } else {
  195. while (boolean_1 && int_3 < int_6 && this.text.charAt(int_3) == ' ') {
  196. ++int_3;
  197. }
  198. }
  199. } else {
  200. while (boolean_1 && int_3 > 0 && this.text.charAt(int_3 - 1) == ' ') {
  201. --int_3;
  202. }
  203. while (int_3 > 0 && this.text.charAt(int_3 - 1) != ' ') {
  204. --int_3;
  205. }
  206. }
  207. }
  208. return int_3;
  209. }
  210. public void moveCursor(int int_1) {
  211. this.method_1883(this.cursorMax + int_1);
  212. }
  213. public void method_1883(int int_1) {
  214. this.setCursor(int_1);
  215. if (!this.field_17037) {
  216. this.method_1884(this.cursorMax);
  217. }
  218. this.onChanged(this.text);
  219. }
  220. public void method_1870() {
  221. this.method_1883(0);
  222. }
  223. public void method_1872() {
  224. this.method_1883(this.text.length());
  225. }
  226. public boolean keyPressed(int int_1, int int_2, int int_3) {
  227. if (this.isVisible() && this.isFocused()) {
  228. this.field_17037 = Gui.isShiftPressed();
  229. if (Gui.isSelectAllShortcutPressed(int_1)) {
  230. this.method_1872();
  231. this.method_1884(0);
  232. return true;
  233. } else if (Gui.isCopyShortcutPressed(int_1)) {
  234. MinecraftClient.getInstance().keyboard.setClipboard(this.getSelectedText());
  235. return true;
  236. } else if (Gui.isPasteShortcutPressed(int_1)) {
  237. if (this.editable) {
  238. this.addText(MinecraftClient.getInstance().keyboard.getClipboard());
  239. }
  240. return true;
  241. } else if (Gui.isCutShortcutPressed(int_1)) {
  242. MinecraftClient.getInstance().keyboard.setClipboard(this.getSelectedText());
  243. if (this.editable) {
  244. this.addText("");
  245. }
  246. return true;
  247. } else {
  248. switch (int_1) {
  249. case 259:
  250. if (this.editable) {
  251. this.method_16873(-1);
  252. }
  253. return true;
  254. case 260:
  255. case 264:
  256. case 265:
  257. case 266:
  258. case 267:
  259. default:
  260. return int_1 != 256;
  261. case 261:
  262. if (this.editable) {
  263. this.method_16873(1);
  264. }
  265. return true;
  266. case 262:
  267. if (Gui.isControlPressed()) {
  268. this.method_1883(this.method_1853(1));
  269. } else {
  270. this.moveCursor(1);
  271. }
  272. return true;
  273. case 263:
  274. if (Gui.isControlPressed()) {
  275. this.method_1883(this.method_1853(-1));
  276. } else {
  277. this.moveCursor(-1);
  278. }
  279. return true;
  280. case 268:
  281. this.method_1870();
  282. return true;
  283. case 269:
  284. this.method_1872();
  285. return true;
  286. }
  287. }
  288. } else {
  289. return false;
  290. }
  291. }
  292. public boolean charTyped(char char_1, int int_1) {
  293. if (this.isVisible() && this.isFocused()) {
  294. if (SharedConstants.isValidChar(char_1)) {
  295. if (this.editable) {
  296. this.addText(Character.toString(char_1));
  297. }
  298. return true;
  299. } else {
  300. return false;
  301. }
  302. } else {
  303. return false;
  304. }
  305. }
  306. @Override
  307. public List<IWidget> getListeners() {
  308. return new ArrayList<>();
  309. }
  310. public boolean mouseClicked(double double_1, double double_2, int int_1) {
  311. if (!this.isVisible()) {
  312. return false;
  313. } else {
  314. boolean boolean_1 = double_1 >= (double) this.x && double_1 < (double) (this.x + this.width) && double_2 >= (double) this.y && double_2 < (double) (this.y + this.height);
  315. if (this.field_2096) {
  316. this.setFocused(boolean_1);
  317. }
  318. if (this.focused && boolean_1 && int_1 == 0) {
  319. int int_2 = MathHelper.floor(double_1) - this.x;
  320. if (this.hasBorder) {
  321. int_2 -= 4;
  322. }
  323. String string_1 = this.fontRenderer.method_1714(this.text.substring(this.field_2103), this.method_1859());
  324. this.method_1883(this.fontRenderer.method_1714(string_1, int_2).length() + this.field_2103);
  325. return true;
  326. } else {
  327. return false;
  328. }
  329. }
  330. }
  331. public void draw(int int_1, int int_2, float float_1) {
  332. if (this.isVisible()) {
  333. if (this.hasBorder()) {
  334. drawRect(this.x - 1, this.y - 1, this.x + this.width + 1, this.y + this.height + 1, -6250336);
  335. drawRect(this.x, this.y, this.x + this.width, this.y + this.height, -16777216);
  336. }
  337. int int_3 = this.editable ? this.field_2100 : this.field_2098;
  338. int int_4 = this.cursorMax - this.field_2103;
  339. int int_5 = this.cursorMin - this.field_2103;
  340. String string_1 = this.fontRenderer.method_1714(this.text.substring(this.field_2103), this.method_1859());
  341. boolean boolean_1 = int_4 >= 0 && int_4 <= string_1.length();
  342. boolean boolean_2 = this.focused && this.focusedTicks / 6 % 2 == 0 && boolean_1;
  343. int int_6 = this.hasBorder ? this.x + 4 : this.x;
  344. int int_7 = this.hasBorder ? this.y + (this.height - 8) / 2 : this.y;
  345. int int_8 = int_6;
  346. if (int_5 > string_1.length()) {
  347. int_5 = string_1.length();
  348. }
  349. if (!string_1.isEmpty()) {
  350. String string_2 = boolean_1 ? string_1.substring(0, int_4) : string_1;
  351. int_8 = this.fontRenderer.drawWithShadow((String) this.field_2099.apply(string_2, this.field_2103), (float) int_6, (float) int_7, int_3);
  352. }
  353. boolean boolean_3 = this.cursorMax < this.text.length() || this.text.length() >= this.getMaxLength();
  354. int int_9 = int_8;
  355. if (!boolean_1) {
  356. int_9 = int_4 > 0 ? int_6 + this.width : int_6;
  357. } else if (boolean_3) {
  358. int_9 = int_8 - 1;
  359. --int_8;
  360. }
  361. if (!string_1.isEmpty() && boolean_1 && int_4 < string_1.length()) {
  362. this.fontRenderer.drawWithShadow((String) this.field_2099.apply(string_1.substring(int_4), this.cursorMax), (float) int_8, (float) int_7, int_3);
  363. }
  364. if (!boolean_3 && this.suggestion != null) {
  365. this.fontRenderer.drawWithShadow(this.suggestion, (float) (int_9 - 1), (float) int_7, -8355712);
  366. }
  367. int var10002;
  368. int var10003;
  369. if (boolean_2) {
  370. if (boolean_3) {
  371. int var10001 = int_7 - 1;
  372. var10002 = int_9 + 1;
  373. var10003 = int_7 + 1;
  374. this.fontRenderer.getClass();
  375. Drawable.drawRect(int_9, var10001, var10002, var10003 + 9, -3092272);
  376. } else {
  377. this.fontRenderer.drawWithShadow("_", (float) int_9, (float) int_7, int_3);
  378. }
  379. }
  380. if (int_5 != int_4) {
  381. int int_10 = int_6 + this.fontRenderer.getStringWidth(string_1.substring(0, int_5));
  382. var10002 = int_7 - 1;
  383. var10003 = int_10 - 1;
  384. int var10004 = int_7 + 1;
  385. this.fontRenderer.getClass();
  386. this.method_1886(int_9, var10002, var10003, var10004 + 9);
  387. }
  388. }
  389. }
  390. private void method_1886(int int_1, int int_2, int int_3, int int_4) {
  391. int int_6;
  392. if (int_1 < int_3) {
  393. int_6 = int_1;
  394. int_1 = int_3;
  395. int_3 = int_6;
  396. }
  397. if (int_2 < int_4) {
  398. int_6 = int_2;
  399. int_2 = int_4;
  400. int_4 = int_6;
  401. }
  402. if (int_3 > this.x + this.width) {
  403. int_3 = this.x + this.width;
  404. }
  405. if (int_1 > this.x + this.width) {
  406. int_1 = this.x + this.width;
  407. }
  408. Tessellator tessellator_1 = Tessellator.getInstance();
  409. BufferBuilder bufferBuilder_1 = tessellator_1.getBufferBuilder();
  410. GlStateManager.color4f(0.0F, 0.0F, 255.0F, 255.0F);
  411. GlStateManager.disableTexture();
  412. GlStateManager.enableColorLogicOp();
  413. GlStateManager.logicOp(GlStateManager.LogicOp.OR_REVERSE);
  414. bufferBuilder_1.begin(7, VertexFormats.POSITION);
  415. bufferBuilder_1.vertex((double) int_1, (double) int_4, 0.0D).next();
  416. bufferBuilder_1.vertex((double) int_3, (double) int_4, 0.0D).next();
  417. bufferBuilder_1.vertex((double) int_3, (double) int_2, 0.0D).next();
  418. bufferBuilder_1.vertex((double) int_1, (double) int_2, 0.0D).next();
  419. tessellator_1.draw();
  420. GlStateManager.disableColorLogicOp();
  421. GlStateManager.enableTexture();
  422. }
  423. public int getMaxLength() {
  424. return this.maxLength;
  425. }
  426. public void setMaxLength(int int_1) {
  427. this.maxLength = int_1;
  428. if (this.text.length() > int_1) {
  429. this.text = this.text.substring(0, int_1);
  430. this.onChanged(this.text);
  431. }
  432. }
  433. public int getCursor() {
  434. return this.cursorMax;
  435. }
  436. public void setCursor(int int_1) {
  437. this.cursorMax = MathHelper.clamp(int_1, 0, this.text.length());
  438. }
  439. public boolean hasBorder() {
  440. return this.hasBorder;
  441. }
  442. public void setHasBorder(boolean boolean_1) {
  443. this.hasBorder = boolean_1;
  444. }
  445. public void method_1868(int int_1) {
  446. this.field_2100 = int_1;
  447. }
  448. public void method_1860(int int_1) {
  449. this.field_2098 = int_1;
  450. }
  451. public void setHasFocus(boolean boolean_1) {
  452. this.setFocused(boolean_1);
  453. }
  454. public boolean hasFocus() {
  455. return true;
  456. }
  457. public boolean isFocused() {
  458. return this.focused;
  459. }
  460. public void setFocused(boolean boolean_1) {
  461. if (boolean_1 && !this.focused) {
  462. this.focusedTicks = 0;
  463. }
  464. this.focused = boolean_1;
  465. }
  466. public void setIsEditable(boolean boolean_1) {
  467. this.editable = boolean_1;
  468. }
  469. public int method_1859() {
  470. return this.hasBorder() ? this.width - 8 : this.width;
  471. }
  472. public void method_1884(int int_1) {
  473. int int_2 = this.text.length();
  474. this.cursorMin = MathHelper.clamp(int_1, 0, int_2);
  475. if (this.fontRenderer != null) {
  476. if (this.field_2103 > int_2) {
  477. this.field_2103 = int_2;
  478. }
  479. int int_3 = this.method_1859();
  480. String string_1 = this.fontRenderer.method_1714(this.text.substring(this.field_2103), int_3);
  481. int int_4 = string_1.length() + this.field_2103;
  482. if (this.cursorMin == this.field_2103) {
  483. this.field_2103 -= this.fontRenderer.method_1711(this.text, int_3, true).length();
  484. }
  485. if (this.cursorMin > int_4) {
  486. this.field_2103 += this.cursorMin - int_4;
  487. } else if (this.cursorMin <= this.field_2103) {
  488. this.field_2103 -= this.field_2103 - this.cursorMin;
  489. }
  490. this.field_2103 = MathHelper.clamp(this.field_2103, 0, int_2);
  491. }
  492. }
  493. public void method_1856(boolean boolean_1) {
  494. this.field_2096 = boolean_1;
  495. }
  496. public boolean isVisible() {
  497. return this.visible;
  498. }
  499. public void setVisible(boolean boolean_1) {
  500. this.visible = boolean_1;
  501. }
  502. public void setSuggestion(String string_1) {
  503. this.suggestion = string_1;
  504. }
  505. public int method_1889(int int_1) {
  506. return int_1 > this.text.length() ? this.x : this.x + this.fontRenderer.getStringWidth(this.text.substring(0, int_1));
  507. }
  508. public void setX(int int_1) {
  509. this.x = int_1;
  510. }
  511. }