mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-09 23:34:20 +00:00
TextEditor: Improve Unicode editing behaviour and performance
This commit is contained in:
parent
427852836c
commit
9ce2feaf41
30 changed files with 1370 additions and 1059 deletions
|
|
@ -2411,6 +2411,7 @@ add_library( ${BINARY_NAME}
|
|||
"../../../../../modules/juce_gui_basics/widgets/juce_TableListBox.h"
|
||||
"../../../../../modules/juce_gui_basics/widgets/juce_TextEditor.cpp"
|
||||
"../../../../../modules/juce_gui_basics/widgets/juce_TextEditor.h"
|
||||
"../../../../../modules/juce_gui_basics/widgets/juce_TextEditorModel.cpp"
|
||||
"../../../../../modules/juce_gui_basics/widgets/juce_Toolbar.cpp"
|
||||
"../../../../../modules/juce_gui_basics/widgets/juce_Toolbar.h"
|
||||
"../../../../../modules/juce_gui_basics/widgets/juce_ToolbarItemComponent.cpp"
|
||||
|
|
@ -5016,6 +5017,7 @@ set_source_files_properties(
|
|||
"../../../../../modules/juce_gui_basics/widgets/juce_TableListBox.h"
|
||||
"../../../../../modules/juce_gui_basics/widgets/juce_TextEditor.cpp"
|
||||
"../../../../../modules/juce_gui_basics/widgets/juce_TextEditor.h"
|
||||
"../../../../../modules/juce_gui_basics/widgets/juce_TextEditorModel.cpp"
|
||||
"../../../../../modules/juce_gui_basics/widgets/juce_Toolbar.cpp"
|
||||
"../../../../../modules/juce_gui_basics/widgets/juce_Toolbar.h"
|
||||
"../../../../../modules/juce_gui_basics/widgets/juce_ToolbarItemComponent.cpp"
|
||||
|
|
|
|||
|
|
@ -2949,6 +2949,9 @@
|
|||
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\widgets\juce_TextEditor.cpp">
|
||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\widgets\juce_TextEditorModel.cpp">
|
||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\widgets\juce_Toolbar.cpp">
|
||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
|
|
|
|||
|
|
@ -3772,6 +3772,9 @@
|
|||
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\widgets\juce_TextEditor.cpp">
|
||||
<Filter>JUCE Modules\juce_gui_basics\widgets</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\widgets\juce_TextEditorModel.cpp">
|
||||
<Filter>JUCE Modules\juce_gui_basics\widgets</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\widgets\juce_Toolbar.cpp">
|
||||
<Filter>JUCE Modules\juce_gui_basics\widgets</Filter>
|
||||
</ClCompile>
|
||||
|
|
|
|||
|
|
@ -2949,6 +2949,9 @@
|
|||
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\widgets\juce_TextEditor.cpp">
|
||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\widgets\juce_TextEditorModel.cpp">
|
||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\widgets\juce_Toolbar.cpp">
|
||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
|
|
|
|||
|
|
@ -3772,6 +3772,9 @@
|
|||
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\widgets\juce_TextEditor.cpp">
|
||||
<Filter>JUCE Modules\juce_gui_basics\widgets</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\widgets\juce_TextEditorModel.cpp">
|
||||
<Filter>JUCE Modules\juce_gui_basics\widgets</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\widgets\juce_Toolbar.cpp">
|
||||
<Filter>JUCE Modules\juce_gui_basics\widgets</Filter>
|
||||
</ClCompile>
|
||||
|
|
|
|||
|
|
@ -2173,6 +2173,7 @@ add_library( ${BINARY_NAME}
|
|||
"../../../../../modules/juce_gui_basics/widgets/juce_TableListBox.h"
|
||||
"../../../../../modules/juce_gui_basics/widgets/juce_TextEditor.cpp"
|
||||
"../../../../../modules/juce_gui_basics/widgets/juce_TextEditor.h"
|
||||
"../../../../../modules/juce_gui_basics/widgets/juce_TextEditorModel.cpp"
|
||||
"../../../../../modules/juce_gui_basics/widgets/juce_Toolbar.cpp"
|
||||
"../../../../../modules/juce_gui_basics/widgets/juce_Toolbar.h"
|
||||
"../../../../../modules/juce_gui_basics/widgets/juce_ToolbarItemComponent.cpp"
|
||||
|
|
@ -4438,6 +4439,7 @@ set_source_files_properties(
|
|||
"../../../../../modules/juce_gui_basics/widgets/juce_TableListBox.h"
|
||||
"../../../../../modules/juce_gui_basics/widgets/juce_TextEditor.cpp"
|
||||
"../../../../../modules/juce_gui_basics/widgets/juce_TextEditor.h"
|
||||
"../../../../../modules/juce_gui_basics/widgets/juce_TextEditorModel.cpp"
|
||||
"../../../../../modules/juce_gui_basics/widgets/juce_Toolbar.cpp"
|
||||
"../../../../../modules/juce_gui_basics/widgets/juce_Toolbar.h"
|
||||
"../../../../../modules/juce_gui_basics/widgets/juce_ToolbarItemComponent.cpp"
|
||||
|
|
|
|||
|
|
@ -2642,6 +2642,9 @@
|
|||
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\widgets\juce_TextEditor.cpp">
|
||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\widgets\juce_TextEditorModel.cpp">
|
||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\widgets\juce_Toolbar.cpp">
|
||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
|
|
|
|||
|
|
@ -3289,6 +3289,9 @@
|
|||
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\widgets\juce_TextEditor.cpp">
|
||||
<Filter>JUCE Modules\juce_gui_basics\widgets</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\widgets\juce_TextEditorModel.cpp">
|
||||
<Filter>JUCE Modules\juce_gui_basics\widgets</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\widgets\juce_Toolbar.cpp">
|
||||
<Filter>JUCE Modules\juce_gui_basics\widgets</Filter>
|
||||
</ClCompile>
|
||||
|
|
|
|||
|
|
@ -2303,6 +2303,7 @@ add_library( ${BINARY_NAME}
|
|||
"../../../../../modules/juce_gui_basics/widgets/juce_TableListBox.h"
|
||||
"../../../../../modules/juce_gui_basics/widgets/juce_TextEditor.cpp"
|
||||
"../../../../../modules/juce_gui_basics/widgets/juce_TextEditor.h"
|
||||
"../../../../../modules/juce_gui_basics/widgets/juce_TextEditorModel.cpp"
|
||||
"../../../../../modules/juce_gui_basics/widgets/juce_Toolbar.cpp"
|
||||
"../../../../../modules/juce_gui_basics/widgets/juce_Toolbar.h"
|
||||
"../../../../../modules/juce_gui_basics/widgets/juce_ToolbarItemComponent.cpp"
|
||||
|
|
@ -4721,6 +4722,7 @@ set_source_files_properties(
|
|||
"../../../../../modules/juce_gui_basics/widgets/juce_TableListBox.h"
|
||||
"../../../../../modules/juce_gui_basics/widgets/juce_TextEditor.cpp"
|
||||
"../../../../../modules/juce_gui_basics/widgets/juce_TextEditor.h"
|
||||
"../../../../../modules/juce_gui_basics/widgets/juce_TextEditorModel.cpp"
|
||||
"../../../../../modules/juce_gui_basics/widgets/juce_Toolbar.cpp"
|
||||
"../../../../../modules/juce_gui_basics/widgets/juce_Toolbar.h"
|
||||
"../../../../../modules/juce_gui_basics/widgets/juce_ToolbarItemComponent.cpp"
|
||||
|
|
|
|||
|
|
@ -2776,6 +2776,9 @@
|
|||
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\widgets\juce_TextEditor.cpp">
|
||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\widgets\juce_TextEditorModel.cpp">
|
||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\widgets\juce_Toolbar.cpp">
|
||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
|
|
|
|||
|
|
@ -3496,6 +3496,9 @@
|
|||
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\widgets\juce_TextEditor.cpp">
|
||||
<Filter>JUCE Modules\juce_gui_basics\widgets</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\widgets\juce_TextEditorModel.cpp">
|
||||
<Filter>JUCE Modules\juce_gui_basics\widgets</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\widgets\juce_Toolbar.cpp">
|
||||
<Filter>JUCE Modules\juce_gui_basics\widgets</Filter>
|
||||
</ClCompile>
|
||||
|
|
|
|||
|
|
@ -2776,6 +2776,9 @@
|
|||
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\widgets\juce_TextEditor.cpp">
|
||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\widgets\juce_TextEditorModel.cpp">
|
||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\widgets\juce_Toolbar.cpp">
|
||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
|
|
|
|||
|
|
@ -3496,6 +3496,9 @@
|
|||
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\widgets\juce_TextEditor.cpp">
|
||||
<Filter>JUCE Modules\juce_gui_basics\widgets</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\widgets\juce_TextEditorModel.cpp">
|
||||
<Filter>JUCE Modules\juce_gui_basics\widgets</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\widgets\juce_Toolbar.cpp">
|
||||
<Filter>JUCE Modules\juce_gui_basics\widgets</Filter>
|
||||
</ClCompile>
|
||||
|
|
|
|||
|
|
@ -2192,6 +2192,7 @@ add_library( ${BINARY_NAME}
|
|||
"../../../../../modules/juce_gui_basics/widgets/juce_TableListBox.h"
|
||||
"../../../../../modules/juce_gui_basics/widgets/juce_TextEditor.cpp"
|
||||
"../../../../../modules/juce_gui_basics/widgets/juce_TextEditor.h"
|
||||
"../../../../../modules/juce_gui_basics/widgets/juce_TextEditorModel.cpp"
|
||||
"../../../../../modules/juce_gui_basics/widgets/juce_Toolbar.cpp"
|
||||
"../../../../../modules/juce_gui_basics/widgets/juce_Toolbar.h"
|
||||
"../../../../../modules/juce_gui_basics/widgets/juce_ToolbarItemComponent.cpp"
|
||||
|
|
@ -4537,6 +4538,7 @@ set_source_files_properties(
|
|||
"../../../../../modules/juce_gui_basics/widgets/juce_TableListBox.h"
|
||||
"../../../../../modules/juce_gui_basics/widgets/juce_TextEditor.cpp"
|
||||
"../../../../../modules/juce_gui_basics/widgets/juce_TextEditor.h"
|
||||
"../../../../../modules/juce_gui_basics/widgets/juce_TextEditorModel.cpp"
|
||||
"../../../../../modules/juce_gui_basics/widgets/juce_Toolbar.cpp"
|
||||
"../../../../../modules/juce_gui_basics/widgets/juce_Toolbar.h"
|
||||
"../../../../../modules/juce_gui_basics/widgets/juce_ToolbarItemComponent.cpp"
|
||||
|
|
|
|||
|
|
@ -2663,6 +2663,9 @@
|
|||
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\widgets\juce_TextEditor.cpp">
|
||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\widgets\juce_TextEditorModel.cpp">
|
||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\widgets\juce_Toolbar.cpp">
|
||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
|
|
|
|||
|
|
@ -3343,6 +3343,9 @@
|
|||
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\widgets\juce_TextEditor.cpp">
|
||||
<Filter>JUCE Modules\juce_gui_basics\widgets</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\widgets\juce_TextEditorModel.cpp">
|
||||
<Filter>JUCE Modules\juce_gui_basics\widgets</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\widgets\juce_Toolbar.cpp">
|
||||
<Filter>JUCE Modules\juce_gui_basics\widgets</Filter>
|
||||
</ClCompile>
|
||||
|
|
|
|||
|
|
@ -1805,6 +1805,9 @@
|
|||
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\widgets\juce_TextEditor.cpp">
|
||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\widgets\juce_TextEditorModel.cpp">
|
||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\widgets\juce_Toolbar.cpp">
|
||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
|
|
|
|||
|
|
@ -2182,6 +2182,9 @@
|
|||
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\widgets\juce_TextEditor.cpp">
|
||||
<Filter>JUCE Modules\juce_gui_basics\widgets</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\widgets\juce_TextEditorModel.cpp">
|
||||
<Filter>JUCE Modules\juce_gui_basics\widgets</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\widgets\juce_Toolbar.cpp">
|
||||
<Filter>JUCE Modules\juce_gui_basics\widgets</Filter>
|
||||
</ClCompile>
|
||||
|
|
|
|||
|
|
@ -1805,6 +1805,9 @@
|
|||
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\widgets\juce_TextEditor.cpp">
|
||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\widgets\juce_TextEditorModel.cpp">
|
||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\widgets\juce_Toolbar.cpp">
|
||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
|
|
|
|||
|
|
@ -2182,6 +2182,9 @@
|
|||
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\widgets\juce_TextEditor.cpp">
|
||||
<Filter>JUCE Modules\juce_gui_basics\widgets</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\widgets\juce_TextEditorModel.cpp">
|
||||
<Filter>JUCE Modules\juce_gui_basics\widgets</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\widgets\juce_Toolbar.cpp">
|
||||
<Filter>JUCE Modules\juce_gui_basics\widgets</Filter>
|
||||
</ClCompile>
|
||||
|
|
|
|||
|
|
@ -2784,6 +2784,9 @@
|
|||
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\widgets\juce_TextEditor.cpp">
|
||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\widgets\juce_TextEditorModel.cpp">
|
||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\widgets\juce_Toolbar.cpp">
|
||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
|
|
|
|||
|
|
@ -3544,6 +3544,9 @@
|
|||
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\widgets\juce_TextEditor.cpp">
|
||||
<Filter>JUCE Modules\juce_gui_basics\widgets</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\widgets\juce_TextEditorModel.cpp">
|
||||
<Filter>JUCE Modules\juce_gui_basics\widgets</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\widgets\juce_Toolbar.cpp">
|
||||
<Filter>JUCE Modules\juce_gui_basics\widgets</Filter>
|
||||
</ClCompile>
|
||||
|
|
|
|||
|
|
@ -2784,6 +2784,9 @@
|
|||
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\widgets\juce_TextEditor.cpp">
|
||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\widgets\juce_TextEditorModel.cpp">
|
||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\widgets\juce_Toolbar.cpp">
|
||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
|
|
|
|||
|
|
@ -3544,6 +3544,9 @@
|
|||
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\widgets\juce_TextEditor.cpp">
|
||||
<Filter>JUCE Modules\juce_gui_basics\widgets</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\widgets\juce_TextEditorModel.cpp">
|
||||
<Filter>JUCE Modules\juce_gui_basics\widgets</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\widgets\juce_Toolbar.cpp">
|
||||
<Filter>JUCE Modules\juce_gui_basics\widgets</Filter>
|
||||
</ClCompile>
|
||||
|
|
|
|||
|
|
@ -2662,6 +2662,9 @@
|
|||
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\widgets\juce_TextEditor.cpp">
|
||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\widgets\juce_TextEditorModel.cpp">
|
||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\widgets\juce_Toolbar.cpp">
|
||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
|
|
|
|||
|
|
@ -3340,6 +3340,9 @@
|
|||
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\widgets\juce_TextEditor.cpp">
|
||||
<Filter>JUCE Modules\juce_gui_basics\widgets</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\widgets\juce_TextEditorModel.cpp">
|
||||
<Filter>JUCE Modules\juce_gui_basics\widgets</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\widgets\juce_Toolbar.cpp">
|
||||
<Filter>JUCE Modules\juce_gui_basics\widgets</Filter>
|
||||
</ClCompile>
|
||||
|
|
|
|||
|
|
@ -369,6 +369,7 @@
|
|||
#include "widgets/juce_Slider.cpp"
|
||||
#include "widgets/juce_TableHeaderComponent.cpp"
|
||||
#include "widgets/juce_TableListBox.cpp"
|
||||
#include "widgets/juce_TextEditorModel.cpp"
|
||||
#include "widgets/juce_TextEditor.cpp"
|
||||
#include "widgets/juce_Toolbar.cpp"
|
||||
#include "widgets/juce_ToolbarItemComponent.cpp"
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -252,6 +252,9 @@ public:
|
|||
|
||||
/** Applies a font to all the text in the editor.
|
||||
|
||||
This function also calls
|
||||
applyColourToAllText (findColour (TextEditor::ColourIds::textColourId), false);
|
||||
|
||||
If the changeCurrentFont argument is true then this will also set the
|
||||
new font as the font to be used for any new text that's added.
|
||||
|
||||
|
|
@ -774,8 +777,6 @@ protected:
|
|||
|
||||
private:
|
||||
//==============================================================================
|
||||
JUCE_PUBLIC_IN_DLL_BUILD (class UniformTextSection)
|
||||
struct Iterator;
|
||||
struct TextHolderComponent;
|
||||
struct TextEditorViewport;
|
||||
struct InsertAction;
|
||||
|
|
@ -827,8 +828,51 @@ private:
|
|||
unsigned int lastTransactionTime = 0;
|
||||
Font currentFont { withDefaultMetrics (FontOptions { 14.0f }) };
|
||||
mutable int totalNumChars = 0;
|
||||
int caretPosition = 0;
|
||||
OwnedArray<UniformTextSection> sections;
|
||||
|
||||
//==============================================================================
|
||||
enum class Edge
|
||||
{
|
||||
leading,
|
||||
trailing
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
struct CaretState
|
||||
{
|
||||
public:
|
||||
explicit CaretState (const TextEditor* ownerIn);
|
||||
|
||||
int getPosition() const { return position; }
|
||||
Edge getEdge() const { return edge; }
|
||||
|
||||
void setPosition (int newPosition);
|
||||
|
||||
/* Not all visual edge positions are permitted e.g. a trailing caret after a newline
|
||||
is not allowed. getVisualIndex() and getEdge() will return the closest permitted
|
||||
values to the preferred one.
|
||||
*/
|
||||
void setPreferredEdge (Edge newEdge);
|
||||
|
||||
/* The returned value is in the range [0, TextEditor::getTotalNumChars()]. It returns the
|
||||
glyph index to which the caret is closest visually. This is significant when
|
||||
differentiating between the end of one line and the beginning of the next.
|
||||
*/
|
||||
int getVisualIndex() const;
|
||||
|
||||
void updateEdge();
|
||||
|
||||
//==============================================================================
|
||||
CaretState withPosition (int newPosition) const;
|
||||
CaretState withPreferredEdge (Edge newEdge) const;
|
||||
|
||||
private:
|
||||
const TextEditor& owner;
|
||||
int position = 0;
|
||||
Edge edge = Edge::trailing;
|
||||
Edge preferredEdge = Edge::trailing;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
String textToShowWhenEmpty;
|
||||
Colour colourForTextWhenEmpty;
|
||||
juce_wchar passwordCharacter;
|
||||
|
|
@ -849,17 +893,21 @@ private:
|
|||
ListenerList<Listener> listeners;
|
||||
Array<Range<int>> underlinedSections;
|
||||
|
||||
class ParagraphStorage;
|
||||
class ParagraphsModel;
|
||||
struct TextEditorStorageChunks;
|
||||
class TextEditorStorage;
|
||||
|
||||
void moveCaret (int newCaretPos);
|
||||
void moveCaretTo (int newPosition, bool isSelecting);
|
||||
void recreateCaret();
|
||||
void handleCommandMessage (int) override;
|
||||
void coalesceSimilarSections();
|
||||
void splitSection (int sectionIndex, int charToSplitAt);
|
||||
void clearInternal (UndoManager*);
|
||||
void insert (const String&, int insertIndex, const Font&, Colour, UndoManager*, int newCaretPos);
|
||||
void reinsert (int insertIndex, const OwnedArray<UniformTextSection>&);
|
||||
void remove (Range<int>, UndoManager*, int caretPositionToMoveTo);
|
||||
void getCharPosition (int index, Point<float>&, float& lineHeight) const;
|
||||
void reinsert (const TextEditorStorageChunks& chunks);
|
||||
void remove (Range<int>, UndoManager*, int caretPositionToMoveTo, TextEditorStorageChunks* removedOut = nullptr);
|
||||
std::pair<Point<float>, float> getTextSelectionEdge (int index, Edge edge) const;
|
||||
std::pair<Point<float>, float> getCursorEdge (const CaretState& caret) const;
|
||||
void updateCaretPosition();
|
||||
void updateValueFromText();
|
||||
void textWasChangedByValue();
|
||||
|
|
@ -879,7 +927,21 @@ private:
|
|||
bool undoOrRedo (bool shouldUndo);
|
||||
UndoManager* getUndoManager() noexcept;
|
||||
void setSelection (Range<int>) noexcept;
|
||||
Point<int> getTextOffset() const noexcept;
|
||||
Point<int> getTextOffset() const;
|
||||
|
||||
Edge getEdgeTypeCloserToPosition (int indexInText, Point<float> pos) const;
|
||||
|
||||
std::unique_ptr<TextEditorStorage> textStorage;
|
||||
CaretState caretState;
|
||||
|
||||
bool isTextStorageHeightGreaterEqualThan (float value) const;
|
||||
float getTextStorageHeight() const;
|
||||
float getYOffset() const;
|
||||
void updateBaseShapedTextOptions();
|
||||
Range<int64> getLineRangeForIndex (int index);
|
||||
|
||||
template <typename T>
|
||||
detail::RangedValues<T> getGlyphRanges (const detail::RangedValues<T>& textRanges) const;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TextEditor)
|
||||
};
|
||||
|
|
|
|||
572
modules/juce_gui_basics/widgets/juce_TextEditorModel.cpp
Normal file
572
modules/juce_gui_basics/widgets/juce_TextEditorModel.cpp
Normal file
|
|
@ -0,0 +1,572 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE framework.
|
||||
Copyright (c) Raw Material Software Limited
|
||||
|
||||
JUCE is an open source framework subject to commercial or open source
|
||||
licensing.
|
||||
|
||||
By downloading, installing, or using the JUCE framework, or combining the
|
||||
JUCE framework with any other source code, object code, content or any other
|
||||
copyrightable work, you agree to the terms of the JUCE End User Licence
|
||||
Agreement, and all incorporated terms including the JUCE Privacy Policy and
|
||||
the JUCE Website Terms of Service, as applicable, which will bind you. If you
|
||||
do not agree to the terms of these agreements, we will not license the JUCE
|
||||
framework to you, and you must discontinue the installation or download
|
||||
process and cease use of the JUCE framework.
|
||||
|
||||
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
|
||||
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
|
||||
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
|
||||
|
||||
Or:
|
||||
|
||||
You may also use this code under the terms of the AGPLv3:
|
||||
https://www.gnu.org/licenses/agpl-3.0.en.html
|
||||
|
||||
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
|
||||
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
|
||||
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
class TextEditor::ParagraphStorage
|
||||
{
|
||||
public:
|
||||
ParagraphStorage (String s, const TextEditorStorage* storageIn)
|
||||
: text { std::move (s) },
|
||||
numBytesAsUTF8 { text.getNumBytesAsUTF8() },
|
||||
storage { *storageIn }
|
||||
{
|
||||
updatePasswordReplacementText();
|
||||
}
|
||||
|
||||
const String& getText() const
|
||||
{
|
||||
return text;
|
||||
}
|
||||
|
||||
const String& getTextForDisplay() const;
|
||||
|
||||
size_t getNumBytesAsUTF8() const;
|
||||
|
||||
void setRange (Range<int64> rangeIn)
|
||||
{
|
||||
range = rangeIn;
|
||||
}
|
||||
|
||||
auto getRange() const
|
||||
{
|
||||
return range;
|
||||
}
|
||||
|
||||
const detail::ShapedText& getShapedText();
|
||||
|
||||
float getHeight()
|
||||
{
|
||||
if (! height.has_value())
|
||||
height = getShapedText().getHeight();
|
||||
|
||||
return *height;
|
||||
}
|
||||
|
||||
int64 getNumGlyphs()
|
||||
{
|
||||
if (! numGlyphs.has_value())
|
||||
numGlyphs = getShapedText().getNumGlyphs();
|
||||
|
||||
return *numGlyphs;
|
||||
}
|
||||
|
||||
float getTop();
|
||||
|
||||
int64 getStartingGlyph();
|
||||
|
||||
void clearShapedText();
|
||||
|
||||
private:
|
||||
void updatePasswordReplacementText();
|
||||
|
||||
String text;
|
||||
std::optional<String> passwordReplacementText;
|
||||
size_t numBytesAsUTF8;
|
||||
Range<int64> range;
|
||||
const TextEditorStorage& storage;
|
||||
std::optional<detail::ShapedText> shapedText;
|
||||
std::optional<float> height;
|
||||
std::optional<int64> numGlyphs;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
class TextEditor::ParagraphsModel
|
||||
{
|
||||
public:
|
||||
using ParagraphItem = detail::RangedValuesIteratorItem<const std::unique_ptr<ParagraphStorage>>;
|
||||
|
||||
explicit ParagraphsModel (const TextEditorStorage* ownerIn)
|
||||
: owner { *ownerIn }
|
||||
{}
|
||||
|
||||
void set (Range<int64> range, const String& text)
|
||||
{
|
||||
using namespace detail;
|
||||
|
||||
const auto codepointBeforeRange = getTextInRange (Range<int64>::withStartAndLength (range.getStart() - 1, 1));
|
||||
|
||||
Ranges::Operations ops;
|
||||
|
||||
ranges.drop (range, ops);
|
||||
|
||||
if (! text.isEmpty())
|
||||
{
|
||||
ranges.insert ({ range.getStart(), range.getStart() + text.length() }, ops);
|
||||
mergeForward (ranges, *ranges.getIndexForEnclosingRange (range.getStart()), ops);
|
||||
}
|
||||
|
||||
if (const auto newParagraphIndex = ranges.getIndexForEnclosingRange (range.getStart()))
|
||||
ranges.mergeBack (*newParagraphIndex, ops);
|
||||
|
||||
const auto splitBeforeOffset = range.getStart() + 1 - (codepointBeforeRange.isEmpty() ? 0 : 1);
|
||||
|
||||
for (auto breakAfterIndex : UnicodeHelpers::getLineBreaks (codepointBeforeRange + text))
|
||||
ranges.split (breakAfterIndex + splitBeforeOffset, ops);
|
||||
|
||||
handleOps (ops, text);
|
||||
}
|
||||
|
||||
String getText() const
|
||||
{
|
||||
const auto numBytes = std::accumulate (storage.begin(),
|
||||
storage.end(),
|
||||
(size_t) 0,
|
||||
[] (auto sum, auto& p)
|
||||
{
|
||||
return sum + p->getNumBytesAsUTF8();
|
||||
});
|
||||
|
||||
MemoryOutputStream mo;
|
||||
mo.preallocate (numBytes);
|
||||
|
||||
for (const auto& paragraph : storage)
|
||||
mo << paragraph->getText();
|
||||
|
||||
return mo.toUTF8();
|
||||
}
|
||||
|
||||
String getTextInRange (Range<int64> range) const
|
||||
{
|
||||
String text;
|
||||
|
||||
for (const auto& partialRange : ranges.getIntersectionsWith (range))
|
||||
{
|
||||
const auto i = *ranges.getIndexForEnclosingRange (partialRange.getStart());
|
||||
const auto fullRange = ranges.get (i);
|
||||
auto& paragraph = *storage[i];
|
||||
const auto startInParagraph = (int) (partialRange.getStart() - fullRange.getStart());
|
||||
text += paragraph.getText().substring (startInParagraph,
|
||||
startInParagraph + (int) partialRange.getLength());
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
auto begin() const
|
||||
{
|
||||
return detail::RangedValuesIterator<const std::unique_ptr<ParagraphStorage>> { storage.data(),
|
||||
ranges.data(),
|
||||
ranges.data() };
|
||||
}
|
||||
|
||||
auto end() const
|
||||
{
|
||||
return detail::RangedValuesIterator<const std::unique_ptr<ParagraphStorage>> { storage.data(),
|
||||
ranges.data(),
|
||||
ranges.data() + ranges.size() };
|
||||
}
|
||||
|
||||
std::optional<ParagraphItem> getParagraphContainingCodepointIndex (int64 index)
|
||||
{
|
||||
const auto paragraphIndex = ranges.getIndexForEnclosingRange (index);
|
||||
|
||||
if (! paragraphIndex.has_value())
|
||||
return std::nullopt;
|
||||
|
||||
return ParagraphItem { ranges.get (*paragraphIndex),
|
||||
storage[*paragraphIndex] };
|
||||
}
|
||||
|
||||
bool isEmpty() const { return storage.empty(); }
|
||||
|
||||
ParagraphItem back() const
|
||||
{
|
||||
jassert (! ranges.isEmpty());
|
||||
return { ranges.get (ranges.size() - 1), storage.back() };
|
||||
}
|
||||
|
||||
int64 getTotalNumChars() const
|
||||
{
|
||||
if (ranges.isEmpty())
|
||||
return 0;
|
||||
|
||||
return ranges.getRanges().back().getEnd();
|
||||
}
|
||||
|
||||
int64 getTotalNumGlyphs() const
|
||||
{
|
||||
return std::accumulate (storage.begin(),
|
||||
storage.end(),
|
||||
(int64) 0,
|
||||
[] (const auto& sum, const auto& item)
|
||||
{
|
||||
return sum + item->getNumGlyphs();
|
||||
});
|
||||
}
|
||||
|
||||
private:
|
||||
static void mergeForward (detail::Ranges& ranges, size_t index, detail::Ranges::Operations& ops)
|
||||
{
|
||||
if (ranges.size() > index + 1)
|
||||
return ranges.mergeBack (index + 1, ops);
|
||||
}
|
||||
|
||||
void handleOps (const detail::Ranges::Operations& ops, const String& text)
|
||||
{
|
||||
using namespace detail;
|
||||
|
||||
for (const auto& op : ops)
|
||||
{
|
||||
if (auto* newOp = std::get_if<Ranges::Ops::New> (&op))
|
||||
{
|
||||
storage.insert (iteratorWithAdvance (storage.begin(), newOp->index),
|
||||
createParagraph (text));
|
||||
}
|
||||
else if (auto* split = std::get_if<Ranges::Ops::Split> (&op))
|
||||
{
|
||||
const auto& splitValue = storage[split->index]->getText();
|
||||
const auto localLeftRange = split->leftRange.movedToStartAt (0);
|
||||
const auto localRightRange = split->rightRange.movedToStartAt (localLeftRange.getEnd());
|
||||
|
||||
auto leftSplitValue = splitValue.substring ((int) localLeftRange.getStart(),
|
||||
(int) localLeftRange.getEnd());
|
||||
|
||||
auto rightSplitValue = splitValue.substring ((int) localRightRange.getStart(),
|
||||
(int) localRightRange.getEnd());
|
||||
|
||||
storage[split->index] = createParagraph (std::move (leftSplitValue));
|
||||
|
||||
storage.insert (iteratorWithAdvance (storage.begin(), split->index + 1),
|
||||
createParagraph (std::move (rightSplitValue)));
|
||||
}
|
||||
else if (auto* erased = std::get_if<Ranges::Ops::Erase> (&op))
|
||||
{
|
||||
storage.erase (iteratorWithAdvance (storage.begin(), erased->range.getStart()),
|
||||
iteratorWithAdvance (storage.begin(), erased->range.getEnd()));
|
||||
}
|
||||
else if (auto* changed = std::get_if<Ranges::Ops::Change> (&op))
|
||||
{
|
||||
const auto oldRange = changed->oldRange;
|
||||
const auto newRange = changed->newRange;
|
||||
|
||||
// This happens when a range just gets shifted due to drop or insert operations
|
||||
if (oldRange.getLength() == newRange.getLength())
|
||||
continue;
|
||||
|
||||
auto deltaStart = (int) (newRange.getStart() - oldRange.getStart());
|
||||
auto deltaEnd = (int) (newRange.getEnd() - oldRange.getEnd());
|
||||
|
||||
auto& paragraph = storage[changed->index];
|
||||
const auto& oldText = paragraph->getText();
|
||||
|
||||
jassert (deltaStart >= 0);
|
||||
|
||||
if (deltaEnd <= 0)
|
||||
{
|
||||
paragraph = createParagraph (oldText.substring (deltaStart, oldText.length() + deltaEnd));
|
||||
}
|
||||
else
|
||||
{
|
||||
jassert (changed->index + 1 < storage.size());
|
||||
paragraph = createParagraph (oldText.substring (deltaStart, oldText.length())
|
||||
+ storage[changed->index + 1]->getText().substring (0, deltaEnd));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto [index, range] : enumerate (ranges, size_t{}))
|
||||
storage[index]->setRange (range);
|
||||
}
|
||||
|
||||
std::unique_ptr<ParagraphStorage> createParagraph (String s) const
|
||||
{
|
||||
return std::make_unique<ParagraphStorage> (s, &owner);
|
||||
}
|
||||
|
||||
const TextEditorStorage& owner;
|
||||
detail::Ranges ranges;
|
||||
std::vector<std::unique_ptr<ParagraphStorage>> storage;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
struct TextEditor::TextEditorStorageChunks
|
||||
{
|
||||
std::vector<int64> positions;
|
||||
std::vector<String> texts;
|
||||
std::vector<Font> fonts;
|
||||
std::vector<Colour> colours;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
class TextEditor::TextEditorStorage
|
||||
{
|
||||
public:
|
||||
void set (Range<int64> range, const String& text, const Font& font, const Colour& colour)
|
||||
{
|
||||
paragraphs.set (range, text);
|
||||
|
||||
detail::Ranges::Operations ops;
|
||||
|
||||
fonts.drop (range, ops);
|
||||
colours.drop (range, ops);
|
||||
ops.clear();
|
||||
|
||||
const auto insertionRange = Range<int64>::withStartAndLength (range.getStart(),
|
||||
(int64) text.length());
|
||||
fonts.insert (insertionRange, font, ops);
|
||||
colours.insert (insertionRange, colour, ops);
|
||||
}
|
||||
|
||||
void setFontForAllText (const Font& font)
|
||||
{
|
||||
detail::Ranges::Operations ops;
|
||||
fonts.set ({ 0, paragraphs.getTotalNumChars() }, font, ops);
|
||||
clearShapedTexts();
|
||||
}
|
||||
|
||||
void setColourForAllText (const Colour& colour)
|
||||
{
|
||||
detail::Ranges::Operations ops;
|
||||
colours.set ({ 0, paragraphs.getTotalNumChars() }, colour, ops);
|
||||
clearShapedTexts();
|
||||
}
|
||||
|
||||
void remove (Range<int64> range, TextEditorStorageChunks* removedOut)
|
||||
{
|
||||
using namespace detail;
|
||||
|
||||
detail::Ranges::Operations ops;
|
||||
|
||||
RangedValues<int64> rangeConstraint;
|
||||
rangeConstraint.set (range, 0, ops);
|
||||
|
||||
if (removedOut != nullptr)
|
||||
{
|
||||
for (const auto [r, font, colour, _] : makeIntersectingRangedValues (&fonts, &colours, &rangeConstraint))
|
||||
{
|
||||
ignoreUnused (_);
|
||||
|
||||
removedOut->positions.push_back (r.getStart());
|
||||
removedOut->texts.push_back (getTextInRange (r));
|
||||
removedOut->fonts.push_back (font);
|
||||
removedOut->colours.push_back (colour);
|
||||
}
|
||||
}
|
||||
|
||||
paragraphs.set (range, "");
|
||||
ops.clear();
|
||||
fonts.drop (range, ops);
|
||||
colours.drop (range, ops);
|
||||
}
|
||||
|
||||
void addChunks (const TextEditorStorageChunks& chunks)
|
||||
{
|
||||
for (size_t i = 0; i < chunks.positions.size(); ++i)
|
||||
{
|
||||
set (Range<int64>::withStartAndLength (chunks.positions[i], 0),
|
||||
chunks.texts[i],
|
||||
chunks.fonts[i],
|
||||
chunks.colours[i]);
|
||||
}
|
||||
}
|
||||
|
||||
String getText() const
|
||||
{
|
||||
return paragraphs.getText();
|
||||
}
|
||||
|
||||
String getTextInRange (Range<int64> range) const
|
||||
{
|
||||
return paragraphs.getTextInRange (range);
|
||||
}
|
||||
|
||||
detail::RangedValues<Font> getFonts (Range<int64> range) const
|
||||
{
|
||||
return fonts.getIntersectionsStartingAtZeroWith (range);
|
||||
}
|
||||
|
||||
const auto& getColours() const
|
||||
{
|
||||
return colours;
|
||||
}
|
||||
|
||||
auto begin() const { return paragraphs.begin(); }
|
||||
auto end() const { return paragraphs.end(); }
|
||||
|
||||
auto isEmpty() const { return paragraphs.isEmpty(); }
|
||||
auto back() const { return paragraphs.back(); }
|
||||
|
||||
std::optional<Font> getLastFont() const
|
||||
{
|
||||
if (fonts.isEmpty())
|
||||
return std::nullopt;
|
||||
|
||||
return fonts.back().value;
|
||||
}
|
||||
|
||||
int64 getTotalNumChars() const
|
||||
{
|
||||
return paragraphs.getTotalNumChars();
|
||||
}
|
||||
|
||||
int64 getTotalNumGlyphs() const
|
||||
{
|
||||
return paragraphs.getTotalNumGlyphs();
|
||||
}
|
||||
|
||||
void setBaseShapedTextOptions (detail::ShapedTextOptions options, juce_wchar passwordCharacterIn)
|
||||
{
|
||||
if (std::exchange (baseShapedTextOptions, options) != options)
|
||||
clearShapedTexts();
|
||||
|
||||
if (std::exchange (passwordCharacter, passwordCharacterIn) != passwordCharacterIn)
|
||||
clearShapedTexts();
|
||||
}
|
||||
|
||||
detail::ShapedTextOptions getShapedTextOptions (Range<int64> range) const
|
||||
{
|
||||
return baseShapedTextOptions.withFonts (getFonts (range));
|
||||
}
|
||||
|
||||
juce_wchar getPasswordCharacter() const
|
||||
{
|
||||
return passwordCharacter;
|
||||
}
|
||||
|
||||
auto getParagraphContainingCodepointIndex (int64 index)
|
||||
{
|
||||
return paragraphs.getParagraphContainingCodepointIndex (index);
|
||||
}
|
||||
|
||||
private:
|
||||
void clearShapedTexts()
|
||||
{
|
||||
for (auto p : paragraphs)
|
||||
p.value->clearShapedText();
|
||||
}
|
||||
|
||||
detail::RangedValues<Font> fonts;
|
||||
detail::RangedValues<Colour> colours;
|
||||
ParagraphsModel paragraphs { this };
|
||||
detail::ShapedTextOptions baseShapedTextOptions;
|
||||
juce_wchar passwordCharacter = 0;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
const String& TextEditor::ParagraphStorage::getTextForDisplay() const
|
||||
{
|
||||
if (passwordReplacementText.has_value())
|
||||
return *passwordReplacementText;
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
size_t TextEditor::ParagraphStorage::getNumBytesAsUTF8() const
|
||||
{
|
||||
return numBytesAsUTF8;
|
||||
}
|
||||
|
||||
const detail::ShapedText& TextEditor::ParagraphStorage::getShapedText()
|
||||
{
|
||||
if (! shapedText.has_value())
|
||||
shapedText.emplace (getTextForDisplay(), storage.getShapedTextOptions (range));
|
||||
|
||||
return *shapedText;
|
||||
}
|
||||
|
||||
float TextEditor::ParagraphStorage::getTop()
|
||||
{
|
||||
float top = 0.0f;
|
||||
|
||||
for (const auto paragraphItem : storage)
|
||||
{
|
||||
if (paragraphItem.value.get() == this)
|
||||
break;
|
||||
|
||||
top += paragraphItem.value->getHeight();
|
||||
}
|
||||
|
||||
return top;
|
||||
}
|
||||
|
||||
int64 TextEditor::ParagraphStorage::getStartingGlyph()
|
||||
{
|
||||
int64 startingGlyph = 0;
|
||||
|
||||
for (const auto paragraph : storage)
|
||||
{
|
||||
if (paragraph.value.get() == this)
|
||||
break;
|
||||
|
||||
startingGlyph += paragraph.value->getNumGlyphs();
|
||||
}
|
||||
|
||||
return startingGlyph;
|
||||
}
|
||||
|
||||
void TextEditor::ParagraphStorage::updatePasswordReplacementText()
|
||||
{
|
||||
const auto passwordChar = storage.getPasswordCharacter();
|
||||
|
||||
if (passwordChar == 0)
|
||||
{
|
||||
passwordReplacementText.reset();
|
||||
return;
|
||||
}
|
||||
|
||||
constexpr juce_wchar cr = 0x0d;
|
||||
constexpr juce_wchar lf = 0x0a;
|
||||
|
||||
const auto startIt = text.begin();
|
||||
auto endIt = text.end();
|
||||
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
if (endIt == startIt)
|
||||
break;
|
||||
|
||||
auto newEnd = endIt - 1;
|
||||
|
||||
if (*newEnd != cr && *newEnd != lf)
|
||||
break;
|
||||
|
||||
endIt = newEnd;
|
||||
}
|
||||
|
||||
passwordReplacementText = String::repeatedString (String::charToString (passwordChar),
|
||||
(int) startIt.lengthUpTo (endIt))
|
||||
+ String { endIt, text.end() };
|
||||
}
|
||||
|
||||
void TextEditor::ParagraphStorage::clearShapedText()
|
||||
{
|
||||
shapedText.reset();
|
||||
height.reset();
|
||||
numGlyphs.reset();
|
||||
updatePasswordReplacementText();
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue