ShareBox: keyboard handle, animated scroll, chosen items jump to top.

This commit is contained in:
John Preston 2016-09-06 17:45:10 +03:00
parent 52a7ed77ba
commit 34331f558f
7 changed files with 174 additions and 90 deletions

View file

@ -109,3 +109,4 @@ shareNameTop: 6px;
shareColumnSkip: 6px; shareColumnSkip: 6px;
shareSelectDuration: 150; shareSelectDuration: 150;
shareActivateDuration: 150; shareActivateDuration: 150;
shareScrollDuration: 300;

View file

@ -42,13 +42,14 @@ ShareBox::ShareBox(SubmitCallback &&callback) : ItemListBox(st::boxScroll)
init(_inner, bottomSkip, topSkip); init(_inner, bottomSkip, topSkip);
connect(_inner, SIGNAL(selectedChanged()), this, SLOT(onSelectedChanged())); connect(_inner, SIGNAL(selectedChanged()), this, SLOT(onSelectedChanged()));
connect(_inner, SIGNAL(mustScrollTo(int,int)), this, SLOT(onMustScrollTo(int,int)));
connect(_share, SIGNAL(clicked()), this, SLOT(onShare())); connect(_share, SIGNAL(clicked()), this, SLOT(onShare()));
connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose())); connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose()));
connect(scrollArea(), SIGNAL(scrolled()), this, SLOT(onScroll())); connect(scrollArea(), SIGNAL(scrolled()), this, SLOT(onScroll()));
connect(_filter, SIGNAL(changed()), this, SLOT(onFilterUpdate())); connect(_filter, SIGNAL(changed()), this, SLOT(onFilterUpdate()));
// connect(_filter, SIGNAL(submitted(bool)), this, SLOT(onSubmit())); connect(_filter, SIGNAL(submitted(bool)), _inner, SLOT(onSelectActive()));
connect(_filterCancel, SIGNAL(clicked()), this, SLOT(onFilterCancel())); connect(_filterCancel, SIGNAL(clicked()), this, SLOT(onFilterCancel()));
connect(_inner, SIGNAL(selectAllQuery()), _filter, SLOT(selectAll())); connect(_inner, SIGNAL(filterCancel()), this, SLOT(onFilterCancel()));
connect(_inner, SIGNAL(searchByUsername()), this, SLOT(onNeedSearchByUsername())); connect(_inner, SIGNAL(searchByUsername()), this, SLOT(onNeedSearchByUsername()));
_filterCancel->setAttribute(Qt::WA_OpaquePaintEvent); _filterCancel->setAttribute(Qt::WA_OpaquePaintEvent);
@ -149,6 +150,24 @@ void ShareBox::resizeEvent(QResizeEvent *e) {
_bottomShadow->setGeometry(0, height() - st::boxButtonPadding.bottom() - _share->height() - st::boxButtonPadding.top() - st::lineWidth, 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()) {
if (e->key() == Qt::Key_Up) {
_inner->activateSkipColumn(-1);
} else if (e->key() == Qt::Key_Down) {
_inner->activateSkipColumn(1);
} else if (e->key() == Qt::Key_PageUp) {
_inner->activateSkipPage(scrollArea()->height(), -1);
} else if (e->key() == Qt::Key_PageDown) {
_inner->activateSkipPage(scrollArea()->height(), 1);
} else {
ItemListBox::keyPressEvent(e);
}
} else {
ItemListBox::keyPressEvent(e);
}
}
void ShareBox::moveButtons() { void ShareBox::moveButtons() {
_share->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _share->height()); _share->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _share->height());
auto cancelRight = st::boxButtonPadding.right(); auto cancelRight = st::boxButtonPadding.right();
@ -163,7 +182,6 @@ void ShareBox::onFilterCancel() {
} }
void ShareBox::onFilterUpdate() { void ShareBox::onFilterUpdate() {
scrollArea()->scrollToY(0);
_filterCancel->setVisible(!_filter->getLastText().isEmpty()); _filterCancel->setVisible(!_filter->getLastText().isEmpty());
_inner->updateFilter(_filter->getLastText()); _inner->updateFilter(_filter->getLastText());
} }
@ -180,6 +198,21 @@ void ShareBox::onSelectedChanged() {
update(); update();
} }
void ShareBox::onMustScrollTo(int top, int bottom) {
auto scrollTop = scrollArea()->scrollTop(), scrollBottom = scrollTop + scrollArea()->height();
auto from = scrollTop, to = scrollTop;
if (scrollTop > top) {
to = top;
} else if (scrollBottom < bottom) {
to = bottom - (scrollBottom - scrollTop);
}
if (from != to) {
START_ANIMATION(_scrollAnimation, func([this]() {
scrollArea()->scrollToY(_scrollAnimation.current(scrollArea()->scrollTop()));
}), from, to, st::shareScrollDuration, anim::sineInOut);
}
}
void ShareBox::onScroll() { void ShareBox::onScroll() {
auto scroll = scrollArea(); auto scroll = scrollArea();
auto scrollTop = scroll->scrollTop(); auto scrollTop = scroll->scrollTop();
@ -218,6 +251,36 @@ void ShareInner::setVisibleTopBottom(int visibleTop, int visibleBottom) {
loadProfilePhotos(visibleTop); loadProfilePhotos(visibleTop);
} }
void ShareInner::activateSkipRow(int direction) {
activateSkipColumn(direction * _columnCount);
}
int ShareInner::displayedChatsCount() const {
return _filter.isEmpty() ? _chatsIndexed->size() : (_filtered.size() + d_byUsernameFiltered.size());
}
void ShareInner::activateSkipColumn(int direction) {
if (_active < 0) {
if (direction > 0) {
setActive(0);
}
return;
}
auto count = displayedChatsCount();
auto active = _active + direction;
if (active < 0) {
active = (_active > 0) ? 0 : -1;
}
if (active >= count) {
active = count - 1;
}
setActive(active);
}
void ShareInner::activateSkipPage(int pageHeight, int direction) {
activateSkipRow(direction * (pageHeight / _rowHeight));
}
void ShareInner::notifyPeerUpdated(const Notify::PeerUpdate &update) { void ShareInner::notifyPeerUpdated(const Notify::PeerUpdate &update) {
if (update.flags & Notify::PeerUpdate::Flag::NameChanged) { if (update.flags & Notify::PeerUpdate::Flag::NameChanged) {
_chatsIndexed->peerNameChanged(update.peer, update.oldNames, update.oldNameFirstChars); _chatsIndexed->peerNameChanged(update.peer, update.oldNames, update.oldNameFirstChars);
@ -247,12 +310,22 @@ void ShareInner::repaintChatAtIndex(int index) {
} }
ShareInner::Chat *ShareInner::getChatAtIndex(int index) { ShareInner::Chat *ShareInner::getChatAtIndex(int index) {
if (index < 0) return nullptr;
auto row = ([this, index]() -> Dialogs::Row* { auto row = ([this, index]() -> Dialogs::Row* {
if (index < 0) return nullptr;
if (_filter.isEmpty()) return _chatsIndexed->rowAtY(index, 1); if (_filter.isEmpty()) return _chatsIndexed->rowAtY(index, 1);
return (index < _filtered.size()) ? _filtered[index] : nullptr; return (index < _filtered.size()) ? _filtered[index] : nullptr;
})(); })();
return row ? static_cast<Chat*>(row->attached) : nullptr; if (row) {
return static_cast<Chat*>(row->attached);
}
if (!_filter.isEmpty()) {
index -= _filtered.size();
if (index >= 0 && index < d_byUsernameFiltered.size()) {
return d_byUsernameFiltered[index];
}
}
return nullptr;
} }
void ShareInner::repaintChat(PeerData *peer) { void ShareInner::repaintChat(PeerData *peer) {
@ -275,6 +348,12 @@ int ShareInner::chatIndex(PeerData *peer) const {
} }
++index; ++index;
} }
for_const (auto row, d_byUsernameFiltered) {
if (row->peer == peer) {
return index;
}
++index;
}
} }
return -1; return -1;
} }
@ -347,6 +426,8 @@ void ShareInner::setActive(int active) {
_active = active; _active = active;
changeNameFg(_active, st::shareNameFg, st::shareNameActiveFg); changeNameFg(_active, st::shareNameFg, st::shareNameActiveFg);
} }
auto y = (_active < _columnCount) ? 0 : (_rowsTop + ((_active / _columnCount) * _rowHeight));
emit mustScrollTo(y, y + _rowHeight);
} }
void ShareInner::paintChat(Painter &p, Chat *chat, int index) { void ShareInner::paintChat(Painter &p, Chat *chat, int index) {
@ -441,28 +522,14 @@ void ShareInner::paintEvent(QPaintEvent *e) {
auto indexFrom = rowFrom * _columnCount; auto indexFrom = rowFrom * _columnCount;
auto indexTo = rowTo * _columnCount; auto indexTo = rowTo * _columnCount;
if (_filter.isEmpty()) { if (_filter.isEmpty()) {
if (!_chatsIndexed->isEmpty() || !_byUsername.isEmpty()) { if (!_chatsIndexed->isEmpty()) {
if (!_chatsIndexed->isEmpty()) { auto i = _chatsIndexed->cfind(indexFrom, 1);
auto i = _chatsIndexed->cfind(indexFrom, 1); for (auto end = _chatsIndexed->cend(); i != end; ++i) {
for (auto end = _chatsIndexed->cend(); i != end; ++i) { if (indexFrom >= indexTo) {
if (indexFrom >= indexTo) { break;
break;
}
paintChat(p, getChat(*i), indexFrom);
++indexFrom;
}
indexFrom -= _chatsIndexed->size();
indexTo -= _chatsIndexed->size();
}
if (!_byUsername.isEmpty()) {
if (indexFrom < 0) indexFrom = 0;
while (indexFrom < indexTo) {
if (indexFrom >= d_byUsername.size()) {
break;
}
paintChat(p, d_byUsername[indexFrom], indexFrom);
++indexFrom;
} }
paintChat(p, getChat(*i), indexFrom);
++indexFrom;
} }
} else { } else {
// empty // empty
@ -475,7 +542,8 @@ void ShareInner::paintEvent(QPaintEvent *e) {
p.setFont(st::noContactsFont); p.setFont(st::noContactsFont);
p.setPen(st::noContactsColor); p.setPen(st::noContactsColor);
} else { } else {
if (!_filtered.isEmpty()) { auto filteredSize = _filtered.size();
if (filteredSize) {
if (indexFrom < 0) indexFrom = 0; if (indexFrom < 0) indexFrom = 0;
while (indexFrom < indexTo) { while (indexFrom < indexTo) {
if (indexFrom >= _filtered.size()) { if (indexFrom >= _filtered.size()) {
@ -484,8 +552,8 @@ void ShareInner::paintEvent(QPaintEvent *e) {
paintChat(p, getChat(_filtered[indexFrom]), indexFrom); paintChat(p, getChat(_filtered[indexFrom]), indexFrom);
++indexFrom; ++indexFrom;
} }
indexFrom -= _filtered.size(); indexFrom -= filteredSize;
indexTo -= _filtered.size(); indexTo -= filteredSize;
} }
if (!_byUsernameFiltered.isEmpty()) { if (!_byUsernameFiltered.isEmpty()) {
if (indexFrom < 0) indexFrom = 0; if (indexFrom < 0) indexFrom = 0;
@ -493,7 +561,7 @@ void ShareInner::paintEvent(QPaintEvent *e) {
if (indexFrom >= d_byUsernameFiltered.size()) { if (indexFrom >= d_byUsernameFiltered.size()) {
break; break;
} }
paintChat(p, d_byUsernameFiltered[indexFrom], indexFrom); paintChat(p, d_byUsernameFiltered[indexFrom], filteredSize + indexFrom);
++indexFrom; ++indexFrom;
} }
} }
@ -523,8 +591,7 @@ void ShareInner::updateUpon(const QPoint &pos) {
auto xupon = (x >= left) && (x < left + (_rowWidth - st::shareColumnSkip)); auto xupon = (x >= left) && (x < left + (_rowWidth - st::shareColumnSkip));
auto yupon = (y >= top) && (y < top + st::sharePhotoRadius * 2 + st::shareNameTop + st::shareNameFont->height * 2); auto yupon = (y >= top) && (y < top + st::sharePhotoRadius * 2 + st::shareNameTop + st::shareNameFont->height * 2);
auto upon = (xupon && yupon) ? (row * _columnCount + column) : -1; auto upon = (xupon && yupon) ? (row * _columnCount + column) : -1;
auto count = _filter.isEmpty() ? (_chatsIndexed->size() + d_byUsername.size()) : (_filtered.size() + d_byUsernameFiltered.size()); if (upon >= displayedChatsCount()) {
if (upon >= count) {
upon = -1; upon = -1;
} }
_upon = upon; _upon = upon;
@ -533,12 +600,14 @@ void ShareInner::updateUpon(const QPoint &pos) {
void ShareInner::mousePressEvent(QMouseEvent *e) { void ShareInner::mousePressEvent(QMouseEvent *e) {
if (e->button() == Qt::LeftButton) { if (e->button() == Qt::LeftButton) {
updateUpon(e->pos()); updateUpon(e->pos());
if (_upon >= 0) { changeCheckState(getChatAtIndex(_upon));
changeCheckState(getChatAtIndex(_upon));
}
} }
} }
void ShareInner::onSelectActive() {
changeCheckState(getChatAtIndex(_active > 0 ? _active : 0));
}
void ShareInner::resizeEvent(QResizeEvent *e) { void ShareInner::resizeEvent(QResizeEvent *e) {
_columnSkip = (width() - _columnCount * st::sharePhotoRadius * 2) / float64(_columnCount + 1); _columnSkip = (width() - _columnCount * st::sharePhotoRadius * 2) / float64(_columnCount + 1);
_rowWidthReal = st::sharePhotoRadius * 2 + _columnSkip; _rowWidthReal = st::sharePhotoRadius * 2 + _columnSkip;
@ -563,6 +632,20 @@ float64 anim_bumpy(const float64 &delta, const float64 &dt) {
} }
void ShareInner::changeCheckState(Chat *chat) { void ShareInner::changeCheckState(Chat *chat) {
if (!chat) return;
if (!_filter.isEmpty()) {
auto row = _chatsIndexed->getRow(chat->peer->id);
if (!row) {
row = _chatsIndexed->addToEnd(App::history(chat->peer)).value(0);
}
chat = getChat(row);
if (!chat->selected) {
_chatsIndexed->moveToTop(chat->peer);
}
emit filterCancel();
}
chat->selected = !chat->selected; chat->selected = !chat->selected;
if (chat->selected) { if (chat->selected) {
_selected.insert(chat->peer); _selected.insert(chat->peer);
@ -582,7 +665,9 @@ void ShareInner::changeCheckState(Chat *chat) {
START_ANIMATION(chat->selection, func([this, chat] { START_ANIMATION(chat->selection, func([this, chat] {
repaintChat(chat->peer); repaintChat(chat->peer);
}), chat->selected ? 0 : 1, chat->selected ? 1 : 0, st::shareSelectDuration, anim_bumpy); }), chat->selected ? 0 : 1, chat->selected ? 1 : 0, st::shareSelectDuration, anim_bumpy);
setActive(chatIndex(chat->peer)); if (chat->selected) {
setActive(chatIndex(chat->peer));
}
emit selectedChanged(); emit selectedChanged();
} }
@ -684,11 +769,10 @@ void ShareInner::updateFilter(QString filter) {
_filter = filter; _filter = filter;
_byUsernameFiltered.clear(); _byUsernameFiltered.clear();
d_byUsernameFiltered.clear(); for (int i = 0, l = d_byUsernameFiltered.size(); i < l; ++i) {
for (int i = 0, l = _byUsernameDatas.size(); i < l; ++i) { delete d_byUsernameFiltered[i];
delete _byUsernameDatas[i];
} }
_byUsernameDatas.clear(); d_byUsernameFiltered.clear();
if (_filter.isEmpty()) { if (_filter.isEmpty()) {
refresh(); refresh();
@ -731,34 +815,13 @@ void ShareInner::updateFilter(QString filter) {
} }
} }
} }
_byUsernameFiltered.reserve(_byUsername.size());
d_byUsernameFiltered.reserve(d_byUsername.size());
for (int i = 0, l = _byUsername.size(); i < l; ++i) {
auto &names = _byUsername[i]->names;
PeerData::Names::const_iterator nb = names.cbegin(), ne = names.cend(), ni;
for (fi = fb; fi != fe; ++fi) {
auto filterName = *fi;
for (ni = nb; ni != ne; ++ni) {
if (ni->startsWith(*fi)) {
break;
}
}
if (ni == ne) {
break;
}
}
if (fi == fe) {
_byUsernameFiltered.push_back(_byUsername[i]);
d_byUsernameFiltered.push_back(d_byUsername[i]);
}
}
} }
refresh(); refresh();
_searching = true; _searching = true;
emit searchByUsername(); emit searchByUsername();
} }
setActive(-1);
update(); update();
loadProfilePhotos(0); loadProfilePhotos(0);
} }
@ -781,8 +844,10 @@ void ShareInner::peopleReceived(const QString &query, const QVector<MTPPeer> &pe
if (!peer || !peer->canWrite()) continue; if (!peer || !peer->canWrite()) continue;
auto chat = new Chat(peer); auto chat = new Chat(peer);
_byUsernameDatas.push_back(chat);
updateChatName(chat, peer); updateChatName(chat, peer);
if (auto row = _chatsIndexed->getRow(peer->id)) {
continue;
}
_byUsernameFiltered.push_back(peer); _byUsernameFiltered.push_back(peer);
d_byUsernameFiltered.push_back(chat); d_byUsernameFiltered.push_back(chat);
@ -793,22 +858,12 @@ void ShareInner::peopleReceived(const QString &query, const QVector<MTPPeer> &pe
} }
void ShareInner::refresh() { void ShareInner::refresh() {
if (_filter.isEmpty()) { auto count = displayedChatsCount();
if (!_chatsIndexed->isEmpty() || !_byUsername.isEmpty()) { if (count) {
auto count = _chatsIndexed->size() + _byUsername.size(); auto rows = (count / _columnCount) + (count % _columnCount ? 1 : 0);
auto rows = (count / _columnCount) + (count % _columnCount ? 1 : 0); resize(width(), _rowsTop + rows * _rowHeight);
resize(width(), _rowsTop + rows * _rowHeight);
} else {
resize(width(), st::noContactsHeight);
}
} else { } else {
if (_filtered.isEmpty() && _byUsernameFiltered.isEmpty()) { resize(width(), st::noContactsHeight);
resize(width(), st::noContactsHeight);
} else {
auto count = _filtered.size() + _byUsernameFiltered.size();
auto rows = (count / _columnCount) + (count % _columnCount ? 1 : 0);
resize(width(), _rowsTop + rows * _rowHeight);
}
} }
update(); update();
} }
@ -821,17 +876,12 @@ ShareInner::~ShareInner() {
QVector<PeerData*> ShareInner::selected() const { QVector<PeerData*> ShareInner::selected() const {
QVector<PeerData*> result; QVector<PeerData*> result;
result.reserve(_dataMap.size() + _byUsername.size()); result.reserve(_dataMap.size());
for_const (auto chat, _dataMap) { for_const (auto chat, _dataMap) {
if (chat->selected) { if (chat->selected) {
result.push_back(chat->peer); result.push_back(chat->peer);
} }
} }
for (int i = 0, l = _byUsername.size(); i < l; ++i) {
if (d_byUsername[i]->selected) {
result.push_back(_byUsername[i]);
}
}
return result; return result;
} }

View file

@ -55,9 +55,12 @@ private slots:
void onShare(); void onShare();
void onSelectedChanged(); void onSelectedChanged();
void onMustScrollTo(int top, int bottom);
protected: protected:
void paintEvent(QPaintEvent *e) override; void paintEvent(QPaintEvent *e) override;
void resizeEvent(QResizeEvent *e) override; void resizeEvent(QResizeEvent *e) override;
void keyPressEvent(QKeyEvent *e) override;
void doSetInnerFocus() override; void doSetInnerFocus() override;
@ -90,6 +93,8 @@ private:
using PeopleQueries = QMap<mtpRequestId, QString>; using PeopleQueries = QMap<mtpRequestId, QString>;
PeopleQueries _peopleQueries; PeopleQueries _peopleQueries;
IntAnimation _scrollAnimation;
}; };
namespace internal { namespace internal {
@ -105,13 +110,20 @@ public:
void peopleReceived(const QString &query, const QVector<MTPPeer> &people); void peopleReceived(const QString &query, const QVector<MTPPeer> &people);
void activateSkipRow(int direction);
void activateSkipColumn(int direction);
void activateSkipPage(int pageHeight, int direction);
void setVisibleTopBottom(int visibleTop, int visibleBottom) override; void setVisibleTopBottom(int visibleTop, int visibleBottom) override;
void updateFilter(QString filter = QString()); void updateFilter(QString filter = QString());
~ShareInner(); ~ShareInner();
public slots:
void onSelectActive();
signals: signals:
void selectAllQuery(); void mustScrollTo(int ymin, int ymax);
void filterCancel();
void searchByUsername(); void searchByUsername();
void selectedChanged(); void selectedChanged();
@ -127,6 +139,8 @@ private:
// Observed notifications. // Observed notifications.
void notifyPeerUpdated(const Notify::PeerUpdate &update); void notifyPeerUpdated(const Notify::PeerUpdate &update);
int displayedChatsCount() const;
static constexpr int WideCacheScale = 4; static constexpr int WideCacheScale = 4;
struct Chat { struct Chat {
Chat(PeerData *peer); Chat(PeerData *peer);
@ -192,9 +206,8 @@ private:
QString _lastQuery; QString _lastQuery;
using ByUsernameRows = QVector<PeerData*>; using ByUsernameRows = QVector<PeerData*>;
using ByUsernameDatas = QVector<Chat*>; using ByUsernameDatas = QVector<Chat*>;
ByUsernameRows _byUsername, _byUsernameFiltered; ByUsernameRows _byUsernameFiltered;
ByUsernameDatas d_byUsername, d_byUsernameFiltered; // filtered is partly subset of d_byUsername, partly subset of _byUsernameDatas ByUsernameDatas d_byUsernameFiltered;
ByUsernameDatas _byUsernameDatas;
}; };

View file

@ -71,6 +71,16 @@ void IndexedList::adjustByPos(const RowsByLetter &links) {
} }
} }
void IndexedList::moveToTop(PeerData *peer) {
if (_list.moveToTop(peer->id)) {
for_const (auto ch, peer->chars) {
if (auto list = _index.value(ch)) {
list->moveToTop(peer->id);
}
}
}
}
void IndexedList::peerNameChanged(PeerData *peer, const PeerData::Names &oldNames, const PeerData::NameFirstChars &oldChars) { void IndexedList::peerNameChanged(PeerData *peer, const PeerData::Names &oldNames, const PeerData::NameFirstChars &oldChars) {
t_assert(_sortMode != SortMode::Date); t_assert(_sortMode != SortMode::Date);
if (_sortMode == SortMode::Name) { if (_sortMode == SortMode::Name) {

View file

@ -34,6 +34,7 @@ public:
RowsByLetter addToEnd(History *history); RowsByLetter addToEnd(History *history);
Row *addByName(History *history); Row *addByName(History *history);
void adjustByPos(const RowsByLetter &links); void adjustByPos(const RowsByLetter &links);
void moveToTop(PeerData *peer);
// For sortMode != SortMode::Date // For sortMode != SortMode::Date
void peerNameChanged(PeerData *peer, const PeerData::Names &oldNames, const PeerData::NameFirstChars &oldChars); void peerNameChanged(PeerData *peer, const PeerData::Names &oldNames, const PeerData::NameFirstChars &oldChars);

View file

@ -189,6 +189,14 @@ void List::adjustByPos(Row *row) {
} }
} }
bool List::moveToTop(PeerId peerId) {
auto i = _rowByPeer.find(peerId);
if (i == _rowByPeer.cend()) return false;
insertBefore(i.value(), _begin);
return true;
}
bool List::del(PeerId peerId, Row *replacedBy) { bool List::del(PeerId peerId, Row *replacedBy) {
auto i = _rowByPeer.find(peerId); auto i = _rowByPeer.find(peerId);
if (i == _rowByPeer.cend()) return false; if (i == _rowByPeer.cend()) return false;

View file

@ -53,10 +53,9 @@ public:
void paint(Painter &p, int32 w, int32 hFrom, int32 hTo, PeerData *act, PeerData *sel, bool onlyBackground) const; void paint(Painter &p, int32 w, int32 hFrom, int32 hTo, PeerData *act, PeerData *sel, bool onlyBackground) const;
Row *addToEnd(History *history); Row *addToEnd(History *history);
bool insertBefore(Row *row, Row *before);
bool insertAfter(Row *row, Row *after);
Row *adjustByName(const PeerData *peer); Row *adjustByName(const PeerData *peer);
Row *addByName(History *history); Row *addByName(History *history);
bool moveToTop(PeerId peerId);
void adjustByPos(Row *row); void adjustByPos(Row *row);
bool del(PeerId peerId, Row *replacedBy = nullptr); bool del(PeerId peerId, Row *replacedBy = nullptr);
void remove(Row *row); void remove(Row *row);
@ -114,6 +113,8 @@ public:
private: private:
void adjustCurrent(int y, int h) const; void adjustCurrent(int y, int h) const;
bool insertBefore(Row *row, Row *before);
bool insertAfter(Row *row, Row *after);
static Row *next(Row *row) { static Row *next(Row *row) {
return row->_next; return row->_next;
} }