From 6591a01452918ce40ca101bb6cfe9770a44d16be Mon Sep 17 00:00:00 2001 From: David Schulz Date: Tue, 20 Jun 2017 08:28:10 +0200 Subject: TextEditor: Add line annotations Displaying short descriptive text of a TextMark at line end. Currently implemented for ClangTextMark and BookMark. Change-Id: Idc6b579bda0382ad94b2e236b715696396b10460 Reviewed-by: Nikolai Kosjar --- src/plugins/texteditor/textmark.cpp | 90 +++++++++++++++++++++++++++++++++++-- 1 file changed, 87 insertions(+), 3 deletions(-) (limited to 'src/plugins/texteditor/textmark.cpp') diff --git a/src/plugins/texteditor/textmark.cpp b/src/plugins/texteditor/textmark.cpp index 975cc7a41c..15939a3f44 100644 --- a/src/plugins/texteditor/textmark.cpp +++ b/src/plugins/texteditor/textmark.cpp @@ -33,6 +33,7 @@ #include #include +#include using namespace Core; using namespace Utils; @@ -57,6 +58,24 @@ private: QHash > m_marks; }; +class AnnotationColors +{ +public: + static AnnotationColors &getAnnotationColors(const QColor &markColor, + const QColor &backgroundColor); + +public: + using SourceColors = QPair; + QColor rectColor; + QColor textColor; + +private: + static double clipHsl(double value); + +private: + static QHash m_colorCache; +}; + TextMarkRegistry *m_instance = nullptr; TextMark::TextMark(const QString &fileName, int lineNumber, Id category, double widthFactor) @@ -99,11 +118,49 @@ int TextMark::lineNumber() const return m_lineNumber; } -void TextMark::paint(QPainter *painter, const QRect &rect) const +void TextMark::paintIcon(QPainter *painter, const QRect &rect) const { m_icon.paint(painter, rect, Qt::AlignCenter); } +void TextMark::paintAnnotation(QPainter *painter, + QRectF *annotationRect, + const QFontMetrics &fm) const +{ + QString text = lineAnnotation(); + if (text.isEmpty()) + return; + + const bool drawIcon = !m_icon.isNull(); + int textWidth = fm.width(text); + constexpr qreal margin = 1; + const qreal iconHeight = annotationRect->height() - 2 * margin; + const qreal iconWidth = iconHeight * m_widthFactor + 2 * margin; + qreal annotationWidth = (drawIcon ? textWidth + iconWidth : textWidth) + margin; + if (annotationRect->left() + annotationWidth > annotationRect->right()) { + textWidth = int(annotationRect->width() - (drawIcon ? iconWidth + margin : margin)); + text = fm.elidedText(text, Qt::ElideRight, textWidth); + annotationWidth = annotationRect->width(); + } + const QColor markColor = m_hasColor ? Utils::creatorTheme()->color(m_color).toHsl() + : painter->pen().color(); + const AnnotationColors &colors = + AnnotationColors::getAnnotationColors(markColor, painter->background().color()); + + painter->save(); + annotationRect->setWidth(annotationWidth); + painter->setPen(colors.rectColor); + painter->setBrush(colors.rectColor); + painter->drawRect(*annotationRect); + painter->setPen(colors.textColor); + if (drawIcon) { + paintIcon(painter, annotationRect->adjusted( + margin, margin, -(textWidth + 2 * margin), -margin).toAlignedRect()); + } + painter->drawText(annotationRect->adjusted(iconWidth, 0, 0, 0), Qt::AlignLeft, text); + painter->restore(); +} + void TextMark::updateLineNumber(int lineNumber) { m_lineNumber = lineNumber; @@ -176,7 +233,7 @@ void TextMark::dragToLine(int lineNumber) Q_UNUSED(lineNumber); } -void TextMark::addToToolTipLayout(QGridLayout *target) +void TextMark::addToToolTipLayout(QGridLayout *target) const { auto *contentLayout = new QVBoxLayout; addToolTipContent(contentLayout); @@ -191,7 +248,7 @@ void TextMark::addToToolTipLayout(QGridLayout *target) } } -bool TextMark::addToolTipContent(QLayout *target) +bool TextMark::addToolTipContent(QLayout *target) const { QString text = m_toolTip; if (text.isEmpty()) { @@ -304,6 +361,33 @@ void TextMarkRegistry::allDocumentsRenamed(const QString &oldName, const QString mark->updateFileName(newName); } +QHash AnnotationColors::m_colorCache; + +AnnotationColors &AnnotationColors::getAnnotationColors(const QColor &markColor, + const QColor &backgroundColor) +{ + AnnotationColors &colors = m_colorCache[{markColor, backgroundColor}]; + if (!colors.rectColor.isValid() || !colors.textColor.isValid()) { + const double backgroundSaturation = clipHsl(markColor.hslSaturationF() / 2); + const double backgroundLightness = clipHsl(backgroundColor.lightnessF()); + const double foregroundLightness = clipHsl(backgroundLightness > 0.5 + ? backgroundLightness - 0.5 + : backgroundLightness + 0.5); + colors.rectColor.setHslF(markColor.hslHueF(), + backgroundSaturation, + backgroundLightness); + colors.textColor.setHslF(markColor.hslHueF(), + markColor.hslSaturationF(), + foregroundLightness); + } + return colors; +} + +double AnnotationColors::clipHsl(double value) +{ + return std::max(0.15, std::min(0.85, value)); +} + } // namespace TextEditor #include "textmark.moc" -- cgit v1.2.1