00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "kdockwidget.h"
00019 #include "kdockwidget_private.h"
00020
00021 #include <qpainter.h>
00022 #include <qcursor.h>
00023 #include <kdebug.h>
00024 #include <qtimer.h>
00025
00026 KDockSplitter::KDockSplitter(QWidget *parent, const char *name, Orientation orient, int pos, bool highResolution)
00027 : QWidget(parent, name)
00028 {
00029 divider = 0L;
00030 child0 = 0L;
00031 child1 = 0L;
00032 fixedWidth0=-1;
00033 fixedWidth1=-1;
00034 fixedHeight0=-1;
00035 fixedHeight1=-1;
00036
00037 m_orientation = orient;
00038 mOpaqueResize = false;
00039 mKeepSize = false;
00040 mHighResolution = highResolution;
00041 setSeparatorPos( pos, false );
00042 initialised = false;
00043 }
00044
00045 void KDockSplitter::activate(QWidget *c0, QWidget *c1)
00046 {
00047 if ( c0 ) child0 = c0;
00048 if ( c1 ) child1 = c1;
00049
00050 setupMinMaxSize();
00051
00052 if (divider) delete divider;
00053 divider = new QFrame(this, "pannerdivider");
00054 divider->setFrameStyle(QFrame::Panel | QFrame::Raised);
00055 divider->setLineWidth(1);
00056 divider->raise();
00057
00058 if (m_orientation == Horizontal)
00059 divider->setCursor(QCursor(sizeVerCursor));
00060 else
00061 divider->setCursor(QCursor(sizeHorCursor));
00062
00063 divider->installEventFilter(this);
00064
00065 initialised= true;
00066
00067 updateName();
00068
00069 divider->show();
00070 resizeEvent(0);
00071 if (fixedWidth0!=-1) restoreFromForcedFixedSize((KDockWidget*)child0);
00072 if (fixedWidth1!=-1) restoreFromForcedFixedSize((KDockWidget*)child1);
00073 if (((KDockWidget*)child0)->forcedFixedWidth()!=-1)
00074 {
00075 setForcedFixedWidth(((KDockWidget*)child0),((KDockWidget*)child0)->forcedFixedWidth());
00076
00077 }
00078 else
00079 if (((KDockWidget*)child1)->forcedFixedWidth()!=-1)
00080 {
00081 setForcedFixedWidth(((KDockWidget*)child1),((KDockWidget*)child1)->forcedFixedWidth());
00082
00083 }
00084 }
00085
00086
00087
00088
00089
00090
00091
00092
00093 void KDockSplitter::setForcedFixedWidth(KDockWidget *dw,int w)
00094 {
00095 int factor = (mHighResolution)? 10000:100;
00096 if (dw==child0)
00097 {
00098 fixedWidth0=w;
00099
00100 savedXPos=xpos;
00101 setSeparatorPos(w*factor/width(),true);
00102
00103 }
00104 else
00105 {
00106 fixedWidth1=w;
00107 savedXPos=xpos;
00108 setSeparatorPos((width()-w)*factor/width(),true);
00109
00110
00111 }
00112 }
00113
00114 void KDockSplitter::setForcedFixedHeight(KDockWidget *dw,int h)
00115 {
00116 int factor = (mHighResolution)? 10000:100;
00117 if (dw==child0)
00118 {
00119 fixedHeight0=h;
00120
00121 savedXPos=xpos;
00122 setSeparatorPos(h*factor/height(),true);
00123
00124 }
00125 else
00126 {
00127 fixedHeight1=h;
00128 savedXPos=xpos;
00129 setSeparatorPos((height()-h)*factor/height(),true);
00130
00131 }
00132 }
00133
00134 void KDockSplitter::restoreFromForcedFixedSize(KDockWidget *dw)
00135 {
00136 if (dw==child0)
00137 {
00138 fixedWidth0=-1;
00139 fixedHeight0=-1;
00140 setSeparatorPos(savedXPos,true);
00141 }
00142 else
00143 {
00144 fixedWidth1=-1;
00145 fixedHeight1=-1;
00146 setSeparatorPos(savedXPos,true);
00147 }
00148 }
00149
00150
00151 void KDockSplitter::setupMinMaxSize()
00152 {
00153
00154 int minx, maxx, miny, maxy;
00155 if (m_orientation == Horizontal) {
00156 miny = child0->minimumSize().height() + child1->minimumSize().height()+4;
00157 maxy = child0->maximumSize().height() + child1->maximumSize().height()+4;
00158 minx = (child0->minimumSize().width() > child1->minimumSize().width()) ? child0->minimumSize().width() : child1->minimumSize().width();
00159 maxx = (child0->maximumSize().width() > child1->maximumSize().width()) ? child0->maximumSize().width() : child1->maximumSize().width();
00160
00161 miny = (miny > 4) ? miny : 4;
00162 maxy = (maxy < 32000) ? maxy : 32000;
00163 minx = (minx > 2) ? minx : 2;
00164 maxx = (maxx < 32000) ? maxx : 32000;
00165 } else {
00166 minx = child0->minimumSize().width() + child1->minimumSize().width()+4;
00167 maxx = child0->maximumSize().width() + child1->maximumSize().width()+4;
00168 miny = (child0->minimumSize().height() > child1->minimumSize().height()) ? child0->minimumSize().height() : child1->minimumSize().height();
00169 maxy = (child0->maximumSize().height() > child1->maximumSize().height()) ? child0->maximumSize().height() : child1->maximumSize().height();
00170
00171 minx = (minx > 4) ? minx : 4;
00172 maxx = (maxx < 32000) ? maxx : 32000;
00173 miny = (miny > 2) ? miny : 2;
00174 maxy = (maxy < 32000) ? maxy : 32000;
00175 }
00176 setMinimumSize(minx, miny);
00177 setMaximumSize(maxx, maxy);
00178 }
00179
00180 void KDockSplitter::deactivate()
00181 {
00182 if (divider) delete divider;
00183 divider = 0L;
00184 initialised= false;
00185 }
00186
00187 void KDockSplitter::setSeparatorPos(int pos, bool do_resize)
00188 {
00189 xpos = pos;
00190 if (do_resize)
00191 resizeEvent(0);
00192 }
00193
00194 int KDockSplitter::separatorPos() const
00195 {
00196 return xpos;
00197 }
00198
00199 void KDockSplitter::resizeEvent(QResizeEvent *ev)
00200 {
00201
00202
00203 if (initialised){
00204 int factor = (mHighResolution)? 10000:100;
00205
00206 if (ev && mKeepSize && isVisible()) {
00207
00208
00209 if (ev->oldSize().width() != ev->size().width())
00210 {
00211 if (m_orientation == Horizontal) {
00212 xpos = factor * checkValue( child0->height()+1 ) / height();
00213 } else {
00214 xpos = factor * checkValue( child0->width()+1 ) / width();
00215 }
00216
00217 }
00218 }
00219 else
00220 {
00221
00222 if (ev && isVisible()) {
00223 if (m_orientation == Horizontal) {
00224 if (ev->oldSize().height() != ev->size().height())
00225 {
00226 if (fixedHeight0!=-1)
00227 xpos=fixedHeight0*factor/height();
00228 else
00229 if (fixedHeight1!=-1)
00230 xpos=(height()-fixedHeight1)*factor/height();
00231 }
00232 }
00233 else
00234 {
00235 if (ev->oldSize().width() != ev->size().width())
00236 {
00237 if (fixedWidth0!=-1)
00238 xpos=fixedWidth0*factor/width();
00239 else
00240 if (fixedWidth1!=-1)
00241 xpos=(width()-fixedWidth1)*factor/width();
00242 }
00243 }
00244 }
00245
00246 }
00247
00248 int position = checkValue( (m_orientation == Vertical ? width() : height()) * xpos/factor );
00249 if (m_orientation == Horizontal){
00250 child0->setGeometry(0, 0, width(), position);
00251 child1->setGeometry(0, position+4, width(), height()-position-4);
00252 divider->setGeometry(0, position, width(), 4);
00253 } else {
00254 child0->setGeometry(0, 0, position, height());
00255 child1->setGeometry(position+4, 0, width()-position-4, height());
00256 divider->setGeometry(position, 0, 4, height());
00257 }
00258 }
00259 }
00260
00261 int KDockSplitter::checkValue( int position ) const
00262 {
00263 if (initialised){
00264 if (m_orientation == Vertical){
00265 if (position < (child0->minimumSize().width()))
00266 position = child0->minimumSize().width();
00267 if ((width()-4-position) < (child1->minimumSize().width()))
00268 position = width() - (child1->minimumSize().width()) -4;
00269 } else {
00270 if (position < (child0->minimumSize().height()))
00271 position = (child0->minimumSize().height());
00272 if ((height()-4-position) < (child1->minimumSize().height()))
00273 position = height() - (child1->minimumSize().height()) -4;
00274 }
00275 }
00276
00277 if (position < 0) position = 0;
00278
00279 if ((m_orientation == Vertical) && (position > width()))
00280 position = width();
00281 if ((m_orientation == Horizontal) && (position > height()))
00282 position = height();
00283
00284 return position;
00285 }
00286
00287 bool KDockSplitter::eventFilter(QObject *o, QEvent *e)
00288 {
00289 QMouseEvent *mev;
00290 bool handled = false;
00291 int factor = (mHighResolution)? 10000:100;
00292
00293 switch (e->type()) {
00294 case QEvent::MouseMove:
00295 mev= (QMouseEvent*)e;
00296 child0->setUpdatesEnabled(mOpaqueResize);
00297 child1->setUpdatesEnabled(mOpaqueResize);
00298 if (m_orientation == Horizontal) {
00299 if ((fixedHeight0!=-1) || (fixedHeight1!=-1))
00300 {
00301 handled=true; break;
00302 }
00303
00304 if (!mOpaqueResize) {
00305 int position = checkValue( mapFromGlobal(mev->globalPos()).y() );
00306 divider->move( 0, position );
00307 } else {
00308 xpos = factor * checkValue( mapFromGlobal(mev->globalPos()).y() ) / height();
00309 resizeEvent(0);
00310 divider->repaint(true);
00311 }
00312 } else {
00313 if ((fixedWidth0!=-1) || (fixedWidth1!=-1))
00314 {
00315 handled=true; break;
00316 }
00317 if (!mOpaqueResize) {
00318 int position = checkValue( mapFromGlobal(QCursor::pos()).x() );
00319 divider->move( position, 0 );
00320 } else {
00321 xpos = factor * checkValue( mapFromGlobal( mev->globalPos()).x() ) / width();
00322 resizeEvent(0);
00323 divider->repaint(true);
00324 }
00325 }
00326 handled= true;
00327 break;
00328 case QEvent::MouseButtonRelease:
00329 child0->setUpdatesEnabled(true);
00330 child1->setUpdatesEnabled(true);
00331 mev= (QMouseEvent*)e;
00332 if (m_orientation == Horizontal){
00333 if ((fixedHeight0!=-1) || (fixedHeight1!=-1))
00334 {
00335 handled=true; break;
00336 }
00337 xpos = factor* checkValue( mapFromGlobal(mev->globalPos()).y() ) / height();
00338 resizeEvent(0);
00339 divider->repaint(true);
00340 } else {
00341 if ((fixedWidth0!=-1) || (fixedWidth1!=-1))
00342 {
00343 handled=true; break;
00344 }
00345 xpos = factor* checkValue( mapFromGlobal(mev->globalPos()).x() ) / width();
00346 resizeEvent(0);
00347 divider->repaint(true);
00348 }
00349 handled= true;
00350 break;
00351 default:
00352 break;
00353 }
00354 return (handled) ? true : QWidget::eventFilter( o, e );
00355 }
00356
00357 bool KDockSplitter::event( QEvent* e )
00358 {
00359 if ( e->type() == QEvent::LayoutHint ){
00360
00361 setupMinMaxSize();
00362 setSeparatorPos(xpos);
00363 }
00364 return QWidget::event(e);
00365 }
00366
00367 QWidget* KDockSplitter::getAnother( QWidget* w ) const
00368 {
00369 return ( w == child0 ) ? child1 : child0;
00370 }
00371
00372 void KDockSplitter::updateName()
00373 {
00374 if ( !initialised ) return;
00375
00376 QString new_name = QString( child0->name() ) + "," + child1->name();
00377 parentWidget()->setName( new_name.latin1() );
00378 parentWidget()->setCaption( child0->caption() + "," + child1->caption() );
00379 parentWidget()->repaint( false );
00380
00381 ((KDockWidget*)parentWidget())->firstName = child0->name();
00382 ((KDockWidget*)parentWidget())->lastName = child1->name();
00383 ((KDockWidget*)parentWidget())->splitterOrientation = m_orientation;
00384
00385 QWidget* p = parentWidget()->parentWidget();
00386 if ( p != 0L && p->inherits("KDockSplitter" ) )
00387 ((KDockSplitter*)p)->updateName();
00388 }
00389
00390 void KDockSplitter::setOpaqueResize(bool b)
00391 {
00392 mOpaqueResize = b;
00393 }
00394
00395 bool KDockSplitter::opaqueResize() const
00396 {
00397 return mOpaqueResize;
00398 }
00399
00400 void KDockSplitter::setKeepSize(bool b)
00401 {
00402 mKeepSize = b;
00403 }
00404
00405 bool KDockSplitter::keepSize() const
00406 {
00407 return mKeepSize;
00408 }
00409
00410 void KDockSplitter::setHighResolution(bool b)
00411 {
00412 if (mHighResolution) {
00413 if (!b) xpos = xpos/100;
00414 } else {
00415 if (b) xpos = xpos*100;
00416 }
00417 mHighResolution = b;
00418 }
00419
00420 bool KDockSplitter::highResolution() const
00421 {
00422 return mHighResolution;
00423 }
00424
00425
00426
00427 KDockButton_Private::KDockButton_Private( QWidget *parent, const char * name )
00428 :QPushButton( parent, name )
00429 {
00430 moveMouse = false;
00431 setFocusPolicy( NoFocus );
00432 }
00433
00434 KDockButton_Private::~KDockButton_Private()
00435 {
00436 }
00437
00438 void KDockButton_Private::drawButton( QPainter* p )
00439 {
00440 p->fillRect( 0,0, width(), height(), QBrush(colorGroup().brush(QColorGroup::Background)) );
00441 p->drawPixmap( (width() - pixmap()->width()) / 2, (height() - pixmap()->height()) / 2, *pixmap() );
00442 if ( moveMouse && !isDown() ){
00443 p->setPen( white );
00444 p->moveTo( 0, height() - 1 );
00445 p->lineTo( 0, 0 );
00446 p->lineTo( width() - 1, 0 );
00447
00448 p->setPen( colorGroup().dark() );
00449 p->lineTo( width() - 1, height() - 1 );
00450 p->lineTo( 0, height() - 1 );
00451 }
00452 if ( isOn() || isDown() ){
00453 p->setPen( colorGroup().dark() );
00454 p->moveTo( 0, height() - 1 );
00455 p->lineTo( 0, 0 );
00456 p->lineTo( width() - 1, 0 );
00457
00458 p->setPen( white );
00459 p->lineTo( width() - 1, height() - 1 );
00460 p->lineTo( 0, height() - 1 );
00461 }
00462 }
00463
00464 void KDockButton_Private::enterEvent( QEvent * )
00465 {
00466 moveMouse = true;
00467 repaint();
00468 }
00469
00470 void KDockButton_Private::leaveEvent( QEvent * )
00471 {
00472 moveMouse = false;
00473 repaint();
00474 }
00475
00476
00477 KDockWidgetPrivate::KDockWidgetPrivate()
00478 : QObject()
00479 ,index(-1)
00480 ,splitPosInPercent(50)
00481 ,pendingFocusInEvent(false)
00482 ,blockHasUndockedSignal(false)
00483 ,pendingDtor(false)
00484 ,forcedWidth(-1)
00485 ,forcedHeight(-1)
00486 ,isContainer(false)
00487 ,container(0)
00488 ,resizePos(0,0)
00489 ,resizing(false)
00490 {
00491 #ifndef NO_KDE2
00492 windowType = NET::Normal;
00493 #endif
00494
00495 _parent = 0L;
00496 transient = false;
00497 }
00498
00499 KDockWidgetPrivate::~KDockWidgetPrivate()
00500 {
00501 }
00502
00503 void KDockWidgetPrivate::slotFocusEmbeddedWidget(QWidget* w)
00504 {
00505 if (w) {
00506 QWidget* embeddedWdg = ((KDockWidget*)w)->getWidget();
00507 if (embeddedWdg && ((embeddedWdg->focusPolicy() == QWidget::ClickFocus) || (embeddedWdg->focusPolicy() == QWidget::StrongFocus))) {
00508 embeddedWdg->setFocus();
00509 }
00510 }
00511 }
00512
00513 #ifndef NO_INCLUDE_MOCFILES // for Qt-only projects, because tmake doesn't take this name
00514 #include "kdockwidget_private.moc"
00515 #endif