Added masked shadow corners for special layers.
This commit is contained in:
parent
549edbe5c7
commit
b9a702f6e0
6 changed files with 172 additions and 28 deletions
|
|
@ -227,6 +227,8 @@ PRIVATE
|
|||
ui/abstract_button.h
|
||||
ui/basic_click_handlers.cpp
|
||||
ui/basic_click_handlers.h
|
||||
ui/cached_special_layer_shadow_corners.cpp
|
||||
ui/cached_special_layer_shadow_corners.h
|
||||
ui/click_handler.cpp
|
||||
ui/click_handler.h
|
||||
ui/delayed_activation.cpp
|
||||
|
|
|
|||
71
ui/cached_special_layer_shadow_corners.cpp
Normal file
71
ui/cached_special_layer_shadow_corners.cpp
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
// This file is part of Desktop App Toolkit,
|
||||
// a set of libraries for developing nice desktop applications.
|
||||
//
|
||||
// For license and copyright information please follow this link:
|
||||
// https://github.com/desktop-app/legal/blob/master/LEGAL
|
||||
//
|
||||
#include "ui/cached_special_layer_shadow_corners.h"
|
||||
|
||||
#include "ui/effects/ripple_animation.h"
|
||||
#include "styles/style_layers.h"
|
||||
|
||||
namespace Ui {
|
||||
namespace {
|
||||
|
||||
[[nodiscard]] std::array<QImage, 4> PrepareSpecialLayerShadowCorners() {
|
||||
const auto &st = st::boxRoundShadow;
|
||||
|
||||
const auto s = QSize(
|
||||
st::boxRadius * 2 + st.extend.left(),
|
||||
st::boxRadius * 2 + st.extend.right());
|
||||
const auto mask = Ui::RippleAnimation::maskByDrawer(s, false, [&](
|
||||
QPainter &p) {
|
||||
p.drawRoundedRect(QRect(QPoint(), s), st::boxRadius, st::boxRadius);
|
||||
});
|
||||
struct Corner {
|
||||
const style::icon &icon;
|
||||
QPoint factor;
|
||||
};
|
||||
const auto corners = std::vector<Corner>{
|
||||
Corner{ st.topLeft, QPoint(1, 1) },
|
||||
Corner{ st.bottomLeft, QPoint(1, 0) },
|
||||
Corner{ st.topRight, QPoint(0, 1) },
|
||||
Corner{ st.bottomRight, QPoint(0, 0) },
|
||||
};
|
||||
const auto processCorner = [&](int i) {
|
||||
const auto &corner = corners[i];
|
||||
auto result = QImage(
|
||||
corner.icon.size() * style::DevicePixelRatio(),
|
||||
QImage::Format_ARGB32_Premultiplied);
|
||||
result.setDevicePixelRatio(style::DevicePixelRatio());
|
||||
result.fill(Qt::transparent);
|
||||
|
||||
{
|
||||
QPainter p(&result);
|
||||
corner.icon.paint(p, 0, 0, corner.icon.width());
|
||||
p.setCompositionMode(QPainter::CompositionMode_DestinationOut);
|
||||
p.drawImage(
|
||||
corner.icon.width() * corner.factor.x()
|
||||
- mask.width() / style::DevicePixelRatio() / 2,
|
||||
corner.icon.height() * corner.factor.y()
|
||||
- mask.height() / style::DevicePixelRatio() / 2,
|
||||
mask);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
return std::array<QImage, 4>{ {
|
||||
processCorner(0),
|
||||
processCorner(1),
|
||||
processCorner(2),
|
||||
processCorner(3),
|
||||
} };
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
const std::array<QImage, 4> &SpecialLayerShadowCorners() {
|
||||
static const auto custom = PrepareSpecialLayerShadowCorners();
|
||||
return custom;
|
||||
}
|
||||
|
||||
} // namespace Ui
|
||||
13
ui/cached_special_layer_shadow_corners.h
Normal file
13
ui/cached_special_layer_shadow_corners.h
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
// This file is part of Desktop App Toolkit,
|
||||
// a set of libraries for developing nice desktop applications.
|
||||
//
|
||||
// For license and copyright information please follow this link:
|
||||
// https://github.com/desktop-app/legal/blob/master/LEGAL
|
||||
//
|
||||
#pragma once
|
||||
|
||||
namespace Ui {
|
||||
|
||||
[[nodiscard]] const std::array<QImage, 4> &SpecialLayerShadowCorners();
|
||||
|
||||
} // namespace Ui
|
||||
|
|
@ -6,6 +6,7 @@
|
|||
//
|
||||
#include "ui/layers/layer_widget.h"
|
||||
|
||||
#include "ui/cached_special_layer_shadow_corners.h"
|
||||
#include "ui/layers/box_layer_widget.h"
|
||||
#include "ui/widgets/shadow.h"
|
||||
#include "ui/image/image_prepare.h"
|
||||
|
|
@ -21,7 +22,7 @@ namespace Ui {
|
|||
|
||||
class LayerStackWidget::BackgroundWidget : public TWidget {
|
||||
public:
|
||||
explicit BackgroundWidget(QWidget *parent);
|
||||
using TWidget::TWidget;
|
||||
|
||||
void setDoneCallback(Fn<void()> callback) {
|
||||
_doneCallback = std::move(callback);
|
||||
|
|
@ -63,7 +64,6 @@ private:
|
|||
int _mainMenuCacheWidth = 0;
|
||||
QPixmap _specialLayerCache;
|
||||
QPixmap _layerCache;
|
||||
RoundRect _roundRect;
|
||||
|
||||
Fn<void()> _doneCallback;
|
||||
|
||||
|
|
@ -84,11 +84,6 @@ private:
|
|||
|
||||
};
|
||||
|
||||
LayerStackWidget::BackgroundWidget::BackgroundWidget(QWidget *parent)
|
||||
: TWidget(parent)
|
||||
, _roundRect(st::boxRadius, st::boxBg) {
|
||||
}
|
||||
|
||||
void LayerStackWidget::BackgroundWidget::setCacheImages(
|
||||
QPixmap &&bodyCache,
|
||||
QPixmap &&mainMenuCache,
|
||||
|
|
@ -262,15 +257,9 @@ void LayerStackWidget::BackgroundWidget::paintEvent(QPaintEvent *e) {
|
|||
if (topCorners || bottomCorners) {
|
||||
p.setClipRegion(QRegion(rect()) - specialLayerBox.marginsRemoved(QMargins(st::boxRadius, 0, st::boxRadius, 0)) - specialLayerBox.marginsRemoved(QMargins(0, st::boxRadius, 0, st::boxRadius)));
|
||||
}
|
||||
Ui::Shadow::paint(p, specialLayerBox, width(), st::boxRoundShadow, sides);
|
||||
|
||||
Ui::Shadow::paint(p, specialLayerBox, width(), st::boxRoundShadow, sides, Ui::SpecialLayerShadowCorners());
|
||||
if (topCorners || bottomCorners) {
|
||||
// In case of painting the shadow above the special layer we get
|
||||
// glitches in the corners, so we need to paint the corners once more.
|
||||
p.setClipping(false);
|
||||
auto parts = (topCorners ? (RectPart::TopLeft | RectPart::TopRight) : RectPart::None)
|
||||
| (bottomCorners ? (RectPart::BottomLeft | RectPart::BottomRight) : RectPart::None);
|
||||
_roundRect.paint(p, specialLayerBox, parts);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,22 +14,42 @@
|
|||
#include <QtGui/QtEvents>
|
||||
|
||||
namespace Ui {
|
||||
namespace {
|
||||
|
||||
PlainShadow::PlainShadow(QWidget *parent)
|
||||
: PlainShadow(parent, st::shadowFg) {
|
||||
}
|
||||
struct CustomShadowCorners {
|
||||
struct Image {
|
||||
public:
|
||||
Image(const QImage &image)
|
||||
: _image(image) {
|
||||
}
|
||||
void paint(QPainter &p, int x, int y, int outerw) const {
|
||||
p.drawImage(x, y, _image);
|
||||
}
|
||||
[[nodiscard]] bool empty() const {
|
||||
return _image.isNull();
|
||||
}
|
||||
[[nodiscard]] int width() const {
|
||||
return _image.width() / style::DevicePixelRatio();
|
||||
}
|
||||
[[nodiscard]] int height() const {
|
||||
return _image.height() / style::DevicePixelRatio();
|
||||
}
|
||||
private:
|
||||
const QImage &_image;
|
||||
};
|
||||
const style::icon &left;
|
||||
Image topLeft;
|
||||
const style::icon ⊤
|
||||
Image topRight;
|
||||
const style::icon &right;
|
||||
Image bottomRight;
|
||||
const style::icon ⊥
|
||||
Image bottomLeft;
|
||||
const style::margins &extend;
|
||||
};
|
||||
|
||||
PlainShadow::PlainShadow(QWidget *parent, style::color color)
|
||||
: RpWidget(parent)
|
||||
, _color(color) {
|
||||
resize(st::lineWidth, st::lineWidth);
|
||||
}
|
||||
|
||||
void PlainShadow::paintEvent(QPaintEvent *e) {
|
||||
QPainter(this).fillRect(e->rect(), _color);
|
||||
}
|
||||
|
||||
void Shadow::paint(QPainter &p, const QRect &box, int outerWidth, const style::Shadow &st, RectParts sides) {
|
||||
template <typename Shadow>
|
||||
void ShadowPaint(QPainter &p, const QRect &box, int outerWidth, const Shadow &st, RectParts sides) {
|
||||
auto left = (sides & RectPart::Left);
|
||||
auto top = (sides & RectPart::Top);
|
||||
auto right = (sides & RectPart::Right);
|
||||
|
|
@ -84,6 +104,47 @@ void Shadow::paint(QPainter &p, const QRect &box, int outerWidth, const style::S
|
|||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
PlainShadow::PlainShadow(QWidget *parent)
|
||||
: PlainShadow(parent, st::shadowFg) {
|
||||
}
|
||||
|
||||
PlainShadow::PlainShadow(QWidget *parent, style::color color)
|
||||
: RpWidget(parent)
|
||||
, _color(color) {
|
||||
resize(st::lineWidth, st::lineWidth);
|
||||
}
|
||||
|
||||
void PlainShadow::paintEvent(QPaintEvent *e) {
|
||||
QPainter(this).fillRect(e->rect(), _color);
|
||||
}
|
||||
|
||||
void Shadow::paint(QPainter &p, const QRect &box, int outerWidth, const style::Shadow &st, RectParts sides) {
|
||||
ShadowPaint<style::Shadow>(p, box, outerWidth, st, std::move(sides));
|
||||
}
|
||||
|
||||
void Shadow::paint(
|
||||
QPainter &p,
|
||||
const QRect &box,
|
||||
int outerWidth,
|
||||
const style::Shadow &st,
|
||||
RectParts sides,
|
||||
const std::array<QImage, 4> &corners) {
|
||||
const auto shadow = CustomShadowCorners{
|
||||
.left = st.left,
|
||||
.topLeft = CustomShadowCorners::Image(corners[0]),
|
||||
.top = st.top,
|
||||
.topRight = CustomShadowCorners::Image(corners[2]),
|
||||
.right = st.right,
|
||||
.bottomRight = CustomShadowCorners::Image(corners[3]),
|
||||
.bottom = st.bottom,
|
||||
.bottomLeft = CustomShadowCorners::Image(corners[1]),
|
||||
.extend = st.extend,
|
||||
};
|
||||
ShadowPaint<CustomShadowCorners>(p, box, outerWidth, shadow, std::move(sides));
|
||||
}
|
||||
|
||||
QPixmap Shadow::grab(
|
||||
not_null<TWidget*> target,
|
||||
const style::Shadow &shadow,
|
||||
|
|
|
|||
|
|
@ -46,6 +46,14 @@ public:
|
|||
const style::Shadow &st,
|
||||
RectParts sides = RectPart::AllSides);
|
||||
|
||||
static void paint(
|
||||
QPainter &p,
|
||||
const QRect &box,
|
||||
int outerWidth,
|
||||
const style::Shadow &st,
|
||||
RectParts sides,
|
||||
const std::array<QImage, 4> &corners);
|
||||
|
||||
static QPixmap grab(
|
||||
not_null<TWidget*> target,
|
||||
const style::Shadow &shadow,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue