Extract a reusable Ui::ResizeArea class.

This commit is contained in:
John Preston 2017-11-12 19:41:00 +04:00
parent 3a25313e61
commit bca9b3ca3f
5 changed files with 194 additions and 42 deletions

View File

@ -38,6 +38,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "data/data_drafts.h" #include "data/data_drafts.h"
#include "ui/widgets/dropdown_menu.h" #include "ui/widgets/dropdown_menu.h"
#include "ui/focus_persister.h" #include "ui/focus_persister.h"
#include "ui/resize_area.h"
#include "chat_helpers/message_field.h" #include "chat_helpers/message_field.h"
#include "chat_helpers/stickers.h" #include "chat_helpers/stickers.h"
#include "observer_peer.h" #include "observer_peer.h"
@ -226,7 +227,6 @@ MainWidget::MainWidget(
, _controller(controller) , _controller(controller)
, _dialogsWidth(st::dialogsWidthMin) , _dialogsWidth(st::dialogsWidthMin)
, _sideShadow(this) , _sideShadow(this)
, _sideResizeArea(this)
, _dialogs(this, _controller) , _dialogs(this, _controller)
, _history(this, _controller) , _history(this, _controller)
, _playerPlaylist(this, Media::Player::Panel::Layout::OnlyPlaylist) , _playerPlaylist(this, Media::Player::Panel::Layout::OnlyPlaylist)
@ -292,8 +292,6 @@ MainWidget::MainWidget(
_webPageOrGameUpdater.setSingleShot(true); _webPageOrGameUpdater.setSingleShot(true);
connect(&_webPageOrGameUpdater, SIGNAL(timeout()), this, SLOT(webPagesOrGamesUpdate())); connect(&_webPageOrGameUpdater, SIGNAL(timeout()), this, SLOT(webPagesOrGamesUpdate()));
_sideResizeArea->setCursor(style::cur_sizehor);
using Update = Window::Theme::BackgroundUpdate; using Update = Window::Theme::BackgroundUpdate;
subscribe(Window::Theme::Background(), [this](const Update &update) { subscribe(Window::Theme::Background(), [this](const Update &update) {
if (update.type == Update::Type::New || update.type == Update::Type::Changed) { if (update.type == Update::Type::New || update.type == Update::Type::Changed) {
@ -354,8 +352,6 @@ MainWidget::MainWidget(
orderWidgets(); orderWidgets();
_sideResizeArea->installEventFilter(this);
#ifndef TDESKTOP_DISABLE_AUTOUPDATE #ifndef TDESKTOP_DISABLE_AUTOUPDATE
Sandbox::startUpdateCheck(); Sandbox::startUpdateCheck();
#endif // !TDESKTOP_DISABLE_AUTOUPDATE #endif // !TDESKTOP_DISABLE_AUTOUPDATE
@ -3078,7 +3074,12 @@ void MainWidget::orderWidgets() {
if (_thirdShadow) { if (_thirdShadow) {
_thirdShadow->raise(); _thirdShadow->raise();
} }
_sideResizeArea->raise(); if (_firstColumnResizeArea) {
_firstColumnResizeArea->raise();
}
if (_thirdColumnResizeArea) {
_thirdColumnResizeArea->raise();
}
_playerPlaylist->raise(); _playerPlaylist->raise();
_playerPanel->raise(); _playerPanel->raise();
for (auto &instance : _playerFloats) { for (auto &instance : _playerFloats) {
@ -3458,22 +3459,12 @@ void MainWidget::updateControlsGeometry() {
_hider->setGeometryToLeft(dialogsWidth, 0, mainSectionWidth, height()); _hider->setGeometryToLeft(dialogsWidth, 0, mainSectionWidth, height());
} }
} }
_sideResizeArea->setGeometryToLeft(_history->x(), 0, st::historyResizeWidth, height());
auto isSideResizeAreaVisible = [this] {
if (width() < st::columnMinimalWidthLeft + st::columnMinimalWidthMain) {
return false;
}
if (Adaptive::OneColumn() && !isMainSectionShown()) {
return false;
}
return true;
};
_sideResizeArea->setVisible(isSideResizeAreaVisible());
if (_mainSection) { if (_mainSection) {
auto mainSectionGeometry = QRect(_history->x(), mainSectionTop, _history->width(), height() - mainSectionTop); auto mainSectionGeometry = QRect(_history->x(), mainSectionTop, _history->width(), height() - mainSectionTop);
_mainSection->setGeometryWithTopMoved(mainSectionGeometry, _contentScrollAddToY); _mainSection->setGeometryWithTopMoved(mainSectionGeometry, _contentScrollAddToY);
} }
if (_overview) _overview->setGeometry(_history->geometry()); if (_overview) _overview->setGeometry(_history->geometry());
refreshResizeAreas();
updateMediaPlayerPosition(); updateMediaPlayerPosition();
updateMediaPlaylistPosition(_playerPlaylist->x()); updateMediaPlaylistPosition(_playerPlaylist->x());
_contentScrollAddToY = 0; _contentScrollAddToY = 0;
@ -3482,6 +3473,84 @@ void MainWidget::updateControlsGeometry() {
} }
} }
void MainWidget::refreshResizeAreas() {
if (!Adaptive::OneColumn()) {
ensureFirstColumnResizeAreaCreated();
_firstColumnResizeArea->setGeometryToLeft(
_history->x(),
0,
st::historyResizeWidth,
height());
} else if (_firstColumnResizeArea) {
_firstColumnResizeArea.destroy();
}
if (Adaptive::ThreeColumn() && _thirdSection) {
ensureThirdColumnResizeAreaCreated();
_thirdColumnResizeArea->setGeometryToLeft(
_thirdSection->x(),
0,
st::historyResizeWidth,
height());
} else if (_thirdColumnResizeArea) {
_thirdColumnResizeArea.destroy();
}
}
template <typename MoveCallback, typename FinishCallback>
void MainWidget::createResizeArea(
object_ptr<Ui::ResizeArea> &area,
MoveCallback &&moveCallback,
FinishCallback &&finishCallback) {
area.create(this);
area->show();
area->addMoveLeftCallback(
std::forward<MoveCallback>(moveCallback));
area->addMoveFinishedCallback(
std::forward<FinishCallback>(finishCallback));
orderWidgets();
}
void MainWidget::ensureFirstColumnResizeAreaCreated() {
if (_firstColumnResizeArea) {
return;
}
auto moveLeftCallback = [=](int globalLeft) {
auto newWidth = globalLeft - mapToGlobal(QPoint(0, 0)).x();
auto newRatio = (newWidth < st::dialogsWidthMin / 2)
? 0.
: float64(newWidth) / width();
Auth().data().setDialogsWidthRatio(newRatio);
};
auto moveFinishedCallback = [=] {
if (!Adaptive::OneColumn()
&& Auth().data().dialogsWidthRatio() > 0) {
Auth().data().setDialogsWidthRatio(
float64(_dialogsWidth) / width());
}
Local::writeUserSettings();
};
createResizeArea(
_firstColumnResizeArea,
std::move(moveLeftCallback),
std::move(moveFinishedCallback));
}
void MainWidget::ensureThirdColumnResizeAreaCreated() {
if (_thirdColumnResizeArea) {
return;
}
auto moveLeftCallback = [=](int globalLeft) {
};
auto moveFinishedCallback = [=] {
};
createResizeArea(
_thirdColumnResizeArea,
std::move(moveLeftCallback),
std::move(moveFinishedCallback));
}
void MainWidget::updateDialogsWidthAnimated() { void MainWidget::updateDialogsWidthAnimated() {
if (Auth().data().dialogsWidthRatio() > 0) { if (Auth().data().dialogsWidthRatio() > 0) {
return; return;
@ -3581,27 +3650,7 @@ void MainWidget::keyPressEvent(QKeyEvent *e) {
} }
bool MainWidget::eventFilter(QObject *o, QEvent *e) { bool MainWidget::eventFilter(QObject *o, QEvent *e) {
if (o == _sideResizeArea) { if (e->type() == QEvent::FocusIn) {
auto mouseLeft = [this, e] {
return mapFromGlobal(static_cast<QMouseEvent*>(e)->globalPos()).x();
};
if (e->type() == QEvent::MouseButtonPress && static_cast<QMouseEvent*>(e)->button() == Qt::LeftButton) {
_resizingSide = true;
_resizingSideShift = mouseLeft() - (Adaptive::OneColumn() ? 0 : _dialogsWidth);
} else if (e->type() == QEvent::MouseButtonRelease) {
_resizingSide = false;
if (!Adaptive::OneColumn()
&& Auth().data().dialogsWidthRatio() > 0) {
Auth().data().setDialogsWidthRatio(
float64(_dialogsWidth) / width());
}
Local::writeUserSettings();
} else if (e->type() == QEvent::MouseMove && _resizingSide) {
auto newWidth = mouseLeft() - _resizingSideShift;
auto newRatio = (newWidth < st::dialogsWidthMin / 2) ? 0. : float64(newWidth) / width();
Auth().data().setDialogsWidthRatio(newRatio);
}
} else if (e->type() == QEvent::FocusIn) {
if (auto widget = qobject_cast<QWidget*>(o)) { if (auto widget = qobject_cast<QWidget*>(o)) {
if (_history == widget || _history->isAncestorOf(widget) if (_history == widget || _history->isAncestorOf(widget)
|| (_overview && (_overview == widget || _overview->isAncestorOf(widget))) || (_overview && (_overview == widget || _overview->isAncestorOf(widget)))

View File

@ -44,6 +44,7 @@ class Float;
} // namespace Media } // namespace Media
namespace Ui { namespace Ui {
class ResizeArea;
class PlainShadow; class PlainShadow;
class DropdownMenu; class DropdownMenu;
template <typename Widget> template <typename Widget>
@ -558,6 +559,15 @@ private:
void viewsIncrementDone(QVector<MTPint> ids, const MTPVector<MTPint> &result, mtpRequestId req); void viewsIncrementDone(QVector<MTPint> ids, const MTPVector<MTPint> &result, mtpRequestId req);
bool viewsIncrementFail(const RPCError &error, mtpRequestId req); bool viewsIncrementFail(const RPCError &error, mtpRequestId req);
void refreshResizeAreas();
template <typename MoveCallback, typename FinishCallback>
void createResizeArea(
object_ptr<Ui::ResizeArea> &area,
MoveCallback &&moveCallback,
FinishCallback &&finishCallback);
void ensureFirstColumnResizeAreaCreated();
void ensureThirdColumnResizeAreaCreated();
not_null<Window::Controller*> _controller; not_null<Window::Controller*> _controller;
bool _started = false; bool _started = false;
@ -578,7 +588,8 @@ private:
object_ptr<Ui::PlainShadow> _sideShadow; object_ptr<Ui::PlainShadow> _sideShadow;
object_ptr<Ui::PlainShadow> _thirdShadow = { nullptr }; object_ptr<Ui::PlainShadow> _thirdShadow = { nullptr };
object_ptr<TWidget> _sideResizeArea; object_ptr<Ui::ResizeArea> _firstColumnResizeArea = { nullptr };
object_ptr<Ui::ResizeArea> _thirdColumnResizeArea = { nullptr };
object_ptr<DialogsWidget> _dialogs; object_ptr<DialogsWidget> _dialogs;
object_ptr<HistoryWidget> _history; object_ptr<HistoryWidget> _history;
object_ptr<Window::SectionWidget> _mainSection = { nullptr }; object_ptr<Window::SectionWidget> _mainSection = { nullptr };
@ -670,7 +681,7 @@ private:
std::unique_ptr<App::WallPaper> _background; std::unique_ptr<App::WallPaper> _background;
bool _resizingSide = false; bool _firstColumnResizing = false;
int _resizingSideShift = 0; int _firstColumnResizingShift = 0;
}; };

View File

@ -0,0 +1,91 @@
/*
This file is part of Telegram Desktop,
the official desktop version of Telegram messaging app, see https://telegram.org
Telegram Desktop is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
It is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
In addition, as a special exception, the copyright holders give permission
to link the code of portions of this program with the OpenSSL library.
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#pragma once
#include "ui/rp_widget.h"
namespace Ui {
class ResizeArea : public RpWidget {
public:
ResizeArea(QWidget *parent) : RpWidget(parent) {
setCursor(style::cur_sizehor);
}
rpl::producer<int> moveLeft() const {
return _moveLeft.events();
}
template <typename Callback>
void addMoveLeftCallback(Callback &&callback) {
moveLeft()
| rpl::start_with_next(
std::forward<Callback>(callback),
lifetime());
}
rpl::producer<> moveFinished() const {
return _moveFinished.events();
}
template <typename Callback>
void addMoveFinishedCallback(Callback &&callback) {
moveFinished()
| rpl::start_with_next(
std::forward<Callback>(callback),
lifetime());
}
~ResizeArea() {
moveFinish();
}
protected:
void mousePressEvent(QMouseEvent *e) override {
if (e->button() == Qt::LeftButton) {
_moving = true;
_moveStartLeft = e->pos().x();
}
}
void mouseReleaseEvent(QMouseEvent *e) override {
if (e->button() == Qt::LeftButton) {
moveFinish();
}
}
void mouseMoveEvent(QMouseEvent *e) override {
if (_moving) {
_moveLeft.fire(e->globalPos().x() - _moveStartLeft);
}
}
private:
void moveFinish() {
if (base::take(_moving)) {
_moveFinished.fire({});
}
}
rpl::event_stream<int> _moveLeft;
rpl::event_stream<> _moveFinished;
int _moveStartLeft = 0;
bool _moving = false;
};
} // namespace Ui

View File

@ -32,7 +32,7 @@ windowShadowShift: 1px;
columnMinimalWidthLeft: 260px; columnMinimalWidthLeft: 260px;
columnMinimalWidthMain: 380px; columnMinimalWidthMain: 380px;
columnMinimalWidthThird: 345px;//292px;//345px; columnMinimalWidthThird: 292px;//345px;
adaptiveChatWideWidth: 880px; adaptiveChatWideWidth: 880px;

View File

@ -609,6 +609,7 @@
<(src_loc)/ui/focus_persister.h <(src_loc)/ui/focus_persister.h
<(src_loc)/ui/images.cpp <(src_loc)/ui/images.cpp
<(src_loc)/ui/images.h <(src_loc)/ui/images.h
<(src_loc)/ui/resize_area.h
<(src_loc)/ui/rp_widget.h <(src_loc)/ui/rp_widget.h
<(src_loc)/ui/search_field_controller.cpp <(src_loc)/ui/search_field_controller.cpp
<(src_loc)/ui/search_field_controller.h <(src_loc)/ui/search_field_controller.h