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