mirror of
https://github.com/vale981/tdesktop
synced 2025-03-06 02:01:40 -05:00
Moved Passport panel code to Ui::SeparatePanel.
This commit is contained in:
parent
5c0cc8a947
commit
a29e8f9a06
9 changed files with 720 additions and 585 deletions
|
@ -675,7 +675,9 @@ for restype in typesList:
|
|||
|
||||
forwards += 'class MTPD' + name + ';\n'; # data class forward declaration
|
||||
|
||||
dataText += ', '.join(prmsStr) + ') : ' + ', '.join(prmsInit) + ' {\n\t}\n';
|
||||
dataText += ', '.join(prmsStr) + ');\n';
|
||||
|
||||
constructsBodies += 'MTPD' + name + '::MTPD' + name + '(' + ', '.join(prmsStr) + ') : ' + ', '.join(prmsInit) + ' {\n}\n';
|
||||
|
||||
dataText += '\n';
|
||||
for paramName in prmsList: # fields declaration
|
||||
|
@ -746,20 +748,11 @@ for restype in typesList:
|
|||
typesText += ' {\n';
|
||||
typesText += 'public:\n';
|
||||
typesText += '\tMTP' + restype + '()'; # default constructor
|
||||
inits = [];
|
||||
if not (withType):
|
||||
if (withData):
|
||||
inits.append('TypeDataOwner(' + newFast + ')');
|
||||
if (withData and not withType):
|
||||
typesText += ';\n';
|
||||
methods += '\nMTP' + restype + '::MTP' + restype + '()';
|
||||
if (inits):
|
||||
methods += ' : ' + ', '.join(inits);
|
||||
methods += ' {\n}\n';
|
||||
methods += '\nMTP' + restype + '::MTP' + restype + '() : TypeDataOwner(' + newFast + ') {\n}\n';
|
||||
else:
|
||||
if (inits):
|
||||
typesText += ' : ' + ', '.join(inits);
|
||||
typesText += ' {\n\t}\n';
|
||||
typesText += ' = default;\n';
|
||||
|
||||
if (withData):
|
||||
typesText += getters;
|
||||
|
|
|
@ -713,3 +713,33 @@ topBarConnectingAnimation: InfiniteRadialAnimation(defaultInfiniteRadialAnimatio
|
|||
}
|
||||
|
||||
infoFeedLeaveIconMargins: margins(10px, 12px, 20px, 10px);
|
||||
|
||||
separatePanelBorderCacheSize: 60px;
|
||||
separatePanelTitleHeight: 62px;
|
||||
separatePanelClose: IconButton(boxTitleClose) {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
|
||||
rippleAreaPosition: point(8px, 8px);
|
||||
rippleAreaSize: 44px;
|
||||
ripple: RippleAnimation(defaultRippleAnimation) {
|
||||
color: windowBgOver;
|
||||
}
|
||||
}
|
||||
separatePanelTitleFont: font(18px semibold);
|
||||
separatePanelTitle: FlatLabel(defaultFlatLabel) {
|
||||
textFg: boxTitleFg;
|
||||
maxHeight: 26px;
|
||||
style: TextStyle(defaultTextStyle) {
|
||||
font: separatePanelTitleFont;
|
||||
linkFont: separatePanelTitleFont;
|
||||
linkFontOver: font(18px semibold underline);
|
||||
}
|
||||
}
|
||||
separatePanelTitleTop: 18px;
|
||||
separatePanelTitleLeft: 22px;
|
||||
separatePanelTitleSkip: 0px;
|
||||
separatePanelBack: IconButton(separatePanelClose) {
|
||||
icon: infoTopBarBackIcon;
|
||||
iconOver: infoTopBarBackIconOver;
|
||||
}
|
||||
|
|
|
@ -37,37 +37,7 @@ passportVerifyErrorLabel: FlatLabel(passportErrorLabel) {
|
|||
align: align(topleft);
|
||||
}
|
||||
|
||||
passportPanelWidth: 392px;
|
||||
passportPanelHeight: 600px;
|
||||
passportPanelBorderCacheSize: 60px;
|
||||
passportPanelTitleHeight: 62px;
|
||||
passportPanelClose: IconButton(boxTitleClose) {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
|
||||
rippleAreaPosition: point(8px, 8px);
|
||||
rippleAreaSize: 44px;
|
||||
ripple: RippleAnimation(defaultRippleAnimation) {
|
||||
color: windowBgOver;
|
||||
}
|
||||
}
|
||||
passportPanelTitleFont: font(18px semibold);
|
||||
passportPanelTitle: FlatLabel(defaultFlatLabel) {
|
||||
textFg: boxTitleFg;
|
||||
maxHeight: 26px;
|
||||
style: TextStyle(defaultTextStyle) {
|
||||
font: passportPanelTitleFont;
|
||||
linkFont: passportPanelTitleFont;
|
||||
linkFontOver: font(18px semibold underline);
|
||||
}
|
||||
}
|
||||
passportPanelTitleTop: 18px;
|
||||
passportPanelTitleLeft: 22px;
|
||||
passportPanelTitleSkip: 0px;
|
||||
passportPanelBack: IconButton(passportPanelClose) {
|
||||
icon: infoTopBarBackIcon;
|
||||
iconOver: infoTopBarBackIconOver;
|
||||
}
|
||||
passportPanelSize: size(392px, 600px);
|
||||
|
||||
passportPasswordFieldBottom: 306px;
|
||||
passportPasswordFieldSkip: 29px;
|
||||
|
|
|
@ -10,16 +10,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "passport/passport_panel_controller.h"
|
||||
#include "passport/passport_panel_form.h"
|
||||
#include "passport/passport_panel_password.h"
|
||||
#include "window/main_window.h"
|
||||
#include "platform/platform_specific.h"
|
||||
#include "ui/widgets/shadow.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/widgets/separate_panel.h"
|
||||
#include "ui/widgets/labels.h"
|
||||
#include "ui/wrap/padding_wrap.h"
|
||||
#include "ui/wrap/fade_wrap.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "window/layer_widget.h"
|
||||
#include "messenger.h"
|
||||
#include "styles/style_passport.h"
|
||||
#include "styles/style_widgets.h"
|
||||
#include "styles/style_calls.h"
|
||||
|
@ -28,515 +22,85 @@ namespace Passport {
|
|||
|
||||
Panel::Panel(not_null<PanelController*> controller)
|
||||
: _controller(controller)
|
||||
, _close(this, st::passportPanelClose)
|
||||
, _title(
|
||||
this,
|
||||
lang(lng_passport_title),
|
||||
Ui::FlatLabel::InitType::Simple,
|
||||
st::passportPanelTitle)
|
||||
, _back(this, object_ptr<Ui::IconButton>(this, st::passportPanelBack))
|
||||
, _body(this) {
|
||||
setMouseTracking(true);
|
||||
setWindowIcon(Window::CreateIcon());
|
||||
initControls();
|
||||
initLayout();
|
||||
}
|
||||
, _widget(std::make_unique<Ui::SeparatePanel>()) {
|
||||
_widget->setTitle(Lang::Viewer(lng_passport_title));
|
||||
_widget->setInnerSize(st::passportPanelSize);
|
||||
|
||||
void Panel::initControls() {
|
||||
widthValue(
|
||||
) | rpl::start_with_next([=](int width) {
|
||||
_back->moveToLeft(_padding.left(), _padding.top());
|
||||
_close->moveToRight(_padding.right(), _padding.top());
|
||||
_title->resizeToWidth(width
|
||||
- _padding.left() - _back->width()
|
||||
- _padding.right() - _close->width());
|
||||
updateTitlePosition();
|
||||
}, lifetime());
|
||||
|
||||
_close->addClickHandler([=] {
|
||||
rpl::merge(
|
||||
_widget->closeRequests(),
|
||||
_widget->destroyRequests()
|
||||
) | rpl::start_with_next([=] {
|
||||
_controller->cancelAuth();
|
||||
});
|
||||
|
||||
_back->toggledValue(
|
||||
) | rpl::start_with_next([=](bool toggled) {
|
||||
_titleLeft.start(
|
||||
[=] { updateTitlePosition(); },
|
||||
toggled ? 0. : 1.,
|
||||
toggled ? 1. : 0.,
|
||||
st::fadeWrapDuration);
|
||||
}, _title->lifetime());
|
||||
_back->hide(anim::type::instant);
|
||||
_titleLeft.finish();
|
||||
|
||||
_title->setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||
}
|
||||
|
||||
void Panel::updateTitlePosition() {
|
||||
const auto progress = _titleLeft.current(_back->toggled() ? 1. : 0.);
|
||||
const auto left = anim::interpolate(
|
||||
st::passportPanelTitleLeft,
|
||||
_back->width() + st::passportPanelTitleSkip,
|
||||
progress);
|
||||
_title->moveToLeft(
|
||||
_padding.left() + left,
|
||||
_padding.top() + st::passportPanelTitleTop);
|
||||
|
||||
}, _widget->lifetime());
|
||||
}
|
||||
|
||||
rpl::producer<> Panel::backRequests() const {
|
||||
return rpl::merge(
|
||||
_back->entity()->clicks(),
|
||||
_synteticBackRequests.events());
|
||||
return _widget->backRequests();
|
||||
}
|
||||
|
||||
void Panel::setBackAllowed(bool allowed) {
|
||||
if (allowed != _back->toggled()) {
|
||||
_back->toggle(allowed, anim::type::normal);
|
||||
}
|
||||
_widget->setBackAllowed(allowed);
|
||||
}
|
||||
|
||||
void Panel::showAndActivate() {
|
||||
toggleOpacityAnimation(true);
|
||||
raise();
|
||||
setWindowState(windowState() | Qt::WindowActive);
|
||||
activateWindow();
|
||||
setFocus();
|
||||
}
|
||||
|
||||
void Panel::keyPressEvent(QKeyEvent *e) {
|
||||
if (e->key() == Qt::Key_Escape && _back->toggled()) {
|
||||
_synteticBackRequests.fire({});
|
||||
}
|
||||
return RpWidget::keyPressEvent(e);
|
||||
}
|
||||
|
||||
void Panel::initLayout() {
|
||||
setWindowFlags(Qt::WindowFlags(Qt::FramelessWindowHint)
|
||||
| Qt::WindowStaysOnTopHint
|
||||
| Qt::BypassWindowManagerHint
|
||||
| Qt::NoDropShadowWindowHint
|
||||
| Qt::Dialog);
|
||||
setAttribute(Qt::WA_MacAlwaysShowToolWindow);
|
||||
setAttribute(Qt::WA_NoSystemBackground, true);
|
||||
setAttribute(Qt::WA_TranslucentBackground, true);
|
||||
|
||||
initGeometry();
|
||||
createBorderImage();
|
||||
|
||||
Platform::InitOnTopPanel(this);
|
||||
}
|
||||
|
||||
void Panel::createBorderImage() {
|
||||
if (!_useTransparency || !_borderParts.isNull()) {
|
||||
return;
|
||||
}
|
||||
const auto cacheSize = st::passportPanelBorderCacheSize;
|
||||
auto cache = QImage(
|
||||
cacheSize * cIntRetinaFactor(),
|
||||
cacheSize * cIntRetinaFactor(),
|
||||
QImage::Format_ARGB32_Premultiplied);
|
||||
cache.setDevicePixelRatio(cRetinaFactor());
|
||||
cache.fill(Qt::transparent);
|
||||
{
|
||||
Painter p(&cache);
|
||||
auto inner = QRect(0, 0, cacheSize, cacheSize).marginsRemoved(
|
||||
_padding);
|
||||
Ui::Shadow::paint(p, inner, width(), st::callShadow);
|
||||
p.setCompositionMode(QPainter::CompositionMode_Source);
|
||||
p.setBrush(st::windowBg);
|
||||
p.setPen(Qt::NoPen);
|
||||
PainterHighQualityEnabler hq(p);
|
||||
p.drawRoundedRect(
|
||||
myrtlrect(inner),
|
||||
st::callRadius,
|
||||
st::callRadius);
|
||||
}
|
||||
_borderParts = App::pixmapFromImageInPlace(std::move(cache));
|
||||
}
|
||||
|
||||
void Panel::toggleOpacityAnimation(bool visible) {
|
||||
if (_visible == visible) {
|
||||
return;
|
||||
}
|
||||
|
||||
_visible = visible;
|
||||
if (_useTransparency) {
|
||||
if (_animationCache.isNull()) {
|
||||
showControls();
|
||||
_animationCache = Ui::GrabWidget(this);
|
||||
hideChildren();
|
||||
}
|
||||
_opacityAnimation.start(
|
||||
[this] { opacityCallback(); },
|
||||
_visible ? 0. : 1.,
|
||||
_visible ? 1. : 0.,
|
||||
st::callPanelDuration,
|
||||
_visible ? anim::easeOutCirc : anim::easeInCirc);
|
||||
}
|
||||
if (isHidden() && _visible) {
|
||||
show();
|
||||
}
|
||||
}
|
||||
|
||||
void Panel::opacityCallback() {
|
||||
update();
|
||||
if (!_visible && !_opacityAnimation.animating()) {
|
||||
finishAnimating();
|
||||
}
|
||||
}
|
||||
|
||||
void Panel::finishAnimating() {
|
||||
_animationCache = QPixmap();
|
||||
if (_visible) {
|
||||
showControls();
|
||||
_inner->setFocus();
|
||||
} else {
|
||||
destroyDelayed();
|
||||
}
|
||||
}
|
||||
|
||||
void Panel::showControls() {
|
||||
showChildren();
|
||||
if (!_back->toggled()) {
|
||||
_back->setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
void Panel::destroyDelayed() {
|
||||
hide();
|
||||
_controller->cancelAuth();
|
||||
not_null<Ui::RpWidget*> Panel::widget() const {
|
||||
return _widget.get();
|
||||
}
|
||||
|
||||
int Panel::hideAndDestroyGetDuration() {
|
||||
toggleOpacityAnimation(false);
|
||||
if (_animationCache.isNull()) {
|
||||
destroyDelayed();
|
||||
return 0;
|
||||
}
|
||||
return st::callPanelDuration;
|
||||
return _widget->hideAndDestroyGetDuration();
|
||||
}
|
||||
|
||||
void Panel::showAskPassword() {
|
||||
showInner(base::make_unique_q<PanelAskPassword>(_body, _controller));
|
||||
_widget->showInner(
|
||||
base::make_unique_q<PanelAskPassword>(_widget.get(), _controller));
|
||||
setBackAllowed(false);
|
||||
}
|
||||
|
||||
void Panel::showNoPassword() {
|
||||
showInner(base::make_unique_q<PanelNoPassword>(_body, _controller));
|
||||
_widget->showInner(
|
||||
base::make_unique_q<PanelNoPassword>(_widget.get(), _controller));
|
||||
setBackAllowed(false);
|
||||
}
|
||||
|
||||
void Panel::showCriticalError(const QString &error) {
|
||||
auto container = base::make_unique_q<Ui::PaddingWrap<Ui::FlatLabel>>(
|
||||
_body,
|
||||
_widget.get(),
|
||||
object_ptr<Ui::FlatLabel>(
|
||||
_body,
|
||||
_widget.get(),
|
||||
error,
|
||||
Ui::FlatLabel::InitType::Simple,
|
||||
st::passportErrorLabel),
|
||||
style::margins(0, st::passportPanelHeight / 3, 0, 0));
|
||||
style::margins(0, st::passportPanelSize.height() / 3, 0, 0));
|
||||
container->widthValue(
|
||||
) | rpl::start_with_next([label = container->entity()](int width) {
|
||||
label->resize(width, label->height());
|
||||
}, container->lifetime());
|
||||
showInner(std::move(container));
|
||||
|
||||
_widget->showInner(std::move(container));
|
||||
setBackAllowed(false);
|
||||
}
|
||||
|
||||
void Panel::showForm() {
|
||||
showInner(base::make_unique_q<PanelForm>(_body, _controller));
|
||||
_widget->showInner(
|
||||
base::make_unique_q<PanelForm>(_widget.get(), _controller));
|
||||
setBackAllowed(false);
|
||||
}
|
||||
|
||||
void Panel::showEditValue(object_ptr<Ui::RpWidget> from) {
|
||||
showInner(base::unique_qptr<Ui::RpWidget>(from.data()));
|
||||
_widget->showInner(base::unique_qptr<Ui::RpWidget>(from.data()));
|
||||
}
|
||||
|
||||
void Panel::showBox(
|
||||
object_ptr<BoxContent> box,
|
||||
LayerOptions options,
|
||||
anim::type animated) {
|
||||
ensureLayerCreated();
|
||||
_layer->showBox(std::move(box), options, animated);
|
||||
_widget->showBox(std::move(box), options, animated);
|
||||
}
|
||||
|
||||
void Panel::ensureLayerCreated() {
|
||||
if (_layer) {
|
||||
return;
|
||||
}
|
||||
_layer.create(_body);
|
||||
_layer->setHideByBackgroundClick(false);
|
||||
_layer->move(0, 0);
|
||||
_body->sizeValue(
|
||||
) | rpl::start_with_next([=](QSize size) {
|
||||
_layer->resize(size);
|
||||
}, _layer->lifetime());
|
||||
_layer->hideFinishEvents(
|
||||
) | rpl::start_with_next([=, pointer = _layer.data()]{
|
||||
if (_layer != pointer) {
|
||||
return;
|
||||
}
|
||||
auto saved = std::exchange(_layer, nullptr);
|
||||
if (Ui::InFocusChain(saved)) {
|
||||
setFocus();
|
||||
}
|
||||
saved.destroyDelayed();
|
||||
}, _layer->lifetime());
|
||||
void Panel::showToast(const QString &text) {
|
||||
_widget->showToast(text);
|
||||
}
|
||||
|
||||
void Panel::showInner(base::unique_qptr<Ui::RpWidget> inner) {
|
||||
_inner = std::move(inner);
|
||||
_inner->setParent(_body);
|
||||
_inner->move(0, 0);
|
||||
_body->sizeValue(
|
||||
) | rpl::start_with_next([=](QSize size) {
|
||||
_inner->resize(size);
|
||||
}, _inner->lifetime());
|
||||
_inner->show();
|
||||
|
||||
if (_layer) {
|
||||
_layer->raise();
|
||||
}
|
||||
|
||||
showAndActivate();
|
||||
}
|
||||
|
||||
void Panel::focusInEvent(QFocusEvent *e) {
|
||||
crl::on_main(this, [=] {
|
||||
if (_layer) {
|
||||
_layer->setInnerFocus();
|
||||
} else if (!_inner->isHidden()) {
|
||||
_inner->setFocus();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void Panel::initGeometry() {
|
||||
const auto center = Messenger::Instance().getPointForCallPanelCenter();
|
||||
_useTransparency = Platform::TranslucentWindowsSupported(center);
|
||||
setAttribute(Qt::WA_OpaquePaintEvent, !_useTransparency);
|
||||
_padding = _useTransparency
|
||||
? st::callShadow.extend
|
||||
: style::margins(
|
||||
st::lineWidth,
|
||||
st::lineWidth,
|
||||
st::lineWidth,
|
||||
st::lineWidth);
|
||||
const auto screen = QApplication::desktop()->screenGeometry(center);
|
||||
const auto rect = QRect(
|
||||
0,
|
||||
0,
|
||||
st::passportPanelWidth,
|
||||
st::passportPanelHeight);
|
||||
setGeometry(
|
||||
rect.translated(center - rect.center()).marginsAdded(_padding));
|
||||
updateControlsGeometry();
|
||||
}
|
||||
|
||||
void Panel::resizeEvent(QResizeEvent *e) {
|
||||
updateControlsGeometry();
|
||||
}
|
||||
|
||||
void Panel::updateControlsGeometry() {
|
||||
const auto top = _padding.top() + st::passportPanelTitleHeight;
|
||||
_body->setGeometry(
|
||||
_padding.left(),
|
||||
top,
|
||||
width() - _padding.left() - _padding.right(),
|
||||
height() - top - _padding.bottom());
|
||||
}
|
||||
|
||||
void Panel::paintEvent(QPaintEvent *e) {
|
||||
Painter p(this);
|
||||
if (!_animationCache.isNull()) {
|
||||
auto opacity = _opacityAnimation.current(
|
||||
getms(),
|
||||
_visible ? 1. : 0.);
|
||||
if (!_opacityAnimation.animating()) {
|
||||
finishAnimating();
|
||||
if (isHidden()) return;
|
||||
} else {
|
||||
Platform::StartTranslucentPaint(p, e);
|
||||
p.setOpacity(opacity);
|
||||
|
||||
PainterHighQualityEnabler hq(p);
|
||||
auto marginRatio = (1. - opacity) / 5;
|
||||
auto marginWidth = qRound(width() * marginRatio);
|
||||
auto marginHeight = qRound(height() * marginRatio);
|
||||
p.drawPixmap(
|
||||
rect().marginsRemoved(
|
||||
QMargins(
|
||||
marginWidth,
|
||||
marginHeight,
|
||||
marginWidth,
|
||||
marginHeight)),
|
||||
_animationCache,
|
||||
QRect(QPoint(0, 0), _animationCache.size()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (_useTransparency) {
|
||||
Platform::StartTranslucentPaint(p, e);
|
||||
paintShadowBorder(p);
|
||||
} else {
|
||||
paintOpaqueBorder(p);
|
||||
}
|
||||
}
|
||||
|
||||
void Panel::paintShadowBorder(Painter &p) const {
|
||||
const auto factor = cIntRetinaFactor();
|
||||
const auto size = st::passportPanelBorderCacheSize;
|
||||
const auto part1 = size / 3;
|
||||
const auto part2 = size - part1;
|
||||
const auto corner = QSize(part1, part1) * factor;
|
||||
|
||||
const auto topleft = QRect(QPoint(0, 0), corner);
|
||||
p.drawPixmap(QRect(0, 0, part1, part1), _borderParts, topleft);
|
||||
|
||||
const auto topright = QRect(QPoint(part2, 0) * factor, corner);
|
||||
p.drawPixmap(
|
||||
QRect(width() - part1, 0, part1, part1),
|
||||
_borderParts,
|
||||
topright);
|
||||
|
||||
const auto bottomleft = QRect(QPoint(0, part2) * factor, corner);
|
||||
p.drawPixmap(
|
||||
QRect(0, height() - part1, part1, part1),
|
||||
_borderParts,
|
||||
bottomleft);
|
||||
|
||||
const auto bottomright = QRect(QPoint(part2, part2) * factor, corner);
|
||||
p.drawPixmap(
|
||||
QRect(width() - part1, height() - part1, part1, part1),
|
||||
_borderParts,
|
||||
bottomright);
|
||||
|
||||
const auto left = QRect(
|
||||
QPoint(0, part1) * factor,
|
||||
QSize(_padding.left(), part2 - part1) * factor);
|
||||
p.drawPixmap(
|
||||
QRect(0, part1, _padding.left(), height() - 2 * part1),
|
||||
_borderParts,
|
||||
left);
|
||||
|
||||
const auto top = QRect(
|
||||
QPoint(part1, 0) * factor,
|
||||
QSize(part2 - part1, _padding.top() + st::callRadius) * factor);
|
||||
p.drawPixmap(
|
||||
QRect(
|
||||
part1,
|
||||
0,
|
||||
width() - 2 * part1,
|
||||
_padding.top() + st::callRadius),
|
||||
_borderParts,
|
||||
top);
|
||||
|
||||
const auto right = QRect(
|
||||
QPoint(size - _padding.right(), part1) * factor,
|
||||
QSize(_padding.right(), part2 - part1) * factor);
|
||||
p.drawPixmap(
|
||||
QRect(
|
||||
width() - _padding.right(),
|
||||
part1,
|
||||
_padding.right(),
|
||||
height() - 2 * part1),
|
||||
_borderParts,
|
||||
right);
|
||||
|
||||
const auto bottom = QRect(
|
||||
QPoint(part1, size - _padding.bottom() - st::callRadius) * factor,
|
||||
QSize(part2 - part1, _padding.bottom() + st::callRadius) * factor);
|
||||
p.drawPixmap(
|
||||
QRect(
|
||||
part1,
|
||||
height() - _padding.bottom() - st::callRadius,
|
||||
width() - 2 * part1,
|
||||
_padding.bottom() + st::callRadius),
|
||||
_borderParts,
|
||||
bottom);
|
||||
|
||||
p.fillRect(
|
||||
_padding.left(),
|
||||
_padding.top() + st::callRadius,
|
||||
width() - _padding.left() - _padding.right(),
|
||||
height() - _padding.top() - _padding.bottom() - 2 * st::callRadius,
|
||||
st::windowBg);
|
||||
}
|
||||
|
||||
void Panel::paintOpaqueBorder(Painter &p) const {
|
||||
const auto border = st::windowShadowFgFallback;
|
||||
p.fillRect(0, 0, width(), _padding.top(), border);
|
||||
p.fillRect(
|
||||
myrtlrect(
|
||||
0,
|
||||
_padding.top(),
|
||||
_padding.left(),
|
||||
height() - _padding.top()),
|
||||
border);
|
||||
p.fillRect(
|
||||
myrtlrect(
|
||||
width() - _padding.right(),
|
||||
_padding.top(),
|
||||
_padding.right(),
|
||||
height() - _padding.top()),
|
||||
border);
|
||||
p.fillRect(
|
||||
_padding.left(),
|
||||
height() - _padding.bottom(),
|
||||
width() - _padding.left() - _padding.right(),
|
||||
_padding.bottom(),
|
||||
border);
|
||||
|
||||
p.fillRect(
|
||||
_padding.left(),
|
||||
_padding.top(),
|
||||
width() - _padding.left() - _padding.right(),
|
||||
height() - _padding.top() - _padding.bottom(),
|
||||
st::windowBg);
|
||||
}
|
||||
|
||||
void Panel::closeEvent(QCloseEvent *e) {
|
||||
// #TODO passport
|
||||
}
|
||||
|
||||
void Panel::mousePressEvent(QMouseEvent *e) {
|
||||
auto dragArea = myrtlrect(
|
||||
_padding.left(),
|
||||
_padding.top(),
|
||||
width() - _padding.left() - _padding.right(),
|
||||
st::passportPanelTitleHeight);
|
||||
if (e->button() == Qt::LeftButton) {
|
||||
if (dragArea.contains(e->pos())) {
|
||||
_dragging = true;
|
||||
_dragStartMousePosition = e->globalPos();
|
||||
_dragStartMyPosition = QPoint(x(), y());
|
||||
} else if (!rect().contains(e->pos())) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Panel::mouseMoveEvent(QMouseEvent *e) {
|
||||
if (_dragging) {
|
||||
if (!(e->buttons() & Qt::LeftButton)) {
|
||||
_dragging = false;
|
||||
} else {
|
||||
move(_dragStartMyPosition
|
||||
+ (e->globalPos() - _dragStartMousePosition));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Panel::mouseReleaseEvent(QMouseEvent *e) {
|
||||
if (e->button() == Qt::LeftButton) {
|
||||
_dragging = false;
|
||||
}
|
||||
}
|
||||
|
||||
void Panel::leaveEventHook(QEvent *e) {
|
||||
}
|
||||
|
||||
void Panel::leaveToChildEvent(QEvent *e, QWidget *child) {
|
||||
}
|
||||
Panel::~Panel() = default;
|
||||
|
||||
} // namespace Passport
|
||||
|
|
|
@ -7,32 +7,19 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
*/
|
||||
#pragma once
|
||||
|
||||
#include "ui/rp_widget.h"
|
||||
#include "boxes/abstract_box.h"
|
||||
|
||||
namespace Ui {
|
||||
class IconButton;
|
||||
class FlatLabel;
|
||||
template <typename Widget>
|
||||
class FadeWrapScaled;
|
||||
class RpWidget;
|
||||
class SeparatePanel;
|
||||
} // namespace Ui
|
||||
|
||||
namespace Window {
|
||||
class LayerStackWidget;
|
||||
} // namespace Window
|
||||
|
||||
namespace Passport {
|
||||
|
||||
class PanelController;
|
||||
|
||||
class Panel
|
||||
: public Ui::RpWidget
|
||||
, private base::Subscriber {
|
||||
|
||||
class Panel {
|
||||
public:
|
||||
Panel(not_null<PanelController*> controller);
|
||||
|
||||
void showAndActivate();
|
||||
int hideAndDestroyGetDuration();
|
||||
|
||||
void showAskPassword();
|
||||
|
@ -44,63 +31,18 @@ public:
|
|||
object_ptr<BoxContent> box,
|
||||
LayerOptions options,
|
||||
anim::type animated);
|
||||
void showToast(const QString &text);
|
||||
|
||||
rpl::producer<> backRequests() const;
|
||||
void setBackAllowed(bool allowed);
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
void closeEvent(QCloseEvent *e) override;
|
||||
void resizeEvent(QResizeEvent *e) override;
|
||||
void focusInEvent(QFocusEvent *e) override;
|
||||
void mousePressEvent(QMouseEvent *e) override;
|
||||
void mouseReleaseEvent(QMouseEvent *e) override;
|
||||
void mouseMoveEvent(QMouseEvent *e) override;
|
||||
void leaveEventHook(QEvent *e) override;
|
||||
void leaveToChildEvent(QEvent *e, QWidget *child) override;
|
||||
void keyPressEvent(QKeyEvent *e) override;
|
||||
not_null<Ui::RpWidget*> widget() const;
|
||||
|
||||
~Panel();
|
||||
|
||||
private:
|
||||
void initControls();
|
||||
void initLayout();
|
||||
void initGeometry();
|
||||
void showControls();
|
||||
void updateControlsGeometry();
|
||||
void createBorderImage();
|
||||
void opacityCallback();
|
||||
void showInner(base::unique_qptr<Ui::RpWidget> inner);
|
||||
void ensureLayerCreated();
|
||||
|
||||
void updateTitlePosition();
|
||||
void paintShadowBorder(Painter &p) const;
|
||||
void paintOpaqueBorder(Painter &p) const;
|
||||
|
||||
void toggleOpacityAnimation(bool visible);
|
||||
void finishAnimating();
|
||||
void destroyDelayed();
|
||||
|
||||
not_null<PanelController*> _controller;
|
||||
object_ptr<Ui::IconButton> _close;
|
||||
object_ptr<Ui::FlatLabel> _title;
|
||||
object_ptr<Ui::FadeWrapScaled<Ui::IconButton>> _back;
|
||||
object_ptr<Ui::RpWidget> _body;
|
||||
base::unique_qptr<Ui::RpWidget> _inner;
|
||||
object_ptr<Window::LayerStackWidget> _layer = { nullptr };
|
||||
rpl::event_stream<> _synteticBackRequests;
|
||||
|
||||
bool _useTransparency = true;
|
||||
style::margins _padding;
|
||||
|
||||
bool _dragging = false;
|
||||
QPoint _dragStartMousePosition;
|
||||
QPoint _dragStartMyPosition;
|
||||
|
||||
Animation _titleLeft;
|
||||
bool _visible = false;
|
||||
|
||||
Animation _opacityAnimation;
|
||||
QPixmap _animationCache;
|
||||
QPixmap _borderParts;
|
||||
std::unique_ptr<Ui::SeparatePanel> _widget;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "boxes/passcode_box.h"
|
||||
#include "boxes/confirm_box.h"
|
||||
#include "ui/toast/toast.h"
|
||||
#include "ui/rp_widget.h"
|
||||
#include "ui/countryinput.h"
|
||||
#include "layout.h"
|
||||
#include "styles/style_boxes.h"
|
||||
|
@ -492,7 +493,7 @@ void PanelController::setupPassword() {
|
|||
notEmptyPassport,
|
||||
hint,
|
||||
newSecureSecretSalt));
|
||||
box->connect(box, &PasscodeBox::reloadPassword, _panel.get(), [=] {
|
||||
box->connect(box, &PasscodeBox::reloadPassword, [=] {
|
||||
_form->reloadPassword();
|
||||
});
|
||||
}
|
||||
|
@ -894,7 +895,8 @@ void PanelController::editWithUpload(int index, int documentIndex) {
|
|||
Expects(documentIndex >= 0
|
||||
&& documentIndex < _scopes[index].documents.size());
|
||||
|
||||
EditScans::ChooseScan(_panel.get(), [=](QByteArray &&content) {
|
||||
const auto widget = _panel->widget();
|
||||
EditScans::ChooseScan(widget.get(), [=](QByteArray &&content) {
|
||||
base::take(_scopeDocumentTypeBox);
|
||||
editScope(index, documentIndex);
|
||||
if (_scopes[index].documents[documentIndex]->requiresSpecialScan(
|
||||
|
@ -949,7 +951,7 @@ void PanelController::editScope(int index, int documentIndex) {
|
|||
case Scope::Type::Address: {
|
||||
auto result = _editDocument
|
||||
? object_ptr<PanelEditDocument>(
|
||||
_panel.get(),
|
||||
_panel->widget(),
|
||||
this,
|
||||
GetDocumentScheme(
|
||||
_editScope->type,
|
||||
|
@ -960,7 +962,7 @@ void PanelController::editScope(int index, int documentIndex) {
|
|||
valueFiles(*_editDocument),
|
||||
valueSpecialFiles(*_editDocument))
|
||||
: object_ptr<PanelEditDocument>(
|
||||
_panel.get(),
|
||||
_panel->widget(),
|
||||
this,
|
||||
GetDocumentScheme(_editScope->type),
|
||||
_editValue->data.parsedInEdit);
|
||||
|
@ -980,7 +982,7 @@ void PanelController::editScope(int index, int documentIndex) {
|
|||
const auto existing = getDefaultContactValue(_editScope->type);
|
||||
_panelHasUnsavedChanges = nullptr;
|
||||
return object_ptr<PanelEditContact>(
|
||||
_panel.get(),
|
||||
_panel->widget(),
|
||||
this,
|
||||
GetContactScheme(_editScope->type),
|
||||
value,
|
||||
|
@ -1206,11 +1208,7 @@ void PanelController::showBox(
|
|||
}
|
||||
|
||||
void PanelController::showToast(const QString &text) {
|
||||
Expects(_panel != nullptr);
|
||||
|
||||
auto toast = Ui::Toast::Config();
|
||||
toast.text = text;
|
||||
Ui::Toast::Show(_panel.get(), toast);
|
||||
_panel->showToast(text);
|
||||
}
|
||||
|
||||
rpl::lifetime &PanelController::lifetime() {
|
||||
|
|
532
Telegram/SourceFiles/ui/widgets/separate_panel.cpp
Normal file
532
Telegram/SourceFiles/ui/widgets/separate_panel.cpp
Normal file
|
@ -0,0 +1,532 @@
|
|||
/*
|
||||
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/widgets/separate_panel.h"
|
||||
|
||||
#include "window/main_window.h"
|
||||
#include "platform/platform_specific.h"
|
||||
#include "ui/widgets/shadow.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/widgets/labels.h"
|
||||
#include "ui/wrap/padding_wrap.h"
|
||||
#include "ui/wrap/fade_wrap.h"
|
||||
#include "ui/toast/toast.h"
|
||||
#include "ui/widgets/tooltip.h"
|
||||
#include "window/layer_widget.h"
|
||||
#include "messenger.h"
|
||||
#include "styles/style_widgets.h"
|
||||
#include "styles/style_info.h"
|
||||
#include "styles/style_calls.h"
|
||||
|
||||
namespace Ui {
|
||||
|
||||
SeparatePanel::SeparatePanel()
|
||||
: _close(this, st::separatePanelClose)
|
||||
, _back(this, object_ptr<Ui::IconButton>(this, st::separatePanelBack))
|
||||
, _body(this) {
|
||||
setMouseTracking(true);
|
||||
setWindowIcon(Window::CreateIcon());
|
||||
initControls();
|
||||
initLayout();
|
||||
}
|
||||
|
||||
void SeparatePanel::setTitle(rpl::producer<QString> title) {
|
||||
_title.create(this, std::move(title), st::separatePanelTitle);
|
||||
_title->setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||
}
|
||||
|
||||
void SeparatePanel::initControls() {
|
||||
widthValue(
|
||||
) | rpl::start_with_next([=](int width) {
|
||||
_back->moveToLeft(_padding.left(), _padding.top());
|
||||
_close->moveToRight(_padding.right(), _padding.top());
|
||||
if (_title) {
|
||||
_title->resizeToWidth(width
|
||||
- _padding.left() - _back->width()
|
||||
- _padding.right() - _close->width());
|
||||
updateTitlePosition();
|
||||
}
|
||||
}, lifetime());
|
||||
|
||||
_back->toggledValue(
|
||||
) | rpl::start_with_next([=](bool toggled) {
|
||||
_titleLeft.start(
|
||||
[=] { updateTitlePosition(); },
|
||||
toggled ? 0. : 1.,
|
||||
toggled ? 1. : 0.,
|
||||
st::fadeWrapDuration);
|
||||
}, _back->lifetime());
|
||||
_back->hide(anim::type::instant);
|
||||
_titleLeft.finish();
|
||||
}
|
||||
|
||||
void SeparatePanel::updateTitlePosition() {
|
||||
if (!_title) {
|
||||
return;
|
||||
}
|
||||
const auto progress = _titleLeft.current(_back->toggled() ? 1. : 0.);
|
||||
const auto left = anim::interpolate(
|
||||
st::separatePanelTitleLeft,
|
||||
_back->width() + st::separatePanelTitleSkip,
|
||||
progress);
|
||||
_title->moveToLeft(
|
||||
_padding.left() + left,
|
||||
_padding.top() + st::separatePanelTitleTop);
|
||||
}
|
||||
|
||||
rpl::producer<> SeparatePanel::backRequests() const {
|
||||
return rpl::merge(
|
||||
_back->entity()->clicks(),
|
||||
_synteticBackRequests.events());
|
||||
}
|
||||
|
||||
rpl::producer<> SeparatePanel::closeRequests() const {
|
||||
return _close->clicks();
|
||||
}
|
||||
|
||||
rpl::producer<> SeparatePanel::destroyRequests() const {
|
||||
return _destroyRequests.events();
|
||||
}
|
||||
|
||||
void SeparatePanel::setBackAllowed(bool allowed) {
|
||||
if (allowed != _back->toggled()) {
|
||||
_back->toggle(allowed, anim::type::normal);
|
||||
}
|
||||
}
|
||||
|
||||
void SeparatePanel::showAndActivate() {
|
||||
toggleOpacityAnimation(true);
|
||||
raise();
|
||||
setWindowState(windowState() | Qt::WindowActive);
|
||||
activateWindow();
|
||||
setFocus();
|
||||
}
|
||||
|
||||
void SeparatePanel::keyPressEvent(QKeyEvent *e) {
|
||||
if (e->key() == Qt::Key_Escape && _back->toggled()) {
|
||||
_synteticBackRequests.fire({});
|
||||
}
|
||||
return RpWidget::keyPressEvent(e);
|
||||
}
|
||||
|
||||
void SeparatePanel::initLayout() {
|
||||
setWindowFlags(Qt::WindowFlags(Qt::FramelessWindowHint)
|
||||
| Qt::WindowStaysOnTopHint
|
||||
| Qt::BypassWindowManagerHint
|
||||
| Qt::NoDropShadowWindowHint
|
||||
| Qt::Dialog);
|
||||
setAttribute(Qt::WA_MacAlwaysShowToolWindow);
|
||||
setAttribute(Qt::WA_NoSystemBackground, true);
|
||||
setAttribute(Qt::WA_TranslucentBackground, true);
|
||||
|
||||
createBorderImage();
|
||||
|
||||
Platform::InitOnTopPanel(this);
|
||||
}
|
||||
|
||||
void SeparatePanel::createBorderImage() {
|
||||
const auto shadowPadding = st::callShadow.extend;
|
||||
const auto cacheSize = st::separatePanelBorderCacheSize;
|
||||
auto cache = QImage(
|
||||
cacheSize * cIntRetinaFactor(),
|
||||
cacheSize * cIntRetinaFactor(),
|
||||
QImage::Format_ARGB32_Premultiplied);
|
||||
cache.setDevicePixelRatio(cRetinaFactor());
|
||||
cache.fill(Qt::transparent);
|
||||
{
|
||||
Painter p(&cache);
|
||||
auto inner = QRect(0, 0, cacheSize, cacheSize).marginsRemoved(
|
||||
shadowPadding);
|
||||
Ui::Shadow::paint(p, inner, cacheSize, st::callShadow);
|
||||
p.setCompositionMode(QPainter::CompositionMode_Source);
|
||||
p.setBrush(st::windowBg);
|
||||
p.setPen(Qt::NoPen);
|
||||
PainterHighQualityEnabler hq(p);
|
||||
p.drawRoundedRect(
|
||||
myrtlrect(inner),
|
||||
st::callRadius,
|
||||
st::callRadius);
|
||||
}
|
||||
_borderParts = App::pixmapFromImageInPlace(std::move(cache));
|
||||
}
|
||||
|
||||
void SeparatePanel::toggleOpacityAnimation(bool visible) {
|
||||
if (_visible == visible) {
|
||||
return;
|
||||
}
|
||||
|
||||
_visible = visible;
|
||||
if (_useTransparency) {
|
||||
if (_animationCache.isNull()) {
|
||||
showControls();
|
||||
_animationCache = Ui::GrabWidget(this);
|
||||
hideChildren();
|
||||
}
|
||||
_opacityAnimation.start(
|
||||
[this] { opacityCallback(); },
|
||||
_visible ? 0. : 1.,
|
||||
_visible ? 1. : 0.,
|
||||
st::callPanelDuration,
|
||||
_visible ? anim::easeOutCirc : anim::easeInCirc);
|
||||
}
|
||||
if (isHidden() && _visible) {
|
||||
show();
|
||||
}
|
||||
}
|
||||
|
||||
void SeparatePanel::opacityCallback() {
|
||||
update();
|
||||
if (!_visible && !_opacityAnimation.animating()) {
|
||||
finishAnimating();
|
||||
}
|
||||
}
|
||||
|
||||
void SeparatePanel::finishAnimating() {
|
||||
_animationCache = QPixmap();
|
||||
if (_visible) {
|
||||
showControls();
|
||||
_inner->setFocus();
|
||||
} else {
|
||||
destroyDelayed();
|
||||
}
|
||||
}
|
||||
|
||||
void SeparatePanel::showControls() {
|
||||
showChildren();
|
||||
if (!_back->toggled()) {
|
||||
_back->setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
void SeparatePanel::destroyDelayed() {
|
||||
hide();
|
||||
_destroyRequests.fire({});
|
||||
}
|
||||
|
||||
int SeparatePanel::hideAndDestroyGetDuration() {
|
||||
toggleOpacityAnimation(false);
|
||||
if (_animationCache.isNull()) {
|
||||
destroyDelayed();
|
||||
return 0;
|
||||
}
|
||||
return st::callPanelDuration;
|
||||
}
|
||||
|
||||
void SeparatePanel::showBox(
|
||||
object_ptr<BoxContent> box,
|
||||
LayerOptions options,
|
||||
anim::type animated) {
|
||||
ensureLayerCreated();
|
||||
_layer->showBox(std::move(box), options, animated);
|
||||
}
|
||||
|
||||
void SeparatePanel::showToast(const QString &text) {
|
||||
auto toast = Ui::Toast::Config();
|
||||
toast.text = text;
|
||||
Ui::Toast::Show(this, toast);
|
||||
}
|
||||
|
||||
void SeparatePanel::ensureLayerCreated() {
|
||||
if (_layer) {
|
||||
return;
|
||||
}
|
||||
_layer.create(_body);
|
||||
_layer->setHideByBackgroundClick(false);
|
||||
_layer->move(0, 0);
|
||||
_body->sizeValue(
|
||||
) | rpl::start_with_next([=](QSize size) {
|
||||
_layer->resize(size);
|
||||
}, _layer->lifetime());
|
||||
_layer->hideFinishEvents(
|
||||
) | rpl::start_with_next([=, pointer = _layer.data()]{
|
||||
if (_layer != pointer) {
|
||||
return;
|
||||
}
|
||||
auto saved = std::exchange(_layer, nullptr);
|
||||
if (Ui::InFocusChain(saved)) {
|
||||
setFocus();
|
||||
}
|
||||
saved.destroyDelayed();
|
||||
}, _layer->lifetime());
|
||||
}
|
||||
|
||||
void SeparatePanel::showInner(base::unique_qptr<Ui::RpWidget> inner) {
|
||||
Expects(!size().isEmpty());
|
||||
|
||||
_inner = std::move(inner);
|
||||
_inner->setParent(_body);
|
||||
_inner->move(0, 0);
|
||||
_body->sizeValue(
|
||||
) | rpl::start_with_next([=](QSize size) {
|
||||
_inner->resize(size);
|
||||
}, _inner->lifetime());
|
||||
_inner->show();
|
||||
|
||||
if (_layer) {
|
||||
_layer->raise();
|
||||
}
|
||||
|
||||
showAndActivate();
|
||||
}
|
||||
|
||||
void SeparatePanel::focusInEvent(QFocusEvent *e) {
|
||||
crl::on_main(this, [=] {
|
||||
if (_layer) {
|
||||
_layer->setInnerFocus();
|
||||
} else if (!_inner->isHidden()) {
|
||||
_inner->setFocus();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void SeparatePanel::setInnerSize(QSize size) {
|
||||
Expects(!size.isEmpty());
|
||||
|
||||
if (rect().isEmpty()) {
|
||||
initGeometry(size);
|
||||
} else {
|
||||
updateGeometry(size);
|
||||
}
|
||||
}
|
||||
|
||||
void SeparatePanel::initGeometry(QSize size) {
|
||||
const auto center = Messenger::Instance().getPointForCallPanelCenter();
|
||||
_useTransparency = Platform::TranslucentWindowsSupported(center);
|
||||
_padding = _useTransparency
|
||||
? st::callShadow.extend
|
||||
: style::margins(
|
||||
st::lineWidth,
|
||||
st::lineWidth,
|
||||
st::lineWidth,
|
||||
st::lineWidth);
|
||||
setAttribute(Qt::WA_OpaquePaintEvent, !_useTransparency);
|
||||
const auto screen = QApplication::desktop()->screenGeometry(center);
|
||||
const auto rect = QRect(QPoint(), size);
|
||||
setGeometry(
|
||||
rect.translated(center - rect.center()).marginsAdded(_padding));
|
||||
updateControlsGeometry();
|
||||
}
|
||||
|
||||
void SeparatePanel::updateGeometry(QSize size) {
|
||||
setGeometry(
|
||||
x(),
|
||||
y(),
|
||||
_padding.left() + size.width() + _padding.right(),
|
||||
_padding.top() + size.height() + _padding.bottom());
|
||||
updateControlsGeometry();
|
||||
update();
|
||||
}
|
||||
|
||||
void SeparatePanel::resizeEvent(QResizeEvent *e) {
|
||||
updateControlsGeometry();
|
||||
}
|
||||
|
||||
void SeparatePanel::updateControlsGeometry() {
|
||||
const auto top = _padding.top() + st::separatePanelTitleHeight;
|
||||
_body->setGeometry(
|
||||
_padding.left(),
|
||||
top,
|
||||
width() - _padding.left() - _padding.right(),
|
||||
height() - top - _padding.bottom());
|
||||
}
|
||||
|
||||
void SeparatePanel::paintEvent(QPaintEvent *e) {
|
||||
Painter p(this);
|
||||
if (!_animationCache.isNull()) {
|
||||
auto opacity = _opacityAnimation.current(
|
||||
getms(),
|
||||
_visible ? 1. : 0.);
|
||||
if (!_opacityAnimation.animating()) {
|
||||
finishAnimating();
|
||||
if (isHidden()) return;
|
||||
} else {
|
||||
Platform::StartTranslucentPaint(p, e);
|
||||
p.setOpacity(opacity);
|
||||
|
||||
PainterHighQualityEnabler hq(p);
|
||||
auto marginRatio = (1. - opacity) / 5;
|
||||
auto marginWidth = qRound(width() * marginRatio);
|
||||
auto marginHeight = qRound(height() * marginRatio);
|
||||
p.drawPixmap(
|
||||
rect().marginsRemoved(
|
||||
QMargins(
|
||||
marginWidth,
|
||||
marginHeight,
|
||||
marginWidth,
|
||||
marginHeight)),
|
||||
_animationCache,
|
||||
QRect(QPoint(0, 0), _animationCache.size()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (_useTransparency) {
|
||||
Platform::StartTranslucentPaint(p, e);
|
||||
paintShadowBorder(p);
|
||||
} else {
|
||||
paintOpaqueBorder(p);
|
||||
}
|
||||
}
|
||||
|
||||
void SeparatePanel::paintShadowBorder(Painter &p) const {
|
||||
const auto factor = cIntRetinaFactor();
|
||||
const auto size = st::separatePanelBorderCacheSize;
|
||||
const auto part1 = size / 3;
|
||||
const auto part2 = size - part1;
|
||||
const auto corner = QSize(part1, part1) * factor;
|
||||
|
||||
const auto topleft = QRect(QPoint(0, 0), corner);
|
||||
p.drawPixmap(QRect(0, 0, part1, part1), _borderParts, topleft);
|
||||
|
||||
const auto topright = QRect(QPoint(part2, 0) * factor, corner);
|
||||
p.drawPixmap(
|
||||
QRect(width() - part1, 0, part1, part1),
|
||||
_borderParts,
|
||||
topright);
|
||||
|
||||
const auto bottomleft = QRect(QPoint(0, part2) * factor, corner);
|
||||
p.drawPixmap(
|
||||
QRect(0, height() - part1, part1, part1),
|
||||
_borderParts,
|
||||
bottomleft);
|
||||
|
||||
const auto bottomright = QRect(QPoint(part2, part2) * factor, corner);
|
||||
p.drawPixmap(
|
||||
QRect(width() - part1, height() - part1, part1, part1),
|
||||
_borderParts,
|
||||
bottomright);
|
||||
|
||||
const auto left = QRect(
|
||||
QPoint(0, part1) * factor,
|
||||
QSize(_padding.left(), part2 - part1) * factor);
|
||||
p.drawPixmap(
|
||||
QRect(0, part1, _padding.left(), height() - 2 * part1),
|
||||
_borderParts,
|
||||
left);
|
||||
|
||||
const auto top = QRect(
|
||||
QPoint(part1, 0) * factor,
|
||||
QSize(part2 - part1, _padding.top() + st::callRadius) * factor);
|
||||
p.drawPixmap(
|
||||
QRect(
|
||||
part1,
|
||||
0,
|
||||
width() - 2 * part1,
|
||||
_padding.top() + st::callRadius),
|
||||
_borderParts,
|
||||
top);
|
||||
|
||||
const auto right = QRect(
|
||||
QPoint(size - _padding.right(), part1) * factor,
|
||||
QSize(_padding.right(), part2 - part1) * factor);
|
||||
p.drawPixmap(
|
||||
QRect(
|
||||
width() - _padding.right(),
|
||||
part1,
|
||||
_padding.right(),
|
||||
height() - 2 * part1),
|
||||
_borderParts,
|
||||
right);
|
||||
|
||||
const auto bottom = QRect(
|
||||
QPoint(part1, size - _padding.bottom() - st::callRadius) * factor,
|
||||
QSize(part2 - part1, _padding.bottom() + st::callRadius) * factor);
|
||||
p.drawPixmap(
|
||||
QRect(
|
||||
part1,
|
||||
height() - _padding.bottom() - st::callRadius,
|
||||
width() - 2 * part1,
|
||||
_padding.bottom() + st::callRadius),
|
||||
_borderParts,
|
||||
bottom);
|
||||
|
||||
p.fillRect(
|
||||
_padding.left(),
|
||||
_padding.top() + st::callRadius,
|
||||
width() - _padding.left() - _padding.right(),
|
||||
height() - _padding.top() - _padding.bottom() - 2 * st::callRadius,
|
||||
st::windowBg);
|
||||
}
|
||||
|
||||
void SeparatePanel::paintOpaqueBorder(Painter &p) const {
|
||||
const auto border = st::windowShadowFgFallback;
|
||||
p.fillRect(0, 0, width(), _padding.top(), border);
|
||||
p.fillRect(
|
||||
myrtlrect(
|
||||
0,
|
||||
_padding.top(),
|
||||
_padding.left(),
|
||||
height() - _padding.top()),
|
||||
border);
|
||||
p.fillRect(
|
||||
myrtlrect(
|
||||
width() - _padding.right(),
|
||||
_padding.top(),
|
||||
_padding.right(),
|
||||
height() - _padding.top()),
|
||||
border);
|
||||
p.fillRect(
|
||||
_padding.left(),
|
||||
height() - _padding.bottom(),
|
||||
width() - _padding.left() - _padding.right(),
|
||||
_padding.bottom(),
|
||||
border);
|
||||
|
||||
p.fillRect(
|
||||
_padding.left(),
|
||||
_padding.top(),
|
||||
width() - _padding.left() - _padding.right(),
|
||||
height() - _padding.top() - _padding.bottom(),
|
||||
st::windowBg);
|
||||
}
|
||||
|
||||
void SeparatePanel::closeEvent(QCloseEvent *e) {
|
||||
// #TODO passport
|
||||
}
|
||||
|
||||
void SeparatePanel::mousePressEvent(QMouseEvent *e) {
|
||||
auto dragArea = myrtlrect(
|
||||
_padding.left(),
|
||||
_padding.top(),
|
||||
width() - _padding.left() - _padding.right(),
|
||||
st::separatePanelTitleHeight);
|
||||
if (e->button() == Qt::LeftButton) {
|
||||
if (dragArea.contains(e->pos())) {
|
||||
_dragging = true;
|
||||
_dragStartMousePosition = e->globalPos();
|
||||
_dragStartMyPosition = QPoint(x(), y());
|
||||
} else if (!rect().contains(e->pos())) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SeparatePanel::mouseMoveEvent(QMouseEvent *e) {
|
||||
if (_dragging) {
|
||||
if (!(e->buttons() & Qt::LeftButton)) {
|
||||
_dragging = false;
|
||||
} else {
|
||||
move(_dragStartMyPosition
|
||||
+ (e->globalPos() - _dragStartMousePosition));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SeparatePanel::mouseReleaseEvent(QMouseEvent *e) {
|
||||
if (e->button() == Qt::LeftButton) {
|
||||
_dragging = false;
|
||||
}
|
||||
}
|
||||
|
||||
void SeparatePanel::leaveEventHook(QEvent *e) {
|
||||
Ui::Tooltip::Hide();
|
||||
}
|
||||
|
||||
void SeparatePanel::leaveToChildEvent(QEvent *e, QWidget *child) {
|
||||
Ui::Tooltip::Hide();
|
||||
}
|
||||
|
||||
} // namespace Ui
|
104
Telegram/SourceFiles/ui/widgets/separate_panel.h
Normal file
104
Telegram/SourceFiles/ui/widgets/separate_panel.h
Normal file
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
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 "boxes/abstract_box.h"
|
||||
|
||||
namespace Ui {
|
||||
class IconButton;
|
||||
class FlatLabel;
|
||||
template <typename Widget>
|
||||
class FadeWrapScaled;
|
||||
} // namespace Ui
|
||||
|
||||
namespace Window {
|
||||
class LayerStackWidget;
|
||||
} // namespace Window
|
||||
|
||||
namespace Ui {
|
||||
|
||||
class SeparatePanel : public Ui::RpWidget {
|
||||
public:
|
||||
SeparatePanel();
|
||||
|
||||
void setTitle(rpl::producer<QString> title);
|
||||
void setInnerSize(QSize size);
|
||||
|
||||
void showAndActivate();
|
||||
int hideAndDestroyGetDuration();
|
||||
|
||||
void showInner(base::unique_qptr<Ui::RpWidget> inner);
|
||||
void showBox(
|
||||
object_ptr<BoxContent> box,
|
||||
LayerOptions options,
|
||||
anim::type animated);
|
||||
void showToast(const QString &text);
|
||||
|
||||
rpl::producer<> backRequests() const;
|
||||
rpl::producer<> closeRequests() const;
|
||||
rpl::producer<> destroyRequests() const;
|
||||
void setBackAllowed(bool allowed);
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
void closeEvent(QCloseEvent *e) override;
|
||||
void resizeEvent(QResizeEvent *e) override;
|
||||
void focusInEvent(QFocusEvent *e) override;
|
||||
void mousePressEvent(QMouseEvent *e) override;
|
||||
void mouseReleaseEvent(QMouseEvent *e) override;
|
||||
void mouseMoveEvent(QMouseEvent *e) override;
|
||||
void leaveEventHook(QEvent *e) override;
|
||||
void leaveToChildEvent(QEvent *e, QWidget *child) override;
|
||||
void keyPressEvent(QKeyEvent *e) override;
|
||||
|
||||
private:
|
||||
void initControls();
|
||||
void initLayout();
|
||||
void initGeometry(QSize size);
|
||||
void updateGeometry(QSize size);
|
||||
void showControls();
|
||||
void updateControlsGeometry();
|
||||
void createBorderImage();
|
||||
void opacityCallback();
|
||||
void ensureLayerCreated();
|
||||
|
||||
void updateTitlePosition();
|
||||
void paintShadowBorder(Painter &p) const;
|
||||
void paintOpaqueBorder(Painter &p) const;
|
||||
|
||||
void toggleOpacityAnimation(bool visible);
|
||||
void finishAnimating();
|
||||
void destroyDelayed();
|
||||
|
||||
object_ptr<Ui::IconButton> _close;
|
||||
object_ptr<Ui::FlatLabel> _title = { nullptr };
|
||||
object_ptr<Ui::FadeWrapScaled<Ui::IconButton>> _back;
|
||||
object_ptr<Ui::RpWidget> _body;
|
||||
base::unique_qptr<Ui::RpWidget> _inner;
|
||||
object_ptr<Window::LayerStackWidget> _layer = { nullptr };
|
||||
rpl::event_stream<> _synteticBackRequests;
|
||||
rpl::event_stream<> _destroyRequests;
|
||||
|
||||
bool _useTransparency = true;
|
||||
style::margins _padding;
|
||||
|
||||
bool _dragging = false;
|
||||
QPoint _dragStartMousePosition;
|
||||
QPoint _dragStartMyPosition;
|
||||
|
||||
Animation _titleLeft;
|
||||
bool _visible = false;
|
||||
|
||||
Animation _opacityAnimation;
|
||||
QPixmap _animationCache;
|
||||
QPixmap _borderParts;
|
||||
|
||||
};
|
||||
|
||||
} // namespace Ui
|
|
@ -667,6 +667,8 @@
|
|||
<(src_loc)/ui/widgets/multi_select.h
|
||||
<(src_loc)/ui/widgets/popup_menu.cpp
|
||||
<(src_loc)/ui/widgets/popup_menu.h
|
||||
<(src_loc)/ui/widgets/separate_panel.cpp
|
||||
<(src_loc)/ui/widgets/separate_panel.h
|
||||
<(src_loc)/ui/widgets/scroll_area.cpp
|
||||
<(src_loc)/ui/widgets/scroll_area.h
|
||||
<(src_loc)/ui/widgets/shadow.cpp
|
||||
|
|
Loading…
Add table
Reference in a new issue