added scrollbar and smooth scrolling

This commit is contained in:
fourtf 2017-01-26 04:26:40 +01:00
parent 3d6b9f7645
commit 700c756f5a
12 changed files with 333 additions and 10 deletions

View file

@ -18,6 +18,10 @@ Channel::Channel(const QString &channel)
, channelLink("https://twitch.tv/" + name)
, popoutPlayerLink("https://player.twitch.tv/?channel=" + name)
{
for (int i = 0; i < 40; i++) {
addMessage(std::shared_ptr<messages::Message>(
new messages::Message("test xD test")));
}
}
QVector<std::shared_ptr<messages::Message>>

View file

@ -93,6 +93,12 @@ public:
QVector<std::shared_ptr<messages::Message>> getMessagesClone();
QVector<std::shared_ptr<messages::Message>> &
getMessages()
{
return messages;
}
private:
QVector<std::shared_ptr<messages::Message>> messages;

129
channel.h.zT7500 Normal file
View file

@ -0,0 +1,129 @@
#ifndef CHANNEL_H
#define CHANNEL_H
#include "concurrentmap.h"
#include "messages/lazyloadedimage.h"
#include <QMap>
#include <QMutex>
#include <QString>
#include <QVector>
#include <memory>
namespace chatterino {
namespace messages {
class Message;
}
class Channel
{
public:
Channel(const QString &channel);
// properties
const ConcurrentMap<QString, messages::LazyLoadedImage *> &
getBttvChannelEmotes() const
{
return bttvChannelEmotes;
}
const ConcurrentMap<QString, messages::LazyLoadedImage *> &
getFfzChannelEmotes() const
{
return ffzChannelEmotes;
}
const QMutex &
getMessageMutex() const
{
return messageMutex;
}
const QString &
getName() const
{
return name;
}
int
getRoomID() const
{
return roomID;
}
const QString &
getSubLink() const
{
return subLink;
}
const QString &
getChannelLink() const
{
return channelLink;
}
const QString &
getPopoutPlayerLink() const
{
return popoutPlayerLink;
}
bool
getIsLive() const
{
return isLive;
}
int
getStreamViewerCount() const
{
return streamViewerCount;
}
const QString &
getStreamStatus() const
{
return streamStatus;
}
const QString &
getStreamGame() const
{
return streamGame;
}
// methods
void addMessage(std::shared_ptr<messages::Message> message);
QVector<std::shared_ptr<messages::Message>> getMessagesClone();
QVector<std::shared_ptr<messages::Message>> &
getMessages() const
{
return messages;
}
QMutex &
getMessageMutes() const
{
return messageMutex;
}
private:
QVector<std::shared_ptr<messages::Message>> messages;
QString name;
int roomID;
ConcurrentMap<QString, messages::LazyLoadedImage *> bttvChannelEmotes;
ConcurrentMap<QString, messages::LazyLoadedImage *> ffzChannelEmotes;
QMutex messageMutex;
QString subLink;
QString channelLink;
QString popoutPlayerLink;
bool isLive;
int streamViewerCount;
QString streamStatus;
QString streamGame;
};
}
#endif // CHANNEL_H

View file

@ -46,6 +46,8 @@ ColorScheme::setColors(float hue, float multiplyer)
ChatInputBackground = getColor(0, 0.1, 0.95);
ChatInputBorder = getColor(0, 0.1, 0.9);
ScrollbarBG = ChatBackground;
// generate color lookuptable
fillLookupTableValues(this->middleLookupTable, 0.000, 0.166, 0.66, 0.5);
fillLookupTableValues(this->middleLookupTable, 0.166, 0.333, 0.5, 0.55);

View file

@ -18,6 +18,7 @@ Settings::Settings()
, theme(this->settingsItems, "theme", "dark")
, selectedUser(this->settingsItems, "selectedUser", "")
, emoteScale(this->settingsItems, "emoteScale", 1.0)
, mouseScrollMultiplier(this->settingsItems, "mouseScrollMultiplier", 1.0)
, scaleEmotesByLineHeight(this->settingsItems, "scaleEmotesByLineHeight",
false)
, showTimestamps(this->settingsItems, "showTimestamps", true)

View file

@ -82,6 +82,7 @@ public:
Setting<QString> theme;
Setting<QString> selectedUser;
Setting<float> emoteScale;
Setting<float> mouseScrollMultiplier;
Setting<bool> scaleEmotesByLineHeight;
Setting<bool> showTimestamps;
Setting<bool> showTimestampSeconds;

View file

@ -59,6 +59,9 @@ ChatWidget::setChannelName(const QString &name)
} else {
this->channel = Channels::addChannel(channel);
}
this->view.layoutMessages();
this->view.repaint();
}
void

View file

@ -8,7 +8,6 @@
#include <math.h>
#include <QPainter>
#include <QScroller>
#include <functional>
namespace chatterino {
@ -19,12 +18,12 @@ ChatWidgetView::ChatWidgetView(ChatWidget *parent)
, chatWidget(parent)
, scrollbar(this)
{
auto scroll = QScroller::scroller(this);
scroll->scrollTo(QPointF(0, 100));
this->scrollbar.setSmallChange(2);
QObject::connect(&Settings::getInstance(), &Settings::wordTypeMaskChanged,
this, &ChatWidgetView::wordTypeMaskChanged);
this->scrollbar.getValueChanged().connect([this] { repaint(); });
}
ChatWidgetView::~ChatWidgetView()
@ -50,9 +49,25 @@ ChatWidgetView::layoutMessages()
redraw |= message.get()->layout(this->width(), true);
}
updateScrollbar();
return redraw;
}
void
ChatWidgetView::updateScrollbar()
{
auto c = this->chatWidget->getChannel();
if (c == NULL) {
return;
}
// this->scrollbar.setValue(0);
this->scrollbar.setLargeChange(10);
this->scrollbar.setMaximum(c->getMessages().size());
}
void
ChatWidgetView::resizeEvent(QResizeEvent *)
{
@ -163,5 +178,15 @@ ChatWidgetView::paintEvent(QPaintEvent *)
}
}
}
void
ChatWidgetView::wheelEvent(QWheelEvent *event)
{
this->scrollbar.setValue(
this->scrollbar.getValue() -
event->delta() / 10.0 *
Settings::getInstance().mouseScrollMultiplier.get(),
true);
}
}
}

View file

@ -6,6 +6,8 @@
#include "widgets/scrollbar.h"
#include <QPaintEvent>
#include <QScroller>
#include <QWheelEvent>
#include <QWidget>
namespace chatterino {
@ -22,10 +24,15 @@ public:
bool layoutMessages();
void updateScrollbar();
protected:
void resizeEvent(QResizeEvent *);
void paintEvent(QPaintEvent *);
void wheelEvent(QWheelEvent *event);
void scroll(int dx, int dy);
private:
ChatWidget *chatWidget;

View file

@ -1,6 +1,7 @@
#include "widgets/scrollbar.h"
#include "colorscheme.h"
#include <QMouseEvent>
#include <QPainter>
#define MIN_THUMB_HEIGHT 10
@ -11,15 +12,27 @@ 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()
@ -88,6 +101,8 @@ ScrollBar::paintEvent(QPaintEvent *)
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();
@ -99,6 +114,94 @@ ScrollBar::paintEvent(QPaintEvent *)
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->repaint();
}
} 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);
}
} else if (y < this->thumbRect.y()) {
if (this->mouseDownIndex == 0) {
this->setValue(this->value - this->smallChange);
}
} else if (this->thumbRect.contains(2, y)) {
// do nothing
} else if (y < height() - this->buttonHeight) {
if (this->mouseDownIndex == 0) {
this->setValue(this->value + this->smallChange);
}
} else {
if (this->mouseDownIndex == 0) {
this->setValue(this->value + this->smallChange);
}
}
this->mouseDownIndex = -1;
repaint();
}
void
ScrollBar::leaveEvent(QEvent *)
{
this->mouseOverIndex = -1;
repaint();
}
void
ScrollBar::updateScroll()
{

View file

@ -4,7 +4,9 @@
#include "widgets/scrollbarhighlight.h"
#include <QMutex>
#include <QPropertyAnimation>
#include <QWidget>
#include <boost/signals2.hpp>
#include <functional>
namespace chatterino {
@ -21,6 +23,8 @@ public:
void removeHighlightsWhere(std::function<bool(ScrollBarHighlight &)> func);
void addHighlight(ScrollBarHighlight *highlight);
Q_PROPERTY(qreal value READ getValue WRITE setValue)
void
setMaximum(qreal value)
{
@ -54,11 +58,26 @@ public:
}
void
setValue(qreal value)
setValue(qreal value, bool animated = false)
{
this->value = value;
value = std::max(this->minimum,
std::min(this->maximum - this->largeChange, value));
this->updateScroll();
if (this->value != value) {
if (animated) {
this->valueAnimation.stop();
this->valueAnimation.setStartValue(this->value);
this->valueAnimation.setEndValue(value);
this->valueAnimation.start();
} else {
this->value = value;
}
this->updateScroll();
this->valueChanged();
this->repaint();
}
}
qreal
@ -91,10 +110,27 @@ public:
return this->value;
}
boost::signals2::signal<void()> &
getValueChanged()
{
return valueChanged;
}
private:
QMutex mutex;
ScrollBarHighlight *highlights;
QPropertyAnimation valueAnimation;
void paintEvent(QPaintEvent *);
void mouseMoveEvent(QMouseEvent *event);
void mousePressEvent(QMouseEvent *event);
void mouseReleaseEvent(QMouseEvent *event);
void leaveEvent(QEvent *);
int mouseOverIndex;
int mouseDownIndex;
QPoint lastMousePosition;
int buttonHeight;
int trackHeight;
@ -107,6 +143,8 @@ private:
qreal smallChange;
qreal value;
boost::signals2::signal<void()> valueChanged;
void updateScroll();
};
}

View file

@ -4,17 +4,21 @@ namespace chatterino {
QMutex Windows::windowMutex;
widgets::MainWindow *Windows::mainWindow(NULL);
widgets::MainWindow *Windows::mainWindow(nullptr);
void
Windows::layoutVisibleChatWidgets(Channel *channel)
{
Windows::mainWindow->layoutVisibleChatWidgets(channel);
if (Windows::mainWindow != nullptr) {
Windows::mainWindow->layoutVisibleChatWidgets(channel);
}
}
void
Windows::repaintVisibleChatWidgets(Channel *channel)
{
Windows::mainWindow->repaintVisibleChatWidgets(channel);
if (Windows::mainWindow != nullptr) {
Windows::mainWindow->repaintVisibleChatWidgets(channel);
}
}
}