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