diff --git a/src/ui/Avatar.cc b/src/ui/Avatar.cpp
index 2f10db39..4b4cd272 100644
--- a/src/ui/Avatar.cc
+++ b/src/ui/Avatar.cpp
@@ -1,7 +1,7 @@
#include <QPainter>
-#include "Avatar.h"
#include "Utils.h"
+#include "ui/Avatar.h"
Avatar::Avatar(QWidget *parent)
: QWidget(parent)
diff --git a/src/ui/Avatar.h b/src/ui/Avatar.h
new file mode 100644
index 00000000..41967af5
--- /dev/null
+++ b/src/ui/Avatar.h
@@ -0,0 +1,47 @@
+#pragma once
+
+#include <QIcon>
+#include <QImage>
+#include <QPixmap>
+#include <QWidget>
+
+#include "Theme.h"
+
+class Avatar : public QWidget
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QColor textColor WRITE setTextColor READ textColor)
+ Q_PROPERTY(QColor backgroundColor WRITE setBackgroundColor READ backgroundColor)
+
+public:
+ explicit Avatar(QWidget *parent = 0);
+
+ void setBackgroundColor(const QColor &color);
+ void setIcon(const QIcon &icon);
+ void setImage(const QImage &image);
+ void setLetter(const QString &letter);
+ void setSize(int size);
+ void setTextColor(const QColor &color);
+
+ QColor backgroundColor() const;
+ QColor textColor() const;
+ int size() const;
+
+ QSize sizeHint() const override;
+
+protected:
+ void paintEvent(QPaintEvent *event) override;
+
+private:
+ void init();
+
+ ui::AvatarType type_;
+ QString letter_;
+ QColor background_color_;
+ QColor text_color_;
+ QIcon icon_;
+ QImage image_;
+ QPixmap pixmap_;
+ int size_;
+};
diff --git a/src/ui/Badge.cc b/src/ui/Badge.cpp
index 6701f9b7..6701f9b7 100644
--- a/src/ui/Badge.cc
+++ b/src/ui/Badge.cpp
diff --git a/src/ui/Badge.h b/src/ui/Badge.h
new file mode 100644
index 00000000..fd73ad30
--- /dev/null
+++ b/src/ui/Badge.h
@@ -0,0 +1,62 @@
+#pragma once
+
+#include <QColor>
+#include <QIcon>
+#include <QWidget>
+#include <QtGlobal>
+
+#include "OverlayWidget.h"
+
+class Badge : public OverlayWidget
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QColor textColor WRITE setTextColor READ textColor)
+ Q_PROPERTY(QColor backgroundColor WRITE setBackgroundColor READ backgroundColor)
+ Q_PROPERTY(QPointF relativePosition WRITE setRelativePosition READ relativePosition)
+
+public:
+ explicit Badge(QWidget *parent = 0);
+ explicit Badge(const QIcon &icon, QWidget *parent = 0);
+ explicit Badge(const QString &text, QWidget *parent = 0);
+
+ void setBackgroundColor(const QColor &color);
+ void setTextColor(const QColor &color);
+ void setIcon(const QIcon &icon);
+ void setRelativePosition(const QPointF &pos);
+ void setRelativePosition(qreal x, qreal y);
+ void setRelativeXPosition(qreal x);
+ void setRelativeYPosition(qreal y);
+ void setText(const QString &text);
+ void setDiameter(int diameter);
+
+ QIcon icon() const;
+ QString text() const;
+ QColor backgroundColor() const;
+ QColor textColor() const;
+ QPointF relativePosition() const;
+ QSize sizeHint() const override;
+ qreal relativeXPosition() const;
+ qreal relativeYPosition() const;
+
+ int diameter() const;
+
+protected:
+ void paintEvent(QPaintEvent *event) override;
+
+private:
+ void init();
+
+ QColor background_color_;
+ QColor text_color_;
+
+ QIcon icon_;
+ QSize size_;
+ QString text_;
+
+ int padding_;
+ int diameter_;
+
+ qreal x_;
+ qreal y_;
+};
diff --git a/src/ui/DropShadow.h b/src/ui/DropShadow.h
new file mode 100644
index 00000000..b7ba1985
--- /dev/null
+++ b/src/ui/DropShadow.h
@@ -0,0 +1,111 @@
+#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);
+ }
+};
diff --git a/src/ui/FlatButton.cc b/src/ui/FlatButton.cpp
index 45a7683e..45a7683e 100644
--- a/src/ui/FlatButton.cc
+++ b/src/ui/FlatButton.cpp
diff --git a/src/ui/FlatButton.h b/src/ui/FlatButton.h
new file mode 100644
index 00000000..9c2bf425
--- /dev/null
+++ b/src/ui/FlatButton.h
@@ -0,0 +1,185 @@
+#pragma once
+
+#include <QPaintEvent>
+#include <QPainter>
+#include <QPushButton>
+#include <QStateMachine>
+
+#include "Theme.h"
+
+class RippleOverlay;
+class FlatButton;
+
+class FlatButtonStateMachine : public QStateMachine
+{
+ Q_OBJECT
+
+ Q_PROPERTY(qreal overlayOpacity WRITE setOverlayOpacity READ overlayOpacity)
+ Q_PROPERTY(
+ qreal checkedOverlayProgress WRITE setCheckedOverlayProgress READ checkedOverlayProgress)
+
+public:
+ explicit FlatButtonStateMachine(FlatButton *parent);
+ ~FlatButtonStateMachine();
+
+ void setOverlayOpacity(qreal opacity);
+ void setCheckedOverlayProgress(qreal opacity);
+
+ inline qreal overlayOpacity() const;
+ inline qreal checkedOverlayProgress() const;
+
+ void startAnimations();
+ void setupProperties();
+ void updateCheckedStatus();
+
+signals:
+ void buttonPressed();
+ void buttonChecked();
+ void buttonUnchecked();
+
+protected:
+ bool eventFilter(QObject *watched, QEvent *event) override;
+
+private:
+ void addTransition(QObject *object, const char *signal, QState *fromState, QState *toState);
+ void addTransition(QObject *object,
+ QEvent::Type eventType,
+ QState *fromState,
+ QState *toState);
+ void addTransition(QAbstractTransition *transition, QState *fromState, QState *toState);
+
+ FlatButton *const button_;
+
+ QState *const top_level_state_;
+ QState *const config_state_;
+ QState *const checkable_state_;
+ QState *const checked_state_;
+ QState *const unchecked_state_;
+ QState *const neutral_state_;
+ QState *const neutral_focused_state_;
+ QState *const hovered_state_;
+ QState *const hovered_focused_state_;
+ QState *const pressed_state_;
+
+ qreal overlay_opacity_;
+ qreal checked_overlay_progress_;
+
+ bool was_checked_;
+};
+
+inline qreal
+FlatButtonStateMachine::overlayOpacity() const
+{
+ return overlay_opacity_;
+}
+
+inline qreal
+FlatButtonStateMachine::checkedOverlayProgress() const
+{
+ return checked_overlay_progress_;
+}
+
+class FlatButton : public QPushButton
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QColor foregroundColor WRITE setForegroundColor READ foregroundColor)
+ Q_PROPERTY(QColor backgroundColor WRITE setBackgroundColor READ backgroundColor)
+ Q_PROPERTY(QColor overlayColor WRITE setOverlayColor READ overlayColor)
+ Q_PROPERTY(QColor disabledForegroundColor WRITE setDisabledForegroundColor READ
+ disabledForegroundColor)
+ Q_PROPERTY(QColor disabledBackgroundColor WRITE setDisabledBackgroundColor READ
+ disabledBackgroundColor)
+ Q_PROPERTY(qreal fontSize WRITE setFontSize READ fontSize)
+
+public:
+ explicit FlatButton(QWidget *parent = 0,
+ ui::ButtonPreset preset = ui::ButtonPreset::FlatPreset);
+ explicit FlatButton(const QString &text,
+ QWidget *parent = 0,
+ ui::ButtonPreset preset = ui::ButtonPreset::FlatPreset);
+ FlatButton(const QString &text,
+ ui::Role role,
+ QWidget *parent = 0,
+ ui::ButtonPreset preset = ui::ButtonPreset::FlatPreset);
+ ~FlatButton();
+
+ void applyPreset(ui::ButtonPreset preset);
+
+ void setBackgroundColor(const QColor &color);
+ void setBackgroundMode(Qt::BGMode mode);
+ void setBaseOpacity(qreal opacity);
+ void setCheckable(bool value);
+ void setCornerRadius(qreal radius);
+ void setDisabledBackgroundColor(const QColor &color);
+ void setDisabledForegroundColor(const QColor &color);
+ void setFixedRippleRadius(qreal radius);
+ void setFontSize(qreal size);
+ void setForegroundColor(const QColor &color);
+ void setHasFixedRippleRadius(bool value);
+ void setIconPlacement(ui::ButtonIconPlacement placement);
+ void setOverlayColor(const QColor &color);
+ void setOverlayStyle(ui::OverlayStyle style);
+ void setRippleStyle(ui::RippleStyle style);
+ void setRole(ui::Role role);
+
+ QColor foregroundColor() const;
+ QColor backgroundColor() const;
+ QColor overlayColor() const;
+ QColor disabledForegroundColor() const;
+ QColor disabledBackgroundColor() const;
+
+ qreal fontSize() const;
+ qreal cornerRadius() const;
+ qreal baseOpacity() const;
+
+ bool hasFixedRippleRadius() const;
+
+ ui::Role role() const;
+ ui::OverlayStyle overlayStyle() const;
+ ui::RippleStyle rippleStyle() const;
+ ui::ButtonIconPlacement iconPlacement() const;
+
+ Qt::BGMode backgroundMode() const;
+
+ QSize sizeHint() const override;
+
+protected:
+ int IconPadding = 0;
+
+ void checkStateSet() override;
+ void mousePressEvent(QMouseEvent *event) override;
+ void mouseReleaseEvent(QMouseEvent *event) override;
+ void resizeEvent(QResizeEvent *event) override;
+ void paintEvent(QPaintEvent *event) override;
+
+ virtual void paintBackground(QPainter *painter);
+ virtual void paintForeground(QPainter *painter);
+ virtual void updateClipPath();
+
+ void init();
+
+private:
+ RippleOverlay *ripple_overlay_;
+ FlatButtonStateMachine *state_machine_;
+
+ ui::Role role_;
+ ui::RippleStyle ripple_style_;
+ ui::ButtonIconPlacement icon_placement_;
+ ui::OverlayStyle overlay_style_;
+
+ Qt::BGMode bg_mode_;
+
+ QColor background_color_;
+ QColor foreground_color_;
+ QColor overlay_color_;
+ QColor disabled_color_;
+ QColor disabled_background_color_;
+
+ qreal fixed_ripple_radius_;
+ qreal corner_radius_;
+ qreal base_opacity_;
+ qreal font_size_;
+
+ bool use_fixed_ripple_radius_;
+};
diff --git a/src/ui/FloatingButton.cc b/src/ui/FloatingButton.cpp
index 74dcd482..74dcd482 100644
--- a/src/ui/FloatingButton.cc
+++ b/src/ui/FloatingButton.cpp
diff --git a/src/ui/FloatingButton.h b/src/ui/FloatingButton.h
new file mode 100644
index 00000000..91e99ebb
--- /dev/null
+++ b/src/ui/FloatingButton.h
@@ -0,0 +1,26 @@
+#pragma once
+
+#include "RaisedButton.h"
+
+constexpr int DIAMETER = 40;
+constexpr int ICON_SIZE = 18;
+
+constexpr int OFFSET_X = 30;
+constexpr int OFFSET_Y = 20;
+
+class FloatingButton : public RaisedButton
+{
+ Q_OBJECT
+
+public:
+ FloatingButton(const QIcon &icon, QWidget *parent = nullptr);
+
+ QSize sizeHint() const override { return QSize(DIAMETER, DIAMETER); };
+ QRect buttonGeometry() const;
+
+protected:
+ bool event(QEvent *event) override;
+ bool eventFilter(QObject *obj, QEvent *event) override;
+
+ void paintEvent(QPaintEvent *event) override;
+};
diff --git a/src/ui/InfoMessage.cpp b/src/ui/InfoMessage.cpp
index b150e61b..3151bedf 100644
--- a/src/ui/InfoMessage.cpp
+++ b/src/ui/InfoMessage.cpp
@@ -1,5 +1,5 @@
+#include "InfoMessage.h"
#include "Config.h"
-#include "InfoMessage.hpp"
#include <QDateTime>
#include <QPainter>
diff --git a/src/ui/InfoMessage.h b/src/ui/InfoMessage.h
new file mode 100644
index 00000000..58f98b0c
--- /dev/null
+++ b/src/ui/InfoMessage.h
@@ -0,0 +1,47 @@
+#pragma once
+
+#include <QColor>
+#include <QDateTime>
+#include <QWidget>
+
+class InfoMessage : public QWidget
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QColor textColor WRITE setTextColor READ textColor)
+ Q_PROPERTY(QColor boxColor WRITE setBoxColor READ boxColor)
+
+public:
+ explicit InfoMessage(QWidget *parent = nullptr);
+ InfoMessage(QString msg, QWidget *parent = nullptr);
+
+ void setTextColor(QColor color) { textColor_ = color; }
+ void setBoxColor(QColor color) { boxColor_ = color; }
+ void saveDatetime(QDateTime datetime) { datetime_ = datetime; }
+
+ QColor textColor() const { return textColor_; }
+ QColor boxColor() const { return boxColor_; }
+ QDateTime datetime() const { return datetime_; }
+
+protected:
+ void paintEvent(QPaintEvent *event) override;
+
+ int width_;
+ int height_;
+
+ QString msg_;
+ QFont font_;
+
+ QDateTime datetime_;
+
+ QColor textColor_ = QColor("black");
+ QColor boxColor_ = QColor("white");
+};
+
+class DateSeparator : public InfoMessage
+{
+ Q_OBJECT
+
+public:
+ DateSeparator(QDateTime datetime, QWidget *parent = nullptr);
+};
diff --git a/src/ui/Label.cc b/src/ui/Label.cpp
index 8bd8c54e..8bd8c54e 100644
--- a/src/ui/Label.cc
+++ b/src/ui/Label.cpp
diff --git a/src/ui/Label.h b/src/ui/Label.h
new file mode 100644
index 00000000..09cf27d7
--- /dev/null
+++ b/src/ui/Label.h
@@ -0,0 +1,25 @@
+#pragma once
+
+#include <QLabel>
+
+class Label : public QLabel
+{
+ Q_OBJECT
+
+public:
+ explicit Label(QWidget *parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags());
+ explicit Label(const QString &text,
+ QWidget *parent = Q_NULLPTR,
+ Qt::WindowFlags f = Qt::WindowFlags());
+
+signals:
+ void clicked(QMouseEvent *e);
+ void pressed(QMouseEvent *e);
+ void released(QMouseEvent *e);
+
+protected:
+ void mousePressEvent(QMouseEvent *e) override;
+ void mouseReleaseEvent(QMouseEvent *e) override;
+
+ QPoint pressPosition_;
+};
diff --git a/src/ui/LoadingIndicator.cc b/src/ui/LoadingIndicator.cpp
index f64151ce..f64151ce 100644
--- a/src/ui/LoadingIndicator.cc
+++ b/src/ui/LoadingIndicator.cpp
diff --git a/src/ui/LoadingIndicator.h b/src/ui/LoadingIndicator.h
new file mode 100644
index 00000000..bb33fe6c
--- /dev/null
+++ b/src/ui/LoadingIndicator.h
@@ -0,0 +1,38 @@
+#pragma once
+
+#include <QColor>
+#include <QPaintEvent>
+#include <QPainter>
+#include <QTimer>
+#include <QWidget>
+
+class LoadingIndicator : public QWidget
+{
+ Q_OBJECT
+ Q_PROPERTY(QColor color READ color WRITE setColor)
+
+public:
+ LoadingIndicator(QWidget *parent = 0);
+ virtual ~LoadingIndicator();
+
+ void paintEvent(QPaintEvent *e);
+
+ void start();
+ void stop();
+
+ QColor color() { return color_; }
+ void setColor(QColor color) { color_ = color; }
+
+ int interval() { return interval_; }
+ void setInterval(int interval) { interval_ = interval; }
+
+private slots:
+ void onTimeout();
+
+private:
+ int interval_;
+ int angle_;
+
+ QColor color_;
+ QTimer *timer_;
+};
diff --git a/src/ui/Menu.h b/src/ui/Menu.h
new file mode 100644
index 00000000..4c2a3c68
--- /dev/null
+++ b/src/ui/Menu.h
@@ -0,0 +1,32 @@
+#pragma once
+
+#include <QMenu>
+
+#include "Config.h"
+
+class Menu : public QMenu
+{
+public:
+ Menu(QWidget *parent = nullptr)
+ : QMenu(parent)
+ {
+ QFont font;
+ font.setPixelSize(conf::fontSize);
+
+ setFont(font);
+ setStyleSheet(
+ "QMenu { color: black; background-color: white; margin: 0px;}"
+ "QMenu::item {"
+ "color: black; padding: 7px 20px; border: 1px solid transparent;"
+ "margin: 2px 0px; }"
+ "QMenu::item:selected { color: black; background: rgba(180, 180, 180, 100); }");
+ };
+
+protected:
+ void leaveEvent(QEvent *e)
+ {
+ Q_UNUSED(e);
+
+ hide();
+ }
+};
diff --git a/src/ui/OverlayModal.cc b/src/ui/OverlayModal.cpp
index 6aa16b07..6aa16b07 100644
--- a/src/ui/OverlayModal.cc
+++ b/src/ui/OverlayModal.cpp
diff --git a/src/ui/OverlayModal.h b/src/ui/OverlayModal.h
new file mode 100644
index 00000000..a761e3ed
--- /dev/null
+++ b/src/ui/OverlayModal.h
@@ -0,0 +1,45 @@
+/*
+ * nheko Copyright (C) 2017 Konstantinos Sideris <siderisk@auth.gr>
+ *
+ * This program 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.
+ *
+ * This program 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <QKeyEvent>
+#include <QMouseEvent>
+#include <QPaintEvent>
+
+#include "OverlayWidget.h"
+
+class OverlayModal : public OverlayWidget
+{
+public:
+ OverlayModal(QWidget *parent, QWidget *content);
+
+ void setColor(QColor color) { color_ = color; }
+ void setDismissible(bool state) { isDismissible_ = state; }
+
+protected:
+ void paintEvent(QPaintEvent *event) override;
+ void keyPressEvent(QKeyEvent *event) override;
+ void mousePressEvent(QMouseEvent *event) override;
+
+private:
+ QWidget *content_;
+ QColor color_;
+
+ //! Decides whether or not the modal can be removed by clicking into it.
+ bool isDismissible_ = true;
+};
diff --git a/src/ui/OverlayWidget.cc b/src/ui/OverlayWidget.cpp
index ccac0116..ccac0116 100644
--- a/src/ui/OverlayWidget.cc
+++ b/src/ui/OverlayWidget.cpp
diff --git a/src/ui/OverlayWidget.h b/src/ui/OverlayWidget.h
new file mode 100644
index 00000000..6662479d
--- /dev/null
+++ b/src/ui/OverlayWidget.h
@@ -0,0 +1,21 @@
+#pragma once
+
+#include <QEvent>
+#include <QPainter>
+#include <QStyleOption>
+#include <QWidget>
+
+class OverlayWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit OverlayWidget(QWidget *parent = nullptr);
+
+protected:
+ bool event(QEvent *event) override;
+ bool eventFilter(QObject *obj, QEvent *event) override;
+
+ QRect overlayGeometry() const;
+ void paintEvent(QPaintEvent *event) override;
+};
diff --git a/src/ui/Painter.h b/src/ui/Painter.h
new file mode 100644
index 00000000..8de39651
--- /dev/null
+++ b/src/ui/Painter.h
@@ -0,0 +1,161 @@
+#pragma once
+
+#include <QFontMetrics>
+#include <QPaintDevice>
+#include <QPainter>
+
+class Painter : public QPainter
+{
+public:
+ explicit Painter(QPaintDevice *device)
+ : QPainter(device)
+ {}
+
+ void drawTextLeft(int x, int y, const QString &text)
+ {
+ QFontMetrics m(fontMetrics());
+ drawText(x, y + m.ascent(), text);
+ }
+
+ void drawTextRight(int x, int y, int outerw, const QString &text, int textWidth = -1)
+ {
+ QFontMetrics m(fontMetrics());
+ if (textWidth < 0)
+ textWidth = m.width(text);
+ drawText((outerw - x - textWidth), y + m.ascent(), text);
+ }
+
+ void drawPixmapLeft(int x, int y, const QPixmap &pix, const QRect &from)
+ {
+ drawPixmap(QPoint(x, y), pix, from);
+ }
+
+ void drawPixmapLeft(const QPoint &p, const QPixmap &pix, const QRect &from)
+ {
+ return drawPixmapLeft(p.x(), p.y(), pix, from);
+ }
+
+ void drawPixmapLeft(int x, int y, int w, int h, const QPixmap &pix, const QRect &from)
+ {
+ drawPixmap(QRect(x, y, w, h), pix, from);
+ }
+
+ void drawPixmapLeft(const QRect &r, const QPixmap &pix, const QRect &from)
+ {
+ return drawPixmapLeft(r.x(), r.y(), r.width(), r.height(), pix, from);
+ }
+
+ void drawPixmapLeft(int x, int y, int outerw, const QPixmap &pix)
+ {
+ Q_UNUSED(outerw);
+ drawPixmap(QPoint(x, y), pix);
+ }
+
+ void drawPixmapLeft(const QPoint &p, int outerw, const QPixmap &pix)
+ {
+ return drawPixmapLeft(p.x(), p.y(), outerw, pix);
+ }
+
+ void drawPixmapRight(int x, int y, int outerw, const QPixmap &pix, const QRect &from)
+ {
+ drawPixmap(
+ QPoint((outerw - x - (from.width() / pix.devicePixelRatio())), y), pix, from);
+ }
+
+ void drawPixmapRight(const QPoint &p, int outerw, const QPixmap &pix, const QRect &from)
+ {
+ return drawPixmapRight(p.x(), p.y(), outerw, pix, from);
+ }
+ void drawPixmapRight(int x,
+ int y,
+ int w,
+ int h,
+ int outerw,
+ const QPixmap &pix,
+ const QRect &from)
+ {
+ drawPixmap(QRect((outerw - x - w), y, w, h), pix, from);
+ }
+
+ void drawPixmapRight(const QRect &r, int outerw, const QPixmap &pix, const QRect &from)
+ {
+ return drawPixmapRight(r.x(), r.y(), r.width(), r.height(), outerw, pix, from);
+ }
+
+ void drawPixmapRight(int x, int y, int outerw, const QPixmap &pix)
+ {
+ drawPixmap(QPoint((outerw - x - (pix.width() / pix.devicePixelRatio())), y), pix);
+ }
+
+ void drawPixmapRight(const QPoint &p, int outerw, const QPixmap &pix)
+ {
+ return drawPixmapRight(p.x(), p.y(), outerw, pix);
+ }
+
+ void drawAvatar(const QPixmap &pix, int w, int h, int d)
+ {
+ QPainterPath pp;
+ pp.addEllipse((w - d) / 2, (h - d) / 2, d, d);
+
+ QRect region((w - d) / 2, (h - d) / 2, d, d);
+
+ setClipPath(pp);
+ drawPixmap(region, pix);
+ }
+
+ void drawLetterAvatar(const QString &c,
+ const QColor &penColor,
+ const QColor &brushColor,
+ int w,
+ int h,
+ int d)
+ {
+ QRect region((w - d) / 2, (h - d) / 2, d, d);
+
+ setPen(Qt::NoPen);
+ setBrush(brushColor);
+
+ drawEllipse(region.center(), d / 2, d / 2);
+
+ setBrush(Qt::NoBrush);
+ drawEllipse(region.center(), d / 2, d / 2);
+
+ setPen(penColor);
+ drawText(region.translated(0, -1), Qt::AlignCenter, c);
+ }
+};
+
+class PainterHighQualityEnabler
+{
+public:
+ PainterHighQualityEnabler(Painter &p)
+ : _painter(p)
+ {
+ static constexpr QPainter::RenderHint Hints[] = {QPainter::Antialiasing,
+ QPainter::SmoothPixmapTransform,
+ QPainter::TextAntialiasing,
+ QPainter::HighQualityAntialiasing};
+
+ auto hints = _painter.renderHints();
+ for (const auto &hint : Hints) {
+ if (!(hints & hint))
+ hints_ |= hint;
+ }
+
+ if (hints_)
+ _painter.setRenderHints(hints_);
+ }
+
+ ~PainterHighQualityEnabler()
+ {
+ if (hints_)
+ _painter.setRenderHints(hints_, false);
+ }
+
+ PainterHighQualityEnabler(const PainterHighQualityEnabler &other) = delete;
+ PainterHighQualityEnabler &operator=(const PainterHighQualityEnabler &other) = delete;
+
+private:
+ Painter &_painter;
+ QPainter::RenderHints hints_ = 0;
+};
diff --git a/src/ui/RaisedButton.cc b/src/ui/RaisedButton.cpp
index c519f84f..c519f84f 100644
--- a/src/ui/RaisedButton.cc
+++ b/src/ui/RaisedButton.cpp
diff --git a/src/ui/RaisedButton.h b/src/ui/RaisedButton.h
new file mode 100644
index 00000000..edd5ee4a
--- /dev/null
+++ b/src/ui/RaisedButton.h
@@ -0,0 +1,28 @@
+#pragma once
+
+#include <QGraphicsDropShadowEffect>
+#include <QState>
+#include <QStateMachine>
+
+#include "FlatButton.h"
+
+class RaisedButton : public FlatButton
+{
+ Q_OBJECT
+
+public:
+ explicit RaisedButton(QWidget *parent = 0);
+ explicit RaisedButton(const QString &text, QWidget *parent = 0);
+ ~RaisedButton();
+
+protected:
+ bool event(QEvent *event) override;
+
+private:
+ void init();
+
+ QStateMachine *shadow_state_machine_;
+ QState *normal_state_;
+ QState *pressed_state_;
+ QGraphicsDropShadowEffect *effect_;
+};
diff --git a/src/ui/Ripple.cc b/src/ui/Ripple.cpp
index e22c4a62..e22c4a62 100644
--- a/src/ui/Ripple.cc
+++ b/src/ui/Ripple.cpp
diff --git a/src/ui/Ripple.h b/src/ui/Ripple.h
new file mode 100644
index 00000000..9184f061
--- /dev/null
+++ b/src/ui/Ripple.h
@@ -0,0 +1,145 @@
+#pragma once
+
+#include <QBrush>
+#include <QEasingCurve>
+#include <QParallelAnimationGroup>
+#include <QPoint>
+#include <QPropertyAnimation>
+
+class RippleOverlay;
+
+class Ripple : public QParallelAnimationGroup
+{
+ Q_OBJECT
+
+ Q_PROPERTY(qreal radius WRITE setRadius READ radius)
+ Q_PROPERTY(qreal opacity WRITE setOpacity READ opacity)
+
+public:
+ explicit Ripple(const QPoint ¢er, QObject *parent = 0);
+ Ripple(const QPoint ¢er, RippleOverlay *overlay, QObject *parent = 0);
+
+ inline void setOverlay(RippleOverlay *overlay);
+
+ void setRadius(qreal radius);
+ void setOpacity(qreal opacity);
+ void setColor(const QColor &color);
+ void setBrush(const QBrush &brush);
+
+ inline qreal radius() const;
+ inline qreal opacity() const;
+ inline QColor color() const;
+ inline QBrush brush() const;
+ inline QPoint center() const;
+
+ inline QPropertyAnimation *radiusAnimation() const;
+ inline QPropertyAnimation *opacityAnimation() const;
+
+ inline void setOpacityStartValue(qreal value);
+ inline void setOpacityEndValue(qreal value);
+ inline void setRadiusStartValue(qreal value);
+ inline void setRadiusEndValue(qreal value);
+ inline void setDuration(int msecs);
+
+protected slots:
+ void destroy();
+
+private:
+ Q_DISABLE_COPY(Ripple)
+
+ QPropertyAnimation *animate(const QByteArray &property,
+ const QEasingCurve &easing = QEasingCurve::OutQuad,
+ int duration = 800);
+
+ void init();
+
+ RippleOverlay *overlay_;
+
+ QPropertyAnimation *const radius_anim_;
+ QPropertyAnimation *const opacity_anim_;
+
+ qreal radius_;
+ qreal opacity_;
+
+ QPoint center_;
+ QBrush brush_;
+};
+
+inline void
+Ripple::setOverlay(RippleOverlay *overlay)
+{
+ overlay_ = overlay;
+}
+
+inline qreal
+Ripple::radius() const
+{
+ return radius_;
+}
+
+inline qreal
+Ripple::opacity() const
+{
+ return opacity_;
+}
+
+inline QColor
+Ripple::color() const
+{
+ return brush_.color();
+}
+
+inline QBrush
+Ripple::brush() const
+{
+ return brush_;
+}
+
+inline QPoint
+Ripple::center() const
+{
+ return center_;
+}
+
+inline QPropertyAnimation *
+Ripple::radiusAnimation() const
+{
+ return radius_anim_;
+}
+
+inline QPropertyAnimation *
+Ripple::opacityAnimation() const
+{
+ return opacity_anim_;
+}
+
+inline void
+Ripple::setOpacityStartValue(qreal value)
+{
+ opacity_anim_->setStartValue(value);
+}
+
+inline void
+Ripple::setOpacityEndValue(qreal value)
+{
+ opacity_anim_->setEndValue(value);
+}
+
+inline void
+Ripple::setRadiusStartValue(qreal value)
+{
+ radius_anim_->setStartValue(value);
+}
+
+inline void
+Ripple::setRadiusEndValue(qreal value)
+{
+ radius_anim_->setEndValue(value);
+}
+
+inline void
+Ripple::setDuration(int msecs)
+{
+ radius_anim_->setDuration(msecs);
+ opacity_anim_->setDuration(msecs);
+}
diff --git a/src/ui/RippleOverlay.cc b/src/ui/RippleOverlay.cpp
index 20e98c0f..20e98c0f 100644
--- a/src/ui/RippleOverlay.cc
+++ b/src/ui/RippleOverlay.cpp
diff --git a/src/ui/RippleOverlay.h b/src/ui/RippleOverlay.h
new file mode 100644
index 00000000..9ef91fbf
--- /dev/null
+++ b/src/ui/RippleOverlay.h
@@ -0,0 +1,57 @@
+#pragma once
+
+#include <QPainterPath>
+
+#include "OverlayWidget.h"
+
+class Ripple;
+
+class RippleOverlay : public OverlayWidget
+{
+ Q_OBJECT
+
+public:
+ explicit RippleOverlay(QWidget *parent = 0);
+
+ void addRipple(Ripple *ripple);
+ void addRipple(const QPoint &position, qreal radius = 300);
+
+ void removeRipple(Ripple *ripple);
+
+ inline void setClipping(bool enable);
+ inline bool hasClipping() const;
+
+ inline void setClipPath(const QPainterPath &path);
+
+protected:
+ void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE;
+
+private:
+ Q_DISABLE_COPY(RippleOverlay)
+
+ void paintRipple(QPainter *painter, Ripple *ripple);
+
+ QList<Ripple *> ripples_;
+ QPainterPath clip_path_;
+ bool use_clip_;
+};
+
+inline void
+RippleOverlay::setClipping(bool enable)
+{
+ use_clip_ = enable;
+ update();
+}
+
+inline bool
+RippleOverlay::hasClipping() const
+{
+ return use_clip_;
+}
+
+inline void
+RippleOverlay::setClipPath(const QPainterPath &path)
+{
+ clip_path_ = path;
+ update();
+}
diff --git a/src/ui/ScrollBar.cc b/src/ui/ScrollBar.cpp
index 37218a13..37218a13 100644
--- a/src/ui/ScrollBar.cc
+++ b/src/ui/ScrollBar.cpp
diff --git a/src/ui/ScrollBar.h b/src/ui/ScrollBar.h
new file mode 100644
index 00000000..2b5382aa
--- /dev/null
+++ b/src/ui/ScrollBar.h
@@ -0,0 +1,54 @@
+/*
+ * nheko Copyright (C) 2017 Konstantinos Sideris <siderisk@auth.gr>
+ *
+ * This program 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.
+ *
+ * This program 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <QPainter>
+#include <QScrollArea>
+#include <QScrollBar>
+
+class ScrollBar : public QScrollBar
+{
+ Q_OBJECT
+ Q_PROPERTY(QColor backgroundColor READ backgroundColor WRITE setBackgroundColor)
+ Q_PROPERTY(QColor handleColor READ handleColor WRITE setHandleColor)
+
+public:
+ ScrollBar(QScrollArea *area, QWidget *parent = nullptr);
+
+ QColor backgroundColor() const { return bgColor_; }
+ void setBackgroundColor(QColor &color) { bgColor_ = color; }
+
+ QColor handleColor() const { return handleColor_; }
+ void setHandleColor(QColor &color) { handleColor_ = color; }
+
+protected:
+ void paintEvent(QPaintEvent *e) override;
+
+private:
+ int roundRadius_ = 4;
+ int handleWidth_ = 7;
+ int minHandleHeight_ = 20;
+
+ const int Padding = 4;
+
+ QScrollArea *area_;
+ QRect handle_;
+
+ QColor bgColor_ = QColor(33, 33, 33, 30);
+ QColor handleColor_ = QColor(0, 0, 0, 80);
+};
diff --git a/src/ui/SnackBar.cc b/src/ui/SnackBar.cpp
index 43a4c85d..43a4c85d 100644
--- a/src/ui/SnackBar.cc
+++ b/src/ui/SnackBar.cpp
diff --git a/src/ui/SnackBar.h b/src/ui/SnackBar.h
new file mode 100644
index 00000000..eed59c87
--- /dev/null
+++ b/src/ui/SnackBar.h
@@ -0,0 +1,79 @@
+#pragma once
+
+#include <QCoreApplication>
+#include <QPaintEvent>
+#include <QTimer>
+#include <deque>
+
+#include "OverlayWidget.h"
+
+enum class SnackBarPosition
+{
+ Bottom,
+ Top,
+};
+
+class SnackBar : public OverlayWidget
+{
+ Q_OBJECT
+
+public:
+ explicit SnackBar(QWidget *parent);
+
+ 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 hideMessage();
+
+private:
+ void stopTimers();
+ void start();
+
+ QColor bgColor_;
+ QColor textColor_;
+
+ qreal bgOpacity_;
+ qreal offset_;
+
+ std::deque<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/TextField.cc b/src/ui/TextField.cpp
index 0c936e69..0c936e69 100644
--- a/src/ui/TextField.cc
+++ b/src/ui/TextField.cpp
diff --git a/src/ui/TextField.h b/src/ui/TextField.h
new file mode 100644
index 00000000..1675a2e0
--- /dev/null
+++ b/src/ui/TextField.h
@@ -0,0 +1,174 @@
+#pragma once
+
+#include <QColor>
+#include <QLineEdit>
+#include <QPaintEvent>
+#include <QPropertyAnimation>
+#include <QStateMachine>
+#include <QtGlobal>
+
+class TextField;
+class TextFieldLabel;
+class TextFieldStateMachine;
+
+class TextField : public QLineEdit
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QColor textColor WRITE setTextColor READ textColor)
+ Q_PROPERTY(QColor inkColor WRITE setInkColor READ inkColor)
+ Q_PROPERTY(QColor labelColor WRITE setLabelColor READ labelColor)
+ Q_PROPERTY(QColor underlineColor WRITE setUnderlineColor READ underlineColor)
+ Q_PROPERTY(QColor backgroundColor WRITE setBackgroundColor READ backgroundColor)
+
+public:
+ explicit TextField(QWidget *parent = 0);
+
+ void setInkColor(const QColor &color);
+ void setBackgroundColor(const QColor &color);
+ void setLabel(const QString &label);
+ void setLabelColor(const QColor &color);
+ void setLabelFontSize(qreal size);
+ void setShowLabel(bool value);
+ void setTextColor(const QColor &color);
+ void setUnderlineColor(const QColor &color);
+
+ QColor inkColor() const;
+ QColor labelColor() const;
+ QColor textColor() const;
+ QColor underlineColor() const;
+ QColor backgroundColor() const;
+ QString label() const;
+ bool hasLabel() const;
+ qreal labelFontSize() const;
+
+protected:
+ bool event(QEvent *event) override;
+ void paintEvent(QPaintEvent *event) override;
+
+private:
+ void init();
+
+ QColor ink_color_;
+ QColor background_color_;
+ QColor label_color_;
+ QColor text_color_;
+ QColor underline_color_;
+ QString label_text_;
+ TextFieldLabel *label_;
+ TextFieldStateMachine *state_machine_;
+ bool show_label_;
+ qreal label_font_size_;
+};
+
+class TextFieldLabel : public QWidget
+{
+ Q_OBJECT
+
+ Q_PROPERTY(qreal scale WRITE setScale READ scale)
+ Q_PROPERTY(QPointF offset WRITE setOffset READ offset)
+ Q_PROPERTY(QColor color WRITE setColor READ color)
+
+public:
+ TextFieldLabel(TextField *parent);
+
+ inline void setColor(const QColor &color);
+ inline void setOffset(const QPointF &pos);
+ inline void setScale(qreal scale);
+
+ inline QColor color() const;
+ inline QPointF offset() const;
+ inline qreal scale() const;
+
+protected:
+ void paintEvent(QPaintEvent *event) override;
+
+private:
+ TextField *const text_field_;
+
+ QColor color_;
+ qreal scale_;
+ qreal x_;
+ qreal y_;
+};
+
+inline void
+TextFieldLabel::setColor(const QColor &color)
+{
+ color_ = color;
+ update();
+}
+
+inline void
+TextFieldLabel::setOffset(const QPointF &pos)
+{
+ x_ = pos.x();
+ y_ = pos.y();
+ update();
+}
+
+inline void
+TextFieldLabel::setScale(qreal scale)
+{
+ scale_ = scale;
+ update();
+}
+
+inline QPointF
+TextFieldLabel::offset() const
+{
+ return QPointF(x_, y_);
+}
+inline qreal
+TextFieldLabel::scale() const
+{
+ return scale_;
+}
+inline QColor
+TextFieldLabel::color() const
+{
+ return color_;
+}
+
+class TextFieldStateMachine : public QStateMachine
+{
+ Q_OBJECT
+
+ Q_PROPERTY(qreal progress WRITE setProgress READ progress)
+
+public:
+ TextFieldStateMachine(TextField *parent);
+
+ inline void setProgress(qreal progress);
+ void setLabel(TextFieldLabel *label);
+
+ inline qreal progress() const;
+
+public slots:
+ void setupProperties();
+
+private:
+ QPropertyAnimation *color_anim_;
+ QPropertyAnimation *offset_anim_;
+
+ QState *focused_state_;
+ QState *normal_state_;
+
+ TextField *text_field_;
+ TextFieldLabel *label_;
+
+ qreal progress_;
+};
+
+inline void
+TextFieldStateMachine::setProgress(qreal progress)
+{
+ progress_ = progress;
+ text_field_->update();
+}
+
+inline qreal
+TextFieldStateMachine::progress() const
+{
+ return progress_;
+}
diff --git a/src/ui/Theme.cc b/src/ui/Theme.cpp
index 7209864a..7209864a 100644
--- a/src/ui/Theme.cc
+++ b/src/ui/Theme.cpp
diff --git a/src/ui/Theme.h b/src/ui/Theme.h
new file mode 100644
index 00000000..7a0bdcb7
--- /dev/null
+++ b/src/ui/Theme.h
@@ -0,0 +1,97 @@
+#pragma once
+
+#include <QColor>
+#include <QHash>
+#include <QObject>
+
+namespace ui {
+enum class AvatarType
+{
+ Icon,
+ Image,
+ Letter
+};
+
+namespace sidebar {
+static const int SmallSize = 60;
+static const int NormalSize = 260;
+static const int CommunitiesSidebarSize = 48;
+}
+// Default font size.
+const int FontSize = 16;
+
+// Default avatar size. Width and height.
+const int AvatarSize = 40;
+
+enum class ButtonPreset
+{
+ FlatPreset,
+ CheckablePreset
+};
+
+enum class RippleStyle
+{
+ CenteredRipple,
+ PositionedRipple,
+ NoRipple
+};
+
+enum class OverlayStyle
+{
+ NoOverlay,
+ TintedOverlay,
+ GrayOverlay
+};
+
+enum class Role
+{
+ Default,
+ Primary,
+ Secondary
+};
+
+enum class ButtonIconPlacement
+{
+ LeftIcon,
+ RightIcon
+};
+
+enum class ProgressType
+{
+ DeterminateProgress,
+ IndeterminateProgress
+};
+
+enum class Color
+{
+ Black,
+ BrightWhite,
+ FadedWhite,
+ MediumWhite,
+ DarkGreen,
+ LightGreen,
+ BrightGreen,
+ Gray,
+ Red,
+ Blue,
+ Transparent
+};
+
+} // namespace ui
+
+class Theme : public QObject
+{
+ Q_OBJECT
+public:
+ explicit Theme(QObject *parent = 0);
+
+ QColor getColor(const QString &key) const;
+
+ void setColor(const QString &key, const QColor &color);
+ void setColor(const QString &key, ui::Color color);
+
+private:
+ QColor rgba(int r, int g, int b, qreal a) const;
+
+ QHash<QString, QColor> colors_;
+};
diff --git a/src/ui/ThemeManager.cc b/src/ui/ThemeManager.cpp
index 7baed1f3..7baed1f3 100644
--- a/src/ui/ThemeManager.cc
+++ b/src/ui/ThemeManager.cpp
diff --git a/src/ui/ThemeManager.h b/src/ui/ThemeManager.h
new file mode 100644
index 00000000..d35ff754
--- /dev/null
+++ b/src/ui/ThemeManager.h
@@ -0,0 +1,31 @@
+#pragma once
+
+#include <QCommonStyle>
+
+#include "Theme.h"
+
+class ThemeManager : public QCommonStyle
+{
+ Q_OBJECT
+
+public:
+ inline static ThemeManager &instance();
+
+ void setTheme(Theme *theme);
+ QColor themeColor(const QString &key) const;
+
+private:
+ ThemeManager();
+
+ ThemeManager(ThemeManager const &);
+ void operator=(ThemeManager const &);
+
+ Theme *theme_;
+};
+
+inline ThemeManager &
+ThemeManager::instance()
+{
+ static ThemeManager instance;
+ return instance;
+}
diff --git a/src/ui/ToggleButton.cc b/src/ui/ToggleButton.cpp
index 755f528f..755f528f 100644
--- a/src/ui/ToggleButton.cc
+++ b/src/ui/ToggleButton.cpp
diff --git a/src/ui/ToggleButton.h b/src/ui/ToggleButton.h
new file mode 100644
index 00000000..14c3450b
--- /dev/null
+++ b/src/ui/ToggleButton.h
@@ -0,0 +1,110 @@
+#pragma once
+
+#include <QAbstractButton>
+#include <QColor>
+
+class ToggleTrack;
+class ToggleThumb;
+
+enum class Position
+{
+ Left,
+ Right
+};
+
+class Toggle : public QAbstractButton
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QColor activeColor WRITE setActiveColor READ activeColor)
+ Q_PROPERTY(QColor disabledColor WRITE setDisabledColor READ disabledColor)
+ Q_PROPERTY(QColor inactiveColor WRITE setInactiveColor READ inactiveColor)
+ Q_PROPERTY(QColor trackColor WRITE setTrackColor READ trackColor)
+
+public:
+ Toggle(QWidget *parent = nullptr);
+
+ void setState(bool isEnabled);
+
+ void setActiveColor(const QColor &color);
+ void setDisabledColor(const QColor &color);
+ void setInactiveColor(const QColor &color);
+ void setTrackColor(const QColor &color);
+
+ QColor activeColor() const { return activeColor_; };
+ QColor disabledColor() const { return disabledColor_; };
+ QColor inactiveColor() const { return inactiveColor_; };
+ QColor trackColor() const { return trackColor_.isValid() ? trackColor_ : QColor("#eee"); };
+
+ QSize sizeHint() const override { return QSize(64, 48); };
+
+protected:
+ void paintEvent(QPaintEvent *event) override;
+
+private:
+ void init();
+ void setupProperties();
+
+ ToggleTrack *track_;
+ ToggleThumb *thumb_;
+
+ QColor disabledColor_;
+ QColor activeColor_;
+ QColor inactiveColor_;
+ QColor trackColor_;
+};
+
+class ToggleThumb : public QWidget
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QColor thumbColor WRITE setThumbColor READ thumbColor)
+
+public:
+ ToggleThumb(Toggle *parent);
+
+ Position shift() const { return position_; };
+ qreal offset() const { return offset_; };
+ QColor thumbColor() const { return thumbColor_; };
+
+ void setShift(Position position);
+ void setThumbColor(const QColor &color)
+ {
+ thumbColor_ = color;
+ update();
+ };
+
+protected:
+ bool eventFilter(QObject *obj, QEvent *event) override;
+ void paintEvent(QPaintEvent *event) override;
+
+private:
+ void updateOffset();
+
+ Toggle *const toggle_;
+ QColor thumbColor_;
+
+ Position position_;
+ qreal offset_;
+};
+
+class ToggleTrack : public QWidget
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QColor trackColor WRITE setTrackColor READ trackColor)
+
+public:
+ ToggleTrack(Toggle *parent);
+
+ void setTrackColor(const QColor &color);
+ QColor trackColor() const { return trackColor_; };
+
+protected:
+ bool eventFilter(QObject *obj, QEvent *event) override;
+ void paintEvent(QPaintEvent *event) override;
+
+private:
+ Toggle *const toggle_;
+ QColor trackColor_;
+};
|