New media player layout started.

This commit is contained in:
John Preston 2016-09-17 22:28:33 +03:00
parent 50fa8b63c9
commit ce1973fd30
13 changed files with 448 additions and 0 deletions

View File

@ -50,6 +50,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "localstorage.h"
#include "shortcuts.h"
#include "media/media_audio.h"
#include "media/player/media_player_button.h"
#include "media/player/media_player_widget.h"
#include "core/qthelp_regex.h"
#include "core/qthelp_url.h"
#include "window/chat_background.h"
@ -75,6 +77,11 @@ MainWidget::MainWidget(MainWindow *window) : TWidget(window)
, _api(new ApiWrap(this)) {
setGeometry(QRect(0, st::titleHeight, App::wnd()->width(), App::wnd()->height() - st::titleHeight));
if (!_mediaPlayer) {
_mediaPlayer = new Media::Player::Widget(this);
App::wnd()->getTitle()->playerButton()->installEventFilter(_mediaPlayer);
}
MTP::setGlobalDoneHandler(rpcDone(&MainWidget::updateReceived));
_ptsWaiter.setRequesting(true);
updateScrollColors();
@ -2405,6 +2412,7 @@ void MainWidget::orderWidgets() {
_dialogs->raise();
_mediaType->raise();
_sideShadow.raise();
if (_mediaPlayer) _mediaPlayer->raise();
if (_hider) _hider->raise();
}
@ -2664,6 +2672,9 @@ inline int chatsListWidth(int windowWidth) {
void MainWidget::resizeEvent(QResizeEvent *e) {
int32 tbh = _topBar->isHidden() ? 0 : st::topBarHeight;
if (_mediaPlayer) {
_mediaPlayer->moveToRight(0, 0);
}
if (Adaptive::OneColumn()) {
_dialogsWidth = width();
_player->setGeometry(0, 0, _dialogsWidth, _player->height());

View File

@ -27,6 +27,12 @@ namespace Dialogs {
class Row;
} // namespace Dialogs
namespace Media {
namespace Player {
class Widget;
} // namespace Player
} // namespace Media
namespace Ui {
class PeerAvatarButton;
} // namespace Ui
@ -580,6 +586,7 @@ private:
ChildWidget<OverviewWidget> _overview = { nullptr };
ChildWidget<PlayerWidget> _player;
ChildWidget<Window::TopBarWidget> _topBar;
ChildWidget<Media::Player::Widget> _mediaPlayer = { nullptr };
ConfirmBox *_forwardConfirm = nullptr; // for single column layout
ChildWidget<HistoryHider> _hider = { nullptr };
std_::vector_of_moveable<std_::unique_ptr<StackItem>> _stack;

View File

@ -31,3 +31,63 @@ mediaPlayerTitleButtonPauseTop: 8px;
mediaPlayerTitleButtonPauseStroke: 3px;
mediaPlayerTitleButtonPlayLeft: 10px;
mediaPlayerTitleButtonPlayTop: 7px;
mediaPlayerMarginLeft: 10px;
mediaPlayerMarginBottom: 10px;
mediaPlayerWidth: 344px;
mediaPlayerCoverHeight: 102px;
mediaPlayerPlayButton: IconButton {
width: 32px;
height: 32px;
opacity: 1.;
overOpacity: 1.;
icon: icon {
{ "player_play", #54b5ed, point(6px, 7px) },
};
iconPosition: point(0px, 0px);
downIconPosition: point(0px, 0px);
duration: 0;
}
mediaPlayerPauseIcon: icon {
{ "player_pause", #54b5ed, point(9px, 8px) }
};
mediaPlayerRepeatButton: IconButton(mediaPlayerPlayButton) {
icon: icon {
{ "player_repeat", #54b5ed, point(9px, 9px)}
};
}
mediaPlayerPadding: 18px;
mediaPlayerNameTop: 24px;
mediaPlayerPlayLeft: 9px;
mediaPlayerPlayTop: 58px;
mediaPlayerNameFont: normalFont;
mediaPlayerNameFg: windowTextFg;
mediaPlayerTimeFont: normalFont;
mediaPlayerTimeFg: windowSubTextFg;
mediaPlayerPlaybackTop: 32px;
mediaPlayerPlaybackPadding: 8px;
mediaPlayerPlaybackBg: #54b5ed;
mediaPlayerPlaybackLine: 3px;
mediaPlayerVolumeRight: 50px;
mediaPlayerVolumeWidth: 86px;
mediaPlayerVolumeLength: 64px;
mediaPlayerVolumeIcon0: icon {
{ "player_volume0", #54b5ed },
};
mediaPlayerVolumeIcon1: icon {
{ "player_volume1", #54b5ed },
};
mediaPlayerVolumeIcon2: icon {
{ "player_volume2", #54b5ed },
};
mediaPlayerVolumeIcon3: icon {
{ "player_volume3", #54b5ed },
};

View File

@ -21,8 +21,44 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "stdafx.h"
#include "media/player/media_player_cover.h"
#include "ui/flatlabel.h"
#include "ui/widgets/label_simple.h"
#include "ui/buttons/icon_button.h"
#include "media/player/media_player_playback.h"
#include "media/player/media_player_volume_controller.h"
#include "styles/style_media_player.h"
namespace Media {
namespace Player {
CoverWidget::CoverWidget(QWidget *parent) : TWidget(parent)
, _nameLabel(this)
, _timeLabel(this)
, _playback(this)
, _playPause(this, st::mediaPlayerPlayButton)
, _volumeController(this)
, _repeatTrack(this, st::mediaPlayerRepeatButton) {
setAttribute(Qt::WA_OpaquePaintEvent);
_playPause->setIcon(&st::mediaPlayerPauseIcon);
}
void CoverWidget::resizeEvent(QResizeEvent *e) {
_nameLabel->moveToLeft(st::mediaPlayerPadding, st::mediaPlayerNameTop - st::mediaPlayerNameFont->ascent);
_timeLabel->moveToRight(st::mediaPlayerPadding, st::mediaPlayerNameTop - st::mediaPlayerTimeFont->ascent);
_playback->setGeometry(st::mediaPlayerPadding, st::mediaPlayerPlaybackTop, width() - 2 * st::mediaPlayerPadding, 2 * st::mediaPlayerPlaybackPadding + st::mediaPlayerPlaybackLine);
_repeatTrack->moveToRight(st::mediaPlayerPlayLeft, st::mediaPlayerPlayTop);
_volumeController->moveToRight(st::mediaPlayerVolumeRight, st::mediaPlayerPlayTop + (_playPause->height() - _volumeController->height()) / 2);
updatePlayPrevNextPositions();
}
void CoverWidget::paintEvent(QPaintEvent *e) {
Painter p(this);
p.fillRect(e->rect(), st::windowBg);
}
void CoverWidget::updatePlayPrevNextPositions() {
_playPause->moveToLeft(st::mediaPlayerPlayLeft, st::mediaPlayerPlayTop);
}
} // namespace Player
} // namespace Media

View File

@ -20,8 +20,39 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
*/
#pragma once
class FlatLabel;
namespace Ui {
class LabelSimple;
class IconButton;
} // namespace Ui
namespace Media {
namespace Player {
class PlaybackWidget;
class VolumeController;
class CoverWidget : public TWidget {
public:
CoverWidget(QWidget *parent);
protected:
void resizeEvent(QResizeEvent *e) override;
void paintEvent(QPaintEvent *e) override;
private:
void updatePlayPrevNextPositions();
ChildWidget<FlatLabel> _nameLabel;
ChildWidget<Ui::LabelSimple> _timeLabel;
ChildWidget<PlaybackWidget> _playback;
ChildWidget<Ui::IconButton> _previousTrack = { nullptr };
ChildWidget<Ui::IconButton> _playPause;
ChildWidget<Ui::IconButton> _nextTrack = { nullptr };
ChildWidget<VolumeController> _volumeController;
ChildWidget<Ui::IconButton> _repeatTrack;
};
} // namespace Clip
} // namespace Media

View File

@ -23,5 +23,10 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
namespace Media {
namespace Player {
class ListWidget : public ScrolledWidget {
public:
};
} // namespace Clip
} // namespace Media

View File

@ -21,8 +21,19 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "stdafx.h"
#include "media/player/media_player_playback.h"
#include "styles/style_media_player.h"
namespace Media {
namespace Player {
PlaybackWidget::PlaybackWidget(QWidget *parent) : TWidget(parent) {
}
void PlaybackWidget::paintEvent(QPaintEvent *e) {
Painter p(this);
p.fillRect(0, st::mediaPlayerPlaybackPadding, width(), st::mediaPlayerPlaybackLine, st::mediaPlayerPlaybackBg);
}
} // namespace Player
} // namespace Media

View File

@ -23,5 +23,16 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
namespace Media {
namespace Player {
class PlaybackWidget : public TWidget {
public:
PlaybackWidget(QWidget *parent);
protected:
void paintEvent(QPaintEvent *e) override;
private:
};
} // namespace Clip
} // namespace Media

View File

@ -21,8 +21,32 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "stdafx.h"
#include "media/player/media_player_volume_controller.h"
#include "styles/style_media_player.h"
namespace Media {
namespace Player {
VolumeController::VolumeController(QWidget *parent) : TWidget(parent) {
resize(st::mediaPlayerVolumeWidth, 2 * st::mediaPlayerPlaybackPadding + st::mediaPlayerPlaybackLine);
}
void VolumeController::paintEvent(QPaintEvent *e) {
Painter p(this);
st::mediaPlayerVolumeIcon0.paint(p, QPoint(0, (height() - st::mediaPlayerVolumeIcon0.height()) / 2), width());
auto left = rtl() ? 0 : width() - st::mediaPlayerVolumeLength;
p.fillRect(left, st::mediaPlayerPlaybackPadding, st::mediaPlayerVolumeLength, st::mediaPlayerPlaybackLine, st::mediaPlayerPlaybackBg);
}
void VolumeController::mousePressEvent(QMouseEvent *e) {
}
void VolumeController::mouseMoveEvent(QMouseEvent *e) {
}
void VolumeController::mouseReleaseEvent(QMouseEvent *e) {
}
} // namespace Player
} // namespace Media

View File

@ -23,5 +23,19 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
namespace Media {
namespace Player {
class VolumeController : public TWidget {
public:
VolumeController(QWidget *parent);
protected:
void paintEvent(QPaintEvent *e) override;
void mousePressEvent(QMouseEvent *e) override;
void mouseMoveEvent(QMouseEvent *e) override;
void mouseReleaseEvent(QMouseEvent *e) override;
private:
};
} // namespace Clip
} // namespace Media

View File

@ -21,8 +21,185 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "stdafx.h"
#include "media/player/media_player_widget.h"
#include "media/player/media_player_cover.h"
#include "media/player/media_player_list.h"
#include "styles/style_media_player.h"
#include "mainwindow.h"
namespace Media {
namespace Player {
Widget::Widget(QWidget *parent) : TWidget(parent)
, _shadow(st::defaultInnerDropdown.shadow)
, _cover(this) {
_hideTimer.setSingleShot(true);
connect(&_hideTimer, SIGNAL(timeout()), this, SLOT(onHideStart()));
_showTimer.setSingleShot(true);
connect(&_showTimer, SIGNAL(timeout()), this, SLOT(onShowStart()));
connect(_scroll, SIGNAL(scrolled()), this, SLOT(onScroll()));
if (cPlatform() == dbipMac || cPlatform() == dbipMacOld) {
connect(App::wnd()->windowHandle(), SIGNAL(activeChanged()), this, SLOT(onWindowActiveChanged()));
}
hide();
resize(contentLeft() + st::mediaPlayerWidth, st::mediaPlayerCoverHeight + st::mediaPlayerMarginBottom);
}
bool Widget::overlaps(const QRect &globalRect) {
if (isHidden() || !_a_appearance.isNull()) return false;
auto marginLeft = rtl() ? 0 : contentLeft();
auto marginRight = rtl() ? contentLeft() : 0;
return rect().marginsRemoved(QMargins(marginLeft, 0, marginRight, st::mediaPlayerMarginBottom)).contains(QRect(mapFromGlobal(globalRect.topLeft()), globalRect.size()));
}
void Widget::onWindowActiveChanged() {
if (!App::wnd()->windowHandle()->isActive() && !isHidden()) {
leaveEvent(nullptr);
}
}
void Widget::resizeEvent(QResizeEvent *e) {
_cover->resize(width() - contentLeft(), st::mediaPlayerCoverHeight);
_cover->moveToRight(0, 0);
if (_scroll) {
_scroll->resize(width(), height() - _cover->height());
_scroll->moveToRight(0, _cover->height());
_list->resizeToWidth(width());
}
//_scroll->setGeometry(rect().marginsRemoved(_st.padding).marginsRemoved(_st.scrollMargin));
//if (auto widget = static_cast<ScrolledWidget*>(_scroll->widget())) {
// widget->resizeToWidth(_scroll->width());
// onScroll();
//}
}
void Widget::onScroll() {
//if (auto widget = static_cast<ScrolledWidget*>(_scroll->widget())) {
// int visibleTop = _scroll->scrollTop();
// int visibleBottom = visibleTop + _scroll->height();
// widget->setVisibleTopBottom(visibleTop, visibleBottom);
//}
}
void Widget::paintEvent(QPaintEvent *e) {
Painter p(this);
if (!_cache.isNull()) {
bool animating = _a_appearance.animating(getms());
if (animating) {
p.setOpacity(_a_appearance.current(_hiding));
} else if (_hiding) {
hidingFinished();
return;
}
p.drawPixmap(0, 0, _cache);
if (!animating) {
showChildren();
_cache = QPixmap();
}
return;
}
// draw shadow
auto shadowedRect = myrtlrect(contentLeft(), 0, contentWidth(), height() - st::mediaPlayerMarginBottom);
auto shadowedSides = (rtl() ? Ui::RectShadow::Side::Right : Ui::RectShadow::Side::Left) | Ui::RectShadow::Side::Bottom;
_shadow.paint(p, shadowedRect, st::defaultInnerDropdown.shadowShift, shadowedSides);
p.fillRect(shadowedRect, st::windowBg);
}
void Widget::enterEvent(QEvent *e) {
_hideTimer.stop();
if (_a_appearance.animating(getms())) {
onShowStart();
} else {
_showTimer.start(0);
}
return TWidget::enterEvent(e);
}
void Widget::leaveEvent(QEvent *e) {
_showTimer.stop();
if (_a_appearance.animating(getms())) {
onHideStart();
} else {
_hideTimer.start(300);
}
return TWidget::leaveEvent(e);
}
void Widget::otherEnter() {
_hideTimer.stop();
if (_a_appearance.animating(getms())) {
onShowStart();
} else {
_showTimer.start(300);
}
}
void Widget::otherLeave() {
_showTimer.stop();
if (_a_appearance.animating(getms())) {
onHideStart();
} else {
_hideTimer.start(0);
}
}
void Widget::onShowStart() {
if (isHidden()) {
show();
} else if (!_hiding) {
return;
}
_hiding = false;
startAnimation();
}
void Widget::onHideStart() {
if (_hiding) return;
_hiding = true;
startAnimation();
}
void Widget::startAnimation() {
auto from = _hiding ? 1. : 0.;
auto to = _hiding ? 0. : 1.;
if (_a_appearance.isNull()) {
showChildren();
_cache = myGrab(this);
}
hideChildren();
START_ANIMATION(_a_appearance, func([this]() {
update();
if (!_a_appearance.animating(getms()) && _hiding) {
_hiding = false;
hidingFinished();
}
}), from, to, st::defaultInnerDropdown.duration, anim::linear);
}
void Widget::hidingFinished() {
hide();
showChildren();
}
int Widget::contentLeft() const {
return st::mediaPlayerMarginLeft;
}
bool Widget::eventFilter(QObject *obj, QEvent *e) {
if (e->type() == QEvent::Enter) {
otherEnter();
} else if (e->type() == QEvent::Leave) {
otherLeave();
}
return false;
}
} // namespace Player
} // namespace Media

View File

@ -20,8 +20,65 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
*/
#pragma once
#include "ui/boxshadow.h"
class ScrollArea;
namespace Media {
namespace Player {
class CoverWidget;
class ListWidget;
class Widget : public TWidget {
Q_OBJECT
public:
Widget(QWidget *parent);
bool overlaps(const QRect &globalRect);
void otherEnter();
void otherLeave();
protected:
void resizeEvent(QResizeEvent *e) override;
void paintEvent(QPaintEvent *e) override;
void enterEvent(QEvent *e) override;
void leaveEvent(QEvent *e) override;
bool eventFilter(QObject *obj, QEvent *e) override;
private slots:
void onShowStart();
void onHideStart();
void onScroll();
void onWindowActiveChanged();
private:
void hidingFinished();
int contentLeft() const;
int contentWidth() const {
return width() - contentLeft();
}
void startAnimation();
bool _hiding = false;
QPixmap _cache;
FloatAnimation _a_appearance;
QTimer _hideTimer, _showTimer;
Ui::RectShadow _shadow;
ChildWidget<CoverWidget> _cover;
ChildWidget<ListWidget> _list = { nullptr };
ChildWidget<ScrollArea> _scroll = { nullptr };
};
} // namespace Clip
} // namespace Media

View File

@ -61,6 +61,10 @@ public:
void maximizedChanged(bool maximized, bool force = false);
Media::Player::TitleButton *playerButton() {
return _player;
}
HitTestType hitTest(const QPoint &p);
void setHideLevel(float64 level);