diff --git a/bin/app/data/color_schemes/bright.xml b/bin/app/data/color_schemes/bright.xml
index 8203db9f..da80a91e 100644
--- a/bin/app/data/color_schemes/bright.xml
+++ b/bin/app/data/color_schemes/bright.xml
@@ -62,7 +62,7 @@
- transparent
+ white
#A0A0A0
@@ -72,7 +72,7 @@
black
- transparent
+ white
@@ -86,20 +86,50 @@
#CC9533
-
+
- #90EBEBEB
- #90B6D1DD
+
+ transparent
+ transparent
+
+
+ #B2B2B2
+ transparent
+
+
+ #B2B2B2
+ #EDEDED
+
- #60E4EEF2
- #90E4EEF2
+
+ transparent
+ transparent
+
+
+ transparent
+ transparent
+
+
+ transparent
+ transparent
+
- #80FF0000
- #FFFF0000
+
+ transparent
+ #80FF0000
+
+
+ transparent
+ #FFFF0000
+
+
+ transparent
+ #FFFF0000
+
-
+
diff --git a/bin/app/data/color_schemes/dark.xml b/bin/app/data/color_schemes/dark.xml
index 8fbd9513..50a3e961 100644
--- a/bin/app/data/color_schemes/dark.xml
+++ b/bin/app/data/color_schemes/dark.xml
@@ -62,7 +62,7 @@
- transparent
+ #272728
#A0A0A0
@@ -72,7 +72,7 @@
#F7F7F7
- transparent
+ #272728
@@ -86,20 +86,50 @@
#D69C36
-
+
- #20EBEBEB
- #40B6D1DD
+
+ transparent
+ transparent
+
+
+ #B2B2B2
+ transparent
+
+
+ #B2B2B2
+ #4A4A4A
+
- #10E4EEF2
- #18E4EEF2
+
+ transparent
+ transparent
+
+
+ transparent
+ transparent
+
+
+ transparent
+ transparent
+
- #A0FF0000
- #FFFF0000
+
+ transparent
+ #A0FF0000
+
+
+ transparent
+ #FFFF0000
+
+
+ transparent
+ #FFFF0000
+
-
+
diff --git a/setup/MacOSX/Info.plist.in b/setup/MacOSX/Info.plist.in
index eae9b81a..dcce5538 100644
--- a/setup/MacOSX/Info.plist.in
+++ b/setup/MacOSX/Info.plist.in
@@ -37,6 +37,6 @@
CFBundleIconFile
icon
LSMinimumSystemVersion
- 10.10
+ 10.9
diff --git a/src/app/qt/element/QtCodeArea.cpp b/src/app/qt/element/QtCodeArea.cpp
index ba5a8ef8..69441c81 100644
--- a/src/app/qt/element/QtCodeArea.cpp
+++ b/src/app/qt/element/QtCodeArea.cpp
@@ -24,6 +24,8 @@
#include "settings/ApplicationSettings.h"
#include "settings/ColorScheme.h"
+std::vector QtCodeArea::s_annotationColors;
+
MouseWheelOverScrollbarFilter::MouseWheelOverScrollbarFilter(QObject* parent)
: QObject(parent)
{
@@ -70,6 +72,10 @@ void QtCodeArea::LineNumberArea::paintEvent(QPaintEvent *event)
m_codeArea->lineNumberAreaPaintEvent(event);
}
+void QtCodeArea::clearAnnotationColors()
+{
+ s_annotationColors.clear();
+}
QtCodeArea::QtCodeArea(
uint startLineNumber,
@@ -87,6 +93,7 @@ QtCodeArea::QtCodeArea(
, m_panningValue(-1)
, m_setIDECursorPositionAction(nullptr)
, m_eventPosition(0, 0)
+ , m_isActiveFile(false)
{
setObjectName("code_area");
setReadOnly(true);
@@ -174,12 +181,23 @@ void QtCodeArea::lineNumberAreaPaintEvent(QPaintEvent *event)
int top = static_cast(blockBoundingGeometry(block).translated(contentOffset()).top());
int bottom = top + static_cast(blockBoundingRect(block).height());
+ std::set activeLineNumbers = getActiveLineNumbers();
+
+ ColorScheme* scheme = ColorScheme::getInstance().get();
+ QColor backgroundColor(scheme->getColor("code/snippet/line_number/background").c_str());
+ backgroundColor.setAlpha(150);
+
while (block.isValid() && top <= event->rect().bottom())
{
if (block.isVisible() && bottom >= event->rect().top())
{
- QString number = QString::number(blockNumber + m_startLineNumber);
- painter.drawText(0, top, m_lineNumberArea->width() - 13, fontMetrics().height(), Qt::AlignRight, number);
+ int number = blockNumber + m_startLineNumber;
+ painter.drawText(0, top, m_lineNumberArea->width() - 13, fontMetrics().height(), Qt::AlignRight, QString::number(number));
+
+ if (!m_isActiveFile && activeLineNumbers.find(number) == activeLineNumbers.end())
+ {
+ painter.fillRect(0, top, m_lineNumberArea->width(), fontMetrics().height(), backgroundColor);
+ }
}
block = block.next();
@@ -226,6 +244,11 @@ bool QtCodeArea::isActive() const
return false;
}
+void QtCodeArea::setIsActiveFile(bool isActiveFile)
+{
+ m_isActiveFile = isActiveFile;
+}
+
void QtCodeArea::resizeEvent(QResizeEvent *e)
{
QPlainTextEdit::resizeEvent(e);
@@ -249,22 +272,50 @@ void QtCodeArea::paintEvent(QPaintEvent* event)
QTextBlock block = firstVisibleBlock();
int top = blockBoundingGeometry(block).translated(contentOffset()).top();
int blockHeight = blockBoundingRect(block).height();
+ int borderRadius = 3;
- ColorScheme* scheme = ColorScheme::getInstance().get();
-
- QColor scopeColor(scheme->getColor("code/snippet/highlight/scope/normal").c_str());
- QColor activeScopeColor(scheme->getColor("code/snippet/highlight/scope/hover").c_str());
-
- for (const ScopeAnnotation& scope : m_scopeAnnotations)
+ for (const Annotation& annotation : m_annotations)
{
- painter.fillRect(
- 0, top + scope.startLine * blockHeight,
- width(), (scope.endLine - scope.startLine + 1) * blockHeight,
- (scope.isFocused || scope.startLine == scope.endLine) ? activeScopeColor : scopeColor
- );
+ const AnnotationColor& color = getAnnotationColorForAnnotation(annotation);
+
+ painter.setPen(QPen(color.border.c_str()));
+ painter.setBrush(QBrush(color.fill.c_str()));
+
+ if (annotation.isScope)
+ {
+ painter.drawRoundedRect(
+ 0, top + (annotation.startLine - m_startLineNumber) * blockHeight,
+ width(), (annotation.endLine - annotation.startLine + 1) * blockHeight,
+ borderRadius, borderRadius
+ );
+ }
+ else
+ {
+ std::vector rects = getCursorRectsForAnnotation(annotation);
+ for (QRect rect : rects)
+ {
+ rect.adjust(-1, 0, 1, 1);
+ painter.drawRoundedRect(rect, borderRadius, borderRadius);
+ }
+ }
}
QPlainTextEdit::paintEvent(event);
+
+ QPainter painter2(viewport());
+ std::set activeLineNumbers = getActiveLineNumbers();
+
+ ColorScheme* scheme = ColorScheme::getInstance().get();
+ QColor backgroundColor(scheme->getColor("code/snippet/background").c_str());
+ backgroundColor.setAlpha(75);
+
+ for (int i = 0; i < document()->blockCount(); i++)
+ {
+ if (!m_isActiveFile && activeLineNumbers.find(i + m_startLineNumber) == activeLineNumbers.end())
+ {
+ painter.fillRect(0, top + i * blockHeight, width(), blockHeight, backgroundColor);
+ }
+ }
}
void QtCodeArea::enterEvent(QEvent* event)
@@ -407,19 +458,6 @@ void QtCodeArea::setIDECursorPosition()
MessageMoveIDECursor(m_locationFile->getFilePath().str(), lineColumn.first, lineColumn.second).dispatch();
}
-QtCodeArea::ScopeAnnotation::ScopeAnnotation()
- : startLine(0)
- , endLine(0)
- , tokenId(0)
- , isFocused(false)
-{
-}
-
-bool QtCodeArea::ScopeAnnotation::operator!=(const ScopeAnnotation& other) const
-{
- return (startLine != other.startLine || endLine != other.endLine || tokenId != other.tokenId || isFocused != other.isFocused);
-}
-
const QtCodeArea::Annotation* QtCodeArea::findAnnotationForPosition(int pos) const
{
const Annotation* annotationPtr = nullptr;
@@ -468,10 +506,14 @@ void QtCodeArea::createAnnotations(std::shared_ptr locationFi
if (startLocation->getLineNumber() < m_startLineNumber)
{
annotation.start = startTextEditPosition();
+ annotation.startLine = m_startLineNumber;
+ annotation.startCol = 0;
}
else
{
annotation.start = toTextEditPosition(startLocation->getLineNumber(), startLocation->getColumnNumber() - 1);
+ annotation.startLine = startLocation->getLineNumber();
+ annotation.startCol = startLocation->getColumnNumber() - 1;
}
}
else
@@ -485,10 +527,14 @@ void QtCodeArea::createAnnotations(std::shared_ptr locationFi
if (endLocation->getLineNumber() > endLineNumber)
{
annotation.end = endTextEditPosition();
+ annotation.endLine = endLineNumber;
+ annotation.endCol = document()->findBlockByLineNumber(document()->blockCount() - 1).length();
}
else
{
annotation.end = toTextEditPosition(endLocation->getLineNumber(), endLocation->getColumnNumber());
+ annotation.endLine = endLocation->getLineNumber();
+ annotation.endCol = endLocation->getColumnNumber();
}
}
else
@@ -498,7 +544,13 @@ void QtCodeArea::createAnnotations(std::shared_ptr locationFi
annotation.tokenId = startLocation->getTokenId();
annotation.locationId = startLocation->getId();
+
annotation.isScope = (startLocation->getType() == TokenLocation::LOCATION_SCOPE);
+ annotation.isError = false;
+
+ annotation.isActive = false;
+ annotation.isFocused = false;
+
m_annotations.push_back(annotation);
}
);
@@ -509,98 +561,29 @@ void QtCodeArea::annotateText()
Id focusedTokenId = m_fileWidget->getFocusedTokenId();
const std::vector& activeIds = m_fileWidget->getActiveTokenIds();
const std::vector& hoverIds = m_hoveredLocationIds;
- const std::vector& errorMessages = m_fileWidget->getErrorMessages();
-
- std::vector scopeAnnotations;
-
- ColorScheme* scheme = ColorScheme::getInstance().get();
-
- QColor locationColor(scheme->getColor("code/snippet/highlight/location/normal").c_str());
- QColor activeLocationColor(scheme->getColor("code/snippet/highlight/location/hover").c_str());
-
- QColor errorColor(scheme->getColor("code/snippet/highlight/error/normal").c_str());
- QColor activeErrorColor(scheme->getColor("code/snippet/highlight/error/hover").c_str());
-
- QList extraSelections;
-
- for (const Annotation& annotation: m_annotations)
- {
- bool isActive = std::find(activeIds.begin(), activeIds.end(), annotation.tokenId) != activeIds.end();
- bool isHovered = std::find(hoverIds.begin(), hoverIds.end(), annotation.locationId) != hoverIds.end();
- bool isFocused = (annotation.tokenId == focusedTokenId);
-
- QColor color;
- if (isHovered && errorMessages.size())
- {
- color = activeErrorColor;
- }
- else if (errorMessages.size())
- {
- color = errorColor;
- }
- else if (isActive || isFocused || isHovered)
- {
- color = activeLocationColor;
- }
- else
- {
- color = locationColor;
- }
-
- QTextEdit::ExtraSelection selection;
- selection.format.setBackground(color);
-
- ScopeAnnotation scopeAnnotation;
-
- selection.cursor = textCursor();
- selection.cursor.clearSelection();
- selection.cursor.setPosition(annotation.start);
- scopeAnnotation.startLine = selection.cursor.blockNumber();
- selection.cursor.setPosition(annotation.end, QTextCursor::KeepAnchor);
- scopeAnnotation.endLine = selection.cursor.blockNumber();
-
- if (annotation.isScope || (isActive && activeIds.size() == 1))
- {
- if (isActive || isFocused)
- {
- scopeAnnotation.tokenId = annotation.tokenId;
- if (!isActive)
- {
- scopeAnnotation.isFocused = isFocused;
- }
- scopeAnnotations.push_back(scopeAnnotation);
- }
- }
-
- if (!annotation.isScope || (isActive && activeIds.size() == 1 && scopeAnnotation.startLine == scopeAnnotation.endLine))
- {
- extraSelections.append(selection);
- }
- }
-
- setExtraSelections(extraSelections);
+ bool isError = m_fileWidget->getErrorMessages().size() > 0;
bool needsUpdate = false;
- if (scopeAnnotations.size() != m_scopeAnnotations.size())
+
+ for (Annotation& annotation: m_annotations)
{
- needsUpdate = true;
- }
- else
- {
- for (size_t i = 0; i < scopeAnnotations.size(); i++)
+ bool wasActive = annotation.isActive;
+ bool wasFocused = annotation.isFocused;
+
+ annotation.isActive = std::find(activeIds.begin(), activeIds.end(), annotation.tokenId) != activeIds.end();
+ annotation.isFocused = std::find(hoverIds.begin(), hoverIds.end(), annotation.locationId) != hoverIds.end() || (annotation.tokenId == focusedTokenId);
+
+ annotation.isError = isError;
+
+ if (wasFocused != annotation.isFocused || wasActive != annotation.isActive)
{
- if (scopeAnnotations[i] != m_scopeAnnotations[i])
- {
- needsUpdate = true;
- break;
- }
+ needsUpdate = true;
}
}
- m_scopeAnnotations = scopeAnnotations;
-
if (needsUpdate)
{
+ m_lineNumberArea->update();
viewport()->update();
}
}
@@ -670,6 +653,130 @@ int QtCodeArea::endTextEditPosition() const
return position - 1;
}
+std::set QtCodeArea::getActiveLineNumbers() const
+{
+ std::set activeLineNumbers;
+
+ if (m_isActiveFile)
+ {
+ return activeLineNumbers;
+ }
+
+ for (const Annotation& annotation : m_annotations)
+ {
+ if (annotation.isActive)
+ {
+ for (int i = annotation.startLine; i <= annotation.endLine; i++)
+ {
+ activeLineNumbers.insert(i);
+ }
+ }
+ }
+
+ if (activeLineNumbers.size())
+ {
+ for (const Annotation& annotation : m_annotations)
+ {
+ if (annotation.isFocused)
+ {
+ for (int i = annotation.startLine; i <= annotation.endLine; i++)
+ {
+ activeLineNumbers.insert(i);
+ }
+ }
+ }
+ }
+
+ return activeLineNumbers;
+}
+
+std::vector QtCodeArea::getCursorRectsForAnnotation(const Annotation& annotation) const
+{
+ std::vector rects;
+
+ QTextCursor cursor = textCursor();
+ cursor.clearSelection();
+ cursor.setPosition(annotation.start);
+ QRect rectStart = cursorRect(cursor);
+ QRect rectEnd;
+
+ int line = annotation.startLine;
+ while (line <= annotation.endLine)
+ {
+ if (line == annotation.endLine)
+ {
+ cursor.setPosition(annotation.end);
+ }
+ else
+ {
+ cursor.setPosition(toTextEditPosition(line, document()->findBlockByLineNumber(line - m_startLineNumber).length() - 1));
+ }
+
+ rectEnd = cursorRect(cursor);
+ rects.push_back(QRect(rectStart.left(), rectStart.top(), rectEnd.right() - rectStart.left(), rectEnd.bottom() - rectStart.top()));
+
+ line++;
+
+ if (int(line - m_startLineNumber) < document()->blockCount())
+ {
+ cursor.setPosition(toTextEditPosition(line, 0));
+ rectStart = cursorRect(cursor);
+ }
+ }
+
+ return rects;
+}
+
+const QtCodeArea::AnnotationColor& QtCodeArea::getAnnotationColorForAnnotation(const Annotation& annotation)
+{
+ if (!s_annotationColors.size())
+ {
+ ColorScheme* scheme = ColorScheme::getInstance().get();
+ std::vector types;
+ types.push_back("location");
+ types.push_back("scope");
+ types.push_back("error");
+
+ std::vector states;
+ states.push_back("normal");
+ states.push_back("focus");
+ states.push_back("active");
+
+ for (const std::string& type : types)
+ {
+ for (const std::string& state : states)
+ {
+ AnnotationColor color;
+ color.border = scheme->getColor("code/snippet/selection/" + type + "/" + state + "/border");
+ color.fill = scheme->getColor("code/snippet/selection/" + type + "/" + state + "/fill");
+ s_annotationColors.push_back(color);
+ }
+ }
+ }
+
+ size_t i = 0;
+
+ if (annotation.isScope)
+ {
+ i = 3;
+ }
+ else if (annotation.isError)
+ {
+ i = 6;
+ }
+
+ if (annotation.isActive)
+ {
+ i += 2;
+ }
+ else if (annotation.isFocused)
+ {
+ i += 1;
+ }
+
+ return s_annotationColors[i];
+}
+
void QtCodeArea::createActions()
{
m_setIDECursorPositionAction = new QAction(tr("Set IDE Cursor"), this);
diff --git a/src/app/qt/element/QtCodeArea.h b/src/app/qt/element/QtCodeArea.h
index 40919022..97110d21 100644
--- a/src/app/qt/element/QtCodeArea.h
+++ b/src/app/qt/element/QtCodeArea.h
@@ -1,8 +1,9 @@
#ifndef QT_CODE_AREA_H
#define QT_CODE_AREA_H
-#include
#include
+#include
+#include
#include
@@ -53,6 +54,8 @@ public:
QtCodeArea *m_codeArea;
};
+ static void clearAnnotationColors();
+
QtCodeArea(
uint startLineNumber,
const std::string& code,
@@ -78,6 +81,8 @@ public:
bool isActive() const;
+ void setIsActiveFile(bool isActiveFile);
+
protected:
virtual void resizeEvent(QResizeEvent *event) Q_DECL_OVERRIDE;
virtual void showEvent(QShowEvent* event) Q_DECL_OVERRIDE;
@@ -100,24 +105,31 @@ private slots:
private:
struct Annotation
{
- int start;
- int end;
- Id tokenId;
- Id locationId;
- bool isScope;
- };
-
- struct ScopeAnnotation
- {
- ScopeAnnotation();
- bool operator!=(const ScopeAnnotation& other) const;
-
int startLine;
int endLine;
+
+ int startCol;
+ int endCol;
+
+ int start;
+ int end;
+
Id tokenId;
+ Id locationId;
+
+ bool isScope;
+ bool isError;
+
+ bool isActive;
bool isFocused;
};
+ struct AnnotationColor
+ {
+ std::string border;
+ std::string fill;
+ };
+
const Annotation* findAnnotationForPosition(int pos) const;
std::vector findLocationIdsForPosition(int pos) const;
@@ -126,15 +138,20 @@ private:
void setHoveredAnnotation(const Annotation* annotation);
- bool locationBelongsToSnippet(TokenLocation* location) const;
-
int toTextEditPosition(int lineNumber, int columnNumber) const;
std::pair toLineColumn(int textEditPosition) const;
int startTextEditPosition() const;
int endTextEditPosition() const;
+ std::set getActiveLineNumbers() const;
+ std::vector getCursorRectsForAnnotation(const Annotation& annotation) const;
+
+ const AnnotationColor& getAnnotationColorForAnnotation(const Annotation& annotation);
+
void createActions();
+ static std::vector s_annotationColors;
+
QtCodeFile* m_fileWidget;
QWidget* m_lineNumberArea;
@@ -145,7 +162,6 @@ private:
std::shared_ptr m_locationFile;
std::vector m_annotations;
- std::vector m_scopeAnnotations;
const Annotation* m_hoveredAnnotation;
std::vector m_hoveredLocationIds;
@@ -155,7 +171,9 @@ private:
QAction* m_setIDECursorPositionAction;
QPoint m_eventPosition; // is needed for IDE cursor control via context menu
- // the position where the context menu is opened needs to be stored
+ // the position where the context menu is opened needs to be stored]
+
+ bool m_isActiveFile;
};
#endif // QT_CODE_AREA_H
diff --git a/src/app/qt/element/QtCodeFile.cpp b/src/app/qt/element/QtCodeFile.cpp
index 444449e6..30fa6fc2 100644
--- a/src/app/qt/element/QtCodeFile.cpp
+++ b/src/app/qt/element/QtCodeFile.cpp
@@ -160,6 +160,10 @@ void QtCodeFile::addCodeSnippet(
snippet->setProperty("isLast", true);
m_fileSnippet = snippet;
+ if (!m_snippets.size())
+ {
+ m_fileSnippet->setIsActiveFile(true);
+ }
clickedMaximizeButton();
if (refCount != -1)
diff --git a/src/app/qt/element/QtCodeSnippet.cpp b/src/app/qt/element/QtCodeSnippet.cpp
index 7bc5c255..3985547d 100644
--- a/src/app/qt/element/QtCodeSnippet.cpp
+++ b/src/app/qt/element/QtCodeSnippet.cpp
@@ -140,6 +140,11 @@ bool QtCodeSnippet::isActive() const
return m_codeArea->isActive();
}
+void QtCodeSnippet::setIsActiveFile(bool isActiveFile)
+{
+ m_codeArea->setIsActiveFile(isActiveFile);
+}
+
void QtCodeSnippet::contextMenuEvent(QContextMenuEvent* event)
{
QMenu menu(this);
diff --git a/src/app/qt/element/QtCodeSnippet.h b/src/app/qt/element/QtCodeSnippet.h
index 4759686a..1762af73 100644
--- a/src/app/qt/element/QtCodeSnippet.h
+++ b/src/app/qt/element/QtCodeSnippet.h
@@ -42,6 +42,8 @@ public:
bool isActive() const;
+ void setIsActiveFile(bool isActiveFile);
+
protected:
virtual void contextMenuEvent(QContextMenuEvent* event) Q_DECL_OVERRIDE;
diff --git a/src/app/qt/view/QtCodeView.cpp b/src/app/qt/view/QtCodeView.cpp
index fec7f032..2a8422af 100644
--- a/src/app/qt/view/QtCodeView.cpp
+++ b/src/app/qt/view/QtCodeView.cpp
@@ -3,6 +3,7 @@
#include "utility/file/FileSystem.h"
#include "qt/utility/utilityQt.h"
+#include "qt/element/QtCodeArea.h"
#include "qt/element/QtCodeFileList.h"
#include "qt/view/QtViewWidgetWrapper.h"
#include "settings/ColorScheme.h"
@@ -83,6 +84,7 @@ void QtCodeView::doRefreshView()
{
setStyleSheet();
m_widget->clearCodeSnippets();
+ QtCodeArea::clearAnnotationColors();
}
void QtCodeView::doShowCodeSnippets(const std::vector& snippets)