mirror of
https://github.com/vale981/tdesktop
synced 2025-03-06 10:11:41 -05:00
Members block in group conversation view finished (except Xcode project).
This commit is contained in:
parent
f0a8356ff0
commit
7db7b177c0
19 changed files with 304 additions and 19 deletions
|
@ -1734,6 +1734,17 @@ dropdownDef: dropdown {
|
||||||
width: 0px;
|
width: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
defaultInnerDropdownShadow: icon {
|
||||||
|
{ "dropdown_shadow", windowShadowFg },
|
||||||
|
};
|
||||||
|
defaultInnerDropdown: InnerDropdown {
|
||||||
|
padding: margins(10px, 10px, 10px, 10px);
|
||||||
|
shadow: defaultInnerDropdownShadow;
|
||||||
|
shadowShift: 1px;
|
||||||
|
|
||||||
|
duration: 150;
|
||||||
|
}
|
||||||
|
|
||||||
dropdownAttachDocument: iconedButton(btnAttachDocument) {
|
dropdownAttachDocument: iconedButton(btnAttachDocument) {
|
||||||
iconPos: point(14px, 13px);
|
iconPos: point(14px, 13px);
|
||||||
downIconPos: point(14px, 14px);
|
downIconPos: point(14px, 14px);
|
||||||
|
|
|
@ -246,6 +246,18 @@ dropdown {
|
||||||
width: pixels;
|
width: pixels;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
InnerDropdown {
|
||||||
|
padding: margins;
|
||||||
|
shadow: icon;
|
||||||
|
shadowShift: pixels;
|
||||||
|
|
||||||
|
duration: int;
|
||||||
|
width: pixels;
|
||||||
|
|
||||||
|
scrollMargin: margins;
|
||||||
|
scrollPadding: margins;
|
||||||
|
}
|
||||||
|
|
||||||
PopupMenu {
|
PopupMenu {
|
||||||
skip: pixels;
|
skip: pixels;
|
||||||
|
|
||||||
|
|
BIN
Telegram/Resources/icons/dropdown_shadow.png
Normal file
BIN
Telegram/Resources/icons/dropdown_shadow.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 128 B |
BIN
Telegram/Resources/icons/dropdown_shadow@2x.png
Normal file
BIN
Telegram/Resources/icons/dropdown_shadow@2x.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 146 B |
|
@ -646,6 +646,10 @@ bool Generator::collectUniqueValues() {
|
||||||
int iconMaskIndex = 0;
|
int iconMaskIndex = 0;
|
||||||
std::function<bool(const Variable&)> collector = [this, &collector, &fontFamilyIndex, &iconMaskIndex](const Variable &variable) {
|
std::function<bool(const Variable&)> collector = [this, &collector, &fontFamilyIndex, &iconMaskIndex](const Variable &variable) {
|
||||||
auto value = variable.value;
|
auto value = variable.value;
|
||||||
|
if (!value.copyOf().isEmpty()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
switch (value.type().tag) {
|
switch (value.type().tag) {
|
||||||
case Tag::Invalid:
|
case Tag::Invalid:
|
||||||
case Tag::Int:
|
case Tag::Int:
|
||||||
|
|
|
@ -52,7 +52,7 @@ const Struct *Module::findStruct(const FullName &name) const {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
for (const auto &module : included_) {
|
for (const auto &module : included_) {
|
||||||
if (auto result = findStructInModule(name, *module)) {
|
if (auto result = module->findStruct(name)) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -68,12 +68,14 @@ bool Module::addVariable(const Variable &value) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Variable *Module::findVariable(const FullName &name) const {
|
const Variable *Module::findVariable(const FullName &name, bool *outFromThisModule) const {
|
||||||
if (auto result = findVariableInModule(name, *this)) {
|
if (auto result = findVariableInModule(name, *this)) {
|
||||||
|
if (outFromThisModule) *outFromThisModule = true;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
for (const auto &module : included_) {
|
for (const auto &module : included_) {
|
||||||
if (auto result = findVariableInModule(name, *module)) {
|
if (auto result = module->findVariable(name)) {
|
||||||
|
if (outFromThisModule) *outFromThisModule = false;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,7 +75,7 @@ public:
|
||||||
// Returns false if there is a variable with such name already.
|
// Returns false if there is a variable with such name already.
|
||||||
bool addVariable(const Variable &value);
|
bool addVariable(const Variable &value);
|
||||||
// Returns nullptr if there is no such variable in result_ or any of included modules.
|
// Returns nullptr if there is no such variable in result_ or any of included modules.
|
||||||
const Variable *findVariable(const FullName &name) const;
|
const Variable *findVariable(const FullName &name, bool *outFromThisModule = nullptr) const;
|
||||||
bool hasVariables() const {
|
bool hasVariables() const {
|
||||||
return !variables_.isEmpty();
|
return !variables_.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,6 +43,7 @@ constexpr int kErrorUnknownField = 803;
|
||||||
constexpr int kErrorIdentifierNotFound = 804;
|
constexpr int kErrorIdentifierNotFound = 804;
|
||||||
constexpr int kErrorAlreadyDefined = 805;
|
constexpr int kErrorAlreadyDefined = 805;
|
||||||
constexpr int kErrorBadString = 806;
|
constexpr int kErrorBadString = 806;
|
||||||
|
constexpr int kErrorIconDuplicate = 807;
|
||||||
|
|
||||||
QString findInputFile(const Options &options) {
|
QString findInputFile(const Options &options) {
|
||||||
for (const auto &dir : options.includePaths) {
|
for (const auto &dir : options.includePaths) {
|
||||||
|
@ -351,7 +352,8 @@ structure::Value ParsedFile::defaultConstructedStruct(const structure::FullName
|
||||||
}
|
}
|
||||||
|
|
||||||
void ParsedFile::applyStructParent(structure::Value &result, const structure::FullName &parentName) {
|
void ParsedFile::applyStructParent(structure::Value &result, const structure::FullName &parentName) {
|
||||||
if (auto parent = module_->findVariable(parentName)) {
|
bool fromTheSameModule = false;
|
||||||
|
if (auto parent = module_->findVariable(parentName, &fromTheSameModule)) {
|
||||||
if (parent->value.type() != result.type()) {
|
if (parent->value.type() != result.type()) {
|
||||||
logErrorTypeMismatch() << "parent '" << logFullName(parentName) << "' has type '" << logType(parent->value.type()) << "' while child value has type " << logType(result.type());
|
logErrorTypeMismatch() << "parent '" << logFullName(parentName) << "' has type '" << logType(parent->value.type()) << "' while child value has type " << logType(result.type());
|
||||||
return;
|
return;
|
||||||
|
@ -374,6 +376,22 @@ void ParsedFile::applyStructParent(structure::Value &result, const structure::Fu
|
||||||
const auto &srcValue(srcField.variable.value);
|
const auto &srcValue(srcField.variable.value);
|
||||||
auto &dstValue(dstField.variable.value);
|
auto &dstValue(dstField.variable.value);
|
||||||
logAssert(srcValue.type() == dstValue.type()) << "struct field type check failed";
|
logAssert(srcValue.type() == dstValue.type()) << "struct field type check failed";
|
||||||
|
|
||||||
|
// Optimization: don't let the style files to contain unnamed inherited
|
||||||
|
// icons from the other (included) style files, because they will
|
||||||
|
// duplicate the binary data across different style c++ source files.
|
||||||
|
//
|
||||||
|
// Example:
|
||||||
|
// a.style has "A: Struct { icon: icon { ..file.. } };" and
|
||||||
|
// b.style has "B: Struct(A) { .. };" with non-overriden icon field.
|
||||||
|
// Then both style_a.cpp and style_b.cpp will contain binary data of "file".
|
||||||
|
if (!fromTheSameModule
|
||||||
|
&& srcValue.type().tag == structure::TypeTag::Icon
|
||||||
|
&& !srcValue.Icon().parts.empty()
|
||||||
|
&& srcValue.copyOf().isEmpty()) {
|
||||||
|
logError(kErrorIconDuplicate) << "an unnamed icon field '" << logFullName(srcField.variable.name) << "' is inherited from parent '" << logFullName(parentName) << "'";
|
||||||
|
return;
|
||||||
|
}
|
||||||
dstValue = srcValue;
|
dstValue = srcValue;
|
||||||
dstField.status = Status::Implicit;
|
dstField.status = Status::Implicit;
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,3 +29,16 @@ historyToDownArrow: icon {
|
||||||
{ "history_down_arrow", #b9b9b9, point(14px, 19px) },
|
{ "history_down_arrow", #b9b9b9, point(14px, 19px) },
|
||||||
};
|
};
|
||||||
historyToDownPaddingTop: 10px;
|
historyToDownPaddingTop: 10px;
|
||||||
|
|
||||||
|
membersInnerScroll: flatScroll(solidScroll) {
|
||||||
|
deltat: 3px;
|
||||||
|
deltab: 3px;
|
||||||
|
width: 8px;
|
||||||
|
deltax: 3px;
|
||||||
|
}
|
||||||
|
membersInnerWidth: 310px;
|
||||||
|
membersInnerHeightMax: 360px;
|
||||||
|
membersInnerDropdown: InnerDropdown(defaultInnerDropdown) {
|
||||||
|
scrollMargin: margins(0px, 5px, 0px, 5px);
|
||||||
|
scrollPadding: margins(0px, 3px, 8px, 3px);
|
||||||
|
}
|
||||||
|
|
|
@ -6027,9 +6027,12 @@ QRect HistoryWidget::getMembersShowAreaGeometry() const {
|
||||||
void HistoryWidget::setMembersShowAreaActive(bool active) {
|
void HistoryWidget::setMembersShowAreaActive(bool active) {
|
||||||
if (active && _peer && (_peer->isChat() || _peer->isMegagroup())) {
|
if (active && _peer && (_peer->isChat() || _peer->isMegagroup())) {
|
||||||
if (!_membersDropdown) {
|
if (!_membersDropdown) {
|
||||||
_membersDropdown = new Ui::InnerDropdown(this, st::dropdownDef, st::solidScroll);
|
_membersDropdown = new Ui::InnerDropdown(this, st::membersInnerDropdown, st::membersInnerScroll);
|
||||||
_membersDropdown->setOwnedWidget(new Profile::MembersWidget(_membersDropdown, _peer, Profile::MembersWidget::TitleVisibility::Hidden));
|
_membersDropdown->setOwnedWidget(new Profile::MembersWidget(_membersDropdown, _peer, Profile::MembersWidget::TitleVisibility::Hidden));
|
||||||
_membersDropdown->setGeometry(0, 0, st::emojiPanWidth, st::emojiPanMaxHeight);
|
_membersDropdown->resize(st::membersInnerWidth, _membersDropdown->height());
|
||||||
|
|
||||||
|
_membersDropdown->setMaxHeight(countMembersDropdownHeightMax());
|
||||||
|
_membersDropdown->moveToLeft(0, 0);
|
||||||
connect(_membersDropdown, SIGNAL(hidden()), this, SLOT(onMembersDropdownHidden()));
|
connect(_membersDropdown, SIGNAL(hidden()), this, SLOT(onMembersDropdownHidden()));
|
||||||
}
|
}
|
||||||
_membersDropdown->otherEnter();
|
_membersDropdown->otherEnter();
|
||||||
|
@ -6721,6 +6724,9 @@ void HistoryWidget::resizeEvent(QResizeEvent *e) {
|
||||||
_historyToEnd->moveToRight(st::historyToDownPosition.x(), _scroll.y() + _scroll.height() - _historyToEnd->height() - st::historyToDownPosition.y());
|
_historyToEnd->moveToRight(st::historyToDownPosition.x(), _scroll.y() + _scroll.height() - _historyToEnd->height() - st::historyToDownPosition.y());
|
||||||
|
|
||||||
_emojiPan.setMaxHeight(height() - st::dropdownDef.padding.top() - st::dropdownDef.padding.bottom() - _attachEmoji.height());
|
_emojiPan.setMaxHeight(height() - st::dropdownDef.padding.top() - st::dropdownDef.padding.bottom() - _attachEmoji.height());
|
||||||
|
if (_membersDropdown) {
|
||||||
|
_membersDropdown->setMaxHeight(countMembersDropdownHeightMax());
|
||||||
|
}
|
||||||
|
|
||||||
switch (_attachDrag) {
|
switch (_attachDrag) {
|
||||||
case DragStateFiles:
|
case DragStateFiles:
|
||||||
|
@ -7682,6 +7688,13 @@ void HistoryWidget::cancelReplyAfterMediaSend(bool lastKeyboardUsed) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int HistoryWidget::countMembersDropdownHeightMax() const {
|
||||||
|
int result = height() - st::membersInnerDropdown.padding.top() - st::membersInnerDropdown.padding.bottom();
|
||||||
|
result -= _attachEmoji.height();
|
||||||
|
accumulate_min(result, st::membersInnerHeightMax);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
void HistoryWidget::cancelEdit() {
|
void HistoryWidget::cancelEdit() {
|
||||||
if (!_editMsgId) return;
|
if (!_editMsgId) return;
|
||||||
|
|
||||||
|
|
|
@ -867,6 +867,8 @@ private:
|
||||||
|
|
||||||
void cancelReplyAfterMediaSend(bool lastKeyboardUsed);
|
void cancelReplyAfterMediaSend(bool lastKeyboardUsed);
|
||||||
|
|
||||||
|
int countMembersDropdownHeightMax() const;
|
||||||
|
|
||||||
MsgId _replyToId = 0;
|
MsgId _replyToId = 0;
|
||||||
Text _replyToName;
|
Text _replyToName;
|
||||||
int _replyToNameVersion = 0;
|
int _replyToNameVersion = 0;
|
||||||
|
|
|
@ -31,7 +31,7 @@ BlockWidget::BlockWidget(QWidget *parent, PeerData *peer, const QString &title)
|
||||||
}
|
}
|
||||||
|
|
||||||
int BlockWidget::contentTop() const {
|
int BlockWidget::contentTop() const {
|
||||||
return st::profileBlockMarginTop + (emptyTitle() ? 0 : st::profileBlockTitleHeight);
|
return emptyTitle() ? 0 : (st::profileBlockMarginTop + st::profileBlockTitleHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlockWidget::paintEvent(QPaintEvent *e) {
|
void BlockWidget::paintEvent(QPaintEvent *e) {
|
||||||
|
|
|
@ -60,7 +60,7 @@ BoxShadow::BoxShadow(const style::sprite &topLeft) : _size(topLeft.pxWidth()), _
|
||||||
_corners.setDevicePixelRatio(cRetinaFactor());
|
_corners.setDevicePixelRatio(cRetinaFactor());
|
||||||
_colors.reserve(_pixsize);
|
_colors.reserve(_pixsize);
|
||||||
uchar prev = 0;
|
uchar prev = 0;
|
||||||
for (int32 i = 0; i < _pixsize; ++i) {
|
for (int i = 0; i < _pixsize; ++i) {
|
||||||
uchar a = (cornersImage.pixel(QPoint(i, _pixsize - 1)) >> 24);
|
uchar a = (cornersImage.pixel(QPoint(i, _pixsize - 1)) >> 24);
|
||||||
if (a < prev) break;
|
if (a < prev) break;
|
||||||
|
|
||||||
|
@ -112,3 +112,79 @@ style::margins BoxShadow::getDimensions(int32 shifty) const {
|
||||||
int32 d = _colors.size() / cIntRetinaFactor();
|
int32 d = _colors.size() / cIntRetinaFactor();
|
||||||
return style::margins(d - shifty, d - 2 * shifty, d - shifty, d);
|
return style::margins(d - shifty, d - 2 * shifty, d - shifty, d);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
|
||||||
|
RectShadow::RectShadow(const style::icon &topLeft) : _size(topLeft.width()), _pixsize(_size * cIntRetinaFactor()) {
|
||||||
|
if (!_size) return;
|
||||||
|
|
||||||
|
QImage cornersImage(_pixsize * 2, _pixsize * 2, QImage::Format_ARGB32_Premultiplied);
|
||||||
|
cornersImage.setDevicePixelRatio(cRetinaFactor());
|
||||||
|
{
|
||||||
|
Painter p(&cornersImage);
|
||||||
|
p.setCompositionMode(QPainter::CompositionMode_Source);
|
||||||
|
topLeft.paint(p, QPoint(0, 0), _size);
|
||||||
|
}
|
||||||
|
if (rtl()) cornersImage = cornersImage.mirrored(true, false);
|
||||||
|
{
|
||||||
|
QPainter p(&cornersImage);
|
||||||
|
p.setCompositionMode(QPainter::CompositionMode_Source);
|
||||||
|
QImage m = cornersImage.mirrored();
|
||||||
|
m.setDevicePixelRatio(cRetinaFactor());
|
||||||
|
p.drawImage(0, _size, m, 0, _pixsize, _pixsize, _pixsize);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
QPainter p(&cornersImage);
|
||||||
|
p.setCompositionMode(QPainter::CompositionMode_Source);
|
||||||
|
QImage m = cornersImage.mirrored(true, false);
|
||||||
|
m.setDevicePixelRatio(cRetinaFactor());
|
||||||
|
p.drawImage(_size, 0, m, _pixsize, 0, _pixsize, _pixsize * 2);
|
||||||
|
}
|
||||||
|
_corners = QPixmap::fromImage(cornersImage, Qt::ColorOnly);
|
||||||
|
_corners.setDevicePixelRatio(cRetinaFactor());
|
||||||
|
|
||||||
|
uchar prev = 0;
|
||||||
|
for (int i = 0; i < _pixsize; ++i) {
|
||||||
|
uchar a = (cornersImage.pixel(QPoint(i, _pixsize - 1)) >> 24);
|
||||||
|
if (a < prev) break;
|
||||||
|
|
||||||
|
++_thickness;
|
||||||
|
prev = a;
|
||||||
|
}
|
||||||
|
|
||||||
|
_left = QPixmap::fromImage(cornersImage.copy(0, _pixsize - 1, _thickness, 1), Qt::ColorOnly);
|
||||||
|
_left.setDevicePixelRatio(cRetinaFactor());
|
||||||
|
_top = QPixmap::fromImage(cornersImage.copy(_pixsize - 1, 0, 1, _thickness), Qt::ColorOnly);
|
||||||
|
_top.setDevicePixelRatio(cRetinaFactor());
|
||||||
|
_right = QPixmap::fromImage(cornersImage.copy(_pixsize * 2 - _thickness, _pixsize, _thickness, 1), Qt::ColorOnly);
|
||||||
|
_right.setDevicePixelRatio(cRetinaFactor());
|
||||||
|
_bottom = QPixmap::fromImage(cornersImage.copy(_pixsize, _pixsize * 2 - _thickness, 1, _thickness), Qt::ColorOnly);
|
||||||
|
_bottom.setDevicePixelRatio(cRetinaFactor());
|
||||||
|
}
|
||||||
|
|
||||||
|
void RectShadow::paint(Painter &p, const QRect &box, int shifty, Sides sides) {
|
||||||
|
if (!_size) return;
|
||||||
|
|
||||||
|
int32 rshifty = shifty * cIntRetinaFactor();
|
||||||
|
int32 count = _thickness, countsize = count / cIntRetinaFactor(), minus = _size - countsize + shifty;
|
||||||
|
bool left = (sides & Side::Left), top = (sides & Side::Top), right = (sides & Side::Right), bottom = (sides & Side::Bottom);
|
||||||
|
if (left && top) p.drawPixmap(box.left() - _size + minus, box.top() - _size + minus + shifty, _corners, 0, 0, _pixsize, _pixsize);
|
||||||
|
if (right && top) p.drawPixmap(box.left() + box.width() - minus, box.top() - _size + minus + shifty, _corners, _pixsize, 0, _pixsize, _pixsize);
|
||||||
|
if (right && bottom) p.drawPixmap(box.left() + box.width() - minus, box.top() + box.height() - minus + shifty, _corners, _pixsize, _pixsize, _pixsize, _pixsize);
|
||||||
|
if (left && bottom) p.drawPixmap(box.left() - _size + minus, box.top() + box.height() - minus + shifty, _corners, 0, _pixsize, _pixsize, _pixsize);
|
||||||
|
|
||||||
|
bool wasSmooth = p.renderHints().testFlag(QPainter::SmoothPixmapTransform);
|
||||||
|
if (wasSmooth) p.setRenderHint(QPainter::SmoothPixmapTransform, false);
|
||||||
|
if (left) p.drawPixmap(box.left() - countsize + shifty, box.top() + (top ? minus : 0) + shifty, countsize - shifty, box.height() - (bottom ? minus : 0) - (top ? minus : 0), _left, 0, 0, count - rshifty, 1);
|
||||||
|
if (top) p.drawPixmap(box.left() + (left ? minus : 0), box.top() - countsize + 2 * shifty, box.width() - (right ? minus : 0) - (left ? minus : 0), countsize - 2 * shifty, _top, 0, 0, 1, count - 2 * rshifty);
|
||||||
|
if (right) p.drawPixmap(box.left() + box.width(), box.top() + (top ? minus : 0) + shifty, countsize - shifty, box.height() - (bottom ? minus : 0) - (top ? minus : 0), _right, rshifty, 0, count - rshifty, 1);
|
||||||
|
if (bottom) p.drawPixmap(box.left() + (left ? minus : 0), box.top() + box.height(), box.width() - (right ? minus : 0) - (left ? minus : 0), countsize, _bottom, 0, 0, 1, count);
|
||||||
|
if (wasSmooth) p.setRenderHint(QPainter::SmoothPixmapTransform);
|
||||||
|
}
|
||||||
|
|
||||||
|
style::margins RectShadow::getDimensions(int32 shifty) const {
|
||||||
|
int d = _thickness / cIntRetinaFactor();
|
||||||
|
return style::margins(d - shifty, d - 2 * shifty, d - shifty, d);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Ui
|
||||||
|
|
|
@ -42,3 +42,32 @@ private:
|
||||||
QVector<style::color> _colors;
|
QVector<style::color> _colors;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
|
||||||
|
class RectShadow {
|
||||||
|
public:
|
||||||
|
enum class Side {
|
||||||
|
Left = 0x01,
|
||||||
|
Top = 0x02,
|
||||||
|
Right = 0x04,
|
||||||
|
Bottom = 0x08,
|
||||||
|
};
|
||||||
|
Q_DECLARE_FLAGS(Sides, Side);
|
||||||
|
Q_DECLARE_FRIEND_OPERATORS_FOR_FLAGS(Sides);
|
||||||
|
|
||||||
|
RectShadow(const style::icon &topLeft);
|
||||||
|
|
||||||
|
void paint(Painter &p, const QRect &box, int shifty, Sides sides = Side::Left | Side::Top | Side::Right | Side::Bottom);
|
||||||
|
style::margins getDimensions(int shifty) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
int _size, _pixsize;
|
||||||
|
int _thickness = 0;
|
||||||
|
QPixmap _corners, _left, _top, _right, _bottom;
|
||||||
|
|
||||||
|
};
|
||||||
|
Q_DECLARE_OPERATORS_FOR_FLAGS(RectShadow::Sides);
|
||||||
|
|
||||||
|
} // namespace Ui
|
|
@ -27,7 +27,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
|
|
||||||
InnerDropdown::InnerDropdown(QWidget *parent, const style::dropdown &st, const style::flatScroll &scrollSt) : TWidget(parent)
|
InnerDropdown::InnerDropdown(QWidget *parent, const style::InnerDropdown &st, const style::flatScroll &scrollSt) : TWidget(parent)
|
||||||
, _st(st)
|
, _st(st)
|
||||||
, _shadow(_st.shadow)
|
, _shadow(_st.shadow)
|
||||||
, _scroll(this, scrollSt) {
|
, _scroll(this, scrollSt) {
|
||||||
|
@ -44,10 +44,35 @@ InnerDropdown::InnerDropdown(QWidget *parent, const style::dropdown &st, const s
|
||||||
}
|
}
|
||||||
|
|
||||||
void InnerDropdown::setOwnedWidget(ScrolledWidget *widget) {
|
void InnerDropdown::setOwnedWidget(ScrolledWidget *widget) {
|
||||||
_scroll->setOwnedWidget(widget);
|
auto container = new internal::Container(_scroll, widget, _st);
|
||||||
|
connect(container, SIGNAL(heightUpdated()), this, SLOT(onWidgetHeightUpdated()));
|
||||||
|
_scroll->setOwnedWidget(container);
|
||||||
|
container->resizeToWidth(_scroll->width());
|
||||||
|
container->moveToLeft(0, 0);
|
||||||
|
container->show();
|
||||||
widget->show();
|
widget->show();
|
||||||
widget->move(0, 0);
|
}
|
||||||
widget->resizeToWidth(_scroll->width() - st::scrollDef.width);
|
|
||||||
|
void InnerDropdown::setMaxHeight(int newMaxHeight) {
|
||||||
|
_maxHeight = newMaxHeight;
|
||||||
|
updateHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
void InnerDropdown::onWidgetHeightUpdated() {
|
||||||
|
updateHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
void InnerDropdown::updateHeight() {
|
||||||
|
int newHeight = _st.padding.top() + _st.scrollMargin.top() + _st.scrollMargin.bottom() + _st.padding.bottom();
|
||||||
|
if (auto widget = static_cast<ScrolledWidget*>(_scroll->widget())) {
|
||||||
|
newHeight += widget->height();
|
||||||
|
}
|
||||||
|
if (_maxHeight > 0) {
|
||||||
|
accumulate_min(newHeight, _maxHeight);
|
||||||
|
}
|
||||||
|
if (newHeight != height()) {
|
||||||
|
resize(width(), newHeight);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void InnerDropdown::onWindowActiveChanged() {
|
void InnerDropdown::onWindowActiveChanged() {
|
||||||
|
@ -57,9 +82,9 @@ void InnerDropdown::onWindowActiveChanged() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void InnerDropdown::resizeEvent(QResizeEvent *e) {
|
void InnerDropdown::resizeEvent(QResizeEvent *e) {
|
||||||
_scroll->setGeometry(rect().marginsRemoved(_st.padding));
|
_scroll->setGeometry(rect().marginsRemoved(_st.padding).marginsRemoved(_st.scrollMargin));
|
||||||
if (auto widget = static_cast<ScrolledWidget*>(_scroll->widget())) {
|
if (auto widget = static_cast<ScrolledWidget*>(_scroll->widget())) {
|
||||||
widget->resizeToWidth(_scroll->width() - st::scrollDef.width);
|
widget->resizeToWidth(_scroll->width());
|
||||||
onScroll();
|
onScroll();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -73,7 +98,7 @@ void InnerDropdown::onScroll() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void InnerDropdown::paintEvent(QPaintEvent *e) {
|
void InnerDropdown::paintEvent(QPaintEvent *e) {
|
||||||
QPainter p(this);
|
Painter p(this);
|
||||||
|
|
||||||
if (!_cache.isNull()) {
|
if (!_cache.isNull()) {
|
||||||
bool animating = _a_appearance.animating(getms());
|
bool animating = _a_appearance.animating(getms());
|
||||||
|
@ -182,4 +207,41 @@ bool InnerDropdown::eventFilter(QObject *obj, QEvent *e) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
Container::Container(QWidget *parent, ScrolledWidget *child, const style::InnerDropdown &st) : ScrolledWidget(parent), _st(st) {
|
||||||
|
child->setParent(this);
|
||||||
|
child->moveToLeft(_st.scrollPadding.left(), _st.scrollPadding.top());
|
||||||
|
connect(child, SIGNAL(heightUpdated()), this, SLOT(onHeightUpdate()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Container::setVisibleTopBottom(int visibleTop, int visibleBottom) {
|
||||||
|
if (auto child = static_cast<ScrolledWidget*>(children().front())) {
|
||||||
|
child->setVisibleTopBottom(visibleTop - _st.scrollPadding.top(), visibleBottom - _st.scrollPadding.top());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Container::onHeightUpdate() {
|
||||||
|
int newHeight = _st.scrollPadding.top() + _st.scrollPadding.bottom();
|
||||||
|
if (auto child = static_cast<ScrolledWidget*>(children().front())) {
|
||||||
|
newHeight += child->height();
|
||||||
|
}
|
||||||
|
if (newHeight != height()) {
|
||||||
|
resize(width(), newHeight);
|
||||||
|
emit heightUpdated();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int Container::resizeGetHeight(int newWidth) {
|
||||||
|
int innerWidth = newWidth - _st.scrollPadding.left() - _st.scrollPadding.right();
|
||||||
|
int result = _st.scrollPadding.top() + _st.scrollPadding.bottom();
|
||||||
|
if (auto child = static_cast<ScrolledWidget*>(children().front())) {
|
||||||
|
child->resizeToWidth(innerWidth);
|
||||||
|
child->moveToLeft(_st.scrollPadding.left(), _st.scrollPadding.top());
|
||||||
|
result += child->height();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
} // namespace Ui
|
} // namespace Ui
|
||||||
|
|
|
@ -20,6 +20,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "ui/boxshadow.h"
|
||||||
|
|
||||||
class ScrollArea;
|
class ScrollArea;
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
|
@ -28,7 +30,7 @@ class InnerDropdown : public TWidget {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
InnerDropdown(QWidget *parent, const style::dropdown &st = st::dropdownDef, const style::flatScroll &scrollSt = st::scrollDef);
|
InnerDropdown(QWidget *parent, const style::InnerDropdown &st = st::defaultInnerDropdown, const style::flatScroll &scrollSt = st::scrollDef);
|
||||||
|
|
||||||
void setOwnedWidget(ScrolledWidget *widget);
|
void setOwnedWidget(ScrolledWidget *widget);
|
||||||
|
|
||||||
|
@ -38,6 +40,8 @@ public:
|
||||||
return rect().marginsRemoved(_st.padding).contains(QRect(mapFromGlobal(globalRect.topLeft()), globalRect.size()));
|
return rect().marginsRemoved(_st.padding).contains(QRect(mapFromGlobal(globalRect.topLeft()), globalRect.size()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setMaxHeight(int newMaxHeight);
|
||||||
|
|
||||||
void otherEnter();
|
void otherEnter();
|
||||||
void otherLeave();
|
void otherLeave();
|
||||||
|
|
||||||
|
@ -56,6 +60,7 @@ private slots:
|
||||||
void onHideStart();
|
void onHideStart();
|
||||||
void onWindowActiveChanged();
|
void onWindowActiveChanged();
|
||||||
void onScroll();
|
void onScroll();
|
||||||
|
void onWidgetHeightUpdated();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void repaintCallback();
|
void repaintCallback();
|
||||||
|
@ -65,7 +70,9 @@ private:
|
||||||
|
|
||||||
void startAnimation();
|
void startAnimation();
|
||||||
|
|
||||||
const style::dropdown &_st;
|
void updateHeight();
|
||||||
|
|
||||||
|
const style::InnerDropdown &_st;
|
||||||
|
|
||||||
bool _hiding = false;
|
bool _hiding = false;
|
||||||
|
|
||||||
|
@ -74,9 +81,32 @@ private:
|
||||||
|
|
||||||
QTimer _hideTimer;
|
QTimer _hideTimer;
|
||||||
|
|
||||||
BoxShadow _shadow;
|
RectShadow _shadow;
|
||||||
ChildWidget<ScrollArea> _scroll;
|
ChildWidget<ScrollArea> _scroll;
|
||||||
|
|
||||||
|
int _maxHeight = 0;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
class Container : public ScrolledWidget {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
Container(QWidget *parent, ScrolledWidget *child, const style::InnerDropdown &st);
|
||||||
|
void setVisibleTopBottom(int visibleTop, int visibleBottom) override;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void onHeightUpdate();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
int resizeGetHeight(int newWidth) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const style::InnerDropdown &_st;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
} // namespace Ui
|
} // namespace Ui
|
||||||
|
|
|
@ -270,6 +270,8 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
class ScrolledWidget : public TWidget {
|
class ScrolledWidget : public TWidget {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ScrolledWidget(QWidget *parent = nullptr) : TWidget(parent) {
|
ScrolledWidget(QWidget *parent = nullptr) : TWidget(parent) {
|
||||||
}
|
}
|
||||||
|
@ -289,4 +291,7 @@ protected:
|
||||||
return height();
|
return height();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void heightUpdated();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -204,6 +204,7 @@ SOURCES += \
|
||||||
./SourceFiles/ui/flatlabel.cpp \
|
./SourceFiles/ui/flatlabel.cpp \
|
||||||
./SourceFiles/ui/flattextarea.cpp \
|
./SourceFiles/ui/flattextarea.cpp \
|
||||||
./SourceFiles/ui/images.cpp \
|
./SourceFiles/ui/images.cpp \
|
||||||
|
./SourceFiles/ui/inner_dropdown.cpp \
|
||||||
./SourceFiles/ui/scrollarea.cpp \
|
./SourceFiles/ui/scrollarea.cpp \
|
||||||
./SourceFiles/ui/twidget.cpp \
|
./SourceFiles/ui/twidget.cpp \
|
||||||
./SourceFiles/window/main_window.cpp \
|
./SourceFiles/window/main_window.cpp \
|
||||||
|
@ -361,6 +362,7 @@ HEADERS += \
|
||||||
./SourceFiles/ui/flatlabel.h \
|
./SourceFiles/ui/flatlabel.h \
|
||||||
./SourceFiles/ui/flattextarea.h \
|
./SourceFiles/ui/flattextarea.h \
|
||||||
./SourceFiles/ui/images.h \
|
./SourceFiles/ui/images.h \
|
||||||
|
./SourceFiles/ui/inner_dropdown.h \
|
||||||
./SourceFiles/ui/scrollarea.h \
|
./SourceFiles/ui/scrollarea.h \
|
||||||
./SourceFiles/ui/twidget.h \
|
./SourceFiles/ui/twidget.h \
|
||||||
./SourceFiles/window/main_window.h \
|
./SourceFiles/window/main_window.h \
|
||||||
|
|
|
@ -86,6 +86,7 @@ compilers: GeneratedFiles/qrc_telegram.cpp\
|
||||||
GeneratedFiles/Debug/moc_flattextarea.cpp\
|
GeneratedFiles/Debug/moc_flattextarea.cpp\
|
||||||
GeneratedFiles/Debug/moc_history.cpp\
|
GeneratedFiles/Debug/moc_history.cpp\
|
||||||
GeneratedFiles/Debug/moc_historywidget.cpp\
|
GeneratedFiles/Debug/moc_historywidget.cpp\
|
||||||
|
GeneratedFiles/Debug/moc_inner_dropdown.cpp\
|
||||||
GeneratedFiles/Debug/moc_introcode.cpp\
|
GeneratedFiles/Debug/moc_introcode.cpp\
|
||||||
GeneratedFiles/Debug/moc_introphone.cpp\
|
GeneratedFiles/Debug/moc_introphone.cpp\
|
||||||
GeneratedFiles/Debug/moc_intropwdcheck.cpp\
|
GeneratedFiles/Debug/moc_intropwdcheck.cpp\
|
||||||
|
@ -223,6 +224,7 @@ compiler_moc_header_make_all: GeneratedFiles/Debug/moc_aboutbox.cpp\
|
||||||
GeneratedFiles/Debug/moc_flattextarea.cpp\
|
GeneratedFiles/Debug/moc_flattextarea.cpp\
|
||||||
GeneratedFiles/Debug/moc_history.cpp\
|
GeneratedFiles/Debug/moc_history.cpp\
|
||||||
GeneratedFiles/Debug/moc_historywidget.cpp\
|
GeneratedFiles/Debug/moc_historywidget.cpp\
|
||||||
|
GeneratedFiles/Debug/moc_inner_dropdown.cpp\
|
||||||
GeneratedFiles/Debug/moc_introcode.cpp\
|
GeneratedFiles/Debug/moc_introcode.cpp\
|
||||||
GeneratedFiles/Debug/moc_introphone.cpp\
|
GeneratedFiles/Debug/moc_introphone.cpp\
|
||||||
GeneratedFiles/Debug/moc_intropwdcheck.cpp\
|
GeneratedFiles/Debug/moc_intropwdcheck.cpp\
|
||||||
|
@ -303,6 +305,7 @@ compiler_moc_header_clean:
|
||||||
GeneratedFiles/Debug/moc_flattextarea.cpp\
|
GeneratedFiles/Debug/moc_flattextarea.cpp\
|
||||||
GeneratedFiles/Debug/moc_history.cpp\
|
GeneratedFiles/Debug/moc_history.cpp\
|
||||||
GeneratedFiles/Debug/moc_historywidget.cpp\
|
GeneratedFiles/Debug/moc_historywidget.cpp\
|
||||||
|
GeneratedFiles/Debug/moc_inner_dropdown.cpp\
|
||||||
GeneratedFiles/Debug/moc_introcode.cpp\
|
GeneratedFiles/Debug/moc_introcode.cpp\
|
||||||
GeneratedFiles/Debug/moc_introphone.cpp\
|
GeneratedFiles/Debug/moc_introphone.cpp\
|
||||||
GeneratedFiles/Debug/moc_intropwdcheck.cpp\
|
GeneratedFiles/Debug/moc_intropwdcheck.cpp\
|
||||||
|
@ -456,6 +459,9 @@ GeneratedFiles/Debug/moc_history.cpp: SourceFiles/history.h
|
||||||
GeneratedFiles/Debug/moc_historywidget.cpp: SourceFiles/historywidget.h
|
GeneratedFiles/Debug/moc_historywidget.cpp: SourceFiles/historywidget.h
|
||||||
$(MOC_FILE) SourceFiles/historywidget.h -o GeneratedFiles/Debug/moc_historywidget.cpp
|
$(MOC_FILE) SourceFiles/historywidget.h -o GeneratedFiles/Debug/moc_historywidget.cpp
|
||||||
|
|
||||||
|
GeneratedFiles/Debug/moc_inner_dropdown.cpp: SourceFiles/ui/inner_dropdown.h
|
||||||
|
$(MOC_FILE) SourceFiles/ui/inner_dropdown.h -o GeneratedFiles/Debug/moc_inner_dropdown.cpp
|
||||||
|
|
||||||
GeneratedFiles/Debug/moc_introcode.cpp: SourceFiles/intro/introcode.h
|
GeneratedFiles/Debug/moc_introcode.cpp: SourceFiles/intro/introcode.h
|
||||||
$(MOC_FILE) SourceFiles/intro/introcode.h -o GeneratedFiles/Debug/moc_introcode.cpp
|
$(MOC_FILE) SourceFiles/intro/introcode.h -o GeneratedFiles/Debug/moc_introcode.cpp
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue