mirror of
https://github.com/WarmUpTill/SceneSwitcher.git
synced 2026-03-21 17:34:57 -05:00
Rework section widget to support dynamically sized content
This commit is contained in:
parent
2454ea8fa5
commit
aa7714210a
|
|
@ -14,18 +14,30 @@ public:
|
|||
explicit Section(const int animationDuration = 300,
|
||||
QWidget *parent = 0);
|
||||
|
||||
void SetContent(QWidget *w);
|
||||
void SetContent(QWidget *w, bool collapsed = true);
|
||||
void AddHeaderWidget(QWidget *);
|
||||
|
||||
public slots:
|
||||
void Collapse(bool collapsed);
|
||||
protected:
|
||||
bool eventFilter(QObject *obj, QEvent *event) override;
|
||||
|
||||
private slots:
|
||||
void AnimationFinished();
|
||||
void Collapse(bool collapse);
|
||||
|
||||
private:
|
||||
void SetupAnimations();
|
||||
void CleanUpPreviousContent();
|
||||
|
||||
QGridLayout *_mainLayout;
|
||||
QHBoxLayout *_headerWidgetLayout;
|
||||
QToolButton *_toggleButton;
|
||||
QFrame *_headerLine;
|
||||
QParallelAnimationGroup *_toggleAnimation = nullptr;
|
||||
QParallelAnimationGroup *_contentAnimation = nullptr;
|
||||
QScrollArea *_contentArea = nullptr;
|
||||
QWidget *_content = nullptr;
|
||||
int _animationDuration;
|
||||
std::atomic_bool _transitioning = {false};
|
||||
int _headerHeight = 0;
|
||||
int _contentHeight = 0;
|
||||
};
|
||||
|
|
|
|||
149
src/section.cpp
149
src/section.cpp
|
|
@ -1,7 +1,9 @@
|
|||
#include <QPropertyAnimation>
|
||||
#include "headers/section.hpp"
|
||||
#include "headers/utility.hpp"
|
||||
|
||||
#include <QPropertyAnimation>
|
||||
#include <QEvent>
|
||||
|
||||
Section::Section(const int animationDuration, QWidget *parent)
|
||||
: QWidget(parent), _animationDuration(animationDuration)
|
||||
{
|
||||
|
|
@ -38,18 +40,102 @@ Section::Section(const int animationDuration, QWidget *parent)
|
|||
connect(_toggleButton, &QToolButton::toggled, this, &Section::Collapse);
|
||||
}
|
||||
|
||||
void Section::Collapse(bool collapsed)
|
||||
void Section::Collapse(bool collapse)
|
||||
{
|
||||
_toggleButton->setChecked(collapsed);
|
||||
_toggleButton->setArrowType(!collapsed ? Qt::ArrowType::DownArrow
|
||||
: Qt::ArrowType::RightArrow);
|
||||
_toggleAnimation->setDirection(!collapsed
|
||||
_toggleButton->setChecked(collapse);
|
||||
_toggleButton->setArrowType(!collapse ? Qt::ArrowType::DownArrow
|
||||
: Qt::ArrowType::RightArrow);
|
||||
_toggleAnimation->setDirection(!collapse
|
||||
? QAbstractAnimation::Forward
|
||||
: QAbstractAnimation::Backward);
|
||||
_transitioning = true;
|
||||
_toggleAnimation->start();
|
||||
}
|
||||
|
||||
void Section::SetContent(QWidget *w)
|
||||
void Section::SetContent(QWidget *w, bool collapsed)
|
||||
{
|
||||
CleanUpPreviousContent();
|
||||
delete _contentArea;
|
||||
|
||||
// Setup contentArea
|
||||
_contentArea = new QScrollArea(this);
|
||||
_contentArea->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
||||
_contentArea->setStyleSheet("QScrollArea { border: none; }");
|
||||
_contentArea->setMaximumHeight(0);
|
||||
_contentArea->setMinimumHeight(0);
|
||||
|
||||
w->installEventFilter(this);
|
||||
_content = w;
|
||||
auto newLayout = new QVBoxLayout();
|
||||
newLayout->setContentsMargins(0, 0, 0, 0);
|
||||
newLayout->addWidget(w);
|
||||
_contentArea->setLayout(newLayout);
|
||||
_mainLayout->addWidget(_contentArea, 1, 0, 1, 3);
|
||||
|
||||
_headerHeight = sizeHint().height() - _contentArea->maximumHeight();
|
||||
_contentHeight = newLayout->sizeHint().height();
|
||||
|
||||
if (collapsed) {
|
||||
this->setMinimumHeight(_headerHeight);
|
||||
_contentArea->setMaximumHeight(0);
|
||||
} else {
|
||||
this->setMinimumHeight(_headerHeight + _contentHeight);
|
||||
_contentArea->setMaximumHeight(_contentHeight);
|
||||
}
|
||||
SetupAnimations();
|
||||
Collapse(collapsed);
|
||||
}
|
||||
|
||||
void Section::AddHeaderWidget(QWidget *w)
|
||||
{
|
||||
_headerWidgetLayout->addWidget(w);
|
||||
}
|
||||
|
||||
bool Section::eventFilter(QObject *obj, QEvent *event)
|
||||
{
|
||||
if (event->type() == QEvent::Resize && !_transitioning) {
|
||||
_contentHeight = _content->sizeHint().height();
|
||||
setMaximumHeight(_headerHeight + _contentHeight);
|
||||
setMinimumHeight(_headerHeight + _contentHeight);
|
||||
_contentArea->setMaximumHeight(_contentHeight);
|
||||
SetupAnimations();
|
||||
}
|
||||
return QObject::eventFilter(obj, event);
|
||||
}
|
||||
|
||||
void Section::SetupAnimations()
|
||||
{
|
||||
delete _toggleAnimation;
|
||||
|
||||
_toggleAnimation = new QParallelAnimationGroup(this);
|
||||
_toggleAnimation->addAnimation(
|
||||
new QPropertyAnimation(this, "minimumHeight"));
|
||||
_toggleAnimation->addAnimation(
|
||||
new QPropertyAnimation(this, "maximumHeight"));
|
||||
_toggleAnimation->addAnimation(
|
||||
new QPropertyAnimation(_contentArea, "maximumHeight"));
|
||||
|
||||
for (int i = 0; i < _toggleAnimation->animationCount() - 1; ++i) {
|
||||
QPropertyAnimation *SectionAnimation =
|
||||
static_cast<QPropertyAnimation *>(
|
||||
_toggleAnimation->animationAt(i));
|
||||
SectionAnimation->setDuration(_animationDuration);
|
||||
SectionAnimation->setStartValue(_headerHeight);
|
||||
SectionAnimation->setEndValue(_headerHeight + _contentHeight);
|
||||
}
|
||||
|
||||
QPropertyAnimation *contentAnimation =
|
||||
static_cast<QPropertyAnimation *>(_toggleAnimation->animationAt(
|
||||
_toggleAnimation->animationCount() - 1));
|
||||
contentAnimation->setDuration(_animationDuration);
|
||||
contentAnimation->setStartValue(0);
|
||||
contentAnimation->setEndValue(_contentHeight);
|
||||
|
||||
QWidget::connect(_toggleAnimation, SIGNAL(finished()), this,
|
||||
SLOT(AnimationFinished()));
|
||||
}
|
||||
|
||||
void Section::CleanUpPreviousContent()
|
||||
{
|
||||
// Clean up previous content
|
||||
if (_contentArea) {
|
||||
|
|
@ -59,54 +145,9 @@ void Section::SetContent(QWidget *w)
|
|||
delete oldLayout;
|
||||
}
|
||||
}
|
||||
|
||||
delete _contentArea;
|
||||
delete _toggleAnimation;
|
||||
|
||||
// Setup contentArea
|
||||
_contentArea = new QScrollArea(this);
|
||||
_contentArea->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
||||
|
||||
// Start out collapsed
|
||||
_contentArea->setMaximumHeight(0);
|
||||
_contentArea->setMinimumHeight(0);
|
||||
|
||||
auto newLayout = new QVBoxLayout();
|
||||
newLayout->addWidget(w);
|
||||
_contentArea->setLayout(newLayout);
|
||||
_mainLayout->addWidget(_contentArea, 1, 0, 1, 3);
|
||||
|
||||
// Animation Setup
|
||||
_toggleAnimation = new QParallelAnimationGroup(this);
|
||||
_toggleAnimation->addAnimation(
|
||||
new QPropertyAnimation(this, "minimumHeight"));
|
||||
_toggleAnimation->addAnimation(
|
||||
new QPropertyAnimation(this, "maximumHeight"));
|
||||
_toggleAnimation->addAnimation(
|
||||
new QPropertyAnimation(_contentArea, "maximumHeight"));
|
||||
|
||||
const auto collapsedHeight =
|
||||
sizeHint().height() - _contentArea->maximumHeight();
|
||||
auto contentHeight = newLayout->sizeHint().height();
|
||||
|
||||
for (int i = 0; i < _toggleAnimation->animationCount() - 1; ++i) {
|
||||
QPropertyAnimation *SectionAnimation =
|
||||
static_cast<QPropertyAnimation *>(
|
||||
_toggleAnimation->animationAt(i));
|
||||
SectionAnimation->setDuration(_animationDuration);
|
||||
SectionAnimation->setStartValue(collapsedHeight);
|
||||
SectionAnimation->setEndValue(collapsedHeight + contentHeight);
|
||||
}
|
||||
|
||||
QPropertyAnimation *contentAnimation =
|
||||
static_cast<QPropertyAnimation *>(_toggleAnimation->animationAt(
|
||||
_toggleAnimation->animationCount() - 1));
|
||||
contentAnimation->setDuration(_animationDuration);
|
||||
contentAnimation->setStartValue(0);
|
||||
contentAnimation->setEndValue(contentHeight);
|
||||
}
|
||||
|
||||
void Section::AddHeaderWidget(QWidget *w)
|
||||
void Section::AnimationFinished()
|
||||
{
|
||||
_headerWidgetLayout->addWidget(w);
|
||||
_transitioning = false;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user