generic_box.cpp 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  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/layers/generic_box.h"
  8. #include "ui/wrap/vertical_layout.h"
  9. #include "ui/wrap/padding_wrap.h"
  10. #include "ui/wrap/wrap.h"
  11. #include "styles/style_layers.h"
  12. namespace Ui {
  13. void GenericBox::prepare() {
  14. _init(this);
  15. const auto currentWidth = width();
  16. const auto pinnedToTop = _pinnedToTopContent.data();
  17. const auto pinnedToBottom = _pinnedToBottomContent.data();
  18. if (pinnedToTop) {
  19. pinnedToTop->resizeToWidth(currentWidth);
  20. }
  21. if (pinnedToBottom) {
  22. pinnedToBottom->resizeToWidth(currentWidth);
  23. }
  24. auto wrap = object_ptr<Ui::OverrideMargins>(this, std::move(_owned));
  25. wrap->resizeToWidth(currentWidth);
  26. rpl::combine(
  27. pinnedToTop ? pinnedToTop->heightValue() : rpl::single(0),
  28. wrap->heightValue(),
  29. pinnedToBottom ? pinnedToBottom->heightValue() : rpl::single(0)
  30. ) | rpl::start_with_next([=](int top, int height, int bottom) {
  31. Expects(_minHeight >= 0);
  32. Expects(!_maxHeight || _minHeight <= _maxHeight);
  33. setInnerTopSkip(top);
  34. setInnerBottomSkip(bottom);
  35. const auto desired = top + height + bottom;
  36. setDimensions(
  37. currentWidth,
  38. std::clamp(
  39. desired,
  40. _minHeight,
  41. _maxHeight ? _maxHeight : std::max(_minHeight, desired)),
  42. true);
  43. }, wrap->lifetime());
  44. setInnerWidget(
  45. std::move(wrap),
  46. _scrollSt ? *_scrollSt : st::boxScroll,
  47. pinnedToTop ? pinnedToTop->height() : 0,
  48. pinnedToBottom ? pinnedToBottom->height() : 0);
  49. if (pinnedToBottom) {
  50. rpl::combine(
  51. heightValue(),
  52. pinnedToBottom->heightValue()
  53. ) | rpl::start_with_next([=](int outer, int height) {
  54. pinnedToBottom->move(0, outer - height);
  55. }, pinnedToBottom->lifetime());
  56. }
  57. if (const auto onstack = _initScroll) {
  58. onstack();
  59. }
  60. }
  61. void GenericBox::addSkip(int height) {
  62. addRow(object_ptr<Ui::FixedHeightWidget>(this, height));
  63. }
  64. void GenericBox::setInnerFocus() {
  65. if (_focus) {
  66. _focus();
  67. } else {
  68. BoxContent::setInnerFocus();
  69. }
  70. }
  71. void GenericBox::showFinished() {
  72. const auto guard = QPointer(this);
  73. if (const auto onstack = _showFinished) {
  74. onstack();
  75. if (!guard) {
  76. return;
  77. }
  78. }
  79. _showFinishes.fire({});
  80. }
  81. not_null<Ui::RpWidget*> GenericBox::doSetPinnedToTopContent(
  82. object_ptr<Ui::RpWidget> content) {
  83. _pinnedToTopContent = std::move(content);
  84. return _pinnedToTopContent.data();
  85. }
  86. not_null<Ui::RpWidget*> GenericBox::doSetPinnedToBottomContent(
  87. object_ptr<Ui::RpWidget> content) {
  88. _pinnedToBottomContent = std::move(content);
  89. return _pinnedToBottomContent.data();
  90. }
  91. int GenericBox::rowsCount() const {
  92. return _content->count();
  93. }
  94. int GenericBox::width() const {
  95. return _width ? _width : st::boxWidth;
  96. }
  97. not_null<Ui::VerticalLayout*> GenericBox::verticalLayout() {
  98. return _content;
  99. }
  100. rpl::producer<> BoxShowFinishes(not_null<GenericBox*> box) {
  101. const auto singleShot = box->lifetime().make_state<rpl::lifetime>();
  102. const auto showFinishes = singleShot->make_state<rpl::event_stream<>>();
  103. box->setShowFinishedCallback([=] {
  104. showFinishes->fire({});
  105. singleShot->destroy();
  106. box->setShowFinishedCallback(nullptr);
  107. });
  108. return showFinishes->events();
  109. }
  110. } // namespace Ui