Add drop shadow to emoji panel

- Minor refactoring
This commit is contained in:
Konstantinos Sideris 2017-05-31 02:35:28 +03:00
parent 83cdd79e08
commit 5197f8a886
4 changed files with 244 additions and 139 deletions

View file

@ -17,9 +17,7 @@
#pragma once #pragma once
#include <QFrame>
#include <QGraphicsOpacityEffect> #include <QGraphicsOpacityEffect>
#include <QParallelAnimationGroup>
#include <QPropertyAnimation> #include <QPropertyAnimation>
#include <QScrollArea> #include <QScrollArea>
#include <QWidget> #include <QWidget>
@ -27,7 +25,7 @@
#include "EmojiCategory.h" #include "EmojiCategory.h"
#include "EmojiProvider.h" #include "EmojiProvider.h"
class EmojiPanel : public QFrame class EmojiPanel : public QWidget
{ {
Q_OBJECT Q_OBJECT
@ -43,25 +41,24 @@ signals:
protected: protected:
void leaveEvent(QEvent *event); void leaveEvent(QEvent *event);
void paintEvent(QPaintEvent *event);
private: private:
void showEmojiCategory(const EmojiCategory *category); void showEmojiCategory(const EmojiCategory *category);
QPropertyAnimation *opacity_anim_; QPropertyAnimation *animation_;
QPropertyAnimation *size_anim_;
QGraphicsOpacityEffect *opacity_; QGraphicsOpacityEffect *opacity_;
QParallelAnimationGroup *animation_;
EmojiProvider emoji_provider_; EmojiProvider emoji_provider_;
QScrollArea *scroll_area_; QScrollArea *scrollArea_;
int shadowMargin_;
// Panel dimensions. // Panel dimensions.
const int WIDTH = 370; int width_;
const int HEIGHT = 350; int height_;
const int ANIMATION_DURATION = 100; int animationDuration_;
const int ANIMATION_OFFSET = 50; int categoryIconSize_;
const int category_icon_size_ = 20;
}; };

100
include/ui/DropShadow.h Normal file
View file

@ -0,0 +1,100 @@
#pragma once
#include <QColor>
#include <QLinearGradient>
#include <QPainter>
class DropShadow
{
public:
static void draw(QPainter &painter,
qint16 margin,
qreal radius,
QColor start,
QColor end,
qreal startPosition,
qreal endPosition0,
qreal endPosition1,
qreal width,
qreal height)
{
painter.setPen(Qt::NoPen);
QLinearGradient gradient;
gradient.setColorAt(startPosition, start);
gradient.setColorAt(endPosition0, end);
// Right
QPointF right0(width - margin, height / 2);
QPointF right1(width, height / 2);
gradient.setStart(right0);
gradient.setFinalStop(right1);
painter.setBrush(QBrush(gradient));
painter.drawRoundRect(QRectF(QPointF(width - margin * radius, margin), QPointF(width, height - margin)), 0.0, 0.0);
// Left
QPointF left0(margin, height / 2);
QPointF left1(0, height / 2);
gradient.setStart(left0);
gradient.setFinalStop(left1);
painter.setBrush(QBrush(gradient));
painter.drawRoundRect(QRectF(QPointF(margin * radius, margin), QPointF(0, height - margin)), 0.0, 0.0);
// Top
QPointF top0(width / 2, margin);
QPointF top1(width / 2, 0);
gradient.setStart(top0);
gradient.setFinalStop(top1);
painter.setBrush(QBrush(gradient));
painter.drawRoundRect(QRectF(QPointF(width - margin, 0), QPointF(margin, margin)), 0.0, 0.0);
// Bottom
QPointF bottom0(width / 2, height - margin);
QPointF bottom1(width / 2, height);
gradient.setStart(bottom0);
gradient.setFinalStop(bottom1);
painter.setBrush(QBrush(gradient));
painter.drawRoundRect(QRectF(QPointF(margin, height - margin), QPointF(width - margin, height)), 0.0, 0.0);
// BottomRight
QPointF bottomright0(width - margin, height - margin);
QPointF bottomright1(width, height);
gradient.setStart(bottomright0);
gradient.setFinalStop(bottomright1);
gradient.setColorAt(endPosition1, end);
painter.setBrush(QBrush(gradient));
painter.drawRoundRect(QRectF(bottomright0, bottomright1), 0.0, 0.0);
// BottomLeft
QPointF bottomleft0(margin, height - margin);
QPointF bottomleft1(0, height);
gradient.setStart(bottomleft0);
gradient.setFinalStop(bottomleft1);
gradient.setColorAt(endPosition1, end);
painter.setBrush(QBrush(gradient));
painter.drawRoundRect(QRectF(bottomleft0, bottomleft1), 0.0, 0.0);
// TopLeft
QPointF topleft0(margin, margin);
QPointF topleft1(0, 0);
gradient.setStart(topleft0);
gradient.setFinalStop(topleft1);
gradient.setColorAt(endPosition1, end);
painter.setBrush(QBrush(gradient));
painter.drawRoundRect(QRectF(topleft0, topleft1), 0.0, 0.0);
// TopRight
QPointF topright0(width - margin, margin);
QPointF topright1(width, 0);
gradient.setStart(topright0);
gradient.setFinalStop(topright1);
gradient.setColorAt(endPosition1, end);
painter.setBrush(QBrush(gradient));
painter.drawRoundRect(QRectF(topright0, topright1), 0.0, 0.0);
// Widget
painter.setBrush(QBrush("#FFFFFF"));
painter.setRenderHint(QPainter::Antialiasing);
painter.drawRoundRect(QRectF(QPointF(margin, margin), QPointF(width - margin, height - margin)), radius, radius);
}
};

View file

@ -15,20 +15,24 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <QDebug>
#include <QLabel>
#include <QPushButton> #include <QPushButton>
#include <QScrollArea> #include <QScrollArea>
#include <QScrollBar> #include <QScrollBar>
#include <QVBoxLayout> #include <QVBoxLayout>
#include "Avatar.h" #include "Avatar.h"
#include "DropShadow.h"
#include "EmojiCategory.h" #include "EmojiCategory.h"
#include "EmojiPanel.h" #include "EmojiPanel.h"
#include "FlatButton.h" #include "FlatButton.h"
EmojiPanel::EmojiPanel(QWidget *parent) EmojiPanel::EmojiPanel(QWidget *parent)
: QFrame(parent) : QWidget(parent)
, shadowMargin_{3}
, width_{370}
, height_{350}
, animationDuration_{100}
, categoryIconSize_{20}
{ {
setStyleSheet( setStyleSheet(
"QWidget {background: #f8fbfe; color: #e8e8e8; border: none;}" "QWidget {background: #f8fbfe; color: #e8e8e8; border: none;}"
@ -40,172 +44,158 @@ EmojiPanel::EmojiPanel(QWidget *parent)
setAttribute(Qt::WA_TranslucentBackground, true); setAttribute(Qt::WA_TranslucentBackground, true);
setWindowFlags(Qt::FramelessWindowHint | Qt::ToolTip); setWindowFlags(Qt::FramelessWindowHint | Qt::ToolTip);
// TODO: Make it MainWindow aware auto mainWidget = new QWidget(this);
auto main_frame_ = new QFrame(this); mainWidget->setMaximumSize(width_, height_);
main_frame_->setMaximumSize(WIDTH, HEIGHT);
auto top_layout = new QVBoxLayout(this); auto topLayout = new QVBoxLayout(this);
top_layout->addWidget(main_frame_); topLayout->addWidget(mainWidget);
top_layout->setMargin(0); topLayout->setMargin(shadowMargin_);
auto content_layout = new QVBoxLayout(main_frame_); auto contentLayout = new QVBoxLayout(mainWidget);
content_layout->setMargin(0); contentLayout->setMargin(0);
auto emoji_categories = new QFrame(main_frame_); auto emojiCategories = new QFrame(mainWidget);
emoji_categories->setStyleSheet("background-color: #f2f2f2"); emojiCategories->setStyleSheet("background-color: #f2f2f2");
auto categories_layout = new QHBoxLayout(emoji_categories); auto categoriesLayout = new QHBoxLayout(emojiCategories);
categories_layout->setSpacing(6); categoriesLayout->setSpacing(6);
categories_layout->setMargin(5); categoriesLayout->setMargin(5);
auto people_category = new FlatButton(emoji_categories); auto peopleCategory = new FlatButton(emojiCategories);
people_category->setIcon(QIcon(":/icons/icons/emoji-categories/people.png")); peopleCategory->setIcon(QIcon(":/icons/icons/emoji-categories/people.png"));
people_category->setIconSize(QSize(category_icon_size_, category_icon_size_)); peopleCategory->setIconSize(QSize(categoryIconSize_, categoryIconSize_));
people_category->setForegroundColor("gray"); peopleCategory->setForegroundColor("gray");
auto nature_category = new FlatButton(emoji_categories); auto natureCategory_ = new FlatButton(emojiCategories);
nature_category->setIcon(QIcon(":/icons/icons/emoji-categories/nature.png")); natureCategory_->setIcon(QIcon(":/icons/icons/emoji-categories/nature.png"));
nature_category->setIconSize(QSize(category_icon_size_, category_icon_size_)); natureCategory_->setIconSize(QSize(categoryIconSize_, categoryIconSize_));
nature_category->setForegroundColor("gray"); natureCategory_->setForegroundColor("gray");
auto food_category = new FlatButton(emoji_categories); auto foodCategory_ = new FlatButton(emojiCategories);
food_category->setIcon(QIcon(":/icons/icons/emoji-categories/foods.png")); foodCategory_->setIcon(QIcon(":/icons/icons/emoji-categories/foods.png"));
food_category->setIconSize(QSize(category_icon_size_, category_icon_size_)); foodCategory_->setIconSize(QSize(categoryIconSize_, categoryIconSize_));
food_category->setForegroundColor("gray"); foodCategory_->setForegroundColor("gray");
auto activity_category = new FlatButton(emoji_categories); auto activityCategory = new FlatButton(emojiCategories);
activity_category->setIcon(QIcon(":/icons/icons/emoji-categories/activity.png")); activityCategory->setIcon(QIcon(":/icons/icons/emoji-categories/activity.png"));
activity_category->setIconSize(QSize(category_icon_size_, category_icon_size_)); activityCategory->setIconSize(QSize(categoryIconSize_, categoryIconSize_));
activity_category->setForegroundColor("gray"); activityCategory->setForegroundColor("gray");
auto travel_category = new FlatButton(emoji_categories); auto travelCategory = new FlatButton(emojiCategories);
travel_category->setIcon(QIcon(":/icons/icons/emoji-categories/travel.png")); travelCategory->setIcon(QIcon(":/icons/icons/emoji-categories/travel.png"));
travel_category->setIconSize(QSize(category_icon_size_, category_icon_size_)); travelCategory->setIconSize(QSize(categoryIconSize_, categoryIconSize_));
travel_category->setForegroundColor("gray"); travelCategory->setForegroundColor("gray");
auto objects_category = new FlatButton(emoji_categories); auto objectsCategory = new FlatButton(emojiCategories);
objects_category->setIcon(QIcon(":/icons/icons/emoji-categories/objects.png")); objectsCategory->setIcon(QIcon(":/icons/icons/emoji-categories/objects.png"));
objects_category->setIconSize(QSize(category_icon_size_, category_icon_size_)); objectsCategory->setIconSize(QSize(categoryIconSize_, categoryIconSize_));
objects_category->setForegroundColor("gray"); objectsCategory->setForegroundColor("gray");
auto symbols_category = new FlatButton(emoji_categories); auto symbolsCategory = new FlatButton(emojiCategories);
symbols_category->setIcon(QIcon(":/icons/icons/emoji-categories/symbols.png")); symbolsCategory->setIcon(QIcon(":/icons/icons/emoji-categories/symbols.png"));
symbols_category->setIconSize(QSize(category_icon_size_, category_icon_size_)); symbolsCategory->setIconSize(QSize(categoryIconSize_, categoryIconSize_));
symbols_category->setForegroundColor("gray"); symbolsCategory->setForegroundColor("gray");
auto flags_category = new FlatButton(emoji_categories); auto flagsCategory = new FlatButton(emojiCategories);
flags_category->setIcon(QIcon(":/icons/icons/emoji-categories/flags.png")); flagsCategory->setIcon(QIcon(":/icons/icons/emoji-categories/flags.png"));
flags_category->setIconSize(QSize(category_icon_size_, category_icon_size_)); flagsCategory->setIconSize(QSize(categoryIconSize_, categoryIconSize_));
flags_category->setForegroundColor("gray"); flagsCategory->setForegroundColor("gray");
categories_layout->addWidget(people_category); categoriesLayout->addWidget(peopleCategory);
categories_layout->addWidget(nature_category); categoriesLayout->addWidget(natureCategory_);
categories_layout->addWidget(food_category); categoriesLayout->addWidget(foodCategory_);
categories_layout->addWidget(activity_category); categoriesLayout->addWidget(activityCategory);
categories_layout->addWidget(travel_category); categoriesLayout->addWidget(travelCategory);
categories_layout->addWidget(objects_category); categoriesLayout->addWidget(objectsCategory);
categories_layout->addWidget(symbols_category); categoriesLayout->addWidget(symbolsCategory);
categories_layout->addWidget(flags_category); categoriesLayout->addWidget(flagsCategory);
scroll_area_ = new QScrollArea(this); scrollArea_ = new QScrollArea(this);
scroll_area_->setWidgetResizable(true); scrollArea_->setWidgetResizable(true);
scroll_area_->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); scrollArea_->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
auto scroll_widget_ = new QWidget(this); auto scrollWidget = new QWidget(this);
auto scroll_layout_ = new QVBoxLayout(scroll_widget_); auto scrollLayout = new QVBoxLayout(scrollWidget);
scroll_layout_->setMargin(0); scrollLayout->setMargin(0);
scroll_area_->setWidget(scroll_widget_); scrollArea_->setWidget(scrollWidget);
auto people_emoji = new EmojiCategory(tr("Smileys & People"), emoji_provider_.people, scroll_widget_); auto peopleEmoji = new EmojiCategory(tr("Smileys & People"), emoji_provider_.people, scrollWidget);
scroll_layout_->addWidget(people_emoji); scrollLayout->addWidget(peopleEmoji);
auto nature_emoji = new EmojiCategory(tr("Animals & Nature"), emoji_provider_.nature, scroll_widget_); auto natureEmoji = new EmojiCategory(tr("Animals & Nature"), emoji_provider_.nature, scrollWidget);
scroll_layout_->addWidget(nature_emoji); scrollLayout->addWidget(natureEmoji);
auto food_emoji = new EmojiCategory(tr("Food & Drink"), emoji_provider_.food, scroll_widget_); auto foodEmoji = new EmojiCategory(tr("Food & Drink"), emoji_provider_.food, scrollWidget);
scroll_layout_->addWidget(food_emoji); scrollLayout->addWidget(foodEmoji);
auto activity_emoji = new EmojiCategory(tr("Activity"), emoji_provider_.activity, scroll_widget_); auto activityEmoji = new EmojiCategory(tr("Activity"), emoji_provider_.activity, scrollWidget);
scroll_layout_->addWidget(activity_emoji); scrollLayout->addWidget(activityEmoji);
auto travel_emoji = new EmojiCategory(tr("Travel & Places"), emoji_provider_.travel, scroll_widget_); auto travelEmoji = new EmojiCategory(tr("Travel & Places"), emoji_provider_.travel, scrollWidget);
scroll_layout_->addWidget(travel_emoji); scrollLayout->addWidget(travelEmoji);
auto objects_emoji = new EmojiCategory(tr("Objects"), emoji_provider_.objects, scroll_widget_); auto objectsEmoji = new EmojiCategory(tr("Objects"), emoji_provider_.objects, scrollWidget);
scroll_layout_->addWidget(objects_emoji); scrollLayout->addWidget(objectsEmoji);
auto symbols_emoji = new EmojiCategory(tr("Symbols"), emoji_provider_.symbols, scroll_widget_); auto symbolsEmoji = new EmojiCategory(tr("Symbols"), emoji_provider_.symbols, scrollWidget);
scroll_layout_->addWidget(symbols_emoji); scrollLayout->addWidget(symbolsEmoji);
auto flags_emoji = new EmojiCategory(tr("Flags"), emoji_provider_.flags, scroll_widget_); auto flagsEmoji = new EmojiCategory(tr("Flags"), emoji_provider_.flags, scrollWidget);
scroll_layout_->addWidget(flags_emoji); scrollLayout->addWidget(flagsEmoji);
content_layout->addStretch(1); contentLayout->addStretch(1);
content_layout->addWidget(scroll_area_); contentLayout->addWidget(scrollArea_);
content_layout->addWidget(emoji_categories); contentLayout->addWidget(emojiCategories);
setLayout(top_layout);
opacity_ = new QGraphicsOpacityEffect(this); opacity_ = new QGraphicsOpacityEffect(this);
opacity_->setOpacity(1.0); opacity_->setOpacity(1.0);
setGraphicsEffect(opacity_); setGraphicsEffect(opacity_);
opacity_anim_ = new QPropertyAnimation(opacity_, "opacity", this); animation_ = new QPropertyAnimation(opacity_, "opacity", this);
opacity_anim_->setDuration(ANIMATION_DURATION); animation_->setDuration(animationDuration_);
opacity_anim_->setStartValue(1); animation_->setStartValue(1);
opacity_anim_->setEndValue(0); animation_->setEndValue(0);
size_anim_ = new QPropertyAnimation(this); connect(peopleEmoji, &EmojiCategory::emojiSelected, this, &EmojiPanel::emojiSelected);
size_anim_->setTargetObject(main_frame_); connect(peopleCategory, &QPushButton::clicked, [this, peopleEmoji]() {
size_anim_->setPropertyName("geometry"); this->showEmojiCategory(peopleEmoji);
size_anim_->setDuration(ANIMATION_DURATION);
size_anim_->setStartValue(QRect(0, 0, WIDTH, HEIGHT));
size_anim_->setEndValue(QRect(ANIMATION_OFFSET, ANIMATION_OFFSET, WIDTH - ANIMATION_OFFSET, HEIGHT - ANIMATION_OFFSET));
animation_ = new QParallelAnimationGroup(this);
animation_->addAnimation(opacity_anim_);
animation_->addAnimation(size_anim_);
connect(people_emoji, &EmojiCategory::emojiSelected, this, &EmojiPanel::emojiSelected);
connect(people_category, &QPushButton::clicked, [this, people_emoji]() {
this->showEmojiCategory(people_emoji);
}); });
connect(nature_emoji, &EmojiCategory::emojiSelected, this, &EmojiPanel::emojiSelected); connect(natureEmoji, &EmojiCategory::emojiSelected, this, &EmojiPanel::emojiSelected);
connect(nature_category, &QPushButton::clicked, [this, nature_emoji]() { connect(natureCategory_, &QPushButton::clicked, [this, natureEmoji]() {
this->showEmojiCategory(nature_emoji); this->showEmojiCategory(natureEmoji);
}); });
connect(food_emoji, &EmojiCategory::emojiSelected, this, &EmojiPanel::emojiSelected); connect(foodEmoji, &EmojiCategory::emojiSelected, this, &EmojiPanel::emojiSelected);
connect(food_category, &QPushButton::clicked, [this, food_emoji]() { connect(foodCategory_, &QPushButton::clicked, [this, foodEmoji]() {
this->showEmojiCategory(food_emoji); this->showEmojiCategory(foodEmoji);
}); });
connect(activity_emoji, &EmojiCategory::emojiSelected, this, &EmojiPanel::emojiSelected); connect(activityEmoji, &EmojiCategory::emojiSelected, this, &EmojiPanel::emojiSelected);
connect(activity_category, &QPushButton::clicked, [this, activity_emoji]() { connect(activityCategory, &QPushButton::clicked, [this, activityEmoji]() {
this->showEmojiCategory(activity_emoji); this->showEmojiCategory(activityEmoji);
}); });
connect(travel_emoji, &EmojiCategory::emojiSelected, this, &EmojiPanel::emojiSelected); connect(travelEmoji, &EmojiCategory::emojiSelected, this, &EmojiPanel::emojiSelected);
connect(travel_category, &QPushButton::clicked, [this, travel_emoji]() { connect(travelCategory, &QPushButton::clicked, [this, travelEmoji]() {
this->showEmojiCategory(travel_emoji); this->showEmojiCategory(travelEmoji);
}); });
connect(objects_emoji, &EmojiCategory::emojiSelected, this, &EmojiPanel::emojiSelected); connect(objectsEmoji, &EmojiCategory::emojiSelected, this, &EmojiPanel::emojiSelected);
connect(objects_category, &QPushButton::clicked, [this, objects_emoji]() { connect(objectsCategory, &QPushButton::clicked, [this, objectsEmoji]() {
this->showEmojiCategory(objects_emoji); this->showEmojiCategory(objectsEmoji);
}); });
connect(symbols_emoji, &EmojiCategory::emojiSelected, this, &EmojiPanel::emojiSelected); connect(symbolsEmoji, &EmojiCategory::emojiSelected, this, &EmojiPanel::emojiSelected);
connect(symbols_category, &QPushButton::clicked, [this, symbols_emoji]() { connect(symbolsCategory, &QPushButton::clicked, [this, symbolsEmoji]() {
this->showEmojiCategory(symbols_emoji); this->showEmojiCategory(symbolsEmoji);
}); });
connect(flags_emoji, &EmojiCategory::emojiSelected, this, &EmojiPanel::emojiSelected); connect(flagsEmoji, &EmojiCategory::emojiSelected, this, &EmojiPanel::emojiSelected);
connect(flags_category, &QPushButton::clicked, [this, flags_emoji]() { connect(flagsCategory, &QPushButton::clicked, [this, flagsEmoji]() {
this->showEmojiCategory(flags_emoji); this->showEmojiCategory(flagsEmoji);
}); });
connect(animation_, &QAbstractAnimation::finished, [this]() { connect(animation_, &QAbstractAnimation::finished, [this]() {
@ -217,7 +207,7 @@ EmojiPanel::EmojiPanel(QWidget *parent)
void EmojiPanel::showEmojiCategory(const EmojiCategory *category) void EmojiPanel::showEmojiCategory(const EmojiCategory *category)
{ {
auto posToGo = category->mapToParent(QPoint()).y(); auto posToGo = category->mapToParent(QPoint()).y();
auto current = scroll_area_->verticalScrollBar()->value(); auto current = scrollArea_->verticalScrollBar()->value();
if (current == posToGo) if (current == posToGo)
return; return;
@ -228,10 +218,10 @@ void EmojiPanel::showEmojiCategory(const EmojiCategory *category)
// To ensure the category is at the top, we move to the top // To ensure the category is at the top, we move to the top
// and go as normal to the next category. // and go as normal to the next category.
if (current > posToGo) if (current > posToGo)
this->scroll_area_->ensureVisible(0, 0, 0, 0); this->scrollArea_->ensureVisible(0, 0, 0, 0);
posToGo += 6 * 50; posToGo += 6 * 50;
this->scroll_area_->ensureVisible(0, posToGo, 0, 0); this->scrollArea_->ensureVisible(0, posToGo, 0, 0);
} }
void EmojiPanel::leaveEvent(QEvent *event) void EmojiPanel::leaveEvent(QEvent *event)
@ -241,6 +231,23 @@ void EmojiPanel::leaveEvent(QEvent *event)
fadeOut(); fadeOut();
} }
void EmojiPanel::paintEvent(QPaintEvent *event)
{
QPainter p(this);
DropShadow::draw(p,
shadowMargin_,
4.0,
QColor(120, 120, 120, 92),
QColor(255, 255, 255, 0),
0.0,
1.0,
0.6,
width(),
height());
QWidget::paintEvent(event);
}
void EmojiPanel::fadeOut() void EmojiPanel::fadeOut()
{ {
animation_->setDirection(QAbstractAnimation::Forward); animation_->setDirection(QAbstractAnimation::Forward);

View file

@ -25,6 +25,7 @@
FilteredTextEdit::FilteredTextEdit(QWidget *parent) FilteredTextEdit::FilteredTextEdit(QWidget *parent)
: QTextEdit(parent) : QTextEdit(parent)
{ {
setAcceptRichText(false);
} }
void FilteredTextEdit::keyPressEvent(QKeyEvent *event) void FilteredTextEdit::keyPressEvent(QKeyEvent *event)