mirror of
https://github.com/Chatterino/chatterino2.git
synced 2024-11-21 22:24:07 +01:00
added scrollbar and smooth scrolling
This commit is contained in:
parent
3d6b9f7645
commit
700c756f5a
12 changed files with 333 additions and 10 deletions
|
@ -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>>
|
||||
|
|
|
@ -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
129
channel.h.zT7500
Normal 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
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -59,6 +59,9 @@ ChatWidget::setChannelName(const QString &name)
|
|||
} else {
|
||||
this->channel = Channels::addChannel(channel);
|
||||
}
|
||||
|
||||
this->view.layoutMessages();
|
||||
this->view.repaint();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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()
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
value = std::max(this->minimum,
|
||||
std::min(this->maximum - this->largeChange, value));
|
||||
|
||||
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();
|
||||
};
|
||||
}
|
||||
|
|
|
@ -4,17 +4,21 @@ namespace chatterino {
|
|||
|
||||
QMutex Windows::windowMutex;
|
||||
|
||||
widgets::MainWindow *Windows::mainWindow(NULL);
|
||||
widgets::MainWindow *Windows::mainWindow(nullptr);
|
||||
|
||||
void
|
||||
Windows::layoutVisibleChatWidgets(Channel *channel)
|
||||
{
|
||||
if (Windows::mainWindow != nullptr) {
|
||||
Windows::mainWindow->layoutVisibleChatWidgets(channel);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Windows::repaintVisibleChatWidgets(Channel *channel)
|
||||
{
|
||||
if (Windows::mainWindow != nullptr) {
|
||||
Windows::mainWindow->repaintVisibleChatWidgets(channel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue