diff --git a/kstyle/CMakeLists.txt b/kstyle/CMakeLists.txt --- a/kstyle/CMakeLists.txt +++ b/kstyle/CMakeLists.txt @@ -5,7 +5,8 @@ Config GuiAddons ConfigWidgets - WindowSystem) + WindowSystem + IconThemes) find_package(Qt5 COMPONENTS Quick) set(BREEZE_HAVE_QTQUICK ${Qt5Quick_FOUND}) @@ -93,15 +94,17 @@ breezestyleplugin.cpp breezetileset.cpp breezewindowmanager.cpp + breezetoolsareamanager.cpp ) +kconfig_add_kcfg_files(breeze_PART_SRCS ../kdecoration/breezesettings.kcfgc) kconfig_add_kcfg_files(breeze_PART_SRCS breezestyleconfigdata.kcfgc) add_library(breeze MODULE ${breeze_PART_SRCS}) target_link_libraries(breeze Qt5::Core Qt5::Gui Qt5::Widgets Qt5::DBus) if( BREEZE_HAVE_QTQUICK ) target_link_libraries(breeze Qt5::Quick) endif() -target_link_libraries(breeze KF5::ConfigCore KF5::ConfigWidgets KF5::GuiAddons KF5::WindowSystem) +target_link_libraries(breeze KF5::ConfigCore KF5::ConfigWidgets KF5::GuiAddons KF5::WindowSystem KF5::IconThemes) target_link_libraries(breeze breezecommon5) if(KF5FrameworkIntegration_FOUND) diff --git a/kstyle/breeze.h b/kstyle/breeze.h --- a/kstyle/breeze.h +++ b/kstyle/breeze.h @@ -101,7 +101,7 @@ ScrollBar_DoubleButtonHeight = 2*ScrollBar_Extend, // toolbars - ToolBar_FrameWidth = 2, + ToolBar_FrameWidth = 6, ToolBar_HandleExtent = 10, ToolBar_HandleWidth = 6, ToolBar_SeparatorWidth = 8, diff --git a/kstyle/breezehelper.h b/kstyle/breezehelper.h --- a/kstyle/breezehelper.h +++ b/kstyle/breezehelper.h @@ -23,11 +23,13 @@ #include "breeze.h" #include "breezeanimationdata.h" +#include "breezesettings.h" #include "config-breeze.h" #include #include +#include #include #include @@ -53,6 +55,9 @@ //* pointer to shared config KSharedConfig::Ptr config() const; + //* pointer to kdecoration config + QSharedPointer decorationConfig() const; + //*@name color utilities //@{ @@ -245,6 +250,9 @@ //* generic shadow for ellipses void renderEllipseShadow( QPainter*, const QRectF&, const QColor& ) const; + + //* draw the tools area border + void renderToolsAreaBorder ( QPainter*, const QWidget*, bool menubar = false ) const; //@} @@ -263,6 +271,26 @@ //* returns true if a given widget supports alpha channel bool hasAlphaChannel( const QWidget* ) const; + //* returns true if widget is in the tools area + bool isInToolsArea( const QWidget* ) const; + + //* returns false if tools area is empty + bool toolsAreaHasContents ( const QWidget* ) const; + + //* returns true if tools area has a toolbar + bool toolsAreaHasToolBar ( const QWidget* ) const; + + //* returns true if the tools area should be drawn + bool shouldDrawToolsArea ( const QWidget* ) const; + + //* returns the tools area border color + QColor toolsAreaBorderColor ( const QWidget* ) const; + + //* returns the united rectangle of all toolbars in the tools area + QRect toolsAreaToolbarsRect (const QWidget* widget) const; + + QToolBar* grabToolBarForToolsArea ( const QWidget* ) const; + //@} //@name high dpi utility functions @@ -308,6 +336,9 @@ //* configuration KSharedConfig::Ptr _config; + //* decoration configuration + QSharedPointer _decorationConfig; + //*@name brushes //@{ KStatefulBrush _viewFocusBrush; diff --git a/kstyle/breezehelper.cpp b/kstyle/breezehelper.cpp --- a/kstyle/breezehelper.cpp +++ b/kstyle/breezehelper.cpp @@ -27,6 +27,7 @@ #include #include +#include #if BREEZE_HAVE_X11 #include @@ -42,21 +43,29 @@ //____________________________________________________________________ Helper::Helper( KSharedConfig::Ptr config ): - _config( std::move( config ) ) + _config( std::move( config ) ), + _decorationConfig( new InternalSettings() ) {} //____________________________________________________________________ KSharedConfig::Ptr Helper::config() const { return _config; } + + //____________________________________________________________________ + QSharedPointer Helper::decorationConfig() const + { return _decorationConfig; } + //____________________________________________________________________ void Helper::loadConfig() { _viewFocusBrush = KStatefulBrush( KColorScheme::View, KColorScheme::FocusColor ); _viewHoverBrush = KStatefulBrush( KColorScheme::View, KColorScheme::HoverColor ); _viewNegativeTextBrush = KStatefulBrush( KColorScheme::View, KColorScheme::NegativeText ); const QPalette palette( QApplication::palette() ); + _config->reparseConfiguration(); + _decorationConfig->load(); const KConfigGroup group( _config->group( "WM" ) ); _activeTitleBarColor = group.readEntry( "activeBackground", palette.color( QPalette::Active, QPalette::Highlight ) ); _activeTitleBarTextColor = group.readEntry( "activeForeground", palette.color( QPalette::Active, QPalette::HighlightedText ) ); @@ -1604,4 +1613,175 @@ return pixmap.devicePixelRatio(); } + bool Helper::isInToolsArea(const QWidget* widget) const + { + if (!shouldDrawToolsArea(widget)) return false; + + auto castedWidget = const_cast(widget); + + auto grabMainWindow = [](QWidget *widget) { + auto window = qobject_cast(widget->window()); + return window; + }; + auto checkToolbarInToolsArea = [this, grabMainWindow](QWidget* widget) { + auto toolbar = qobject_cast(widget); + + if (toolbar == nullptr) { + return false; + } + + QMainWindow* window; + if ((window = grabMainWindow(widget))) { + auto rect = this->toolsAreaToolbarsRect(widget); + if (widget->parentWidget() != widget->window()) return false; + if (toolbar->isFloating()) return false; + if (toolbar->orientation() == Qt::Vertical) return false; + if (window->toolBarArea(toolbar) != Qt::TopToolBarArea) return false; + if (window->width() != rect.width()) return false; + } + + return true; + }; + auto checkMenubarInToolsArea = [grabMainWindow](QWidget *widget) { + QMainWindow* window; + if ((window = grabMainWindow(widget))) { + if (window->menuWidget() == widget) { + return true; + } + } + + return false; + }; + + if (!widget) return false; + + if (!widget->isVisible()) { + return false; + } + if (widget->window()->windowType() == Qt::Dialog) { + return false; + } + + if (checkToolbarInToolsArea(castedWidget)) { + return true; + } else if (checkMenubarInToolsArea(castedWidget)) { + return true; + } else { + auto parent = castedWidget->parentWidget(); + while (parent != nullptr) { + if (checkToolbarInToolsArea(parent)) { + return true; + } + if (checkMenubarInToolsArea(parent)) { + return true; + } + parent = parent->parentWidget(); + } + } + + return false; + } + + QRect Helper::toolsAreaToolbarsRect (const QWidget* widget) const { + auto window = qobject_cast(widget->window()); + if (!window) return QRect(); + + QList widgets = window->findChildren(QString(), Qt::FindDirectChildrenOnly); + QRect rect = QRect(); + for (auto toolbar : widgets) { + if (window->toolBarArea(toolbar) == Qt::TopToolBarArea) { + rect = rect.united(toolbar->geometry()); + } + } + + return rect; + } + + bool Helper::toolsAreaHasToolBar (const QWidget* widget) const { + if (!shouldDrawToolsArea(widget)) return false; + + auto mainWindow = qobject_cast(widget->window()); + if (mainWindow == nullptr) { + return false; + } + + QList widgets = mainWindow->findChildren(QString(), Qt::FindDirectChildrenOnly); + for (auto widget : widgets) { + if (this->isInToolsArea(widget) == true) { + return true; + } + } + + return false; + } + + void Helper::renderToolsAreaBorder(QPainter* painter, const QWidget* widget, bool menubar) const { + if (!shouldDrawToolsArea(widget)) return; + + if (!menubar) { + auto rect = this->toolsAreaToolbarsRect(widget); + + if (rect.bottom() != widget->geometry().bottom()) return; + } + + painter->setPen(toolsAreaBorderColor(widget)); + painter->setRenderHints(QPainter::Antialiasing, false); + painter->setBrush(Qt::NoBrush); + + painter->drawLine( + widget->rect().left()*2, + widget->rect().bottom(), + widget->rect().right()*2, + widget->rect().bottom() + ); + } + + QToolBar* Helper::grabToolBarForToolsArea(const QWidget *widget) const { + auto mainWindow = qobject_cast(widget->window()); + if (mainWindow == nullptr) { + return nullptr; + } + + QList widgets = mainWindow->findChildren(QString(), Qt::FindDirectChildrenOnly); + for (auto widget : widgets) { + if (this->isInToolsArea(widget)) { + return widget; + } + } + + return nullptr; + } + + bool Helper::shouldDrawToolsArea(const QWidget* widget) const { + if (!widget) return false; + auto toolbar = qobject_cast(widget); + if (toolbar) { + if (toolbar->isFloating()) { + return false; + } + } + return (widget->window()->palette().color(QPalette::Window) != this->titleBarColor(true)); + } + + bool Helper::toolsAreaHasContents(const QWidget* widget) const { + QList widgets = widget->window()->findChildren(); + for (auto widget : widgets) { + if (this->isInToolsArea(widget)) { + return true; + } + } + return false; + } + + QColor Helper::toolsAreaBorderColor(const QWidget* widget) const { + QColor border( + KColorUtils::mix( + titleBarColor(widget->isActiveWindow()), + titleBarTextColor(widget->isActiveWindow()), + 0.5 + ) + ); + border.setAlpha(255); + return border; + } } diff --git a/kstyle/breezestyle.h b/kstyle/breezestyle.h --- a/kstyle/breezestyle.h +++ b/kstyle/breezestyle.h @@ -60,6 +60,7 @@ class WidgetExplorer; class WindowManager; class BlurHelper; + class ToolsAreaManager; //* convenience typedef for base class #if !BREEZE_HAVE_KSTYLE @@ -275,6 +276,7 @@ bool drawIndicatorToolBarHandlePrimitive( const QStyleOption*, QPainter*, const QWidget* ) const; bool drawIndicatorToolBarSeparatorPrimitive( const QStyleOption*, QPainter*, const QWidget* ) const; bool drawIndicatorBranchPrimitive( const QStyleOption*, QPainter*, const QWidget* ) const; + bool drawWidgetPrimitive( const QStyleOption*, QPainter*, const QWidget* ) const; //@} @@ -306,6 +308,8 @@ bool drawToolBoxTabLabelControl( const QStyleOption*, QPainter*, const QWidget* ) const; bool drawToolBoxTabShapeControl( const QStyleOption*, QPainter*, const QWidget* ) const; bool drawDockWidgetTitleControl( const QStyleOption*, QPainter*, const QWidget* ) const; + bool drawToolBarControl( const QStyleOption*, QPainter*, const QWidget* ) const; + bool drawMenuBarEmptyAreaControl( const QStyleOption*, QPainter*, const QWidget* ) const; //*@} @@ -497,6 +501,9 @@ //* splitter Factory, to extend splitters hit area SplitterFactory* _splitterFactory = nullptr; + //* signal manager for the tools area + ToolsAreaManager* _toolsAreaManager = nullptr; + //* widget explorer WidgetExplorer* _widgetExplorer = nullptr; diff --git a/kstyle/breezestyle.cpp b/kstyle/breezestyle.cpp --- a/kstyle/breezestyle.cpp +++ b/kstyle/breezestyle.cpp @@ -31,13 +31,17 @@ #include "breezewidgetexplorer.h" #include "breezewindowmanager.h" #include "breezeblurhelper.h" +#include "breezetoolsareamanager.h" #include +#include #include +#include #include #include #include +#include #include #include #include @@ -164,6 +168,7 @@ , _frameShadowFactory( new FrameShadowFactory( this ) ) , _mdiWindowShadowFactory( new MdiWindowShadowFactory( this ) ) , _splitterFactory( new SplitterFactory( this ) ) + , _toolsAreaManager ( new ToolsAreaManager( this, _helper ) ) , _widgetExplorer( new WidgetExplorer( this ) ) , _tabBarData( new BreezePrivate::TabBarData( this ) ) #if BREEZE_HAVE_KSTYLE @@ -183,6 +188,12 @@ QStringLiteral( "/BreezeDecoration" ), QStringLiteral( "org.kde.Breeze.Style" ), QStringLiteral( "reparseConfiguration" ), this, SLOT(configurationChanged()) ); + + dbus.connect( QString(), + QStringLiteral( "/KGlobalSettings" ), + QStringLiteral( "org.kde.KGlobalSettings" ), + QStringLiteral( "notifyChange" ), this, SLOT(configurationChanged()) ); + #if QT_VERSION < 0x050D00 // Check if Qt version < 5.13 this->addEventFilter(qApp); #else @@ -213,6 +224,7 @@ _mdiWindowShadowFactory->registerWidget( widget ); _shadowHelper->registerWidget( widget ); _splitterFactory->registerWidget( widget ); + _toolsAreaManager->registerWidget ( widget ); // enable mouse over effects for all necessary widgets if( @@ -350,8 +362,9 @@ setTranslucentBackground( widget ); + } else if ( qobject_cast (widget) || qobject_cast (widget) ) { + widget->setAttribute(Qt::WA_StyledBackground); } - // base class polishing ParentStyleClass::polish( widget ); @@ -439,6 +452,7 @@ _windowManager->unregisterWidget( widget ); _splitterFactory->unregisterWidget( widget ); _blurHelper->unregisterWidget( widget ); + _toolsAreaManager->unregisterWidget ( widget ); // remove event filter if( qobject_cast( widget ) || @@ -844,6 +858,7 @@ case PE_FrameTabBarBase: fcn = &Style::drawFrameTabBarBasePrimitive; break; case PE_FrameWindow: fcn = &Style::drawFrameWindowPrimitive; break; case PE_FrameFocusRect: fcn = _frameFocusPrimitive; break; + case PE_Widget: fcn = &Style::drawWidgetPrimitive; break; // fallback default: break; @@ -860,6 +875,25 @@ } + bool Style::drawWidgetPrimitive( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { + Q_UNUSED(option) + if (qobject_cast(widget) || qobject_cast (widget)) { + if (!_helper->toolsAreaHasContents(widget) && _helper->shouldDrawToolsArea(widget)) { + painter->setPen(_helper->toolsAreaBorderColor(widget)); + painter->setRenderHints(QPainter::Antialiasing, false); + painter->setBrush(Qt::NoBrush); + + painter->drawLine( + widget->rect().left()*2, + widget->rect().top(), + widget->rect().right()*2, + widget->rect().top() + ); + } + } + return true; + } + //______________________________________________________________ void Style::drawControl( ControlElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { @@ -882,10 +916,10 @@ case CE_RadioButtonLabel: fcn = &Style::drawCheckBoxLabelControl; break; case CE_ToolButtonLabel: fcn = &Style::drawToolButtonLabelControl; break; case CE_ComboBoxLabel: fcn = &Style::drawComboBoxLabelControl; break; - case CE_MenuBarEmptyArea: fcn = &Style::emptyControl; break; + case CE_MenuBarEmptyArea: fcn = &Style::drawMenuBarEmptyAreaControl; break; case CE_MenuBarItem: fcn = &Style::drawMenuBarItemControl; break; case CE_MenuItem: fcn = &Style::drawMenuItemControl; break; - case CE_ToolBar: fcn = &Style::emptyControl; break; + case CE_ToolBar: fcn = &Style::drawToolBarControl; break; case CE_ProgressBar: fcn = &Style::drawProgressBarControl; break; case CE_ProgressBarContents: fcn = &Style::drawProgressBarContentsControl; break; case CE_ProgressBarGroove: fcn = &Style::drawProgressBarGrooveControl; break; @@ -1331,6 +1365,12 @@ // reload configuration loadConfiguration(); + // load new titlebar colours into tools area animations + _toolsAreaManager->updateAnimations(); + + // trigger update of tools area + emit _toolsAreaManager->toolbarUpdated(); + } //____________________________________________________________________ @@ -4225,7 +4265,12 @@ // copy rect and palette const auto& rect = option->rect; - const auto& palette = option->palette; + auto palette = option->palette; + + if (_helper->isInToolsArea(widget)) { + palette.setColor(QPalette::ButtonText, _helper->titleBarTextColor(widget->isActiveWindow())); + palette.setColor(QPalette::WindowText, _helper->titleBarTextColor(widget->isActiveWindow())); + } // state const State& state( option->state ); @@ -4304,6 +4349,10 @@ // make sure there is enough room for icon if( iconRect.isValid() ) iconRect = centerRect( iconRect, iconSize ); + QPalette::ColorRole textRole( QPalette::ButtonText ); + if( flat ) textRole = ( ((hasFocus&&sunken) || (state & State_Sunken))&&!mouseOver) ? QPalette::HighlightedText: QPalette::WindowText; + else if( hasFocus&&!mouseOver ) textRole = QPalette::HighlightedText; + // render arrow or icon if( hasArrow && iconRect.isValid() ) { @@ -4329,19 +4378,20 @@ else if( mouseOver && flat ) iconMode = QIcon::Active; else iconMode = QIcon::Normal; - const QPixmap pixmap = toolButtonOption->icon.pixmap( iconSize, iconMode, iconState ); + QPixmap pixmap = toolButtonOption->icon.pixmap( iconSize, iconMode, iconState ); + if (_helper->isInToolsArea(widget)) { + KIconLoader::global()->setCustomPalette(widget->palette()); + pixmap = toolButtonOption->icon.pixmap( iconSize, iconMode, iconState ); + KIconLoader::global()->resetPalette(); + } drawItemPixmap( painter, iconRect, Qt::AlignCenter, pixmap ); } // render text if( hasText && textRect.isValid() ) { - QPalette::ColorRole textRole( QPalette::ButtonText ); - if( flat ) textRole = ( ((hasFocus&&sunken) || (state & State_Sunken))&&!mouseOver) ? QPalette::HighlightedText: QPalette::WindowText; - else if( hasFocus&&!mouseOver ) textRole = QPalette::HighlightedText; - painter->setFont(toolButtonOption->font); drawItemText( painter, textRect, textFlags, palette, enabled, toolButtonOption->text, textRole ); @@ -4509,15 +4559,28 @@ // copy rect and palette const auto& rect( option->rect ); - const auto& palette( option->palette ); + auto palette( option->palette ); + + palette.setColor(QPalette::WindowText, _helper->titleBarTextColor(widget->isActiveWindow())); // store state const State& state( option->state ); const bool enabled( state & State_Enabled ); const bool selected( enabled && (state & State_Selected) ); const bool sunken( enabled && (state & State_Sunken) ); const bool useStrongFocus( StyleConfigData::menuItemDrawStrongFocus() ); + painter->save(); + painter->setRenderHints( QPainter::Antialiasing ); + + painter->setPen(_helper->titleBarColor(widget->isActiveWindow())); + painter->setBrush(_helper->titleBarColor(widget->isActiveWindow())); + + QRectF copy(widget->geometry()); + copy.setTop(widget->childrenRect().top()); + + painter->drawRect(copy); + // render hover and focus if( useStrongFocus && ( selected || sunken ) ) { @@ -4596,8 +4659,13 @@ } - return true; + if (!_helper->toolsAreaHasToolBar(widget)) { + _helper->renderToolsAreaBorder(painter, widget, true); + } + + painter->restore(); + return true; } @@ -4817,6 +4885,64 @@ return true; } + bool Style::drawToolBarControl( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const + { + auto toolbar = const_cast(qobject_cast(widget)); + + if (!_helper->isInToolsArea(widget)) { + toolbar->setPalette(toolbar->parentWidget()->palette()); + return true; + } + + + auto palette = toolbar->palette(); + palette.setColor( QPalette::Window, _toolsAreaManager->background(widget) ); + palette.setColor( QPalette::WindowText, _toolsAreaManager->foreground(widget) ); + + toolbar->setPalette(palette); + + painter->save(); + painter->setRenderHints( QPainter::Antialiasing ); + + painter->setBrush(palette.color(QPalette::Window)); + painter->setPen(Qt::NoPen); + + QRectF copy(widget->geometry()); + copy.setTop(widget->childrenRect().top() - 10); + + painter->drawRect(copy); + + _helper->renderToolsAreaBorder(painter, widget); + + painter->restore(); + return true; + } + + bool Style::drawMenuBarEmptyAreaControl( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const + { + if (!_helper->isInToolsArea(widget)) { + return true; + } + + painter->save(); + painter->setRenderHints( QPainter::Antialiasing ); + + painter->setPen(_helper->titleBarColor(widget->isActiveWindow())); + painter->setBrush(_helper->titleBarColor(widget->isActiveWindow())); + + QRectF copy(widget->geometry()); + copy.setTop(widget->childrenRect().top()); + + painter->drawRect(copy); + + if (!_helper->toolsAreaHasToolBar(widget)) { + _helper->renderToolsAreaBorder(painter, widget, true); + } + + painter->restore(); + return true; + } + //___________________________________________________________________________________ bool Style::drawProgressBarControl( const QStyleOption* option, QPainter* painter, const QWidget* widget ) const { diff --git a/kstyle/breezetoolsareamanager.h b/kstyle/breezetoolsareamanager.h new file mode 100644 --- /dev/null +++ b/kstyle/breezetoolsareamanager.h @@ -0,0 +1,40 @@ +#ifndef breezetoolsareamanager_h +#define breezetoolsareamanager_h + +#include +#include +#include "breezehelper.h" + +namespace Breeze { + struct ToolsAreaAnimation { + QPointer foregroundColorAnimation; + QPointer backgroundColorAnimation; + bool prevActive; + }; + class ToolsAreaManager: public QObject + { + Q_OBJECT + + public: + explicit ToolsAreaManager(QObject *parent = nullptr, Helper* helper = nullptr); + ~ToolsAreaManager(); + void registerWidget(QWidget *widget); + void unregisterWidget(QWidget *widget); + void updateAnimations(); + + QColor foreground(const QWidget *widget); + QColor background(const QWidget *widget); + + QMap animationMap; + + Q_SIGNALS: + void toolbarUpdated(); + + private: + void registerAnimation( QWidget *widget ); + QList _registeredWidgets; + Helper* _helper; + }; +} + +#endif \ No newline at end of file diff --git a/kstyle/breezetoolsareamanager.cpp b/kstyle/breezetoolsareamanager.cpp new file mode 100644 --- /dev/null +++ b/kstyle/breezetoolsareamanager.cpp @@ -0,0 +1,177 @@ +#include "breezetoolsareamanager.h" +#include +#include +#include +#include +#include +#include + +namespace Breeze { + ToolsAreaManager::ToolsAreaManager(QObject *parent, Helper *helper) : QObject(parent), _helper(helper) { + + } + + ToolsAreaManager::~ToolsAreaManager() { + for (auto entry : animationMap) { + delete entry.foregroundColorAnimation; + delete entry.backgroundColorAnimation; + } + } + + void ToolsAreaManager::updateAnimations() { + for (auto entry : animationMap) { + entry.foregroundColorAnimation->setStartValue(_helper->titleBarTextColor(false)); + entry.foregroundColorAnimation->setEndValue(_helper->titleBarTextColor(true)); + + entry.backgroundColorAnimation->setStartValue(_helper->titleBarColor(false)); + entry.backgroundColorAnimation->setEndValue(_helper->titleBarColor(true)); + + entry.foregroundColorAnimation->setDuration( + _helper->decorationConfig()->animationsEnabled() ? + _helper->decorationConfig()->animationsDuration() : + 0 + ); + entry.backgroundColorAnimation->setDuration( + _helper->decorationConfig()->animationsEnabled() ? + _helper->decorationConfig()->animationsDuration() : + 0 + ); + } + } + + void ToolsAreaManager::registerAnimation(QWidget *widget) { + auto window = widget->window()->windowHandle(); + if (window && !animationMap.contains(window)) { + + auto foregroundColorAnimation = new QVariantAnimation(this); + connect(foregroundColorAnimation, &QVariantAnimation::valueChanged, + this, &ToolsAreaManager::toolbarUpdated); + + auto backgroundColorAnimation = new QVariantAnimation(this); + connect(backgroundColorAnimation, &QVariantAnimation::valueChanged, + this, &ToolsAreaManager::toolbarUpdated); + + foregroundColorAnimation->setStartValue(_helper->titleBarTextColor(false)); + foregroundColorAnimation->setEndValue(_helper->titleBarTextColor(true)); + + backgroundColorAnimation->setStartValue(_helper->titleBarColor(false)); + backgroundColorAnimation->setEndValue(_helper->titleBarColor(true)); + + foregroundColorAnimation->setDuration( + _helper->decorationConfig()->animationsEnabled() ? + _helper->decorationConfig()->animationsDuration() : + 0 + ); + backgroundColorAnimation->setDuration( + _helper->decorationConfig()->animationsEnabled() ? + _helper->decorationConfig()->animationsDuration() : + 0 + ); + + animationMap[window] = ToolsAreaAnimation{ + foregroundColorAnimation, + backgroundColorAnimation, + window->isActive(), + }; + + connect(window, &QWindow::activeChanged, + this, [=]() { + if (animationMap[window].foregroundColorAnimation.isNull() || animationMap[window].backgroundColorAnimation.isNull()) return; + + auto prevActive = animationMap[window].prevActive; + if (prevActive && !window->isActive()) { + animationMap[window].foregroundColorAnimation->setDirection(QAbstractAnimation::Backward); + animationMap[window].backgroundColorAnimation->setDirection(QAbstractAnimation::Backward); + + animationMap[window].foregroundColorAnimation->start(); + animationMap[window].backgroundColorAnimation->start(); + } else if (!prevActive && window->isActive()) { + animationMap[window].foregroundColorAnimation->setDirection(QAbstractAnimation::Forward); + animationMap[window].backgroundColorAnimation->setDirection(QAbstractAnimation::Forward); + + animationMap[window].foregroundColorAnimation->start(); + animationMap[window].backgroundColorAnimation->start(); + } + animationMap[window].prevActive = window->isActive(); + }); + + } + } + + QColor ToolsAreaManager::foreground(const QWidget *widget) { + auto window = widget->window()->windowHandle(); + if (window && animationMap.contains(window) && animationMap[window].foregroundColorAnimation) { + return animationMap[window].foregroundColorAnimation->currentValue().value(); + } + return QColor(); + } + + QColor ToolsAreaManager::background(const QWidget *widget) { + auto window = widget->window()->windowHandle(); + if (window && animationMap.contains(window) && animationMap[window].backgroundColorAnimation) { + return animationMap[window].backgroundColorAnimation->currentValue().value(); + } + return QColor(); + } + + + void ToolsAreaManager::registerWidget(QWidget *widget) + { + auto window = qobject_cast (widget); + if (window) { + connect(this, &ToolsAreaManager::toolbarUpdated, + window, [this, window]() { + if (_helper->toolsAreaHasContents(window)) { + window->setContentsMargins(0,0,0,0); + } else { + window->setContentsMargins(0,1,0,0); + } + }); + } + connect(this, &ToolsAreaManager::toolbarUpdated, + widget, [widget]() { + widget->update(); + }); + auto toolbar = qobject_cast(widget); + if (toolbar) { + connect(toolbar, &QToolBar::visibilityChanged, + this, [this]() { + emit this->toolbarUpdated(); + }); + connect(toolbar, &QToolBar::orientationChanged, + this, [this]() { + emit this->toolbarUpdated(); + }); + connect(toolbar, &QToolBar::topLevelChanged, + this, [this]() { + emit this->toolbarUpdated(); + }); + } + connect(widget, &QObject::destroyed, + this, [this, widget]() { + this->unregisterWidget(widget); + }); + registerAnimation(widget); + _registeredWidgets << widget; + emit this->toolbarUpdated(); + } + + void ToolsAreaManager::unregisterWidget(QWidget *widget) + { + _registeredWidgets.removeAll(widget); + QList toRemove; + for (auto window : animationMap.keys()) { + bool hasWidget = false; + if (std::none_of(_registeredWidgets.begin(), _registeredWidgets.end(), [window](QWidget *widget) { + return window == widget->window()->windowHandle(); + })) { + delete animationMap[window].foregroundColorAnimation; + delete animationMap[window].backgroundColorAnimation; + toRemove << window; + } + } + for (auto entry : toRemove) { + animationMap.remove(entry); + } + } +} \ No newline at end of file