361 lines
		
	
	
	
		
			11 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			361 lines
		
	
	
	
		
			11 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/*
 | 
						|
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.
 | 
						|
 | 
						|
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
 | 
						|
Copyright (c) 2014 John Preston, https://desktop.telegram.org
 | 
						|
*/
 | 
						|
#include "stdafx.h"
 | 
						|
#include "lang.h"
 | 
						|
#include "style.h"
 | 
						|
 | 
						|
#include "title.h"
 | 
						|
#include "mainwidget.h"
 | 
						|
#include "window.h"
 | 
						|
#include "application.h"
 | 
						|
#include "boxes/contactsbox.h"
 | 
						|
#include "boxes/aboutbox.h"
 | 
						|
 | 
						|
TitleHider::TitleHider(QWidget *parent) : QWidget(parent), _level(0) {
 | 
						|
}
 | 
						|
 | 
						|
void TitleHider::paintEvent(QPaintEvent *e) {
 | 
						|
	QPainter p(this);
 | 
						|
	p.setOpacity(_level * st::layerAlpha);
 | 
						|
	p.fillRect(App::main()->dlgsWidth() - st::dlgShadow, 0, width() + st::dlgShadow - App::main()->dlgsWidth(), height(), st::layerBG->b);
 | 
						|
}
 | 
						|
 | 
						|
void TitleHider::mousePressEvent(QMouseEvent *e) {
 | 
						|
	if (e->button() == Qt::LeftButton) {
 | 
						|
		emit static_cast<TitleWidget*>(parentWidget())->hiderClicked();
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void TitleHider::setLevel(float64 level) {
 | 
						|
	_level = level;
 | 
						|
	update();
 | 
						|
}
 | 
						|
 | 
						|
TitleWidget::TitleWidget(Window *window)
 | 
						|
	: QWidget(window)
 | 
						|
	, wnd(window)
 | 
						|
    , hideLevel(0)
 | 
						|
    , hider(0)
 | 
						|
	, _back(this, st::titleBackButton, lang(lng_menu_back))
 | 
						|
	, _cancel(this, lang(lng_cancel), st::titleTextButton)
 | 
						|
	, _settings(this, lang(lng_menu_settings), st::titleTextButton)
 | 
						|
	, _contacts(this, lang(lng_menu_contacts), st::titleTextButton)
 | 
						|
	, _about(this, lang(lng_menu_about), st::titleTextButton)
 | 
						|
	, _update(this, window, lang(lng_menu_update))
 | 
						|
	, _minimize(this, window)
 | 
						|
	, _maximize(this, window)
 | 
						|
	, _restore(this, window)
 | 
						|
	, _close(this, window)
 | 
						|
    , lastMaximized(!(window->windowState() & Qt::WindowMaximized))
 | 
						|
{
 | 
						|
	setGeometry(0, 0, wnd->width(), st::titleHeight);
 | 
						|
	_update.hide();
 | 
						|
	if (App::app()->updatingState() == Application::UpdatingReady) {
 | 
						|
		showUpdateBtn();
 | 
						|
	}
 | 
						|
	stateChanged();
 | 
						|
 | 
						|
	connect(&_back, SIGNAL(clicked()), window, SLOT(hideSettings()));
 | 
						|
	connect(&_cancel, SIGNAL(clicked()), this, SIGNAL(hiderClicked()));
 | 
						|
	connect(&_settings, SIGNAL(clicked()), window, SLOT(showSettings()));
 | 
						|
	connect(&_contacts, SIGNAL(clicked()), this, SLOT(onContacts()));
 | 
						|
	connect(&_about, SIGNAL(clicked()), this, SLOT(onAbout()));
 | 
						|
	connect(wnd->windowHandle(), SIGNAL(windowStateChanged(Qt::WindowState)), this, SLOT(stateChanged(Qt::WindowState)));
 | 
						|
	connect(App::app(), SIGNAL(updateReady()), this, SLOT(showUpdateBtn()));
 | 
						|
        
 | 
						|
    if (cPlatform() != dbipWindows) {
 | 
						|
        _minimize.hide();
 | 
						|
        _maximize.hide();
 | 
						|
        _restore.hide();
 | 
						|
        _close.hide();
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
void TitleWidget::paintEvent(QPaintEvent *e) {
 | 
						|
	QPainter p(this);
 | 
						|
 | 
						|
	p.fillRect(QRect(0, 0, width(), st::titleHeight), st::titleBG->b);
 | 
						|
	if (!_cancel.isHidden()) {
 | 
						|
		p.setPen(st::titleTextButton.color->p);
 | 
						|
		p.setFont(st::titleTextButton.font->f);
 | 
						|
		p.drawText(st::titleMenuOffset - st::titleTextButton.width / 2, st::titleTextButton.textTop + st::titleTextButton.font->ascent, lang(lng_forward_choose));
 | 
						|
	}
 | 
						|
	p.drawPixmap(st::titleIconPos, App::sprite(), st::titleIconImg);
 | 
						|
	if (!cWideMode() && !_counter.isNull() && App::main()) {
 | 
						|
		p.drawPixmap(st::titleIconPos.x() + st::titleIconImg.pxWidth() - (_counter.width() / cIntRetinaFactor()), st::titleIconPos.y() + st::titleIconImg.pxHeight() - (_counter.height() / cIntRetinaFactor()), _counter);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
bool TitleWidget::animStep(float64 ms) {
 | 
						|
	float64 phase = sin(M_PI_2 * (ms / st::updateBlinkDuration));
 | 
						|
	if (phase < 0) phase = -phase;
 | 
						|
	_update.setOverLevel(phase);
 | 
						|
	return true;
 | 
						|
}
 | 
						|
 | 
						|
void TitleWidget::setHideLevel(float64 level) {
 | 
						|
	if (level != hideLevel) {
 | 
						|
		hideLevel = level;
 | 
						|
		if (hideLevel) {
 | 
						|
			if (!hider) {
 | 
						|
				hider = new TitleHider(this);
 | 
						|
				hider->move(0, 0);
 | 
						|
				hider->resize(size());
 | 
						|
				if (cWideMode()) {
 | 
						|
					hider->show();
 | 
						|
				} else {
 | 
						|
					hider->hide();
 | 
						|
				}
 | 
						|
			}
 | 
						|
			hider->setLevel(hideLevel);
 | 
						|
		} else {
 | 
						|
			if (hider) hider->deleteLater();
 | 
						|
			hider = 0;
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void TitleWidget::onContacts() {
 | 
						|
	if (App::wnd() && App::wnd()->isHidden()) App::wnd()->showFromTray();
 | 
						|
 | 
						|
	if (!App::self()) return;
 | 
						|
	App::wnd()->showLayer(new ContactsBox());
 | 
						|
}
 | 
						|
 | 
						|
void TitleWidget::onAbout() {
 | 
						|
	if (App::wnd() && App::wnd()->isHidden()) App::wnd()->showFromTray();
 | 
						|
	App::wnd()->showLayer(new AboutBox());
 | 
						|
}
 | 
						|
 | 
						|
TitleWidget::~TitleWidget() {
 | 
						|
	delete hider;
 | 
						|
	hider = 0;
 | 
						|
}
 | 
						|
 | 
						|
void TitleWidget::resizeEvent(QResizeEvent *e) {
 | 
						|
	QPoint p(width() - ((cPlatform() == dbipWindows && lastMaximized) ? 0 : st::sysBtnDelta), 0);
 | 
						|
 | 
						|
	if (!_update.isHidden()) {
 | 
						|
		p.setX(p.x() - _update.width());
 | 
						|
		_update.move(p);
 | 
						|
		p.setX(p.x() + _update.width());
 | 
						|
	}
 | 
						|
	_cancel.move(p.x() - _cancel.width(), 0);
 | 
						|
 | 
						|
    if (cPlatform() == dbipWindows) {
 | 
						|
        p.setX(p.x() - _close.width());
 | 
						|
        _close.move(p);
 | 
						|
        
 | 
						|
        p.setX(p.x() - _maximize.width());
 | 
						|
        _restore.move(p); _maximize.move(p);
 | 
						|
        
 | 
						|
        p.setX(p.x() - _minimize.width());
 | 
						|
        _minimize.move(p);
 | 
						|
    }
 | 
						|
    
 | 
						|
	_settings.move(st::titleMenuOffset, 0);
 | 
						|
	_back.move(st::titleMenuOffset, 0);
 | 
						|
	_back.resize((_minimize.isHidden() ? (_update.isHidden() ? width() : _update.x()) : _minimize.x()) - st::titleMenuOffset, _back.height());
 | 
						|
	if (MTP::authedId() && _back.isHidden() && _cancel.isHidden()) {
 | 
						|
		_contacts.show();
 | 
						|
		_contacts.move(_settings.x() + _settings.width(), 0);
 | 
						|
		_about.move(_contacts.x() + _contacts.width(), 0);
 | 
						|
	} else {
 | 
						|
		_contacts.hide();
 | 
						|
		if (!MTP::authedId()) _about.move(_settings.x() + _settings.width(), 0);
 | 
						|
	}
 | 
						|
 | 
						|
	if (hider) hider->resize(size());
 | 
						|
}
 | 
						|
 | 
						|
void TitleWidget::updateBackButton() {
 | 
						|
	if (!cWideMode() && App::main() && App::main()->selectingPeer()) {
 | 
						|
		_cancel.show();
 | 
						|
		if (!_back.isHidden()) _back.hide();
 | 
						|
		_settings.hide();
 | 
						|
		_contacts.hide();
 | 
						|
		_about.hide();
 | 
						|
	} else {
 | 
						|
		_cancel.hide();
 | 
						|
		bool authed = (MTP::authedId() > 0);
 | 
						|
		if (cWideMode()) {
 | 
						|
			if (!_back.isHidden()) _back.hide();
 | 
						|
			_settings.show();
 | 
						|
			if (authed) _contacts.show();
 | 
						|
			_about.show();
 | 
						|
		} else {
 | 
						|
			bool need = App::wnd()->needBackButton();
 | 
						|
			if (need && _back.isHidden()) {
 | 
						|
				_back.show();
 | 
						|
				_settings.hide();
 | 
						|
				_contacts.hide();
 | 
						|
				_about.hide();
 | 
						|
			} else if (!need && !_back.isHidden()) {
 | 
						|
				_back.hide();
 | 
						|
				_settings.show();
 | 
						|
				if (authed) _contacts.show();
 | 
						|
				_about.show();
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
	showUpdateBtn();
 | 
						|
	update();
 | 
						|
}
 | 
						|
 | 
						|
void TitleWidget::updateWideMode() {
 | 
						|
	updateBackButton();
 | 
						|
	if (!cWideMode()) {
 | 
						|
		updateCounter();
 | 
						|
	}
 | 
						|
	if (hider) {
 | 
						|
		if (cWideMode()) {
 | 
						|
			hider->show();
 | 
						|
		} else {
 | 
						|
			hider->hide();
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void TitleWidget::updateCounter() {
 | 
						|
	if (cWideMode() || !MTP::authedId()) return;
 | 
						|
 | 
						|
	int32 counter = App::histories().unreadFull;
 | 
						|
	style::color bg = (App::histories().unreadMuted < counter) ? st::counterBG : st::counterMuteBG;
 | 
						|
	
 | 
						|
	if (counter > 0) {
 | 
						|
		int32 size = -16;
 | 
						|
		switch (cScale()) {
 | 
						|
		case dbisOneAndQuarter: size = -20; break;
 | 
						|
		case dbisOneAndHalf: size = -24; break;
 | 
						|
		case dbisTwo: size = -32; break;
 | 
						|
		}
 | 
						|
		_counter = QPixmap::fromImage(App::wnd()->iconWithCounter(size, counter, bg, false));
 | 
						|
		_counter.setDevicePixelRatio(cRetinaFactor());
 | 
						|
		update(QRect(st::titleIconPos, st::titleIconImg.pxSize()));
 | 
						|
	} else {
 | 
						|
		if (!_counter.isNull()) {
 | 
						|
			_counter = QPixmap();
 | 
						|
			update(QRect(st::titleIconPos, st::titleIconImg.pxSize()));
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void TitleWidget::mousePressEvent(QMouseEvent *e) {
 | 
						|
	if (wnd->psHandleTitle()) return;
 | 
						|
	if (e->buttons() & Qt::LeftButton) {
 | 
						|
		wnd->wStartDrag(e);
 | 
						|
		e->accept();
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void TitleWidget::mouseDoubleClickEvent(QMouseEvent *e) {
 | 
						|
	if (wnd->psHandleTitle()) return;
 | 
						|
	Qt::WindowStates s(wnd->windowState());
 | 
						|
	if (s.testFlag(Qt::WindowMaximized)) {
 | 
						|
		wnd->setWindowState(s & ~Qt::WindowMaximized);
 | 
						|
	} else {
 | 
						|
		wnd->setWindowState(s | Qt::WindowMaximized);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void TitleWidget::stateChanged(Qt::WindowState state) {
 | 
						|
	if (state == Qt::WindowMinimized) return;
 | 
						|
	maximizedChanged(state == Qt::WindowMaximized);
 | 
						|
}
 | 
						|
 | 
						|
void TitleWidget::showUpdateBtn() {
 | 
						|
	if (!cWideMode() && App::main() && App::main()->selectingPeer()) {
 | 
						|
		_cancel.show();
 | 
						|
		_update.hide();
 | 
						|
		_minimize.hide();
 | 
						|
		_restore.hide();
 | 
						|
		_maximize.hide();
 | 
						|
		_close.hide();
 | 
						|
		return;
 | 
						|
	}
 | 
						|
	bool updateReady = App::app()->updatingState() == Application::UpdatingReady;
 | 
						|
	if (updateReady || cEvalScale(cConfigScale()) != cEvalScale(cRealScale())) {
 | 
						|
		_update.setText(lang(updateReady ? lng_menu_update : lng_menu_restart));
 | 
						|
		_update.show();
 | 
						|
		resizeEvent(0);
 | 
						|
		_minimize.hide();
 | 
						|
		_restore.hide();
 | 
						|
		_maximize.hide();
 | 
						|
		_close.hide();
 | 
						|
		anim::start(this);
 | 
						|
	} else {
 | 
						|
		_update.hide();
 | 
						|
		if (cPlatform() == dbipWindows) {
 | 
						|
			_minimize.show();
 | 
						|
			maximizedChanged(wnd->windowState().testFlag(Qt::WindowMaximized), true);
 | 
						|
			_close.show();
 | 
						|
		}
 | 
						|
		anim::stop(this);
 | 
						|
	}
 | 
						|
	resizeEvent(0);
 | 
						|
	update();
 | 
						|
}
 | 
						|
 | 
						|
void TitleWidget::maximizedChanged(bool maximized, bool force) {
 | 
						|
	if (lastMaximized == maximized && !force) return;
 | 
						|
 | 
						|
	lastMaximized = maximized;
 | 
						|
 | 
						|
    if (cPlatform() != dbipWindows || !_update.isHidden()) return;
 | 
						|
	if (maximized) {
 | 
						|
		_maximize.clearState();
 | 
						|
	} else {
 | 
						|
		_restore.clearState();
 | 
						|
	}
 | 
						|
 | 
						|
	_maximize.setVisible(!maximized);
 | 
						|
	_restore.setVisible(maximized);
 | 
						|
 | 
						|
	resizeEvent(0);
 | 
						|
}
 | 
						|
 | 
						|
HitTestType TitleWidget::hitTest(const QPoint &p) {
 | 
						|
	if (App::wnd() && App::wnd()->layerShown()) return HitTestNone;
 | 
						|
 | 
						|
	int x(p.x()), y(p.y()), w(width()), h(height() - st::titleShadow);
 | 
						|
	if (cWideMode() && hider && x >= App::main()->dlgsWidth()) return HitTestNone;
 | 
						|
 | 
						|
	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
 | 
						|
        || (_update.hitTest(p - _update.geometry().topLeft()) == HitTestSysButton && _update.isVisible())
 | 
						|
		|| (_minimize.hitTest(p - _minimize.geometry().topLeft()) == HitTestSysButton)
 | 
						|
		|| (_maximize.hitTest(p - _maximize.geometry().topLeft()) == HitTestSysButton)
 | 
						|
		|| (_restore.hitTest(p - _restore.geometry().topLeft()) == HitTestSysButton)
 | 
						|
		|| (_close.hitTest(p - _close.geometry().topLeft()) == HitTestSysButton)
 | 
						|
	) {
 | 
						|
		return HitTestSysButton;
 | 
						|
	} else if (x >= 0 && x < w && y >= 0 && y < h) {
 | 
						|
		if (false
 | 
						|
			|| (!_back.isHidden() && _back.geometry().contains(x, y))
 | 
						|
			|| (!_cancel.isHidden() && _cancel.geometry().contains(x, y))
 | 
						|
			|| (!_settings.isHidden() && _settings.geometry().contains(x, y))
 | 
						|
			|| (!_contacts.isHidden() && _contacts.geometry().contains(x, y))
 | 
						|
			|| (!_about.isHidden() && _about.geometry().contains(x, y))
 | 
						|
		) {
 | 
						|
			return HitTestClient;
 | 
						|
		}
 | 
						|
		return HitTestCaption;
 | 
						|
	}
 | 
						|
	return HitTestNone;
 | 
						|
}
 |