mirror of
https://github.com/Chatterino/chatterino2.git
synced 2024-11-21 22:24:07 +01:00
Remove getApp
and getSettings
calls from Message-Rendering (#4535)
* refactor: remove singletons from message rendering * chore: add changelog entry * Disable the `cppcoreguidelines-avoid-const-or-ref-data-members` clang-tidy check * auto *app * Selection is a struct, not a class * Use ChannelView's `signalHolder_` instead of `channelConnections_` * Remove `applySettings` step, instead just connect & set each setting individually * rename & constify some context values * Handle empty "last message color" setting value better (as it was originally in this pr before I removed that change :-) * unrelated mini refactor cleanup * let painSelection handle size_t instead of int * Add some more comments to the MessageLayoutContext structs --------- Co-authored-by: Rasmus Karlsson <rasmus.karlsson@pajlada.com>
This commit is contained in:
parent
95aee044e2
commit
71594ad0d8
14 changed files with 312 additions and 131 deletions
|
@ -18,6 +18,7 @@ Checks: "-*,
|
|||
-cppcoreguidelines-pro-bounds-array-to-pointer-decay,
|
||||
-cppcoreguidelines-owning-memory,
|
||||
-cppcoreguidelines-avoid-magic-numbers,
|
||||
-cppcoreguidelines-avoid-const-or-ref-data-members,
|
||||
-readability-magic-numbers,
|
||||
-performance-noexcept-move-constructor,
|
||||
-misc-non-private-member-variables-in-classes,
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
- Dev: Moved preprocessor Git and date definitions to executables only. (#4681)
|
||||
- Dev: Refactored tests to be able to use `ctest` and run in debug builds. (#4700)
|
||||
- Dev: Added the ability to use an alternate linker using the `-DUSE_ALTERNATE_LINKER=...` CMake parameter. (#4711)
|
||||
- Dev: Removed `getApp` and `getSettings` calls from message rendering. (#4535)
|
||||
|
||||
## 2.4.4
|
||||
|
||||
|
|
|
@ -209,6 +209,8 @@ set(SOURCE_FILES
|
|||
messages/layouts/MessageLayout.hpp
|
||||
messages/layouts/MessageLayoutContainer.cpp
|
||||
messages/layouts/MessageLayoutContainer.hpp
|
||||
messages/layouts/MessageLayoutContext.cpp
|
||||
messages/layouts/MessageLayoutContext.hpp
|
||||
messages/layouts/MessageLayoutElement.cpp
|
||||
messages/layouts/MessageLayoutElement.hpp
|
||||
messages/search/AuthorPredicate.cpp
|
||||
|
|
|
@ -24,7 +24,6 @@ namespace chatterino::literals {
|
|||
namespace detail {
|
||||
// NOLINTBEGIN(modernize-avoid-c-arrays)
|
||||
// NOLINTBEGIN(cppcoreguidelines-avoid-c-arrays)
|
||||
// NOLINTBEGIN(cppcoreguidelines-avoid-const-or-ref-data-members)
|
||||
|
||||
template <size_t N>
|
||||
struct LiteralResolver {
|
||||
|
@ -95,7 +94,6 @@ namespace detail {
|
|||
}
|
||||
};
|
||||
|
||||
// NOLINTEND(cppcoreguidelines-avoid-const-or-ref-data-members)
|
||||
// NOLINTEND(cppcoreguidelines-avoid-c-arrays)
|
||||
// NOLINTEND(modernize-avoid-c-arrays)
|
||||
|
||||
|
|
|
@ -1,16 +1,14 @@
|
|||
#include "messages/layouts/MessageLayout.hpp"
|
||||
|
||||
#include "Application.hpp"
|
||||
#include "debug/Benchmark.hpp"
|
||||
#include "messages/layouts/MessageLayoutContainer.hpp"
|
||||
#include "messages/layouts/MessageLayoutContext.hpp"
|
||||
#include "messages/layouts/MessageLayoutElement.hpp"
|
||||
#include "messages/Message.hpp"
|
||||
#include "messages/MessageElement.hpp"
|
||||
#include "messages/Selection.hpp"
|
||||
#include "providers/colors/ColorProvider.hpp"
|
||||
#include "singletons/Emotes.hpp"
|
||||
#include "singletons/Settings.hpp"
|
||||
#include "singletons/Theme.hpp"
|
||||
#include "singletons/WindowManager.hpp"
|
||||
#include "util/DebugCount.hpp"
|
||||
#include "util/StreamerMode.hpp"
|
||||
|
@ -198,83 +196,76 @@ void MessageLayout::actuallyLayout(int width, MessageElementFlags flags)
|
|||
}
|
||||
|
||||
// Painting
|
||||
void MessageLayout::paint(QPainter &painter, int width, int y, int messageIndex,
|
||||
Selection &selection, bool isLastReadMessage,
|
||||
bool isWindowFocused, bool isMentions)
|
||||
void MessageLayout::paint(const MessagePaintContext &ctx)
|
||||
{
|
||||
auto app = getApp();
|
||||
QPixmap *pixmap = this->ensureBuffer(painter, width);
|
||||
QPixmap *pixmap = this->ensureBuffer(ctx.painter, ctx.canvasWidth);
|
||||
|
||||
if (!this->bufferValid_ || !selection.isEmpty())
|
||||
if (!this->bufferValid_ || !ctx.selection.isEmpty())
|
||||
{
|
||||
this->updateBuffer(pixmap, messageIndex, selection);
|
||||
this->updateBuffer(pixmap, ctx);
|
||||
}
|
||||
|
||||
// draw on buffer
|
||||
painter.drawPixmap(0, y, *pixmap);
|
||||
// painter.drawPixmap(0, y, this->container.width,
|
||||
// this->container.getHeight(), *pixmap);
|
||||
ctx.painter.drawPixmap(0, ctx.y, *pixmap);
|
||||
|
||||
// draw gif emotes
|
||||
this->container_.paintAnimatedElements(painter, y);
|
||||
this->container_.paintAnimatedElements(ctx.painter, ctx.y);
|
||||
|
||||
// draw disabled
|
||||
if (this->message_->flags.has(MessageFlag::Disabled))
|
||||
{
|
||||
painter.fillRect(0, y, pixmap->width(), pixmap->height(),
|
||||
app->themes->messages.disabled);
|
||||
// painter.fillRect(0, y, pixmap->width(), pixmap->height(),
|
||||
// QBrush(QColor(64, 64, 64, 64)));
|
||||
ctx.painter.fillRect(0, ctx.y, pixmap->width(), pixmap->height(),
|
||||
ctx.messageColors.disabled);
|
||||
}
|
||||
|
||||
if (this->message_->flags.has(MessageFlag::RecentMessage))
|
||||
{
|
||||
painter.fillRect(0, y, pixmap->width(), pixmap->height(),
|
||||
app->themes->messages.disabled);
|
||||
ctx.painter.fillRect(0, ctx.y, pixmap->width(), pixmap->height(),
|
||||
ctx.messageColors.disabled);
|
||||
}
|
||||
|
||||
if (!isMentions &&
|
||||
if (!ctx.isMentions &&
|
||||
(this->message_->flags.has(MessageFlag::RedeemedChannelPointReward) ||
|
||||
this->message_->flags.has(MessageFlag::RedeemedHighlight)) &&
|
||||
getSettings()->enableRedeemedHighlight.getValue())
|
||||
ctx.preferences.enableRedeemedHighlight)
|
||||
{
|
||||
painter.fillRect(
|
||||
0, y, this->scale_ * 4, pixmap->height(),
|
||||
ctx.painter.fillRect(
|
||||
0, ctx.y, int(this->scale_ * 4), pixmap->height(),
|
||||
*ColorProvider::instance().color(ColorType::RedeemedHighlight));
|
||||
}
|
||||
|
||||
// draw selection
|
||||
if (!selection.isEmpty())
|
||||
if (!ctx.selection.isEmpty())
|
||||
{
|
||||
this->container_.paintSelection(painter, messageIndex, selection, y);
|
||||
this->container_.paintSelection(ctx.painter, ctx.messageIndex,
|
||||
ctx.selection, ctx.y);
|
||||
}
|
||||
|
||||
// draw message seperation line
|
||||
if (getSettings()->separateMessages.getValue())
|
||||
if (ctx.preferences.separateMessages)
|
||||
{
|
||||
painter.fillRect(0, y, this->container_.getWidth() + 64, 1,
|
||||
app->themes->splits.messageSeperator);
|
||||
ctx.painter.fillRect(0, ctx.y, this->container_.getWidth() + 64, 1,
|
||||
ctx.messageColors.messageSeperator);
|
||||
}
|
||||
|
||||
// draw last read message line
|
||||
if (isLastReadMessage)
|
||||
if (ctx.isLastReadMessage)
|
||||
{
|
||||
QColor color;
|
||||
if (getSettings()->lastMessageColor != QStringLiteral(""))
|
||||
if (ctx.preferences.lastMessageColor.isValid())
|
||||
{
|
||||
color = QColor(getSettings()->lastMessageColor.getValue());
|
||||
color = ctx.preferences.lastMessageColor;
|
||||
}
|
||||
else
|
||||
{
|
||||
color = isWindowFocused
|
||||
? app->themes->tabs.selected.backgrounds.regular
|
||||
: app->themes->tabs.selected.backgrounds.unfocused;
|
||||
color = ctx.isWindowFocused
|
||||
? ctx.messageColors.focusedLastMessageLine
|
||||
: ctx.messageColors.unfocusedLastMessageLine;
|
||||
}
|
||||
|
||||
QBrush brush(color, static_cast<Qt::BrushStyle>(
|
||||
getSettings()->lastMessagePattern.getValue()));
|
||||
QBrush brush(color, ctx.preferences.lastMessagePattern);
|
||||
|
||||
painter.fillRect(0, y + this->container_.getHeight() - 1,
|
||||
ctx.painter.fillRect(0, ctx.y + this->container_.getHeight() - 1,
|
||||
pixmap->width(), 1, brush);
|
||||
}
|
||||
|
||||
|
@ -305,45 +296,42 @@ QPixmap *MessageLayout::ensureBuffer(QPainter &painter, int width)
|
|||
return this->buffer_.get();
|
||||
}
|
||||
|
||||
void MessageLayout::updateBuffer(QPixmap *buffer, int /*messageIndex*/,
|
||||
Selection & /*selection*/)
|
||||
void MessageLayout::updateBuffer(QPixmap *buffer,
|
||||
const MessagePaintContext &ctx)
|
||||
{
|
||||
if (buffer->isNull())
|
||||
{
|
||||
return;
|
||||
|
||||
auto app = getApp();
|
||||
auto settings = getSettings();
|
||||
}
|
||||
|
||||
QPainter painter(buffer);
|
||||
painter.setRenderHint(QPainter::SmoothPixmapTransform);
|
||||
|
||||
// draw background
|
||||
QColor backgroundColor = [this, &app] {
|
||||
if (getSettings()->alternateMessages.getValue() &&
|
||||
QColor backgroundColor = [&] {
|
||||
if (ctx.preferences.alternateMessages &&
|
||||
this->flags.has(MessageLayoutFlag::AlternateBackground))
|
||||
{
|
||||
return app->themes->messages.backgrounds.alternate;
|
||||
}
|
||||
else
|
||||
{
|
||||
return app->themes->messages.backgrounds.regular;
|
||||
return ctx.messageColors.alternate;
|
||||
}
|
||||
|
||||
return ctx.messageColors.regular;
|
||||
}();
|
||||
|
||||
if (this->message_->flags.has(MessageFlag::ElevatedMessage) &&
|
||||
getSettings()->enableElevatedMessageHighlight.getValue())
|
||||
{
|
||||
backgroundColor = blendColors(backgroundColor,
|
||||
*ColorProvider::instance().color(
|
||||
ColorType::ElevatedMessageHighlight));
|
||||
}
|
||||
|
||||
else if (this->message_->flags.has(MessageFlag::FirstMessage) &&
|
||||
getSettings()->enableFirstMessageHighlight.getValue())
|
||||
ctx.preferences.enableElevatedMessageHighlight)
|
||||
{
|
||||
backgroundColor = blendColors(
|
||||
backgroundColor,
|
||||
*ColorProvider::instance().color(ColorType::FirstMessageHighlight));
|
||||
*ctx.colorProvider.color(ColorType::ElevatedMessageHighlight));
|
||||
}
|
||||
|
||||
else if (this->message_->flags.has(MessageFlag::FirstMessage) &&
|
||||
ctx.preferences.enableFirstMessageHighlight)
|
||||
{
|
||||
backgroundColor = blendColors(
|
||||
backgroundColor,
|
||||
*ctx.colorProvider.color(ColorType::FirstMessageHighlight));
|
||||
}
|
||||
else if ((this->message_->flags.has(MessageFlag::Highlighted) ||
|
||||
this->message_->flags.has(MessageFlag::HighlightedWhisper)) &&
|
||||
|
@ -354,22 +342,21 @@ void MessageLayout::updateBuffer(QPixmap *buffer, int /*messageIndex*/,
|
|||
blendColors(backgroundColor, *this->message_->highlightColor);
|
||||
}
|
||||
else if (this->message_->flags.has(MessageFlag::Subscription) &&
|
||||
getSettings()->enableSubHighlight)
|
||||
ctx.preferences.enableSubHighlight)
|
||||
{
|
||||
// Blend highlight color with usual background color
|
||||
backgroundColor = blendColors(
|
||||
backgroundColor,
|
||||
*ColorProvider::instance().color(ColorType::Subscription));
|
||||
backgroundColor, *ctx.colorProvider.color(ColorType::Subscription));
|
||||
}
|
||||
else if ((this->message_->flags.has(MessageFlag::RedeemedHighlight) ||
|
||||
this->message_->flags.has(
|
||||
MessageFlag::RedeemedChannelPointReward)) &&
|
||||
settings->enableRedeemedHighlight.getValue())
|
||||
ctx.preferences.enableRedeemedHighlight)
|
||||
{
|
||||
// Blend highlight color with usual background color
|
||||
backgroundColor = blendColors(
|
||||
backgroundColor,
|
||||
*ColorProvider::instance().color(ColorType::RedeemedHighlight));
|
||||
backgroundColor =
|
||||
blendColors(backgroundColor,
|
||||
*ctx.colorProvider.color(ColorType::RedeemedHighlight));
|
||||
}
|
||||
else if (this->message_->flags.has(MessageFlag::AutoMod))
|
||||
{
|
||||
|
@ -383,7 +370,7 @@ void MessageLayout::updateBuffer(QPixmap *buffer, int /*messageIndex*/,
|
|||
painter.fillRect(buffer->rect(), backgroundColor);
|
||||
|
||||
// draw message
|
||||
this->container_.paintElements(painter);
|
||||
this->container_.paintElements(painter, ctx);
|
||||
|
||||
#ifdef FOURTF
|
||||
// debug
|
||||
|
|
|
@ -18,6 +18,7 @@ using MessagePtr = std::shared_ptr<const Message>;
|
|||
struct Selection;
|
||||
struct MessageLayoutContainer;
|
||||
class MessageLayoutElement;
|
||||
struct MessagePaintContext;
|
||||
|
||||
enum class MessageElementFlag : int64_t;
|
||||
using MessageElementFlags = FlagsEnum<MessageElementFlag>;
|
||||
|
@ -49,9 +50,7 @@ public:
|
|||
bool layout(int width, float scale_, MessageElementFlags flags);
|
||||
|
||||
// Painting
|
||||
void paint(QPainter &painter, int width, int y, int messageIndex,
|
||||
Selection &selection, bool isLastReadMessage,
|
||||
bool isWindowFocused, bool isMentions);
|
||||
void paint(const MessagePaintContext &ctx);
|
||||
void invalidateBuffer();
|
||||
void deleteBuffer();
|
||||
void deleteCache();
|
||||
|
@ -72,7 +71,7 @@ public:
|
|||
private:
|
||||
// methods
|
||||
void actuallyLayout(int width, MessageElementFlags flags);
|
||||
void updateBuffer(QPixmap *pixmap, int messageIndex, Selection &selection);
|
||||
void updateBuffer(QPixmap *buffer, const MessagePaintContext &ctx);
|
||||
|
||||
// Create new buffer if required, returning the buffer
|
||||
QPixmap *ensureBuffer(QPainter &painter, int width);
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "MessageLayoutContainer.hpp"
|
||||
|
||||
#include "Application.hpp"
|
||||
#include "messages/layouts/MessageLayoutContext.hpp"
|
||||
#include "messages/layouts/MessageLayoutElement.hpp"
|
||||
#include "messages/Message.hpp"
|
||||
#include "messages/MessageElement.hpp"
|
||||
|
@ -151,7 +152,7 @@ void MessageLayoutContainer::_addElement(MessageLayoutElement *element,
|
|||
}
|
||||
|
||||
// top margin
|
||||
if (this->elements_.size() == 0)
|
||||
if (this->elements_.empty())
|
||||
{
|
||||
this->currentY_ = int(this->margin.top * this->scale_);
|
||||
}
|
||||
|
@ -386,7 +387,7 @@ void MessageLayoutContainer::breakLine()
|
|||
element->getRect().y() + this->lineHeight_ + yExtra));
|
||||
}
|
||||
|
||||
if (this->lines_.size() != 0)
|
||||
if (!this->lines_.empty())
|
||||
{
|
||||
this->lines_.back().endIndex = this->lineStart_;
|
||||
this->lines_.back().endCharIndex = this->charIndex_;
|
||||
|
@ -395,7 +396,7 @@ void MessageLayoutContainer::breakLine()
|
|||
{(int)lineStart_, 0, this->charIndex_, 0,
|
||||
QRect(-100000, this->currentY_, 200000, lineHeight_)});
|
||||
|
||||
for (int i = this->lineStart_; i < this->elements_.size(); i++)
|
||||
for (auto i = this->lineStart_; i < this->elements_.size(); i++)
|
||||
{
|
||||
this->charIndex_ += this->elements_[i]->getSelectionIndexCount();
|
||||
}
|
||||
|
@ -465,7 +466,7 @@ void MessageLayoutContainer::end()
|
|||
|
||||
this->height_ += this->lineHeight_;
|
||||
|
||||
if (this->lines_.size() != 0)
|
||||
if (!this->lines_.empty())
|
||||
{
|
||||
this->lines_[0].rect.setTop(-100000);
|
||||
this->lines_.back().rect.setBottom(100000);
|
||||
|
@ -480,7 +481,7 @@ bool MessageLayoutContainer::canCollapse()
|
|||
this->flags_.has(MessageFlag::Collapsed);
|
||||
}
|
||||
|
||||
bool MessageLayoutContainer::isCollapsed()
|
||||
bool MessageLayoutContainer::isCollapsed() const
|
||||
{
|
||||
return this->isCollapsed_;
|
||||
}
|
||||
|
@ -499,7 +500,8 @@ MessageLayoutElement *MessageLayoutContainer::getElementAt(QPoint point)
|
|||
}
|
||||
|
||||
// painting
|
||||
void MessageLayoutContainer::paintElements(QPainter &painter)
|
||||
void MessageLayoutContainer::paintElements(QPainter &painter,
|
||||
const MessagePaintContext &ctx)
|
||||
{
|
||||
for (const std::unique_ptr<MessageLayoutElement> &element : this->elements_)
|
||||
{
|
||||
|
@ -508,7 +510,7 @@ void MessageLayoutContainer::paintElements(QPainter &painter)
|
|||
painter.drawRect(element->getRect());
|
||||
#endif
|
||||
|
||||
element->paint(painter);
|
||||
element->paint(painter, ctx.messageColors);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -521,10 +523,12 @@ void MessageLayoutContainer::paintAnimatedElements(QPainter &painter,
|
|||
}
|
||||
}
|
||||
|
||||
void MessageLayoutContainer::paintSelection(QPainter &painter, int messageIndex,
|
||||
Selection &selection, int yOffset)
|
||||
void MessageLayoutContainer::paintSelection(QPainter &painter,
|
||||
size_t messageIndex,
|
||||
const Selection &selection,
|
||||
int yOffset)
|
||||
{
|
||||
auto app = getApp();
|
||||
auto *app = getApp();
|
||||
QColor selectionColor = app->themes->messages.selection;
|
||||
|
||||
// don't draw anything
|
||||
|
@ -713,7 +717,7 @@ void MessageLayoutContainer::paintSelection(QPainter &painter, int messageIndex,
|
|||
// selection
|
||||
int MessageLayoutContainer::getSelectionIndex(QPoint point)
|
||||
{
|
||||
if (this->elements_.size() == 0)
|
||||
if (this->elements_.empty())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
@ -774,7 +778,7 @@ int MessageLayoutContainer::getSelectionIndex(QPoint point)
|
|||
// fourtf: no idea if this is acurate LOL
|
||||
int MessageLayoutContainer::getLastCharacterIndex() const
|
||||
{
|
||||
if (this->lines_.size() == 0)
|
||||
if (this->lines_.empty())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
@ -791,7 +795,7 @@ int MessageLayoutContainer::getFirstMessageCharacterIndex() const
|
|||
|
||||
// Get the index of the first character of the real message
|
||||
int index = 0;
|
||||
for (auto &element : this->elements_)
|
||||
for (const auto &element : this->elements_)
|
||||
{
|
||||
if (element->getFlags().hasAny(skippedFlags))
|
||||
{
|
||||
|
@ -853,11 +857,9 @@ void MessageLayoutContainer::addSelectionText(QString &str, uint32_t from,
|
|||
element->addCopyTextToString(str, 0, to - index);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
element->addCopyTextToString(str);
|
||||
}
|
||||
}
|
||||
|
||||
index += indexCount;
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ enum class FirstWord { Neutral, RTL, LTR };
|
|||
using MessageFlags = FlagsEnum<MessageFlag>;
|
||||
class MessageLayoutElement;
|
||||
struct Selection;
|
||||
struct MessagePaintContext;
|
||||
|
||||
struct Margin {
|
||||
int top;
|
||||
|
@ -73,10 +74,10 @@ struct MessageLayoutContainer {
|
|||
MessageLayoutElement *getElementAt(QPoint point);
|
||||
|
||||
// painting
|
||||
void paintElements(QPainter &painter);
|
||||
void paintElements(QPainter &painter, const MessagePaintContext &ctx);
|
||||
void paintAnimatedElements(QPainter &painter, int yOffset);
|
||||
void paintSelection(QPainter &painter, int messageIndex,
|
||||
Selection &selection, int yOffset);
|
||||
void paintSelection(QPainter &painter, size_t messageIndex,
|
||||
const Selection &selection, int yOffset);
|
||||
|
||||
// selection
|
||||
int getSelectionIndex(QPoint point);
|
||||
|
@ -85,7 +86,7 @@ struct MessageLayoutContainer {
|
|||
void addSelectionText(QString &str, uint32_t from, uint32_t to,
|
||||
CopyMode copymode);
|
||||
|
||||
bool isCollapsed();
|
||||
bool isCollapsed() const;
|
||||
|
||||
private:
|
||||
struct Line {
|
||||
|
|
82
src/messages/layouts/MessageLayoutContext.cpp
Normal file
82
src/messages/layouts/MessageLayoutContext.cpp
Normal file
|
@ -0,0 +1,82 @@
|
|||
#include "messages/layouts/MessageLayoutContext.hpp"
|
||||
|
||||
#include "singletons/Settings.hpp"
|
||||
#include "singletons/Theme.hpp"
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
void MessageColors::applyTheme(Theme *theme)
|
||||
{
|
||||
this->regular = theme->messages.backgrounds.regular;
|
||||
this->alternate = theme->messages.backgrounds.alternate;
|
||||
|
||||
this->disabled = theme->messages.disabled;
|
||||
this->selection = theme->messages.selection;
|
||||
this->system = theme->messages.textColors.system;
|
||||
|
||||
this->messageSeperator = theme->splits.messageSeperator;
|
||||
|
||||
this->focusedLastMessageLine = theme->tabs.selected.backgrounds.regular;
|
||||
this->unfocusedLastMessageLine = theme->tabs.selected.backgrounds.unfocused;
|
||||
}
|
||||
|
||||
void MessagePreferences::connectSettings(Settings *settings,
|
||||
pajlada::Signals::SignalHolder &holder)
|
||||
{
|
||||
settings->enableRedeemedHighlight.connect(
|
||||
[this](const auto &newValue) {
|
||||
this->enableRedeemedHighlight = newValue;
|
||||
},
|
||||
holder);
|
||||
|
||||
settings->enableElevatedMessageHighlight.connect(
|
||||
[this](const auto &newValue) {
|
||||
this->enableElevatedMessageHighlight = newValue;
|
||||
},
|
||||
holder);
|
||||
|
||||
settings->enableFirstMessageHighlight.connect(
|
||||
[this](const auto &newValue) {
|
||||
this->enableFirstMessageHighlight = newValue;
|
||||
},
|
||||
holder);
|
||||
|
||||
settings->enableSubHighlight.connect(
|
||||
[this](const auto &newValue) {
|
||||
this->enableSubHighlight = newValue;
|
||||
},
|
||||
holder);
|
||||
|
||||
settings->alternateMessages.connect(
|
||||
[this](const auto &newValue) {
|
||||
this->alternateMessages = newValue;
|
||||
},
|
||||
holder);
|
||||
|
||||
settings->separateMessages.connect(
|
||||
[this](const auto &newValue) {
|
||||
this->separateMessages = newValue;
|
||||
},
|
||||
holder);
|
||||
|
||||
settings->lastMessageColor.connect(
|
||||
[this](const auto &newValue) {
|
||||
if (newValue.isEmpty())
|
||||
{
|
||||
this->lastMessageColor = QColor();
|
||||
}
|
||||
else
|
||||
{
|
||||
this->lastMessageColor = QColor(newValue);
|
||||
}
|
||||
},
|
||||
holder);
|
||||
|
||||
settings->lastMessagePattern.connect(
|
||||
[this](const auto &newValue) {
|
||||
this->lastMessagePattern = static_cast<Qt::BrushStyle>(newValue);
|
||||
},
|
||||
holder);
|
||||
}
|
||||
|
||||
} // namespace chatterino
|
74
src/messages/layouts/MessageLayoutContext.hpp
Normal file
74
src/messages/layouts/MessageLayoutContext.hpp
Normal file
|
@ -0,0 +1,74 @@
|
|||
#pragma once
|
||||
|
||||
#include <QColor>
|
||||
#include <QPainter>
|
||||
|
||||
namespace pajlada::Signals {
|
||||
class SignalHolder;
|
||||
} // namespace pajlada::Signals
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
class ColorProvider;
|
||||
class Theme;
|
||||
class Settings;
|
||||
struct Selection;
|
||||
|
||||
// TODO: Figure out if this could be a subset of Theme instead (e.g. Theme::MessageColors)
|
||||
struct MessageColors {
|
||||
QColor regular;
|
||||
QColor alternate;
|
||||
QColor disabled;
|
||||
QColor selection;
|
||||
QColor system;
|
||||
|
||||
QColor messageSeperator;
|
||||
|
||||
QColor focusedLastMessageLine;
|
||||
QColor unfocusedLastMessageLine;
|
||||
|
||||
void applyTheme(Theme *theme);
|
||||
};
|
||||
|
||||
// TODO: Explore if we can let settings own this
|
||||
struct MessagePreferences {
|
||||
QColor lastMessageColor;
|
||||
Qt::BrushStyle lastMessagePattern{};
|
||||
|
||||
bool enableRedeemedHighlight{};
|
||||
bool enableElevatedMessageHighlight{};
|
||||
bool enableFirstMessageHighlight{};
|
||||
bool enableSubHighlight{};
|
||||
|
||||
bool alternateMessages{};
|
||||
bool separateMessages{};
|
||||
|
||||
void connectSettings(Settings *settings,
|
||||
pajlada::Signals::SignalHolder &holder);
|
||||
};
|
||||
|
||||
struct MessagePaintContext {
|
||||
QPainter &painter;
|
||||
const Selection &selection;
|
||||
const ColorProvider &colorProvider;
|
||||
const MessageColors &messageColors;
|
||||
const MessagePreferences &preferences;
|
||||
|
||||
// width of the area we have to draw on
|
||||
const int canvasWidth{};
|
||||
// whether the painting should be treated as if this view's window is focused
|
||||
const bool isWindowFocused{};
|
||||
// whether the painting should be treated as if this view is the special mentions view
|
||||
const bool isMentions{};
|
||||
|
||||
// y coordinate we're currently painting at
|
||||
int y{};
|
||||
|
||||
// Index of the message that is currently being painted
|
||||
// This index refers to the snapshot being used in the painting
|
||||
size_t messageIndex{};
|
||||
|
||||
bool isLastReadMessage{};
|
||||
};
|
||||
|
||||
} // namespace chatterino
|
|
@ -3,9 +3,9 @@
|
|||
#include "Application.hpp"
|
||||
#include "messages/Emote.hpp"
|
||||
#include "messages/Image.hpp"
|
||||
#include "messages/layouts/MessageLayoutContext.hpp"
|
||||
#include "messages/MessageElement.hpp"
|
||||
#include "providers/twitch/TwitchEmotes.hpp"
|
||||
#include "singletons/Theme.hpp"
|
||||
#include "util/DebugCount.hpp"
|
||||
|
||||
#include <QDebug>
|
||||
|
@ -137,7 +137,8 @@ int ImageLayoutElement::getSelectionIndexCount() const
|
|||
return this->trailingSpace ? 2 : 1;
|
||||
}
|
||||
|
||||
void ImageLayoutElement::paint(QPainter &painter)
|
||||
void ImageLayoutElement::paint(QPainter &painter,
|
||||
const MessageColors & /*messageColors*/)
|
||||
{
|
||||
if (this->image_ == nullptr)
|
||||
{
|
||||
|
@ -228,7 +229,8 @@ int LayeredImageLayoutElement::getSelectionIndexCount() const
|
|||
return this->trailingSpace ? 2 : 1;
|
||||
}
|
||||
|
||||
void LayeredImageLayoutElement::paint(QPainter &painter)
|
||||
void LayeredImageLayoutElement::paint(QPainter &painter,
|
||||
const MessageColors & /*messageColors*/)
|
||||
{
|
||||
auto fullRect = QRectF(this->getRect());
|
||||
|
||||
|
@ -329,7 +331,8 @@ ImageWithBackgroundLayoutElement::ImageWithBackgroundLayoutElement(
|
|||
{
|
||||
}
|
||||
|
||||
void ImageWithBackgroundLayoutElement::paint(QPainter &painter)
|
||||
void ImageWithBackgroundLayoutElement::paint(
|
||||
QPainter &painter, const MessageColors & /*messageColors*/)
|
||||
{
|
||||
if (this->image_ == nullptr)
|
||||
{
|
||||
|
@ -360,7 +363,8 @@ ImageWithCircleBackgroundLayoutElement::ImageWithCircleBackgroundLayoutElement(
|
|||
{
|
||||
}
|
||||
|
||||
void ImageWithCircleBackgroundLayoutElement::paint(QPainter &painter)
|
||||
void ImageWithCircleBackgroundLayoutElement::paint(
|
||||
QPainter &painter, const MessageColors & /*messageColors*/)
|
||||
{
|
||||
if (this->image_ == nullptr)
|
||||
{
|
||||
|
@ -423,7 +427,8 @@ int TextLayoutElement::getSelectionIndexCount() const
|
|||
return this->getText().length() + (this->trailingSpace ? 1 : 0);
|
||||
}
|
||||
|
||||
void TextLayoutElement::paint(QPainter &painter)
|
||||
void TextLayoutElement::paint(QPainter &painter,
|
||||
const MessageColors & /*messageColors*/)
|
||||
{
|
||||
auto app = getApp();
|
||||
QString text = this->getText();
|
||||
|
@ -532,13 +537,14 @@ int TextIconLayoutElement::getSelectionIndexCount() const
|
|||
return this->trailingSpace ? 2 : 1;
|
||||
}
|
||||
|
||||
void TextIconLayoutElement::paint(QPainter &painter)
|
||||
void TextIconLayoutElement::paint(QPainter &painter,
|
||||
const MessageColors &messageColors)
|
||||
{
|
||||
auto app = getApp();
|
||||
auto *app = getApp();
|
||||
|
||||
QFont font = app->fonts->getFont(FontStyle::Tiny, this->scale);
|
||||
|
||||
painter.setPen(app->themes->messages.textColors.system);
|
||||
painter.setPen(messageColors.system);
|
||||
painter.setFont(font);
|
||||
|
||||
QTextOption option;
|
||||
|
@ -598,7 +604,8 @@ ReplyCurveLayoutElement::ReplyCurveLayoutElement(MessageElement &creator,
|
|||
{
|
||||
}
|
||||
|
||||
void ReplyCurveLayoutElement::paint(QPainter &painter)
|
||||
void ReplyCurveLayoutElement::paint(QPainter &painter,
|
||||
const MessageColors & /*messageColors*/)
|
||||
{
|
||||
QRectF paintRect(this->getRect());
|
||||
QPainterPath path;
|
||||
|
|
|
@ -21,6 +21,7 @@ class Image;
|
|||
using ImagePtr = std::shared_ptr<Image>;
|
||||
enum class FontStyle : uint8_t;
|
||||
enum class MessageElementFlag : int64_t;
|
||||
struct MessageColors;
|
||||
|
||||
class MessageLayoutElement : boost::noncopyable
|
||||
{
|
||||
|
@ -44,7 +45,8 @@ public:
|
|||
virtual void addCopyTextToString(QString &str, uint32_t from = 0,
|
||||
uint32_t to = UINT32_MAX) const = 0;
|
||||
virtual int getSelectionIndexCount() const = 0;
|
||||
virtual void paint(QPainter &painter) = 0;
|
||||
virtual void paint(QPainter &painter,
|
||||
const MessageColors &messageColors) = 0;
|
||||
virtual void paintAnimated(QPainter &painter, int yOffset) = 0;
|
||||
virtual int getMouseOverIndex(const QPoint &abs) const = 0;
|
||||
virtual int getXFromIndex(int index) = 0;
|
||||
|
@ -75,7 +77,7 @@ protected:
|
|||
void addCopyTextToString(QString &str, uint32_t from = 0,
|
||||
uint32_t to = UINT32_MAX) const override;
|
||||
int getSelectionIndexCount() const override;
|
||||
void paint(QPainter &painter) override;
|
||||
void paint(QPainter &painter, const MessageColors &messageColors) override;
|
||||
void paintAnimated(QPainter &painter, int yOffset) override;
|
||||
int getMouseOverIndex(const QPoint &abs) const override;
|
||||
int getXFromIndex(int index) override;
|
||||
|
@ -94,7 +96,7 @@ protected:
|
|||
void addCopyTextToString(QString &str, uint32_t from = 0,
|
||||
uint32_t to = UINT32_MAX) const override;
|
||||
int getSelectionIndexCount() const override;
|
||||
void paint(QPainter &painter) override;
|
||||
void paint(QPainter &painter, const MessageColors &messageColors) override;
|
||||
void paintAnimated(QPainter &painter, int yOffset) override;
|
||||
int getMouseOverIndex(const QPoint &abs) const override;
|
||||
int getXFromIndex(int index) override;
|
||||
|
@ -110,7 +112,7 @@ public:
|
|||
const QSize &size, QColor color);
|
||||
|
||||
protected:
|
||||
void paint(QPainter &painter) override;
|
||||
void paint(QPainter &painter, const MessageColors &messageColors) override;
|
||||
|
||||
private:
|
||||
QColor color_;
|
||||
|
@ -125,7 +127,7 @@ public:
|
|||
int padding);
|
||||
|
||||
protected:
|
||||
void paint(QPainter &painter) override;
|
||||
void paint(QPainter &painter, const MessageColors &messageColors) override;
|
||||
|
||||
private:
|
||||
const QColor color_;
|
||||
|
@ -147,7 +149,7 @@ protected:
|
|||
void addCopyTextToString(QString &str, uint32_t from = 0,
|
||||
uint32_t to = UINT32_MAX) const override;
|
||||
int getSelectionIndexCount() const override;
|
||||
void paint(QPainter &painter) override;
|
||||
void paint(QPainter &painter, const MessageColors &messageColors) override;
|
||||
void paintAnimated(QPainter &painter, int yOffset) override;
|
||||
int getMouseOverIndex(const QPoint &abs) const override;
|
||||
int getXFromIndex(int index) override;
|
||||
|
@ -171,7 +173,7 @@ protected:
|
|||
void addCopyTextToString(QString &str, uint32_t from = 0,
|
||||
uint32_t to = UINT32_MAX) const override;
|
||||
int getSelectionIndexCount() const override;
|
||||
void paint(QPainter &painter) override;
|
||||
void paint(QPainter &painter, const MessageColors &messageColors) override;
|
||||
void paintAnimated(QPainter &painter, int yOffset) override;
|
||||
int getMouseOverIndex(const QPoint &abs) const override;
|
||||
int getXFromIndex(int index) override;
|
||||
|
@ -189,7 +191,7 @@ public:
|
|||
float radius, float neededMargin);
|
||||
|
||||
protected:
|
||||
void paint(QPainter &painter) override;
|
||||
void paint(QPainter &painter, const MessageColors &messageColors) override;
|
||||
void paintAnimated(QPainter &painter, int yOffset) override;
|
||||
int getMouseOverIndex(const QPoint &abs) const override;
|
||||
int getXFromIndex(int index) override;
|
||||
|
|
|
@ -11,12 +11,14 @@
|
|||
#include "messages/Emote.hpp"
|
||||
#include "messages/Image.hpp"
|
||||
#include "messages/layouts/MessageLayout.hpp"
|
||||
#include "messages/layouts/MessageLayoutContext.hpp"
|
||||
#include "messages/layouts/MessageLayoutElement.hpp"
|
||||
#include "messages/LimitedQueueSnapshot.hpp"
|
||||
#include "messages/Message.hpp"
|
||||
#include "messages/MessageBuilder.hpp"
|
||||
#include "messages/MessageElement.hpp"
|
||||
#include "messages/MessageThread.hpp"
|
||||
#include "providers/colors/ColorProvider.hpp"
|
||||
#include "providers/LinkResolver.hpp"
|
||||
#include "providers/twitch/TwitchAccount.hpp"
|
||||
#include "providers/twitch/TwitchChannel.hpp"
|
||||
|
@ -61,7 +63,6 @@
|
|||
#include <functional>
|
||||
#include <memory>
|
||||
|
||||
#define DRAW_WIDTH (this->width())
|
||||
#define SELECTION_RESUME_SCROLLING_MSG_THRESHOLD 3
|
||||
#define CHAT_HOVER_PAUSE_DURATION 1000
|
||||
#define TOOLTIP_EMOTE_ENTRIES_LIMIT 7
|
||||
|
@ -201,6 +202,10 @@ ChannelView::ChannelView(BaseWidget *parent, Split *split, Context context,
|
|||
auto curve = QEasingCurve();
|
||||
curve.setCustomType(highlightEasingFunction);
|
||||
this->highlightAnimation_.setEasingCurve(curve);
|
||||
|
||||
this->messageColors_.applyTheme(getTheme());
|
||||
this->messagePreferences_.connectSettings(getSettings(),
|
||||
this->signalHolder_);
|
||||
}
|
||||
|
||||
void ChannelView::initializeLayout()
|
||||
|
@ -378,6 +383,7 @@ void ChannelView::themeChangedEvent()
|
|||
|
||||
this->setupHighlightAnimationColors();
|
||||
this->queueLayout();
|
||||
this->messageColors_.applyTheme(getTheme());
|
||||
}
|
||||
|
||||
void ChannelView::setupHighlightAnimationColors()
|
||||
|
@ -1247,32 +1253,47 @@ void ChannelView::drawMessages(QPainter &painter)
|
|||
return;
|
||||
}
|
||||
|
||||
int y = int(-(messagesSnapshot[start].get()->getHeight() *
|
||||
(fmod(this->scrollBar_->getRelativeCurrentValue(), 1))));
|
||||
|
||||
MessageLayout *end = nullptr;
|
||||
bool windowFocused = this->window() == QApplication::activeWindow();
|
||||
|
||||
auto app = getApp();
|
||||
bool isMentions = this->underlyingChannel_ == app->twitch->mentionsChannel;
|
||||
MessagePaintContext ctx = {
|
||||
.painter = painter,
|
||||
.selection = this->selection_,
|
||||
.colorProvider = ColorProvider::instance(),
|
||||
.messageColors = this->messageColors_,
|
||||
.preferences = this->messagePreferences_,
|
||||
|
||||
for (size_t i = start; i < messagesSnapshot.size(); ++i)
|
||||
.canvasWidth = this->width(),
|
||||
.isWindowFocused = this->window() == QApplication::activeWindow(),
|
||||
.isMentions =
|
||||
this->underlyingChannel_ == getApp()->twitch->mentionsChannel,
|
||||
|
||||
.y = int(-(messagesSnapshot[start]->getHeight() *
|
||||
(fmod(this->scrollBar_->getRelativeCurrentValue(), 1)))),
|
||||
.messageIndex = start,
|
||||
.isLastReadMessage = false,
|
||||
|
||||
};
|
||||
bool showLastMessageIndicator = getSettings()->showLastMessageIndicator;
|
||||
|
||||
for (; ctx.messageIndex < messagesSnapshot.size(); ++ctx.messageIndex)
|
||||
{
|
||||
MessageLayout *layout = messagesSnapshot[i].get();
|
||||
MessageLayout *layout = messagesSnapshot[ctx.messageIndex].get();
|
||||
|
||||
bool isLastMessage = false;
|
||||
if (getSettings()->showLastMessageIndicator)
|
||||
if (showLastMessageIndicator)
|
||||
{
|
||||
isLastMessage = this->lastReadMessage_.get() == layout;
|
||||
ctx.isLastReadMessage = this->lastReadMessage_.get() == layout;
|
||||
}
|
||||
else
|
||||
{
|
||||
ctx.isLastReadMessage = false;
|
||||
}
|
||||
|
||||
layout->paint(painter, DRAW_WIDTH, y, i, this->selection_,
|
||||
isLastMessage, windowFocused, isMentions);
|
||||
layout->paint(ctx);
|
||||
|
||||
if (this->highlightedMessage_ == layout)
|
||||
{
|
||||
painter.fillRect(
|
||||
0, y, layout->getWidth(), layout->getHeight(),
|
||||
0, ctx.y, layout->getWidth(), layout->getHeight(),
|
||||
this->highlightAnimation_.currentValue().value<QColor>());
|
||||
if (this->highlightAnimation_.state() == QVariantAnimation::Stopped)
|
||||
{
|
||||
|
@ -1280,10 +1301,10 @@ void ChannelView::drawMessages(QPainter &painter)
|
|||
}
|
||||
}
|
||||
|
||||
y += layout->getHeight();
|
||||
ctx.y += layout->getHeight();
|
||||
|
||||
end = layout;
|
||||
if (y > this->height())
|
||||
if (ctx.y > this->height())
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "common/FlagsEnum.hpp"
|
||||
#include "messages/layouts/MessageLayoutContext.hpp"
|
||||
#include "messages/LimitedQueue.hpp"
|
||||
#include "messages/LimitedQueueSnapshot.hpp"
|
||||
#include "messages/Selection.hpp"
|
||||
|
@ -343,6 +344,9 @@ private:
|
|||
|
||||
std::unordered_set<std::shared_ptr<MessageLayout>> messagesOnScreen_;
|
||||
|
||||
MessageColors messageColors_;
|
||||
MessagePreferences messagePreferences_;
|
||||
|
||||
static constexpr int leftPadding = 8;
|
||||
static constexpr int scrollbarPadding = 8;
|
||||
|
||||
|
|
Loading…
Reference in a new issue