#include "widgets/scrollbar.h" #include "colorscheme.h" #include #include #define MIN_THUMB_HEIGHT 10 namespace chatterino { namespace widgets { ScrollBar::ScrollBar(QWidget *widget) : QWidget(widget) , mutex() , valueAnimation(this, "value") , highlights(NULL) , mouseOverIndex(-1) , mouseDownIndex(-1) , lastMousePosition() , buttonHeight(16) , trackHeight(100) , thumbRect() , maximum() , minimum() , largeChange() , smallChange() , value() , valueChanged() { resize(16, 100); valueAnimation.setDuration(300); valueAnimation.setEasingCurve(QEasingCurve(QEasingCurve::OutCubic)); this->setMouseTracking(true); } ScrollBar::~ScrollBar() { auto highlight = this->highlights; while (highlight != NULL) { auto tmp = highlight->next; delete highlight; highlight = tmp; } } void ScrollBar::removeHighlightsWhere(std::function func) { this->mutex.lock(); ScrollBarHighlight *last = NULL; ScrollBarHighlight *current = this->highlights; while (current != NULL) { if (func(*current)) { if (last == NULL) { this->highlights = current->next; } else { last->next = current->next; } auto oldCurrent = current; current = current->next; last = current; delete oldCurrent; } } this->mutex.unlock(); } void ScrollBar::addHighlight(ScrollBarHighlight *highlight) { this->mutex.lock(); if (this->highlights == NULL) { this->highlights = highlight; } else { highlight->next = this->highlights->next; this->highlights->next = highlight; } this->mutex.unlock(); } void ScrollBar::paintEvent(QPaintEvent *) { QPainter painter(this); painter.fillRect(rect(), ColorScheme::getInstance().ScrollbarBG); painter.fillRect(QRect(0, 0, width(), this->buttonHeight), QColor(255, 0, 0)); painter.fillRect( QRect(0, height() - this->buttonHeight, width(), this->buttonHeight), QColor(255, 0, 0)); painter.fillRect(this->thumbRect, QColor(0, 255, 255)); ScrollBarHighlight *highlight = this->highlights; this->mutex.lock(); // do { // painter.fillRect(); // } while ((highlight = highlight->next()) != NULL); this->mutex.unlock(); } void ScrollBar::mouseMoveEvent(QMouseEvent *event) { if (this->mouseDownIndex == -1) { int y = event->pos().y(); auto oldIndex = this->mouseOverIndex; if (y < this->buttonHeight) { this->mouseOverIndex = 0; } else if (y < this->thumbRect.y()) { this->mouseOverIndex = 1; } else if (this->thumbRect.contains(2, y)) { this->mouseOverIndex = 2; } else if (y < height() - this->buttonHeight) { this->mouseOverIndex = 3; } else { this->mouseOverIndex = 4; } if (oldIndex != this->mouseOverIndex) { this->update(); } } else if (this->mouseDownIndex == 2) { int delta = event->pos().y() - lastMousePosition.y(); this->setValue(this->value + (qreal)delta / this->trackHeight * maximum); } this->lastMousePosition = event->pos(); } void ScrollBar::mousePressEvent(QMouseEvent *event) { int y = event->pos().y(); if (y < this->buttonHeight) { this->mouseDownIndex = 0; } else if (y < this->thumbRect.y()) { this->mouseDownIndex = 1; } else if (this->thumbRect.contains(2, y)) { this->mouseDownIndex = 2; } else if (y < height() - this->buttonHeight) { this->mouseDownIndex = 3; } else { this->mouseDownIndex = 4; } } void ScrollBar::mouseReleaseEvent(QMouseEvent *event) { int y = event->pos().y(); if (y < this->buttonHeight) { if (this->mouseDownIndex == 0) { this->setValue(this->value - this->smallChange, true); } } else if (y < this->thumbRect.y()) { if (this->mouseDownIndex == 1) { this->setValue(this->value - this->smallChange, true); } } else if (this->thumbRect.contains(2, y)) { // do nothing } else if (y < height() - this->buttonHeight) { if (this->mouseDownIndex == 3) { this->setValue(this->value + this->smallChange, true); } } else { if (this->mouseDownIndex == 4) { this->setValue(this->value + this->smallChange, true); } } this->mouseDownIndex = -1; update(); } void ScrollBar::leaveEvent(QEvent *) { this->mouseOverIndex = -1; update(); } void ScrollBar::updateScroll() { this->trackHeight = height() - this->buttonHeight - this->buttonHeight - MIN_THUMB_HEIGHT - 1; this->thumbRect = QRect(0, (int)(this->value / this->maximum * this->trackHeight) + 1 + this->buttonHeight, width(), (int)(this->largeChange / this->maximum * this->trackHeight) + MIN_THUMB_HEIGHT); update(); } } }