File indexing completed on 2024-04-28 15:30:59
0001 /* 0002 SPDX-FileCopyrightText: 2013-2018 Dominik Haumann <dhaumann@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "katetextanimation.h" 0008 0009 #include "katedocument.h" 0010 #include "katerenderer.h" 0011 #include "kateview.h" 0012 #include "kateviewinternal.h" 0013 0014 #include <QPainter> 0015 #include <QPointF> 0016 #include <QRect> 0017 #include <QSizeF> 0018 #include <QTimeLine> 0019 0020 KateTextAnimation::KateTextAnimation(KTextEditor::Range range, KTextEditor::Attribute::Ptr attribute, KateViewInternal *view) 0021 : QObject(view) 0022 , m_range(range) 0023 , m_attribute(std::move(attribute)) 0024 , m_doc(view->view()->doc()) 0025 , m_view(view) 0026 , m_timeLine(new QTimeLine(250, this)) 0027 , m_value(0.0) 0028 { 0029 m_text = view->view()->doc()->text(range); 0030 0031 connect(m_timeLine, &QTimeLine::valueChanged, this, &KateTextAnimation::nextFrame); 0032 connect(m_timeLine, &QTimeLine::finished, this, &KateTextAnimation::deleteLater); 0033 0034 m_timeLine->setEasingCurve(QEasingCurve::SineCurve); 0035 m_timeLine->start(); 0036 0037 QObject::connect(view, &KTextEditor::View::destroyed, m_timeLine, &QTimeLine::stop); 0038 } 0039 0040 KateTextAnimation::~KateTextAnimation() 0041 { 0042 // if still running, we need to update the view a last time to avoid artifacts 0043 if (m_timeLine->state() == QTimeLine::Running) { 0044 m_timeLine->stop(); 0045 nextFrame(0.0); 0046 } 0047 } 0048 0049 QRectF KateTextAnimation::rectForText() 0050 { 0051 const QFontMetricsF fm = m_view->view()->renderer()->currentFontMetrics(); 0052 const int lineHeight = m_view->view()->renderer()->lineHeight(); 0053 QPoint pixelPos = m_view->cursorToCoordinate(m_range.start(), /*bool realCursor*/ true, /*bool includeBorder*/ false); 0054 0055 if (pixelPos.x() == -1 || pixelPos.y() == -1) { 0056 return QRectF(); 0057 } else { 0058 QRectF rect(pixelPos.x(), pixelPos.y(), fm.boundingRect(m_view->view()->doc()->text(m_range)).width(), lineHeight); 0059 const QPointF center = rect.center(); 0060 const qreal factor = 1.0 + 0.5 * m_value; 0061 rect.setWidth(rect.width() * factor); 0062 rect.setHeight(rect.height() * factor); 0063 rect.moveCenter(center); 0064 return rect; 0065 } 0066 } 0067 0068 void KateTextAnimation::draw(QPainter &painter) 0069 { 0070 // could happen in corner cases: timeLine emitted finished(), but this object 0071 // is not yet deleted. Therefore, draw() might be called in paintEvent(). 0072 if (m_timeLine->state() == QTimeLine::NotRunning) { 0073 return; 0074 } 0075 0076 // get current rect and fill background 0077 QRectF rect = rectForText(); 0078 painter.fillRect(rect, m_attribute->background()); 0079 0080 // scale font with animation 0081 QFont f = m_view->view()->renderer()->currentFont(); 0082 f.setBold(m_attribute->fontBold()); 0083 f.setPointSizeF(f.pointSizeF() * (1.0 + 0.5 * m_value)); 0084 painter.setFont(f); 0085 0086 painter.setPen(m_attribute->foreground().color()); 0087 // finally draw contents on the view 0088 painter.drawText(rect, m_text); 0089 } 0090 0091 void KateTextAnimation::nextFrame(qreal value) 0092 { 0093 // cache previous rect for update 0094 const QRectF prevRect = rectForText(); 0095 0096 m_value = value; 0097 0098 // next rect is used to draw the text 0099 const QRectF nextRect = rectForText(); 0100 0101 // due to rounding errors, increase the rect 1px to avoid artifacts 0102 const QRect updateRect = nextRect.united(prevRect).adjusted(-1, -1, 1, 1).toRect(); 0103 0104 // request repaint 0105 m_view->update(updateRect); 0106 } 0107 0108 #include "moc_katetextanimation.cpp"