2
0

custom_input_box.c 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. /*******************************************************************************************
  2. *
  3. * raygui - basic calculator app with custom input box for float values
  4. *
  5. * DEPENDENCIES:
  6. * raylib 4.5 - Windowing/input management and drawing.
  7. * raygui 3.5 - Immediate-mode GUI controls.
  8. *
  9. * COMPILATION (Windows - MinGW):
  10. * gcc -o $(NAME_PART).exe $(FILE_NAME) -I../../src -lraylib -lopengl32 -lgdi32 -std=c99
  11. *
  12. **********************************************************************************************/
  13. #include "raylib.h"
  14. #define RAYGUI_IMPLEMENTATION
  15. #include "../../src/raygui.h"
  16. int guiFloatingPointIndex = 0; // Global variable shared by all GuiFloatBox()
  17. int GuiFloatBox(Rectangle bounds, const char* text, float* value, int minValue, int maxValue, bool editMode); // Custom input box that works with float values. Basicly GuiValueBox(), but with some changes
  18. int main()
  19. {
  20. InitWindow(250, 100, "Basic calculator");
  21. // General variables
  22. SetTargetFPS(60);
  23. float variableA = 0.0f;
  24. float variableB = 0.0f;
  25. float result = 0.0f;
  26. char operation[2];
  27. operation[0] = '+';
  28. operation[1] = '\0';
  29. bool variableAMode = false;
  30. bool variableBMode = false;
  31. //--------------------------------------------------------------------------------------
  32. // Main game loop
  33. while (!WindowShouldClose())
  34. {
  35. // Draw
  36. //----------------------------------------------------------------------------------
  37. BeginDrawing();
  38. ClearBackground(RAYWHITE);
  39. if (GuiFloatBox((Rectangle){ 10, 10, 100, 20 }, NULL, &variableA, -1000000.0, 1000000.0, variableAMode)) variableAMode = !variableAMode;
  40. if (GuiFloatBox((Rectangle){ 140, 10, 100, 20 }, NULL, &variableB, -1000000.0, 1000000.0, variableBMode)) variableBMode = !variableBMode;
  41. if (GuiButton((Rectangle){ 10, 70, 50, 20 }, "+"))
  42. {
  43. result = variableA + variableB;
  44. operation[0] = '+';
  45. }
  46. if (GuiButton((Rectangle){ 70, 70, 50, 20 }, "-"))
  47. {
  48. result = variableA - variableB;
  49. operation[0] = '-';
  50. }
  51. if (GuiButton((Rectangle){ 130, 70, 50, 20 }, "*"))
  52. {
  53. result = variableA * variableB;
  54. operation[0] = '*';
  55. }
  56. if (GuiButton((Rectangle){ 190, 70, 50, 20 }, "/"))
  57. {
  58. result = variableA / variableB;
  59. operation[0] = '/';
  60. }
  61. DrawText(operation, 123, 15, 10, DARKGRAY);
  62. GuiFloatBox((Rectangle){ 55, 40, 135, 20 }, "= ", &result, -2000000.0, 2000000.0, false);
  63. EndDrawing();
  64. //----------------------------------------------------------------------------------
  65. }
  66. CloseWindow();
  67. }
  68. // Float Box control, updates input text with numbers
  69. int GuiFloatBox(Rectangle bounds, const char* text, float* value, int minValue, int maxValue, bool editMode)
  70. {
  71. #if !defined(RAYGUI_VALUEBOX_MAX_CHARS)
  72. #define RAYGUI_VALUEBOX_MAX_CHARS 32
  73. #endif
  74. int result = 0;
  75. GuiState state = guiState;
  76. char textValue[RAYGUI_VALUEBOX_MAX_CHARS + 1] = "\0";
  77. Rectangle textBounds = { 0 };
  78. if (text != NULL)
  79. {
  80. textBounds.width = (float)GetTextWidth(text) + 2;
  81. textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE);
  82. textBounds.x = bounds.x + bounds.width + GuiGetStyle(VALUEBOX, TEXT_PADDING);
  83. textBounds.y = bounds.y + bounds.height / 2.0f - GuiGetStyle(DEFAULT, TEXT_SIZE) / 2.0f;
  84. if (GuiGetStyle(VALUEBOX, TEXT_ALIGNMENT) == TEXT_ALIGN_LEFT) textBounds.x = bounds.x - textBounds.width - GuiGetStyle(VALUEBOX, TEXT_PADDING);
  85. }
  86. // Update control
  87. //--------------------------------------------------------------------
  88. if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode)
  89. {
  90. Vector2 mousePoint = GetMousePosition();
  91. if (*value >= 0) sprintf(textValue, "+%.3f", *value);
  92. else sprintf(textValue, "%.3f", *value);
  93. bool valueHasChanged = false;
  94. int keyCount = (int)strlen(textValue) - guiFloatingPointIndex;
  95. if (editMode)
  96. {
  97. state = STATE_PRESSED;
  98. // Only allow keys in range [48..57]
  99. if (keyCount < RAYGUI_VALUEBOX_MAX_CHARS)
  100. {
  101. if (GetTextWidth(textValue) < bounds.width)
  102. {
  103. int key = GetCharPressed();
  104. if ((key >= 48) && (key <= 57) && guiFloatingPointIndex)
  105. {
  106. if (guiFloatingPointIndex && guiFloatingPointIndex != 4) guiFloatingPointIndex--;
  107. textValue[keyCount] = (char)key;
  108. textValue[++keyCount] = '\0';
  109. valueHasChanged = true;
  110. }
  111. }
  112. }
  113. // Delete text
  114. if (keyCount > 0)
  115. {
  116. if (IsKeyPressed(KEY_BACKSPACE))
  117. {
  118. if (guiFloatingPointIndex < 4) guiFloatingPointIndex++;
  119. keyCount--;
  120. textValue[keyCount] = '\0';
  121. valueHasChanged = true;
  122. }
  123. }
  124. // Change sign
  125. if (IsKeyPressed(KEY_MINUS))
  126. {
  127. if (textValue[0] == '+') textValue[0] = '-';
  128. else if (textValue[0] == '-') textValue[0] = '+';
  129. valueHasChanged = true;
  130. }
  131. // Add decimal separator
  132. if ((IsKeyPressed(KEY_COMMA) || IsKeyPressed(KEY_PERIOD)) && guiFloatingPointIndex == 4)
  133. {
  134. guiFloatingPointIndex--;
  135. valueHasChanged = true;
  136. }
  137. if (valueHasChanged)
  138. {
  139. *value = atof(textValue);
  140. }
  141. if (IsKeyPressed(KEY_ENTER) || (!CheckCollisionPointRec(mousePoint, bounds) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON)))
  142. {
  143. guiFloatingPointIndex = 0;
  144. result = 1;
  145. }
  146. }
  147. else
  148. {
  149. if (*value > maxValue) *value = maxValue;
  150. else if (*value < minValue) *value = minValue;
  151. if (CheckCollisionPointRec(mousePoint, bounds))
  152. {
  153. state = STATE_FOCUSED;
  154. if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) result = 1;
  155. }
  156. }
  157. }
  158. //--------------------------------------------------------------------
  159. // Draw control
  160. //--------------------------------------------------------------------
  161. Color baseColor = BLANK;
  162. sprintf(textValue, "%.3f", *value);
  163. if (state == STATE_PRESSED)
  164. {
  165. baseColor = GetColor(GuiGetStyle(VALUEBOX, BASE_COLOR_PRESSED));
  166. textValue[(int)strlen(textValue) - guiFloatingPointIndex] = '\0';
  167. }
  168. else if (state == STATE_DISABLED) baseColor = GetColor(GuiGetStyle(VALUEBOX, BASE_COLOR_DISABLED));
  169. // WARNING: BLANK color does not work properly with Fade()
  170. GuiDrawRectangle(bounds, GuiGetStyle(VALUEBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(VALUEBOX, BORDER + (state * 3))), guiAlpha), baseColor);
  171. GuiDrawText(textValue, GetTextBounds(VALUEBOX, bounds), TEXT_ALIGN_CENTER, Fade(GetColor(GuiGetStyle(VALUEBOX, TEXT + (state * 3))), guiAlpha));
  172. // Draw cursor
  173. if (editMode)
  174. {
  175. // NOTE: ValueBox internal text is always centered
  176. Rectangle cursor = { bounds.x + GetTextWidth(textValue) / 2.0f + bounds.width / 2.0f + 1, bounds.y + 2.0f * GuiGetStyle(VALUEBOX, BORDER_WIDTH), 4, bounds.height - 4 * GuiGetStyle(VALUEBOX, BORDER_WIDTH) };
  177. GuiDrawRectangle(cursor, 0, BLANK, Fade(GetColor(GuiGetStyle(VALUEBOX, BORDER_COLOR_PRESSED)), guiAlpha));
  178. }
  179. // Draw text label if provided
  180. GuiDrawText(text, textBounds, (GuiGetStyle(VALUEBOX, TEXT_ALIGNMENT) == TEXT_ALIGN_RIGHT) ? TEXT_ALIGN_LEFT : TEXT_ALIGN_RIGHT, Fade(GetColor(GuiGetStyle(LABEL, TEXT + (state * 3))), guiAlpha));
  181. //--------------------------------------------------------------------
  182. return result;
  183. }