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
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
00079 }
00080 else
00081 if (((KDockWidget*)child1)->forcedFixedWidth()!=-1)
00082 {
00083 setForcedFixedWidth(((KDockWidget*)child1),((KDockWidget*)child1)->forcedFixedWidth());
00084
00085 }
00086
00087 if (((KDockWidget*)child0)->forcedFixedHeight()!=-1)
00088 {
00089 setForcedFixedHeight(((KDockWidget*)child0),((KDockWidget*)child0)->forcedFixedHeight());
00090
00091 }
00092 else
00093 if (((KDockWidget*)child1)->forcedFixedHeight()!=-1)
00094 {
00095 setForcedFixedHeight(((KDockWidget*)child1),((KDockWidget*)child1)->forcedFixedHeight());
00096
00097 }
00098
00099
00100 }
00101
00102
00103
00104
00105
00106
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
00116 savedXPos=xpos;
00117 setSeparatorPos(w*factor/width(),true);
00118
00119 }
00120 else
00121 {
00122 fixedWidth1=w;
00123 savedXPos=xpos;
00124 setSeparatorPos((width()-w)*factor/width(),true);
00125
00126
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
00138 savedXPos=xpos;
00139 setSeparatorPos(h*factor/height(),true);
00140
00141 }
00142 else
00143 {
00144 fixedHeight1=h;
00145 savedXPos=xpos;
00146 setSeparatorPos((height()-h)*factor/height(),true);
00147
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
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
00227
00228 if (initialised){
00229 int factor = (mHighResolution)? 10000:100;
00230
00231 if (ev && mKeepSize && isVisible()) {
00232
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
00247 if ( isVisible()) {
00248 if (m_orientation == Horizontal) {
00249
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
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
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 {
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
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