Qucs-GUI  0.0.19
/home/travis/build/Qucs/qucs/qucs/qucs/diagrams/tabdiagram.cpp
Go to the documentation of this file.
00001 /***************************************************************************
00002                                tabdiagram.cpp
00003                               ----------------
00004     begin                : Fri Oct 24 2003
00005     copyright            : (C) 2003 by Michael Margraf
00006     email                : michael.margraf@alumni.tu-berlin.de
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  *                                                                         *
00011  *   This program is free software; you can redistribute it and/or modify  *
00012  *   it under the terms of the GNU General Public License as published by  *
00013  *   the Free Software Foundation; either version 2 of the License, or     *
00014  *   (at your option) any later version.                                   *
00015  *                                                                         *
00016  ***************************************************************************/
00017 
00023 #include <QFontMetrics>
00024 #include <QPolygon>
00025 #include <QPainter>
00026 
00027 #include "tabdiagram.h"
00028 #include "main.h"
00029 #include <cmath>
00030 #include "misc.h"
00031 
00032 
00033 TabDiagram::TabDiagram(int _cx, int _cy) : Diagram(_cx, _cy)
00034 {
00035   x1 = 0;    // no extension to select area
00036   y1 = 0;
00037   x2 = x3 = 300;  // initial size of diagram
00038   y2 = 200;
00039   Name = "Tab";
00040   xAxis.limit_min = 0.0;  // scroll bar position (needs to be saved in file)
00041 
00042   calcDiagram();
00043 }
00044 
00045 TabDiagram::~TabDiagram()
00046 {
00047 }
00048 
00049 // ------------------------------------------------------------
00050 void TabDiagram::paint(ViewPainter *p)
00051 {
00052   // paint all lines
00053   foreach(Line *pl, Lines) {
00054     p->Painter->setPen(pl->style);
00055     p->drawLine(cx+pl->x1, cy-pl->y1, cx+pl->x2, cy-pl->y2);
00056   }
00057 
00058   if(x1 > 0) {  // paint scroll bar ?
00059     int   x, y, dx, dy;
00060     QPolygon Points;
00061     y = y2 - 20;
00062     // draw scroll bar
00063     int by = cy-y + yAxis.numGraphs;
00064     p->fillRect(cx-14, by+1, 12, zAxis.numGraphs-1, QColor(192, 192, 192));
00065 
00066     // draw frame for scroll bar
00067     p->Painter->setPen(QPen(Qt::black,0));
00068     p->drawLine(cx-17, cy-y2, cx-17, cy);
00069     p->drawLine(cx-17, cy-y2, cx, cy-y2);
00070     p->drawLine(cx-17, cy, cx, cy);
00071     y += 2;
00072     p->drawLine(cx-17, cy-y, cx, cy-y);
00073     y -= y2;
00074     p->drawLine(cx-17, cy+y, cx, cy+y);
00075 
00076     // draw the arrows above and below the scroll bar
00077     p->Painter->setBrush(QColor(192, 192, 192));
00078     p->Painter->setPen(QColor(152, 152, 152));
00079     p->drawLine(cx-2, by, cx-2, by + zAxis.numGraphs);
00080     p->drawLine(cx-15, by + zAxis.numGraphs, cx-2, by + zAxis.numGraphs);
00081 
00082     p->map(cx-14, cy-y2+3, x, y);
00083     p->map(cx-3,  cy-y2+14, dx, dy);
00084     Points.setPoints(3, x, dy, (x+dx)>>1, y, dx, dy);
00085     p->Painter->drawConvexPolygon(Points);
00086     p->Painter->setPen(QColor(224, 224, 224));
00087     p->Painter->drawLine(x, dy, (x+dx)>>1, y);
00088     p->drawLine(cx-15, by, cx-2, by);
00089     p->drawLine(cx-15, by, cx-15, by + zAxis.numGraphs);
00090 
00091     p->Painter->setPen(QColor(152, 152, 152));
00092     dy -= y;
00093     p->map(cx-14,  cy-3, x, y);
00094     Points.setPoints(3, x, y-dy, (x+dx)>>1, y, dx, y-dy);
00095     p->Painter->drawConvexPolygon(Points);
00096     p->Painter->setPen(QColor(208, 208, 208));
00097     p->Painter->drawLine(x, y-dy, (x+dx)>>1, y);
00098     p->Painter->setPen(QColor(224, 224, 224));
00099     p->Painter->drawLine(x, y-dy, dx, y-dy);
00100 
00101     p->Painter->setBrush(QBrush(Qt::NoBrush));
00102   }
00103 
00104 
00105   p->Painter->setPen(Qt::black);
00106   // write whole text
00107   foreach(Text *pt, Texts)
00108     p->drawText(pt->s, cx+pt->x, cy-pt->y);
00109 
00110 
00111   if(isSelected) {
00112     p->Painter->setPen(QPen(Qt::darkGray,3));
00113     p->drawRect(cx-5, cy-y2-5, x2+10, y2+10);
00114     p->Painter->setPen(QPen(Qt::darkRed,2));
00115     p->drawResizeRect(cx, cy-y2);  // markers for changing the size
00116     p->drawResizeRect(cx, cy);
00117     p->drawResizeRect(cx+x2, cy-y2);
00118     p->drawResizeRect(cx+x2, cy);
00119   }
00120 }
00121 
00122 // ------------------------------------------------------------
00123 // calculates the text in the tabular
00124 int TabDiagram::calcDiagram()
00125 {
00126   Lines.clear();
00127   Texts.clear();
00128   Arcs.clear();
00129 
00130   x1 = 0;  // no scroll bar
00131   x3 = x2;
00132   // get size of text using the screen-compatible metric
00133   QFontMetrics metrics(QucsSettings.font, 0);
00134   int tHeight = metrics.lineSpacing();
00135   QString Str;
00136   int colWidth=0, x=8, y;
00137 
00138   if(y2 < (41 + MIN_SCROLLBAR_SIZE))
00139     y2 = 41 + MIN_SCROLLBAR_SIZE;
00140 
00141   if(y2 < (tHeight + 8))
00142     y2 = tHeight + 8;
00143   y = y2 - tHeight - 6;
00144 
00145   // outer frame
00146   Lines.append(new Line(0, y2, x2, y2, QPen(Qt::black,0)));
00147   Lines.append(new Line(0, y2, 0, 0, QPen(Qt::black,0)));
00148   Lines.append(new Line(x2, y2, x2, 0, QPen(Qt::black,0)));
00149   Lines.append(new Line(0, 0, x2, 0, QPen(Qt::black,0)));
00150   Lines.append(new Line(0, y+2, x2, y+2, QPen(Qt::black,2)));
00151 
00152   if(xAxis.limit_min < 0.0)
00153     xAxis.limit_min = 0.0;
00154 
00155   Graph *firstGraph;
00156 
00157   QListIterator<Graph *> ig(Graphs);
00158   Graph *g = 0;
00159   if (ig.hasNext()) // point to first graph
00160     g = ig.next();
00161 
00162   if(g == 0) {  // no variables specified in diagram ?
00163     Str = QObject::tr("no variables");
00164     colWidth = checkColumnWidth(Str, metrics, colWidth, x, y2);
00165     if(colWidth >= 0)
00166       Texts.append(new Text(x-4, y2-2, Str)); // independent variable
00167     return 0;
00168   }
00169 
00170   int NumAll=0;   // how many numbers per column
00171   int NumLeft=0;  // how many numbers could not be written
00172 
00173   double *py, *px;
00174   int counting, invisibleCount=0;
00175   int startWriting, lastCount = 1;
00176 
00177   // any graph with data ?
00178   while(g->isEmpty()) {
00179     if (!ig.hasNext()) break; // no more graphs
00180     g = ig.next(); // point to next graph
00181   }
00182 
00183   if(!g->isEmpty()) { // did we find a graph with data ?
00184     // ................................................
00185     counting = g->axis(0)->count * g->countY;  // number of values
00186     NumAll = counting;
00187     
00188     invisibleCount = counting - y/tHeight;
00189     if(invisibleCount <= 0)  xAxis.limit_min = 0.0;// height bigger than needed
00190     else {
00191       NumLeft = invisibleCount - int(xAxis.limit_min + 0.5);
00192       if(invisibleCount < int(xAxis.limit_min + 0.5))
00193   xAxis.limit_min = double(invisibleCount); // adjust limit of scroll bar
00194     }
00195     
00196     for(int h = g->numAxes(); h>0;){
00197     DataX const *pD = g->axis(--h); // BUG
00198       colWidth = 0;
00199       Str = pD->Var;
00200       colWidth = checkColumnWidth(Str, metrics, colWidth, x, y2);
00201       if(colWidth < 0)  goto funcEnd;
00202       startWriting = int(xAxis.limit_min + 0.5);  // when to reach visible area
00203       
00204       Texts.append(new Text(x-4, y2-2, Str)); // independent variable
00205       if(pD->count != 0) {
00206   y = y2-tHeight-5;
00207   counting /= pD->count;   // how many rows to be skipped
00208   for(int z1=0; z1<lastCount; z1++) {
00209     px = pD->Points;
00210     for(int z=pD->count; z>0; z--) {
00211       if(startWriting <= 0) { // reached visible area ?
00212         y += tHeight*startWriting;
00213         startWriting = 0;
00214         if(y < tHeight) break;  // no room for more rows ?
00215         Str = misc::StringNum(*px, 'g', g->Precision);
00216         colWidth = checkColumnWidth(Str, metrics, colWidth, x, y);
00217         if(colWidth < 0)  goto funcEnd;
00218         
00219         Texts.append(new Text( x, y, Str));
00220         y -= tHeight*counting;
00221       }
00222       else startWriting -= counting;
00223       px++;
00224     }
00225     if(pD == g->axis(0))   // only paint one time
00226       if(y >= tHeight) if(y < y2-tHeight-5)
00227         Lines.append(new Line(0, y+1, x2, y+1, QPen(Qt::black,0)));
00228   }
00229   lastCount *= pD->count;
00230       }
00231       x += colWidth+15;
00232       Lines.append(new Line(x-8, y2, x-8, 0, QPen(Qt::black,0)));
00233     }
00234     Lines.last()->style = QPen(Qt::black,2);
00235   }  // of "if no data in graphs"
00236 
00237   
00238   firstGraph = g;
00239   // ................................................
00240   // all dependent variables
00241   foreach(Graph *g, Graphs) {
00242     y = y2-tHeight-5;
00243     colWidth = 0;
00244 
00245     Str = g->Var;
00246     colWidth = checkColumnWidth(Str, metrics, colWidth, x, y2);
00247     if(colWidth < 0)  goto funcEnd;
00248     Texts.append(new Text(x, y2-2, Str));  // dependent variable
00249 
00250 
00251     startWriting = int(xAxis.limit_min + 0.5); // when to reach visible area
00252     py = g->cPointsY - 2;
00253     if(g->axis(0)) {
00254 
00255       if (!g->cPointsY) {   // no data points
00256   Str = QObject::tr("invalid");
00257   colWidth = checkColumnWidth(Str, metrics, colWidth, x, y);
00258   if(colWidth < 0)  goto funcEnd;
00259   Texts.append(new Text(x, y, Str));
00260       }
00261       else if(sameDependencies(g, firstGraph)) {
00262         int z=g->axis(0)->count * g->countY;
00263         if(z > NumAll)  NumAll = z;
00264 
00265         if(g->Var.right(2) != ".X")
00266           for(; z>0; z--) {
00267             py += 2;
00268             if(startWriting-- > 0) continue; // reached visible area ?
00269             if(y < tHeight) break;           // no room for more rows ?
00270             switch(g->numMode) {
00271               case 0: Str = misc::complexRect(*py, *(py+1), g->Precision); break;
00272               case 1: Str = misc::complexDeg (*py, *(py+1), g->Precision); break;
00273               case 2: Str = misc::complexRad (*py, *(py+1), g->Precision); break;
00274             }
00275 
00276             colWidth = checkColumnWidth(Str, metrics, colWidth, x, y);
00277             if(colWidth < 0)  goto funcEnd;
00278 
00279             Texts.append(new Text(x, y, Str));
00280             y -= tHeight;
00281           }
00282 
00283         else {  // digital data
00284           char *pcy = (char*)g->cPointsY;
00285           for(; z>0; z--) {
00286             if(startWriting-- > 0) {  // reached visible area ?
00287               pcy += strlen(pcy) + 1;
00288               continue;
00289             }
00290             if(y < tHeight) break;           // no room for more rows ?
00291             Str = QString(pcy);
00292 
00293             colWidth = checkColumnWidth(Str, metrics, colWidth, x, y);
00294             if(colWidth < 0)  goto funcEnd;
00295 
00296             Texts.append(new Text(x, y, Str));
00297             pcy += strlen(pcy) + 1;
00298             y -= tHeight;
00299           }
00300         }
00301 
00302         if(z > NumLeft)  NumLeft = z;
00303       }  // of "if(sameDeps)"
00304       else {
00305         Str = QObject::tr("wrong dependency");
00306         colWidth = checkColumnWidth(Str, metrics, colWidth, x, y);
00307         if(colWidth < 0)  goto funcEnd;
00308         Texts.append(new Text(x, y, Str));
00309       }
00310     }
00311     else {   // no data in graph
00312       Str = QObject::tr("no data");
00313       colWidth = checkColumnWidth(Str, metrics, colWidth, x, y);
00314       if(colWidth < 0)  goto funcEnd;
00315       Texts.append(new Text(x, y, Str));
00316     }
00317     x += colWidth+15;
00318     if(g != Graphs.last())   // do not paint last line
00319       Lines.append(new Line(x-8, y2, x-8, 0, QPen(Qt::black,0)));
00320   }
00321 
00322 funcEnd:
00323   if(invisibleCount > 0) {  // could all numbers be written ?
00324     x1 = 18;   // extend the select area to the left
00325 
00326     zAxis.limit_max = double(NumAll);  // number of data (rows) 
00327 
00328     // calculate data for painting scroll bar
00329     y = int(xAxis.limit_min + 0.5);
00330     NumLeft = NumAll - NumLeft - y;
00331 
00332     // position of scroll bar in pixel
00333     yAxis.numGraphs = (y2 - 39) * y / NumAll;
00334 
00335     // height of scroll bar
00336     zAxis.numGraphs = (y2 - 39) * NumLeft / NumAll;
00337     if(zAxis.numGraphs < MIN_SCROLLBAR_SIZE) {
00338       yAxis.numGraphs -= (MIN_SCROLLBAR_SIZE - zAxis.numGraphs + 1)
00339                          * y / NumAll;
00340       zAxis.numGraphs = MIN_SCROLLBAR_SIZE;
00341     }
00342 
00343     xAxis.numGraphs = NumLeft;  // number of lines in the diagram
00344   }
00345 
00346   return 1;
00347 }
00348 
00349 // ------------------------------------------------------------
00350 int TabDiagram::scroll(int clickPos)
00351 {
00352   if(x1 <= 0) return 0;   // no scroll bar ?
00353   int tmp = int(xAxis.limit_min + 0.5);
00354 
00355   int y = cy;
00356   if(clickPos > (cy-20)) {  // scroll one line down ?
00357     xAxis.limit_min++;
00358   }
00359   else {
00360     y -= y2 - 20;
00361     if(clickPos < y) {  // scroll bar one line up ?
00362       if(xAxis.limit_min <= 0.0)  return 0;
00363       xAxis.limit_min--;
00364     }
00365     else {
00366       y += yAxis.numGraphs;
00367       if(clickPos < y)   // scroll bar one page up ?
00368         xAxis.limit_min -= double(xAxis.numGraphs);
00369       else {
00370         y += zAxis.numGraphs;
00371         if(clickPos > y)   // a page down?
00372           xAxis.limit_min += double(xAxis.numGraphs);
00373         else
00374           return 2;  // click on position bar
00375       }
00376     }
00377   }
00378 
00379   calcDiagram();
00380   if(tmp == int(xAxis.limit_min + 0.5))
00381     return 0;   // did anything change ?
00382 
00383   return 1;
00384 }
00385 
00386 // ------------------------------------------------------------
00387 bool TabDiagram::scrollTo(int initial, int, int dy)
00388 {
00389   int tmp = int(xAxis.limit_min + 0.5);
00390   xAxis.limit_min  = double(initial);
00391   xAxis.limit_min += double(dy) / double(y2 - 39) * zAxis.limit_max;
00392   xAxis.limit_min  = floor(xAxis.limit_min + 0.5);
00393 
00394   calcDiagram();
00395   if(tmp == int(xAxis.limit_min + 0.5))
00396     return false;   // did anything change ?
00397 
00398   return true;
00399 }
00400 
00401 // ------------------------------------------------------------
00402 Diagram* TabDiagram::newOne()
00403 {
00404   return new TabDiagram();
00405 }
00406 
00407 // ------------------------------------------------------------
00408 Element* TabDiagram::info(QString& Name, char* &BitmapFile, bool getNewOne)
00409 {
00410   Name = QObject::tr("Tabular");
00411   BitmapFile = (char *) "tabular";
00412 
00413   if(getNewOne)  return new TabDiagram();
00414   return 0;
00415 }
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines