KDevelop API Documentation

splitter.cpp

Go to the documentation of this file.
00001 /* This file is part of the KDE project
00002    Copyright (C) 2001 Bernd Gehrmann <bernd@kdevelop.org>
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 as published by the Free Software Foundation; either
00007    version 2 of the License, or (at your option) any later version.
00008 
00009    This library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Library General Public License for more details.
00013 
00014    You should have received a copy of the GNU Library General Public License
00015    along with this library; see the file COPYING.LIB.  If not, write to
00016    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00017    Boston, MA 02111-1307, USA.
00018 */
00019 
00020 #include <qframe.h>
00021 #include <qpainter.h>
00022 #include <qtimer.h>
00023 #include <qstyle.h>
00024 #include <kdebug.h>
00025 
00026 #include "splitter.h"
00027 
00028 
00029 Splitter::Splitter(QWidget *parent, const char *name)
00030     : QWidget(parent, name)
00031 {
00032     _or = Horizontal;
00033 
00034     handlelist.setAutoDelete(true);
00035 }
00036 
00037 
00038 Splitter::~Splitter()
00039 {}
00040 
00041 
00042 void Splitter::setOrientation(Orientation orient)
00043 {
00044     if (orient != _or) {
00045         if (!childlist.isEmpty()) {
00046             if (hasMultipleChildren()) {
00047                 kdDebug(9000) << "Cannot change the orientation of a splitter with several widgets." << endl;
00048                 return;
00049             }
00050             if (orient == Horizontal) {
00051                 SplitterHandle *handle = new SplitterHandle(childlist.first(), this, "handle");
00052                 //                handle->show();
00053                 handlelist.append(handle);
00054             } else {
00055                 handlelist.remove((uint)0);
00056             }
00057         }
00058 
00059         _or = orient;
00060         doLayout();
00061     }
00062 }
00063 
00064 
00065 Qt::Orientation Splitter::orientation() const
00066 {
00067     return _or;
00068 }
00069 
00070 
00071 bool Splitter::hasMultipleChildren() const
00072 {
00073     return childlist.count() > 1;
00074 }
00075 
00076 
00077 QWidget *Splitter::firstChild()
00078 {
00079     return childlist.first();
00080 }
00081 
00082 
00083 int Splitter::handleWidth() const
00084 {
00085     return (orientation() == Horizontal)? style().pixelMetric(QStyle::PM_SplitterWidth, this) : 0;
00086 }
00087 
00088 
00089 void Splitter::addChild(QWidget *w)
00090 {
00091     kdDebug(9000) << "add child" << endl;
00092     //    connect( w, SIGNAL(destroyed()), this, SLOT(childDestroyed()) );
00093     if (childlist.count()) {
00094         // When we already have children, this is the same as
00095         // a split of the last one
00096         splitChild(childlist.last(), w);
00097     } else {
00098         childlist.append(w);
00099         if (orientation() == Horizontal) {
00100             SplitterHandle *handle = new SplitterHandle(w, this, "handle");
00101             handlelist.append(handle);
00102         }
00103     }
00104 
00105     doLayout();
00106 }
00107 
00108 
00109 void Splitter::splitChild(QWidget *old, QWidget *w)
00110 {
00111 #if 0
00112     kdDebug(9000) << "splitChild - Old list of splitter children:" << endl;
00113     QPtrListIterator<QWidget> it1(childlist);
00114     for (; it1.current(); ++it1)
00115         kdDebug(9000) << it1.current()->name() << endl;
00116 #endif
00117 
00118     int offset = 0;
00119     for (uint i = 0; i < childlist.count(); ++i) {
00120         if (childlist.at(i) == old) {
00121             childlist.insert(i+1, w);
00122             if (orientation() == Horizontal) {
00123                 SplitterHandle *handle = new SplitterHandle(w, this, "handle");
00124                 handlelist.insert(i+1, handle);
00125             }
00126             if (i+1 != childlist.count()-1) {
00127                 sizes.insert(sizes.at(i), sizes[i]/2 - handleWidth());
00128                 sizes[i+1] = sizes[i]/2;
00129             } else {
00130                 int total = (orientation() == Horizontal)? width() : height();
00131                 sizes.insert(sizes.at(i), (total-offset)/2);
00132             }
00133             doLayout();
00134             return;
00135         }
00136         offset += sizes[i];
00137         offset += handleWidth();
00138     }
00139 
00140     kdDebug(9000) << "Huh? Old child not in splitter" << endl;
00141 }
00142 
00143 
00144 void Splitter::replaceChild(QWidget *old, QWidget *w)
00145 {
00146     for (uint i=0; i < childlist.count(); ++i)
00147         if (childlist.at(i) == old) {
00148             childlist.remove(i);
00149             if (orientation() == Horizontal)
00150                 handlelist.remove(i);
00151             childlist.insert(i, w);
00152             if (orientation() == Horizontal) {
00153                 SplitterHandle *handle = new SplitterHandle(w, this, "handle");
00154                 handlelist.insert(i, handle);
00155             }
00156             doLayout();
00157             return;
00158         }
00159 
00160     kdDebug(9000) << "Huh? Old child not in splitter" << endl;
00161 }
00162 
00163 
00164 void Splitter::moveSplitter(QWidget *w, int pos)
00165 {
00166     int offset = 0;
00167     for (uint i=0; i < childlist.count(); ++i) {
00168         if (childlist.at(i) == w) {
00169             if (i != childlist.count()) {
00170                 sizes[i] = pos-offset;
00171                 break;
00172             }
00173         }
00174         offset += sizes[i];
00175         offset += handleWidth();
00176     }
00177 
00178     doLayout();
00179 }
00180 
00181 
00182 void Splitter::doLayout()
00183 {
00184     setUpdatesEnabled(false);
00185 
00186     if (orientation() == Horizontal) {
00187 
00188         int offset = 0;
00189         uint i;
00190         for (i=0; i+1 < childlist.count(); ++i) {
00191             sizes[i] = QMAX(sizes[i], childlist.at(i)->minimumSizeHint().width());
00192             childlist.at(i)->setGeometry(offset, 0, sizes[i], height());
00193             offset += childlist.at(i)->width();
00194             handlelist.at(i)->setGeometry(offset, 0, style().pixelMetric(QStyle::PM_SplitterWidth, this), height());
00195             handlelist.at(i)->show();
00196             offset += handlelist.at(i)->width();
00197         }
00198 
00199         if (childlist.count()) {
00200             childlist.at(i)->setGeometry(offset, 0, width()-offset, height());
00201             handlelist.at(i)->hide();
00202         }
00203 
00204     } else {
00205 
00206         int offset = 0;
00207         uint i;
00208         for (i=0; i+1 < childlist.count(); ++i) {
00209             sizes[i] = QMAX(sizes[i], childlist.at(i)->minimumSizeHint().height());
00210             childlist.at(i)->setGeometry(0, offset, width(), sizes[i]);
00211             offset += childlist.at(i)->height();
00212         }
00213 
00214         if (childlist.count())
00215             childlist.at(i)->setGeometry(0, offset, width(), height()-offset);
00216 
00217     }
00218 
00219     setUpdatesEnabled(true);
00220 }
00221 
00222 
00223 
00224 QSize Splitter::minimumSizeHint() const
00225 {
00226     int extent = 0;
00227     for (uint i = 0; i < childlist.count(); ++i) {
00228         // Bah.
00229         Splitter *that = (Splitter*) this;
00230         QSize s = that->childlist.at(i)->minimumSizeHint();
00231         extent = QMAX(extent, (orientation()==Horizontal)? s.height() : s.width());
00232     }
00233     return (orientation()==Horizontal)? QSize(0, extent) : QSize(extent, 0);
00234 }
00235 
00236 
00237 void Splitter::childEvent(QChildEvent *e)
00238 {
00239     if (e->type() != QEvent::ChildRemoved)
00240         return;
00241 
00242     QObject *o = e->child();
00243 
00244     for (uint i=0; i<childlist.count(); ++i) {
00245         if (childlist.at(i) == o) {
00246             childlist.remove(i);
00247             if (orientation() == Horizontal)
00248                 handlelist.remove(i);
00249             if (i == childlist.count())
00250                 sizes.remove(i-1);
00251             else
00252                 sizes.remove(i);
00253             doLayout();
00254             if (childlist.count() < 2)
00255                 QTimer::singleShot(0, this, SLOT(collapse()));
00256             break;
00257         }
00258     }
00259 }
00260 
00261 
00262 void Splitter::collapse()
00263 {
00264     emit collapsed(this);
00265 }
00266 
00267 
00268 void Splitter::resizeEvent(QResizeEvent */*e*/)
00269 {
00270     doLayout();
00271 }
00272 
00273 
00274 SplitterBar::SplitterBar(QWidget *parent, const char *name)
00275     : QFrame(parent, name)
00276 {
00277     setFrameStyle(Panel | Raised);
00278     setLineWidth(1);
00279     setFixedHeight(fontMetrics().lineSpacing()+2);
00280 
00281     offset = 0;
00282 }
00283 
00284 
00285 SplitterBar::~SplitterBar()
00286 {}
00287 
00288 
00289 void SplitterBar::mouseMoveEvent(QMouseEvent *e)
00290 {
00291     if (e->state() & LeftButton) {
00292         QWidget *p = parentWidget();
00293         QWidget *gp = p->parentWidget();
00294         if (!gp->inherits("Splitter"))
00295             return;
00296         // If we are in a horizontal splitter, look if this horizontal
00297         // splitter is nested in a vertical splitter, when is then
00298         // used.
00299         if (static_cast<Splitter*>(gp)->orientation() == Horizontal) {
00300             p = gp;
00301             gp = p->parentWidget();
00302             if (!gp->inherits("Splitter"))
00303                 return;
00304         }
00305         int pos = gp->mapFromGlobal(e->globalPos()).y() + offset;
00306     static_cast<Splitter*>(gp)->moveSplitter(p, pos);
00307     }
00308 }
00309 
00310 
00311 void SplitterBar::mousePressEvent(QMouseEvent *e)
00312 {
00313     if ( e->button() & LeftButton )
00314     offset = height()-e->pos().y();
00315 }
00316 
00317 
00318 void SplitterBar::childEvent(QChildEvent *e)
00319 {
00320     if (e->type() == QEvent::ChildInserted && e->child()->isWidgetType())
00321         e->child()->installEventFilter(this);
00322     else if (e->type() == QEvent::ChildRemoved && e->child()->isWidgetType())
00323         e->child()->removeEventFilter(this);
00324 }
00325 
00326 
00327 bool SplitterBar::eventFilter(QObject *o, QEvent *e)
00328 {
00329     if (e->type() == QEvent::MouseButtonPress)
00330         mousePressEvent(static_cast<QMouseEvent*>(e));
00331     else if(e->type() == QEvent::MouseMove)
00332         mouseMoveEvent(static_cast<QMouseEvent*>(e));
00333 
00334     return QWidget::eventFilter(o, e);
00335 }
00336 
00337 
00338 SplitterHandle::SplitterHandle(QWidget *embeddedSibling, Splitter *parent, const char *name)
00339     : QWidget(parent, name)
00340 {
00341     sibling = embeddedSibling;
00342     setCursor(splitHCursor);
00343     //    setFixedWidth(QMIN(style().splitterWidth(), QApplication::globalStrut().width()));
00344 }
00345 
00346 
00347 SplitterHandle::~SplitterHandle()
00348 {}
00349 
00350 
00351 void SplitterHandle::mouseMoveEvent(QMouseEvent *e)
00352 {
00353     if (e->state() & LeftButton) {
00354         int pos = parentWidget()->mapFromGlobal(e->globalPos()).x() + offset;
00355     static_cast<Splitter*>(parentWidget())->moveSplitter(sibling, pos);
00356     }
00357 }
00358 
00359 
00360 void SplitterHandle::mousePressEvent(QMouseEvent *e)
00361 {
00362     if ( e->button() & LeftButton )
00363     offset = -e->pos().x();
00364 }
00365 
00366 
00367 void SplitterHandle::paintEvent(QPaintEvent *)
00368 {
00369     QPainter p(this);
00370     style().drawPrimitive(QStyle::PE_Splitter, &p, QRect(0, 0, width(), height()), colorGroup(), QStyle::Style_Horizontal);
00371 }
00372 
00373 #include "splitter.moc"
KDE Logo
This file is part of the documentation for KDevelop Version 3.1.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Wed Mar 23 00:03:52 2005 by doxygen 1.3.9.1 written by Dimitri van Heesch, © 1997-2003