From cf1baaf6eabaaf314011deea17f24db8ed1ae88c Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Wed, 30 Apr 2014 23:32:41 +0200 Subject: [PATCH] - Highlighting Fixes ( Single line comments in quoted text don't occur anymore. / Better number recognition) - Line numbers in ScriptEditor --- interface/src/ScriptHighlighting.cpp | 19 +++- interface/src/ScriptHighlighting.h | 1 + interface/src/ui/ScriptEditBox.cpp | 107 ++++++++++++++++++++++ interface/src/ui/ScriptEditBox.h | 38 ++++++++ interface/src/ui/ScriptEditorWidget.h | 1 - interface/src/ui/ScriptLineNumberArea.cpp | 28 ++++++ interface/src/ui/ScriptLineNumberArea.h | 31 +++++++ interface/ui/scriptEditorWidget.ui | 23 ++++- 8 files changed, 240 insertions(+), 8 deletions(-) create mode 100644 interface/src/ui/ScriptEditBox.cpp create mode 100644 interface/src/ui/ScriptEditBox.h create mode 100644 interface/src/ui/ScriptLineNumberArea.cpp create mode 100644 interface/src/ui/ScriptLineNumberArea.h diff --git a/interface/src/ScriptHighlighting.cpp b/interface/src/ScriptHighlighting.cpp index 3ab1394097..3d63ba55a8 100644 --- a/interface/src/ScriptHighlighting.cpp +++ b/interface/src/ScriptHighlighting.cpp @@ -22,6 +22,7 @@ ScriptHighlighting::ScriptHighlighting(QTextDocument* parent) : _numberRegex = QRegExp("[0-9]+(\\.[0-9]+){0,1}"); _singleLineComment = QRegExp("//[^\n]*"); _truefalseRegex = QRegExp("\\b(true|false)\\b"); + _alphacharRegex = QRegExp("[A-Za-z]"); } void ScriptHighlighting::highlightBlock(const QString& text) { @@ -60,7 +61,19 @@ void ScriptHighlighting::formatComments(const QString& text) { int index = _singleLineComment.indexIn(text); while (index >= 0) { int length = _singleLineComment.matchedLength(); - setFormat(index, length, Qt::lightGray); + int quoted_index = _qoutedTextRegex.indexIn(text); + bool valid = true; + while (quoted_index >= 0 && valid) { + int quoted_length = _qoutedTextRegex.matchedLength(); + if (quoted_index <= index && index <= (quoted_index + quoted_length)) { + valid = false; + } + quoted_index = _qoutedTextRegex.indexIn(text, quoted_index + quoted_length); + } + + if (valid) { + setFormat(index, length, Qt::lightGray); + } index = _singleLineComment.indexIn(text, index + length); } } @@ -78,7 +91,9 @@ void ScriptHighlighting::formatNumbers(const QString& text){ int index = _numberRegex.indexIn(text); while (index >= 0) { int length = _numberRegex.matchedLength(); - setFormat(index, length, Qt::green); + if (index == 0 || _alphacharRegex.indexIn(text, index - 1) != (index - 1)) { + setFormat(index, length, Qt::green); + } index = _numberRegex.indexIn(text, index + length); } } diff --git a/interface/src/ScriptHighlighting.h b/interface/src/ScriptHighlighting.h index d86d6f4d77..232d594308 100644 --- a/interface/src/ScriptHighlighting.h +++ b/interface/src/ScriptHighlighting.h @@ -34,6 +34,7 @@ protected: void formatTrueFalse(const QString& text); private: + QRegExp _alphacharRegex; QRegExp _keywordRegex; QRegExp _qoutedTextRegex; QRegExp _multiLineCommentBegin; diff --git a/interface/src/ui/ScriptEditBox.cpp b/interface/src/ui/ScriptEditBox.cpp new file mode 100644 index 0000000000..4c2b6564ba --- /dev/null +++ b/interface/src/ui/ScriptEditBox.cpp @@ -0,0 +1,107 @@ +// +// ScriptEditBox.cpp +// interface/src/ui +// +// Created by Thijs Wenker on 4/30/14. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "ScriptEditBox.h" +#include "ScriptLineNumberArea.h" +#include "Application.h" + +ScriptEditBox::ScriptEditBox(QWidget* parent) : + QPlainTextEdit(parent) +{ + _scriptLineNumberArea = new ScriptLineNumberArea(this); + + connect(this, SIGNAL(blockCountChanged(int)), this, SLOT(updateLineNumberAreaWidth(int))); + connect(this, SIGNAL(updateRequest(QRect, int)), this, SLOT(updateLineNumberArea(QRect, int))); + connect(this, SIGNAL(cursorPositionChanged()), this, SLOT(highlightCurrentLine())); + + updateLineNumberAreaWidth(0); + highlightCurrentLine(); +} + +int ScriptEditBox::lineNumberAreaWidth() { + int digits = 1; + const int SPACER_PIXELS = 3; + const int BASE_TEN = 10; + int max = qMax(1, blockCount()); + while (max >= BASE_TEN) { + max /= BASE_TEN; + ++digits; + } + return SPACER_PIXELS + fontMetrics().width(QLatin1Char('H')) * digits; +} + +void ScriptEditBox::updateLineNumberAreaWidth(int) { + setViewportMargins(lineNumberAreaWidth(), 0, 0, 0); +} + +void ScriptEditBox::updateLineNumberArea(const QRect& rect, int dy) { + if (dy) { + _scriptLineNumberArea->scroll(0, dy); + } else { + _scriptLineNumberArea->update(0, rect.y(), _scriptLineNumberArea->width(), rect.height()); + } + + if (rect.contains(viewport()->rect())) { + updateLineNumberAreaWidth(0); + } +} + +void ScriptEditBox::resizeEvent(QResizeEvent* e) { + QPlainTextEdit::resizeEvent(e); + + QRect cr = contentsRect(); + _scriptLineNumberArea->setGeometry(QRect(cr.left(), cr.top(), lineNumberAreaWidth(), cr.height())); +} + +void ScriptEditBox::highlightCurrentLine() { + QList extraSelections; + + if (!isReadOnly()) { + QTextEdit::ExtraSelection selection; + + QColor lineColor = QColor(Qt::gray).lighter(); + + selection.format.setBackground(lineColor); + selection.format.setProperty(QTextFormat::FullWidthSelection, true); + selection.cursor = textCursor(); + selection.cursor.clearSelection(); + extraSelections.append(selection); + } + + setExtraSelections(extraSelections); +} + +void ScriptEditBox::lineNumberAreaPaintEvent(QPaintEvent* event) +{ + QPainter painter(_scriptLineNumberArea); + painter.fillRect(event->rect(), Qt::lightGray); + QTextBlock block = firstVisibleBlock(); + int blockNumber = block.blockNumber(); + int top = (int) blockBoundingGeometry(block).translated(contentOffset()).top(); + int bottom = top + (int) blockBoundingRect(block).height(); + + while (block.isValid() && top <= event->rect().bottom()) { + if (block.isVisible() && bottom >= event->rect().top()) { + QFont font = painter.font(); + font.setBold(this->textCursor().blockNumber() == block.blockNumber()); + painter.setFont(font); + QString number = QString::number(blockNumber + 1); + painter.setPen(Qt::black); + painter.drawText(0, top, _scriptLineNumberArea->width(), fontMetrics().height(), + Qt::AlignRight, number); + } + + block = block.next(); + top = bottom; + bottom = top + (int) blockBoundingRect(block).height(); + ++blockNumber; + } +} diff --git a/interface/src/ui/ScriptEditBox.h b/interface/src/ui/ScriptEditBox.h new file mode 100644 index 0000000000..ea00ec02b6 --- /dev/null +++ b/interface/src/ui/ScriptEditBox.h @@ -0,0 +1,38 @@ +// +// ScriptEditBox.h +// interface/src/ui +// +// Created by Thijs Wenker on 4/30/14. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_ScriptEditBox_h +#define hifi_ScriptEditBox_h + +#include + +class ScriptEditBox : public QPlainTextEdit { + Q_OBJECT + +public: + ScriptEditBox(QWidget* parent = NULL); + + void lineNumberAreaPaintEvent(QPaintEvent* event); + int lineNumberAreaWidth(); + +protected: + void resizeEvent(QResizeEvent* event); + +private slots: + void updateLineNumberAreaWidth(int); + void highlightCurrentLine(); + void updateLineNumberArea(const QRect&, int); + +private: + QWidget* _scriptLineNumberArea; +}; + +#endif // hifi_ScriptEditBox_h diff --git a/interface/src/ui/ScriptEditorWidget.h b/interface/src/ui/ScriptEditorWidget.h index 3e50280a62..1a96661cf7 100644 --- a/interface/src/ui/ScriptEditorWidget.h +++ b/interface/src/ui/ScriptEditorWidget.h @@ -13,7 +13,6 @@ #define hifi_ScriptEditorWidget_h #include -#include "ScriptEditorWidget.h" #include "ScriptEngine.h" namespace Ui { diff --git a/interface/src/ui/ScriptLineNumberArea.cpp b/interface/src/ui/ScriptLineNumberArea.cpp new file mode 100644 index 0000000000..9173c72375 --- /dev/null +++ b/interface/src/ui/ScriptLineNumberArea.cpp @@ -0,0 +1,28 @@ +// +// ScriptLineNumberArea.cpp +// interface/src/ui +// +// Created by Thijs Wenker on 4/30/14. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "ScriptLineNumberArea.h" + +#include "Application.h" + +ScriptLineNumberArea::ScriptLineNumberArea(ScriptEditBox* scriptEditBox) : + QWidget(scriptEditBox) +{ + _scriptEditBox = scriptEditBox; +} + +QSize ScriptLineNumberArea::sizeHint() { + return QSize(_scriptEditBox->lineNumberAreaWidth(), 0); +} + +void ScriptLineNumberArea::paintEvent(QPaintEvent* event) { + _scriptEditBox->lineNumberAreaPaintEvent(event); +} diff --git a/interface/src/ui/ScriptLineNumberArea.h b/interface/src/ui/ScriptLineNumberArea.h new file mode 100644 index 0000000000..75be2048f0 --- /dev/null +++ b/interface/src/ui/ScriptLineNumberArea.h @@ -0,0 +1,31 @@ +// +// ScriptLineNumberArea.h +// interface/src/ui +// +// Created by Thijs Wenker on 4/30/14. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_ScriptLineNumberArea_h +#define hifi_ScriptLineNumberArea_h + +#include +#include "ScriptEditBox.h" + +class ScriptLineNumberArea : public QWidget { + +public: + ScriptLineNumberArea(ScriptEditBox* scriptEditBox); + QSize sizeHint(); + +protected: + void paintEvent(QPaintEvent* event); + +private: + ScriptEditBox* _scriptEditBox; +}; + +#endif // hifi_ScriptLineNumberArea_h diff --git a/interface/ui/scriptEditorWidget.ui b/interface/ui/scriptEditorWidget.ui index 363f99b635..8aeeff363f 100644 --- a/interface/ui/scriptEditorWidget.ui +++ b/interface/ui/scriptEditorWidget.ui @@ -39,11 +39,20 @@ 0 - + + 0 + + + 0 + + + 0 + + 0 - + Courier @@ -56,9 +65,6 @@ font: 16px "Courier"; - - false - @@ -144,6 +150,13 @@ + + + ScriptEditBox + QTextEdit +
ui/ScriptEditBox.h
+
+