improved handling of relayouting messages

This commit is contained in:
fourtf 2018-06-04 16:10:54 +02:00
parent bd5f9853f9
commit 7ad4e36dbb
10 changed files with 87 additions and 126 deletions

View file

@ -147,10 +147,10 @@ void Image::loadImage()
loadedEventQueued = true; loadedEventQueued = true;
QTimer::singleShot(500, [] { QTimer::singleShot(500, [] {
getApp()->emotes->incGeneration(); getApp()->windows->incGeneration();
auto app = getApp(); auto app = getApp();
app->windows->layoutVisibleChatWidgets(); app->windows->layoutChannelViews();
loadedEventQueued = false; loadedEventQueued = false;
}); });
} }

View file

@ -3,6 +3,7 @@
#include "application.hpp" #include "application.hpp"
#include "singletons/emotemanager.hpp" #include "singletons/emotemanager.hpp"
#include "singletons/settingsmanager.hpp" #include "singletons/settingsmanager.hpp"
#include "singletons/windowmanager.hpp"
#include "util/benchmark.hpp" #include "util/benchmark.hpp"
#include <QApplication> #include <QApplication>
@ -59,52 +60,24 @@ bool MessageLayout::layout(int width, float scale, MessageElement::Flags flags)
layoutRequired |= widthChanged; layoutRequired |= widthChanged;
this->currentLayoutWidth_ = width; this->currentLayoutWidth_ = width;
// check if emotes changed // check if layout state changed
bool imagesChanged = this->emoteGeneration_ != app->emotes->getGeneration(); if (this->layoutState_ != app->windows->getGeneration()) {
layoutRequired |= imagesChanged; layoutRequired = true;
this->emoteGeneration_ = app->emotes->getGeneration(); this->flags |= RequiresBufferUpdate;
this->layoutState_ = app->windows->getGeneration();
// check if text changed }
bool textChanged = this->fontGeneration_ != app->fonts->getGeneration();
layoutRequired |= textChanged;
this->fontGeneration_ = app->fonts->getGeneration();
// check if work mask changed // check if work mask changed
bool wordMaskChanged = this->currentWordFlags_ != flags; // app->settings->getWordTypeMask(); layoutRequired |= this->currentWordFlags_ != flags;
layoutRequired |= wordMaskChanged;
this->currentWordFlags_ = flags; // app->settings->getWordTypeMask(); this->currentWordFlags_ = flags; // app->settings->getWordTypeMask();
// check if timestamp format changed
bool timestampFormatChanged = this->timestampFormat_ != app->settings->timestampFormat;
this->timestampFormat_ = app->settings->timestampFormat.getValue();
layoutRequired |= timestampFormatChanged;
// check if layout was requested manually // check if layout was requested manually
layoutRequired |= bool(this->flags & RequiresLayout); layoutRequired |= bool(this->flags & RequiresLayout);
this->flags &= ~RequiresLayout; this->flags &= decltype(RequiresLayout)(~RequiresLayout);
// check if dpi changed // check if dpi changed
bool scaleChanged = this->scale_ != scale; layoutRequired |= this->scale_ != scale;
layoutRequired |= scaleChanged;
this->scale_ = scale; this->scale_ = scale;
imagesChanged |= scaleChanged;
textChanged |= scaleChanged;
// update word sizes if needed
if (imagesChanged) {
// this->container.updateImages();
this->flags |= MessageLayout::RequiresBufferUpdate;
}
if (textChanged) {
// this->container.updateText();
this->flags |= MessageLayout::RequiresBufferUpdate;
}
if (widthChanged || wordMaskChanged) {
this->deleteBuffer();
}
// return if no layout is required
if (!layoutRequired) { if (!layoutRequired) {
return false; return false;
@ -112,7 +85,7 @@ bool MessageLayout::layout(int width, float scale, MessageElement::Flags flags)
int oldHeight = this->container_.getHeight(); int oldHeight = this->container_.getHeight();
this->actuallyLayout(width, flags); this->actuallyLayout(width, flags);
if (this->container_.getHeight() != oldHeight) { if (widthChanged || this->container_.getHeight() != oldHeight) {
this->deleteBuffer(); this->deleteBuffer();
} }
this->invalidateBuffer(); this->invalidateBuffer();

View file

@ -67,9 +67,7 @@ private:
int height_ = 0; int height_ = 0;
int currentLayoutWidth_ = -1; int currentLayoutWidth_ = -1;
int fontGeneration_ = -1; int layoutState_ = -1;
int emoteGeneration_ = -1;
QString timestampFormat_;
float scale_ = -1; float scale_ = -1;
unsigned int bufferUpdatedCount_ = 0; unsigned int bufferUpdatedCount_ = 0;

View file

@ -46,16 +46,6 @@ public:
util::EmoteData getTwitchEmoteById(long int id, const QString &emoteName); util::EmoteData getTwitchEmoteById(long int id, const QString &emoteName);
int getGeneration()
{
return _generation;
}
void incGeneration()
{
_generation++;
}
pajlada::Signals::NoArgSignal &getGifUpdateSignal(); pajlada::Signals::NoArgSignal &getGifUpdateSignal();
// Bit badge/emotes? // Bit badge/emotes?
@ -145,8 +135,6 @@ private:
pajlada::Signals::NoArgSignal gifUpdateTimerSignal; pajlada::Signals::NoArgSignal gifUpdateTimerSignal;
QTimer gifUpdateTimer; QTimer gifUpdateTimer;
bool gifUpdateTimerInitiated = false; bool gifUpdateTimerInitiated = false;
int _generation = 0;
}; };
} // namespace singletons } // namespace singletons

View file

@ -3,7 +3,9 @@
#include <QDebug> #include <QDebug>
#include <QtGlobal> #include <QtGlobal>
#include "application.hpp"
#include "util/assertinguithread.hpp" #include "util/assertinguithread.hpp"
#include "windowmanager.hpp"
#ifdef Q_OS_WIN32 #ifdef Q_OS_WIN32
#define DEFAULT_FONT_FAMILY "Segoe UI" #define DEFAULT_FONT_FAMILY "Segoe UI"
@ -27,27 +29,33 @@ FontManager::FontManager()
{ {
qDebug() << "init FontManager"; qDebug() << "init FontManager";
this->chatFontFamily.connect([this](const std::string &newValue, auto) { this->chatFontFamily.connect([this](const std::string &, auto) {
util::assertInGuiThread(); util::assertInGuiThread();
this->incGeneration(); if (getApp()->windows) {
getApp()->windows->incGeneration();
}
for (auto &map : this->fontsByType) { for (auto &map : this->fontsByType) {
map.clear(); map.clear();
} }
this->fontChanged.invoke(); this->fontChanged.invoke();
}); });
this->chatFontSize.connect([this](const int &newValue, auto) { this->chatFontSize.connect([this](const int &, auto) {
util::assertInGuiThread(); util::assertInGuiThread();
this->incGeneration(); if (getApp()->windows) {
getApp()->windows->incGeneration();
}
for (auto &map : this->fontsByType) { for (auto &map : this->fontsByType) {
map.clear(); map.clear();
} }
this->fontChanged.invoke(); this->fontChanged.invoke();
}); });
this->fontsByType.resize((size_t)EndType); this->fontsByType.resize(size_t(EndType));
} }
QFont FontManager::getFont(FontManager::Type type, float scale) QFont FontManager::getFont(FontManager::Type type, float scale)
@ -60,23 +68,13 @@ QFontMetrics FontManager::getFontMetrics(FontManager::Type type, float scale)
return this->getOrCreateFontData(type, scale).metrics; return this->getOrCreateFontData(type, scale).metrics;
} }
int FontManager::getGeneration() const
{
return this->generation;
}
void FontManager::incGeneration()
{
this->generation++;
}
FontManager::FontData &FontManager::getOrCreateFontData(Type type, float scale) FontManager::FontData &FontManager::getOrCreateFontData(Type type, float scale)
{ {
util::assertInGuiThread(); util::assertInGuiThread();
assert(type >= 0 && type < EndType); assert(type >= 0 && type < EndType);
auto &map = this->fontsByType[(size_t)type]; auto &map = this->fontsByType[size_t(type)];
// find element // find element
auto it = map.find(scale); auto it = map.find(scale);
@ -109,7 +107,7 @@ FontManager::FontData FontManager::createFontData(Type type, float scale)
auto data = sizeScale[type]; auto data = sizeScale[type];
return FontData(QFont(QString::fromStdString(this->chatFontFamily.getValue()), return FontData(QFont(QString::fromStdString(this->chatFontFamily.getValue()),
this->chatFontSize.getValue() * data.scale * scale, data.weight, int(this->chatFontSize.getValue() * data.scale * scale), data.weight,
data.italic)); data.italic));
} }
@ -128,7 +126,7 @@ FontManager::FontData FontManager::createFontData(Type type, float scale)
}; };
UiFontData &data = defaultSize[type]; UiFontData &data = defaultSize[type];
QFont font(data.name, data.size * scale, data.weight, data.italic); QFont font(data.name, int(data.size * scale), data.weight, data.italic);
return FontData(font); return FontData(font);
} }
} }

View file

@ -42,9 +42,6 @@ public:
QFont getFont(Type type, float scale); QFont getFont(Type type, float scale);
QFontMetrics getFontMetrics(Type type, float scale); QFontMetrics getFontMetrics(Type type, float scale);
int getGeneration() const;
void incGeneration();
pajlada::Settings::Setting<std::string> chatFontFamily; pajlada::Settings::Setting<std::string> chatFontFamily;
pajlada::Settings::Setting<int> chatFontSize; pajlada::Settings::Setting<int> chatFontSize;
@ -79,8 +76,6 @@ private:
FontData createFontData(Type type, float scale); FontData createFontData(Type type, float scale);
std::vector<std::unordered_map<float, FontData>> fontsByType; std::vector<std::unordered_map<float, FontData>> fontsByType;
int generation = 0;
}; };
} // namespace singletons } // namespace singletons

View file

@ -39,13 +39,18 @@ void SettingManager::initialize()
this->timestampFormat.connect([](auto, auto) { this->timestampFormat.connect([](auto, auto) {
auto app = getApp(); auto app = getApp();
app->windows->layoutVisibleChatWidgets(); app->windows->layoutChannelViews();
}); });
this->emoteScale.connect([](auto, auto) { this->emoteScale.connect([](auto, auto) { getApp()->windows->forceLayoutChannelViews(); });
getApp()->fonts->incGeneration();
getApp()->windows->layoutVisibleChatWidgets(); this->timestampFormat.connect([](auto, auto) { getApp()->windows->forceLayoutChannelViews(); });
}); this->alternateMessageBackground.connect(
[](auto, auto) { getApp()->windows->forceLayoutChannelViews(); });
this->seperateMessages.connect(
[](auto, auto) { getApp()->windows->forceLayoutChannelViews(); });
this->collapseLongMessages.connect(
[](auto, auto) { getApp()->windows->forceLayoutChannelViews(); });
} }
MessageElement::Flags SettingManager::getWordFlags() MessageElement::Flags SettingManager::getWordFlags()

View file

@ -58,11 +58,17 @@ WindowManager::WindowManager()
qDebug() << "init WindowManager"; qDebug() << "init WindowManager";
} }
void WindowManager::layoutVisibleChatWidgets(Channel *channel) void WindowManager::layoutChannelViews(Channel *channel)
{ {
this->layout.invoke(channel); this->layout.invoke(channel);
} }
void WindowManager::forceLayoutChannelViews()
{
this->incGeneration();
this->layoutChannelViews(nullptr);
}
void WindowManager::repaintVisibleChatWidgets(Channel *channel) void WindowManager::repaintVisibleChatWidgets(Channel *channel)
{ {
if (this->mainWindow != nullptr) { if (this->mainWindow != nullptr) {
@ -394,5 +400,15 @@ void WindowManager::closeAll()
} }
} }
int WindowManager::getGeneration() const
{
return this->generation;
}
void WindowManager::incGeneration()
{
this->generation++;
}
} // namespace singletons } // namespace singletons
} // namespace chatterino } // namespace chatterino

View file

@ -1,7 +1,7 @@
#pragma once #pragma once
#include "widgets/window.hpp"
#include "widgets/splitcontainer.hpp" #include "widgets/splitcontainer.hpp"
#include "widgets/window.hpp"
namespace chatterino { namespace chatterino {
// namespace widgets { // namespace widgets {
@ -19,7 +19,8 @@ public:
void showSettingsDialog(); void showSettingsDialog();
void showAccountSelectPopup(QPoint point); void showAccountSelectPopup(QPoint point);
void layoutVisibleChatWidgets(Channel *channel = nullptr); void layoutChannelViews(Channel *channel = nullptr);
void forceLayoutChannelViews();
void repaintVisibleChatWidgets(Channel *channel = nullptr); void repaintVisibleChatWidgets(Channel *channel = nullptr);
void repaintGifEmotes(); void repaintGifEmotes();
// void updateAll(); // void updateAll();
@ -35,12 +36,17 @@ public:
void initialize(); void initialize();
void closeAll(); void closeAll();
int getGeneration() const;
void incGeneration();
pajlada::Signals::NoArgSignal repaintGifs; pajlada::Signals::NoArgSignal repaintGifs;
pajlada::Signals::Signal<Channel *> layout; pajlada::Signals::Signal<Channel *> layout;
private: private:
bool initialized = false; bool initialized = false;
std::atomic<int> generation{0};
std::vector<widgets::Window *> windows; std::vector<widgets::Window *> windows;
widgets::Window *mainWindow = nullptr; widgets::Window *mainWindow = nullptr;

View file

@ -51,12 +51,9 @@ AppearancePage::AppearancePage()
auto form = application.emplace<QFormLayout>(); auto form = application.emplace<QFormLayout>();
auto *theme = this->createComboBox({THEME_ITEMS}, app->themes->themeName); auto *theme = this->createComboBox({THEME_ITEMS}, app->themes->themeName);
QObject::connect(theme, &QComboBox::currentTextChanged, [](const QString &) { QObject::connect(theme, &QComboBox::currentTextChanged,
getApp()->fonts->incGeneration(); [](const QString &) { getApp()->windows->forceLayoutChannelViews(); });
getApp()->windows->repaintVisibleChatWidgets();
});
// clang-format off
form->addRow("Theme:", theme); form->addRow("Theme:", theme);
// form->addRow("Theme color:", this->createThemeColorChanger()); // form->addRow("Theme color:", this->createThemeColorChanger());
form->addRow("Font:", this->createFontChanger()); form->addRow("Font:", this->createFontChanger());
@ -67,9 +64,10 @@ AppearancePage::AppearancePage()
form->addRow("", this->createCheckBox(TAB_USER, app->settings->hideUserButton)); form->addRow("", this->createCheckBox(TAB_USER, app->settings->hideUserButton));
#endif #endif
form->addRow("Scrolling:", this->createCheckBox(SCROLL_SMOOTH, app->settings->enableSmoothScrolling)); form->addRow("Scrolling:",
form->addRow("", this->createCheckBox(SCROLL_NEWMSG, app->settings->enableSmoothScrollingNewMessages)); this->createCheckBox(SCROLL_SMOOTH, app->settings->enableSmoothScrolling));
// clang-format on form->addRow("", this->createCheckBox(SCROLL_NEWMSG,
app->settings->enableSmoothScrollingNewMessages));
} }
auto messages = layout.emplace<QGroupBox>("Messages").emplace<QVBoxLayout>(); auto messages = layout.emplace<QGroupBox>("Messages").emplace<QVBoxLayout>();
@ -84,27 +82,11 @@ AppearancePage::AppearancePage()
messages.append(this->createCheckBox("Show badges", app->settings->showBadges)); messages.append(this->createCheckBox("Show badges", app->settings->showBadges));
auto *collapseMessages = this->createCheckBox("Collapse large messages (3+ lines)", messages.append(this->createCheckBox("Collapse large messages (3+ lines)",
app->settings->collapseLongMessages); app->settings->collapseLongMessages));
QObject::connect(collapseMessages, &QCheckBox::toggled, messages.append(this->createCheckBox("Seperate messages", app->settings->seperateMessages));
[] { getApp()->windows->layoutVisibleChatWidgets(); }); messages.append(this->createCheckBox("Alternate message background color",
messages.append(collapseMessages); app->settings->alternateMessageBackground));
{
auto checkbox =
this->createCheckBox("Seperate messages", app->settings->seperateMessages);
messages.append(checkbox);
QObject::connect(checkbox, &QCheckBox::toggled,
[](bool) { getApp()->windows->repaintVisibleChatWidgets(); });
}
{
auto checkbox = this->createCheckBox("Alternate message background color",
app->settings->alternateMessageBackground);
messages.append(checkbox);
QObject::connect(checkbox, &QCheckBox::toggled, [](bool) {
getApp()->fonts->incGeneration(); // fourtf: hacky solution
getApp()->windows->repaintVisibleChatWidgets();
});
}
messages.append(this->createCheckBox("Show message length while typing", messages.append(this->createCheckBox("Show message length while typing",
app->settings->showMessageLength)); app->settings->showMessageLength));
@ -160,7 +142,7 @@ QLayout *AppearancePage::createThemeColorChanger()
// SLIDER // SLIDER
QSlider *slider = new QSlider(Qt::Horizontal); QSlider *slider = new QSlider(Qt::Horizontal);
layout->addWidget(slider); layout->addWidget(slider);
slider->setValue(std::min(std::max(themeHue.getValue(), 0.0), 1.0) * 100); slider->setValue(int(std::min(std::max(themeHue.getValue(), 0.0), 1.0) * 100));
// BUTTON // BUTTON
QPushButton *button = new QPushButton; QPushButton *button = new QPushButton;