discrete_sliders.h 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. /*
  2. This file is part of Telegram Desktop,
  3. the official desktop application for the Telegram messaging service.
  4. For license and copyright information please follow this link:
  5. https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
  6. */
  7. #pragma once
  8. #include "ui/rp_widget.h"
  9. #include "ui/round_rect.h"
  10. #include "ui/effects/animations.h"
  11. #include "ui/text/text.h"
  12. namespace style {
  13. struct TextStyle;
  14. struct SettingsSlider;
  15. } // namespace style
  16. namespace st {
  17. extern const style::SettingsSlider &defaultSettingsSlider;
  18. } // namespace st
  19. namespace Ui {
  20. class RippleAnimation;
  21. class DiscreteSlider : public RpWidget {
  22. public:
  23. DiscreteSlider(QWidget *parent, bool snapToLabel);
  24. ~DiscreteSlider();
  25. void addSection(const QString &label);
  26. void addSection(
  27. const TextWithEntities &label,
  28. Text::MarkedContext context = {});
  29. void setSections(const std::vector<QString> &labels);
  30. void setSections(
  31. const std::vector<TextWithEntities> &labels,
  32. Text::MarkedContext context = {});
  33. int activeSection() const {
  34. return _activeIndex;
  35. }
  36. void setActiveSection(int index);
  37. void setActiveSectionFast(int index);
  38. void finishAnimating();
  39. void setAdditionalContentWidthToSection(int index, int width);
  40. [[nodiscard]] rpl::producer<int> sectionActivated() const {
  41. return _sectionActivated.events();
  42. }
  43. protected:
  44. void timerEvent(QTimerEvent *e) override;
  45. void mousePressEvent(QMouseEvent *e) override;
  46. void mouseMoveEvent(QMouseEvent *e) override;
  47. void mouseReleaseEvent(QMouseEvent *e) override;
  48. int resizeGetHeight(int newWidth) override = 0;
  49. struct Section {
  50. Section(const QString &label, const style::TextStyle &st);
  51. Section(
  52. const TextWithEntities &label,
  53. const style::TextStyle &st,
  54. const Text::MarkedContext &context);
  55. Text::String label;
  56. std::unique_ptr<RippleAnimation> ripple;
  57. int left = 0;
  58. int width = 0;
  59. int contentWidth = 0;
  60. };
  61. struct Range {
  62. int left = 0;
  63. int width = 0;
  64. };
  65. [[nodiscard]] Range getFinalActiveRange() const;
  66. [[nodiscard]] Range getCurrentActiveRange() const;
  67. [[nodiscard]] int getSectionsCount() const {
  68. return _sections.size();
  69. }
  70. void enumerateSections(Fn<bool(Section&)> callback);
  71. void enumerateSections(Fn<bool(const Section&)> callback) const;
  72. virtual void startRipple(int sectionIndex) {
  73. }
  74. void stopAnimation() {
  75. _a_left.stop();
  76. _a_width.stop();
  77. }
  78. void refresh();
  79. void setSelectOnPress(bool selectOnPress);
  80. std::vector<Section> &sectionsRef();
  81. private:
  82. void activateCallback();
  83. virtual const style::TextStyle &getLabelStyle() const = 0;
  84. virtual int getAnimationDuration() const = 0;
  85. int getIndexFromPosition(QPoint pos);
  86. void setSelectedSection(int index);
  87. std::vector<Section> _sections;
  88. int _activeIndex = 0;
  89. bool _selectOnPress = true;
  90. bool _snapToLabel = false;
  91. rpl::event_stream<int> _sectionActivated;
  92. int _pressed = -1;
  93. int _selected = 0;
  94. Ui::Animations::Simple _a_left;
  95. Ui::Animations::Simple _a_width;
  96. int _timerId = -1;
  97. crl::time _callbackAfterMs = 0;
  98. };
  99. class SettingsSlider : public DiscreteSlider {
  100. public:
  101. SettingsSlider(
  102. QWidget *parent,
  103. const style::SettingsSlider &st = st::defaultSettingsSlider);
  104. [[nodiscard]] const style::SettingsSlider &st() const;
  105. [[nodiscard]] int centerOfSection(int section) const;
  106. virtual void fitWidthToSections();
  107. void setRippleTopRoundRadius(int radius);
  108. protected:
  109. void paintEvent(QPaintEvent *e) override;
  110. int resizeGetHeight(int newWidth) override;
  111. void startRipple(int sectionIndex) override;
  112. std::vector<float64> countSectionsWidths(int newWidth) const;
  113. private:
  114. const style::TextStyle &getLabelStyle() const override;
  115. int getAnimationDuration() const override;
  116. QImage prepareRippleMask(int sectionIndex, const Section &section);
  117. void resizeSections(int newWidth);
  118. const style::SettingsSlider &_st;
  119. std::optional<Ui::RoundRect> _bar;
  120. std::optional<Ui::RoundRect> _barActive;
  121. int _rippleTopRoundRadius = 0;
  122. };
  123. } // namespace Ui