diff --git a/Telegram/Resources/basic.style b/Telegram/Resources/basic.style index 55c6121ca0..62a8d173fd 100644 --- a/Telegram/Resources/basic.style +++ b/Telegram/Resources/basic.style @@ -395,8 +395,7 @@ boxSearchCancel: iconedButton { height: 48px; } -titleBG: #6389a8; -titleColor: #0f8dcc;//rgb(20, 136, 210); +titleBg: #6389a8; titleHeight: 39px; titleIconPos: point(7px, 7px); titleIconImg: sprite(161px, 100px, 26px, 26px); @@ -440,13 +439,16 @@ btnDefIconed: iconedButton { cursor: cursor(pointer); } +titleButtonFg: #c4d8e9; +titleButtonActiveFg: #ffffff; +titleButtonDuration: 150; sysBtnDelta: 6px; sysUpd: sysButton { size: size(31px, 39px); img: sprite(184px, 1px, 19px, 19px); - color: #c4d8e9; - overColor: white; - duration: 150; + color: titleButtonFg; + overColor: titleButtonActiveFg; + duration: titleButtonDuration; } updateBlinkDuration: 500; sysMin: sysButton(sysUpd) { diff --git a/Telegram/Resources/icons/title_pause.png b/Telegram/Resources/icons/title_pause.png deleted file mode 100644 index b2508ac808..0000000000 Binary files a/Telegram/Resources/icons/title_pause.png and /dev/null differ diff --git a/Telegram/Resources/icons/title_pause@2x.png b/Telegram/Resources/icons/title_pause@2x.png deleted file mode 100644 index 9c62362e55..0000000000 Binary files a/Telegram/Resources/icons/title_pause@2x.png and /dev/null differ diff --git a/Telegram/Resources/icons/title_play.png b/Telegram/Resources/icons/title_play.png deleted file mode 100644 index 90bd38b2e1..0000000000 Binary files a/Telegram/Resources/icons/title_play.png and /dev/null differ diff --git a/Telegram/Resources/icons/title_play@2x.png b/Telegram/Resources/icons/title_play@2x.png deleted file mode 100644 index 11c9a68d42..0000000000 Binary files a/Telegram/Resources/icons/title_play@2x.png and /dev/null differ diff --git a/Telegram/SourceFiles/localstorage.cpp b/Telegram/SourceFiles/localstorage.cpp index 28d1bece68..bab5f62fd5 100644 --- a/Telegram/SourceFiles/localstorage.cpp +++ b/Telegram/SourceFiles/localstorage.cpp @@ -31,13 +31,13 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "mainwidget.h" #include "mainwindow.h" #include "lang.h" -#include "playerwidget.h" +#include "media/media_audio.h" #include "apiwrap.h" namespace Local { namespace { -typedef quint64 FileKey; +using FileKey = quint64; static const char tdfMagic[] = { 'T', 'D', 'F', '$' }; static const int32 tdfMagicLen = sizeof(tdfMagic); diff --git a/Telegram/SourceFiles/media/player/media_player.style b/Telegram/SourceFiles/media/player/media_player.style index 30d08fdccb..1113a7fd9e 100644 --- a/Telegram/SourceFiles/media/player/media_player.style +++ b/Telegram/SourceFiles/media/player/media_player.style @@ -21,3 +21,13 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org using "basic.style"; +mediaPlayerTitleButtonSize: size(titleHeight, titleHeight); +mediaPlayerTitleButtonInner: size(25px, 25px); +mediaPlayerTitleButtonInnerBg: #49708f; +mediaPlayerTitleButtonTransformDuration: 200; + +mediaPlayerTitleButtonPauseLeft: 8px; +mediaPlayerTitleButtonPauseTop: 8px; +mediaPlayerTitleButtonPauseStroke: 3px; +mediaPlayerTitleButtonPlayLeft: 10px; +mediaPlayerTitleButtonPlayTop: 7px; diff --git a/Telegram/SourceFiles/media/player/media_player_button.cpp b/Telegram/SourceFiles/media/player/media_player_button.cpp index d2272e5884..7955662452 100644 --- a/Telegram/SourceFiles/media/player/media_player_button.cpp +++ b/Telegram/SourceFiles/media/player/media_player_button.cpp @@ -21,8 +21,140 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "stdafx.h" #include "media/player/media_player_button.h" +#include "styles/style_media_player.h" +#include "media/media_audio.h" + namespace Media { namespace Player { +TitleButton::TitleButton(QWidget *parent) : Button(parent) { + setAttribute(Qt::WA_OpaquePaintEvent); + resize(st::mediaPlayerTitleButtonSize); + + setClickedCallback([this]() { + setShowPause(!_showPause); + }); +} + +void TitleButton::setShowPause(bool showPause) { + if (_showPause != showPause) { + _showPause = showPause; + START_ANIMATION(_iconTransformToPause, func([this]() { + update(); + }), _showPause ? 0. : 1., _showPause ? 1. : 0., st::mediaPlayerTitleButtonTransformDuration, anim::linear); + update(); + } +} + +void TitleButton::finishIconTransform() { + if (_iconTransformToPause.animating(getms())) { + _iconTransformToPause.finish(); + update(); + } +} + +void TitleButton::paintEvent(QPaintEvent *e) { + Painter p(this); + p.fillRect(rect(), st::titleBg); + + p.setBrush(st::mediaPlayerTitleButtonInnerBg); + p.setPen(Qt::NoPen); + + p.setRenderHint(QPainter::HighQualityAntialiasing, true); + p.drawEllipse((width() - st::mediaPlayerTitleButtonInner.width()) / 2, (height() - st::mediaPlayerTitleButtonInner.height()) / 2, st::mediaPlayerTitleButtonInner.width(), st::mediaPlayerTitleButtonInner.height()); + p.setRenderHint(QPainter::HighQualityAntialiasing, false); + + paintIcon(p); +} + +void TitleButton::onStateChanged(int oldState, ButtonStateChangeSource source) { + if ((oldState & StateOver) != (_state & StateOver)) { + auto over = (_state & StateOver); + START_ANIMATION(_iconFg, func([this]() { + update(); + }), over ? st::titleButtonFg->c : st::titleButtonActiveFg->c, over ? st::titleButtonActiveFg->c : st::titleButtonFg->c, st::titleButtonDuration, anim::linear); + } +} + +namespace { + +template +QPainterPath interpolatePaths(QPointF (&from)[N], QPointF (&to)[N], float64 k) { + static_assert(N > 1, "Wrong points count in path!"); + + auto from_coef = k, to_coef = 1. - k; + QPainterPath result; + auto x = from[0].x() * from_coef + to[0].x() * to_coef; + auto y = from[0].y() * from_coef + to[0].y() * to_coef; + result.moveTo(x, y); + for (int i = 1; i != N; ++i) { + result.lineTo(from[i].x() * from_coef + to[i].x() * to_coef, from[i].y() * from_coef + to[i].y() * to_coef); + } + result.lineTo(x, y); + return result; +} + +} // namespace + +void TitleButton::paintIcon(Painter &p) { + auto over = (_state & StateOver); + auto icon = _iconFg.current(getms(), over ? st::titleButtonActiveFg->c : st::titleButtonFg->c); + auto showPause = _iconTransformToPause.current(getms(), _showPause ? 1. : 0.); + auto pauseWidth = st::mediaPlayerTitleButtonInner.width() - 2 * st::mediaPlayerTitleButtonPauseLeft; + auto playWidth = pauseWidth; + auto pauseHeight = st::mediaPlayerTitleButtonInner.height() - 2 * st::mediaPlayerTitleButtonPauseTop; + auto playHeight = st::mediaPlayerTitleButtonInner.height() - 2 * st::mediaPlayerTitleButtonPlayTop; + auto pauseStroke = st::mediaPlayerTitleButtonPauseStroke; + + qreal left = (width() - st::mediaPlayerTitleButtonInner.width()) / 2; + qreal top = (height() - st::mediaPlayerTitleButtonInner.height()) / 2; + + auto pauseLeft = left + st::mediaPlayerTitleButtonPauseLeft; + auto playLeft = left + st::mediaPlayerTitleButtonPlayLeft; + auto pauseTop = top + st::mediaPlayerTitleButtonPauseTop; + auto playTop = top + st::mediaPlayerTitleButtonPlayTop; + + p.setRenderHint(QPainter::HighQualityAntialiasing, true); + p.setPen(Qt::NoPen); + + if (showPause == 0.) { + QPainterPath pathPlay; + pathPlay.moveTo(playLeft, playTop); + pathPlay.lineTo(playLeft + playWidth, playTop + (playHeight / 2.)); + pathPlay.lineTo(playLeft, playTop + playHeight); + pathPlay.lineTo(playLeft, playTop); + p.fillPath(pathPlay, icon); + } else { + QPointF pathLeftPause[] = { + { pauseLeft, pauseTop }, + { pauseLeft + pauseStroke, pauseTop }, + { pauseLeft + pauseStroke, pauseTop + pauseHeight }, + { pauseLeft, pauseTop + pauseHeight }, + }; + QPointF pathLeftPlay[] = { + { playLeft, playTop }, + { playLeft + (playWidth / 2.), playTop + (playHeight / 4.) }, + { playLeft + (playWidth / 2.), playTop + (3 * playHeight / 4.) }, + { playLeft, playTop + playHeight }, + }; + p.fillPath(interpolatePaths(pathLeftPause, pathLeftPlay, showPause), icon); + + QPointF pathRightPause[] = { + { pauseLeft + pauseWidth - pauseStroke, pauseTop }, + { pauseLeft + pauseWidth, pauseTop }, + { pauseLeft + pauseWidth, pauseTop + pauseHeight }, + { pauseLeft + pauseWidth - pauseStroke, pauseTop + pauseHeight }, + }; + QPointF pathRightPlay[] = { + { playLeft + (playWidth / 2.), playTop + (playHeight / 4.) }, + { playLeft + playWidth, playTop + (playHeight / 2.) }, + { playLeft + playWidth, playTop + (playHeight / 2.) }, + { playLeft + (playWidth / 2.), playTop + (3 * playHeight / 4.) }, + }; + p.fillPath(interpolatePaths(pathRightPause, pathRightPlay, showPause), icon); + } + p.setRenderHint(QPainter::HighQualityAntialiasing, false); +} + } // namespace Player } // namespace Media diff --git a/Telegram/SourceFiles/media/player/media_player_button.h b/Telegram/SourceFiles/media/player/media_player_button.h index 948c760127..e07539aa0b 100644 --- a/Telegram/SourceFiles/media/player/media_player_button.h +++ b/Telegram/SourceFiles/media/player/media_player_button.h @@ -20,8 +20,31 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org */ #pragma once +#include "ui/button.h" + namespace Media { namespace Player { +class TitleButton : public Button { +public: + TitleButton(QWidget *parent); + + void setShowPause(bool showPause); + void finishIconTransform(); + +protected: + void paintEvent(QPaintEvent *e) override; + + void onStateChanged(int oldState, ButtonStateChangeSource source) override; + +private: + void paintIcon(Painter &p); + + bool _showPause = true; + FloatAnimation _iconTransformToPause; + ColorAnimation _iconFg; + +}; + } // namespace Clip } // namespace Media diff --git a/Telegram/SourceFiles/platform/win/main_window_win.cpp b/Telegram/SourceFiles/platform/win/main_window_win.cpp index 789d6fd791..17d745abf2 100644 --- a/Telegram/SourceFiles/platform/win/main_window_win.cpp +++ b/Telegram/SourceFiles/platform/win/main_window_win.cpp @@ -666,7 +666,7 @@ void MainWindow::psRefreshTaskbarIcon() { w->setWindowFlags(::operator|(Qt::Tool, Qt::FramelessWindowHint)); w->setGeometry(x() + 1, y() + 1, 1, 1); QPalette p(w->palette()); - p.setColor(QPalette::Background, st::titleBG->c); + p.setColor(QPalette::Background, st::titleBg->c); QWindow *wnd = w->windowHandle(); w->setPalette(p); w->show(); diff --git a/Telegram/SourceFiles/shortcuts.cpp b/Telegram/SourceFiles/shortcuts.cpp index b8f45cbd81..23de564016 100644 --- a/Telegram/SourceFiles/shortcuts.cpp +++ b/Telegram/SourceFiles/shortcuts.cpp @@ -28,7 +28,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org namespace ShortcutCommands { -typedef bool(*Handler)(); +using Handler = bool(*)(); bool lock_telegram() { if (auto w = App::wnd()) { diff --git a/Telegram/SourceFiles/title.cpp b/Telegram/SourceFiles/title.cpp index f75eb8d58b..05adda84b3 100644 --- a/Telegram/SourceFiles/title.cpp +++ b/Telegram/SourceFiles/title.cpp @@ -27,6 +27,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "application.h" #include "boxes/contactsbox.h" #include "boxes/aboutbox.h" +#include "media/player/media_player_button.h" TitleHider::TitleHider(QWidget *parent) : QWidget(parent), _level(0) { } @@ -56,6 +57,7 @@ TitleWidget::TitleWidget(MainWindow *window) : TWidget(window) , _settings(this, lang(lng_menu_settings), st::titleTextButton) , _contacts(this, lang(lng_menu_contacts), st::titleTextButton) , _about(this, lang(lng_menu_about), st::titleTextButton) +, _player(this) , _lock(this, window) , _update(this, window, lang(lng_menu_update)) , _minimize(this, window) @@ -101,7 +103,7 @@ TitleWidget::TitleWidget(MainWindow *window) : TWidget(window) void TitleWidget::paintEvent(QPaintEvent *e) { Painter p(this); - p.fillRect(QRect(0, 0, width(), st::titleHeight), st::titleBG->b); + p.fillRect(rect(), st::titleBg); if (!_cancel.isHidden()) { p.setPen(st::titleTextButton.color->p); p.setFont(st::titleTextButton.font->f); @@ -189,6 +191,10 @@ void TitleWidget::resizeEvent(QResizeEvent *e) { p.setX(p.x() - _lock.width()); _lock.move(p); } + if (_player) { + p.setX(p.x() - _player->width()); + _player->move(p); + } _settings.move(st::titleMenuOffset, 0); if (MTP::authedId() && _cancel.isHidden() && !App::passcoded()) { @@ -368,6 +374,7 @@ HitTestType TitleWidget::hitTest(const QPoint &p) { if (x >= st::titleIconPos.x() && y >= st::titleIconPos.y() && x < st::titleIconPos.x() + st::titleIconImg.pxWidth() && y < st::titleIconPos.y() + st::titleIconImg.pxHeight()) { return HitTestIcon; } else if (false + || (_player && _player->geometry().contains(p)) || (_lock.hitTest(p - _lock.geometry().topLeft()) == HitTestSysButton && _lock.isVisible()) || (_update.hitTest(p - _update.geometry().topLeft()) == HitTestSysButton && _update.isVisible()) || (_minimize.hitTest(p - _minimize.geometry().topLeft()) == HitTestSysButton) diff --git a/Telegram/SourceFiles/title.h b/Telegram/SourceFiles/title.h index 7d6f4f760f..72ffb02207 100644 --- a/Telegram/SourceFiles/title.h +++ b/Telegram/SourceFiles/title.h @@ -24,6 +24,11 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "sysbuttons.h" class MainWindow; +namespace Media { +namespace Player { +class TitleButton; +} // namespace Player +} // namespace Media class TitleHider : public QWidget { public: @@ -89,6 +94,7 @@ private: FlatButton _cancel, _settings, _contacts, _about; + ChildWidget _player = { nullptr }; LockBtn _lock; UpdateBtn _update; MinimizeBtn _minimize;