Qucs-GUI
0.0.19
|
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 }