diff --git a/CMakeLists.txt b/CMakeLists.txt
index 99ae1d62..6415b912 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -171,6 +171,7 @@ set(SRC_FILES
src/ui/FlatButton.cc
src/ui/OverlayModal.cc
src/ui/ScrollBar.cc
+ src/ui/SnackBar.cc
src/ui/RaisedButton.cc
src/ui/Ripple.cc
src/ui/RippleOverlay.cc
@@ -249,6 +250,7 @@ qt5_wrap_cpp(MOC_HEADERS
include/ui/FlatButton.h
include/ui/OverlayWidget.h
include/ui/ScrollBar.h
+ include/ui/SnackBar.h
include/ui/RaisedButton.h
include/ui/Ripple.h
include/ui/RippleOverlay.h
@@ -292,9 +294,6 @@ if (APPLE)
endif()
if (BUILD_TESTS)
- #
- # Build tests.
- #
enable_testing()
find_package(GTest REQUIRED)
@@ -312,26 +311,23 @@ if (BUILD_TESTS)
add_test(MatrixEvents events_test)
add_test(MatrixEventCollection event_collection_test)
add_test(MatrixMessageEvents message_events)
-else()
- #
- # Build the executable.
- #
+endif()
+
if(APPVEYOR_BUILD)
set (NHEKO_LIBS matrix_events Qt5::Widgets Qt5::Network lmdb)
else()
set (NHEKO_LIBS matrix_events Qt5::Widgets Qt5::Network ${LMDB_LIBRARY})
endif()
- set (NHEKO_DEPS ${OS_BUNDLE} ${SRC_FILES} ${UI_HEADERS} ${MOC_HEADERS} ${QRC} ${LANG_QRC} ${QM_SRC})
+set (NHEKO_DEPS ${OS_BUNDLE} ${SRC_FILES} ${UI_HEADERS} ${MOC_HEADERS} ${QRC} ${LANG_QRC} ${QM_SRC})
- if(APPLE)
- add_executable (nheko ${NHEKO_DEPS})
- target_link_libraries (nheko ${NHEKO_LIBS} Qt5::MacExtras)
- elseif(WIN32)
- add_executable (nheko ${ICON_FILE} ${NHEKO_DEPS})
- target_link_libraries (nheko ${NTDLIB} ${NHEKO_LIBS} Qt5::WinMain)
- else()
- add_executable (nheko ${NHEKO_DEPS})
- target_link_libraries (nheko ${NHEKO_LIBS})
- endif()
+if(APPLE)
+ add_executable (nheko ${NHEKO_DEPS})
+ target_link_libraries (nheko ${NHEKO_LIBS} Qt5::MacExtras)
+elseif(WIN32)
+ add_executable (nheko ${ICON_FILE} ${NHEKO_DEPS})
+ target_link_libraries (nheko ${NTDLIB} ${NHEKO_LIBS} Qt5::WinMain)
+else()
+ add_executable (nheko ${NHEKO_DEPS})
+ target_link_libraries (nheko ${NHEKO_LIBS})
endif()
diff --git a/include/ui/SnackBar.h b/include/ui/SnackBar.h
new file mode 100644
index 00000000..076b7105
--- /dev/null
+++ b/include/ui/SnackBar.h
@@ -0,0 +1,80 @@
+#pragma once
+
+#include <QCoreApplication>
+#include <QPaintEvent>
+#include <QStateMachine>
+#include <QTimer>
+
+#include "OverlayWidget.h"
+
+enum class SnackBarPosition {
+ Bottom,
+ Top,
+};
+
+class SnackBar : public OverlayWidget
+{
+ Q_OBJECT
+
+public:
+ explicit SnackBar(QWidget *parent);
+ ~SnackBar();
+
+ inline void setBackgroundColor(const QColor &color);
+ inline void setTextColor(const QColor &color);
+ inline void setPosition(SnackBarPosition pos);
+
+public slots:
+ void showMessage(const QString &msg);
+
+protected:
+ void paintEvent(QPaintEvent *event) override;
+ void mousePressEvent(QMouseEvent *event) override;
+
+private slots:
+ void onTimeout();
+ void hideMessage();
+
+private:
+ void stopTimers();
+ void start();
+
+ QColor bgColor_;
+ QColor textColor_;
+
+ qreal bgOpacity_;
+ qreal offset_;
+
+ QList<QString> messages_;
+
+ QTimer *showTimer_;
+ QTimer *hideTimer_;
+
+ int duration_;
+ int boxWidth_;
+ int boxHeight_;
+ int boxPadding_;
+
+ SnackBarPosition position_;
+};
+
+inline void
+SnackBar::setPosition(SnackBarPosition pos)
+{
+ position_ = pos;
+ update();
+}
+
+inline void
+SnackBar::setBackgroundColor(const QColor &color)
+{
+ bgColor_ = color;
+ update();
+}
+
+inline void
+SnackBar::setTextColor(const QColor &color)
+{
+ textColor_ = color;
+ update();
+}
diff --git a/src/ui/SnackBar.cc b/src/ui/SnackBar.cc
new file mode 100644
index 00000000..673c2f93
--- /dev/null
+++ b/src/ui/SnackBar.cc
@@ -0,0 +1,143 @@
+#include <QDebug>
+#include <QPainter>
+
+#include "SnackBar.h"
+
+constexpr int STARTING_OFFSET = 1;
+
+SnackBar::SnackBar(QWidget *parent)
+ : OverlayWidget(parent)
+{
+ bgOpacity_ = 0.9;
+ duration_ = 6000;
+ boxWidth_ = 400;
+ boxHeight_ = 40;
+ boxPadding_ = 10;
+ textColor_ = QColor("white");
+ bgColor_ = QColor("#333");
+ offset_ = STARTING_OFFSET;
+ position_ = SnackBarPosition::Top;
+
+ QFont font("Open Sans", 14, QFont::Medium);
+ setFont(font);
+
+ showTimer_ = new QTimer();
+ hideTimer_ = new QTimer();
+ hideTimer_->setSingleShot(true);
+
+ connect(showTimer_, SIGNAL(timeout()), this, SLOT(onTimeout()));
+ connect(hideTimer_, SIGNAL(timeout()), this, SLOT(hideMessage()));
+}
+
+SnackBar::~SnackBar()
+{
+ stopTimers();
+
+ delete showTimer_;
+ delete hideTimer_;
+}
+
+void
+SnackBar::start()
+{
+ show();
+ raise();
+
+ showTimer_->start(10);
+}
+
+void
+SnackBar::hideMessage()
+{
+ stopTimers();
+ hide();
+
+ // Moving on to the next message.
+ messages_.removeFirst();
+
+ // Reseting the starting position of the widget.
+ offset_ = STARTING_OFFSET;
+
+ if (!messages_.isEmpty())
+ start();
+}
+
+void
+SnackBar::stopTimers()
+{
+ showTimer_->stop();
+ hideTimer_->stop();
+}
+
+void
+SnackBar::showMessage(const QString &msg)
+{
+ messages_.push_back(msg);
+
+ // There is already an active message.
+ if (isVisible())
+ return;
+
+ start();
+}
+
+void
+SnackBar::onTimeout()
+{
+ offset_ -= 0.5;
+
+ if (offset_ <= 0.0) {
+ showTimer_->stop();
+ hideTimer_->start(duration_);
+ }
+
+ update();
+}
+
+void
+SnackBar::mousePressEvent(QMouseEvent *)
+{
+ hideMessage();
+}
+
+void
+SnackBar::paintEvent(QPaintEvent *event)
+{
+ Q_UNUSED(event)
+
+ if (messages_.isEmpty())
+ return;
+
+ auto message_ = messages_.first();
+
+ QPainter p(this);
+ p.setRenderHint(QPainter::Antialiasing);
+
+ QBrush brush;
+ brush.setStyle(Qt::SolidPattern);
+ brush.setColor(bgColor_);
+ p.setBrush(brush);
+ p.setOpacity(bgOpacity_);
+
+ QRect r(0, 0, boxWidth_, boxHeight_);
+
+ p.setPen(Qt::white);
+ QRect br = p.boundingRect(r, Qt::AlignHCenter | Qt::AlignTop | Qt::TextWordWrap, message_);
+
+ p.setPen(Qt::NoPen);
+ r = br.united(r).adjusted(-boxPadding_, -boxPadding_, boxPadding_, boxPadding_);
+
+ const qreal s = 1 - offset_;
+
+ if (position_ == SnackBarPosition::Bottom)
+ p.translate((width() - (r.width() - 2 * boxPadding_)) / 2,
+ height() - boxPadding_ - s * (r.height()));
+ else
+ p.translate((width() - (r.width() - 2 * boxPadding_)) / 2,
+ s * (r.height()) - 2 * boxPadding_);
+
+ br.moveCenter(r.center());
+ p.drawRoundedRect(r.adjusted(0, 0, 0, 3), 3, 3);
+ p.setPen(textColor_);
+ p.drawText(br, Qt::AlignHCenter | Qt::AlignTop | Qt::TextWordWrap, message_);
+}
|