Scicos blocks: use the new MVC graphic for scopes
[scilab.git] / scilab / modules / scicos_blocks / src / c / cevscpe.c
index 2ab114d..00313e9 100755 (executable)
-/*  Scicos
-*
-*  Copyright (C) INRIA - METALAU Project <scicos@inria.fr>
-*
-* This program is free software; you can redistribute it and/or modify
-* it under the terms of the GNU General Public License as published by
-* the Free Software Foundation; either version 2 of the License, or
-* (at your option) any later version.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-* GNU General Public License for more details.
-*
-* You should have received a copy of the GNU General Public License
-* along with this program; if not, write to the Free Software
-* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*
-* See the file ./license.txt
-*/
-/*--------------------------------------------------------------------------*/
-/**
-   \file cevscpe.c
-   \author Benoit Bayol
-   \version 1.0
-   \date September 2006 - January 2007
-   \brief CEVSCPE is a scope that indicates when the clocks is activated
-   \see CEVENTSCOPE.sci in macros/scicos_blocks/Sinks/
-*/
-/*--------------------------------------------------------------------------*/
-#include "scicos.h"
-#include "scoMemoryScope.h"
-#include "scoWindowScope.h"
-#include "scoMisc.h"
-#include "scoGetProperty.h"
-#include "scoSetProperty.h"
-#include "scicos_block4.h"
-#include "DrawingBridge.h"
-#include "SetJavaProperty.h"
-#include "scicos_malloc.h"
-#include "scicos_free.h"
-#include "MALLOC.h"
+/*
+ *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+ *  Copyright (C) 2011 - Scilab Enterprises - ClĂ©ment DAVID
+ *
+ *  This file must be used under the terms of the CeCILL.
+ *  This source file is licensed as described in the file COPYING, which
+ *  you should have received as part of this distribution.  The terms
+ *  are also available at
+ *  http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
+ *
+ */
+
 #include "dynlib_scicos_blocks.h"
-/*--------------------------------------------------------------------------*/
-/** \fn cscopxy_draw(scicos_block * block, ScopeMemory ** pScopeMemory, int firstdraw)
-    \brief Function to draw or redraw the window
+#include "scoUtils.h"
+
+#include "MALLOC.h"
+#include "elementary_functions.h"
+#include "string.h"
+
+#include "getGraphicObjectProperty.h"
+#include "setGraphicObjectProperty.h"
+#include "graphicObjectProperties.h"
+#include "createGraphicObject.h"
+
+#include "CurrentFigure.h"
+
+#include "scicos_block4.h"
+#include "scicos.h"
+
+#include "localization.h"
+
+#include "FigureList.h"
+#include "BuildObjects.h"
+#include "AxesModel.h"
+
+/*****************************************************************************
+ * Internal container structure
+ ****************************************************************************/
+
+#define DEFAULT_MAX_NUMBER_OF_POINTS 8
+
+/**
+ * Container structure
+ */
+typedef struct
+{
+    struct
+    {
+        int *numberOfPoints;
+        int *maxNumberOfPoints;
+        double **data;
+    } internal;
+
+    struct
+    {
+        int periodCounter;
+
+        char *cachedFigureUID;
+        char *cachedAxeUID;
+        char **cachedSegsUIDs;
+    } scope;
+} sco_data;
+
+/**
+ * Get (and allocate on demand) the internal data used on this scope
+ * \param block the block
+ * \return the scope data
+ */
+static sco_data *getScoData(scicos_block * block);
+
+/**
+ * Release any internal data
+ *
+ * \param block the block
+ */
+static void freeScoData(scicos_block * block);
+
+/**
+ * Append the data to the current data
+ *
+ * \param block the block
+ * \param input the input (0-indexed)
+ * \param t the current time
+ */
+static void appendData(scicos_block * block, int input, double t);
+
+/**
+ * Push the block data to the segs
+ *
+ * \param block the block
+ * \param input the selected input
+ *
+ */
+static BOOL pushData(scicos_block * block, int input);
+
+/*****************************************************************************
+ * Graphics utils
+ ****************************************************************************/
+
+/**
+ * Get (and allocate on demand) the figure associated with the block
+ * \param block the block
+ * \return a valid figure UID or NULL on error
+ */
+static char *getFigure(scicos_block * block);
+
+/**
+ * Get (and allocate on demand) the axe associated with the input
+ *
+ * \param pFigureUID the parent figure UID
+ * \param block the block
+ * \return a valid axe UID or NULL on error
+ */
+static char *getAxe(char *pFigureUID, scicos_block * block);
+
+/**
+ * Get (and allocate on demand) the segs associated with the input
+ *
+ * \param pAxeUID the parent axe UID
+ * \param block the block
+ * \param input the current row index (0-indexed)
+ * \return a valid polyline UID or NULL on error
+ */
+static char *getSegs(char *pAxeUID, scicos_block * block, int input);
+
+/**
+ * Set the segs buffer size
+ *
+ * \param block the block
+ * \param maxNumberOfPoints the size of the buffer
+ */
+static BOOL setSegsBuffers(scicos_block * block, int maxNumberOfPoints);
+
+/**
+ * Set the axes bounds
+ *
+ * \param block the block
+ * \param periodCounter number of past periods since startup
+ */
+static BOOL setBounds(scicos_block * block, int periodCounter);
+
+/*****************************************************************************
+ * Simulation function
+ ****************************************************************************/
+
+/** \fn void cscope(scicos_block * block,int flag)
+    \brief the computational function
+    \param block A pointer to a scicos_block
+    \param flag An int which indicates the state of the block (init, update, ending)
 */
-SCICOS_BLOCKS_IMPEXP void cevscpe_draw(scicos_block * block, ScopeMemory ** pScopeMemory, int firstdraw)
+SCICOS_BLOCKS_IMPEXP void cevscpe(scicos_block * block, scicos_flag flag)
 {
-  /* Declarations */
+    char *pFigureUID;
+
+    double t;
+    int i;
+    int mask;
+    int nclk = block->nipar - 6;
+    sco_data *sco;
 
-  int nipar = 0; //Number of elements in ipar vector
-  int i; //As usual
-  int * ipar = NULL;
-  double * rpar = NULL; //Integer Parameter
-  int nbr_colors = 0; //Number of colors and lines IS ALSO number of channels
-  int win = 0; //To give a name to the window
-  int color_flag = 0; //0/1 color flag -- NOT USED
-  int  * colors = NULL; //Begin at ipar[2] and has a measure of 8 max
-  int dimension = 2;
-  double period = 0.; //Refresh Period of the scope is a vector here
-  int number_of_subwin = 0;
-  int number_of_curves_by_subwin = 0;
-  double xmin = 0., xmax = 0., ymin = 0., ymax = 0;
-  int win_pos[2], win_dim[2];
-  char *label = NULL;
+    BOOL result;
 
-  /* Initialization */
-  ipar =  GetIparPtrs(block);
-  win = ipar[0];
-  color_flag = ipar[1]; /*not used*/
-  rpar = GetRparPtrs(block);
-  period = rpar[0];
-  nipar = GetNipar(block);
-  label = GetLabelPtrs(block);
-  nbr_colors = nipar-6;
-  colors=(int*)scicos_malloc(nbr_colors*sizeof(int));
-  for( i = 2 ; i < nbr_colors+2 ; i++)
+    switch (flag)
     {
-      colors[i-2] = ipar[i];
+
+    case Initialization:
+        sco = getScoData(block);
+        if (sco == NULL)
+        {
+            set_block_error(-5);
+        }
+        pFigureUID = getFigure(block);
+        if (pFigureUID == NULL)
+        {
+            // allocation error
+            set_block_error(-5);
+            break;
+        }
+
+        setSegsBuffers(block, DEFAULT_MAX_NUMBER_OF_POINTS);
+        break;
+
+    case StateUpdate:
+        pFigureUID = getFigure(block);
+
+        t = get_scicos_time();
+
+        // select only the masked indexes
+        for (i = 0; i < nclk; i++)
+        {
+            mask = 1 << i;
+            if ((block->nevprt & mask) == mask)
+            {
+                appendData(block, i, t);
+
+                result = pushData(block, i);
+                if (result == FALSE)
+                {
+                    Coserror("%s: unable to push some data.", "cevscpe");
+                    break;
+                }
+            }
+        }
+        break;
+
+    case Ending:
+        freeScoData(block);
+        break;
+
+    default:
+        break;
     }
+}
 
-  number_of_subwin = 1;
-  number_of_curves_by_subwin = nbr_colors;
+/*-------------------------------------------------------------------------*/
 
-  ymin = 0;
-  ymax = 1;
+/*****************************************************************************
+ *
+ * Container management
+ *
+ ****************************************************************************/
 
-  win_pos[0] = ipar[(nipar-1) - 3];
-  win_pos[1] = ipar[(nipar-1) - 2];
-  win_dim[0] = ipar[(nipar-1) - 1];
-  win_dim[1] = ipar[nipar-1];
+static sco_data *getScoData(scicos_block * block)
+{
+    sco_data *sco = (sco_data *) * (block->work);
+    int i, j;
+
+    int nclk = block->nipar - 6;
 
-  if(firstdraw == 1)
+    if (sco == NULL)
     {
-      scoInitScopeMemory(block->work,pScopeMemory, number_of_subwin, &number_of_curves_by_subwin);
-      scoSetLongDrawSize(*pScopeMemory,0,5000);
-      scoSetShortDrawSize(*pScopeMemory,0,1);
-      scoSetPeriod(*pScopeMemory,0,period);
+        /*
+         * Data allocation
+         */
+
+        sco = (sco_data *) MALLOC(sizeof(sco_data));
+        if (sco == NULL)
+            goto error_handler_sco;
+
+        sco->internal.numberOfPoints = (int *)CALLOC(nclk, sizeof(int));
+        if (sco->internal.numberOfPoints == NULL)
+        {
+            goto error_handler_numberOfPoints;
+        }
+        sco->internal.maxNumberOfPoints = (int *)MALLOC(nclk * sizeof(int));
+        if (sco->internal.numberOfPoints == NULL)
+        {
+            goto error_handler_maxNumberOfPoints;
+        }
+        for (i = 0; i < nclk; i++)
+        {
+            sco->internal.maxNumberOfPoints[i] = DEFAULT_MAX_NUMBER_OF_POINTS;
+        }
+
+        sco->internal.data = (double **)CALLOC(2 * nclk, sizeof(double *));
+        if (sco->internal.data == NULL)
+            goto error_handler_data;
+
+        for (i = 0; i < nclk; i++)
+        {
+            /*
+             * Alloc base pointer
+             */
+            sco->internal.data[2 * i + 0] = (double *)CALLOC(3 * DEFAULT_MAX_NUMBER_OF_POINTS, sizeof(double));
+            if (sco->internal.data[2 * i + 0] == NULL)
+                goto error_handler_data_i;
+
+            /*
+             * Alloc direction pointer
+             */
+            sco->internal.data[2 * i + 1] = (double *)CALLOC(3 * DEFAULT_MAX_NUMBER_OF_POINTS, sizeof(double));
+            if (sco->internal.data[2 * i + 1] == NULL)
+            {
+                FREE(sco->internal.data[2 * i + 0]);
+                goto error_handler_data_i;
+            }
+        }
+
+        sco->scope.periodCounter = 0;
+        sco->scope.cachedFigureUID = NULL;
+        sco->scope.cachedAxeUID = NULL;
+        sco->scope.cachedSegsUIDs = (char **)CALLOC(nclk, sizeof(char *));
+        if (sco->scope.cachedSegsUIDs == NULL)
+        {
+            goto error_handler_data_i;
+        }
+
+        *(block->work) = sco;
     }
 
-  xmin = period*scoGetPeriodCounter(*pScopeMemory,0);
-  xmax = period*(scoGetPeriodCounter(*pScopeMemory,0)+1);
+    return sco;
 
-  scoInitOfWindow(*pScopeMemory, dimension, win, win_pos, win_dim, &xmin, &xmax, &ymin, &ymax, NULL, NULL);
-  if(scoGetScopeActivation(*pScopeMemory) == 1)
+    /*
+     * Error management (out of normal flow)
+     */
+
+error_handler_data_i:
+    for (j = 0; j < i; j++)
     {
-      scoAddTitlesScope(*pScopeMemory,label,"t","y",NULL);
-      scoAddCoupleOfSegments(*pScopeMemory,colors);
+        FREE(sco->internal.data[2 * j + 0]);
+        FREE(sco->internal.data[2 * j + 1]);
     }
-  scicos_free(colors);
+    FREE(sco->internal.data);
+error_handler_data:
+    FREE(sco->internal.maxNumberOfPoints);
+error_handler_maxNumberOfPoints:
+    FREE(sco->internal.numberOfPoints);
+error_handler_numberOfPoints:
+    FREE(sco);
+error_handler_sco:
+    // allocation error
+    set_block_error(-5);
+    return NULL;
+}
+
+static void freeScoData(scicos_block * block)
+{
+    sco_data *sco = getScoData(block);
+    int i;
+
+    int nclk = block->nipar - 6;
+
+    if (sco != NULL)
+    {
+        for (i = 0; i < nclk; i++)
+        {
+            FREE(sco->internal.data[i]);
+        }
+        FREE(sco->internal.data);
+        FREE(sco->internal.maxNumberOfPoints);
+        FREE(sco->internal.numberOfPoints);
 
-    /* use only single buffering to be sure to draw on the screen */
-    if (scoGetPointerScopeWindow(*pScopeMemory) != NULL) {
-        sciSetJavaUseSingleBuffer(scoGetPointerScopeWindow(*pScopeMemory), TRUE);
+//      Commented due to the C++ allocation
+//      see http://bugzilla.scilab.org/show_bug.cgi?id=9747
+//      FREE(sco->scope.cachedFigureUID);
+//      FREE(sco->scope.cachedAxeUID);
+//      sco->scope.cachedFigureUID = NULL;
+//      for (i=0; i<nclk; i++) {
+//              FREE(sco->scope.cachedPolylinesUIDs[i]);
+//              sco->scope.cachedPolylinesUIDs[i] = NULL;
+//      }
+//      sco->scope.cachedAxeUID = NULL;
+
+        FREE(sco->scope.cachedSegsUIDs);
+
+        FREE(sco);
     }
 }
-/*--------------------------------------------------------------------------*/
-/** \fn void cevscpe(scicos_block * block, int flag)
-    \brief the computational function
-    \param block A pointer to a scicos_block
-    \param flag An int which indicates the state of the block (init, update, ending)
-*/
-SCICOS_BLOCKS_IMPEXP void cevscpe(scicos_block * block, int flag)
+
+static sco_data *reallocScoData(scicos_block * block, int input, int numberOfPoints)
 {
+    sco_data *sco = getScoData(block);
+    double *ptr;
+    int maxNumberOfPoints = sco->internal.maxNumberOfPoints[input];
+    int setLen;
 
-  ScopeMemory * pScopeMemory = NULL;
-  int nbseg = 0;
-  int tab[20];
-  scoGraphicalObject pShortDraw, pLongDraw;
-  int i = 0;
-  double t = 0;
+    /*
+     * Realloc base pointer
+     */
+    ptr = (double *)REALLOC(sco->internal.data[2 * input], 3 * numberOfPoints * sizeof(double));
+    if (ptr == NULL)
+        goto error_handler;
 
-  switch(flag)
+    for (setLen = numberOfPoints - maxNumberOfPoints; setLen >= 0; setLen--)
     {
-    case Initialization:
-      {
-    cevscpe_draw(block,&pScopeMemory,1);
-    break;
-      }
+        ptr[3 * (maxNumberOfPoints + setLen) + 0] = ptr[3 * (maxNumberOfPoints - 1) + 0];
+        ptr[3 * (maxNumberOfPoints + setLen) + 1] = ptr[3 * (maxNumberOfPoints - 1) + 1];
+        ptr[3 * (maxNumberOfPoints + setLen) + 2] = ptr[3 * (maxNumberOfPoints - 1) + 2];
+    }
+    sco->internal.data[2 * input] = ptr;
 
-    case StateUpdate:
-      {
+    /*
+     * Realloc direction pointer
+     */
+    ptr = (double *)REALLOC(sco->internal.data[2 * input + 1], 3 * numberOfPoints * sizeof(double));
+    if (ptr == NULL)
+        goto error_handler;
 
-    /* Charging elements */
+    for (setLen = numberOfPoints - maxNumberOfPoints; setLen >= 0; setLen--)
+    {
+        ptr[3 * (maxNumberOfPoints + setLen) + 0] = ptr[3 * (maxNumberOfPoints - 1) + 0];
+        ptr[3 * (maxNumberOfPoints + setLen) + 1] = ptr[3 * (maxNumberOfPoints - 1) + 1];
+        ptr[3 * (maxNumberOfPoints + setLen) + 2] = ptr[3 * (maxNumberOfPoints - 1) + 2];
+    }
+    sco->internal.data[2 * input + 1] = ptr;
 
-    scoRetrieveScopeMemory(block->work,&pScopeMemory);
+    sco->internal.maxNumberOfPoints[input] = numberOfPoints;
+    return sco;
 
-    if(scoGetScopeActivation(pScopeMemory) == 1)
-      {
+error_handler:
+    freeScoData(block);
+    // allocation error
+    set_block_error(-5);
+    return NULL;
+}
 
-        t = get_scicos_time();
-        if(scoGetPointerScopeWindow(pScopeMemory) == NULL)
-          {
-        cevscpe_draw(block,&pScopeMemory,0);
-          }
-
-        scoRefreshDataBoundsX(pScopeMemory,t);
-
-        /*Not Factorize*/
-
-        for(i = 0 ; i < scoGetNumberOfCurvesBySubwin(pScopeMemory,0) ; i++)
-          {
-        if((GetNevIn(block)&(1<<i))==(1<<i))
-          {
-            tab[nbseg]=i;
-            nbseg++;
-          }
-          }
-
-        for(i = 0 ; i < nbseg ; i++)
-          {
-        pShortDraw = scoGetPointerShortDraw(pScopeMemory,0,tab[i]);
-        pSEGS_FEATURE(pShortDraw)->vx[0] = t;
-        pSEGS_FEATURE(pShortDraw)->vx[1] = t;
-        pSEGS_FEATURE(pShortDraw)->vy[0] = i*0.8/nbseg;
-        pSEGS_FEATURE(pShortDraw)->vy[1] = (i+1)*0.8/nbseg;
-        pSEGS_FEATURE(pShortDraw)->Nbr1 = 2;
-        pSEGS_FEATURE(pShortDraw)->Nbr2 = 2;
-          }
-        /*End of Not Factorize*/
-        scoDrawScopeAmplitudeTimeStyle(pScopeMemory,t);
-      }
-    break;
-      }
+static void appendData(scicos_block * block, int input, double t)
+{
+    sco_data *sco = getScoData(block);
+    int maxNumberOfPoints = sco->internal.maxNumberOfPoints[input];
+    int numberOfPoints = sco->internal.numberOfPoints[input];
 
-    case Ending:
-      {
+    /*
+     * Handle the case where the t is greater than the data_bounds
+     */
+    if (t > ((sco->scope.periodCounter + 1) * block->rpar[0]))
+    {
+        sco->scope.periodCounter++;
 
-                scoRetrieveScopeMemory(block->work, &pScopeMemory);
-                if(scoGetScopeActivation(pScopeMemory) == 1)
-                {
-                    /* sciSetUsedWindow(scoGetWindowID(pScopeMemory)); */
-                    /* Check if figure is still opened, otherwise, don't try to destroy it again. */
-                    if(scoGetPointerScopeWindow(pScopeMemory) != NULL)
-                    {
-                        for(i = 0 ; i < scoGetNumberOfCurvesBySubwin(pScopeMemory,0) ; i++)
-                        {
-                            /* maybe a bug here in the last argument of the following instruction (see tab[i]) */
-                            pLongDraw = scoGetPointerLongDraw(pScopeMemory,0,i);
-                            forceRedraw(pLongDraw);
-                        }
-
-
-                        /* pShortDraw = sciGetCurrentFigure(); */
-                        pShortDraw = scoGetPointerScopeWindow(pScopeMemory);
-                        clearUserData(pShortDraw);
-                        /* pFIGURE_FEATURE(pShortDraw)->user_data = NULL; */
-                        /* pFIGURE_FEATURE(pShortDraw)->size_of_user_data = 0; */
-                        /* restore double buffering */
-                        if (pShortDraw) {
-                            sciSetJavaUseSingleBuffer(pShortDraw, FALSE);
-                        }
-                        scoDelCoupleOfSegments(pScopeMemory);
-                    }
-                }
-                scoFreeScopeMemory(block->work,&pScopeMemory);
-                break;
+        numberOfPoints = 0;
+        sco->internal.numberOfPoints[input] = 0;
+        if (setBounds(block, sco->scope.periodCounter) == FALSE)
+        {
+            set_block_error(-5);
+            freeScoData(block);
+            sco = NULL;
+        }
+    }
+
+    /*
+     * Handle the case where the scope has more points than maxNumberOfPoints
+     */
+    if (sco != NULL && numberOfPoints >= maxNumberOfPoints)
+    {
+        // on a full scope, re-alloc
+        maxNumberOfPoints = maxNumberOfPoints + DEFAULT_MAX_NUMBER_OF_POINTS;
+        sco = reallocScoData(block, input, maxNumberOfPoints);
+
+        // reconfigure related graphic objects
+        if (setSegsBuffers(block, maxNumberOfPoints) == FALSE)
+        {
+            set_block_error(-5);
+            freeScoData(block);
+            sco = NULL;
+        }
+    }
+
+    /*
+     * Update data
+     */
+    if (sco != NULL)
+    {
+        int setLen;
+
+        /*
+         * Base pointer
+         */
+        for (setLen = maxNumberOfPoints - numberOfPoints; setLen >= 0; setLen--)
+        {
+            sco->internal.data[2 * input][3 * (numberOfPoints + setLen) + 0] = t;   // x
+            sco->internal.data[2 * input][3 * (numberOfPoints + setLen) + 1] = 0;   // y
+            sco->internal.data[2 * input][3 * (numberOfPoints + setLen) + 2] = (double)input;   // z
+        }
+
+        /*
+         * Direction pointer
+         */
+        for (setLen = maxNumberOfPoints - numberOfPoints; setLen >= 0; setLen--)
+        {
+            sco->internal.data[2 * input][3 * (numberOfPoints + setLen) + 0] = t;   // x
+            sco->internal.data[2 * input][3 * (numberOfPoints + setLen) + 1] = 0.8; // y
+            sco->internal.data[2 * input][3 * (numberOfPoints + setLen) + 2] = (double)input;   // z
+        }
+
+        sco->internal.numberOfPoints[input]++;
+    }
+}
+
+static BOOL pushData(scicos_block * block, int input)
+{
+    char *pFigureUID;
+    char *pAxeUID;
+    char *pSegsUID;
+
+    int dataLen;
+    double *base;
+    double *direction;
+    sco_data *sco;
+
+    BOOL result = TRUE;
+
+    pFigureUID = getFigure(block);
+    pAxeUID = getAxe(pFigureUID, block);
+    pSegsUID = getSegs(pAxeUID, block, input);
+
+    sco = getScoData(block);
+    if (sco == NULL)
+        return FALSE;
+
+    // select the right input and row
+    base = sco->internal.data[2 * input];
+    direction = sco->internal.data[2 * input + 1];
+
+    dataLen = 3 * sco->internal.maxNumberOfPoints[input];
+
+    result &= setGraphicObjectProperty(pSegsUID, __GO_BASE__, base, jni_double_vector, dataLen);
+    result &= setGraphicObjectProperty(pSegsUID, __GO_DIRECTION__, direction, jni_double_vector, dataLen);
+
+    return result;
+}
+
+/*****************************************************************************
+ *
+ * Graphic utils
+ *
+ ****************************************************************************/
+
+/**
+ * Set properties on the figure.
+ *
+ * \param pFigureUID the figure uid
+ * \param block the current block
+ */
+static void setFigureSettings(char *pFigureUID, scicos_block * block)
+{
+    int nipar = GetNipar(block);
+    int *ipar = GetIparPtrs(block);
+
+    int win_pos[2];
+    int win_dim[2];
+
+    win_pos[0] = ipar[(nipar - 1) - 3];
+    win_pos[1] = ipar[(nipar - 1) - 2];
+    win_dim[0] = ipar[(nipar - 1) - 1];
+    win_dim[1] = ipar[nipar - 1];
+
+    setGraphicObjectProperty(pFigureUID, __GO_POSITION__, &win_pos, jni_int_vector, 2);
+    setGraphicObjectProperty(pFigureUID, __GO_SIZE__, &win_dim, jni_int_vector, 2);
+};
+
+/*****************************************************************************
+ *
+ * Graphic
+ *
+ ****************************************************************************/
+
+static char *getFigure(scicos_block * block)
+{
+    signed int figNum;
+    char *pFigureUID = NULL;
+    char *pAxe = NULL;
+    static const int i__1 = 1;
+    sco_data *sco = getScoData(block);
+
+    // fast path for an existing object
+    if (sco->scope.cachedFigureUID != NULL)
+    {
+        return sco->scope.cachedFigureUID;
+    }
+
+    figNum = block->ipar[0];
+
+    // with a negative id, use the block number indexed from a constant.
+    if (figNum < 0)
+    {
+        figNum = 20000 + get_block_number();
+    }
+
+    pFigureUID = getFigureFromIndex(figNum);
+    // create on demand
+    if (pFigureUID == NULL)
+    {
+        pFigureUID = createNewFigureWithAxes();
+        setGraphicObjectProperty(pFigureUID, __GO_ID__, &figNum, jni_int, 1);
+
+        // set configured parameters
+        setFigureSettings(pFigureUID, block);
+
+        // allocate the axes through the getter
+        pAxe = getAxe(pFigureUID, block);
+
+        /*
+         * Setup according to block settings
+         */
+        setLabel(pAxe, __GO_X_AXIS_LABEL__, "t");
+        setLabel(pAxe, __GO_Y_AXIS_LABEL__, "y");
+
+        setGraphicObjectProperty(pAxe, __GO_X_AXIS_VISIBLE__, &i__1, jni_bool, 1);
+        setGraphicObjectProperty(pAxe, __GO_Y_AXIS_VISIBLE__, &i__1, jni_bool, 1);
+
+        setBounds(block, 0);
+
+        sco->scope.cachedFigureUID = pFigureUID;
+    }
+
+    if (sco->scope.cachedFigureUID == NULL)
+    {
+        sco->scope.cachedFigureUID = pFigureUID;
+    }
+    return pFigureUID;
+}
+
+static char *getAxe(char *pFigureUID, scicos_block * block)
+{
+    char *pAxe;
+    int i;
+
+    int nclk = block->nipar - 6;
+    sco_data *sco = getScoData(block);
+
+    // fast path for an existing object
+    if (sco->scope.cachedAxeUID != NULL)
+    {
+        return sco->scope.cachedAxeUID;
+    }
+
+    pAxe = findChildWithKindAt(pFigureUID, __GO_AXES__, 0);
+
+    /*
+     * Allocate if necessary
+     */
+    if (pAxe == NULL)
+    {
+        pAxe = cloneGraphicObject(getAxesModel());
+
+        if (pAxe != NULL)
+        {
+            setGraphicObjectRelationship(pFigureUID, pAxe);
+
+            // allocate the segs through the getter
+            for (i = 0; i < nclk; i++)
+            {
+                getSegs(pAxe, block, i);
+            }
+
+            sco->scope.cachedAxeUID = pAxe;
+        }
+    }
+
+    if (sco->scope.cachedAxeUID == NULL)
+    {
+        sco->scope.cachedAxeUID = pAxe;
+    }
+    return pAxe;
+}
+
+static char *getSegs(char *pAxeUID, scicos_block * block, int input)
+{
+    char *pSegs;
+    static const BOOL b__true = TRUE;
+    static const double d__1 = 1.0;
+
+    int color;
+
+    sco_data *sco = getScoData(block);
+
+    // fast path for an existing object
+    if (sco->scope.cachedSegsUIDs != NULL && sco->scope.cachedSegsUIDs[input] != NULL)
+    {
+        return sco->scope.cachedSegsUIDs[input];
+    }
+
+    pSegs = findChildWithKindAt(pAxeUID, __GO_SEGS__, input);
+
+    /*
+     * Allocate if necessary
+     */
+    if (pSegs == NULL)
+    {
+        pSegs = createGraphicObject(__GO_SEGS__);
+
+        if (pSegs != NULL)
+        {
+            createDataObject(pSegs, __GO_SEGS__);
+            setGraphicObjectRelationship(pAxeUID, pSegs);
+
+            setGraphicObjectProperty(pSegs, __GO_NUMBER_ARROWS__, &sco->internal.maxNumberOfPoints[input], jni_int, 1);
+
+            // Setup properties
+            setGraphicObjectProperty(pSegs, __GO_LINE_THICKNESS__, &d__1, jni_double, 1);
+
+            color = block->ipar[2 + input];
+            if (color > 0)
+            {
+                setGraphicObjectProperty(pSegs, __GO_LINE_MODE__, &b__true, jni_bool, 1);
+                setGraphicObjectProperty(pSegs, __GO_SEGS_COLORS__, &color, jni_int_vector, 1);
             }
+            else
+            {
+                color = -color;
+                setGraphicObjectProperty(pSegs, __GO_MARK_MODE__, &b__true, jni_bool, 1);
+                setGraphicObjectProperty(pSegs, __GO_MARK_STYLE__, &color, jni_int, 1);
+            }
+
+            sco->scope.cachedSegsUIDs[input] = pSegs;
+        }
+    }
+
+    if (sco->scope.cachedSegsUIDs != NULL && sco->scope.cachedSegsUIDs[input] == NULL)
+    {
+        sco->scope.cachedSegsUIDs[input] = pSegs;
+    }
+    return pSegs;
+}
+
+static BOOL setSegsBuffers(scicos_block * block, int maxNumberOfPoints)
+{
+    char *pFigureUID;
+    char *pAxeUID;
+    char *pSegsUID;
+
+    int i;
+    int nclk = block->nipar - 6;
+    BOOL result = TRUE;
+
+    int color;
+
+    pFigureUID = getFigure(block);
+    pAxeUID = getAxe(pFigureUID, block);
+    for (i = 0; i < nclk; i++)
+    {
+        pSegsUID = getSegs(pAxeUID, block, i);
+        result &= setGraphicObjectProperty(pSegsUID, __GO_NUMBER_ARROWS__, &maxNumberOfPoints, jni_int, 1);
+
+        /*
+         * Update color due to bug #9902
+         * http://bugzilla.scilab.org/show_bug.cgi?id=9902
+         */
+        color = block->ipar[2 + i];
+        if (color > 0)
+        {
+            setGraphicObjectProperty(pSegsUID, __GO_SEGS_COLORS__, &color, jni_int_vector, 1);
+        }
+
     }
+
+    return result;
+}
+
+static BOOL setBounds(scicos_block * block, int periodCounter)
+{
+    char *pFigureUID;
+    char *pAxeUID;
+
+    double dataBounds[6];
+    double period = block->rpar[0];
+
+    dataBounds[0] = periodCounter * period; // xMin
+    dataBounds[1] = (periodCounter + 1) * period;   // xMax
+    dataBounds[2] = 0;          // yMin
+    dataBounds[3] = 1;          // yMax
+    dataBounds[4] = -1.0;       // zMin
+    dataBounds[5] = 1.0;        // zMax
+
+    pFigureUID = getFigure(block);
+    pAxeUID = getAxe(pFigureUID, block);
+    return setGraphicObjectProperty(pAxeUID, __GO_DATA_BOUNDS__, dataBounds, jni_double_vector, 6);
 }
-/*--------------------------------------------------------------------------*/