From 88269df8fd9f3043b25d04716a206401a1faa67e Mon Sep 17 00:00:00 2001 From: Linloir <3145078758@qq.com> Date: Fri, 16 Dec 2022 11:12:45 +0800 Subject: [PATCH] [UI] Sidebar update - New side bar - Fix button size - Fix expand / collapse animation --- FinalProject/sidebar.cpp | 286 +++++++++++++++++++++++++++++++++++++++ FinalProject/sidebar.h | 63 +++++++++ 2 files changed, 349 insertions(+) create mode 100644 FinalProject/sidebar.cpp create mode 100644 FinalProject/sidebar.h diff --git a/FinalProject/sidebar.cpp b/FinalProject/sidebar.cpp new file mode 100644 index 0000000..fa3118d --- /dev/null +++ b/FinalProject/sidebar.cpp @@ -0,0 +1,286 @@ +#pragma once + +#include +#include +#include +#include + +#include "sidebar.h" + +SideBar::SideBar(QWidget* parent) + : QWidget(parent) +{ + setAttribute(Qt::WA_StyledBackground, true); + setMaximumWidth(_collapsedWidth); + + // Create stylesheet + setObjectName("sideBar"); + QString sideBarStyleSheet = "QWidget#sideBar{background-color:" + _backgroundColor.name() + "; }"; + setStyleSheet(sideBarStyleSheet); + + // Create main layout + _mainLayout = new QVBoxLayout(this); + _mainLayout->setSpacing(8); + _mainLayout->setContentsMargins(16, 16, 16, 16); + _mainLayout->setAlignment(Qt::AlignTop | Qt::AlignLeft); + _mainLayout->addSpacing(8); // Add the top spacing between the expand button and the window edge + + // Create expand button + _expandButton = new PushButton(nullptr, this); + _expandButton->setMargin(18, 16, 18, 16); + _expandButton->setIndicatorColor(QColor(255, 255, 255, 0)); // Set indicator to transparent + _expandButton->setHoverColor(QColor(0, 0, 0, 10)); + _expandButton->setPressedColor(QColor(0, 0, 0, 20)); + int buttonSize = _collapsedWidth - _mainLayout->contentsMargins().left() - _mainLayout->contentsMargins().right(); + int buttonSizeMax = _expandedWidth - _mainLayout->contentsMargins().left() - _mainLayout->contentsMargins().right(); + _expandButton->setMinimumSize(buttonSize, buttonSize); + _expandButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum); + _expandButtonIcon = new QLabel(_expandButton); + _expandButtonIcon->setFont(QFont("Font Awesome 6 Free Solid", 14)); + _expandButtonIcon->setText("\uf0c9"); + _expandButton->setChildWidget(_expandButtonIcon); + + // Connect the expand button event to expand / collapse event + connect(_expandButton, &PushButton::onClick, this, [=]() { + if (_expanded) { + collapse(); + } + else { + expand(); + } + }); + + // Add expand button to main layout + _mainLayout->addWidget(_expandButton); + _expandButton->show(); + + // Create the page icon button container widget + _pageIconButtonWidget = new QWidget(this); + _pageIconButtonWidget->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); + _pageIconButtonLayout = new QVBoxLayout(_pageIconButtonWidget); + _pageIconButtonLayout->setSpacing(8); + _pageIconButtonLayout->setContentsMargins(0, 0, 0, 0); + _pageIconButtonLayout->setAlignment(Qt::AlignTop | Qt::AlignLeft); + _pageIconButtonWidget->setLayout(_pageIconButtonLayout); + + // Create the page text button container widget + _pageTextButtonWidget = new QWidget(this); + _pageTextButtonWidget->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); + _pageTextButtonLayout = new QVBoxLayout(_pageTextButtonWidget); + _pageTextButtonLayout->setSpacing(8); + _pageTextButtonLayout->setContentsMargins(0, 0, 0, 0); + _pageTextButtonLayout->setAlignment(Qt::AlignTop | Qt::AlignLeft); + _pageTextButtonWidget->setLayout(_pageTextButtonLayout); + + // Add page icon and text button container widgets to main layout + _mainLayout->addWidget(_pageIconButtonWidget); + _mainLayout->addWidget(_pageTextButtonWidget); + + // Display the icon buttons + _pageIconButtonWidget->show(); + _pageTextButtonWidget->hide(); +} + +SideBar::~SideBar() {} + +void SideBar::expand() { + // Add animation to expand the side bar + QPropertyAnimation* expandAnimation = new QPropertyAnimation(this, "maximumWidth"); + expandAnimation->setDuration(200); + expandAnimation->setEasingCurve(QEasingCurve::InOutQuad); + expandAnimation->setStartValue(width()); + expandAnimation->setEndValue(_expandedWidth); + expandAnimation->start(QAbstractAnimation::DeleteWhenStopped); + + // Show the page text buttons + _pageIconButtonWidget->hide(); + _pageTextButtonWidget->show(); + + // Set the expand state + _expanded = true; +} + +void SideBar::collapse() { + // Add animation to collapse the side bar + QPropertyAnimation* collapseAnimation = new QPropertyAnimation(this, "maximumWidth"); + collapseAnimation->setDuration(200); + collapseAnimation->setEasingCurve(QEasingCurve::InOutQuad); + collapseAnimation->setStartValue(width()); + collapseAnimation->setEndValue(_collapsedWidth); + collapseAnimation->start(QAbstractAnimation::DeleteWhenStopped); + + // Show the page icon buttons + _pageIconButtonWidget->show(); + _pageTextButtonWidget->hide(); + + // Set the expand state + _expanded = false; +} + +void SideBar::setBackgroundColor(QColor color) { + _backgroundColor = color; + QString sideBarStyleSheet = "QWidget#sideBar{background-color:" + _backgroundColor.name() + "; }"; + setStyleSheet(sideBarStyleSheet); +} + +void SideBar::setExpandedWidth(int width) { + if (width <= 0) { + return; + } + _expandedWidth = width; +} + +void SideBar::setCollapsedWidth(int width) { + if (width <= 0) { + return; + } + _collapsedWidth = width; +} + +void SideBar::selectPage(PageWidget* page) { + // Check for input validity + if (page == nullptr) { + return; + } + + // Deselect current page if there is one + if (_currentPage != nullptr) { + // Find the buttons of the current page + int index = _pageList.indexOf(_currentPage); + PushButton* currentPageIconButton = _pageButtonList.at(index).first; + PushButton* currentPageTextButton = _pageButtonList.at(index).second; + + // Deselect both the buttons + currentPageIconButton->deselect(); + currentPageTextButton->deselect(); + } + + // Temporarily store the current page + PageWidget* previousPage = _currentPage; + + // Select the new page + int index = _pageList.indexOf(page); + PushButton* newPageIconButton = _pageButtonList.at(index).first; + PushButton* newPageTextButton = _pageButtonList.at(index).second; + newPageIconButton->select(); + newPageTextButton->select(); + _currentPage = page; + + // Emit the page selected signal + emit onPageChanged(previousPage, page); +} + +void SideBar::addPage(PageWidget* page) { + // Call on the page's get button method to get icon button & text button + PushButton* iconButton = page->getPageIconButton(_pageIconButtonWidget); + PushButton* textButton = page->getPageTextButton(_pageTextButtonWidget); + + // Store the page in the page list + _pageList.append(page); + + // Store the corresponding buttons + _pageButtonList.append(QPair(iconButton, textButton)); + + // Add the icon button to the icon button layout + _pageIconButtonLayout->addWidget(iconButton); + iconButton->show(); + + // Add the text button to the text button layout + _pageTextButtonLayout->addWidget(textButton); + textButton->show(); + + // Resize the buttons and set size policy to fixed + int buttonSize = _collapsedWidth - _mainLayout->contentsMargins().left() - _mainLayout->contentsMargins().right(); + int buttonSizeMax = _expandedWidth - _mainLayout->contentsMargins().left() - _mainLayout->contentsMargins().right(); + iconButton->setMinimumSize(buttonSize, buttonSize); + textButton->setMinimumSize(buttonSize, buttonSize); + iconButton->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); + textButton->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); + + // Connect the button click event with page selection + connect(iconButton, &PushButton::onClick, this, [=]() { + selectPage(page); + }); + connect(textButton, &PushButton::onClick, this, [=]() { + selectPage(page); + }); + + // Select the page if there are no pages + if (_currentPage == nullptr) { + selectPage(page); + } +} + +void SideBar::insertPage(PageWidget* page, int index) { + // Call on the page's get button method to get icon button & text button + PushButton* iconButton = page->getPageIconButton(_pageIconButtonWidget); + PushButton* textButton = page->getPageTextButton(_pageTextButtonWidget); + + // Store the page + _pageList.insert(index, page); + + // Store the corresponding buttons + _pageButtonList.insert(index, QPair(iconButton, textButton)); + + // Add the icon button to the icon button layout + _pageIconButtonLayout->insertWidget(index, iconButton); + iconButton->show(); + + // Add the text button to the text button layout + _pageTextButtonLayout->insertWidget(index, textButton); + textButton->show(); + + // Resize the buttons and set size policy to fixed + int buttonSize = _collapsedWidth - _mainLayout->contentsMargins().left() - _mainLayout->contentsMargins().right(); + int buttonSizeMax = _expandedWidth - _mainLayout->contentsMargins().left() - _mainLayout->contentsMargins().right(); + iconButton->setMinimumSize(buttonSize, buttonSize); + textButton->setMinimumSize(buttonSize, buttonSize); + iconButton->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); + textButton->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); + + // Connect the button click event with page selection + connect(iconButton, &PushButton::onClick, this, [=]() { + selectPage(page); + }); + connect(textButton, &PushButton::onClick, this, [=]() { + selectPage(page); + }); + + // Select the page if there are no pages + if (_currentPage == nullptr) { + selectPage(page); + } +} + +void SideBar::removePage(PageWidget* page) { + // Get the index of the page from the page list + int index = _pageList.indexOf(page); + + // Get the corresponding buttons + PushButton* iconButton = _pageButtonList.at(index).first; + PushButton* textButton = _pageButtonList.at(index).second; + + // Remove the page from the list + _pageList.removeAt(index); + + // Remove the icon and text buttons from the list + _pageButtonList.removeAt(index); + + // Remove the icon button from the icon button layout + _pageIconButtonLayout->removeWidget(iconButton); + iconButton->hide(); + + // Remove the text button from the text button layout + _pageTextButtonLayout->removeWidget(textButton); + textButton->hide(); + + // Select the first page if the current page is the page being removed + if (_currentPage == page) { + if (_pageList.size() > 0) { + selectPage(_pageList.first()); + } + else { + _currentPage = nullptr; + } + } +} diff --git a/FinalProject/sidebar.h b/FinalProject/sidebar.h new file mode 100644 index 0000000..231959a --- /dev/null +++ b/FinalProject/sidebar.h @@ -0,0 +1,63 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +#include "pushbutton.h" +#include "pagewidget.h" + +class SideBar : public QWidget +{ + Q_OBJECT + +public: + SideBar(QWidget* parent = 0); + ~SideBar(); + +private: + // Initialized flag + bool _initialized = false; + + // UI control variables + QColor _backgroundColor = QColor(230, 230, 230); + int _collapsedWidth = 90; + int _expandedWidth = 200; + + // UI widgets + PushButton* _expandButton; + QLabel* _expandButtonIcon; + QVBoxLayout* _mainLayout = nullptr; // Layout expand icon and page selection buttons + QWidget* _pageIconButtonWidget = nullptr; // Container for page icon buttons + QVBoxLayout* _pageIconButtonLayout = nullptr; // Layout page icon buttons + QWidget* _pageTextButtonWidget = nullptr; // Container for page text buttons + QVBoxLayout* _pageTextButtonLayout = nullptr; // Layout page text buttons + + // Interaction controls + bool _expanded = false; + PageWidget* _currentPage = nullptr; + + // State storage + // QMap> _pageButtonMap; + QList _pageList; + QList> _pageButtonList; + +private: + void expand(); + void collapse(); + void selectPage(PageWidget* page); + +public: + void setBackgroundColor(QColor color); + void setCollapsedWidth(int width); + void setExpandedWidth(int width); + void addPage(PageWidget* page); + void insertPage(PageWidget* page, int index); + void removePage(PageWidget* page); + +signals: + void onPageChanged(PageWidget* previousPage, PageWidget* currentPage); +};