/* This file is part of Telegram Desktop, the official desktop application for the Telegram messaging service. For license and copyright information please follow this link: https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "boxes/peer_list_widgets.h" #include "ui/painter.h" #include "ui/widgets/buttons.h" #include "ui/wrap/vertical_layout.h" #include "styles/style_boxes.h" namespace { using State = std::unique_ptr; } // namespace PeerListWidgets::PeerListWidgets( not_null parent, not_null controller) : Ui::RpWidget(parent) , _controller(controller) , _st(controller->computeListSt()) { _content = base::make_unique_q(this); parent->sizeValue() | rpl::start_with_next([this](const QSize &size) { _content->resizeToWidth(size.width()); resize(size.width(), _content->height()); }, lifetime()); } crl::time PeerListWidgets::paintRow( Painter &p, crl::time now, bool selected, not_null row) { const auto &st = row->computeSt(_st.item); row->lazyInitialize(st); const auto outerWidth = _content->width(); const auto w = outerWidth; auto refreshStatusAt = row->refreshStatusTime(); if (refreshStatusAt > 0 && now >= refreshStatusAt) { row->refreshStatus(); refreshStatusAt = row->refreshStatusTime(); } const auto refreshStatusIn = (refreshStatusAt > 0) ? std::max(refreshStatusAt - now, crl::time(1)) : 0; row->paintUserpic( p, st, st.photoPosition.x(), st.photoPosition.y(), outerWidth); p.setPen(st::contactsNameFg); const auto skipRight = st.photoPosition.x(); const auto rightActionSize = row->rightActionSize(); const auto rightActionMargins = rightActionSize.isEmpty() ? QMargins() : row->rightActionMargins(); const auto &name = row->name(); const auto namePosition = st.namePosition; const auto namex = namePosition.x(); const auto namey = namePosition.y(); auto namew = outerWidth - namex - skipRight; if (!rightActionSize.isEmpty() && (namey < rightActionMargins.top() + rightActionSize.height()) && (namey + st.nameStyle.font->height > rightActionMargins.top())) { namew -= rightActionMargins.left() + rightActionSize.width() + rightActionMargins.right() - skipRight; } const auto statusx = st.statusPosition.x(); const auto statusy = st.statusPosition.y(); auto statusw = outerWidth - statusx - skipRight; if (!rightActionSize.isEmpty() && (statusy < rightActionMargins.top() + rightActionSize.height()) && (statusy + st::contactsStatusFont->height > rightActionMargins.top())) { statusw -= rightActionMargins.left() + rightActionSize.width() + rightActionMargins.right() - skipRight; } namew -= row->paintNameIconGetWidth( p, [=] { updateRow(row); }, now, namex, namey, name.maxWidth(), namew, w, selected); auto nameCheckedRatio = row->disabled() ? 0. : row->checkedRatio(); p.setPen(anim::pen(st.nameFg, st.nameFgChecked, nameCheckedRatio)); name.drawLeftElided(p, namex, namey, namew, w); p.setFont(st::contactsStatusFont); row->paintStatusText(p, st, statusx, statusy, statusw, w, selected); row->elementsPaint(p, outerWidth, selected, 0); return refreshStatusIn; } void PeerListWidgets::appendRow(std::unique_ptr row) { Expects(row != nullptr); if (_rowsById.find(row->id()) == _rowsById.cend()) { const auto raw = row.get(); const auto &st = raw->computeSt(_st.item); raw->setAbsoluteIndex(_rows.size()); _rows.push_back(std::move(row)); const auto widget = _content->add( object_ptr::fromRaw( Ui::CreateSimpleSettingsButton( _content.get(), st.button.ripple, st.button.textBgOver))); widget->resize(widget->width(), st.height); widget->paintRequest() | rpl::start_with_next([=, this] { auto p = Painter(widget); const auto selected = widget->isOver() || widget->isDown(); paintRow(p, crl::now(), selected, raw); }, widget->lifetime()); widget->setClickedCallback([this, raw] { _controller->rowClicked(raw); }); } } PeerListRow *PeerListWidgets::findRow(PeerListRowId id) { const auto it = _rowsById.find(id); return (it == _rowsById.cend()) ? nullptr : it->second.get(); } void PeerListWidgets::updateRow(not_null row) { const auto it = ranges::find_if( _rows, [row](const auto &r) { return r.get() == row; }); if (it != _rows.end()) { const auto index = std::distance(_rows.begin(), it); if (const auto widget = _content->widgetAt(index)) { widget->update(); } } } int PeerListWidgets::fullRowsCount() { return _rows.size(); } [[nodiscard]] not_null PeerListWidgets::rowAt(int index) { Expects(index >= 0 && index < _rows.size()); return _rows[index].get(); } void PeerListWidgets::refreshRows() { _content->resizeToWidth(width()); resize(width(), _content->height()); } void PeerListWidgetsDelegate::setContent(PeerListWidgets *content) { _content = content; } void PeerListWidgetsDelegate::setUiShow( std::shared_ptr uiShow) { _uiShow = std::move(uiShow); } void PeerListWidgetsDelegate::peerListSetHideEmpty(bool hide) { Unexpected("...PeerListWidgetsDelegate::peerListSetHideEmpty"); } void PeerListWidgetsDelegate::peerListAppendRow( std::unique_ptr row) { _content->appendRow(std::move(row)); } void PeerListWidgetsDelegate::peerListAppendSearchRow( std::unique_ptr row) { Unexpected("...PeerListWidgetsDelegate::peerListAppendSearchRow"); } void PeerListWidgetsDelegate::peerListAppendFoundRow( not_null row) { Unexpected("...PeerListWidgetsDelegate::peerListAppendFoundRow"); } void PeerListWidgetsDelegate::peerListPrependRow( std::unique_ptr row) { Unexpected("...PeerListWidgetsDelegate::peerListPrependRow"); } void PeerListWidgetsDelegate::peerListPrependRowFromSearchResult( not_null row) { Unexpected( "...PeerListWidgetsDelegate::peerListPrependRowFromSearchResult"); } PeerListRow* PeerListWidgetsDelegate::peerListFindRow(PeerListRowId id) { return _content->findRow(id); } auto PeerListWidgetsDelegate::peerListLastRowMousePosition() -> std::optional { Unexpected("...PeerListWidgetsDelegate::peerListLastRowMousePosition"); } void PeerListWidgetsDelegate::peerListUpdateRow(not_null row) { _content->updateRow(row); } void PeerListWidgetsDelegate::peerListRemoveRow(not_null row) { Unexpected("...PeerListWidgetsDelegate::peerListRemoveRow"); } void PeerListWidgetsDelegate::peerListConvertRowToSearchResult( not_null row) { Unexpected( "...PeerListWidgetsDelegate::peerListConvertRowToSearchResult"); } void PeerListWidgetsDelegate::peerListSetRowChecked( not_null row, bool checked) { Unexpected("...PeerListWidgetsDelegate::peerListSetRowChecked"); } void PeerListWidgetsDelegate::peerListSetRowHidden( not_null row, bool hidden) { Unexpected("...PeerListWidgetsDelegate::peerListSetRowHidden"); } void PeerListWidgetsDelegate::peerListSetForeignRowChecked( not_null row, bool checked, anim::type animated) { } int PeerListWidgetsDelegate::peerListFullRowsCount() { return _content->fullRowsCount(); } not_null PeerListWidgetsDelegate::peerListRowAt(int index) { return _content->rowAt(index); } int PeerListWidgetsDelegate::peerListSearchRowsCount() { Unexpected("...PeerListWidgetsDelegate::peerListSearchRowsCount"); } not_null PeerListWidgetsDelegate::peerListSearchRowAt(int) { Unexpected("...PeerListWidgetsDelegate::peerListSearchRowAt"); } void PeerListWidgetsDelegate::peerListRefreshRows() { _content->refreshRows(); } void PeerListWidgetsDelegate::peerListSetDescription( object_ptr) { Unexpected("...PeerListWidgetsDelegate::peerListSetDescription"); } void PeerListWidgetsDelegate::peerListSetSearchNoResults( object_ptr) { Unexpected("...PeerListWidgetsDelegate::peerListSetSearchNoResults"); } void PeerListWidgetsDelegate::peerListSetAboveWidget( object_ptr) { Unexpected("...PeerListWidgetsDelegate::peerListSetAboveWidget"); } void PeerListWidgetsDelegate::peerListSetAboveSearchWidget( object_ptr) { Unexpected("...PeerListWidgetsDelegate::peerListSetAboveSearchWidget"); } void PeerListWidgetsDelegate::peerListSetBelowWidget( object_ptr) { Unexpected("...PeerListWidgetsDelegate::peerListSetBelowWidget"); } void PeerListWidgetsDelegate::peerListSetSearchMode(PeerListSearchMode mode) { Unexpected("...PeerListWidgetsDelegate::peerListSetSearchMode"); } void PeerListWidgetsDelegate::peerListMouseLeftGeometry() { Unexpected("...PeerListWidgetsDelegate::peerListMouseLeftGeometry"); } void PeerListWidgetsDelegate::peerListSortRows( Fn) { Unexpected("...PeerListWidgetsDelegate::peerListSortRows"); } int PeerListWidgetsDelegate::peerListPartitionRows( Fn border) { Unexpected("...PeerListWidgetsDelegate::peerListPartitionRows"); } State PeerListWidgetsDelegate::peerListSaveState() const { Unexpected("...PeerListWidgetsDelegate::peerListSaveState"); return nullptr; } void PeerListWidgetsDelegate::peerListRestoreState( std::unique_ptr state) { Unexpected("...PeerListWidgetsDelegate::peerListRestoreState"); } void PeerListWidgetsDelegate::peerListShowRowMenu( not_null row, bool highlightRow, Fn)> destroyed) { } void PeerListWidgetsDelegate::peerListSelectSkip(int direction) { // _content->selectSkip(direction); } void PeerListWidgetsDelegate::peerListPressLeftToContextMenu(bool shown) { Unexpected("...PeerListWidgetsDelegate::peerListPressLeftToContextMenu"); } bool PeerListWidgetsDelegate::peerListTrackRowPressFromGlobal(QPoint) { return false; } std::shared_ptr PeerListWidgetsDelegate::peerListUiShow() { Expects(_uiShow != nullptr); return _uiShow; } void PeerListWidgetsDelegate::peerListAddSelectedPeerInBunch( not_null peer) { Unexpected("...PeerListWidgetsDelegate::peerListAddSelectedPeerInBunch"); } void PeerListWidgetsDelegate::peerListAddSelectedRowInBunch( not_null row) { Unexpected("...PeerListWidgetsDelegate::peerListAddSelectedRowInBunch"); } void PeerListWidgetsDelegate::peerListFinishSelectedRowsBunch() { Unexpected("...PeerListWidgetsDelegate::peerListFinishSelectedRowsBunch"); } void PeerListWidgetsDelegate::peerListSetTitle(rpl::producer title) { Unexpected("...PeerListWidgetsDelegate::peerListSetTitle"); } void PeerListWidgetsDelegate::peerListSetAdditionalTitle( rpl::producer title) { Unexpected("...PeerListWidgetsDelegate::peerListSetAdditionalTitle"); } bool PeerListWidgetsDelegate::peerListIsRowChecked( not_null row) { Unexpected("...PeerListWidgetsDelegate::peerListIsRowChecked"); return false; } void PeerListWidgetsDelegate::peerListScrollToTop() { Unexpected("...PeerListWidgetsDelegate::peerListScrollToTop"); } int PeerListWidgetsDelegate::peerListSelectedRowsCount() { Unexpected("...PeerListWidgetsDelegate::peerListSelectedRowsCount"); return 0; }