TSP: The Transport Sample Protocol



Main Page | Modules | Alphabetical List | Data Structures | File List | Data Fields | Globals | Related Pages

gdisp_plot2Doriginal.c

Go to the documentation of this file.
00001 
00043 /*
00044  * System includes.
00045  */
00046 #include <stdio.h>
00047 #include <stdlib.h>
00048 #include <assert.h>
00049 #include <string.h>
00050 #include <errno.h>
00051 
00052 
00053 /*
00054  * For key manipulation.
00055  */
00056 #include <gdk/gdkkeysyms.h>
00057 
00058 
00059 /*
00060  * GDISP+ includes.
00061  */
00062 #include "gdisp_kernel.h"
00063 #include "gdisp_prototypes.h"
00064 
00065 #include "gdisp_plot2D.h"
00066 
00067 
00068 /*
00069  --------------------------------------------------------------------
00070                              STATIC ROUTINES
00071  --------------------------------------------------------------------
00072 */
00073 
00074 #undef DEBUG_2D
00075 
00076 #define EVENT_METHOD(widget,event) \
00077         GTK_WIDGET_CLASS(GTK_OBJECT(widget)->klass)->event
00078 
00079 #define X_WIN_TO_PLOT(plot,x) (x)
00080 #define Y_WIN_TO_PLOT(plot,y) ((plot)->p2dAreaHeight - (y))
00081 
00082 #define X_PLOT_TO_WIN(plot,x) (x)
00083 #define Y_PLOT_TO_WIN(plot,y) ((plot)->p2dAreaHeight - (y))
00084 
00085 #define Y_SYMBOL_OFFSET 15
00086 
00087 
00088 /*
00089  * Are the drop coordinates inside the X zone ?
00090  * 'x' and 'y' are in plot coordinates.
00091  */
00092 static gboolean
00093 gdisp_isInsideXZone (Plot2D_T *plot,
00094                      guint     x,
00095                      guint     y)
00096 {
00097 
00098   /*
00099    * Y
00100    * |       Y zone
00101    * |
00102    * | /--------------------
00103    * |/        X zone
00104    * +-----------------------> X
00105    *
00106    */
00107 
00108   guint coefficient = 5; /* 20 % */
00109 
00110   /*
00111    * Apply filter.
00112    */
00113   if (x < plot->p2dAreaWidth / coefficient) {
00114 
00115     if (y < (plot->p2dAreaHeight * x / plot->p2dAreaWidth)) {
00116 
00117       return TRUE;
00118 
00119     }
00120 
00121   }
00122   else {
00123 
00124     if (y < plot->p2dAreaHeight / coefficient) {
00125 
00126       return TRUE;
00127 
00128     }
00129 
00130   }
00131 
00132   return FALSE;
00133 
00134 }
00135 
00136 
00137 /*
00138  * Function in order to sort symbols alphabetically' when inserting
00139  * them into the double-linked list.
00140  */
00141 static gint
00142 gdisp_sortSymbolByName(gconstpointer data1,
00143                        gconstpointer data2)
00144 {
00145 
00146   Symbol_T *symbol1 = (Symbol_T*)data1,
00147            *symbol2 = (Symbol_T*)data2;
00148 
00149   return (strcmp(symbol1->sInfo.name,symbol2->sInfo.name));
00150 
00151 }
00152 
00153 
00154 /*
00155  * Copy back buffer into graphic area (front buffer).
00156  */
00157 static void
00158 gdisp_plot2DSwapBuffers (Kernel_T *kernel,
00159                          Plot2D_T *plot)
00160 {
00161 
00162 #if defined(DEBUG_2D)
00163   fprintf(stdout,"Swaping front and back buffers.\n");
00164   fflush (stdout);
00165 #endif
00166 
00167   /*
00168    * Copy back buffer into front buffer.
00169    */
00170   gdk_draw_pixmap(plot->p2dArea->window,
00171                   plot->p2dGContext,
00172                   plot->p2dBackBuffer,
00173                   0,
00174                   0,
00175                   0,
00176                   0,
00177                   plot->p2dArea->allocation.width,
00178                   plot->p2dArea->allocation.height);
00179 
00180 }
00181 
00182 
00183 /*
00184  * Redraw back buffer content.
00185  */
00186 static void
00187 gdisp_plot2DDrawBackBuffer (Kernel_T *kernel,
00188                             Plot2D_T *plot)
00189 {
00190 
00191   GList    *symbolItem =    (GList*)NULL;
00192   Symbol_T *symbol     = (Symbol_T*)NULL;
00193   guint     xPosition  =               0;
00194   guint     yPosition  =               0;
00195   gint      lBearing   =               0;
00196   gint      rBearing   =               0;
00197   gint      width      =               0;
00198   gint      ascent     =               0;
00199   gint      descent    =               0;
00200   GdkColor *backColor  = (GdkColor*)NULL;
00201   GdkColor *xAreaColor = (GdkColor*)NULL;
00202   GdkPoint  xPolygon[4];
00203 
00204 
00205 #if defined(DEBUG_2D)
00206   fprintf(stdout,"Drawing into back buffer.\n");
00207   fflush (stdout);
00208 #endif
00209 
00210   /*
00211    * By now, just paint a rectangle according to focus.
00212    */
00213   if (plot->p2dHasFocus == TRUE) {
00214 
00215     backColor  = &kernel->colors[155];
00216     xAreaColor = &kernel->colors[154];
00217 
00218   }
00219   else {
00220 
00221     backColor  = &kernel->colors[150];
00222     xAreaColor = &kernel->colors[150];
00223 
00224   }
00225 
00226   gdk_gc_set_foreground(plot->p2dGContext,
00227                         backColor);
00228 
00229   gdk_draw_rectangle(plot->p2dBackBuffer,
00230                      plot->p2dGContext,
00231                      TRUE, /* rectangle is filled */
00232                      0,
00233                      0,
00234                      plot->p2dArea->allocation.width,
00235                      plot->p2dArea->allocation.height);
00236 
00237 
00238   /*
00239    * X area.
00240    */
00241   gdk_gc_set_foreground(plot->p2dGContext,
00242                         xAreaColor);
00243 
00244   xPolygon[0].x = X_PLOT_TO_WIN(plot,0                      );
00245   xPolygon[0].y = Y_PLOT_TO_WIN(plot,0                      );
00246   
00247   xPolygon[1].x = X_PLOT_TO_WIN(plot,plot->p2dAreaWidth  / 5);
00248   xPolygon[1].y = Y_PLOT_TO_WIN(plot,plot->p2dAreaHeight / 5);
00249 
00250   xPolygon[2].x = X_PLOT_TO_WIN(plot,plot->p2dAreaWidth     );
00251   xPolygon[2].y = Y_PLOT_TO_WIN(plot,plot->p2dAreaHeight / 5);
00252 
00253   xPolygon[3].x = X_PLOT_TO_WIN(plot,plot->p2dAreaWidth     );
00254   xPolygon[3].y = Y_PLOT_TO_WIN(plot,0                      );
00255 
00256   gdk_draw_polygon(plot->p2dBackBuffer,
00257                    plot->p2dGContext,
00258                    TRUE, /* filled */
00259                    xPolygon,
00260                    sizeof(xPolygon) / sizeof(xPolygon[0]));
00261 
00262   /*
00263    * Symbol list attached to the X axis.
00264    */
00265   gdk_gc_set_foreground(plot->p2dGContext,
00266                         &kernel->colors[42]);
00267 
00268   xPosition = plot->p2dAreaWidth  - Y_SYMBOL_OFFSET;
00269   yPosition = plot->p2dAreaHeight - Y_SYMBOL_OFFSET;
00270 
00271   symbolItem = g_list_first(plot->p2dXSymbolList);
00272   if (symbolItem != (GList*)NULL) {
00273 
00274     symbol = (Symbol_T*)symbolItem->data;
00275 
00276     xPosition -= gdk_string_width(plot->p2dFont,
00277                                   symbol->sInfo.name);
00278 
00279     gdk_draw_string(plot->p2dBackBuffer,
00280                     plot->p2dFont,
00281                     plot->p2dGContext,
00282                     xPosition,
00283                     yPosition,
00284                     symbol->sInfo.name);
00285 
00286   }
00287 
00288   /*
00289    * Symbol list attached to the Y axis.
00290    */
00291   gdk_gc_set_foreground(plot->p2dGContext,
00292                         &kernel->colors[42 /* black */]);
00293 
00294   xPosition = Y_SYMBOL_OFFSET;
00295   yPosition = Y_SYMBOL_OFFSET;
00296 
00297   symbolItem = g_list_first(plot->p2dYSymbolList);
00298   while (symbolItem != (GList*)NULL) {
00299 
00300     symbol = (Symbol_T*)symbolItem->data;
00301 
00302     gdk_draw_string(plot->p2dBackBuffer,
00303                     plot->p2dFont,
00304                     plot->p2dGContext,
00305                     xPosition,
00306                     yPosition,
00307                     symbol->sInfo.name);
00308 
00309     /*
00310      * Underline selected symbol.
00311      */
00312     if (symbolItem == plot->p2dSelectedSymbol) {
00313 
00314       gdk_string_extents(plot->p2dFont,
00315                          symbol->sInfo.name,
00316                          &lBearing,
00317                          &rBearing,
00318                          &width,
00319                          &ascent,
00320                          &descent);
00321 
00322       gdk_draw_line(plot->p2dBackBuffer,
00323                     plot->p2dGContext,
00324                     xPosition,                /* x1 */
00325                     yPosition + descent,      /* y1 */
00326                     xPosition + width,        /* x2 */
00327                     yPosition + descent);     /* y2 */
00328 
00329     }
00330 
00331     yPosition += Y_SYMBOL_OFFSET;
00332 
00333     symbolItem = g_list_next(symbolItem);
00334 
00335   }
00336 
00337   /*
00338    * Black lines around the graphic area.
00339    */
00340   gdk_gc_set_foreground(plot->p2dGContext,
00341                         &kernel->colors[42 /* black */]);
00342 
00343   gdk_draw_line(plot->p2dBackBuffer,
00344                 plot->p2dGContext,
00345                 0,                                   /* x1 */
00346                 0,                                   /* y1 */
00347                 plot->p2dArea->allocation.width - 1, /* x2 */
00348                 0);                                  /* y2 */
00349 
00350   gdk_draw_line(plot->p2dBackBuffer,
00351                 plot->p2dGContext,
00352                 plot->p2dArea->allocation.width  - 1,  /* x1 */
00353                 0,                                     /* y1 */
00354                 plot->p2dArea->allocation.width  - 1,  /* x2 */
00355                 plot->p2dArea->allocation.height - 1); /* y2 */
00356 }
00357 
00358 
00359 /*
00360  * Treat 'expose' X event.
00361  * What shall I do when the graphic area has to be refreshed ?
00362  */
00363 static gboolean
00364 gdisp_plot2DExpose (GtkWidget       *area,
00365                     GdkEventExpose  *event,
00366                     gpointer         data)
00367 {
00368 
00369   Kernel_T *kernel = (Kernel_T*)data;
00370   Plot2D_T *plot   = (Plot2D_T*)NULL;
00371 
00372   /*
00373    * Graphic area has now to be repainted.
00374    */
00375   plot = (Plot2D_T*)gtk_object_get_data(GTK_OBJECT(area),
00376                                         "plotPointer");
00377 
00378 #if defined(DEBUG_2D)
00379   fprintf(stdout,"Expose event\n");
00380   fflush (stdout);
00381 #endif
00382 
00383   gdk_gc_set_clip_rectangle(plot->p2dGContext,
00384                             &event->area);
00385 
00386   gdisp_plot2DSwapBuffers(kernel,plot);
00387 
00388   gdk_gc_set_clip_rectangle(plot->p2dGContext,
00389                             (GdkRectangle*)NULL);
00390 
00391   return TRUE;
00392 
00393 }
00394 
00395 
00396 /*
00397  * Treat 'configure' X event.
00398  * What shall I do when the graphic area has to be re-configured ?
00399  */
00400 static gboolean
00401 gdisp_plot2DConfigure (GtkWidget         *area,
00402                        GdkEventConfigure *event,
00403                        gpointer           data)
00404 {
00405 
00406   Kernel_T *kernel        = (Kernel_T*)data;
00407   Plot2D_T *plot          = (Plot2D_T*)NULL;
00408 
00409 
00410   /*
00411    * Get plot private data.
00412    */
00413   plot = (Plot2D_T*)gtk_object_get_data(GTK_OBJECT(area),
00414                                         "plotPointer");
00415 
00416 #if defined(DEBUG_2D)
00417   fprintf(stdout,"Configure event.\n");
00418   fflush (stdout);
00419 #endif
00420 
00421   /*
00422    * Don't know why, but GTK generates a 'configure' event when
00423    * showing widgets before returning into the main X loop. Strange.
00424    */
00425   if (event->width == 1 && event->height == 1) {
00426 
00427 #if defined(DEBUG_2D)
00428     fprintf(stdout,"Configure event returns suddendly.\n");
00429     fflush (stdout);
00430 #endif
00431 
00432     return TRUE;
00433 
00434   }
00435 
00436 
00437   /*
00438    * Graphic area has now to be resized
00439    */
00440   plot->p2dAreaWidth  = event->width;
00441   plot->p2dAreaHeight = event->height;
00442 
00443 
00444   /*
00445    * Some difficulties to create the back buffer in the 'create' procedure,
00446    * because some window information are not yet available.
00447    * So create it here.
00448    */
00449   if (plot->p2dBackBuffer != (GdkPixmap*)NULL) {
00450 
00451     gdk_pixmap_unref(plot->p2dBackBuffer);
00452 
00453   }
00454 
00455 
00456   /*
00457    * Create a pixmap for double buffering.
00458    * Deduce depth from graphic area window.
00459    */
00460 #if defined(DEBUG_2D)
00461   fprintf(stdout,"Creating back buffer.\n");
00462   fflush (stdout);
00463 #endif
00464 
00465   plot->p2dBackBuffer = gdk_pixmap_new(plot->p2dArea->window,
00466                                        plot->p2dAreaWidth,
00467                                        plot->p2dAreaHeight,
00468                                        -1 /* same as window */);
00469 
00470   assert(plot->p2dBackBuffer);
00471 
00472 
00473   /*
00474    * The configure operation is done after a resize request.
00475    * So refresh back buffer.
00476    */
00477   gdisp_plot2DDrawBackBuffer(kernel,plot);
00478 
00479   return TRUE;
00480 
00481 }
00482 
00483 
00484 /*
00485  * Treat 'enter-notify' X event.
00486  * What shall I do when the mouse enters the graphic area ?
00487  */
00488 static gboolean
00489 gdisp_plot2DEnterNotify (GtkWidget        *area,
00490                          GdkEventCrossing *event,
00491                          gpointer          data)
00492 {
00493 
00494   Kernel_T *kernel = (Kernel_T*)data;
00495   Plot2D_T *plot   = (Plot2D_T*)NULL;
00496 
00497   /*
00498    * Graphic area has now the focus.
00499    */
00500   plot = (Plot2D_T*)gtk_object_get_data(GTK_OBJECT(area),
00501                                         "plotPointer");
00502 
00503   plot->p2dHasFocus = TRUE;
00504   gdisp_plot2DDrawBackBuffer(kernel,plot);
00505   gdisp_plot2DSwapBuffers   (kernel,plot);
00506 
00507   return TRUE;
00508 
00509 }
00510 
00511 
00512 /*
00513  * Treat 'leave-notify' X event.
00514  * What shall I do when the mouse leaves the graphic area ?
00515  */
00516 static gboolean
00517 gdisp_plot2DLeaveNotify (GtkWidget        *area,
00518                          GdkEventCrossing *event,
00519                          gpointer          data)
00520 {
00521 
00522   Kernel_T *kernel = (Kernel_T*)data;
00523   Plot2D_T *plot   = (Plot2D_T*)NULL;
00524 
00525   /*
00526    * Graphic area has lost the focus.
00527    */
00528   plot = (Plot2D_T*)gtk_object_get_data(GTK_OBJECT(area),
00529                                         "plotPointer");
00530 
00531   plot->p2dHasFocus = FALSE;
00532   gdisp_plot2DDrawBackBuffer(kernel,plot);
00533   gdisp_plot2DSwapBuffers   (kernel,plot);
00534 
00535   return TRUE;
00536 
00537 }
00538 
00539 
00540 /*
00541  * Treat 'key-press' X event.
00542  * What shall I do when the user press a key on the graphic area ?
00543  */
00544 #if defined(WAIT_FORT_GTK_BUG_CORRECTION)
00545 
00546 static gboolean
00547 gdisp_plot2DKeyPress (GtkWidget   *area,
00548                       GdkEventKey *event,
00549                       gpointer     data)
00550 {
00551 
00552   Kernel_T *kernel = (Kernel_T*)data;
00553   Plot2D_T *plot   = (Plot2D_T*)NULL;
00554 
00555 
00556   /*
00557    * 'key press' events on a graphic area are not well treated
00558    * in version 1.2 of GTK.
00559    * SORRY.
00560    */
00561 
00562   /*
00563    * Graphic area has lost the focus.
00564    */
00565   plot = (Plot2D_T*)gtk_object_get_data(GTK_OBJECT(area),
00566                                         "plotPointer");
00567 
00568   /*
00569    * Delete all symbols in case of 'c/C' key (clear all),
00570    * or delete one symbol in case of 'd/D' key (delete one).
00571    */
00572   switch (event->keyval) {
00573 
00574   case GDK_c :
00575   case GDK_C :
00576     if (plot->p2dXSymbolList != (GList*)NULL)
00577       g_list_free(plot->p2dXSymbolList);
00578     if (plot->p2dYSymbolList != (GList*)NULL)
00579       g_list_free(plot->p2dYSymbolList);
00580     plot->p2dXSymbolList     = (GList*)NULL;
00581     plot->p2dYSymbolList     = (GList*)NULL;
00582     plot->p2dSelectedSymbol  = (GList*)NULL;
00583     break;
00584 
00585   case GDK_d :
00586   case GDK_D :
00587     if (plot->p2dSelectedSymbol != (GList*)NULL) {
00588       plot->p2dYSymbolList = g_list_remove_link(plot->p2dYSymbolList,
00589                                                 plot->p2dSelectedSymbol);
00590       g_list_free(plot->p2dSelectedSymbol);
00591       plot->p2dSelectedSymbol = (GList*)NULL;
00592     }
00593     break;
00594 
00595   default :
00596     break;
00597 
00598   }
00599 
00600   /*
00601    * Refresh graphic area.
00602    */
00603   gdisp_plot2DDrawBackBuffer(kernel,plot);
00604   gdisp_plot2DSwapBuffers   (kernel,plot);
00605 
00606   return TRUE;
00607 
00608 }
00609 
00610 #endif
00611 
00612 /*
00613  * Treat 'button-press' X event.
00614  * What shall I do when the user press a button on the graphic area ?
00615  */
00616 static gboolean
00617 gdisp_plot2DButtonPress (GtkWidget      *area,
00618                          GdkEventButton *event,
00619                          gpointer        data)
00620 {
00621 
00622   Kernel_T *kernel = (Kernel_T*)data;
00623   Plot2D_T *plot   = (Plot2D_T*)NULL;
00624 
00625 
00626   /*
00627    * Graphic area has lost the focus.
00628    */
00629   plot = (Plot2D_T*)gtk_object_get_data(GTK_OBJECT(area),
00630                                         "plotPointer");
00631 
00632   /*
00633    * Nothing to be done if button identity is not 3.
00634    */
00635   if (event->button != 3) {
00636 
00637     return TRUE;
00638 
00639   }
00640 
00641   /*
00642    * 'button3' removes the selected symbol from the list.
00643    * 'shift' + 'button3' removes all symbols.
00644    */
00645   if (event->state & GDK_SHIFT_MASK) {
00646 
00647     if (plot->p2dXSymbolList != (GList*)NULL)
00648       g_list_free(plot->p2dXSymbolList);
00649 
00650     if (plot->p2dYSymbolList != (GList*)NULL)
00651       g_list_free(plot->p2dYSymbolList);
00652 
00653     plot->p2dXSymbolList     = (GList*)NULL;
00654     plot->p2dYSymbolList     = (GList*)NULL;
00655     plot->p2dSelectedSymbol  = (GList*)NULL;
00656 
00657   }
00658   else {
00659 
00660     if (plot->p2dSelectedSymbol != (GList*)NULL) {
00661 
00662       plot->p2dYSymbolList = g_list_remove_link(plot->p2dYSymbolList,
00663                                                 plot->p2dSelectedSymbol);
00664 
00665       g_list_free(plot->p2dSelectedSymbol);
00666       plot->p2dSelectedSymbol = (GList*)NULL;
00667 
00668     }
00669 
00670   }
00671 
00672   /*
00673    * Refresh graphic area.
00674    */
00675   gdisp_plot2DDrawBackBuffer(kernel,plot);
00676   gdisp_plot2DSwapBuffers   (kernel,plot);
00677 
00678   return TRUE;
00679 
00680 }
00681 
00682 
00683 /*
00684  * Treat 'motion-notify' X event.
00685  * What shall I do when the mouse moves over the graphic area ?
00686  */
00687 static gboolean
00688 gdisp_plot2DMotionNotify (GtkWidget      *area,
00689                           GdkEventMotion *event,
00690                           gpointer        data)
00691 {
00692 
00693   Kernel_T *kernel     = (Kernel_T*)data;
00694   Plot2D_T *plot       = (Plot2D_T*)NULL;
00695 
00696   GList    *symbolItem =    (GList*)NULL;
00697   Symbol_T *symbol     = (Symbol_T*)NULL;
00698   guint     xPosition  =               0;
00699   guint     yPosition  =               0;
00700   gint      lBearing   =               0;
00701   gint      rBearing   =               0;
00702   gint      width      =               0;
00703   gint      ascent     =               0;
00704   gint      descent    =               0;
00705 
00706 #if defined(DEBUG_2D)
00707   fprintf(stdout,"Motion notify event.\n");
00708   fflush (stdout);
00709 #endif
00710 
00711 
00712   /*
00713    * Graphic area has lost the focus.
00714    */
00715   plot = (Plot2D_T*)gtk_object_get_data(GTK_OBJECT(area),
00716                                         "plotPointer");
00717 
00718 
00719   /*
00720    * Return if no symbol available.
00721    */
00722   if (plot->p2dYSymbolList == (GList*)NULL) {
00723 
00724     return TRUE;
00725 
00726   }
00727 
00728   /*
00729    * Take care of hints from X Server.
00730    */
00731   if (event->is_hint) {
00732   
00733     gdk_window_get_pointer(event->window,
00734                            &xPosition,
00735                            &yPosition,
00736                            &event->state);
00737 
00738     event->x = (gdouble)xPosition;
00739     event->y = (gdouble)yPosition;
00740 
00741   }
00742 
00743   /*
00744    * Try to get the symbol the mouse is over.
00745    */
00746   xPosition = Y_SYMBOL_OFFSET;
00747   yPosition = Y_SYMBOL_OFFSET;
00748 
00749   symbolItem = g_list_first(plot->p2dYSymbolList);
00750   while (symbolItem != (GList*)NULL) {
00751 
00752     symbol = (Symbol_T*)symbolItem->data;
00753 
00754     /*
00755      * Compute surrounding rectangle dimensions.
00756      */
00757     gdk_string_extents(plot->p2dFont,
00758                        symbol->sInfo.name,
00759                        &lBearing,
00760                        &rBearing,
00761                        &width,
00762                        &ascent,
00763                        &descent);
00764 
00765     if (xPosition          < event->x && event->x < xPosition + width &&
00766         yPosition - ascent < event->y && event->y < yPosition + descent  ) {
00767 
00768       if (symbolItem != plot->p2dSelectedSymbol) {
00769 
00770         /*
00771          * This symbol becomes the new selected one, refresh graphic area.
00772          */
00773         plot->p2dSelectedSymbol = symbolItem;
00774 
00775         gdisp_plot2DDrawBackBuffer(kernel,plot);
00776         gdisp_plot2DSwapBuffers   (kernel,plot);
00777 
00778       }
00779 
00780       /*
00781        * Stop here investigations, because selected symbol is found.
00782        */
00783       return TRUE;
00784 
00785     } /* Inside rectangle */
00786 
00787     yPosition += Y_SYMBOL_OFFSET;
00788 
00789     symbolItem = g_list_next(symbolItem);
00790 
00791   }
00792 
00793   /*
00794    * No symbol is selected, because the mouse is not inside any rectangle.
00795    * Refresh graphic area.
00796    */
00797   if (plot->p2dSelectedSymbol != (GList*)NULL) {
00798 
00799     plot->p2dSelectedSymbol = (GList*)NULL;
00800 
00801     gdisp_plot2DDrawBackBuffer(kernel,plot);
00802     gdisp_plot2DSwapBuffers   (kernel,plot);
00803 
00804   }
00805 
00806   return TRUE;
00807 
00808 }
00809 
00810 
00811 /*
00812  * Create a '2D plot' by providing an opaque structure to the
00813  * caller. This opaque structure will be given as an argument to all
00814  * plot function. These functions remain generic.
00815  */
00816 static void*
00817 gdisp_createPlot2D (Kernel_T *kernel)
00818 {
00819 
00820 #define FROZEN_RULER
00821 
00822   Plot2D_T *plot = (Plot2D_T*)NULL;
00823 
00824 
00825   /*
00826    * Dynamic allocation.
00827    */
00828   plot = g_malloc0(sizeof(Plot2D_T));
00829   assert(plot);
00830 
00831   /*
00832    * Few initialisations.
00833    */
00834   plot->p2dHasFocus = FALSE;
00835   plot->p2dType     = GD_PLOT_2D_X;
00836 
00837   /*
00838    * Create a table : dimension 2 x 2, homogeneous.
00839    * Insert a graphic area and two rulers in it.
00840    */
00841   plot->p2dTable = gtk_table_new(2,
00842                                  2,
00843                                  FALSE);
00844 
00845   plot->p2dArea = gtk_drawing_area_new();
00846 
00847   gtk_table_attach(GTK_TABLE(plot->p2dTable),
00848                    plot->p2dArea,
00849                    1,
00850                    2,
00851                    0,
00852                    1,
00853                    GTK_EXPAND | GTK_FILL,
00854                    GTK_EXPAND | GTK_FILL,
00855                    0,
00856                    0 );
00857 
00858   gtk_widget_set_events(plot->p2dArea,
00859                         GDK_POINTER_MOTION_MASK      |
00860                         GDK_POINTER_MOTION_HINT_MASK |
00861                         GDK_ENTER_NOTIFY_MASK        |
00862                         GDK_LEAVE_NOTIFY_MASK        |
00863                         GDK_BUTTON_PRESS_MASK          );
00864 
00865   gtk_signal_connect(GTK_OBJECT(plot->p2dArea),
00866                      "expose_event",
00867                      (GtkSignalFunc)gdisp_plot2DExpose,
00868                      (gpointer)kernel);
00869 
00870   gtk_signal_connect (GTK_OBJECT(plot->p2dArea),
00871                       "configure_event",
00872                       (GtkSignalFunc)gdisp_plot2DConfigure,
00873                       (gpointer)kernel); 
00874 
00875   gtk_signal_connect(GTK_OBJECT(plot->p2dArea),
00876                      "enter_notify_event",
00877                      (GtkSignalFunc)gdisp_plot2DEnterNotify,
00878                      (gpointer)kernel);
00879 
00880   gtk_signal_connect(GTK_OBJECT(plot->p2dArea),
00881                      "leave_notify_event",
00882                      (GtkSignalFunc)gdisp_plot2DLeaveNotify,
00883                      (gpointer)kernel);
00884 
00885 #if defined(WAIT_FORT_GTK_BUG_CORRECTION)
00886   gtk_signal_connect(GTK_OBJECT(plot->p2dArea),
00887                      "key_press_event",
00888                      (GtkSignalFunc)gdisp_plot2DKeyPress,
00889                      (gpointer)kernel);
00890 #endif
00891 
00892   gtk_signal_connect(GTK_OBJECT(plot->p2dArea),
00893                      "button_press_event",
00894                      (GtkSignalFunc)gdisp_plot2DButtonPress,
00895                      (gpointer)kernel);
00896 
00897   gtk_signal_connect(GTK_OBJECT(plot->p2dArea),
00898                      "motion_notify_event",
00899                      (GtkSignalFunc)gdisp_plot2DMotionNotify,
00900                      (gpointer)kernel);
00901 
00902   gtk_object_set_data(GTK_OBJECT(plot->p2dArea),
00903                       "plotPointer",
00904                       (gpointer)plot);
00905 
00906   /*
00907    * The horizontal ruler goes on bottom.
00908    * As the mouse moves across the drawing area, a 'motion_notify_event'
00909    * is passed to the appropriate event handler for the ruler.
00910    */
00911   plot->p2dHRuler = gtk_hruler_new();
00912 
00913   gtk_ruler_set_metric(GTK_RULER(plot->p2dHRuler),
00914                        GTK_PIXELS);
00915 
00916   gtk_ruler_set_range(GTK_RULER(plot->p2dHRuler),
00917                       0,
00918                       10,
00919                       0,
00920                       10);
00921 
00922 #if !defined(FROZEN_RULER)
00923   gtk_signal_connect_object(GTK_OBJECT(plot->p2dArea),
00924                             "motion_notify_event",
00925                             (GtkSignalFunc)EVENT_METHOD(plot->p2dHRuler,
00926                                                         motion_notify_event),
00927                             GTK_OBJECT(plot->p2dHRuler));
00928 #endif
00929 
00930 #if defined(FROZEN_RULER)
00931   gtk_widget_set_sensitive(plot->p2dHRuler,
00932                            FALSE /* no sensitive */);
00933 #endif
00934 
00935   gtk_table_attach(GTK_TABLE(plot->p2dTable),
00936                    plot->p2dHRuler,
00937                    1,
00938                    2,
00939                    1,
00940                    2,
00941                    GTK_EXPAND | GTK_SHRINK | GTK_FILL,
00942                    GTK_FILL,
00943                    0,
00944                    0);
00945     
00946   /*
00947    * The vertical ruler goes on the left.
00948    * As the mouse moves across the drawing area, a 'motion_notify_event'
00949    * is passed to the appropriate event handler for the ruler.
00950    */
00951   plot->p2dVRuler = gtk_vruler_new();
00952 
00953   gtk_ruler_set_metric(GTK_RULER(plot->p2dVRuler),
00954                        GTK_PIXELS);
00955 
00956   gtk_ruler_set_range(GTK_RULER(plot->p2dVRuler),
00957                       -10,
00958                       0,
00959                       0,
00960                       10);
00961 
00962 #if !defined(FROZEN_RULER)
00963   gtk_signal_connect_object(GTK_OBJECT(plot->p2dArea),
00964                             "motion_notify_event",
00965                             (GtkSignalFunc)EVENT_METHOD(plot->p2dVRuler,
00966                                                         motion_notify_event),
00967                             GTK_OBJECT(plot->p2dVRuler));
00968 #endif
00969 
00970 #if defined(FROZEN_RULER)
00971   gtk_widget_set_sensitive(plot->p2dVRuler,
00972                            FALSE /* no sensitive */);
00973 #endif
00974 
00975   gtk_table_attach(GTK_TABLE(plot->p2dTable),
00976                    plot->p2dVRuler,
00977                    0,
00978                    1,
00979                    0,
00980                    1,
00981                    GTK_FILL,
00982                    GTK_EXPAND | GTK_SHRINK | GTK_FILL,
00983                    0,
00984                    0);
00985 
00986   /*
00987    * Create a graphic context specific to this plot.
00988    */
00989   plot->p2dGContext =
00990     gdk_gc_new(GTK_WIDGET(kernel->widgets.mainBoardWindow)->window);
00991   plot->p2dFont     = kernel->fonts[GD_FONT_SMALL][GD_FONT_FIXED];
00992 
00993 
00994   /*
00995    * Return the opaque structure.
00996    */
00997   return (void*)plot;
00998 
00999 }
01000 
01001 
01002 /*
01003  * Destroy a '2D' plot opaque structure.
01004  */
01005 static void
01006 gdisp_destroyPlot2D(Kernel_T *kernel,
01007                     void     *data)
01008 {
01009 
01010   Plot2D_T *plot = (Plot2D_T*)data;
01011 
01012   /*
01013    * Free symbol list.
01014    */
01015   g_list_free(plot->p2dXSymbolList);
01016   g_list_free(plot->p2dYSymbolList);
01017 
01018   /*
01019    * Now destroy everything.
01020    */
01021   gdk_gc_destroy    (plot->p2dGContext  );
01022   gdk_pixmap_unref  (plot->p2dBackBuffer);
01023   gtk_widget_destroy(plot->p2dArea      );
01024   gtk_widget_destroy(plot->p2dHRuler    );
01025   gtk_widget_destroy(plot->p2dVRuler    );
01026   gtk_widget_destroy(plot->p2dTable     );
01027 
01028   /*
01029    * Free opaque structure.
01030    */
01031   memset(plot,0,sizeof(Plot2D_T));
01032   g_free(plot);
01033 
01034 }
01035 
01036 
01037 /*
01038  * Record the parent widget.
01039  */
01040 static void
01041 gdisp_setPlot2DParent (Kernel_T  *kernel,
01042                        void      *data,
01043                        GtkWidget *parent)
01044 {
01045 
01046   Plot2D_T *plot = (Plot2D_T*)data;
01047 
01048   /*
01049    * Remember my parent.
01050    */
01051   plot->p2dParent = parent;
01052 
01053 }
01054 
01055 
01056 /*
01057  * Record initial dimensions provided by the calling process.
01058  */
01059 static void
01060 gdisp_setPlot2DInitialDimensions (Kernel_T *kernel,
01061                                   void     *data,
01062                                   guint     width,
01063                                   guint     height)
01064 {
01065 
01066   Plot2D_T *plot = (Plot2D_T*)data;
01067 
01068   /*
01069    * Remember my initial width and height.
01070    */
01071   plot->p2dAreaWidth  = width;
01072   plot->p2dAreaHeight = height;
01073 
01074 }
01075 
01076 
01077 /*
01078  * Give back to the calling process the top level widget
01079  * in order to be inserted in a possible container for further
01080  * dynamic X management.
01081  */
01082 static GtkWidget*
01083 gdisp_getPlot2DTopLevelWidget (Kernel_T  *kernel,
01084                                void      *data)
01085 {
01086 
01087   Plot2D_T *plot = (Plot2D_T*)data;
01088 
01089 #if defined(DEBUG_2D)
01090   fprintf(stdout,"Getting back plot 2D top level widget.\n");
01091   fflush (stdout);
01092 #endif
01093 
01094   return (GtkWidget*)plot->p2dTable;
01095 
01096 }
01097 
01098 
01099 /*
01100  * By now, the '2D plot' widgets are created, but not shown yet.
01101  * Show them here.
01102  */
01103 static void
01104 gdisp_showPlot2D (Kernel_T  *kernel,
01105                   void      *data)
01106 {
01107 
01108   Plot2D_T *plot = (Plot2D_T*)data;
01109 
01110 #if defined(DEBUG_2D)
01111   fprintf(stdout,"Showing plot 2D.\n");
01112   fflush (stdout);
01113 #endif
01114 
01115   /*
01116    * Now show everything.
01117    */
01118   gtk_widget_show(plot->p2dArea  );
01119   gtk_widget_show(plot->p2dHRuler);
01120   gtk_widget_show(plot->p2dVRuler);
01121   gtk_widget_show(plot->p2dTable );
01122 
01123   /*
01124    * These 'show' operations generate 'configure" events. Strange.
01125    */
01126 
01127 }
01128 
01129 
01130 /*
01131  * Return to calling process what king of plot we are.
01132  */
01133 static PlotType_T
01134 gdisp_getPlot2DType (Kernel_T *kernel,
01135                      void     *data)
01136 {
01137 
01138   Plot2D_T *plot = (Plot2D_T*)data;
01139 
01140 #if defined(DEBUG_2D)
01141   fprintf(stdout,"Getting back plot type (2D).\n");
01142 #endif
01143 
01144   /*
01145    * Must be GD_PLOT_2D_X. See 'create' routine.
01146    */
01147   return plot->p2dType;
01148 
01149 }
01150 
01151 
01152 /*
01153  * Record any incoming symbols.
01154  * The drop coordinate (0,0) is at the lower left corner of the graphic area.
01155  */
01156 static void
01157 gdisp_addSymbolsToPlot2D (Kernel_T *kernel,
01158                           void     *data,
01159                           GList    *symbolList,
01160                           guchar    zoneId)
01161 {
01162 
01163   Plot2D_T *plot   = (Plot2D_T*)data;
01164   GList    *symbol =    (GList*)NULL;
01165 
01166 #if defined(DEBUG_2D)
01167   fprintf(stdout,"Adding symbols to plot 2D.\n");
01168   fflush (stdout);
01169 #endif
01170 
01171   /*
01172    * If drop coordinates are in the X zone, the symbol has to be
01173    * attached to the X axis (often time axis).
01174    */
01175   if (gdisp_isInsideXZone(plot,xDrop,yDrop) == TRUE) {
01176 
01177     /*
01178      * Only one symbol on X axis.
01179      * So free previous list and create another one.
01180      */
01181     g_list_free(plot->p2dXSymbolList);
01182     plot->p2dXSymbolList = (GList*)NULL;
01183 
01184     /*
01185      * Take the first symbol of the incoming list.
01186      */
01187     symbol = g_list_first(symbolList);
01188     if (symbol != (GList*)NULL) {
01189 
01190       plot->p2dXSymbolList = g_list_append(plot->p2dXSymbolList,
01191                                            symbol->data);
01192 
01193     }
01194 
01195   }
01196   else {
01197 
01198     /*
01199      * Incoming symbols are to be attached to the Y axis.
01200      */
01201 
01202     /*
01203      * Loop over all incoming symbols and store only those that
01204      * are not already in the final list.
01205      */
01206     symbol = g_list_first(symbolList);
01207     while (symbol != (GList*)NULL) {
01208 
01209       if (g_list_find(plot->p2dYSymbolList,symbol->data) == (GList*)NULL) {
01210 
01211         plot->p2dYSymbolList = g_list_append(plot->p2dYSymbolList,
01212                                              symbol->data);
01213 
01214       }
01215 
01216       symbol = g_list_next(symbol);
01217 
01218     }
01219 
01220     /*
01221      * Sort symbols by name.
01222      */
01223     plot->p2dYSymbolList = g_list_sort(plot->p2dYSymbolList,
01224                                        gdisp_sortSymbolByName);
01225 
01226   }
01227 
01228   /*
01229    * Refresh graphic area only if back buffer exists.
01230    */
01231   if (plot->p2dBackBuffer != (GdkPixmap*)NULL) {
01232 
01233     gdisp_plot2DDrawBackBuffer(kernel,plot);
01234     gdisp_plot2DSwapBuffers   (kernel,plot);
01235 
01236   }
01237 
01238 }
01239 
01240 
01241 /*
01242  * Broadcast all symbols.
01243  */
01244 static GList*
01245 gdisp_getSymbolsFromPlot2D (Kernel_T *kernel,
01246                             void     *data,
01247                             gchar     axis)
01248 {
01249 
01250   Plot2D_T *plot = (Plot2D_T*)data;
01251 
01252 #if defined(DEBUG_2D)
01253   fprintf(stdout,"Give back the list of symbols handled by the plot 2D.\n");
01254   fflush (stdout);
01255 #endif
01256 
01257   switch (axis) {
01258 
01259   case 'X' :
01260     return plot->p2dXSymbolList;
01261     break;
01262 
01263   case 'Y' :
01264     return plot->p2dYSymbolList;
01265     break;
01266 
01267   default :
01268     return (GList*)NULL;
01269     break;
01270 
01271   }
01272 
01273 }
01274 
01275 
01276 /*
01277  * Real time Step Action.
01278  */
01279 static void
01280 gdisp_stepOnPlot2D (Kernel_T *kernel,
01281                     void     *data)
01282 {
01283 
01284   /*
01285    * Nothing to be done on 2D plot.
01286    */
01287 
01288 }
01289 
01290 
01291 /*
01292  --------------------------------------------------------------------
01293                              PUBLIC ROUTINES
01294  --------------------------------------------------------------------
01295 */
01296 
01297 
01298 void
01299 gdisp_initPlot2DSystem (Kernel_T     *kernel,
01300                         PlotSystem_T *plotSystem)
01301 {
01302 
01303   /*
01304    * We must here provide all 'Plot2D' private functions
01305    * that remain 'static' here, but accessible from everywhere
01306    * via the kernel.
01307    */
01308   plotSystem->psCreate            = gdisp_createPlot2D;
01309   plotSystem->psDestroy           = gdisp_destroyPlot2D;
01310   plotSystem->psSetParent         = gdisp_setPlot2DParent;
01311   plotSystem->psGetTopLevelWidget = gdisp_getPlot2DTopLevelWidget;
01312   plotSystem->psShow              = gdisp_showPlot2D;
01313   plotSystem->psGetType           = gdisp_getPlot2DType;
01314   plotSystem->psAddSymbols        = gdisp_addSymbolsToPlot2D;
01315   plotSystem->psGetSymbols        = gdisp_getSymbolsFromPlot2D;
01316   plotSystem->psSetDimensions     = gdisp_setPlot2DInitialDimensions;
01317   plotSystem->psStep              = gdisp_stepOnPlot2D;
01318 
01319 }
01320 
Framework Home Page.

Beware !! TSP wave is coming...