This commit is contained in:
fourtf
2018-05-23 04:22:17 +02:00
parent bf560d37bd
commit dafbda6a4a
22 changed files with 404 additions and 1103 deletions
+100 -74
View File
@@ -3,6 +3,8 @@
#include <QDebug>
#include <QtGlobal>
#include "util/assertinguithread.hpp"
#ifdef Q_OS_WIN32
#define DEFAULT_FONT_FAMILY "Segoe UI"
#define DEFAULT_FONT_SIZE 10
@@ -20,86 +22,110 @@ namespace chatterino {
namespace singletons {
FontManager::FontManager()
: currentFontFamily("/appearance/currentFontFamily", DEFAULT_FONT_FAMILY)
, currentFontSize("/appearance/currentFontSize", DEFAULT_FONT_SIZE)
// , currentFont(this->currentFontFamily.getValue().c_str(), currentFontSize.getValue())
: chatFontFamily("/appearance/currentFontFamily", DEFAULT_FONT_FAMILY)
, chatFontSize("/appearance/currentFontSize", DEFAULT_FONT_SIZE)
{
qDebug() << "init FontManager";
this->currentFontFamily.connect([this](const std::string &newValue, auto) {
this->chatFontFamily.connect([this](const std::string &newValue, auto) {
util::assertInGuiThread();
this->incGeneration();
// this->currentFont.setFamily(newValue.c_str());
this->currentFontByScale.clear();
this->fontChanged.invoke();
});
this->currentFontSize.connect([this](const int &newValue, auto) {
this->incGeneration();
// this->currentFont.setSize(newValue);
this->currentFontByScale.clear();
this->fontChanged.invoke();
});
}
QFont &FontManager::getFont(FontManager::Type type, float scale)
{
// return this->currentFont.getFont(type);
return this->getCurrentFont(scale).getFont(type);
}
QFontMetrics &FontManager::getFontMetrics(FontManager::Type type, float scale)
{
// return this->currentFont.getFontMetrics(type);
return this->getCurrentFont(scale).getFontMetrics(type);
}
FontManager::FontData &FontManager::Font::getFontData(FontManager::Type type)
{
switch (type) {
case Tiny:
return this->tiny;
case Small:
return this->small;
case MediumSmall:
return this->mediumSmall;
case Medium:
return this->medium;
case MediumBold:
return this->mediumBold;
case MediumItalic:
return this->mediumItalic;
case Large:
return this->large;
case VeryLarge:
return this->veryLarge;
default:
qDebug() << "Unknown font type:" << type << ", defaulting to medium";
return this->medium;
}
}
QFont &FontManager::Font::getFont(Type type)
{
return this->getFontData(type).font;
}
QFontMetrics &FontManager::Font::getFontMetrics(Type type)
{
return this->getFontData(type).metrics;
}
FontManager::Font &FontManager::getCurrentFont(float scale)
{
for (auto it = this->currentFontByScale.begin(); it != this->currentFontByScale.end(); it++) {
if (it->first == scale) {
return it->second;
for (auto &map : this->fontsByType) {
map.clear();
}
}
this->currentFontByScale.push_back(
std::make_pair(scale, Font(this->currentFontFamily.getValue().c_str(),
this->currentFontSize.getValue() * scale)));
this->fontChanged.invoke();
});
return this->currentFontByScale.back().second;
this->chatFontSize.connect([this](const int &newValue, auto) {
util::assertInGuiThread();
this->incGeneration();
for (auto &map : this->fontsByType) {
map.clear();
}
this->fontChanged.invoke();
});
this->fontsByType.resize((size_t)EndType);
}
QFont FontManager::getFont(FontManager::Type type, float scale)
{
return this->getOrCreateFontData(type, scale).font;
}
QFontMetrics FontManager::getFontMetrics(FontManager::Type type, float scale)
{
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)
{
util::assertInGuiThread();
assert(type >= 0 && type < EndType);
auto &map = this->fontsByType[(size_t)type];
// find element
auto it = map.find(scale);
if (it != map.end()) {
// return if found
qDebug() << it->second.font;
return it->second;
}
// emplace new element
auto result = map.emplace(scale, this->createFontData(type, scale));
assert(result.second);
return result.first->second;
}
FontManager::FontData FontManager::createFontData(Type type, float scale)
{
// check if it's a chat (scale the setting)
if (type >= ChatStart && type <= ChatEnd) {
static std::unordered_map<Type, ChatFontData> sizeScale{
{ChatSmall, {0.6f, false, QFont::Normal}},
{ChatMediumSmall, {0.8f, false, QFont::Normal}},
{ChatMedium, {1, false, QFont::Normal}},
{ChatMediumBold, {1, false, QFont::Medium}},
{ChatMediumItalic, {1, true, QFont::Normal}},
{ChatLarge, {1.2f, false, QFont::Normal}},
{ChatVeryLarge, {1.4f, false, QFont::Normal}},
};
auto data = sizeScale[type];
return FontData(QFont(QString::fromStdString(this->chatFontFamily.getValue()),
this->chatFontSize.getValue() * data.scale * scale, data.weight,
data.italic));
}
// normal Ui font (use pt size)
{
static std::unordered_map<Type, UiFontData> defaultSize{
{Tiny, {8, "Monospace", false, QFont::Normal}},
{UiMedium, {12, DEFAULT_FONT_FAMILY, false, QFont::Normal}},
{UiTabs, {9, "Segoe UI", false, QFont::Normal}},
};
UiFontData &data = defaultSize[type];
QFont font(data.name, data.size * scale, data.weight, data.italic);
return FontData(font);
}
}
} // namespace singletons
+45 -99
View File
@@ -3,136 +3,82 @@
#include <QFont>
#include <QFontDatabase>
#include <QFontMetrics>
#include <array>
#include <boost/noncopyable.hpp>
#include <pajlada/settings/setting.hpp>
#include <pajlada/signals/signal.hpp>
#include <unordered_map>
namespace chatterino {
namespace singletons {
class FontManager
class FontManager : boost::noncopyable
{
public:
FontManager();
FontManager(const FontManager &) = delete;
FontManager(FontManager &&) = delete;
~FontManager() = delete;
// font data gets set in createFontData(...)
enum Type : uint8_t {
Tiny,
Small,
MediumSmall,
Medium,
MediumBold,
MediumItalic,
Large,
VeryLarge,
ChatSmall,
ChatMediumSmall,
ChatMedium,
ChatMediumBold,
ChatMediumItalic,
ChatLarge,
ChatVeryLarge,
UiMedium,
UiTabs,
// don't remove this value
EndType,
// make sure to update these values accordingly!
ChatStart = ChatSmall,
ChatEnd = ChatVeryLarge,
};
QFont &getFont(Type type, float scale);
QFontMetrics &getFontMetrics(Type type, float scale);
QFont getFont(Type type, float scale);
QFontMetrics getFontMetrics(Type type, float scale);
int getGeneration() const
{
return this->generation;
}
int getGeneration() const;
void incGeneration();
void incGeneration()
{
this->generation++;
}
pajlada::Settings::Setting<std::string> currentFontFamily;
pajlada::Settings::Setting<int> currentFontSize;
pajlada::Settings::Setting<std::string> chatFontFamily;
pajlada::Settings::Setting<int> chatFontSize;
pajlada::Signals::NoArgSignal fontChanged;
private:
struct FontData {
FontData(QFont &&_font)
FontData(const QFont &_font)
: font(_font)
, metrics(this->font)
, metrics(_font)
{
}
QFont font;
QFontMetrics metrics;
const QFont font;
const QFontMetrics metrics;
};
struct Font {
Font() = delete;
Font(const char *fontFamilyName, int mediumSize)
: tiny(QFont("Monospace", 8))
, small(QFont(fontFamilyName, mediumSize - 4))
, mediumSmall(QFont(fontFamilyName, mediumSize - 2))
, medium(QFont(fontFamilyName, mediumSize))
, mediumBold(QFont(fontFamilyName, mediumSize, QFont::DemiBold))
, mediumItalic(QFont(fontFamilyName, mediumSize, -1, true))
, large(QFont(fontFamilyName, mediumSize))
, veryLarge(QFont(fontFamilyName, mediumSize))
{
tiny.font.setStyleHint(QFont::TypeWriter);
}
void setFamily(const char *newFamily)
{
this->small.font.setFamily(newFamily);
this->mediumSmall.font.setFamily(newFamily);
this->medium.font.setFamily(newFamily);
this->mediumBold.font.setFamily(newFamily);
this->mediumItalic.font.setFamily(newFamily);
this->large.font.setFamily(newFamily);
this->veryLarge.font.setFamily(newFamily);
this->updateMetrics();
}
void setSize(int newMediumSize)
{
this->small.font.setPointSize(newMediumSize - 4);
this->mediumSmall.font.setPointSize(newMediumSize - 2);
this->medium.font.setPointSize(newMediumSize);
this->mediumBold.font.setPointSize(newMediumSize);
this->mediumItalic.font.setPointSize(newMediumSize);
this->large.font.setPointSize(newMediumSize + 2);
this->veryLarge.font.setPointSize(newMediumSize + 4);
this->updateMetrics();
}
void updateMetrics()
{
this->small.metrics = QFontMetrics(this->small.font);
this->mediumSmall.metrics = QFontMetrics(this->mediumSmall.font);
this->medium.metrics = QFontMetrics(this->medium.font);
this->mediumBold.metrics = QFontMetrics(this->mediumBold.font);
this->mediumItalic.metrics = QFontMetrics(this->mediumItalic.font);
this->large.metrics = QFontMetrics(this->large.font);
this->veryLarge.metrics = QFontMetrics(this->veryLarge.font);
}
FontData &getFontData(Type type);
QFont &getFont(Type type);
QFontMetrics &getFontMetrics(Type type);
FontData tiny;
FontData small;
FontData mediumSmall;
FontData medium;
FontData mediumBold;
FontData mediumItalic;
FontData large;
FontData veryLarge;
struct ChatFontData {
float scale;
bool italic;
QFont::Weight weight;
};
Font &getCurrentFont(float scale);
struct UiFontData {
float size;
const char *name;
bool italic;
QFont::Weight weight;
};
// Future plans:
// Could have multiple fonts in here, such as "Menu font", "Application font", "Chat font"
FontData &getOrCreateFontData(Type type, float scale);
FontData createFontData(Type type, float scale);
std::list<std::pair<float, Font>> currentFontByScale;
std::vector<std::unordered_map<float, FontData>> fontsByType;
int generation = 0;
};
+40 -20
View File
@@ -52,7 +52,6 @@ void ThemeManager::actuallyUpdate(double hue, double multiplier)
isLight = multiplier > 0;
bool lightWin = isLight;
QColor none(0, 0, 0, 0);
QColor themeColor = QColor::fromHslF(hue, 0.43, 0.5);
QColor themeColorNoSat = QColor::fromHslF(hue, 0, 0.5);
@@ -69,7 +68,7 @@ void ThemeManager::actuallyUpdate(double hue, double multiplier)
#ifdef Q_OS_LINUX
this->window.background = lightWin ? "#fff" : QColor(61, 60, 56);
#else
this->window.background = lightWin ? "#fff" : "#444";
this->window.background = lightWin ? "#fff" : "#111";
#endif
QColor fg = this->window.text = lightWin ? "#000" : "#eee";
@@ -89,27 +88,48 @@ void ThemeManager::actuallyUpdate(double hue, double multiplier)
/// TABS
if (lightWin) {
this->tabs.regular = {fg, {bg, QColor("#ccc"), bg}};
this->tabs.regular = {QColor("#444"),
{QColor("#fff"), QColor("#fff"), QColor("#fff")},
{QColor("#fff"), QColor("#fff"), QColor("#fff")}};
this->tabs.newMessage = {
fg,
{QBrush(blendColors(themeColor, "#ccc", 0.9), Qt::FDiagPattern),
QBrush(blendColors(themeColor, "#ccc", 0.9), Qt::FDiagPattern),
QBrush(blendColors(themeColorNoSat, "#ccc", 0.9), Qt::FDiagPattern)}};
this->tabs.highlighted = {fg, {QColor("#ccc"), QColor("#ccc"), QColor("#bbb")}};
this->tabs.selected = {QColor("#fff"),
{QColor("#777"), QColor("#777"), QColor("#888")}};
} else {
this->tabs.regular = {fg, {bg, QColor("#555"), bg}};
this->tabs.newMessage = {
fg,
{QBrush(blendColors(themeColor, "#666", 0.7), Qt::FDiagPattern),
QBrush(blendColors(themeColor, "#666", 0.5), Qt::FDiagPattern),
QBrush(blendColors(themeColorNoSat, "#666", 0.7), Qt::FDiagPattern)}};
this->tabs.highlighted = {fg, {QColor("#777"), QColor("#777"), QColor("#666")}};
fg, {bg, QColor("#ccc"), bg}, {QColor("#aaa"), QColor("#aaa"), QColor("#aaa")}};
this->tabs.highlighted = {fg,
{bg, QColor("#ccc"), bg},
{QColor("#b60505"), QColor("#b60505"), QColor("#b60505")}};
this->tabs.selected = {QColor("#000"),
{QColor("#999"), QColor("#999"), QColor("#888")}};
{QColor("#b4d7ff"), QColor("#b4d7ff"), QColor("#b4d7ff")},
{QColor("#00aeef"), QColor("#00aeef"), QColor("#00aeef")}};
} else {
this->tabs.regular = {QColor("#aaa"),
{QColor("#252525"), QColor("#252525"), QColor("#252525")},
{QColor("#444"), QColor("#444"), QColor("#444")}};
this->tabs.newMessage = {fg,
{QColor("#252525"), QColor("#252525"), QColor("#252525")},
{QColor("#888"), QColor("#888"), QColor("#888")}};
this->tabs.highlighted = {fg,
{QColor("#252525"), QColor("#252525"), QColor("#252525")},
{QColor("#ee6166"), QColor("#ee6166"), QColor("#ee6166")}};
this->tabs.selected = {QColor("#fff"),
{QColor("#555555"), QColor("#555555"), QColor("#555555")},
{QColor("#00aeef"), QColor("#00aeef"), QColor("#00aeef")}};
}
// this->tabs.newMessage = {
// fg,
// {QBrush(blendColors(themeColor, "#ccc", 0.9), Qt::FDiagPattern),
// QBrush(blendColors(themeColor, "#ccc", 0.9), Qt::FDiagPattern),
// QBrush(blendColors(themeColorNoSat, "#ccc", 0.9), Qt::FDiagPattern)}};
// this->tabs.newMessage = {
// fg,
// {QBrush(blendColors(themeColor, "#666", 0.7), Qt::FDiagPattern),
// QBrush(blendColors(themeColor, "#666", 0.5), Qt::FDiagPattern),
// QBrush(blendColors(themeColorNoSat, "#666", 0.7),
// Qt::FDiagPattern)}};
// this->tabs.highlighted = {fg, {QColor("#777"), QColor("#777"),
// QColor("#666")}};
this->tabs.bottomLine = this->tabs.selected.backgrounds.regular.color();
}
@@ -163,7 +183,7 @@ void ThemeManager::actuallyUpdate(double hue, double multiplier)
this->messages.selection = isLightTheme() ? QColor(0, 0, 0, 64) : QColor(255, 255, 255, 64);
this->updated.invoke();
}
} // namespace singletons
QColor ThemeManager::blendColors(const QColor &color1, const QColor &color2, qreal ratio)
{
+8 -3
View File
@@ -25,11 +25,16 @@ public:
struct TabColors {
QColor text;
struct Backgrounds {
struct {
QBrush regular;
QBrush hover;
QBrush unfocused;
} backgrounds;
struct {
QColor regular;
QColor hover;
QColor unfocused;
} line;
};
/// WINDOW
@@ -43,9 +48,9 @@ public:
/// TABS
struct {
TabColors regular;
TabColors selected;
TabColors highlighted;
TabColors newMessage;
TabColors highlighted;
TabColors selected;
QColor border;
QColor bottomLine;
} tabs;
+12 -10
View File
@@ -188,27 +188,27 @@ void WindowManager::initialize()
// load tabs
QJsonArray tabs = window_obj.value("tabs").toArray();
for (QJsonValue tab_val : tabs) {
widgets::SplitContainer *tab = window.getNotebook().addNewPage();
widgets::SplitContainer *page = window.getNotebook().addPage(false);
QJsonObject tab_obj = tab_val.toObject();
// set custom title
QJsonValue title_val = tab_obj.value("title");
if (title_val.isString()) {
tab->getTab()->setTitle(title_val.toString());
tab->getTab()->useDefaultTitle = false;
page->getTab()->setTitle(title_val.toString());
page->getTab()->useDefaultTitle = false;
}
// selected
if (tab_obj.value("selected").toBool(false)) {
window.getNotebook().select(tab);
window.getNotebook().select(page);
}
// load splits
QJsonObject splitRoot = tab_obj.value("splits2").toObject();
if (!splitRoot.isEmpty()) {
tab->decodeFromJson(splitRoot);
page->decodeFromJson(splitRoot);
continue;
}
@@ -217,12 +217,12 @@ void WindowManager::initialize()
int colNr = 0;
for (QJsonValue column_val : tab_obj.value("splits").toArray()) {
for (QJsonValue split_val : column_val.toArray()) {
widgets::Split *split = new widgets::Split(tab);
widgets::Split *split = new widgets::Split(page);
QJsonObject split_obj = split_val.toObject();
split->setChannel(decodeChannel(split_obj));
tab->appendSplit(split);
page->appendSplit(split);
}
colNr++;
}
@@ -231,7 +231,7 @@ void WindowManager::initialize()
if (mainWindow == nullptr) {
mainWindow = &createWindow(widgets::Window::Main);
mainWindow->getNotebook().addNewPage(true);
mainWindow->getNotebook().addPage(true);
}
this->initialized = true;
@@ -268,9 +268,11 @@ void WindowManager::save()
// window tabs
QJsonArray tabs_arr;
for (int tab_i = 0; tab_i < window->getNotebook().tabCount(); tab_i++) {
for (int tab_i = 0; tab_i < window->getNotebook().getPageCount(); tab_i++) {
QJsonObject tab_obj;
widgets::SplitContainer *tab = window->getNotebook().tabAt(tab_i);
widgets::SplitContainer *tab =
dynamic_cast<widgets::SplitContainer *>(window->getNotebook().getPageAt(tab_i));
assert(tab != nullptr);
// custom tab title
if (!tab->getTab()->useDefaultTitle) {