File indexing completed on 2024-03-24 04:44:22
0001 /*************************************************************************** 0002 * Copyright (C) 2017-2018 by Emmanuel Lepage Vallee * 0003 * Author : Emmanuel Lepage Vallee <emmanuel.lepage@kde.org> * 0004 * * 0005 * This program is free software; you can redistribute it and/or modify * 0006 * it under the terms of the GNU General Public License as published by * 0007 * the Free Software Foundation; either version 3 of the License, or * 0008 * (at your option) any later version. * 0009 * * 0010 * This program is distributed in the hope that it will be useful, * 0011 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 0012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 0013 * GNU General Public License for more details. * 0014 * * 0015 * You should have received a copy of the GNU General Public License * 0016 * along with this program. If not, see <http://www.gnu.org/licenses/>. * 0017 **************************************************************************/ 0018 #include "flickablescrollbar.h" 0019 0020 // KQuickItemViews 0021 #include "views/flickable.h" 0022 0023 class FlickableScrollBarPrivate : public QObject 0024 { 0025 Q_OBJECT 0026 public: 0027 Flickable *m_pView {nullptr}; 0028 qreal m_HandleHeight { 0 }; 0029 qreal m_Position { 0 }; 0030 bool m_Visible { false }; 0031 0032 FlickableScrollBar* q_ptr; 0033 0034 public Q_SLOTS: 0035 void recomputeGeometry(); 0036 }; 0037 0038 FlickableScrollBar::FlickableScrollBar(QQuickItem* parent) : QQuickItem(parent), 0039 d_ptr(new FlickableScrollBarPrivate) 0040 { 0041 d_ptr->q_ptr = this; 0042 } 0043 0044 FlickableScrollBar::~FlickableScrollBar() 0045 { 0046 delete d_ptr; 0047 } 0048 0049 QObject* FlickableScrollBar::view() const 0050 { 0051 return d_ptr->m_pView; 0052 } 0053 0054 void FlickableScrollBar::setView(QObject* v) 0055 { 0056 if (d_ptr->m_pView) { 0057 disconnect(d_ptr->m_pView, &Flickable::contentHeightChanged, 0058 d_ptr, &FlickableScrollBarPrivate::recomputeGeometry); 0059 disconnect(d_ptr->m_pView, &Flickable::contentYChanged, 0060 d_ptr, &FlickableScrollBarPrivate::recomputeGeometry); 0061 disconnect(d_ptr->m_pView, &Flickable::heightChanged, 0062 d_ptr, &FlickableScrollBarPrivate::recomputeGeometry); 0063 } 0064 0065 d_ptr->m_pView = qobject_cast<Flickable*>(v); 0066 0067 Q_ASSERT((!v) || d_ptr->m_pView); 0068 0069 connect(d_ptr->m_pView, &Flickable::contentHeightChanged, 0070 d_ptr, &FlickableScrollBarPrivate::recomputeGeometry); 0071 connect(d_ptr->m_pView, &Flickable::contentYChanged, 0072 d_ptr, &FlickableScrollBarPrivate::recomputeGeometry); 0073 connect(d_ptr->m_pView, &Flickable::heightChanged, 0074 d_ptr, &FlickableScrollBarPrivate::recomputeGeometry); 0075 0076 d_ptr->recomputeGeometry(); 0077 } 0078 0079 qreal FlickableScrollBar::position() const 0080 { 0081 return d_ptr->m_Position; 0082 } 0083 0084 void FlickableScrollBar::setPosition(qreal p) 0085 { 0086 if (!d_ptr->m_pView) 0087 return; 0088 0089 // Simple rule of 3 0090 d_ptr->m_pView->setContentY( 0091 (p * d_ptr->m_pView->contentHeight()) / d_ptr->m_pView->height() 0092 ); 0093 } 0094 0095 qreal FlickableScrollBar::handleHeight() const 0096 { 0097 return d_ptr->m_HandleHeight; 0098 } 0099 0100 bool FlickableScrollBar::isHandleVisible() const 0101 { 0102 return d_ptr->m_Visible; 0103 } 0104 0105 /** 0106 * The idea behind the scrollhandle is that the height represent the height of a 0107 * page until it gets too small. In mobile mode, the height is always the same 0108 * regardless of the content height to hide less space on the smaller screen. 0109 */ 0110 void FlickableScrollBarPrivate::recomputeGeometry() 0111 { 0112 if (!m_pView) 0113 return; 0114 0115 const qreal oldP = m_Position; 0116 const qreal oldH = m_HandleHeight; 0117 0118 const qreal totalHeight = m_pView->contentHeight(); 0119 const qreal pageHeight = m_pView->height(); 0120 const qreal pageCount = totalHeight/pageHeight; 0121 const qreal handleHeight = std::max(pageHeight/pageCount, 50.0); 0122 const qreal handleBegin = (m_pView->contentY()*pageHeight)/totalHeight; 0123 0124 m_HandleHeight = handleHeight; 0125 m_Position = handleBegin; 0126 m_Visible = totalHeight > pageHeight; 0127 0128 if (oldH != m_HandleHeight) 0129 emit q_ptr->handleHeightChanged(); 0130 0131 if (oldP != m_Position) 0132 emit q_ptr->positionChanged (); 0133 } 0134 0135 #include <flickablescrollbar.moc>