kdeui Library API Documentation

kdockwidget_private.cpp

00001 /* This file is part of the KDE libraries
00002    Copyright (C) 2000 Max Judin <novaprint@mtu-net.ru>
00003    Copyright (C) 2002,2003 Joseph Wenninger <jowenn@kde.org>
00004 
00005    This library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Library General Public
00007    License version 2 as published by the Free Software Foundation.
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 #include "kdockwidget.h"
00020 #include "kdockwidget_p.h"
00021 #include "kdockwidget_private.h"
00022 
00023 #include <qpainter.h>
00024 #include <qcursor.h>
00025 #include <kdebug.h>
00026 #include <qtimer.h>
00027 
00028 KDockSplitter::KDockSplitter(QWidget *parent, const char *name, Orientation orient, int pos, bool highResolution)
00029 : QWidget(parent, name)
00030 {
00031   divider = 0L;
00032   child0 = 0L;
00033   child1 = 0L;
00034   fixedWidth0=-1;
00035   fixedWidth1=-1;
00036   fixedHeight0=-1;
00037   fixedHeight1=-1;
00038 
00039   m_orientation = orient;
00040   mOpaqueResize = false;
00041   mKeepSize = false;
00042   mHighResolution = highResolution;
00043   setSeparatorPos( pos, false );
00044   initialised = false;
00045 }
00046 
00047 void KDockSplitter::activate(QWidget *c0, QWidget *c1)
00048 {
00049   if ( c0 ) child0 = c0;
00050   if ( c1 ) child1 = c1;
00051 
00052   setupMinMaxSize();
00053 
00054   if (divider) delete divider;
00055   divider = new QFrame(this, "pannerdivider");
00056   divider->setFrameStyle(QFrame::Panel | QFrame::Raised);
00057   divider->setLineWidth(1);
00058   divider->raise();
00059 
00060   if (m_orientation == Horizontal)
00061     divider->setCursor(QCursor(sizeVerCursor));
00062   else
00063     divider->setCursor(QCursor(sizeHorCursor));
00064 
00065   divider->installEventFilter(this);
00066 
00067   initialised= true;
00068 
00069   updateName();
00070 
00071   divider->show();
00072   resizeEvent(0);
00073   if (fixedWidth0!=-1) restoreFromForcedFixedSize((KDockWidget*)child0);
00074   if (fixedWidth1!=-1) restoreFromForcedFixedSize((KDockWidget*)child1);
00075   if (((KDockWidget*)child0)->forcedFixedWidth()!=-1)
00076   {
00077     setForcedFixedWidth(((KDockWidget*)child0),((KDockWidget*)child0)->forcedFixedWidth());
00078     //QTimer::singleShot(100,this,SLOT(delayedResize()));
00079   }
00080   else
00081   if (((KDockWidget*)child1)->forcedFixedWidth()!=-1)
00082   {
00083     setForcedFixedWidth(((KDockWidget*)child1),((KDockWidget*)child1)->forcedFixedWidth());
00084     //QTimer::singleShot(100,this,SLOT(delayedResize()));
00085   }
00086 
00087   if (((KDockWidget*)child0)->forcedFixedHeight()!=-1)
00088   {
00089         setForcedFixedHeight(((KDockWidget*)child0),((KDockWidget*)child0)->forcedFixedHeight());
00090         //QTimer::singleShot(100,this,SLOT(delayedResize()));
00091   }
00092   else
00093   if (((KDockWidget*)child1)->forcedFixedHeight()!=-1)
00094   {
00095         setForcedFixedHeight(((KDockWidget*)child1),((KDockWidget*)child1)->forcedFixedHeight());
00096         //QTimer::singleShot(100,this,SLOT(delayedResize()));
00097   }
00098 
00099 
00100 }
00101 
00102 /*
00103 void KDockSplitter::delayedResize()
00104 {
00105     kdDebug()<<"*********************** DELAYED RESIZE !!!!!!!!!!!!!!!"<<endl;
00106     resizeEvent(0);
00107 }*/
00108 
00109 void KDockSplitter::setForcedFixedWidth(KDockWidget *dw,int w)
00110 {
00111     int factor = (mHighResolution)? 10000:100;
00112     if (dw==child0)
00113     {
00114                 fixedWidth0=w;
00115 //      setupMinMaxSize();
00116                 savedXPos=xpos;
00117         setSeparatorPos(w*factor/width(),true);
00118 //      kdDebug()<<"Set forced fixed width for widget 0 :"<<w<<endl;
00119     }
00120         else
00121     {
00122                 fixedWidth1=w;
00123                 savedXPos=xpos;
00124         setSeparatorPos((width()-w)*factor/width(),true);
00125 //      kdDebug()<<"Set forced fixed width for widget 1 :"<<w<<endl;
00126 //      kdDebug()<<"Width() :"<<width()<<endl;
00127     }
00128     divider->hide();
00129 }
00130 
00131 void KDockSplitter::setForcedFixedHeight(KDockWidget *dw,int h)
00132 {
00133     int factor = (mHighResolution)? 10000:100;
00134     if (dw==child0)
00135     {
00136                 fixedHeight0=h;
00137 //      setupMinMaxSize();
00138         savedXPos=xpos;
00139         setSeparatorPos(h*factor/height(),true);
00140 //      kdDebug()<<"Set forced fixed width for widget 0 :"<<h<<endl;
00141     }
00142         else
00143     {
00144                 fixedHeight1=h;
00145         savedXPos=xpos;
00146         setSeparatorPos((height()-h)*factor/height(),true);
00147 //      kdDebug()<<"Set forced fixed height for widget 1 :"<<h<<endl;
00148     }
00149         divider->hide();
00150 }
00151 
00152 void KDockSplitter::restoreFromForcedFixedSize(KDockWidget *dw)
00153 {
00154     if (dw==child0)
00155     {
00156         fixedWidth0=-1;
00157         fixedHeight0=-1;
00158         setSeparatorPos(savedXPos,true);
00159     }
00160     else
00161     {
00162         fixedWidth1=-1;
00163         fixedHeight1=-1;
00164         setSeparatorPos(savedXPos,true);
00165     }
00166     divider->show();
00167 }
00168 
00169 
00170 void KDockSplitter::setupMinMaxSize()
00171 {
00172   // Set the minimum and maximum sizes
00173   int minx, maxx, miny, maxy;
00174   if (m_orientation == Horizontal) {
00175     miny = child0->minimumSize().height() + child1->minimumSize().height()+4;
00176     maxy = child0->maximumSize().height() + child1->maximumSize().height()+4;
00177     minx = (child0->minimumSize().width() > child1->minimumSize().width()) ? child0->minimumSize().width() : child1->minimumSize().width();
00178     maxx = (child0->maximumSize().width() > child1->maximumSize().width()) ? child0->maximumSize().width() : child1->maximumSize().width();
00179 
00180     miny = (miny > 4) ? miny : 4;
00181     maxy = (maxy < 32000) ? maxy : 32000;
00182     minx = (minx > 2) ? minx : 2;
00183     maxx = (maxx < 32000) ? maxx : 32000;
00184   } else {
00185     minx = child0->minimumSize().width() + child1->minimumSize().width()+4;
00186     maxx = child0->maximumSize().width() + child1->maximumSize().width()+4;
00187     miny = (child0->minimumSize().height() > child1->minimumSize().height()) ? child0->minimumSize().height() : child1->minimumSize().height();
00188     maxy = (child0->maximumSize().height() > child1->maximumSize().height()) ? child0->maximumSize().height() : child1->maximumSize().height();
00189 
00190     minx = (minx > 4) ? minx : 4;
00191     maxx = (maxx < 32000) ? maxx : 32000;
00192     miny = (miny > 2) ? miny : 2;
00193     maxy = (maxy < 32000) ? maxy : 32000;
00194   }
00195   setMinimumSize(minx, miny);
00196   setMaximumSize(maxx, maxy);
00197 }
00198 
00199 void KDockSplitter::deactivate()
00200 {
00201   delete divider;
00202   divider = 0L;
00203   initialised= false;
00204 }
00205 
00206 void KDockSplitter::setSeparatorPos(int pos, bool do_resize)
00207 {
00208   xpos = pos;
00209   if (do_resize)
00210     resizeEvent(0);
00211 }
00212 
00213 void KDockSplitter::setSeparatorPosX( int pos, bool do_resize )
00214 {
00215   savedXPos = pos;
00216   setSeparatorPos( pos, do_resize );
00217 }
00218 
00219 int KDockSplitter::separatorPos() const
00220 {
00221   return xpos;
00222 }
00223 
00224 void KDockSplitter::resizeEvent(QResizeEvent *ev)
00225 {
00226 //  kdDebug()<<"ResizeEvent :"<< ((initialised) ? "initialised":"not initialised")<<", "<< ((ev) ? "real event":"")<<
00227 //  ", "<<(isVisible() ?"visible":"")<<endl;
00228   if (initialised){
00229     int factor = (mHighResolution)? 10000:100;
00230     // real resize event, recalculate xpos
00231     if (ev && mKeepSize && isVisible()) {
00232 //  kdDebug()<<"mKeepSize : "<< ((m_orientation == Horizontal) ? "Horizontal":"Vertical") <<endl;
00233 
00234       if (ev->oldSize().width() != ev->size().width())
00235       {
00236           if (m_orientation == Horizontal) {
00237           xpos = factor * checkValue( child0->height()+1 ) / height();
00238           } else {
00239           xpos = factor * checkValue( child0->width()+1 ) / width();
00240       }
00241 
00242           }
00243       }
00244           else
00245           {
00246 //  kdDebug()<<"!mKeepSize : "<< ((m_orientation == Horizontal) ? "Horizontal":"Vertical") <<endl;
00247     if (/*ev &&*/ isVisible()) {
00248         if (m_orientation == Horizontal) {
00249         /*  if (ev->oldSize().height() != ev->size().height())*/
00250             {
00251               if (fixedHeight0!=-1)
00252                 xpos=fixedHeight0*factor/height();
00253               else
00254               if (fixedHeight1!=-1)
00255                 xpos=(height()-fixedHeight1)*factor/height();
00256             }
00257         }
00258         else
00259         {
00260 /*              if (ev->oldSize().width() != ev->size().width()) */
00261             {
00262               if (fixedWidth0!=-1)
00263                 xpos=fixedWidth0*factor/width();
00264               else
00265               if (fixedWidth1!=-1)
00266                 xpos=(width()-fixedWidth1)*factor/width();
00267             }
00268         }
00269     }
00270 //  else kdDebug()<<"Something else happened"<<endl;
00271    }
00272 
00273     KDockContainer *dc;
00274     KDockWidget *c0=(KDockWidget*)child0;
00275     KDockWidget *c1=(KDockWidget*)child1;
00276     bool stdHandling=false;
00277     if ((fixedWidth0==-1) && (fixedWidth1==-1)) {
00278         if ((c0->getWidget()) && (dc=dynamic_cast<KDockContainer*>(c0->getWidget()))
00279          && (dc->m_overlapMode)) {
00280             int position= (m_orientation == Vertical ? width() : height()) * xpos/factor;
00281             position=checkValueOverlapped(position,child0);
00282             child0->raise();
00283             divider->raise();
00284                       if (m_orientation == Horizontal){
00285                         child0->setGeometry(0, 0, width(), position);
00286                         child1->setGeometry(0, dc->m_nonOverlapSize+4, width(),
00287                         height()-dc->m_nonOverlapSize-4);
00288                         divider->setGeometry(0, position, width(), 4);
00289                       } else {
00290                         child0->setGeometry(0, 0, position, height());
00291                         child1->setGeometry(dc->m_nonOverlapSize+4, 0,
00292                         width()-dc->m_nonOverlapSize-4, height());
00293                         divider->setGeometry(position, 0, 4, height());
00294                       }
00295         } else {
00296          if ((c1->getWidget()) && (dc=dynamic_cast<KDockContainer*>(c1->getWidget()))
00297              && (dc->m_overlapMode)) {
00298                     int position= (m_orientation == Vertical ? width() : height()) * xpos/factor;
00299             position=checkValueOverlapped(position,child1);
00300                     child1->raise();
00301                     divider->raise();
00302                           if (m_orientation == Horizontal){
00303                             child0->setGeometry(0, 0, width(), height()-dc->m_nonOverlapSize-4);
00304                             child1->setGeometry(0, position+4, width(),
00305                                             height()-position-4);
00306                             divider->setGeometry(0, position, width(), 4);
00307                           } else {
00308                             child0->setGeometry(0, 0, width()-dc->m_nonOverlapSize-4, height());
00309                             child1->setGeometry(position+4, 0,
00310                                             width()-position-4, height());
00311                             divider->setGeometry(position, 0, 4, height());
00312                           }
00313         }
00314         else stdHandling=true;
00315           }
00316             }
00317      else stdHandling=true;
00318 
00319     if (stdHandling) {
00320               int position = checkValue( (m_orientation == Vertical ? width() : height()) * xpos/factor );
00321               if (m_orientation == Horizontal){
00322                 child0->setGeometry(0, 0, width(), position);
00323                 child1->setGeometry(0, position+4, width(), height()-position-4);
00324                 divider->setGeometry(0, position, width(), 4);
00325               } else {
00326                 child0->setGeometry(0, 0, position, height());
00327                 child1->setGeometry(position+4, 0, width()-position-4, height());
00328                 divider->setGeometry(position, 0, 4, height());
00329     }
00330 
00331     }
00332 
00333   }
00334 }
00335 
00336 int KDockSplitter::checkValueOverlapped(int position, QWidget *overlappingWidget) const {
00337     if (initialised) {
00338         if (m_orientation == Vertical) {
00339             if (child0==overlappingWidget) {
00340                 if (position<(child0->minimumSize().width()))
00341                     position=child0->minimumSize().width();
00342                 if (position>width()) position=width()-4;
00343             } else if (position>(width()-(child1->minimumSize().width())-4)){
00344                 position=width()-(child1->minimumSize().width())-4;
00345                 if (position<0) position=0;
00346             }
00347         } else {// orientation  == Horizontal
00348             if (child0==overlappingWidget) {
00349                 if (position<(child0->minimumSize().height()))
00350                     position=child0->minimumSize().height();
00351                 if (position>height()) position=height()-4;
00352             } else if (position>(height()-(child1->minimumSize().height())-4)){
00353                 position=height()-(child1->minimumSize().height())-4;
00354                 if (position<0) position=0;
00355 
00356             }
00357         }
00358 
00359     }
00360     return position;
00361 }
00362 
00363 int KDockSplitter::checkValue( int position ) const
00364 {
00365   if (initialised){
00366     if (m_orientation == Vertical){
00367       if (position < (child0->minimumSize().width()))
00368         position = child0->minimumSize().width();
00369       if ((width()-4-position) < (child1->minimumSize().width()))
00370         position = width() - (child1->minimumSize().width()) -4;
00371     } else {
00372       if (position < (child0->minimumSize().height()))
00373         position = (child0->minimumSize().height());
00374       if ((height()-4-position) < (child1->minimumSize().height()))
00375         position = height() - (child1->minimumSize().height()) -4;
00376     }
00377   }
00378 
00379   if (position < 0) position = 0;
00380 
00381   if ((m_orientation == Vertical) && (position > width()))
00382     position = width();
00383   if ((m_orientation == Horizontal) && (position > height()))
00384     position = height();
00385 
00386   return position;
00387 }
00388 
00389 bool KDockSplitter::eventFilter(QObject *o, QEvent *e)
00390 {
00391   QMouseEvent *mev;
00392   bool handled = false;
00393   int factor = (mHighResolution)? 10000:100;
00394 
00395   switch (e->type()) {
00396     case QEvent::MouseMove:
00397       mev= (QMouseEvent*)e;
00398       child0->setUpdatesEnabled(mOpaqueResize);
00399       child1->setUpdatesEnabled(mOpaqueResize);
00400       if (m_orientation == Horizontal) {
00401         if ((fixedHeight0!=-1) || (fixedHeight1!=-1))
00402         {
00403                 handled=true; break;
00404         }
00405 
00406     if (!mOpaqueResize) {
00407           int position = checkValue( mapFromGlobal(mev->globalPos()).y() );
00408           divider->move( 0, position );
00409         } else {
00410           xpos = factor * checkValue( mapFromGlobal(mev->globalPos()).y() ) / height();
00411           resizeEvent(0);
00412           divider->repaint(true);
00413         }
00414       } else {
00415         if ((fixedWidth0!=-1) || (fixedWidth1!=-1))
00416         {
00417                 handled=true; break;
00418         }
00419         if (!mOpaqueResize) {
00420           int position = checkValue( mapFromGlobal(QCursor::pos()).x() );
00421           divider->move( position, 0 );
00422         } else {
00423           xpos = factor * checkValue( mapFromGlobal( mev->globalPos()).x() ) / width();
00424           resizeEvent(0);
00425           divider->repaint(true);
00426         }
00427       }
00428       handled= true;
00429       break;
00430     case QEvent::MouseButtonRelease:
00431       child0->setUpdatesEnabled(true);
00432       child1->setUpdatesEnabled(true);
00433       mev= (QMouseEvent*)e;
00434       if (m_orientation == Horizontal){
00435         if ((fixedHeight0!=-1) || (fixedHeight1!=-1))
00436         {
00437                 handled=true; break;
00438         }
00439         xpos = factor* checkValue( mapFromGlobal(mev->globalPos()).y() ) / height();
00440         resizeEvent(0);
00441         divider->repaint(true);
00442       } else {
00443         if ((fixedWidth0!=-1) || (fixedWidth1!=-1))
00444         {
00445                 handled=true; break;
00446         }
00447         xpos = factor* checkValue( mapFromGlobal(mev->globalPos()).x() ) / width();
00448         resizeEvent(0);
00449         divider->repaint(true);
00450       }
00451       handled= true;
00452       break;
00453     default:
00454       break;
00455   }
00456   return (handled) ? true : QWidget::eventFilter( o, e );
00457 }
00458 
00459 bool KDockSplitter::event( QEvent* e )
00460 {
00461   if ( e->type() == QEvent::LayoutHint ){
00462     // change children min/max size
00463     setupMinMaxSize();
00464     setSeparatorPos(xpos);
00465   }
00466   return QWidget::event(e);
00467 }
00468 
00469 QWidget* KDockSplitter::getAnother( QWidget* w ) const
00470 {
00471   return ( w == child0 ) ? child1 : child0;
00472 }
00473 
00474 void KDockSplitter::updateName()
00475 {
00476   if ( !initialised ) return;
00477 
00478   QString new_name = QString( child0->name() ) + "," + child1->name();
00479   parentWidget()->setName( new_name.latin1() );
00480   parentWidget()->setCaption( child0->caption() + "," + child1->caption() );
00481   parentWidget()->repaint( false );
00482 
00483   ((KDockWidget*)parentWidget())->firstName = child0->name();
00484   ((KDockWidget*)parentWidget())->lastName = child1->name();
00485   ((KDockWidget*)parentWidget())->splitterOrientation = m_orientation;
00486 
00487   QWidget* p = parentWidget()->parentWidget();
00488   if ( p != 0L && p->inherits("KDockSplitter" ) )
00489     ((KDockSplitter*)p)->updateName();
00490 }
00491 
00492 void KDockSplitter::setOpaqueResize(bool b)
00493 {
00494   mOpaqueResize = b;
00495 }
00496 
00497 bool KDockSplitter::opaqueResize() const
00498 {
00499   return mOpaqueResize;
00500 }
00501 
00502 void KDockSplitter::setKeepSize(bool b)
00503 {
00504   mKeepSize = b;
00505 }
00506 
00507 bool KDockSplitter::keepSize() const
00508 {
00509   return mKeepSize;
00510 }
00511 
00512 void KDockSplitter::setHighResolution(bool b)
00513 {
00514   if (mHighResolution) {
00515     if (!b) xpos = xpos/100;
00516   } else {
00517     if (b) xpos = xpos*100;
00518   }
00519   mHighResolution = b;
00520 }
00521 
00522 bool KDockSplitter::highResolution() const
00523 {
00524   return mHighResolution;
00525 }
00526 
00527 
00528 /*************************************************************************/
00529 KDockButton_Private::KDockButton_Private( QWidget *parent, const char * name )
00530 :QPushButton( parent, name )
00531 {
00532   moveMouse = false;
00533   setFocusPolicy( NoFocus );
00534 }
00535 
00536 KDockButton_Private::~KDockButton_Private()
00537 {
00538 }
00539 
00540 void KDockButton_Private::drawButton( QPainter* p )
00541 {
00542   p->fillRect( 0,0, width(), height(), QBrush(colorGroup().brush(QColorGroup::Background)) );
00543   p->drawPixmap( (width() - pixmap()->width()) / 2, (height() - pixmap()->height()) / 2, *pixmap() );
00544   if ( moveMouse && !isDown() ){
00545     p->setPen( white );
00546     p->moveTo( 0, height() - 1 );
00547     p->lineTo( 0, 0 );
00548     p->lineTo( width() - 1, 0 );
00549 
00550     p->setPen( colorGroup().dark() );
00551     p->lineTo( width() - 1, height() - 1 );
00552     p->lineTo( 0, height() - 1 );
00553   }
00554   if ( isOn() || isDown() ){
00555     p->setPen( colorGroup().dark() );
00556     p->moveTo( 0, height() - 1 );
00557     p->lineTo( 0, 0 );
00558     p->lineTo( width() - 1, 0 );
00559 
00560     p->setPen( white );
00561     p->lineTo( width() - 1, height() - 1 );
00562     p->lineTo( 0, height() - 1 );
00563   }
00564 }
00565 
00566 void KDockButton_Private::enterEvent( QEvent * )
00567 {
00568   moveMouse = true;
00569   repaint();
00570 }
00571 
00572 void KDockButton_Private::leaveEvent( QEvent * )
00573 {
00574   moveMouse = false;
00575   repaint();
00576 }
00577 
00578 /*************************************************************************/
00579 KDockWidgetPrivate::KDockWidgetPrivate()
00580   : QObject()
00581   ,index(-1)
00582   ,splitPosInPercent(50)
00583   ,pendingFocusInEvent(false)
00584   ,blockHasUndockedSignal(false)
00585   ,pendingDtor(false)
00586   ,forcedWidth(-1)
00587   ,forcedHeight(-1)
00588   ,isContainer(false)
00589   ,container(0)
00590   ,resizePos(0,0)
00591   ,resizing(false)
00592 {
00593 #ifndef NO_KDE2
00594   windowType = NET::Normal;
00595 #endif
00596 
00597   _parent = 0L;
00598   transient = false;
00599 }
00600 
00601 KDockWidgetPrivate::~KDockWidgetPrivate()
00602 {
00603 }
00604 
00605 void KDockWidgetPrivate::slotFocusEmbeddedWidget(QWidget* w)
00606 {
00607    if (w) {
00608       QWidget* embeddedWdg = ((KDockWidget*)w)->getWidget();
00609       if (embeddedWdg && ((embeddedWdg->focusPolicy() == QWidget::ClickFocus) || (embeddedWdg->focusPolicy() == QWidget::StrongFocus))) {
00610          embeddedWdg->setFocus();
00611       }
00612    }
00613 }
00614 
00615 #ifndef NO_INCLUDE_MOCFILES // for Qt-only projects, because tmake doesn't take this name
00616 #include "kdockwidget_private.moc"
00617 #endif
KDE Logo
This file is part of the documentation for kdeui Library Version 3.3.90.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Wed Mar 30 10:12:00 2005 by doxygen 1.3.9.1 written by Dimitri van Heesch, © 1997-2003