Skip to content

Commit

Permalink
Fixed annotation folding for quotes and comment blocks.
Browse files Browse the repository at this point in the history
If user moves inside the hidden block then unfold automatically.
  • Loading branch information
adeas31 committed May 22, 2016
1 parent 329215b commit afdff3c
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 33 deletions.
37 changes: 34 additions & 3 deletions OMEdit/OMEditGUI/Editors/BaseEditor.cpp
Expand Up @@ -652,7 +652,7 @@ void BaseEditor::PlainTextEdit::lineNumberAreaPaintEvent(QPaintEvent *event)
const int lineNumbersWidth = mpLineNumberArea->width() - collapseColumnWidth;

while (block.isValid() && top <= event->rect().bottom()) {
QTextDocument *doc = document();
QTextDocument *pTextDocument = document();
top = bottom;
const qreal height = blockBoundingRect(block).height();
bottom = top + height;
Expand All @@ -663,7 +663,7 @@ void BaseEditor::PlainTextEdit::lineNumberAreaPaintEvent(QPaintEvent *event)

if (!nextVisibleBlock.isVisible()) {
// invisible blocks do have zero line count
nextVisibleBlock = doc->findBlockByLineNumber(nextVisibleBlock.firstLineNumber());
nextVisibleBlock = pTextDocument->findBlockByLineNumber(nextVisibleBlock.firstLineNumber());
nextVisibleBlockNumber = nextVisibleBlock.blockNumber();
}

Expand Down Expand Up @@ -707,6 +707,7 @@ void BaseEditor::PlainTextEdit::lineNumberAreaPaintEvent(QPaintEvent *event)
if (pTextEditorPage->getSyntaxHighlightingGroupBox()->isChecked() && pTextEditorPage->getCodeFoldingCheckBox()->isChecked()) {
painter.save();
painter.setRenderHint(QPainter::Antialiasing, false);
painter.setPen(Qt::gray);

TextBlockUserData *nextBlockUserData = BaseEditorDocumentLayout::testUserData(nextBlock);
bool drawFoldingControl = nextBlockUserData && BaseEditorDocumentLayout::foldingIndent(block) < nextBlockUserData->foldingIndent();
Expand All @@ -715,7 +716,7 @@ void BaseEditor::PlainTextEdit::lineNumberAreaPaintEvent(QPaintEvent *event)
int boxWidth = foldBoxWidth(fm);
int size = boxWidth / 4;
QRect foldingMarkerBox(lineNumbersWidth + size, top + size, 2 * (size) + 1, 2 * (size) + 1);
QRect foldingLineBox(lineNumbersWidth + size, top, 2 * (size) + 1, fm.height());
QRect foldingLineBox(lineNumbersWidth + size, top, 2 * (size) + 1, height);

if (drawEnd) {
painter.drawLine(QPointF(foldingLineBox.center().x(), foldingLineBox.top()), foldingLineBox.center());
Expand Down Expand Up @@ -883,6 +884,7 @@ void BaseEditor::PlainTextEdit::updateCursorPosition()
Label *pCursorPositionLabel = mpBaseEditor->getModelWidget()->getCursorPositionLabel();
pCursorPositionLabel->setText(QString("Line: %1, Col: %2").arg(line).arg(column));
}
ensureCursorVisible();
}

/*!
Expand Down Expand Up @@ -995,6 +997,35 @@ void BaseEditor::PlainTextEdit::moveCursorVisible(bool ensureVisible)
}
}

/*!
* \brief BaseEditor::PlainTextEdit::ensureCursorVisible
* Makes sure cursor is visible when user moves it inside hidden block.
*/
void BaseEditor::PlainTextEdit::ensureCursorVisible()
{
QTextBlock block = textCursor().block();
if (!block.isVisible()) {
BaseEditorDocumentLayout *pDocumentLayout = qobject_cast<BaseEditorDocumentLayout*>(document()->documentLayout());
// Open all folds of current line.
int indent = BaseEditorDocumentLayout::foldingIndent(block);
block = block.previous();
while (block.isValid()) {
const int indent2 = BaseEditorDocumentLayout::foldingIndent(block);
if (BaseEditorDocumentLayout::canFold(block) && indent2 < indent) {
BaseEditorDocumentLayout::foldOrUnfold(block, true);
if (block.isVisible()) {
break;
}
indent = indent2;
}
block = block.previous();
}
pDocumentLayout->requestUpdate();
pDocumentLayout->emitDocumentSizeChanged();
}
QPlainTextEdit::ensureCursorVisible();
}

/*!
* \brief BaseEditor::PlainTextEdit::highlightCurrentLine
* Hightlights the current line.
Expand Down
5 changes: 5 additions & 0 deletions OMEdit/OMEditGUI/Editors/BaseEditor.h
Expand Up @@ -103,6 +103,7 @@ class TextBlockUserData : public QTextBlockUserData
: mFoldingIndent(0)
, mFolded(false)
, mFoldingEndIncluded(false)
, mFoldingState(false)
, mLeadingSpaces(-1)
{}
~TextBlockUserData();
Expand Down Expand Up @@ -142,6 +143,8 @@ class TextBlockUserData : public QTextBlockUserData
// Set whether the last character of the folded region will show when the code is folded.
inline void setFoldingEndIncluded(bool foldingEndIncluded) {mFoldingEndIncluded = foldingEndIncluded;}
inline bool foldingEndIncluded() const {return mFoldingEndIncluded;}
inline void setFoldingState(bool foldingState) {mFoldingState = foldingState;}
inline bool foldingState() const {return mFoldingState;}

inline void setLeadingSpaces(int leadingSpaces) {mLeadingSpaces = leadingSpaces;}
inline int getLeadingSpaces() {return mLeadingSpaces;}
Expand All @@ -151,6 +154,7 @@ class TextBlockUserData : public QTextBlockUserData
int mFoldingIndent;
bool mFolded;
bool mFoldingEndIncluded;
bool mFoldingState;
int mLeadingSpaces;
};

Expand Down Expand Up @@ -194,6 +198,7 @@ class BaseEditor : public QWidget
void toggleBreakpoint(const QString fileName, int lineNumber);
void indentOrUnindent(bool doIndent);
void moveCursorVisible(bool ensureVisible = true);
void ensureCursorVisible();
private:
BaseEditor *mpBaseEditor;
LineNumberArea *mpLineNumberArea;
Expand Down
86 changes: 56 additions & 30 deletions OMEdit/OMEditGUI/Editors/ModelicaEditor.cpp
Expand Up @@ -708,10 +708,16 @@ void ModelicaTextHighlighter::highlightMultiLine(const QString &text)
/* Hand-written recognizer beats the crap known as QRegEx ;) */
int index = 0, startIndex = 0;
int blockState = previousBlockState();
// store parentheses info
Parentheses parentheses;
bool foldingState = false;
QTextBlock previousTextBlck = currentBlock().previous();
TextBlockUserData *pPreviousTextBlockUserData = BaseEditorDocumentLayout::userData(previousTextBlck);
if (pPreviousTextBlockUserData) {
foldingState = pPreviousTextBlockUserData->foldingState();
}
QRegExp annotationRegExp("\\bannotation\\b");
int annotationIndex = annotationRegExp.indexIn(text);
// store parentheses info
Parentheses parentheses;
TextBlockUserData *pTextBlockUserData = BaseEditorDocumentLayout::userData(currentBlock());
if (pTextBlockUserData) {
pTextBlockUserData->clearParentheses();
Expand Down Expand Up @@ -742,21 +748,6 @@ void ModelicaTextHighlighter::highlightMultiLine(const QString &text)
blockState = 0;
}
break;
case 4:
if (text[index] == ';') {
if (index == text.length() - 1) { // if we have some text after closing the annotation then we don't want to fold it.
if (annotationIndex < 0) { // if we have one line annotation, we don't want to fold it.
pTextBlockUserData->setFoldingIndent(1);
}
pTextBlockUserData->setFoldingEndIncluded(true);
} else {
pTextBlockUserData->setFoldingIndent(0);
}
blockState = 0;
} else if (annotationIndex < 0) { // if we have one line annotation, we don't want to fold it.
pTextBlockUserData->setFoldingIndent(1);
}
break;
default:
/* check if single line comment then set the blockstate to 1. */
if (text[index] == '/' && index+1<text.length() && text[index+1] == '/') {
Expand All @@ -769,16 +760,6 @@ void ModelicaTextHighlighter::highlightMultiLine(const QString &text)
} else if (text[index] == '"') {
startIndex = index;
blockState = 3;
} else if (text[index] == 'a' && index+9<text.length() && text[index+1] == 'n' && text[index+2] == 'n' && text[index+3] == 'o'
&& text[index+4] == 't' && text[index+5] == 'a' && text[index+6] == 't' && text[index+7] == 'i' && text[index+8] == 'o'
&& text[index+9] == 'n') {
if (index+9 == text.length() - 1) { // if we just have annotation keyword in the line
index = index + 9;
blockState = 4;
} else if (index+10<text.length() && (text[index+10] == '(' || text[index+10] == ' ')) { // if annotation keyword is followed by '(' or space.
index = index + 10;
blockState = 4;
}
}
}
// if no single line comment, no multi line comment and no quotes then store the parentheses
Expand All @@ -789,10 +770,54 @@ void ModelicaTextHighlighter::highlightMultiLine(const QString &text)
parentheses.append(Parenthesis(Parenthesis::Closed, text[index], index));
}
}
if (foldingState) {
// if no single line comment, no multi line comment and no quotes then check for annotation end
if (blockState < 1 || blockState > 3) {
if (text[index] == ';') {
if (index == text.length() - 1) { // if we have some text after closing the annotation then we don't want to fold it.
if (annotationIndex < 0) { // if we have one line annotation, we don't want to fold it.
pTextBlockUserData->setFoldingIndent(1);
}
pTextBlockUserData->setFoldingEndIncluded(true);
} else {
pTextBlockUserData->setFoldingIndent(0);
}
foldingState = false;
} else if (annotationIndex < 0) { // if we have one line annotation, we don't want to fold it.
pTextBlockUserData->setFoldingIndent(1);
}
} else if (annotationIndex < 0) { // if we have one line annotation, we don't want to fold it.
pTextBlockUserData->setFoldingIndent(1);
} else if (startIndex < annotationIndex) { // if we have annotation word before quote or comment block is starting then fold.
pTextBlockUserData->setFoldingIndent(1);
}
} else {
// if no single line comment, no multi line comment and no quotes then check for annotation start
if (blockState < 1 || blockState > 3) {
if (text[index] == 'a' && index+9<text.length() && text[index+1] == 'n' && text[index+2] == 'n' && text[index+3] == 'o'
&& text[index+4] == 't' && text[index+5] == 'a' && text[index+6] == 't' && text[index+7] == 'i' && text[index+8] == 'o'
&& text[index+9] == 'n') {
if (index+9 == text.length() - 1) { // if we just have annotation keyword in the line
index = index + 9;
foldingState = true;
} else if (index+10<text.length() && (text[index+10] == '(' || text[index+10] == ' ')) { // if annotation keyword is followed by '(' or space.
index = index + 10;
foldingState = true;
}
}
}
}
index++;
}
if (pTextBlockUserData) {
pTextBlockUserData->setParentheses(parentheses);
if (foldingState) {
pTextBlockUserData->setFoldingState(true);
// Hanldle empty blocks inside annotaiton section
if (text.isEmpty() && foldingState) {
pTextBlockUserData->setFoldingIndent(1);
}
}
// set text block user data
setCurrentBlockUserData(pTextBlockUserData);
}
Expand All @@ -805,9 +830,6 @@ void ModelicaTextHighlighter::highlightMultiLine(const QString &text)
setFormat(startIndex, text.length()-startIndex, mQuotationFormat);
setCurrentBlockState(3);
break;
case 4:
setCurrentBlockState(4);
break;
}
}

Expand All @@ -820,6 +842,10 @@ void ModelicaTextHighlighter::highlightBlock(const QString &text)
}
// set text block state
setCurrentBlockState(0);
TextBlockUserData *pTextBlockUserData = BaseEditorDocumentLayout::userData(currentBlock());
if (pTextBlockUserData) {
pTextBlockUserData->setFoldingState(false);
}
setFormat(0, text.length(), mpModelicaEditorPage->getTextRuleColor());
foreach (const HighlightingRule &rule, mHighlightingRules) {
QRegExp expression(rule.mPattern);
Expand Down

0 comments on commit afdff3c

Please sign in to comment.