kscrollview.cpp
00001 /* This file is part of the KDE libraries 00002 Copyright (C) 2005 Allan Sandfeld Jensen <kde@carewolf.com> 00003 00004 This library is free software; you can redistribute it and/or 00005 modify it under the terms of the GNU Library General Public 00006 License version 2 as published by the Free Software Foundation. 00007 00008 This library is distributed in the hope that it will be useful, 00009 but WITHOUT ANY WARRANTY; without even the implied warranty of 00010 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00011 Library General Public License for more details. 00012 00013 You should have received a copy of the GNU Library General Public License 00014 along with this library; see the file COPYING.LIB. If not, write to 00015 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00016 Boston, MA 02110-1301, USA. 00017 */ 00018 00019 #include "config.h" 00020 00021 #include <qtimer.h> 00022 #include <qevent.h> 00023 #include <qapplication.h> 00024 00025 #include "kscrollview.h" 00026 #include <kdebug.h> 00027 #include <kconfig.h> 00028 #include <kglobal.h> 00029 00030 struct KScrollView::KScrollViewPrivate { 00031 KScrollViewPrivate() : dx(0), dy(0), ddx(0), ddy(0), rdx(0), rdy(0), scrolling(false) {} 00032 QTimer timer; 00033 int dx; 00034 int dy; 00035 // Step size * 16 and residual to avoid huge difference between 1px/step and 2px/step 00036 int ddx; 00037 int ddy; 00038 int rdx; 00039 int rdy; 00040 bool scrolling; 00041 }; 00042 00043 KScrollView::KScrollView( QWidget *parent, const char *name, Qt::WFlags f ) 00044 : QScrollView( parent, name, f ) 00045 { 00046 d = new KScrollViewPrivate; 00047 connect(&d->timer, SIGNAL(timeout()), this, SLOT(scrollTick())); 00048 } 00049 00050 KScrollView::~KScrollView() 00051 { 00052 delete d; 00053 } 00054 00055 void KScrollView::scrollBy(int dx, int dy) 00056 { 00057 KConfigGroup cfg( KGlobal::config(), "KDE" ); 00058 if( !cfg.readBoolEntry( "SmoothScrolling", true )) { 00059 QScrollView::scrollBy( dx, dy ); 00060 return; 00061 } 00062 // scrolling destination 00063 int full_dx = d->dx + dx; 00064 int full_dy = d->dy + dy; 00065 00066 // scrolling speed 00067 int ddx = 0; 00068 int ddy = 0; 00069 00070 int steps = SCROLL_TIME/SCROLL_TICK; 00071 00072 ddx = (full_dx*16)/steps; 00073 ddy = (full_dy*16)/steps; 00074 00075 // don't go under 1px/step 00076 if (ddx > 0 && ddx < 16) ddx = 16; 00077 if (ddy > 0 && ddy < 16) ddy = 16; 00078 if (ddx < 0 && ddx > -16) ddx = -16; 00079 if (ddy < 0 && ddy > -16) ddy = -16; 00080 00081 d->dx = full_dx; 00082 d->dy = full_dy; 00083 d->ddx = ddx; 00084 d->ddy = ddy; 00085 00086 if (!d->scrolling) { 00087 scrollTick(); 00088 startScrolling(); 00089 } 00090 } 00091 /* 00092 void KScrollView::scrollBy(int dx, int dy) 00093 { 00094 if (d->scrolling) 00095 setContentsPos( d->x+dx, d->y+dy ); 00096 else 00097 setContentsPos( contentsX() + dx, contentsY() + dy); 00098 } 00099 00100 void KScrollView::setContentsPos(int x, int y) 00101 { 00102 if (x < 0) x = 0; 00103 if (y < 0) y = 0; 00104 00105 int dx = x - contentsX(); 00106 int dy = y - contentsY(); 00107 00108 // to large to smooth out 00109 // if (dx > 1000 || dy > 1000) return QScrollView::setContentsPos(x,y); 00110 00111 // scrolling speed 00112 int ddx = 0; 00113 int ddy = 0; 00114 00115 int steps = SCROLL_TIME/SCROLL_TICK; 00116 00117 ddx = (dx*16)/steps; 00118 ddy = (dy*16)/steps; 00119 00120 d->x = x; 00121 d->y = y; 00122 d->dx = dx; 00123 d->dy = dy; 00124 d->ddx = ddx; 00125 d->ddy = ddy; 00126 00127 if (!d->scrolling) { 00128 scrollTick(); 00129 startScrolling(); 00130 } 00131 } */ 00132 00133 void KScrollView::scrollTick() { 00134 if (d->dx == 0 && d->dy == 0) { 00135 stopScrolling(); 00136 return; 00137 } 00138 00139 int tddx = d->ddx + d->rdx; 00140 int tddy = d->ddy + d->rdy; 00141 00142 int ddx = tddx / 16; 00143 int ddy = tddy / 16; 00144 d->rdx = tddx % 16; 00145 d->rdy = tddy % 16; 00146 00147 if (d->dx > 0 && ddx > d->dx) ddx = d->dx; 00148 else 00149 if (d->dx < 0 && ddx < d->dx) ddx = d->dx; 00150 00151 if (d->dy > 0 && ddy > d->dy) ddy = d->dy; 00152 else 00153 if (d->dy < 0 && ddy < d->dy) ddy = d->dy; 00154 00155 d->dx -= ddx; 00156 d->dy -= ddy; 00157 00158 // QScrollView::setContentsPos( contentsX() + ddx, contentsY() + ddy); 00159 QScrollView::scrollBy(ddx, ddy); 00160 } 00161 00162 void KScrollView::startScrolling() 00163 { 00164 d->scrolling = true; 00165 d->timer.start(SCROLL_TICK, false); 00166 } 00167 00168 void KScrollView::stopScrolling() 00169 { 00170 d->timer.stop(); 00171 d->dx = d->dy = 0; 00172 d->scrolling = false; 00173 } 00174 00175 // Overloaded from QScrollView and QScrollBar 00176 void KScrollView::wheelEvent( QWheelEvent *e ) 00177 { 00178 int pageStep = verticalScrollBar()->pageStep(); 00179 int lineStep = verticalScrollBar()->lineStep(); 00180 int step = QMIN( QApplication::wheelScrollLines()*lineStep, pageStep ); 00181 if ( ( e->state() & ControlButton ) || ( e->state() & ShiftButton ) ) 00182 step = pageStep; 00183 00184 int dy = (e->delta()*step)/120; 00185 scrollBy(0,-dy); 00186 e->accept(); 00187 } 00188 00189 #include "kscrollview.moc"