Signed-off-by: falkTX <falktx@falktx.com>tags/22.02
| @@ -1 +1 @@ | |||
| Subproject commit 400dca29de54e1cceee55f22672e940ae5d5e005 | |||
| Subproject commit 493837049e773e45f842c0ee83b6b69c7c56adf9 | |||
| @@ -75,6 +75,15 @@ | |||
| "tags": [ | |||
| "Utility" | |||
| ] | |||
| }, | |||
| { | |||
| "slug": "TextEditor", | |||
| "disabled": false, | |||
| "name": "Text Editor", | |||
| "description": "A embed text editor inside Cardinal", | |||
| "tags": [ | |||
| "Utility" | |||
| ] | |||
| } | |||
| ] | |||
| } | |||
| @@ -0,0 +1,21 @@ | |||
| MIT License | |||
| Copyright (c) 2017 BalazsJako | |||
| Permission is hereby granted, free of charge, to any person obtaining a copy | |||
| of this software and associated documentation files (the "Software"), to deal | |||
| in the Software without restriction, including without limitation the rights | |||
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |||
| copies of the Software, and to permit persons to whom the Software is | |||
| furnished to do so, subject to the following conditions: | |||
| The above copyright notice and this permission notice shall be included in all | |||
| copies or substantial portions of the Software. | |||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |||
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |||
| SOFTWARE. | |||
| @@ -0,0 +1,398 @@ | |||
| #pragma once | |||
| #include <string> | |||
| #include <vector> | |||
| #include <array> | |||
| #include <memory> | |||
| #include <unordered_set> | |||
| #include <unordered_map> | |||
| #include <map> | |||
| #include <regex> | |||
| #include "../DearImGui/imgui.h" | |||
| class TextEditor | |||
| { | |||
| public: | |||
| enum class PaletteIndex | |||
| { | |||
| Default, | |||
| Keyword, | |||
| Number, | |||
| String, | |||
| CharLiteral, | |||
| Punctuation, | |||
| Preprocessor, | |||
| Identifier, | |||
| KnownIdentifier, | |||
| PreprocIdentifier, | |||
| Comment, | |||
| MultiLineComment, | |||
| Background, | |||
| Cursor, | |||
| Selection, | |||
| ErrorMarker, | |||
| Breakpoint, | |||
| LineNumber, | |||
| CurrentLineFill, | |||
| CurrentLineFillInactive, | |||
| CurrentLineEdge, | |||
| Max | |||
| }; | |||
| enum class SelectionMode | |||
| { | |||
| Normal, | |||
| Word, | |||
| Line | |||
| }; | |||
| struct Breakpoint | |||
| { | |||
| int mLine; | |||
| bool mEnabled; | |||
| std::string mCondition; | |||
| Breakpoint() | |||
| : mLine(-1) | |||
| , mEnabled(false) | |||
| {} | |||
| }; | |||
| // Represents a character coordinate from the user's point of view, | |||
| // i. e. consider an uniform grid (assuming fixed-width font) on the | |||
| // screen as it is rendered, and each cell has its own coordinate, starting from 0. | |||
| // Tabs are counted as [1..mTabSize] count empty spaces, depending on | |||
| // how many space is necessary to reach the next tab stop. | |||
| // For example, coordinate (1, 5) represents the character 'B' in a line "\tABC", when mTabSize = 4, | |||
| // because it is rendered as " ABC" on the screen. | |||
| struct Coordinates | |||
| { | |||
| int mLine, mColumn; | |||
| Coordinates() : mLine(0), mColumn(0) {} | |||
| Coordinates(int aLine, int aColumn) : mLine(aLine), mColumn(aColumn) | |||
| { | |||
| assert(aLine >= 0); | |||
| assert(aColumn >= 0); | |||
| } | |||
| static Coordinates Invalid() { static Coordinates invalid(-1, -1); return invalid; } | |||
| bool operator ==(const Coordinates& o) const | |||
| { | |||
| return | |||
| mLine == o.mLine && | |||
| mColumn == o.mColumn; | |||
| } | |||
| bool operator !=(const Coordinates& o) const | |||
| { | |||
| return | |||
| mLine != o.mLine || | |||
| mColumn != o.mColumn; | |||
| } | |||
| bool operator <(const Coordinates& o) const | |||
| { | |||
| if (mLine != o.mLine) | |||
| return mLine < o.mLine; | |||
| return mColumn < o.mColumn; | |||
| } | |||
| bool operator >(const Coordinates& o) const | |||
| { | |||
| if (mLine != o.mLine) | |||
| return mLine > o.mLine; | |||
| return mColumn > o.mColumn; | |||
| } | |||
| bool operator <=(const Coordinates& o) const | |||
| { | |||
| if (mLine != o.mLine) | |||
| return mLine < o.mLine; | |||
| return mColumn <= o.mColumn; | |||
| } | |||
| bool operator >=(const Coordinates& o) const | |||
| { | |||
| if (mLine != o.mLine) | |||
| return mLine > o.mLine; | |||
| return mColumn >= o.mColumn; | |||
| } | |||
| }; | |||
| struct Identifier | |||
| { | |||
| Coordinates mLocation; | |||
| std::string mDeclaration; | |||
| }; | |||
| typedef std::string String; | |||
| typedef std::unordered_map<std::string, Identifier> Identifiers; | |||
| typedef std::unordered_set<std::string> Keywords; | |||
| typedef std::map<int, std::string> ErrorMarkers; | |||
| typedef std::unordered_set<int> Breakpoints; | |||
| typedef std::array<ImU32, (unsigned)PaletteIndex::Max> Palette; | |||
| typedef uint8_t Char; | |||
| struct Glyph | |||
| { | |||
| Char mChar; | |||
| PaletteIndex mColorIndex = PaletteIndex::Default; | |||
| bool mComment : 1; | |||
| bool mMultiLineComment : 1; | |||
| bool mPreprocessor : 1; | |||
| Glyph(Char aChar, PaletteIndex aColorIndex) : mChar(aChar), mColorIndex(aColorIndex), | |||
| mComment(false), mMultiLineComment(false), mPreprocessor(false) {} | |||
| }; | |||
| typedef std::vector<Glyph> Line; | |||
| typedef std::vector<Line> Lines; | |||
| struct LanguageDefinition | |||
| { | |||
| typedef std::pair<std::string, PaletteIndex> TokenRegexString; | |||
| typedef std::vector<TokenRegexString> TokenRegexStrings; | |||
| typedef bool(*TokenizeCallback)(const char * in_begin, const char * in_end, const char *& out_begin, const char *& out_end, PaletteIndex & paletteIndex); | |||
| typedef void(*ColorizeCallback)(Lines &lines, void *data); | |||
| std::string mName; | |||
| Keywords mKeywords; | |||
| Identifiers mIdentifiers; | |||
| Identifiers mPreprocIdentifiers; | |||
| std::string mCommentStart, mCommentEnd, mSingleLineComment; | |||
| char mPreprocChar; | |||
| bool mAutoIndentation; | |||
| ColorizeCallback mColorize; | |||
| void *mColorizeData; | |||
| TokenizeCallback mTokenize; | |||
| TokenRegexStrings mTokenRegexStrings; | |||
| bool mCaseSensitive; | |||
| LanguageDefinition() | |||
| : mPreprocChar('#') | |||
| , mAutoIndentation(true) | |||
| , mColorize(nullptr) | |||
| , mColorizeData(nullptr) | |||
| , mTokenize(nullptr) | |||
| , mCaseSensitive(true) | |||
| { | |||
| } | |||
| static const LanguageDefinition& CPlusPlus(); | |||
| static const LanguageDefinition& HLSL(); | |||
| static const LanguageDefinition& GLSL(); | |||
| static const LanguageDefinition& C(); | |||
| static const LanguageDefinition& SQL(); | |||
| static const LanguageDefinition& AngelScript(); | |||
| static const LanguageDefinition& Lua(); | |||
| }; | |||
| TextEditor(); | |||
| ~TextEditor(); | |||
| void SetLanguageDefinition(const LanguageDefinition& aLanguageDef); | |||
| const LanguageDefinition& GetLanguageDefinition() const { return mLanguageDefinition; } | |||
| const Palette& GetPalette() const { return mPaletteBase; } | |||
| void SetPalette(const Palette& aValue); | |||
| void SetErrorMarkers(const ErrorMarkers& aMarkers) { mErrorMarkers = aMarkers; } | |||
| void SetBreakpoints(const Breakpoints& aMarkers) { mBreakpoints = aMarkers; } | |||
| void Render(const char* aTitle, const ImVec2& aSize = ImVec2(), bool aBorder = false); | |||
| void SetText(const std::string& aText); | |||
| std::string GetText() const; | |||
| void SetTextLines(const std::vector<std::string>& aLines); | |||
| std::vector<std::string> GetTextLines() const; | |||
| std::string GetSelectedText() const; | |||
| std::string GetCurrentLineText()const; | |||
| int GetTotalLines() const { return (int)mLines.size(); } | |||
| bool IsOverwrite() const { return mOverwrite; } | |||
| void SetReadOnly(bool aValue); | |||
| bool IsReadOnly() const { return mReadOnly; } | |||
| bool IsTextChanged() const { return mTextChanged; } | |||
| bool IsCursorPositionChanged() const { return mCursorPositionChanged; } | |||
| bool IsColorizerEnabled() const { return mColorizerEnabled; } | |||
| void SetColorizerEnable(bool aValue); | |||
| Coordinates GetCursorPosition() const { return GetActualCursorCoordinates(); } | |||
| void SetCursorPosition(const Coordinates& aPosition); | |||
| inline void SetHandleMouseInputs (bool aValue){ mHandleMouseInputs = aValue;} | |||
| inline bool IsHandleMouseInputsEnabled() const { return mHandleMouseInputs; } | |||
| inline void SetHandleKeyboardInputs (bool aValue){ mHandleKeyboardInputs = aValue;} | |||
| inline bool IsHandleKeyboardInputsEnabled() const { return mHandleKeyboardInputs; } | |||
| inline void SetImGuiChildIgnored (bool aValue){ mIgnoreImGuiChild = aValue;} | |||
| inline bool IsImGuiChildIgnored() const { return mIgnoreImGuiChild; } | |||
| inline void SetShowWhitespaces(bool aValue) { mShowWhitespaces = aValue; } | |||
| inline bool IsShowingWhitespaces() const { return mShowWhitespaces; } | |||
| void SetTabSize(int aValue); | |||
| inline int GetTabSize() const { return mTabSize; } | |||
| void InsertText(const std::string& aValue); | |||
| void InsertText(const char* aValue); | |||
| void MoveUp(int aAmount = 1, bool aSelect = false); | |||
| void MoveDown(int aAmount = 1, bool aSelect = false); | |||
| void MoveLeft(int aAmount = 1, bool aSelect = false, bool aWordMode = false); | |||
| void MoveRight(int aAmount = 1, bool aSelect = false, bool aWordMode = false); | |||
| void MoveTop(bool aSelect = false); | |||
| void MoveBottom(bool aSelect = false); | |||
| void MoveHome(bool aSelect = false); | |||
| void MoveEnd(bool aSelect = false); | |||
| void SetSelectionStart(const Coordinates& aPosition); | |||
| void SetSelectionEnd(const Coordinates& aPosition); | |||
| void SetSelection(const Coordinates& aStart, const Coordinates& aEnd, SelectionMode aMode = SelectionMode::Normal); | |||
| void SelectWordUnderCursor(); | |||
| void SelectAll(); | |||
| bool HasSelection() const; | |||
| void Copy(); | |||
| void Cut(); | |||
| void Paste(); | |||
| void Delete(); | |||
| bool CanUndo() const; | |||
| bool CanRedo() const; | |||
| void Undo(int aSteps = 1); | |||
| void Redo(int aSteps = 1); | |||
| static const Palette& GetDarkPalette(); | |||
| static const Palette& GetLightPalette(); | |||
| static const Palette& GetRetroBluePalette(); | |||
| private: | |||
| typedef std::vector<std::pair<std::regex, PaletteIndex>> RegexList; | |||
| struct EditorState | |||
| { | |||
| Coordinates mSelectionStart; | |||
| Coordinates mSelectionEnd; | |||
| Coordinates mCursorPosition; | |||
| }; | |||
| class UndoRecord | |||
| { | |||
| public: | |||
| UndoRecord() {} | |||
| ~UndoRecord() {} | |||
| UndoRecord( | |||
| const std::string& aAdded, | |||
| const TextEditor::Coordinates aAddedStart, | |||
| const TextEditor::Coordinates aAddedEnd, | |||
| const std::string& aRemoved, | |||
| const TextEditor::Coordinates aRemovedStart, | |||
| const TextEditor::Coordinates aRemovedEnd, | |||
| TextEditor::EditorState& aBefore, | |||
| TextEditor::EditorState& aAfter); | |||
| void Undo(TextEditor* aEditor); | |||
| void Redo(TextEditor* aEditor); | |||
| std::string mAdded; | |||
| Coordinates mAddedStart; | |||
| Coordinates mAddedEnd; | |||
| std::string mRemoved; | |||
| Coordinates mRemovedStart; | |||
| Coordinates mRemovedEnd; | |||
| EditorState mBefore; | |||
| EditorState mAfter; | |||
| }; | |||
| typedef std::vector<UndoRecord> UndoBuffer; | |||
| void ProcessInputs(); | |||
| void Colorize(int aFromLine = 0, int aCount = -1); | |||
| void ColorizeRange(int aFromLine = 0, int aToLine = 0); | |||
| void ColorizeInternal(); | |||
| float TextDistanceToLineStart(const Coordinates& aFrom) const; | |||
| void EnsureCursorVisible(); | |||
| int GetPageSize() const; | |||
| std::string GetText(const Coordinates& aStart, const Coordinates& aEnd) const; | |||
| Coordinates GetActualCursorCoordinates() const; | |||
| Coordinates SanitizeCoordinates(const Coordinates& aValue) const; | |||
| void Advance(Coordinates& aCoordinates) const; | |||
| void DeleteRange(const Coordinates& aStart, const Coordinates& aEnd); | |||
| int InsertTextAt(Coordinates& aWhere, const char* aValue); | |||
| void AddUndo(UndoRecord& aValue); | |||
| Coordinates ScreenPosToCoordinates(const ImVec2& aPosition) const; | |||
| Coordinates FindWordStart(const Coordinates& aFrom) const; | |||
| Coordinates FindWordEnd(const Coordinates& aFrom) const; | |||
| Coordinates FindNextWord(const Coordinates& aFrom) const; | |||
| int GetCharacterIndex(const Coordinates& aCoordinates) const; | |||
| int GetCharacterColumn(int aLine, int aIndex) const; | |||
| int GetLineCharacterCount(int aLine) const; | |||
| int GetLineMaxColumn(int aLine) const; | |||
| bool IsOnWordBoundary(const Coordinates& aAt) const; | |||
| void RemoveLine(int aStart, int aEnd); | |||
| void RemoveLine(int aIndex); | |||
| Line& InsertLine(int aIndex); | |||
| void EnterCharacter(ImWchar aChar, bool aShift); | |||
| void Backspace(); | |||
| void DeleteSelection(); | |||
| std::string GetWordUnderCursor() const; | |||
| std::string GetWordAt(const Coordinates& aCoords) const; | |||
| ImU32 GetGlyphColor(const Glyph& aGlyph) const; | |||
| void HandleKeyboardInputs(); | |||
| void HandleMouseInputs(); | |||
| void Render(); | |||
| float mLineSpacing; | |||
| Lines mLines; | |||
| EditorState mState; | |||
| UndoBuffer mUndoBuffer; | |||
| int mUndoIndex; | |||
| int mTabSize; | |||
| bool mOverwrite; | |||
| bool mReadOnly; | |||
| bool mWithinRender; | |||
| bool mScrollToCursor; | |||
| bool mScrollToTop; | |||
| bool mTextChanged; | |||
| bool mColorizerEnabled; | |||
| float mTextStart; // position (in pixels) where a code line starts relative to the left of the TextEditor. | |||
| int mLeftMargin; | |||
| bool mCursorPositionChanged; | |||
| int mColorRangeMin, mColorRangeMax; | |||
| SelectionMode mSelectionMode; | |||
| bool mHandleKeyboardInputs; | |||
| bool mHandleMouseInputs; | |||
| bool mIgnoreImGuiChild; | |||
| bool mShowWhitespaces; | |||
| Palette mPaletteBase; | |||
| Palette mPalette; | |||
| LanguageDefinition mLanguageDefinition; | |||
| RegexList mRegexList; | |||
| bool mCheckComments; | |||
| Breakpoints mBreakpoints; | |||
| ErrorMarkers mErrorMarkers; | |||
| ImVec2 mCharAdvance; | |||
| Coordinates mInteractiveStart, mInteractiveEnd; | |||
| std::string mLineBuffer; | |||
| uint64_t mStartTime; | |||
| float mLastClick; | |||
| }; | |||
| @@ -722,30 +722,6 @@ struct IldaeilWidget : ImGuiWidget, IdleCallback, Thread { | |||
| std::strcpy(fPluginSearchString, "Search..."); | |||
| ImGuiStyle& style(ImGui::GetStyle()); | |||
| style.FrameRounding = 4; | |||
| ImVec4* colors = ImGui::GetStyle().Colors; | |||
| ImVec4 color_Cardinal = ImVec4(0.76f, 0.11f, 0.22f, 1.00f); | |||
| ImVec4 color_DimCardinal = ImVec4(171.0 / 255.0, 54.0 / 255.0, 73.0 / 255.0, 1.00f); | |||
| colors[ImGuiCol_Text] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f); | |||
| colors[ImGuiCol_TextDisabled] = ImVec4(0.50f, 0.50f, 0.50f, 1.00f); | |||
| colors[ImGuiCol_WindowBg] = ImVec4(0.101f, 0.101f, 0.101f, 0.94f); | |||
| colors[ImGuiCol_FrameBg] = ImVec4(0.20f, 0.21f, 0.22f, 0.54f); | |||
| colors[ImGuiCol_FrameBgHovered] = ImVec4(0.40f, 0.40f, 0.40f, 0.40f); | |||
| colors[ImGuiCol_FrameBgActive] = ImVec4(0.18f, 0.18f, 0.18f, 0.67f); | |||
| colors[ImGuiCol_TitleBgActive] = ImVec4(0.29f, 0.29f, 0.29f, 1.00f); | |||
| colors[ImGuiCol_CheckMark] = color_Cardinal; | |||
| colors[ImGuiCol_SliderGrab] = color_DimCardinal; | |||
| colors[ImGuiCol_SliderGrabActive] = color_Cardinal; | |||
| colors[ImGuiCol_Button] = color_DimCardinal; | |||
| colors[ImGuiCol_ButtonHovered] = color_Cardinal; | |||
| colors[ImGuiCol_ButtonActive] = color_Cardinal; | |||
| colors[ImGuiCol_TextSelectedBg] = ImVec4(0.87f, 0.87f, 0.87f, 0.35f); | |||
| colors[ImGuiCol_Header] = ImVec4(0.44f, 0.44f, 0.44f, 0.40f); | |||
| colors[ImGuiCol_HeaderHovered] = color_DimCardinal; | |||
| colors[ImGuiCol_HeaderActive] = color_Cardinal; | |||
| if (checkIfPluginIsLoaded()) | |||
| fIdleState = kIdleInitPluginAlreadyLoaded; | |||
| @@ -0,0 +1,125 @@ | |||
| /* | |||
| * Syntax highlighting text editor (for ImGui in DPF) | |||
| * Copyright (C) 2021 Filipe Coelho <falktx@falktx.com> | |||
| * Copyright (c) 2017 BalazsJako | |||
| * | |||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | |||
| * of this software and associated documentation files (the "Software"), to deal | |||
| * in the Software without restriction, including without limitation the rights | |||
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |||
| * copies of the Software, and to permit persons to whom the Software is | |||
| * furnished to do so, subject to the following conditions: | |||
| * | |||
| * The above copyright notice and this permission notice shall be included in all | |||
| * copies or substantial portions of the Software. | |||
| * | |||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |||
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |||
| * SOFTWARE. | |||
| */ | |||
| #include "ImGuiTextEditor.hpp" | |||
| #include "DearImGuiColorTextEditor/TextEditor.h" | |||
| // -------------------------------------------------------------------------------------------------------------------- | |||
| struct ImGuiTextEditor::PrivateData { | |||
| ImGuiTextEditor* const self; | |||
| TextEditor editor; | |||
| std::string file; | |||
| explicit PrivateData(ImGuiTextEditor* const s) | |||
| : self(s) | |||
| { | |||
| // https://github.com/BalazsJako/ColorTextEditorDemo/blob/master/main.cpp | |||
| editor.SetLanguageDefinition(TextEditor::LanguageDefinition::CPlusPlus()); | |||
| editor.SetText("" | |||
| "// Welcome to a real text editor inside Cardinal\n" | |||
| "\n" | |||
| "#define I_AM_A_MACRO\n" | |||
| "\n" | |||
| "int and_i_am_a_variable;\n" | |||
| "\n" | |||
| "/* look ma, a comment! */\n" | |||
| "int such_highlight_much_wow() { return 1337; }\n" | |||
| ); | |||
| editor.SetCursorPosition(TextEditor::Coordinates(8, 0)); | |||
| } | |||
| DISTRHO_DECLARE_NON_COPYABLE(PrivateData) | |||
| }; | |||
| // -------------------------------------------------------------------------------------------------------------------- | |||
| ImGuiTextEditor::ImGuiTextEditor() | |||
| : ImGuiWidget(), | |||
| pData(new PrivateData(this)) {} | |||
| ImGuiTextEditor::~ImGuiTextEditor() | |||
| { | |||
| delete pData; | |||
| } | |||
| // -------------------------------------------------------------------------------------------------------------------- | |||
| void ImGuiTextEditor::setText(const std::string& text) | |||
| { | |||
| pData->editor.SetText(text); | |||
| } | |||
| std::string ImGuiTextEditor::getText() const | |||
| { | |||
| return pData->editor.GetText(); | |||
| } | |||
| void ImGuiTextEditor::setTextLines(const std::vector<std::string>& lines) | |||
| { | |||
| pData->editor.SetTextLines(lines); | |||
| } | |||
| std::vector<std::string> ImGuiTextEditor::getTextLines() const | |||
| { | |||
| return pData->editor.GetTextLines(); | |||
| } | |||
| std::string ImGuiTextEditor::getSelectedText() const | |||
| { | |||
| return pData->editor.GetSelectedText(); | |||
| } | |||
| std::string ImGuiTextEditor::getCurrentLineText()const | |||
| { | |||
| return pData->editor.GetCurrentLineText(); | |||
| } | |||
| // -------------------------------------------------------------------------------------------------------------------- | |||
| void ImGuiTextEditor::drawImGui() | |||
| { | |||
| ImGui::SetNextWindowPos(ImVec2(0, 0)); | |||
| ImGui::SetNextWindowSize(ImVec2(box.size.x, box.size.y)); | |||
| if (ImGui::Begin("TextEdit", nullptr, ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoResize)) | |||
| { | |||
| TextEditor& editor(pData->editor); | |||
| const TextEditor::Coordinates cpos = editor.GetCursorPosition(); | |||
| ImGui::Text("%6d/%-6d %6d lines | %s | %s | %s | %s", | |||
| cpos.mLine + 1, cpos.mColumn + 1, | |||
| editor.GetTotalLines(), | |||
| editor.IsOverwrite() ? "Ovr" : "Ins", | |||
| editor.CanUndo() ? "*" : " ", | |||
| editor.GetLanguageDefinition().mName.c_str(), | |||
| pData->file.c_str()); | |||
| editor.Render("TextEditor"); | |||
| } | |||
| ImGui::End(); | |||
| } | |||
| @@ -0,0 +1,56 @@ | |||
| /* | |||
| * Syntax highlighting text editor (for ImGui in DPF, converted to VCV) | |||
| * Copyright (C) 2021 Filipe Coelho <falktx@falktx.com> | |||
| * Copyright (c) 2017 BalazsJako | |||
| * | |||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | |||
| * of this software and associated documentation files (the "Software"), to deal | |||
| * in the Software without restriction, including without limitation the rights | |||
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |||
| * copies of the Software, and to permit persons to whom the Software is | |||
| * furnished to do so, subject to the following conditions: | |||
| * | |||
| * The above copyright notice and this permission notice shall be included in all | |||
| * copies or substantial portions of the Software. | |||
| * | |||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |||
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |||
| * SOFTWARE. | |||
| */ | |||
| #pragma once | |||
| #include "ImGuiWidget.hpp" | |||
| #include "DearImGuiColorTextEditor/TextEditor.h" | |||
| #include <string> | |||
| #include <vector> | |||
| struct ImGuiTextEditor : ImGuiWidget | |||
| { | |||
| struct PrivateData; | |||
| PrivateData* const pData; | |||
| ImGuiTextEditor(); | |||
| ~ImGuiTextEditor() override; | |||
| /** | |||
| Methods from internal TextEdit. | |||
| */ | |||
| void setText(const std::string& text); | |||
| std::string getText() const; | |||
| void setTextLines(const std::vector<std::string>& lines); | |||
| std::vector<std::string> getTextLines() const; | |||
| std::string getSelectedText() const; | |||
| std::string getCurrentLineText()const; | |||
| protected: | |||
| /** @internal */ | |||
| void drawImGui() override; | |||
| }; | |||
| @@ -38,11 +38,34 @@ struct ImGuiWidget::PrivateData { | |||
| io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; | |||
| io.IniFilename = nullptr; | |||
| /* | |||
| ImGuiStyle& style(ImGui::GetStyle()); | |||
| style.FrameRounding = 4; | |||
| /* | |||
| style.ScaleAllSizes(scaleFactor); | |||
| */ | |||
| const ImVec4 color_Cardinal(0.76f, 0.11f, 0.22f, 1.00f); | |||
| const ImVec4 color_DimCardinal(171.0 / 255.0, 54.0 / 255.0, 73.0 / 255.0, 1.00f); | |||
| ImVec4* const colors = style.Colors; | |||
| colors[ImGuiCol_Text] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f); | |||
| colors[ImGuiCol_TextDisabled] = ImVec4(0.50f, 0.50f, 0.50f, 1.00f); | |||
| colors[ImGuiCol_WindowBg] = ImVec4(0.101f, 0.101f, 0.101f, 0.94f); | |||
| colors[ImGuiCol_FrameBg] = ImVec4(0.20f, 0.21f, 0.22f, 0.54f); | |||
| colors[ImGuiCol_FrameBgHovered] = ImVec4(0.40f, 0.40f, 0.40f, 0.40f); | |||
| colors[ImGuiCol_FrameBgActive] = ImVec4(0.18f, 0.18f, 0.18f, 0.67f); | |||
| colors[ImGuiCol_TitleBgActive] = ImVec4(0.29f, 0.29f, 0.29f, 1.00f); | |||
| colors[ImGuiCol_CheckMark] = color_Cardinal; | |||
| colors[ImGuiCol_SliderGrab] = color_DimCardinal; | |||
| colors[ImGuiCol_SliderGrabActive] = color_Cardinal; | |||
| colors[ImGuiCol_Button] = color_DimCardinal; | |||
| colors[ImGuiCol_ButtonHovered] = color_Cardinal; | |||
| colors[ImGuiCol_ButtonActive] = color_Cardinal; | |||
| colors[ImGuiCol_TextSelectedBg] = ImVec4(0.87f, 0.87f, 0.87f, 0.35f); | |||
| colors[ImGuiCol_Header] = ImVec4(0.44f, 0.44f, 0.44f, 0.40f); | |||
| colors[ImGuiCol_HeaderHovered] = color_DimCardinal; | |||
| colors[ImGuiCol_HeaderActive] = color_Cardinal; | |||
| #ifndef DGL_NO_SHARED_RESOURCES | |||
| using namespace dpf_resources; | |||
| ImFontConfig fc; | |||
| @@ -0,0 +1,139 @@ | |||
| /* | |||
| * DISTRHO Cardinal Plugin | |||
| * Copyright (C) 2021 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU General Public License as | |||
| * published by the Free Software Foundation; either version 3 of | |||
| * the License, or any later version. | |||
| * | |||
| * This program is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| * GNU General Public License for more details. | |||
| * | |||
| * For a full copy of the GNU General Public License see the LICENSE file. | |||
| */ | |||
| #include "plugincontext.hpp" | |||
| #ifndef HEADLESS | |||
| # include "ImGuiTextEditor.hpp" | |||
| # include "extra/FileBrowserDialog.hpp" | |||
| #endif | |||
| #include <fstream> | |||
| // -------------------------------------------------------------------------------------------------------------------- | |||
| struct TextEditorModule : Module { | |||
| enum ParamIds { | |||
| NUM_PARAMS | |||
| }; | |||
| enum InputIds { | |||
| NUM_INPUTS | |||
| }; | |||
| enum OutputIds { | |||
| NUM_OUTPUTS | |||
| }; | |||
| enum LightIds { | |||
| NUM_LIGHTS | |||
| }; | |||
| TextEditorModule() | |||
| { | |||
| config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); | |||
| } | |||
| ~TextEditorModule() override | |||
| { | |||
| } | |||
| void process(const ProcessArgs&) override | |||
| { | |||
| } | |||
| DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(TextEditorModule) | |||
| }; | |||
| // -------------------------------------------------------------------------------------------------------------------- | |||
| #ifndef HEADLESS | |||
| struct TextEditorWidget : ImGuiTextEditor | |||
| { | |||
| TextEditorWidget() : ImGuiTextEditor() {} | |||
| DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(TextEditorWidget) | |||
| }; | |||
| // -------------------------------------------------------------------------------------------------------------------- | |||
| struct TextEditorLoadFileItem : MenuItem { | |||
| TextEditorWidget* widget = nullptr; | |||
| void onAction(const event::Action &e) override | |||
| { | |||
| WeakPtr<TextEditorWidget> widget = this->widget; | |||
| async_dialog_filebrowser(false, nullptr, "Load File", [widget](char* path) | |||
| { | |||
| if (path) | |||
| { | |||
| if (widget) | |||
| { | |||
| std::ifstream f(path); | |||
| if (f.good()) | |||
| { | |||
| const std::string str((std::istreambuf_iterator<char>(f)), std::istreambuf_iterator<char>()); | |||
| widget->setText(str); | |||
| } | |||
| } | |||
| free(path); | |||
| } | |||
| }); | |||
| } | |||
| }; | |||
| // -------------------------------------------------------------------------------------------------------------------- | |||
| struct TextEditorModuleWidget : ModuleWidget { | |||
| TextEditorWidget* textEditorWidget = nullptr; | |||
| TextEditorModuleWidget(TextEditorModule* const module) | |||
| { | |||
| setModule(module); | |||
| setPanel(APP->window->loadSvg(asset::plugin(pluginInstance, "res/Ildaeil.svg"))); | |||
| if (module != nullptr) | |||
| { | |||
| textEditorWidget = new TextEditorWidget(); | |||
| textEditorWidget->box.pos = Vec(2 * RACK_GRID_WIDTH, 0); | |||
| textEditorWidget->box.size = Vec(box.size.x - 2 * RACK_GRID_WIDTH, box.size.y); | |||
| addChild(textEditorWidget); | |||
| } | |||
| addChild(createWidget<ScrewBlack>(Vec(0, 0))); | |||
| addChild(createWidget<ScrewBlack>(Vec(0, RACK_GRID_HEIGHT - RACK_GRID_WIDTH))); | |||
| addChild(createWidget<ScrewBlack>(Vec(RACK_GRID_WIDTH, 0))); | |||
| addChild(createWidget<ScrewBlack>(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH))); | |||
| } | |||
| void appendContextMenu(Menu *menu) override { | |||
| menu->addChild(new MenuEntry); | |||
| TextEditorLoadFileItem* loadFileItem = new TextEditorLoadFileItem; | |||
| loadFileItem->text = "Load File"; | |||
| loadFileItem->widget = textEditorWidget; | |||
| menu->addChild(loadFileItem); | |||
| } | |||
| DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(TextEditorModuleWidget) | |||
| }; | |||
| #else | |||
| typedef ModuleWidget TextEditorModuleWidget; | |||
| #endif | |||
| // -------------------------------------------------------------------------------------------------------------------- | |||
| Model* modelTextEditor = createModel<TextEditorModule, TextEditorModuleWidget>("TextEditor"); | |||
| // -------------------------------------------------------------------------------------------------------------------- | |||
| @@ -34,3 +34,4 @@ extern Model* modelHostCV; | |||
| extern Model* modelHostParameters; | |||
| extern Model* modelHostTime; | |||
| extern Model* modelIldaeil; | |||
| extern Model* modelTextEditor; | |||
| @@ -192,10 +192,13 @@ PLUGIN_FILES += Cardinal/src/HostCV.cpp | |||
| PLUGIN_FILES += Cardinal/src/HostParameters.cpp | |||
| PLUGIN_FILES += Cardinal/src/HostTime.cpp | |||
| PLUGIN_FILES += Cardinal/src/Ildaeil.cpp | |||
| PLUGIN_FILES += Cardinal/src/TextEditor.cpp | |||
| ifneq ($(HEADLESS),true) | |||
| PLUGIN_FILES += Cardinal/src/ImGuiWidget.cpp | |||
| PLUGIN_FILES += Cardinal/src/ImGuiTextEditor.cpp | |||
| PLUGIN_FILES += $(wildcard Cardinal/src/DearImGui/*.cpp) | |||
| PLUGIN_FILES += $(wildcard Cardinal/src/DearImGuiColorTextEditor/*.cpp) | |||
| endif | |||
| ifneq ($(NOPLUGINS),true) | |||
| @@ -675,6 +675,7 @@ static void initStatic__Cardinal() | |||
| p->addModel(modelHostParameters); | |||
| p->addModel(modelHostTime); | |||
| p->addModel(modelIldaeil); | |||
| p->addModel(modelTextEditor); | |||
| } | |||
| } | |||