mirror of https://github.com/procxx/kepka.git
ShareBox and CountrySelect use Ui::MultiSelect as a search field.
This commit is contained in:
parent
48332c0c6b
commit
8bc4e3816b
|
@ -68,37 +68,6 @@ aboutRevokePublicLabel: flatLabel(labelDefFlat) {
|
|||
textFg: windowTextFg;
|
||||
}
|
||||
|
||||
boxSearchField: InputField(defaultInputField) {
|
||||
textBg: transparent;
|
||||
textMargins: margins(2px, 7px, 2px, 0px);
|
||||
|
||||
placeholderFg: #999;
|
||||
placeholderFgActive: #aaa;
|
||||
placeholderMargins: margins(2px, 0px, 2px, 0px);
|
||||
duration: 150;
|
||||
|
||||
border: 0px;
|
||||
borderActive: 0px;
|
||||
borderError: 0px;
|
||||
|
||||
height: 32px;
|
||||
|
||||
font: normalFont;
|
||||
}
|
||||
boxSearchCancel: IconButton {
|
||||
width: 41px;
|
||||
height: 48px;
|
||||
|
||||
opacity: 0.3;
|
||||
overOpacity: 0.4;
|
||||
|
||||
icon: icon {{ "box_search_cancel", #000000 }};
|
||||
iconPosition: point(8px, 18px);
|
||||
downIconPosition: point(8px, 19px);
|
||||
|
||||
duration: 150;
|
||||
}
|
||||
|
||||
contactsMultiSelect: MultiSelect {
|
||||
padding: margins(8px, 8px, 8px, 8px);
|
||||
maxHeight: 104px;
|
||||
|
@ -128,12 +97,40 @@ contactsMultiSelect: MultiSelect {
|
|||
}
|
||||
itemSkip: 8px;
|
||||
|
||||
field: boxSearchField;
|
||||
field: InputField(defaultInputField) {
|
||||
textBg: transparent;
|
||||
textMargins: margins(2px, 7px, 2px, 0px);
|
||||
|
||||
placeholderFg: #999;
|
||||
placeholderFgActive: #aaa;
|
||||
placeholderMargins: margins(2px, 0px, 2px, 0px);
|
||||
|
||||
border: 0px;
|
||||
borderActive: 0px;
|
||||
borderError: 0px;
|
||||
|
||||
height: 32px;
|
||||
|
||||
font: normalFont;
|
||||
}
|
||||
fieldMinWidth: 42px;
|
||||
fieldIcon: icon {{ "box_search_icon", #aaaaaa, point(11px, 9px) }};
|
||||
fieldIconSkip: 36px;
|
||||
fieldCancel: boxSearchCancel;
|
||||
|
||||
fieldCancel: IconButton {
|
||||
width: 41px;
|
||||
height: 48px;
|
||||
|
||||
opacity: 0.3;
|
||||
overOpacity: 0.4;
|
||||
|
||||
icon: icon {{ "box_search_cancel", #000000 }};
|
||||
iconPosition: point(8px, 18px);
|
||||
downIconPosition: point(8px, 19px);
|
||||
|
||||
duration: 150;
|
||||
}
|
||||
fieldCancelSkip: 34px;
|
||||
fieldMinWidth: 42px;
|
||||
}
|
||||
contactsPhotoCheckbox: RoundImageCheckbox {
|
||||
imageRadius: 21px;
|
||||
|
|
|
@ -32,6 +32,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||
#include "application.h"
|
||||
#include "ui/filedialog.h"
|
||||
#include "ui/widgets/multi_select.h"
|
||||
#include "ui/widgets/widget_slide_wrap.h"
|
||||
#include "boxes/photocropbox.h"
|
||||
#include "boxes/confirmbox.h"
|
||||
#include "observer_peer.h"
|
||||
|
@ -43,7 +44,7 @@ QString cantInviteError() {
|
|||
|
||||
ContactsBox::ContactsBox() : ItemListBox(st::contactsScroll)
|
||||
, _inner(this, CreatingGroupNone)
|
||||
, _select(this, st::contactsMultiSelect, lang(lng_participant_filter))
|
||||
, _select(this, new Ui::MultiSelect(this, st::contactsMultiSelect, lang(lng_participant_filter)), QMargins(0, 0, 0, 0), [this] { updateScrollSkips(); })
|
||||
, _next(this, lang(lng_create_group_next), st::defaultBoxButton)
|
||||
, _cancel(this, lang(lng_cancel), st::cancelBoxButton)
|
||||
, _topShadow(this) {
|
||||
|
@ -52,7 +53,7 @@ ContactsBox::ContactsBox() : ItemListBox(st::contactsScroll)
|
|||
|
||||
ContactsBox::ContactsBox(const QString &name, const QImage &photo) : ItemListBox(st::boxScroll)
|
||||
, _inner(this, CreatingGroupGroup)
|
||||
, _select(this, st::contactsMultiSelect, lang(lng_participant_filter))
|
||||
, _select(this, new Ui::MultiSelect(this, st::contactsMultiSelect, lang(lng_participant_filter)), QMargins(0, 0, 0, 0), [this] { updateScrollSkips(); })
|
||||
, _next(this, lang(lng_create_group_create), st::defaultBoxButton)
|
||||
, _cancel(this, lang(lng_create_group_back), st::cancelBoxButton)
|
||||
, _topShadow(this)
|
||||
|
@ -63,7 +64,7 @@ ContactsBox::ContactsBox(const QString &name, const QImage &photo) : ItemListBox
|
|||
|
||||
ContactsBox::ContactsBox(ChannelData *channel) : ItemListBox(st::boxScroll)
|
||||
, _inner(this, channel, MembersFilter::Recent, MembersAlreadyIn())
|
||||
, _select(this, st::contactsMultiSelect, lang(lng_participant_filter))
|
||||
, _select(this, new Ui::MultiSelect(this, st::contactsMultiSelect, lang(lng_participant_filter)), QMargins(0, 0, 0, 0), [this] { updateScrollSkips(); })
|
||||
, _next(this, lang(lng_participant_invite), st::defaultBoxButton)
|
||||
, _cancel(this, lang(lng_create_group_skip), st::cancelBoxButton)
|
||||
, _topShadow(this) {
|
||||
|
@ -72,7 +73,7 @@ ContactsBox::ContactsBox(ChannelData *channel) : ItemListBox(st::boxScroll)
|
|||
|
||||
ContactsBox::ContactsBox(ChannelData *channel, MembersFilter filter, const MembersAlreadyIn &already) : ItemListBox((filter == MembersFilter::Admins) ? st::contactsScroll : st::boxScroll)
|
||||
, _inner(this, channel, filter, already)
|
||||
, _select(this, st::contactsMultiSelect, lang(lng_participant_filter))
|
||||
, _select(this, new Ui::MultiSelect(this, st::contactsMultiSelect, lang(lng_participant_filter)), QMargins(0, 0, 0, 0), [this] { updateScrollSkips(); })
|
||||
, _next(this, lang(lng_participant_invite), st::defaultBoxButton)
|
||||
, _cancel(this, lang(lng_cancel), st::cancelBoxButton)
|
||||
, _topShadow(this) {
|
||||
|
@ -81,7 +82,7 @@ ContactsBox::ContactsBox(ChannelData *channel, MembersFilter filter, const Membe
|
|||
|
||||
ContactsBox::ContactsBox(ChatData *chat, MembersFilter filter) : ItemListBox(st::boxScroll)
|
||||
, _inner(this, chat, filter)
|
||||
, _select(this, st::contactsMultiSelect, lang(lng_participant_filter))
|
||||
, _select(this, new Ui::MultiSelect(this, st::contactsMultiSelect, lang(lng_participant_filter)), QMargins(0, 0, 0, 0), [this] { updateScrollSkips(); })
|
||||
, _next(this, lang((filter == MembersFilter::Admins) ? lng_settings_save : lng_participant_invite), st::defaultBoxButton)
|
||||
, _cancel(this, lang(lng_cancel), st::cancelBoxButton)
|
||||
, _topShadow(this) {
|
||||
|
@ -90,7 +91,7 @@ ContactsBox::ContactsBox(ChatData *chat, MembersFilter filter) : ItemListBox(st:
|
|||
|
||||
ContactsBox::ContactsBox(UserData *bot) : ItemListBox(st::contactsScroll)
|
||||
, _inner(this, bot)
|
||||
, _select(this, st::contactsMultiSelect, lang(lng_participant_filter))
|
||||
, _select(this, new Ui::MultiSelect(this, st::contactsMultiSelect, lang(lng_participant_filter)), QMargins(0, 0, 0, 0), [this] { updateScrollSkips(); })
|
||||
, _next(this, lang(lng_create_group_next), st::defaultBoxButton)
|
||||
, _cancel(this, lang(lng_cancel), st::cancelBoxButton)
|
||||
, _topShadow(this) {
|
||||
|
@ -101,7 +102,7 @@ void ContactsBox::init() {
|
|||
_select->resizeToWidth(st::boxWideWidth);
|
||||
|
||||
auto inviting = (_inner->creating() == CreatingGroupGroup) || (_inner->channel() && _inner->membersFilter() == MembersFilter::Recent) || _inner->chat();
|
||||
auto topSkip = st::boxTitleHeight + _select->height();
|
||||
auto topSkip = getTopScrollSkip();
|
||||
auto bottomSkip = inviting ? (st::boxButtonPadding.top() + _next.height() + st::boxButtonPadding.bottom()) : st::boxScrollSkip;
|
||||
ItemListBox::init(_inner, bottomSkip, topSkip);
|
||||
|
||||
|
@ -109,6 +110,20 @@ void ContactsBox::init() {
|
|||
_inner->setPeerSelectedChangedCallback([this](PeerData *peer, bool checked) {
|
||||
onPeerSelectedChanged(peer, checked);
|
||||
});
|
||||
for (auto i : _inner->selected()) {
|
||||
addPeerToMultiSelect(i, true);
|
||||
}
|
||||
_inner->setAllAdminsChangedCallback([this] {
|
||||
if (_inner->allAdmins()) {
|
||||
_select->entity()->clearQuery();
|
||||
_select->slideUp();
|
||||
_inner->setFocus();
|
||||
} else {
|
||||
_select->slideDown();
|
||||
_select->entity()->setInnerFocus();
|
||||
}
|
||||
updateScrollSkips();
|
||||
});
|
||||
|
||||
if (_inner->channel() && _inner->membersFilter() == MembersFilter::Admins) {
|
||||
_next.hide();
|
||||
|
@ -128,15 +143,14 @@ void ContactsBox::init() {
|
|||
}
|
||||
connect(&_cancel, SIGNAL(clicked()), this, SLOT(onClose()));
|
||||
connect(scrollArea(), SIGNAL(scrolled()), this, SLOT(onScroll()));
|
||||
_select->setQueryChangedCallback([this](const QString &query) { onFilterUpdate(query); });
|
||||
_select->setItemRemovedCallback([this](uint64 itemId) {
|
||||
_select->entity()->setQueryChangedCallback([this](const QString &query) { onFilterUpdate(query); });
|
||||
_select->entity()->setItemRemovedCallback([this](uint64 itemId) {
|
||||
if (auto peer = App::peerLoaded(itemId)) {
|
||||
_inner->peerUnselected(peer);
|
||||
update();
|
||||
}
|
||||
});
|
||||
_select->setSubmittedCallback([this](bool) { onSubmit(); });
|
||||
_select->setResizedCallback([this] { updateScrollSkips(); });
|
||||
_select->entity()->setSubmittedCallback([this](bool) { onSubmit(); });
|
||||
connect(_inner, SIGNAL(mustScrollTo(int, int)), scrollArea(), SLOT(scrollToY(int, int)));
|
||||
connect(_inner, SIGNAL(searchByUsername()), this, SLOT(onNeedSearchByUsername()));
|
||||
connect(_inner, SIGNAL(adminAdded()), this, SIGNAL(adminAdded()));
|
||||
|
@ -148,7 +162,7 @@ void ContactsBox::init() {
|
|||
}
|
||||
|
||||
bool ContactsBox::onSearchByUsername(bool searchCache) {
|
||||
auto q = _select->getQuery();
|
||||
auto q = _select->entity()->getQuery();
|
||||
if (q.isEmpty()) {
|
||||
if (_peopleRequest) {
|
||||
_peopleRequest = 0;
|
||||
|
@ -216,7 +230,11 @@ bool ContactsBox::peopleFailed(const RPCError &error, mtpRequestId req) {
|
|||
}
|
||||
|
||||
void ContactsBox::showAll() {
|
||||
_select->show();
|
||||
if (_inner->chat() && _inner->membersFilter() == MembersFilter::Admins && _inner->allAdmins()) {
|
||||
_select->hideFast();
|
||||
} else {
|
||||
_select->showFast();
|
||||
}
|
||||
if (_inner->channel() && _inner->membersFilter() == MembersFilter::Admins) {
|
||||
_next.hide();
|
||||
_cancel.hide();
|
||||
|
@ -236,7 +254,11 @@ void ContactsBox::showAll() {
|
|||
}
|
||||
|
||||
void ContactsBox::doSetInnerFocus() {
|
||||
_select->setInnerFocus();
|
||||
if (_select->isHidden()) {
|
||||
_inner->setFocus();
|
||||
} else {
|
||||
_select->entity()->setInnerFocus();
|
||||
}
|
||||
}
|
||||
|
||||
void ContactsBox::onSubmit() {
|
||||
|
@ -282,10 +304,18 @@ void ContactsBox::paintEvent(QPaintEvent *e) {
|
|||
}
|
||||
}
|
||||
|
||||
int ContactsBox::getTopScrollSkip() const {
|
||||
auto result = st::boxTitleHeight;
|
||||
if (!_select->isHidden()) {
|
||||
result += _select->height();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void ContactsBox::updateScrollSkips() {
|
||||
auto oldScrollHeight = scrollArea()->height();
|
||||
auto inviting = (_inner->creating() == CreatingGroupGroup) || (_inner->channel() && _inner->membersFilter() == MembersFilter::Recent) || _inner->chat();
|
||||
auto topSkip = st::boxTitleHeight + _select->height();
|
||||
auto topSkip = getTopScrollSkip();
|
||||
auto bottomSkip = inviting ? (st::boxButtonPadding.top() + _next.height() + st::boxButtonPadding.bottom()) : st::boxScrollSkip;
|
||||
setScrollSkips(bottomSkip, topSkip);
|
||||
auto scrollHeightDelta = scrollArea()->height() - oldScrollHeight;
|
||||
|
@ -293,7 +323,7 @@ void ContactsBox::updateScrollSkips() {
|
|||
scrollArea()->scrollToY(scrollArea()->scrollTop() - scrollHeightDelta);
|
||||
}
|
||||
|
||||
_topShadow.setGeometry(0, st::boxTitleHeight + _select->height(), width(), st::lineWidth);
|
||||
_topShadow.setGeometry(0, topSkip, width(), st::lineWidth);
|
||||
}
|
||||
|
||||
void ContactsBox::resizeEvent(QResizeEvent *e) {
|
||||
|
@ -321,24 +351,30 @@ void ContactsBox::onFilterUpdate(const QString &filter) {
|
|||
_inner->updateFilter(filter);
|
||||
}
|
||||
|
||||
void ContactsBox::addPeerToMultiSelect(PeerData *peer, bool skipAnimation) {
|
||||
auto getColor = [peer]() -> const style::color & {
|
||||
switch (peer->colorIndex) {
|
||||
case 1: return st::historyPeer2UserpicFg;
|
||||
case 2: return st::historyPeer3UserpicFg;
|
||||
case 3: return st::historyPeer4UserpicFg;
|
||||
case 4: return st::historyPeer5UserpicFg;
|
||||
case 5: return st::historyPeer6UserpicFg;
|
||||
case 6: return st::historyPeer7UserpicFg;
|
||||
case 7: return st::historyPeer8UserpicFg;
|
||||
default: return st::historyPeer1UserpicFg;
|
||||
}
|
||||
};
|
||||
using AddItemWay = Ui::MultiSelect::AddItemWay;
|
||||
auto addItemWay = skipAnimation ? AddItemWay::SkipAnimation : AddItemWay::Default;
|
||||
_select->entity()->addItem(peer->id, peer->shortName(), getColor(), PaintUserpicCallback(peer), addItemWay);
|
||||
}
|
||||
|
||||
void ContactsBox::onPeerSelectedChanged(PeerData *peer, bool checked) {
|
||||
if (checked) {
|
||||
auto getColor = [peer]() -> const style::color &{
|
||||
switch (peer->colorIndex) {
|
||||
case 1: return st::historyPeer2UserpicFg;
|
||||
case 2: return st::historyPeer3UserpicFg;
|
||||
case 3: return st::historyPeer4UserpicFg;
|
||||
case 4: return st::historyPeer5UserpicFg;
|
||||
case 5: return st::historyPeer6UserpicFg;
|
||||
case 6: return st::historyPeer7UserpicFg;
|
||||
case 7: return st::historyPeer8UserpicFg;
|
||||
default: return st::historyPeer1UserpicFg;
|
||||
}
|
||||
};
|
||||
_select->addItem(peer->id, peer->shortName(), getColor(), PaintUserpicCallback(peer));
|
||||
_select->clearQuery();
|
||||
addPeerToMultiSelect(peer);
|
||||
_select->entity()->clearQuery();
|
||||
} else {
|
||||
_select->removeItem(peer->id);
|
||||
_select->entity()->removeItem(peer->id);
|
||||
}
|
||||
update();
|
||||
}
|
||||
|
@ -346,7 +382,7 @@ void ContactsBox::onPeerSelectedChanged(PeerData *peer, bool checked) {
|
|||
void ContactsBox::onInvite() {
|
||||
QVector<UserData*> users(_inner->selected());
|
||||
if (users.isEmpty()) {
|
||||
_select->setInnerFocus();
|
||||
_select->entity()->setInnerFocus();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -364,7 +400,7 @@ void ContactsBox::onCreate() {
|
|||
|
||||
auto users = _inner->selectedInputs();
|
||||
if (users.isEmpty() || (users.size() == 1 && users.at(0).type() == mtpc_inputUserSelf)) {
|
||||
_select->setInnerFocus();
|
||||
_select->entity()->setInnerFocus();
|
||||
return;
|
||||
}
|
||||
_saveRequestId = MTP::send(MTPmessages_CreateChat(MTP_vector<MTPInputUser>(users), MTP_string(_creationName)), rpcDone(&ContactsBox::creationDone), rpcFail(&ContactsBox::creationFail));
|
||||
|
@ -514,7 +550,7 @@ bool ContactsBox::creationFail(const RPCError &error) {
|
|||
onClose();
|
||||
return true;
|
||||
} else if (error.type() == "USERS_TOO_FEW") {
|
||||
_select->setInnerFocus();
|
||||
_select->entity()->setInnerFocus();
|
||||
return true;
|
||||
} else if (error.type() == "PEER_FLOOD") {
|
||||
Ui::showLayer(new InformBox(cantInviteError()), KeepOtherLayers);
|
||||
|
@ -641,7 +677,7 @@ void ContactsBox::Inner::init() {
|
|||
}
|
||||
|
||||
void ContactsBox::Inner::initList() {
|
||||
if (!usingMultiSelect()) return;
|
||||
if (!_chat || _membersFilter != MembersFilter::Admins) return;
|
||||
|
||||
QList<UserData*> admins, others;
|
||||
admins.reserve(_chat->admins.size() + 1);
|
||||
|
@ -653,7 +689,9 @@ void ContactsBox::Inner::initList() {
|
|||
if (i.key()->id == peerFromUser(_chat->creator)) continue;
|
||||
if (!_allAdmins.checked() && _chat->admins.contains(i.key())) {
|
||||
admins.push_back(i.key());
|
||||
_checkedContacts.insert(i.key());
|
||||
if (!_checkedContacts.contains(i.key())) {
|
||||
_checkedContacts.insert(i.key());
|
||||
}
|
||||
} else {
|
||||
others.push_back(i.key());
|
||||
}
|
||||
|
@ -716,10 +754,10 @@ void ContactsBox::Inner::onNoAddAdminBox(QObject *obj) {
|
|||
}
|
||||
|
||||
void ContactsBox::Inner::onAllAdminsChanged() {
|
||||
if (_saving) {
|
||||
if (_allAdmins.checked() != _allAdminsChecked) {
|
||||
_allAdmins.setChecked(_allAdminsChecked);
|
||||
}
|
||||
if (_saving && _allAdmins.checked() != _allAdminsChecked) {
|
||||
_allAdmins.setChecked(_allAdminsChecked);
|
||||
} else if (_allAdminsChangedCallback) {
|
||||
_allAdminsChangedCallback();
|
||||
}
|
||||
update();
|
||||
}
|
||||
|
@ -1355,7 +1393,8 @@ void ContactsBox::Inner::changeCheckState(Dialogs::Row *row) {
|
|||
void ContactsBox::Inner::changeCheckState(ContactData *data, PeerData *peer) {
|
||||
t_assert(usingMultiSelect());
|
||||
|
||||
if (data->checkbox->checked()) {
|
||||
if (_chat && _membersFilter == MembersFilter::Admins && _allAdmins.checked()) {
|
||||
} else if (data->checkbox->checked()) {
|
||||
changePeerCheckState(data, peer, false);
|
||||
} else if (selectedCount() < ((_channel && _channel->isMegagroup()) ? Global::MegagroupSizeMax() : Global::ChatSizeMax())) {
|
||||
changePeerCheckState(data, peer, true);
|
||||
|
@ -1385,7 +1424,7 @@ void ContactsBox::Inner::changePeerCheckState(ContactData *data, PeerData *peer,
|
|||
} else {
|
||||
_checkedContacts.remove(peer);
|
||||
}
|
||||
if (useCallback != ChangeStateWay::SkipCallback) {
|
||||
if (useCallback != ChangeStateWay::SkipCallback && _peerSelectedChangedCallback) {
|
||||
_peerSelectedChangedCallback(peer, checked);
|
||||
}
|
||||
}
|
||||
|
@ -1874,12 +1913,12 @@ QVector<UserData*> ContactsBox::Inner::selected() {
|
|||
}
|
||||
}
|
||||
result.reserve(_contactsData.size());
|
||||
for (ContactsData::const_iterator i = _contactsData.cbegin(), e = _contactsData.cend(); i != e; ++i) {
|
||||
for (auto i = _contactsData.cbegin(), e = _contactsData.cend(); i != e; ++i) {
|
||||
if (i.value()->checkbox->checked() && i.key()->isUser()) {
|
||||
result.push_back(i.key()->asUser());
|
||||
}
|
||||
}
|
||||
for (int32 i = 0, l = _byUsername.size(); i < l; ++i) {
|
||||
for (int i = 0, l = _byUsername.size(); i < l; ++i) {
|
||||
if (d_byUsername[i]->checkbox->checked() && _byUsername[i]->isUser()) {
|
||||
result.push_back(_byUsername[i]->asUser());
|
||||
}
|
||||
|
@ -1899,12 +1938,12 @@ QVector<MTPInputUser> ContactsBox::Inner::selectedInputs() {
|
|||
}
|
||||
}
|
||||
result.reserve(_contactsData.size());
|
||||
for (ContactsData::const_iterator i = _contactsData.cbegin(), e = _contactsData.cend(); i != e; ++i) {
|
||||
for (auto i = _contactsData.cbegin(), e = _contactsData.cend(); i != e; ++i) {
|
||||
if (i.value()->checkbox->checked() && i.key()->isUser()) {
|
||||
result.push_back(i.key()->asUser()->inputUser);
|
||||
}
|
||||
}
|
||||
for (int32 i = 0, l = _byUsername.size(); i < l; ++i) {
|
||||
for (int i = 0, l = _byUsername.size(); i < l; ++i) {
|
||||
if (d_byUsername[i]->checkbox->checked() && _byUsername[i]->isUser()) {
|
||||
result.push_back(_byUsername[i]->asUser()->inputUser);
|
||||
}
|
||||
|
|
|
@ -32,6 +32,8 @@ class IndexedList;
|
|||
|
||||
namespace Ui {
|
||||
class MultiSelect;
|
||||
template <typename Widget>
|
||||
class WidgetSlideWrap;
|
||||
} // namespace Ui
|
||||
|
||||
QString cantInviteError();
|
||||
|
@ -79,13 +81,15 @@ protected:
|
|||
|
||||
private:
|
||||
void init();
|
||||
int getTopScrollSkip() const;
|
||||
void updateScrollSkips();
|
||||
void onFilterUpdate(const QString &filter);
|
||||
void onPeerSelectedChanged(PeerData *peer, bool checked);
|
||||
void addPeerToMultiSelect(PeerData *peer, bool skipAnimation = false);
|
||||
|
||||
class Inner;
|
||||
ChildWidget<Inner> _inner;
|
||||
ChildWidget<Ui::MultiSelect> _select;
|
||||
ChildWidget<Ui::WidgetSlideWrap<Ui::MultiSelect>> _select;
|
||||
|
||||
BoxButton _next, _cancel;
|
||||
MembersFilter _membersFilter;
|
||||
|
@ -151,6 +155,9 @@ public:
|
|||
bool allAdmins() const {
|
||||
return _allAdmins.checked();
|
||||
}
|
||||
void setAllAdminsChangedCallback(base::lambda_unique<void()> allAdminsChangedCallback) {
|
||||
_allAdminsChangedCallback = std_::move(allAdminsChangedCallback);
|
||||
}
|
||||
|
||||
void loadProfilePhotos(int32 yFrom);
|
||||
void chooseParticipant();
|
||||
|
@ -259,6 +266,7 @@ private:
|
|||
Checkbox _allAdmins;
|
||||
int32 _aboutWidth;
|
||||
Text _aboutAllAdmins, _aboutAdmins;
|
||||
base::lambda_unique<void()> _allAdminsChangedCallback;
|
||||
|
||||
PeerData *_addToPeer = nullptr;
|
||||
UserData *_addAdmin = nullptr;
|
||||
|
|
|
@ -23,6 +23,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||
|
||||
#include "dialogs/dialogs_indexed_list.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "styles/style_history.h"
|
||||
#include "observer_peer.h"
|
||||
#include "lang.h"
|
||||
#include "mainwindow.h"
|
||||
|
@ -32,7 +33,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||
#include "boxes/confirmbox.h"
|
||||
#include "apiwrap.h"
|
||||
#include "ui/toast/toast.h"
|
||||
#include "ui/buttons/icon_button.h"
|
||||
#include "ui/widgets/multi_select.h"
|
||||
#include "history/history_media_types.h"
|
||||
#include "boxes/contactsbox.h"
|
||||
|
||||
|
@ -40,30 +41,37 @@ ShareBox::ShareBox(CopyCallback &©Callback, SubmitCallback &&submitCallback,
|
|||
, _copyCallback(std_::move(copyCallback))
|
||||
, _submitCallback(std_::move(submitCallback))
|
||||
, _inner(this, std_::move(filterCallback))
|
||||
, _filter(this, st::boxSearchField, lang(lng_participant_filter))
|
||||
, _filterCancel(this, st::boxSearchCancel)
|
||||
, _select(this, st::contactsMultiSelect, lang(lng_participant_filter))
|
||||
, _copy(this, lang(lng_share_copy_link), st::defaultBoxButton)
|
||||
, _share(this, lang(lng_share_confirm), st::defaultBoxButton)
|
||||
, _cancel(this, lang(lng_cancel), st::cancelBoxButton)
|
||||
, _topShadow(this)
|
||||
, _bottomShadow(this) {
|
||||
int topSkip = st::boxTitleHeight + _filter->height();
|
||||
int bottomSkip = st::boxButtonPadding.top() + _share->height() + st::boxButtonPadding.bottom();
|
||||
_select->resizeToWidth(st::boxWideWidth);
|
||||
|
||||
auto topSkip = getTopScrollSkip();
|
||||
auto bottomSkip = st::boxButtonPadding.top() + _share->height() + st::boxButtonPadding.bottom();
|
||||
init(_inner, bottomSkip, topSkip);
|
||||
|
||||
connect(_inner, SIGNAL(selectedChanged()), this, SLOT(onSelectedChanged()));
|
||||
connect(_inner, SIGNAL(mustScrollTo(int,int)), this, SLOT(onMustScrollTo(int,int)));
|
||||
connect(_copy, SIGNAL(clicked()), this, SLOT(onCopyLink()));
|
||||
connect(_share, SIGNAL(clicked()), this, SLOT(onSubmit()));
|
||||
connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose()));
|
||||
connect(scrollArea(), SIGNAL(scrolled()), this, SLOT(onScroll()));
|
||||
connect(_filter, SIGNAL(changed()), this, SLOT(onFilterUpdate()));
|
||||
connect(_filter, SIGNAL(submitted(bool)), _inner, SLOT(onSelectActive()));
|
||||
connect(_filterCancel, SIGNAL(clicked()), this, SLOT(onFilterCancel()));
|
||||
connect(_inner, SIGNAL(filterCancel()), this, SLOT(onFilterCancel()));
|
||||
_select->setQueryChangedCallback([this](const QString &query) { onFilterUpdate(query); });
|
||||
_select->setItemRemovedCallback([this](uint64 itemId) {
|
||||
if (auto peer = App::peerLoaded(itemId)) {
|
||||
_inner->peerUnselected(peer);
|
||||
onSelectedChanged();
|
||||
update();
|
||||
}
|
||||
});
|
||||
_select->setResizedCallback([this] { updateScrollSkips(); });
|
||||
_select->setSubmittedCallback([this](bool) { _inner->onSelectActive(); });
|
||||
connect(_inner, SIGNAL(searchByUsername()), this, SLOT(onNeedSearchByUsername()));
|
||||
|
||||
_filterCancel->setAttribute(Qt::WA_OpaquePaintEvent);
|
||||
_inner->setPeerSelectedChangedCallback([this](PeerData *peer, bool checked) {
|
||||
onPeerSelectedChanged(peer, checked);
|
||||
});
|
||||
|
||||
_searchTimer.setSingleShot(true);
|
||||
connect(&_searchTimer, SIGNAL(timeout()), this, SLOT(onSearchByUsername()));
|
||||
|
@ -73,8 +81,29 @@ ShareBox::ShareBox(CopyCallback &©Callback, SubmitCallback &&submitCallback,
|
|||
prepare();
|
||||
}
|
||||
|
||||
int ShareBox::getTopScrollSkip() const {
|
||||
auto result = st::boxTitleHeight;
|
||||
if (!_select->isHidden()) {
|
||||
result += _select->height();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void ShareBox::updateScrollSkips() {
|
||||
auto oldScrollHeight = scrollArea()->height();
|
||||
auto topSkip = getTopScrollSkip();
|
||||
auto bottomSkip = st::boxButtonPadding.top() + _share->height() + st::boxButtonPadding.bottom();
|
||||
setScrollSkips(bottomSkip, topSkip);
|
||||
auto scrollHeightDelta = scrollArea()->height() - oldScrollHeight;
|
||||
if (scrollHeightDelta) {
|
||||
scrollArea()->scrollToY(scrollArea()->scrollTop() - scrollHeightDelta);
|
||||
}
|
||||
|
||||
_topShadow->setGeometry(0, topSkip, width(), st::lineWidth);
|
||||
}
|
||||
|
||||
bool ShareBox::onSearchByUsername(bool searchCache) {
|
||||
auto query = _filter->getLastText().trimmed();
|
||||
auto query = _select->getQuery();
|
||||
if (query.isEmpty()) {
|
||||
if (_peopleRequest) {
|
||||
_peopleRequest = 0;
|
||||
|
@ -142,7 +171,7 @@ bool ShareBox::peopleFailed(const RPCError &error, mtpRequestId requestId) {
|
|||
}
|
||||
|
||||
void ShareBox::doSetInnerFocus() {
|
||||
_filter->setFocus();
|
||||
_select->setInnerFocus();
|
||||
}
|
||||
|
||||
void ShareBox::paintEvent(QPaintEvent *e) {
|
||||
|
@ -154,17 +183,21 @@ void ShareBox::paintEvent(QPaintEvent *e) {
|
|||
|
||||
void ShareBox::resizeEvent(QResizeEvent *e) {
|
||||
ItemListBox::resizeEvent(e);
|
||||
_filter->resize(width(), _filter->height());
|
||||
_filter->moveToLeft(0, st::boxTitleHeight);
|
||||
_filterCancel->moveToRight(0, st::boxTitleHeight);
|
||||
|
||||
_select->resizeToWidth(width());
|
||||
_select->moveToLeft(0, st::boxTitleHeight);
|
||||
|
||||
updateScrollSkips();
|
||||
|
||||
_inner->resizeToWidth(width());
|
||||
moveButtons();
|
||||
_topShadow->setGeometry(0, st::boxTitleHeight + _filter->height(), width(), st::lineWidth);
|
||||
_topShadow->setGeometry(0, getTopScrollSkip(), width(), st::lineWidth);
|
||||
_bottomShadow->setGeometry(0, height() - st::boxButtonPadding.bottom() - _share->height() - st::boxButtonPadding.top() - st::lineWidth, width(), st::lineWidth);
|
||||
}
|
||||
|
||||
void ShareBox::keyPressEvent(QKeyEvent *e) {
|
||||
if (_filter->hasFocus()) {
|
||||
auto focused = focusWidget();
|
||||
if (_select == focused || _select->isAncestorOf(focusWidget())) {
|
||||
if (e->key() == Qt::Key_Up) {
|
||||
_inner->activateSkipColumn(-1);
|
||||
} else if (e->key() == Qt::Key_Down) {
|
||||
|
@ -194,13 +227,38 @@ void ShareBox::updateButtonsVisibility() {
|
|||
_cancel->setVisible(hasSelected);
|
||||
}
|
||||
|
||||
void ShareBox::onFilterCancel() {
|
||||
_filter->setText(QString());
|
||||
void ShareBox::onFilterUpdate(const QString &query) {
|
||||
scrollArea()->scrollToY(0);
|
||||
_inner->updateFilter(query);
|
||||
}
|
||||
|
||||
void ShareBox::onFilterUpdate() {
|
||||
_filterCancel->setVisible(!_filter->getLastText().isEmpty());
|
||||
_inner->updateFilter(_filter->getLastText());
|
||||
void ShareBox::addPeerToMultiSelect(PeerData *peer, bool skipAnimation) {
|
||||
auto getColor = [peer]() -> const style::color & {
|
||||
switch (peer->colorIndex) {
|
||||
case 1: return st::historyPeer2UserpicFg;
|
||||
case 2: return st::historyPeer3UserpicFg;
|
||||
case 3: return st::historyPeer4UserpicFg;
|
||||
case 4: return st::historyPeer5UserpicFg;
|
||||
case 5: return st::historyPeer6UserpicFg;
|
||||
case 6: return st::historyPeer7UserpicFg;
|
||||
case 7: return st::historyPeer8UserpicFg;
|
||||
default: return st::historyPeer1UserpicFg;
|
||||
}
|
||||
};
|
||||
using AddItemWay = Ui::MultiSelect::AddItemWay;
|
||||
auto addItemWay = skipAnimation ? AddItemWay::SkipAnimation : AddItemWay::Default;
|
||||
_select->addItem(peer->id, peer->shortName(), getColor(), PaintUserpicCallback(peer), addItemWay);
|
||||
}
|
||||
|
||||
void ShareBox::onPeerSelectedChanged(PeerData *peer, bool checked) {
|
||||
if (checked) {
|
||||
addPeerToMultiSelect(peer);
|
||||
_select->clearQuery();
|
||||
} else {
|
||||
_select->removeItem(peer->id);
|
||||
}
|
||||
onSelectedChanged();
|
||||
update();
|
||||
}
|
||||
|
||||
void ShareBox::onSubmit() {
|
||||
|
@ -597,17 +655,34 @@ void ShareBox::Inner::changeCheckState(Chat *chat) {
|
|||
if (!chat->checkbox.checked()) {
|
||||
_chatsIndexed->moveToTop(chat->peer);
|
||||
}
|
||||
emit filterCancel();
|
||||
}
|
||||
|
||||
chat->checkbox.setChecked(!chat->checkbox.checked());
|
||||
if (chat->checkbox.checked()) {
|
||||
changePeerCheckState(chat, !chat->checkbox.checked());
|
||||
}
|
||||
|
||||
void ShareBox::Inner::peerUnselected(PeerData *peer) {
|
||||
// If data is nullptr we simply won't do anything.
|
||||
auto chat = _dataMap.value(peer, nullptr);
|
||||
changePeerCheckState(chat, false, ChangeStateWay::SkipCallback);
|
||||
}
|
||||
|
||||
void ShareBox::Inner::setPeerSelectedChangedCallback(base::lambda_unique<void(PeerData *peer, bool selected)> callback) {
|
||||
_peerSelectedChangedCallback = std_::move(callback);
|
||||
}
|
||||
|
||||
void ShareBox::Inner::changePeerCheckState(Chat *chat, bool checked, ChangeStateWay useCallback) {
|
||||
if (chat) {
|
||||
chat->checkbox.setChecked(checked);
|
||||
}
|
||||
if (checked) {
|
||||
_selected.insert(chat->peer);
|
||||
setActive(chatIndex(chat->peer));
|
||||
} else {
|
||||
_selected.remove(chat->peer);
|
||||
}
|
||||
emit selectedChanged();
|
||||
if (useCallback != ChangeStateWay::SkipCallback && _peerSelectedChangedCallback) {
|
||||
_peerSelectedChangedCallback(chat->peer, checked);
|
||||
}
|
||||
}
|
||||
|
||||
bool ShareBox::Inner::hasSelected() const {
|
||||
|
|
|
@ -36,7 +36,7 @@ struct PeerUpdate;
|
|||
} // namespace Notify
|
||||
|
||||
namespace Ui {
|
||||
class IconButton;
|
||||
class MultiSelect;
|
||||
} // namespace Ui
|
||||
|
||||
QString appendShareGameScoreUrl(const QString &url, const FullMsgId &fullId);
|
||||
|
@ -52,8 +52,6 @@ public:
|
|||
ShareBox(CopyCallback &©Callback, SubmitCallback &&submitCallback, FilterCallback &&filterCallback);
|
||||
|
||||
private slots:
|
||||
void onFilterUpdate();
|
||||
void onFilterCancel();
|
||||
void onScroll();
|
||||
|
||||
bool onSearchByUsername(bool searchCache = false);
|
||||
|
@ -61,7 +59,6 @@ private slots:
|
|||
|
||||
void onSubmit();
|
||||
void onCopyLink();
|
||||
void onSelectedChanged();
|
||||
|
||||
void onMustScrollTo(int top, int bottom);
|
||||
|
||||
|
@ -73,8 +70,15 @@ protected:
|
|||
void doSetInnerFocus() override;
|
||||
|
||||
private:
|
||||
void onFilterUpdate(const QString &query);
|
||||
void onSelectedChanged();
|
||||
void moveButtons();
|
||||
void updateButtonsVisibility();
|
||||
int getTopScrollSkip() const;
|
||||
void updateScrollSkips();
|
||||
|
||||
void addPeerToMultiSelect(PeerData *peer, bool skipAnimation = false);
|
||||
void onPeerSelectedChanged(PeerData *peer, bool checked);
|
||||
|
||||
void peopleReceived(const MTPcontacts_Found &result, mtpRequestId requestId);
|
||||
bool peopleFailed(const RPCError &error, mtpRequestId requestId);
|
||||
|
@ -84,8 +88,7 @@ private:
|
|||
|
||||
class Inner;
|
||||
ChildWidget<Inner> _inner;
|
||||
ChildWidget<InputField> _filter;
|
||||
ChildWidget<Ui::IconButton> _filterCancel;
|
||||
ChildWidget<Ui::MultiSelect> _select;
|
||||
|
||||
ChildWidget<BoxButton> _copy;
|
||||
ChildWidget<BoxButton> _share;
|
||||
|
@ -116,6 +119,9 @@ class ShareBox::Inner : public ScrolledWidget, public RPCSender, private base::S
|
|||
public:
|
||||
Inner(QWidget *parent, ShareBox::FilterCallback &&filterCallback);
|
||||
|
||||
void setPeerSelectedChangedCallback(base::lambda_unique<void(PeerData *peer, bool selected)> callback);
|
||||
void peerUnselected(PeerData *peer);
|
||||
|
||||
QVector<PeerData*> selected() const;
|
||||
bool hasSelected() const;
|
||||
|
||||
|
@ -134,9 +140,7 @@ public slots:
|
|||
|
||||
signals:
|
||||
void mustScrollTo(int ymin, int ymax);
|
||||
void filterCancel();
|
||||
void searchByUsername();
|
||||
void selectedChanged();
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
|
@ -170,6 +174,11 @@ private:
|
|||
|
||||
void loadProfilePhotos(int yFrom);
|
||||
void changeCheckState(Chat *chat);
|
||||
enum class ChangeStateWay {
|
||||
Default,
|
||||
SkipCallback,
|
||||
};
|
||||
void changePeerCheckState(Chat *chat, bool checked, ChangeStateWay useCallback = ChangeStateWay::Default);
|
||||
|
||||
Chat *getChat(Dialogs::Row *row);
|
||||
void setActive(int active);
|
||||
|
@ -198,6 +207,8 @@ private:
|
|||
using SelectedChats = OrderedSet<PeerData*>;
|
||||
SelectedChats _selected;
|
||||
|
||||
base::lambda_unique<void(PeerData *peer, bool selected)> _peerSelectedChangedCallback;
|
||||
|
||||
ChatData *data(Dialogs::Row *row);
|
||||
|
||||
bool _searching = false;
|
||||
|
|
|
@ -60,7 +60,7 @@ struct lambda_wrap_helper_base {
|
|||
|
||||
protected:
|
||||
static void bad_construct_copy(void *lambda, const void *source) {
|
||||
throw std::exception();
|
||||
t_assert(!"base::lambda bad_construct_copy() called!");
|
||||
}
|
||||
|
||||
};
|
||||
|
@ -72,7 +72,8 @@ struct lambda_wrap_empty : public lambda_wrap_helper_base<Return, Args...> {
|
|||
static void construct_move_other_method(void *lambda, void *source) {
|
||||
}
|
||||
static Return call_method(const void *lambda, Args... args) {
|
||||
throw std::exception();
|
||||
t_assert(!"base::lambda empty call_method() called!");
|
||||
return Return();
|
||||
}
|
||||
static void destruct_method(const void *lambda) {
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||
#include "lang.h"
|
||||
#include "application.h"
|
||||
#include "ui/scrollarea.h"
|
||||
#include "ui/buttons/icon_button.h"
|
||||
#include "ui/widgets/multi_select.h"
|
||||
#include "boxes/contactsbox.h"
|
||||
#include "countries.h"
|
||||
#include "styles/style_boxes.h"
|
||||
|
@ -65,7 +65,8 @@ namespace {
|
|||
countriesFiltered.reserve(countriesCount);
|
||||
countriesNames.resize(countriesCount);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
const CountriesByCode &countriesByCode() {
|
||||
initCountries();
|
||||
|
@ -196,19 +197,17 @@ void CountryInput::setText(const QString &newText) {
|
|||
|
||||
CountrySelectBox::CountrySelectBox() : ItemListBox(st::countriesScroll, st::boxWidth)
|
||||
, _inner(this)
|
||||
, _filter(this, st::boxSearchField, lang(lng_country_ph))
|
||||
, _filterCancel(this, st::boxSearchCancel)
|
||||
, _select(this, st::contactsMultiSelect, lang(lng_country_ph))
|
||||
, _topShadow(this) {
|
||||
ItemListBox::init(_inner, st::boxScrollSkip, st::boxTitleHeight + _filter->height());
|
||||
_select->resizeToWidth(st::boxWidth);
|
||||
|
||||
connect(_filter, SIGNAL(changed()), this, SLOT(onFilterUpdate()));
|
||||
connect(_filter, SIGNAL(submitted(bool)), this, SLOT(onSubmit()));
|
||||
connect(_filterCancel, SIGNAL(clicked()), this, SLOT(onFilterCancel()));
|
||||
ItemListBox::init(_inner, st::boxScrollSkip, st::boxTitleHeight + _select->height());
|
||||
|
||||
_select->setQueryChangedCallback([this](const QString &query) { onFilterUpdate(query); });
|
||||
_select->setSubmittedCallback([this](bool) { onSubmit(); });
|
||||
connect(_inner, SIGNAL(mustScrollTo(int, int)), scrollArea(), SLOT(scrollToY(int, int)));
|
||||
connect(_inner, SIGNAL(countryChosen(const QString&)), this, SIGNAL(countryChosen(const QString&)));
|
||||
|
||||
_filterCancel->setAttribute(Qt::WA_OpaquePaintEvent);
|
||||
|
||||
prepare();
|
||||
}
|
||||
|
||||
|
@ -239,40 +238,27 @@ void CountrySelectBox::paintEvent(QPaintEvent *e) {
|
|||
|
||||
void CountrySelectBox::resizeEvent(QResizeEvent *e) {
|
||||
ItemListBox::resizeEvent(e);
|
||||
_filter->resize(width(), _filter->height());
|
||||
_filter->moveToLeft(0, st::boxTitleHeight);
|
||||
_filterCancel->moveToRight(0, st::boxTitleHeight);
|
||||
_inner->resize(width(), _inner->height());
|
||||
_topShadow.setGeometry(0, st::boxTitleHeight + _filter->height(), width(), st::lineWidth);
|
||||
|
||||
_select->resizeToWidth(width());
|
||||
_select->moveToLeft(0, st::boxTitleHeight);
|
||||
|
||||
_inner->resizeToWidth(width());
|
||||
_topShadow.setGeometry(0, st::boxTitleHeight + _select->height(), width(), st::lineWidth);
|
||||
}
|
||||
|
||||
void CountrySelectBox::showAll() {
|
||||
_filter->show();
|
||||
if (_filter->getLastText().isEmpty()) {
|
||||
_filterCancel->hide();
|
||||
} else {
|
||||
_filterCancel->show();
|
||||
}
|
||||
_select->show();
|
||||
_topShadow.show();
|
||||
ItemListBox::showAll();
|
||||
}
|
||||
|
||||
void CountrySelectBox::onFilterCancel() {
|
||||
_filter->setText(QString());
|
||||
}
|
||||
|
||||
void CountrySelectBox::onFilterUpdate() {
|
||||
void CountrySelectBox::onFilterUpdate(const QString &query) {
|
||||
scrollArea()->scrollToY(0);
|
||||
if (_filter->getLastText().isEmpty()) {
|
||||
_filterCancel->hide();
|
||||
} else {
|
||||
_filterCancel->show();
|
||||
}
|
||||
_inner->updateFilter(_filter->getLastText());
|
||||
_inner->updateFilter(query);
|
||||
}
|
||||
|
||||
void CountrySelectBox::doSetInnerFocus() {
|
||||
_filter->setFocus();
|
||||
_select->setInnerFocus();
|
||||
}
|
||||
|
||||
CountrySelectBox::Inner::Inner(QWidget *parent) : ScrolledWidget(parent)
|
||||
|
|
|
@ -29,10 +29,9 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||
QString findValidCode(QString fullCode);
|
||||
|
||||
class CountrySelect;
|
||||
class InputField;
|
||||
|
||||
namespace Ui {
|
||||
class IconButton;
|
||||
class MultiSelect;
|
||||
} // namespace Ui
|
||||
|
||||
class CountryInput : public QWidget {
|
||||
|
@ -82,8 +81,6 @@ signals:
|
|||
void countryChosen(const QString &iso);
|
||||
|
||||
public slots:
|
||||
void onFilterUpdate();
|
||||
void onFilterCancel();
|
||||
void onSubmit();
|
||||
|
||||
protected:
|
||||
|
@ -95,10 +92,11 @@ protected:
|
|||
void showAll() override;
|
||||
|
||||
private:
|
||||
void onFilterUpdate(const QString &query);
|
||||
|
||||
class Inner;
|
||||
ChildWidget<Inner> _inner;
|
||||
ChildWidget<InputField> _filter;
|
||||
ChildWidget<Ui::IconButton> _filterCancel;
|
||||
ChildWidget<Ui::MultiSelect> _select;
|
||||
|
||||
ScrollableBoxShadow _topShadow;
|
||||
|
||||
|
|
|
@ -1890,9 +1890,7 @@ void InputField::step_placeholderFg(float64 ms, bool timer) {
|
|||
void InputField::step_placeholderShift(float64 ms, bool timer) {
|
||||
float64 dt = ms / _st.duration;
|
||||
if (dt >= 1) {
|
||||
_a_placeholderShift.stop();
|
||||
a_placeholderLeft.finish();
|
||||
a_placeholderOpacity.finish();
|
||||
finishPlaceholderAnimation();
|
||||
} else {
|
||||
a_placeholderLeft.update(dt, anim::linear);
|
||||
a_placeholderOpacity.update(dt, anim::linear);
|
||||
|
@ -1900,6 +1898,13 @@ void InputField::step_placeholderShift(float64 ms, bool timer) {
|
|||
if (timer) update();
|
||||
}
|
||||
|
||||
void InputField::finishPlaceholderAnimation() {
|
||||
_a_placeholderShift.stop();
|
||||
a_placeholderLeft.finish();
|
||||
a_placeholderOpacity.finish();
|
||||
update();
|
||||
}
|
||||
|
||||
void InputField::step_border(float64 ms, bool timer) {
|
||||
float64 dt = ms / _st.duration;
|
||||
if (dt >= 1) {
|
||||
|
|
|
@ -343,6 +343,7 @@ public:
|
|||
}
|
||||
void updatePlaceholder();
|
||||
void setPlaceholderHidden(bool forcePlaceholderHidden);
|
||||
void finishPlaceholderAnimation();
|
||||
|
||||
void step_placeholderFg(float64 ms, bool timer);
|
||||
void step_placeholderShift(float64 ms, bool timer);
|
||||
|
|
|
@ -433,8 +433,8 @@ QString MultiSelect::getQuery() const {
|
|||
return _inner->getQuery();
|
||||
}
|
||||
|
||||
void MultiSelect::addItem(uint64 itemId, const QString &text, const style::color &color, PaintRoundImage paintRoundImage) {
|
||||
_inner->addItem(std_::make_unique<Inner::Item>(_st.item, itemId, text, color, std_::move(paintRoundImage)));
|
||||
void MultiSelect::addItem(uint64 itemId, const QString &text, const style::color &color, PaintRoundImage paintRoundImage, AddItemWay way) {
|
||||
_inner->addItem(std_::make_unique<Inner::Item>(_st.item, itemId, text, color, std_::move(paintRoundImage)), way);
|
||||
}
|
||||
|
||||
void MultiSelect::setItemRemovedCallback(base::lambda_unique<void(uint64 itemId)> callback) {
|
||||
|
@ -710,7 +710,7 @@ void MultiSelect::Inner::mousePressEvent(QMouseEvent *e) {
|
|||
}
|
||||
}
|
||||
|
||||
void MultiSelect::Inner::addItem(std_::unique_ptr<Item> item) {
|
||||
void MultiSelect::Inner::addItem(std_::unique_ptr<Item> item, AddItemWay way) {
|
||||
auto wasEmpty = _items.empty();
|
||||
item->setUpdateCallback([this, item = item.get()] {
|
||||
auto itemRect = item->paintArea(width() - _st.padding.left() - _st.padding.top());
|
||||
|
@ -723,7 +723,12 @@ void MultiSelect::Inner::addItem(std_::unique_ptr<Item> item) {
|
|||
if (wasEmpty) {
|
||||
updateHasAnyItems(true);
|
||||
}
|
||||
_items.back()->showAnimated();
|
||||
if (way != AddItemWay::SkipAnimation) {
|
||||
_items.back()->showAnimated();
|
||||
} else {
|
||||
_field->finishPlaceholderAnimation();
|
||||
finishHeightAnimation();
|
||||
}
|
||||
}
|
||||
|
||||
void MultiSelect::Inner::computeItemsGeometry(int newWidth) {
|
||||
|
@ -765,16 +770,23 @@ void MultiSelect::Inner::updateItemsGeometry() {
|
|||
if (newHeight == _newHeight) return;
|
||||
|
||||
_newHeight = newHeight;
|
||||
_height.start([this] {
|
||||
auto newHeight = _height.current(_newHeight);
|
||||
if (auto heightDelta = newHeight - height()) {
|
||||
resize(width(), newHeight);
|
||||
if (_resizedCallback) {
|
||||
_resizedCallback(heightDelta);
|
||||
}
|
||||
update();
|
||||
_height.start([this] { updateHeightStep(); }, height(), _newHeight, _st.item.duration);
|
||||
}
|
||||
|
||||
void MultiSelect::Inner::updateHeightStep() {
|
||||
auto newHeight = _height.current(_newHeight);
|
||||
if (auto heightDelta = newHeight - height()) {
|
||||
resize(width(), newHeight);
|
||||
if (_resizedCallback) {
|
||||
_resizedCallback(heightDelta);
|
||||
}
|
||||
}, height(), _newHeight, _st.item.duration);
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
void MultiSelect::Inner::finishHeightAnimation() {
|
||||
_height.finish();
|
||||
updateHeightStep();
|
||||
}
|
||||
|
||||
void MultiSelect::Inner::setItemText(uint64 itemId, const QString &text) {
|
||||
|
|
|
@ -40,8 +40,12 @@ public:
|
|||
void setSubmittedCallback(base::lambda_unique<void(bool ctrlShiftEnter)> callback);
|
||||
void setResizedCallback(base::lambda_unique<void()> callback);
|
||||
|
||||
enum class AddItemWay {
|
||||
Default,
|
||||
SkipAnimation,
|
||||
};
|
||||
using PaintRoundImage = base::lambda_unique<void(Painter &p, int x, int y, int outerWidth, int size)>;
|
||||
void addItem(uint64 itemId, const QString &text, const style::color &color, PaintRoundImage paintRoundImage);
|
||||
void addItem(uint64 itemId, const QString &text, const style::color &color, PaintRoundImage paintRoundImage, AddItemWay way = AddItemWay::Default);
|
||||
void setItemText(uint64 itemId, const QString &text);
|
||||
|
||||
void setItemRemovedCallback(base::lambda_unique<void(uint64 itemId)> callback);
|
||||
|
@ -82,7 +86,7 @@ public:
|
|||
void setSubmittedCallback(base::lambda_unique<void(bool ctrlShiftEnter)> callback);
|
||||
|
||||
class Item;
|
||||
void addItem(std_::unique_ptr<Item> item);
|
||||
void addItem(std_::unique_ptr<Item> item, AddItemWay way);
|
||||
void setItemText(uint64 itemId, const QString &text);
|
||||
|
||||
void setItemRemovedCallback(base::lambda_unique<void(uint64 itemId)> callback);
|
||||
|
@ -120,6 +124,8 @@ private:
|
|||
updateSelection(QPoint(-1, -1));
|
||||
}
|
||||
void updateCursor();
|
||||
void updateHeightStep();
|
||||
void finishHeightAnimation();
|
||||
enum class ChangeActiveWay {
|
||||
Default,
|
||||
SkipSetFocus,
|
||||
|
|
|
@ -30,7 +30,7 @@ public:
|
|||
using UpdateCallback = base::lambda_unique<void()>;
|
||||
WidgetSlideWrap(QWidget *parent, Widget *entity
|
||||
, style::margins entityPadding
|
||||
, UpdateCallback &&updateCallback
|
||||
, UpdateCallback updateCallback
|
||||
, int duration = st::widgetSlideDuration) : TWidget(parent)
|
||||
, _entity(entity)
|
||||
, _padding(entityPadding)
|
||||
|
|
|
@ -92,11 +92,11 @@ MultiSelect {
|
|||
itemSkip: pixels;
|
||||
|
||||
field: InputField;
|
||||
fieldMinWidth: pixels;
|
||||
fieldIcon: icon;
|
||||
fieldIconSkip: pixels;
|
||||
fieldCancel: IconButton;
|
||||
fieldCancelSkip: pixels;
|
||||
fieldMinWidth: pixels;
|
||||
}
|
||||
|
||||
widgetSlideDuration: 200;
|
||||
|
|
Loading…
Reference in New Issue