Add text editor module for cardinal
Signed-off-by: falkTX <falktx@falktx.com>
This commit is contained in:
parent
bba168ecc6
commit
268c31c029
13 changed files with 3957 additions and 26 deletions
2
dpf
2
dpf
|
@ -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"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
21
plugins/Cardinal/src/DearImGuiColorTextEditor/LICENSE
Normal file
21
plugins/Cardinal/src/DearImGuiColorTextEditor/LICENSE
Normal file
|
@ -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.
|
3179
plugins/Cardinal/src/DearImGuiColorTextEditor/TextEditor.cpp
Normal file
3179
plugins/Cardinal/src/DearImGuiColorTextEditor/TextEditor.cpp
Normal file
File diff suppressed because it is too large
Load diff
398
plugins/Cardinal/src/DearImGuiColorTextEditor/TextEditor.h
Normal file
398
plugins/Cardinal/src/DearImGuiColorTextEditor/TextEditor.h
Normal file
|
@ -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;
|
||||
|
||||
|
|
125
plugins/Cardinal/src/ImGuiTextEditor.cpp
Normal file
125
plugins/Cardinal/src/ImGuiTextEditor.cpp
Normal file
|
@ -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();
|
||||
}
|
56
plugins/Cardinal/src/ImGuiTextEditor.hpp
Normal file
56
plugins/Cardinal/src/ImGuiTextEditor.hpp
Normal file
|
@ -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;
|
||||
|
|
139
plugins/Cardinal/src/TextEditor.cpp
Normal file
139
plugins/Cardinal/src/TextEditor.cpp
Normal file
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue