TSP: The Transport Sample Protocol



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

gdisp_pages.c

Go to the documentation of this file.
00001 
00043 /*
00044  * Authorize Drag and Drop operations.
00045  */
00046 #define GD_PAGE_HAS_DND
00047 
00048 
00049 /*
00050  * System includes.
00051  */
00052 #include <stdio.h>
00053 #include <stdlib.h>
00054 #include <assert.h>
00055 #include <string.h>
00056 
00057 
00058 /*
00059  * GDISP+ includes.
00060  */
00061 #include "gdisp_kernel.h"
00062 #include "gdisp_prototypes.h"
00063 #if defined(GD_PAGE_HAS_DND)
00064 #  include "gdisp_dragAndDrop.h"
00065 #endif
00066 
00067 
00068 /*
00069  * Page border width and row/columns spacings.
00070  * These are used when drop operation occurs. We must deduce from X and
00071  * Y drop location in page window coordinates, what is the target plot.
00072  */
00073 #define GD_PAGE_BORDER_WIDTH  5
00074 #define GD_PAGE_ROW_SPACINGS 10
00075 #define GD_PAGE_COL_SPACINGS 10
00076 #define GD_PAGE_ICON_OFFSET  20
00077 
00078 /*
00079  --------------------------------------------------------------------
00080                              STATIC ROUTINES
00081  --------------------------------------------------------------------
00082 */
00083 
00084 
00085 /*
00086  * The "delete_event" occurs when the window manager sens this event
00087  * to the application, usually by the "close" option, or on the titlebar.
00088  * Returning TRUE means that we do not want to have the "destroy" event 
00089  * emitted, keeping GDISP+ running. Returning FALSE, we ask that "destroy"
00090  * be emitted, which in turn will call the "destroy" signal handler.
00091  */
00092 static gint
00093 gdispManageDeleteEventFromWM (GtkWidget *pageWindow,
00094                               GdkEvent  *event,
00095                               gpointer   data)
00096 {
00097 
00098   Kernel_T *kernel = (Kernel_T*)data;
00099 
00100   /*
00101    * Allow the window manager to close graphic page windows
00102    * only if sampling is off.
00103    */
00104   return (kernel->samplingThreadMustExit == FALSE ? TRUE : FALSE);
00105 
00106 }
00107 
00108 
00109 /*
00110  * The "destroy" event occurs when we call "gtk_widget_destroy" on
00111  * the top-level window, of if we return FALSE in the "delete_event"
00112  * callback (see above).
00113  */
00114 static void
00115 gdispDestroySignalHandler (GtkWidget *pageWindow,
00116                            gpointer   data)
00117 {
00118 
00119   Kernel_T         *kernel         = (Kernel_T*)data;
00120 
00121   PlotSystemData_T *plotSystemData = (PlotSystemData_T*)NULL;
00122   GString          *messageString  =  (GString*)NULL;
00123   GList            *pageItem       =    (GList*)NULL;
00124   Page_T           *page           =   (Page_T*)NULL;
00125 
00126 
00127   /*
00128    * Search the corresponding graphic page in the kernel.
00129    */
00130   pageItem = g_list_first(kernel->pageList);
00131   while (pageItem != (GList*)NULL) {
00132 
00133     page = (Page_T*)pageItem->data;
00134     if (page->pWindow == pageWindow) {
00135 
00136       /*
00137        * We have found the graphic page the window belongs to.
00138        */
00139       break; /* out of while */
00140 
00141     }
00142 
00143     page     = (Page_T*)NULL;
00144     pageItem = g_list_next(pageItem);
00145 
00146   }
00147 
00148   /*
00149    * We have found the graphic page the window belongs to.
00150    */
00151   if (page != (Page_T*)NULL) {
00152 
00153     /*
00154      * Remove the page from the kernel list.
00155      */
00156     kernel->pageList = g_list_remove(kernel->pageList,
00157                                      (gpointer)page);
00158 
00159     /*
00160      * Destroy all plots.
00161      */
00162     plotSystemData = page->pPlotSystemData;
00163     while (plotSystemData <
00164            page->pPlotSystemData + (page->pRows * page->pColumns)) {
00165 
00166       (*plotSystemData->plotSystem->psDestroy)(kernel,
00167                                                plotSystemData->plotData);
00168 
00169       plotSystemData->plotData = (void*)NULL;
00170 
00171       plotSystemData++;
00172 
00173     }
00174 
00175     /*
00176      * Delete resources.
00177      */
00178     gtk_widget_destroy(page->pWindow);
00179     g_string_free(page->pName,TRUE);
00180 
00181     g_free(page->pPlotSystemData);
00182 
00183     memset(page,0,sizeof(Page_T));
00184     g_free(page);
00185 
00186     /*
00187      * Message.
00188      */
00189     messageString = g_string_new((gchar*)NULL);
00190     g_string_sprintf(messageString,
00191                      "Graphic page correctly destroyed (%d remaining).",
00192                      g_list_length(kernel->pageList));
00193     kernel->outputFunc(kernel,messageString,GD_MESSAGE);
00194 
00195   }
00196 
00197 
00198 }
00199 
00200 
00201 /*
00202  * Treat 'expose' X event.
00203  * What shall I do when the page has to be re-drawn ?
00204  */
00205 #if defined(GD_PAGE_TREAT_EXPOSE_EVENT)
00206 
00207 static gboolean
00208 gdispHandlePageExpose (GtkWidget      *pWindow,
00209                        GdkEventExpose *event,
00210                        gpointer        data)
00211 {
00212 
00213   Kernel_T *kernel = (Kernel_T*)data;
00214 
00215   /*
00216    * The only way I have found to keep the main board and the databook
00217    * on the top of all other windows, is to trace page window expose
00218    * events.
00219    */
00220   if (kernel->widgets.dataBookWindow != (GtkWidget*)NULL) {
00221     gdk_window_raise(GTK_WIDGET(kernel->widgets.dataBookWindow)->window);
00222   }
00223   if (kernel->widgets.mainBoardWindow != (GtkWidget*)NULL) {
00224     gdk_window_raise(GTK_WIDGET(kernel->widgets.mainBoardWindow)->window);
00225   }
00226 
00227   return TRUE;
00228 
00229 }
00230 
00231 #endif
00232 
00233 #if defined(GD_PAGE_HAS_DND)
00234 
00235 
00236 /*
00237  * DND "drag_begin" handler : this is called whenever a drag starts.
00238  */
00239 static void
00240 gdisp_beginDNDCallback (GtkWidget      *pageWindow,
00241                         GdkDragContext *dragContext,
00242                         gpointer        data)
00243 {
00244 
00245   Kernel_T *kernel = (Kernel_T*)data;
00246 
00247   /*
00248    * Put any needed drag begin setup code here.
00249    */
00250   assert(kernel);
00251   assert(dragContext);
00252 
00253 #if defined(_DND_DEBUG_)
00254   fprintf(stdout,"begin DND Callback for page window.\n");
00255   fflush (stdout);
00256 #endif
00257 
00258   /*
00259    * Nothing to be done here because no drag operation from the
00260    * page window.
00261    */
00262 
00263 }
00264 
00265 
00266 /*
00267  * DND "drag_end" handler : this is called when a drag and drop has
00268  * completed. So this function is the last one to be called in
00269  * any given DND operation.
00270  */
00271 static void
00272 gdisp_endDNDCallback (GtkWidget      *pageWindow,
00273                       GdkDragContext *dragContext,
00274                       gpointer        data)
00275 {
00276 
00277   Kernel_T *kernel = (Kernel_T*)data;
00278 
00279   /*
00280    * Put any needed drag end cleanup code here.
00281    */
00282   assert(kernel);
00283   assert(dragContext);
00284 
00285 #if defined(_DND_DEBUG_)
00286   fprintf(stdout,"end DND Callback for page window.\n");
00287   fflush (stdout);
00288 #endif
00289 
00290   /*
00291    * Nothing to be done here because no drag operation from the
00292    * page window.
00293    */
00294 
00295 }
00296 
00297 
00298 /*
00299  * Analyse mouse position over a plot.
00300  */
00301 static gboolean
00302 gdisp_analysePositionOverPlot ( Kernel_T          *kernel,
00303                                 PlotSystemData_T  *plotSystemData,
00304                                 gdouble            xPosition,
00305                                 gdouble            yPosition,
00306                                 PlotSystemZone_T **zone )
00307 {
00308 
00309   GArray           *plotZones       =           (GArray*)NULL;
00310   guint             currentZoneId   =                       0;
00311   PlotSystem_T     *plotSystem      =     (PlotSystem_T*)NULL;
00312   PlotSystemZone_T *currentZone     = (PlotSystemZone_T*)NULL;
00313   gboolean          isInsideZone    =                   FALSE;
00314   gboolean          canDrop         =                    TRUE;
00315 
00316   /*
00317    * Retreive plot zones.
00318    * Default plot ? If it is, use the currently selected plot type
00319    * in order to get its zones.
00320    */
00321   *zone = (PlotSystemZone_T*)NULL;
00322 
00323   if ((*plotSystemData->plotSystem->psGetType)
00324       (kernel,plotSystemData->plotData) == GD_PLOT_DEFAULT) {
00325 
00326     /* change plot system */
00327     plotSystem = &kernel->plotSystems[kernel->currentPlotType];
00328     plotZones = (*plotSystem->psGetDropZones)(kernel);
00329 
00330   }
00331   else {
00332 
00333     plotZones = (*plotSystemData->plotSystem->psGetDropZones)(kernel);
00334 
00335   }
00336 
00337   /*
00338    * If there is no zone, drop is allowed everywhere.
00339    * If one or several zones exist, drop is allowed according to the
00340    * zone the mouse is over.
00341    * If one or several zones exist and the mouse is over none of them,
00342    * drop is refused.
00343    */
00344   if (plotZones != (GArray*)NULL) {
00345 
00346     /*
00347      * Search the zone the mouse is over.
00348      */
00349     while (currentZoneId < plotZones->len && isInsideZone == FALSE) {
00350 
00351       currentZone = &g_array_index(plotZones,PlotSystemZone_T,currentZoneId);
00352 
00353       isInsideZone = gdisp_positionIsInsideZone(currentZone,
00354                                                 xPosition,
00355                                                 yPosition);
00356 
00357       if (isInsideZone == FALSE) {
00358         currentZoneId++;
00359       }
00360 
00361     } /* loop over all declared zones */
00362 
00363     /*
00364      * Proceed if we have found a zone.
00365      */
00366     if (isInsideZone == TRUE) {
00367 
00368       *zone   = currentZone;
00369       canDrop = currentZone->pszAcceptDrops;
00370 
00371     }
00372     else {
00373 
00374       *zone   = (PlotSystemZone_T*)NULL;
00375       canDrop = FALSE;
00376 
00377     }
00378 
00379   } /* plotZones != (GArray*)NULL */
00380 
00381   return canDrop;
00382 
00383 }
00384 
00385 
00386 /*
00387  * DND "drag_motion" handler is called whenever the pointer is
00388  * dragging over the target widget.
00389  */
00390 static gboolean
00391 gdisp_dragMotionDNDCallback (GtkWidget      *pageWindow,
00392                              GdkDragContext *dragContext,
00393                              gint            xPositionInPageWindow,
00394                              gint            yPositionInPageWindow,
00395                              guint           time,
00396                              gpointer        data)
00397 {
00398 
00399   Kernel_T         *kernel          =         (Kernel_T*)data;
00400   Page_T           *page            =           (Page_T*)NULL;
00401 
00402   guint             plotWidth       =                       0;
00403   guint             plotHeight      =                       0;
00404   guint             nColumn         =                       0;
00405   guint             nRow            =                       0;
00406   guint             xPositionInPlot =                       0;
00407   guint             yPositionInPlot =                       0;
00408   gdouble           xRatioInPlot    =                     0.0;
00409   gdouble           yRatioInPlot    =                     0.0;
00410 
00411   PlotSystemData_T *plotSystemData  = (PlotSystemData_T*)NULL;
00412   guint             plotIdentity    =                       0;
00413   gboolean          canDrop         =                   FALSE;
00414   PlotSystemZone_T *currentZone     = (PlotSystemZone_T*)NULL;
00415 
00416   gint              windowAttrMask  =                       0;
00417   GdkWindowAttr     windowAttr;
00418 
00419   Pixmap_T         *iconPixmap      =         (Pixmap_T*)NULL;
00420 
00421 
00422   /*
00423    * Put any needed drag motion code here.
00424    */
00425   assert(kernel);
00426   assert(dragContext);
00427 
00428 #if defined(_DND_DEBUG_)
00429   fprintf(stdout,
00430           "data Motion DND Callback for page window (%d,%d).\n",
00431           xPositionInPageWindow,
00432           yPositionInPageWindow);
00433   fflush (stdout);
00434 #endif
00435 
00436   /*
00437    * Set drag status to COPY action.
00438    * We always copy the symbols, NOT moving them from the list to the plot.
00439    */
00440   gdk_drag_status(dragContext,
00441                   GDK_ACTION_COPY,
00442                   time);
00443 
00444   /*
00445    * Compute the size of each plot of the table.
00446    */
00447   page = (Page_T*)gtk_object_get_data(GTK_OBJECT(pageWindow),
00448                                       "pageInformation");
00449 
00450   plotWidth  =
00451     (pageWindow->allocation.width - (2 * GD_PAGE_BORDER_WIDTH) -
00452      ((page->pColumns - 1) * GD_PAGE_COL_SPACINGS)) / page->pColumns;
00453 
00454   plotHeight =
00455     (pageWindow->allocation.height - (2 * GD_PAGE_BORDER_WIDTH) -
00456      ((page->pRows    - 1) * GD_PAGE_ROW_SPACINGS)) / page->pRows;
00457 
00458   /*
00459    * Deduce on what plot the drop operation occurs.
00460    */
00461   if (xPositionInPageWindow > GD_PAGE_BORDER_WIDTH &&
00462       yPositionInPageWindow > GD_PAGE_BORDER_WIDTH    ) {
00463 
00464     nColumn =
00465       (xPositionInPageWindow - GD_PAGE_BORDER_WIDTH) /
00466       (plotWidth  + GD_PAGE_COL_SPACINGS);
00467 
00468     nRow    = 
00469       (yPositionInPageWindow - GD_PAGE_BORDER_WIDTH) /
00470       (plotHeight + GD_PAGE_ROW_SPACINGS);
00471 
00472     /*
00473      * Am I over a plot ?
00474      */
00475     if ((xPositionInPageWindow <
00476          (nColumn * (plotWidth  + GD_PAGE_COL_SPACINGS) + plotWidth )) &&
00477         (yPositionInPageWindow <
00478          (nRow    * (plotHeight + GD_PAGE_ROW_SPACINGS) + plotHeight))) {
00479 
00480       /*
00481        * Yes, I am over a plot.
00482        * Compute drop coordinates in the plot reference.
00483        */
00484       xPositionInPlot = (xPositionInPageWindow - GD_PAGE_BORDER_WIDTH) -
00485         (nColumn * (plotWidth  + GD_PAGE_COL_SPACINGS));
00486 
00487       yPositionInPlot = (yPositionInPageWindow - GD_PAGE_BORDER_WIDTH) -
00488         (nRow    * (plotHeight + GD_PAGE_ROW_SPACINGS));
00489 
00490       yPositionInPlot = plotHeight - yPositionInPlot;
00491 
00492       /*
00493        * GDK windows may have different sizes, compute the drop
00494        * coordinates as a percentage of the plot dimensions.
00495        */
00496       xRatioInPlot = (gdouble)xPositionInPlot / (gdouble)plotWidth;
00497       yRatioInPlot = (gdouble)yPositionInPlot / (gdouble)plotHeight;
00498 
00499       /*
00500        * Retreive current plot handle.
00501        */
00502       plotIdentity   = nRow * page->pColumns + nColumn;
00503       plotSystemData = &page->pPlotSystemData[plotIdentity];
00504 
00505       /*
00506        * Analyse position over plot.
00507        */
00508       canDrop = gdisp_analysePositionOverPlot(kernel,
00509                                               plotSystemData,
00510                                               xRatioInPlot,
00511                                               yRatioInPlot,
00512                                               &currentZone);
00513 
00514     } /* i am over a plot */
00515 
00516   }
00517 
00518   /*
00519    * Have we already built the icon window ?
00520    * No ? So create it.
00521    * Yes ? Check if the parent has changed (drag over several windows).
00522    */
00523   if (kernel->dndIconWindow == (GdkWindow*)NULL) {
00524 
00525     memset(&windowAttr,0,sizeof(GdkWindowAttr));
00526 
00527     windowAttr.event_mask  = GDK_EXPOSURE_MASK;
00528     windowAttr.x           = xPositionInPageWindow - GD_PAGE_ICON_OFFSET;
00529     windowAttr.y           = yPositionInPageWindow - GD_PAGE_ICON_OFFSET;
00530     windowAttr.width       = GD_PAGE_ICON_OFFSET;
00531     windowAttr.height      = GD_PAGE_ICON_OFFSET;
00532     windowAttr.window_type = GDK_WINDOW_CHILD;
00533     windowAttr.wclass      = GDK_INPUT_OUTPUT;
00534     windowAttr.visual      = kernel->visual;
00535     windowAttr.colormap    = kernel->colormap;
00536     windowAttrMask         = GDK_WA_X        |
00537                              GDK_WA_Y        |
00538                              GDK_WA_COLORMAP |
00539                              GDK_WA_VISUAL;
00540 
00541     kernel->dndIconWindowParent = GTK_WIDGET(page->pWindow)->window;
00542 
00543     kernel->dndIconWindow = gdk_window_new(kernel->dndIconWindowParent,
00544                                            &windowAttr,
00545                                            windowAttrMask);
00546 
00547     gdk_window_show(kernel->dndIconWindow);
00548 
00549     kernel->dndIconWindowGc = gdk_gc_new(kernel->dndIconWindow);
00550 
00551   }
00552   else {
00553 
00554     /*
00555      * D&D Icon window exists. Check if the icon window must be reparented.
00556      * It is typically the case when the mouse crosses window borders during
00557      * the drag process.
00558      */
00559     if (kernel->dndIconWindowParent != GTK_WIDGET(page->pWindow)->window) {
00560 
00561       kernel->dndIconWindowParent = GTK_WIDGET(page->pWindow)->window;
00562 
00563       gdk_window_reparent(kernel->dndIconWindow,
00564                           kernel->dndIconWindowParent,
00565                           xPositionInPageWindow - GD_PAGE_ICON_OFFSET,
00566                           yPositionInPageWindow - GD_PAGE_ICON_OFFSET);
00567 
00568     } /* end of reparent operation */
00569 
00570   }
00571 
00572   /*
00573    * Move icon window according to mouse position.
00574    * Update content with the correct pixmap according to drop authorization.
00575    */
00576   if (currentZone == (PlotSystemZone_T*)NULL) {
00577 
00578     if (canDrop == TRUE) {
00579 
00580       iconPixmap = gdisp_getPixmapById(kernel,
00581                                        GD_PIX_okButton2,
00582                                        page->pWindow);
00583 
00584     }
00585     else {
00586 
00587       iconPixmap = gdisp_getPixmapById(kernel,
00588                                        GD_PIX_error,
00589                                        page->pWindow);
00590 
00591     }
00592 
00593   }
00594   else {
00595 
00596       iconPixmap = gdisp_getPixmapByAddr(kernel,
00597                                          currentZone->pszIcon,
00598                                          page->pWindow);
00599 
00600   }
00601 
00602   kernel->dndIconPixmap     = iconPixmap->pixmap;
00603   kernel->dndIconPixmapMask = iconPixmap->mask;
00604 
00605   gdk_window_move_resize(kernel->dndIconWindow,
00606                          xPositionInPageWindow - iconPixmap->width,
00607                          yPositionInPageWindow - iconPixmap->height,
00608                          iconPixmap->width,
00609                          iconPixmap->height);
00610 
00611   gdk_draw_pixmap(kernel->dndIconWindow,
00612                   kernel->dndIconWindowGc,
00613                   kernel->dndIconPixmap,
00614                   0,
00615                   0,
00616                   0,
00617                   0,
00618                   iconPixmap->width,
00619                   iconPixmap->height);
00620 
00621   gdk_window_shape_combine_mask(kernel->dndIconWindow,
00622                                 kernel->dndIconPixmapMask,
00623                                 0,
00624                                 0);
00625 
00626   return FALSE;
00627 
00628 }
00629 
00630 
00631 /*
00632  * DND "drag_data_get" handler, for handling requests for DND
00633  * data on the specified widget. This function is called when
00634  * there is need for DND data on the source, so this function is
00635  * responsable for setting up the dynamic data exchange buffer
00636  * (DDE as sometimes it is called) and sending it out.
00637  */
00638 static void
00639 gdisp_dataRequestDNDCallback (GtkWidget        *pageWindow,
00640                               GdkDragContext   *dragContext,
00641                               GtkSelectionData *selectionData,
00642                               guint             entryInfo,
00643                               guint             time,
00644                               gpointer          data)
00645 {
00646 
00647   Kernel_T *kernel = (Kernel_T*)data;
00648 
00649   /*
00650    * Put any needed data request code here.
00651    */
00652   assert(kernel);
00653   assert(dragContext);
00654 
00655 #if defined(_DND_DEBUG_)
00656   fprintf(stdout,"data Request DND Callback for page window.\n");
00657   fflush (stdout);
00658 #endif
00659 
00660   /*
00661    * Nothing to be done here because no drag operation from the
00662    * page window.
00663    */
00664 
00665 }
00666 
00667 
00668 /*
00669  * Finalize Drag & Drop operation according to Drag & Drop scope.
00670  */
00671 static void
00672 gdisp_finalizeDragAndDropOperation(Kernel_T         *kernel,
00673                                    Page_T           *page,
00674                                    PlotSystemData_T *plotSystemData,
00675                                    guint             plotWidth,
00676                                    guint             plotHeight,
00677                                    guint             nColumn,
00678                                    guint             nRow,
00679                                    guchar            zoneId)
00680 {
00681 
00682   GtkWidget        *plotTopLevel        =    (GtkWidget*)NULL;
00683   GString          *messageString       =      (GString*)NULL;
00684   PlotSystem_T     *requestedPlotSystem = (PlotSystem_T*)NULL;
00685   gchar            *plotName            =        (gchar*)NULL;
00686   PlotSystemInfo_T  plotInformation;
00687 
00688 
00689   /*
00690    * If the plot we are over, is a 'default plot', replace
00691    * it by the plot the type of which is currently selected.
00692    */
00693   if ((*plotSystemData->plotSystem->psGetType)
00694                      (kernel,plotSystemData->plotData) == GD_PLOT_DEFAULT) {
00695 
00696     /*
00697      * Destroy this default plot.
00698      * Create a new one and attach it correctly to the table.
00699      * Set up its parent and finally show it.
00700      */
00701 
00702     /* change plot system */
00703     requestedPlotSystem = &kernel->plotSystems[kernel->currentPlotType];
00704 
00705     /* check out if this kind of plot is fully supported... */
00706     if (requestedPlotSystem->psIsSupported == FALSE) {
00707 
00708       messageString = g_string_new((gchar*)NULL);
00709 
00710       /*
00711        * CAUTION :
00712        * 'psGetInformation' may not exist... as plot is not fully supported.
00713        */
00714       if (requestedPlotSystem->psGetInformation != (aFunction_T)NULL) {
00715 
00716         (*requestedPlotSystem->psGetInformation)(kernel,
00717                                                  &plotInformation);
00718 
00719         plotName = plotInformation.psName != (gchar*)NULL ?
00720                                    plotInformation.psName : "unknown";
00721 
00722       }
00723       else {
00724 
00725         plotName = "unknown";
00726 
00727       }
00728 
00729       g_string_sprintf(messageString,
00730                        "Requested graphic plot not fully supported (%s).",
00731                        plotName);
00732 
00733       kernel->outputFunc(kernel,messageString,GD_ERROR);
00734 
00735       return;
00736 
00737     }
00738 
00739     /* destroy */
00740     (*plotSystemData->plotSystem->psDestroy)(kernel,
00741                                              plotSystemData->plotData);
00742 
00743     /* re-create */
00744     plotSystemData->plotSystem = requestedPlotSystem;
00745     plotSystemData->plotData   =
00746                        (*plotSystemData->plotSystem->psCreate)(kernel);
00747 
00748     /* set parent widget */
00749     (*plotSystemData->plotSystem->psSetParent)(kernel,
00750                                                plotSystemData->plotData,
00751                                                page->pWindow);
00752 
00753     /* set initial dimensions */
00754     (*plotSystemData->plotSystem->psSetDimensions)(kernel,
00755                                                    plotSystemData->plotData,
00756                                                    plotWidth,
00757                                                    plotHeight);
00758 
00759     /* attach new plot */
00760     plotTopLevel =
00761       (*plotSystemData->plotSystem->psGetTopLevelWidget)
00762                                       (kernel,plotSystemData->plotData);
00763 
00764     gtk_table_attach_defaults(GTK_TABLE(page->pTable),
00765                               plotTopLevel,
00766                               nColumn,
00767                               nColumn + 1,
00768                               nRow,
00769                               nRow    + 1);
00770 
00771     /* show it */
00772     (*plotSystemData->plotSystem->psShow)(kernel,
00773                                           plotSystemData->plotData);
00774 
00775   } /* current plot is a 'default plot' */
00776 
00777   /*
00778    * Add symbols to the plot we are over.
00779    */
00780   (*plotSystemData->plotSystem->psAddSymbols)(kernel,
00781                                               plotSystemData->plotData,
00782                                               kernel->dndSelection,
00783                                               zoneId);
00784 
00785   /*
00786    * Do not forget to update symbols <-> providers assignments.
00787    */
00788   (*kernel->assignSymbolsToProviders)(kernel);
00789 
00790 }
00791 
00792 
00793 /*
00794  * DND "drag_data_received" handler. When 'gdisp_dataRequestDNDCallback'
00795  * calls 'gtk_selection_data_set()' to send out the data, this function
00796  * receives it and is responsible for handling it.
00797  *
00798  * This is also the only DND callback function where the given
00799  * inputs may reflect those of the drop target, so we need to check
00800  * if this is the same structure or not.
00801  */
00802 static void
00803 gdisp_dataReceivedDNDCallback (GtkWidget        *pageWindow,
00804                                GdkDragContext   *dragContext,
00805                                gint              xPositionInPageWindow,
00806                                gint              yPositionInPageWindow,
00807                                GtkSelectionData *selectionData,
00808                                guint             entryInfo,
00809                                guint             time,
00810                                gpointer          data)
00811 {
00812 
00813   Kernel_T         *kernel          =         (Kernel_T*)data;
00814   gchar            *action          =            (gchar*)NULL;
00815   Page_T           *page            =           (Page_T*)NULL;
00816   GList            *pageItem        =            (GList*)NULL;
00817 
00818   guint             plotWidth       =                       0;
00819   guint             plotHeight      =                       0;
00820   guint             nColumn         =                       0;
00821   guint             nRow            =                       0;
00822   guint             xPositionInPlot =                       0;
00823   guint             yPositionInPlot =                       0;
00824   gdouble           xRatioInPlot    =                     0.0;
00825   gdouble           yRatioInPlot    =                     0.0;
00826 
00827   PlotSystemData_T *plotSystemData  = (PlotSystemData_T*)NULL;
00828   guint             plotIdentity    =                       0;
00829 
00830   gboolean          canDrop         =                   FALSE;
00831   PlotSystemZone_T *currentZone     = (PlotSystemZone_T*)NULL;
00832 
00833 
00834   /*
00835    * Put any needed data received code here.
00836    */
00837   assert(kernel);
00838   assert(dragContext);
00839 
00840 #if defined(_DND_DEBUG_)
00841   fprintf(stdout,
00842           "data Receive DND Callback for page window (%d,%d).\n",
00843           xPositionInPageWindow,
00844           yPositionInPageWindow);
00845   fflush (stdout);
00846 #endif
00847 
00848   /*
00849    * Important, check if we actually got data.
00850    * Sometimes errors occur and 'selectionData' is NULL.
00851    */
00852   if (selectionData == (GtkSelectionData*)NULL) {
00853 
00854     return;
00855 
00856   }
00857   if (selectionData->length < 0) {
00858 
00859     return;
00860 
00861   }
00862 
00863   /*
00864    * Now check if the data format type is one that we support
00865    * (remember, data format type, not data type).
00866    *
00867    * We check this by testing if info matches one of the info
00868    * values that we have defined.
00869    *
00870    * Note that we can also iterate through the atoms in :
00871    *
00872    *  GList *glist = dragContext->targets;
00873    *
00874    *  while (glist != (GList*)NULL) {
00875    *
00876    *    gchar *name = gdk_atom_name((GdkAtom)glist->data);
00877    *
00878    *    ... strcmp the name to see if it matches one that we support...
00879    *
00880    *    glist = glist->next;
00881    *
00882    *  }
00883    *
00884    */
00885   if (entryInfo == GD_DND_TARGET_INFO) {
00886 
00887     /*
00888      * Pick up what action to perform.
00889      */
00890     action = (gchar*)selectionData->data;
00891     if (strcmp(action,GD_DND_SYMBOL_LIST_EXCHANGE) ==0) {
00892 
00893       /*
00894        * Compute the size of each plot of the table.
00895        */
00896       page = (Page_T*)gtk_object_get_data(GTK_OBJECT(pageWindow),
00897                                           "pageInformation");
00898 
00899       plotWidth  =
00900         (pageWindow->allocation.width - (2 * GD_PAGE_BORDER_WIDTH) -
00901          ((page->pColumns - 1) * GD_PAGE_COL_SPACINGS)) / page->pColumns;
00902 
00903       plotHeight =
00904         (pageWindow->allocation.height - (2 * GD_PAGE_BORDER_WIDTH) -
00905          ((page->pRows    - 1) * GD_PAGE_ROW_SPACINGS)) / page->pRows;
00906 
00907       /*
00908        * Deduce on what plot the drop operation occurs.
00909        */
00910       if (xPositionInPageWindow > GD_PAGE_BORDER_WIDTH &&
00911           yPositionInPageWindow > GD_PAGE_BORDER_WIDTH    ) {
00912 
00913         nColumn =
00914           (xPositionInPageWindow - GD_PAGE_BORDER_WIDTH) /
00915           (plotWidth  + GD_PAGE_COL_SPACINGS);
00916 
00917         nRow    = 
00918           (yPositionInPageWindow - GD_PAGE_BORDER_WIDTH) /
00919           (plotHeight + GD_PAGE_ROW_SPACINGS);
00920 
00921         /*
00922          * Am I over a plot ?
00923          */
00924         if ((xPositionInPageWindow <
00925              (nColumn * (plotWidth  + GD_PAGE_COL_SPACINGS) + plotWidth )) &&
00926             (yPositionInPageWindow <
00927              (nRow    * (plotHeight + GD_PAGE_ROW_SPACINGS) + plotHeight))) {
00928 
00929           /*
00930            * Yes, I am over a plot.
00931            * Compute drop coordinates in the plot reference.
00932            */
00933           xPositionInPlot = (xPositionInPageWindow - GD_PAGE_BORDER_WIDTH) -
00934             (nColumn * (plotWidth  + GD_PAGE_COL_SPACINGS));
00935 
00936           yPositionInPlot = (yPositionInPageWindow - GD_PAGE_BORDER_WIDTH) -
00937             (nRow    * (plotHeight + GD_PAGE_ROW_SPACINGS));
00938 
00939           yPositionInPlot = plotHeight - yPositionInPlot;
00940 
00941           /*
00942            * For BROADCAST purpose, as GDK windows may have different
00943            * sizes, compute the drop coordinates as a percentage of the
00944            * plot dimensions.
00945            */
00946           xRatioInPlot = (gdouble)xPositionInPlot / (gdouble)plotWidth;
00947           yRatioInPlot = (gdouble)yPositionInPlot / (gdouble)plotHeight;
00948 
00949           /*
00950            * Take care of Drag & Drop operation scope.
00951            */
00952           switch (kernel->dndScope) {
00953 
00954           case GD_DND_UNICAST :
00955 
00956             /*
00957              * Retreive current plot handle.
00958              */
00959             plotIdentity   = nRow * page->pColumns + nColumn;
00960             plotSystemData = &page->pPlotSystemData[plotIdentity];
00961 
00962             /*
00963              * Analyse position over plot.
00964              */
00965             canDrop = gdisp_analysePositionOverPlot(kernel,
00966                                                     plotSystemData,
00967                                                     xRatioInPlot,
00968                                                     yRatioInPlot,
00969                                                     &currentZone);
00970 
00971             /*
00972              * Finalize Drag & Drop operation according to Drag & Drop scope.
00973              */
00974             if (canDrop == TRUE)
00975               gdisp_finalizeDragAndDropOperation(kernel,
00976                                                  page,
00977                                                  plotSystemData,
00978                                                  plotWidth,
00979                                                  plotHeight,
00980                                                  nColumn,
00981                                                  nRow,
00982                                                  currentZone ?
00983                                                  currentZone->pszId : 0);
00984 
00985             break;
00986 
00987           case GD_DND_MULTICAST :
00988 
00989             /*
00990              * Loop over all graphic plots of the current page.
00991              */
00992             for (nRow=0; nRow<page->pRows; nRow++) {
00993 
00994               for (nColumn=0; nColumn<page->pColumns; nColumn++) {
00995 
00996                 plotIdentity   = nRow * page->pColumns + nColumn;
00997                 plotSystemData = &page->pPlotSystemData[plotIdentity];
00998 
00999                 canDrop = gdisp_analysePositionOverPlot(kernel,
01000                                                         plotSystemData,
01001                                                         xRatioInPlot,
01002                                                         yRatioInPlot,
01003                                                         &currentZone);
01004 
01005                 if (canDrop == TRUE)
01006                   gdisp_finalizeDragAndDropOperation(kernel,
01007                                                      page,
01008                                                      plotSystemData,
01009                                                      plotWidth,
01010                                                      plotHeight,
01011                                                      nColumn,
01012                                                      nRow,
01013                                                      currentZone ?
01014                                                      currentZone->pszId : 0);
01015 
01016               } /* columns */
01017 
01018             } /* rows */
01019 
01020             break;
01021 
01022           case GD_DND_BROADCAST :
01023 
01024             /*
01025              * Loop over all graphic plots of all existing graphic pages.
01026              * The difference between the BROADCAST mode and the two previous
01027              * ones is that we loop here upon all graphic pages that MAY have
01028              * different sizes.
01029              * So "plotWidth", "plotHeight" and drop coordinates have to be
01030              * recomputed for each page.
01031              */
01032             pageItem = g_list_first(kernel->pageList);
01033             while (pageItem != (GList*)NULL) {
01034 
01035               page       = (Page_T*)pageItem->data;
01036               pageWindow = page->pWindow;
01037 
01038               plotWidth  =
01039                 (pageWindow->allocation.width  - (2 * GD_PAGE_BORDER_WIDTH) -
01040                  ((page->pColumns - 1) * GD_PAGE_COL_SPACINGS)) / page->pColumns;
01041 
01042               plotHeight =
01043                 (pageWindow->allocation.height - (2 * GD_PAGE_BORDER_WIDTH) -
01044                  ((page->pRows    - 1) * GD_PAGE_ROW_SPACINGS)) / page->pRows;
01045 
01046               xPositionInPlot = (guint)(xRatioInPlot * (gdouble)plotWidth );
01047               yPositionInPlot = (guint)(yRatioInPlot * (gdouble)plotHeight);
01048 
01049               for (nRow=0; nRow<page->pRows; nRow++) {
01050 
01051                 for (nColumn=0; nColumn<page->pColumns; nColumn++) {
01052 
01053                   plotIdentity   = nRow * page->pColumns + nColumn;
01054                   plotSystemData = &page->pPlotSystemData[plotIdentity];
01055 
01056                   canDrop = gdisp_analysePositionOverPlot(kernel,
01057                                                           plotSystemData,
01058                                                           xRatioInPlot,
01059                                                           yRatioInPlot,
01060                                                           &currentZone);
01061 
01062                   if (canDrop == TRUE)
01063                     gdisp_finalizeDragAndDropOperation(kernel,
01064                                                        page,
01065                                                        plotSystemData,
01066                                                        plotWidth,
01067                                                        plotHeight,
01068                                                        nColumn,
01069                                                        nRow,
01070                                                        currentZone ?
01071                                                        currentZone->pszId : 0);
01072 
01073                 } /* columns */
01074 
01075               } /* rows */
01076 
01077               pageItem = g_list_next(pageItem);
01078 
01079             } /* while */
01080 
01081             break;
01082 
01083           default :
01084 
01085             break;
01086 
01087           } /* end of switch (kernel->dndScope) */
01088 
01089         } /* Am I over a plot ? */
01090 
01091       }
01092 
01093     }
01094     else {
01095 
01096       /* nothing else is supported by now */
01097 
01098     }
01099 
01100   } /* test on 'entryInfo' */
01101 
01102   /*
01103    * Now all is done, what about removing icon window ?
01104    */
01105   if (kernel->dndIconWindow != (GdkWindow*)NULL) {
01106 
01107     gdk_window_destroy(kernel->dndIconWindow);
01108     kernel->dndIconWindow       = (GdkWindow*)NULL;
01109     kernel->dndIconWindowParent = (GdkWindow*)NULL;
01110     kernel->dndIconPixmap       = (GdkPixmap*)NULL;
01111     kernel->dndIconPixmapMask   = (GdkBitmap*)NULL;
01112 
01113     gdk_gc_destroy(kernel->dndIconWindowGc);
01114     kernel->dndIconWindowGc = (GdkGC*)NULL;
01115 
01116   }
01117 
01118 }
01119 
01120 
01121 /*
01122  * DND "drag_data_delete" handler, this function is called when
01123  * the data on the source `should' be deleted (ie if the DND was
01124  * a move).
01125  */
01126 static void
01127 gdisp_dataDestroyedDNDCallback (GtkWidget      *pageWindow,
01128                                 GdkDragContext *dragContext,
01129                                 gpointer        data)
01130 {
01131 
01132   Kernel_T *kernel = (Kernel_T*)data;
01133 
01134   /*
01135    * Put any needed data destroyed code here.
01136    */
01137   assert(kernel);
01138   assert(dragContext);
01139 
01140 #if defined(_DND_DEBUG_)
01141   fprintf(stdout,"data Destroy DND Callback for page window.\n");
01142   fflush (stdout);
01143 #endif
01144 
01145   /*
01146    * This procedure does nothing because there is nothing to be done here.
01147    * No drag operation from the page window.
01148    */
01149 
01150 }
01151 
01152 
01153 #endif /* GD_PAGE_HAS_DND */
01154 
01155 
01156 /*
01157  * Routine that acts as a callback to retreive the symbols of a plot.
01158  */
01159 static void
01160 gdisp_getSymbolsInOnePlot ( Kernel_T         *kernel,
01161                             Page_T           *page,
01162                             PlotSystemData_T *plotSystemData,
01163                             void             *userData )
01164 {
01165 
01166   GList **symbolList = (GList**)userData;
01167   GList  *symbolItem =  (GList*)NULL;
01168 
01169   /*
01170    * Read the list of symbols on the X axis.
01171    */
01172   symbolItem =
01173     (*plotSystemData->plotSystem->psGetSymbols)(kernel,
01174                                                 plotSystemData->plotData,
01175                                                 'X');
01176 
01177   symbolItem = g_list_first(symbolItem);
01178 
01179   while (symbolItem != (GList*)NULL) {
01180 
01181     if (g_list_find(*symbolList,symbolItem->data) == (GList*)NULL) {
01182 
01183       *symbolList = g_list_append(*symbolList,
01184                                   symbolItem->data);
01185 
01186     }
01187 
01188     symbolItem = g_list_next(symbolItem);
01189 
01190   }
01191 
01192 
01193   /*
01194    * Read the list of symbols on the Y axis.
01195    */
01196   symbolItem =
01197     (*plotSystemData->plotSystem->psGetSymbols)(kernel,
01198                                                 plotSystemData->plotData,
01199                                                 'Y');
01200 
01201   symbolItem = g_list_first(symbolItem);
01202 
01203   while (symbolItem != (GList*)NULL) {
01204 
01205     if (g_list_find(*symbolList,symbolItem->data) == (GList*)NULL) {
01206 
01207       *symbolList = g_list_append(*symbolList,
01208                                   symbolItem->data);
01209 
01210     }
01211 
01212     symbolItem = g_list_next(symbolItem);
01213 
01214   }
01215 
01216 }
01217 
01218 
01219 /*
01220  --------------------------------------------------------------------
01221                              PUBLIC ROUTINES
01222  --------------------------------------------------------------------
01223 */
01224 
01225 
01226 /*
01227  * Create GDISP+ graphic page.
01228  */
01229 void
01230 gdisp_createGraphicPage (gpointer factoryData,
01231                          guint    pageDimension)
01232 {
01233 
01234   Kernel_T         *kernel         =  (Kernel_T*)factoryData;
01235   Page_T           *newPage        =           (Page_T*)NULL;
01236   GString          *messageString  =          (GString*)NULL;
01237   PlotSystemData_T *plotSystemData = (PlotSystemData_T*)NULL;
01238   PlotSystem_T     *defaultSystem  =     (PlotSystem_T*)NULL;
01239   GtkWidget        *plotTopLevel   =        (GtkWidget*)NULL;
01240   GdkGeometry       pWindowHints;
01241 #if defined(GD_PAGE_HAS_DND)
01242   GtkTargetEntry    targetEntry;
01243 #endif
01244 
01245   gint              screenWidth    =                 0;
01246   gint              screenHeight   =                 0;
01247   gint              row            =                 0;
01248   gint              column         =                 0;
01249 
01250 
01251   /* --------------------- BEGIN --------------------- */
01252 
01253   assert(kernel);
01254 
01255   /*
01256    * Custom dimension management is not done yet.
01257    */
01258   if (pageDimension == 0) {
01259     return;
01260   }
01261 
01262   /*
01263    * CAUTION.
01264    * Before anything, we must check out whether 'default plot' plot system
01265    * is fully supported. Without default plot system, the graphic page
01266    * can not be created.
01267    */
01268   defaultSystem = &kernel->plotSystems[GD_PLOT_DEFAULT];
01269   if (defaultSystem->psIsSupported == FALSE) {
01270 
01271     messageString = g_string_new((gchar*)NULL);
01272     g_string_sprintf(messageString,
01273                      "Default plot system not fully supported.");
01274     kernel->outputFunc(kernel,messageString,GD_ERROR);
01275 
01276     messageString = g_string_new((gchar*)NULL);
01277     g_string_sprintf(messageString,
01278                      "Aborting graphic page creation.");
01279     kernel->outputFunc(kernel,messageString,GD_WARNING);
01280 
01281     return;
01282 
01283   }
01284 
01285   /*
01286    * Allocate memory for this new graphic page.
01287    * Insert the new graphic page into the kernel page list.
01288    */
01289   newPage = (Page_T*)g_malloc0(sizeof(Page_T));
01290   assert(newPage);
01291 
01292   newPage->pRows    = pageDimension;
01293   newPage->pColumns = pageDimension;
01294 
01295   newPage->pName    = g_string_new("Graphic Page");
01296   assert(newPage->pName);
01297 
01298   g_string_sprintf(newPage->pName,
01299                    "Graphic Page #%d",
01300                    g_list_length(kernel->pageList) + 1);
01301 
01302   /* --------------------- PLOT SYSTEMS --------------------- */
01303 
01304   /*
01305    * Allocate memory for plot systems.
01306    * When the graphic page is created, all that it has is default plots.
01307    */
01308   newPage->pPlotSystemData =
01309     (PlotSystemData_T*)g_malloc0(newPage->pRows *
01310                                  newPage->pColumns * sizeof(PlotSystemData_T));
01311   assert(newPage->pPlotSystemData);
01312 
01313   plotSystemData = newPage->pPlotSystemData;
01314 
01315   while (plotSystemData <
01316          newPage->pPlotSystemData + (newPage->pRows * newPage->pColumns)) {
01317 
01318     plotSystemData->plotSystem = &kernel->plotSystems[GD_PLOT_DEFAULT];
01319     plotSystemData->plotData   =
01320                        (*plotSystemData->plotSystem->psCreate)(kernel);
01321     plotSystemData->plotCycle  = G_MAXINT;
01322 
01323     plotSystemData++;
01324 
01325   }
01326 
01327   /* ------------------------ MAIN WINDOW ------------------------ */
01328 
01329   /*
01330    * Now, deal with graphic page top-level window.
01331    * The GTK_WINDOW_TOPLEVEL argument specifies that we want the window
01332    * to undergo window manager decoration and placement.
01333    */
01334   screenWidth  = gdk_screen_width ();
01335   screenHeight = gdk_screen_height();
01336 
01337   newPage->pWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL);
01338   assert(newPage->pWindow);
01339 
01340   gtk_signal_connect(GTK_OBJECT(newPage->pWindow),
01341                      "delete_event",
01342                      GTK_SIGNAL_FUNC(gdispManageDeleteEventFromWM),
01343                      (gpointer)kernel);
01344 
01345   gtk_signal_connect(GTK_OBJECT(newPage->pWindow),
01346                      "destroy",
01347                      GTK_SIGNAL_FUNC(gdispDestroySignalHandler),
01348                      (gpointer)kernel);
01349 
01350 #if defined(GD_PAGE_TREAT_EXPOSE_EVENT)
01351   gtk_signal_connect (GTK_OBJECT(newPage->pWindow),
01352                       "expose_event",
01353                       (GtkSignalFunc)gdispHandlePageExpose,
01354                       (gpointer)kernel); 
01355 #endif
01356 
01357 #if defined(GD_PAGE_HAS_DND)
01358 
01359 
01360   /*
01361    * Drag And Drop settings.
01362    * Set up the 'page window' as a potential DND destination.
01363    * First we set up 'targetEntry' which is a structure which specifies
01364    * the kinds (which we define) of drops accepted on this widget.
01365    */
01366   targetEntry.target = GD_DND_TARGET_NAME;
01367   targetEntry.flags  = 0;
01368   targetEntry.info   = GD_DND_TARGET_INFO;
01369 
01370   /*
01371    * Set the drag destination for this widget, using the
01372    * above target entry types, accept only copies.
01373    */
01374   gtk_drag_dest_set(newPage->pWindow,
01375                     GTK_DEST_DEFAULT_MOTION    |
01376                     GTK_DEST_DEFAULT_HIGHLIGHT | GTK_DEST_DEFAULT_DROP,
01377                     &targetEntry,
01378                     sizeof(targetEntry) / sizeof(GtkTargetEntry),
01379                     GDK_ACTION_COPY);
01380 
01381   /*
01382    * Set DND signals on 'cList'.
01383    */
01384   gtk_signal_connect(GTK_OBJECT(newPage->pWindow),
01385                      "drag_begin",
01386                      GTK_SIGNAL_FUNC(gdisp_beginDNDCallback),
01387                      kernel);
01388 
01389   gtk_signal_connect(GTK_OBJECT(newPage->pWindow),
01390                      "drag_end",
01391                      GTK_SIGNAL_FUNC(gdisp_endDNDCallback),
01392                      kernel);
01393 
01394   gtk_signal_connect(GTK_OBJECT(newPage->pWindow),
01395                      "drag_motion",
01396                      GTK_SIGNAL_FUNC(gdisp_dragMotionDNDCallback),
01397                      kernel);
01398 
01399   gtk_signal_connect(GTK_OBJECT(newPage->pWindow),
01400                      "drag_data_get",
01401                      GTK_SIGNAL_FUNC(gdisp_dataRequestDNDCallback),
01402                      kernel);
01403 
01404   gtk_signal_connect(GTK_OBJECT(newPage->pWindow),
01405                      "drag_data_received",
01406                      GTK_SIGNAL_FUNC(gdisp_dataReceivedDNDCallback),
01407                      kernel);
01408 
01409   gtk_signal_connect(GTK_OBJECT(newPage->pWindow),
01410                      "drag_data_delete",
01411                      GTK_SIGNAL_FUNC(gdisp_dataDestroyedDNDCallback),
01412                      kernel);
01413 
01414 #endif /* GD_PAGE_HAS_DND */
01415 
01416   gtk_object_set_data(GTK_OBJECT(newPage->pWindow),
01417                       "pageInformation",
01418                       (gpointer)newPage);
01419 
01420 
01421   /*
01422    * Set up window size, title and border width.
01423    */
01424   gtk_widget_set_usize(GTK_WIDGET(newPage->pWindow),
01425                        3 * screenWidth  / 4,  /* width  */
01426                        3 * screenHeight / 4); /* height */
01427 
01428   gtk_window_set_title(GTK_WINDOW(newPage->pWindow),
01429                        newPage->pName->str);
01430 
01431   gtk_container_set_border_width(GTK_CONTAINER(newPage->pWindow),
01432                                  GD_PAGE_BORDER_WIDTH);
01433 
01434   pWindowHints.min_aspect = (gdouble)screenWidth / (gdouble)screenHeight;
01435   pWindowHints.max_aspect = pWindowHints.min_aspect;
01436 
01437   gtk_widget_show(newPage->pWindow);
01438 
01439   gdk_window_set_geometry_hints(GTK_WIDGET(newPage->pWindow)->window,
01440                                 &pWindowHints,
01441                                 GDK_HINT_ASPECT);
01442 
01443   /*
01444    * Create a table with the correct dimensions.
01445    */
01446   newPage->pTable = gtk_table_new(newPage->pRows,
01447                                   newPage->pColumns,
01448                                   TRUE /* homogeneous */);
01449 
01450   gtk_table_set_row_spacings(GTK_TABLE(newPage->pTable),
01451                              GD_PAGE_ROW_SPACINGS);
01452   gtk_table_set_col_spacings(GTK_TABLE(newPage->pTable),
01453                              GD_PAGE_COL_SPACINGS);
01454 
01455   gtk_container_add(GTK_CONTAINER(newPage->pWindow),
01456                     newPage->pTable);
01457 
01458   gtk_widget_show   (newPage->pTable);
01459 
01460 
01461   /*
01462    * Attach each graphic plots to the correct place.
01463    */
01464   plotSystemData = newPage->pPlotSystemData;
01465 
01466   for (row=0; row<newPage->pRows; row++) {
01467 
01468     for (column=0; column<newPage->pColumns; column++) {
01469 
01470       (*plotSystemData->plotSystem->psSetParent)(kernel,
01471                                                  plotSystemData->plotData,
01472                                                  newPage->pWindow);
01473 
01474       plotTopLevel =
01475         (*plotSystemData->plotSystem->psGetTopLevelWidget)
01476                                          (kernel,plotSystemData->plotData);
01477 
01478       gtk_table_attach_defaults(GTK_TABLE(newPage->pTable),
01479                                 plotTopLevel,
01480                                 column,
01481                                 column + 1,
01482                                 row,
01483                                 row    + 1);
01484 
01485       plotSystemData++;
01486 
01487     } /* columns */
01488 
01489   } /* rows */
01490 
01491 
01492   /*
01493    * Show all plots.
01494    */
01495   plotSystemData = newPage->pPlotSystemData;
01496   while (plotSystemData <
01497          newPage->pPlotSystemData + (newPage->pRows * newPage->pColumns)) {
01498 
01499     (*plotSystemData->plotSystem->psShow)(kernel,
01500                                           plotSystemData->plotData);
01501 
01502     plotSystemData++;
01503 
01504   }
01505 
01506   /*
01507    * Message.
01508    */
01509   messageString = g_string_new((gchar*)NULL);
01510   g_string_sprintf(messageString,
01511                    "Graphic page correctly created (%d).",
01512                    g_list_length(kernel->pageList));
01513   kernel->outputFunc(kernel,messageString,GD_MESSAGE);
01514 
01515   /*
01516    * Now that all has been created within the graphic page,
01517    * insert the graphic page into the kernel page list.
01518    */
01519   kernel->pageList = g_list_append(kernel->pageList,
01520                                    (gpointer)newPage);
01521   assert(kernel->pageList);
01522 
01523 }
01524 
01525 
01526 /*
01527  * Return the whole set of symbols affected to plots in pages.
01528  */
01529 GList*
01530 gdisp_getSymbolsInPages (Kernel_T *kernel)
01531 {
01532 
01533   GList *symbolList = (GList*)NULL;
01534 
01535 
01536   /*
01537    * Loop over all plots defined in the kernel.
01538    */
01539   gdisp_loopOnGraphicPlots (kernel,
01540                             gdisp_getSymbolsInOnePlot,
01541                             (void*)&symbolList);
01542 
01543   return symbolList;
01544 
01545 }
01546 
Framework Home Page.

Beware !! TSP wave is coming...