mirror of https://github.com/procxx/kepka.git
Photo and video overview and background gallery checkboxes improved.
This commit is contained in:
parent
e880c4876e
commit
9fa284a6d1
Binary file not shown.
Before Width: | Height: | Size: 313 B After Width: | Height: | Size: 309 B |
Binary file not shown.
Before Width: | Height: | Size: 632 B After Width: | Height: | Size: 623 B |
|
@ -27,6 +27,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||||
#include "window/window_theme.h"
|
#include "window/window_theme.h"
|
||||||
#include "styles/style_overview.h"
|
#include "styles/style_overview.h"
|
||||||
#include "styles/style_boxes.h"
|
#include "styles/style_boxes.h"
|
||||||
|
#include "ui/effects/round_image_checkbox.h"
|
||||||
|
|
||||||
BackgroundBox::BackgroundBox() : ItemListBox(st::backgroundScroll)
|
BackgroundBox::BackgroundBox() : ItemListBox(st::backgroundScroll)
|
||||||
, _inner(this) {
|
, _inner(this) {
|
||||||
|
@ -50,10 +51,8 @@ void BackgroundBox::onBackgroundChosen(int index) {
|
||||||
}
|
}
|
||||||
|
|
||||||
BackgroundBox::Inner::Inner(QWidget *parent) : TWidget(parent)
|
BackgroundBox::Inner::Inner(QWidget *parent) : TWidget(parent)
|
||||||
, _bgCount(0)
|
, _check(std_::make_unique<Ui::RoundCheckbox>(st::overviewCheck, [this] { update(); })) {
|
||||||
, _rows(0)
|
_check->setChecked(true, Ui::RoundCheckbox::SetStyle::Fast);
|
||||||
, _over(-1)
|
|
||||||
, _overDown(-1) {
|
|
||||||
if (App::cServerBackgrounds().isEmpty()) {
|
if (App::cServerBackgrounds().isEmpty()) {
|
||||||
resize(BackgroundsInRow * (st::backgroundSize.width() + st::backgroundPadding) + st::backgroundPadding, 2 * (st::backgroundSize.height() + st::backgroundPadding) + st::backgroundPadding);
|
resize(BackgroundsInRow * (st::backgroundSize.width() + st::backgroundPadding) + st::backgroundPadding, 2 * (st::backgroundSize.height() + st::backgroundPadding) + st::backgroundPadding);
|
||||||
MTP::send(MTPaccount_GetWallPapers(), rpcDone(&Inner::gotWallpapers));
|
MTP::send(MTPaccount_GetWallPapers(), rpcDone(&Inner::gotWallpapers));
|
||||||
|
@ -157,9 +156,9 @@ void BackgroundBox::Inner::paintEvent(QPaintEvent *e) {
|
||||||
p.drawPixmap(x, y, pix);
|
p.drawPixmap(x, y, pix);
|
||||||
|
|
||||||
if (paper.id == Window::Theme::Background()->id()) {
|
if (paper.id == Window::Theme::Background()->id()) {
|
||||||
int checkPosX = x + st::backgroundSize.width() - st::overviewPhotoChecked.width();
|
auto checkLeft = x + st::backgroundSize.width() - st::overviewCheckSkip - st::overviewCheck.size;
|
||||||
int checkPosY = y + st::backgroundSize.height() - st::overviewPhotoChecked.height();
|
auto checkTop = y + st::backgroundSize.height() - st::overviewCheckSkip - st::overviewCheck.size;
|
||||||
st::overviewPhotoChecked.paint(p, QPoint(checkPosX, checkPosY), width());
|
_check->paint(p, getms(), checkLeft, checkTop, width());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -198,5 +197,4 @@ void BackgroundBox::Inner::mouseReleaseEvent(QMouseEvent *e) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BackgroundBox::Inner::resizeEvent(QResizeEvent *e) {
|
BackgroundBox::Inner::~Inner() = default;
|
||||||
}
|
|
||||||
|
|
|
@ -22,6 +22,10 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||||
|
|
||||||
#include "boxes/abstractbox.h"
|
#include "boxes/abstractbox.h"
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class RoundCheckbox;
|
||||||
|
} // namespace Ui
|
||||||
|
|
||||||
class BackgroundBox : public ItemListBox {
|
class BackgroundBox : public ItemListBox {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
@ -43,6 +47,7 @@ class BackgroundBox::Inner : public TWidget, public RPCSender, private base::Sub
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Inner(QWidget *parent);
|
Inner(QWidget *parent);
|
||||||
|
~Inner();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void backgroundChosen(int index);
|
void backgroundChosen(int index);
|
||||||
|
@ -52,13 +57,15 @@ protected:
|
||||||
void mouseMoveEvent(QMouseEvent *e) override;
|
void mouseMoveEvent(QMouseEvent *e) override;
|
||||||
void mousePressEvent(QMouseEvent *e) override;
|
void mousePressEvent(QMouseEvent *e) override;
|
||||||
void mouseReleaseEvent(QMouseEvent *e) override;
|
void mouseReleaseEvent(QMouseEvent *e) override;
|
||||||
void resizeEvent(QResizeEvent *e) override;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void gotWallpapers(const MTPVector<MTPWallPaper> &result);
|
void gotWallpapers(const MTPVector<MTPWallPaper> &result);
|
||||||
void updateWallpapers();
|
void updateWallpapers();
|
||||||
|
|
||||||
int32 _bgCount, _rows;
|
int _bgCount = 0;
|
||||||
int32 _over, _overDown;
|
int _rows = 0;
|
||||||
|
int _over = -1;
|
||||||
|
int _overDown = -1;
|
||||||
|
std_::unique_ptr<Ui::RoundCheckbox> _check;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -304,11 +304,11 @@ contactsPhotoCheckbox: RoundImageCheckbox {
|
||||||
selectWidth: 2px;
|
selectWidth: 2px;
|
||||||
selectFg: windowBgActive;
|
selectFg: windowBgActive;
|
||||||
selectDuration: 150;
|
selectDuration: 150;
|
||||||
checkBorder: windowBg;
|
check: RoundCheckbox(defaultRoundCheckbox) {
|
||||||
checkBg: windowBgActive;
|
size: 20px;
|
||||||
checkRadius: 10px;
|
sizeSmall: 0.3;
|
||||||
checkSmallRadius: 3px;
|
check: icon {{ "default_checkbox_check", windowFgActive, point(3px, 6px) }};
|
||||||
checkIcon: icon {{ "default_checkbox_check", windowFgActive, point(3px, 6px) }};
|
}
|
||||||
}
|
}
|
||||||
contactsPhotoDisabledCheckFg: #bbbbbb;
|
contactsPhotoDisabledCheckFg: #bbbbbb;
|
||||||
contactsNameCheckedFg: #2b88b8;
|
contactsNameCheckedFg: #2b88b8;
|
||||||
|
|
|
@ -1002,11 +1002,11 @@ void ContactsBox::Inner::paintDisabledCheckUserpic(Painter &p, PeerData *peer, i
|
||||||
auto userpicBorderPen = st::contactsPhotoDisabledCheckFg->p;
|
auto userpicBorderPen = st::contactsPhotoDisabledCheckFg->p;
|
||||||
userpicBorderPen.setWidth(st::contactsPhotoCheckbox.selectWidth);
|
userpicBorderPen.setWidth(st::contactsPhotoCheckbox.selectWidth);
|
||||||
|
|
||||||
auto iconDiameter = 2 * st::contactsPhotoCheckbox.checkRadius;
|
auto iconDiameter = st::contactsPhotoCheckbox.check.size;
|
||||||
auto iconLeft = x + userpicDiameter + st::contactsPhotoCheckbox.selectWidth - iconDiameter;
|
auto iconLeft = x + userpicDiameter + st::contactsPhotoCheckbox.selectWidth - iconDiameter;
|
||||||
auto iconTop = y + userpicDiameter + st::contactsPhotoCheckbox.selectWidth - iconDiameter;
|
auto iconTop = y + userpicDiameter + st::contactsPhotoCheckbox.selectWidth - iconDiameter;
|
||||||
auto iconEllipse = rtlrect(iconLeft, iconTop, iconDiameter, iconDiameter, outerWidth);
|
auto iconEllipse = rtlrect(iconLeft, iconTop, iconDiameter, iconDiameter, outerWidth);
|
||||||
auto iconBorderPen = st::contactsPhotoCheckbox.checkBorder->p;
|
auto iconBorderPen = st::contactsPhotoCheckbox.check.border->p;
|
||||||
iconBorderPen.setWidth(st::contactsPhotoCheckbox.selectWidth);
|
iconBorderPen.setWidth(st::contactsPhotoCheckbox.selectWidth);
|
||||||
|
|
||||||
peer->paintUserpicLeft(p, userpicRadius * 2, userpicLeft, userpicTop, width());
|
peer->paintUserpicLeft(p, userpicRadius * 2, userpicLeft, userpicTop, width());
|
||||||
|
@ -1023,7 +1023,7 @@ void ContactsBox::Inner::paintDisabledCheckUserpic(Painter &p, PeerData *peer, i
|
||||||
|
|
||||||
p.setRenderHint(QPainter::HighQualityAntialiasing, false);
|
p.setRenderHint(QPainter::HighQualityAntialiasing, false);
|
||||||
|
|
||||||
st::contactsPhotoCheckbox.checkIcon.paint(p, iconEllipse.topLeft(), outerWidth);
|
st::contactsPhotoCheckbox.check.check.paint(p, iconEllipse.topLeft(), outerWidth);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ContactsBox::Inner::paintEvent(QPaintEvent *e) {
|
void ContactsBox::Inner::paintEvent(QPaintEvent *e) {
|
||||||
|
|
|
@ -2082,8 +2082,8 @@ void MainWidget::fillPeerMenu(PeerData *peer, base::lambda<QAction*(const QStrin
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (peer->isChat()) {
|
} else if (peer->isChat()) {
|
||||||
callback(lang(lng_profile_clear_history), std_::move(clearHistoryHandler));
|
|
||||||
callback(lang(lng_profile_clear_and_exit), std_::move(deleteAndLeaveHandler));
|
callback(lang(lng_profile_clear_and_exit), std_::move(deleteAndLeaveHandler));
|
||||||
|
callback(lang(lng_profile_clear_history), std_::move(clearHistoryHandler));
|
||||||
} else if (peer->isChannel() && peer->asChannel()->amIn() && !peer->asChannel()->amCreator()) {
|
} else if (peer->isChannel() && peer->asChannel()->amIn() && !peer->asChannel()->amCreator()) {
|
||||||
callback(lang(peer->isMegagroup() ? lng_profile_leave_group : lng_profile_leave_channel), std_::move(deleteAndLeaveHandler));
|
callback(lang(peer->isMegagroup() ? lng_profile_leave_group : lng_profile_leave_channel), std_::move(deleteAndLeaveHandler));
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,21 +43,22 @@ OverviewFileLayout {
|
||||||
fileDateTop: pixels;
|
fileDateTop: pixels;
|
||||||
}
|
}
|
||||||
|
|
||||||
overviewCheckBg: #00000042;
|
overviewCheckBg: #00000040;
|
||||||
overviewCheckedBg: #2fa9e2;
|
overviewCheckFg: windowBg;
|
||||||
|
overviewCheckFgActive: windowBg;
|
||||||
|
overviewCheckPressedSize: 0.8;
|
||||||
|
overviewCheck: RoundCheckbox(defaultRoundCheckbox) {
|
||||||
|
bgInactive: overviewCheckBg;
|
||||||
|
size: 29px;
|
||||||
|
sizeSmall: 0.3;
|
||||||
|
check: icon {{ "overview_photo_check", overviewCheckFgActive, point(4px, 8px) }};
|
||||||
|
}
|
||||||
|
overviewCheckSkip: 5px;
|
||||||
|
|
||||||
overviewPhotoSkip: 10px;
|
overviewPhotoSkip: 10px;
|
||||||
overviewPhotoBg: #F1F1F1;
|
overviewPhotoBg: #F1F1F1;
|
||||||
overviewPhotoMinSize: minPhotoSize;
|
overviewPhotoMinSize: minPhotoSize;
|
||||||
overviewPhotoCheck: icon {
|
overviewPhotoSelectOverlay: #40ace333;
|
||||||
{ size(31px, 31px), overviewCheckBg },
|
|
||||||
{ "overview_photo_check", #ffffff, point(4px, 8px) },
|
|
||||||
};
|
|
||||||
overviewPhotoChecked: icon {
|
|
||||||
{ size(31px, 31px), overviewCheckedBg },
|
|
||||||
{ "overview_photo_check", #ffffff, point(4px, 8px) },
|
|
||||||
};
|
|
||||||
overviewPhotoSelectOverlay: #0a7bb03f;
|
|
||||||
|
|
||||||
overviewVideoBg: #000000;
|
overviewVideoBg: #000000;
|
||||||
|
|
||||||
|
@ -111,11 +112,11 @@ linksPhotoSize: 46px;
|
||||||
linksPhotoPadding: 12px;
|
linksPhotoPadding: 12px;
|
||||||
overviewLinksCheck: icon {
|
overviewLinksCheck: icon {
|
||||||
{ "overview_links_check_bg", overviewCheckBg },
|
{ "overview_links_check_bg", overviewCheckBg },
|
||||||
{ "overview_links_check", #ffffff, point(4px, 5px) },
|
{ "overview_links_check", overviewCheckFg, point(4px, 5px) },
|
||||||
};
|
};
|
||||||
overviewLinksChecked: icon {
|
overviewLinksChecked: icon {
|
||||||
{ "overview_links_check_bg", overviewCheckedBg },
|
{ "overview_links_check_bg", windowBgActive },
|
||||||
{ "overview_links_check", #ffffff, point(4px, 5px) },
|
{ "overview_links_check", overviewCheckFgActive, point(4px, 5px) },
|
||||||
};
|
};
|
||||||
|
|
||||||
overviewFilter: FlatInput(defaultFlatInput) {
|
overviewFilter: FlatInput(defaultFlatInput) {
|
||||||
|
|
|
@ -35,6 +35,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||||
#include "media/player/media_player_instance.h"
|
#include "media/player/media_player_instance.h"
|
||||||
#include "localstorage.h"
|
#include "localstorage.h"
|
||||||
#include "history/history_media_types.h"
|
#include "history/history_media_types.h"
|
||||||
|
#include "ui/effects/round_image_checkbox.h"
|
||||||
|
|
||||||
namespace Overview {
|
namespace Overview {
|
||||||
namespace Layout {
|
namespace Layout {
|
||||||
|
@ -101,7 +102,7 @@ void RadialProgressItem::step_radial(uint64 ms, bool timer) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RadialProgressItem::ensureRadial() const {
|
void RadialProgressItem::ensureRadial() {
|
||||||
if (!_radial) {
|
if (!_radial) {
|
||||||
_radial = new Ui::RadialAnimation(animation(const_cast<RadialProgressItem*>(this), &RadialProgressItem::step_radial));
|
_radial = new Ui::RadialAnimation(animation(const_cast<RadialProgressItem*>(this), &RadialProgressItem::step_radial));
|
||||||
}
|
}
|
||||||
|
@ -118,21 +119,25 @@ RadialProgressItem::~RadialProgressItem() {
|
||||||
delete base::take(_radial);
|
delete base::take(_radial);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileBase::setStatusSize(int32 newSize, int32 fullSize, int32 duration, qint64 realDuration) const {
|
void StatusText::update(int newSize, int fullSize, int duration, int64 realDuration) {
|
||||||
_statusSize = newSize;
|
setSize(newSize);
|
||||||
if (_statusSize == FileStatusSizeReady) {
|
if (_size == FileStatusSizeReady) {
|
||||||
_statusText = (duration >= 0) ? formatDurationAndSizeText(duration, fullSize) : (duration < -1 ? formatGifAndSizeText(fullSize) : formatSizeText(fullSize));
|
_text = (duration >= 0) ? formatDurationAndSizeText(duration, fullSize) : (duration < -1 ? formatGifAndSizeText(fullSize) : formatSizeText(fullSize));
|
||||||
} else if (_statusSize == FileStatusSizeLoaded) {
|
} else if (_size == FileStatusSizeLoaded) {
|
||||||
_statusText = (duration >= 0) ? formatDurationText(duration) : (duration < -1 ? qsl("GIF") : formatSizeText(fullSize));
|
_text = (duration >= 0) ? formatDurationText(duration) : (duration < -1 ? qsl("GIF") : formatSizeText(fullSize));
|
||||||
} else if (_statusSize == FileStatusSizeFailed) {
|
} else if (_size == FileStatusSizeFailed) {
|
||||||
_statusText = lang(lng_attach_failed);
|
_text = lang(lng_attach_failed);
|
||||||
} else if (_statusSize >= 0) {
|
} else if (_size >= 0) {
|
||||||
_statusText = formatDownloadText(_statusSize, fullSize);
|
_text = formatDownloadText(_size, fullSize);
|
||||||
} else {
|
} else {
|
||||||
_statusText = formatPlayedText(-_statusSize - 1, realDuration);
|
_text = formatPlayedText(-_size - 1, realDuration);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void StatusText::setSize(int newSize) {
|
||||||
|
_size = newSize;
|
||||||
|
}
|
||||||
|
|
||||||
Date::Date(const QDate &date, bool month)
|
Date::Date(const QDate &date, bool month)
|
||||||
: _date(date)
|
: _date(date)
|
||||||
, _text(month ? langMonthFull(date) : langDayOfMonthFull(date)) {
|
, _text(month ? langMonthFull(date) : langDayOfMonthFull(date)) {
|
||||||
|
@ -144,7 +149,7 @@ void Date::initDimensions() {
|
||||||
_minh = st::linksDateMargin.top() + st::normalFont->height + st::linksDateMargin.bottom() + st::linksBorder;
|
_minh = st::linksDateMargin.top() + st::normalFont->height + st::linksDateMargin.bottom() + st::linksBorder;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Date::paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) const {
|
void Date::paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) {
|
||||||
if (clip.intersects(QRect(0, st::linksDateMargin.top(), _width, st::normalFont->height))) {
|
if (clip.intersects(QRect(0, st::linksDateMargin.top(), _width, st::normalFont->height))) {
|
||||||
p.setPen(st::linksDateColor);
|
p.setPen(st::linksDateColor);
|
||||||
p.setFont(st::semiboldFont);
|
p.setFont(st::semiboldFont);
|
||||||
|
@ -152,25 +157,62 @@ void Date::paint(Painter &p, const QRect &clip, TextSelection selection, const P
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
class PhotoVideoCheckbox {
|
||||||
|
public:
|
||||||
|
template <typename UpdateCallback>
|
||||||
|
PhotoVideoCheckbox(UpdateCallback callback) : _updateCallback(callback), _check(st::overviewCheck, _updateCallback) {
|
||||||
|
}
|
||||||
|
|
||||||
void paintPhotoVideoCheck(Painter &p, int width, int height, bool selected) {
|
void paint(Painter &p, uint64 ms, int width, int height, bool selected, bool selecting);
|
||||||
int checkPosX = width - st::overviewPhotoCheck.width();
|
|
||||||
int checkPosY = height - st::overviewPhotoCheck.height();
|
void setActive(bool active);
|
||||||
|
void setPressed(bool pressed);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void startAnimation();
|
||||||
|
|
||||||
|
base::lambda_copy<void()> _updateCallback;
|
||||||
|
Ui::RoundCheckbox _check;
|
||||||
|
|
||||||
|
FloatAnimation _pression;
|
||||||
|
bool _active = false;
|
||||||
|
bool _pressed = false;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
void PhotoVideoCheckbox::paint(Painter &p, uint64 ms, int width, int height, bool selected, bool selecting) {
|
||||||
if (selected) {
|
if (selected) {
|
||||||
p.fillRect(QRect(0, 0, width, height), st::overviewPhotoSelectOverlay);
|
p.fillRect(0, 0, width, height, st::overviewPhotoSelectOverlay);
|
||||||
st::overviewPhotoChecked.paint(p, QPoint(checkPosX, checkPosY), width);
|
}
|
||||||
} else {
|
_check.setDisplayInactive(selecting);
|
||||||
st::overviewPhotoCheck.paint(p, QPoint(checkPosX, checkPosY), width);
|
_check.setChecked(selected);
|
||||||
|
auto pression = _pression.current(ms, (_active && _pressed) ? 1. : 0.);
|
||||||
|
auto masterScale = 1. - (1. - st::overviewCheckPressedSize) * pression;
|
||||||
|
_check.paint(p, ms, width - st::overviewCheckSkip - st::overviewCheck.size, height - st::overviewCheckSkip - st::overviewCheck.size, width, masterScale);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PhotoVideoCheckbox::setActive(bool active) {
|
||||||
|
_active = active;
|
||||||
|
if (_pressed) {
|
||||||
|
startAnimation();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
void PhotoVideoCheckbox::setPressed(bool pressed) {
|
||||||
|
_pressed = pressed;
|
||||||
|
if (_active) {
|
||||||
|
startAnimation();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PhotoVideoCheckbox::startAnimation() {
|
||||||
|
auto showPressed = (_pressed && _active);
|
||||||
|
_pression.start(_updateCallback, showPressed ? 0. : 1., showPressed ? 1. : 0., st::overviewCheck.duration);
|
||||||
|
}
|
||||||
|
|
||||||
Photo::Photo(PhotoData *photo, HistoryItem *parent) : ItemBase(parent)
|
Photo::Photo(PhotoData *photo, HistoryItem *parent) : ItemBase(parent)
|
||||||
, _data(photo)
|
, _data(photo)
|
||||||
, _link(new PhotoOpenClickHandler(photo))
|
, _link(new PhotoOpenClickHandler(photo)) {
|
||||||
, _goodLoaded(false) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Photo::initDimensions() {
|
void Photo::initDimensions() {
|
||||||
|
@ -187,7 +229,7 @@ int32 Photo::resizeGetHeight(int32 width) {
|
||||||
return _height;
|
return _height;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Photo::paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) const {
|
void Photo::paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) {
|
||||||
bool good = _data->loaded(), selected = (selection == FullSelection);
|
bool good = _data->loaded(), selected = (selection == FullSelection);
|
||||||
if (!good) {
|
if (!good) {
|
||||||
_data->medium->automaticLoad(_parent);
|
_data->medium->automaticLoad(_parent);
|
||||||
|
@ -225,9 +267,19 @@ void Photo::paint(Painter &p, const QRect &clip, TextSelection selection, const
|
||||||
} else {
|
} else {
|
||||||
p.drawPixmap(0, 0, _pix);
|
p.drawPixmap(0, 0, _pix);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (selected || context->selecting) {
|
if (selected || context->selecting) {
|
||||||
paintPhotoVideoCheck(p, _width, _height, selected);
|
ensureCheckboxCreated();
|
||||||
}
|
}
|
||||||
|
if (_check) {
|
||||||
|
_check->paint(p, context->ms, _width, _height, selected, context->selecting);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Photo::ensureCheckboxCreated() {
|
||||||
|
if (!_check) _check = std_::make_unique<PhotoVideoCheckbox>([this] {
|
||||||
|
Ui::repaintHistoryItem(_parent);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void Photo::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const {
|
void Photo::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const {
|
||||||
|
@ -236,7 +288,19 @@ void Photo::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, i
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Video::Video(DocumentData *video, HistoryItem *parent) : FileBase(parent)
|
void Photo::clickHandlerActiveChanged(const ClickHandlerPtr &action, bool active) {
|
||||||
|
if (_check) {
|
||||||
|
_check->setActive(active);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Photo::clickHandlerPressedChanged(const ClickHandlerPtr &action, bool pressed) {
|
||||||
|
if (_check) {
|
||||||
|
_check->setPressed(pressed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Video::Video(DocumentData *video, HistoryItem *parent) : RadialProgressItem(parent)
|
||||||
, _data(video)
|
, _data(video)
|
||||||
, _duration(formatDurationText(_data->duration()))
|
, _duration(formatDurationText(_data->duration()))
|
||||||
, _thumbLoaded(false) {
|
, _thumbLoaded(false) {
|
||||||
|
@ -254,7 +318,7 @@ int32 Video::resizeGetHeight(int32 width) {
|
||||||
return _height;
|
return _height;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Video::paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) const {
|
void Video::paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) {
|
||||||
bool selected = (selection == FullSelection), thumbLoaded = _data->thumb->loaded();
|
bool selected = (selection == FullSelection), thumbLoaded = _data->thumb->loaded();
|
||||||
|
|
||||||
_data->automaticLoad(_parent);
|
_data->automaticLoad(_parent);
|
||||||
|
@ -305,13 +369,13 @@ void Video::paint(Painter &p, const QRect &clip, TextSelection selection, const
|
||||||
if (!selected && !context->selecting && !loaded) {
|
if (!selected && !context->selecting && !loaded) {
|
||||||
if (clip.intersects(QRect(0, _height - st::normalFont->height, _width, st::normalFont->height))) {
|
if (clip.intersects(QRect(0, _height - st::normalFont->height, _width, st::normalFont->height))) {
|
||||||
int32 statusX = st::msgDateImgPadding.x(), statusY = _height - st::normalFont->height - st::msgDateImgPadding.y();
|
int32 statusX = st::msgDateImgPadding.x(), statusY = _height - st::normalFont->height - st::msgDateImgPadding.y();
|
||||||
int32 statusW = st::normalFont->width(_statusText) + 2 * st::msgDateImgPadding.x();
|
int32 statusW = st::normalFont->width(_status.text()) + 2 * st::msgDateImgPadding.x();
|
||||||
int32 statusH = st::normalFont->height + 2 * st::msgDateImgPadding.y();
|
int32 statusH = st::normalFont->height + 2 * st::msgDateImgPadding.y();
|
||||||
statusX = _width - statusW + statusX;
|
statusX = _width - statusW + statusX;
|
||||||
p.fillRect(rtlrect(statusX - st::msgDateImgPadding.x(), statusY - st::msgDateImgPadding.y(), statusW, statusH, _width), selected ? st::msgDateImgBgSelected : st::msgDateImgBg);
|
p.fillRect(rtlrect(statusX - st::msgDateImgPadding.x(), statusY - st::msgDateImgPadding.y(), statusW, statusH, _width), selected ? st::msgDateImgBgSelected : st::msgDateImgBg);
|
||||||
p.setFont(st::normalFont);
|
p.setFont(st::normalFont);
|
||||||
p.setPen(st::msgDateImgColor);
|
p.setPen(st::msgDateImgColor);
|
||||||
p.drawTextLeft(statusX, statusY, _width, _statusText, statusW - 2 * st::msgDateImgPadding.x());
|
p.drawTextLeft(statusX, statusY, _width, _status.text(), statusW - 2 * st::msgDateImgPadding.x());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (clip.intersects(QRect(0, 0, _width, st::normalFont->height))) {
|
if (clip.intersects(QRect(0, 0, _width, st::normalFont->height))) {
|
||||||
|
@ -358,8 +422,32 @@ void Video::paint(Painter &p, const QRect &clip, TextSelection selection, const
|
||||||
_radial->draw(p, rinner, st::msgFileRadialLine, selected ? st::msgInBgSelected : st::msgInBg);
|
_radial->draw(p, rinner, st::msgFileRadialLine, selected ? st::msgInBgSelected : st::msgInBg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (selected || context->selecting) {
|
if (selected || context->selecting) {
|
||||||
paintPhotoVideoCheck(p, _width, _height, selected);
|
ensureCheckboxCreated();
|
||||||
|
}
|
||||||
|
if (_check) {
|
||||||
|
_check->paint(p, context->ms, _width, _height, selected, context->selecting);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Video::ensureCheckboxCreated() {
|
||||||
|
if (!_check) _check = std_::make_unique<PhotoVideoCheckbox>([this] {
|
||||||
|
Ui::repaintHistoryItem(_parent);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void Video::clickHandlerActiveChanged(const ClickHandlerPtr &action, bool active) {
|
||||||
|
RadialProgressItem::clickHandlerActiveChanged(action, active);
|
||||||
|
if (_check) {
|
||||||
|
_check->setActive(active);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Video::clickHandlerPressedChanged(const ClickHandlerPtr &action, bool pressed) {
|
||||||
|
RadialProgressItem::clickHandlerPressedChanged(action, pressed);
|
||||||
|
if (_check) {
|
||||||
|
_check->setPressed(pressed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -371,9 +459,9 @@ void Video::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, i
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Video::updateStatusText() const {
|
void Video::updateStatusText() {
|
||||||
bool showPause = false;
|
bool showPause = false;
|
||||||
int32 statusSize = 0;
|
int statusSize = 0;
|
||||||
if (_data->status == FileDownloadFailed || _data->status == FileUploadFailed) {
|
if (_data->status == FileDownloadFailed || _data->status == FileUploadFailed) {
|
||||||
statusSize = FileStatusSizeFailed;
|
statusSize = FileStatusSizeFailed;
|
||||||
} else if (_data->status == FileUploading) {
|
} else if (_data->status == FileUploading) {
|
||||||
|
@ -385,18 +473,18 @@ void Video::updateStatusText() const {
|
||||||
} else {
|
} else {
|
||||||
statusSize = FileStatusSizeReady;
|
statusSize = FileStatusSizeReady;
|
||||||
}
|
}
|
||||||
if (statusSize != _statusSize) {
|
if (statusSize != _status.size()) {
|
||||||
int32 status = statusSize, size = _data->size;
|
int status = statusSize, size = _data->size;
|
||||||
if (statusSize >= 0 && statusSize < 0x7F000000) {
|
if (statusSize >= 0 && statusSize < 0x7F000000) {
|
||||||
size = status;
|
size = status;
|
||||||
status = FileStatusSizeReady;
|
status = FileStatusSizeReady;
|
||||||
}
|
}
|
||||||
setStatusSize(status, size, -1, 0);
|
_status.update(status, size, -1, 0);
|
||||||
_statusSize = statusSize;
|
_status.setSize(statusSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Voice::Voice(DocumentData *voice, HistoryItem *parent) : FileBase(parent)
|
Voice::Voice(DocumentData *voice, HistoryItem *parent) : RadialProgressItem(parent)
|
||||||
, _data(voice)
|
, _data(voice)
|
||||||
, _namel(new DocumentOpenClickHandler(_data)) {
|
, _namel(new DocumentOpenClickHandler(_data)) {
|
||||||
AddComponents(Info::Bit());
|
AddComponents(Info::Bit());
|
||||||
|
@ -417,7 +505,7 @@ void Voice::initDimensions() {
|
||||||
_minh = st::overviewFileLayout.songPadding.top() + st::overviewFileLayout.songThumbSize + st::overviewFileLayout.songPadding.bottom() + st::lineWidth;
|
_minh = st::overviewFileLayout.songPadding.top() + st::overviewFileLayout.songThumbSize + st::overviewFileLayout.songPadding.bottom() + st::lineWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Voice::paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) const {
|
void Voice::paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) {
|
||||||
bool selected = (selection == FullSelection);
|
bool selected = (selection == FullSelection);
|
||||||
|
|
||||||
_data->automaticLoad(_parent);
|
_data->automaticLoad(_parent);
|
||||||
|
@ -474,7 +562,7 @@ void Voice::paint(Painter &p, const QRect &clip, TextSelection selection, const
|
||||||
auto icon = ([showPause, this, selected] {
|
auto icon = ([showPause, this, selected] {
|
||||||
if (showPause) {
|
if (showPause) {
|
||||||
return &(selected ? st::historyFileInPauseSelected : st::historyFileInPause);
|
return &(selected ? st::historyFileInPauseSelected : st::historyFileInPause);
|
||||||
} else if (_statusSize < 0 || _statusSize == FileStatusSizeLoaded) {
|
} else if (_status.size() < 0 || _status.size() == FileStatusSizeLoaded) {
|
||||||
return &(selected ? st::historyFileInPlaySelected : st::historyFileInPlay);
|
return &(selected ? st::historyFileInPlaySelected : st::historyFileInPlay);
|
||||||
} else if (_data->loading()) {
|
} else if (_data->loading()) {
|
||||||
return &(selected ? st::historyFileInCancelSelected : st::historyFileInCancel);
|
return &(selected ? st::historyFileInCancelSelected : st::historyFileInCancel);
|
||||||
|
@ -495,14 +583,14 @@ void Voice::paint(Painter &p, const QRect &clip, TextSelection selection, const
|
||||||
p.setFont(st::normalFont);
|
p.setFont(st::normalFont);
|
||||||
p.setPen(selected ? st::mediaInFgSelected : st::mediaInFg);
|
p.setPen(selected ? st::mediaInFgSelected : st::mediaInFg);
|
||||||
int32 unreadx = nameleft;
|
int32 unreadx = nameleft;
|
||||||
if (_statusSize == FileStatusSizeLoaded || _statusSize == FileStatusSizeReady) {
|
if (_status.size() == FileStatusSizeLoaded || _status.size() == FileStatusSizeReady) {
|
||||||
textstyleSet(&(selected ? st::mediaInStyleSelected : st::mediaInStyle));
|
textstyleSet(&(selected ? st::mediaInStyleSelected : st::mediaInStyle));
|
||||||
_details.drawLeftElided(p, nameleft, statustop, namewidth, _width);
|
_details.drawLeftElided(p, nameleft, statustop, namewidth, _width);
|
||||||
textstyleRestore();
|
textstyleRestore();
|
||||||
unreadx += _details.maxWidth();
|
unreadx += _details.maxWidth();
|
||||||
} else {
|
} else {
|
||||||
int32 statusw = st::normalFont->width(_statusText);
|
int32 statusw = st::normalFont->width(_status.text());
|
||||||
p.drawTextLeft(nameleft, statustop, _width, _statusText, statusw);
|
p.drawTextLeft(nameleft, statustop, _width, _status.text(), statusw);
|
||||||
unreadx += statusw;
|
unreadx += statusw;
|
||||||
}
|
}
|
||||||
if (_parent->isMediaUnread() && unreadx + st::mediaUnreadSkip + st::mediaUnreadSize <= _width) {
|
if (_parent->isMediaUnread() && unreadx + st::mediaUnreadSkip + st::mediaUnreadSize <= _width) {
|
||||||
|
@ -519,8 +607,6 @@ void Voice::paint(Painter &p, const QRect &clip, TextSelection selection, const
|
||||||
void Voice::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const {
|
void Voice::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const {
|
||||||
bool loaded = _data->loaded();
|
bool loaded = _data->loaded();
|
||||||
|
|
||||||
bool showPause = updateStatusText();
|
|
||||||
|
|
||||||
int32 nameleft = 0, nametop = 0, nameright = 0, statustop = 0, datetop = 0;
|
int32 nameleft = 0, nametop = 0, nameright = 0, statustop = 0, datetop = 0;
|
||||||
|
|
||||||
nameleft = st::overviewFileLayout.songPadding.left() + st::overviewFileLayout.songThumbSize + st::overviewFileLayout.songPadding.right();
|
nameleft = st::overviewFileLayout.songPadding.left() + st::overviewFileLayout.songThumbSize + st::overviewFileLayout.songPadding.right();
|
||||||
|
@ -534,7 +620,7 @@ void Voice::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, i
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (rtlrect(nameleft, statustop, _width - nameleft - nameright, st::normalFont->height, _width).contains(x, y)) {
|
if (rtlrect(nameleft, statustop, _width - nameleft - nameright, st::normalFont->height, _width).contains(x, y)) {
|
||||||
if (_statusSize == FileStatusSizeLoaded || _statusSize == FileStatusSizeReady) {
|
if (_status.size() == FileStatusSizeLoaded || _status.size() == FileStatusSizeReady) {
|
||||||
auto textState = _details.getStateLeft(x - nameleft, y - statustop, _width, _width);
|
auto textState = _details.getStateLeft(x - nameleft, y - statustop, _width, _width);
|
||||||
link = textState.link;
|
link = textState.link;
|
||||||
cursor = textState.uponSymbol ? HistoryInTextCursorState : HistoryDefaultCursorState;
|
cursor = textState.uponSymbol ? HistoryInTextCursorState : HistoryDefaultCursorState;
|
||||||
|
@ -546,7 +632,7 @@ void Voice::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, i
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Voice::updateName() const {
|
void Voice::updateName() {
|
||||||
int32 version = 0;
|
int32 version = 0;
|
||||||
if (const HistoryMessageForwarded *fwd = _parent->Get<HistoryMessageForwarded>()) {
|
if (const HistoryMessageForwarded *fwd = _parent->Get<HistoryMessageForwarded>()) {
|
||||||
if (_parent->fromOriginal()->isChannel()) {
|
if (_parent->fromOriginal()->isChannel()) {
|
||||||
|
@ -561,7 +647,7 @@ void Voice::updateName() const {
|
||||||
_nameVersion = version;
|
_nameVersion = version;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Voice::updateStatusText() const {
|
bool Voice::updateStatusText() {
|
||||||
bool showPause = false;
|
bool showPause = false;
|
||||||
int32 statusSize = 0, realDuration = 0;
|
int32 statusSize = 0, realDuration = 0;
|
||||||
if (_data->status == FileDownloadFailed || _data->status == FileUploadFailed) {
|
if (_data->status == FileDownloadFailed || _data->status == FileUploadFailed) {
|
||||||
|
@ -580,13 +666,13 @@ bool Voice::updateStatusText() const {
|
||||||
} else {
|
} else {
|
||||||
statusSize = FileStatusSizeReady;
|
statusSize = FileStatusSizeReady;
|
||||||
}
|
}
|
||||||
if (statusSize != _statusSize) {
|
if (statusSize != _status.size()) {
|
||||||
setStatusSize(statusSize, _data->size, _data->voice()->duration, realDuration);
|
_status.update(statusSize, _data->size, _data->voice()->duration, realDuration);
|
||||||
}
|
}
|
||||||
return showPause;
|
return showPause;
|
||||||
}
|
}
|
||||||
|
|
||||||
Document::Document(DocumentData *document, HistoryItem *parent, const style::OverviewFileLayout &st) : FileBase(parent)
|
Document::Document(DocumentData *document, HistoryItem *parent, const style::OverviewFileLayout &st) : RadialProgressItem(parent)
|
||||||
, _data(document)
|
, _data(document)
|
||||||
, _msgl(goToMessageClickHandler(parent))
|
, _msgl(goToMessageClickHandler(parent))
|
||||||
, _namel(new DocumentOpenClickHandler(_data))
|
, _namel(new DocumentOpenClickHandler(_data))
|
||||||
|
@ -600,7 +686,7 @@ Document::Document(DocumentData *document, HistoryItem *parent, const style::Ove
|
||||||
|
|
||||||
setDocumentLinks(_data);
|
setDocumentLinks(_data);
|
||||||
|
|
||||||
setStatusSize(FileStatusSizeReady, _data->size, _data->song() ? _data->song()->duration : -1, 0);
|
_status.update(FileStatusSizeReady, _data->size, _data->song() ? _data->song()->duration : -1, 0);
|
||||||
|
|
||||||
if (withThumb()) {
|
if (withThumb()) {
|
||||||
_data->thumb->load();
|
_data->thumb->load();
|
||||||
|
@ -630,7 +716,7 @@ void Document::initDimensions() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Document::paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) const {
|
void Document::paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) {
|
||||||
bool selected = (selection == FullSelection);
|
bool selected = (selection == FullSelection);
|
||||||
|
|
||||||
_data->automaticLoad(_parent);
|
_data->automaticLoad(_parent);
|
||||||
|
@ -786,7 +872,7 @@ void Document::paint(Painter &p, const QRect &clip, TextSelection selection, con
|
||||||
if (clip.intersects(rtlrect(nameleft, statustop, availwidth, st::normalFont->height, _width))) {
|
if (clip.intersects(rtlrect(nameleft, statustop, availwidth, st::normalFont->height, _width))) {
|
||||||
p.setFont(st::normalFont);
|
p.setFont(st::normalFont);
|
||||||
p.setPen(st::mediaInFg);
|
p.setPen(st::mediaInFg);
|
||||||
p.drawTextLeft(nameleft, statustop, _width, _statusText);
|
p.drawTextLeft(nameleft, statustop, _width, _status.text());
|
||||||
}
|
}
|
||||||
if (datetop >= 0 && clip.intersects(rtlrect(nameleft, datetop, _datew, st::normalFont->height, _width))) {
|
if (datetop >= 0 && clip.intersects(rtlrect(nameleft, datetop, _datew, st::normalFont->height, _width))) {
|
||||||
p.setFont(ClickHandler::showAsActive(_msgl) ? st::normalFont->underline() : st::normalFont);
|
p.setFont(ClickHandler::showAsActive(_msgl) ? st::normalFont->underline() : st::normalFont);
|
||||||
|
@ -798,8 +884,6 @@ void Document::paint(Painter &p, const QRect &clip, TextSelection selection, con
|
||||||
void Document::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const {
|
void Document::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const {
|
||||||
bool loaded = _data->loaded() || Local::willStickerImageLoad(_data->mediaKey());
|
bool loaded = _data->loaded() || Local::willStickerImageLoad(_data->mediaKey());
|
||||||
|
|
||||||
bool showPause = updateStatusText();
|
|
||||||
|
|
||||||
int32 nameleft = 0, nametop = 0, nameright = 0, statustop = 0, datetop = 0;
|
int32 nameleft = 0, nametop = 0, nameright = 0, statustop = 0, datetop = 0;
|
||||||
bool wthumb = withThumb();
|
bool wthumb = withThumb();
|
||||||
|
|
||||||
|
@ -850,7 +934,7 @@ void Document::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Document::updateStatusText() const {
|
bool Document::updateStatusText() {
|
||||||
bool showPause = false;
|
bool showPause = false;
|
||||||
int32 statusSize = 0, realDuration = 0;
|
int32 statusSize = 0, realDuration = 0;
|
||||||
if (_data->status == FileDownloadFailed || _data->status == FileUploadFailed) {
|
if (_data->status == FileDownloadFailed || _data->status == FileUploadFailed) {
|
||||||
|
@ -880,8 +964,8 @@ bool Document::updateStatusText() const {
|
||||||
} else {
|
} else {
|
||||||
statusSize = FileStatusSizeReady;
|
statusSize = FileStatusSizeReady;
|
||||||
}
|
}
|
||||||
if (statusSize != _statusSize) {
|
if (statusSize != _status.size()) {
|
||||||
setStatusSize(statusSize, _data->size, _data->song() ? _data->song()->duration : -1, realDuration);
|
_status.update(statusSize, _data->size, _data->song() ? _data->song()->duration : -1, realDuration);
|
||||||
}
|
}
|
||||||
return showPause;
|
return showPause;
|
||||||
}
|
}
|
||||||
|
@ -1041,7 +1125,7 @@ int32 Link::resizeGetHeight(int32 width) {
|
||||||
return _height;
|
return _height;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Link::paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) const {
|
void Link::paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) {
|
||||||
int32 left = st::linksPhotoSize + st::linksPhotoPadding, top = st::linksMargin.top() + st::linksBorder, w = _width - left;
|
int32 left = st::linksPhotoSize + st::linksPhotoPadding, top = st::linksMargin.top() + st::linksBorder, w = _width - left;
|
||||||
if (clip.intersects(rtlrect(0, top, st::linksPhotoSize, st::linksPhotoSize, _width))) {
|
if (clip.intersects(rtlrect(0, top, st::linksPhotoSize, st::linksPhotoSize, _width))) {
|
||||||
if (_page && _page->photo) {
|
if (_page && _page->photo) {
|
||||||
|
|
|
@ -39,8 +39,7 @@ public:
|
||||||
class ItemBase;
|
class ItemBase;
|
||||||
class AbstractItem : public LayoutItemBase {
|
class AbstractItem : public LayoutItemBase {
|
||||||
public:
|
public:
|
||||||
|
virtual void paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) = 0;
|
||||||
virtual void paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) const = 0;
|
|
||||||
|
|
||||||
virtual ItemBase *toMediaItem() {
|
virtual ItemBase *toMediaItem() {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -115,7 +114,7 @@ protected:
|
||||||
void step_iconOver(float64 ms, bool timer);
|
void step_iconOver(float64 ms, bool timer);
|
||||||
void step_radial(uint64 ms, bool timer);
|
void step_radial(uint64 ms, bool timer);
|
||||||
|
|
||||||
void ensureRadial() const;
|
void ensureRadial();
|
||||||
void checkRadialFinished();
|
void checkRadialFinished();
|
||||||
|
|
||||||
bool isRadialAnimation(uint64 ms) const {
|
bool isRadialAnimation(uint64 ms) const {
|
||||||
|
@ -132,28 +131,33 @@ protected:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
mutable Ui::RadialAnimation *_radial;
|
Ui::RadialAnimation *_radial;
|
||||||
anim::fvalue a_iconOver;
|
anim::fvalue a_iconOver;
|
||||||
mutable Animation _a_iconOver;
|
Animation _a_iconOver;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class FileBase : public RadialProgressItem {
|
class StatusText {
|
||||||
public:
|
public:
|
||||||
FileBase(HistoryItem *parent) : RadialProgressItem(parent) {
|
// duration = -1 - no duration, duration = -2 - "GIF" duration
|
||||||
|
void update(int newSize, int fullSize, int duration, int64 realDuration);
|
||||||
|
void setSize(int newSize);
|
||||||
|
|
||||||
|
int size() const {
|
||||||
|
return _size;
|
||||||
|
}
|
||||||
|
QString text() const {
|
||||||
|
return _text;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
private:
|
||||||
// >= 0 will contain download / upload string, _statusSize = loaded bytes
|
// >= 0 will contain download / upload string, _size = loaded bytes
|
||||||
// < 0 will contain played string, _statusSize = -(seconds + 1) played
|
// < 0 will contain played string, _size = -(seconds + 1) played
|
||||||
// 0x7FFFFFF0 will contain status for not yet downloaded file
|
// 0x7FFFFFF0 will contain status for not yet downloaded file
|
||||||
// 0x7FFFFFF1 will contain status for already downloaded file
|
// 0x7FFFFFF1 will contain status for already downloaded file
|
||||||
// 0x7FFFFFF2 will contain status for failed to download / upload file
|
// 0x7FFFFFF2 will contain status for failed to download / upload file
|
||||||
mutable int32 _statusSize;
|
int _size = 0;
|
||||||
mutable QString _statusText;
|
QString _text;
|
||||||
|
|
||||||
// duration = -1 - no duration, duration = -2 - "GIF" duration
|
|
||||||
void setStatusSize(int32 newSize, int32 fullSize, int32 duration, qint64 realDuration) const;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -166,7 +170,7 @@ public:
|
||||||
Date(const QDate &date, bool month);
|
Date(const QDate &date, bool month);
|
||||||
|
|
||||||
void initDimensions() override;
|
void initDimensions() override;
|
||||||
void paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) const override;
|
void paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QDate _date;
|
QDate _date;
|
||||||
|
@ -174,33 +178,45 @@ private:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class PhotoVideoCheckbox;
|
||||||
|
|
||||||
class Photo : public ItemBase {
|
class Photo : public ItemBase {
|
||||||
public:
|
public:
|
||||||
Photo(PhotoData *photo, HistoryItem *parent);
|
Photo(PhotoData *photo, HistoryItem *parent);
|
||||||
|
|
||||||
void initDimensions() override;
|
void initDimensions() override;
|
||||||
int32 resizeGetHeight(int32 width) override;
|
int32 resizeGetHeight(int32 width) override;
|
||||||
void paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) const override;
|
void paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) override;
|
||||||
void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const override;
|
void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const override;
|
||||||
|
|
||||||
|
void clickHandlerActiveChanged(const ClickHandlerPtr &action, bool active) override;
|
||||||
|
void clickHandlerPressedChanged(const ClickHandlerPtr &action, bool pressed) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void ensureCheckboxCreated();
|
||||||
|
|
||||||
|
std_::unique_ptr<PhotoVideoCheckbox> _check;
|
||||||
|
|
||||||
PhotoData *_data;
|
PhotoData *_data;
|
||||||
ClickHandlerPtr _link;
|
ClickHandlerPtr _link;
|
||||||
|
|
||||||
mutable QPixmap _pix;
|
QPixmap _pix;
|
||||||
mutable bool _goodLoaded;
|
bool _goodLoaded = false;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class Video : public FileBase {
|
class Video : public RadialProgressItem {
|
||||||
public:
|
public:
|
||||||
Video(DocumentData *video, HistoryItem *parent);
|
Video(DocumentData *video, HistoryItem *parent);
|
||||||
|
|
||||||
void initDimensions() override;
|
void initDimensions() override;
|
||||||
int32 resizeGetHeight(int32 width) override;
|
int32 resizeGetHeight(int32 width) override;
|
||||||
void paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) const override;
|
void paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) override;
|
||||||
void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const override;
|
void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const override;
|
||||||
|
|
||||||
|
void clickHandlerActiveChanged(const ClickHandlerPtr &action, bool active) override;
|
||||||
|
void clickHandlerPressedChanged(const ClickHandlerPtr &action, bool pressed) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
float64 dataProgress() const override {
|
float64 dataProgress() const override {
|
||||||
return _data->progress();
|
return _data->progress();
|
||||||
|
@ -216,22 +232,27 @@ protected:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void ensureCheckboxCreated();
|
||||||
|
|
||||||
|
std_::unique_ptr<PhotoVideoCheckbox> _check;
|
||||||
|
|
||||||
DocumentData *_data;
|
DocumentData *_data;
|
||||||
|
StatusText _status;
|
||||||
|
|
||||||
QString _duration;
|
QString _duration;
|
||||||
mutable QPixmap _pix;
|
QPixmap _pix;
|
||||||
mutable bool _thumbLoaded;
|
bool _thumbLoaded = false;
|
||||||
|
|
||||||
void updateStatusText() const;
|
void updateStatusText();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class Voice : public FileBase {
|
class Voice : public RadialProgressItem {
|
||||||
public:
|
public:
|
||||||
Voice(DocumentData *voice, HistoryItem *parent);
|
Voice(DocumentData *voice, HistoryItem *parent);
|
||||||
|
|
||||||
void initDimensions() override;
|
void initDimensions() override;
|
||||||
void paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) const override;
|
void paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) override;
|
||||||
void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const override;
|
void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -250,22 +271,23 @@ protected:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DocumentData *_data;
|
DocumentData *_data;
|
||||||
|
StatusText _status;
|
||||||
ClickHandlerPtr _namel;
|
ClickHandlerPtr _namel;
|
||||||
|
|
||||||
mutable Text _name, _details;
|
Text _name, _details;
|
||||||
mutable int32 _nameVersion;
|
int _nameVersion;
|
||||||
|
|
||||||
void updateName() const;
|
void updateName();
|
||||||
bool updateStatusText() const;
|
bool updateStatusText();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class Document : public FileBase {
|
class Document : public RadialProgressItem {
|
||||||
public:
|
public:
|
||||||
Document(DocumentData *document, HistoryItem *parent, const style::OverviewFileLayout &st);
|
Document(DocumentData *document, HistoryItem *parent, const style::OverviewFileLayout &st);
|
||||||
|
|
||||||
void initDimensions() override;
|
void initDimensions() override;
|
||||||
void paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) const override;
|
void paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) override;
|
||||||
void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const override;
|
void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const override;
|
||||||
|
|
||||||
virtual DocumentData *getDocument() const override {
|
virtual DocumentData *getDocument() const override {
|
||||||
|
@ -288,12 +310,13 @@ protected:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DocumentData *_data;
|
DocumentData *_data;
|
||||||
|
StatusText _status;
|
||||||
ClickHandlerPtr _msgl, _namel;
|
ClickHandlerPtr _msgl, _namel;
|
||||||
|
|
||||||
const style::OverviewFileLayout &_st;
|
const style::OverviewFileLayout &_st;
|
||||||
|
|
||||||
mutable bool _thumbForLoaded = false;
|
bool _thumbForLoaded = false;
|
||||||
mutable QPixmap _thumb;
|
QPixmap _thumb;
|
||||||
|
|
||||||
Text _name;
|
Text _name;
|
||||||
QString _date, _ext;
|
QString _date, _ext;
|
||||||
|
@ -303,7 +326,7 @@ private:
|
||||||
bool withThumb() const {
|
bool withThumb() const {
|
||||||
return !_data->thumb->isNull() && _data->thumb->width() && _data->thumb->height();
|
return !_data->thumb->isNull() && _data->thumb->width() && _data->thumb->height();
|
||||||
}
|
}
|
||||||
bool updateStatusText() const;
|
bool updateStatusText();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -313,7 +336,7 @@ public:
|
||||||
|
|
||||||
void initDimensions() override;
|
void initDimensions() override;
|
||||||
int32 resizeGetHeight(int32 width) override;
|
int32 resizeGetHeight(int32 width) override;
|
||||||
void paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) const override;
|
void paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) override;
|
||||||
void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const override;
|
void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -24,23 +24,25 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
static constexpr int kWideScale = 4;
|
static constexpr int kWideScale = 3;
|
||||||
|
|
||||||
void prepareCheckCaches(const style::RoundImageCheckbox *st, QPixmap &checkBgCache, QPixmap &checkFullCache) {
|
void prepareCheckCaches(const style::RoundCheckbox *st, bool displayInactive, QPixmap &checkBgCache, QPixmap &checkFullCache) {
|
||||||
auto size = st->checkRadius * 2;
|
auto size = st->size;
|
||||||
auto wideSize = size * kWideScale;
|
auto wideSize = size * kWideScale;
|
||||||
auto cache = QImage(wideSize * cIntRetinaFactor(), wideSize * cIntRetinaFactor(), QImage::Format_ARGB32_Premultiplied);
|
auto cache = QImage(wideSize * cIntRetinaFactor(), wideSize * cIntRetinaFactor(), QImage::Format_ARGB32_Premultiplied);
|
||||||
cache.setDevicePixelRatio(cRetinaFactor());
|
cache.setDevicePixelRatio(cRetinaFactor());
|
||||||
|
cache.fill(Qt::transparent);
|
||||||
{
|
{
|
||||||
Painter p(&cache);
|
Painter p(&cache);
|
||||||
p.setCompositionMode(QPainter::CompositionMode_Source);
|
|
||||||
p.fillRect(0, 0, wideSize, wideSize, Qt::transparent);
|
|
||||||
p.setCompositionMode(QPainter::CompositionMode_SourceOver);
|
|
||||||
p.setRenderHint(QPainter::HighQualityAntialiasing, true);
|
p.setRenderHint(QPainter::HighQualityAntialiasing, true);
|
||||||
auto pen = st->checkBorder->p;
|
if (displayInactive) {
|
||||||
pen.setWidth(st->selectWidth);
|
p.setPen(Qt::NoPen);
|
||||||
|
} else {
|
||||||
|
auto pen = st->border->p;
|
||||||
|
pen.setWidth(st->width);
|
||||||
p.setPen(pen);
|
p.setPen(pen);
|
||||||
p.setBrush(st->checkBg);
|
}
|
||||||
|
p.setBrush(st->bgActive);
|
||||||
auto ellipse = QRect((wideSize - size) / 2, (wideSize - size) / 2, size, size);
|
auto ellipse = QRect((wideSize - size) / 2, (wideSize - size) / 2, size, size);
|
||||||
p.drawEllipse(ellipse);
|
p.drawEllipse(ellipse);
|
||||||
}
|
}
|
||||||
|
@ -48,32 +50,183 @@ void prepareCheckCaches(const style::RoundImageCheckbox *st, QPixmap &checkBgCac
|
||||||
{
|
{
|
||||||
Painter p(&cacheIcon);
|
Painter p(&cacheIcon);
|
||||||
auto ellipse = QRect((wideSize - size) / 2, (wideSize - size) / 2, size, size);
|
auto ellipse = QRect((wideSize - size) / 2, (wideSize - size) / 2, size, size);
|
||||||
st->checkIcon.paint(p, ellipse.topLeft(), wideSize);
|
st->check.paint(p, ellipse.topLeft(), wideSize);
|
||||||
}
|
}
|
||||||
checkBgCache = App::pixmapFromImageInPlace(std_::move(cache));
|
checkBgCache = App::pixmapFromImageInPlace(std_::move(cache));
|
||||||
checkBgCache.setDevicePixelRatio(cRetinaFactor());
|
|
||||||
checkFullCache = App::pixmapFromImageInPlace(std_::move(cacheIcon));
|
checkFullCache = App::pixmapFromImageInPlace(std_::move(cacheIcon));
|
||||||
checkFullCache.setDevicePixelRatio(cRetinaFactor());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
RoundImageCheckbox::RoundImageCheckbox(const style::RoundImageCheckbox &st, const base::lambda_copy<void()> &updateCallback, PaintRoundImage &&paintRoundImage)
|
RoundCheckbox::RoundCheckbox(const style::RoundCheckbox &st, const base::lambda_copy<void()> &updateCallback)
|
||||||
: _st(st)
|
: _st(st)
|
||||||
, _updateCallback(updateCallback)
|
, _updateCallback(updateCallback) {
|
||||||
, _paintRoundImage(std_::move(paintRoundImage)) {
|
|
||||||
prepareCheckCaches(&_st, _wideCheckBgCache, _wideCheckFullCache);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RoundImageCheckbox::paint(Painter &p, uint64 ms, int x, int y, int outerWidth) {
|
QRect RoundCheckbox::cacheDestRect(int x, int y, float64 scale) const {
|
||||||
_selection.step(ms);
|
auto iconSizeFull = kWideScale * _st.size;
|
||||||
|
auto iconSize = qRound(iconSizeFull * scale);
|
||||||
|
if (iconSize % 2 != iconSizeFull % 2) {
|
||||||
|
++iconSize;
|
||||||
|
}
|
||||||
|
auto iconShift = (iconSizeFull - iconSize) / 2;
|
||||||
|
auto iconLeft = x - (kWideScale - 1) * _st.size / 2 + iconShift;
|
||||||
|
auto iconTop = y - (kWideScale - 1) * _st.size / 2 + iconShift;
|
||||||
|
return QRect(iconLeft, iconTop, iconSize, iconSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RoundCheckbox::paint(Painter &p, uint64 ms, int x, int y, int outerWidth, float64 masterScale) {
|
||||||
for (auto &icon : _icons) {
|
for (auto &icon : _icons) {
|
||||||
icon.fadeIn.step(ms);
|
icon.fadeIn.step(ms);
|
||||||
icon.fadeOut.step(ms);
|
icon.fadeOut.step(ms);
|
||||||
}
|
}
|
||||||
removeFadeOutedIcons();
|
removeFadeOutedIcons();
|
||||||
|
|
||||||
auto selectionLevel = _selection.current(_checked ? 1. : 0.);
|
auto cacheSize = kWideScale * _st.size * cIntRetinaFactor();
|
||||||
|
auto cacheFrom = QRect(0, 0, cacheSize, cacheSize);
|
||||||
|
auto displayInactive = !_inactiveCacheBg.isNull();
|
||||||
|
auto inactiveTo = cacheDestRect(x, y, masterScale);
|
||||||
|
p.setRenderHint(QPainter::SmoothPixmapTransform, true);
|
||||||
|
if (!_inactiveCacheBg.isNull()) {
|
||||||
|
p.drawPixmap(inactiveTo, _inactiveCacheBg, cacheFrom);
|
||||||
|
}
|
||||||
|
for (auto &icon : _icons) {
|
||||||
|
auto fadeIn = icon.fadeIn.current(1.);
|
||||||
|
auto fadeOut = icon.fadeOut.current(1.);
|
||||||
|
auto to = cacheDestRect(x, y, (1. - (1. - _st.sizeSmall) * (1. - fadeOut)) * masterScale);
|
||||||
|
p.setOpacity(fadeIn * fadeOut);
|
||||||
|
if (fadeOut < 1.) {
|
||||||
|
p.drawPixmapLeft(to, outerWidth, icon.wideCheckCache, cacheFrom);
|
||||||
|
} else {
|
||||||
|
auto realDivider = ((kWideScale - 1) * _st.size / 2 + qMax(fadeIn - 0.5, 0.) * 2. * _st.size);
|
||||||
|
auto divider = qRound(realDivider * masterScale);
|
||||||
|
auto cacheDivider = qRound(realDivider) * cIntRetinaFactor();
|
||||||
|
p.drawPixmapLeft(QRect(to.x(), to.y(), divider, to.height()), outerWidth, _wideCheckFullCache, QRect(0, 0, cacheDivider, cacheFrom.height()));
|
||||||
|
p.drawPixmapLeft(QRect(to.x() + divider, to.y(), to.width() - divider, to.height()), outerWidth, _wideCheckBgCache, QRect(cacheDivider, 0, cacheFrom.width() - cacheDivider, _wideCheckBgCache.height()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p.setOpacity(1.);
|
||||||
|
if (!_inactiveCacheFg.isNull()) {
|
||||||
|
p.drawPixmap(inactiveTo, _inactiveCacheFg, cacheFrom);
|
||||||
|
}
|
||||||
|
p.setRenderHint(QPainter::SmoothPixmapTransform, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RoundCheckbox::setChecked(bool newChecked, SetStyle speed) {
|
||||||
|
if (_checked == newChecked) {
|
||||||
|
if (speed != SetStyle::Animated && !_icons.isEmpty()) {
|
||||||
|
_icons.back().fadeIn.finish();
|
||||||
|
_icons.back().fadeOut.finish();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_checked = newChecked;
|
||||||
|
if (_checked) {
|
||||||
|
if (_wideCheckBgCache.isNull()) {
|
||||||
|
prepareCheckCaches(&_st, _displayInactive, _wideCheckBgCache, _wideCheckFullCache);
|
||||||
|
}
|
||||||
|
_icons.push_back(Icon());
|
||||||
|
_icons.back().fadeIn.start(_updateCallback, 0, 1, _st.duration);
|
||||||
|
if (speed != SetStyle::Animated) {
|
||||||
|
_icons.back().fadeIn.finish();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (speed == SetStyle::Animated) {
|
||||||
|
prepareWideCheckIconCache(&_icons.back());
|
||||||
|
}
|
||||||
|
_icons.back().fadeOut.start(_updateCallback, 1, 0, _st.duration);
|
||||||
|
if (speed != SetStyle::Animated) {
|
||||||
|
_icons.back().fadeOut.finish();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RoundCheckbox::setDisplayInactive(bool displayInactive) {
|
||||||
|
if (_displayInactive != displayInactive) {
|
||||||
|
_displayInactive = displayInactive;
|
||||||
|
if (_displayInactive) {
|
||||||
|
prepareInactiveCache();
|
||||||
|
} else {
|
||||||
|
_inactiveCacheBg = _inactiveCacheFg = QPixmap();
|
||||||
|
}
|
||||||
|
if (!_wideCheckBgCache.isNull()) {
|
||||||
|
prepareCheckCaches(&_st, _displayInactive, _wideCheckBgCache, _wideCheckFullCache);
|
||||||
|
}
|
||||||
|
for (auto &icon : _icons) {
|
||||||
|
if (!icon.wideCheckCache.isNull()) {
|
||||||
|
prepareWideCheckIconCache(&icon);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RoundCheckbox::removeFadeOutedIcons() {
|
||||||
|
while (!_icons.empty() && !_icons.front().fadeIn.animating() && !_icons.front().fadeOut.animating()) {
|
||||||
|
if (_icons.size() > 1 || !_checked) {
|
||||||
|
_icons.erase(_icons.begin());
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RoundCheckbox::prepareWideCheckIconCache(Icon *icon) {
|
||||||
|
auto cacheWidth = _wideCheckBgCache.width() / _wideCheckBgCache.devicePixelRatio();
|
||||||
|
auto cacheHeight = _wideCheckBgCache.height() / _wideCheckBgCache.devicePixelRatio();
|
||||||
|
auto wideCache = QImage(cacheWidth * cIntRetinaFactor(), cacheHeight * cIntRetinaFactor(), QImage::Format_ARGB32_Premultiplied);
|
||||||
|
wideCache.setDevicePixelRatio(cRetinaFactor());
|
||||||
|
{
|
||||||
|
Painter p(&wideCache);
|
||||||
|
p.setCompositionMode(QPainter::CompositionMode_Source);
|
||||||
|
auto iconSize = kWideScale * _st.size;
|
||||||
|
auto divider = qRound((kWideScale - 1) * _st.size / 2 + qMax(icon->fadeIn.current(1.) - 0.5, 0.) * 2. * _st.size);
|
||||||
|
p.drawPixmapLeft(QRect(0, 0, divider, iconSize), cacheWidth, _wideCheckFullCache, QRect(0, 0, divider * cIntRetinaFactor(), _wideCheckFullCache.height()));
|
||||||
|
p.drawPixmapLeft(QRect(divider, 0, iconSize - divider, iconSize), cacheWidth, _wideCheckBgCache, QRect(divider * cIntRetinaFactor(), 0, _wideCheckBgCache.width() - divider * cIntRetinaFactor(), _wideCheckBgCache.height()));
|
||||||
|
}
|
||||||
|
icon->wideCheckCache = App::pixmapFromImageInPlace(std_::move(wideCache));
|
||||||
|
icon->wideCheckCache.setDevicePixelRatio(cRetinaFactor());
|
||||||
|
}
|
||||||
|
|
||||||
|
void RoundCheckbox::prepareInactiveCache() {
|
||||||
|
auto wideSize = _st.size * kWideScale;
|
||||||
|
auto ellipse = QRect((wideSize - _st.size) / 2, (wideSize - _st.size) / 2, _st.size, _st.size);
|
||||||
|
|
||||||
|
auto cacheBg = QImage(wideSize * cIntRetinaFactor(), wideSize * cIntRetinaFactor(), QImage::Format_ARGB32_Premultiplied);
|
||||||
|
cacheBg.setDevicePixelRatio(cRetinaFactor());
|
||||||
|
cacheBg.fill(Qt::transparent);
|
||||||
|
auto cacheFg = cacheBg;
|
||||||
|
if (_st.bgInactive) {
|
||||||
|
Painter p(&cacheBg);
|
||||||
|
p.setRenderHint(QPainter::HighQualityAntialiasing, true);
|
||||||
|
p.setPen(Qt::NoPen);
|
||||||
|
p.setBrush(_st.bgInactive);
|
||||||
|
p.drawEllipse(ellipse);
|
||||||
|
}
|
||||||
|
_inactiveCacheBg = App::pixmapFromImageInPlace(std_::move(cacheBg));
|
||||||
|
|
||||||
|
{
|
||||||
|
Painter p(&cacheFg);
|
||||||
|
p.setRenderHint(QPainter::HighQualityAntialiasing, true);
|
||||||
|
auto pen = _st.border->p;
|
||||||
|
pen.setWidth(_st.width);
|
||||||
|
p.setPen(pen);
|
||||||
|
p.setBrush(Qt::NoBrush);
|
||||||
|
p.drawEllipse(ellipse);
|
||||||
|
}
|
||||||
|
_inactiveCacheFg = App::pixmapFromImageInPlace(std_::move(cacheFg));
|
||||||
|
}
|
||||||
|
|
||||||
|
RoundImageCheckbox::RoundImageCheckbox(const style::RoundImageCheckbox &st, const base::lambda_copy<void()> &updateCallback, PaintRoundImage &&paintRoundImage)
|
||||||
|
: _st(st)
|
||||||
|
, _updateCallback(updateCallback)
|
||||||
|
, _paintRoundImage(std_::move(paintRoundImage))
|
||||||
|
, _check(_st.check, _updateCallback) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void RoundImageCheckbox::paint(Painter &p, uint64 ms, int x, int y, int outerWidth) {
|
||||||
|
_selection.step(ms);
|
||||||
|
|
||||||
|
auto selectionLevel = _selection.current(checked() ? 1. : 0.);
|
||||||
if (_selection.animating()) {
|
if (_selection.animating()) {
|
||||||
auto userpicRadius = qRound(kWideScale * (_st.imageRadius + (_st.imageSmallRadius - _st.imageRadius) * selectionLevel));
|
auto userpicRadius = qRound(kWideScale * (_st.imageRadius + (_st.imageSmallRadius - _st.imageRadius) * selectionLevel));
|
||||||
auto userpicShift = kWideScale * _st.imageRadius - userpicRadius;
|
auto userpicShift = kWideScale * _st.imageRadius - userpicRadius;
|
||||||
|
@ -89,7 +242,7 @@ void RoundImageCheckbox::paint(Painter &p, uint64 ms, int x, int y, int outerWid
|
||||||
if (!_wideCache.isNull()) {
|
if (!_wideCache.isNull()) {
|
||||||
_wideCache = QPixmap();
|
_wideCache = QPixmap();
|
||||||
}
|
}
|
||||||
auto userpicRadius = _checked ? _st.imageSmallRadius : _st.imageRadius;
|
auto userpicRadius = checked() ? _st.imageSmallRadius : _st.imageRadius;
|
||||||
auto userpicShift = _st.imageRadius - userpicRadius;
|
auto userpicShift = _st.imageRadius - userpicRadius;
|
||||||
auto userpicLeft = x + userpicShift;
|
auto userpicLeft = x + userpicShift;
|
||||||
auto userpicTop = y + userpicShift;
|
auto userpicTop = y + userpicShift;
|
||||||
|
@ -108,78 +261,32 @@ void RoundImageCheckbox::paint(Painter &p, uint64 ms, int x, int y, int outerWid
|
||||||
p.setRenderHint(QPainter::HighQualityAntialiasing, false);
|
p.setRenderHint(QPainter::HighQualityAntialiasing, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
p.setRenderHint(QPainter::SmoothPixmapTransform, true);
|
auto iconLeft = x + 2 * _st.imageRadius + _st.selectWidth - _st.check.size;
|
||||||
for (auto &icon : _icons) {
|
auto iconTop = y + 2 * _st.imageRadius + _st.selectWidth - _st.check.size;
|
||||||
auto fadeIn = icon.fadeIn.current(1.);
|
_check.paint(p, ms, iconLeft, iconTop, outerWidth);
|
||||||
auto fadeOut = icon.fadeOut.current(1.);
|
|
||||||
auto iconRadius = qRound(kWideScale * (_st.checkSmallRadius + fadeOut * (_st.checkRadius - _st.checkSmallRadius)));
|
|
||||||
auto iconShift = kWideScale * _st.checkRadius - iconRadius;
|
|
||||||
auto iconLeft = x + 2 * _st.imageRadius + _st.selectWidth - 2 * _st.checkRadius - (kWideScale - 1) * _st.checkRadius + iconShift;
|
|
||||||
auto iconTop = y + 2 * _st.imageRadius + _st.selectWidth - 2 * _st.checkRadius - (kWideScale - 1) * _st.checkRadius + iconShift;
|
|
||||||
auto to = QRect(iconLeft, iconTop, iconRadius * 2, iconRadius * 2);
|
|
||||||
auto from = QRect(QPoint(0, 0), _wideCheckFullCache.size());
|
|
||||||
auto opacity = fadeIn * fadeOut;
|
|
||||||
p.setOpacity(opacity);
|
|
||||||
if (fadeOut < 1.) {
|
|
||||||
p.drawPixmapLeft(to, outerWidth, icon.wideCheckCache, from);
|
|
||||||
} else {
|
|
||||||
auto divider = qRound((kWideScale - 2) * _st.checkRadius + fadeIn * 3 * _st.checkRadius);
|
|
||||||
p.drawPixmapLeft(QRect(iconLeft, iconTop, divider, iconRadius * 2), outerWidth, _wideCheckFullCache, QRect(0, 0, divider * cIntRetinaFactor(), _wideCheckFullCache.height()));
|
|
||||||
p.drawPixmapLeft(QRect(iconLeft + divider, iconTop, iconRadius * 2 - divider, iconRadius * 2), outerWidth, _wideCheckBgCache, QRect(divider * cIntRetinaFactor(), 0, _wideCheckBgCache.width() - divider * cIntRetinaFactor(), _wideCheckBgCache.height()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
p.setRenderHint(QPainter::SmoothPixmapTransform, false);
|
|
||||||
p.setOpacity(1.);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float64 RoundImageCheckbox::checkedAnimationRatio() const {
|
float64 RoundImageCheckbox::checkedAnimationRatio() const {
|
||||||
return snap(_selection.current(_checked ? 1. : 0.), 0., 1.);
|
return snap(_selection.current(checked() ? 1. : 0.), 0., 1.);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RoundImageCheckbox::setChecked(bool checked, SetStyle speed) {
|
void RoundImageCheckbox::setChecked(bool newChecked, SetStyle speed) {
|
||||||
if (_checked == checked) {
|
auto changed = (checked() != newChecked);
|
||||||
|
_check.setChecked(newChecked, speed);
|
||||||
|
if (!changed) {
|
||||||
if (speed != SetStyle::Animated) {
|
if (speed != SetStyle::Animated) {
|
||||||
if (!_icons.isEmpty()) {
|
|
||||||
_icons.back().fadeIn.finish();
|
|
||||||
_icons.back().fadeOut.finish();
|
|
||||||
}
|
|
||||||
_selection.finish();
|
_selection.finish();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_checked = checked;
|
|
||||||
if (_checked) {
|
|
||||||
_icons.push_back(Icon());
|
|
||||||
_icons.back().fadeIn.start(_updateCallback, 0, 1, _st.selectDuration);
|
|
||||||
if (speed != SetStyle::Animated) {
|
|
||||||
_icons.back().fadeIn.finish();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
_icons.back().fadeOut.start(_updateCallback, 1, 0, _st.selectDuration);
|
|
||||||
if (speed == SetStyle::Animated) {
|
|
||||||
prepareWideCheckIconCache(&_icons.back());
|
|
||||||
} else {
|
|
||||||
_icons.back().fadeOut.finish();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (speed == SetStyle::Animated) {
|
if (speed == SetStyle::Animated) {
|
||||||
prepareWideCache();
|
prepareWideCache();
|
||||||
_selection.start(_updateCallback, _checked ? 0 : 1, _checked ? 1 : 0, _st.selectDuration, anim::bumpy(1.25));
|
_selection.start(_updateCallback, checked() ? 0 : 1, checked() ? 1 : 0, _st.selectDuration, anim::bumpy(1.25));
|
||||||
} else {
|
} else {
|
||||||
_selection.finish();
|
_selection.finish();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RoundImageCheckbox::removeFadeOutedIcons() {
|
|
||||||
while (!_icons.empty() && !_icons.front().fadeIn.animating() && !_icons.front().fadeOut.animating()) {
|
|
||||||
if (_icons.size() > 1 || !_checked) {
|
|
||||||
_icons.erase(_icons.begin());
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void RoundImageCheckbox::prepareWideCache() {
|
void RoundImageCheckbox::prepareWideCache() {
|
||||||
if (_wideCache.isNull()) {
|
if (_wideCache.isNull()) {
|
||||||
auto size = _st.imageRadius * 2;
|
auto size = _st.imageRadius * 2;
|
||||||
|
@ -197,21 +304,4 @@ void RoundImageCheckbox::prepareWideCache() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RoundImageCheckbox::prepareWideCheckIconCache(Icon *icon) {
|
|
||||||
auto cacheWidth = _wideCheckBgCache.width() / _wideCheckBgCache.devicePixelRatio();
|
|
||||||
auto cacheHeight = _wideCheckBgCache.height() / _wideCheckBgCache.devicePixelRatio();
|
|
||||||
auto wideCache = QImage(cacheWidth * cIntRetinaFactor(), cacheHeight * cIntRetinaFactor(), QImage::Format_ARGB32_Premultiplied);
|
|
||||||
wideCache.setDevicePixelRatio(cRetinaFactor());
|
|
||||||
{
|
|
||||||
Painter p(&wideCache);
|
|
||||||
p.setCompositionMode(QPainter::CompositionMode_Source);
|
|
||||||
auto iconRadius = kWideScale * _st.checkRadius;
|
|
||||||
auto divider = qRound((kWideScale - 2) * _st.checkRadius + icon->fadeIn.current(1.) * (kWideScale - 1) * _st.checkRadius);
|
|
||||||
p.drawPixmapLeft(QRect(0, 0, divider, iconRadius * 2), cacheWidth, _wideCheckFullCache, QRect(0, 0, divider * cIntRetinaFactor(), _wideCheckFullCache.height()));
|
|
||||||
p.drawPixmapLeft(QRect(divider, 0, iconRadius * 2 - divider, iconRadius * 2), cacheWidth, _wideCheckBgCache, QRect(divider * cIntRetinaFactor(), 0, _wideCheckBgCache.width() - divider * cIntRetinaFactor(), _wideCheckBgCache.height()));
|
|
||||||
}
|
|
||||||
icon->wideCheckCache = App::pixmapFromImageInPlace(std_::move(wideCache));
|
|
||||||
icon->wideCheckCache.setDevicePixelRatio(cRetinaFactor());
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Ui
|
} // namespace Ui
|
||||||
|
|
|
@ -24,6 +24,47 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
|
|
||||||
|
class RoundCheckbox {
|
||||||
|
public:
|
||||||
|
RoundCheckbox(const style::RoundCheckbox &st, const base::lambda_copy<void()> &updateCallback);
|
||||||
|
|
||||||
|
void paint(Painter &p, uint64 ms, int x, int y, int outerWidth, float64 masterScale = 1.);
|
||||||
|
|
||||||
|
void setDisplayInactive(bool displayInactive);
|
||||||
|
bool checked() const {
|
||||||
|
return _checked;
|
||||||
|
}
|
||||||
|
enum class SetStyle {
|
||||||
|
Animated,
|
||||||
|
Fast,
|
||||||
|
};
|
||||||
|
void setChecked(bool newChecked, SetStyle speed = SetStyle::Animated);
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct Icon {
|
||||||
|
FloatAnimation fadeIn;
|
||||||
|
FloatAnimation fadeOut;
|
||||||
|
QPixmap wideCheckCache;
|
||||||
|
};
|
||||||
|
void removeFadeOutedIcons();
|
||||||
|
void prepareWideCheckIconCache(Icon *icon);
|
||||||
|
void prepareInactiveCache();
|
||||||
|
QRect cacheDestRect(int x, int y, float64 scale) const;
|
||||||
|
|
||||||
|
const style::RoundCheckbox &_st;
|
||||||
|
base::lambda_copy<void()> _updateCallback;
|
||||||
|
|
||||||
|
bool _checked = false;
|
||||||
|
std_::vector_of_moveable<Icon> _icons;
|
||||||
|
|
||||||
|
bool _displayInactive = false;
|
||||||
|
QPixmap _inactiveCacheBg, _inactiveCacheFg;
|
||||||
|
|
||||||
|
// Those pixmaps are shared among all checkboxes that have the same style.
|
||||||
|
QPixmap _wideCheckBgCache, _wideCheckFullCache;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
class RoundImageCheckbox {
|
class RoundImageCheckbox {
|
||||||
public:
|
public:
|
||||||
using PaintRoundImage = base::lambda<void(Painter &p, int x, int y, int outerWidth, int size)>;
|
using PaintRoundImage = base::lambda<void(Painter &p, int x, int y, int outerWidth, int size)>;
|
||||||
|
@ -33,35 +74,22 @@ public:
|
||||||
float64 checkedAnimationRatio() const;
|
float64 checkedAnimationRatio() const;
|
||||||
|
|
||||||
bool checked() const {
|
bool checked() const {
|
||||||
return _checked;
|
return _check.checked();
|
||||||
}
|
}
|
||||||
enum class SetStyle {
|
using SetStyle = RoundCheckbox::SetStyle;
|
||||||
Animated,
|
void setChecked(bool newChecked, SetStyle speed = SetStyle::Animated);
|
||||||
Fast,
|
|
||||||
};
|
|
||||||
void setChecked(bool checked, SetStyle speed = SetStyle::Animated);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct Icon {
|
|
||||||
FloatAnimation fadeIn;
|
|
||||||
FloatAnimation fadeOut;
|
|
||||||
QPixmap wideCheckCache;
|
|
||||||
};
|
|
||||||
void removeFadeOutedIcons();
|
|
||||||
void prepareWideCache();
|
void prepareWideCache();
|
||||||
void prepareWideCheckIconCache(Icon *icon);
|
|
||||||
|
|
||||||
const style::RoundImageCheckbox &_st;
|
const style::RoundImageCheckbox &_st;
|
||||||
base::lambda_copy<void()> _updateCallback;
|
base::lambda_copy<void()> _updateCallback;
|
||||||
PaintRoundImage _paintRoundImage;
|
PaintRoundImage _paintRoundImage;
|
||||||
|
|
||||||
bool _checked = false;
|
|
||||||
QPixmap _wideCache;
|
QPixmap _wideCache;
|
||||||
FloatAnimation _selection;
|
FloatAnimation _selection;
|
||||||
std_::vector_of_moveable<Icon> _icons;
|
|
||||||
|
|
||||||
// Those pixmaps are shared among all checkboxes that have the same style.
|
RoundCheckbox _check;
|
||||||
QPixmap _wideCheckBgCache, _wideCheckFullCache;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -319,17 +319,24 @@ FilledSlider {
|
||||||
duration: int;
|
duration: int;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RoundCheckbox {
|
||||||
|
border: color;
|
||||||
|
bgInactive: color;
|
||||||
|
bgActive: color;
|
||||||
|
width: pixels;
|
||||||
|
size: pixels;
|
||||||
|
sizeSmall: double;
|
||||||
|
duration: int;
|
||||||
|
check: icon;
|
||||||
|
}
|
||||||
|
|
||||||
RoundImageCheckbox {
|
RoundImageCheckbox {
|
||||||
imageRadius: pixels;
|
imageRadius: pixels;
|
||||||
imageSmallRadius: pixels;
|
imageSmallRadius: pixels;
|
||||||
selectWidth: pixels;
|
selectWidth: pixels;
|
||||||
selectFg: color;
|
selectFg: color;
|
||||||
selectDuration: int;
|
selectDuration: int;
|
||||||
checkBorder: color;
|
check: RoundCheckbox;
|
||||||
checkBg: color;
|
|
||||||
checkRadius: pixels;
|
|
||||||
checkSmallRadius: pixels;
|
|
||||||
checkIcon: icon;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MultiSelectItem {
|
MultiSelectItem {
|
||||||
|
@ -738,6 +745,13 @@ defaultPanelAnimation: PanelAnimation {
|
||||||
shadow: defaultRoundShadow;
|
shadow: defaultRoundShadow;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
defaultRoundCheckbox: RoundCheckbox {
|
||||||
|
border: windowBg;
|
||||||
|
bgActive: windowBgActive;
|
||||||
|
width: 2px;
|
||||||
|
duration: 150;
|
||||||
|
}
|
||||||
|
|
||||||
defaultMenuArrow: icon {{ "dropdown_submenu_arrow", #373737 }};
|
defaultMenuArrow: icon {{ "dropdown_submenu_arrow", #373737 }};
|
||||||
defaultMenu: Menu {
|
defaultMenu: Menu {
|
||||||
skip: 0px;
|
skip: 0px;
|
||||||
|
|
Loading…
Reference in New Issue