buttons.h 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. // This file is part of Desktop App Toolkit,
  2. // a set of libraries for developing nice desktop applications.
  3. //
  4. // For license and copyright information please follow this link:
  5. // https://github.com/desktop-app/legal/blob/master/LEGAL
  6. //
  7. #pragma once
  8. #include "ui/abstract_button.h"
  9. #include "ui/round_rect.h"
  10. #include "ui/effects/animations.h"
  11. #include "ui/text/text.h"
  12. #include "styles/style_widgets.h"
  13. #include <memory>
  14. class Painter;
  15. namespace st {
  16. extern const style::SettingsButton &defaultSettingsButton;
  17. } // namespace st
  18. namespace Ui {
  19. class RippleAnimation;
  20. class NumbersAnimation;
  21. class ToggleView;
  22. class LinkButton : public AbstractButton {
  23. public:
  24. LinkButton(QWidget *parent, const QString &text, const style::LinkButton &st = st::defaultLinkButton);
  25. int naturalWidth() const override;
  26. void setText(const QString &text);
  27. void setColorOverride(std::optional<QColor> textFg);
  28. protected:
  29. void paintEvent(QPaintEvent *e) override;
  30. void onStateChanged(State was, StateChangeSource source) override;
  31. private:
  32. void resizeToText();
  33. const style::LinkButton &_st;
  34. QString _text;
  35. int _textWidth = 0;
  36. std::optional<QColor> _textFgOverride;
  37. };
  38. class RippleButton : public AbstractButton {
  39. public:
  40. RippleButton(QWidget *parent, const style::RippleAnimation &st);
  41. void setForceRippled(
  42. bool rippled,
  43. anim::type animated = anim::type::normal);
  44. bool forceRippled() const {
  45. return _forceRippled;
  46. }
  47. static QPoint DisabledRippleStartPosition() {
  48. return QPoint(-0x3FFFFFFF, -0x3FFFFFFF);
  49. }
  50. void clearState() override;
  51. void paintRipple(
  52. QPainter &p,
  53. const QPoint &point,
  54. const QColor *colorOverride = nullptr);
  55. void paintRipple(
  56. QPainter &p,
  57. int x,
  58. int y,
  59. const QColor *colorOverride = nullptr);
  60. void finishAnimating();
  61. ~RippleButton();
  62. protected:
  63. void onStateChanged(State was, StateChangeSource source) override;
  64. virtual QImage prepareRippleMask() const;
  65. virtual QPoint prepareRippleStartPosition() const;
  66. private:
  67. void ensureRipple();
  68. const style::RippleAnimation &_st;
  69. std::unique_ptr<RippleAnimation> _ripple;
  70. bool _forceRippled = false;
  71. rpl::lifetime _forceRippledSubscription;
  72. };
  73. class FlatButton : public RippleButton {
  74. public:
  75. FlatButton(QWidget *parent, const QString &text, const style::FlatButton &st);
  76. void setText(const QString &text);
  77. void setWidth(int w);
  78. void setColorOverride(std::optional<QColor> color);
  79. void setTextMargins(QMargins margins);
  80. int32 textWidth() const;
  81. protected:
  82. void paintEvent(QPaintEvent *e) override;
  83. void onStateChanged(State was, StateChangeSource source) override;
  84. private:
  85. QString _text;
  86. QMargins _textMargins;
  87. int _width = 0;
  88. std::optional<QColor> _colorOverride;
  89. const style::FlatButton &_st;
  90. };
  91. class RoundButton : public RippleButton {
  92. public:
  93. RoundButton(
  94. QWidget *parent,
  95. rpl::producer<QString> text,
  96. const style::RoundButton &st);
  97. void setText(rpl::producer<QString> text);
  98. void setText(rpl::producer<TextWithEntities> text);
  99. void setNumbersText(const QString &numbersText) {
  100. setNumbersText(numbersText, numbersText.toInt());
  101. }
  102. void setNumbersText(int numbers) {
  103. setNumbersText(QString::number(numbers), numbers);
  104. }
  105. void setWidthChangedCallback(Fn<void()> callback);
  106. void setBrushOverride(std::optional<QBrush> brush);
  107. void setPenOverride(std::optional<QPen> pen);
  108. void finishNumbersAnimation();
  109. [[nodiscard]] int contentWidth() const;
  110. void setFullWidth(int newFullWidth);
  111. void setFullRadius(bool enabled);
  112. enum class TextTransform {
  113. NoTransform,
  114. ToUpper,
  115. };
  116. void setTextTransform(TextTransform transform);
  117. ~RoundButton();
  118. protected:
  119. void paintEvent(QPaintEvent *e) override;
  120. QImage prepareRippleMask() const override;
  121. QPoint prepareRippleStartPosition() const override;
  122. private:
  123. void setNumbersText(const QString &numbersText, int numbers);
  124. void numbersAnimationCallback();
  125. void resizeToText(const TextWithEntities &text);
  126. [[nodiscard]] int addedWidth() const;
  127. rpl::variable<TextWithEntities> _textFull;
  128. Ui::Text::String _text;
  129. std::unique_ptr<NumbersAnimation> _numbers;
  130. int _fullWidthOverride = 0;
  131. const style::RoundButton &_st;
  132. std::optional<QBrush> _brushOverride;
  133. std::optional<QPen> _penOverride;
  134. RoundRect _roundRect;
  135. RoundRect _roundRectOver;
  136. TextTransform _transform = TextTransform::ToUpper;
  137. bool _fullRadius = false;
  138. };
  139. class IconButton : public RippleButton {
  140. public:
  141. IconButton(QWidget *parent, const style::IconButton &st);
  142. [[nodiscard]] const style::IconButton &st() const;
  143. // Pass nullptr to restore the default icon.
  144. void setIconOverride(const style::icon *iconOverride, const style::icon *iconOverOverride = nullptr);
  145. void setRippleColorOverride(const style::color *colorOverride);
  146. protected:
  147. void paintEvent(QPaintEvent *e) override;
  148. void onStateChanged(State was, StateChangeSource source) override;
  149. QImage prepareRippleMask() const override;
  150. QPoint prepareRippleStartPosition() const override;
  151. [[nodiscard]] float64 iconOverOpacity() const;
  152. private:
  153. const style::IconButton &_st;
  154. const style::icon *_iconOverride = nullptr;
  155. const style::icon *_iconOverrideOver = nullptr;
  156. const style::color *_rippleColorOverride = nullptr;
  157. Ui::Animations::Simple _a_over;
  158. };
  159. class CrossButton : public RippleButton {
  160. public:
  161. CrossButton(QWidget *parent, const style::CrossButton &st);
  162. void toggle(bool shown, anim::type animated);
  163. void show(anim::type animated) {
  164. return toggle(true, animated);
  165. }
  166. void hide(anim::type animated) {
  167. return toggle(false, animated);
  168. }
  169. void finishAnimating() {
  170. _showAnimation.stop();
  171. animationCallback();
  172. }
  173. bool toggled() const {
  174. return _shown;
  175. }
  176. void setLoadingAnimation(bool enabled);
  177. protected:
  178. void paintEvent(QPaintEvent *e) override;
  179. void onStateChanged(State was, StateChangeSource source) override;
  180. QImage prepareRippleMask() const override;
  181. QPoint prepareRippleStartPosition() const override;
  182. private:
  183. bool loadingCallback(crl::time now);
  184. bool stopLoadingAnimation(crl::time now);
  185. void animationCallback();
  186. const style::CrossButton &_st;
  187. bool _shown = false;
  188. Ui::Animations::Simple _showAnimation;
  189. crl::time _loadingStopMs = 0;
  190. Ui::Animations::Basic _loadingAnimation;
  191. };
  192. class SettingsButton : public Ui::RippleButton {
  193. public:
  194. SettingsButton(
  195. QWidget *parent,
  196. rpl::producer<QString> &&text,
  197. const style::SettingsButton &st = st::defaultSettingsButton);
  198. SettingsButton(
  199. QWidget *parent,
  200. rpl::producer<TextWithEntities> &&text,
  201. const style::SettingsButton &st = st::defaultSettingsButton);
  202. SettingsButton(
  203. QWidget *parent,
  204. nullptr_t,
  205. const style::SettingsButton &st = st::defaultSettingsButton);
  206. ~SettingsButton();
  207. SettingsButton *toggleOn(
  208. rpl::producer<bool> &&toggled,
  209. bool ignoreClick = false);
  210. bool toggled() const;
  211. rpl::producer<bool> toggledChanges() const;
  212. rpl::producer<bool> toggledValue() const;
  213. void setToggleLocked(bool locked);
  214. void setColorOverride(std::optional<QColor> textColorOverride);
  215. void setPaddingOverride(style::margins padding);
  216. [[nodiscard]] const style::SettingsButton &st() const;
  217. [[nodiscard]] int fullTextWidth() const;
  218. void finishAnimating();
  219. protected:
  220. int resizeGetHeight(int newWidth) override;
  221. void onStateChanged(
  222. State was,
  223. StateChangeSource source) override;
  224. void paintEvent(QPaintEvent *e) override;
  225. void paintBg(Painter &p, const QRect &rect, bool over) const;
  226. void paintText(Painter &p, bool over, int outerw) const;
  227. void paintToggle(Painter &p, int outerw) const;
  228. [[nodiscard]] QRect maybeToggleRect() const;
  229. private:
  230. void setText(TextWithEntities &&text);
  231. [[nodiscard]] QRect toggleRect() const;
  232. const style::SettingsButton &_st;
  233. style::margins _padding;
  234. Ui::Text::String _text;
  235. std::unique_ptr<Ui::ToggleView> _toggle;
  236. std::optional<QColor> _textColorOverride;
  237. };
  238. [[nodiscard]] not_null<RippleButton*> CreateSimpleRectButton(
  239. QWidget *parent,
  240. const style::RippleAnimation &st);
  241. [[nodiscard]] not_null<RippleButton*> CreateSimpleSettingsButton(
  242. QWidget *parent,
  243. const style::RippleAnimation &st,
  244. const style::color &bg);
  245. [[nodiscard]] not_null<RippleButton*> CreateSimpleCircleButton(
  246. QWidget *parent,
  247. const style::RippleAnimation &st);
  248. [[nodiscard]] not_null<RippleButton*> CreateSimpleRoundButton(
  249. QWidget *parent,
  250. const style::RippleAnimation &st);
  251. } // namespace Ui