00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "kivio_doc.h"
00020 #include "stencilbardockmanager.h"
00021 #include "stencilbarbutton.h"
00022 #include "kivio_stackbar.h"
00023 #include "kivio_view.h"
00024
00025 #include <qcursor.h>
00026 #include <qvaluelist.h>
00027 #include <qapplication.h>
00028 #include <qwindowdefs.h>
00029 #include <qtimer.h>
00030 #include <qrect.h>
00031 #include <qframe.h>
00032 #include <qpainter.h>
00033
00034 #include <klocale.h>
00035 #include <kdebug.h>
00036
00037 StencilBarDockManager::StencilBarDockManager( KivioView* parent, const char* name )
00038 : QWidget(parent,name)
00039 {
00040 dragButton = 0L;
00041 dragWidget = 0L;
00042 m_pView = parent;
00043 m_destinationBar = 0L;
00044 dragPos = OnDesktop;
00045
00046 m_pBars.setAutoDelete(true);
00047
00048 m_pDoc = m_pView->doc();
00049 connect(m_pDoc, SIGNAL(sig_deleteStencilSet(DragBarButton*, QWidget*, KivioStackBar*)), this,
00050 SLOT(slotDeleteStencilSet(DragBarButton*, QWidget*, KivioStackBar*)));
00051
00052 moveManager = new KoToolDockMoveManager();
00053 connect(moveManager,SIGNAL(positionChanged()),SLOT(slotMoving()));
00054 }
00055
00056 StencilBarDockManager::~StencilBarDockManager()
00057 {
00058 delete moveManager;
00059 }
00060
00061 void StencilBarDockManager::insertStencilSet( QWidget* w, const QString& caption,
00062 BarPos pos, QRect , KivioStackBar* destinationBar )
00063 {
00064 KivioStackBar* bar = 0L;
00065
00066 if(destinationBar) {
00067 bar = destinationBar;
00068 } else {
00069 Qt::Dock position = Qt::DockLeft;
00070
00071 if ( pos == AutoSelect ) {
00072 pos = Left;
00073 }
00074
00075 switch (pos) {
00076 case OnDesktop:
00077 position = Qt::DockTornOff;
00078 break;
00079 case Left:
00080 {
00081 QPtrList<QDockWindow> dockList = m_pView->mainWindow()->dockWindows(Qt::DockLeft);
00082
00083 for(QDockWindow* dock = dockList.first(); dock; dock = dockList.next()) {
00084 if(::qt_cast<KivioStackBar*>(dock) && (static_cast<KivioStackBar*>(dock)->view() == m_pView)) {
00085 bar = static_cast<KivioStackBar*>(dock);
00086 break;
00087 }
00088 }
00089
00090 position = Qt::DockLeft;
00091 break;
00092 }
00093 case Top:
00094 {
00095 QPtrList<QDockWindow> dockList = m_pView->mainWindow()->dockWindows(Qt::DockTop);
00096
00097 for(QDockWindow* dock = dockList.first(); dock; dock = dockList.next()) {
00098 if(::qt_cast<KivioStackBar*>(dock) && (static_cast<KivioStackBar*>(dock)->view() == m_pView)) {
00099 bar = static_cast<KivioStackBar*>(dock);
00100 break;
00101 }
00102 }
00103
00104 position = Qt::DockTop;
00105 break;
00106 }
00107 case Right:
00108 {
00109 QPtrList<QDockWindow> dockList = m_pView->mainWindow()->dockWindows(Qt::DockRight);
00110
00111 for(QDockWindow* dock = dockList.first(); dock; dock = dockList.next()) {
00112 if(::qt_cast<KivioStackBar*>(dock) && (static_cast<KivioStackBar*>(dock)->view() == m_pView)) {
00113 bar = static_cast<KivioStackBar*>(dock);
00114 break;
00115 }
00116 }
00117
00118 position = Qt::DockRight;
00119 break;
00120 }
00121 case Bottom:
00122 {
00123 QPtrList<QDockWindow> dockList = m_pView->mainWindow()->dockWindows(Qt::DockBottom);
00124
00125 for(QDockWindow* dock = dockList.first(); dock; dock = dockList.next()) {
00126 if(::qt_cast<KivioStackBar*>(dock) && (static_cast<KivioStackBar*>(dock)->view() == m_pView)) {
00127 bar = static_cast<KivioStackBar*>(dock);
00128 break;
00129 }
00130 }
00131
00132 position = Qt::DockBottom;
00133 break;
00134 }
00135 case OnTopLevelBar:
00136 position = Qt::DockTornOff;
00137 break;
00138 default:
00139 break;
00140 }
00141
00142 if (!bar) {
00143 bar = new KivioStackBar(m_pView, m_pView->mainWindow());
00144 m_pView->mainWindow()->moveDockWindow(bar, position);
00145 m_pBars.append(bar);
00146 connect(bar,SIGNAL(beginDragPage(DragBarButton*)),SLOT(slotBeginDragPage(DragBarButton*)));
00147 connect(bar,SIGNAL(finishDragPage(DragBarButton*)),SLOT(slotFinishDragPage(DragBarButton*)));
00148 connect(bar,SIGNAL(deleteButton(DragBarButton*,QWidget*,KivioStackBar*)),
00149 m_pDoc, SLOT(slotDeleteStencilSet(DragBarButton*,QWidget*,KivioStackBar*)));
00150 }
00151 }
00152
00153 bar->insertPage(w,caption);
00154 bar->showPage(w);
00155 bar->show();
00156 }
00157
00158 void StencilBarDockManager::slotBeginDragPage( DragBarButton* w )
00159 {
00160 m_destinationBar = 0L;
00161 dragButton = w;
00162 dragWidget = ((KivioStackBar*)sender())->findPage(dragButton);
00163 dragButton->setUpdatesEnabled(false);
00164 dragWidget->setUpdatesEnabled(false);
00165 dragPos = OnDesktop;
00166 moveManager->doMove(dragButton);
00167 }
00168
00169 void StencilBarDockManager::slotFinishDragPage( DragBarButton* )
00170 {
00171 moveManager->stop();
00172 dragButton->setUpdatesEnabled(true);
00173 dragButton->update();
00174
00175 dragWidget->setUpdatesEnabled(true);
00176 dragWidget->update();
00177
00178 QString caption(dragButton->text());
00179 KivioStackBar* bar = (KivioStackBar*)sender();
00180 bar->removePage(dragWidget);
00181
00182 insertStencilSet(dragWidget,caption,dragPos,moveManager->geometry(),m_destinationBar);
00183
00184
00185 if (!bar->visiblePage()) {
00186 int k = m_pBars.findRef(bar);
00187
00188 if ( k!= -1 ) {
00189 m_pBars.remove(k);
00190 m_pBars.insert(k,0L);
00191 }
00192 }
00193
00194 dragButton = 0L;
00195 dragWidget = 0L;
00196 m_destinationBar = 0L;
00197 }
00198
00199
00200 void StencilBarDockManager::slotMoving()
00201 {
00202 m_destinationBar = 0L;
00203 QPoint p = QCursor::pos();
00204 QPoint globalPos;
00205
00206
00207 for ( KivioStackBar* bar = m_pBars.first(); bar; bar = m_pBars.next() ) {
00208 if ( bar->geometry().contains(p) ) {
00209 if(bar->place() == QDockWindow::OutsideDock) {
00210 dragPos = OnTopLevelBar;
00211 globalPos = bar->geometry().topLeft();
00212 } else {
00213 dragPos = AutoSelect;
00214 globalPos = bar->mapToGlobal(bar->geometry().topLeft());
00215 }
00216
00217 m_destinationBar = bar;
00218 moveManager->movePause(true,false);
00219 moveManager->setGeometry(globalPos.x(),
00220 moveManager->y(),
00221 bar->width(),
00222 moveManager->getWidget()->sizeHint().height());
00223 return;
00224 }
00225 }
00226
00227
00228 QRect mr(m_pView->mapToGlobal(QPoint(0,0)),m_pView->size());
00229
00230 if ( mr.contains(p) ) {
00231 QRect r(mr);
00232 r.setWidth(r.width()/4);
00233 if ( r.contains(p) && !m_pBars.at(Left) ) {
00234 moveManager->movePause();
00235 moveManager->setGeometry(r);
00236 dragPos = Left;
00237 return;
00238 }
00239
00240 r.moveBy(r.width()*3,0);
00241
00242 if ( r.contains(p) && !m_pBars.at(Right) ) {
00243 moveManager->movePause();
00244 moveManager->setGeometry(r);
00245 dragPos = Right;
00246 return;
00247 }
00248
00249 QRect t(mr);
00250
00251 t.setHeight(t.height()/4);
00252 if ( t.contains(p) && !m_pBars.at(Top) ) {
00253 moveManager->movePause();
00254 moveManager->setGeometry(t);
00255 dragPos = Top;
00256 return;
00257 }
00258
00259 t.moveBy(0,t.height()*3);
00260
00261 if ( t.contains(p) && !m_pBars.at(Bottom) ) {
00262 moveManager->movePause();
00263 moveManager->setGeometry(t);
00264 dragPos = Bottom;
00265 return;
00266 }
00267 }
00268
00269
00270 moveManager->resize(dragWidget->size());
00271 moveManager->movePause(false,false);
00272 dragPos = OnDesktop;
00273 }
00274
00275 void StencilBarDockManager::slotDeleteStencilSet( DragBarButton* pBtn, QWidget *, KivioStackBar *pBar )
00276 {
00277 pBar->deletePageAndButton(pBtn);
00278
00279
00280 if (!pBar->visiblePage()) {
00281 int k = m_pBars.findRef(pBar);
00282
00283 if ( k!= -1 ) {
00284 m_pBars.remove(k);
00285 pBar = 0;
00286 } else {
00287 delete pBar;
00288 pBar = 0;
00289 }
00290 }
00291 }
00292
00293 void StencilBarDockManager::setAllStackBarsShown(bool shown)
00294 {
00295 for(KivioStackBar* bar = m_pBars.first(); bar; bar = m_pBars.next()) {
00296 if(shown) {
00297 bar->show();
00298 } else {
00299 bar->hide();
00300 }
00301 }
00302 }
00303
00304
00305
00306
00307
00308 KoToolDockMoveManager::KoToolDockMoveManager()
00309 : QObject()
00310 {
00311 #if defined Q_WS_X11 && !defined K_WS_QTONLY
00312 XGCValues gv;
00313 #endif
00314
00315 working=false;
00316 noLast=true;
00317
00318 #if defined Q_WS_X11 && !defined K_WS_QTONLY
00319 scr = qt_xscreen();
00320 root = qt_xrootwin();
00321
00322 gv.function = GXxor;
00323 gv.line_width = 2;
00324 gv.foreground = WhitePixel(qt_xdisplay(), scr)^BlackPixel(qt_xdisplay(), scr);
00325 gv.subwindow_mode = IncludeInferiors;
00326 long mask = GCForeground | GCFunction | GCLineWidth | GCSubwindowMode;
00327 rootgc = XCreateGC(qt_xdisplay(), qt_xrootwin(), mask, &gv);
00328 #endif
00329
00330 timer = new QTimer(this);
00331 }
00332
00333 KoToolDockMoveManager::~KoToolDockMoveManager()
00334 {
00335 stop();
00336 delete timer;
00337 }
00338
00339 void KoToolDockMoveManager::doMove( QWidget* _w )
00340 {
00341 if (working)
00342 return;
00343
00344 working=true;
00345 isDoMove = true;
00346 mirrorX=false;
00347 mirrorY=false;
00348
00349 setWidget(_w);
00350
00351 offX = rx - p.x();
00352 offY = ry - p.y();
00353
00354 orig_x = p.x();
00355 orig_y = p.y();
00356 orig_w = w;
00357 orig_h = h;
00358
00359 QApplication::setOverrideCursor(QCursor(sizeAllCursor));
00360
00361 movePause(false,false);
00362
00363 drawRectangle(xp, yp, w, h);
00364
00365 timer->disconnect();
00366 connect(timer,SIGNAL(timeout()),SLOT(doMoveInternal()));
00367 timer->start(0);
00368 }
00369
00370 void KoToolDockMoveManager::doMoveInternal()
00371 {
00372 if ( !working )
00373 return;
00374
00375 if (!pauseMoveX)
00376 rx = QCursor::pos().x();
00377
00378 if (!pauseMoveY)
00379 ry = QCursor::pos().y();
00380
00381 xp = rx - offX;
00382 yp = ry - offY;
00383
00384 emit positionChanged();
00385
00386 if (check(xp, yp, w, h)) {
00387 paintProcess(false,xp, yp, w, h);
00388
00389 #if defined Q_WS_X11 && !defined K_WS_QTONLY
00390 XFlush(qt_xdisplay());
00391 XSync(qt_xdisplay(),false);
00392 #endif
00393 }
00394 }
00395
00396 void KoToolDockMoveManager::stop()
00397 {
00398 if (!working)
00399 return;
00400
00401 timer->stop();
00402 QApplication::restoreOverrideCursor();
00403
00404 paintProcess();
00405 #if defined Q_WS_X11 && !defined K_WS_QTONLY
00406 XFlush(qt_xdisplay());
00407 #endif
00408
00409 working = false;
00410 }
00411
00412 void KoToolDockMoveManager::setGeometry( const QRect& r )
00413 {
00414 setGeometry(r.x(),r.y(),r.width(),r.height());
00415 }
00416
00417 void KoToolDockMoveManager::setGeometry(int _x, int _y, int _w, int _h)
00418 {
00419 xp=_x;
00420 yp=_y;
00421 w=_w;
00422 h=_h;
00423
00424 check(_x, _y, _w, _h, true);
00425 paintProcess(false,_x, _y, _w, _h);
00426
00427 #if defined Q_WS_X11 && !defined K_WS_QTONLY
00428 XFlush(qt_xdisplay());
00429 XSync(qt_xdisplay(),false);
00430 #endif
00431 }
00432
00433 void KoToolDockMoveManager::drawRectangle( int _x, int _y, int _w, int _h)
00434 {
00435 if (!noLast)
00436 return;
00437
00438 ox = _x;
00439 oy = _y;
00440 ow = _w;
00441 oh = _h;
00442
00443 #if defined Q_WS_X11 && !defined K_WS_QTONLY
00444 XDrawRectangle(qt_xdisplay(), root, rootgc, _x, _y, _w, _h);
00445 #endif
00446 noLast = false;
00447 }
00448
00449 void KoToolDockMoveManager::paintProcess( bool onlyDelete, int _x, int _y, int _w, int _h )
00450 {
00451 if (noLast && onlyDelete)
00452 return;
00453
00454 if ( ox == _x && oy == _y && ow ==_w && oh == _h )
00455 return;
00456
00457 #if defined Q_WS_X11 && !defined K_WS_QTONLY
00458 XDrawRectangle(qt_xdisplay(), root, rootgc, ox, oy, ow, oh);
00459 #endif
00460 noLast = true;
00461
00462 drawRectangle(_x,_y,_w,_h);
00463 }
00464
00465 void KoToolDockMoveManager::movePause( bool horizontal, bool vertical )
00466 {
00467 pauseMoveX = horizontal;
00468 pauseMoveY = vertical;
00469 }
00470
00471 void KoToolDockMoveManager::moveContinue()
00472 {
00473 pauseMoveX = false;
00474 pauseMoveY = false;
00475 }
00476
00477 void KoToolDockMoveManager::doXResize( QWidget* w, bool mirror )
00478 {
00479 if (working)
00480 return;
00481
00482 mirrorX = mirror;
00483 mirrorY = false;
00484
00485 yOnly = false;
00486 xOnly = true;
00487
00488 doResize(w);
00489 }
00490
00491 void KoToolDockMoveManager::doYResize( QWidget* w, bool mirror )
00492 {
00493 if (working)
00494 return;
00495
00496 mirrorX = false;
00497 mirrorY = mirror;
00498
00499 yOnly = true;
00500 xOnly = false;
00501
00502 doResize(w);
00503 }
00504
00505 void KoToolDockMoveManager::doXYResize( QWidget* w, bool _mirrorX, bool _mirrorY )
00506 {
00507 if (working)
00508 return;
00509
00510 mirrorX = _mirrorX;
00511 mirrorY = _mirrorY;
00512
00513 yOnly = false;
00514 xOnly = false;
00515
00516 doResize(w);
00517 }
00518
00519 void KoToolDockMoveManager::doResizeInternal()
00520 {
00521 if (!yOnly)
00522 rx = QCursor::pos().x();
00523
00524 if (!xOnly)
00525 ry = QCursor::pos().y();
00526
00527 int dx = rx - sx;
00528 int dy = ry - sy;
00529
00530 if ( mirrorX ){
00531 w = rr.width() - dx;
00532 xp = rr.x() + dx;
00533 } else {
00534 w = rr.width() + dx;
00535 }
00536
00537 if ( mirrorY ){
00538 h = rr.height() - dy;
00539 yp = rr.y() + dy;
00540 } else {
00541 h = rr.height() + dy;
00542 }
00543
00544 emit sizeChanged();
00545
00546 if (check(xp, yp, w, h)) {
00547 paintProcess(false,xp, yp, w, h);
00548
00549 #if defined Q_WS_X11 && !defined K_WS_QTONLY
00550 XFlush(qt_xdisplay());
00551 XSync(qt_xdisplay(),false);
00552 #endif
00553 }
00554 }
00555
00556 void KoToolDockMoveManager::setWidget( QWidget* _w )
00557 {
00558 widget = _w;
00559 minSize = widget->minimumSize();
00560 maxSize = widget->maximumSize();
00561
00562 rr = QRect(widget->mapToGlobal(QPoint(0,0)),widget->size());
00563 p = rr.topLeft();
00564
00565 xp = rr.x();
00566 yp = rr.y();
00567 w = rr.width();
00568 h = rr.height();
00569
00570 rx = QCursor::pos().x();
00571 ry = QCursor::pos().y();
00572 }
00573
00574 void KoToolDockMoveManager::doResize( QWidget* _w )
00575 {
00576 setWidget(_w);
00577
00578 working=true;
00579 isDoMove = false;
00580
00581 QPoint curPos = QCursor::pos();
00582 sx = curPos.x();
00583 sy = curPos.y();
00584
00585 offX = sx - p.x();
00586 offY = sy - p.y();
00587
00588 drawRectangle(xp, yp, w, h);
00589
00590 timer->disconnect();
00591 connect(timer,SIGNAL(timeout()),SLOT(doResizeInternal()));
00592 timer->start(0);
00593 }
00594
00595 bool KoToolDockMoveManager::check(int& x, int& y, int& w, int& h, bool change)
00596 {
00597
00598 int w1 = QMIN(QMAX(minSize.width(), w), maxSize.width());
00599 int h1 = QMIN(QMAX(minSize.height(), h), maxSize.height());
00600
00601 bool f1 = (w1-w)+(h1-h) == 0;
00602
00603 if (change) {
00604 if (mirrorX)
00605 x += w - w1;
00606 w = w1;
00607 if (mirrorY)
00608 y += h - h1;
00609 h = h1;
00610 }
00611
00612 int x0 = x;
00613 int y0 = y;
00614 int w0 = w;
00615 int h0 = h;
00616
00617 if (isDoMove)
00618 emit fixPosition(x0,y0,w0,h0);
00619 else
00620 emit fixSize(x0,y0,w0,h0);
00621
00622 bool f2 = (x0==x)&&(y0==y)&&(w0==w)&&(h0==h);
00623
00624 if (change) {
00625 x = x0;
00626 y = y0;
00627 w = w0;
00628 h = h0;
00629 }
00630
00631 return f1&&f2;
00632 }
00633
00634 QRect KoToolDockMoveManager::geometry()
00635 {
00636 int x0 = xp;
00637 int y0 = yp;
00638 int w0 = w;
00639 int h0 = h;
00640 check(x0,y0,w0,h0,true);
00641
00642 return QRect(x0,y0,w0,h0);
00643 }
00644
00645 #include "stencilbardockmanager.moc"