QSize HistoryInvoice::countOptimalSize() { auto lineHeight = unitedLineHeight(); if (_attach) { if (_status.hasSkipBlock()) { _status.removeSkipBlock(); } } else { _status.updateSkipBlock( _parent->skipBlockWidth(), _parent->skipBlockHeight()); } // init dimensions auto l = st::msgPadding.left(), r = st::msgPadding.right(); auto skipBlockWidth = _parent->skipBlockWidth(); auto maxWidth = skipBlockWidth; auto minHeight = 0; auto titleMinHeight = _title.isEmpty() ? 0 : lineHeight; // enable any count of lines in game description / message auto descMaxLines = 4096; auto descriptionMinHeight = _description.isEmpty() ? 0 : qMin(_description.minHeight(), descMaxLines * lineHeight); if (!_title.isEmpty()) { accumulate_max(maxWidth, _title.maxWidth()); minHeight += titleMinHeight; } if (!_description.isEmpty()) { accumulate_max(maxWidth, _description.maxWidth()); minHeight += descriptionMinHeight; } if (_attach) { auto attachAtTop = _title.isEmpty() && _description.isEmpty(); if (!attachAtTop) minHeight += st::mediaInBubbleSkip; _attach->initDimensions(); auto bubble = _attach->bubbleMargins(); auto maxMediaWidth = _attach->maxWidth() - bubble.left() - bubble.right(); if (isBubbleBottom() && _attach->customInfoLayout()) { maxMediaWidth += skipBlockWidth; } accumulate_max(maxWidth, maxMediaWidth); minHeight += _attach->minHeight() - bubble.top() - bubble.bottom(); } else { accumulate_max(maxWidth, _status.maxWidth()); minHeight += st::mediaInBubbleSkip + _status.minHeight(); } auto padding = inBubblePadding(); maxWidth += padding.left() + padding.right(); minHeight += padding.top() + padding.bottom(); return { maxWidth, minHeight }; }
void MessagesSliceBuilder::mergeSliceData( std::optional<int> count, const base::flat_set<MessagePosition> &messageIds, std::optional<int> skippedBefore, std::optional<int> skippedAfter) { if (messageIds.empty()) { if (count && _fullCount != count) { _fullCount = count; if (*_fullCount <= _ids.size()) { _fullCount = _ids.size(); _skippedBefore = _skippedAfter = 0; } } fillSkippedAndSliceToLimits(); return; } if (count) { _fullCount = count; } const auto impossible = MessagePosition(-1, FullMsgId()); auto wasMinId = _ids.empty() ? impossible : _ids.front(); auto wasMaxId = _ids.empty() ? impossible : _ids.back(); _ids.merge(messageIds.begin(), messageIds.end()); auto adjustSkippedBefore = [&](MessagePosition oldId, int oldSkippedBefore) { auto it = _ids.find(oldId); Assert(it != _ids.end()); _skippedBefore = oldSkippedBefore - (it - _ids.begin()); accumulate_max(*_skippedBefore, 0); }; if (skippedBefore) { adjustSkippedBefore(messageIds.front(), *skippedBefore); } else if (wasMinId != impossible && _skippedBefore) { adjustSkippedBefore(wasMinId, *_skippedBefore); } else { _skippedBefore = std::nullopt; } auto adjustSkippedAfter = [&](MessagePosition oldId, int oldSkippedAfter) { auto it = _ids.find(oldId); Assert(it != _ids.end()); _skippedAfter = oldSkippedAfter - (_ids.end() - it - 1); accumulate_max(*_skippedAfter, 0); }; if (skippedAfter) { adjustSkippedAfter(messageIds.back(), *skippedAfter); } else if (wasMaxId != impossible && _skippedAfter) { adjustSkippedAfter(wasMaxId, *_skippedAfter); } else { _skippedAfter = std::nullopt; } fillSkippedAndSliceToLimits(); }
RoundButton::Numbers::Numbers(const style::RoundButton &st, base::lambda<void()> &&animationCallback) : _st(st) , _animationCallback(std_::move(animationCallback)) { for (auto ch = '0'; ch != '9'; ++ch) { accumulate_max(_digitWidth, _st.font->m.width(ch)); } }
QSize HistoryGroupedMedia::countOptimalSize() { if (_caption.hasSkipBlock()) { _caption.updateSkipBlock( _parent->skipBlockWidth(), _parent->skipBlockHeight()); } std::vector<QSize> sizes; sizes.reserve(_parts.size()); for (const auto &part : _parts) { const auto &media = part.content; media->initDimensions(); sizes.push_back(media->sizeForGrouping()); } const auto layout = Ui::LayoutMediaGroup( sizes, st::historyGroupWidthMax, st::historyGroupWidthMin, st::historyGroupSkip); Assert(layout.size() == _parts.size()); auto maxWidth = 0; auto minHeight = 0; for (auto i = 0, count = int(layout.size()); i != count; ++i) { const auto &item = layout[i]; accumulate_max(maxWidth, item.geometry.x() + item.geometry.width()); accumulate_max(minHeight, item.geometry.y() + item.geometry.height()); _parts[i].initialGeometry = item.geometry; _parts[i].sides = item.sides; } if (!_caption.isEmpty()) { auto captionw = maxWidth - st::msgPadding.left() - st::msgPadding.right(); minHeight += st::mediaCaptionSkip + _caption.countHeight(captionw); if (isBubbleBottom()) { minHeight += st::msgPadding.bottom(); } } return { maxWidth, minHeight }; }
QRect MultiSelect::Inner::Item::paintArea(int outerWidth) const { if (_copies.empty()) { return rect(); } auto yMin = 0, yMax = 0; for_const (auto ©, _copies) { accumulate_max(yMax, copy.y); if (yMin) { accumulate_min(yMin, copy.y); } else { yMin = copy.y; } }
QSize HistoryGroupedMedia::countCurrentSize(int newWidth) { accumulate_min(newWidth, maxWidth()); auto newHeight = 0; if (newWidth < st::historyGroupWidthMin) { return { newWidth, newHeight }; } const auto initialSpacing = st::historyGroupSkip; const auto factor = newWidth / float64(maxWidth()); const auto scale = [&](int value) { return int(std::round(value * factor)); }; const auto spacing = scale(initialSpacing); for (auto &part : _parts) { const auto sides = part.sides; const auto initialGeometry = part.initialGeometry; const auto needRightSkip = !(sides & RectPart::Right); const auto needBottomSkip = !(sides & RectPart::Bottom); const auto initialLeft = initialGeometry.x(); const auto initialTop = initialGeometry.y(); const auto initialRight = initialLeft + initialGeometry.width() + (needRightSkip ? initialSpacing : 0); const auto initialBottom = initialTop + initialGeometry.height() + (needBottomSkip ? initialSpacing : 0); const auto left = scale(initialLeft); const auto top = scale(initialTop); const auto width = scale(initialRight) - left - (needRightSkip ? spacing : 0); const auto height = scale(initialBottom) - top - (needBottomSkip ? spacing : 0); part.geometry = QRect(left, top, width, height); accumulate_max(newHeight, top + height); } if (!_caption.isEmpty()) { const auto captionw = newWidth - st::msgPadding.left() - st::msgPadding.right(); newHeight += st::mediaCaptionSkip + _caption.countHeight(captionw); if (isBubbleBottom()) { newHeight += st::msgPadding.bottom(); } } return { newWidth, newHeight }; }
RippleAnimation::Ripple::Ripple(const style::RippleAnimation &st, QPoint origin, int startRadius, const QPixmap &mask, Fn<void()> update) : _st(st) , _update(update) , _origin(origin) , _radiusFrom(startRadius) , _frame(mask.size(), QImage::Format_ARGB32_Premultiplied) { _frame.setDevicePixelRatio(mask.devicePixelRatio()); QPoint points[] = { { 0, 0 }, { _frame.width() / cIntRetinaFactor(), 0 }, { _frame.width() / cIntRetinaFactor(), _frame.height() / cIntRetinaFactor() }, { 0, _frame.height() / cIntRetinaFactor() }, }; for (auto point : points) { accumulate_max(_radiusTo, style::point::dotProduct(_origin - point, _origin - point)); } _radiusTo = qRound(sqrt(_radiusTo)); _show.start(_update, 0., 1., _st.showDuration, anim::easeOutQuint); }
int documentMaxStatusWidth(DocumentData *document) { auto result = st::normalFont->width(formatDownloadText(document->size, document->size)); const auto duration = document->getDuration(); if (const auto song = document->song()) { accumulate_max(result, st::normalFont->width(formatPlayedText(duration, duration))); accumulate_max(result, st::normalFont->width(formatDurationAndSizeText(duration, document->size))); } else if (const auto voice = document->voice()) { accumulate_max(result, st::normalFont->width(formatPlayedText(duration, duration))); accumulate_max(result, st::normalFont->width(formatDurationAndSizeText(duration, document->size))); } else if (document->isVideoFile()) { accumulate_max(result, st::normalFont->width(formatDurationAndSizeText(duration, document->size))); } else { accumulate_max(result, st::normalFont->width(formatSizeText(document->size))); } return result; }
void paintUnreadCount(Painter &p, const QString &text, int x, int y, const UnreadBadgeStyle &st, int *outUnreadWidth) { int unreadWidth = st.font->width(text); int unreadRectWidth = unreadWidth + 2 * st.padding; int unreadRectHeight = st.size; accumulate_max(unreadRectWidth, unreadRectHeight); int unreadRectLeft = x; if ((st.align & Qt::AlignHorizontal_Mask) & style::al_center) { unreadRectLeft = (x - unreadRectWidth) / 2; } else if ((st.align & Qt::AlignHorizontal_Mask) & style::al_right) { unreadRectLeft = x - unreadRectWidth; } int unreadRectTop = y; if (outUnreadWidth) { *outUnreadWidth = unreadRectWidth; } paintUnreadBadge(p, QRect(unreadRectLeft, unreadRectTop, unreadRectWidth, unreadRectHeight), st); auto textTop = st.textTop ? st.textTop : (unreadRectHeight - st.font->height) / 2; p.setFont(st.font); p.setPen(st.active ? st::dialogsUnreadFgActive : (st.selected ? st::dialogsUnreadFgOver : st::dialogsUnreadFg)); p.drawText(unreadRectLeft + (unreadRectWidth - unreadWidth) / 2, unreadRectTop + textTop + st.font->ascent, text); }
SearchResult ParseSearchResult( not_null<PeerData*> peer, Storage::SharedMediaType type, MsgId messageId, SparseIdsLoadDirection direction, const MTPmessages_Messages &data) { auto result = SearchResult(); result.noSkipRange = MsgRange{ messageId, messageId }; auto messages = [&] { switch (data.type()) { case mtpc_messages_messages: { auto &d = data.c_messages_messages(); App::feedUsers(d.vusers); App::feedChats(d.vchats); result.fullCount = d.vmessages.v.size(); return &d.vmessages.v; } break; case mtpc_messages_messagesSlice: { auto &d = data.c_messages_messagesSlice(); App::feedUsers(d.vusers); App::feedChats(d.vchats); result.fullCount = d.vcount.v; return &d.vmessages.v; } break; case mtpc_messages_channelMessages: { auto &d = data.c_messages_channelMessages(); if (auto channel = peer->asChannel()) { channel->ptsReceived(d.vpts.v); } else { LOG(("API Error: received messages.channelMessages when " "no channel was passed! (ParseSearchResult)")); } App::feedUsers(d.vusers); App::feedChats(d.vchats); result.fullCount = d.vcount.v; return &d.vmessages.v; } break; case mtpc_messages_messagesNotModified: { LOG(("API Error: received messages.messagesNotModified! " "(ParseSearchResult)")); return (const QVector<MTPMessage>*)nullptr; } break; } Unexpected("messages.Messages type in ParseSearchResult()"); }(); if (!messages) { return result; } auto addType = NewMessageExisting; result.messageIds.reserve(messages->size()); for (auto &message : *messages) { if (auto item = App::histories().addNewMessage(message, addType)) { auto itemId = item->id; if ((type == Storage::SharedMediaType::kCount) || item->sharedMediaTypes().test(type)) { result.messageIds.push_back(itemId); } accumulate_min(result.noSkipRange.from, itemId); accumulate_max(result.noSkipRange.till, itemId); } } if (messageId && result.messageIds.empty()) { result.noSkipRange = [&]() -> MsgRange { switch (direction) { case SparseIdsLoadDirection::Before: // All old loaded. return { 0, result.noSkipRange.till }; case SparseIdsLoadDirection::Around: // All loaded. return { 0, ServerMaxMsgId }; case SparseIdsLoadDirection::After: // All new loaded. return { result.noSkipRange.from, ServerMaxMsgId }; } Unexpected("Direction in ParseSearchResult"); }(); } return result; }
QSize HistoryGame::countOptimalSize() { auto lineHeight = unitedLineHeight(); const auto item = _parent->data(); if (!_openl && IsServerMsgId(item->id)) { const auto row = 0; const auto column = 0; _openl = std::make_shared<ReplyMarkupClickHandler>( row, column, item->fullId()); } auto title = TextUtilities::SingleLine(_data->title); // init attach if (!_attach) { _attach = CreateAttach(_parent, _data->document, _data->photo); } // init strings if (_description.isEmpty() && !_data->description.isEmpty()) { auto text = _data->description; if (!text.isEmpty()) { if (!_attach) { text += _parent->skipBlock(); } auto marked = TextWithEntities { text }; auto parseFlags = TextParseLinks | TextParseMultiline | TextParseRichText; TextUtilities::ParseEntities(marked, parseFlags); _description.setMarkedText( st::webPageDescriptionStyle, marked, Ui::WebpageTextDescriptionOptions()); } } if (_title.isEmpty() && !title.isEmpty()) { _title.setText( st::webPageTitleStyle, title, Ui::WebpageTextTitleOptions()); } // init dimensions auto l = st::msgPadding.left() + st::webPageLeft, r = st::msgPadding.right(); auto skipBlockWidth = _parent->skipBlockWidth(); auto maxWidth = skipBlockWidth; auto minHeight = 0; auto titleMinHeight = _title.isEmpty() ? 0 : lineHeight; // enable any count of lines in game description / message auto descMaxLines = 4096; auto descriptionMinHeight = _description.isEmpty() ? 0 : qMin(_description.minHeight(), descMaxLines * lineHeight); if (!_title.isEmpty()) { accumulate_max(maxWidth, _title.maxWidth()); minHeight += titleMinHeight; } if (!_description.isEmpty()) { accumulate_max(maxWidth, _description.maxWidth()); minHeight += descriptionMinHeight; } if (_attach) { auto attachAtTop = !_titleLines && !_descriptionLines; if (!attachAtTop) minHeight += st::mediaInBubbleSkip; _attach->initDimensions(); QMargins bubble(_attach->bubbleMargins()); auto maxMediaWidth = _attach->maxWidth() - bubble.left() - bubble.right(); if (isBubbleBottom() && _attach->customInfoLayout()) { maxMediaWidth += skipBlockWidth; } accumulate_max(maxWidth, maxMediaWidth); minHeight += _attach->minHeight() - bubble.top() - bubble.bottom(); } maxWidth += st::msgPadding.left() + st::webPageLeft + st::msgPadding.right(); auto padding = inBubblePadding(); minHeight += padding.top() + padding.bottom(); if (!_gameTagWidth) { _gameTagWidth = st::msgDateFont->width(lang(lng_game_tag).toUpper()); } return { maxWidth, minHeight }; }
int Controller::countThirdColumnWidthFromRatio(int bodyWidth) const { auto result = session().settings().thirdColumnWidth(); accumulate_max(result, st::columnMinimalWidthThird); accumulate_min(result, st::columnMaximalWidthThird); return result; }
int Controller::countDialogsWidthFromRatio(int bodyWidth) const { auto result = qRound(bodyWidth * session().settings().dialogsWidthRatio()); accumulate_max(result, st::columnMinimalWidthLeft); // accumulate_min(result, st::columnMaximalWidthLeft); return result; }