Added initial implementation of loading element effect.
This commit is contained in:
		
							parent
							
								
									cf54d9fb12
								
							
						
					
					
						commit
						f16d30de37
					
				
					 3 changed files with 171 additions and 0 deletions
				
			
		
							
								
								
									
										142
									
								
								Telegram/SourceFiles/ui/effects/loading_element.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										142
									
								
								Telegram/SourceFiles/ui/effects/loading_element.cpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,142 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					This file is part of Telegram Desktop,
 | 
				
			||||||
 | 
					the official desktop application for the Telegram messaging service.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					For license and copyright information please follow this link:
 | 
				
			||||||
 | 
					https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					#include "ui/effects/loading_element.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "ui/effects/glare.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "base/object_ptr.h"
 | 
				
			||||||
 | 
					#include "styles/palette.h"
 | 
				
			||||||
 | 
					#include "styles/style_basic.h"
 | 
				
			||||||
 | 
					#include "styles/style_widgets.h"
 | 
				
			||||||
 | 
					#include "base/random.h"
 | 
				
			||||||
 | 
					#include "ui/painter.h"
 | 
				
			||||||
 | 
					#include "ui/rp_widget.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Ui {
 | 
				
			||||||
 | 
					namespace {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class LoadingElement {
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
						LoadingElement() = default;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						[[nodiscard]] virtual int height() const = 0;
 | 
				
			||||||
 | 
						virtual void paint(QPainter &p, int width) = 0;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class LoadingText final : public LoadingElement {
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
						LoadingText(const style::FlatLabel &st);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						[[nodiscard]] int height() const override;
 | 
				
			||||||
 | 
						void paint(QPainter &p, int width) override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
						const style::FlatLabel &_st;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					LoadingText::LoadingText(const style::FlatLabel &st) : _st(st) {
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int LoadingText::height() const {
 | 
				
			||||||
 | 
						return _st.style.lineHeight;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void LoadingText::paint(QPainter &p, int width) {
 | 
				
			||||||
 | 
						auto hq = PainterHighQualityEnabler(p);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						p.setPen(Qt::NoPen);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						p.setBrush(st::dialogsDateFg);
 | 
				
			||||||
 | 
						const auto h = _st.style.font->ascent;
 | 
				
			||||||
 | 
						p.drawRoundedRect(
 | 
				
			||||||
 | 
							0,
 | 
				
			||||||
 | 
							height() - h - (height() - _st.style.font->height),
 | 
				
			||||||
 | 
							width,
 | 
				
			||||||
 | 
							h,
 | 
				
			||||||
 | 
							h / 2,
 | 
				
			||||||
 | 
							h / 2);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					object_ptr<Ui::RpWidget> CreateLoadingTextWidget(
 | 
				
			||||||
 | 
							not_null<Ui::RpWidget*> parent,
 | 
				
			||||||
 | 
							const style::FlatLabel &st,
 | 
				
			||||||
 | 
							int lines,
 | 
				
			||||||
 | 
							rpl::producer<bool> rtl) {
 | 
				
			||||||
 | 
						auto widget = object_ptr<Ui::RpWidget>(parent);
 | 
				
			||||||
 | 
						const auto raw = widget.data();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct State {
 | 
				
			||||||
 | 
							GlareEffect glare;
 | 
				
			||||||
 | 
							Ui::Animations::Simple animation;
 | 
				
			||||||
 | 
							int lastLineWidth = 0;
 | 
				
			||||||
 | 
							rpl::variable<bool> rtl;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const auto state = widget->lifetime().make_state<State>();
 | 
				
			||||||
 | 
						state->rtl = std::move(rtl);
 | 
				
			||||||
 | 
						state->rtl.value(
 | 
				
			||||||
 | 
						) | rpl::start_with_next([=] { raw->update(); }, raw->lifetime());
 | 
				
			||||||
 | 
						raw->resize(raw->width(), LoadingText(st).height() * lines);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const auto draw = [=](QPainter &p) {
 | 
				
			||||||
 | 
							auto loading = LoadingText(st);
 | 
				
			||||||
 | 
							const auto countRows = lines;
 | 
				
			||||||
 | 
							for (auto i = 0; i < countRows; i++) {
 | 
				
			||||||
 | 
								const auto w = (i == countRows - 1)
 | 
				
			||||||
 | 
									? state->lastLineWidth
 | 
				
			||||||
 | 
									: raw->width();
 | 
				
			||||||
 | 
								loading.paint(p, w);
 | 
				
			||||||
 | 
								p.translate(0, loading.height());
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							p.resetTransform();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							auto &_glare = state->glare;
 | 
				
			||||||
 | 
							if (_glare.glare.birthTime) {
 | 
				
			||||||
 | 
								const auto progress = _glare.progress(crl::now());
 | 
				
			||||||
 | 
								const auto x = (-_glare.width)
 | 
				
			||||||
 | 
									+ (raw->width() + _glare.width * 2) * progress;
 | 
				
			||||||
 | 
								const auto h = raw->height();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								p.drawTiledPixmap(x, 0, _glare.width, h, _glare.pixmap, 0, 0);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						widget->paintRequest(
 | 
				
			||||||
 | 
						) | rpl::start_with_next([=](const QRect &r) {
 | 
				
			||||||
 | 
							auto p = QPainter(raw);
 | 
				
			||||||
 | 
							if (state->rtl.current()) {
 | 
				
			||||||
 | 
								const auto r = raw->rect();
 | 
				
			||||||
 | 
								p.translate(r.center());
 | 
				
			||||||
 | 
								p.scale(-1., 1.);
 | 
				
			||||||
 | 
								p.translate(-r.center());
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							draw(p);
 | 
				
			||||||
 | 
						}, widget->lifetime());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						constexpr auto kTimeout = crl::time(1000);
 | 
				
			||||||
 | 
						constexpr auto kDuration = crl::time(1000);
 | 
				
			||||||
 | 
						widget->widthValue(
 | 
				
			||||||
 | 
						) | rpl::start_with_next([=](int width) {
 | 
				
			||||||
 | 
							state->glare.width = width;
 | 
				
			||||||
 | 
							state->glare.validate(
 | 
				
			||||||
 | 
								st::dialogsBg->c,
 | 
				
			||||||
 | 
								[=] { raw->update(); },
 | 
				
			||||||
 | 
								kTimeout,
 | 
				
			||||||
 | 
								kDuration);
 | 
				
			||||||
 | 
							if (width) {
 | 
				
			||||||
 | 
								state->lastLineWidth = (width / 4) + base::RandomIndex(width / 2);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}, widget->lifetime());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return widget;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace Ui
 | 
				
			||||||
							
								
								
									
										27
									
								
								Telegram/SourceFiles/ui/effects/loading_element.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								Telegram/SourceFiles/ui/effects/loading_element.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,27 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					This file is part of Telegram Desktop,
 | 
				
			||||||
 | 
					the official desktop application for the Telegram messaging service.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					For license and copyright information please follow this link:
 | 
				
			||||||
 | 
					https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template <typename Object>
 | 
				
			||||||
 | 
					class object_ptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace style {
 | 
				
			||||||
 | 
					struct FlatLabel;
 | 
				
			||||||
 | 
					} // namespace style
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Ui {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class RpWidget;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					object_ptr<Ui::RpWidget> CreateLoadingTextWidget(
 | 
				
			||||||
 | 
						not_null<Ui::RpWidget*> parent,
 | 
				
			||||||
 | 
						const style::FlatLabel &st,
 | 
				
			||||||
 | 
						int lines,
 | 
				
			||||||
 | 
						rpl::producer<bool> rtl);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace Ui
 | 
				
			||||||
| 
						 | 
					@ -236,6 +236,8 @@ PRIVATE
 | 
				
			||||||
    ui/effects/fireworks_animation.h
 | 
					    ui/effects/fireworks_animation.h
 | 
				
			||||||
    ui/effects/glare.cpp
 | 
					    ui/effects/glare.cpp
 | 
				
			||||||
    ui/effects/glare.h
 | 
					    ui/effects/glare.h
 | 
				
			||||||
 | 
					    ui/effects/loading_element.cpp
 | 
				
			||||||
 | 
					    ui/effects/loading_element.h
 | 
				
			||||||
    ui/effects/premium_graphics.cpp
 | 
					    ui/effects/premium_graphics.cpp
 | 
				
			||||||
    ui/effects/premium_graphics.h
 | 
					    ui/effects/premium_graphics.h
 | 
				
			||||||
    ui/effects/premium_stars.cpp
 | 
					    ui/effects/premium_stars.cpp
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		
		Reference in a new issue