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