Skip to content

Commit 1ef54aa

Browse files
committed
Switch ImGuiColorTextEdit to goossens fork
Addresses #155. Switched from Joshs fork to goossens' fork of ImGuiColorTextEdit for better performance with larger OTIO files, which were not highlighted at a satisfactory speed before. One downside: this implementation drops the special highlighting of the "OTIO_SCHEMA" string found in the original code. The old fork used regex patterns to highlight the string. The new fork requires a custom tokenizer wrapper to achieve this, which I figured is too much overhead for minimal benefit. Added TODO comment documenting the decision and implementation approach for future reference. This commit completes the dependency upgrade started in the previous commit. The two commits are separated for review purposes (dependency upgrade vs. fork switch), but the first commit requires this one to build successfully. Submodule changes: - URL: github.com/jminor/ImGuiColorTextEdit → github.com/goossens/ImGuiColorTextEdit - Commit: 7dec5d8 (Nov 2022) → a74fb09 (May 2026, master branch) API migrations in inspector.cpp: - OTIOLanguageDef() → OTIOLanguage() (LanguageDefinition → Language class) - SetReadOnly() → SetReadOnlyEnabled() - SetLanguageDefinition() → SetLanguage() - SetErrorMarkers() → ClearMarkers() + AddMarker() - Render(title, false, size) → Render(title, size) - IsTextChanged() → CanUndo() - Added palette initialization to fix static initialization order bug - Removed global otioLangDef variable Disclosure: I used Claude Sonnet 4.5 to help with the porting process.
1 parent 5fb972b commit 1ef54aa

3 files changed

Lines changed: 45 additions & 53 deletions

File tree

.gitmodules

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
url = https://github.com/ocornut/imgui.git
1616
[submodule "libs/ImGuiColorTextEdit"]
1717
path = libs/ImGuiColorTextEdit
18-
url = https://github.com/jminor/ImGuiColorTextEdit.git
18+
url = https://github.com/goossens/ImGuiColorTextEdit.git
1919
[submodule "libs/minizip-ng"]
2020
path = libs/minizip-ng
2121
url = https://github.com/zlib-ng/minizip-ng.git

inspector.cpp

Lines changed: 43 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -23,67 +23,56 @@
2323
#include <implot.h>
2424
#include <TextEditor.h>
2525

26+
#include <regex>
27+
2628
static const char* marker_color_names[] = {
2729
"PINK", "RED", "ORANGE", "YELLOW",
2830
"GREEN", "CYAN", "BLUE", "PURPLE",
2931
"MAGENTA", "BLACK", "WHITE"
3032
};
3133

32-
const TextEditor::LanguageDefinition& OTIOLanguageDef()
34+
const TextEditor::Language* OTIOLanguage()
3335
{
34-
static bool inited = false;
35-
static TextEditor::LanguageDefinition langDef;
36-
if (!inited)
37-
{
38-
static const char* const keywords[] = {
39-
"true", "false", "null"
40-
};
41-
42-
for (auto& k : keywords)
43-
langDef.mKeywords.insert(k);
44-
45-
static const char* const identifiers[] = {
46-
"\"OTIO_SCHEMA\""
47-
};
48-
for (auto& k : identifiers)
49-
{
50-
TextEditor::Identifier id;
51-
id.mDeclaration = "OpenTimelineIO Schema";
52-
langDef.mIdentifiers.insert(std::make_pair(std::string(k), id));
53-
}
54-
55-
langDef.mTokenRegexStrings.push_back(std::make_pair<std::string, TextEditor::PaletteIndex>("\\\"OTIO_SCHEMA\\\"", TextEditor::PaletteIndex::Identifier));
56-
langDef.mTokenRegexStrings.push_back(std::make_pair<std::string, TextEditor::PaletteIndex>("\\\"(\\\\.|[^\\\"])*\\\"", TextEditor::PaletteIndex::String));
57-
langDef.mTokenRegexStrings.push_back(std::make_pair<std::string, TextEditor::PaletteIndex>("[+-]?([0-9]+([.][0-9]*)?|[.][0-9]+)([eE][+-]?[0-9]+)?", TextEditor::PaletteIndex::Number));
58-
langDef.mTokenRegexStrings.push_back(std::make_pair<std::string, TextEditor::PaletteIndex>("[a-zA-Z_][a-zA-Z0-9_]*", TextEditor::PaletteIndex::Identifier));
59-
langDef.mTokenRegexStrings.push_back(std::make_pair<std::string, TextEditor::PaletteIndex>("[\\[\\]\\{\\}\\,\\:]", TextEditor::PaletteIndex::Punctuation));
60-
61-
langDef.mCommentStart = "/*";
62-
langDef.mCommentEnd = "*/";
63-
langDef.mSingleLineComment = "//";
36+
static bool initialized = false;
37+
static TextEditor::Language language;
6438

65-
langDef.mCaseSensitive = true;
66-
langDef.mAutoIndentation = true;
67-
68-
langDef.mName = "JSON";
69-
70-
inited = true;
39+
if (!initialized)
40+
{
41+
const TextEditor::Language* jsonLang = TextEditor::Language::Json();
42+
language = *jsonLang;
43+
language.name = "OTIO/JSON";
44+
45+
// TODO: Special highlighting for "OTIO_SCHEMA" strings
46+
// Old jminor fork: used mTokenRegexStrings with pattern \\\"OTIO_SCHEMA\\\"
47+
// New goossens fork: removed regex API, requires custom tokenizer wrapper
48+
// The problem: "OTIO_SCHEMA" appears quoted in JSON. keywords/identifiers only match bare
49+
// tokens. Recoloring string content requires intercepting with customTokenizer
50+
// before the string state machine consumes it. Too complex for minimal benefit.
51+
52+
initialized = true;
7153
}
72-
return langDef;
54+
55+
return &language;
7356
}
7457

7558
TextEditor jsonEditor;
76-
TextEditor::LanguageDefinition otioLangDef = OTIOLanguageDef();
7759
bool json_rendered = false;
7860
bool json_edited = false;
7961
std::string json_error_message;
8062
int json_error_line = -1;
8163

8264
void UpdateJSONInspector() {
83-
jsonEditor.SetReadOnly(false);
84-
jsonEditor.SetLanguageDefinition(otioLangDef);
65+
// Ensure palette is set (fixes static initialization order issue)
66+
static bool paletteInitialized = false;
67+
if (!paletteInitialized) {
68+
jsonEditor.SetPalette(TextEditor::GetDarkPalette());
69+
paletteInitialized = true;
70+
}
71+
72+
jsonEditor.SetReadOnlyEnabled(false);
73+
jsonEditor.SetLanguage(OTIOLanguage());
8574
jsonEditor.SetText(appState.selected_text);
86-
jsonEditor.SetErrorMarkers({});
75+
jsonEditor.ClearMarkers();
8776
json_rendered = false;
8877
json_edited = false;
8978
json_error_message = "";
@@ -122,10 +111,13 @@ void SetJSONErrorMessage(std::string message) {
122111
wrapped_message += c;
123112
}
124113

114+
jsonEditor.ClearMarkers();
125115
if (json_error_line >= 0) {
126-
jsonEditor.SetErrorMarkers({ { json_error_line, wrapped_message } });
127-
} else {
128-
jsonEditor.SetErrorMarkers({});
116+
jsonEditor.AddMarker(json_error_line,
117+
IM_COL32(255, 0, 0, 255),
118+
IM_COL32(255, 100, 100, 50),
119+
wrapped_message.c_str(),
120+
"");
129121
}
130122

131123
json_error_message = wrapped_message;
@@ -222,17 +214,17 @@ void DrawJSONApplyEditButtons() {
222214
}
223215

224216
void DrawJSONInspector() {
225-
// Check if the text was edited this frame.
226-
// Note that IsTextChanged() is true only until Render is called.
227-
// We have to also check if Render was called since the text
228-
// was last set via SetText() inside UpdateJSONInspector().
229-
if (json_rendered && jsonEditor.IsTextChanged()) {
217+
// Check if the text was edited.
218+
// We use CanUndo() to detect if there are any edits since SetText() was called,
219+
// as SetText() clears the undo stack. We also check json_rendered to ensure
220+
// Render() was called at least once since UpdateJSONInspector().
221+
if (json_rendered && jsonEditor.CanUndo()) {
230222
json_edited = true;
231223
}
232224

233225
auto available_size = ImGui::GetContentRegionAvail();
234226
available_size.y -= ImGui::GetFrameHeightWithSpacing();
235-
jsonEditor.Render("JSON",false, available_size);
227+
jsonEditor.Render("JSON", available_size);
236228
json_rendered = true;
237229

238230
if (json_edited) {

0 commit comments

Comments
 (0)