TextFieldWidget.java 20 KB

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