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