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