mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-20 01:14:20 +00:00
Added read-only support for the CodeEditorComponent.
This commit is contained in:
parent
5e10803565
commit
f89c2ca05d
2 changed files with 83 additions and 52 deletions
|
|
@ -340,6 +340,7 @@ CodeEditorComponent::CodeEditorComponent (CodeDocument& doc, CodeTokeniser* cons
|
|||
columnsOnScreen (0),
|
||||
scrollbarThickness (16),
|
||||
columnToTryToMaintain (-1),
|
||||
readOnly (false),
|
||||
useSpacesForTabs (false),
|
||||
showLineNumbers (false),
|
||||
shouldFollowDocumentChanges (false),
|
||||
|
|
@ -435,6 +436,11 @@ void CodeEditorComponent::setLineNumbersShown (const bool shouldBeShown)
|
|||
}
|
||||
}
|
||||
|
||||
void CodeEditorComponent::setReadOnly (bool b) noexcept
|
||||
{
|
||||
readOnly = b;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void CodeEditorComponent::resized()
|
||||
{
|
||||
|
|
@ -745,37 +751,43 @@ void CodeEditorComponent::insertTextAtCaret (const String& newText)
|
|||
|
||||
void CodeEditorComponent::insertText (const String& newText)
|
||||
{
|
||||
document.deleteSection (selectionStart, selectionEnd);
|
||||
if (! readOnly)
|
||||
{
|
||||
document.deleteSection (selectionStart, selectionEnd);
|
||||
|
||||
if (newText.isNotEmpty())
|
||||
document.insertText (caretPos, newText);
|
||||
if (newText.isNotEmpty())
|
||||
document.insertText (caretPos, newText);
|
||||
|
||||
scrollToKeepCaretOnScreen();
|
||||
scrollToKeepCaretOnScreen();
|
||||
}
|
||||
}
|
||||
|
||||
void CodeEditorComponent::insertTabAtCaret()
|
||||
{
|
||||
if (CharacterFunctions::isWhitespace (caretPos.getCharacter())
|
||||
&& caretPos.getLineNumber() == caretPos.movedBy (1).getLineNumber())
|
||||
if (! readOnly)
|
||||
{
|
||||
moveCaretTo (document.findWordBreakAfter (caretPos), false);
|
||||
}
|
||||
if (CharacterFunctions::isWhitespace (caretPos.getCharacter())
|
||||
&& caretPos.getLineNumber() == caretPos.movedBy (1).getLineNumber())
|
||||
{
|
||||
moveCaretTo (document.findWordBreakAfter (caretPos), false);
|
||||
}
|
||||
|
||||
if (useSpacesForTabs)
|
||||
{
|
||||
const int caretCol = indexToColumn (caretPos.getLineNumber(), caretPos.getIndexInLine());
|
||||
const int spacesNeeded = spacesPerTab - (caretCol % spacesPerTab);
|
||||
insertTextAtCaret (String::repeatedString (" ", spacesNeeded));
|
||||
}
|
||||
else
|
||||
{
|
||||
insertTextAtCaret ("\t");
|
||||
if (useSpacesForTabs)
|
||||
{
|
||||
const int caretCol = indexToColumn (caretPos.getLineNumber(), caretPos.getIndexInLine());
|
||||
const int spacesNeeded = spacesPerTab - (caretCol % spacesPerTab);
|
||||
insertTextAtCaret (String::repeatedString (" ", spacesNeeded));
|
||||
}
|
||||
else
|
||||
{
|
||||
insertTextAtCaret ("\t");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CodeEditorComponent::deleteWhitespaceBackwardsToTabStop()
|
||||
{
|
||||
if (getHighlightedRegion().isEmpty())
|
||||
if (getHighlightedRegion().isEmpty() && ! readOnly)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
|
|
@ -804,43 +816,46 @@ void CodeEditorComponent::unindentSelection() { indentSelectedLines (-spacesPe
|
|||
|
||||
void CodeEditorComponent::indentSelectedLines (const int spacesToAdd)
|
||||
{
|
||||
newTransaction();
|
||||
|
||||
CodeDocument::Position oldSelectionStart (selectionStart), oldSelectionEnd (selectionEnd), oldCaret (caretPos);
|
||||
oldSelectionStart.setPositionMaintained (true);
|
||||
oldSelectionEnd.setPositionMaintained (true);
|
||||
oldCaret.setPositionMaintained (true);
|
||||
|
||||
const int lineStart = selectionStart.getLineNumber();
|
||||
int lineEnd = selectionEnd.getLineNumber();
|
||||
|
||||
if (lineEnd > lineStart && selectionEnd.getIndexInLine() == 0)
|
||||
--lineEnd;
|
||||
|
||||
for (int line = lineStart; line <= lineEnd; ++line)
|
||||
if (! readOnly)
|
||||
{
|
||||
const String lineText (document.getLine (line));
|
||||
const int nonWhitespaceStart = CodeEditorHelpers::findFirstNonWhitespaceChar (lineText);
|
||||
newTransaction();
|
||||
|
||||
if (nonWhitespaceStart > 0 || lineText.trimStart().isNotEmpty())
|
||||
CodeDocument::Position oldSelectionStart (selectionStart), oldSelectionEnd (selectionEnd), oldCaret (caretPos);
|
||||
oldSelectionStart.setPositionMaintained (true);
|
||||
oldSelectionEnd.setPositionMaintained (true);
|
||||
oldCaret.setPositionMaintained (true);
|
||||
|
||||
const int lineStart = selectionStart.getLineNumber();
|
||||
int lineEnd = selectionEnd.getLineNumber();
|
||||
|
||||
if (lineEnd > lineStart && selectionEnd.getIndexInLine() == 0)
|
||||
--lineEnd;
|
||||
|
||||
for (int line = lineStart; line <= lineEnd; ++line)
|
||||
{
|
||||
const CodeDocument::Position wsStart (document, line, 0);
|
||||
const CodeDocument::Position wsEnd (document, line, nonWhitespaceStart);
|
||||
const String lineText (document.getLine (line));
|
||||
const int nonWhitespaceStart = CodeEditorHelpers::findFirstNonWhitespaceChar (lineText);
|
||||
|
||||
const int numLeadingSpaces = indexToColumn (line, wsEnd.getIndexInLine());
|
||||
const int newNumLeadingSpaces = jmax (0, numLeadingSpaces + spacesToAdd);
|
||||
|
||||
if (newNumLeadingSpaces != numLeadingSpaces)
|
||||
if (nonWhitespaceStart > 0 || lineText.trimStart().isNotEmpty())
|
||||
{
|
||||
document.deleteSection (wsStart, wsEnd);
|
||||
document.insertText (wsStart, getTabString (newNumLeadingSpaces));
|
||||
const CodeDocument::Position wsStart (document, line, 0);
|
||||
const CodeDocument::Position wsEnd (document, line, nonWhitespaceStart);
|
||||
|
||||
const int numLeadingSpaces = indexToColumn (line, wsEnd.getIndexInLine());
|
||||
const int newNumLeadingSpaces = jmax (0, numLeadingSpaces + spacesToAdd);
|
||||
|
||||
if (newNumLeadingSpaces != numLeadingSpaces)
|
||||
{
|
||||
document.deleteSection (wsStart, wsEnd);
|
||||
document.insertText (wsStart, getTabString (newNumLeadingSpaces));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
selectionStart = oldSelectionStart;
|
||||
selectionEnd = oldSelectionEnd;
|
||||
caretPos = oldCaret;
|
||||
selectionStart = oldSelectionStart;
|
||||
selectionEnd = oldSelectionEnd;
|
||||
caretPos = oldCaret;
|
||||
}
|
||||
}
|
||||
|
||||
void CodeEditorComponent::cut()
|
||||
|
|
@ -1116,6 +1131,9 @@ void CodeEditorComponent::selectRegion (const CodeDocument::Position& start,
|
|||
//==============================================================================
|
||||
bool CodeEditorComponent::undo()
|
||||
{
|
||||
if (readOnly)
|
||||
return false;
|
||||
|
||||
ScopedValueSetter<bool> svs (shouldFollowDocumentChanges, true, false);
|
||||
document.undo();
|
||||
scrollToKeepCaretOnScreen();
|
||||
|
|
@ -1124,6 +1142,9 @@ bool CodeEditorComponent::undo()
|
|||
|
||||
bool CodeEditorComponent::redo()
|
||||
{
|
||||
if (readOnly)
|
||||
return false;
|
||||
|
||||
ScopedValueSetter<bool> svs (shouldFollowDocumentChanges, true, false);
|
||||
document.redo();
|
||||
scrollToKeepCaretOnScreen();
|
||||
|
|
@ -1169,6 +1190,9 @@ bool CodeEditorComponent::keyPressed (const KeyPress& key)
|
|||
{
|
||||
if (! TextEditorKeyMapper<CodeEditorComponent>::invokeKeyFunction (*this, key))
|
||||
{
|
||||
if (readOnly)
|
||||
return false;
|
||||
|
||||
if (key == KeyPress::tabKey || key.getTextCharacter() == '\t') handleTabKey();
|
||||
else if (key == KeyPress::returnKey) handleReturnKey();
|
||||
else if (key == KeyPress::escapeKey) handleEscapeKey();
|
||||
|
|
@ -1224,7 +1248,7 @@ void CodeEditorComponent::getCommandInfo (const CommandID commandID, Application
|
|||
{
|
||||
case StandardApplicationCommandIDs::cut:
|
||||
result.setInfo (TRANS ("Cut"), TRANS ("Copies the currently selected text to the clipboard and deletes it."), "Editing", 0);
|
||||
result.setActive (anythingSelected);
|
||||
result.setActive (anythingSelected && ! readOnly);
|
||||
result.defaultKeypresses.add (KeyPress ('x', ModifierKeys::commandModifier, 0));
|
||||
break;
|
||||
|
||||
|
|
@ -1236,12 +1260,13 @@ void CodeEditorComponent::getCommandInfo (const CommandID commandID, Application
|
|||
|
||||
case StandardApplicationCommandIDs::paste:
|
||||
result.setInfo (TRANS ("Paste"), TRANS ("Inserts text from the clipboard."), "Editing", 0);
|
||||
result.setActive (! readOnly);
|
||||
result.defaultKeypresses.add (KeyPress ('v', ModifierKeys::commandModifier, 0));
|
||||
break;
|
||||
|
||||
case StandardApplicationCommandIDs::del:
|
||||
result.setInfo (TRANS ("Delete"), TRANS ("Deletes any selected text."), "Editing", 0);
|
||||
result.setActive (anythingSelected);
|
||||
result.setActive (anythingSelected && ! readOnly);
|
||||
break;
|
||||
|
||||
case StandardApplicationCommandIDs::selectAll:
|
||||
|
|
@ -1252,13 +1277,13 @@ void CodeEditorComponent::getCommandInfo (const CommandID commandID, Application
|
|||
case StandardApplicationCommandIDs::undo:
|
||||
result.setInfo (TRANS ("Undo"), TRANS ("Undo"), "Editing", 0);
|
||||
result.defaultKeypresses.add (KeyPress ('z', ModifierKeys::commandModifier, 0));
|
||||
result.setActive (document.getUndoManager().canUndo());
|
||||
result.setActive (document.getUndoManager().canUndo() && ! readOnly);
|
||||
break;
|
||||
|
||||
case StandardApplicationCommandIDs::redo:
|
||||
result.setInfo (TRANS ("Redo"), TRANS ("Redo"), "Editing", 0);
|
||||
result.defaultKeypresses.add (KeyPress ('z', ModifierKeys::commandModifier | ModifierKeys::shiftModifier, 0));
|
||||
result.setActive (document.getUndoManager().canRedo());
|
||||
result.setActive (document.getUndoManager().canRedo() && ! readOnly);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -204,6 +204,12 @@ public:
|
|||
/** Returns the font that the editor is using. */
|
||||
const Font& getFont() const noexcept { return font; }
|
||||
|
||||
/** Makes the editor read-only. */
|
||||
void setReadOnly (bool shouldBeReadOnly) noexcept;
|
||||
|
||||
/** Returns true if the editor is set to be read-only. */
|
||||
bool isReadOnly() const noexcept { return readOnly; }
|
||||
|
||||
//==============================================================================
|
||||
struct JUCE_API ColourScheme
|
||||
{
|
||||
|
|
@ -352,7 +358,7 @@ private:
|
|||
float charWidth;
|
||||
int lineHeight, linesOnScreen, columnsOnScreen;
|
||||
int scrollbarThickness, columnToTryToMaintain;
|
||||
bool useSpacesForTabs, showLineNumbers, shouldFollowDocumentChanges;
|
||||
bool readOnly, useSpacesForTabs, showLineNumbers, shouldFollowDocumentChanges;
|
||||
double xOffset;
|
||||
|
||||
CodeDocument::Position caretPos, selectionStart, selectionEnd;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue