Move App::roundRect to Ui::FillRoundRect.

This commit is contained in:
John Preston 2020-10-13 18:11:53 +03:00
parent b3b11bd9e7
commit 05eb549a3d
66 changed files with 2051 additions and 1847 deletions

View file

@ -21,9 +21,6 @@ add_subdirectory(lib_qr)
add_subdirectory(lib_webrtc)
add_subdirectory(codegen)
include(lib_ui/cmake/generate_styles.cmake)
include(cmake/generate_numbers.cmake)
get_filename_component(src_loc SourceFiles REALPATH)
get_filename_component(res_loc Resources REALPATH)
@ -37,33 +34,6 @@ include(cmake/td_lang.cmake)
include(cmake/td_scheme.cmake)
include(cmake/td_ui.cmake)
set(style_files
boxes/boxes.style
calls/calls.style
chat_helpers/chat_helpers.style
export/view/export.style
info/info.style
intro/intro.style
media/view/media_view.style
media/player/media_player.style
overview/overview.style
passport/passport.style
profile/profile.style
settings/settings.style
ui/filter_icons.style
)
set(dependent_style_files
${submodules_loc}/lib_ui/ui/colors.palette
${submodules_loc}/lib_ui/ui/basic.style
${submodules_loc}/lib_ui/ui/layers/layers.style
${submodules_loc}/lib_ui/ui/widgets/widgets.style
${src_loc}/ui/td_common.style
)
generate_styles(Telegram ${src_loc} "${style_files}" "${dependent_style_files}")
generate_numbers(Telegram ${res_loc}/numbers.txt)
set_target_properties(Telegram PROPERTIES AUTOMOC ON AUTORCC ON)
target_link_libraries(Telegram
@ -359,8 +329,6 @@ PRIVATE
core/launcher.h
core/local_url_handlers.cpp
core/local_url_handlers.h
core/mime_type.cpp
core/mime_type.h
core/sandbox.cpp
core/sandbox.h
core/shortcuts.cpp
@ -1023,8 +991,6 @@ PRIVATE
ui/filter_icons.h
ui/filter_icon_panel.cpp
ui/filter_icon_panel.h
ui/grouped_layout.cpp
ui/grouped_layout.h
ui/item_text_options.cpp
ui/item_text_options.h
ui/resize_area.h

View file

@ -22,6 +22,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "history/view/history_view_service_message.h"
#include "media/audio/media_audio.h"
#include "ui/image/image.h"
#include "ui/cached_round_corners.h"
#include "inline_bots/inline_bot_layout_item.h"
#include "core/crash_reports.h"
#include "core/update_checker.h"
@ -66,14 +67,6 @@ HistoryView::Element *hoveredItem = nullptr,
*pressedLinkItem = nullptr,
*mousedItem = nullptr;
struct CornersPixmaps {
QPixmap p[4];
};
QVector<CornersPixmaps> corners;
using CornersMap = QMap<uint32, CornersPixmaps>;
CornersMap cornersMap;
QImage cornersMaskLarge[4], cornersMaskSmall[4];
} // namespace
namespace App {
@ -104,114 +97,12 @@ namespace App {
return result;
}
void prepareCorners(RoundCorners index, int32 radius, const QBrush &brush, const style::color *shadow = nullptr, QImage *cors = nullptr) {
Expects(::corners.size() > index);
int32 r = radius * cIntRetinaFactor(), s = st::msgShadow * cIntRetinaFactor();
QImage rect(r * 3, r * 3 + (shadow ? s : 0), QImage::Format_ARGB32_Premultiplied), localCors[4];
{
Painter p(&rect);
PainterHighQualityEnabler hq(p);
p.setCompositionMode(QPainter::CompositionMode_Source);
p.fillRect(QRect(0, 0, rect.width(), rect.height()), Qt::transparent);
p.setCompositionMode(QPainter::CompositionMode_SourceOver);
p.setPen(Qt::NoPen);
if (shadow) {
p.setBrush((*shadow)->b);
p.drawRoundedRect(0, s, r * 3, r * 3, r, r);
}
p.setBrush(brush);
p.drawRoundedRect(0, 0, r * 3, r * 3, r, r);
}
if (!cors) cors = localCors;
cors[0] = rect.copy(0, 0, r, r);
cors[1] = rect.copy(r * 2, 0, r, r);
cors[2] = rect.copy(0, r * 2, r, r + (shadow ? s : 0));
cors[3] = rect.copy(r * 2, r * 2, r, r + (shadow ? s : 0));
if (index != SmallMaskCorners && index != LargeMaskCorners) {
for (int i = 0; i < 4; ++i) {
::corners[index].p[i] = pixmapFromImageInPlace(std::move(cors[i]));
::corners[index].p[i].setDevicePixelRatio(cRetinaFactor());
}
}
}
void createMaskCorners() {
QImage mask[4];
prepareCorners(SmallMaskCorners, st::buttonRadius, QColor(255, 255, 255), nullptr, mask);
for (int i = 0; i < 4; ++i) {
::cornersMaskSmall[i] = mask[i].convertToFormat(QImage::Format_ARGB32_Premultiplied);
::cornersMaskSmall[i].setDevicePixelRatio(cRetinaFactor());
}
prepareCorners(LargeMaskCorners, st::historyMessageRadius, QColor(255, 255, 255), nullptr, mask);
for (int i = 0; i < 4; ++i) {
::cornersMaskLarge[i] = mask[i].convertToFormat(QImage::Format_ARGB32_Premultiplied);
::cornersMaskLarge[i].setDevicePixelRatio(cRetinaFactor());
}
}
void createPaletteCorners() {
prepareCorners(MenuCorners, st::buttonRadius, st::menuBg);
prepareCorners(BoxCorners, st::boxRadius, st::boxBg);
prepareCorners(BotKbOverCorners, st::dateRadius, st::msgBotKbOverBgAdd);
prepareCorners(StickerCorners, st::dateRadius, st::msgServiceBg);
prepareCorners(StickerSelectedCorners, st::dateRadius, st::msgServiceBgSelected);
prepareCorners(SelectedOverlaySmallCorners, st::buttonRadius, st::msgSelectOverlay);
prepareCorners(SelectedOverlayLargeCorners, st::historyMessageRadius, st::msgSelectOverlay);
prepareCorners(DateCorners, st::dateRadius, st::msgDateImgBg);
prepareCorners(DateSelectedCorners, st::dateRadius, st::msgDateImgBgSelected);
prepareCorners(OverviewVideoCorners, st::overviewVideoStatusRadius, st::msgDateImgBg);
prepareCorners(OverviewVideoSelectedCorners, st::overviewVideoStatusRadius, st::msgDateImgBgSelected);
prepareCorners(InShadowCorners, st::historyMessageRadius, st::msgInShadow);
prepareCorners(InSelectedShadowCorners, st::historyMessageRadius, st::msgInShadowSelected);
prepareCorners(ForwardCorners, st::historyMessageRadius, st::historyForwardChooseBg);
prepareCorners(MediaviewSaveCorners, st::mediaviewControllerRadius, st::mediaviewSaveMsgBg);
prepareCorners(EmojiHoverCorners, st::buttonRadius, st::emojiPanHover);
prepareCorners(StickerHoverCorners, st::buttonRadius, st::emojiPanHover);
prepareCorners(BotKeyboardCorners, st::buttonRadius, st::botKbBg);
prepareCorners(PhotoSelectOverlayCorners, st::buttonRadius, st::overviewPhotoSelectOverlay);
prepareCorners(Doc1Corners, st::buttonRadius, st::msgFile1Bg);
prepareCorners(Doc2Corners, st::buttonRadius, st::msgFile2Bg);
prepareCorners(Doc3Corners, st::buttonRadius, st::msgFile3Bg);
prepareCorners(Doc4Corners, st::buttonRadius, st::msgFile4Bg);
prepareCorners(MessageInCorners, st::historyMessageRadius, st::msgInBg, &st::msgInShadow);
prepareCorners(MessageInSelectedCorners, st::historyMessageRadius, st::msgInBgSelected, &st::msgInShadowSelected);
prepareCorners(MessageOutCorners, st::historyMessageRadius, st::msgOutBg, &st::msgOutShadow);
prepareCorners(MessageOutSelectedCorners, st::historyMessageRadius, st::msgOutBgSelected, &st::msgOutShadowSelected);
prepareCorners(SendFilesBoxAlbumGroupCorners, st::sendBoxAlbumGroupRadius, st::callFingerprintBg);
}
void createCorners() {
::corners.resize(RoundCornersCount);
createMaskCorners();
createPaletteCorners();
}
void clearCorners() {
::corners.clear();
::cornersMap.clear();
}
void initMedia() {
createCorners();
Ui::StartCachedCorners();
using Update = Window::Theme::BackgroundUpdate;
static auto subscription = Window::Theme::Background()->add_subscription([](const Update &update) {
if (update.paletteChanged()) {
createPaletteCorners();
if (const auto m = App::main()) { // multi good
m->updateScrollColors();
}
HistoryView::serviceColorsUpdated();
} else if (update.type == Update::Type::New) {
prepareCorners(StickerCorners, st::dateRadius, st::msgServiceBg);
prepareCorners(StickerSelectedCorners, st::dateRadius, st::msgServiceBgSelected);
if (const auto m = App::main()) { // multi good
m->updateScrollColors();
}
@ -221,8 +112,7 @@ namespace App {
}
void deinitMedia() {
clearCorners();
Ui::FinishCachedCorners();
Data::clearGlobalStructures();
}
@ -396,132 +286,4 @@ namespace App {
return QPixmap::fromImage(std::move(image), Qt::ColorOnly);
}
void rectWithCorners(Painter &p, QRect rect, const style::color &bg, RoundCorners index, RectParts corners) {
auto parts = RectPart::Top
| RectPart::NoTopBottom
| RectPart::Bottom
| corners;
roundRect(p, rect, bg, index, nullptr, parts);
if ((corners & RectPart::AllCorners) != RectPart::AllCorners) {
const auto size = ::corners[index].p[0].width() / cIntRetinaFactor();
if (!(corners & RectPart::TopLeft)) {
p.fillRect(rect.x(), rect.y(), size, size, bg);
}
if (!(corners & RectPart::TopRight)) {
p.fillRect(rect.x() + rect.width() - size, rect.y(), size, size, bg);
}
if (!(corners & RectPart::BottomLeft)) {
p.fillRect(rect.x(), rect.y() + rect.height() - size, size, size, bg);
}
if (!(corners & RectPart::BottomRight)) {
p.fillRect(rect.x() + rect.width() - size, rect.y() + rect.height() - size, size, size, bg);
}
}
}
void complexOverlayRect(Painter &p, QRect rect, ImageRoundRadius radius, RectParts corners) {
if (radius == ImageRoundRadius::Ellipse) {
PainterHighQualityEnabler hq(p);
p.setPen(Qt::NoPen);
p.setBrush(p.textPalette().selectOverlay);
p.drawEllipse(rect);
} else {
auto overlayCorners = (radius == ImageRoundRadius::Small)
? SelectedOverlaySmallCorners
: SelectedOverlayLargeCorners;
const auto bg = p.textPalette().selectOverlay;
rectWithCorners(p, rect, bg, overlayCorners, corners);
}
}
void complexLocationRect(Painter &p, QRect rect, ImageRoundRadius radius, RectParts corners) {
rectWithCorners(p, rect, st::msgInBg, MessageInCorners, corners);
}
void roundRect(Painter &p, int32 x, int32 y, int32 w, int32 h, style::color bg, const CornersPixmaps &corner, const style::color *shadow, RectParts parts) {
auto cornerWidth = corner.p[0].width() / cIntRetinaFactor();
auto cornerHeight = corner.p[0].height() / cIntRetinaFactor();
if (w < 2 * cornerWidth || h < 2 * cornerHeight) return;
if (w > 2 * cornerWidth) {
if (parts & RectPart::Top) {
p.fillRect(x + cornerWidth, y, w - 2 * cornerWidth, cornerHeight, bg);
}
if (parts & RectPart::Bottom) {
p.fillRect(x + cornerWidth, y + h - cornerHeight, w - 2 * cornerWidth, cornerHeight, bg);
if (shadow) {
p.fillRect(x + cornerWidth, y + h, w - 2 * cornerWidth, st::msgShadow, *shadow);
}
}
}
if (h > 2 * cornerHeight) {
if ((parts & RectPart::NoTopBottom) == RectPart::NoTopBottom) {
p.fillRect(x, y + cornerHeight, w, h - 2 * cornerHeight, bg);
} else {
if (parts & RectPart::Left) {
p.fillRect(x, y + cornerHeight, cornerWidth, h - 2 * cornerHeight, bg);
}
if ((parts & RectPart::Center) && w > 2 * cornerWidth) {
p.fillRect(x + cornerWidth, y + cornerHeight, w - 2 * cornerWidth, h - 2 * cornerHeight, bg);
}
if (parts & RectPart::Right) {
p.fillRect(x + w - cornerWidth, y + cornerHeight, cornerWidth, h - 2 * cornerHeight, bg);
}
}
}
if (parts & RectPart::TopLeft) {
p.drawPixmap(x, y, corner.p[0]);
}
if (parts & RectPart::TopRight) {
p.drawPixmap(x + w - cornerWidth, y, corner.p[1]);
}
if (parts & RectPart::BottomLeft) {
p.drawPixmap(x, y + h - cornerHeight, corner.p[2]);
}
if (parts & RectPart::BottomRight) {
p.drawPixmap(x + w - cornerWidth, y + h - cornerHeight, corner.p[3]);
}
}
void roundRect(Painter &p, int32 x, int32 y, int32 w, int32 h, style::color bg, RoundCorners index, const style::color *shadow, RectParts parts) {
roundRect(p, x, y, w, h, bg, ::corners[index], shadow, parts);
}
void roundShadow(Painter &p, int32 x, int32 y, int32 w, int32 h, style::color shadow, RoundCorners index, RectParts parts) {
auto &corner = ::corners[index];
auto cornerWidth = corner.p[0].width() / cIntRetinaFactor();
auto cornerHeight = corner.p[0].height() / cIntRetinaFactor();
if (parts & RectPart::Bottom) {
p.fillRect(x + cornerWidth, y + h, w - 2 * cornerWidth, st::msgShadow, shadow);
}
if (parts & RectPart::BottomLeft) {
p.fillRect(x, y + h - cornerHeight, cornerWidth, st::msgShadow, shadow);
p.drawPixmap(x, y + h - cornerHeight + st::msgShadow, corner.p[2]);
}
if (parts & RectPart::BottomRight) {
p.fillRect(x + w - cornerWidth, y + h - cornerHeight, cornerWidth, st::msgShadow, shadow);
p.drawPixmap(x + w - cornerWidth, y + h - cornerHeight + st::msgShadow, corner.p[3]);
}
}
void roundRect(Painter &p, int32 x, int32 y, int32 w, int32 h, style::color bg, ImageRoundRadius radius, RectParts parts) {
auto colorKey = ((uint32(bg->c.alpha()) & 0xFF) << 24) | ((uint32(bg->c.red()) & 0xFF) << 16) | ((uint32(bg->c.green()) & 0xFF) << 8) | ((uint32(bg->c.blue()) & 0xFF) << 24);
auto i = cornersMap.find(colorKey);
if (i == cornersMap.cend()) {
QImage images[4];
switch (radius) {
case ImageRoundRadius::Small: prepareCorners(SmallMaskCorners, st::buttonRadius, bg, nullptr, images); break;
case ImageRoundRadius::Large: prepareCorners(LargeMaskCorners, st::historyMessageRadius, bg, nullptr, images); break;
default: p.fillRect(x, y, w, h, bg); return;
}
CornersPixmaps pixmaps;
for (int j = 0; j < 4; ++j) {
pixmaps.p[j] = pixmapFromImageInPlace(std::move(images[j]));
pixmaps.p[j].setDevicePixelRatio(cRetinaFactor());
}
i = cornersMap.insert(colorKey, pixmaps);
}
roundRect(p, x, y, w, h, bg, i.value(), nullptr, parts);
}
}

View file

@ -8,54 +8,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#pragma once
#include "data/data_types.h"
#include "ui/rect_part.h"
enum class ImageRoundRadius;
namespace HistoryView {
class Element;
} // namespace HistoryView
enum RoundCorners : int {
SmallMaskCorners = 0x00, // for images
LargeMaskCorners,
BoxCorners,
MenuCorners,
BotKbOverCorners,
StickerCorners,
StickerSelectedCorners,
SelectedOverlaySmallCorners,
SelectedOverlayLargeCorners,
DateCorners,
DateSelectedCorners,
OverviewVideoCorners,
OverviewVideoSelectedCorners,
ForwardCorners,
MediaviewSaveCorners,
EmojiHoverCorners,
StickerHoverCorners,
BotKeyboardCorners,
PhotoSelectOverlayCorners,
Doc1Corners,
Doc2Corners,
Doc3Corners,
Doc4Corners,
InShadowCorners, // for photos without bg
InSelectedShadowCorners,
MessageInCorners, // with shadow
MessageInSelectedCorners,
MessageOutCorners,
MessageOutSelectedCorners,
SendFilesBoxAlbumGroupCorners,
RoundCornersCount
};
namespace App {
QString formatPhone(QString phone);
@ -90,20 +47,4 @@ namespace App {
QImage readImage(const QString &file, QByteArray *format = nullptr, bool opaque = true, bool *animated = nullptr, QByteArray *content = 0);
QPixmap pixmapFromImageInPlace(QImage &&image);
void complexOverlayRect(Painter &p, QRect rect, ImageRoundRadius radius, RectParts corners);
void complexLocationRect(Painter &p, QRect rect, ImageRoundRadius radius, RectParts corners);
void roundRect(Painter &p, int32 x, int32 y, int32 w, int32 h, style::color bg, RoundCorners index, const style::color *shadow = nullptr, RectParts parts = RectPart::Full);
inline void roundRect(Painter &p, const QRect &rect, style::color bg, RoundCorners index, const style::color *shadow = nullptr, RectParts parts = RectPart::Full) {
return roundRect(p, rect.x(), rect.y(), rect.width(), rect.height(), bg, index, shadow, parts);
}
void roundShadow(Painter &p, int32 x, int32 y, int32 w, int32 h, style::color shadow, RoundCorners index, RectParts parts = RectPart::Full);
inline void roundShadow(Painter &p, const QRect &rect, style::color shadow, RoundCorners index, RectParts parts = RectPart::Full) {
return roundShadow(p, rect.x(), rect.y(), rect.width(), rect.height(), shadow, index, parts);
}
void roundRect(Painter &p, int32 x, int32 y, int32 w, int32 h, style::color bg, ImageRoundRadius radius, RectParts parts = RectPart::Full);
inline void roundRect(Painter &p, const QRect &rect, style::color bg, ImageRoundRadius radius, RectParts parts = RectPart::Full) {
return roundRect(p, rect.x(), rect.y(), rect.width(), rect.height(), bg, radius, parts);
}
};

View file

@ -50,11 +50,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/text/text_options.h"
#include "ui/chat/attach/attach_prepare.h"
#include "ui/controls/emoji_button.h"
#include "ui/cached_round_corners.h"
#include "window/window_session_controller.h"
#include "confirm_box.h"
#include "apiwrap.h"
#include "app.h" // App::pixmapFromImageInPlace.
#include "facades.h" // App::LambdaDelayed.
#include "app.h"
#include "styles/style_layers.h"
#include "styles/style_boxes.h"
#include "styles/style_chat_helpers.h"
@ -484,7 +485,7 @@ void EditCaptionBox::updateEditPreview() {
const auto fileinfo = QFileInfo(file->path);
const auto filename = fileinfo.fileName();
_isImage = fileIsImage(filename, file->mime);
_isImage = Core::FileIsImage(filename, file->mime);
_isAudio = false;
_animated = false;
_photo = false;
@ -516,7 +517,7 @@ void EditCaptionBox::updateEditPreview() {
if (shouldAsDoc) {
auto nameString = filename;
if (const auto song = std::get_if<Info::Song>(fileMedia)) {
nameString = DocumentData::ComposeNameString(
nameString = Ui::ComposeNameString(
filename,
song->title,
song->performer);
@ -623,9 +624,10 @@ void EditCaptionBox::createEditMediaButton() {
_editMedia.create(this, st::editMediaButton);
updateEditMediaButton();
_editMedia->setClickedCallback(
App::LambdaDelayed(st::historyAttach.ripple.hideDuration, this, [=] {
buttonCallback();
}));
App::LambdaDelayed(
st::historyAttach.ripple.hideDuration,
this,
buttonCallback));
}
void EditCaptionBox::prepare() {
@ -894,7 +896,7 @@ void EditCaptionBox::paintEvent(QPaintEvent *e) {
const auto namewidth = w - nameleft - editButton;
const auto x = (width() - w) / 2, y = st::boxPhotoPadding.top();
// App::roundRect(p, x, y, w, h, st::msgInBg, MessageInCorners, &st::msgInShadow);
// Ui::FillRoundCorner(p, x, y, w, h, st::msgInBg, Ui::MessageInCorners, &st::msgInShadow);
if (_thumbw) {
QRect rthumb(style::rtlrect(x + 0, y + 0, st::msgFileThumbSize, st::msgFileThumbSize, width()));

File diff suppressed because it is too large Load diff

View file

@ -35,6 +35,8 @@ class RoundButton;
class InputField;
struct GroupMediaLayout;
class EmojiButton;
class AlbumPreview;
enum class SendFilesWay;
} // namespace Ui
namespace Window {
@ -45,12 +47,6 @@ namespace SendMenu {
enum class Type;
} // namespace SendMenu
enum class SendFilesWay {
Album,
Photos,
Files,
};
class SendFilesBox : public Ui::BoxContent {
public:
enum class SendLimit {
@ -70,7 +66,7 @@ public:
void setConfirmedCallback(
Fn<void(
Ui::PreparedList &&list,
SendFilesWay way,
Ui::SendFilesWay way,
TextWithTags &&caption,
Api::SendOptions options,
bool ctrlShiftEnter)> callback) {
@ -91,8 +87,6 @@ protected:
void resizeEvent(QResizeEvent *e) override;
private:
class AlbumPreview;
void initSendWay();
void initPreview(rpl::producer<int> desiredPreviewHeight);
@ -101,7 +95,7 @@ private:
void setupCaption();
void setupShadows(
not_null<Ui::ScrollArea*> wrap,
not_null<AlbumPreview*> content);
not_null<Ui::AlbumPreview*> content);
void setupEmojiPanel();
void updateEmojiPanelGeometry();
@ -149,7 +143,7 @@ private:
Fn<void(
Ui::PreparedList &&list,
SendFilesWay way,
Ui::SendFilesWay way,
TextWithTags &&caption,
Api::SendOptions options,
bool ctrlShiftEnter)> _confirmedCallback;
@ -161,16 +155,16 @@ private:
base::unique_qptr<ChatHelpers::TabbedPanel> _emojiPanel;
base::unique_qptr<QObject> _emojiFilter;
object_ptr<Ui::Radioenum<SendFilesWay>> _sendAlbum = { nullptr };
object_ptr<Ui::Radioenum<SendFilesWay>> _sendPhotos = { nullptr };
object_ptr<Ui::Radioenum<SendFilesWay>> _sendFiles = { nullptr };
std::shared_ptr<Ui::RadioenumGroup<SendFilesWay>> _sendWay;
object_ptr<Ui::Radioenum<Ui::SendFilesWay>> _sendAlbum = { nullptr };
object_ptr<Ui::Radioenum<Ui::SendFilesWay>> _sendPhotos = { nullptr };
object_ptr<Ui::Radioenum<Ui::SendFilesWay>> _sendFiles = { nullptr };
std::shared_ptr<Ui::RadioenumGroup<Ui::SendFilesWay>> _sendWay;
rpl::variable<int> _footerHeight = 0;
rpl::event_stream<> _albumChanged;
QWidget *_preview = nullptr;
AlbumPreview *_albumPreview = nullptr;
Ui::AlbumPreview *_albumPreview = nullptr;
int _albumVideosCount = 0;
int _albumPhotosCount = 0;

View file

@ -26,6 +26,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/emoji_config.h"
#include "ui/toast/toast.h"
#include "ui/widgets/popup_menu.h"
#include "ui/cached_round_corners.h"
#include "lottie/lottie_multi_player.h"
#include "lottie/lottie_animation.h"
#include "chat_helpers/stickers_lottie.h"
@ -35,7 +36,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "apiwrap.h"
#include "mainwidget.h"
#include "mainwindow.h"
#include "app.h"
#include "styles/style_layers.h"
#include "styles/style_chat_helpers.h"
#include "styles/style_info.h"
@ -661,7 +661,7 @@ void StickerSetBox::Inner::paintSticker(
p.setOpacity(over);
auto tl = position;
if (rtl()) tl.setX(width() - tl.x() - st::stickersSize.width());
App::roundRect(p, QRect(tl, st::stickersSize), st::emojiPanHover, StickerHoverCorners);
Ui::FillRoundRect(p, QRect(tl, st::stickersSize), st::emojiPanHover, Ui::StickerHoverCorners);
p.setOpacity(1);
}

View file

@ -33,9 +33,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/widgets/discrete_sliders.h"
#include "ui/widgets/input_fields.h"
#include "ui/image/image.h"
#include "ui/cached_round_corners.h"
#include "window/window_session_controller.h"
#include "main/main_session.h"
#include "app.h"
#include "styles/style_layers.h"
#include "styles/style_boxes.h"
#include "styles/style_chat_helpers.h"
@ -1129,7 +1129,7 @@ void StickersBox::Inner::paintRow(Painter &p, not_null<Row*> row, int index) {
Ui::Shadow::paint(p, rect, width(), st::boxRoundShadow);
p.setOpacity(1);
App::roundRect(p, rect, st::boxBg, BoxCorners);
Ui::FillRoundRect(p, rect, st::boxBg, Ui::BoxCorners);
p.setOpacity(1. - current);
paintFakeButton(p, row, index);
@ -1318,7 +1318,7 @@ void StickersBox::Inner::paintFakeButton(Painter &p, not_null<Row*> row, int ind
auto textWidth = (_section == Section::Installed) ? _undoWidth : _addWidth;
auto &text = (_section == Section::Installed) ? _undoText : _addText;
auto &textBg = selected ? st.textBgOver : st.textBg;
App::roundRect(p, myrtlrect(rect), textBg, ImageRoundRadius::Small);
Ui::FillRoundRect(p, myrtlrect(rect), textBg, ImageRoundRadius::Small);
if (row->ripple) {
row->ripple->paint(p, rect.x(), rect.y(), width());
if (row->ripple->empty()) {

View file

@ -12,8 +12,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_user.h"
#include "data/data_session.h"
#include "main/main_session.h"
#include "ui/cached_round_corners.h"
#include "facades.h"
#include "app.h"
#include "styles/style_widgets.h"
#include "styles/style_chat.h"
@ -76,7 +76,7 @@ void Style::paintButtonBg(
Painter &p,
const QRect &rect,
float64 howMuchOver) const {
App::roundRect(p, rect, st::botKbBg, BotKeyboardCorners);
Ui::FillRoundRect(p, rect, st::botKbBg, Ui::BotKeyboardCorners);
}
void Style::paintButtonIcon(

View file

@ -12,6 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/widgets/shadow.h"
#include "ui/emoji_config.h"
#include "ui/ui_utility.h"
#include "ui/cached_round_corners.h"
#include "lang/lang_keys.h"
#include "emoji_suggestions_data.h"
#include "emoji_suggestions_helper.h"
@ -20,7 +21,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "core/application.h"
#include "window/window_session_controller.h"
#include "facades.h"
#include "app.h"
#include "styles/style_chat_helpers.h"
namespace ChatHelpers {
@ -211,7 +211,7 @@ void EmojiColorPicker::paintEvent(QPaintEvent *e) {
return;
}
Ui::Shadow::paint(p, inner, width(), st::defaultRoundShadow);
App::roundRect(p, inner, st::boxBg, BoxCorners);
Ui::FillRoundRect(p, inner, st::boxBg, Ui::BoxCorners);
auto x = st::emojiPanMargins.left() + 2 * st::emojiColorsPadding + _singleSize.width();
if (rtl()) x = width() - x - st::emojiColorsSep;
@ -372,7 +372,7 @@ void EmojiColorPicker::drawVariant(Painter &p, int variant) {
if (variant == _selected) {
QPoint tl(w);
if (rtl()) tl.setX(width() - tl.x() - _singleSize.width());
App::roundRect(p, QRect(tl, _singleSize), st::emojiPanHover, StickerHoverCorners);
Ui::FillRoundRect(p, QRect(tl, _singleSize), st::emojiPanHover, Ui::StickerHoverCorners);
}
const auto esize = Ui::Emoji::GetSizeLarge();
Ui::Emoji::Draw(
@ -558,7 +558,7 @@ void EmojiListWidget::paintEvent(QPaintEvent *e) {
if (selected) {
auto tl = w;
if (rtl()) tl.setX(width() - tl.x() - _singleSize.width());
App::roundRect(p, QRect(tl, _singleSize), st::emojiPanHover, StickerHoverCorners);
Ui::FillRoundRect(p, QRect(tl, _singleSize), st::emojiPanHover, Ui::StickerHoverCorners);
}
Ui::Emoji::Draw(
p,

View file

@ -17,11 +17,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/widgets/input_fields.h"
#include "ui/emoji_config.h"
#include "ui/ui_utility.h"
#include "ui/cached_round_corners.h"
#include "platform/platform_specific.h"
#include "core/application.h"
#include "base/event_filter.h"
#include "main/main_session.h"
#include "app.h"
#include "styles/style_chat_helpers.h"
#include <QtWidgets/QApplication>
@ -218,11 +218,11 @@ void SuggestionsWidget::paintEvent(QPaintEvent *e) {
? _pressed
: _selectedAnimation.value(_selected);
if (selected > -1.) {
App::roundRect(
Ui::FillRoundRect(
p,
QRect(selected * _oneWidth, 0, _oneWidth, _oneWidth),
st::emojiPanHover,
StickerHoverCorners);
Ui::StickerHoverCorners);
}
for (auto i = from; i != till; ++i) {

View file

@ -29,10 +29,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/widgets/scroll_area.h"
#include "ui/image/image.h"
#include "ui/ui_utility.h"
#include "ui/cached_round_corners.h"
#include "base/unixtime.h"
#include "window/window_session_controller.h"
#include "facades.h"
#include "app.h"
#include "styles/style_chat.h"
#include "styles/style_widgets.h"
#include "styles/style_chat_helpers.h"
@ -686,7 +686,7 @@ void FieldAutocompleteInner::paintEvent(QPaintEvent *e) {
if (_sel == index) {
QPoint tl(pos);
if (rtl()) tl.setX(width() - tl.x() - st::stickerPanSize.width());
App::roundRect(p, QRect(tl, st::stickerPanSize), st::emojiPanHover, StickerHoverCorners);
Ui::FillRoundRect(p, QRect(tl, st::stickerPanSize), st::emojiPanHover, Ui::StickerHoverCorners);
}
media->checkStickerSmall();

View file

@ -21,6 +21,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/effects/animations.h"
#include "ui/effects/ripple_animation.h"
#include "ui/image/image.h"
#include "ui/cached_round_corners.h"
#include "lottie/lottie_multi_player.h"
#include "lottie/lottie_single_player.h"
#include "lottie/lottie_animation.h"
@ -38,7 +39,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "main/main_session_settings.h"
#include "apiwrap.h"
#include "api/api_toggling_media.h" // Api::ToggleFavedSticker
#include "app.h"
#include "styles/style_chat_helpers.h"
#include "styles/style_window.h"
@ -1537,7 +1537,7 @@ void StickersListWidget::paintStickers(Painter &p, QRect clip) {
auto selected = selectedButton ? (selectedButton->section == info.section) : false;
auto &textBg = selected ? st::stickersTrendingAdd.textBgOver : st::stickersTrendingAdd.textBg;
App::roundRect(p, myrtlrect(add), textBg, ImageRoundRadius::Small);
Ui::FillRoundRect(p, myrtlrect(add), textBg, ImageRoundRadius::Small);
if (set.ripple) {
set.ripple->paint(p, add.x(), add.y(), width());
if (set.ripple->empty()) {
@ -1767,7 +1767,7 @@ void StickersListWidget::paintMegagroupEmptySet(Painter &p, int y, bool buttonSe
: st::stickerGroupCategoryAdd.textBg;
auto button = _megagroupSetButtonRect.translated(0, y);
App::roundRect(p, myrtlrect(button), textBg, ImageRoundRadius::Small);
Ui::FillRoundRect(p, myrtlrect(button), textBg, ImageRoundRadius::Small);
if (_megagroupSetButtonRipple) {
_megagroupSetButtonRipple->paint(p, button.x(), button.y(), width());
if (_megagroupSetButtonRipple->empty()) {
@ -1847,7 +1847,7 @@ void StickersListWidget::paintSticker(Painter &p, Set &set, int y, int section,
if (selected) {
auto tl = pos;
if (rtl()) tl.setX(width() - tl.x() - _singleSize.width());
App::roundRect(p, QRect(tl, _singleSize), st::emojiPanHover, StickerHoverCorners);
Ui::FillRoundRect(p, QRect(tl, _singleSize), st::emojiPanHover, Ui::StickerHoverCorners);
}
media->checkStickerSmall();

View file

@ -18,6 +18,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/widgets/popup_menu.h"
#include "ui/widgets/scroll_area.h"
#include "ui/image/image_prepare.h"
#include "ui/cached_round_corners.h"
#include "window/window_session_controller.h"
#include "main/main_session.h"
#include "main/main_session_settings.h"
@ -521,10 +522,10 @@ void TabbedSelector::paintSlideFrame(Painter &p) {
if (_roundRadius > 0) {
if (full()) {
auto topPart = QRect(0, 0, width(), _tabsSlider->height() + _roundRadius);
App::roundRect(p, topPart, st::emojiPanBg, ImageRoundRadius::Small, RectPart::FullTop | RectPart::NoTopBottom);
Ui::FillRoundRect(p, topPart, st::emojiPanBg, ImageRoundRadius::Small, RectPart::FullTop | RectPart::NoTopBottom);
} else {
auto topPart = QRect(0, 0, width(), 3 * _roundRadius);
App::roundRect(p, topPart, st::emojiPanBg, ImageRoundRadius::Small, RectPart::FullTop);
Ui::FillRoundRect(p, topPart, st::emojiPanBg, ImageRoundRadius::Small, RectPart::FullTop);
}
} else if (full()) {
p.fillRect(0, 0, width(), _tabsSlider->height(), st::emojiPanBg);
@ -538,15 +539,15 @@ void TabbedSelector::paintContent(Painter &p) {
if (_roundRadius > 0) {
if (full()) {
auto topPart = QRect(0, 0, width(), _tabsSlider->height() + _roundRadius);
App::roundRect(p, topPart, st::emojiPanBg, ImageRoundRadius::Small, RectPart::FullTop | RectPart::NoTopBottom);
Ui::FillRoundRect(p, topPart, st::emojiPanBg, ImageRoundRadius::Small, RectPart::FullTop | RectPart::NoTopBottom);
} else {
auto topPart = QRect(0, 0, width(), 3 * _roundRadius);
App::roundRect(p, topPart, st::emojiPanBg, ImageRoundRadius::Small, RectPart::FullTop);
Ui::FillRoundRect(p, topPart, st::emojiPanBg, ImageRoundRadius::Small, RectPart::FullTop);
}
auto bottomPart = QRect(0, _footerTop - _roundRadius, width(), st::emojiFooterHeight + _roundRadius);
auto bottomParts = RectPart::NoTopBottom | RectPart::FullBottom;
App::roundRect(p, bottomPart, bottomBg, ImageRoundRadius::Small, bottomParts);
Ui::FillRoundRect(p, bottomPart, bottomBg, ImageRoundRadius::Small, bottomParts);
} else {
if (full()) {
p.fillRect(0, 0, width(), _tabsSlider->height(), st::emojiPanBg);

View file

@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/send_files_box.h"
#include "ui/widgets/input_fields.h"
#include "ui/chat/attach/attach_common.h"
#include "storage/serialize_common.h"
#include "window/themes/window_theme.h"
#include "window/section_widget.h"
@ -18,7 +19,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace Core {
Settings::Settings()
: _sendFilesWay(SendFilesWay::Album)
: _sendFilesWay(Ui::SendFilesWay::Album)
, _sendSubmitWay(Ui::InputSubmitSettings::Enter)
, _floatPlayerColumn(Window::Column::Second)
, _floatPlayerCorner(RectPart::TopRight)
@ -309,11 +310,11 @@ void Settings::addFromSerialized(const QByteArray &serialized) {
_callAudioDuckingEnabled = (callAudioDuckingEnabled == 1);
_lastSeenWarningSeen = (lastSeenWarningSeen == 1);
_soundOverrides = std::move(soundOverrides);
auto uncheckedSendFilesWay = static_cast<SendFilesWay>(sendFilesWay);
auto uncheckedSendFilesWay = static_cast<Ui::SendFilesWay>(sendFilesWay);
switch (uncheckedSendFilesWay) {
case SendFilesWay::Album:
case SendFilesWay::Photos:
case SendFilesWay::Files: _sendFilesWay = uncheckedSendFilesWay; break;
case Ui::SendFilesWay::Album:
case Ui::SendFilesWay::Photos:
case Ui::SendFilesWay::Files: _sendFilesWay = uncheckedSendFilesWay; break;
}
auto uncheckedSendSubmitWay = static_cast<Ui::InputSubmitSettings>(sendSubmitWay);
switch (uncheckedSendSubmitWay) {
@ -469,7 +470,7 @@ void Settings::resetOnLastLogout() {
//_themesAccentColors = Window::Theme::AccentColors();
_lastSeenWarningSeen = false;
_sendFilesWay = SendFilesWay::Album;
_sendFilesWay = Ui::SendFilesWay::Album;
//_sendSubmitWay = Ui::InputSubmitSettings::Enter;
_soundOverrides = {};

View file

@ -10,11 +10,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "window/themes/window_themes_embedded.h"
#include "window/window_controls_layout.h"
enum class SendFilesWay;
enum class RectPart;
namespace Ui {
enum class InputSubmitSettings;
enum class SendFilesWay;
} // namespace Ui
namespace Window {
@ -229,10 +229,10 @@ public:
[[nodiscard]] bool lastSeenWarningSeen() const {
return _lastSeenWarningSeen;
}
void setSendFilesWay(SendFilesWay way) {
void setSendFilesWay(Ui::SendFilesWay way) {
_sendFilesWay = way;
}
[[nodiscard]] SendFilesWay sendFilesWay() const {
[[nodiscard]] Ui::SendFilesWay sendFilesWay() const {
return _sendFilesWay;
}
void setSendSubmitWay(Ui::InputSubmitSettings value) {
@ -515,7 +515,7 @@ private:
bool _callAudioDuckingEnabled = true;
Window::Theme::AccentColors _themesAccentColors;
bool _lastSeenWarningSeen = false;
SendFilesWay _sendFilesWay;
Ui::SendFilesWay _sendFilesWay;
Ui::InputSubmitSettings _sendSubmitWay;
base::flat_map<QString, QString> _soundOverrides;
bool _exeLaunchWarning = true;

View file

@ -118,4 +118,23 @@ bool IsMimeAcceptedForAlbum(const QString &mime) {
|| (mime == u"video/quicktime"_q);
}
bool FileIsImage(const QString &name, const QString &mime) {
QString lowermime = mime.toLower(), namelower = name.toLower();
if (lowermime.startsWith(qstr("image/"))) {
return true;
} else if (namelower.endsWith(qstr(".bmp"))
|| namelower.endsWith(qstr(".jpg"))
|| namelower.endsWith(qstr(".jpeg"))
|| namelower.endsWith(qstr(".gif"))
|| namelower.endsWith(qstr(".webp"))
|| namelower.endsWith(qstr(".tga"))
|| namelower.endsWith(qstr(".tiff"))
|| namelower.endsWith(qstr(".tif"))
|| namelower.endsWith(qstr(".psd"))
|| namelower.endsWith(qstr(".png"))) {
return true;
}
return false;
}
} // namespace Core

View file

@ -36,12 +36,14 @@ private:
};
MimeType MimeTypeForName(const QString &mime);
MimeType MimeTypeForFile(const QFileInfo &file);
MimeType MimeTypeForData(const QByteArray &data);
[[nodiscard]] MimeType MimeTypeForName(const QString &mime);
[[nodiscard]] MimeType MimeTypeForFile(const QFileInfo &file);
[[nodiscard]] MimeType MimeTypeForData(const QByteArray &data);
bool IsMimeStickerAnimated(const QString &mime);
bool IsMimeSticker(const QString &mime);
bool IsMimeAcceptedForAlbum(const QString &mime);
[[nodiscard]] bool IsMimeStickerAnimated(const QString &mime);
[[nodiscard]] bool IsMimeSticker(const QString &mime);
[[nodiscard]] bool IsMimeAcceptedForAlbum(const QString &mime);
[[nodiscard]] bool FileIsImage(const QString &name, const QString &mime);
} // namespace Core

View file

@ -39,6 +39,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/confirm_box.h"
#include "ui/image/image.h"
#include "ui/text/text_utilities.h"
#include "ui/text/format_values.h"
#include "base/base_file_utilities.h"
#include "mainwindow.h"
#include "core/application.h"
@ -125,25 +126,6 @@ void LaunchWithWarning(
} // namespace
bool fileIsImage(const QString &name, const QString &mime) {
QString lowermime = mime.toLower(), namelower = name.toLower();
if (lowermime.startsWith(qstr("image/"))) {
return true;
} else if (namelower.endsWith(qstr(".bmp"))
|| namelower.endsWith(qstr(".jpg"))
|| namelower.endsWith(qstr(".jpeg"))
|| namelower.endsWith(qstr(".gif"))
|| namelower.endsWith(qstr(".webp"))
|| namelower.endsWith(qstr(".tga"))
|| namelower.endsWith(qstr(".tiff"))
|| namelower.endsWith(qstr(".tif"))
|| namelower.endsWith(qstr(".psd"))
|| namelower.endsWith(qstr(".png"))) {
return true;
}
return false;
}
QString FileNameUnsafe(
not_null<Main::Session*> session,
const QString &title,
@ -1456,12 +1438,12 @@ uint8 DocumentData::cacheTag() const {
QString DocumentData::composeNameString() const {
if (auto songData = song()) {
return ComposeNameString(
return Ui::ComposeNameString(
_filename,
songData->title,
songData->performer);
}
return ComposeNameString(_filename, QString(), QString());
return Ui::ComposeNameString(_filename, QString(), QString());
}
LocationType DocumentData::locationType() const {
@ -1577,7 +1559,7 @@ void DocumentData::setMaybeSupportsStreaming(bool supports) {
void DocumentData::recountIsImage() {
const auto isImage = !isAnimation()
&& !isVideoFile()
&& fileIsImage(filename(), mimeString());
&& Core::FileIsImage(filename(), mimeString());
if (isImage) {
_flags |= Flag::ImageType;
} else {
@ -1635,22 +1617,6 @@ void DocumentData::collectLocalData(not_null<DocumentData*> local) {
}
}
QString DocumentData::ComposeNameString(
const QString &filename,
const QString &songTitle,
const QString &songPerformer) {
if (songTitle.isEmpty() && songPerformer.isEmpty()) {
return filename.isEmpty() ? qsl("Unknown File") : filename;
}
if (songPerformer.isEmpty()) {
return songTitle;
}
auto trackTitle = (songTitle.isEmpty() ? qsl("Unknown Track") : songTitle);
return songPerformer + QString::fromUtf8(" \xe2\x80\x93 ") + trackTitle;
}
namespace Data {
QString FileExtension(const QString &filepath) {

View file

@ -78,8 +78,6 @@ struct VoiceData : public DocumentAdditionalData {
char wavemax = 0;
};
bool fileIsImage(const QString &name, const QString &mime);
namespace Serialize {
class Document;
} // namespace Serialize;
@ -228,10 +226,6 @@ public:
[[nodiscard]] Storage::Cache::Key cacheKey() const;
[[nodiscard]] uint8 cacheTag() const;
[[nodiscard]] static QString ComposeNameString(
const QString &filename,
const QString &songTitle,
const QString &songPerformer);
[[nodiscard]] QString composeNameString() const;
[[nodiscard]] bool canBeStreamed() const;

View file

@ -18,10 +18,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "lang/lang_keys.h"
#include "ui/widgets/shadow.h"
#include "ui/ui_utility.h"
#include "ui/cached_round_corners.h"
#include "mainwindow.h"
#include "apiwrap.h"
#include "mainwidget.h"
#include "app.h"
#include "storage/storage_media_prepare.h"
#include "styles/style_chat_helpers.h"
#include "styles/style_layers.h"
@ -315,7 +315,7 @@ void DragArea::paintEvent(QPaintEvent *e) {
}
Ui::Shadow::paint(p, inner, width(), st::boxRoundShadow);
App::roundRect(p, inner, st::boxBg, BoxCorners);
Ui::FillRoundRect(p, inner, st::boxBg, Ui::BoxCorners);
p.setPen(anim::pen(
st::dragColor,

View file

@ -26,6 +26,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/toast/toast.h"
#include "ui/text/text_options.h"
#include "ui/ui_utility.h"
#include "ui/cached_round_corners.h"
#include "ui/inactive_press.h"
#include "window/window_session_controller.h"
#include "window/window_peer_menu.h"
@ -591,7 +592,7 @@ void HistoryInner::paintEvent(QPaintEvent *e) {
if (!_firstLoading && _botAbout && !_botAbout->info->text.isEmpty() && _botAbout->height > 0) {
if (clip.y() < _botAbout->rect.y() + _botAbout->rect.height() && clip.y() + clip.height() > _botAbout->rect.y()) {
p.setTextPalette(st::inTextPalette);
App::roundRect(p, _botAbout->rect, st::msgInBg, MessageInCorners, &st::msgInShadow);
Ui::FillRoundRect(p, _botAbout->rect, st::msgInBg, Ui::MessageInCorners, &st::msgInShadow);
auto top = _botAbout->rect.top() + st::msgPadding.top();
if (!_history->peer->isRepliesChat()) {

View file

@ -31,6 +31,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/text/text_utilities.h" // Ui::Text::ToUpper
#include "ui/text/format_values.h"
#include "ui/chat/message_bar.h"
#include "ui/chat/attach/attach_common.h"
#include "ui/image/image.h"
#include "ui/special_buttons.h"
#include "ui/controls/emoji_button.h"
@ -4193,17 +4194,17 @@ bool HistoryWidget::confirmSendingFiles(
_field->setTextWithTags({});
box->setConfirmedCallback(crl::guard(this, [=](
Ui::PreparedList &&list,
SendFilesWay way,
Ui::SendFilesWay way,
TextWithTags &&caption,
Api::SendOptions options,
bool ctrlShiftEnter) {
if (showSendingFilesError(list)) {
return;
}
const auto type = (way == SendFilesWay::Files)
const auto type = (way == Ui::SendFilesWay::Files)
? SendMediaType::File
: SendMediaType::Photo;
const auto album = (way == SendFilesWay::Album)
const auto album = (way == Ui::SendFilesWay::Album)
? std::make_shared<SendingAlbum>()
: nullptr;
uploadFilesAfterConfirmation(

View file

@ -19,6 +19,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/toast/toast.h"
#include "ui/text/text_utilities.h"
#include "ui/text/text_entity.h"
#include "ui/cached_round_corners.h"
#include "data/data_session.h"
#include "data/data_user.h"
#include "data/data_channel.h"
@ -30,7 +31,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "apiwrap.h"
#include "layout.h"
#include "facades.h"
#include "app.h"
#include "styles/style_widgets.h"
#include "styles/style_chat.h"
#include "styles/style_dialogs.h"
@ -81,11 +81,11 @@ void KeyboardStyle::paintButtonBg(
Painter &p,
const QRect &rect,
float64 howMuchOver) const {
App::roundRect(p, rect, st::msgServiceBg, StickerCorners);
Ui::FillRoundRect(p, rect, st::msgServiceBg, Ui::StickerCorners);
if (howMuchOver > 0) {
auto o = p.opacity();
p.setOpacity(o * howMuchOver);
App::roundRect(p, rect, st::msgBotKbOverBgAdd, BotKbOverCorners);
Ui::FillRoundRect(p, rect, st::msgBotKbOverBgAdd, Ui::BotKbOverCorners);
p.setOpacity(o);
}
}
@ -141,7 +141,7 @@ QString FastReplyText() {
void PaintBubble(Painter &p, QRect rect, int outerWidth, bool selected, bool outbg, RectPart tailSide, RectParts skip) {
auto &bg = selected ? (outbg ? st::msgOutBgSelected : st::msgInBgSelected) : (outbg ? st::msgOutBg : st::msgInBg);
auto sh = &(selected ? (outbg ? st::msgOutShadowSelected : st::msgInShadowSelected) : (outbg ? st::msgOutShadow : st::msgInShadow));
auto cors = selected ? (outbg ? MessageOutSelectedCorners : MessageInSelectedCorners) : (outbg ? MessageOutCorners : MessageInCorners);
auto cors = selected ? (outbg ? Ui::MessageOutSelectedCorners : Ui::MessageInSelectedCorners) : (outbg ? Ui::MessageOutCorners : Ui::MessageInCorners);
auto parts = RectPart::None | RectPart::NoTopBottom;
if (skip & RectPart::Top) {
if (skip & RectPart::Bottom) {
@ -174,7 +174,7 @@ void PaintBubble(Painter &p, QRect rect, int outerWidth, bool selected, bool out
} else if (!(skip & RectPart::Bottom)) {
parts |= RectPart::FullBottom;
}
App::roundRect(p, rect, bg, cors, sh, parts);
Ui::FillRoundRect(p, rect, bg, cors, sh, parts);
}
void PaintBubble(Painter &p, QRect rect, int outerWidth, bool selected, const std::vector<BubbleSelectionInterval> &selection, bool outbg, RectPart tailSide) {
@ -1799,10 +1799,10 @@ void Message::drawInfo(
auto dateY = infoBottom - st::msgDateFont->height;
if (type == InfoDisplayType::Image) {
auto dateW = infoW + 2 * st::msgDateImgPadding.x(), dateH = st::msgDateFont->height + 2 * st::msgDateImgPadding.y();
App::roundRect(p, dateX - st::msgDateImgPadding.x(), dateY - st::msgDateImgPadding.y(), dateW, dateH, selected ? st::msgDateImgBgSelected : st::msgDateImgBg, selected ? DateSelectedCorners : DateCorners);
Ui::FillRoundRect(p, dateX - st::msgDateImgPadding.x(), dateY - st::msgDateImgPadding.y(), dateW, dateH, selected ? st::msgDateImgBgSelected : st::msgDateImgBg, selected ? Ui::DateSelectedCorners : Ui::DateCorners);
} else if (type == InfoDisplayType::Background) {
auto dateW = infoW + 2 * st::msgDateImgPadding.x(), dateH = st::msgDateFont->height + 2 * st::msgDateImgPadding.y();
App::roundRect(p, dateX - st::msgDateImgPadding.x(), dateY - st::msgDateImgPadding.y(), dateW, dateH, selected ? st::msgServiceBgSelected : st::msgServiceBg, selected ? StickerSelectedCorners : StickerCorners);
Ui::FillRoundRect(p, dateX - st::msgDateImgPadding.x(), dateY - st::msgDateImgPadding.y(), dateW, dateH, selected ? st::msgServiceBgSelected : st::msgServiceBg, selected ? Ui::StickerSelectedCorners : Ui::StickerCorners);
}
dateX += timeLeft();

View file

@ -27,6 +27,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/text/format_values.h"
#include "ui/text/text_utilities.h"
#include "ui/chat/attach/attach_prepare.h"
#include "ui/chat/attach/attach_common.h"
#include "ui/special_buttons.h"
#include "ui/ui_utility.h"
#include "ui/toasts/common_toasts.h"
@ -635,17 +636,17 @@ bool RepliesWidget::confirmSendingFiles(
const auto replyTo = replyToId();
box->setConfirmedCallback(crl::guard(this, [=](
Ui::PreparedList &&list,
SendFilesWay way,
Ui::SendFilesWay way,
TextWithTags &&caption,
Api::SendOptions options,
bool ctrlShiftEnter) {
if (showSendingFilesError(list)) {
return;
}
const auto type = (way == SendFilesWay::Files)
const auto type = (way == Ui::SendFilesWay::Files)
? SendMediaType::File
: SendMediaType::Photo;
const auto album = (way == SendFilesWay::Album)
const auto album = (way == Ui::SendFilesWay::Album)
? std::make_shared<SendingAlbum>()
: nullptr;
uploadFilesAfterConfirmation(

View file

@ -21,6 +21,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/item_text_options.h"
#include "ui/toast/toast.h"
#include "ui/chat/attach/attach_prepare.h"
#include "ui/chat/attach/attach_common.h"
#include "ui/special_buttons.h"
#include "ui/ui_utility.h"
#include "ui/toasts/common_toasts.h"
@ -376,17 +377,17 @@ bool ScheduledWidget::confirmSendingFiles(
box->setConfirmedCallback(crl::guard(this, [=](
Ui::PreparedList &&list,
SendFilesWay way,
Ui::SendFilesWay way,
TextWithTags &&caption,
Api::SendOptions options,
bool ctrlShiftEnter) {
if (showSendingFilesError(list)) {
return;
}
const auto type = (way == SendFilesWay::Files)
const auto type = (way == Ui::SendFilesWay::Files)
? SendMediaType::File
: SendMediaType::Photo;
const auto album = (way == SendFilesWay::Album)
const auto album = (way == Ui::SendFilesWay::Album)
? std::make_shared<SendingAlbum>()
: nullptr;
uploadFilesAfterConfirmation(

View file

@ -18,13 +18,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "history/view/media/history_view_media_common.h"
#include "ui/image/image.h"
#include "ui/text/format_values.h"
#include "ui/cached_round_corners.h"
#include "layout.h" // FullSelection
#include "data/data_session.h"
#include "data/data_document.h"
#include "data/data_document_media.h"
#include "data/data_media_types.h"
#include "data/data_file_origin.h"
#include "app.h"
#include "styles/style_chat.h"
namespace HistoryView {
@ -306,8 +306,8 @@ void Document::draw(
}
p.drawPixmap(rthumb.topLeft(), thumb);
if (selected) {
auto overlayCorners = inWebPage ? SelectedOverlaySmallCorners : SelectedOverlayLargeCorners;
App::roundRect(p, rthumb, p.textPalette().selectOverlay, overlayCorners);
auto overlayCorners = inWebPage ? Ui::SelectedOverlaySmallCorners : Ui::SelectedOverlayLargeCorners;
Ui::FillRoundRect(p, rthumb, p.textPalette().selectOverlay, overlayCorners);
}
if (radial || (!loaded && !_data->loading())) {

View file

@ -15,11 +15,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "history/view/history_view_cursor_state.h"
#include "history/view/media/history_view_media_common.h"
#include "ui/item_text_options.h"
#include "ui/cached_round_corners.h"
#include "core/ui_integration.h"
#include "data/data_session.h"
#include "data/data_game.h"
#include "data/data_media_types.h"
#include "app.h"
#include "styles/style_chat.h"
namespace HistoryView {
@ -261,7 +261,7 @@ void Game::draw(Painter &p, const QRect &r, TextSelection selection, crl::time m
auto gameX = pixwidth - st::msgDateImgDelta - gameW;
auto gameY = pixheight - st::msgDateImgDelta - gameH;
App::roundRect(p, style::rtlrect(gameX, gameY, gameW, gameH, pixwidth), selected ? st::msgDateImgBgSelected : st::msgDateImgBg, selected ? DateSelectedCorners : DateCorners);
Ui::FillRoundRect(p, style::rtlrect(gameX, gameY, gameW, gameH, pixwidth), selected ? st::msgDateImgBgSelected : st::msgDateImgBg, selected ? Ui::DateSelectedCorners : Ui::DateCorners);
p.setFont(st::msgDateFont);
p.setPen(st::msgDateImgFg);

View file

@ -29,12 +29,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/image/image.h"
#include "ui/text/format_values.h"
#include "ui/grouped_layout.h"
#include "ui/cached_round_corners.h"
#include "data/data_session.h"
#include "data/data_streaming.h"
#include "data/data_document.h"
#include "data/data_file_origin.h"
#include "data/data_document_media.h"
#include "app.h"
#include "layout.h" // FullSelection
#include "styles/style_chat.h"
@ -343,7 +343,7 @@ void Gif::draw(Painter &p, const QRect &r, TextSelection selection, crl::time ms
}
}
} else if (!isRound) {
App::roundShadow(p, 0, 0, paintw, height(), selected ? st::msgInShadowSelected : st::msgInShadow, selected ? InSelectedShadowCorners : InShadowCorners);
Ui::FillRoundShadow(p, 0, 0, paintw, height(), selected ? st::msgInShadowSelected : st::msgInShadow, selected ? Ui::InSelectedShadowCorners : Ui::InShadowCorners);
}
auto usex = 0, usew = paintw;
@ -451,14 +451,14 @@ void Gif::draw(Painter &p, const QRect &r, TextSelection selection, crl::time ms
| RectPart::NoTopBottom
| (roundTop ? RectPart::Top : RectPart::None)
| (roundBottom ? RectPart::Bottom : RectPart::None);
App::roundRect(p, rthumb.marginsAdded({ 0, roundTop ? 0 : margin, 0, roundBottom ? 0 : margin }), st::imageBg, roundRadius, parts);
Ui::FillRoundRect(p, rthumb.marginsAdded({ 0, roundTop ? 0 : margin, 0, roundBottom ? 0 : margin }), st::imageBg, roundRadius, parts);
}
}
}
}
if (selected) {
App::complexOverlayRect(p, rthumb, roundRadius, roundCorners);
Ui::FillComplexOverlayRect(p, rthumb, roundRadius, roundCorners);
}
if (radial
@ -553,7 +553,7 @@ void Gif::draw(Painter &p, const QRect &r, TextSelection selection, crl::time ms
if (mediaUnread) {
statusW += st::mediaUnreadSkip + st::mediaUnreadSize;
}
App::roundRect(p, style::rtlrect(statusX - st::msgDateImgPadding.x(), statusY - st::msgDateImgPadding.y(), statusW, statusH, width()), selected ? st::msgServiceBgSelected : st::msgServiceBg, selected ? StickerSelectedCorners : StickerCorners);
Ui::FillRoundRect(p, style::rtlrect(statusX - st::msgDateImgPadding.x(), statusY - st::msgDateImgPadding.y(), statusW, statusH, width()), selected ? st::msgServiceBgSelected : st::msgServiceBg, selected ? Ui::StickerSelectedCorners : Ui::StickerCorners);
p.setFont(st::normalFont);
p.setPen(st::msgServiceFg);
p.drawTextLeft(statusX, statusY, width(), _statusText, statusW - 2 * st::msgDateImgPadding.x());
@ -584,7 +584,7 @@ void Gif::draw(Painter &p, const QRect &r, TextSelection selection, crl::time ms
int recty = painty;
if (rtl()) rectx = width() - rectx - rectw;
App::roundRect(p, rectx, recty, rectw, recth, selected ? st::msgServiceBgSelected : st::msgServiceBg, selected ? StickerSelectedCorners : StickerCorners);
Ui::FillRoundRect(p, rectx, recty, rectw, recth, selected ? st::msgServiceBgSelected : st::msgServiceBg, selected ? Ui::StickerSelectedCorners : Ui::StickerCorners);
p.setPen(st::msgServiceFg);
rectx += st::msgReplyPadding.left();
rectw = innerw;
@ -677,7 +677,7 @@ void Gif::drawCornerStatus(Painter &p, bool selected, QPoint position) const {
const auto statusY = position.y() + st::msgDateImgDelta + padding.y();
const auto around = style::rtlrect(statusX - padding.x(), statusY - padding.y(), statusW, statusH, width());
const auto statusTextTop = statusY + (cornerDownload ? (((statusH - 2 * st::normalFont->height) / 3) - padding.y()) : 0);
App::roundRect(p, around, selected ? st::msgDateImgBgSelected : st::msgDateImgBg, selected ? DateSelectedCorners : DateCorners);
Ui::FillRoundRect(p, around, selected ? st::msgDateImgBgSelected : st::msgDateImgBg, selected ? Ui::DateSelectedCorners : Ui::DateCorners);
p.setFont(st::normalFont);
p.setPen(st::msgDateImgFg);
p.drawTextLeft(statusX + addLeft, statusTextTop, width(), text, statusW - 2 * padding.x());
@ -985,7 +985,7 @@ void Gif::drawGrouped(
}
if (selected) {
App::complexOverlayRect(p, geometry, roundRadius, corners);
Ui::FillComplexOverlayRect(p, geometry, roundRadius, corners);
}
if (radial

View file

@ -15,8 +15,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "history/view/media/history_view_media_common.h"
#include "ui/item_text_options.h"
#include "ui/text/format_values.h"
#include "ui/cached_round_corners.h"
#include "data/data_media_types.h"
#include "app.h"
#include "styles/style_chat.h"
namespace HistoryView {
@ -260,7 +260,7 @@ void Invoice::draw(Painter &p, const QRect &r, TextSelection selection, crl::tim
auto statusX = st::msgDateImgDelta;
auto statusY = st::msgDateImgDelta;
App::roundRect(p, style::rtlrect(statusX, statusY, statusW, statusH, pixwidth), selected ? st::msgDateImgBgSelected : st::msgDateImgBg, selected ? DateSelectedCorners : DateCorners);
Ui::FillRoundRect(p, style::rtlrect(statusX, statusY, statusW, statusH, pixwidth), selected ? st::msgDateImgBgSelected : st::msgDateImgBg, selected ? Ui::DateSelectedCorners : Ui::DateCorners);
p.setFont(st::msgDateFont);
p.setPen(st::msgDateImgFg);

View file

@ -16,10 +16,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "history/view/history_view_cursor_state.h"
#include "ui/image/image.h"
#include "ui/text/text_options.h"
#include "ui/cached_round_corners.h"
#include "data/data_session.h"
#include "data/data_file_origin.h"
#include "data/data_cloud_file.h"
#include "app.h"
#include "styles/style_chat.h"
namespace HistoryView {
@ -179,7 +179,7 @@ void Location::draw(Painter &p, const QRect &r, TextSelection selection, crl::ti
}
painth -= painty;
} else {
App::roundShadow(p, 0, 0, paintw, painth, selected ? st::msgInShadowSelected : st::msgInShadow, selected ? InSelectedShadowCorners : InShadowCorners);
Ui::FillRoundShadow(p, 0, 0, paintw, painth, selected ? st::msgInShadowSelected : st::msgInShadow, selected ? Ui::InSelectedShadowCorners : Ui::InShadowCorners);
}
auto roundRadius = ImageRoundRadius::Large;
@ -191,7 +191,7 @@ void Location::draw(Painter &p, const QRect &r, TextSelection selection, crl::ti
const auto &pix = thumbnail->pixSingle(paintw, painth, paintw, painth, roundRadius, roundCorners);
p.drawPixmap(rthumb.topLeft(), pix);
} else {
App::complexLocationRect(p, rthumb, roundRadius, roundCorners);
Ui::FillComplexLocationRect(p, rthumb, roundRadius, roundCorners);
}
const auto paintMarker = [&](const style::icon &icon) {
icon.paint(
@ -203,7 +203,7 @@ void Location::draw(Painter &p, const QRect &r, TextSelection selection, crl::ti
paintMarker(st::historyMapPoint);
paintMarker(st::historyMapPointInner);
if (selected) {
App::complexOverlayRect(p, rthumb, roundRadius, roundCorners);
Ui::FillComplexOverlayRect(p, rthumb, roundRadius, roundCorners);
}
if (_parent->media() == this) {

View file

@ -15,8 +15,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "lottie/lottie_single_player.h"
#include "core/application.h"
#include "core/core_settings.h"
#include "ui/cached_round_corners.h"
#include "layout.h"
#include "app.h"
#include "styles/style_chat.h"
namespace HistoryView {
@ -206,7 +206,7 @@ void UnwrappedMedia::drawSurrounding(
int recty = 0;
if (rtl()) rectx = width() - rectx - rectw;
App::roundRect(p, rectx, recty, rectw, recth, selected ? st::msgServiceBgSelected : st::msgServiceBg, selected ? StickerSelectedCorners : StickerCorners);
Ui::FillRoundRect(p, rectx, recty, rectw, recth, selected ? st::msgServiceBgSelected : st::msgServiceBg, selected ? Ui::StickerSelectedCorners : Ui::StickerCorners);
p.setPen(st::msgServiceFg);
rectx += st::msgReplyPadding.left();
rectw -= st::msgReplyPadding.left() + st::msgReplyPadding.right();

View file

@ -21,6 +21,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "main/main_session_settings.h"
#include "ui/image/image.h"
#include "ui/grouped_layout.h"
#include "ui/cached_round_corners.h"
#include "data/data_session.h"
#include "data/data_streaming.h"
#include "data/data_photo.h"
@ -28,7 +29,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_file_origin.h"
#include "data/data_auto_download.h"
#include "core/application.h"
#include "app.h"
#include "styles/style_chat.h"
namespace HistoryView {
@ -249,7 +249,7 @@ void Photo::draw(Painter &p, const QRect &r, TextSelection selection, crl::time
rthumb = style::rtlrect(paintx, painty, paintw, painth, width());
}
} else {
App::roundShadow(p, 0, 0, paintw, painth, selected ? st::msgInShadowSelected : st::msgInShadow, selected ? InSelectedShadowCorners : InShadowCorners);
Ui::FillRoundShadow(p, 0, 0, paintw, painth, selected ? st::msgInShadowSelected : st::msgInShadow, selected ? Ui::InSelectedShadowCorners : Ui::InShadowCorners);
}
auto inWebPage = (_parent->media() != this);
auto roundRadius = inWebPage ? ImageRoundRadius::Small : ImageRoundRadius::Large;
@ -272,7 +272,7 @@ void Photo::draw(Painter &p, const QRect &r, TextSelection selection, crl::time
}();
p.drawPixmap(rthumb.topLeft(), pix);
if (selected) {
App::complexOverlayRect(p, rthumb, roundRadius, roundCorners);
Ui::FillComplexOverlayRect(p, rthumb, roundRadius, roundCorners);
}
}
if (radial || (!loaded && !_data->loading())) {
@ -505,7 +505,7 @@ void Photo::drawGrouped(
p.drawPixmap(geometry.topLeft(), *cache);
if (selected) {
const auto roundRadius = ImageRoundRadius::Large;
App::complexOverlayRect(p, geometry, roundRadius, corners);
Ui::FillComplexOverlayRect(p, geometry, roundRadius, corners);
}
const auto displayState = radial

View file

@ -17,9 +17,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_file_origin.h"
#include "base/qthelp_url.h"
#include "ui/text/format_values.h"
#include "ui/cached_round_corners.h"
#include "window/themes/window_theme.h"
#include "layout.h" // FullSelection
#include "app.h"
#include "app.h" // App::pixmapFromImageInPlace.
#include "styles/style_chat.h"
namespace HistoryView {
@ -139,14 +140,14 @@ void ThemeDocument::draw(Painter &p, const QRect &r, TextSelection selection, cr
validateThumbnail();
p.drawPixmap(rthumb.topLeft(), _thumbnail);
if (selected) {
App::complexOverlayRect(p, rthumb, roundRadius, roundCorners);
Ui::FillComplexOverlayRect(p, rthumb, roundRadius, roundCorners);
}
auto statusX = paintx + st::msgDateImgDelta + st::msgDateImgPadding.x();
auto statusY = painty + st::msgDateImgDelta + st::msgDateImgPadding.y();
auto statusW = st::normalFont->width(_statusText) + 2 * st::msgDateImgPadding.x();
auto statusH = st::normalFont->height + 2 * st::msgDateImgPadding.y();
App::roundRect(p, style::rtlrect(statusX - st::msgDateImgPadding.x(), statusY - st::msgDateImgPadding.y(), statusW, statusH, width()), selected ? st::msgDateImgBgSelected : st::msgDateImgBg, selected ? DateSelectedCorners : DateCorners);
Ui::FillRoundRect(p, style::rtlrect(statusX - st::msgDateImgPadding.x(), statusY - st::msgDateImgPadding.y(), statusW, statusH, width()), selected ? st::msgDateImgBgSelected : st::msgDateImgBg, selected ? Ui::DateSelectedCorners : Ui::DateCorners);
p.setFont(st::normalFont);
p.setPen(st::msgDateImgFg);
p.drawTextLeft(statusX, statusY, width(), _statusText, statusW - 2 * st::msgDateImgPadding.x());

View file

@ -19,6 +19,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/image/image.h"
#include "ui/text/text_options.h"
#include "ui/text/format_values.h"
#include "ui/cached_round_corners.h"
#include "layout.h" // FullSelection
#include "data/data_session.h"
#include "data/data_media_types.h"
@ -26,7 +27,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_photo.h"
#include "data/data_photo_media.h"
#include "data/data_file_origin.h"
#include "app.h"
#include "styles/style_chat.h"
namespace HistoryView {
@ -501,7 +501,7 @@ void WebPage::draw(Painter &p, const QRect &r, TextSelection selection, crl::tim
}
p.drawPixmapLeft(padding.left() + paintw - pw, tshift, width(), pix);
if (selected) {
App::roundRect(p, style::rtlrect(padding.left() + paintw - pw, tshift, pw, _pixh, width()), p.textPalette().selectOverlay, SelectedOverlaySmallCorners);
Ui::FillRoundRect(p, style::rtlrect(padding.left() + paintw - pw, tshift, pw, _pixh, width()), p.textPalette().selectOverlay, Ui::SelectedOverlaySmallCorners);
}
paintw -= pw + st::webPagePhotoDelta;
}
@ -569,7 +569,7 @@ void WebPage::draw(Painter &p, const QRect &r, TextSelection selection, crl::tim
auto dateW = pixwidth - dateX - st::msgDateImgDelta;
auto dateH = pixheight - dateY - st::msgDateImgDelta;
App::roundRect(p, dateX, dateY, dateW, dateH, selected ? st::msgDateImgBgSelected : st::msgDateImgBg, selected ? DateSelectedCorners : DateCorners);
Ui::FillRoundRect(p, dateX, dateY, dateW, dateH, selected ? st::msgDateImgBgSelected : st::msgDateImgBg, selected ? Ui::DateSelectedCorners : Ui::DateCorners);
p.setFont(st::msgDateFont);
p.setPen(st::msgDateImgFg);

View file

@ -13,13 +13,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/rp_widget.h"
#include "ui/focus_persister.h"
#include "ui/widgets/buttons.h"
#include "ui/cached_round_corners.h"
#include "window/section_widget.h"
#include "window/window_session_controller.h"
#include "window/main_window.h"
#include "main/main_session.h"
#include "boxes/abstract_box.h"
#include "core/application.h"
#include "app.h"
#include "app.h" // App::quitting.
#include "styles/style_info.h"
#include "styles/style_window.h"
#include "styles/style_layers.h"
@ -269,11 +270,11 @@ void LayerWidget::paintEvent(QPaintEvent *e) {
}
}
if (parts) {
App::roundRect(
Ui::FillRoundRect(
p,
rect(),
st::boxBg,
BoxCorners,
Ui::BoxCorners,
nullptr,
parts);
}

View file

@ -25,9 +25,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "history/view/history_view_cursor_state.h"
#include "ui/image/image.h"
#include "ui/text/format_values.h"
#include "ui/cached_round_corners.h"
#include "main/main_session.h"
#include "lang/lang_keys.h"
#include "app.h"
#include "styles/style_overview.h"
#include "styles/style_chat.h"
#include "styles/style_chat_helpers.h"
@ -460,7 +460,7 @@ void Sticker::paint(Painter &p, const QRect &clip, const PaintContext *context)
auto over = _a_over.value(_active ? 1. : 0.);
if (over > 0) {
p.setOpacity(over);
App::roundRect(p, QRect(QPoint(0, 0), st::stickerPanSize), st::emojiPanHover, StickerHoverCorners);
Ui::FillRoundRect(p, QRect(QPoint(0, 0), st::stickerPanSize), st::emojiPanHover, Ui::StickerHoverCorners);
p.setOpacity(1);
}
@ -734,7 +734,7 @@ void Video::paint(Painter &p, const QRect &clip, const PaintContext *context) co
int durationTop = st::inlineRowMargin + st::inlineThumbSize - st::normalFont->height - st::inlineDurationMargin;
int durationW = _durationWidth + 2 * st::msgDateImgPadding.x(), durationH = st::normalFont->height + 2 * st::msgDateImgPadding.y();
int durationX = (st::inlineThumbSize - durationW) / 2, durationY = st::inlineRowMargin + st::inlineThumbSize - durationH;
App::roundRect(p, durationX, durationY - st::msgDateImgPadding.y(), durationW, durationH, st::msgDateImgBg, DateCorners);
Ui::FillRoundRect(p, durationX, durationY - st::msgDateImgPadding.y(), durationW, durationH, st::msgDateImgBg, Ui::DateCorners);
p.setPen(st::msgDateImgFg);
p.setFont(st::normalFont);
p.drawText(durationX + st::msgDateImgPadding.x(), durationTop + st::normalFont->ascent, _duration);

View file

@ -33,9 +33,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "window/window_session_controller.h"
#include "ui/widgets/scroll_area.h"
#include "ui/widgets/labels.h"
#include "ui/cached_round_corners.h"
#include "history/view/history_view_cursor_state.h"
#include "facades.h"
#include "app.h"
#include "styles/style_chat_helpers.h"
#include <QtWidgets/QApplication>
@ -905,7 +905,7 @@ void Widget::paintEvent(QPaintEvent *e) {
void Widget::paintContent(Painter &p) {
auto inner = innerRect();
App::roundRect(p, inner, st::emojiPanBg, ImageRoundRadius::Small, RectPart::FullTop | RectPart::FullBottom);
Ui::FillRoundRect(p, inner, st::emojiPanBg, ImageRoundRadius::Small, RectPart::FullTop | RectPart::FullBottom);
auto horizontal = horizontalRect();
auto sidesTop = horizontal.y();

View file

@ -18,7 +18,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "media/audio/media_audio.h"
#include "storage/localstorage.h"
#include "history/view/history_view_cursor_state.h"
#include "app.h"
#include "ui/cached_round_corners.h"
int32 documentColorIndex(DocumentData *document, QString &ext) {
auto colorIndex = 0;
@ -118,8 +118,8 @@ style::color documentSelectedColor(int32 colorIndex) {
return colors[colorIndex & 3];
}
RoundCorners documentCorners(int32 colorIndex) {
return RoundCorners(Doc1Corners + (colorIndex & 3));
Ui::CachedRoundCorners documentCorners(int32 colorIndex) {
return Ui::CachedRoundCorners(Ui::Doc1Corners + (colorIndex & 3));
}
[[nodiscard]] HistoryView::TextState LayoutItemBase::getState(

View file

@ -14,7 +14,9 @@ struct TextState;
struct StateRequest;
} // namespace HistoryView
enum RoundCorners : int;
namespace Ui {
enum CachedRoundCorners : int;
} // namespace Ui
constexpr auto FullSelection = TextSelection { 0xFFFF, 0xFFFF };
@ -57,7 +59,7 @@ style::color documentColor(int colorIndex);
style::color documentDarkColor(int colorIndex);
style::color documentOverColor(int colorIndex);
style::color documentSelectedColor(int colorIndex);
RoundCorners documentCorners(int colorIndex);
Ui::CachedRoundCorners documentCorners(int colorIndex);
class PaintContextBase {
public:

View file

@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "chat_helpers/tabbed_selector.h"
#include "ui/widgets/input_fields.h"
#include "ui/chat/attach/attach_common.h"
#include "window/section_widget.h"
#include "support/support_common.h"
#include "storage/serialize_common.h"
@ -367,11 +368,11 @@ void SessionSettings::addFromSerialized(const QByteArray &serialized) {
for (const auto &[key, value] : appSoundOverrides) {
app.setSoundOverride(key, value);
}
auto uncheckedSendFilesWay = static_cast<SendFilesWay>(appSendFilesWay);
auto uncheckedSendFilesWay = static_cast<Ui::SendFilesWay>(appSendFilesWay);
switch (uncheckedSendFilesWay) {
case SendFilesWay::Album:
case SendFilesWay::Photos:
case SendFilesWay::Files: app.setSendFilesWay(uncheckedSendFilesWay); break;
case Ui::SendFilesWay::Album:
case Ui::SendFilesWay::Photos:
case Ui::SendFilesWay::Files: app.setSendFilesWay(uncheckedSendFilesWay); break;
}
auto uncheckedSendSubmitWay = static_cast<Ui::InputSubmitSettings>(
appSendSubmitWay);

View file

@ -19,9 +19,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/widgets/shadow.h"
#include "ui/widgets/scroll_area.h"
#include "ui/ui_utility.h"
#include "ui/cached_round_corners.h"
#include "mainwindow.h"
#include "main/main_session.h"
#include "app.h"
#include "styles/style_overview.h"
#include "styles/style_widgets.h"
#include "styles/style_media_player.h"
@ -159,7 +159,7 @@ void Panel::paintEvent(QPaintEvent *e) {
| RectPart::Top;
Ui::Shadow::paint(p, shadowedRect, width(), st::defaultRoundShadow, shadowedSides);
auto parts = RectPart::Full;
App::roundRect(p, shadowedRect, st::menuBg, MenuCorners, nullptr, parts);
Ui::FillRoundRect(p, shadowedRect, st::menuBg, Ui::MenuCorners, nullptr, parts);
}
void Panel::enterEventHook(QEvent *e) {

View file

@ -12,13 +12,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/widgets/shadow.h"
#include "ui/widgets/continuous_sliders.h"
#include "ui/ui_utility.h"
#include "ui/cached_round_corners.h"
#include "base/object_ptr.h"
#include "mainwindow.h"
#include "main/main_session.h"
#include "window/window_session_controller.h"
#include "core/application.h"
#include "core/core_settings.h"
#include "app.h"
#include "styles/style_media_player.h"
#include "styles/style_widgets.h"
@ -146,7 +146,7 @@ void VolumeWidget::paintEvent(QPaintEvent *e) {
auto shadowedSides = RectPart::Left | RectPart::Right | RectPart::Bottom;
Ui::Shadow::paint(p, shadowedRect, width(), st::defaultRoundShadow, shadowedSides);
auto parts = RectPart::NoTopBottom | RectPart::FullBottom;
App::roundRect(p, QRect(shadowedRect.x(), -st::buttonRadius, shadowedRect.width(), shadowedRect.y() + shadowedRect.height() + st::buttonRadius), st::menuBg, MenuCorners, nullptr, parts);
Ui::FillRoundRect(p, QRect(shadowedRect.x(), -st::buttonRadius, shadowedRect.width(), shadowedRect.y() + shadowedRect.height() + st::buttonRadius), st::menuBg, Ui::MenuCorners, nullptr, parts);
}
void VolumeWidget::enterEventHook(QEvent *e) {

View file

@ -25,6 +25,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/text/format_values.h"
#include "ui/item_text_options.h"
#include "ui/ui_utility.h"
#include "ui/cached_round_corners.h"
#include "boxes/confirm_box.h"
#include "media/audio/media_audio.h"
#include "media/view/media_view_playback_controls.h"
@ -3014,7 +3015,7 @@ void OverlayWidget::paintEvent(QPaintEvent *e) {
_saveMsgOpacity.update(qMin(progress, 1.), anim::linear);
if (_saveMsgOpacity.current() > 0) {
p.setOpacity(_saveMsgOpacity.current());
App::roundRect(p, _saveMsg, st::mediaviewSaveMsgBg, MediaviewSaveCorners);
Ui::FillRoundRect(p, _saveMsg, st::mediaviewSaveMsgBg, Ui::MediaviewSaveCorners);
st::mediaviewSaveMsgCheck.paint(p, _saveMsg.topLeft() + st::mediaviewSaveMsgCheckPos, width());
p.setPen(st::mediaviewSaveMsgFg);

View file

@ -15,8 +15,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/widgets/buttons.h"
#include "ui/widgets/popup_menu.h"
#include "ui/text/format_values.h"
#include "ui/cached_round_corners.h"
#include "lang/lang_keys.h"
#include "app.h"
#include "styles/style_media_view.h"
namespace Media {
@ -429,7 +429,7 @@ void PlaybackControls::paintEvent(QPaintEvent *e) {
_volumeController->setFadeOpacity(1.);
_childrenHidden = false;
}
App::roundRect(p, rect(), st::mediaviewSaveMsgBg, MediaviewSaveCorners);
Ui::FillRoundRect(p, rect(), st::mediaviewSaveMsgBg, Ui::MediaviewSaveCorners);
}
void PlaybackControls::mousePressEvent(QMouseEvent *e) {

View file

@ -38,6 +38,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/image/image.h"
#include "ui/text/format_values.h"
#include "ui/text/text_options.h"
#include "ui/cached_round_corners.h"
#include "app.h"
namespace Overview {
@ -501,7 +502,7 @@ void Video::paint(Painter &p, const QRect &clip, TextSelection selection, const
const auto statusW = icon.width() + padding.x() + st::normalFont->width(text) + 2 * padding.x();
const auto statusH = st::normalFont->height + 2 * padding.y();
p.setOpacity(1. - radialOpacity);
App::roundRect(p, statusX - padding.x(), statusY - padding.y(), statusW, statusH, selected ? st::msgDateImgBgSelected : st::msgDateImgBg, selected ? OverviewVideoSelectedCorners : OverviewVideoCorners);
Ui::FillRoundRect(p, statusX - padding.x(), statusY - padding.y(), statusW, statusH, selected ? st::msgDateImgBgSelected : st::msgDateImgBg, selected ? Ui::OverviewVideoSelectedCorners : Ui::OverviewVideoCorners);
p.setFont(st::normalFont);
p.setPen(st::msgDateImgFg);
icon.paint(p, statusX, statusY + (st::normalFont->height - icon.height()) / 2, _width);
@ -1658,19 +1659,19 @@ void Link::validateThumbnail() {
const auto index = _letter.isEmpty()
? 0
: (_letter[0].unicode() % 4);
const auto fill = [&](style::color color, RoundCorners corners) {
const auto fill = [&](style::color color, Ui::CachedRoundCorners corners) {
auto pixRect = QRect(
0,
0,
st::linksPhotoSize,
st::linksPhotoSize);
App::roundRect(p, pixRect, color, corners);
Ui::FillRoundRect(p, pixRect, color, corners);
};
switch (index) {
case 0: fill(st::msgFile1Bg, Doc1Corners); break;
case 1: fill(st::msgFile2Bg, Doc2Corners); break;
case 2: fill(st::msgFile3Bg, Doc3Corners); break;
case 3: fill(st::msgFile4Bg, Doc4Corners); break;
case 0: fill(st::msgFile1Bg, Ui::Doc1Corners); break;
case 1: fill(st::msgFile2Bg, Ui::Doc2Corners); break;
case 2: fill(st::msgFile3Bg, Ui::Doc3Corners); break;
case 3: fill(st::msgFile4Bg, Ui::Doc4Corners); break;
}
if (!_letter.isEmpty()) {

View file

@ -18,10 +18,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/widgets/labels.h"
#include "ui/widgets/buttons.h"
#include "ui/widgets/scroll_area.h"
#include "ui/cached_round_corners.h"
#include "lang/lang_keys.h"
#include "boxes/abstract_box.h"
#include "window/window_controller.h"
#include "app.h"
#include "styles/style_settings.h"
#include "styles/style_layers.h"
#include "styles/style_info.h"
@ -524,11 +524,11 @@ void LayerWidget::paintEvent(QPaintEvent *e) {
parts |= RectPart::FullBottom;
}
if (parts) {
App::roundRect(
Ui::FillRoundRect(
p,
rect(),
st::boxBg,
BoxCorners,
Ui::BoxCorners,
nullptr,
parts);
}

View file

@ -30,6 +30,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/wrap/vertical_layout.h"
#include "ui/wrap/slide_wrap.h"
#include "ui/image/image_prepare.h"
#include "ui/cached_round_corners.h"
#include "window/section_widget.h"
#include "window/window_session_controller.h"
#include "boxes/peer_list_controllers.h"
@ -859,7 +860,7 @@ void ForwardsPrivacyController::PaintForwardedTooltip(
const auto arrowLeft = arrowLeft2;
const auto geometry = rect.translated(left, top);
App::roundRect(p, geometry, st::toastBg, ImageRoundRadius::Small);
Ui::FillRoundRect(p, geometry, st::toastBg, ImageRoundRadius::Small);
p.setFont(font);
p.setPen(st::toastFg);

View file

@ -14,6 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "mtproto/mtproto_config.h"
#include "ui/effects/animation_value.h"
#include "ui/widgets/input_fields.h"
#include "ui/chat/attach/attach_common.h"
#include "window/themes/window_theme.h"
#include "core/update_checker.h"
#include "platform/platform_specific.h"
@ -918,8 +919,8 @@ bool ReadSetting(
if (!CheckStreamStatus(stream)) return false;
Core::App().settings().setSendFilesWay((v == 1)
? SendFilesWay::Album
: SendFilesWay::Files);
? Ui::SendFilesWay::Album
: Ui::SendFilesWay::Files);
context.legacyRead = true;
} break;

View file

@ -0,0 +1,255 @@
/*
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 "ui/cached_round_corners.h"
#include "ui/ui_utility.h"
#include "ui/image/image_prepare.h"
#include "styles/style_chat.h"
#include "styles/style_layers.h"
#include "styles/style_overview.h"
#include "styles/style_media_view.h"
#include "styles/style_chat_helpers.h"
namespace Ui {
namespace {
struct CornersPixmaps {
QPixmap p[4];
};
std::vector<CornersPixmaps> Corners;
base::flat_map<uint32, CornersPixmaps> CornersMap;
QImage CornersMaskLarge[4], CornersMaskSmall[4];
rpl::lifetime PaletteChangedLifetime;
void PrepareCorners(CachedRoundCorners index, int32 radius, const QBrush &brush, const style::color *shadow = nullptr, QImage *cors = nullptr) {
Expects(Corners.size() > index);
int32 r = radius * style::DevicePixelRatio(), s = st::msgShadow * style::DevicePixelRatio();
QImage rect(r * 3, r * 3 + (shadow ? s : 0), QImage::Format_ARGB32_Premultiplied), localCors[4];
{
Painter p(&rect);
PainterHighQualityEnabler hq(p);
p.setCompositionMode(QPainter::CompositionMode_Source);
p.fillRect(QRect(0, 0, rect.width(), rect.height()), Qt::transparent);
p.setCompositionMode(QPainter::CompositionMode_SourceOver);
p.setPen(Qt::NoPen);
if (shadow) {
p.setBrush((*shadow)->b);
p.drawRoundedRect(0, s, r * 3, r * 3, r, r);
}
p.setBrush(brush);
p.drawRoundedRect(0, 0, r * 3, r * 3, r, r);
}
if (!cors) cors = localCors;
cors[0] = rect.copy(0, 0, r, r);
cors[1] = rect.copy(r * 2, 0, r, r);
cors[2] = rect.copy(0, r * 2, r, r + (shadow ? s : 0));
cors[3] = rect.copy(r * 2, r * 2, r, r + (shadow ? s : 0));
if (index != SmallMaskCorners && index != LargeMaskCorners) {
for (int i = 0; i < 4; ++i) {
Corners[index].p[i] = PixmapFromImage(std::move(cors[i]));
Corners[index].p[i].setDevicePixelRatio(style::DevicePixelRatio());
}
}
}
void CreateMaskCorners() {
QImage mask[4];
PrepareCorners(SmallMaskCorners, st::buttonRadius, QColor(255, 255, 255), nullptr, mask);
for (int i = 0; i < 4; ++i) {
CornersMaskSmall[i] = mask[i].convertToFormat(QImage::Format_ARGB32_Premultiplied);
CornersMaskSmall[i].setDevicePixelRatio(style::DevicePixelRatio());
}
PrepareCorners(LargeMaskCorners, st::historyMessageRadius, QColor(255, 255, 255), nullptr, mask);
for (int i = 0; i < 4; ++i) {
CornersMaskLarge[i] = mask[i].convertToFormat(QImage::Format_ARGB32_Premultiplied);
CornersMaskLarge[i].setDevicePixelRatio(style::DevicePixelRatio());
}
}
void CreatePaletteCorners() {
PrepareCorners(MenuCorners, st::buttonRadius, st::menuBg);
PrepareCorners(BoxCorners, st::boxRadius, st::boxBg);
PrepareCorners(BotKbOverCorners, st::dateRadius, st::msgBotKbOverBgAdd);
PrepareCorners(StickerCorners, st::dateRadius, st::msgServiceBg);
PrepareCorners(StickerSelectedCorners, st::dateRadius, st::msgServiceBgSelected);
PrepareCorners(SelectedOverlaySmallCorners, st::buttonRadius, st::msgSelectOverlay);
PrepareCorners(SelectedOverlayLargeCorners, st::historyMessageRadius, st::msgSelectOverlay);
PrepareCorners(DateCorners, st::dateRadius, st::msgDateImgBg);
PrepareCorners(DateSelectedCorners, st::dateRadius, st::msgDateImgBgSelected);
PrepareCorners(OverviewVideoCorners, st::overviewVideoStatusRadius, st::msgDateImgBg);
PrepareCorners(OverviewVideoSelectedCorners, st::overviewVideoStatusRadius, st::msgDateImgBgSelected);
PrepareCorners(InShadowCorners, st::historyMessageRadius, st::msgInShadow);
PrepareCorners(InSelectedShadowCorners, st::historyMessageRadius, st::msgInShadowSelected);
PrepareCorners(ForwardCorners, st::historyMessageRadius, st::historyForwardChooseBg);
PrepareCorners(MediaviewSaveCorners, st::mediaviewControllerRadius, st::mediaviewSaveMsgBg);
PrepareCorners(EmojiHoverCorners, st::buttonRadius, st::emojiPanHover);
PrepareCorners(StickerHoverCorners, st::buttonRadius, st::emojiPanHover);
PrepareCorners(BotKeyboardCorners, st::buttonRadius, st::botKbBg);
PrepareCorners(PhotoSelectOverlayCorners, st::buttonRadius, st::overviewPhotoSelectOverlay);
PrepareCorners(Doc1Corners, st::buttonRadius, st::msgFile1Bg);
PrepareCorners(Doc2Corners, st::buttonRadius, st::msgFile2Bg);
PrepareCorners(Doc3Corners, st::buttonRadius, st::msgFile3Bg);
PrepareCorners(Doc4Corners, st::buttonRadius, st::msgFile4Bg);
PrepareCorners(MessageInCorners, st::historyMessageRadius, st::msgInBg, &st::msgInShadow);
PrepareCorners(MessageInSelectedCorners, st::historyMessageRadius, st::msgInBgSelected, &st::msgInShadowSelected);
PrepareCorners(MessageOutCorners, st::historyMessageRadius, st::msgOutBg, &st::msgOutShadow);
PrepareCorners(MessageOutSelectedCorners, st::historyMessageRadius, st::msgOutBgSelected, &st::msgOutShadowSelected);
}
} // namespace
void StartCachedCorners() {
Corners.resize(RoundCornersCount);
CreateMaskCorners();
CreatePaletteCorners();
style::PaletteChanged(
) | rpl::start_with_next([=] {
CreatePaletteCorners();
}, PaletteChangedLifetime);
}
void FinishCachedCorners() {
Corners.clear();
CornersMap.clear();
PaletteChangedLifetime.destroy();
}
void RectWithCorners(Painter &p, QRect rect, const style::color &bg, CachedRoundCorners index, RectParts corners) {
auto parts = RectPart::Top
| RectPart::NoTopBottom
| RectPart::Bottom
| corners;
FillRoundRect(p, rect, bg, index, nullptr, parts);
if ((corners & RectPart::AllCorners) != RectPart::AllCorners) {
const auto size = Corners[index].p[0].width() / style::DevicePixelRatio();
if (!(corners & RectPart::TopLeft)) {
p.fillRect(rect.x(), rect.y(), size, size, bg);
}
if (!(corners & RectPart::TopRight)) {
p.fillRect(rect.x() + rect.width() - size, rect.y(), size, size, bg);
}
if (!(corners & RectPart::BottomLeft)) {
p.fillRect(rect.x(), rect.y() + rect.height() - size, size, size, bg);
}
if (!(corners & RectPart::BottomRight)) {
p.fillRect(rect.x() + rect.width() - size, rect.y() + rect.height() - size, size, size, bg);
}
}
}
void FillComplexOverlayRect(Painter &p, QRect rect, ImageRoundRadius radius, RectParts corners) {
if (radius == ImageRoundRadius::Ellipse) {
PainterHighQualityEnabler hq(p);
p.setPen(Qt::NoPen);
p.setBrush(p.textPalette().selectOverlay);
p.drawEllipse(rect);
} else {
auto overlayCorners = (radius == ImageRoundRadius::Small)
? SelectedOverlaySmallCorners
: SelectedOverlayLargeCorners;
const auto bg = p.textPalette().selectOverlay;
RectWithCorners(p, rect, bg, overlayCorners, corners);
}
}
void FillComplexLocationRect(Painter &p, QRect rect, ImageRoundRadius radius, RectParts corners) {
RectWithCorners(p, rect, st::msgInBg, MessageInCorners, corners);
}
void FillRoundRect(Painter &p, int32 x, int32 y, int32 w, int32 h, style::color bg, const CornersPixmaps &corner, const style::color *shadow, RectParts parts) {
auto cornerWidth = corner.p[0].width() / style::DevicePixelRatio();
auto cornerHeight = corner.p[0].height() / style::DevicePixelRatio();
if (w < 2 * cornerWidth || h < 2 * cornerHeight) return;
if (w > 2 * cornerWidth) {
if (parts & RectPart::Top) {
p.fillRect(x + cornerWidth, y, w - 2 * cornerWidth, cornerHeight, bg);
}
if (parts & RectPart::Bottom) {
p.fillRect(x + cornerWidth, y + h - cornerHeight, w - 2 * cornerWidth, cornerHeight, bg);
if (shadow) {
p.fillRect(x + cornerWidth, y + h, w - 2 * cornerWidth, st::msgShadow, *shadow);
}
}
}
if (h > 2 * cornerHeight) {
if ((parts & RectPart::NoTopBottom) == RectPart::NoTopBottom) {
p.fillRect(x, y + cornerHeight, w, h - 2 * cornerHeight, bg);
} else {
if (parts & RectPart::Left) {
p.fillRect(x, y + cornerHeight, cornerWidth, h - 2 * cornerHeight, bg);
}
if ((parts & RectPart::Center) && w > 2 * cornerWidth) {
p.fillRect(x + cornerWidth, y + cornerHeight, w - 2 * cornerWidth, h - 2 * cornerHeight, bg);
}
if (parts & RectPart::Right) {
p.fillRect(x + w - cornerWidth, y + cornerHeight, cornerWidth, h - 2 * cornerHeight, bg);
}
}
}
if (parts & RectPart::TopLeft) {
p.drawPixmap(x, y, corner.p[0]);
}
if (parts & RectPart::TopRight) {
p.drawPixmap(x + w - cornerWidth, y, corner.p[1]);
}
if (parts & RectPart::BottomLeft) {
p.drawPixmap(x, y + h - cornerHeight, corner.p[2]);
}
if (parts & RectPart::BottomRight) {
p.drawPixmap(x + w - cornerWidth, y + h - cornerHeight, corner.p[3]);
}
}
void FillRoundRect(Painter &p, int32 x, int32 y, int32 w, int32 h, style::color bg, CachedRoundCorners index, const style::color *shadow, RectParts parts) {
FillRoundRect(p, x, y, w, h, bg, Corners[index], shadow, parts);
}
void FillRoundShadow(Painter &p, int32 x, int32 y, int32 w, int32 h, style::color shadow, CachedRoundCorners index, RectParts parts) {
auto &corner = Corners[index];
auto cornerWidth = corner.p[0].width() / style::DevicePixelRatio();
auto cornerHeight = corner.p[0].height() / style::DevicePixelRatio();
if (parts & RectPart::Bottom) {
p.fillRect(x + cornerWidth, y + h, w - 2 * cornerWidth, st::msgShadow, shadow);
}
if (parts & RectPart::BottomLeft) {
p.fillRect(x, y + h - cornerHeight, cornerWidth, st::msgShadow, shadow);
p.drawPixmap(x, y + h - cornerHeight + st::msgShadow, corner.p[2]);
}
if (parts & RectPart::BottomRight) {
p.fillRect(x + w - cornerWidth, y + h - cornerHeight, cornerWidth, st::msgShadow, shadow);
p.drawPixmap(x + w - cornerWidth, y + h - cornerHeight + st::msgShadow, corner.p[3]);
}
}
void FillRoundRect(Painter &p, int32 x, int32 y, int32 w, int32 h, style::color bg, ImageRoundRadius radius, RectParts parts) {
auto colorKey = ((uint32(bg->c.alpha()) & 0xFF) << 24) | ((uint32(bg->c.red()) & 0xFF) << 16) | ((uint32(bg->c.green()) & 0xFF) << 8) | ((uint32(bg->c.blue()) & 0xFF) << 24);
auto i = CornersMap.find(colorKey);
if (i == CornersMap.cend()) {
QImage images[4];
switch (radius) {
case ImageRoundRadius::Small: PrepareCorners(SmallMaskCorners, st::buttonRadius, bg, nullptr, images); break;
case ImageRoundRadius::Large: PrepareCorners(LargeMaskCorners, st::historyMessageRadius, bg, nullptr, images); break;
default: p.fillRect(x, y, w, h, bg); return;
}
CornersPixmaps pixmaps;
for (int j = 0; j < 4; ++j) {
pixmaps.p[j] = PixmapFromImage(std::move(images[j]));
pixmaps.p[j].setDevicePixelRatio(style::DevicePixelRatio());
}
i = CornersMap.emplace(colorKey, pixmaps).first;
}
FillRoundRect(p, x, y, w, h, bg, i->second, nullptr, parts);
}
} // namespace Ui

View file

@ -0,0 +1,75 @@
/*
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
*/
#pragma once
#include "ui/rect_part.h"
class Painter;
enum class ImageRoundRadius;
namespace Ui {
enum CachedRoundCorners : int {
SmallMaskCorners = 0x00, // for images
LargeMaskCorners,
BoxCorners,
MenuCorners,
BotKbOverCorners,
StickerCorners,
StickerSelectedCorners,
SelectedOverlaySmallCorners,
SelectedOverlayLargeCorners,
DateCorners,
DateSelectedCorners,
OverviewVideoCorners,
OverviewVideoSelectedCorners,
ForwardCorners,
MediaviewSaveCorners,
EmojiHoverCorners,
StickerHoverCorners,
BotKeyboardCorners,
PhotoSelectOverlayCorners,
Doc1Corners,
Doc2Corners,
Doc3Corners,
Doc4Corners,
InShadowCorners, // for photos without bg
InSelectedShadowCorners,
MessageInCorners, // with shadow
MessageInSelectedCorners,
MessageOutCorners,
MessageOutSelectedCorners,
RoundCornersCount
};
void FillComplexOverlayRect(Painter &p, QRect rect, ImageRoundRadius radius, RectParts corners);
void FillComplexLocationRect(Painter &p, QRect rect, ImageRoundRadius radius, RectParts corners);
void FillRoundRect(Painter &p, int32 x, int32 y, int32 w, int32 h, style::color bg, CachedRoundCorners index, const style::color *shadow = nullptr, RectParts parts = RectPart::Full);
inline void FillRoundRect(Painter &p, const QRect &rect, style::color bg, CachedRoundCorners index, const style::color *shadow = nullptr, RectParts parts = RectPart::Full) {
return FillRoundRect(p, rect.x(), rect.y(), rect.width(), rect.height(), bg, index, shadow, parts);
}
void FillRoundShadow(Painter &p, int32 x, int32 y, int32 w, int32 h, style::color shadow, CachedRoundCorners index, RectParts parts = RectPart::Full);
inline void FillRoundShadow(Painter &p, const QRect &rect, style::color shadow, CachedRoundCorners index, RectParts parts = RectPart::Full) {
return FillRoundShadow(p, rect.x(), rect.y(), rect.width(), rect.height(), shadow, index, parts);
}
void FillRoundRect(Painter &p, int32 x, int32 y, int32 w, int32 h, style::color bg, ImageRoundRadius radius, RectParts parts = RectPart::Full);
inline void FillRoundRect(Painter &p, const QRect &rect, style::color bg, ImageRoundRadius radius, RectParts parts = RectPart::Full) {
return FillRoundRect(p, rect.x(), rect.y(), rect.width(), rect.height(), bg, radius, parts);
}
void StartCachedCorners();
void FinishCachedCorners();
} // namespace Ui

View file

@ -0,0 +1,484 @@
/*
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 "ui/chat/attach/attach_album_preview.h"
#include "ui/chat/attach/attach_album_thumbnail.h"
#include "ui/chat/attach/attach_prepare.h"
#include "styles/style_chat.h"
#include "styles/style_boxes.h"
#include "styles/style_layers.h"
namespace Ui {
namespace {
constexpr auto kDragDuration = crl::time(200);
} // namespace
AlbumPreview::AlbumPreview(
QWidget *parent,
const PreparedList &list,
SendFilesWay way)
: RpWidget(parent)
, _list(list)
, _sendWay(way) {
setMouseTracking(true);
prepareThumbs();
updateSize();
updateFileRows();
}
AlbumPreview::~AlbumPreview() = default;
void AlbumPreview::setSendWay(SendFilesWay way) {
if (_sendWay != way) {
cancelDrag();
_sendWay = way;
}
updateSize();
updateFileRows();
update();
}
void AlbumPreview::updateFileRows() {
Expects(_order.size() == _thumbs.size());
const auto isFile = (_sendWay == SendFilesWay::Files);
for (auto i = 0; i < _order.size(); i++) {
_thumbs[i]->updateFileRow(isFile ? _order[i] : -1);
}
}
std::vector<int> AlbumPreview::takeOrder() {
auto reordered = std::vector<std::unique_ptr<AlbumThumbnail>>();
reordered.reserve(_thumbs.size());
for (auto index : _order) {
reordered.push_back(std::move(_thumbs[index]));
}
_thumbs = std::move(reordered);
return std::exchange(_order, defaultOrder());
}
auto AlbumPreview::generateOrderedLayout() const
-> std::vector<GroupMediaLayout> {
auto sizes = ranges::view::all(
_order
) | ranges::view::transform([&](int index) {
return _list.files[index].shownDimensions;
}) | ranges::to_vector;
auto layout = LayoutMediaGroup(
sizes,
st::sendMediaPreviewSize,
st::historyGroupWidthMin / 2,
st::historyGroupSkip / 2);
Assert(layout.size() == _order.size());
return layout;
}
std::vector<int> AlbumPreview::defaultOrder() const {
const auto count = int(_list.files.size());
return ranges::view::ints(0, count) | ranges::to_vector;
}
void AlbumPreview::prepareThumbs() {
_order = defaultOrder();
const auto count = int(_list.files.size());
const auto layout = generateOrderedLayout();
_thumbs.reserve(count);
for (auto i = 0; i != count; ++i) {
_thumbs.push_back(std::make_unique<AlbumThumbnail>(
_list.files[i],
layout[i],
this,
[=] { changeThumbByIndex(thumbIndex(thumbUnderCursor())); },
[=] { deleteThumbByIndex(thumbIndex(thumbUnderCursor())); }));
}
_thumbsHeight = countLayoutHeight(layout);
_photosHeight = ranges::accumulate(ranges::view::all(
_thumbs
) | ranges::view::transform([](const auto &thumb) {
return thumb->photoHeight();
}), 0) + (count - 1) * st::sendMediaPreviewPhotoSkip;
_filesHeight = count * st::sendMediaFileThumbSize
+ (count - 1) * st::sendMediaFileThumbSkip;
}
int AlbumPreview::contentLeft() const {
return (st::boxWideWidth - st::sendMediaPreviewSize) / 2;
}
int AlbumPreview::contentTop() const {
return 0;
}
AlbumThumbnail *AlbumPreview::findThumb(QPoint position) const {
position -= QPoint(contentLeft(), contentTop());
auto top = 0;
const auto isPhotosWay = (_sendWay == SendFilesWay::Photos);
const auto skip = isPhotosWay
? st::sendMediaPreviewPhotoSkip
: st::sendMediaFileThumbSkip;
auto find = [&](const auto &thumb) {
if (_sendWay == SendFilesWay::Album) {
return thumb->containsPoint(position);
} else if (isPhotosWay || _sendWay == SendFilesWay::Files) {
const auto bottom = top + (isPhotosWay
? thumb->photoHeight()
: st::sendMediaFileThumbSize);
const auto isUnderTop = (position.y() > top);
top = bottom + skip;
return isUnderTop && (position.y() < bottom);
}
return false;
};
const auto i = ranges::find_if(_thumbs, std::move(find));
return (i == _thumbs.end()) ? nullptr : i->get();
}
not_null<AlbumThumbnail*> AlbumPreview::findClosestThumb(
QPoint position) const {
Expects(_draggedThumb != nullptr);
if (const auto exact = findThumb(position)) {
return exact;
}
auto result = _draggedThumb;
auto distance = _draggedThumb->distanceTo(position);
for (const auto &thumb : _thumbs) {
const auto check = thumb->distanceTo(position);
if (check < distance) {
distance = check;
result = thumb.get();
}
}
return result;
}
int AlbumPreview::orderIndex(
not_null<AlbumThumbnail*> thumb) const {
const auto i = ranges::find_if(_order, [&](int index) {
return (_thumbs[index].get() == thumb);
});
Assert(i != _order.end());
return int(i - _order.begin());
}
void AlbumPreview::cancelDrag() {
_thumbsHeightAnimation.stop();
_finishDragAnimation.stop();
_shrinkAnimation.stop();
if (_draggedThumb) {
_draggedThumb->moveInAlbum({ 0, 0 });
_draggedThumb = nullptr;
}
if (_suggestedThumb) {
const auto suggestedIndex = orderIndex(_suggestedThumb);
if (suggestedIndex > 0) {
_thumbs[_order[suggestedIndex - 1]]->suggestMove(0., [] {});
}
if (suggestedIndex < int(_order.size() - 1)) {
_thumbs[_order[suggestedIndex + 1]]->suggestMove(0., [] {});
}
_suggestedThumb->suggestMove(0., [] {});
_suggestedThumb->finishAnimations();
_suggestedThumb = nullptr;
}
_paintedAbove = nullptr;
update();
}
void AlbumPreview::finishDrag() {
Expects(_draggedThumb != nullptr);
Expects(_suggestedThumb != nullptr);
if (_suggestedThumb != _draggedThumb) {
const auto currentIndex = orderIndex(_draggedThumb);
const auto newIndex = orderIndex(_suggestedThumb);
const auto delta = (currentIndex < newIndex) ? 1 : -1;
const auto realIndex = _order[currentIndex];
for (auto i = currentIndex; i != newIndex; i += delta) {
_order[i] = _order[i + delta];
}
_order[newIndex] = realIndex;
const auto layout = generateOrderedLayout();
for (auto i = 0, count = int(_order.size()); i != count; ++i) {
_thumbs[_order[i]]->moveToLayout(layout[i]);
}
_finishDragAnimation.start([=] { update(); }, 0., 1., kDragDuration);
updateSizeAnimated(layout);
} else {
for (const auto &thumb : _thumbs) {
thumb->resetLayoutAnimation();
}
_draggedThumb->animateLayoutToInitial();
_finishDragAnimation.start([=] { update(); }, 0., 1., kDragDuration);
}
}
int AlbumPreview::countLayoutHeight(
const std::vector<GroupMediaLayout> &layout) const {
const auto accumulator = [](int current, const auto &item) {
return std::max(current, item.geometry.y() + item.geometry.height());
};
return ranges::accumulate(layout, 0, accumulator);
}
void AlbumPreview::updateSizeAnimated(
const std::vector<GroupMediaLayout> &layout) {
const auto newHeight = countLayoutHeight(layout);
if (newHeight != _thumbsHeight) {
_thumbsHeightAnimation.start(
[=] { updateSize(); },
_thumbsHeight,
newHeight,
kDragDuration);
_thumbsHeight = newHeight;
}
}
void AlbumPreview::updateSize() {
const auto newHeight = [&] {
switch (_sendWay) {
case SendFilesWay::Album:
return int(std::round(_thumbsHeightAnimation.value(
_thumbsHeight)));
case SendFilesWay::Photos: return _photosHeight;
case SendFilesWay::Files: return _filesHeight;
}
Unexpected("Send way in AlbumPreview::updateSize");
}();
if (height() != newHeight) {
resize(st::boxWideWidth, newHeight);
}
}
void AlbumPreview::paintEvent(QPaintEvent *e) {
Painter p(this);
switch (_sendWay) {
case SendFilesWay::Album: paintAlbum(p); break;
case SendFilesWay::Photos: paintPhotos(p, e->rect()); break;
case SendFilesWay::Files: paintFiles(p, e->rect()); break;
}
}
void AlbumPreview::paintAlbum(Painter &p) const {
const auto shrink = _shrinkAnimation.value(_draggedThumb ? 1. : 0.);
const auto moveProgress = _finishDragAnimation.value(1.);
const auto left = contentLeft();
const auto top = contentTop();
for (const auto &thumb : _thumbs) {
if (thumb.get() != _paintedAbove) {
thumb->paintInAlbum(p, left, top, shrink, moveProgress);
}
}
if (_paintedAbove) {
_paintedAbove->paintInAlbum(p, left, top, shrink, moveProgress);
}
}
void AlbumPreview::paintPhotos(Painter &p, QRect clip) const {
const auto left = (st::boxWideWidth - st::sendMediaPreviewSize) / 2;
auto top = 0;
const auto outerWidth = width();
for (const auto &thumb : _thumbs) {
const auto bottom = top + thumb->photoHeight();
const auto guard = gsl::finally([&] {
top = bottom + st::sendMediaPreviewPhotoSkip;
});
if (top >= clip.y() + clip.height()) {
break;
} else if (bottom <= clip.y()) {
continue;
}
thumb->paintPhoto(p, left, top, outerWidth);
}
}
void AlbumPreview::paintFiles(Painter &p, QRect clip) const {
const auto fileHeight = st::sendMediaFileThumbSize
+ st::sendMediaFileThumbSkip;
const auto bottom = clip.y() + clip.height();
const auto from = std::clamp(clip.y() / fileHeight, 0, int(_thumbs.size()));
const auto till = std::clamp((bottom + fileHeight - 1) / fileHeight, 0, int(_thumbs.size()));
const auto left = (st::boxWideWidth - st::sendMediaPreviewSize) / 2;
const auto outerWidth = width();
auto top = from * fileHeight;
for (auto i = from; i != till; ++i) {
_thumbs[i]->paintFile(p, left, top, outerWidth);
top += fileHeight;
}
}
int AlbumPreview::thumbIndex(AlbumThumbnail *thumb) {
if (!thumb) {
return -1;
}
const auto thumbIt = ranges::find_if(_thumbs, [&](auto &t) {
return t.get() == thumb;
});
Expects(thumbIt != _thumbs.end());
return std::distance(_thumbs.begin(), thumbIt);
}
AlbumThumbnail *AlbumPreview::thumbUnderCursor() {
return findThumb(mapFromGlobal(QCursor::pos()));
}
void AlbumPreview::deleteThumbByIndex(int index) {
if (index < 0) {
return;
}
const auto orderIt = ranges::find(_order, index);
Expects(orderIt != _order.end());
_order.erase(orderIt);
ranges::for_each(_order, [=](auto &i) {
if (i > index) {
i--;
}
});
_thumbDeleted.fire(std::move(index));
}
void AlbumPreview::changeThumbByIndex(int index) {
if (index < 0) {
return;
}
_thumbChanged.fire(std::move(index));
}
void AlbumPreview::thumbButtonsCallback(
not_null<AlbumThumbnail*> thumb,
AttachButtonType type) {
const auto index = thumbIndex(thumb);
switch (type) {
case AttachButtonType::None: return;
case AttachButtonType::Edit: changeThumbByIndex(index); break;
case AttachButtonType::Delete: deleteThumbByIndex(index); break;
}
}
void AlbumPreview::mousePressEvent(QMouseEvent *e) {
if (_finishDragAnimation.animating()) {
return;
}
const auto position = e->pos();
cancelDrag();
if (const auto thumb = findThumb(position)) {
if (thumb->buttonsContainPoint(e->pos())) {
thumbButtonsCallback(thumb, thumb->buttonTypeFromPoint(e->pos()));
return;
}
_paintedAbove = _suggestedThumb = _draggedThumb = thumb;
_draggedStartPosition = position;
_shrinkAnimation.start(
[=] { update(); },
0.,
1.,
AlbumThumbnail::kShrinkDuration);
}
}
void AlbumPreview::mouseMoveEvent(QMouseEvent *e) {
if (_sendWay == SendFilesWay::Files) {
applyCursor(style::cur_default);
return;
}
const auto isAlbum = (_sendWay == SendFilesWay::Album);
if (isAlbum && _draggedThumb) {
const auto position = e->pos();
_draggedThumb->moveInAlbum(position - _draggedStartPosition);
updateSuggestedDrag(_draggedThumb->center());
update();
} else {
const auto thumb = findThumb(e->pos());
const auto regularCursor = isAlbum
? style::cur_sizeall
: style::cur_default;
const auto cursor = thumb
? (thumb->buttonsContainPoint(e->pos())
? style::cur_pointer
: regularCursor)
: style::cur_default;
applyCursor(cursor);
}
}
void AlbumPreview::applyCursor(style::cursor cursor) {
if (_cursor != cursor) {
_cursor = cursor;
setCursor(_cursor);
}
}
void AlbumPreview::updateSuggestedDrag(QPoint position) {
auto closest = findClosestThumb(position);
auto closestIndex = orderIndex(closest);
const auto draggedIndex = orderIndex(_draggedThumb);
const auto closestIsBeforePoint = closest->isPointAfter(position);
if (closestIndex < draggedIndex && closestIsBeforePoint) {
closest = _thumbs[_order[++closestIndex]].get();
} else if (closestIndex > draggedIndex && !closestIsBeforePoint) {
closest = _thumbs[_order[--closestIndex]].get();
}
if (_suggestedThumb == closest) {
return;
}
const auto last = int(_order.size()) - 1;
if (_suggestedThumb) {
const auto suggestedIndex = orderIndex(_suggestedThumb);
if (suggestedIndex < draggedIndex && suggestedIndex > 0) {
const auto previous = _thumbs[_order[suggestedIndex - 1]].get();
previous->suggestMove(0., [=] { update(); });
} else if (suggestedIndex > draggedIndex && suggestedIndex < last) {
const auto next = _thumbs[_order[suggestedIndex + 1]].get();
next->suggestMove(0., [=] { update(); });
}
_suggestedThumb->suggestMove(0., [=] { update(); });
}
_suggestedThumb = closest;
const auto suggestedIndex = closestIndex;
if (_suggestedThumb != _draggedThumb) {
const auto delta = (suggestedIndex < draggedIndex) ? 1. : -1.;
if (delta > 0. && suggestedIndex > 0) {
const auto previous = _thumbs[_order[suggestedIndex - 1]].get();
previous->suggestMove(-delta, [=] { update(); });
} else if (delta < 0. && suggestedIndex < last) {
const auto next = _thumbs[_order[suggestedIndex + 1]].get();
next->suggestMove(-delta, [=] { update(); });
}
_suggestedThumb->suggestMove(delta, [=] { update(); });
}
}
void AlbumPreview::mouseReleaseEvent(QMouseEvent *e) {
if (_draggedThumb) {
finishDrag();
_shrinkAnimation.start(
[=] { update(); },
1.,
0.,
AlbumThumbnail::kShrinkDuration);
_draggedThumb = nullptr;
_suggestedThumb = nullptr;
update();
}
}
} // namespace Ui

View file

@ -0,0 +1,99 @@
/*
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
*/
#pragma once
#include "ui/rp_widget.h"
#include "ui/chat/attach/attach_common.h"
namespace Ui {
struct PreparedList;
struct GroupMediaLayout;
class AlbumThumbnail;
class AlbumPreview final : public RpWidget {
public:
AlbumPreview(
QWidget *parent,
const PreparedList &list,
SendFilesWay way);
~AlbumPreview();
void setSendWay(SendFilesWay way);
std::vector<int> takeOrder();
auto thumbDeleted() {
return _thumbDeleted.events();
}
auto thumbChanged() {
return _thumbChanged.events();
}
protected:
void paintEvent(QPaintEvent *e) override;
void mousePressEvent(QMouseEvent *e) override;
void mouseMoveEvent(QMouseEvent *e) override;
void mouseReleaseEvent(QMouseEvent *e) override;
private:
int countLayoutHeight(
const std::vector<GroupMediaLayout> &layout) const;
std::vector<GroupMediaLayout> generateOrderedLayout() const;
std::vector<int> defaultOrder() const;
void prepareThumbs();
void updateSizeAnimated(const std::vector<GroupMediaLayout> &layout);
void updateSize();
void updateFileRows();
int thumbIndex(AlbumThumbnail *thumb);
AlbumThumbnail *thumbUnderCursor();
void deleteThumbByIndex(int index);
void changeThumbByIndex(int index);
void thumbButtonsCallback(
not_null<AlbumThumbnail*> thumb,
AttachButtonType type);
void paintAlbum(Painter &p) const;
void paintPhotos(Painter &p, QRect clip) const;
void paintFiles(Painter &p, QRect clip) const;
void applyCursor(style::cursor cursor);
int contentLeft() const;
int contentTop() const;
AlbumThumbnail *findThumb(QPoint position) const;
not_null<AlbumThumbnail*> findClosestThumb(QPoint position) const;
void updateSuggestedDrag(QPoint position);
int orderIndex(not_null<AlbumThumbnail*> thumb) const;
void cancelDrag();
void finishDrag();
const PreparedList &_list;
SendFilesWay _sendWay = SendFilesWay::Files;
style::cursor _cursor = style::cur_default;
std::vector<int> _order;
std::vector<std::unique_ptr<AlbumThumbnail>> _thumbs;
int _thumbsHeight = 0;
int _photosHeight = 0;
int _filesHeight = 0;
AlbumThumbnail *_draggedThumb = nullptr;
AlbumThumbnail *_suggestedThumb = nullptr;
AlbumThumbnail *_paintedAbove = nullptr;
QPoint _draggedStartPosition;
rpl::event_stream<int> _thumbDeleted;
rpl::event_stream<int> _thumbChanged;
mutable Animations::Simple _thumbsHeightAnimation;
mutable Animations::Simple _shrinkAnimation;
mutable Animations::Simple _finishDragAnimation;
};
} // namespace Ui

View file

@ -0,0 +1,543 @@
/*
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 "ui/chat/attach/attach_album_thumbnail.h"
#include "ui/chat/attach/attach_prepare.h"
#include "ui/image/image_prepare.h"
#include "ui/text/format_values.h"
#include "ui/widgets/buttons.h"
#include "ui/ui_utility.h"
#include "base/call_delayed.h"
#include "styles/style_chat.h"
#include "styles/style_boxes.h"
#include <QtCore/QFileInfo>
namespace Ui {
AlbumThumbnail::AlbumThumbnail(
const PreparedFile &file,
const GroupMediaLayout &layout,
QWidget *parent,
Fn<void()> editCallback,
Fn<void()> deleteCallback)
: _layout(layout)
, _fullPreview(file.preview)
, _shrinkSize(int(std::ceil(st::historyMessageRadius / 1.4)))
, _isVideo(file.type == PreparedFile::AlbumType::Video)
, _buttonsRect(st::sendBoxAlbumGroupRadius, st::callFingerprintBg) {
Expects(!_fullPreview.isNull());
moveToLayout(layout);
using Option = Images::Option;
const auto previewWidth = _fullPreview.width();
const auto previewHeight = _fullPreview.height();
const auto imageWidth = std::max(
previewWidth / style::DevicePixelRatio(),
st::minPhotoSize);
const auto imageHeight = std::max(
previewHeight / style::DevicePixelRatio(),
st::minPhotoSize);
_photo = PixmapFromImage(Images::prepare(
_fullPreview,
previewWidth,
previewHeight,
Option::RoundedLarge | Option::RoundedAll,
imageWidth,
imageHeight));
const auto idealSize = st::sendMediaFileThumbSize * style::DevicePixelRatio();
const auto fileThumbSize = (previewWidth > previewHeight)
? QSize(previewWidth * idealSize / previewHeight, idealSize)
: QSize(idealSize, previewHeight * idealSize / previewWidth);
_fileThumb = PixmapFromImage(Images::prepare(
_fullPreview,
fileThumbSize.width(),
fileThumbSize.height(),
Option::RoundedSmall | Option::RoundedAll,
st::sendMediaFileThumbSize,
st::sendMediaFileThumbSize
));
const auto availableFileWidth = st::sendMediaPreviewSize
- st::sendMediaFileThumbSkip
- st::sendMediaFileThumbSize
// Right buttons.
- st::sendBoxAlbumGroupButtonFile.width * 2
- st::sendBoxAlbumGroupEditInternalSkip * 2
- st::sendBoxAlbumGroupSkipRight;
const auto filepath = file.path;
if (filepath.isEmpty()) {
//_name = filedialogDefaultName( // #TODO files
// u"image"_q,
// u".png"_q,
// QString(),
// true);
_name = "image.png";
_status = u"%1x%2"_q.arg(
_fullPreview.width()
).arg(
_fullPreview.height()
);
} else {
auto fileinfo = QFileInfo(filepath);
_name = fileinfo.fileName();
_status = FormatSizeText(fileinfo.size());
}
_nameWidth = st::semiboldFont->width(_name);
if (_nameWidth > availableFileWidth) {
_name = st::semiboldFont->elided(
_name,
availableFileWidth,
Qt::ElideMiddle);
_nameWidth = st::semiboldFont->width(_name);
}
_statusWidth = st::normalFont->width(_status);
_editMedia.create(parent, st::sendBoxAlbumGroupButtonFile);
_deleteMedia.create(parent, st::sendBoxAlbumGroupButtonFile);
const auto duration = st::historyAttach.ripple.hideDuration;
_editMedia->setClickedCallback([=] {
base::call_delayed(duration, parent, editCallback);
});
_deleteMedia->setClickedCallback([=] {
base::call_delayed(duration, parent, deleteCallback);
});
_editMedia->setIconOverride(&st::editMediaButtonIconFile);
_deleteMedia->setIconOverride(&st::sendBoxAlbumGroupDeleteButtonIconFile);
updateFileRow(-1);
}
void AlbumThumbnail::updateFileRow(int row) {
if (row < 0) {
_editMedia->hide();
_deleteMedia->hide();
return;
}
_editMedia->show();
_deleteMedia->show();
const auto fileHeight = st::sendMediaFileThumbSize
+ st::sendMediaFileThumbSkip;
const auto top = row * fileHeight + st::sendBoxAlbumGroupSkipTop;
const auto size = st::editMediaButtonSize;
auto right = st::sendBoxAlbumGroupSkipRight + size;
_deleteMedia->moveToRight(right, top);
right += st::sendBoxAlbumGroupEditInternalSkip + size;
_editMedia->moveToRight(right, top);
}
void AlbumThumbnail::resetLayoutAnimation() {
_animateFromGeometry = std::nullopt;
}
void AlbumThumbnail::animateLayoutToInitial() {
_animateFromGeometry = countRealGeometry();
_suggestedMove = 0.;
_albumPosition = QPoint(0, 0);
}
void AlbumThumbnail::moveToLayout(const GroupMediaLayout &layout) {
animateLayoutToInitial();
_layout = layout;
const auto width = _layout.geometry.width();
const auto height = _layout.geometry.height();
_albumCorners = GetCornersFromSides(_layout.sides);
using Option = Images::Option;
const auto options = Option::Smooth
| Option::RoundedLarge
| ((_albumCorners & RectPart::TopLeft)
? Option::RoundedTopLeft
: Option::None)
| ((_albumCorners & RectPart::TopRight)
? Option::RoundedTopRight
: Option::None)
| ((_albumCorners & RectPart::BottomLeft)
? Option::RoundedBottomLeft
: Option::None)
| ((_albumCorners & RectPart::BottomRight)
? Option::RoundedBottomRight
: Option::None);
const auto pixSize = GetImageScaleSizeForGeometry(
{ _fullPreview.width(), _fullPreview.height() },
{ width, height });
const auto pixWidth = pixSize.width() * style::DevicePixelRatio();
const auto pixHeight = pixSize.height() * style::DevicePixelRatio();
_albumImage = PixmapFromImage(Images::prepare(
_fullPreview,
pixWidth,
pixHeight,
options,
width,
height));
}
int AlbumThumbnail::photoHeight() const {
return _photo.height() / style::DevicePixelRatio();
}
void AlbumThumbnail::paintInAlbum(
Painter &p,
int left,
int top,
float64 shrinkProgress,
float64 moveProgress) {
const auto shrink = anim::interpolate(0, _shrinkSize, shrinkProgress);
_lastShrinkValue = shrink;
const auto geometry = countCurrentGeometry(moveProgress);
const auto x = left + geometry.x();
const auto y = top + geometry.y();
if (shrink > 0 || moveProgress < 1.) {
const auto size = geometry.size();
if (shrinkProgress < 1 && _albumCorners != RectPart::None) {
prepareCache(size, shrink);
p.drawImage(x, y, _albumCache);
} else {
const auto to = QRect({ x, y }, size).marginsRemoved(
{ shrink, shrink, shrink, shrink }
);
drawSimpleFrame(p, to, size);
}
} else {
p.drawPixmap(x, y, _albumImage);
}
if (_isVideo) {
const auto inner = QRect(
x + (geometry.width() - st::msgFileSize) / 2,
y + (geometry.height() - st::msgFileSize) / 2,
st::msgFileSize,
st::msgFileSize);
{
PainterHighQualityEnabler hq(p);
p.setPen(Qt::NoPen);
p.setBrush(st::msgDateImgBg);
p.drawEllipse(inner);
}
st::historyFileThumbPlay.paintInCenter(p, inner);
}
_lastRectOfButtons = paintButtons(
p,
{ x, y },
geometry.width(),
shrinkProgress);
}
void AlbumThumbnail::prepareCache(QSize size, int shrink) {
const auto width = std::max(
_layout.geometry.width(),
_animateFromGeometry ? _animateFromGeometry->width() : 0);
const auto height = std::max(
_layout.geometry.height(),
_animateFromGeometry ? _animateFromGeometry->height() : 0);
const auto cacheSize = QSize(width, height) * style::DevicePixelRatio();
if (_albumCache.width() < cacheSize.width()
|| _albumCache.height() < cacheSize.height()) {
_albumCache = QImage(cacheSize, QImage::Format_ARGB32_Premultiplied);
}
_albumCache.fill(Qt::transparent);
{
Painter p(&_albumCache);
const auto to = QRect(QPoint(), size).marginsRemoved(
{ shrink, shrink, shrink, shrink }
);
drawSimpleFrame(p, to, size);
}
Images::prepareRound(
_albumCache,
ImageRoundRadius::Large,
_albumCorners,
QRect(QPoint(), size * style::DevicePixelRatio()));
_albumCache.setDevicePixelRatio(style::DevicePixelRatio());
}
void AlbumThumbnail::drawSimpleFrame(Painter &p, QRect to, QSize size) const {
const auto fullWidth = _fullPreview.width();
const auto fullHeight = _fullPreview.height();
const auto previewSize = GetImageScaleSizeForGeometry(
{ fullWidth, fullHeight },
{ size.width(), size.height() });
const auto previewWidth = previewSize.width() * style::DevicePixelRatio();
const auto previewHeight = previewSize.height() * style::DevicePixelRatio();
const auto width = size.width() * style::DevicePixelRatio();
const auto height = size.height() * style::DevicePixelRatio();
const auto scaleWidth = to.width() / float64(width);
const auto scaleHeight = to.height() / float64(height);
const auto Round = [](float64 value) {
return int(std::round(value));
};
const auto [from, fillBlack] = [&] {
if (previewWidth < width && previewHeight < height) {
const auto toWidth = Round(previewWidth * scaleWidth);
const auto toHeight = Round(previewHeight * scaleHeight);
return std::make_pair(
QRect(0, 0, fullWidth, fullHeight),
QMargins(
(to.width() - toWidth) / 2,
(to.height() - toHeight) / 2,
to.width() - toWidth - (to.width() - toWidth) / 2,
to.height() - toHeight - (to.height() - toHeight) / 2));
} else if (previewWidth * height > previewHeight * width) {
if (previewHeight >= height) {
const auto takeWidth = previewWidth * height / previewHeight;
const auto useWidth = fullWidth * width / takeWidth;
return std::make_pair(
QRect(
(fullWidth - useWidth) / 2,
0,
useWidth,
fullHeight),
QMargins(0, 0, 0, 0));
} else {
const auto takeWidth = previewWidth;
const auto useWidth = fullWidth * width / takeWidth;
const auto toHeight = Round(previewHeight * scaleHeight);
const auto toSkip = (to.height() - toHeight) / 2;
return std::make_pair(
QRect(
(fullWidth - useWidth) / 2,
0,
useWidth,
fullHeight),
QMargins(
0,
toSkip,
0,
to.height() - toHeight - toSkip));
}
} else {
if (previewWidth >= width) {
const auto takeHeight = previewHeight * width / previewWidth;
const auto useHeight = fullHeight * height / takeHeight;
return std::make_pair(
QRect(
0,
(fullHeight - useHeight) / 2,
fullWidth,
useHeight),
QMargins(0, 0, 0, 0));
} else {
const auto takeHeight = previewHeight;
const auto useHeight = fullHeight * height / takeHeight;
const auto toWidth = Round(previewWidth * scaleWidth);
const auto toSkip = (to.width() - toWidth) / 2;
return std::make_pair(
QRect(
0,
(fullHeight - useHeight) / 2,
fullWidth,
useHeight),
QMargins(
toSkip,
0,
to.width() - toWidth - toSkip,
0));
}
}
}();
p.drawImage(to.marginsRemoved(fillBlack), _fullPreview, from);
if (fillBlack.top() > 0) {
p.fillRect(to.x(), to.y(), to.width(), fillBlack.top(), st::imageBg);
}
if (fillBlack.bottom() > 0) {
p.fillRect(
to.x(),
to.y() + to.height() - fillBlack.bottom(),
to.width(),
fillBlack.bottom(),
st::imageBg);
}
if (fillBlack.left() > 0) {
p.fillRect(
to.x(),
to.y() + fillBlack.top(),
fillBlack.left(),
to.height() - fillBlack.top() - fillBlack.bottom(),
st::imageBg);
}
if (fillBlack.right() > 0) {
p.fillRect(
to.x() + to.width() - fillBlack.right(),
to.y() + fillBlack.top(),
fillBlack.right(),
to.height() - fillBlack.top() - fillBlack.bottom(),
st::imageBg);
}
}
void AlbumThumbnail::paintPhoto(Painter &p, int left, int top, int outerWidth) {
const auto width = _photo.width() / style::DevicePixelRatio();
p.drawPixmapLeft(
left + (st::sendMediaPreviewSize - width) / 2,
top,
outerWidth,
_photo);
_lastRectOfButtons = paintButtons(
p,
{ left, top },
st::sendMediaPreviewSize,
0);
}
void AlbumThumbnail::paintFile(Painter &p, int left, int top, int outerWidth) {
const auto textLeft = left
+ st::sendMediaFileThumbSize
+ st::sendMediaFileThumbSkip;
p.drawPixmap(left, top, _fileThumb);
p.setFont(st::semiboldFont);
p.setPen(st::historyFileNameInFg);
p.drawTextLeft(
textLeft,
top + st::sendMediaFileNameTop,
outerWidth,
_name,
_nameWidth);
p.setFont(st::normalFont);
p.setPen(st::mediaInFg);
p.drawTextLeft(
textLeft,
top + st::sendMediaFileStatusTop,
outerWidth,
_status,
_statusWidth);
}
bool AlbumThumbnail::containsPoint(QPoint position) const {
return _layout.geometry.contains(position);
}
bool AlbumThumbnail::buttonsContainPoint(QPoint position) const {
return _lastRectOfButtons.contains(position);
}
AttachButtonType AlbumThumbnail::buttonTypeFromPoint(QPoint position) const {
if (!buttonsContainPoint(position)) {
return AttachButtonType::None;
}
return (position.x() < _lastRectOfButtons.center().x())
? AttachButtonType::Edit
: AttachButtonType::Delete;
}
int AlbumThumbnail::distanceTo(QPoint position) const {
const auto delta = (_layout.geometry.center() - position);
return QPoint::dotProduct(delta, delta);
}
bool AlbumThumbnail::isPointAfter(QPoint position) const {
return position.x() > _layout.geometry.center().x();
}
void AlbumThumbnail::moveInAlbum(QPoint to) {
_albumPosition = to;
}
QPoint AlbumThumbnail::center() const {
auto realGeometry = _layout.geometry;
realGeometry.moveTopLeft(realGeometry.topLeft() + _albumPosition);
return realGeometry.center();
}
void AlbumThumbnail::suggestMove(float64 delta, Fn<void()> callback) {
if (_suggestedMove != delta) {
_suggestedMoveAnimation.start(
std::move(callback),
_suggestedMove,
delta,
kShrinkDuration);
_suggestedMove = delta;
}
}
QRect AlbumThumbnail::countRealGeometry() const {
const auto addLeft = int(std::round(
_suggestedMoveAnimation.value(_suggestedMove) * _lastShrinkValue));
const auto current = _layout.geometry;
const auto realTopLeft = current.topLeft()
+ _albumPosition
+ QPoint(addLeft, 0);
return { realTopLeft, current.size() };
}
QRect AlbumThumbnail::countCurrentGeometry(float64 progress) const {
const auto now = countRealGeometry();
if (_animateFromGeometry && progress < 1.) {
return {
anim::interpolate(_animateFromGeometry->x(), now.x(), progress),
anim::interpolate(_animateFromGeometry->y(), now.y(), progress),
anim::interpolate(_animateFromGeometry->width(), now.width(), progress),
anim::interpolate(_animateFromGeometry->height(), now.height(), progress)
};
}
return now;
}
void AlbumThumbnail::finishAnimations() {
_suggestedMoveAnimation.stop();
}
QRect AlbumThumbnail::paintButtons(
Painter &p,
QPoint point,
int outerWidth,
float64 shrinkProgress) {
const auto skipInternal = st::sendBoxAlbumGroupEditInternalSkip;
const auto size = st::sendBoxAlbumGroupHeight;
const auto skipRight = st::sendBoxAlbumGroupSkipRight;
const auto skipTop = st::sendBoxAlbumGroupSkipTop;
const auto groupWidth = size * 2 + skipInternal;
// If the width is tiny, it would be better to not display the buttons.
if (groupWidth > outerWidth) {
return QRect();
}
// If the width is too small,
// it would be better to display the buttons in the center.
const auto groupX = point.x() + ((groupWidth + skipRight * 2 > outerWidth)
? (outerWidth - groupWidth) / 2
: outerWidth - skipRight - groupWidth);
const auto groupY = point.y() + skipTop;
const auto deleteLeft = skipInternal + size;
p.setOpacity(1.0 - shrinkProgress);
QRect groupRect(groupX, groupY, groupWidth, size);
_buttonsRect.paint(p, groupRect);
const auto editP = st::sendBoxAlbumGroupEditButtonIconPosition;
const auto deleteP = st::sendBoxAlbumGroupDeleteButtonIconPosition;
st::sendBoxAlbumGroupEditButtonIcon.paintInCenter(
p,
QRect(groupX + editP.x(), groupY + editP.y(), size, size));
st::sendBoxAlbumGroupDeleteButtonIcon.paintInCenter(
p,
QRect(
groupX + deleteLeft + deleteP.x(),
groupY + deleteP.y(),
size,
size));
p.setOpacity(1);
return groupRect;
}
} // namespace Ui

View file

@ -0,0 +1,97 @@
/*
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
*/
#pragma once
#include "ui/chat/attach/attach_common.h"
#include "ui/effects/animations.h"
#include "ui/grouped_layout.h"
#include "ui/round_rect.h"
#include "base/object_ptr.h"
namespace Ui {
struct PreparedFile;
class IconButton;
class AlbumThumbnail final {
public:
AlbumThumbnail(
const PreparedFile &file,
const GroupMediaLayout &layout,
QWidget *parent,
Fn<void()> editCallback,
Fn<void()> deleteCallback);
void moveToLayout(const GroupMediaLayout &layout);
void animateLayoutToInitial();
void resetLayoutAnimation();
int photoHeight() const;
void paintInAlbum(
Painter &p,
int left,
int top,
float64 shrinkProgress,
float64 moveProgress);
void paintPhoto(Painter &p, int left, int top, int outerWidth);
void paintFile(Painter &p, int left, int top, int outerWidth);
bool containsPoint(QPoint position) const;
bool buttonsContainPoint(QPoint position) const;
AttachButtonType buttonTypeFromPoint(QPoint position) const;
int distanceTo(QPoint position) const;
bool isPointAfter(QPoint position) const;
void moveInAlbum(QPoint to);
QPoint center() const;
void suggestMove(float64 delta, Fn<void()> callback);
void finishAnimations();
void updateFileRow(int row);
static constexpr auto kShrinkDuration = crl::time(150);
private:
QRect countRealGeometry() const;
QRect countCurrentGeometry(float64 progress) const;
void prepareCache(QSize size, int shrink);
void drawSimpleFrame(Painter &p, QRect to, QSize size) const;
QRect paintButtons(
Painter &p,
QPoint point,
int outerWidth,
float64 shrinkProgress);
GroupMediaLayout _layout;
std::optional<QRect> _animateFromGeometry;
const QImage _fullPreview;
const int _shrinkSize = 0;
QPixmap _albumImage;
QImage _albumCache;
QPoint _albumPosition;
RectParts _albumCorners = RectPart::None;
QPixmap _photo;
QPixmap _fileThumb;
QString _name;
QString _status;
int _nameWidth = 0;
int _statusWidth = 0;
bool _isVideo = false;
float64 _suggestedMove = 0.;
Animations::Simple _suggestedMoveAnimation;
int _lastShrinkValue = 0;
RoundRect _buttonsRect;
QRect _lastRectOfButtons;
object_ptr<IconButton> _editMedia = nullptr;
object_ptr<IconButton> _deleteMedia = nullptr;
};
} // namespace Ui

View file

@ -0,0 +1,24 @@
/*
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
*/
#pragma once
namespace Ui {
enum class AttachButtonType {
Edit,
Delete,
None,
};
enum class SendFilesWay {
Album,
Photos,
Files,
};
} // namespace Ui

View file

@ -0,0 +1,173 @@
/*
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 "ui/chat/attach/attach_single_file_preview.h"
#include "ui/chat/attach/attach_prepare.h"
#include "ui/text/format_values.h"
#include "ui/text/text_options.h"
#include "ui/image/image_prepare.h"
#include "ui/cached_round_corners.h"
#include "core/mime_type.h"
#include "styles/style_chat.h"
#include "styles/style_boxes.h"
#include <QtCore/QFileInfo>
namespace Ui {
SingleFilePreview::SingleFilePreview(
QWidget *parent,
const PreparedFile &file)
: RpWidget(parent) {
preparePreview(file);
}
void SingleFilePreview::prepareThumb(const QImage &preview) {
if (preview.isNull()) {
return;
}
auto originalWidth = preview.width();
auto originalHeight = preview.height();
auto thumbWidth = st::msgFileThumbSize;
if (originalWidth > originalHeight) {
thumbWidth = (originalWidth * st::msgFileThumbSize)
/ originalHeight;
}
auto options = Images::Option::Smooth
| Images::Option::RoundedSmall
| Images::Option::RoundedTopLeft
| Images::Option::RoundedTopRight
| Images::Option::RoundedBottomLeft
| Images::Option::RoundedBottomRight;
_fileThumb = PixmapFromImage(Images::prepare(
preview,
thumbWidth * style::DevicePixelRatio(),
0,
options,
st::msgFileThumbSize,
st::msgFileThumbSize));
}
void SingleFilePreview::preparePreview(const PreparedFile &file) {
auto preview = QImage();
if (const auto image = std::get_if<PreparedFileInformation::Image>(
&file.information->media)) {
preview = image->data;
} else if (const auto video = std::get_if<PreparedFileInformation::Video>(
&file.information->media)) {
preview = video->thumbnail;
}
prepareThumb(preview);
const auto filepath = file.path;
if (filepath.isEmpty()) {
//auto filename = filedialogDefaultName(
// qsl("image"),
// qsl(".png"),
// QString(),
// true); // #TODO files
auto filename = "image.png";
_nameText.setText(
st::semiboldTextStyle,
filename,
NameTextOptions());
_statusText = u"%1x%2"_q.arg(preview.width()).arg(preview.height());
_statusWidth = qMax(_nameText.maxWidth(), st::normalFont->width(_statusText));
_fileIsImage = true;
} else {
auto fileinfo = QFileInfo(filepath);
auto filename = fileinfo.fileName();
_fileIsImage = Core::FileIsImage(filename, Core::MimeTypeForFile(fileinfo).name());
auto songTitle = QString();
auto songPerformer = QString();
if (file.information) {
if (const auto song = std::get_if<PreparedFileInformation::Song>(
&file.information->media)) {
songTitle = song->title;
songPerformer = song->performer;
_fileIsAudio = true;
}
}
const auto nameString = ComposeNameString(
filename,
songTitle,
songPerformer);
_nameText.setText(
st::semiboldTextStyle,
nameString,
NameTextOptions());
_statusText = FormatSizeText(fileinfo.size());
_statusWidth = qMax(
_nameText.maxWidth(),
st::normalFont->width(_statusText));
}
}
void SingleFilePreview::paintEvent(QPaintEvent *e) {
Painter p(this);
auto w = width() - st::boxPhotoPadding.left() - st::boxPhotoPadding.right();
auto h = _fileThumb.isNull() ? (st::msgFilePadding.top() + st::msgFileSize + st::msgFilePadding.bottom()) : (st::msgFileThumbPadding.top() + st::msgFileThumbSize + st::msgFileThumbPadding.bottom());
auto nameleft = 0, nametop = 0, nameright = 0, statustop = 0, linktop = 0;
if (_fileThumb.isNull()) {
nameleft = st::msgFilePadding.left() + st::msgFileSize + st::msgFilePadding.right();
nametop = st::msgFileNameTop;
nameright = st::msgFilePadding.left();
statustop = st::msgFileStatusTop;
} else {
nameleft = st::msgFileThumbPadding.left() + st::msgFileThumbSize + st::msgFileThumbPadding.right();
nametop = st::msgFileThumbNameTop;
nameright = st::msgFileThumbPadding.left();
statustop = st::msgFileThumbStatusTop;
linktop = st::msgFileThumbLinkTop;
}
auto namewidth = w - nameleft - (_fileThumb.isNull() ? st::msgFilePadding.left() : st::msgFileThumbPadding.left());
int32 x = (width() - w) / 2, y = st::boxPhotoPadding.top();
FillRoundRect(p, x, y, w, h, st::msgOutBg, MessageOutCorners, &st::msgOutShadow);
if (_fileThumb.isNull()) {
QRect inner(style::rtlrect(x + st::msgFilePadding.left(), y + st::msgFilePadding.top(), st::msgFileSize, st::msgFileSize, width()));
p.setPen(Qt::NoPen);
p.setBrush(st::msgFileOutBg);
{
PainterHighQualityEnabler hq(p);
p.drawEllipse(inner);
}
auto &icon = _fileIsAudio
? st::historyFileOutPlay
: _fileIsImage
? st::historyFileOutImage
: st::historyFileOutDocument;
icon.paintInCenter(p, inner);
} else {
QRect rthumb(style::rtlrect(x + st::msgFileThumbPadding.left(), y + st::msgFileThumbPadding.top(), st::msgFileThumbSize, st::msgFileThumbSize, width()));
p.drawPixmap(rthumb.topLeft(), _fileThumb);
}
p.setFont(st::semiboldFont);
p.setPen(st::historyFileNameOutFg);
_nameText.drawLeftElided(p, x + nameleft, y + nametop, namewidth, width());
auto &status = st::mediaOutFg;
p.setFont(st::normalFont);
p.setPen(status);
p.drawTextLeft(x + nameleft, y + statustop, width(), _statusText);
}
rpl::producer<int> SingleFilePreview::desiredHeightValue() const {
auto h = _fileThumb.isNull()
? (st::msgFilePadding.top() + st::msgFileSize + st::msgFilePadding.bottom())
: (st::msgFileThumbPadding.top() + st::msgFileThumbSize + st::msgFileThumbPadding.bottom());
return rpl::single(st::boxPhotoPadding.top() + h + st::msgShadow);
}
} // namespace Ui

View file

@ -0,0 +1,40 @@
/*
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
*/
#pragma once
#include "ui/rp_widget.h"
namespace Ui {
struct PreparedFile;
class SingleFilePreview final : public RpWidget {
public:
SingleFilePreview(
QWidget *parent,
const PreparedFile &file);
rpl::producer<int> desiredHeightValue() const override;
protected:
void paintEvent(QPaintEvent *e) override;
private:
void preparePreview(const PreparedFile &file);
void prepareThumb(const QImage &preview);
QPixmap _fileThumb;
Text::String _nameText;
bool _fileIsAudio = false;
bool _fileIsImage = false;
QString _statusText;
int _statusWidth = 0;
};
} // namespace Ui

View file

@ -12,9 +12,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/effects/panel_animation.h"
#include "ui/ui_utility.h"
#include "ui/filter_icons.h"
#include "ui/cached_round_corners.h"
#include "lang/lang_keys.h"
#include "core/application.h"
#include "app.h"
#include "styles/style_chat_helpers.h"
#include "styles/style_window.h"
@ -102,7 +102,7 @@ void FilterIconPanel::setupInner() {
_inner->paintRequest(
) | rpl::start_with_next([=](QRect clip) {
auto p = Painter(_inner);
App::roundRect(
Ui::FillRoundRect(
p,
_inner->rect(),
st::emojiPanBg,
@ -122,11 +122,11 @@ void FilterIconPanel::setupInner() {
continue;
}
if (i == selected) {
App::roundRect(
Ui::FillRoundRect(
p,
rect,
st::emojiPanHover,
StickerHoverCorners);
Ui::StickerHoverCorners);
}
const auto icon = LookupFilterIcon(kIcons[i]).normal;
icon->paintInCenter(p, rect, st::emojiIconFg->c);

View file

@ -444,8 +444,8 @@ std::vector<float64> ComplexLayouter::CropRatios(
constexpr auto kMaxRatio = 2.75;
constexpr auto kMinRatio = 0.6667;
return (averageRatio > 1.1)
? snap(ratio, 1., kMaxRatio)
: snap(ratio, kMinRatio, 1.);
? std::clamp(ratio, 1., kMaxRatio)
: std::clamp(ratio, kMinRatio, 1.);
}) | ranges::to_vector;
}

View file

@ -128,4 +128,20 @@ QString FillAmountAndCurrency(uint64 amount, const QString &currency) {
//return currencyText + amountText;
}
QString ComposeNameString(
const QString &filename,
const QString &songTitle,
const QString &songPerformer) {
if (songTitle.isEmpty() && songPerformer.isEmpty()) {
return filename.isEmpty() ? u"Unknown File"_q : filename;
}
if (songPerformer.isEmpty()) {
return songTitle;
}
auto trackTitle = (songTitle.isEmpty() ? u"Unknown Track"_q : songTitle);
return songPerformer + QString::fromUtf8(" \xe2\x80\x93 ") + trackTitle;
}
} // namespace Ui

View file

@ -25,4 +25,9 @@ inline constexpr auto FileStatusSizeFailed = 0x7FFFFFF2;
uint64 amount,
const QString &currency);
[[nodiscard]] QString ComposeNameString(
const QString &filename,
const QString &songTitle,
const QString &songPerformer);
} // namespace Ui

View file

@ -118,7 +118,8 @@ struct BackgroundUpdate {
[[nodiscard]] bool paletteChanged() const {
return (type == Type::TestingTheme)
|| (type == Type::RevertingTheme)
|| (type == Type::ApplyingEdit);
|| (type == Type::ApplyingEdit)
|| (type == Type::New);
}
Type type;
bool tiled;

View file

@ -10,9 +10,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/widgets/buttons.h"
#include "ui/widgets/shadow.h"
#include "ui/ui_utility.h"
#include "ui/cached_round_corners.h"
#include "window/themes/window_theme.h"
#include "lang/lang_keys.h"
#include "app.h"
#include "styles/style_layers.h"
#include "styles/style_boxes.h"
@ -62,7 +62,7 @@ void WarningWidget::paintEvent(QPaintEvent *e) {
}
Ui::Shadow::paint(p, _inner, width(), st::boxRoundShadow);
App::roundRect(p, _inner, st::boxBg, BoxCorners);
Ui::FillRoundRect(p, _inner, st::boxBg, Ui::BoxCorners);
p.setFont(st::boxTitleFont);
p.setPen(st::boxTitleFg);

View file

@ -10,9 +10,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "lang/lang_keys.h"
#include "ui/widgets/buttons.h"
#include "ui/widgets/shadow.h"
#include "ui/cached_round_corners.h"
#include "mainwidget.h"
#include "facades.h"
#include "app.h"
#include "styles/style_layers.h"
#include "styles/style_chat.h"
@ -57,7 +57,7 @@ void HistoryHider::paintEvent(QPaintEvent *e) {
p.setFont(st::historyForwardChooseFont);
auto w = st::historyForwardChooseMargins.left() + _chooseWidth + st::historyForwardChooseMargins.right();
auto h = st::historyForwardChooseMargins.top() + st::historyForwardChooseFont->height + st::historyForwardChooseMargins.bottom();
App::roundRect(p, (width() - w) / 2, (height() - h) / 2, w, h, st::historyForwardChooseBg, ForwardCorners);
Ui::FillRoundRect(p, (width() - w) / 2, (height() - h) / 2, w, h, st::historyForwardChooseBg, Ui::ForwardCorners);
p.setPen(st::historyForwardChooseFg);
p.drawText(_box, _text, QTextOption(style::al_center));

View file

@ -9,11 +9,25 @@ init_target(td_ui)
add_library(tdesktop::td_ui ALIAS td_ui)
include(lib_ui/cmake/generate_styles.cmake)
include(cmake/generate_numbers.cmake)
set(style_files
ui/td_common.style
ui/filter_icons.style
ui/chat/chat.style
boxes/boxes.style
dialogs/dialogs.style
chat_helpers/chat_helpers.style
calls/calls.style
export/view/export.style
info/info.style
intro/intro.style
media/player/media_player.style
passport/passport.style
profile/profile.style
settings/settings.style
media/view/media_view.style
overview/overview.style
window/window.style
)
@ -25,14 +39,27 @@ set(dependent_style_files
)
generate_styles(td_ui ${src_loc} "${style_files}" "${dependent_style_files}")
generate_numbers(td_ui ${res_loc}/numbers.txt)
target_precompile_headers(td_ui PRIVATE ${src_loc}/ui/ui_pch.h)
nice_target_sources(td_ui ${src_loc}
PRIVATE
${style_files}
core/mime_type.cpp
core/mime_type.h
ui/chat/attach/attach_album_thumbnail.cpp
ui/chat/attach/attach_album_thumbnail.h
ui/chat/attach/attach_album_preview.cpp
ui/chat/attach/attach_album_preview.h
ui/chat/attach/attach_common.h
ui/chat/attach/attach_extensions.cpp
ui/chat/attach/attach_extensions.h
ui/chat/attach/attach_prepare.cpp
ui/chat/attach/attach_prepare.h
ui/chat/attach/attach_single_file_preview.cpp
ui/chat/attach/attach_single_file_preview.h
ui/chat/message_bar.cpp
ui/chat/message_bar.h
ui/chat/pinned_bar.cpp
@ -47,7 +74,11 @@ PRIVATE
ui/text/text_options.h
ui/toasts/common_toasts.cpp
ui/toasts/common_toasts.h
ui/cached_round_corners.cpp
ui/cached_round_corners.h
ui/grouped_layout.cpp
ui/grouped_layout.h
ui/ui_pch.h
)