00001
00002
00003 char *graph_cpp = "$Id: sxy_graph.cpp,v 1.8 2003/04/25 20:21:43 clinio Exp $";
00004
00005
00006
00007 #include <float.h>
00008 #include <stdlib.h>
00009
00010 extern "C" {
00011 #include <iup.h>
00012 #include <cd.h>
00013 #include <cdiup.h>
00014 #include <cdps.h>
00015 #ifdef WIN32
00016 #include <cdprint.h>
00017 #include <cdclipbd.h>
00018 #endif
00019 }
00020
00021 #include "sxy_graph.h"
00022 #include "sxy_task.h"
00023 #include "sxy_chart.h"
00024 #include "sxy_axis.h"
00025 #include "sxy_utils.h"
00026
00027
00028
00029 #define GRAPH_ATTR_NAME "GRAPH_POINTER"
00030 #define MAX_CHARTS 10
00031 #define MAX_TASKS 64
00032
00033
00034
00035
00036
00039 SXYGraph::SXYGraph(Ihandle* iupcnv) : iup_canvas(iupcnv) {
00040
00041
00042 assert(iupcnv);
00043 IupMap(IupGetDialog(iupcnv));
00044
00045
00046 charts_vector = new SXYVector<SXYChart*>(MAX_CHARTS, NULL);
00047 tasks_vector = new SXYVector<SXYTask*>(MAX_TASKS, NULL);
00048
00049
00050 cd_canvas = cdCreateCanvas(CD_IUP, iup_canvas);
00051 assert(cd_canvas);
00052
00053
00054
00055 IupSetAttribute(iup_canvas, IUP_ACTION, "iupActionCallback");
00056 IupSetAttribute(iup_canvas, IUP_BUTTON_CB, "iupButtonCallback");
00057 IupSetAttribute(iup_canvas, IUP_MOTION_CB, "iupMotionCallback");
00058 IupSetAttribute(iup_canvas, IUP_RESIZE_CB, "iupResizeCallback");
00059 IupSetAttribute(iup_canvas, IUP_ENTERWINDOW_CB , "iupEnterCallback");
00060 IupSetAttribute(iup_canvas, IUP_LEAVEWINDOW_CB , "iupLeaveCallback");
00061
00062 IupSetFunction("iupActionCallback", (Icallback)SXYGraph::iupActionCallback);
00063 IupSetFunction("iupButtonCallback", (Icallback)SXYGraph::iupButtonCallback);
00064 IupSetFunction("iupMotionCallback", (Icallback)SXYGraph::iupMotionCallback);
00065 IupSetFunction("iupResizeCallback", (Icallback)SXYGraph::iupResizeCallback);
00066 IupSetFunction("iupEnterCallback", (Icallback)SXYGraph::iupEnterCallback);
00067 IupSetFunction("iupLeaveCallback", (Icallback)SXYGraph::iupLeaveCallback);
00068
00069
00070
00071
00072 IupSetAttribute(iup_canvas, GRAPH_ATTR_NAME, (char*)this);
00073 }
00074
00075
00076
00078 SXYGraph::~SXYGraph() {
00079
00080 if (charts_vector) delete charts_vector;
00081 charts_vector = NULL;
00082
00083 if (tasks_vector) delete tasks_vector;
00084 tasks_vector = NULL;
00085
00086
00087 cdKillCanvas(cd_canvas);
00088 cd_canvas = NULL;
00089 }
00090
00091
00092
00095 cdCanvas* SXYGraph::getCdCanvas(void) {
00096 return cd_canvas;
00097 }
00098
00099
00100
00103 Ihandle* SXYGraph::getIupCanvas(void) {
00104 return iup_canvas;
00105 }
00106
00107
00108
00109 int SXYGraph::getDeviceSizeMM(double& w, double& h) {
00110 double ww, hh;
00111 cdCanvas* cd = getCdCanvas();
00112 assert(cd);
00113 if (cdActivate(cd) == CD_ERROR) return 0;
00114 cdGetCanvasSize( NULL, NULL, &ww, &hh );
00115 w = ww; h = hh;
00116 return 1;
00117 }
00118
00119
00120
00121 void SXYGraph::fitAllAxis(SXYAxisOrientation orientation) {
00122 int ncharts = getNumCharts();
00123 double min = FLT_MAX, max = -FLT_MAX;
00124 int i;
00125
00126 for (i = 0; i < ncharts; i++) {
00127 SXYChart* cht = getChart(i);
00128 if (cht) {
00129 int nxaxes = cht->getNumAxes(orientation);
00130 for (int j = 0; j < nxaxes; j++)
00131 {
00132 SXYAxis* ax = cht->getAxis(orientation, j);
00133 double tmin, tmax;
00134 ax->getScales(tmin, tmax);
00135 if (tmin < min) min = tmin;
00136 if (tmax > max) max = tmax;
00137 }
00138 }
00139 }
00140
00141 SXYUtil::calcZoomOut(min, max);
00142
00143 for (i = 0; i < ncharts; i++) {
00144 SXYChart* cht = getChart(i);
00145 if (cht) cht->setAllAxis(orientation, min, max);
00146 }
00147 }
00148
00149
00150
00151 void SXYGraph::fitScales(SXYGraphFitOption opt) {
00152
00153
00154
00155 switch(opt) {
00156 case ALL_X: {
00157 int ncharts = getNumCharts();
00158 for (int i = 0; i < ncharts; i++) {
00159 SXYChart* cht = getChart(i);
00160 if (cht) cht->fitScale(HORIZONTAL_AXIS);
00161 }
00162 fitAllAxis(HORIZONTAL_AXIS);
00163 break;
00164 }
00165 case ALL_Y: {
00166 int ncharts = getNumCharts();
00167 for (int i = 0; i < ncharts; i++) {
00168 SXYChart* cht = getChart(i);
00169 if (cht) cht->fitScale(VERTICAL_AXIS);
00170 }
00171 fitAllAxis(VERTICAL_AXIS);
00172 break;
00173 }
00174 case INDIVIDUAL_X: {
00175 int ncharts = getNumCharts();
00176 for (int i = 0; i < ncharts; i++) {
00177 SXYChart* cht = getChart(i);
00178 if (cht) cht->fitScale(HORIZONTAL_AXIS);
00179 }
00180 break;
00181 }
00182 case INDIVIDUAL_Y: {
00183 int ncharts = getNumCharts();
00184 for (int i = 0; i < ncharts; i++) {
00185 SXYChart* cht = getChart(i);
00186 if (cht) cht->fitScale(VERTICAL_AXIS);
00187 }
00188 break;
00189 }
00190 }
00191 }
00192
00193
00194
00195 void SXYGraph::setZoom(double xratio, double yratio) {
00196
00197 int ncharts = getNumCharts();
00198 for (int i = 0; i < ncharts; i++) {
00199 SXYChart* cht = getChart(i);
00200 if (cht) cht->setZoom(xratio, yratio);
00201 }
00202 }
00203
00204
00205
00206 void SXYGraph::drawChartsAt(cdCanvas* cnv, SXYGraphDoubleBufferMode mode) {
00207
00208 assert(cnv != NULL);
00209
00210
00211 if (cdActivate(cnv) == CD_ERROR) {
00212 IupMessage( "Erro interno", "Falha de desenho do gráfico!" );
00213 return;
00214 }
00215
00216
00217 int ncharts = getNumCharts();
00218 for (int i = 0; i < ncharts; i++) {
00219 SXYChart* cht = getChart(i);
00220 if (cht) cht->repaintChart(cnv, mode);
00221 }
00222
00223
00224 activateDisplayCanvas();
00225 }
00226
00227
00228
00229 void SXYGraph::redrawGraph(void) {
00230 assert(cd_canvas);
00231 drawChartsAt(cd_canvas, WITH_DOUBLE_BUFFER);
00232 cdFlush();
00233 }
00234
00235
00236
00237 void SXYGraph::copyGraph(int width, int height) {
00238 #ifdef WIN32
00239 cdCanvas* clipboard_canvas = NULL;
00240 static char buffer[64];
00241 sprintf(buffer, "%dx%d", width, height);
00242 clipboard_canvas = cdCreateCanvas(CD_CLIPBOARD, buffer);
00243 if (clipboard_canvas == NULL) {
00244 fprintf( stderr, "No clipboard_canvas created for copyGraph()\n");
00245 return;
00246 }
00247 drawChartsAt(clipboard_canvas, WITHOUT_DOUBLE_BUFFER);
00248 cdKillCanvas(clipboard_canvas);
00249 #endif
00250 redrawGraph();
00251 }
00252
00253
00254
00255 void SXYGraph::printGraph(int ask, char* ps_cmd) {
00256 cdCanvas* printer_canvas = NULL;
00257 #ifdef WIN32
00258 ps_cmd = NULL;
00259 if ( ask ) printer_canvas = cdCreateCanvas( CD_PRINTER, "SXY -d" );
00260 else printer_canvas = cdCreateCanvas( CD_PRINTER, "SXY" );
00261
00262 #else
00263 static char buffer[128];
00264 char* filename = tempnam( "/tmp/", "sxy_ps" );
00265 sprintf( buffer, "%s -o -pCD_A4" , filename);
00266 printer_canvas = cdCreateCanvas( CD_PS, buffer );
00267 #endif
00268
00269
00270 if (printer_canvas == NULL) {
00271 fprintf( stderr, "No printer_canvas created for printGraph()\n");
00272 return;
00273 }
00274 drawChartsAt(printer_canvas, WITHOUT_DOUBLE_BUFFER);
00275 cdKillCanvas(printer_canvas);
00276
00277 #ifdef WIN32
00278 #else
00279 if (ps_cmd != NULL)
00280 { sprintf(buffer, ps_cmd, filename);
00281 system(buffer);
00282 }
00283 #endif
00284 redrawGraph();
00285 }
00286
00287
00288
00289 SXYTask* SXYGraph::getTask(int i) {
00290 assert(tasks_vector != NULL);
00291 return tasks_vector->getElement(i);
00292 }
00293
00294
00295
00296 int SXYGraph::getNumTasks(void) {
00297 if (tasks_vector == NULL) return 0;
00298 return tasks_vector->getLength();
00299 }
00300
00301
00302
00303 void SXYGraph::insertTask(SXYTask* tsk) {
00304 assert(tasks_vector != NULL);
00305 tasks_vector->insertElement(tsk);
00306 }
00307
00308
00309
00310 void SXYGraph::removeTask(SXYTask* tsk) {
00311 assert(tasks_vector != NULL);
00312 tasks_vector->removeElement(tsk);
00313 }
00314
00315
00316
00317 SXYChart* SXYGraph::getChart(int i) {
00318 assert(charts_vector != NULL);
00319 return charts_vector->getElement(i);
00320 }
00321
00322
00323
00324 int SXYGraph::getNumCharts(void) {
00325 if (charts_vector == NULL) return 0;
00326 return charts_vector->getLength();
00327 }
00328
00329
00330
00331 void SXYGraph::insertChart(SXYChart* cht) {
00332 assert(charts_vector != NULL);
00333 charts_vector->insertElement(cht);
00334 }
00335
00336
00337
00338 void SXYGraph::removeChart(SXYChart* cht) {
00339 assert(charts_vector != NULL);
00340 charts_vector->removeElement(cht);
00341 }
00342
00343
00344
00345 void SXYGraph::setStandartTasks(void) {
00346 this->insertTask(SXYTask::DEFAULT_MOVE_POINT_TASK);
00347 this->insertTask(SXYTask::DEFAULT_MOVE_LEGEND_TASK);
00348 this->insertTask(SXYTask::DEFAULT_ZOOM_IN_TASK);
00349 this->insertTask(SXYTask::DEFAULT_ADJUST_AXIS_TASK);
00350 this->insertTask(SXYTask::DEFAULT_EDIT_TEXT_TASK);
00351 this->insertTask(SXYTask::DEFAULT_CHANGE_COLORS_TASK);
00352 }
00353
00354
00355
00356 void SXYGraph::tryGridAdjust() {
00357 int n = getNumCharts();
00358 while(--n >= 0) {
00359 SXYChart* cht = getChart(n);
00360 assert(cht != NULL);
00361 cht->tryGridAdjust();
00362 }
00363 }
00364
00365
00366
00367
00368
00369
00370
00371 int SXYGraph::getChartOfEvent(int x, int y) {
00372 activateDisplayCanvas();
00373
00374
00375
00376 int ncharts = getNumCharts();
00377 for (int c = 0; c < ncharts; c++) {
00378 SXYChart* cht = getChart(c);
00379 XYCartesian* xycart = cht->getXyGraph();
00380 int bxmin, bymin, bxmax, bymax;
00381 xycart->getViewport(bxmin, bxmax, bymin, bymax);
00382
00383
00384 if (bxmin < x && x < bxmax && bymin < y && y < bymax) return c;
00385 }
00386 return -1;
00387 }
00388
00389
00390
00391 void SXYGraph::activateDisplayCanvas(void) {
00392 assert(cd_canvas);
00393 if (cdActivate(cd_canvas) == CD_ERROR) {
00394 IupMessage( "Erro interno", "Falha na volta de desenho do gráfico!" );
00395 }
00396 }
00397
00398
00399
00400 SXYGraph* SXYGraph::getThis( Ihandle* handle ) {
00401 return (SXYGraph*) IupGetAttribute( handle, GRAPH_ATTR_NAME );
00402 }
00403
00404
00405
00406 int SXYGraph::iupLeaveCallback( Ihandle* h ) {
00407 SXYGraph* graph = getThis( h );
00408
00409 int ntasks = graph->getNumTasks();
00410 for (int t = 0; t < ntasks; t++) {
00411 SXYTask* tsk = graph->getTask(t);
00412 assert (tsk);
00413 if ( tsk->mouseLeave(graph) == CALLBACK_TREATED ) return IUP_DEFAULT;
00414 }
00415
00416 if (graph) graph->mouseLeave();
00417
00418 return IUP_DEFAULT;
00419 }
00420
00421
00422
00423 int SXYGraph::iupEnterCallback( Ihandle* h ) {
00424 SXYGraph* graph = getThis( h );
00425
00426 int ntasks = graph->getNumTasks();
00427 for (int t = 0; t < ntasks; t++) {
00428 SXYTask* tsk = graph->getTask(t);
00429 assert (tsk);
00430 if ( tsk->mouseEnter(graph) == CALLBACK_TREATED ) return IUP_DEFAULT;
00431 }
00432
00433 if (graph) graph->mouseEnter();
00434 return IUP_DEFAULT;
00435 }
00436
00437
00438
00439 int SXYGraph::iupActionCallback( Ihandle* h ) {
00440 SXYGraph* graph = getThis( h );
00441 if (graph) graph->redrawGraph();
00442 return IUP_DEFAULT;
00443 }
00444
00445
00446
00447 int SXYGraph::iupMotionCallback(Ihandle* h, int x, int y, char *r) {
00448 SXYGraph* graph = getThis( h );
00449 if (!graph) return IUP_DEFAULT;
00450
00451 int sft = isshift(r);
00452 int ctr = iscontrol(r);
00453 graph->activateDisplayCanvas();
00454 cdCanvas2Raster( &x, &y );
00455
00456
00457 int ntasks = graph->getNumTasks();
00458 for (int t = 0; t < ntasks; t++) {
00459 SXYTask* tsk = graph->getTask(t);
00460 assert (tsk);
00461 if (tsk->mouseMotion(graph, x, y, sft, ctr) == CALLBACK_TREATED)
00462 return IUP_DEFAULT;
00463 }
00464
00465 graph->mouseMotion(x, y, sft, ctr);
00466 return IUP_DEFAULT;
00467 }
00468
00469
00470
00471 int SXYGraph::iupButtonCallback(Ihandle* h, int b, int e, int x, int y, char *r) {
00472 SXYGraph* graph = getThis( h );
00473 if (!graph) return IUP_DEFAULT;
00474
00475 int sft = isshift(r);
00476 int ctr = iscontrol(r);
00477 int but = (b == IUP_BUTTON1 ? 1 : b == IUP_BUTTON2 ? 2 : 3 );
00478 graph->activateDisplayCanvas();
00479 cdCanvas2Raster( &x, &y );
00480
00481 int ntasks = graph->getNumTasks();
00482 for (int t = 0; t < ntasks; t++) {
00483 SXYTask* tsk = graph->getTask(t);
00484 assert (tsk);
00485 if (e==1) {
00486 if (tsk->mouseClick(graph, but, x, y, sft, ctr) == CALLBACK_TREATED)
00487 return IUP_DEFAULT;
00488 }
00489 else {
00490 if (tsk->mouseUnclick(graph, but, x, y, sft, ctr) == CALLBACK_TREATED)
00491 return IUP_DEFAULT;
00492 }
00493 }
00494
00495 if (e==1) graph->mouseClick(but, x, y, sft, ctr);
00496 else graph->mouseUnclick(but, x, y, sft, ctr);
00497
00498
00499 return IUP_DEFAULT;
00500 }
00501
00502
00503
00504 int SXYGraph::iupResizeCallback( Ihandle* h, int width, int height ) {
00505 SXYGraph* graph = getThis( h );
00506 if (!graph) return IUP_DEFAULT;
00507 graph->activateDisplayCanvas();
00508 return IUP_DEFAULT;
00509 }
00510