imgui_utils.cpp 3.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. /*******************************************************************************************
  2. *
  3. * raylib-extras [ImGui] example - asset browser
  4. *
  5. * This is a more complex ImGui Integration
  6. * It shows how to build windows on top of 2d and 3d views using a render texture
  7. *
  8. * Copyright (c) 2024 Jeffery Myers
  9. *
  10. ********************************************************************************************/
  11. #include "imgui_utils.h"
  12. #include "imgui.h"
  13. #include "imgui_internal.h"
  14. namespace ImGuiUtils
  15. {
  16. bool IsSpace(char aCharacter)
  17. {
  18. // all space characters are values 32 or less (space is 32)
  19. // so we can convert them to a bitmask and use a single condition
  20. const int mask = (1 << (' ' - 1)) | (1 << ('\f' - 1)) | (1 << ('\n' - 1)) | (1 << ('\r' - 1)) | (1 << ('\t' - 1)) | (1 << ('\v' - 1));
  21. return (mask & (1 << ((aCharacter && aCharacter <= 32) * (aCharacter - 1)))) != 0;
  22. }
  23. //-------------------------------------------------------------------------------------------------
  24. // Todo: Add support for soft-hyphens when using word boundaries?
  25. //-------------------------------------------------------------------------------------------------
  26. void TextWithEllipsis(const char* string, float aMaxWidth, bool useWordBoundaries, float aSpacing)
  27. {
  28. char const* partStart = string;
  29. char const* partEnd = string;
  30. ImWchar elipsisChar = ImGui::GetFont()->EllipsisChar;
  31. char elipsisText[8];
  32. ImTextStrToUtf8(elipsisText, sizeof(elipsisText), &elipsisChar, (&elipsisChar) + 1);
  33. if (aSpacing < 0.0f) aSpacing = ImGui::GetStyle().ItemSpacing.x;
  34. float const ellipsisWidth = ImGui::CalcTextSize(elipsisText).x + aSpacing;
  35. float width = 0;
  36. bool addElipsis = false;
  37. while (*partStart != 0 )
  38. {
  39. // Add space to next segment
  40. while (IsSpace(*partEnd))
  41. partEnd++;
  42. if (useWordBoundaries)
  43. {
  44. // get next 'word' by looking for space after non-space
  45. while (*partEnd != 0 && !IsSpace(*partEnd))
  46. ++partEnd;
  47. }
  48. else
  49. {
  50. if (*partEnd != 0)
  51. ++partEnd;
  52. }
  53. ImVec2 const wordSize = ImGui::CalcTextSize(partStart, partEnd);
  54. // Clearly we have space for this word so just add it
  55. if (wordSize.x + width + ellipsisWidth < aMaxWidth)
  56. {
  57. width += wordSize.x;
  58. partStart = partEnd;
  59. }
  60. // If we're just at the end of the word and we just fit then we can commit here
  61. else if (*partEnd == 0 && wordSize.x + width < aMaxWidth)
  62. {
  63. width += wordSize.x;
  64. partStart = partEnd;
  65. }
  66. // we're done so add elipsis where the current segment starts
  67. else
  68. {
  69. addElipsis = true;
  70. break;
  71. }
  72. }
  73. ImGui::TextUnformatted(string, partStart);
  74. if (addElipsis)
  75. {
  76. ImGui::SameLine(0.0f, aSpacing);
  77. ImGui::TextUnformatted(elipsisText);
  78. }
  79. }
  80. }