00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include "KDGanttMinimizeSplitter.h"
00035 #ifndef QT_NO_SPLITTER
00036
00037 #include "qpainter.h"
00038 #include "qdrawutil.h"
00039 #include "qbitmap.h"
00040 #if QT_VERSION >= 300
00041 #include "qptrlist.h"
00042 #include "qmemarray.h"
00043 #else
00044 #include <qlist.h>
00045 #include <qarray.h>
00046 #define QPtrList QList
00047 #define QMemArray QArray
00048 #endif
00049 #include "qlayoutengine_p.h"
00050 #include "qobjectlist.h"
00051 #include "qstyle.h"
00052 #include "qapplication.h"
00053 #include <qvaluelist.h>
00054 #include <qcursor.h>
00055 #ifndef KDGANTT_MASTER_CVS
00056 #include "KDGanttMinimizeSplitter.moc"
00057 #endif
00058
00059
00060 #ifndef DOXYGEN_SKIP_INTERNAL
00061
00062 #if QT_VERSION >= 300
00063 static int mouseOffset;
00064 static int opaqueOldPos = -1;
00065
00066
00067 KDGanttSplitterHandle::KDGanttSplitterHandle( Qt::Orientation o,
00068 KDGanttMinimizeSplitter *parent, const char * name )
00069 : QWidget( parent, name ), _activeButton( 0 ), _collapsed( false )
00070 {
00071 s = parent;
00072 setOrientation(o);
00073 setMouseTracking( true );
00074 }
00075
00076 QSize KDGanttSplitterHandle::sizeHint() const
00077 {
00078 return QSize(8,8);
00079 }
00080
00081 void KDGanttSplitterHandle::setOrientation( Qt::Orientation o )
00082 {
00083 orient = o;
00084 #ifndef QT_NO_CURSOR
00085 if ( o == KDGanttMinimizeSplitter::Horizontal )
00086 setCursor( splitHCursor );
00087 else
00088 setCursor( splitVCursor );
00089 #endif
00090 }
00091
00092
00093 void KDGanttSplitterHandle::mouseMoveEvent( QMouseEvent *e )
00094 {
00095 updateCursor( e->pos() );
00096 if ( !(e->state()&LeftButton) )
00097 return;
00098
00099 if ( _activeButton != 0)
00100 return;
00101
00102 QCOORD pos = s->pick(parentWidget()->mapFromGlobal(e->globalPos()))
00103 - mouseOffset;
00104 if ( opaque() ) {
00105 s->moveSplitter( pos, id() );
00106 } else {
00107 int min = pos; int max = pos;
00108 s->getRange( id(), &min, &max );
00109 s->setRubberband( QMAX( min, QMIN(max, pos )));
00110 }
00111 _collapsed = false;
00112 }
00113
00114 void KDGanttSplitterHandle::mousePressEvent( QMouseEvent *e )
00115 {
00116 if ( e->button() == LeftButton ) {
00117 _activeButton = onButton( e->pos() );
00118 mouseOffset = s->pick(e->pos());
00119 if ( _activeButton != 0)
00120 repaint();
00121 updateCursor( e->pos() );
00122 }
00123 }
00124
00125 void KDGanttSplitterHandle::updateCursor( const QPoint& p)
00126 {
00127 if ( onButton( p ) != 0 ) {
00128 setCursor( arrowCursor );
00129 }
00130 else {
00131 if ( orient == KDGanttMinimizeSplitter::Horizontal )
00132 setCursor( splitHCursor );
00133 else
00134 setCursor( splitVCursor );
00135 }
00136 }
00137
00138
00139 void KDGanttSplitterHandle::mouseReleaseEvent( QMouseEvent *e )
00140 {
00141 if ( _activeButton != 0 ) {
00142 if ( onButton( e->pos() ) == _activeButton )
00143 {
00144 int pos;
00145 int min, max;
00146 if ( !_collapsed ) {
00147 s->expandPos( id(), &min, &max );
00148 if ( s->minimizeDirection() == KDGanttMinimizeSplitter::Left
00149 || s->minimizeDirection() == KDGanttMinimizeSplitter::Up ) {
00150 pos = min;
00151 }
00152 else {
00153 pos = max;
00154 }
00155
00156 _origPos = s->pick(mapToParent( QPoint( 0,0 ) ));
00157 s->moveSplitter( pos, id() );
00158 _collapsed = true;
00159 }
00160 else {
00161 s->moveSplitter( _origPos, id() );
00162 _collapsed = false;
00163 }
00164
00165 }
00166 _activeButton = 0;
00167 updateCursor( e->pos() );
00168 }
00169 else {
00170 if ( !opaque() && e->button() == LeftButton ) {
00171 QCOORD pos = s->pick(parentWidget()->mapFromGlobal(e->globalPos()))
00172 - mouseOffset;
00173 s->setRubberband( -1 );
00174 s->moveSplitter( pos, id() );
00175 }
00176 }
00177 repaint();
00178 }
00179
00180 int KDGanttSplitterHandle::onButton( const QPoint& p )
00181 {
00182 QValueList<QPointArray> list = buttonRegions();
00183 int index = 1;
00184 for( QValueList<QPointArray>::Iterator it = list.begin(); it != list.end(); ++it ) {
00185 QRect rect = (*it).boundingRect();
00186 rect.setLeft( rect.left()- 4 );
00187 rect.setRight( rect.right() + 4);
00188 rect.setTop( rect.top()- 4 );
00189 rect.setBottom( rect.bottom() + 4);
00190 if ( rect.contains( p ) ) {
00191 return index;
00192 }
00193 index++;
00194 }
00195 return 0;
00196 }
00197
00198
00199 QValueList<QPointArray> KDGanttSplitterHandle::buttonRegions()
00200 {
00201 QValueList<QPointArray> list;
00202
00203 int sw = 8;
00204 int voffset[] = { (int) -sw*3, (int) sw*3 };
00205 for ( int i = 0; i < 2; i++ ) {
00206 QPointArray arr;
00207 if ( !_collapsed && s->minimizeDirection() == KDGanttMinimizeSplitter::Right ||
00208 _collapsed && s->minimizeDirection() == KDGanttMinimizeSplitter::Left) {
00209 int mid = height()/2 + voffset[i];
00210 arr.setPoints( 3,
00211 1, mid - sw + 4,
00212 sw-3, mid,
00213 1, mid + sw -4);
00214 }
00215 else if ( !_collapsed && s->minimizeDirection() == KDGanttMinimizeSplitter::Left ||
00216 _collapsed && s->minimizeDirection() == KDGanttMinimizeSplitter::Right ) {
00217 int mid = height()/2 + voffset[i];
00218 arr.setPoints( 3,
00219 sw-4, mid - sw + 4,
00220 0, mid,
00221 sw-4, mid + sw - 4);
00222 }
00223 else if ( !_collapsed && s->minimizeDirection() == KDGanttMinimizeSplitter::Up ||
00224 _collapsed && s->minimizeDirection() == KDGanttMinimizeSplitter::Down) {
00225 int mid = width()/2 + voffset[i];
00226 arr.setPoints( 3,
00227 mid - sw + 4, sw-4,
00228 mid, 0,
00229 mid + sw - 4, sw-4 );
00230 }
00231 else if ( !_collapsed && s->minimizeDirection() == KDGanttMinimizeSplitter::Down ||
00232 _collapsed && s->minimizeDirection() == KDGanttMinimizeSplitter::Up ) {
00233 int mid = width()/2 + voffset[i];
00234 arr.setPoints( 3,
00235 mid - sw + 4, 1,
00236 mid, sw-3,
00237 mid + sw -4, 1);
00238 }
00239 list.append( arr );
00240 }
00241 return list;
00242 }
00243
00244 void KDGanttSplitterHandle::paintEvent( QPaintEvent * )
00245 {
00246 QPixmap buffer( size() );
00247 QPainter p( &buffer );
00248
00249
00250 p.setBrush( colorGroup().background() );
00251 p.setPen( colorGroup().foreground() );
00252 p.drawRect( rect() );
00253 parentWidget()->style().drawPrimitive( QStyle::PE_Panel, &p, rect(),
00254 parentWidget()->colorGroup());
00255
00256 int sw = 8;
00257
00258
00259 QColor col = colorGroup().background().dark( 200 );
00260 p.setBrush( col );
00261 p.setPen( col );
00262
00263 QValueList<QPointArray> list = buttonRegions();
00264 int index = 1;
00265 for ( QValueList<QPointArray>::Iterator it = list.begin(); it != list.end(); ++it ) {
00266 if ( index == _activeButton ) {
00267 p.save();
00268 p.translate( parentWidget()->style().pixelMetric( QStyle::PM_ButtonShiftHorizontal ),
00269 parentWidget()->style().pixelMetric( QStyle::PM_ButtonShiftVertical ) );
00270 p.drawPolygon( *it, true );
00271 p.restore();
00272 }
00273 else {
00274 p.drawPolygon( *it, true );
00275 }
00276 index++;
00277 }
00278
00279
00280 if ( s->minimizeDirection() == KDGanttMinimizeSplitter::Left ||
00281 s->minimizeDirection() == KDGanttMinimizeSplitter::Right ) {
00282 int mid = height()/2;
00283 p.drawLine ( 2, mid - sw, 2, mid + sw );
00284 p.drawLine ( 4, mid - sw, 4, mid + sw );
00285 }
00286 else if ( s->minimizeDirection() == KDGanttMinimizeSplitter::Up ||
00287 s->minimizeDirection() == KDGanttMinimizeSplitter::Down ) {
00288 int mid = width()/2;
00289 p.drawLine( mid -sw, 2, mid +sw, 2 );
00290 p.drawLine( mid -sw, 4, mid +sw, 4 );
00291 }
00292 bitBlt( this, 0, 0, &buffer );
00293 }
00294 #endif
00295
00296 class QSplitterLayoutStruct
00297 {
00298 public:
00299 KDGanttMinimizeSplitter::ResizeMode mode;
00300 QCOORD sizer;
00301 bool isSplitter;
00302 QWidget *wid;
00303 };
00304
00305 class QSplitterData
00306 {
00307 public:
00308 QSplitterData() : opaque( FALSE ), firstShow( TRUE ) {}
00309
00310 QPtrList<QSplitterLayoutStruct> list;
00311 bool opaque;
00312 bool firstShow;
00313 };
00314
00315 void kdganttGeomCalc( QMemArray<QLayoutStruct> &chain, int start, int count, int pos,
00316 int space, int spacer );
00317 #endif // DOXYGEN_SKIP_INTERNAL
00318
00319
00369 static QSize minSize( const QWidget* )
00370 {
00371 return QSize(0,0);
00372 }
00373
00374
00375 static QSize minSizeHint( const QWidget* w )
00376 {
00377 QSize min = w->minimumSize();
00378 QSize s;
00379 if ( min.height() <= 0 || min.width() <= 0 )
00380 s = w->minimumSizeHint();
00381 if ( min.height() > 0 )
00382 s.setHeight( min.height() );
00383 if ( min.width() > 0 )
00384 s.setWidth( min.width() );
00385 return s.expandedTo(QSize(0,0));
00386 }
00387
00388
00389
00394 KDGanttMinimizeSplitter::KDGanttMinimizeSplitter( QWidget *parent, const char *name )
00395 :QFrame(parent,name,WPaintUnclipped)
00396 {
00397 #if QT_VERSION >= 300
00398 orient = Horizontal;
00399 init();
00400 #endif
00401 }
00402
00407 KDGanttMinimizeSplitter::KDGanttMinimizeSplitter( Orientation o, QWidget *parent, const char *name )
00408 :QFrame(parent,name,WPaintUnclipped)
00409 {
00410 #if QT_VERSION >= 300
00411 orient = o;
00412 init();
00413 #endif
00414 }
00415
00419 KDGanttMinimizeSplitter::~KDGanttMinimizeSplitter()
00420 {
00421 #if QT_VERSION >= 300
00422 data->list.setAutoDelete( TRUE );
00423 delete data;
00424 #endif
00425 }
00426
00427
00428 #if QT_VERSION >= 300
00429 void KDGanttMinimizeSplitter::init()
00430 {
00431 data = new QSplitterData;
00432 if ( orient == Horizontal )
00433 setSizePolicy( QSizePolicy(QSizePolicy::Expanding,QSizePolicy::Minimum) );
00434 else
00435 setSizePolicy( QSizePolicy(QSizePolicy::Minimum,QSizePolicy::Expanding) );
00436 }
00437 #endif
00438
00439
00440
00447 void KDGanttMinimizeSplitter::setOrientation( Orientation o )
00448 {
00449 #if QT_VERSION >= 300
00450 if ( orient == o )
00451 return;
00452 orient = o;
00453
00454 if ( orient == Horizontal )
00455 setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Minimum ) );
00456 else
00457 setSizePolicy( QSizePolicy( QSizePolicy::Minimum, QSizePolicy::Expanding ) );
00458
00459 QSplitterLayoutStruct *s = data->list.first();
00460 while ( s ) {
00461 if ( s->isSplitter )
00462 ((KDGanttSplitterHandle*)s->wid)->setOrientation( o );
00463 s = data->list.next();
00464 }
00465 recalc( isVisible() );
00466 #endif
00467 }
00468
00469
00470 #if QT_VERSION >= 300
00471
00474 void KDGanttMinimizeSplitter::resizeEvent( QResizeEvent * )
00475 {
00476 doResize();
00477 }
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489 QSplitterLayoutStruct *KDGanttMinimizeSplitter::addWidget( QWidget *w, bool first )
00490 {
00491 QSplitterLayoutStruct *s;
00492 KDGanttSplitterHandle *newHandle = 0;
00493 if ( data->list.count() > 0 ) {
00494 s = new QSplitterLayoutStruct;
00495 s->mode = KeepSize;
00496 QString tmp = "qt_splithandle_";
00497 tmp += w->name();
00498 newHandle = new KDGanttSplitterHandle( orientation(), this, tmp.latin1() );
00499 s->wid = newHandle;
00500 newHandle->setId(data->list.count());
00501 s->isSplitter = TRUE;
00502 s->sizer = pick( newHandle->sizeHint() );
00503 if ( first )
00504 data->list.insert( 0, s );
00505 else
00506 data->list.append( s );
00507 }
00508 s = new QSplitterLayoutStruct;
00509 s->mode = Stretch;
00510 s->wid = w;
00511 if ( !testWState( WState_Resized ) && w->sizeHint().isValid() )
00512 s->sizer = pick( w->sizeHint() );
00513 else
00514 s->sizer = pick( w->size() );
00515 s->isSplitter = FALSE;
00516 if ( first )
00517 data->list.insert( 0, s );
00518 else
00519 data->list.append( s );
00520 if ( newHandle && isVisible() )
00521 newHandle->show();
00522 return s;
00523 }
00524
00525
00530 void KDGanttMinimizeSplitter::childEvent( QChildEvent *c )
00531 {
00532 if ( c->type() == QEvent::ChildInserted ) {
00533 if ( !c->child()->isWidgetType() )
00534 return;
00535
00536 if ( ((QWidget*)c->child())->testWFlags( WType_TopLevel ) )
00537 return;
00538
00539 QSplitterLayoutStruct *s = data->list.first();
00540 while ( s ) {
00541 if ( s->wid == c->child() )
00542 return;
00543 s = data->list.next();
00544 }
00545 addWidget( (QWidget*)c->child() );
00546 recalc( isVisible() );
00547
00548 } else if ( c->type() == QEvent::ChildRemoved ) {
00549 QSplitterLayoutStruct *p = 0;
00550 if ( data->list.count() > 1 )
00551 p = data->list.at(1);
00552 QSplitterLayoutStruct *s = data->list.first();
00553 while ( s ) {
00554 if ( s->wid == c->child() ) {
00555 data->list.removeRef( s );
00556 delete s;
00557 if ( p && p->isSplitter ) {
00558 data->list.removeRef( p );
00559 delete p->wid;
00560 delete p;
00561 }
00562 recalcId();
00563 doResize();
00564 return;
00565 }
00566 p = s;
00567 s = data->list.next();
00568 }
00569 }
00570 }
00571
00572
00577 void KDGanttMinimizeSplitter::setRubberband( int p )
00578 {
00579 QPainter paint( this );
00580 paint.setPen( gray );
00581 paint.setBrush( gray );
00582 paint.setRasterOp( XorROP );
00583 QRect r = contentsRect();
00584 const int rBord = 3;
00585 int sw = style().pixelMetric(QStyle::PM_SplitterWidth, this);
00586 if ( orient == Horizontal ) {
00587 if ( opaqueOldPos >= 0 )
00588 paint.drawRect( opaqueOldPos + sw/2 - rBord , r.y(),
00589 2*rBord, r.height() );
00590 if ( p >= 0 )
00591 paint.drawRect( p + sw/2 - rBord, r.y(), 2*rBord, r.height() );
00592 } else {
00593 if ( opaqueOldPos >= 0 )
00594 paint.drawRect( r.x(), opaqueOldPos + sw/2 - rBord,
00595 r.width(), 2*rBord );
00596 if ( p >= 0 )
00597 paint.drawRect( r.x(), p + sw/2 - rBord, r.width(), 2*rBord );
00598 }
00599 opaqueOldPos = p;
00600 }
00601
00602
00604 bool KDGanttMinimizeSplitter::event( QEvent *e )
00605 {
00606 if ( e->type() == QEvent::LayoutHint || ( e->type() == QEvent::Show && data->firstShow ) ) {
00607 recalc( isVisible() );
00608 if ( e->type() == QEvent::Show )
00609 data->firstShow = FALSE;
00610 }
00611 return QWidget::event( e );
00612 }
00613
00614
00622 void KDGanttMinimizeSplitter::drawSplitter( QPainter *p,
00623 QCOORD x, QCOORD y, QCOORD w, QCOORD h )
00624 {
00625 style().drawPrimitive(QStyle::PE_Splitter, p, QRect(x, y, w, h), colorGroup(),
00626 (orientation() == Qt::Horizontal ?
00627 QStyle::Style_Horizontal : 0));
00628 }
00629
00630
00636 int KDGanttMinimizeSplitter::idAfter( QWidget* w ) const
00637 {
00638 QSplitterLayoutStruct *s = data->list.first();
00639 bool seen_w = FALSE;
00640 while ( s ) {
00641 if ( s->isSplitter && seen_w )
00642 return data->list.at();
00643 if ( !s->isSplitter && s->wid == w )
00644 seen_w = TRUE;
00645 s = data->list.next();
00646 }
00647 return 0;
00648 }
00649
00650
00663 void KDGanttMinimizeSplitter::moveSplitter( QCOORD p, int id )
00664 {
00665 p = adjustPos( p, id );
00666
00667 QSplitterLayoutStruct *s = data->list.at(id);
00668 int oldP = orient == Horizontal ? s->wid->x() : s->wid->y();
00669 bool upLeft;
00670 if ( QApplication::reverseLayout() && orient == Horizontal ) {
00671 p += s->wid->width();
00672 upLeft = p > oldP;
00673 } else
00674 upLeft = p < oldP;
00675
00676 moveAfter( p, id, upLeft );
00677 moveBefore( p-1, id-1, upLeft );
00678
00679 storeSizes();
00680 }
00681
00682
00683 void KDGanttMinimizeSplitter::setG( QWidget *w, int p, int s, bool isSplitter )
00684 {
00685 if ( orient == Horizontal ) {
00686 if ( QApplication::reverseLayout() && orient == Horizontal && !isSplitter )
00687 p = contentsRect().width() - p - s;
00688 w->setGeometry( p, contentsRect().y(), s, contentsRect().height() );
00689 } else
00690 w->setGeometry( contentsRect().x(), p, contentsRect().width(), s );
00691 }
00692
00693
00694
00695
00696
00697
00698
00699 void KDGanttMinimizeSplitter::moveBefore( int pos, int id, bool upLeft )
00700 {
00701 if( id < 0 )
00702 return;
00703 QSplitterLayoutStruct *s = data->list.at(id);
00704 if ( !s )
00705 return;
00706 QWidget *w = s->wid;
00707 if ( w->isHidden() ) {
00708 moveBefore( pos, id-1, upLeft );
00709 } else if ( s->isSplitter ) {
00710 int pos1, pos2;
00711 int dd = s->sizer;
00712 if( QApplication::reverseLayout() && orient == Horizontal ) {
00713 pos1 = pos;
00714 pos2 = pos + dd;
00715 } else {
00716 pos2 = pos - dd;
00717 pos1 = pos2 + 1;
00718 }
00719 if ( upLeft ) {
00720 setG( w, pos1, dd, TRUE );
00721 moveBefore( pos2, id-1, upLeft );
00722 } else {
00723 moveBefore( pos2, id-1, upLeft );
00724 setG( w, pos1, dd, TRUE );
00725 }
00726 } else {
00727 int dd, newLeft, nextPos;
00728 if( QApplication::reverseLayout() && orient == Horizontal ) {
00729 dd = w->geometry().right() - pos;
00730 dd = QMAX( pick(minSize(w)), QMIN(dd, pick(w->maximumSize())));
00731 newLeft = pos+1;
00732 nextPos = newLeft + dd;
00733 } else {
00734 dd = pos - pick( w->pos() ) + 1;
00735 dd = QMAX( pick(minSize(w)), QMIN(dd, pick(w->maximumSize())));
00736 newLeft = pos-dd+1;
00737 nextPos = newLeft - 1;
00738 }
00739 setG( w, newLeft, dd, TRUE );
00740 moveBefore( nextPos, id-1, upLeft );
00741 }
00742 }
00743
00744
00745
00746
00747
00748
00749
00750 void KDGanttMinimizeSplitter::moveAfter( int pos, int id, bool upLeft )
00751 {
00752 QSplitterLayoutStruct *s = id < int(data->list.count()) ?
00753 data->list.at(id) : 0;
00754 if ( !s )
00755 return;
00756 QWidget *w = s->wid;
00757 if ( w->isHidden() ) {
00758 moveAfter( pos, id+1, upLeft );
00759 } else if ( pick( w->pos() ) == pos ) {
00760
00761 return;
00762 } else if ( s->isSplitter ) {
00763 int dd = s->sizer;
00764 int pos1, pos2;
00765 if( QApplication::reverseLayout() && orient == Horizontal ) {
00766 pos2 = pos - dd;
00767 pos1 = pos2 + 1;
00768 } else {
00769 pos1 = pos;
00770 pos2 = pos + dd;
00771 }
00772 if ( upLeft ) {
00773 setG( w, pos1, dd, TRUE );
00774 moveAfter( pos2, id+1, upLeft );
00775 } else {
00776 moveAfter( pos2, id+1, upLeft );
00777 setG( w, pos1, dd, TRUE );
00778 }
00779 } else {
00780 int left = pick( w->pos() );
00781 int right, dd, newLeft, nextPos;
00782 if ( QApplication::reverseLayout() && orient == Horizontal ) {
00783 dd = pos - left + 1;
00784 dd = QMAX( pick(minSize(w)), QMIN(dd, pick(w->maximumSize())));
00785 newLeft = pos-dd+1;
00786 nextPos = newLeft - 1;
00787 } else {
00788 right = pick( w->geometry().bottomRight() );
00789 dd = right - pos + 1;
00790 dd = QMAX( pick(minSize(w)), QMIN(dd, pick(w->maximumSize())));
00791
00792 newLeft = pos;
00793 nextPos = newLeft + dd;
00794 }
00795 setG( w, newLeft, dd, TRUE );
00796
00797 moveAfter( nextPos, id+1, upLeft );
00798 }
00799 }
00800
00801
00802 void KDGanttMinimizeSplitter::expandPos( int id, int* min, int* max )
00803 {
00804 QSplitterLayoutStruct *s = data->list.at(id-1);
00805 QWidget* w = s->wid;
00806 *min = pick( w->mapToParent( QPoint(0,0) ) );
00807
00808 if ( (uint) id == data->list.count() ) {
00809 pick( size() );
00810 }
00811 else {
00812 QSplitterLayoutStruct *s = data->list.at(id+1);
00813 QWidget* w = s->wid;
00814 *max = pick( w->mapToParent( QPoint( w->width(), w->height() ) ) ) -8;
00815 }
00816 }
00817
00818
00825 void KDGanttMinimizeSplitter::getRange( int id, int *min, int *max )
00826 {
00827 int minB = 0;
00828 int maxB = 0;
00829 int minA = 0;
00830 int maxA = 0;
00831 int n = data->list.count();
00832 if ( id < 0 || id >= n )
00833 return;
00834 int i;
00835 for ( i = 0; i < id; i++ ) {
00836 QSplitterLayoutStruct *s = data->list.at(i);
00837 if ( s->wid->isHidden() ) {
00838
00839 } else if ( s->isSplitter ) {
00840 minB += s->sizer;
00841 maxB += s->sizer;
00842 } else {
00843 minB += pick( minSize(s->wid) );
00844 maxB += pick( s->wid->maximumSize() );
00845 }
00846 }
00847 for ( i = id; i < n; i++ ) {
00848 QSplitterLayoutStruct *s = data->list.at(i);
00849 if ( s->wid->isHidden() ) {
00850
00851 } else if ( s->isSplitter ) {
00852 minA += s->sizer;
00853 maxA += s->sizer;
00854 } else {
00855 minA += pick( minSize(s->wid) );
00856 maxA += pick( s->wid->maximumSize() );
00857 }
00858 }
00859 QRect r = contentsRect();
00860 if ( orient == Horizontal && QApplication::reverseLayout() ) {
00861 int splitterWidth = style().pixelMetric(QStyle::PM_SplitterWidth, this);
00862 if ( min )
00863 *min = pick(r.topRight()) - QMIN( maxB, pick(r.size())-minA ) - splitterWidth;
00864 if ( max )
00865 *max = pick(r.topRight()) - QMAX( minB, pick(r.size())-maxA ) - splitterWidth;
00866 } else {
00867 if ( min )
00868 *min = pick(r.topLeft()) + QMAX( minB, pick(r.size())-maxA );
00869 if ( max )
00870 *max = pick(r.topLeft()) + QMIN( maxB, pick(r.size())-minA );
00871 }
00872 }
00873
00874
00881 int KDGanttMinimizeSplitter::adjustPos( int p, int id )
00882 {
00883 int min = 0;
00884 int max = 0;
00885 getRange( id, &min, &max );
00886 p = QMAX( min, QMIN( p, max ) );
00887
00888 return p;
00889 }
00890
00891
00892 void KDGanttMinimizeSplitter::doResize()
00893 {
00894 QRect r = contentsRect();
00895 int i;
00896 int n = data->list.count();
00897 QMemArray<QLayoutStruct> a( n );
00898 for ( i = 0; i< n; i++ ) {
00899 a[i].init();
00900 QSplitterLayoutStruct *s = data->list.at(i);
00901 if ( s->wid->isHidden() ) {
00902 a[i].stretch = 0;
00903 a[i].sizeHint = a[i].minimumSize = 0;
00904 a[i].maximumSize = 0;
00905 } else if ( s->isSplitter ) {
00906 a[i].stretch = 0;
00907 a[i].sizeHint = a[i].minimumSize = a[i].maximumSize = s->sizer;
00908 a[i].empty = FALSE;
00909 } else if ( s->mode == KeepSize ) {
00910 a[i].stretch = 0;
00911 a[i].minimumSize = pick( minSize(s->wid) );
00912 a[i].sizeHint = s->sizer;
00913 a[i].maximumSize = pick( s->wid->maximumSize() );
00914 a[i].empty = FALSE;
00915 } else if ( s->mode == FollowSizeHint ) {
00916 a[i].stretch = 0;
00917 a[i].minimumSize = a[i].sizeHint = pick( s->wid->sizeHint() );
00918 a[i].maximumSize = pick( s->wid->maximumSize() );
00919 a[i].empty = FALSE;
00920 } else {
00921 a[i].stretch = s->sizer;
00922 a[i].maximumSize = pick( s->wid->maximumSize() );
00923 a[i].sizeHint = a[i].minimumSize = pick( minSize(s->wid) );
00924 a[i].empty = FALSE;
00925 }
00926 }
00927
00928 kdganttGeomCalc( a, 0, n, pick( r.topLeft() ), pick( r.size() ), 0 );
00929
00930 for ( i = 0; i< n; i++ ) {
00931 QSplitterLayoutStruct *s = data->list.at(i);
00932 setG( s->wid, a[i].pos, a[i].size );
00933 }
00934
00935 }
00936
00937
00938 void KDGanttMinimizeSplitter::recalc( bool update )
00939 {
00940 int fi = 2*frameWidth();
00941 int maxl = fi;
00942 int minl = fi;
00943 int maxt = QWIDGETSIZE_MAX;
00944 int mint = fi;
00945 int n = data->list.count();
00946 bool first = TRUE;
00947
00948
00949
00950
00951
00952 for ( int i = 0; i< n; i++ ) {
00953 QSplitterLayoutStruct *s = data->list.at(i);
00954 if ( !s->isSplitter ) {
00955 QSplitterLayoutStruct *p = (i > 0) ? data->list.at( i-1 ) : 0;
00956 if ( p && p->isSplitter )
00957 if ( first || s->wid->isHidden() )
00958 p->wid->hide();
00959 else
00960 p->wid->show();
00961 if ( !s->wid->isHidden() )
00962 first = FALSE;
00963 }
00964 }
00965
00966 bool empty=TRUE;
00967 for ( int j = 0; j< n; j++ ) {
00968 QSplitterLayoutStruct *s = data->list.at(j);
00969 if ( !s->wid->isHidden() ) {
00970 empty = FALSE;
00971 if ( s->isSplitter ) {
00972 minl += s->sizer;
00973 maxl += s->sizer;
00974 } else {
00975 QSize minS = minSize(s->wid);
00976 minl += pick( minS );
00977 maxl += pick( s->wid->maximumSize() );
00978 mint = QMAX( mint, trans( minS ));
00979 int tm = trans( s->wid->maximumSize() );
00980 if ( tm > 0 )
00981 maxt = QMIN( maxt, tm );
00982 }
00983 }
00984 }
00985 if ( empty ) {
00986 if ( parentWidget() != 0 && parentWidget()->inherits("KDGanttMinimizeSplitter") ) {
00987
00988 maxl = maxt = 0;
00989 } else {
00990
00991 maxl = QWIDGETSIZE_MAX;
00992 }
00993 } else {
00994 maxl = QMIN( maxl, QWIDGETSIZE_MAX );
00995 }
00996 if ( maxt < mint )
00997 maxt = mint;
00998
00999 if ( orient == Horizontal ) {
01000 setMaximumSize( maxl, maxt );
01001 setMinimumSize( minl, mint );
01002 } else {
01003 setMaximumSize( maxt, maxl );
01004 setMinimumSize( mint, minl );
01005 }
01006 if ( update )
01007 doResize();
01008 }
01009
01016 void KDGanttMinimizeSplitter::setResizeMode( QWidget *w, ResizeMode mode )
01017 {
01018 processChildEvents();
01019 QSplitterLayoutStruct *s = data->list.first();
01020 while ( s ) {
01021 if ( s->wid == w ) {
01022 s->mode = mode;
01023 return;
01024 }
01025 s = data->list.next();
01026 }
01027 s = addWidget( w, TRUE );
01028 s->mode = mode;
01029 }
01030
01031
01038 bool KDGanttMinimizeSplitter::opaqueResize() const
01039 {
01040 return data->opaque;
01041 }
01042
01043
01052 void KDGanttMinimizeSplitter::setOpaqueResize( bool on )
01053 {
01054 data->opaque = on;
01055 }
01056
01057
01062 void KDGanttMinimizeSplitter::moveToFirst( QWidget *w )
01063 {
01064 processChildEvents();
01065 bool found = FALSE;
01066 QSplitterLayoutStruct *s = data->list.first();
01067 while ( s ) {
01068 if ( s->wid == w ) {
01069 found = TRUE;
01070 QSplitterLayoutStruct *p = data->list.prev();
01071 if ( p ) {
01072 data->list.take();
01073 data->list.take();
01074 data->list.insert( 0, p );
01075 data->list.insert( 0, s );
01076 }
01077 break;
01078 }
01079 s = data->list.next();
01080 }
01081 if ( !found )
01082 addWidget( w, TRUE );
01083 recalcId();
01084 }
01085
01086
01091 void KDGanttMinimizeSplitter::moveToLast( QWidget *w )
01092 {
01093 processChildEvents();
01094 bool found = FALSE;
01095 QSplitterLayoutStruct *s = data->list.first();
01096 while ( s ) {
01097 if ( s->wid == w ) {
01098 found = TRUE;
01099 data->list.take();
01100 QSplitterLayoutStruct *p = data->list.current();
01101 if ( p ) {
01102 data->list.take();
01103 data->list.append( p );
01104 }
01105 data->list.append( s );
01106 break;
01107 }
01108 s = data->list.next();
01109 }
01110 if ( !found )
01111 addWidget( w);
01112 recalcId();
01113 }
01114
01115
01116 void KDGanttMinimizeSplitter::recalcId()
01117 {
01118 int n = data->list.count();
01119 for ( int i = 0; i < n; i++ ) {
01120 QSplitterLayoutStruct *s = data->list.at(i);
01121 if ( s->isSplitter )
01122 ((KDGanttSplitterHandle*)s->wid)->setId(i);
01123 }
01124 }
01125
01126
01129 QSize KDGanttMinimizeSplitter::sizeHint() const
01130 {
01131 constPolish();
01132 int l = 0;
01133 int t = 0;
01134 if ( children() ) {
01135 const QObjectList * c = children();
01136 QObjectListIt it( *c );
01137 QObject * o;
01138
01139 while( (o=it.current()) != 0 ) {
01140 ++it;
01141 if ( o->isWidgetType() &&
01142 !((QWidget*)o)->isHidden() ) {
01143 QSize s = ((QWidget*)o)->sizeHint();
01144 if ( s.isValid() ) {
01145 l += pick( s );
01146 t = QMAX( t, trans( s ) );
01147 }
01148 }
01149 }
01150 }
01151 return orientation() == Horizontal ? QSize( l, t ) : QSize( t, l );
01152 }
01153
01154
01159 QSize KDGanttMinimizeSplitter::minimumSizeHint() const
01160 {
01161 constPolish();
01162 int l = 0;
01163 int t = 0;
01164 if ( children() ) {
01165 const QObjectList * c = children();
01166 QObjectListIt it( *c );
01167 QObject * o;
01168
01169 while( (o=it.current()) != 0 ) {
01170 ++it;
01171 if ( o->isWidgetType() &&
01172 !((QWidget*)o)->isHidden() ) {
01173 QSize s = minSizeHint((QWidget*)o);
01174 if ( s.isValid() ) {
01175 l += pick( s );
01176 t = QMAX( t, trans( s ) );
01177 }
01178 }
01179 }
01180 }
01181 return orientation() == Horizontal ? QSize( l, t ) : QSize( t, l );
01182 }
01183
01184
01185
01186
01187
01188
01189 void KDGanttMinimizeSplitter::storeSizes()
01190 {
01191 QSplitterLayoutStruct *s = data->list.first();
01192 while ( s ) {
01193 if ( !s->isSplitter )
01194 s->sizer = pick( s->wid->size() );
01195 s = data->list.next();
01196 }
01197 }
01198
01199
01200 #if 0 // ### remove this code ASAP
01201
01209 void KDGanttMinimizeSplitter::setHidden( QWidget *w, bool hide )
01210 {
01211 if ( w == w1 ) {
01212 w1show = !hide;
01213 } else if ( w == w2 ) {
01214 w2show = !hide;
01215 } else {
01216 #ifdef QT_CHECK_RANGE
01217 qWarning( "KDGanttMinimizeSplitter::setHidden(), unknown widget" );
01218 #endif
01219 return;
01220 }
01221 if ( hide )
01222 w->hide();
01223 else
01224 w->show();
01225 recalc( TRUE );
01226 }
01227
01228
01233 bool KDGanttMinimizeSplitter::isHidden( QWidget *w ) const
01234 {
01235 if ( w == w1 )
01236 return !w1show;
01237 else if ( w == w2 )
01238 return !w2show;
01239 #ifdef QT_CHECK_RANGE
01240 else
01241 qWarning( "KDGanttMinimizeSplitter::isHidden(), unknown widget" );
01242 #endif
01243 return FALSE;
01244 }
01245 #endif
01246
01247
01269 QValueList<int> KDGanttMinimizeSplitter::sizes() const
01270 {
01271 if ( !testWState(WState_Polished) ) {
01272 QWidget* that = (QWidget*) this;
01273 that->polish();
01274 }
01275 QValueList<int> list;
01276 QSplitterLayoutStruct *s = data->list.first();
01277 while ( s ) {
01278 if ( !s->isSplitter )
01279 list.append( s->sizer );
01280 s = data->list.next();
01281 }
01282 return list;
01283 }
01284
01285
01286
01300 void KDGanttMinimizeSplitter::setSizes( QValueList<int> list )
01301 {
01302 processChildEvents();
01303 QValueList<int>::Iterator it = list.begin();
01304 QSplitterLayoutStruct *s = data->list.first();
01305 while ( s && it != list.end() ) {
01306 if ( !s->isSplitter ) {
01307 s->sizer = *it;
01308 ++it;
01309 }
01310 s = data->list.next();
01311 }
01312 doResize();
01313 }
01314
01315
01321 void KDGanttMinimizeSplitter::processChildEvents()
01322 {
01323 QApplication::sendPostedEvents( this, QEvent::ChildInserted );
01324 }
01325
01326
01331 void KDGanttMinimizeSplitter::styleChange( QStyle& old )
01332 {
01333 int sw = style().pixelMetric(QStyle::PM_SplitterWidth, this);
01334 QSplitterLayoutStruct *s = data->list.first();
01335 while ( s ) {
01336 if ( s->isSplitter )
01337 s->sizer = sw;
01338 s = data->list.next();
01339 }
01340 doResize();
01341 QFrame::styleChange( old );
01342 }
01343
01344 #endif
01345
01353 void KDGanttMinimizeSplitter::setMinimizeDirection( Direction direction )
01354 {
01355 _direction = direction;
01356 }
01357
01361 KDGanttMinimizeSplitter::Direction KDGanttMinimizeSplitter::minimizeDirection() const
01362 {
01363 return _direction;
01364 }
01365
01366
01367
01368
01369
01370 static inline int toFixed( int i ) { return i * 256; }
01371 static inline int fRound( int i ) {
01372 return ( i % 256 < 128 ) ? i / 256 : 1 + i / 256;
01373 }
01374 void kdganttGeomCalc( QMemArray<QLayoutStruct> &chain, int start, int count, int pos,
01375 int space, int spacer )
01376 {
01377 typedef int fixed;
01378 int cHint = 0;
01379 int cMin = 0;
01380 int cMax = 0;
01381 int sumStretch = 0;
01382 int spacerCount = 0;
01383
01384 bool wannaGrow = FALSE;
01385
01386
01387 int i;
01388 for ( i = start; i < start + count; i++ ) {
01389 chain[i].done = FALSE;
01390 cHint += chain[i].sizeHint;
01391 cMin += chain[i].minimumSize;
01392 cMax += chain[i].maximumSize;
01393 sumStretch += chain[i].stretch;
01394 if ( !chain[i].empty )
01395 spacerCount++;
01396 wannaGrow = wannaGrow || chain[i].expansive;
01397 }
01398
01399 int extraspace = 0;
01400 if ( spacerCount )
01401 spacerCount--;
01402 if ( space < cMin + spacerCount * spacer ) {
01403
01404 for ( i = start; i < start+count; i++ ) {
01405 chain[i].size = chain[i].minimumSize;
01406 chain[i].done = TRUE;
01407 }
01408 } else if ( space < cHint + spacerCount*spacer ) {
01409
01410
01411
01412 int n = count;
01413 int space_left = space - spacerCount*spacer;
01414 int overdraft = cHint - space_left;
01415
01416 for ( i = start; i < start+count; i++ ) {
01417 if ( !chain[i].done && chain[i].minimumSize >= chain[i].sizeHint) {
01418 chain[i].size = chain[i].sizeHint;
01419 chain[i].done = TRUE;
01420 space_left -= chain[i].sizeHint;
01421
01422 n--;
01423 }
01424 }
01425 bool finished = n == 0;
01426 while ( !finished ) {
01427 finished = TRUE;
01428 fixed fp_over = toFixed( overdraft );
01429 fixed fp_w = 0;
01430
01431 for ( i = start; i < start+count; i++ ) {
01432 if ( chain[i].done )
01433 continue;
01434
01435 fp_w += fp_over / n;
01436
01437
01438 int w = fRound( fp_w );
01439 chain[i].size = chain[i].sizeHint - w;
01440 fp_w -= toFixed( w );
01441 if ( chain[i].size < chain[i].minimumSize ) {
01442 chain[i].done = TRUE;
01443 chain[i].size = chain[i].minimumSize;
01444 finished = FALSE;
01445 overdraft -= chain[i].sizeHint - chain[i].minimumSize;
01446
01447 n--;
01448 break;
01449 }
01450 }
01451 }
01452 } else {
01453 int n = count;
01454 int space_left = space - spacerCount*spacer;
01455
01456 for ( i = start; i < start + count; i++ ) {
01457 if ( !chain[i].done && (chain[i].maximumSize <= chain[i].sizeHint
01458 || wannaGrow && !chain[i].expansive) ) {
01459 chain[i].size = chain[i].sizeHint;
01460 chain[i].done = TRUE;
01461 space_left -= chain[i].sizeHint;
01462 sumStretch -= chain[i].stretch;
01463 n--;
01464 }
01465 }
01466 extraspace = space_left;
01467
01468
01469
01470
01471
01472
01473
01474
01475
01476
01477 int surplus, deficit;
01478 do {
01479 surplus = deficit = 0;
01480 fixed fp_space = toFixed( space_left );
01481 fixed fp_w = 0;
01482 for ( i = start; i < start+count; i++ ) {
01483 if ( chain[i].done )
01484 continue;
01485 extraspace = 0;
01486 if ( sumStretch <= 0 )
01487 fp_w += fp_space / n;
01488 else
01489 fp_w += (fp_space * chain[i].stretch) / sumStretch;
01490 int w = fRound( fp_w );
01491 chain[i].size = w;
01492 fp_w -= toFixed( w );
01493 if ( w < chain[i].sizeHint ) {
01494 deficit += chain[i].sizeHint - w;
01495 } else if ( w > chain[i].maximumSize ) {
01496 surplus += w - chain[i].maximumSize;
01497 }
01498 }
01499 if ( deficit > 0 && surplus <= deficit ) {
01500
01501 for ( i = start; i < start+count; i++ ) {
01502 if ( !chain[i].done &&
01503 chain[i].size < chain[i].sizeHint ) {
01504 chain[i].size = chain[i].sizeHint;
01505 chain[i].done = TRUE;
01506 space_left -= chain[i].sizeHint;
01507 sumStretch -= chain[i].stretch;
01508 n--;
01509 }
01510 }
01511 }
01512 if ( surplus > 0 && surplus >= deficit ) {
01513
01514 for ( i = start; i < start+count; i++ ) {
01515 if ( !chain[i].done &&
01516 chain[i].size > chain[i].maximumSize ) {
01517 chain[i].size = chain[i].maximumSize;
01518 chain[i].done = TRUE;
01519 space_left -= chain[i].maximumSize;
01520 sumStretch -= chain[i].stretch;
01521 n--;
01522 }
01523 }
01524 }
01525 } while ( n > 0 && surplus != deficit );
01526 if ( n == 0 )
01527 extraspace = space_left;
01528 }
01529
01530
01531
01532
01533
01534 int extra = extraspace / ( spacerCount + 2 );
01535 int p = pos + extra;
01536 for ( i = start; i < start+count; i++ ) {
01537 chain[i].pos = p;
01538 p = p + chain[i].size;
01539 if ( !chain[i].empty )
01540 p += spacer+extra;
01541 }
01542 }
01543
01544 #endif
01545