diff --git a/Telegram/Resources/basic.style b/Telegram/Resources/basic.style index ab50abf448..77912a38d7 100644 --- a/Telegram/Resources/basic.style +++ b/Telegram/Resources/basic.style @@ -1734,6 +1734,17 @@ dropdownDef: dropdown { width: 0px; } +defaultInnerDropdownShadow: icon { + { "dropdown_shadow", windowShadowFg }, +}; +defaultInnerDropdown: InnerDropdown { + padding: margins(10px, 10px, 10px, 10px); + shadow: defaultInnerDropdownShadow; + shadowShift: 1px; + + duration: 150; +} + dropdownAttachDocument: iconedButton(btnAttachDocument) { iconPos: point(14px, 13px); downIconPos: point(14px, 14px); diff --git a/Telegram/Resources/basic_types.style b/Telegram/Resources/basic_types.style index 30d53110aa..c8e1fa0f40 100644 --- a/Telegram/Resources/basic_types.style +++ b/Telegram/Resources/basic_types.style @@ -246,6 +246,18 @@ dropdown { width: pixels; } +InnerDropdown { + padding: margins; + shadow: icon; + shadowShift: pixels; + + duration: int; + width: pixels; + + scrollMargin: margins; + scrollPadding: margins; +} + PopupMenu { skip: pixels; diff --git a/Telegram/Resources/icons/dropdown_shadow.png b/Telegram/Resources/icons/dropdown_shadow.png new file mode 100644 index 0000000000..7055a8b49d Binary files /dev/null and b/Telegram/Resources/icons/dropdown_shadow.png differ diff --git a/Telegram/Resources/icons/dropdown_shadow@2x.png b/Telegram/Resources/icons/dropdown_shadow@2x.png new file mode 100644 index 0000000000..1931c7b11f Binary files /dev/null and b/Telegram/Resources/icons/dropdown_shadow@2x.png differ diff --git a/Telegram/SourceFiles/codegen/style/generator.cpp b/Telegram/SourceFiles/codegen/style/generator.cpp index 801d5220f0..84aa5e57e1 100644 --- a/Telegram/SourceFiles/codegen/style/generator.cpp +++ b/Telegram/SourceFiles/codegen/style/generator.cpp @@ -646,6 +646,10 @@ bool Generator::collectUniqueValues() { int iconMaskIndex = 0; std::function collector = [this, &collector, &fontFamilyIndex, &iconMaskIndex](const Variable &variable) { auto value = variable.value; + if (!value.copyOf().isEmpty()) { + return true; + } + switch (value.type().tag) { case Tag::Invalid: case Tag::Int: diff --git a/Telegram/SourceFiles/codegen/style/module.cpp b/Telegram/SourceFiles/codegen/style/module.cpp index d11d4cdd08..ca49d8a23a 100644 --- a/Telegram/SourceFiles/codegen/style/module.cpp +++ b/Telegram/SourceFiles/codegen/style/module.cpp @@ -52,7 +52,7 @@ const Struct *Module::findStruct(const FullName &name) const { return result; } for (const auto &module : included_) { - if (auto result = findStructInModule(name, *module)) { + if (auto result = module->findStruct(name)) { return result; } } @@ -68,12 +68,14 @@ bool Module::addVariable(const Variable &value) { return true; } -const Variable *Module::findVariable(const FullName &name) const { +const Variable *Module::findVariable(const FullName &name, bool *outFromThisModule) const { if (auto result = findVariableInModule(name, *this)) { + if (outFromThisModule) *outFromThisModule = true; return result; } for (const auto &module : included_) { - if (auto result = findVariableInModule(name, *module)) { + if (auto result = module->findVariable(name)) { + if (outFromThisModule) *outFromThisModule = false; return result; } } diff --git a/Telegram/SourceFiles/codegen/style/module.h b/Telegram/SourceFiles/codegen/style/module.h index a890fd7dd5..f8a0432863 100644 --- a/Telegram/SourceFiles/codegen/style/module.h +++ b/Telegram/SourceFiles/codegen/style/module.h @@ -75,7 +75,7 @@ public: // Returns false if there is a variable with such name already. bool addVariable(const Variable &value); // Returns nullptr if there is no such variable in result_ or any of included modules. - const Variable *findVariable(const FullName &name) const; + const Variable *findVariable(const FullName &name, bool *outFromThisModule = nullptr) const; bool hasVariables() const { return !variables_.isEmpty(); } diff --git a/Telegram/SourceFiles/codegen/style/parsed_file.cpp b/Telegram/SourceFiles/codegen/style/parsed_file.cpp index 859a7a4285..a7acde2317 100644 --- a/Telegram/SourceFiles/codegen/style/parsed_file.cpp +++ b/Telegram/SourceFiles/codegen/style/parsed_file.cpp @@ -43,6 +43,7 @@ constexpr int kErrorUnknownField = 803; constexpr int kErrorIdentifierNotFound = 804; constexpr int kErrorAlreadyDefined = 805; constexpr int kErrorBadString = 806; +constexpr int kErrorIconDuplicate = 807; QString findInputFile(const Options &options) { for (const auto &dir : options.includePaths) { @@ -351,7 +352,8 @@ structure::Value ParsedFile::defaultConstructedStruct(const structure::FullName } void ParsedFile::applyStructParent(structure::Value &result, const structure::FullName &parentName) { - if (auto parent = module_->findVariable(parentName)) { + bool fromTheSameModule = false; + if (auto parent = module_->findVariable(parentName, &fromTheSameModule)) { if (parent->value.type() != result.type()) { logErrorTypeMismatch() << "parent '" << logFullName(parentName) << "' has type '" << logType(parent->value.type()) << "' while child value has type " << logType(result.type()); return; @@ -374,6 +376,22 @@ void ParsedFile::applyStructParent(structure::Value &result, const structure::Fu const auto &srcValue(srcField.variable.value); auto &dstValue(dstField.variable.value); logAssert(srcValue.type() == dstValue.type()) << "struct field type check failed"; + + // Optimization: don't let the style files to contain unnamed inherited + // icons from the other (included) style files, because they will + // duplicate the binary data across different style c++ source files. + // + // Example: + // a.style has "A: Struct { icon: icon { ..file.. } };" and + // b.style has "B: Struct(A) { .. };" with non-overriden icon field. + // Then both style_a.cpp and style_b.cpp will contain binary data of "file". + if (!fromTheSameModule + && srcValue.type().tag == structure::TypeTag::Icon + && !srcValue.Icon().parts.empty() + && srcValue.copyOf().isEmpty()) { + logError(kErrorIconDuplicate) << "an unnamed icon field '" << logFullName(srcField.variable.name) << "' is inherited from parent '" << logFullName(parentName) << "'"; + return; + } dstValue = srcValue; dstField.status = Status::Implicit; } diff --git a/Telegram/SourceFiles/history/history.style b/Telegram/SourceFiles/history/history.style index 1a5d33f1d7..9ab0bd79fd 100644 --- a/Telegram/SourceFiles/history/history.style +++ b/Telegram/SourceFiles/history/history.style @@ -29,3 +29,16 @@ historyToDownArrow: icon { { "history_down_arrow", #b9b9b9, point(14px, 19px) }, }; historyToDownPaddingTop: 10px; + +membersInnerScroll: flatScroll(solidScroll) { + deltat: 3px; + deltab: 3px; + width: 8px; + deltax: 3px; +} +membersInnerWidth: 310px; +membersInnerHeightMax: 360px; +membersInnerDropdown: InnerDropdown(defaultInnerDropdown) { + scrollMargin: margins(0px, 5px, 0px, 5px); + scrollPadding: margins(0px, 3px, 8px, 3px); +} diff --git a/Telegram/SourceFiles/historywidget.cpp b/Telegram/SourceFiles/historywidget.cpp index e2018e752a..cefc5bc07f 100644 --- a/Telegram/SourceFiles/historywidget.cpp +++ b/Telegram/SourceFiles/historywidget.cpp @@ -6027,9 +6027,12 @@ QRect HistoryWidget::getMembersShowAreaGeometry() const { void HistoryWidget::setMembersShowAreaActive(bool active) { if (active && _peer && (_peer->isChat() || _peer->isMegagroup())) { if (!_membersDropdown) { - _membersDropdown = new Ui::InnerDropdown(this, st::dropdownDef, st::solidScroll); + _membersDropdown = new Ui::InnerDropdown(this, st::membersInnerDropdown, st::membersInnerScroll); _membersDropdown->setOwnedWidget(new Profile::MembersWidget(_membersDropdown, _peer, Profile::MembersWidget::TitleVisibility::Hidden)); - _membersDropdown->setGeometry(0, 0, st::emojiPanWidth, st::emojiPanMaxHeight); + _membersDropdown->resize(st::membersInnerWidth, _membersDropdown->height()); + + _membersDropdown->setMaxHeight(countMembersDropdownHeightMax()); + _membersDropdown->moveToLeft(0, 0); connect(_membersDropdown, SIGNAL(hidden()), this, SLOT(onMembersDropdownHidden())); } _membersDropdown->otherEnter(); @@ -6721,6 +6724,9 @@ void HistoryWidget::resizeEvent(QResizeEvent *e) { _historyToEnd->moveToRight(st::historyToDownPosition.x(), _scroll.y() + _scroll.height() - _historyToEnd->height() - st::historyToDownPosition.y()); _emojiPan.setMaxHeight(height() - st::dropdownDef.padding.top() - st::dropdownDef.padding.bottom() - _attachEmoji.height()); + if (_membersDropdown) { + _membersDropdown->setMaxHeight(countMembersDropdownHeightMax()); + } switch (_attachDrag) { case DragStateFiles: @@ -7682,6 +7688,13 @@ void HistoryWidget::cancelReplyAfterMediaSend(bool lastKeyboardUsed) { } } +int HistoryWidget::countMembersDropdownHeightMax() const { + int result = height() - st::membersInnerDropdown.padding.top() - st::membersInnerDropdown.padding.bottom(); + result -= _attachEmoji.height(); + accumulate_min(result, st::membersInnerHeightMax); + return result; +} + void HistoryWidget::cancelEdit() { if (!_editMsgId) return; diff --git a/Telegram/SourceFiles/historywidget.h b/Telegram/SourceFiles/historywidget.h index e274de9d3a..f506787c44 100644 --- a/Telegram/SourceFiles/historywidget.h +++ b/Telegram/SourceFiles/historywidget.h @@ -867,6 +867,8 @@ private: void cancelReplyAfterMediaSend(bool lastKeyboardUsed); + int countMembersDropdownHeightMax() const; + MsgId _replyToId = 0; Text _replyToName; int _replyToNameVersion = 0; diff --git a/Telegram/SourceFiles/profile/profile_block_widget.cpp b/Telegram/SourceFiles/profile/profile_block_widget.cpp index f6d108fa79..93007eefc2 100644 --- a/Telegram/SourceFiles/profile/profile_block_widget.cpp +++ b/Telegram/SourceFiles/profile/profile_block_widget.cpp @@ -31,7 +31,7 @@ BlockWidget::BlockWidget(QWidget *parent, PeerData *peer, const QString &title) } int BlockWidget::contentTop() const { - return st::profileBlockMarginTop + (emptyTitle() ? 0 : st::profileBlockTitleHeight); + return emptyTitle() ? 0 : (st::profileBlockMarginTop + st::profileBlockTitleHeight); } void BlockWidget::paintEvent(QPaintEvent *e) { diff --git a/Telegram/SourceFiles/ui/boxshadow.cpp b/Telegram/SourceFiles/ui/boxshadow.cpp index 0ca3d787dd..9e52f62296 100644 --- a/Telegram/SourceFiles/ui/boxshadow.cpp +++ b/Telegram/SourceFiles/ui/boxshadow.cpp @@ -60,7 +60,7 @@ BoxShadow::BoxShadow(const style::sprite &topLeft) : _size(topLeft.pxWidth()), _ _corners.setDevicePixelRatio(cRetinaFactor()); _colors.reserve(_pixsize); uchar prev = 0; - for (int32 i = 0; i < _pixsize; ++i) { + for (int i = 0; i < _pixsize; ++i) { uchar a = (cornersImage.pixel(QPoint(i, _pixsize - 1)) >> 24); if (a < prev) break; @@ -112,3 +112,79 @@ style::margins BoxShadow::getDimensions(int32 shifty) const { int32 d = _colors.size() / cIntRetinaFactor(); return style::margins(d - shifty, d - 2 * shifty, d - shifty, d); } + +namespace Ui { + +RectShadow::RectShadow(const style::icon &topLeft) : _size(topLeft.width()), _pixsize(_size * cIntRetinaFactor()) { + if (!_size) return; + + QImage cornersImage(_pixsize * 2, _pixsize * 2, QImage::Format_ARGB32_Premultiplied); + cornersImage.setDevicePixelRatio(cRetinaFactor()); + { + Painter p(&cornersImage); + p.setCompositionMode(QPainter::CompositionMode_Source); + topLeft.paint(p, QPoint(0, 0), _size); + } + if (rtl()) cornersImage = cornersImage.mirrored(true, false); + { + QPainter p(&cornersImage); + p.setCompositionMode(QPainter::CompositionMode_Source); + QImage m = cornersImage.mirrored(); + m.setDevicePixelRatio(cRetinaFactor()); + p.drawImage(0, _size, m, 0, _pixsize, _pixsize, _pixsize); + } + { + QPainter p(&cornersImage); + p.setCompositionMode(QPainter::CompositionMode_Source); + QImage m = cornersImage.mirrored(true, false); + m.setDevicePixelRatio(cRetinaFactor()); + p.drawImage(_size, 0, m, _pixsize, 0, _pixsize, _pixsize * 2); + } + _corners = QPixmap::fromImage(cornersImage, Qt::ColorOnly); + _corners.setDevicePixelRatio(cRetinaFactor()); + + uchar prev = 0; + for (int i = 0; i < _pixsize; ++i) { + uchar a = (cornersImage.pixel(QPoint(i, _pixsize - 1)) >> 24); + if (a < prev) break; + + ++_thickness; + prev = a; + } + + _left = QPixmap::fromImage(cornersImage.copy(0, _pixsize - 1, _thickness, 1), Qt::ColorOnly); + _left.setDevicePixelRatio(cRetinaFactor()); + _top = QPixmap::fromImage(cornersImage.copy(_pixsize - 1, 0, 1, _thickness), Qt::ColorOnly); + _top.setDevicePixelRatio(cRetinaFactor()); + _right = QPixmap::fromImage(cornersImage.copy(_pixsize * 2 - _thickness, _pixsize, _thickness, 1), Qt::ColorOnly); + _right.setDevicePixelRatio(cRetinaFactor()); + _bottom = QPixmap::fromImage(cornersImage.copy(_pixsize, _pixsize * 2 - _thickness, 1, _thickness), Qt::ColorOnly); + _bottom.setDevicePixelRatio(cRetinaFactor()); +} + +void RectShadow::paint(Painter &p, const QRect &box, int shifty, Sides sides) { + if (!_size) return; + + int32 rshifty = shifty * cIntRetinaFactor(); + int32 count = _thickness, countsize = count / cIntRetinaFactor(), minus = _size - countsize + shifty; + bool left = (sides & Side::Left), top = (sides & Side::Top), right = (sides & Side::Right), bottom = (sides & Side::Bottom); + if (left && top) p.drawPixmap(box.left() - _size + minus, box.top() - _size + minus + shifty, _corners, 0, 0, _pixsize, _pixsize); + if (right && top) p.drawPixmap(box.left() + box.width() - minus, box.top() - _size + minus + shifty, _corners, _pixsize, 0, _pixsize, _pixsize); + if (right && bottom) p.drawPixmap(box.left() + box.width() - minus, box.top() + box.height() - minus + shifty, _corners, _pixsize, _pixsize, _pixsize, _pixsize); + if (left && bottom) p.drawPixmap(box.left() - _size + minus, box.top() + box.height() - minus + shifty, _corners, 0, _pixsize, _pixsize, _pixsize); + + bool wasSmooth = p.renderHints().testFlag(QPainter::SmoothPixmapTransform); + if (wasSmooth) p.setRenderHint(QPainter::SmoothPixmapTransform, false); + if (left) p.drawPixmap(box.left() - countsize + shifty, box.top() + (top ? minus : 0) + shifty, countsize - shifty, box.height() - (bottom ? minus : 0) - (top ? minus : 0), _left, 0, 0, count - rshifty, 1); + if (top) p.drawPixmap(box.left() + (left ? minus : 0), box.top() - countsize + 2 * shifty, box.width() - (right ? minus : 0) - (left ? minus : 0), countsize - 2 * shifty, _top, 0, 0, 1, count - 2 * rshifty); + if (right) p.drawPixmap(box.left() + box.width(), box.top() + (top ? minus : 0) + shifty, countsize - shifty, box.height() - (bottom ? minus : 0) - (top ? minus : 0), _right, rshifty, 0, count - rshifty, 1); + if (bottom) p.drawPixmap(box.left() + (left ? minus : 0), box.top() + box.height(), box.width() - (right ? minus : 0) - (left ? minus : 0), countsize, _bottom, 0, 0, 1, count); + if (wasSmooth) p.setRenderHint(QPainter::SmoothPixmapTransform); +} + +style::margins RectShadow::getDimensions(int32 shifty) const { + int d = _thickness / cIntRetinaFactor(); + return style::margins(d - shifty, d - 2 * shifty, d - shifty, d); +} + +} // namespace Ui diff --git a/Telegram/SourceFiles/ui/boxshadow.h b/Telegram/SourceFiles/ui/boxshadow.h index bd4bb77650..3eeb302926 100644 --- a/Telegram/SourceFiles/ui/boxshadow.h +++ b/Telegram/SourceFiles/ui/boxshadow.h @@ -42,3 +42,32 @@ private: QVector _colors; }; + +namespace Ui { + +class RectShadow { +public: + enum class Side { + Left = 0x01, + Top = 0x02, + Right = 0x04, + Bottom = 0x08, + }; + Q_DECLARE_FLAGS(Sides, Side); + Q_DECLARE_FRIEND_OPERATORS_FOR_FLAGS(Sides); + + RectShadow(const style::icon &topLeft); + + void paint(Painter &p, const QRect &box, int shifty, Sides sides = Side::Left | Side::Top | Side::Right | Side::Bottom); + style::margins getDimensions(int shifty) const; + +private: + + int _size, _pixsize; + int _thickness = 0; + QPixmap _corners, _left, _top, _right, _bottom; + +}; +Q_DECLARE_OPERATORS_FOR_FLAGS(RectShadow::Sides); + +} // namespace Ui \ No newline at end of file diff --git a/Telegram/SourceFiles/ui/inner_dropdown.cpp b/Telegram/SourceFiles/ui/inner_dropdown.cpp index dd1b492832..ad6ccf2384 100644 --- a/Telegram/SourceFiles/ui/inner_dropdown.cpp +++ b/Telegram/SourceFiles/ui/inner_dropdown.cpp @@ -27,7 +27,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org namespace Ui { -InnerDropdown::InnerDropdown(QWidget *parent, const style::dropdown &st, const style::flatScroll &scrollSt) : TWidget(parent) +InnerDropdown::InnerDropdown(QWidget *parent, const style::InnerDropdown &st, const style::flatScroll &scrollSt) : TWidget(parent) , _st(st) , _shadow(_st.shadow) , _scroll(this, scrollSt) { @@ -44,10 +44,35 @@ InnerDropdown::InnerDropdown(QWidget *parent, const style::dropdown &st, const s } void InnerDropdown::setOwnedWidget(ScrolledWidget *widget) { - _scroll->setOwnedWidget(widget); + auto container = new internal::Container(_scroll, widget, _st); + connect(container, SIGNAL(heightUpdated()), this, SLOT(onWidgetHeightUpdated())); + _scroll->setOwnedWidget(container); + container->resizeToWidth(_scroll->width()); + container->moveToLeft(0, 0); + container->show(); widget->show(); - widget->move(0, 0); - widget->resizeToWidth(_scroll->width() - st::scrollDef.width); +} + +void InnerDropdown::setMaxHeight(int newMaxHeight) { + _maxHeight = newMaxHeight; + updateHeight(); +} + +void InnerDropdown::onWidgetHeightUpdated() { + updateHeight(); +} + +void InnerDropdown::updateHeight() { + int newHeight = _st.padding.top() + _st.scrollMargin.top() + _st.scrollMargin.bottom() + _st.padding.bottom(); + if (auto widget = static_cast(_scroll->widget())) { + newHeight += widget->height(); + } + if (_maxHeight > 0) { + accumulate_min(newHeight, _maxHeight); + } + if (newHeight != height()) { + resize(width(), newHeight); + } } void InnerDropdown::onWindowActiveChanged() { @@ -57,9 +82,9 @@ void InnerDropdown::onWindowActiveChanged() { } void InnerDropdown::resizeEvent(QResizeEvent *e) { - _scroll->setGeometry(rect().marginsRemoved(_st.padding)); + _scroll->setGeometry(rect().marginsRemoved(_st.padding).marginsRemoved(_st.scrollMargin)); if (auto widget = static_cast(_scroll->widget())) { - widget->resizeToWidth(_scroll->width() - st::scrollDef.width); + widget->resizeToWidth(_scroll->width()); onScroll(); } } @@ -73,7 +98,7 @@ void InnerDropdown::onScroll() { } void InnerDropdown::paintEvent(QPaintEvent *e) { - QPainter p(this); + Painter p(this); if (!_cache.isNull()) { bool animating = _a_appearance.animating(getms()); @@ -182,4 +207,41 @@ bool InnerDropdown::eventFilter(QObject *obj, QEvent *e) { return false; } +namespace internal { + +Container::Container(QWidget *parent, ScrolledWidget *child, const style::InnerDropdown &st) : ScrolledWidget(parent), _st(st) { + child->setParent(this); + child->moveToLeft(_st.scrollPadding.left(), _st.scrollPadding.top()); + connect(child, SIGNAL(heightUpdated()), this, SLOT(onHeightUpdate())); +} + +void Container::setVisibleTopBottom(int visibleTop, int visibleBottom) { + if (auto child = static_cast(children().front())) { + child->setVisibleTopBottom(visibleTop - _st.scrollPadding.top(), visibleBottom - _st.scrollPadding.top()); + } +} + +void Container::onHeightUpdate() { + int newHeight = _st.scrollPadding.top() + _st.scrollPadding.bottom(); + if (auto child = static_cast(children().front())) { + newHeight += child->height(); + } + if (newHeight != height()) { + resize(width(), newHeight); + emit heightUpdated(); + } +} + +int Container::resizeGetHeight(int newWidth) { + int innerWidth = newWidth - _st.scrollPadding.left() - _st.scrollPadding.right(); + int result = _st.scrollPadding.top() + _st.scrollPadding.bottom(); + if (auto child = static_cast(children().front())) { + child->resizeToWidth(innerWidth); + child->moveToLeft(_st.scrollPadding.left(), _st.scrollPadding.top()); + result += child->height(); + } + return result; +} + +} // namespace internal } // namespace Ui diff --git a/Telegram/SourceFiles/ui/inner_dropdown.h b/Telegram/SourceFiles/ui/inner_dropdown.h index 827016002d..55974f78e9 100644 --- a/Telegram/SourceFiles/ui/inner_dropdown.h +++ b/Telegram/SourceFiles/ui/inner_dropdown.h @@ -20,6 +20,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org */ #pragma once +#include "ui/boxshadow.h" + class ScrollArea; namespace Ui { @@ -28,7 +30,7 @@ class InnerDropdown : public TWidget { Q_OBJECT public: - InnerDropdown(QWidget *parent, const style::dropdown &st = st::dropdownDef, const style::flatScroll &scrollSt = st::scrollDef); + InnerDropdown(QWidget *parent, const style::InnerDropdown &st = st::defaultInnerDropdown, const style::flatScroll &scrollSt = st::scrollDef); void setOwnedWidget(ScrolledWidget *widget); @@ -38,6 +40,8 @@ public: return rect().marginsRemoved(_st.padding).contains(QRect(mapFromGlobal(globalRect.topLeft()), globalRect.size())); } + void setMaxHeight(int newMaxHeight); + void otherEnter(); void otherLeave(); @@ -56,6 +60,7 @@ private slots: void onHideStart(); void onWindowActiveChanged(); void onScroll(); + void onWidgetHeightUpdated(); private: void repaintCallback(); @@ -65,7 +70,9 @@ private: void startAnimation(); - const style::dropdown &_st; + void updateHeight(); + + const style::InnerDropdown &_st; bool _hiding = false; @@ -74,9 +81,32 @@ private: QTimer _hideTimer; - BoxShadow _shadow; + RectShadow _shadow; ChildWidget _scroll; + int _maxHeight = 0; + }; +namespace internal { + +class Container : public ScrolledWidget { + Q_OBJECT + +public: + Container(QWidget *parent, ScrolledWidget *child, const style::InnerDropdown &st); + void setVisibleTopBottom(int visibleTop, int visibleBottom) override; + +private slots: + void onHeightUpdate(); + +protected: + int resizeGetHeight(int newWidth) override; + +private: + const style::InnerDropdown &_st; + +}; + +} // namespace internal } // namespace Ui diff --git a/Telegram/SourceFiles/ui/scrollarea.h b/Telegram/SourceFiles/ui/scrollarea.h index 43a0d4817d..524811308e 100644 --- a/Telegram/SourceFiles/ui/scrollarea.h +++ b/Telegram/SourceFiles/ui/scrollarea.h @@ -270,6 +270,8 @@ public: }; class ScrolledWidget : public TWidget { + Q_OBJECT + public: ScrolledWidget(QWidget *parent = nullptr) : TWidget(parent) { } @@ -289,4 +291,7 @@ protected: return height(); } +signals: + void heightUpdated(); + }; diff --git a/Telegram/Telegram.pro b/Telegram/Telegram.pro index 321ae0d44f..ad3dacc98c 100644 --- a/Telegram/Telegram.pro +++ b/Telegram/Telegram.pro @@ -204,6 +204,7 @@ SOURCES += \ ./SourceFiles/ui/flatlabel.cpp \ ./SourceFiles/ui/flattextarea.cpp \ ./SourceFiles/ui/images.cpp \ + ./SourceFiles/ui/inner_dropdown.cpp \ ./SourceFiles/ui/scrollarea.cpp \ ./SourceFiles/ui/twidget.cpp \ ./SourceFiles/window/main_window.cpp \ @@ -361,6 +362,7 @@ HEADERS += \ ./SourceFiles/ui/flatlabel.h \ ./SourceFiles/ui/flattextarea.h \ ./SourceFiles/ui/images.h \ + ./SourceFiles/ui/inner_dropdown.h \ ./SourceFiles/ui/scrollarea.h \ ./SourceFiles/ui/twidget.h \ ./SourceFiles/window/main_window.h \ diff --git a/Telegram/Telegram.xcodeproj/qt_preprocess.mak b/Telegram/Telegram.xcodeproj/qt_preprocess.mak index 5d7ef74901..0707e159e1 100644 --- a/Telegram/Telegram.xcodeproj/qt_preprocess.mak +++ b/Telegram/Telegram.xcodeproj/qt_preprocess.mak @@ -86,6 +86,7 @@ compilers: GeneratedFiles/qrc_telegram.cpp\ GeneratedFiles/Debug/moc_flattextarea.cpp\ GeneratedFiles/Debug/moc_history.cpp\ GeneratedFiles/Debug/moc_historywidget.cpp\ + GeneratedFiles/Debug/moc_inner_dropdown.cpp\ GeneratedFiles/Debug/moc_introcode.cpp\ GeneratedFiles/Debug/moc_introphone.cpp\ GeneratedFiles/Debug/moc_intropwdcheck.cpp\ @@ -223,6 +224,7 @@ compiler_moc_header_make_all: GeneratedFiles/Debug/moc_aboutbox.cpp\ GeneratedFiles/Debug/moc_flattextarea.cpp\ GeneratedFiles/Debug/moc_history.cpp\ GeneratedFiles/Debug/moc_historywidget.cpp\ + GeneratedFiles/Debug/moc_inner_dropdown.cpp\ GeneratedFiles/Debug/moc_introcode.cpp\ GeneratedFiles/Debug/moc_introphone.cpp\ GeneratedFiles/Debug/moc_intropwdcheck.cpp\ @@ -303,6 +305,7 @@ compiler_moc_header_clean: GeneratedFiles/Debug/moc_flattextarea.cpp\ GeneratedFiles/Debug/moc_history.cpp\ GeneratedFiles/Debug/moc_historywidget.cpp\ + GeneratedFiles/Debug/moc_inner_dropdown.cpp\ GeneratedFiles/Debug/moc_introcode.cpp\ GeneratedFiles/Debug/moc_introphone.cpp\ GeneratedFiles/Debug/moc_intropwdcheck.cpp\ @@ -456,6 +459,9 @@ GeneratedFiles/Debug/moc_history.cpp: SourceFiles/history.h GeneratedFiles/Debug/moc_historywidget.cpp: SourceFiles/historywidget.h $(MOC_FILE) SourceFiles/historywidget.h -o GeneratedFiles/Debug/moc_historywidget.cpp +GeneratedFiles/Debug/moc_inner_dropdown.cpp: SourceFiles/ui/inner_dropdown.h + $(MOC_FILE) SourceFiles/ui/inner_dropdown.h -o GeneratedFiles/Debug/moc_inner_dropdown.cpp + GeneratedFiles/Debug/moc_introcode.cpp: SourceFiles/intro/introcode.h $(MOC_FILE) SourceFiles/intro/introcode.h -o GeneratedFiles/Debug/moc_introcode.cpp