QskSubWindow titleBar improvements

This commit is contained in:
Uwe Rathmann 2018-10-29 20:11:48 +01:00
parent 85f816e42d
commit 5da92830df
8 changed files with 292 additions and 65 deletions

View File

@ -22,20 +22,25 @@
class SubWindow : public QskSubWindow
{
public:
SubWindow( const QString& graphicSource, QQuickItem* parent = nullptr )
SubWindow( const QString& iconSource, QQuickItem* parent = nullptr )
: QskSubWindow( parent )
{
setObjectName( graphicSource );
setObjectName( iconSource );
const QUrl url( iconSource );
setWindowTitle( url.fileName() );
setWindowIconSource( url );
auto label = new QskGraphicLabel( this );
label->setSource( graphicSource );
label->setSource( iconSource );
label->setAlignment( Qt::AlignCenter );
setSizePolicy( QskSizePolicy::MinimumExpanding,
QskSizePolicy::MinimumExpanding );
QskShortcutMap::addShortcut( this, QKeySequence( Qt::Key_P ), true,
[ graphicSource ] { qDebug() << graphicSource; } );
[ iconSource ] { qDebug() << iconSource; } );
}
};

View File

@ -655,8 +655,9 @@ void QskMaterialSkin::initSubWindowHints()
const ColorPalette& pal = m_data->palette;
// panel
// Panel
setSkinHint( Q::Panel | Decoration, true );
setMargins( Q::Panel | Padding, 10 );
setBoxShape( Q::Panel, 0 );
setBoxBorderMetrics( Q::Panel, 2 );
@ -668,11 +669,19 @@ void QskMaterialSkin::initSubWindowHints()
setBoxBorderColors( Q::Panel, colors );
// title bar
// TitleBar
setGradient( Q::TitleBar, pal.darker200 );
setGradient( Q::TitleBar | Q::Focused, pal.accentColor );
setFontRole( Q::TitleBar, QskSkin::TinyFont );
// TitleBarText
setFontRole( Q::TitleBarText, QskSkin::SmallFont );
setSkinHint( Q::TitleBarText | Alignment,
static_cast<int>( Qt::AlignLeft | Qt::AlignVCenter ) );
for ( auto subControl : { Q::Panel, Q::TitleBar, Q::TitleBarText } )
setAnimation( subControl | Color, qskDuration );
}
#include "moc_QskMaterialSkin.cpp"

View File

@ -739,11 +739,14 @@ void QskSquiekSkin::initSubWindowHints()
const ColorPalette& pal = m_data->palette;
const qreal radius = 5.0;
// Panel
setSkinHint( Q::Panel | Decoration, true );
setMargins( Q::Panel | Padding, 10 );
setBoxBorderMetrics( Q::Panel, 2 );
setBoxShape( Q::Panel, 0 );
setBoxShape( Q::Panel, radius, radius, 0, 0, Qt::AbsoluteSize );
QskBoxBorderColors borderColors;
borderColors.setColorsAt( Qt::TopEdge | Qt::LeftEdge, pal.lighter125 );
@ -754,9 +757,22 @@ void QskSquiekSkin::initSubWindowHints()
// TitleBar
setFontRole( Q::TitleBar, QskSkin::TinyFont );
setGradient( Q::TitleBar | Q::Focused, pal.highlighted );
setGradient( Q::TitleBar, pal.contrasted );
setMetric( Q::TitleBar | Spacing, 5 );
setMetric( Q::TitleBar | MinimumHeight, 20 );
setBoxShape( Q::TitleBar, radius, radius, 0, 0, Qt::AbsoluteSize );
// TitleBarText
setFontRole( Q::TitleBarText, QskSkin::SmallFont );
setColor( Q::TitleBarText | Q::Focused, pal.highlightedText );
setColor( Q::TitleBarText, pal.themeForeground );
setSkinHint( Q::TitleBarText | Alignment,
static_cast<int>( Qt::AlignLeft | Qt::AlignVCenter ) );
for ( auto subControl : { Q::Panel, Q::TitleBar, Q::TitleBarText } )
setAnimation( subControl | Color, qskDuration );
}
#include "moc_QskSquiekSkin.cpp"

View File

@ -6,24 +6,41 @@
#include "QskSubWindow.h"
#include "QskAspect.h"
#include "QskFunctions.h"
#include "QskGraphic.h"
#include "QskGraphicProvider.h"
#include "QskTextOptions.h"
#include "QskQuick.h"
#include <qurl.h>
QSK_SUBCONTROL( QskSubWindow, Panel )
QSK_SUBCONTROL( QskSubWindow, TitleBar )
QSK_SUBCONTROL( QskSubWindow, TitleBarSymbol )
QSK_SUBCONTROL( QskSubWindow, TitleBarText )
class QskSubWindow::PrivateData
{
public:
PrivateData()
: isWindowIconSourceDirty( false )
{
// should be available from the platform somehow. TODO ...
windowButtons = QskSubWindow::WindowButtons( QskSubWindow::MinimizeButton |
QskSubWindow::MaximizeButton | QskSubWindow::CloseButton );
windowTitleTextOptions.setElideMode( Qt::ElideRight );
}
QskSubWindow::WindowButtons windowButtons;
QString title;
QString windowTitle;
QskTextOptions windowTitleTextOptions;
QUrl windowIconSource;
QskGraphic windowIcon;
bool isWindowIconSourceDirty : 1;
};
QskSubWindow::QskSubWindow( QQuickItem* parent )
@ -45,7 +62,7 @@ void QskSubWindow::setDecorated( bool on )
if ( on == isDecorated() )
return;
const auto subControl = effectiveSubcontrol( QskSubWindow::TitleBar );
const auto subControl = effectiveSubcontrol( QskSubWindow::Panel );
setFlagHint( subControl | QskAspect::Decoration, on );
resetImplicitSize(); // in case some parent wants to layout
@ -58,23 +75,93 @@ void QskSubWindow::setDecorated( bool on )
bool QskSubWindow::isDecorated() const
{
return flagHint< bool >( TitleBar | QskAspect::Decoration, true );
return flagHint< bool >( Panel | QskAspect::Decoration, true );
}
void QskSubWindow::setTitle( const QString& title )
void QskSubWindow::setWindowTitle( const QString& title )
{
if ( m_data->title != title )
if ( m_data->windowTitle != title )
{
m_data->title = title;
Q_EMIT titleChanged();
m_data->windowTitle = title;
Q_EMIT windowTitleChanged();
}
}
QString QskSubWindow::title() const
QString QskSubWindow::windowTitle() const
{
return m_data->title;
return m_data->windowTitle;
}
void QskSubWindow::setWindowTitleTextOptions( const QskTextOptions& options )
{
if ( options != m_data->windowTitleTextOptions )
{
m_data->windowTitleTextOptions = options;
update();
Q_EMIT windowTitleTextOptionsChanged();
}
}
QskTextOptions QskSubWindow::windowTitleTextOptions() const
{
return m_data->windowTitleTextOptions;
}
void QskSubWindow::setWindowIconSource( const QUrl& url )
{
if ( m_data->windowIconSource == url )
return;
m_data->windowIconSource = url;
m_data->windowIcon.reset();
m_data->isWindowIconSourceDirty = true;
polish();
update();
Q_EMIT windowIconSourceChanged();
}
QUrl QskSubWindow::windowIconSource() const
{
return m_data->windowIconSource;
}
void QskSubWindow::setWindowIcon( const QskGraphic& graphic )
{
if ( graphic != m_data->windowIcon )
{
m_data->windowIcon = graphic;
if ( !m_data->windowIconSource.isEmpty() )
{
m_data->windowIconSource = QString();
m_data->isWindowIconSourceDirty = false;
Q_EMIT windowIconSourceChanged();
}
polish();
update();
Q_EMIT windowIconChanged();
}
}
QskGraphic QskSubWindow::windowIcon() const
{
return m_data->windowIcon;
}
bool QskSubWindow::hasWindowIcon() const
{
return !( windowIcon().isEmpty() && windowIconSource().isEmpty() );
}
void QskSubWindow::setWindowButtons( WindowButtons buttons )
{
if ( buttons != m_data->windowButtons )
@ -122,6 +209,22 @@ bool QskSubWindow::event( QEvent* event )
return Inherited::event( event );
}
void QskSubWindow::updateLayout()
{
if ( m_data->isWindowIconSourceDirty )
{
if ( !m_data->windowIconSource.isEmpty() )
{
m_data->windowIcon = Qsk::loadGraphic( m_data->windowIconSource );
Q_EMIT windowIconChanged();
}
m_data->isWindowIconSourceDirty = false;
}
Inherited::updateLayout();
}
QRectF QskSubWindow::layoutRect() const
{
QRectF rect = contentsRect();
@ -135,36 +238,20 @@ QRectF QskSubWindow::layoutRect() const
QSizeF QskSubWindow::contentsSizeHint() const
{
qreal w = -1;
qreal h = -1;
const auto children = childItems();
for ( auto child : children )
{
if ( qskIsTransparentForPositioner( child ) )
continue;
const QskControl* control = qobject_cast< QskControl* >( child );
if ( control )
{
const QSizeF sz = control->sizeHint();
w = qMax( w, sz.width() );
h = qMax( h, sz.height() );
}
}
// the size we get from the children
auto hint = Inherited::contentsSizeHint();
#if 1
// should be Minimum Width/Height from the hints
if ( w < 0 )
w = qskDpiScaled( 100 );
if ( hint.width() < 0 )
hint.setWidth( qskDpiScaled( 100 ) );
if ( h < 0 )
h = qskDpiScaled( 80 );
if ( hint.height() < 0 )
hint.setHeight( qskDpiScaled( 80 ) );
#endif
QSizeF hint = outerBoxSize( Panel, QSizeF( w, h ) );
hint.setHeight( hint.height() + titleBarRect().height() );
hint = outerBoxSize( Panel, hint );
hint.setHeight( hint.height() + subControlRect( TitleBar ).height() );
return hint;
}

View File

@ -8,6 +8,10 @@
#include "QskPopup.h"
class QskGraphic;
class QskTextOptions;
class QUrl;
class QSK_EXPORT QskSubWindow : public QskPopup
{
Q_OBJECT
@ -15,8 +19,17 @@ class QSK_EXPORT QskSubWindow : public QskPopup
Q_PROPERTY( bool decorated READ isDecorated
WRITE setDecorated NOTIFY decoratedChanged )
Q_PROPERTY( QString title READ title
WRITE setTitle NOTIFY titleChanged )
Q_PROPERTY( QString windowTitle READ windowTitle
WRITE setWindowTitle NOTIFY windowTitleChanged )
Q_PROPERTY( QskTextOptions windowTitleTextOptions READ windowTitleTextOptions
WRITE setWindowTitleTextOptions NOTIFY windowTitleTextOptionsChanged )
Q_PROPERTY( QUrl windowIconSource READ windowIconSource
WRITE setWindowIconSource NOTIFY windowIconSourceChanged )
Q_PROPERTY( QskGraphic windowIcon READ windowIcon
WRITE setWindowIcon NOTIFY windowIconChanged FINAL )
Q_PROPERTY( WindowButtons windowButtons READ windowButtons
WRITE setWindowButtons NOTIFY windowButtonsChanged )
@ -34,22 +47,33 @@ class QSK_EXPORT QskSubWindow : public QskPopup
Q_ENUM( WindowButton )
Q_DECLARE_FLAGS( WindowButtons, WindowButton )
QSK_SUBCONTROLS( Panel, TitleBar )
QSK_SUBCONTROLS( Panel, TitleBar, TitleBarSymbol, TitleBarText )
QskSubWindow( QQuickItem* parent = nullptr );
~QskSubWindow() override;
Q_INVOKABLE void setTitle( const QString& );
Q_INVOKABLE QString title() const;
void setDecorated( bool );
bool isDecorated() const;
Q_INVOKABLE void setDecorated( bool );
Q_INVOKABLE bool isDecorated() const;
void setWindowTitleTextOptions( const QskTextOptions& );
QskTextOptions windowTitleTextOptions() const;
Q_INVOKABLE void setWindowButtons( WindowButtons );
Q_INVOKABLE WindowButtons windowButtons() const;
void setWindowTitle( const QString& );
QString windowTitle() const;
Q_INVOKABLE void setWindowButton( WindowButton, bool on = true );
Q_INVOKABLE bool testWindowButton( WindowButton ) const;
void setWindowIconSource( const QUrl& );
QUrl windowIconSource() const;
void setWindowIcon( const QskGraphic& );
QskGraphic windowIcon() const;
bool hasWindowIcon() const;
void setWindowButtons( WindowButtons );
WindowButtons windowButtons() const;
void setWindowButton( WindowButton, bool on = true );
bool testWindowButton( WindowButton ) const;
QRectF titleBarRect() const;
@ -57,13 +81,18 @@ class QSK_EXPORT QskSubWindow : public QskPopup
QRectF layoutRect() const override;
Q_SIGNALS:
void titleChanged();
void decoratedChanged();
void windowTitleChanged();
void windowTitleTextOptionsChanged();
void windowIconChanged();
void windowIconSourceChanged();
void windowButtonsChanged();
protected:
bool event( QEvent* ) override;
void updateLayout() override;
void itemChange( QQuickItem::ItemChange,
const QQuickItem::ItemChangeData& ) override;

View File

@ -8,13 +8,15 @@
#include "QskAspect.h"
#include "QskBoxBorderMetrics.h"
#include "QskGraphic.h"
#include "QskTextOptions.h"
#include <qfontmetrics.h>
QskSubWindowSkinlet::QskSubWindowSkinlet( QskSkin* skin )
: Inherited( skin )
{
appendNodeRoles( { PanelRole, TitleBarRole } );
appendNodeRoles( { PanelRole, TitleBarRole, SymbolRole, TitleRole } );
}
QskSubWindowSkinlet::~QskSubWindowSkinlet() = default;
@ -24,15 +26,22 @@ QRectF QskSubWindowSkinlet::subControlRect(
{
const auto subWindow = static_cast< const QskSubWindow* >( skinnable );
if ( subControl == QskSubWindow::TitleBar )
{
return titleBarRect( subWindow );
}
if ( subControl == QskSubWindow::Panel )
{
return subWindow->contentsRect();
}
else if ( subControl == QskSubWindow::TitleBar )
{
return titleBarRect( subWindow );
}
else if ( subControl == QskSubWindow::TitleBarSymbol )
{
return symbolRect( subWindow );
}
else if ( subControl == QskSubWindow::TitleBarText )
{
return titleRect( subWindow );
}
return Inherited::subControlRect( skinnable, subControl );
}
@ -45,10 +54,36 @@ QSGNode* QskSubWindowSkinlet::updateSubNode(
switch ( nodeRole )
{
case PanelRole:
{
return updateBoxNode( subWindow, node, QskSubWindow::Panel );
}
case TitleBarRole:
return updateBoxNode( subWindow, node, QskSubWindow::TitleBar );
{
if ( subWindow->isDecorated() )
return updateBoxNode( subWindow, node, QskSubWindow::TitleBar );
return nullptr;
}
case SymbolRole:
{
if ( subWindow->isDecorated() )
{
return updateGraphicNode( subWindow, node,
subWindow->windowIcon(), QskSubWindow::TitleBarSymbol );
}
return nullptr;
}
case TitleRole:
{
if ( subWindow->isDecorated() )
{
return updateTextNode( subWindow, node, subWindow->windowTitle(),
subWindow->windowTitleTextOptions(), QskSubWindow::TitleBarText );
}
return nullptr;
}
}
return Inherited::updateSubNode( skinnable, nodeRole, node );
@ -71,8 +106,8 @@ qreal QskSubWindowSkinlet::titleBarHeight( const QskSubWindow* subWindow ) const
if ( !subWindow->isDecorated() )
return 0;
const QFontMetricsF fm( subWindow->effectiveFont( QskSubWindow::TitleBar ) );
const QMarginsF margins = subWindow->marginsHint( QskSubWindow::TitleBar | Padding );
const QFontMetricsF fm( subWindow->effectiveFont( QskSubWindow::TitleBarText ) );
const qreal height = fm.height() + margins.top() + margins.bottom();
const qreal minHeight = subWindow->metric( QskSubWindow::TitleBar | MinimumHeight );
@ -80,4 +115,45 @@ qreal QskSubWindowSkinlet::titleBarHeight( const QskSubWindow* subWindow ) const
return qMax( height, minHeight );
}
QRectF QskSubWindowSkinlet::symbolRect( const QskSubWindow* subWindow ) const
{
auto rect = subControlRect( subWindow, QskSubWindow::TitleBar );
rect = subWindow->innerBox( QskSubWindow::TitleBar, rect );
int w = 0;
if ( !rect.isEmpty() )
{
const auto symbol = subWindow->windowIcon();
if ( !symbol.isNull() )
w = symbol.widthForHeight( rect.height() );
rect.setWidth( w );
}
return rect;
}
QRectF QskSubWindowSkinlet::titleRect( const QskSubWindow* subWindow ) const
{
auto rect = subControlRect( subWindow, QskSubWindow::TitleBar );
rect = subWindow->innerBox( QskSubWindow::TitleBar, rect );
if ( !rect.isEmpty() )
{
const auto spacing = subWindow->metric(
QskSubWindow::TitleBar | QskAspect::Spacing );
const auto symbolRect = subControlRect( subWindow, QskSubWindow::TitleBarSymbol );
rect.setX( rect.x() + symbolRect.right() + spacing );
#if 0
const QFontMetricsF fm( subWindow->effectiveFont( QskSubWindow::TitleBarText ) );
rect.setHeight( fm.height() ); // TitleBarText | Alignment
#endif
}
return rect;
}
#include "moc_QskSubWindowSkinlet.cpp"

View File

@ -20,7 +20,9 @@ class QSK_EXPORT QskSubWindowSkinlet : public QskPopupSkinlet
enum NodeRole
{
PanelRole = QskPopupSkinlet::OverlayRole + 1,
TitleBarRole
TitleBarRole,
SymbolRole,
TitleRole
};
Q_INVOKABLE QskSubWindowSkinlet( QskSkin* = nullptr );
@ -35,7 +37,10 @@ class QSK_EXPORT QskSubWindowSkinlet : public QskPopupSkinlet
private:
qreal titleBarHeight( const QskSubWindow* ) const;
QRectF titleBarRect( const QskSubWindow* ) const;
QRectF symbolRect( const QskSubWindow* ) const;
QRectF titleRect( const QskSubWindow* ) const;
};
#endif

View File

@ -53,7 +53,7 @@ static void qskSetupSubWindow(
QskDialog::StandardButton defaultButton, QskInputSubWindow* subWindow )
{
subWindow->setModal( true );
subWindow->setTitle( title );
subWindow->setWindowTitle( title );
subWindow->setStandardButtons( buttons );
if ( defaultButton == QskDialog::NoButton )