You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

137 lines
2.7KB

  1. #include "widgets.hpp"
  2. // for gVg
  3. #include "gui.hpp"
  4. // for key codes
  5. #include <GLFW/glfw3.h>
  6. namespace rack {
  7. void TextField::draw(NVGcontext *vg) {
  8. BNDwidgetState state;
  9. if (this == gFocusedWidget)
  10. state = BND_ACTIVE;
  11. else if (this == gHoveredWidget)
  12. state = BND_HOVER;
  13. else
  14. state = BND_DEFAULT;
  15. bndTextField(vg, 0.0, 0.0, box.size.x, box.size.y, BND_CORNER_NONE, state, -1, text.c_str(), begin, end);
  16. // Draw placeholder text
  17. if (text.empty() && state != BND_ACTIVE) {
  18. bndIconLabelCaret(vg, 0.0, 0.0, box.size.x, box.size.y, -1, bndGetTheme()->textFieldTheme.itemColor, 13, placeholder.c_str(), bndGetTheme()->textFieldTheme.itemColor, 0, -1);
  19. }
  20. }
  21. Widget *TextField::onMouseDown(Vec pos, int button) {
  22. end = begin = bndTextFieldTextPosition(gVg, 0.0, 0.0, box.size.x, box.size.y, -1, text.c_str(), pos.x, pos.y);
  23. return OpaqueWidget::onMouseDown(pos, button);
  24. }
  25. bool TextField::onFocusText(int codepoint) {
  26. char c = codepoint;
  27. std::string newText(1, c);
  28. insertText(newText);
  29. return true;
  30. }
  31. bool TextField::onFocusKey(int key) {
  32. switch (key) {
  33. case GLFW_KEY_BACKSPACE:
  34. if (begin < end) {
  35. text.erase(begin, end - begin);
  36. onTextChange();
  37. }
  38. else {
  39. begin--;
  40. if (begin >= 0) {
  41. text.erase(begin, 1);
  42. onTextChange();
  43. }
  44. }
  45. end = begin;
  46. break;
  47. case GLFW_KEY_DELETE:
  48. if (begin < end) {
  49. text.erase(begin, end - begin);
  50. onTextChange();
  51. }
  52. else {
  53. text.erase(begin, 1);
  54. onTextChange();
  55. }
  56. end = begin;
  57. break;
  58. case GLFW_KEY_LEFT:
  59. if (begin < end) {
  60. }
  61. else {
  62. begin--;
  63. }
  64. end = begin;
  65. break;
  66. case GLFW_KEY_RIGHT:
  67. if (begin < end) {
  68. begin = end;
  69. }
  70. else {
  71. begin++;
  72. }
  73. end = begin;
  74. break;
  75. case GLFW_KEY_HOME:
  76. end = begin = 0;
  77. break;
  78. case GLFW_KEY_END:
  79. end = begin = text.size();
  80. break;
  81. case GLFW_KEY_V:
  82. if (guiIsModPressed()) {
  83. const char *newText = glfwGetClipboardString(gWindow);
  84. if (newText)
  85. insertText(newText);
  86. }
  87. break;
  88. case GLFW_KEY_C:
  89. if (guiIsModPressed()) {
  90. if (begin < end) {
  91. std::string selectedText = text.substr(begin, end - begin);
  92. glfwSetClipboardString(gWindow, selectedText.c_str());
  93. }
  94. }
  95. break;
  96. case GLFW_KEY_ENTER:
  97. if (multiline) {
  98. insertText("\n");
  99. }
  100. else {
  101. onAction();
  102. }
  103. break;
  104. }
  105. begin = mini(maxi(begin, 0), text.size());
  106. end = mini(maxi(end, 0), text.size());
  107. return true;
  108. }
  109. bool TextField::onFocus() {
  110. begin = 0;
  111. end = text.size();
  112. return true;
  113. }
  114. void TextField::insertText(std::string newText) {
  115. if (begin < end)
  116. text.erase(begin, end - begin);
  117. text.insert(begin, newText);
  118. begin += newText.size();
  119. end = begin;
  120. onTextChange();
  121. }
  122. } // namespace rack