Skip to content

Commit b984c54

Browse files
committed
Add color to code tabs and a toolbar for each editor
1 parent 365a743 commit b984c54

2 files changed

Lines changed: 146 additions & 20 deletions

File tree

src/gui/preset_editor/CodeEditorTab.cpp

Lines changed: 125 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
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

1415
namespace Editor {
1516

17+
using CodeDestructor = void (*)(projectm_eval_code*);
18+
using CodeHandle = std::unique_ptr<projectm_eval_code, CodeDestructor>;
19+
1620
CodeEditorTab::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

3983
bool 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+
84193
void 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
}

src/gui/preset_editor/CodeEditorTab.h

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,12 @@ class CodeEditorTab
1414

1515
explicit CodeEditorTab(ExpressionCodeTypes type, std::string& code, int index);
1616

17-
virtual ~CodeEditorTab();
17+
virtual ~CodeEditorTab() = default;
18+
19+
CodeEditorTab(const CodeEditorTab& other) = delete;
20+
CodeEditorTab(CodeEditorTab&& other) noexcept = default;
21+
CodeEditorTab& operator=(const CodeEditorTab& other) = delete;
22+
CodeEditorTab& operator=(CodeEditorTab&& other) noexcept;
1823

1924
bool Draw();
2025

@@ -23,15 +28,28 @@ class CodeEditorTab
2328
std::string Title() const;
2429

2530
private:
31+
using ContextDestructor = void(*)(projectm_eval_context*);
32+
using ContextHandle = std::unique_ptr<projectm_eval_context, ContextDestructor>;
33+
34+
/**
35+
* Draws the editor toolbar for this tab.
36+
* @return true if an action was executed which changed the editor contents, false if not.
37+
*/
38+
bool DrawToolBar();
39+
2640
void CheckCodeSyntax(const std::string& codeToCheck);
2741

2842
ImGuiTabItemFlags _nextRenderingFlags{}; //!< Additional flags to set when rendering the tab next time, e.g. activate it.
2943
std::string _tabTitle; //!< The title of the tab.
44+
ImVec4 _tabColor{0.0f, 0.0f, 1.0f, 1.0f}; //!< The background color of the inactive tab.
45+
ImVec4 _tabActiveColor{0.0f, 0.0f, 1.0f, 1.0f}; //!< The background color of the active tab.
46+
ImVec4 _tabHoverColor{0.0f, 0.0f, 1.0f, 1.0f}; //!< The background color of the hovered tab.
3047
std::string& _code; //!< A reference to the preset code.
31-
TextEditor _textEditor; //!< The expression/shader code editor control.
48+
bool _showWhitespace{true}; //!< If true, the editor will display whitespace.
49+
std::unique_ptr<TextEditor> _textEditor; //!< The expression/shader code editor control.
3250
bool _documentOpen{true}; //!< This flag holds the opened/closed state of the document, e.g. becomes false if the user closes the tab.
3351

34-
projectm_eval_context* _compileTextContext{nullptr}; //!< A projectm-eval context for test-compiling the editor code.
52+
ContextHandle _compileTextContext{nullptr, projectm_eval_context_destroy}; //!< A projectm-eval context for test-compiling the editor code.
3553
};
3654

3755
} // namespace Editor

0 commit comments

Comments
 (0)