Qucs-GUI  0.0.19
/home/travis/build/Qucs/qucs/qucs/qucs/mouseactions.cpp
Go to the documentation of this file.
00001 /***************************************************************************
00002                               mouseactions.cpp
00003                              ------------------
00004     begin                : Thu Aug 28 2003
00005     copyright            : (C) 2003 by Michael Margraf
00006     email                : michael.margraf@alumni.tu-berlin.de
00007  ***************************************************************************/
00008 
00009 /* Copyright (C) 2014 Guilherme Brondani Torri <guitorri@gmail.com>        */
00010 
00011 /***************************************************************************
00012  *                                                                         *
00013  *   This program is free software; you can redistribute it and/or modify  *
00014  *   it under the terms of the GNU General Public License as published by  *
00015  *   the Free Software Foundation; either version 2 of the License, or     *
00016  *   (at your option) any later version.                                   *
00017  *                                                                         *
00018  ***************************************************************************/
00019 #include "qucs.h"
00020 #include "main.h"
00021 #include "node.h"
00022 #include "schematic.h"
00023 #include "mouseactions.h"
00024 #include "module.h"
00025 #include "components/component.h"
00026 #include "components/spicedialog.h"
00027 #include "components/spicefile.h"
00028 #include "components/optimizedialog.h"
00029 #include "components/componentdialog.h"
00030 #include "components/vacomponent.h"
00031 #include "diagrams/diagramdialog.h"
00032 #include "diagrams/markerdialog.h"
00033 #include "diagrams/tabdiagram.h"
00034 #include "diagrams/timingdiagram.h"
00035 #include "dialogs/labeldialog.h"
00036 
00037 #include <QTextStream>
00038 #include <Q3PtrList>
00039 #include <QMouseEvent>
00040 #include <QClipboard>
00041 #include <QApplication>
00042 #include <QMessageBox>
00043 #include <QMenu>
00044 #include <QEvent>
00045 #include <QAction>
00046 #include <QLineEdit>
00047 #include <QDebug>
00048 
00049 #include <limits.h>
00050 #include <stdlib.h>
00051 
00052 
00053 #define  DOC_X_POS(x)  (int(float(x)/Doc->Scale) + Doc->ViewX1)
00054 #define  DOC_Y_POS(y)  (int(float(y)/Doc->Scale) + Doc->ViewY1)
00055 #define  DOC_X_FPOS    (float(Event->pos().x())/Doc->Scale + float(Doc->ViewX1))
00056 #define  DOC_Y_FPOS    (float(Event->pos().y())/Doc->Scale + float(Doc->ViewY1))
00057 
00058 #define  SCR_X_POS(x)  int(float(x - Doc->ViewX1) * Doc->Scale)
00059 #define  SCR_Y_POS(y)  int(float(y - Doc->ViewY1) * Doc->Scale)
00060 
00061 QAction *formerAction;   // remember action before drag n'drop etc.
00062 
00063 
00064 MouseActions::MouseActions(QucsApp* App_)
00065 {
00066   App = App_; // pointer to main app
00067   selElem  = 0;  // no component/diagram is selected
00068   isMoveEqual = false;  // mouse cursor move x and y the same way
00069   focusElement = 0; //element being interacted with mouse
00070 
00071   // ...............................................................
00072   // initialize menu appearing by right mouse button click on component
00073   ComponentMenu = new QMenu(QucsMain);
00074   focusMEvent   = new QMouseEvent(QEvent::MouseButtonPress, QPoint(0,0),
00075           Qt::NoButton, Qt::NoButton);
00076 }
00077 
00078 
00079 MouseActions::~MouseActions()
00080 {
00081   delete ComponentMenu;
00082   delete focusMEvent;
00083 }
00084 
00085 // -----------------------------------------------------------
00086 void MouseActions::setPainter(Schematic *Doc)
00087 {
00088   // contents to viewport transformation
00089 
00090   Doc->PostPaintEvent(_Translate,-Doc->contentsX(), -Doc->contentsY());
00091   Doc->PostPaintEvent(_Scale,Doc->Scale, Doc->Scale);
00092   Doc->PostPaintEvent(_Translate,-Doc->ViewX1, -Doc->ViewY1);
00093   Doc->PostPaintEvent(_DotLine);
00094   Doc->PostPaintEvent(_NotRop);
00095 
00096 }
00097 
00098 // -----------------------------------------------------------
00099 bool MouseActions::pasteElements(Schematic *Doc)
00100 {
00101   QClipboard *cb = QApplication::clipboard();   // get system clipboard
00102   QString s = cb->text(QClipboard::Clipboard);
00103   QTextStream stream(&s, QIODevice::ReadOnly);
00104   movingElements.clear();
00105   if(!Doc->paste(&stream, &movingElements)) return false;
00106 
00107   Element *pe;
00108   int xmax, xmin, ymax, ymin;
00109   xmin = ymin = INT_MAX;
00110   xmax = ymax = INT_MIN;
00111   // First, get the max and min coordinates of all selected elements.
00112   for(pe = movingElements.first(); pe != 0; pe = movingElements.next()) {
00113     if(pe->Type == isWire) {
00114       if(pe->x1 < xmin) xmin = pe->x1;
00115       if(pe->x2 > xmax) xmax = pe->x2;
00116       if(pe->y1 < ymin) ymin = pe->y1;
00117       if(pe->y2 > ymax) ymax = pe->y2;
00118     }
00119     else {
00120       if(pe->cx < xmin) xmin = pe->cx;
00121       if(pe->cx > xmax) xmax = pe->cx;
00122       if(pe->cy < ymin) ymin = pe->cy;
00123       if(pe->cy > ymax) ymax = pe->cy;
00124     }
00125   }
00126 
00127   xmin = -((xmax+xmin) >> 1);   // calculate midpoint
00128   ymin = -((ymax+ymin) >> 1);
00129   Doc->setOnGrid(xmin, ymin);
00130 
00131   // moving with mouse cursor in the midpoint
00132   for(pe = movingElements.first(); pe != 0; pe = movingElements.next())
00133     if(pe->Type & isLabel) {
00134       pe->cx += xmin;  pe->x1 += xmin;
00135       pe->cy += ymin;  pe->y1 += ymin;
00136     }
00137     else
00138       pe->setCenter(xmin, ymin, true);
00139 
00140   return true;
00141 }
00142 
00143 // -----------------------------------------------------------
00144 void MouseActions::editLabel(Schematic *Doc, WireLabel *pl)
00145 {
00146   LabelDialog *Dia = new LabelDialog(pl, Doc);
00147   int Result = Dia->exec();
00148   if(Result == 0) return;
00149 
00150   QString Name  = Dia->NodeName->text();
00151   QString Value = Dia->InitValue->text();
00152   delete Dia;
00153 
00154   if(Name.isEmpty() && Value.isEmpty()) { // if nothing entered, delete label
00155     pl->pOwner->Label = 0;   // delete name of wire
00156     delete pl;
00157   }
00158   else {
00159 /*    Name.replace(' ', '_'); // label must not contain spaces
00160     while(Name.at(0) == '_') Name.remove(0,1);  // must not start with '_'
00161     if(Name.isEmpty()) return;
00162     if(Name == pl->Name) return;*/
00163     if(Result == 1) return;  // nothing changed
00164 
00165     int old_x2 = pl->x2;
00166     pl->setName(Name);   // set new name
00167     pl->initValue = Value;
00168     if(pl->cx > (pl->x1+(pl->x2>>1)))
00169       pl->x1 -= pl->x2 - old_x2; // don't change position due to text width
00170   }
00171 
00172   Doc->sizeOfAll(Doc->UsedX1, Doc->UsedY1, Doc->UsedX2, Doc->UsedY2);
00173   Doc->viewport()->update();
00174   drawn = false;
00175   Doc->setChanged(true, true);
00176 }
00177 
00178 // -----------------------------------------------------------
00179 // Reinserts all elements (moved by the user) back into the schematic.
00180 void MouseActions::endElementMoving(Schematic *Doc, Q3PtrList<Element> *movElements)
00181 {
00182   Element *pe;
00183   for(pe = movElements->first(); pe!=0; pe = movElements->next()) {
00184 //    pe->isSelected = false;  // deselect first (maybe afterwards pe == NULL)
00185     switch(pe->Type) { // FIXME: use casts.
00186       case isWire:
00187         if(pe->x1 == pe->x2)
00188           if(pe->y1 == pe->y2) {
00189             // Delete wires with zero length, but preserve label.
00190             if(((Wire*)pe)->Label) {
00191               Doc->insertNodeLabel((WireLabel*)((Wire*)pe)->Label);
00192               ((Wire*)pe)->Label = 0;
00193             }
00194             delete (Wire*)pe;
00195             break;
00196           }
00197 
00198   Doc->insertWire((Wire*)pe);
00199   break;
00200       case isDiagram:
00201   Doc->Diagrams->append((Diagram*)pe);
00202   break;
00203       case isPainting:
00204   Doc->Paintings->append((Painting*)pe);
00205   break;
00206       case isComponent:
00207       case isAnalogComponent:
00208       case isDigitalComponent:
00209   Doc->insertRawComponent((Component*)pe, false);
00210   break;
00211       case isMovingLabel:
00212       case isHMovingLabel:
00213       case isVMovingLabel:
00214   Doc->insertNodeLabel((WireLabel*)pe);
00215   break;
00216       case isMarker:
00217   assert(dynamic_cast<Marker*>(pe));
00218   break;
00219     }
00220   }
00221 
00222   movElements->clear();
00223   if((MAx3 != 0) || (MAy3 != 0))  // moved or put at the same place ?
00224     Doc->setChanged(true, true);
00225 
00226   // enlarge viewarea if components lie outside the view
00227   Doc->sizeOfAll(Doc->UsedX1, Doc->UsedY1, Doc->UsedX2, Doc->UsedY2);
00228   Doc->enlargeView(Doc->UsedX1, Doc->UsedY1, Doc->UsedX2, Doc->UsedY2);
00229   Doc->viewport()->update();
00230   drawn = false;
00231 }
00232 
00233 // -----------------------------------------------------------
00234 // Moves elements in "movElements" by x/y
00235 void MouseActions::moveElements(Q3PtrList<Element> *movElements, int x, int y)
00236 {
00237   Wire *pw;
00238   Element *pe;
00239   for(pe = movElements->first(); pe != 0; pe = movElements->next()) {
00240     if(pe->Type == isWire) {
00241       pw = (Wire*)pe;   // connected wires are not moved completely
00242 
00243       if(((uintptr_t)pw->Port1) > 3) {
00244   pw->x1 += x;  pw->y1 += y;
00245   if(pw->Label) { pw->Label->cx += x;  pw->Label->cy += y; }
00246       }
00247       else {  if((uintptr_t)(pw->Port1) & 1) { pw->x1 += x; }
00248               if((uintptr_t)(pw->Port1) & 2) { pw->y1 += y; } }
00249 
00250       if(((uintptr_t)pw->Port2) > 3) { pw->x2 += x;  pw->y2 += y; }
00251       else {  if((uintptr_t)(pw->Port2) & 1) pw->x2 += x;
00252               if((uintptr_t)(pw->Port2) & 2) pw->y2 += y; }
00253 
00254       if(pw->Label) {      // root of node label must lie on wire
00255         if(pw->Label->cx < pw->x1) pw->Label->cx = pw->x1;
00256         if(pw->Label->cy < pw->y1) pw->Label->cy = pw->y1;
00257         if(pw->Label->cx > pw->x2) pw->Label->cx = pw->x2;
00258         if(pw->Label->cy > pw->y2) pw->Label->cy = pw->y2;
00259       }
00260 
00261     }
00262     else pe->setCenter(x, y, true);
00263   }
00264 }
00265 
00266 
00267 // ***********************************************************************
00268 // **********                                                   **********
00269 // **********       Functions for serving mouse moving          **********
00270 // **********                                                   **********
00271 // ***********************************************************************
00272 void MouseActions::MMoveElement(Schematic *Doc, QMouseEvent *Event)
00273 {
00274   if(selElem == 0) return;
00275 
00276 //  qDebug() << "MMoveElement got selElem";
00277 
00278   int x  = Event->pos().x();
00279   int y  = Event->pos().y();
00280   int fx = DOC_X_POS(x);
00281   int fy = DOC_Y_POS(y);
00282   int gx = fx;
00283   int gy = fy;
00284   Doc->setOnGrid(gx, gy);
00285 
00286 
00287   //QPainter painter(Doc->viewport());
00288   setPainter(Doc);
00289 
00290   if(selElem->Type == isPainting) {
00291     Doc->PostPaintEvent (_NotRop, 0,0,0,0);
00292     x -= Doc->contentsX();
00293     y -= Doc->contentsY();
00294     ((Painting*)selElem)->MouseMoving(Doc, x, y, gx, gy,
00295                                        Doc, x, y, drawn);
00296     drawn = true;
00297     Doc->viewport()->update();
00298     return;
00299   }  // of "if(isPainting)"
00300 
00301 
00302   // ********** it is a component or diagram
00303   if(drawn) selElem->paintScheme(Doc); // erase old scheme
00304   drawn = true;
00305 
00306 //  Component *comp = (Component*)selElem;
00307   //qDebug() << "desc" << comp->Description << "gx" << gx << "gy" << gy;
00308 
00309   selElem->setCenter(gx, gy);
00310   selElem->paintScheme(Doc); // paint scheme at new position
00311   Doc->viewport()->update();
00312 }
00313 
00314 // -----------------------------------------------------------
00320 void MouseActions::MMoveWire2(Schematic *Doc, QMouseEvent *Event)
00321 {
00322   MAx2  = DOC_X_POS(Event->pos().x());
00323   MAy2  = DOC_Y_POS(Event->pos().y());
00324   Doc->setOnGrid(MAx2, MAy2);
00325 
00326   if(MAx1 == 0) {
00327     Doc->PostPaintEvent (_Line, MAx3, MAy3, MAx3, MAy2); // paint
00328     Doc->PostPaintEvent (_Line, MAx3, MAy2, MAx2, MAy2); // paint
00329   }
00330   else {
00331     Doc->PostPaintEvent (_Line, MAx3, MAy3, MAx2, MAy3); // paint
00332     Doc->PostPaintEvent (_Line, MAx2, MAy3, MAx2, MAy2); // paint
00333   }
00334 
00335   QucsMain->MouseDoubleClickAction = &MouseActions::MDoubleClickWire2;
00336   Doc->viewport()->update();
00337 }
00338 
00339 
00345 void MouseActions::MMoveWire1(Schematic *Doc, QMouseEvent *Event)
00346 {
00347   MAx3 = DOC_X_POS(Event->pos().x());
00348   MAy3 = DOC_Y_POS(Event->pos().y());
00349   Doc->setOnGrid(MAx3, MAy3);
00350 
00351   MAx2  = DOC_X_POS(Doc->viewport()->width());
00352   MAy2  = DOC_Y_POS(Doc->viewport()->height());
00353 
00354   Doc->PostPaintEvent (_Line, Doc->ViewX1, MAy3, MAx2, MAy3);
00355   Doc->PostPaintEvent (_Line, MAx3, Doc->ViewY1, MAx3, MAy2);
00356   Doc->viewport()->update();
00357 }
00358 
00359 
00365 void MouseActions::MMoveSelect(Schematic *Doc, QMouseEvent *Event)
00366 {
00367   //qDebug() << "MMoveSelect " << "select area";
00368   MAx2 = DOC_X_POS(Event->pos().x()) - MAx1;
00369   MAy2 = DOC_Y_POS(Event->pos().y()) - MAy1;
00370   if(isMoveEqual) {    // x and y size must be equal ?
00371     if(abs(MAx2) > abs(MAy2)) {
00372       if(MAx2<0) MAx2 = -abs(MAy2); else MAx2 = abs(MAy2);
00373     }
00374     else { if(MAy2<0) MAy2 = -abs(MAx2); else MAy2 = abs(MAx2); }
00375   }
00376 
00377   Doc->PostPaintEvent (_Rect, MAx1, MAy1, MAx2, MAy2);
00378 }
00379 
00380 // -----------------------------------------------------------
00381 void MouseActions::MMoveResizePainting(Schematic *Doc, QMouseEvent *Event)
00382 {
00383   setPainter(Doc);
00384 
00385   MAx1 = DOC_X_POS(Event->pos().x());
00386   MAy1 = DOC_Y_POS(Event->pos().y());
00387   Doc->setOnGrid(MAx1, MAy1);
00388   ((Painting*)focusElement)->MouseResizeMoving(MAx1, MAy1, Doc);
00389 }
00390 
00391 // -----------------------------------------------------------
00392 // Moves components by keeping the mouse button pressed.
00393 void MouseActions::MMoveMoving(Schematic *Doc, QMouseEvent *Event)
00394 {
00395 
00396   setPainter(Doc);
00397 
00398   MAx2 = DOC_X_POS(Event->pos().x());
00399   MAy2 = DOC_Y_POS(Event->pos().y());
00400 
00401   Doc->setOnGrid(MAx2, MAy2);
00402   MAx3 = MAx1 = MAx2 - MAx1;
00403   MAy3 = MAy1 = MAy2 - MAy1;
00404 
00405   movingElements.clear();
00406   Doc->copySelectedElements(&movingElements);
00407   Doc->viewport()->repaint();
00408 
00409   Wire *pw;
00410   // Changes the position of all moving elements by dx/dy
00411   for(Element *pe=movingElements.first(); pe!=0; pe=movingElements.next()) {
00412     if(pe->Type == isWire) {
00413       pw = (Wire*)pe;   // connecting wires are not moved completely
00414 
00415       if(((uintptr_t)pw->Port1) > 3) { pw->x1 += MAx1;  pw->y1 += MAy1; }
00416       else {  if((uintptr_t)(pw->Port1) & 1) { pw->x1 += MAx1; }
00417               if((uintptr_t)(pw->Port1) & 2) { pw->y1 += MAy1; } }
00418 
00419       if(((uintptr_t)pw->Port2) > 3) { pw->x2 += MAx1;  pw->y2 += MAy1; }
00420       else {  if((uintptr_t)(pw->Port2) & 1) pw->x2 += MAx1;
00421               if((uintptr_t)(pw->Port2) & 2) pw->y2 += MAy1; }
00422 
00423       if(pw->Label) {      // root of node label must lie on wire
00424         if(pw->Label->cx < pw->x1) pw->Label->cx = pw->x1;
00425         if(pw->Label->cy < pw->y1) pw->Label->cy = pw->y1;
00426         if(pw->Label->cx > pw->x2) pw->Label->cx = pw->x2;
00427         if(pw->Label->cy > pw->y2) pw->Label->cy = pw->y2;
00428       }
00429 
00430     }
00431     else pe->setCenter(MAx1, MAy1, true);
00432 
00433   pe->paintScheme(Doc);
00434   }
00435 
00436   drawn = true;
00437   MAx1 = MAx2;
00438   MAy1 = MAy2;
00439   QucsMain->MouseMoveAction = &MouseActions::MMoveMoving2;
00440   QucsMain->MouseReleaseAction = &MouseActions::MReleaseMoving;
00441 
00442 }
00443 
00444 // -----------------------------------------------------------
00445 // Moves components by keeping the mouse button pressed.
00446 void MouseActions::MMoveMoving2(Schematic *Doc, QMouseEvent *Event)
00447 {
00448   setPainter(Doc);
00449 
00450   MAx2 = DOC_X_POS(Event->pos().x());
00451   MAy2 = DOC_Y_POS(Event->pos().y());
00452 
00453   Element *pe;
00454   if(drawn) // erase old scheme
00455     for(pe = movingElements.first(); pe != 0; pe = movingElements.next())
00456       pe->paintScheme(Doc);
00457 //      if(pe->Type == isWire)  if(((Wire*)pe)->Label)
00458 //        if(!((Wire*)pe)->Label->isSelected)
00459 //          ((Wire*)pe)->Label->paintScheme(&painter);
00460 
00461   drawn = true;
00462   if((Event->state() & Qt::ControlModifier) == 0)
00463     Doc->setOnGrid(MAx2, MAy2);  // use grid only if CTRL key not pressed
00464   MAx1 = MAx2 - MAx1;
00465   MAy1 = MAy2 - MAy1;
00466   MAx3 += MAx1;  MAy3 += MAy1;   // keep track of the complete movement
00467 
00468   moveElements(&movingElements, MAx1, MAy1);  // moves elements by MAx1/MAy1
00469 
00470   // paint afterwards to avoid conflict between wire and label painting
00471   for(pe = movingElements.first(); pe != 0; pe = movingElements.next())
00472     pe->paintScheme(Doc);
00473 //    if(pe->Type == isWire)  if(((Wire*)pe)->Label)
00474 //      if(!((Wire*)pe)->Label->isSelected)
00475 //        ((Wire*)pe)->Label->paintScheme(&painter);
00476 
00477   MAx1 = MAx2;
00478   MAy1 = MAy2;
00479 }
00480 
00481 
00487 void MouseActions::MMovePaste(Schematic *Doc, QMouseEvent *Event)
00488 {
00489   MAx1 = DOC_X_POS(Event->pos().x());
00490   MAy1 = DOC_Y_POS(Event->pos().y());
00491   moveElements(Doc,MAx1,MAy1);
00492   paintElementsScheme(Doc);
00493 
00494   drawn = true;
00495   QucsMain->MouseMoveAction = &MouseActions::MMoveMoving2;
00496   QucsMain->MouseReleaseAction = &MouseActions::MReleasePaste;
00497 }
00498 
00499 // -----------------------------------------------------------
00500 // Moves scroll bar of diagram (e.g. tabular) according the mouse cursor.
00501 void MouseActions::MMoveScrollBar(Schematic *Doc, QMouseEvent *Event)
00502 {
00503   TabDiagram *d = (TabDiagram*)focusElement;
00504   int x = DOC_X_POS(Event->pos().x());
00505   int y = DOC_Y_POS(Event->pos().y());
00506 
00507   if(d->scrollTo(MAx2, x - MAx1, y - MAy1)) {
00508     Doc->setChanged(true, true, 'm'); // 'm' = only the first time
00509 
00510 // FIXME #warning QPainter p(Doc->viewport());
00511     // FIXME #warning ViewPainter Painter;
00512     // FIXME #warning Painter.init(&p, Doc->Scale, -Doc->ViewX1, -Doc->ViewY1,
00513 // FIXME #warning                  Doc->contentsX(), Doc->contentsY());
00514 // FIXME #warning     Painter.fillRect(d->cx-d->x1, d->cy-d->y2, d->x2+d->x1, d->y2+d->y1,
00515 // FIXME #warning                      QucsSettings.BGColor);
00516 // FIXME #warning     d->paint(&Painter);
00517   }
00518 }
00519 
00520 
00527 void MouseActions::MMoveDelete(Schematic *Doc, QMouseEvent *Event)
00528 {
00529   MAx3  = DOC_X_POS(Event->pos().x());
00530   MAy3  = DOC_Y_POS(Event->pos().y());
00531 
00532   // cannot draw on the viewport, it is displaced by the size of dock and toolbar
00533   Doc->PostPaintEvent (_Line, MAx3-15, MAy3-15, MAx3+15, MAy3+15,0,0,false);
00534   Doc->PostPaintEvent (_Line, MAx3-15, MAy3+15, MAx3+15, MAy3-15,0,0,false);
00535 }
00536 
00537 
00543 void MouseActions::MMoveLabel(Schematic *Doc, QMouseEvent *Event)
00544 {
00545   MAx3  = DOC_X_POS(Event->pos().x());
00546   MAy3  = DOC_Y_POS(Event->pos().y());
00547 
00548   // paint marker
00549   Doc->PostPaintEvent (_Line, MAx3, MAy3, MAx3+10, MAy3-10);
00550   Doc->PostPaintEvent (_Line, MAx3+10, MAy3-10, MAx3+20, MAy3-10);
00551   Doc->PostPaintEvent (_Line, MAx3+10, MAy3-10, MAx3+10, MAy3-17);
00552 
00553   // paint A
00554   Doc->PostPaintEvent (_Line, MAx3+12, MAy3-12, MAx3+15, MAy3-23);
00555   Doc->PostPaintEvent (_Line, MAx3+14, MAy3-17, MAx3+17, MAy3-17);
00556   Doc->PostPaintEvent (_Line, MAx3+19, MAy3-12, MAx3+16, MAy3-23);
00557 }
00558 
00559 
00565 void MouseActions::MMoveMarker(Schematic *Doc, QMouseEvent *Event)
00566 {
00567   MAx3  = DOC_X_POS(Event->pos().x());
00568   MAy3  = DOC_Y_POS(Event->pos().y());
00569 
00570   Doc->PostPaintEvent (_Line, MAx3, MAy3-2, MAx3-8, MAy3-10);
00571   Doc->PostPaintEvent (_Line, MAx3+1, MAy3-3, MAx3+8, MAy3-10);
00572   Doc->PostPaintEvent (_Line, MAx3-7, MAy3-10, MAx3+7, MAy3-10);
00573 }
00574 
00575 
00581 void MouseActions::MMoveMirrorY(Schematic *Doc, QMouseEvent *Event)
00582 {
00583   MAx3  = DOC_X_POS(Event->pos().x());
00584   MAy3  = DOC_Y_POS(Event->pos().y());
00585 
00586   Doc->PostPaintEvent (_Line, MAx3-11, MAy3-4, MAx3-9, MAy3-9);
00587   Doc->PostPaintEvent (_Line, MAx3-11, MAy3-3, MAx3-6, MAy3-3);
00588   Doc->PostPaintEvent (_Line, MAx3+11, MAy3-4, MAx3+9, MAy3-9);
00589   Doc->PostPaintEvent (_Line, MAx3+11, MAy3-3, MAx3+6, MAy3-3);
00590   Doc->PostPaintEvent (_Arc, MAx3-10, MAy3-8, 21, 10, 16*20, 16*140,false);
00591 }
00592 
00593 
00599 void MouseActions::MMoveMirrorX(Schematic *Doc, QMouseEvent *Event)
00600 {
00601   MAx3  = DOC_X_POS(Event->pos().x());
00602   MAy3  = DOC_Y_POS(Event->pos().y());
00603 
00604   Doc->PostPaintEvent (_Line, MAx3-4, MAy3-11, MAx3-9, MAy3-9);
00605   Doc->PostPaintEvent (_Line, MAx3-3, MAy3-11, MAx3-3, MAy3-6);
00606   Doc->PostPaintEvent (_Line, MAx3-4, MAy3+11, MAx3-9, MAy3+9);
00607   Doc->PostPaintEvent (_Line, MAx3-3, MAy3+11, MAx3-3, MAy3+6);
00608   Doc->PostPaintEvent (_Arc, MAx3-8, MAy3-10, 10, 21, 16*110, 16*140,false);
00609 }
00610 
00616 void MouseActions::MMoveRotate(Schematic *Doc, QMouseEvent *Event)
00617 {
00618   MAx3  = DOC_X_POS(Event->pos().x());
00619   MAy3  = DOC_Y_POS(Event->pos().y());
00620 
00621   Doc->PostPaintEvent (_Line, MAx3-6, MAy3+8, MAx3-6, MAy3+1);
00622   Doc->PostPaintEvent (_Line, MAx3-7, MAy3+8, MAx3-12, MAy3+8);
00623   Doc->PostPaintEvent (_Arc, MAx3-10, MAy3-10, 21, 21, -16*20, 16*240,false);
00624 }
00625 
00626 
00632 void MouseActions::MMoveActivate(Schematic *Doc, QMouseEvent *Event)
00633 {
00634   MAx3  = DOC_X_POS(Event->pos().x());
00635   MAy3  = DOC_Y_POS(Event->pos().y());
00636 
00637   Doc->PostPaintEvent (_Rect, MAx3, MAy3-9, 14, 10);
00638   Doc->PostPaintEvent (_Line, MAx3, MAy3-9, MAx3+13, MAy3);
00639   Doc->PostPaintEvent (_Line, MAx3, MAy3, MAx3+13, MAy3-9);
00640 }
00641 
00642 
00648 void MouseActions::MMoveOnGrid(Schematic *Doc, QMouseEvent *Event)
00649 {
00650   MAx3  = DOC_X_POS(Event->pos().x());
00651   MAy3  = DOC_Y_POS(Event->pos().y());
00652 
00653   Doc->PostPaintEvent (_Line, MAx3+10, MAy3+ 3, MAx3+25, MAy3+3);
00654   Doc->PostPaintEvent (_Line, MAx3+10, MAy3+ 7, MAx3+25, MAy3+7);
00655   Doc->PostPaintEvent (_Line, MAx3+10, MAy3+11, MAx3+25, MAy3+11);
00656   Doc->PostPaintEvent (_Line, MAx3+13, MAy3, MAx3+13, MAy3+15);
00657   Doc->PostPaintEvent (_Line, MAx3+17, MAy3, MAx3+17, MAy3+15);
00658   Doc->PostPaintEvent (_Line, MAx3+21, MAy3, MAx3+21, MAy3+15);
00659 }
00660 
00661 
00667 void MouseActions::MMoveMoveTextB(Schematic *Doc, QMouseEvent *Event)
00668 {
00669   MAx3  = DOC_X_POS(Event->pos().x());
00670   MAy3  = DOC_Y_POS(Event->pos().y());
00671 
00672   Doc->PostPaintEvent (_Line, MAx3+14, MAy3   , MAx3+16, MAy3);
00673   Doc->PostPaintEvent (_Line, MAx3+23, MAy3   , MAx3+25, MAy3);
00674   Doc->PostPaintEvent (_Line, MAx3+13, MAy3   , MAx3+13, MAy3+ 3);
00675   Doc->PostPaintEvent (_Line, MAx3+13, MAy3+ 7, MAx3+13, MAy3+10);
00676   Doc->PostPaintEvent (_Line, MAx3+14, MAy3+10, MAx3+16, MAy3+10);
00677   Doc->PostPaintEvent (_Line, MAx3+23, MAy3+10, MAx3+25, MAy3+10);
00678   Doc->PostPaintEvent (_Line, MAx3+26, MAy3   , MAx3+26, MAy3+ 3);
00679   Doc->PostPaintEvent (_Line, MAx3+26, MAy3+ 7, MAx3+26, MAy3+10);
00680 }
00681 
00682 
00688 void MouseActions::MMoveMoveText(Schematic *Doc, QMouseEvent *Event)
00689 {
00690   int newX = DOC_X_POS(Event->pos().x());
00691   int newY = DOC_Y_POS(Event->pos().y());
00692   MAx1 += newX - MAx3;
00693   MAy1 += newY - MAy3;
00694   MAx3  = newX;
00695   MAy3  = newY;
00696 
00697   Doc->PostPaintEvent (_Rect, MAx1, MAy1, MAx2, MAy2);
00698 }
00699 
00700 
00706 void MouseActions::MMoveZoomIn(Schematic *Doc, QMouseEvent *Event)
00707 {
00708   MAx3  = DOC_X_POS(Event->pos().x());
00709   MAy3  = DOC_Y_POS(Event->pos().y());
00710 
00711   Doc->PostPaintEvent (_Line, MAx3+14, MAy3   , MAx3+22, MAy3);
00712   Doc->PostPaintEvent (_Line, MAx3+18, MAy3-4 , MAx3+18, MAy3+4);
00713   Doc->PostPaintEvent (_Ellipse, MAx3+12, MAy3-6, 13, 13,0,0,false);
00714   Doc->viewport()->update();
00715 }
00716 
00717 
00718 // ************************************************************************
00719 // **********                                                    **********
00720 // **********    Functions for serving mouse button clicking     **********
00721 // **********                                                    **********
00722 // ************************************************************************
00723 
00724 // Is called from several MousePress functions to show right button menu.
00725 void MouseActions::rightPressMenu(Schematic *Doc, QMouseEvent *Event, float fX, float fY)
00726 {
00727   MAx1 = int(fX);
00728   MAy1 = int(fY);
00729   focusElement = Doc->selectElement(fX, fY, false);
00730 
00731   if(focusElement)  // remove special function (4 least significant bits)
00732     focusElement->Type &= isSpecialMask;
00733 
00734 
00735   // define menu
00736   ComponentMenu->clear();
00737   while(true) {
00738     if(focusElement) {
00739       focusElement->isSelected = true;
00740       ComponentMenu->insertItem(
00741          QObject::tr("Edit Properties"), QucsMain, SLOT(slotEditElement()));
00742 
00743       if((focusElement->Type & isComponent) == 0) break;
00744     }
00745     else {
00747       //ComponentMenu->addAction(QucsMain->symEdit);
00748       //to QucsMain->symEdit->addTo(ComponentMenu);
00749       // see http://qt-project.org/doc/qt-4.8/qaction-qt3.html#addTo
00750       QucsMain->symEdit->addTo(ComponentMenu);
00751       QucsMain->fileSettings->addTo(ComponentMenu);
00752     }
00753     if(!QucsMain->moveText->isOn())
00754       QucsMain->moveText->addTo(ComponentMenu);
00755     break;
00756   }
00757   while(true) {
00758     if(focusElement)
00759       if(focusElement->Type == isGraph) break;
00760     if(!QucsMain->onGrid->isOn())
00761       QucsMain->onGrid->addTo(ComponentMenu);
00762     QucsMain->editCopy->addTo(ComponentMenu);
00763     if(!QucsMain->editPaste->isOn())
00764       QucsMain->editPaste->addTo(ComponentMenu);
00765     break;
00766   }
00767 
00768   while (true) {
00769     if (focusElement) {
00770       if (focusElement->Type == isDiagram) {
00771         ComponentMenu->insertItem(QObject::tr("Export as image"), QucsMain,
00772             SLOT(slotSaveDiagramToGraphicsFile()));
00773       }
00774     }
00775     break;
00776   }
00777 
00778   if(!QucsMain->editDelete->isOn())
00779     QucsMain->editDelete->addTo(ComponentMenu);
00780   if(focusElement) if(focusElement->Type == isMarker) {
00781     ComponentMenu->insertSeparator();
00782     QString s = QObject::tr("power matching");
00783     if( ((Marker*)focusElement)->pGraph->Var == "Sopt" )
00784       s = QObject::tr("noise matching");
00785     ComponentMenu->insertItem(s, QucsMain, SLOT(slotPowerMatching()));
00786     if( ((Marker*)focusElement)->pGraph->Var.left(2) == "S[" )
00787       ComponentMenu->insertItem(QObject::tr("2-port matching"), QucsMain,
00788                                 SLOT(slot2PortMatching()));
00789   }
00790   do {
00791     if(focusElement) {
00792       if(focusElement->Type == isDiagram) break;
00793       if(focusElement->Type == isGraph) {
00794         QucsMain->graph2csv->addTo(ComponentMenu);
00795         break;
00796       }
00797     }
00798     ComponentMenu->insertSeparator();
00799     if(focusElement) if(focusElement->Type & isComponent)
00800       if(!QucsMain->editActivate->isOn())
00801         QucsMain->editActivate->addTo(ComponentMenu);
00802     if(!QucsMain->editRotate->isOn())
00803       QucsMain->editRotate->addTo(ComponentMenu);
00804     if(!QucsMain->editMirror->isOn())
00805       QucsMain->editMirror->addTo(ComponentMenu);
00806     if(!QucsMain->editMirrorY->isOn())
00807       QucsMain->editMirrorY->addTo(ComponentMenu);
00808 
00809     // right-click menu to go into hierarchy
00810     if(focusElement) {
00811       if(focusElement->Type & isComponent)
00812   if(((Component*)focusElement)->Model == "Sub")
00813     if(!QucsMain->intoH->isOn())
00814       QucsMain->intoH->addTo(ComponentMenu);
00815     }
00816     // right-click menu to pop out of hierarchy
00817     if(!focusElement)
00818       if(!QucsMain->popH->isOn())
00819   QucsMain->popH->addTo(ComponentMenu);
00820   } while(false);
00821 
00822   *focusMEvent = *Event;  // remember event for "edit component" action
00823   ComponentMenu->popup(Event->globalPos());
00824   Doc->viewport()->update();
00825   drawn = false;
00826 }
00827 
00828 // -----------------------------------------------------------
00829 void MouseActions::MPressLabel(Schematic *Doc, QMouseEvent*, float fX, float fY)
00830 {
00831   int x = int(fX), y = int(fY);
00832   Wire *pw = 0;
00833   WireLabel *pl=0;
00834   Node *pn = Doc->selectedNode(x, y);
00835   if(!pn) {
00836     pw = Doc->selectedWire(x, y);
00837     if(!pw) return;
00838   }
00839 
00840   QString Name, Value;
00841   Element *pe=0;
00842   // is wire line already labeled ?
00843   if(pw) pe = Doc->getWireLabel(pw->Port1);
00844   else pe = Doc->getWireLabel(pn);
00845   if(pe) {
00846     if(pe->Type & isComponent) {
00847       QMessageBox::information(0, QObject::tr("Info"),
00848                  QObject::tr("The ground potential cannot be labeled!"));
00849       return;
00850     }
00851     pl = ((Conductor*)pe)->Label;
00852   }
00853 
00854   LabelDialog *Dia = new LabelDialog(pl, Doc);
00855   if(Dia->exec() == 0) return;
00856 
00857   Name  = Dia->NodeName->text();
00858   Value = Dia->InitValue->text();
00859   delete Dia;
00860 
00861   if(Name.isEmpty() && Value.isEmpty() ) { // if nothing entered, delete name
00862     if(pe) {
00863       if(((Conductor*)pe)->Label)
00864         delete ((Conductor*)pe)->Label; // delete old name
00865       ((Conductor*)pe)->Label = 0;
00866     }
00867     else {
00868       if(pw) pw->setName("", "");   // delete name of wire
00869       else pn->setName("", "");
00870     }
00871   }
00872   else {
00873 /*    Name.replace(' ', '_'); // label must not contain spaces
00874     while(Name.at(0) == '_') Name.remove(0,1);  // must not start with '_'
00875     if(Name.isEmpty()) return;
00876 */
00877     if(pe) {
00878       if(((Conductor*)pe)->Label)
00879         delete ((Conductor*)pe)->Label; // delete old name
00880       ((Conductor*)pe)->Label = 0;
00881     }
00882 
00883     int xl = x+30;
00884     int yl = y-30;
00885     Doc->setOnGrid(xl, yl);
00886     // set new name
00887     if(pw) pw->setName(Name, Value, x-pw->x1 + y-pw->y1, xl, yl);
00888     else pn->setName(Name, Value, xl, yl);
00889   }
00890 
00891   Doc->sizeOfAll(Doc->UsedX1, Doc->UsedY1, Doc->UsedX2, Doc->UsedY2);
00892   Doc->viewport()->update();
00893   drawn = false;
00894   Doc->setChanged(true, true);
00895 }
00896 
00897 // -----------------------------------------------------------
00898 void MouseActions::MPressSelect(Schematic *Doc, QMouseEvent *Event, float fX, float fY)
00899 {
00900   bool Ctrl;
00901   if(Event->state() & Qt::ControlModifier) Ctrl = true;
00902   else Ctrl = false;
00903 
00904   int No=0;
00905   MAx1 = int(fX);
00906   MAy1 = int(fY);
00907   focusElement = Doc->selectElement(fX, fY, Ctrl, &No);
00908   isMoveEqual = false;   // moving not neccessarily square
00909 
00910   if(focusElement)
00911     // print define value in hex, see element.h
00912     qDebug() << "MPressSelect: focusElement->Type" <<  QString("0x%1").arg(focusElement->Type, 0, 16);
00913   else
00914     qDebug() << "MPressSelect";
00915 
00916   if(focusElement)
00917   switch(focusElement->Type)
00918   {
00919     case isPaintingResize:  // resize painting ?
00920       focusElement->Type = isPainting;
00921       QucsMain->MouseReleaseAction = &MouseActions::MReleaseResizePainting;
00922       QucsMain->MouseMoveAction = &MouseActions::MMoveResizePainting;
00923       QucsMain->MousePressAction = 0;
00924       QucsMain->MouseDoubleClickAction = 0;
00925       Doc->grabKeyboard();  // no keyboard inputs during move actions
00926       // Update matching wire label highlighting
00927       Doc->highlightWireLabels ();
00928       return;
00929 
00930     case isDiagramResize:  // resize diagram ?
00931       if(((Diagram*)focusElement)->Name.left(4) != "Rect")
00932         if(((Diagram*)focusElement)->Name.at(0) != 'T')
00933           if(((Diagram*)focusElement)->Name != "Curve")
00934             isMoveEqual = true;  // diagram must be square
00935 
00936       focusElement->Type = isDiagram;
00937       MAx1 = focusElement->cx;
00938       MAx2 = focusElement->x2;
00939       if(((Diagram*)focusElement)->State & 1) {
00940         MAx1 += MAx2;
00941         MAx2 *= -1;
00942       }
00943       MAy1 =  focusElement->cy;
00944       MAy2 = -focusElement->y2;
00945       if(((Diagram*)focusElement)->State & 2) {
00946         MAy1 += MAy2;
00947         MAy2 *= -1;
00948       }
00949 
00950       QucsMain->MouseReleaseAction = &MouseActions::MReleaseResizeDiagram;
00951       QucsMain->MouseMoveAction = &MouseActions::MMoveSelect;
00952       QucsMain->MousePressAction = 0;
00953       QucsMain->MouseDoubleClickAction = 0;
00954       Doc->grabKeyboard(); // no keyboard inputs during move actions
00955       // Update matching wire label highlighting
00956       Doc->highlightWireLabels ();
00957       return;
00958 
00959     case isDiagramHScroll:  // scroll in tabular ?
00960       MAy1 = MAx1;
00961 
00962     case isDiagramVScroll:
00963       focusElement->Type = isDiagram;
00964 
00965       No = ((TabDiagram*)focusElement)->scroll(MAy1);
00966 
00967       switch(No)
00968       {
00969         case 1:
00970           Doc->setChanged(true, true, 'm'); // 'm' = only the first time
00971           break;
00972         case 2:  // move scroll bar with mouse cursor
00973           QucsMain->MouseMoveAction = &MouseActions::MMoveScrollBar;
00974           QucsMain->MousePressAction = 0;
00975           QucsMain->MouseDoubleClickAction = 0;
00976           Doc->grabKeyboard();  // no keyboard inputs during move actions
00977 
00978           // Remember inital scroll bar position.
00979           MAx2 = int(((TabDiagram*)focusElement)->xAxis.limit_min);
00980           // Update matching wire label highlighting
00981           Doc->highlightWireLabels ();
00982           return;
00983       }
00984       // Update matching wire label highlighting
00985       Doc->highlightWireLabels ();
00986       Doc->viewport()->update();
00987       drawn = false;
00988       return;
00989 
00990     case isComponentText:  // property text of component ?
00991       focusElement->Type &= (~isComponentText) | isComponent;
00992 
00993       MAx3 = No;
00994       QucsMain->slotApplyCompText();
00995       // Update matching wire label highlighting
00996       Doc->highlightWireLabels ();
00997       return;
00998 
00999     case isNode:
01000       if (QucsSettings.NodeWiring)
01001       {
01002         MAx1 = 0;   // paint wire corner first up, then left/right
01003         MAx3 = focusElement->cx;  // works even if node is not on grid
01004         MAy3 = focusElement->cy;
01005         QucsMain->MouseMoveAction = &MouseActions::MMoveWire2;
01006         QucsMain->MousePressAction = &MouseActions::MPressWire2;
01007         QucsMain->MouseReleaseAction = 0; // if function is called from elsewhere
01008         QucsMain->MouseDoubleClickAction = 0;
01009 
01010         formerAction = QucsMain->select; // to restore action afterwards
01011         QucsMain->activeAction = QucsMain->insWire;
01012 
01013         QucsMain->select->blockSignals(true);
01014         QucsMain->select->setChecked(false);
01015         QucsMain->select->blockSignals(false);
01016 
01017         QucsMain->insWire->blockSignals(true);
01018         QucsMain->insWire->setChecked(true);
01019         QucsMain->insWire->blockSignals(false);
01020         // Update matching wire label highlighting
01021         Doc->highlightWireLabels ();
01022         return;
01023       }
01024   }
01025 
01026   QucsMain->MousePressAction = 0;
01027   QucsMain->MouseDoubleClickAction = 0;
01028   Doc->grabKeyboard();  // no keyboard inputs during move actions
01029   Doc->viewport()->update();
01030   drawn = false;
01031 
01032   if(focusElement == 0) {
01033     MAx2 = 0;  // if not clicking on an element => open a rectangle
01034     MAy2 = 0;
01035     QucsMain->MouseReleaseAction = &MouseActions::MReleaseSelect2;
01036     QucsMain->MouseMoveAction = &MouseActions::MMoveSelect;
01037   }
01038   else
01039   {
01040     // element could be moved
01041     if(!Ctrl)
01042     {
01043       if(!focusElement->isSelected)// Don't move selected elements if clicked
01044         Doc->deselectElements(focusElement); // element was not selected.
01045       focusElement->isSelected = true;
01046     }
01047     Doc->setOnGrid(MAx1, MAy1);
01048     QucsMain->MouseMoveAction = &MouseActions::MMoveMoving;
01049   }
01050   // Update matching wire label highlighting
01051   Doc->highlightWireLabels ();
01052 }
01053 
01054 // -----------------------------------------------------------
01055 void MouseActions::MPressDelete(Schematic *Doc, QMouseEvent*, float fX, float fY)
01056 {
01057   Element *pe = Doc->selectElement(fX, fY, false);
01058   if(pe)
01059   {
01060     pe->isSelected = true;
01061     Doc->deleteElements();
01062 
01063     Doc->sizeOfAll(Doc->UsedX1, Doc->UsedY1, Doc->UsedX2, Doc->UsedY2);
01064     Doc->viewport()->update();
01065     drawn = false;
01066   }
01067 }
01068 
01069 // -----------------------------------------------------------
01070 void MouseActions::MPressActivate(Schematic *Doc, QMouseEvent*, float fX, float fY)
01071 {
01072   MAx1 = int(fX);
01073   MAy1 = int(fY);
01074   if(!Doc->activateSpecifiedComponent(MAx1, MAy1)) {
01075 //    if(Event->button() != Qt::LeftButton) return;
01076     MAx2 = 0;  // if not clicking on a component => open a rectangle
01077     MAy2 = 0;
01078     QucsMain->MousePressAction = 0;
01079     QucsMain->MouseReleaseAction = &MouseActions::MReleaseActivate;
01080     QucsMain->MouseMoveAction = &MouseActions::MMoveSelect;
01081   }
01082   Doc->viewport()->update();
01083   drawn = false;
01084 }
01085 
01086 // -----------------------------------------------------------
01087 void MouseActions::MPressMirrorX(Schematic *Doc, QMouseEvent*, float fX, float fY)
01088 {
01089   // no use in mirroring wires or diagrams
01090   Component *c = Doc->selectedComponent(int(fX), int(fY));
01091   if(c) {
01092     if(c->Ports.count() < 1) return;  // only mirror components with ports
01093     c->mirrorX();
01094     Doc->setCompPorts(c);
01095   }
01096   else {
01097     Painting *p = Doc->selectedPainting(fX, fY);
01098     if(p == 0) return;
01099     p->mirrorX();
01100   }
01101 
01102   Doc->viewport()->update();
01103   drawn = false;
01104   Doc->setChanged(true, true);
01105 }
01106 
01107 // -----------------------------------------------------------
01108 void MouseActions::MPressMirrorY(Schematic *Doc, QMouseEvent*, float fX, float fY)
01109 {
01110   // no use in mirroring wires or diagrams
01111   Component *c = Doc->selectedComponent(int(fX), int(fY));
01112   if(c) {
01113     if(c->Ports.count() < 1) return;  // only mirror components with ports
01114     c->mirrorY();
01115     Doc->setCompPorts(c);
01116   }
01117   else {
01118     Painting *p = Doc->selectedPainting(fX, fY);
01119     if(p == 0) return;
01120     p->mirrorY();
01121   }
01122 
01123   Doc->viewport()->update();
01124   drawn = false;
01125   Doc->setChanged(true, true);
01126 }
01127 
01128 // -----------------------------------------------------------
01129 void MouseActions::MPressRotate(Schematic *Doc, QMouseEvent*, float fX, float fY)
01130 {
01131   Element *e = Doc->selectElement(int(fX), int(fY), false);
01132   if(e == 0) return;
01133   e->Type &= isSpecialMask;  // remove special functions
01134 
01135 
01136   WireLabel *pl;
01137   int x1, y1, x2, y2;
01138 //  e->isSelected = false;
01139   switch(e->Type) {
01140     case isComponent:
01141     case isAnalogComponent:
01142     case isDigitalComponent:
01143       if(((Component*)e)->Ports.count() < 1)
01144         break;  // do not rotate components without ports
01145       ((Component*)e)->rotate();
01146       Doc->setCompPorts((Component*)e);
01147       // enlarge viewarea if component lies outside the view
01148       ((Component*)e)->entireBounds(x1,y1,x2,y2, Doc->textCorr());
01149       Doc->enlargeView(x1, y1, x2, y2);
01150       break;
01151 
01152     case isWire:
01153       pl = ((Wire*)e)->Label;
01154       ((Wire*)e)->Label = 0;    // prevent label to be deleted
01155       Doc->Wires->setAutoDelete(false);
01156       Doc->deleteWire((Wire*)e);
01157       ((Wire*)e)->Label = pl;
01158       ((Wire*)e)->rotate();
01159       Doc->setOnGrid(e->x1, e->y1);
01160       Doc->setOnGrid(e->x2, e->y2);
01161       if(pl)  Doc->setOnGrid(pl->cx, pl->cy);
01162       Doc->insertWire((Wire*)e);
01163       Doc->Wires->setAutoDelete(true);
01164       if (Doc->Wires->containsRef ((Wire*)e))
01165         Doc->enlargeView(e->x1, e->y1, e->x2, e->y2);
01166       break;
01167 
01168     case isPainting:
01169       ((Painting*)e)->rotate();
01170       // enlarge viewarea if component lies outside the view
01171       ((Painting*)e)->Bounding(x1,y1,x2,y2);
01172       Doc->enlargeView(x1, y1, x2, y2);
01173       break;
01174 
01175     default:
01176       return;
01177   }
01178   Doc->viewport()->update();
01179   drawn = false;
01180   Doc->setChanged(true, true);
01181 }
01182 
01183 // -----------------------------------------------------------
01184 // insert component, diagram, painting into schematic ?!
01185 void MouseActions::MPressElement(Schematic *Doc, QMouseEvent *Event, float, float)
01186 {
01187   if(selElem == 0) return;
01188   //QPainter painter(Doc->viewport());
01189   //setPainter(Doc, &painter);
01190 
01191 
01192   int x1, y1, x2, y2, rot;
01193   if(selElem->Type & isComponent) {
01194     Component *Comp = (Component*)selElem;
01195 //    qDebug() << "+-+ got to switch:" << Comp->Name;
01196     QString entryName = Comp->Name;
01197 
01198     switch(Event->button()) {
01199       case Qt::LeftButton :
01200   // left mouse button inserts component into the schematic
01201   // give the component a pointer to the schematic it's a
01202   // part of
01203   Comp->setSchematic (Doc);
01204   Comp->textSize(x1, y1);
01205   Doc->insertComponent(Comp);
01206   Comp->textSize(x2, y2);
01207   if(Comp->tx < Comp->x1) Comp->tx -= x2 - x1;
01208 
01209     // Note: insertCopmponents does increment  name1 -> name2
01210 //    qDebug() << "  +-+ got to insert:" << Comp->Name;
01211 
01212   // enlarge viewarea if component lies outside the view
01213   Comp->entireBounds(x1,y1,x2,y2, Doc->textCorr());
01214   Doc->enlargeView(x1, y1, x2, y2);
01215 
01216   drawn = false;
01217   Doc->viewport()->update();
01218   Doc->setChanged(true, true);
01219   rot = Comp->rotated;
01220 
01221     // handle static and dynamic components
01222 //    QucsApp::CompChoose;
01223     if (Module::vaComponents.contains(entryName)){
01224       QString filename = Module::vaComponents[entryName];
01225 //      qDebug() << "   ===+ recast";
01226       Comp = dynamic_cast<vacomponent*>(Comp)->newOne(filename); //va component
01227       qDebug() << "   => recast = Comp;" << Comp->Name << "filename: " << filename;
01228     }
01229     else {
01230     Comp = Comp->newOne(); // static component is used, so create a new one
01231     }
01232   rot -= Comp->rotated;
01233   rot &= 3;
01234   while(rot--) Comp->rotate(); // keep last rotation for single component
01235   break;
01236 
01237       case Qt::RightButton :  // right mouse button rotates the component
01238   if(Comp->Ports.count() == 0)
01239     break;  // do not rotate components without ports
01240   Comp->paintScheme(Doc); // erase old component scheme
01241   Comp->rotate();
01242   Comp->paintScheme(Doc); // paint new component scheme
01243   break;
01244 
01245       default: ;   // avoids compiler warnings
01246     }
01247 //    qDebug() << "   => selElem = Comp;" << Comp->Name;
01248     // comp it geting empty
01249     selElem = Comp;
01250     return;
01251 
01252   }  // of "if(isComponent)"
01253   else if(selElem->Type == isDiagram) {
01254     if(Event->button() != Qt::LeftButton) return;
01255 
01256     Diagram *Diag = (Diagram*)selElem;
01257     QFileInfo Info(Doc->DocName);
01258     // dialog is Qt::WDestructiveClose !!!
01259     DiagramDialog *dia =
01260        new DiagramDialog(Diag, Doc);
01261     if(dia->exec() == QDialog::Rejected) {  // don't insert if dialog canceled
01262       Doc->viewport()->update();
01263       drawn = false;
01264       return;
01265     }
01266 
01267     Doc->Diagrams->append(Diag);
01268     Doc->enlargeView(Diag->cx, Diag->cy-Diag->y2, Diag->cx+Diag->x2, Diag->cy);
01269     Doc->setChanged(true, true);   // document has been changed
01270 
01271     Doc->viewport()->repaint();
01272     Diag = Diag->newOne(); // the component is used, so create a new one
01273     Diag->paintScheme(Doc);
01274     selElem = Diag;
01275     return;
01276   }  // of "if(isDiagram)"
01277 
01278 
01279   // ***********  it is a painting !!!
01280   if(((Painting*)selElem)->MousePressing()) {
01281     Doc->Paintings->append((Painting*)selElem);
01282     ((Painting*)selElem)->Bounding(x1,y1,x2,y2);
01283     //Doc->enlargeView(x1, y1, x2, y2);
01284     selElem = ((Painting*)selElem)->newOne();
01285 
01286     Doc->viewport()->update();
01287     Doc->setChanged(true, true);
01288 
01289     MMoveElement(Doc, Event);  // needed before next mouse pressing
01290     drawn = false;
01291   }
01292 }
01293 
01294 
01301 void MouseActions::MPressWire1(Schematic *Doc, QMouseEvent*, float fX, float fY)
01302 {
01303   //Doc->PostPaintEvent (_DotLine);
01304   //Doc->PostPaintEvent (_NotRop);
01305   //if(drawn) {
01306     Doc->PostPaintEvent (_Line, 0, MAy3, MAx2, MAy3); // erase old mouse cross
01307     Doc->PostPaintEvent (_Line, MAx3, 0, MAx3, MAy2);
01308   //}
01309   //drawn = false;
01310 
01311   MAx1 = 0;   // paint wire corner first up, then left/right
01312   MAx3 = int(fX);
01313   MAy3 = int(fY);
01314   Doc->setOnGrid(MAx3, MAy3);
01315 
01316   formerAction = 0; // keep wire action active after first wire finished
01317   QucsMain->MouseMoveAction = &MouseActions::MMoveWire2;
01318   QucsMain->MousePressAction = &MouseActions::MPressWire2;
01319   // Double-click action is set in "MMoveWire2" to not initiate it
01320   // during "Wire1" actions.
01321   Doc->viewport()->update();
01322 }
01323 
01324 
01332 void MouseActions::MPressWire2(Schematic *Doc, QMouseEvent *Event, float fX, float fY)
01333 {
01334 
01335   int set1 = 0, set2 = 0;
01336   switch(Event->button()) {
01337   case Qt::LeftButton :
01338     if(MAx1 == 0) { // which wire direction first ?
01339       if(MAy2 != MAy3)
01340         set1 = Doc->insertWire(new Wire(MAx3, MAy3, MAx3, MAy2));
01341       if(MAx2 != MAx3) {
01342         set2 = set1;
01343         set1 = Doc->insertWire(new Wire(MAx3, MAy2, MAx2, MAy2));
01344       }
01345     }
01346     else {
01347       if(MAx2 != MAx3)
01348         set1 = Doc->insertWire(new Wire(MAx3, MAy3, MAx2, MAy3));
01349       if(MAy2 != MAy3) {
01350         set2 = set1;
01351         set1 = Doc->insertWire(new Wire(MAx2, MAy3, MAx2, MAy2));
01352       }
01353     }
01354 
01355     if(set1 & 2) {
01356       // if last port is connected, then...
01357       if(formerAction) {
01358         // ...restore old action
01359         QucsMain->select->setChecked(true);
01360       }
01361       else {
01362         // ...start a new wire
01363         QucsMain->MouseMoveAction = &MouseActions::MMoveWire1;
01364         QucsMain->MousePressAction = &MouseActions::MPressWire1;
01365         QucsMain->MouseDoubleClickAction = 0;
01366       }
01367     }
01368 
01369     Doc->viewport()->update();
01370     drawn = false;
01371     if(set1 | set2) Doc->setChanged(true, true);
01372     MAx3 = MAx2;
01373     MAy3 = MAy2;
01374     break;
01375 
01377   case Qt::RightButton :
01378     if(MAx1 == 0) {
01379       Doc->PostPaintEvent (_Line, MAx3, MAy3, MAx3, MAy2); // erase old
01380       Doc->PostPaintEvent (_Line, MAx3, MAy2, MAx2, MAy2); // erase old
01381     }
01382     else {
01383       Doc->PostPaintEvent (_Line, MAx3, MAy3, MAx2, MAy3); // erase old
01384       Doc->PostPaintEvent (_Line, MAx2, MAy3, MAx2, MAy2); // erase old
01385     }
01386 
01387     MAx2  = int(fX);
01388     MAy2  = int(fY);
01389     Doc->setOnGrid(MAx2, MAy2);
01390 
01391     MAx1 ^= 1;    // change the painting direction of wire corner
01392     if(MAx1 == 0) {
01393       Doc->PostPaintEvent (_Line, MAx3, MAy3, MAx3, MAy2); // paint
01394       Doc->PostPaintEvent (_Line, MAx3, MAy2, MAx2, MAy2); // paint
01395     }
01396     else {
01397       Doc->PostPaintEvent (_Line, MAx3, MAy3, MAx2, MAy3); // paint
01398       Doc->PostPaintEvent (_Line, MAx2, MAy3, MAx2, MAy2); // paint
01399     }
01400     break;
01401 
01402   default: ;    // avoids compiler warnings
01403   }
01404   Doc->viewport()->update();
01405 }
01406 
01407 // -----------------------------------------------------------
01408 // Is called for setting a marker on a diagram's graph
01409 void MouseActions::MPressMarker(Schematic *Doc, QMouseEvent*, float fX, float fY)
01410 {
01411   MAx1 = int(fX);
01412   MAy1 = int(fY);
01413   Marker *pm = Doc->setMarker(MAx1, MAy1);
01414 
01415   if(pm) {
01416     assert(pm->diag());
01417     int x0 = pm->diag()->cx;
01418     int y0 = pm->diag()->cy;
01419     Doc->enlargeView(x0+pm->x1, y0-pm->y1-pm->y2, x0+pm->x1+pm->x2, y0-pm->y1);
01420   }
01421   Doc->viewport()->update();
01422   drawn = false;
01423 }
01424 
01425 // -----------------------------------------------------------
01426 void MouseActions::MPressOnGrid(Schematic *Doc, QMouseEvent*, float fX, float fY)
01427 {
01428   Element *pe = Doc->selectElement(fX, fY, false);
01429   if(pe)
01430   {
01431     pe->Type &= isSpecialMask;  // remove special functions (4 lowest bits)
01432 
01433     // onGrid is toggle action -> no other element can be selected
01434     pe->isSelected = true;
01435     Doc->elementsOnGrid();
01436 
01437     Doc->sizeOfAll(Doc->UsedX1, Doc->UsedY1, Doc->UsedX2, Doc->UsedY2);
01438     // Update matching wire label highlighting
01439     Doc->highlightWireLabels ();
01440     Doc->viewport()->update();
01441     drawn = false;
01442   }
01443 
01444 }
01445 
01446 // -----------------------------------------------------------
01447 void MouseActions::MPressMoveText(Schematic *Doc, QMouseEvent*, float fX, float fY)
01448 {
01449   MAx1 = int(fX);
01450   MAy1 = int(fY);
01451   focusElement = Doc->selectCompText(MAx1, MAy1, MAx2, MAy2);
01452 
01453   if(focusElement) {
01454     MAx3 = MAx1;
01455     MAy3 = MAy1;
01456     MAx1 = ((Component*)focusElement)->cx + ((Component*)focusElement)->tx;
01457     MAy1 = ((Component*)focusElement)->cy + ((Component*)focusElement)->ty;
01458     Doc->viewport()->update();
01459     drawn = false;
01460     QucsMain->MouseMoveAction = &MouseActions::MMoveMoveText;
01461     QucsMain->MouseReleaseAction = &MouseActions::MReleaseMoveText;
01462     Doc->grabKeyboard();  // no keyboard inputs during move actions
01463   }
01464 }
01465 
01466 // -----------------------------------------------------------
01467 void MouseActions::MPressZoomIn(Schematic *Doc, QMouseEvent*, float fX, float fY)
01468 {
01469   qDebug() << "zoom into box";
01470   MAx1 = int(fX);
01471   MAy1 = int(fY);
01472   MAx2 = 0;  // rectangle size
01473   MAy2 = 0;
01474 
01475   QucsMain->MouseMoveAction = &MouseActions::MMoveSelect;
01476   QucsMain->MouseReleaseAction = &MouseActions::MReleaseZoomIn;
01477   Doc->grabKeyboard();  // no keyboard inputs during move actions
01478   Doc->viewport()->update();
01479   drawn = false;
01480 }
01481 
01482 
01483 // ***********************************************************************
01484 // **********                                                   **********
01485 // **********    Functions for serving mouse button releasing   **********
01486 // **********                                                   **********
01487 // ***********************************************************************
01488 void MouseActions::MReleaseSelect(Schematic *Doc, QMouseEvent *Event)
01489 {
01490   bool ctrl;
01491   if(Event->state() & Qt::ControlModifier) ctrl = true;
01492   else ctrl = false;
01493 
01494   if(!ctrl) Doc->deselectElements(focusElement);
01495 
01496   if(focusElement)  if(Event->button() == Qt::LeftButton)
01497     if(focusElement->Type == isWire) {
01498       Doc->selectWireLine(focusElement, ((Wire*)focusElement)->Port1, ctrl);
01499       Doc->selectWireLine(focusElement, ((Wire*)focusElement)->Port2, ctrl);
01500     }
01501 
01502   Doc->releaseKeyboard();  // allow keyboard inputs again
01503   QucsMain->MousePressAction = &MouseActions::MPressSelect;
01504   QucsMain->MouseReleaseAction = &MouseActions::MReleaseSelect;
01505   QucsMain->MouseDoubleClickAction = &MouseActions::MDoubleClickSelect;
01506   QucsMain->MouseMoveAction = 0;   // no element moving
01507   Doc->highlightWireLabels ();
01508   Doc->viewport()->update();
01509   drawn = false;
01510 }
01511 
01512 // -----------------------------------------------------------
01513 // Is called after the rectangle for selection is released.
01514 void MouseActions::MReleaseSelect2(Schematic *Doc, QMouseEvent *Event)
01515 {
01516   if(Event->button() != Qt::LeftButton) return;
01517 
01518   bool Ctrl;
01519   if(Event->state() & Qt::ControlModifier) Ctrl = true;
01520   else Ctrl = false;
01521 
01522   // selects all elements within the rectangle
01523   Doc->selectElements(MAx1, MAy1, MAx1+MAx2, MAy1+MAy2, Ctrl);
01524 
01525   Doc->releaseKeyboard();  // allow keyboard inputs again
01526   QucsMain->MouseMoveAction = 0;
01527   QucsMain->MousePressAction = &MouseActions::MPressSelect;
01528   QucsMain->MouseReleaseAction = &MouseActions::MReleaseSelect;
01529   QucsMain->MouseDoubleClickAction = &MouseActions::MDoubleClickSelect;
01530   Doc->highlightWireLabels ();
01531   Doc->viewport()->update();
01532   drawn = false;
01533 }
01534 
01535 // -----------------------------------------------------------
01536 void MouseActions::MReleaseActivate(Schematic *Doc, QMouseEvent *Event)
01537 {
01538   if(Event->button() != Qt::LeftButton) return;
01539 
01540   // activates all components within the rectangle
01541   Doc->activateCompsWithinRect(MAx1, MAy1, MAx1+MAx2, MAy1+MAy2);
01542 
01543   QucsMain->MouseMoveAction = &MouseActions::MMoveActivate;
01544   QucsMain->MousePressAction = &MouseActions::MPressActivate;
01545   QucsMain->MouseReleaseAction = 0;
01546   QucsMain->MouseDoubleClickAction = 0;
01547   Doc->highlightWireLabels ();
01548   Doc->viewport()->update();
01549   drawn = false;
01550 }
01551 
01552 // -----------------------------------------------------------
01553 // Is called after moving selected elements.
01554 void MouseActions::MReleaseMoving(Schematic *Doc, QMouseEvent*)
01555 {
01556   // Allow all mouse buttons, because for others than the left one,
01557   // a menu has already created.
01558   endElementMoving(Doc, &movingElements);
01559   Doc->releaseKeyboard();  // allow keyboard inputs again
01560 
01561   QucsMain->MouseMoveAction = 0;
01562   QucsMain->MousePressAction = &MouseActions::MPressSelect;
01563   QucsMain->MouseReleaseAction = &MouseActions::MReleaseSelect;
01564   QucsMain->MouseDoubleClickAction = &MouseActions::MDoubleClickSelect;
01565 }
01566 
01567 // -----------------------------------------------------------
01568 void MouseActions::MReleaseResizeDiagram(Schematic *Doc, QMouseEvent *Event)
01569 {
01570   if(Event->button() != Qt::LeftButton) return;
01571 
01572   MAx3  = focusElement->cx;
01573   MAy3  = focusElement->cy;
01574   if(MAx2 < 0) {    // resize diagram
01575     if(MAx2 > -10) MAx2 = -10;   // not smaller than 10 pixels
01576     focusElement->x2 = -MAx2;
01577     focusElement->cx = MAx1+MAx2;
01578   }
01579   else {
01580     if(MAx2 < 10) MAx2 = 10;
01581     focusElement->x2 = MAx2;
01582     focusElement->cx = MAx1;
01583   }
01584   if(MAy2 < 0) {
01585     if(MAy2 > -10) MAy2 = -10;
01586     focusElement->y2 = -MAy2;
01587     focusElement->cy = MAy1;
01588   }
01589   else {
01590     if(MAy2 < 10) MAy2 = 10;
01591     focusElement->y2 = MAy2;
01592     focusElement->cy = MAy1+MAy2;
01593   }
01594   MAx3 -= focusElement->cx;
01595   MAy3 -= focusElement->cy;
01596 
01597   Diagram *pd = (Diagram*)focusElement;
01598   pd->updateGraphData();
01599   foreach(Graph *pg, pd->Graphs)
01600     foreach(Marker *pm, pg->Markers) {
01601       pm->x1 += MAx3;      // correct changes due to move of diagram corner
01602       pm->y1 += MAy3;
01603     }
01604 
01605   int x1, x2, y1, y2;
01606   pd->Bounding(x1, x2, y1, y2);
01607   Doc->enlargeView(x1, x2, y1, y2);
01608 
01609   QucsMain->MouseMoveAction = 0;
01610   QucsMain->MousePressAction = &MouseActions::MPressSelect;
01611   QucsMain->MouseReleaseAction = &MouseActions::MReleaseSelect;
01612   QucsMain->MouseDoubleClickAction = &MouseActions::MDoubleClickSelect;
01613   Doc->releaseKeyboard();  // allow keyboard inputs again
01614 
01615   Doc->viewport()->update();
01616   drawn = false;
01617   Doc->setChanged(true, true);
01618 }
01619 
01620 // -----------------------------------------------------------
01621 void MouseActions::MReleaseResizePainting(Schematic *Doc, QMouseEvent *Event)
01622 {
01623   if(Event->button() != Qt::LeftButton) return;
01624 
01625   QucsMain->MouseMoveAction = 0;
01626   QucsMain->MousePressAction = &MouseActions::MPressSelect;
01627   QucsMain->MouseReleaseAction = &MouseActions::MReleaseSelect;
01628   QucsMain->MouseDoubleClickAction = &MouseActions::MDoubleClickSelect;
01629   Doc->releaseKeyboard();  // allow keyboard inputs again
01630 
01631   Doc->viewport()->update();
01632   drawn = false;
01633   Doc->setChanged(true, true);
01634 }
01635 
01636 // -----------------------------------------------------------
01637 void MouseActions::paintElementsScheme(Schematic *p)
01638 {
01639   Element *pe;
01640   for(pe = movingElements.first(); pe != 0; pe = movingElements.next())
01641     pe->paintScheme(p);
01642 }
01643 
01644 // -----------------------------------------------------------
01645 void MouseActions::moveElements(Schematic *Doc, int& x1, int& y1)
01646 {
01647   Element *pe;
01648   Doc->setOnGrid(x1, y1);
01649 
01650   for(pe=movingElements.first(); pe!=0; pe=movingElements.next()) {
01651     if(pe->Type & isLabel) {
01652       pe->cx += x1;  pe->x1 += x1;
01653       pe->cy += y1;  pe->y1 += y1;
01654     }
01655     else
01656       pe->setCenter(x1, y1, true);
01657   }
01658 }
01659 
01660 // -----------------------------------------------------------
01661 void MouseActions::rotateElements(Schematic *Doc, int& x1, int& y1)
01662 {
01663   int x2, y2;
01664   Element *pe;
01665   Doc->setOnGrid(x1, y1);
01666 
01667   for(pe = movingElements.first(); pe != 0; pe = movingElements.next()) {
01668     switch(pe->Type) {
01669     case isComponent:
01670     case isAnalogComponent:
01671     case isDigitalComponent:
01672       ((Component*)pe)->rotate(); // rotate !before! rotating the center
01673       x2 = x1 - pe->cx;
01674       pe->setCenter(pe->cy - y1 + x1, x2 + y1);
01675       break;
01676     case isWire:
01677       x2     = pe->x1;
01678       pe->x1 = pe->y1 - y1 + x1;
01679       pe->y1 = x1 - x2 + y1;
01680       x2     = pe->x2;
01681       pe->x2 = pe->y2 - y1 + x1;
01682       pe->y2 = x1 - x2 + y1;
01683       break;
01684     case isPainting:
01685       ((Painting*)pe)->rotate(); // rotate !before! rotating the center
01686       ((Painting*)pe)->getCenter(x2, y2);
01687       pe->setCenter(y2 - y1 + x1, x1 - x2 + y1);
01688           break;
01689     default:
01690       x2 = x1 - pe->cx;   // if diagram -> only rotate cx/cy
01691       pe->setCenter(pe->cy - y1 + x1, x2 + y1);
01692       break;
01693     }
01694   }
01695 }
01696 
01697 // -----------------------------------------------------------
01698 void MouseActions::MReleasePaste(Schematic *Doc, QMouseEvent *Event)
01699 {
01700   int x1, y1, x2, y2, rot;
01701   QFileInfo Info(Doc->DocName);
01702   //QPainter painter(Doc->viewport());
01703 
01704   Element *pe;
01705   switch(Event->button()) {
01706   case Qt::LeftButton :
01707     // insert all moved elements into document
01708     for(pe = movingElements.first(); pe!=0; pe = movingElements.next()) {
01709       pe->isSelected = false;
01710       switch(pe->Type) {
01711   case isWire:
01712     if(pe->x1 == pe->x2) if(pe->y1 == pe->y2)  break;
01713     Doc->insertWire((Wire*)pe);
01714     if (Doc->Wires->containsRef ((Wire*)pe))
01715       Doc->enlargeView(pe->x1, pe->y1, pe->x2, pe->y2);
01716     else pe = NULL;
01717     break;
01718   case isDiagram:
01719     Doc->Diagrams->append((Diagram*)pe);
01720     ((Diagram*)pe)->loadGraphData(Info.dirPath() + QDir::separator() +
01721           Doc->DataSet);
01722     Doc->enlargeView(pe->cx, pe->cy-pe->y2, pe->cx+pe->x2, pe->cy);
01723     break;
01724   case isPainting:
01725     Doc->Paintings->append((Painting*)pe);
01726     ((Painting*)pe)->Bounding(x1,y1,x2,y2);
01727     Doc->enlargeView(x1, y1, x2, y2);
01728     break;
01729   case isMovingLabel:
01730     pe->Type = isNodeLabel;
01731     Doc->placeNodeLabel((WireLabel*)pe);
01732     break;
01733   case isComponent:
01734   case isAnalogComponent:
01735   case isDigitalComponent:
01736     Doc->insertComponent((Component*)pe);
01737     ((Component*)pe)->entireBounds(x1,y1,x2,y2, Doc->textCorr());
01738     Doc->enlargeView(x1, y1, x2, y2);
01739     break;
01740       }
01741     }
01742 
01743     pasteElements(Doc);
01744     // keep rotation sticky for pasted elements
01745     rot = movingRotated;
01746     x1 = y1 = 0;
01747     while(rot--) rotateElements(Doc,x1,y1);
01748 
01749     QucsMain->MouseMoveAction = &MouseActions::MMovePaste;
01750     QucsMain->MousePressAction = 0;
01751     QucsMain->MouseReleaseAction = 0;
01752     QucsMain->MouseDoubleClickAction = 0;
01753 
01754     drawn = false;
01755     Doc->viewport()->update();
01756     Doc->setChanged(true, true);
01757     break;
01758 
01759   // ............................................................
01760   case Qt::RightButton :  // right button rotates the elements
01761     //setPainter(Doc, &painter);
01762 
01763     if(drawn) // erase old scheme
01764       paintElementsScheme(Doc);
01765     drawn = true;
01766 
01767     x1 = DOC_X_POS(Event->pos().x());
01768     y1 = DOC_Y_POS(Event->pos().y());
01769     rotateElements(Doc,x1,y1);
01770     paintElementsScheme(Doc);
01771     // save rotation
01772     movingRotated++;
01773     movingRotated &= 3;
01774     break;
01775 
01776   default: ;    // avoids compiler warnings
01777   }
01778 }
01779 
01780 // -----------------------------------------------------------
01781 void MouseActions::MReleaseMoveText(Schematic *Doc, QMouseEvent *Event)
01782 {
01783   if(Event->button() != Qt::LeftButton) return;
01784 
01785   QucsMain->MouseMoveAction = &MouseActions::MMoveMoveTextB;
01786   QucsMain->MouseReleaseAction = 0;
01787   Doc->releaseKeyboard();  // allow keyboard inputs again
01788 
01789   ((Component*)focusElement)->tx = MAx1 - ((Component*)focusElement)->cx;
01790   ((Component*)focusElement)->ty = MAy1 - ((Component*)focusElement)->cy;
01791   Doc->viewport()->update();
01792   drawn = false;
01793   Doc->setChanged(true, true);
01794 }
01795 
01796 // -----------------------------------------------------------
01797 void MouseActions::MReleaseZoomIn(Schematic *Doc, QMouseEvent *Event)
01798 {
01799   if(Event->button() != Qt::LeftButton) return;
01800 
01801   MAx1 = Event->pos().x();
01802   MAy1 = Event->pos().y();
01803   float DX = float(MAx2);
01804   float DY = float(MAy2);
01805 
01806   float initialScale = Doc->Scale;
01807   float scale = 1;
01808   float xShift = 0;
01809   float yShift = 0;
01810   if((Doc->Scale * DX) < 6.0) {
01811     // a simple click zooms by constant factor
01812     scale = Doc->zoom(1.5)/initialScale;
01813 
01814     xShift = scale * Event->pos().x();
01815     yShift = scale * Event->pos().y();
01816   } else {
01817     float xScale = float(Doc->visibleWidth())  / std::abs(DX);
01818     float yScale = float(Doc->visibleHeight()) / std::abs(DY);
01819     scale = qMin(xScale, yScale)/initialScale;
01820     scale = Doc->zoom(scale)/initialScale;
01821 
01822     xShift = scale * (MAx1 - 0.5*DX);
01823     yShift = scale * (MAy1 - 0.5*DY);
01824   }
01825   xShift -= (0.5*Doc->visibleWidth() + Doc->contentsX());
01826   yShift -= (0.5*Doc->visibleHeight() + Doc->contentsY());
01827   Doc->scrollBy(xShift, yShift);
01828 
01829   QucsMain->MouseMoveAction = &MouseActions::MMoveZoomIn;
01830   QucsMain->MouseReleaseAction = 0;
01831   Doc->releaseKeyboard();  // allow keyboard inputs again
01832 }
01833 
01834 
01835 // ***********************************************************************
01836 // **********                                                   **********
01837 // **********    Functions for mouse button double clicking     **********
01838 // **********                                                   **********
01839 // ***********************************************************************
01840 void MouseActions::editElement(Schematic *Doc, QMouseEvent *Event)
01841 {
01842 //    qDebug() << "+double click, editElement";
01843 
01844   if(focusElement == 0) return;
01845 
01846 //  qDebug() << "+focusElement->Type" << focusElement->Type;
01847 
01848   Graph *pg;
01849   Component *c;
01850   Diagram *dia;
01851   DiagramDialog *ddia;
01852   MarkerDialog *mdia;
01853   int x1, y1, x2, y2;
01854 
01855   QFileInfo Info(Doc->DocName);
01856   float fX = DOC_X_FPOS, fY = DOC_Y_FPOS;
01857 
01858   switch(focusElement->Type) {
01859     case isComponent:
01860     case isAnalogComponent:
01861     case isDigitalComponent:
01862          c = (Component*)focusElement;
01863 //         qDebug() << "cast focusElement into" << c->Name;
01864          if(c->Model == "GND") return;
01865 
01866          if(c->Model == "SPICE") {
01867            SpiceDialog *sd = new SpiceDialog(App, (SpiceFile*)c, Doc);
01868            if(sd->exec() != 1) break;   // dialog is WDestructiveClose
01869          }
01870          else if(c->Model == ".Opt") {
01871            OptimizeDialog *od = new OptimizeDialog((Optimize_Sim*)c, Doc);
01872            if(od->exec() != 1) break;   // dialog is WDestructiveClose
01873          }
01874          else {
01875            ComponentDialog * cd = new ComponentDialog(c, Doc);
01876            if(cd->exec() != 1) break;   // dialog is WDestructiveClose
01877 
01878            Doc->Components->findRef(c);
01879            Doc->Components->take();
01880            Doc->setComponentNumber(c); // for ports/power sources
01881            Doc->Components->append(c);
01882          }
01883 
01884          Doc->setChanged(true, true);
01885          c->entireBounds(x1,y1,x2,y2, Doc->textCorr());
01886          Doc->enlargeView(x1,y1,x2,y2);
01887          break;
01888 
01889     case isDiagram :
01890          dia = (Diagram*)focusElement;
01891          if(dia->Name.at(0) == 'T') { // don't open dialog on scrollbar
01892            if(dia->Name == "Time") {
01893              if(dia->cy < int(fY)) {
01894          if(((TimingDiagram*)focusElement)->scroll(MAx1))
01895            Doc->setChanged(true, true, 'm'); // 'm' = only the first time
01896          break;
01897              }
01898      }
01899            else {
01900              if(dia->cx > int(fX)) {
01901          if(((TabDiagram*)focusElement)->scroll(MAy1))
01902            Doc->setChanged(true, true, 'm'); // 'm' = only the first time
01903          break;
01904              }
01905      }
01906    }
01907 
01908    ddia = new DiagramDialog(dia, Doc);
01909          if(ddia->exec() != QDialog::Rejected)   // is WDestructiveClose
01910            Doc->setChanged(true, true);
01911 
01912    dia->Bounding(x1, x2, y1, y2);
01913    Doc->enlargeView(x1, x2, y1, y2);
01914    break;
01915 
01916     case isGraph :
01917    pg = (Graph*)focusElement;
01918    // searching diagram for this graph
01919    for(dia = Doc->Diagrams->last(); dia != 0; dia = Doc->Diagrams->prev())
01920      if(dia->Graphs.indexOf(pg) >= 0)
01921        break;
01922    if(!dia) break;
01923 
01924 
01925    ddia = new DiagramDialog(dia, Doc, pg);
01926    if(ddia->exec() != QDialog::Rejected)   // is WDestructiveClose
01927      Doc->setChanged(true, true);
01928          break;
01929 
01930     case isWire:
01931          MPressLabel(Doc, Event, fX, fY);
01932          break;
01933 
01934     case isNodeLabel:
01935     case isHWireLabel:
01936     case isVWireLabel:
01937          editLabel(Doc, (WireLabel*)focusElement);
01938          break;
01939 
01940     case isPainting:
01941          if( ((Painting*)focusElement)->Dialog() )
01942            Doc->setChanged(true, true);
01943          break;
01944 
01945     case isMarker:
01946          mdia = new MarkerDialog((Marker*)focusElement, Doc);
01947          if(mdia->exec() > 1)
01948            Doc->setChanged(true, true);
01949          break;
01950   }
01951 
01952   // Very strange: Now an open VHDL editor gets all the keyboard input !?!
01953   // I don't know why it only happens here, nor am I sure whether it only
01954   // happens here. Anyway, I hope the best and give the focus back to the
01955   // current document.
01956   Doc->setFocus();
01957 
01958   Doc->viewport()->update();
01959   drawn = false;
01960 }
01961 
01962 // -----------------------------------------------------------
01963 void MouseActions::MDoubleClickSelect(Schematic *Doc, QMouseEvent *Event)
01964 {
01965   Doc->releaseKeyboard();  // allow keyboard inputs again
01966   QucsMain->editText->setHidden(true);
01967   editElement(Doc, Event);
01968 }
01969 
01970 
01976 void MouseActions::MDoubleClickWire2(Schematic *Doc, QMouseEvent *Event)
01977 {
01978   MPressWire2(Doc, Event, DOC_X_FPOS, DOC_Y_FPOS);
01979 
01980   if(formerAction)
01981     QucsMain->select->setChecked(true);  // restore old action
01982   else {
01983     QucsMain->MouseMoveAction = &MouseActions::MMoveWire1;
01984     QucsMain->MousePressAction = &MouseActions::MPressWire1;
01985     QucsMain->MouseDoubleClickAction = 0;
01986   }
01987 }
01988 
01989 // vim:ts=8:sw=2:noet
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines