Scicos blocks: use the new MVC graphic for scopes
[scilab.git] / scilab / modules / scicos_blocks / src / c / cmatview.c
1 /*
2  *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  *  Copyright (C) 2011 - Scilab Enterprises - ClĂ©ment DAVID
4  *
5  *  This file must be used under the terms of the CeCILL.
6  *  This source file is licensed as described in the file COPYING, which
7  *  you should have received as part of this distribution.  The terms
8  *  are also available at
9  *  http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
10  *
11  */
12
13 #include "dynlib_scicos_blocks.h"
14 #include "scoUtils.h"
15
16 #include "MALLOC.h"
17 #include "elementary_functions.h"
18
19 #include "getGraphicObjectProperty.h"
20 #include "setGraphicObjectProperty.h"
21 #include "graphicObjectProperties.h"
22 #include "createGraphicObject.h"
23
24 #include "CurrentFigure.h"
25
26 #include "scicos_block4.h"
27 #include "scicos.h"
28 #include "math.h"
29
30 #include "localization.h"
31
32 #include "FigureList.h"
33 #include "BuildObjects.h"
34 #include "AxesModel.h"
35
36 /*****************************************************************************
37  * Internal container structure
38  ****************************************************************************/
39
40 /**
41  * Container structure
42  */
43 typedef struct
44 {
45     struct
46     {
47         char *cachedFigureUID;
48         char *cachedAxeUID;
49         char *cachedGrayplotUID;
50     } scope;
51 } sco_data;
52
53 /**
54  * Get (and allocate on demand) the internal data used on this scope
55  * \param block the block
56  * \return the scope data
57  */
58 static sco_data *getScoData(scicos_block * block);
59
60 /**
61  * Release any internal data
62  *
63  * \param block the block
64  */
65 static void freeScoData(scicos_block * block);
66
67 /**
68  * Push the block data to the polyline
69  *
70  * \param data the data to push
71  *
72  */
73 static BOOL pushData(scicos_block * block, double *data);
74
75 /*****************************************************************************
76  * Graphics utils
77  ****************************************************************************/
78
79 /**
80  * Get (and allocate on demand) the figure associated with the block
81  * \param block the block
82  * \return a valid figure UID or NULL on error
83  */
84 static char *getFigure(scicos_block * block);
85
86 /**
87  * Get (and allocate on demand) the axe associated with the input
88  *
89  * \param pFigureUID the parent figure UID
90  * \param block the block
91  * \return a valid axe UID or NULL on error
92  */
93 static char *getAxe(char *pFigureUID, scicos_block * block);
94
95 /**
96  * Get (and allocate on demand) the grayplot
97  *
98  * \param pAxeUID the parent axe UID
99  * \param block the block
100  * \return a valid grayplot UID or NULL on error
101  */
102 static char *getGrayplot(char *pAxeUID, scicos_block * block);
103
104 /**
105  * Set the grayplot and axes bounds
106  *
107  * \param block the block
108  * \param pAxeUID the axe
109  * \param pGrayplotUID the grayplot
110  */
111 static BOOL setBounds(scicos_block * block, char *pAxeUID, char *pGrayplotUID);
112
113 /**
114  * Set the grayplot default values
115  *
116  * \param block the block
117  * \param pGrayplotUID the grayplot
118  */
119 static BOOL setDefaultValues(scicos_block * block, char *pGrayplotUID);
120
121 /*****************************************************************************
122  * Simulation function
123  ****************************************************************************/
124
125 /** \fn void cmatview(scicos_block * block,int flag)
126     \brief the computational function
127     \param block A pointer to a scicos_block
128     \param flag An int which indicates the state of the block (init, update, ending)
129 */
130 SCICOS_BLOCKS_IMPEXP void cmatview(scicos_block * block, scicos_flag flag)
131 {
132     char *pFigureUID;
133
134     double *u;
135     sco_data *sco;
136
137     int i;
138     BOOL result;
139
140     switch (flag)
141     {
142
143     case Initialization:
144         sco = getScoData(block);
145         if (sco == NULL)
146         {
147             set_block_error(-5);
148         }
149         pFigureUID = getFigure(block);
150         if (pFigureUID == NULL)
151         {
152             // allocation error
153             set_block_error(-5);
154         }
155         break;
156
157     case StateUpdate:
158         pFigureUID = getFigure(block);
159
160         u = GetRealInPortPtrs(block, 1);
161
162         result = pushData(block, u);
163         if (result == FALSE)
164         {
165             Coserror("%s: unable to push some data.", "cmatview");
166             break;
167         }
168         break;
169
170     case Ending:
171         freeScoData(block);
172         break;
173
174     default:
175         break;
176     }
177 }
178
179 /*-------------------------------------------------------------------------*/
180
181 /*****************************************************************************
182  *
183  * Container management
184  *
185  ****************************************************************************/
186
187 static sco_data *getScoData(scicos_block * block)
188 {
189     sco_data *sco = (sco_data *) * (block->work);
190     BOOL result;
191
192     if (sco == NULL)
193     {
194         /*
195          * Data allocation
196          */
197
198         sco = (sco_data *) MALLOC(sizeof(sco_data));
199         if (sco == NULL)
200             goto error_handler_sco;
201
202         sco->scope.cachedFigureUID = NULL;
203         sco->scope.cachedAxeUID = NULL;
204         sco->scope.cachedGrayplotUID = NULL;
205
206         *(block->work) = sco;
207     }
208
209     return sco;
210
211     /*
212      * Error management (out of normal flow)
213      */
214
215 error_handler_sco:
216     // allocation error
217     set_block_error(-5);
218     return NULL;
219 }
220
221 static void freeScoData(scicos_block * block)
222 {
223     sco_data *sco = (sco_data *) * (block->work);
224     int i, j;
225
226     if (sco != NULL)
227     {
228         FREE(sco);
229     }
230 }
231
232 static BOOL pushData(scicos_block * block, double *data)
233 {
234     char *pFigureUID;
235     char *pAxeUID;
236     char *pGrayplotUID;
237
238     BOOL result;
239     int i;
240
241     int m, n;
242     double alpha, beta;
243     double *scaledData;
244
245     pFigureUID = getFigure(block);
246     pAxeUID = getAxe(pFigureUID, block);
247     pGrayplotUID = getGrayplot(pAxeUID, block);
248
249     m = GetInPortSize(block, 1, 1);
250     n = GetInPortSize(block, 1, 2);
251
252     /*
253      * Scale the data
254      */
255     alpha = block->rpar[0];
256     beta = block->rpar[1];
257
258     scaledData = (double *)MALLOC(m * n * sizeof(double));
259     if (scaledData == NULL)
260     {
261         return FALSE;
262     }
263
264     for (i = 0; i < m * n; i++)
265     {
266         scaledData[i] = floor(alpha * data[i] + beta);
267     }
268
269     result = setGraphicObjectProperty(pGrayplotUID, __GO_DATA_MODEL_Z__, scaledData, jni_double_vector, m * n);
270     FREE(scaledData);
271
272     return result;
273 }
274
275 /*****************************************************************************
276  *
277  * Graphic utils
278  *
279  ****************************************************************************/
280
281 /*****************************************************************************
282  *
283  * Graphic
284  *
285  ****************************************************************************/
286
287 static char *getFigure(scicos_block * block)
288 {
289     signed int figNum;
290     char *pFigureUID = NULL;
291     char *pAxe = NULL;
292     static const int i__1 = 1;
293     sco_data *sco = (sco_data *) * (block->work);
294
295     int i, j;
296
297     // fast path for an existing object
298     if (sco->scope.cachedFigureUID != NULL)
299     {
300         return sco->scope.cachedFigureUID;
301     }
302
303     figNum = block->ipar[0];
304
305     // with a negative id, use the block number indexed from a constant.
306     if (figNum < 0)
307     {
308         figNum = 20000 + get_block_number();
309     }
310
311     pFigureUID = getFigureFromIndex(figNum);
312     // create on demand
313     if (pFigureUID == NULL)
314     {
315         pFigureUID = createNewFigureWithAxes();
316         setGraphicObjectProperty(pFigureUID, __GO_ID__, &figNum, jni_int, 1);
317
318         setGraphicObjectProperty(pFigureUID, __GO_COLORMAP__, &block->rpar[2], jni_double_vector, block->ipar[2]);
319
320         // allocate the axes through the getter
321         pAxe = getAxe(pFigureUID, block);
322
323         /*
324          * Setup according to block settings
325          */
326         setLabel(pAxe, __GO_X_AXIS_LABEL__, "x");
327         setLabel(pAxe, __GO_Y_AXIS_LABEL__, "y");
328
329         setGraphicObjectProperty(pAxe, __GO_X_AXIS_VISIBLE__, &i__1, jni_bool, 1);
330         setGraphicObjectProperty(pAxe, __GO_Y_AXIS_VISIBLE__, &i__1, jni_bool, 1);
331
332         sco->scope.cachedFigureUID = pFigureUID;
333     }
334
335     if (sco->scope.cachedFigureUID == NULL)
336     {
337         sco->scope.cachedFigureUID = pFigureUID;
338     }
339     return pFigureUID;
340 }
341
342 static char *getAxe(char *pFigureUID, scicos_block * block)
343 {
344     char *pAxe;
345     int i;
346     sco_data *sco = (sco_data *) * (block->work);
347
348     // fast path for an existing object
349     if (sco->scope.cachedAxeUID != NULL)
350     {
351         return sco->scope.cachedAxeUID;
352     }
353
354     pAxe = findChildWithKindAt(pFigureUID, __GO_AXES__, 0);
355
356     /*
357      * Allocate if necessary
358      */
359     if (pAxe == NULL)
360     {
361         pAxe = cloneGraphicObject(getAxesModel());
362
363         if (pAxe != NULL)
364         {
365             setGraphicObjectRelationship(pFigureUID, pAxe);
366
367             getGrayplot(pAxe, block);
368         }
369     }
370
371     if (sco->scope.cachedAxeUID == NULL)
372     {
373         sco->scope.cachedAxeUID = pAxe;
374     }
375     return pAxe;
376 }
377
378 static char *getGrayplot(char *pAxeUID, scicos_block * block)
379 {
380     char *pGrayplot;
381     static const double d__0 = 0.0;
382     static const int i__0 = 0;
383     static const BOOL b__true = TRUE;
384
385     int color;
386
387     sco_data *sco = (sco_data *) * (block->work);
388
389     // fast path for an existing object
390     if (sco->scope.cachedGrayplotUID != NULL)
391     {
392         return sco->scope.cachedGrayplotUID;
393     }
394
395     pGrayplot = findChildWithKindAt(pAxeUID, __GO_GRAYPLOT__, 1);
396
397     /*
398      * Allocate if necessary
399      */
400     if (pGrayplot == NULL)
401     {
402         pGrayplot = createGraphicObject(__GO_GRAYPLOT__);
403
404         if (pGrayplot != NULL)
405         {
406             createDataObject(pGrayplot, __GO_GRAYPLOT__);
407             setGraphicObjectRelationship(pAxeUID, pGrayplot);
408
409             setGraphicObjectProperty(pGrayplot, __GO_DATA_MAPPING__, &i__0, jni_int, 1);
410             setBounds(block, pAxeUID, pGrayplot);
411             setDefaultValues(block, pGrayplot);
412         }
413     }
414
415     if (sco->scope.cachedGrayplotUID == NULL)
416     {
417         sco->scope.cachedGrayplotUID = pGrayplot;
418     }
419     return pGrayplot;
420 }
421
422 static BOOL setBounds(scicos_block * block, char *pAxeUID, char *pGrayplotUID)
423 {
424     BOOL result;
425
426     int gridSize[4];
427     double dataBounds[6];
428
429     int m, n;
430
431     m = GetInPortSize(block, 1, 1);
432     n = GetInPortSize(block, 1, 2);
433
434     gridSize[0] = m;
435     gridSize[1] = 1;
436     gridSize[2] = n;
437     gridSize[3] = 1;
438
439     dataBounds[0] = 0;          // xMin
440     dataBounds[1] = (double)m;  // xMax
441     dataBounds[2] = 0;          // yMin
442     dataBounds[3] = (double)n;  // yMax
443     dataBounds[4] = -1.0;       // zMin
444     dataBounds[5] = 1.0;        // zMax
445
446     result = setGraphicObjectProperty(pGrayplotUID, __GO_DATA_MODEL_GRID_SIZE__, gridSize, jni_int_vector, 4);
447     result &= setGraphicObjectProperty(pAxeUID, __GO_DATA_BOUNDS__, dataBounds, jni_double_vector, 6);
448
449     return result;
450 }
451
452 static BOOL setDefaultValues(scicos_block * block, char *pGrayplotUID)
453 {
454     int m, n, len;
455     int i;
456     double *values;
457
458     BOOL result;
459
460     m = GetInPortSize(block, 1, 1);
461     n = GetInPortSize(block, 1, 2);
462
463     len = max(m, n);
464
465     values = (double *)CALLOC(n * m, sizeof(double));
466     if (values == NULL)
467     {
468         return FALSE;
469     }
470
471     result = setGraphicObjectProperty(pGrayplotUID, __GO_DATA_MODEL_Z__, values, jni_double_vector, m * n);
472
473     for (i = 1; i <= len; i++)
474     {
475         values[i] = (double)i;
476     }
477     result &= setGraphicObjectProperty(pGrayplotUID, __GO_DATA_MODEL_X__, values, jni_double_vector, m);
478     result &= setGraphicObjectProperty(pGrayplotUID, __GO_DATA_MODEL_Y__, values, jni_double_vector, n);
479
480     FREE(values);
481     return result;
482 }