mirror of
https://github.com/Drezil/imgui.git
synced 2024-11-22 03:47:00 +00:00
ImStrv: various tweaks and fixes. removed ImGuiTextRange from ImGuiTextFilter, fix test engine hooks, removed constructor only used twice.
This commit is contained in:
parent
4e894ae1d9
commit
194bf63863
80
imgui.cpp
80
imgui.cpp
@ -2327,41 +2327,39 @@ bool ImGuiTextFilter::Draw(ImStrv label, float width)
|
||||
return value_changed;
|
||||
}
|
||||
|
||||
void ImGuiTextFilter::ImGuiTextRange::split(char separator, ImVector<ImGuiTextRange>* out) const
|
||||
static void ImStrplit(ImStrv in, char separator, ImVector<ImStrv>* out)
|
||||
{
|
||||
out->resize(0);
|
||||
const char* wb = b;
|
||||
const char* wb = in.Begin;
|
||||
const char* we = wb;
|
||||
while (we < e)
|
||||
while (we < in.End)
|
||||
{
|
||||
if (*we == separator)
|
||||
{
|
||||
out->push_back(ImGuiTextRange(wb, we));
|
||||
out->push_back(ImStrv(wb, we));
|
||||
wb = we + 1;
|
||||
}
|
||||
we++;
|
||||
}
|
||||
if (wb != we)
|
||||
out->push_back(ImGuiTextRange(wb, we));
|
||||
out->push_back(ImStrv(wb, we));
|
||||
}
|
||||
|
||||
void ImGuiTextFilter::Build()
|
||||
{
|
||||
Filters.resize(0);
|
||||
ImGuiTextRange input_range(InputBuf, InputBuf + strlen(InputBuf));
|
||||
input_range.split(',', &Filters);
|
||||
ImStrplit(ImStrv(InputBuf, InputBuf + strlen(InputBuf)), ',', &Filters);
|
||||
|
||||
CountGrep = 0;
|
||||
for (int i = 0; i != Filters.Size; i++)
|
||||
{
|
||||
ImGuiTextRange& f = Filters[i];
|
||||
while (f.b < f.e && ImCharIsBlankA(f.b[0]))
|
||||
f.b++;
|
||||
while (f.e > f.b && ImCharIsBlankA(f.e[-1]))
|
||||
f.e--;
|
||||
ImStrv& f = Filters[i];
|
||||
while (f.Begin < f.End && ImCharIsBlankA(f.Begin[0]))
|
||||
f.Begin++;
|
||||
while (f.End > f.Begin && ImCharIsBlankA(f.End[-1]))
|
||||
f.End--;
|
||||
if (f.empty())
|
||||
continue;
|
||||
if (Filters[i].b[0] != '-')
|
||||
if (Filters[i].Begin[0] != '-')
|
||||
CountGrep += 1;
|
||||
}
|
||||
}
|
||||
@ -2372,23 +2370,23 @@ bool ImGuiTextFilter::PassFilter(ImStrv text) const
|
||||
return true;
|
||||
|
||||
if (!text)
|
||||
text.Begin = text.End = "";
|
||||
text = "";
|
||||
|
||||
for (int i = 0; i != Filters.Size; i++)
|
||||
{
|
||||
const ImGuiTextRange& f = Filters[i];
|
||||
const ImStrv& f = Filters[i];
|
||||
if (f.empty())
|
||||
continue;
|
||||
if (f.b[0] == '-')
|
||||
if (f.Begin[0] == '-')
|
||||
{
|
||||
// Subtract
|
||||
if (ImStristr(text.Begin, text.End, f.b + 1, f.e) != NULL)
|
||||
if (ImStristr(text.Begin, text.End, f.Begin + 1, f.End) != NULL)
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Grep
|
||||
if (ImStristr(text.Begin, text.End, f.b, f.e) != NULL)
|
||||
if (ImStristr(text.Begin, text.End, f.Begin, f.End) != NULL)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -2419,6 +2417,8 @@ char ImGuiTextBuffer::EmptyString[1] = { 0 };
|
||||
void ImGuiTextBuffer::append(ImStrv str)
|
||||
{
|
||||
int len = (int)str.length();
|
||||
if (len == 0)
|
||||
return;
|
||||
|
||||
// Add zero-terminator the first time
|
||||
const int write_off = (Buf.Size != 0) ? Buf.Size : 1;
|
||||
@ -2430,8 +2430,7 @@ void ImGuiTextBuffer::append(ImStrv str)
|
||||
}
|
||||
|
||||
Buf.resize(needed_sz);
|
||||
if (len > 0)
|
||||
memcpy(&Buf[write_off - 1], str.Begin, (size_t)len);
|
||||
memcpy(&Buf[write_off - 1], str.Begin, (size_t)len);
|
||||
Buf[write_off - 1 + len] = 0;
|
||||
}
|
||||
|
||||
@ -3023,10 +3022,7 @@ const char* ImGui::GetStyleColorName(ImGuiCol idx)
|
||||
const char* ImGui::FindRenderedTextEnd(ImStrv text)
|
||||
{
|
||||
const char* text_display_end = text.Begin;
|
||||
if (!text.End)
|
||||
text.End = (const char*)-1;
|
||||
|
||||
while (text_display_end < text.End && *text_display_end != '\0' && (text_display_end[0] != '#' || text_display_end[1] != '#'))
|
||||
while (text_display_end < text.End && (text_display_end[0] != '#' || text_display_end[1] != '#'))
|
||||
text_display_end++;
|
||||
return text_display_end;
|
||||
}
|
||||
@ -3039,17 +3035,14 @@ void ImGui::RenderText(ImVec2 pos, ImStrv text, bool hide_text_after_hash)
|
||||
ImGuiWindow* window = g.CurrentWindow;
|
||||
|
||||
// Hide anything after a '##' string
|
||||
const char* text_display_end;
|
||||
if (hide_text_after_hash)
|
||||
text_display_end = FindRenderedTextEnd(text);
|
||||
else
|
||||
text_display_end = text.End;
|
||||
text.End = FindRenderedTextEnd(text);
|
||||
|
||||
if (text.Begin != text_display_end)
|
||||
if (text.Begin != text.End)
|
||||
{
|
||||
window->DrawList->AddText(g.Font, g.FontSize, pos, GetColorU32(ImGuiCol_Text), ImStrv(text.Begin, text_display_end));
|
||||
window->DrawList->AddText(g.Font, g.FontSize, pos, GetColorU32(ImGuiCol_Text), text);
|
||||
if (g.LogEnabled)
|
||||
LogRenderedText(&pos, ImStrv(text.Begin, text_display_end));
|
||||
LogRenderedText(&pos, text);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3099,16 +3092,16 @@ void ImGui::RenderTextClippedEx(ImDrawList* draw_list, const ImVec2& pos_min, co
|
||||
void ImGui::RenderTextClipped(const ImVec2& pos_min, const ImVec2& pos_max, ImStrv text, const ImVec2* text_size_if_known, const ImVec2& align, const ImRect* clip_rect)
|
||||
{
|
||||
// Hide anything after a '##' string
|
||||
const char* text_display_end = FindRenderedTextEnd(text);
|
||||
const int text_len = (int)(text_display_end - text.Begin);
|
||||
if (text_len == 0)
|
||||
// FIXME-IMSTR: This is not new but should be moved out of there.
|
||||
text.End = FindRenderedTextEnd(text);
|
||||
if (text.Begin == text.End)
|
||||
return;
|
||||
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiWindow* window = g.CurrentWindow;
|
||||
RenderTextClippedEx(window->DrawList, pos_min, pos_max, ImStrv(text.Begin, text_display_end), text_size_if_known, align, clip_rect);
|
||||
RenderTextClippedEx(window->DrawList, pos_min, pos_max, text, text_size_if_known, align, clip_rect);
|
||||
if (g.LogEnabled)
|
||||
LogRenderedText(&pos_min, ImStrv(text.Begin, text_display_end));
|
||||
LogRenderedText(&pos_min, text);
|
||||
}
|
||||
|
||||
// Another overly complex function until we reorganize everything into a nice all-in-one helper.
|
||||
@ -3117,8 +3110,6 @@ void ImGui::RenderTextClipped(const ImVec2& pos_min, const ImVec2& pos_max, ImSt
|
||||
void ImGui::RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min, const ImVec2& pos_max, float clip_max_x, float ellipsis_max_x, ImStrv text, const ImVec2* text_size_if_known)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
if (text.End == NULL)
|
||||
text.End = FindRenderedTextEnd(text);
|
||||
const ImVec2 text_size = text_size_if_known ? *text_size_if_known : CalcTextSize(text, false, 0.0f);
|
||||
|
||||
//draw_list->AddLine(ImVec2(pos_max.x, pos_min.y - 4), ImVec2(pos_max.x, pos_max.y + 4), IM_COL32(0, 0, 255, 255));
|
||||
@ -6039,7 +6030,7 @@ bool ImGui::Begin(ImStrv name, bool* p_open, ImGuiWindowFlags flags)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
const ImGuiStyle& style = g.Style;
|
||||
IM_ASSERT(name.Begin != NULL); // Window name required
|
||||
IM_ASSERT(name.Begin != name.End); // Window name required
|
||||
IM_ASSERT(g.WithinFrameScope); // Forgot to call ImGui::NewFrame()
|
||||
IM_ASSERT(g.FrameCountEnded != g.FrameCount); // Called ImGui::Render() or ImGui::EndFrame() and haven't called ImGui::NewFrame() again yet
|
||||
|
||||
@ -11179,7 +11170,7 @@ bool ImGui::SetDragDropPayload(ImStrv type, const void* data, size_t data_size,
|
||||
if (cond == 0)
|
||||
cond = ImGuiCond_Always;
|
||||
|
||||
IM_ASSERT(type.Begin != NULL && "Payload type can not be empty");
|
||||
IM_ASSERT(type.End - type.Begin > 0 && "Payload type can not be empty");
|
||||
IM_ASSERT(type.End - type.Begin < IM_ARRAYSIZE(payload.DataType) && "Payload type can be at most 32 characters long");
|
||||
IM_ASSERT((data != NULL && data_size > 0) || (data == NULL && data_size == 0));
|
||||
IM_ASSERT(cond == ImGuiCond_Always || cond == ImGuiCond_Once);
|
||||
@ -11704,12 +11695,12 @@ void ImGui::LoadIniSettingsFromDisk(ImStrv ini_filename)
|
||||
char* file_data = (char*)ImFileLoadToMemory(ini_filename, "rb", &file_data_size);
|
||||
if (!file_data)
|
||||
return;
|
||||
LoadIniSettingsFromMemory(file_data, (size_t)file_data_size);
|
||||
LoadIniSettingsFromMemory(ImStrv(file_data, file_data + file_data_size));
|
||||
IM_FREE(file_data);
|
||||
}
|
||||
|
||||
// Zero-tolerance, no error reporting, cheap .ini parsing
|
||||
void ImGui::LoadIniSettingsFromMemory(ImStrv ini_data, size_t ini_size)
|
||||
void ImGui::LoadIniSettingsFromMemory(ImStrv ini_data)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
IM_ASSERT(g.Initialized);
|
||||
@ -11718,8 +11709,7 @@ void ImGui::LoadIniSettingsFromMemory(ImStrv ini_data, size_t ini_size)
|
||||
|
||||
// For user convenience, we allow passing a non zero-terminated string (hence the ini_size parameter).
|
||||
// For our convenience and to make the code simpler, we'll also write zero-terminators within the buffer. So let's create a writable copy..
|
||||
if (ini_size == 0)
|
||||
ini_size = ini_data.length();
|
||||
const int ini_size = (int)ini_data.length();
|
||||
g.SettingsIniData.Buf.resize((int)ini_size + 1);
|
||||
char* const buf = g.SettingsIniData.Buf.Data;
|
||||
char* const buf_end = buf + ini_size;
|
||||
|
26
imgui.h
26
imgui.h
@ -278,13 +278,14 @@ struct ImStrv
|
||||
ImStrv() { Begin = End = NULL; }
|
||||
ImStrv(const char* b) { Begin = b; End = b ? b + strlen(b) : NULL; }
|
||||
ImStrv(const char* b, const char* e){ Begin = b; End = e ? e : b + strlen(b); }
|
||||
ImStrv(const char* b, size_t size) { Begin = b; End = b + size; }
|
||||
inline size_t length() const { return (size_t)(End - Begin); }
|
||||
inline bool empty() const { return Begin == End; } // == "" or == NULL
|
||||
inline operator bool() const { return Begin != NULL; } // != NULL
|
||||
#ifdef IM_IMSTR_CLASS_EXTRA
|
||||
IM_IMSTR_CLASS_EXTRA // Define additional constructors and implicit cast operators in imconfig.h to convert back and forth between your string types and ImStrv.
|
||||
#endif
|
||||
// private: bool operator==(ImStrv) { return false; } // [DEBUG] Uncomment to catch undesirable uses of operators
|
||||
// private: bool operator!=(ImStrv) { return false; }
|
||||
};
|
||||
|
||||
IM_MSVC_RUNTIME_CHECKS_RESTORE
|
||||
@ -939,7 +940,7 @@ namespace ImGui
|
||||
// - Set io.IniFilename to NULL to load/save manually. Read io.WantSaveIniSettings description about handling .ini saving manually.
|
||||
// - Important: default value "imgui.ini" is relative to current working dir! Most apps will want to lock this to an absolute path (e.g. same path as executables).
|
||||
IMGUI_API void LoadIniSettingsFromDisk(ImStrv ini_filename); // call after CreateContext() and before the first call to NewFrame(). NewFrame() automatically calls LoadIniSettingsFromDisk(io.IniFilename).
|
||||
IMGUI_API void LoadIniSettingsFromMemory(ImStrv ini_data, size_t ini_size= 0); // call after CreateContext() and before the first call to NewFrame() to provide .ini data from your own data source.
|
||||
IMGUI_API void LoadIniSettingsFromMemory(ImStrv ini_data); // call after CreateContext() and before the first call to NewFrame() to provide .ini data from your own data source.
|
||||
IMGUI_API void SaveIniSettingsToDisk(ImStrv ini_filename); // this is automatically called (if io.IniFilename is not empty) a few seconds after any modification that should be reflected in the .ini file (and also by DestroyContext).
|
||||
IMGUI_API const char* SaveIniSettingsToMemory(size_t* out_ini_size = NULL); // return a zero-terminated string with the .ini data which you can save by your own mean. call when io.WantSaveIniSettings is set, then save data by your own mean and clear io.WantSaveIniSettings.
|
||||
|
||||
@ -2103,7 +2104,7 @@ struct ImGuiInputTextCallbackData
|
||||
ImWchar EventChar; // Character input // Read-write // [CharFilter] Replace character with another one, or set to zero to drop. return 1 is equivalent to setting EventChar=0;
|
||||
ImGuiKey EventKey; // Key pressed (Up/Down/TAB) // Read-only // [Completion,History]
|
||||
char* Buf; // Text buffer // Read-write // [Resize] Can replace pointer / [Completion,History,Always] Only write to pointed data, don't replace the actual pointer!
|
||||
int BufTextLen; // Text length (in bytes) // Read-write // [Resize,Completion,History,Always] Exclude zero-terminator storage. In C land: == strlen(some_text), in C++ land: IM_IMSTR_LENGTH(string)
|
||||
int BufTextLen; // Text length (in bytes) // Read-write // [Resize,Completion,History,Always] Exclude zero-terminator storage. In C land: == strlen(some_text), in C++ land: string.length()
|
||||
int BufSize; // Buffer size (in bytes) = capacity+1 // Read-only // [Resize,Completion,History,Always] Include zero-terminator storage. In C land == ARRAYSIZE(my_char_array), in C++ land: string.capacity()+1
|
||||
bool BufDirty; // Set if you modify Buf/BufTextLen! // Write // [Completion,History,Always]
|
||||
int CursorPos; // // Read-write // [Completion,History,Always]
|
||||
@ -2148,7 +2149,7 @@ struct ImGuiPayload
|
||||
|
||||
ImGuiPayload() { Clear(); }
|
||||
void Clear() { SourceId = SourceParentId = 0; Data = NULL; DataSize = 0; memset(DataType, 0, sizeof(DataType)); DataFrameCount = -1; Preview = Delivery = false; }
|
||||
bool IsDataType(ImStrv type) const { return DataFrameCount != -1 && type == ImStrv(DataType); }
|
||||
bool IsDataType(ImStrv type) const { size_t len = type.length(); return DataFrameCount != -1 && memcmp(DataType, type.Begin, len) == 0 && DataType[len] == 0; }
|
||||
bool IsPreview() const { return Preview; }
|
||||
bool IsDelivery() const { return Delivery; }
|
||||
};
|
||||
@ -2209,20 +2210,9 @@ struct ImGuiTextFilter
|
||||
void Clear() { InputBuf[0] = 0; Build(); }
|
||||
bool IsActive() const { return !Filters.empty(); }
|
||||
|
||||
// [Internal] FIXME-IMSTR: replace this with ImStrv, remove split as an internal function
|
||||
struct ImGuiTextRange
|
||||
{
|
||||
const char* b;
|
||||
const char* e;
|
||||
|
||||
ImGuiTextRange() { b = e = NULL; }
|
||||
ImGuiTextRange(const char* _b, const char* _e) { b = _b; e = _e; }
|
||||
bool empty() const { return b == e; }
|
||||
IMGUI_API void split(char separator, ImVector<ImGuiTextRange>* out) const;
|
||||
};
|
||||
char InputBuf[256];
|
||||
ImVector<ImGuiTextRange>Filters;
|
||||
int CountGrep;
|
||||
char InputBuf[256];
|
||||
ImVector<ImStrv> Filters;
|
||||
int CountGrep;
|
||||
};
|
||||
|
||||
// Helper: Growable text buffer for logging/accumulating text
|
||||
|
@ -6768,7 +6768,7 @@ struct ExampleAppConsole
|
||||
if (match_len > 0)
|
||||
{
|
||||
data->DeleteChars((int)(word_start - data->Buf), (int)(word_end - word_start));
|
||||
data->InsertChars(data->CursorPos, ImStrv(candidates[0], (size_t)match_len));
|
||||
data->InsertChars(data->CursorPos, ImStrv(candidates[0], candidates[0] + match_len));
|
||||
}
|
||||
|
||||
// List matches
|
||||
|
@ -1577,7 +1577,7 @@ void ImDrawList::AddText(const ImFont* font, float font_size, const ImVec2& pos,
|
||||
{
|
||||
if ((col & IM_COL32_A_MASK) == 0)
|
||||
return;
|
||||
if (text.empty())
|
||||
if (text.Begin == text.End)
|
||||
return;
|
||||
|
||||
// Pull default font/size from the shared ImDrawListSharedData instance
|
||||
@ -3351,19 +3351,22 @@ const char* ImFont::CalcWordWrapPositionA(float scale, ImStrv text, float wrap_w
|
||||
float blank_width = 0.0f;
|
||||
wrap_width /= scale; // We work with unscaled widths to avoid scaling every characters
|
||||
|
||||
const char* word_end = text.Begin;
|
||||
const char* text_begin = text.Begin;
|
||||
const char* text_end = text.End;
|
||||
|
||||
const char* word_end = text_begin;
|
||||
const char* prev_word_end = NULL;
|
||||
bool inside_word = true;
|
||||
|
||||
const char* s = text.Begin;
|
||||
while (s < text.End)
|
||||
const char* s = text_begin;
|
||||
while (s < text_end)
|
||||
{
|
||||
unsigned int c = (unsigned int)*s;
|
||||
const char* next_s;
|
||||
if (c < 0x80)
|
||||
next_s = s + 1;
|
||||
else
|
||||
next_s = s + ImTextCharFromUtf8(&c, s, text.End);
|
||||
next_s = s + ImTextCharFromUtf8(&c, s, text_end);
|
||||
if (c == 0)
|
||||
break;
|
||||
|
||||
@ -3436,18 +3439,21 @@ ImVec2 ImFont::CalcTextSizeA(float size, float max_width, float wrap_width, ImSt
|
||||
ImVec2 text_size = ImVec2(0, 0);
|
||||
float line_width = 0.0f;
|
||||
|
||||
const char* text_begin = text.Begin;
|
||||
const char* text_end = text.End;
|
||||
|
||||
const bool word_wrap_enabled = (wrap_width > 0.0f);
|
||||
const char* word_wrap_eol = NULL;
|
||||
|
||||
const char* s = text.Begin;
|
||||
while (s < text.End)
|
||||
const char* s = text_begin;
|
||||
while (s < text_end)
|
||||
{
|
||||
if (word_wrap_enabled)
|
||||
{
|
||||
// Calculate how far we can render. Requires two passes on the string data but keeps the code simple and not intrusive for what's essentially an uncommon feature.
|
||||
if (!word_wrap_eol)
|
||||
{
|
||||
word_wrap_eol = CalcWordWrapPositionA(scale, ImStrv(s, text.End), wrap_width - line_width);
|
||||
word_wrap_eol = CalcWordWrapPositionA(scale, ImStrv(s, text_end), wrap_width - line_width);
|
||||
if (word_wrap_eol == s) // Wrap_width is too small to fit anything. Force displaying 1 character to minimize the height discontinuity.
|
||||
word_wrap_eol++; // +1 may not be a character start point in UTF-8 but it's ok because we use s >= word_wrap_eol below
|
||||
}
|
||||
@ -3461,7 +3467,7 @@ ImVec2 ImFont::CalcTextSizeA(float size, float max_width, float wrap_width, ImSt
|
||||
word_wrap_eol = NULL;
|
||||
|
||||
// Wrapping skips upcoming blanks
|
||||
while (s < text.End)
|
||||
while (s < text_end)
|
||||
{
|
||||
const char c = *s;
|
||||
if (ImCharIsBlankA(c)) { s++; } else if (c == '\n') { s++; break; } else { break; }
|
||||
@ -3479,7 +3485,7 @@ ImVec2 ImFont::CalcTextSizeA(float size, float max_width, float wrap_width, ImSt
|
||||
}
|
||||
else
|
||||
{
|
||||
s += ImTextCharFromUtf8(&c, s, text.End);
|
||||
s += ImTextCharFromUtf8(&c, s, text_end);
|
||||
if (c == 0) // Malformed UTF-8?
|
||||
break;
|
||||
}
|
||||
@ -3552,34 +3558,35 @@ void ImFont::RenderText(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col
|
||||
|
||||
// Fast-forward to first visible line
|
||||
const char* s = text.Begin;
|
||||
const char* text_end = text.End;
|
||||
if (y + line_height < clip_rect.y && !word_wrap_enabled)
|
||||
while (y + line_height < clip_rect.y && s < text.End)
|
||||
while (y + line_height < clip_rect.y && s < text_end)
|
||||
{
|
||||
s = (const char*)memchr(s, '\n', text.End - s);
|
||||
s = s ? s + 1 : text.End;
|
||||
s = (const char*)memchr(s, '\n', text_end - s);
|
||||
s = s ? s + 1 : text_end;
|
||||
y += line_height;
|
||||
}
|
||||
|
||||
// For large text, scan for the last visible line in order to avoid over-reserving in the call to PrimReserve()
|
||||
// Note that very large horizontal line will still be affected by the issue (e.g. a one megabyte string buffer without a newline will likely crash atm)
|
||||
if (text.End - s > 10000 && !word_wrap_enabled)
|
||||
if (text_end - s > 10000 && !word_wrap_enabled)
|
||||
{
|
||||
const char* s_end = s;
|
||||
float y_end = y;
|
||||
while (y_end < clip_rect.w && s_end < text.End)
|
||||
while (y_end < clip_rect.w && s_end < text_end)
|
||||
{
|
||||
s_end = (const char*)memchr(s_end, '\n', text.End - s_end);
|
||||
s_end = s_end ? s_end + 1 : text.End;
|
||||
s_end = (const char*)memchr(s_end, '\n', text_end - s_end);
|
||||
s_end = s_end ? s_end + 1 : text_end;
|
||||
y_end += line_height;
|
||||
}
|
||||
text.End = s_end;
|
||||
text_end = s_end;
|
||||
}
|
||||
if (s == text.End)
|
||||
if (s == text_end)
|
||||
return;
|
||||
|
||||
// Reserve vertices for remaining worse case (over-reserving is useful and easily amortized)
|
||||
const int vtx_count_max = (int)(text.End - s) * 4;
|
||||
const int idx_count_max = (int)(text.End - s) * 6;
|
||||
const int vtx_count_max = (int)(text_end - s) * 4;
|
||||
const int idx_count_max = (int)(text_end - s) * 6;
|
||||
const int idx_expected_size = draw_list->IdxBuffer.Size + idx_count_max;
|
||||
draw_list->PrimReserve(idx_count_max, vtx_count_max);
|
||||
|
||||
@ -3596,7 +3603,7 @@ void ImFont::RenderText(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col
|
||||
// Calculate how far we can render. Requires two passes on the string data but keeps the code simple and not intrusive for what's essentially an uncommon feature.
|
||||
if (!word_wrap_eol)
|
||||
{
|
||||
word_wrap_eol = CalcWordWrapPositionA(scale, ImStrv(s, text.End), wrap_width - (x - pos.x));
|
||||
word_wrap_eol = CalcWordWrapPositionA(scale, ImStrv(s, text_end), wrap_width - (x - pos.x));
|
||||
if (word_wrap_eol == s) // Wrap_width is too small to fit anything. Force displaying 1 character to minimize the height discontinuity.
|
||||
word_wrap_eol++; // +1 may not be a character start point in UTF-8 but it's ok because we use s >= word_wrap_eol below
|
||||
}
|
||||
@ -3608,7 +3615,7 @@ void ImFont::RenderText(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col
|
||||
word_wrap_eol = NULL;
|
||||
|
||||
// Wrapping skips upcoming blanks
|
||||
while (s < text.End)
|
||||
while (s < text_end)
|
||||
{
|
||||
const char c = *s;
|
||||
if (ImCharIsBlankA(c)) { s++; } else if (c == '\n') { s++; break; } else { break; }
|
||||
@ -3625,7 +3632,7 @@ void ImFont::RenderText(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col
|
||||
}
|
||||
else
|
||||
{
|
||||
s += ImTextCharFromUtf8(&c, s, text.End);
|
||||
s += ImTextCharFromUtf8(&c, s, text_end);
|
||||
if (c == 0) // Malformed UTF-8?
|
||||
break;
|
||||
}
|
||||
|
@ -155,17 +155,20 @@ void ImGui::TextEx(ImStrv text, ImGuiTextFlags flags)
|
||||
return;
|
||||
ImGuiContext& g = *GImGui;
|
||||
|
||||
const char* text_begin = text.Begin;
|
||||
const char* text_end = text.End;
|
||||
|
||||
const ImVec2 text_pos(window->DC.CursorPos.x, window->DC.CursorPos.y + window->DC.CurrLineTextBaseOffset);
|
||||
const float wrap_pos_x = window->DC.TextWrapPos;
|
||||
const bool wrap_enabled = (wrap_pos_x >= 0.0f);
|
||||
if (text.End - text.Begin > 2000 && !wrap_enabled)
|
||||
if (text_end - text_begin > 2000 && !wrap_enabled)
|
||||
{
|
||||
// Long text!
|
||||
// Perform manual coarse clipping to optimize for long multi-line text
|
||||
// - From this point we will only compute the width of lines that are visible. Optimization only available when word-wrapping is disabled.
|
||||
// - We also don't vertically center the text within the line full height, which is unlikely to matter because we are likely the biggest and only item on the line.
|
||||
// - We use memchr(), pay attention that well optimized versions of those str/mem functions are much faster than a casually written loop.
|
||||
const char* line = text.Begin;
|
||||
const char* line = text_begin;
|
||||
const float line_height = GetTextLineHeight();
|
||||
ImVec2 text_size(0, 0);
|
||||
|
||||
@ -177,11 +180,11 @@ void ImGui::TextEx(ImStrv text, ImGuiTextFlags flags)
|
||||
if (lines_skippable > 0)
|
||||
{
|
||||
int lines_skipped = 0;
|
||||
while (line < text.End && lines_skipped < lines_skippable)
|
||||
while (line < text_end && lines_skipped < lines_skippable)
|
||||
{
|
||||
const char* line_end = (const char*)memchr(line, '\n', text.End - line);
|
||||
const char* line_end = (const char*)memchr(line, '\n', text_end - line);
|
||||
if (!line_end)
|
||||
line_end = text.End;
|
||||
line_end = text_end;
|
||||
if ((flags & ImGuiTextFlags_NoWidthForLargeClippedText) == 0)
|
||||
text_size.x = ImMax(text_size.x, CalcTextSize(line, line_end).x);
|
||||
line = line_end + 1;
|
||||
@ -192,17 +195,17 @@ void ImGui::TextEx(ImStrv text, ImGuiTextFlags flags)
|
||||
}
|
||||
|
||||
// Lines to render
|
||||
if (line < text.End)
|
||||
if (line < text_end)
|
||||
{
|
||||
ImRect line_rect(pos, pos + ImVec2(FLT_MAX, line_height));
|
||||
while (line < text.End)
|
||||
while (line < text_end)
|
||||
{
|
||||
if (IsClippedEx(line_rect, 0))
|
||||
break;
|
||||
|
||||
const char* line_end = (const char*)memchr(line, '\n', text.End - line);
|
||||
const char* line_end = (const char*)memchr(line, '\n', text_end - line);
|
||||
if (!line_end)
|
||||
line_end = text.End;
|
||||
line_end = text_end;
|
||||
text_size.x = ImMax(text_size.x, CalcTextSize(line, line_end).x);
|
||||
RenderText(pos, ImStrv(line, line_end), false);
|
||||
line = line_end + 1;
|
||||
@ -213,11 +216,11 @@ void ImGui::TextEx(ImStrv text, ImGuiTextFlags flags)
|
||||
|
||||
// Count remaining lines
|
||||
int lines_skipped = 0;
|
||||
while (line < text.End)
|
||||
while (line < text_end)
|
||||
{
|
||||
const char* line_end = (const char*)memchr(line, '\n', text.End - line);
|
||||
const char* line_end = (const char*)memchr(line, '\n', text_end - line);
|
||||
if (!line_end)
|
||||
line_end = text.End;
|
||||
line_end = text_end;
|
||||
if ((flags & ImGuiTextFlags_NoWidthForLargeClippedText) == 0)
|
||||
text_size.x = ImMax(text_size.x, CalcTextSize(line, line_end).x);
|
||||
line = line_end + 1;
|
||||
@ -1618,7 +1621,7 @@ bool ImGui::BeginCombo(ImStrv label, ImStrv preview_value, ImGuiComboFlags flags
|
||||
if (flags & ImGuiComboFlags_CustomPreview)
|
||||
{
|
||||
g.ComboPreviewData.PreviewRect = ImRect(bb.Min.x, bb.Min.y, value_x2, bb.Max.y);
|
||||
IM_ASSERT(!preview_value || preview_value[0] == 0);
|
||||
IM_ASSERT(!preview_value);
|
||||
preview_value = NULL;
|
||||
}
|
||||
|
||||
@ -2346,6 +2349,7 @@ bool ImGui::DragScalar(ImStrv label, ImGuiDataType data_type, void* p_data, floa
|
||||
if (!ItemAdd(total_bb, id, &frame_bb, temp_input_allowed ? ImGuiItemFlags_Inputable : 0))
|
||||
return false;
|
||||
|
||||
// FIXME-IMSTR
|
||||
char format_0[64]; // format may not end with \0
|
||||
const char* format = format_0;
|
||||
IM_ASSERT(format_p.End - format_p.Begin < IM_ARRAYSIZE(format_0));
|
||||
@ -2441,11 +2445,11 @@ bool ImGui::DragScalarN(ImStrv label, ImGuiDataType data_type, void* p_data, int
|
||||
}
|
||||
PopID();
|
||||
|
||||
const char* label_end = FindRenderedTextEnd(label);
|
||||
if (label.Begin != label_end)
|
||||
label.End = FindRenderedTextEnd(label);
|
||||
if (label.Begin != label.End)
|
||||
{
|
||||
SameLine(0, g.Style.ItemInnerSpacing.x);
|
||||
TextEx(ImStrv(label.Begin, label_end));
|
||||
TextEx(label);
|
||||
}
|
||||
|
||||
EndGroup();
|
||||
@ -2498,7 +2502,8 @@ bool ImGui::DragFloatRange2(ImStrv label, float* v_current_min, float* v_current
|
||||
PopItemWidth();
|
||||
SameLine(0, g.Style.ItemInnerSpacing.x);
|
||||
|
||||
TextEx(ImStrv(label.Begin, FindRenderedTextEnd(label)));
|
||||
label.End = FindRenderedTextEnd(label);
|
||||
TextEx(label);
|
||||
EndGroup();
|
||||
PopID();
|
||||
|
||||
@ -2552,7 +2557,8 @@ bool ImGui::DragIntRange2(ImStrv label, int* v_current_min, int* v_current_max,
|
||||
PopItemWidth();
|
||||
SameLine(0, g.Style.ItemInnerSpacing.x);
|
||||
|
||||
TextEx(ImStrv(label.Begin, FindRenderedTextEnd(label)));
|
||||
label.End = FindRenderedTextEnd(label);
|
||||
TextEx(label);
|
||||
EndGroup();
|
||||
PopID();
|
||||
|
||||
@ -2969,6 +2975,7 @@ bool ImGui::SliderScalar(ImStrv label, ImGuiDataType data_type, void* p_data, co
|
||||
if (!ItemAdd(total_bb, id, &frame_bb, temp_input_allowed ? ImGuiItemFlags_Inputable : 0))
|
||||
return false;
|
||||
|
||||
// FIXME-IMSTR
|
||||
char format_0[64]; // format may not end with \0
|
||||
const char* format = format_0;
|
||||
IM_ASSERT(format_p.End - format_p.Begin < IM_ARRAYSIZE(format_0));
|
||||
@ -3062,11 +3069,11 @@ bool ImGui::SliderScalarN(ImStrv label, ImGuiDataType data_type, void* v, int co
|
||||
}
|
||||
PopID();
|
||||
|
||||
const char* label_end = FindRenderedTextEnd(label);
|
||||
if (label.Begin != label_end)
|
||||
label.End = FindRenderedTextEnd(label);
|
||||
if (label.Begin != label.End)
|
||||
{
|
||||
SameLine(0, g.Style.ItemInnerSpacing.x);
|
||||
TextEx(ImStrv(label.Begin, label_end));
|
||||
TextEx(label);
|
||||
}
|
||||
|
||||
EndGroup();
|
||||
@ -3141,6 +3148,7 @@ bool ImGui::VSliderScalar(ImStrv label, const ImVec2& size, ImGuiDataType data_t
|
||||
if (!ItemAdd(frame_bb, id))
|
||||
return false;
|
||||
|
||||
// FIXME-IMSTR
|
||||
char format_0[64]; // format may not end with \0
|
||||
const char* format = format_0;
|
||||
IM_ASSERT(format_p.End - format_p.Begin < IM_ARRAYSIZE(format_0));
|
||||
@ -3391,6 +3399,7 @@ bool ImGui::InputScalar(ImStrv label, ImGuiDataType data_type, void* p_data, con
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiStyle& style = g.Style;
|
||||
|
||||
// FIXME-IMSTR
|
||||
char format_0[64]; // format may not end with \0
|
||||
const char* format = format_0;
|
||||
IM_ASSERT(format_p.End - format_p.Begin < IM_ARRAYSIZE(format_0));
|
||||
@ -3439,11 +3448,11 @@ bool ImGui::InputScalar(ImStrv label, ImGuiDataType data_type, void* p_data, con
|
||||
if (flags & ImGuiInputTextFlags_ReadOnly)
|
||||
EndDisabled();
|
||||
|
||||
const char* label_end = FindRenderedTextEnd(label);
|
||||
if (label.Begin != label_end)
|
||||
label.End = FindRenderedTextEnd(label);
|
||||
if (label.Begin != label.End)
|
||||
{
|
||||
SameLine(0, style.ItemInnerSpacing.x);
|
||||
TextEx(ImStrv(label.Begin, label_end));
|
||||
TextEx(label);
|
||||
}
|
||||
style.FramePadding = backup_frame_padding;
|
||||
|
||||
@ -3485,11 +3494,11 @@ bool ImGui::InputScalarN(ImStrv label, ImGuiDataType data_type, void* p_data, in
|
||||
}
|
||||
PopID();
|
||||
|
||||
const char* label_end = FindRenderedTextEnd(label);
|
||||
if (label.Begin != label_end)
|
||||
label.End = FindRenderedTextEnd(label);
|
||||
if (label.Begin != label.End)
|
||||
{
|
||||
SameLine(0.0f, g.Style.ItemInnerSpacing.x);
|
||||
TextEx(ImStrv(label.Begin, label_end));
|
||||
TextEx(label);
|
||||
}
|
||||
|
||||
EndGroup();
|
||||
@ -4857,11 +4866,11 @@ bool ImGui::ColorEdit4(ImStrv label, float col[4], ImGuiColorEditFlags flags)
|
||||
const float w_full = CalcItemWidth();
|
||||
const float w_button = (flags & ImGuiColorEditFlags_NoSmallPreview) ? 0.0f : (square_sz + style.ItemInnerSpacing.x);
|
||||
const float w_inputs = w_full - w_button;
|
||||
const char* label_display_end = FindRenderedTextEnd(label);
|
||||
g.NextItemData.ClearFlags();
|
||||
|
||||
BeginGroup();
|
||||
PushID(label);
|
||||
label.End = FindRenderedTextEnd(label);
|
||||
|
||||
// If we're not showing any slider there's no point in doing any HSV conversions
|
||||
const ImGuiColorEditFlags flags_untouched = flags;
|
||||
@ -5001,9 +5010,9 @@ bool ImGui::ColorEdit4(ImStrv label, float col[4], ImGuiColorEditFlags flags)
|
||||
if (BeginPopup("picker"))
|
||||
{
|
||||
picker_active_window = g.CurrentWindow;
|
||||
if (label.Begin != label_display_end)
|
||||
if (label.Begin != label.End)
|
||||
{
|
||||
TextEx(ImStrv(label.Begin, label_display_end));
|
||||
TextEx(label);
|
||||
Spacing();
|
||||
}
|
||||
ImGuiColorEditFlags picker_flags_to_forward = ImGuiColorEditFlags_DataTypeMask_ | ImGuiColorEditFlags_PickerMask_ | ImGuiColorEditFlags_InputMask_ | ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_AlphaBar;
|
||||
@ -5014,10 +5023,10 @@ bool ImGui::ColorEdit4(ImStrv label, float col[4], ImGuiColorEditFlags flags)
|
||||
}
|
||||
}
|
||||
|
||||
if (label.Begin != label_display_end && !(flags & ImGuiColorEditFlags_NoLabel))
|
||||
if (label.Begin != label.End && !(flags & ImGuiColorEditFlags_NoLabel))
|
||||
{
|
||||
SameLine(0.0f, style.ItemInnerSpacing.x);
|
||||
TextEx(ImStrv(label.Begin, label_display_end));
|
||||
TextEx(label);
|
||||
}
|
||||
|
||||
// Convert back
|
||||
@ -5580,10 +5589,10 @@ void ImGui::ColorTooltip(ImStrv text, const float* col, ImGuiColorEditFlags flag
|
||||
ImGuiContext& g = *GImGui;
|
||||
|
||||
BeginTooltipEx(ImGuiTooltipFlags_OverridePreviousTooltip, ImGuiWindowFlags_None);
|
||||
const char* text_end = text ? FindRenderedTextEnd(text) : text.Begin;
|
||||
if (text_end > text.Begin)
|
||||
text.End = FindRenderedTextEnd(text);
|
||||
if (text.Begin != text.End)
|
||||
{
|
||||
TextEx(ImStrv(text.Begin, text_end));
|
||||
TextEx(text);
|
||||
Separator();
|
||||
}
|
||||
|
||||
@ -5854,9 +5863,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, ImStrv label)
|
||||
const ImGuiStyle& style = g.Style;
|
||||
const bool display_frame = (flags & ImGuiTreeNodeFlags_Framed) != 0;
|
||||
const ImVec2 padding = (display_frame || (flags & ImGuiTreeNodeFlags_FramePadding)) ? style.FramePadding : ImVec2(style.FramePadding.x, ImMin(window->DC.CurrLineTextBaseOffset, style.FramePadding.y));
|
||||
|
||||
if (!label.End)
|
||||
label.End = FindRenderedTextEnd(label);
|
||||
label.End = FindRenderedTextEnd(label);
|
||||
const ImVec2 label_size = CalcTextSize(label, false);
|
||||
|
||||
// We vertically grow up to current line height up the typical widget height.
|
||||
@ -6929,7 +6936,7 @@ bool ImGui::BeginMenuEx(ImStrv label, ImStrv icon, bool enabled)
|
||||
// (In a typical menu window where all items are BeginMenu() or MenuItem() calls, extra_w will always be 0.0f.
|
||||
// Only when they are other items sticking out we're going to add spacing, yet only register minimum width into the layout system.
|
||||
popup_pos = ImVec2(pos.x, pos.y - style.WindowPadding.y);
|
||||
float icon_w = (icon && icon[0]) ? CalcTextSize(icon, NULL).x : 0.0f;
|
||||
float icon_w = icon ? CalcTextSize(icon, NULL).x : 0.0f;
|
||||
float checkmark_w = IM_FLOOR(g.FontSize * 1.20f);
|
||||
float min_w = window->DC.MenuColumns.DeclColumns(icon_w, label_size.x, 0.0f, checkmark_w); // Feedback to next frame
|
||||
float extra_w = ImMax(0.0f, GetContentRegionAvail().x - min_w);
|
||||
@ -7101,8 +7108,8 @@ bool ImGui::MenuItemEx(ImStrv label, ImStrv icon, ImStrv shortcut, bool selected
|
||||
// Menu item inside a vertical menu
|
||||
// (In a typical menu window where all items are BeginMenu() or MenuItem() calls, extra_w will always be 0.0f.
|
||||
// Only when they are other items sticking out we're going to add spacing, yet only register minimum width into the layout system.
|
||||
float icon_w = (icon && icon[0]) ? CalcTextSize(icon).x : 0.0f;
|
||||
float shortcut_w = (shortcut && shortcut[0]) ? CalcTextSize(shortcut).x : 0.0f;
|
||||
float icon_w = icon ? CalcTextSize(icon).x : 0.0f;
|
||||
float shortcut_w = shortcut ? CalcTextSize(shortcut).x : 0.0f;
|
||||
float checkmark_w = IM_FLOOR(g.FontSize * 1.20f);
|
||||
float min_w = window->DC.MenuColumns.DeclColumns(icon_w, label_size.x, shortcut_w, checkmark_w); // Feedback for next frame
|
||||
float stretch_w = ImMax(0.0f, GetContentRegionAvail().x - min_w);
|
||||
@ -7954,6 +7961,7 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, ImStrv label, bool* p_open, ImGui
|
||||
flags |= ImGuiTabItemFlags_NoCloseButton;
|
||||
|
||||
// Calculate tab contents size
|
||||
label.End = FindRenderedTextEnd(label);
|
||||
ImVec2 size = TabItemCalcSize(label, p_open != NULL);
|
||||
|
||||
// Acquire tab data
|
||||
@ -7982,7 +7990,8 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, ImStrv label, bool* p_open, ImGui
|
||||
// Append name with zero-terminator
|
||||
tab->NameOffset = (ImS32)tab_bar->TabsNames.size();
|
||||
tab_bar->TabsNames.append(label);
|
||||
tab_bar->TabsNames.append(ImStrv("\0", 1));
|
||||
char zero_c = 0;
|
||||
tab_bar->TabsNames.append(ImStrv(&zero_c, &zero_c + 1));
|
||||
|
||||
// Update selected tab
|
||||
if (tab_appearing && (tab_bar->Flags & ImGuiTabBarFlags_AutoSelectNewTabs) && tab_bar->NextSelectedTabId == 0)
|
||||
@ -8191,7 +8200,7 @@ void ImGui::TabItemBackground(ImDrawList* draw_list, const ImRect& bb, ImGuiTabI
|
||||
void ImGui::TabItemLabelAndCloseButton(ImDrawList* draw_list, const ImRect& bb, ImGuiTabItemFlags flags, ImVec2 frame_padding, ImStrv label, ImGuiID tab_id, ImGuiID close_button_id, bool is_contents_visible, bool* out_just_closed, bool* out_text_clipped)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImVec2 label_size = CalcTextSize(label, true);
|
||||
ImVec2 label_size = CalcTextSize(label);
|
||||
|
||||
if (out_just_closed)
|
||||
*out_just_closed = false;
|
||||
|
Loading…
Reference in New Issue
Block a user