Qucs-GUI  0.0.18
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
arrow.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  arrow.cpp
3  -----------
4  begin : Sun Nov 23 2003
5  copyright : (C) 2003 by Michael Margraf
6  email : michael.margraf@alumni.tu-berlin.de
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 #include <QtGui>
18 #include "arrow.h"
19 #include "arrowdialog.h"
20 #include "schematic.h"
21 
22 #include <QLineEdit>
23 #include <QPushButton>
24 #include <QComboBox>
25 //Added by qt3to4:
26 #include <Q3PointArray>
27 #include <math.h>
28 
29 
31 {
32  Name = "Arrow ";
33  isSelected = false;
34  Pen = QPen(QColor());
35  cx = cy = 0;
36  x1 = x2 = 0;
37  y1 = y2 = 0;
38 
39  Height = 20.0;
40  Width = 8.0;
41  Style = 0; // arrow head not filled
42  beta = atan2(double(Width), double(Height));
43  Length = sqrt(Width*Width + Height*Height);
44 }
45 
47 {
48 }
49 
50 // --------------------------------------------------------------------------
52 {
53  Q3PointArray Points;
54  int x1_, y1_, x2_, y2_, x3_, y3_;
55  if(isSelected) {
56  p->Painter->setPen(QPen(Qt::darkGray,Pen.width()+5));
57  p->drawLine(cx, cy, cx+x2, cy+y2);
58  p->drawLine(cx+x2, cy+y2, cx+xp1, cy+yp1);
59  p->drawLine(cx+x2, cy+y2, cx+xp2, cy+yp2);
60  if(Style == 0) { // arrow head with two lines ?
61  p->Painter->setPen(QPen(Qt::white, Pen.width(), Pen.style()));
62  p->drawLine(cx, cy, cx+x2, cy+y2);
63  p->Painter->setPen(QPen(Qt::white, Pen.width(), Qt::SolidLine));
64  p->drawLine(cx+x2, cy+y2, cx+xp1, cy+yp1);
65  p->drawLine(cx+x2, cy+y2, cx+xp2, cy+yp2);
66  }
67  else { // filled arrow head
68  p->drawLine(cx+xp1, cy+yp1, cx+xp2, cy+yp2);
69  p->Painter->setPen(QPen(Qt::white, Pen.width(), Pen.style()));
70  p->drawLine(cx, cy, cx+x2, cy+y2);
71 
72  p->Painter->setPen(QPen(Qt::white, Pen.width(), Qt::SolidLine));
73  p->Painter->setBrush(Qt::white);
74  p->map(cx+xp1, cy+yp1, x1_, y1_);
75  p->map(cx+x2, cy+y2, x2_, y2_);
76  p->map(cx+xp2, cy+yp2, x3_, y3_);
77  Points.setPoints(3, x1_, y1_, x2_, y2_, x3_, y3_);
78  p->Painter->drawConvexPolygon(Points);
79  p->Painter->setBrush(Qt::NoBrush); // no filling for next paintings
80  }
81 
82  p->Painter->setPen(QPen(Qt::darkRed,2));
83  p->drawResizeRect(cx, cy); // markers for changing the size
84  p->drawResizeRect(cx+x2, cy+y2);
85  return;
86  }
87  p->Painter->setPen(Pen);
88  p->drawLine(cx, cy, cx+x2, cy+y2);
89  p->Painter->setPen(QPen(Pen.color(), Pen.width(), Qt::SolidLine));
90  if(Style == 0) { // arrow head with two lines ?
91  p->drawLine(cx+x2, cy+y2, cx+xp1, cy+yp1);
92  p->drawLine(cx+x2, cy+y2, cx+xp2, cy+yp2);
93  }
94  else { // filled arrow head
95  p->Painter->setBrush(Pen.color());
96  p->map(cx+xp1, cy+yp1, x1_, y1_);
97  p->map(cx+x2, cy+y2, x2_, y2_);
98  p->map(cx+xp2, cy+yp2, x3_, y3_);
99  Points.setPoints(3, x1_, y1_, x2_, y2_, x3_, y3_);
100  p->Painter->drawConvexPolygon(Points);
101  p->Painter->setBrush(Qt::NoBrush); // no filling for next paintings
102  }
103 }
104 
105 // --------------------------------------------------------------------------
107 {
108  p->PostPaintEvent(_Line, cx, cy, cx+x2, cy+y2,0,0,false);
109  p->PostPaintEvent(_Line, cx+x2, cy+y2, cx+xp1, cy+yp1,0,0,false);
110  p->PostPaintEvent(_Line, cx+x2, cy+y2, cx+xp2, cy+yp2,0,0,false);
111 }
112 
113 // --------------------------------------------------------------------------
114 void Arrow::getCenter(int& x, int &y)
115 {
116  x = cx+(x2>>1);
117  y = cy+(y2>>1);
118 }
119 
120 // --------------------------------------------------------------------------
121 // Sets the center of the painting to x/y.
122 void Arrow::setCenter(int x, int y, bool relative)
123 {
124  if(relative) { cx += x; cy += y; }
125  else { cx = x-(x2>>1); cy = y-(y2>>1); }
126 }
127 
128 // --------------------------------------------------------------------------
130 {
131  return new Arrow();
132 }
133 
134 // --------------------------------------------------------------------------
135 Element* Arrow::info(QString& Name, char* &BitmapFile, bool getNewOne)
136 {
137  Name = QObject::tr("Arrow");
138  BitmapFile = (char *) "arrow";
139 
140  if(getNewOne) return new Arrow();
141  return 0;
142 }
143 
144 // --------------------------------------------------------------------------
145 bool Arrow::load(const QString& s)
146 {
147  bool ok;
148 
149  QString n;
150  n = s.section(' ',1,1); // cx
151  cx = n.toInt(&ok);
152  if(!ok) return false;
153 
154  n = s.section(' ',2,2); // cy
155  cy = n.toInt(&ok);
156  if(!ok) return false;
157 
158  n = s.section(' ',3,3); // x2
159  x2 = n.toInt(&ok);
160  if(!ok) return false;
161 
162  n = s.section(' ',4,4); // y2
163  y2 = n.toInt(&ok);
164  if(!ok) return false;
165 
166  n = s.section(' ',5,5); // height
167  Height = n.toDouble(&ok);
168  if(!ok) return false;
169 
170  n = s.section(' ',6,6); // width
171  Width = n.toDouble(&ok);
172  if(!ok) return false;
173 
174  n = s.section(' ',7,7); // color
175  QColor co;
176  co.setNamedColor(n);
177  Pen.setColor(co);
178  if(!Pen.color().isValid()) return false;
179 
180  n = s.section(' ',8,8); // thickness
181  Pen.setWidth(n.toInt(&ok));
182  if(!ok) return false;
183 
184  n = s.section(' ',9,9); // line style
185  Pen.setStyle((Qt::PenStyle)n.toInt(&ok));
186  if(!ok) return false;
187 
188  n = s.section(' ',10,10); // arrow style
189  if(!n.isEmpty()) { // backward compatible
190  Style = n.toInt(&ok);
191  if(!ok) return false;
192  }
193 
194  beta = atan2(double(Width), double(Height));
195  Length = sqrt(Width*Width + Height*Height);
196  calcArrowHead();
197  return true;
198 }
199 
200 // --------------------------------------------------------------------------
201 QString Arrow::save()
202 {
203  QString s = Name+QString::number(cx)+" "+QString::number(cy)+" ";
204  s += QString::number(x2)+" "+QString::number(y2)+" ";
205  s += QString::number(int(Height))+" "+QString::number(int(Width))+" ";
206  s += Pen.color().name()+" "+QString::number(Pen.width())+" ";
207  s += QString::number(Pen.style()) + " " + QString::number(Style);
208  return s;
209 }
210 
211 // --------------------------------------------------------------------------
212 QString Arrow::saveCpp()
213 {
214  // arrow not allowed in symbols, thus we use line here
215  QString s =
216  QString ("new Line (%1, %2, %3, %4, QPen (QColor (\"%5\"), %6, %7))").
217  arg(cx+x1).arg(cy+y1).arg(cx+x2).arg(cy+y2).
218  arg(Pen.color().name()).arg(Pen.width()).arg(toPenString(Pen.style()));
219  s = "Lines.append (" + s + ");";
220  return s;
221 }
222 
224 {
225  // arrow not allowed in symbols, thus we use line here
226  QString s =
227  QString("{\"type\" : \"arrow\", "
228  "\"x1\" : %1, \"y1\" : %2, \"x2\" : %3, \"y2\" : %4, "
229  "\"color\" : \"%5\", \"thick\" : %6, \"style\" : \"%7\"},").
230  arg(cx+x1).arg(cy+y1).arg(cx+x2).arg(cy+y2).
231  arg(Pen.color().name()).arg(Pen.width()).arg(toPenString(Pen.style()));
232  return s;
233 }
234 
235 // --------------------------------------------------------------------------
236 // Checks if the resize area was clicked.
237 bool Arrow::resizeTouched(float fX, float fY, float len)
238 {
239  float fCX = float(cx),fCY = float(cy);
240  if(fX < fCX+len) if(fX > fCX-len) if(fY < fCY+len) if(fY > fCY-len) {
241  State = 1;
242  return true;
243  }
244 
245  fCX += float(x2);
246  fCY += float(y2);
247  if(fX < fCX+len) if(fX > fCX-len) if(fY < fCY+len) if(fY > fCY-len) {
248  State = 2;
249  return true;
250  }
251 
252  State = 0;
253  return false;
254 }
255 
256 // --------------------------------------------------------------------------
257 // Mouse move action during resize.
258 void Arrow::MouseResizeMoving(int x, int y, Schematic *p)
259 {
260  paintScheme(p); // erase old painting
261  if(State == 1) { x2 += cx-x; y2 += cy-y; cx = x; cy = y; } // moving shaft
262  else { x2 = x-cx; y2 = y-cy; } // moving head
263 
264  calcArrowHead();
265  paintScheme(p); // paint new painting
266 }
267 
268 // --------------------------------------------------------------------------
270 {
271  double phi = atan2(double(y2), double(x2));
272 
273  double w = beta+phi;
274  xp1 = x2-int(Length*cos(w));
275  yp1 = y2-int(Length*sin(w));
276 
277  w = phi-beta;
278  xp2 = x2-int(Length*cos(w));
279  yp2 = y2-int(Length*sin(w));
280 }
281 
282 // --------------------------------------------------------------------------
283 // fx/fy are the precise coordinates, gx/gy are the coordinates set on grid.
284 // x/y are coordinates without scaling.
286  Schematic *paintScale, int, int, int gx, int gy,
287  Schematic *p, int x, int y, bool drawn)
288 {
289  if(State > 0) {
290  if(State > 1) {
291  calcArrowHead();
292  paintScheme(paintScale); // erase old painting
293  }
294  State++;
295  x2 = gx-cx;
296  y2 = gy-cy;
297  calcArrowHead();
298  paintScheme(paintScale); // paint new painting
299  }
300  else { cx = gx; cy = gy; }
301 
302 
303 // FIXME #warning p->setPen(Qt::SolidLine);
304  if(drawn) {
305  p->PostPaintEvent(_Line, x1+25, y1, x1+13, y1+12,0,0,true); // erase old cursor symbol
306  p->PostPaintEvent(_Line, x1+18, y1+2, x1+25, y1,0,0,true);
307  p->PostPaintEvent(_Line, x1+23, y1+7, x1+25, y1,0,0,true);
308  }
309  x1 = x;
310  y1 = y;
311  p->PostPaintEvent(_Line, x1+25, y1, x1+13, y1+12,0,0,true); // paint new cursor symbol
312  p->PostPaintEvent(_Line, x1+18, y1+2, x1+25, y1,0,0,true);
313  p->PostPaintEvent(_Line, x1+23, y1+7, x1+25, y1,0,0,true);
314 }
315 
316 // --------------------------------------------------------------------------
318 {
319  State++;
320  if(State > 2) {
321  x1 = y1 = 0;
322  State = 0;
323 
324  calcArrowHead();
325  return true; // painting is ready
326  }
327  return false;
328 }
329 
330 // --------------------------------------------------------------------------
331 // Checks if the coordinates x/y point to the painting.
332 // 5 is the precision the user must point onto the painting.
333 bool Arrow::getSelected(float fX, float fY, float w)
334 {
335  float A, xn, yn;
336  // first check if coordinates match the arrow body
337  fX -= float(cx);
338  fY -= float(cy);
339 
340  if(fX < -w) {
341  if(fX < float(x2)-w) // is point between x coordinates ?
342  goto Head1;
343  }
344  else {
345  if(fX > w)
346  if(fX > float(x2)+w)
347  goto Head1;
348  }
349 
350  if(fY < -w) {
351  if(fY < float(y2)-w) // is point between y coordinates ?
352  goto Head1;
353  }
354  else {
355  if(fY > w)
356  if(fY > float(y2)+w)
357  goto Head1;
358  }
359 
360  A = float(x2)*fY - fX*float(y2); // calculate the rectangle area spanned
361  A *= A; // avoid the need for square root
362 
363  if(A <= w*w*float(x2*x2 + y2*y2))
364  return true; // x/y lies on the graph line
365 
366 Head1: // check if coordinates match the first arrow head line
367  xn = float(xp1-x2); fX -= float(x2);
368  yn = float(yp1-y2); fY -= float(y2);
369 
370  if(fX < -w) {
371  if(fX < xn-w) // is point between x coordinates ?
372  goto Head2;
373  }
374  else {
375  if(fX > w)
376  if(fX > xn+w)
377  goto Head2;
378  }
379 
380  if(fY < -w) {
381  if(fY < yn-w) // is point between y coordinates ?
382  goto Head2;
383  }
384  else
385  if(fY > w)
386  if(fY > yn+w)
387  goto Head2;
388 
389  A = xn*fY - fX*yn; // calculate the rectangle area spanned
390  A *= A; // avoid the need for square root
391 
392  if(A <= w*w*(xn*xn + yn*yn))
393  return true; // x/y lies on the arrow head
394 
395 Head2: // check if coordinates match the second arrow head line
396  xn = float(xp2-x2);
397  yn = float(yp2-y2);
398 
399  if(fX < -w) {
400  if(fX < xn-w) // is point between x coordinates ?
401  return false;
402  }
403  else
404  if(fX > w)
405  if(fX > xn+w)
406  return false;
407 
408  if(fY < -w) {
409  if(fY < yn-w) // is point between y coordinates ?
410  return false;
411  }
412  else
413  if(fY > w)
414  if(fY > yn+w)
415  return false;
416 
417  A = xn*fY - fX*yn; // calculate the rectangle area spanned
418  A *= A; // avoid the need for square root
419 
420  if(A <= w*w*(xn*xn + yn*yn))
421  return true; // x/y lies on the arrow head
422 
423  return false;
424 }
425 
426 // --------------------------------------------------------------------------
427 void Arrow::Bounding(int& _x1, int& _y1, int& _x2, int& _y2)
428 {
429  if(x2 < 0) { _x1 = cx+x2; _x2 = cx; }
430  else { _x1 = cx; _x2 = cx+x2; }
431 
432  if(y2 < 0) { _y1 = cy+y2; _y2 = cy; }
433  else { _y1 = cy; _y2 = cy+y2; }
434 }
435 
436 // --------------------------------------------------------------------------
437 // Rotates around the center.
439 {
440  cx += (x2>>1) - (y2>>1);
441  cy += (x2>>1) + (y2>>1);
442 
443  int tmp = x2;
444  x2 = y2;
445  y2 = -tmp;
446 
447  tmp = xp1;
448  xp1 = yp1;
449  yp1 = -tmp;
450 
451  tmp = xp2;
452  xp2 = yp2;
453  yp2 = -tmp;
454 }
455 
456 // --------------------------------------------------------------------------
457 // Mirrors about center line.
459 {
460  yp1 = -yp1;
461  yp2 = -yp2;
462  cy += y2; // change cy after the other changes !
463  y2 = -y2;
464 }
465 
466 // --------------------------------------------------------------------------
467 // Mirrors about center line.
469 {
470  xp1 = -xp1;
471  xp2 = -xp2;
472  cx += x2; // change cx after the other changes !
473  x2 = -x2;
474 }
475 
476 // --------------------------------------------------------------------------
477 // Calls the property dialog for the painting and changes them accordingly.
478 // If there were changes, it returns 'true'.
480 {
481  bool changed = false;
482 
483  ArrowDialog *d = new ArrowDialog();
484  d->HeadWidth->setText(QString::number(Width));
485  d->HeadLength->setText(QString::number(Height));
486  d->ColorButt->setPaletteBackgroundColor(Pen.color());
487  d->LineWidth->setText(QString::number(Pen.width()));
488  d->SetComboBox(Pen.style());
489  d->ArrowStyleBox->setCurrentItem(Style);
490 
491  if(d->exec() == QDialog::Rejected) {
492  delete d;
493  return false;
494  }
495 
496  if(Width != d->HeadWidth->text().toDouble()) {
497  Width = d->HeadWidth->text().toDouble();
498  changed = true;
499  }
500  if(Height != d->HeadLength->text().toDouble()) {
501  Height = d->HeadLength->text().toDouble();
502  changed = true;
503  }
504  if(Pen.color() != d->ColorButt->paletteBackgroundColor()) {
505  Pen.setColor(d->ColorButt->paletteBackgroundColor());
506  changed = true;
507  }
508  if(Pen.width() != d->LineWidth->text().toUInt()) {
509  Pen.setWidth(d->LineWidth->text().toUInt());
510  changed = true;
511  }
512  if(Pen.style() != d->LineStyle) {
513  Pen.setStyle(d->LineStyle);
514  changed = true;
515  }
516  if(Style != d->ArrowStyleBox->currentItem()) {
517  Style = d->ArrowStyleBox->currentItem();
518  changed = true;
519  }
520 
521  beta = atan2(double(Width), double(Height));
522  Length = sqrt(Width*Width + Height*Height);
523  calcArrowHead();
524 
525  delete d;
526  return changed;
527 }
~Arrow()
Definition: arrow.cpp:46
void drawResizeRect(int, int)
QPainter * Painter
Definition: viewpainter.h:58
double Width
Definition: arrow.h:58
void mirrorX()
Definition: arrow.cpp:458
bool load(const QString &)
Definition: arrow.cpp:145
QString toPenString(int)
Definition: painting.cpp:54
int State
Definition: painting.h:56
double Height
Definition: arrow.h:58
int y1
Definition: element.h:153
void PostPaintEvent(PE pe, int x1=0, int y1=0, int x2=0, int y2=0, int a=0, int b=0, bool PaintOnViewport=false)
Definition: schematic.cpp:533
QLineEdit * HeadLength
Definition: arrowdialog.h:45
void MouseResizeMoving(int, int, Schematic *)
Definition: arrow.cpp:258
QLineEdit * HeadWidth
Definition: arrowdialog.h:45
void map(int, int, int &, int &)
Definition: viewpainter.cpp:63
void paint(ViewPainter *)
Definition: arrow.cpp:51
QString saveCpp()
Definition: arrow.cpp:212
int y2
Definition: element.h:153
int x1
Definition: element.h:153
void paintScheme(Schematic *)
Definition: arrow.cpp:106
QString save()
Definition: arrow.cpp:201
Arrow()
Definition: arrow.cpp:30
void drawLine(int, int, int, int)
Definition: viewpainter.cpp:85
Qt::PenStyle LineStyle
Definition: arrowdialog.h:48
void Bounding(int &, int &, int &, int &)
Definition: arrow.cpp:427
int yp1
Definition: arrow.h:60
QLineEdit * LineWidth
Definition: arrowdialog.h:45
Painting * newOne()
Definition: arrow.cpp:129
bool MousePressing()
Definition: arrow.cpp:317
int cx
Definition: element.h:153
void setCenter(int, int, bool relative=false)
Definition: arrow.cpp:122
QString saveJSON()
Definition: arrow.cpp:223
QComboBox * ArrowStyleBox
Definition: arrowdialog.h:47
QPushButton * ColorButt
Definition: arrowdialog.h:46
bool isSelected
Definition: element.h:151
void MouseMoving(Schematic *, int, int, int, int, Schematic *, int, int, bool)
Definition: arrow.cpp:285
QString Name
Definition: painting.h:55
Superclass of all schematic drawing elements.
Definition: element.h:142
double Length
Definition: arrow.h:59
int yp2
Definition: arrow.h:60
void getCenter(int &, int &)
Definition: arrow.cpp:114
void mirrorY()
Definition: arrow.cpp:468
bool getSelected(float, float, float)
Definition: arrow.cpp:333
double beta
Definition: arrow.h:59
QPen Pen
Definition: arrow.h:56
void SetComboBox(Qt::PenStyle)
void rotate()
Definition: arrow.cpp:438
int xp1
Definition: arrow.h:60
int cy
Definition: element.h:153
static Element * info(QString &, char *&, bool getNewOne=false)
Definition: arrow.cpp:135
int xp2
Definition: arrow.h:60
bool resizeTouched(float, float, float)
Definition: arrow.cpp:237
void calcArrowHead()
Definition: arrow.cpp:269
int x2
Definition: element.h:153
int Style
Definition: arrow.h:57
bool Dialog()
Definition: arrow.cpp:479