fix: split header "add split" button inconsistency (#6349)
This commit is contained in:
@@ -78,6 +78,7 @@
|
|||||||
- Dev: Fixed incorrect lua generation of static methods for typescript plugins. (#6190, #6223)
|
- Dev: Fixed incorrect lua generation of static methods for typescript plugins. (#6190, #6223)
|
||||||
- Dev: Merged top/bottom and left/right notebook layouts. (#6215)
|
- Dev: Merged top/bottom and left/right notebook layouts. (#6215)
|
||||||
- Dev: Refactored `Button` and friends. (#6102, #6255, #6266, #6302, #6268, #6334)
|
- Dev: Refactored `Button` and friends. (#6102, #6255, #6266, #6302, #6268, #6334)
|
||||||
|
- Dev: Made "add split" button (part of the split header) a natively rendered button. (#6349)
|
||||||
- Dev: Made Settings & Account button on Linux/macOS SVGs. (#6267)
|
- Dev: Made Settings & Account button on Linux/macOS SVGs. (#6267)
|
||||||
- Dev: Some more setting widget refactors. (#6317)
|
- Dev: Some more setting widget refactors. (#6317)
|
||||||
- Dev: Emoji style / set is now stored lowercase (and matched case-insensitively). Changing emoji style from this point on and then running an old version might mean you will use the Twitter emoji style by default. (#6300)
|
- Dev: Emoji style / set is now stored lowercase (and matched case-insensitively). Changing emoji style from this point on and then running an old version might mean you will use the Twitter emoji style by default. (#6300)
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 106 B |
Binary file not shown.
|
Before Width: | Height: | Size: 106 B |
@@ -613,6 +613,8 @@ set(SOURCE_FILES
|
|||||||
widgets/buttons/Button.hpp
|
widgets/buttons/Button.hpp
|
||||||
widgets/buttons/DimButton.cpp
|
widgets/buttons/DimButton.cpp
|
||||||
widgets/buttons/DimButton.hpp
|
widgets/buttons/DimButton.hpp
|
||||||
|
widgets/buttons/DrawnButton.cpp
|
||||||
|
widgets/buttons/DrawnButton.hpp
|
||||||
widgets/buttons/InitUpdateButton.cpp
|
widgets/buttons/InitUpdateButton.cpp
|
||||||
widgets/buttons/InitUpdateButton.hpp
|
widgets/buttons/InitUpdateButton.hpp
|
||||||
widgets/buttons/LabelButton.cpp
|
widgets/buttons/LabelButton.cpp
|
||||||
|
|||||||
@@ -148,6 +148,7 @@ void Button::enterEvent(QEvent * /*event*/)
|
|||||||
{
|
{
|
||||||
this->mouseOver_ = true;
|
this->mouseOver_ = true;
|
||||||
this->update();
|
this->update();
|
||||||
|
this->mouseOverUpdated();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -157,6 +158,7 @@ void Button::leaveEvent(QEvent * /*event*/)
|
|||||||
{
|
{
|
||||||
this->mouseOver_ = false;
|
this->mouseOver_ = false;
|
||||||
this->update();
|
this->update();
|
||||||
|
this->mouseOverUpdated();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -183,6 +183,11 @@ protected:
|
|||||||
/// Queue up the click animation at the given position
|
/// Queue up the click animation at the given position
|
||||||
void addClickEffect(QPoint position);
|
void addClickEffect(QPoint position);
|
||||||
|
|
||||||
|
/// This is fired when the mouse over state changes
|
||||||
|
virtual void mouseOverUpdated()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void onMouseEffectTimeout();
|
void onMouseEffectTimeout();
|
||||||
void showMenu();
|
void showMenu();
|
||||||
|
|||||||
@@ -0,0 +1,163 @@
|
|||||||
|
#include "widgets/buttons/DrawnButton.hpp"
|
||||||
|
|
||||||
|
#include "singletons/Theme.hpp"
|
||||||
|
|
||||||
|
#include <QPainter>
|
||||||
|
|
||||||
|
namespace chatterino {
|
||||||
|
|
||||||
|
DrawnButton::DrawnButton(Symbol symbol_, Options options, BaseWidget *parent)
|
||||||
|
: Button(parent)
|
||||||
|
, symbol(symbol_)
|
||||||
|
{
|
||||||
|
this->setContentCacheEnabled(true);
|
||||||
|
|
||||||
|
// Set user-defined options
|
||||||
|
this->setOptions(options);
|
||||||
|
|
||||||
|
// Ensure symbol-specific options are initially set
|
||||||
|
this->themeChangedEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawnButton::setOptions(Options options_)
|
||||||
|
{
|
||||||
|
this->options = options_;
|
||||||
|
|
||||||
|
this->invalidateContent();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawnButton::themeChangedEvent()
|
||||||
|
{
|
||||||
|
Button::themeChangedEvent();
|
||||||
|
|
||||||
|
auto &o = this->symbolOptions;
|
||||||
|
|
||||||
|
switch (this->symbol)
|
||||||
|
{
|
||||||
|
case Symbol::Plus: {
|
||||||
|
o.padding = 3;
|
||||||
|
o.thickness = 1;
|
||||||
|
|
||||||
|
o.foreground = this->theme->messages.textColors.system;
|
||||||
|
o.foregroundHover = this->theme->messages.textColors.regular;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->invalidateContent();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawnButton::mouseOverUpdated()
|
||||||
|
{
|
||||||
|
this->invalidateContent();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawnButton::paintContent(QPainter &painter)
|
||||||
|
{
|
||||||
|
QColor fg;
|
||||||
|
QColor bg;
|
||||||
|
|
||||||
|
if (this->mouseOver())
|
||||||
|
{
|
||||||
|
bg = this->getBackgroundHover();
|
||||||
|
fg = this->getForegroundHover();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bg = this->getBackground();
|
||||||
|
fg = this->getForeground();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bg.isValid())
|
||||||
|
{
|
||||||
|
painter.fillRect(this->rect(), bg);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto thickness = this->getThickness();
|
||||||
|
auto padding = this->getPadding();
|
||||||
|
|
||||||
|
switch (this->symbol)
|
||||||
|
{
|
||||||
|
case Symbol::Plus: {
|
||||||
|
QPen pen;
|
||||||
|
pen.setColor(fg);
|
||||||
|
pen.setWidth(thickness);
|
||||||
|
painter.setPen(pen);
|
||||||
|
|
||||||
|
auto innerSize = this->rect().size();
|
||||||
|
innerSize.setHeight(innerSize.width());
|
||||||
|
QRect inner;
|
||||||
|
inner.setSize(innerSize);
|
||||||
|
inner.moveCenter(this->rect().center());
|
||||||
|
|
||||||
|
auto top = inner.top();
|
||||||
|
auto bottom = inner.bottom();
|
||||||
|
auto center = inner.center();
|
||||||
|
auto left = inner.left();
|
||||||
|
auto right = inner.right();
|
||||||
|
|
||||||
|
QLine vertical(center.x(), top + padding, center.x(),
|
||||||
|
bottom - padding);
|
||||||
|
painter.drawLine(vertical);
|
||||||
|
QLine horizontal(left + padding, center.y(), right - padding,
|
||||||
|
center.y());
|
||||||
|
painter.drawLine(horizontal);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int DrawnButton::getPadding() const
|
||||||
|
{
|
||||||
|
auto v =
|
||||||
|
this->options.padding.value_or(this->symbolOptions.padding.value_or(0));
|
||||||
|
|
||||||
|
return static_cast<int>(std::round(static_cast<float>(v) * this->scale()));
|
||||||
|
}
|
||||||
|
|
||||||
|
int DrawnButton::getThickness() const
|
||||||
|
{
|
||||||
|
auto v = this->options.thickness.value_or(
|
||||||
|
this->symbolOptions.thickness.value_or(1));
|
||||||
|
|
||||||
|
return std::max(1, static_cast<int>(
|
||||||
|
std::round(static_cast<double>(v) * this->scale())));
|
||||||
|
}
|
||||||
|
|
||||||
|
QColor DrawnButton::getBackground() const
|
||||||
|
{
|
||||||
|
auto v = this->options.background.value_or(
|
||||||
|
this->symbolOptions.background.value_or(QColor()));
|
||||||
|
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
QColor DrawnButton::getBackgroundHover() const
|
||||||
|
{
|
||||||
|
auto v = this->options.backgroundHover.value_or(
|
||||||
|
this->symbolOptions.backgroundHover.value_or(QColor()));
|
||||||
|
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
QColor DrawnButton::getForeground() const
|
||||||
|
{
|
||||||
|
auto v = this->options.foreground.value_or(
|
||||||
|
this->symbolOptions.foreground.value_or(QColor()));
|
||||||
|
|
||||||
|
assert(v.isValid());
|
||||||
|
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
QColor DrawnButton::getForegroundHover() const
|
||||||
|
{
|
||||||
|
auto v = this->options.foregroundHover.value_or(
|
||||||
|
this->symbolOptions.foregroundHover.value_or(QColor()));
|
||||||
|
|
||||||
|
assert(v.isValid());
|
||||||
|
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace chatterino
|
||||||
@@ -0,0 +1,102 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "widgets/buttons/Button.hpp"
|
||||||
|
|
||||||
|
#include <QWidget>
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
|
namespace chatterino {
|
||||||
|
|
||||||
|
/// A button displaying custom-drawn primitive symbols.
|
||||||
|
class DrawnButton : public Button
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum class Symbol : std::uint8_t {
|
||||||
|
/// +
|
||||||
|
///
|
||||||
|
/// Default values:
|
||||||
|
/// Padding: 2px
|
||||||
|
/// Thickness: 1px
|
||||||
|
Plus,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Options {
|
||||||
|
/// The horizontal and vertical padding, in unscaled pixels, that will be applied when drawing the symbol
|
||||||
|
std::optional<int> padding;
|
||||||
|
|
||||||
|
/// The base line thickness that will be used when drawing the symbol.
|
||||||
|
///
|
||||||
|
/// Each symbol might use the thickness slightly different
|
||||||
|
std::optional<int> thickness;
|
||||||
|
|
||||||
|
std::optional<QColor> background;
|
||||||
|
std::optional<QColor> backgroundHover;
|
||||||
|
|
||||||
|
std::optional<QColor> foreground;
|
||||||
|
std::optional<QColor> foregroundHover;
|
||||||
|
};
|
||||||
|
|
||||||
|
DrawnButton(Symbol symbol_, Options options_, BaseWidget *parent);
|
||||||
|
|
||||||
|
/// Update the override options for this button
|
||||||
|
void setOptions(Options options_);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void themeChangedEvent() override;
|
||||||
|
|
||||||
|
void mouseOverUpdated() override;
|
||||||
|
|
||||||
|
void paintContent(QPainter &painter) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
/// Returns the padding (horizontal and vertical) to be used when drawing this button, taking the widget scale into consideration.
|
||||||
|
///
|
||||||
|
/// Prioritizes the user-defined options over the symbol-defined options.
|
||||||
|
int getPadding() const;
|
||||||
|
|
||||||
|
/// Returns the line thickness to be used when drawing this button, taking the widget scale into consideration.
|
||||||
|
///
|
||||||
|
/// Prioritizes the user-defined options over the symbol-defined options.
|
||||||
|
int getThickness() const;
|
||||||
|
|
||||||
|
/// Returns the background to be used when drawing this button.
|
||||||
|
///
|
||||||
|
/// The color may be invalid, meaning no background is drawn.
|
||||||
|
///
|
||||||
|
/// Prioritizes the user-defined options over the symbol-defined options.
|
||||||
|
QColor getBackground() const;
|
||||||
|
|
||||||
|
/// Returns the background to be used when drawing this button, and the user is hovering over it.
|
||||||
|
///
|
||||||
|
/// The color may be invalid, meaning no background is drawn.
|
||||||
|
///
|
||||||
|
/// Prioritizes the user-defined options over the symbol-defined options.
|
||||||
|
QColor getBackgroundHover() const;
|
||||||
|
|
||||||
|
/// Returns the foreground color to be used when drawing this button.
|
||||||
|
///
|
||||||
|
/// The color must not be invalid.
|
||||||
|
///
|
||||||
|
/// Prioritizes the user-defined options over the symbol-defined options.
|
||||||
|
QColor getForeground() const;
|
||||||
|
|
||||||
|
/// Returns the foreground color to be used when drawing this button, and the user is hovering over it.
|
||||||
|
///
|
||||||
|
/// The color must not be invalid.
|
||||||
|
///
|
||||||
|
/// Prioritizes the user-defined options over the symbol-defined options.
|
||||||
|
QColor getForegroundHover() const;
|
||||||
|
|
||||||
|
/// The options defined by the consumer / class wanting to draw this button
|
||||||
|
Options options;
|
||||||
|
|
||||||
|
/// The default options defined by the symbol
|
||||||
|
Options symbolOptions;
|
||||||
|
|
||||||
|
const Symbol symbol;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace chatterino
|
||||||
@@ -20,6 +20,7 @@
|
|||||||
#include "singletons/WindowManager.hpp"
|
#include "singletons/WindowManager.hpp"
|
||||||
#include "util/Helpers.hpp"
|
#include "util/Helpers.hpp"
|
||||||
#include "util/LayoutHelper.hpp"
|
#include "util/LayoutHelper.hpp"
|
||||||
|
#include "widgets/buttons/DrawnButton.hpp"
|
||||||
#include "widgets/buttons/LabelButton.hpp"
|
#include "widgets/buttons/LabelButton.hpp"
|
||||||
#include "widgets/buttons/PixmapButton.hpp"
|
#include "widgets/buttons/PixmapButton.hpp"
|
||||||
#include "widgets/dialogs/SettingsDialog.hpp"
|
#include "widgets/dialogs/SettingsDialog.hpp"
|
||||||
@@ -42,6 +43,14 @@ namespace {
|
|||||||
|
|
||||||
using namespace chatterino;
|
using namespace chatterino;
|
||||||
|
|
||||||
|
/// The width of the standard button.
|
||||||
|
constexpr const int BUTTON_WIDTH = 28;
|
||||||
|
|
||||||
|
/// The width of the "Add split" button.
|
||||||
|
///
|
||||||
|
/// This matches the scrollbar's full width.
|
||||||
|
constexpr const int ADD_SPLIT_BUTTON_WIDTH = 16;
|
||||||
|
|
||||||
// 5 minutes
|
// 5 minutes
|
||||||
constexpr const qint64 THUMBNAIL_MAX_AGE_MS = 5LL * 60 * 1000;
|
constexpr const qint64 THUMBNAIL_MAX_AGE_MS = 5LL * 60 * 1000;
|
||||||
|
|
||||||
@@ -280,6 +289,13 @@ void SplitHeader::initializeLayout()
|
|||||||
{
|
{
|
||||||
assert(this->layout() == nullptr);
|
assert(this->layout() == nullptr);
|
||||||
|
|
||||||
|
this->addButton_ = new DrawnButton(DrawnButton::Symbol::Plus,
|
||||||
|
{
|
||||||
|
.padding = 3,
|
||||||
|
.thickness = 1,
|
||||||
|
},
|
||||||
|
this);
|
||||||
|
|
||||||
auto *layout = makeLayout<QHBoxLayout>({
|
auto *layout = makeLayout<QHBoxLayout>({
|
||||||
// space
|
// space
|
||||||
makeWidget<BaseWidget>([](auto w) {
|
makeWidget<BaseWidget>([](auto w) {
|
||||||
@@ -353,14 +369,11 @@ void SplitHeader::initializeLayout()
|
|||||||
});
|
});
|
||||||
}),
|
}),
|
||||||
// add split
|
// add split
|
||||||
this->addButton_ = makeWidget<PixmapButton>([&](auto w) {
|
this->addButton_,
|
||||||
w->setPixmap(getResources().buttons.addSplitDark);
|
});
|
||||||
w->setMarginEnabled(false);
|
|
||||||
|
|
||||||
QObject::connect(w, &Button::leftClicked, this, [this]() {
|
QObject::connect(this->addButton_, &Button::leftClicked, this, [this]() {
|
||||||
this->split_->addSibling();
|
this->split_->addSibling();
|
||||||
});
|
|
||||||
}),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
getSettings()->customURIScheme.connect(
|
getSettings()->customURIScheme.connect(
|
||||||
@@ -791,13 +804,15 @@ void SplitHeader::handleChannelChanged()
|
|||||||
|
|
||||||
void SplitHeader::scaleChangedEvent(float scale)
|
void SplitHeader::scaleChangedEvent(float scale)
|
||||||
{
|
{
|
||||||
int w = int(28 * scale);
|
int w = int(BUTTON_WIDTH * scale);
|
||||||
|
int addSplitWidth = int(ADD_SPLIT_BUTTON_WIDTH * scale);
|
||||||
|
|
||||||
this->setFixedHeight(w);
|
this->setFixedHeight(w);
|
||||||
this->dropdownButton_->setFixedWidth(w);
|
this->dropdownButton_->setFixedWidth(w);
|
||||||
this->moderationButton_->setFixedWidth(w);
|
this->moderationButton_->setFixedWidth(w);
|
||||||
this->chattersButton_->setFixedWidth(w);
|
this->chattersButton_->setFixedWidth(w);
|
||||||
this->addButton_->setFixedWidth(w * 5 / 8);
|
|
||||||
|
this->addButton_->setFixedWidth(addSplitWidth);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SplitHeader::setAddButtonVisible(bool value)
|
void SplitHeader::setAddButtonVisible(bool value)
|
||||||
@@ -1061,18 +1076,21 @@ void SplitHeader::themeChangedEvent()
|
|||||||
}
|
}
|
||||||
this->titleLabel_->setPalette(palette);
|
this->titleLabel_->setPalette(palette);
|
||||||
|
|
||||||
|
this->addButton_->setOptions({
|
||||||
|
.background = this->theme->messages.backgrounds.regular,
|
||||||
|
.backgroundHover = this->theme->messages.backgrounds.regular,
|
||||||
|
});
|
||||||
|
|
||||||
// --
|
// --
|
||||||
if (this->theme->isLightTheme())
|
if (this->theme->isLightTheme())
|
||||||
{
|
{
|
||||||
this->chattersButton_->setPixmap(getResources().buttons.chattersDark);
|
this->chattersButton_->setPixmap(getResources().buttons.chattersDark);
|
||||||
this->dropdownButton_->setPixmap(getResources().buttons.menuDark);
|
this->dropdownButton_->setPixmap(getResources().buttons.menuDark);
|
||||||
this->addButton_->setPixmap(getResources().buttons.addSplit);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
this->chattersButton_->setPixmap(getResources().buttons.chattersLight);
|
this->chattersButton_->setPixmap(getResources().buttons.chattersLight);
|
||||||
this->dropdownButton_->setPixmap(getResources().buttons.menuLight);
|
this->dropdownButton_->setPixmap(getResources().buttons.menuLight);
|
||||||
this->addButton_->setPixmap(getResources().buttons.addSplitDark);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this->update();
|
this->update();
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
|
class DrawnButton;
|
||||||
class PixmapButton;
|
class PixmapButton;
|
||||||
class LabelButton;
|
class LabelButton;
|
||||||
class Label;
|
class Label;
|
||||||
@@ -87,7 +88,7 @@ private:
|
|||||||
|
|
||||||
PixmapButton *moderationButton_{};
|
PixmapButton *moderationButton_{};
|
||||||
PixmapButton *chattersButton_{};
|
PixmapButton *chattersButton_{};
|
||||||
PixmapButton *addButton_{};
|
DrawnButton *addButton_{};
|
||||||
|
|
||||||
// states
|
// states
|
||||||
QPoint dragStart_{};
|
QPoint dragStart_{};
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ std::vector<std::shared_ptr<MessageElement>> makeElements(const QString &text)
|
|||||||
auto emote = std::make_shared<Emote>(Emote{
|
auto emote = std::make_shared<Emote>(Emote{
|
||||||
.name = EmoteName{word},
|
.name = EmoteName{word},
|
||||||
.images = ImageSet{Image::fromResourcePixmap(
|
.images = ImageSet{Image::fromResourcePixmap(
|
||||||
getResources().buttons.addSplit)},
|
getResources().twitch.automod)},
|
||||||
.tooltip = {},
|
.tooltip = {},
|
||||||
.homePage = {},
|
.homePage = {},
|
||||||
.id = {},
|
.id = {},
|
||||||
|
|||||||
Reference in New Issue
Block a user