menu_multiline_action.cpp 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  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. #include "ui/widgets/menu/menu_multiline_action.h"
  8. #include "ui/widgets/labels.h"
  9. #include "ui/qt_object_factory.h"
  10. namespace Ui::Menu {
  11. MultilineAction::MultilineAction(
  12. not_null<Ui::RpWidget*> parent,
  13. const style::Menu &st,
  14. const style::FlatLabel &stLabel,
  15. QPoint labelPosition,
  16. TextWithEntities &&about,
  17. const style::icon *icon,
  18. const style::icon *iconOver)
  19. : ItemBase(parent, st)
  20. , _st(st)
  21. , _icon(icon)
  22. , _iconOver(iconOver ? iconOver : icon)
  23. , _labelPosition(labelPosition)
  24. , _text(base::make_unique_q<Ui::FlatLabel>(
  25. this,
  26. rpl::single(std::move(about)),
  27. stLabel))
  28. , _dummyAction(Ui::CreateChild<QAction>(parent.get())) {
  29. ItemBase::enableMouseSelecting();
  30. _text->setAttribute(Qt::WA_TransparentForMouseEvents);
  31. updateMinWidth();
  32. parent->widthValue() | rpl::start_with_next([=](int width) {
  33. const auto top = _labelPosition.y();
  34. const auto skip = _labelPosition.x();
  35. const auto rightSkip = _icon ? _st.itemIconPosition.x() : skip;
  36. _text->resizeToWidth(width - skip - rightSkip);
  37. _text->moveToLeft(skip, top);
  38. resize(width, contentHeight());
  39. }, lifetime());
  40. }
  41. not_null<QAction*> MultilineAction::action() const {
  42. return _dummyAction;
  43. }
  44. bool MultilineAction::isEnabled() const {
  45. return true;
  46. }
  47. int MultilineAction::contentHeight() const {
  48. const auto skip = _labelPosition.y();
  49. return skip
  50. + std::max(_text->height(), _icon ? _icon->height() : 0)
  51. + skip;
  52. }
  53. void MultilineAction::paintEvent(QPaintEvent *e) {
  54. auto p = QPainter(this);
  55. const auto selected = isSelected();
  56. p.fillRect(rect(), selected ? _st.itemBgOver : _st.itemBg);
  57. RippleButton::paintRipple(p, 0, 0);
  58. if (const auto icon = (selected ? _iconOver : _icon)) {
  59. icon->paint(p, _st.itemIconPosition, width());
  60. }
  61. }
  62. void MultilineAction::updateMinWidth() {
  63. const auto skip = _labelPosition.x();
  64. const auto rightSkip = _icon ? _st.itemIconPosition.x() : skip;
  65. auto min = _text->textMaxWidth() / 4;
  66. auto max = _icon ? _st.widthMax : (_text->textMaxWidth() - skip);
  67. _text->resizeToWidth(max);
  68. const auto height = _icon
  69. ? ((_st.itemIconPosition.y() * 2) + _icon->height())
  70. : _text->height();
  71. _text->resizeToWidth(min);
  72. const auto heightMax = _text->height();
  73. if (heightMax > height) {
  74. while (min + 1 < max) {
  75. const auto middle = (max + min) / 2;
  76. _text->resizeToWidth(middle);
  77. if (_text->height() > height) {
  78. min = middle;
  79. } else {
  80. max = middle;
  81. }
  82. }
  83. }
  84. ItemBase::setMinWidth(skip + rightSkip + max);
  85. }
  86. } // namespace Ui::Menu