From 5197f8a886041ea9ebf6c860535cf2effc08a03f Mon Sep 17 00:00:00 2001 From: Konstantinos Sideris Date: Wed, 31 May 2017 02:35:28 +0300 Subject: [PATCH] Add drop shadow to emoji panel - Minor refactoring --- include/EmojiPanel.h | 23 ++-- include/ui/DropShadow.h | 100 ++++++++++++++++ src/EmojiPanel.cc | 259 +++++++++++++++++++++------------------- src/TextInputWidget.cc | 1 + 4 files changed, 244 insertions(+), 139 deletions(-) create mode 100644 include/ui/DropShadow.h diff --git a/include/EmojiPanel.h b/include/EmojiPanel.h index e87ab7a4..14b7692a 100644 --- a/include/EmojiPanel.h +++ b/include/EmojiPanel.h @@ -17,9 +17,7 @@ #pragma once -#include #include -#include #include #include #include @@ -27,7 +25,7 @@ #include "EmojiCategory.h" #include "EmojiProvider.h" -class EmojiPanel : public QFrame +class EmojiPanel : public QWidget { Q_OBJECT @@ -43,25 +41,24 @@ signals: protected: void leaveEvent(QEvent *event); + void paintEvent(QPaintEvent *event); private: void showEmojiCategory(const EmojiCategory *category); - QPropertyAnimation *opacity_anim_; - QPropertyAnimation *size_anim_; + QPropertyAnimation *animation_; QGraphicsOpacityEffect *opacity_; - QParallelAnimationGroup *animation_; EmojiProvider emoji_provider_; - QScrollArea *scroll_area_; + QScrollArea *scrollArea_; + + int shadowMargin_; // Panel dimensions. - const int WIDTH = 370; - const int HEIGHT = 350; + int width_; + int height_; - const int ANIMATION_DURATION = 100; - const int ANIMATION_OFFSET = 50; - - const int category_icon_size_ = 20; + int animationDuration_; + int categoryIconSize_; }; diff --git a/include/ui/DropShadow.h b/include/ui/DropShadow.h new file mode 100644 index 00000000..19d61c8d --- /dev/null +++ b/include/ui/DropShadow.h @@ -0,0 +1,100 @@ +#pragma once + +#include +#include +#include + +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); + } +}; diff --git a/src/EmojiPanel.cc b/src/EmojiPanel.cc index 63b408c0..dde44369 100644 --- a/src/EmojiPanel.cc +++ b/src/EmojiPanel.cc @@ -15,20 +15,24 @@ * along with this program. If not, see . */ -#include -#include #include #include #include #include #include "Avatar.h" +#include "DropShadow.h" #include "EmojiCategory.h" #include "EmojiPanel.h" #include "FlatButton.h" EmojiPanel::EmojiPanel(QWidget *parent) - : QFrame(parent) + : QWidget(parent) + , shadowMargin_{3} + , width_{370} + , height_{350} + , animationDuration_{100} + , categoryIconSize_{20} { setStyleSheet( "QWidget {background: #f8fbfe; color: #e8e8e8; border: none;}" @@ -40,172 +44,158 @@ EmojiPanel::EmojiPanel(QWidget *parent) setAttribute(Qt::WA_TranslucentBackground, true); setWindowFlags(Qt::FramelessWindowHint | Qt::ToolTip); - // TODO: Make it MainWindow aware - auto main_frame_ = new QFrame(this); - main_frame_->setMaximumSize(WIDTH, HEIGHT); + auto mainWidget = new QWidget(this); + mainWidget->setMaximumSize(width_, height_); - auto top_layout = new QVBoxLayout(this); - top_layout->addWidget(main_frame_); - top_layout->setMargin(0); + auto topLayout = new QVBoxLayout(this); + topLayout->addWidget(mainWidget); + topLayout->setMargin(shadowMargin_); - auto content_layout = new QVBoxLayout(main_frame_); - content_layout->setMargin(0); + auto contentLayout = new QVBoxLayout(mainWidget); + contentLayout->setMargin(0); - auto emoji_categories = new QFrame(main_frame_); - emoji_categories->setStyleSheet("background-color: #f2f2f2"); + auto emojiCategories = new QFrame(mainWidget); + emojiCategories->setStyleSheet("background-color: #f2f2f2"); - auto categories_layout = new QHBoxLayout(emoji_categories); - categories_layout->setSpacing(6); - categories_layout->setMargin(5); + auto categoriesLayout = new QHBoxLayout(emojiCategories); + categoriesLayout->setSpacing(6); + categoriesLayout->setMargin(5); - auto people_category = new FlatButton(emoji_categories); - people_category->setIcon(QIcon(":/icons/icons/emoji-categories/people.png")); - people_category->setIconSize(QSize(category_icon_size_, category_icon_size_)); - people_category->setForegroundColor("gray"); + auto peopleCategory = new FlatButton(emojiCategories); + peopleCategory->setIcon(QIcon(":/icons/icons/emoji-categories/people.png")); + peopleCategory->setIconSize(QSize(categoryIconSize_, categoryIconSize_)); + peopleCategory->setForegroundColor("gray"); - auto nature_category = new FlatButton(emoji_categories); - nature_category->setIcon(QIcon(":/icons/icons/emoji-categories/nature.png")); - nature_category->setIconSize(QSize(category_icon_size_, category_icon_size_)); - nature_category->setForegroundColor("gray"); + auto natureCategory_ = new FlatButton(emojiCategories); + natureCategory_->setIcon(QIcon(":/icons/icons/emoji-categories/nature.png")); + natureCategory_->setIconSize(QSize(categoryIconSize_, categoryIconSize_)); + natureCategory_->setForegroundColor("gray"); - auto food_category = new FlatButton(emoji_categories); - food_category->setIcon(QIcon(":/icons/icons/emoji-categories/foods.png")); - food_category->setIconSize(QSize(category_icon_size_, category_icon_size_)); - food_category->setForegroundColor("gray"); + auto foodCategory_ = new FlatButton(emojiCategories); + foodCategory_->setIcon(QIcon(":/icons/icons/emoji-categories/foods.png")); + foodCategory_->setIconSize(QSize(categoryIconSize_, categoryIconSize_)); + foodCategory_->setForegroundColor("gray"); - auto activity_category = new FlatButton(emoji_categories); - activity_category->setIcon(QIcon(":/icons/icons/emoji-categories/activity.png")); - activity_category->setIconSize(QSize(category_icon_size_, category_icon_size_)); - activity_category->setForegroundColor("gray"); + auto activityCategory = new FlatButton(emojiCategories); + activityCategory->setIcon(QIcon(":/icons/icons/emoji-categories/activity.png")); + activityCategory->setIconSize(QSize(categoryIconSize_, categoryIconSize_)); + activityCategory->setForegroundColor("gray"); - auto travel_category = new FlatButton(emoji_categories); - travel_category->setIcon(QIcon(":/icons/icons/emoji-categories/travel.png")); - travel_category->setIconSize(QSize(category_icon_size_, category_icon_size_)); - travel_category->setForegroundColor("gray"); + auto travelCategory = new FlatButton(emojiCategories); + travelCategory->setIcon(QIcon(":/icons/icons/emoji-categories/travel.png")); + travelCategory->setIconSize(QSize(categoryIconSize_, categoryIconSize_)); + travelCategory->setForegroundColor("gray"); - auto objects_category = new FlatButton(emoji_categories); - objects_category->setIcon(QIcon(":/icons/icons/emoji-categories/objects.png")); - objects_category->setIconSize(QSize(category_icon_size_, category_icon_size_)); - objects_category->setForegroundColor("gray"); + auto objectsCategory = new FlatButton(emojiCategories); + objectsCategory->setIcon(QIcon(":/icons/icons/emoji-categories/objects.png")); + objectsCategory->setIconSize(QSize(categoryIconSize_, categoryIconSize_)); + objectsCategory->setForegroundColor("gray"); - auto symbols_category = new FlatButton(emoji_categories); - symbols_category->setIcon(QIcon(":/icons/icons/emoji-categories/symbols.png")); - symbols_category->setIconSize(QSize(category_icon_size_, category_icon_size_)); - symbols_category->setForegroundColor("gray"); + auto symbolsCategory = new FlatButton(emojiCategories); + symbolsCategory->setIcon(QIcon(":/icons/icons/emoji-categories/symbols.png")); + symbolsCategory->setIconSize(QSize(categoryIconSize_, categoryIconSize_)); + symbolsCategory->setForegroundColor("gray"); - auto flags_category = new FlatButton(emoji_categories); - flags_category->setIcon(QIcon(":/icons/icons/emoji-categories/flags.png")); - flags_category->setIconSize(QSize(category_icon_size_, category_icon_size_)); - flags_category->setForegroundColor("gray"); + auto flagsCategory = new FlatButton(emojiCategories); + flagsCategory->setIcon(QIcon(":/icons/icons/emoji-categories/flags.png")); + flagsCategory->setIconSize(QSize(categoryIconSize_, categoryIconSize_)); + flagsCategory->setForegroundColor("gray"); - categories_layout->addWidget(people_category); - categories_layout->addWidget(nature_category); - categories_layout->addWidget(food_category); - categories_layout->addWidget(activity_category); - categories_layout->addWidget(travel_category); - categories_layout->addWidget(objects_category); - categories_layout->addWidget(symbols_category); - categories_layout->addWidget(flags_category); + categoriesLayout->addWidget(peopleCategory); + categoriesLayout->addWidget(natureCategory_); + categoriesLayout->addWidget(foodCategory_); + categoriesLayout->addWidget(activityCategory); + categoriesLayout->addWidget(travelCategory); + categoriesLayout->addWidget(objectsCategory); + categoriesLayout->addWidget(symbolsCategory); + categoriesLayout->addWidget(flagsCategory); - scroll_area_ = new QScrollArea(this); - scroll_area_->setWidgetResizable(true); - scroll_area_->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + scrollArea_ = new QScrollArea(this); + scrollArea_->setWidgetResizable(true); + scrollArea_->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - auto scroll_widget_ = new QWidget(this); - auto scroll_layout_ = new QVBoxLayout(scroll_widget_); + auto scrollWidget = new QWidget(this); + auto scrollLayout = new QVBoxLayout(scrollWidget); - scroll_layout_->setMargin(0); - scroll_area_->setWidget(scroll_widget_); + scrollLayout->setMargin(0); + scrollArea_->setWidget(scrollWidget); - auto people_emoji = new EmojiCategory(tr("Smileys & People"), emoji_provider_.people, scroll_widget_); - scroll_layout_->addWidget(people_emoji); + auto peopleEmoji = new EmojiCategory(tr("Smileys & People"), emoji_provider_.people, scrollWidget); + scrollLayout->addWidget(peopleEmoji); - auto nature_emoji = new EmojiCategory(tr("Animals & Nature"), emoji_provider_.nature, scroll_widget_); - scroll_layout_->addWidget(nature_emoji); + auto natureEmoji = new EmojiCategory(tr("Animals & Nature"), emoji_provider_.nature, scrollWidget); + scrollLayout->addWidget(natureEmoji); - auto food_emoji = new EmojiCategory(tr("Food & Drink"), emoji_provider_.food, scroll_widget_); - scroll_layout_->addWidget(food_emoji); + auto foodEmoji = new EmojiCategory(tr("Food & Drink"), emoji_provider_.food, scrollWidget); + scrollLayout->addWidget(foodEmoji); - auto activity_emoji = new EmojiCategory(tr("Activity"), emoji_provider_.activity, scroll_widget_); - scroll_layout_->addWidget(activity_emoji); + auto activityEmoji = new EmojiCategory(tr("Activity"), emoji_provider_.activity, scrollWidget); + scrollLayout->addWidget(activityEmoji); - auto travel_emoji = new EmojiCategory(tr("Travel & Places"), emoji_provider_.travel, scroll_widget_); - scroll_layout_->addWidget(travel_emoji); + auto travelEmoji = new EmojiCategory(tr("Travel & Places"), emoji_provider_.travel, scrollWidget); + scrollLayout->addWidget(travelEmoji); - auto objects_emoji = new EmojiCategory(tr("Objects"), emoji_provider_.objects, scroll_widget_); - scroll_layout_->addWidget(objects_emoji); + auto objectsEmoji = new EmojiCategory(tr("Objects"), emoji_provider_.objects, scrollWidget); + scrollLayout->addWidget(objectsEmoji); - auto symbols_emoji = new EmojiCategory(tr("Symbols"), emoji_provider_.symbols, scroll_widget_); - scroll_layout_->addWidget(symbols_emoji); + auto symbolsEmoji = new EmojiCategory(tr("Symbols"), emoji_provider_.symbols, scrollWidget); + scrollLayout->addWidget(symbolsEmoji); - auto flags_emoji = new EmojiCategory(tr("Flags"), emoji_provider_.flags, scroll_widget_); - scroll_layout_->addWidget(flags_emoji); + auto flagsEmoji = new EmojiCategory(tr("Flags"), emoji_provider_.flags, scrollWidget); + scrollLayout->addWidget(flagsEmoji); - content_layout->addStretch(1); - content_layout->addWidget(scroll_area_); - content_layout->addWidget(emoji_categories); - - setLayout(top_layout); + contentLayout->addStretch(1); + contentLayout->addWidget(scrollArea_); + contentLayout->addWidget(emojiCategories); opacity_ = new QGraphicsOpacityEffect(this); opacity_->setOpacity(1.0); setGraphicsEffect(opacity_); - opacity_anim_ = new QPropertyAnimation(opacity_, "opacity", this); - opacity_anim_->setDuration(ANIMATION_DURATION); - opacity_anim_->setStartValue(1); - opacity_anim_->setEndValue(0); + animation_ = new QPropertyAnimation(opacity_, "opacity", this); + animation_->setDuration(animationDuration_); + animation_->setStartValue(1); + animation_->setEndValue(0); - size_anim_ = new QPropertyAnimation(this); - size_anim_->setTargetObject(main_frame_); - size_anim_->setPropertyName("geometry"); - 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(peopleEmoji, &EmojiCategory::emojiSelected, this, &EmojiPanel::emojiSelected); + connect(peopleCategory, &QPushButton::clicked, [this, peopleEmoji]() { + this->showEmojiCategory(peopleEmoji); }); - connect(nature_emoji, &EmojiCategory::emojiSelected, this, &EmojiPanel::emojiSelected); - connect(nature_category, &QPushButton::clicked, [this, nature_emoji]() { - this->showEmojiCategory(nature_emoji); + connect(natureEmoji, &EmojiCategory::emojiSelected, this, &EmojiPanel::emojiSelected); + connect(natureCategory_, &QPushButton::clicked, [this, natureEmoji]() { + this->showEmojiCategory(natureEmoji); }); - connect(food_emoji, &EmojiCategory::emojiSelected, this, &EmojiPanel::emojiSelected); - connect(food_category, &QPushButton::clicked, [this, food_emoji]() { - this->showEmojiCategory(food_emoji); + connect(foodEmoji, &EmojiCategory::emojiSelected, this, &EmojiPanel::emojiSelected); + connect(foodCategory_, &QPushButton::clicked, [this, foodEmoji]() { + this->showEmojiCategory(foodEmoji); }); - connect(activity_emoji, &EmojiCategory::emojiSelected, this, &EmojiPanel::emojiSelected); - connect(activity_category, &QPushButton::clicked, [this, activity_emoji]() { - this->showEmojiCategory(activity_emoji); + connect(activityEmoji, &EmojiCategory::emojiSelected, this, &EmojiPanel::emojiSelected); + connect(activityCategory, &QPushButton::clicked, [this, activityEmoji]() { + this->showEmojiCategory(activityEmoji); }); - connect(travel_emoji, &EmojiCategory::emojiSelected, this, &EmojiPanel::emojiSelected); - connect(travel_category, &QPushButton::clicked, [this, travel_emoji]() { - this->showEmojiCategory(travel_emoji); + connect(travelEmoji, &EmojiCategory::emojiSelected, this, &EmojiPanel::emojiSelected); + connect(travelCategory, &QPushButton::clicked, [this, travelEmoji]() { + this->showEmojiCategory(travelEmoji); }); - connect(objects_emoji, &EmojiCategory::emojiSelected, this, &EmojiPanel::emojiSelected); - connect(objects_category, &QPushButton::clicked, [this, objects_emoji]() { - this->showEmojiCategory(objects_emoji); + connect(objectsEmoji, &EmojiCategory::emojiSelected, this, &EmojiPanel::emojiSelected); + connect(objectsCategory, &QPushButton::clicked, [this, objectsEmoji]() { + this->showEmojiCategory(objectsEmoji); }); - connect(symbols_emoji, &EmojiCategory::emojiSelected, this, &EmojiPanel::emojiSelected); - connect(symbols_category, &QPushButton::clicked, [this, symbols_emoji]() { - this->showEmojiCategory(symbols_emoji); + connect(symbolsEmoji, &EmojiCategory::emojiSelected, this, &EmojiPanel::emojiSelected); + connect(symbolsCategory, &QPushButton::clicked, [this, symbolsEmoji]() { + this->showEmojiCategory(symbolsEmoji); }); - connect(flags_emoji, &EmojiCategory::emojiSelected, this, &EmojiPanel::emojiSelected); - connect(flags_category, &QPushButton::clicked, [this, flags_emoji]() { - this->showEmojiCategory(flags_emoji); + connect(flagsEmoji, &EmojiCategory::emojiSelected, this, &EmojiPanel::emojiSelected); + connect(flagsCategory, &QPushButton::clicked, [this, flagsEmoji]() { + this->showEmojiCategory(flagsEmoji); }); connect(animation_, &QAbstractAnimation::finished, [this]() { @@ -217,7 +207,7 @@ EmojiPanel::EmojiPanel(QWidget *parent) void EmojiPanel::showEmojiCategory(const EmojiCategory *category) { auto posToGo = category->mapToParent(QPoint()).y(); - auto current = scroll_area_->verticalScrollBar()->value(); + auto current = scrollArea_->verticalScrollBar()->value(); if (current == posToGo) return; @@ -228,10 +218,10 @@ void EmojiPanel::showEmojiCategory(const EmojiCategory *category) // To ensure the category is at the top, we move to the top // and go as normal to the next category. if (current > posToGo) - this->scroll_area_->ensureVisible(0, 0, 0, 0); + this->scrollArea_->ensureVisible(0, 0, 0, 0); posToGo += 6 * 50; - this->scroll_area_->ensureVisible(0, posToGo, 0, 0); + this->scrollArea_->ensureVisible(0, posToGo, 0, 0); } void EmojiPanel::leaveEvent(QEvent *event) @@ -241,6 +231,23 @@ void EmojiPanel::leaveEvent(QEvent *event) 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() { animation_->setDirection(QAbstractAnimation::Forward); diff --git a/src/TextInputWidget.cc b/src/TextInputWidget.cc index cda00c2c..796a1353 100644 --- a/src/TextInputWidget.cc +++ b/src/TextInputWidget.cc @@ -25,6 +25,7 @@ FilteredTextEdit::FilteredTextEdit(QWidget *parent) : QTextEdit(parent) { + setAcceptRichText(false); } void FilteredTextEdit::keyPressEvent(QKeyEvent *event)