11#include " CodeEditorTab.h"
22
33#include " CodeContextInformation.h"
4+ #include " IconsFontAwesome7.h"
45
56#include < variant>
67
@@ -13,42 +14,90 @@ void projectm_eval_memory_host_unlock_mutex()
1314
1415namespace Editor {
1516
17+ using CodeDestructor = void (*)(projectm_eval_code*);
18+ using CodeHandle = std::unique_ptr<projectm_eval_code, CodeDestructor>;
19+
1620CodeEditorTab::CodeEditorTab (ExpressionCodeTypes type, std::string& code, int index)
1721 : _code(code)
22+ , _textEditor(std::make_unique<TextEditor>())
1823{
1924 _tabTitle = CodeContextInformation::GetContextName (type, index);
20- _textEditor.SetLanguageDefinition (CodeContextInformation::GetLanguageDefinition (type));
21- _textEditor.SetText (code);
25+ _textEditor->SetTabsAsSpaces (true );
26+ _textEditor->SetTabSize (4 );
27+ _textEditor->SetLanguageDefinition (CodeContextInformation::GetLanguageDefinition (type));
28+ _textEditor->SetText (code);
2229
2330 if (type != ExpressionCodeTypes::WarpShader && type != ExpressionCodeTypes::CompositeShader)
2431 {
25- _compileTextContext = projectm_eval_context_create (nullptr , nullptr );
32+ _compileTextContext. reset ( projectm_eval_context_create (nullptr , nullptr ) );
2633 CheckCodeSyntax (code);
2734 }
28- }
2935
30- CodeEditorTab::~CodeEditorTab ()
31- {
32- if (_compileTextContext)
36+ switch (type)
3337 {
34- projectm_eval_context_destroy (_compileTextContext);
35- _compileTextContext = nullptr ;
38+ case ExpressionCodeTypes::PerFrameInit:
39+ case ExpressionCodeTypes::PerFrame:
40+ case ExpressionCodeTypes::PerVertex:
41+ _tabHoverColor = {0xe7 / 256 .f , 0x4c / 256 .f , 0x3c / 256 .f , 1 .0f };
42+ break ;
43+
44+ case ExpressionCodeTypes::CustomWaveInit:
45+ case ExpressionCodeTypes::CustomWavePerFrame:
46+ case ExpressionCodeTypes::CustomWavePerPoint:
47+ _tabHoverColor = {0x29 / 256 .f , 0x80 / 256 .f , 0xb9 / 256 .f , 1 .0f };
48+ break ;
49+
50+ case ExpressionCodeTypes::CustomShapeInit:
51+ case ExpressionCodeTypes::CustomShapePerFrame:
52+ _tabHoverColor = {0x8e / 256 .f , 0x44 / 256 .f , 0xad / 256 .f , 1 .0f };
53+ break ;
54+
55+ case ExpressionCodeTypes::WarpShader:
56+ _tabHoverColor = {0x27 / 256 .f , 0xae / 256 .f , 0x60 / 256 .f , 1 .0f };
57+ break ;
58+
59+ case ExpressionCodeTypes::CompositeShader:
60+ _tabHoverColor = {0xf3 / 256 .f , 0x9c / 256 .f , 0x12 / 256 .f , 1 .0f };
61+ break ;
3662 }
63+
64+ _tabActiveColor = {_tabHoverColor.x * 0 .8f , _tabHoverColor.y * 0 .8f , _tabHoverColor.z * 0 .8f , _tabHoverColor.w };
65+ _tabColor = {_tabHoverColor.x * 0 .5f , _tabHoverColor.y * 0 .5f , _tabHoverColor.z * 0 .5f , _tabHoverColor.w * 0 .75f };
66+ }
67+
68+ CodeEditorTab& CodeEditorTab::operator =(CodeEditorTab&& other) noexcept
69+ {
70+ _nextRenderingFlags = other._nextRenderingFlags ;
71+ _tabTitle = std::move (other._tabTitle );
72+ _tabColor = other._tabColor ;
73+ _tabActiveColor = other._tabActiveColor ;
74+ _tabHoverColor = other._tabHoverColor ;
75+ _code = other._code ;
76+ _textEditor = std::move (other._textEditor );
77+ _documentOpen = other._documentOpen ;
78+ _compileTextContext = std::move (other._compileTextContext );
79+
80+ return *this ;
3781}
3882
3983bool CodeEditorTab::Draw ()
4084{
4185 ImGui::PushID (_tabTitle.c_str ());
4286
87+ ImGui::PushStyleColor (ImGuiCol_Tab, _tabColor);
88+ ImGui::PushStyleColor (ImGuiCol_TabActive, _tabActiveColor);
89+ ImGui::PushStyleColor (ImGuiCol_TabHovered, _tabHoverColor);
4390 bool tabVisible = ImGui::BeginTabItem (_tabTitle.c_str (), &_documentOpen, _nextRenderingFlags);
4491
4592 if (tabVisible)
4693 {
47- _textEditor. Render ((_tabTitle + " ##EditorControl " ). c_str () );
94+ bool textChangedByToolBar = DrawToolBar ( );
4895
49- if (_textEditor.IsTextChanged ())
96+ _textEditor->Render ((_tabTitle + " ##EditorControl" ).c_str ());
97+
98+ if (_textEditor->IsTextChanged () || textChangedByToolBar)
5099 {
51- std::string changedText = _textEditor. GetText ();
100+ std::string changedText = _textEditor-> GetText ();
52101
53102 // The text editor always leaves a newline if empty, check & clear if that's the case.
54103 if (changedText.size () == 1 && changedText.at (0 ) == ' \n ' )
@@ -64,6 +113,10 @@ bool CodeEditorTab::Draw()
64113 ImGui::EndTabItem ();
65114 }
66115
116+ ImGui::PopStyleColor ();
117+ ImGui::PopStyleColor ();
118+ ImGui::PopStyleColor ();
119+
67120 ImGui::PopID ();
68121
69122 _nextRenderingFlags = ImGuiTabItemFlags_None;
@@ -81,21 +134,76 @@ std::string CodeEditorTab::Title() const
81134 return _tabTitle;
82135}
83136
137+ bool CodeEditorTab::DrawToolBar ()
138+ {
139+ bool textChanged = false ;
140+
141+ ImGui::BeginDisabled (!_textEditor->HasSelection ());
142+ if (ImGui::Button (ICON_FA_COPY " Copy##ToolBar" ))
143+ {
144+ _textEditor->Copy ();
145+ }
146+ ImGui::SameLine ();
147+ if (ImGui::Button (ICON_FA_SCISSORS " Cut##ToolBar" ))
148+ {
149+ _textEditor->Cut ();
150+ textChanged= true ;
151+ }
152+ ImGui::EndDisabled ();
153+
154+ ImGui::BeginDisabled (strlen (ImGui::GetClipboardText ()) == 0 );
155+ ImGui::SameLine ();
156+ if (ImGui::Button (ICON_FA_PASTE " Paste##ToolBar" ))
157+ {
158+ _textEditor->Paste ();
159+ textChanged= true ;
160+ }
161+ ImGui::EndDisabled ();
162+
163+ ImGui::SameLine ();
164+ ImGui::Separator ();
165+
166+ ImGui::BeginDisabled (!_textEditor->CanUndo ());
167+ ImGui::SameLine ();
168+ if (ImGui::Button (ICON_FA_ARROW_ROTATE_LEFT " Undo##ToolBar" ))
169+ {
170+ _textEditor->Undo ();
171+ textChanged= true ;
172+ }
173+ ImGui::EndDisabled ();
174+
175+ ImGui::BeginDisabled (!_textEditor->CanRedo ());
176+ ImGui::SameLine ();
177+ if (ImGui::Button (ICON_FA_ARROW_ROTATE_RIGHT " Redo##ToolBar" ))
178+ {
179+ _textEditor->Redo ();
180+ textChanged= true ;
181+ }
182+ ImGui::EndDisabled ();
183+
184+ ImGui::SameLine ();
185+ if (ImGui::Checkbox (" Whitespace##ToolBar" , &_showWhitespace))
186+ {
187+ _textEditor->SetShowWhitespaces (_showWhitespace);
188+ }
189+
190+ return textChanged;
191+ }
192+
84193void CodeEditorTab::CheckCodeSyntax (const std::string& codeToCheck)
85194{
86195 if (_compileTextContext)
87196 {
88- auto * code = projectm_eval_code_compile (_compileTextContext, codeToCheck.c_str ());
197+ auto code = CodeHandle ( projectm_eval_code_compile (_compileTextContext. get () , codeToCheck.c_str ()), projectm_eval_code_destroy );
89198 if (code)
90199 {
91- _textEditor.SetErrorMarkers ({});
92- projectm_eval_code_destroy (code);
200+ _textEditor->SetErrorMarkers ({});
93201 }
94202 else
95203 {
96204 int line{};
97- std::string errorMessage = projectm_eval_get_error (_compileTextContext, &line, nullptr );
98- _textEditor. SetErrorMarkers ({{line, errorMessage}});
205+ std::string errorMessage = projectm_eval_get_error (_compileTextContext. get () , &line, nullptr );
206+ _textEditor-> SetErrorMarkers ({{line, errorMessage}});
99207 }
100208 }
101209}
0 commit comments