kivio

stencilbardockmanager.cpp

00001 /*
00002  * Kivio - Visual Modelling and Flowcharting
00003  * Copyright (C) 2000-2001 theKompany.com & Dave Marotti
00004  *
00005  * This program is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU General Public License
00007  * as published by the Free Software Foundation; either version 2
00008  * of the License, or (at your option) any later version.
00009  *
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program; if not, write to the Free Software
00017  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
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 /*r*/, 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: // hmm this shouldn't happen :)
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   // remove KivioStackBar if no more pages
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   // check existing bars
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   // check "on mainView"
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   // on desktop
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   // remove KivioStackBar if no more pages
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 // KoToolDockMoveManager
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"
KDE Home | KDE Accessibility Home | Description of Access Keys