Update figure function :
[scilab.git] / scilab / modules / gui / sci_gateway / c / sci_figure.c
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2014 - Scilab Enterprises - Antoine ELIAS
4  * Copyright (C) 2014 - Scilab Enterprises - Bruno JOFRET
5  *
6  * This file must be used under the terms of the CeCILL.
7  * This source file is licensed as described in the file COPYING, which
8  * you should have received as part of this distribution.  The terms
9  * are also available at
10  * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt
11  *
12  */
13
14 #include "gw_gui.h"
15 #include "MALLOC.h"
16 #include "api_scilab.h"
17 #include "localization.h"
18 #include "Scierror.h"
19 #include "createGraphicObject.h"
20 #include "BuildObjects.h"
21 #include "setGraphicObjectProperty.h"
22 #include "getGraphicObjectProperty.h"
23 #include "graphicObjectProperties.h"
24 #include "CurrentFigure.h"
25 #include "CurrentSubwin.h"
26 #include "FigureList.h"
27 #include "HandleManagement.h"
28 #include "SetHashTable.h"
29 #include "stricmp.h"
30 #ifdef _MSC_VER
31 #include "strdup_windows.h"
32 #endif
33
34 #include "sciprint.h"
35 #include "addColor.h"
36
37 /*--------------------------------------------------------------------------*/
38 int setDefaultProperties(int _iFig, BOOL bDefaultAxes);
39 /*--------------------------------------------------------------------------*/
40 int sci_figure(char * fname, unsigned long fname_len)
41 {
42     SciErr sciErr;
43     int* piAddr = NULL;
44     int iFig = 0;
45     int iRhs = nbInputArgument(pvApiCtx);
46     int iId = 0;
47     int iPos = 0;
48     int i = 0;
49     int iNewId = -1;
50     int iAxes = 0;
51     int iPropertyOffset = 0;
52     BOOL bDoCreation = TRUE;
53     BOOL bVisible = TRUE; // Create a visible figure by default
54     BOOL bDockable = TRUE; // Create a dockable figure by default
55     BOOL bDefaultAxes = TRUE; // Create an Axes by default
56     int iMenubarType = 1; // Create a 'figure' menubar by default
57     int iToolbarType = 1; // Create a 'figure' toolbar by default
58     double dblId = 0;
59     BOOL status = FALSE;
60
61     //figure(num) -> scf(num)
62     //figure() -> scf()
63
64     //figure(x, "...", ...)
65
66     // figure()
67     if (iRhs == 0) // Auto ID
68     {
69         iFig = createNewFigureWithAxes();
70         iAxes = setDefaultProperties(iFig, TRUE);
71         createScalarHandle(pvApiCtx, iRhs + 1, getHandle(iFig));
72         AssignOutputVariable(pvApiCtx, 1) = iRhs + 1;
73         ReturnArguments(pvApiCtx);
74         return 0;
75     }
76
77     if (iRhs == 1)
78     {
79         //figure(x);
80         sciErr = getVarAddressFromPosition(pvApiCtx, 1, &piAddr);
81         if (sciErr.iErr)
82         {
83             printError(&sciErr, 0);
84             Scierror(999, _("%s: Can not read input argument #%d.\n"), fname, 1);
85             return 0;
86         }
87
88         if (isVarMatrixType(pvApiCtx, piAddr) == 0)
89         {
90             Scierror(999, _("%s: Wrong type for input argument #%d: An integer value expected.\n"), fname, 1);
91             return 0;
92         }
93
94         if (getScalarDouble(pvApiCtx, piAddr, &dblId))
95         {
96             Scierror(999, _("%s: No more memory.\n"), fname);
97             return 0;
98         }
99
100         iId = (int)(dblId + 0.5); //avoid 1.999 -> 1
101
102         //get current fig from id
103         iFig = getFigureFromIndex(iId);
104         if (iFig == 0) // Figure does not exists, create a new one
105         {
106             iFig = createNewFigureWithAxes();
107             setGraphicObjectProperty(iFig, __GO_ID__, &iId, jni_int,  1);
108             iAxes = setDefaultProperties(iFig, TRUE);
109         }
110
111         createScalarHandle(pvApiCtx, iRhs + 1, getHandle(iFig));
112         AssignOutputVariable(pvApiCtx, 1) = iRhs + 1;
113         ReturnArguments(pvApiCtx);
114         return 0;
115     }
116
117     // Prepare property analysis
118     if (iRhs % 2 == 0)
119     {
120         //get highest value of winsid to create the new windows @ + 1
121         iNewId = getValidDefaultFigureId();
122         iPos = 0;
123     }
124     else
125     {
126         iPos = 1;
127         //figure(x, ...);
128         sciErr = getVarAddressFromPosition(pvApiCtx, 1, &piAddr);
129         if (sciErr.iErr)
130         {
131             printError(&sciErr, 0);
132             Scierror(999, _("%s: Can not read input argument #%d.\n"), fname, 1);
133             return 0;
134         }
135
136         if (isVarMatrixType(pvApiCtx, piAddr) == 0)
137         {
138             Scierror(999, _("%s: Wrong type for input argument #%d: An integer value expected.\n"), fname, 1);
139             return 0;
140         }
141
142         if (getScalarDouble(pvApiCtx, piAddr, &dblId))
143         {
144             Scierror(999, _("%s: No more memory.\n"), fname);
145             return 0;
146         }
147
148         iNewId = (int)(dblId + 0.5); //avoid 1.999 -> 1
149         //get current fig from id
150         iFig = getFigureFromIndex(iId);
151         if (iFig != 0) // Figure already exists
152         {
153             bDoCreation = TRUE;
154         }
155     }
156
157     if (bDoCreation)
158     {
159         int* piAddrProp = NULL;
160         char* pstProName = NULL;
161         int* piAddrData = NULL;
162         char* pstPropVal = NULL;
163         for (i = iPos + 1 ; i <= iRhs ; i += 2)
164         {
165             //get property name
166             sciErr = getVarAddressFromPosition(pvApiCtx, i, &piAddrProp);
167             if (sciErr.iErr)
168             {
169                 Scierror(999, _("%s: Can not read input argument #%d.\n"), fname, i);
170                 return 1;
171             }
172
173             if (getAllocatedSingleString(pvApiCtx, piAddrProp, &pstProName))
174             {
175                 Scierror(999, _("%s: Wrong size for input argument #%d: A single string expected.\n"), fname, i);
176                 return 1;
177             }
178             if (stricmp(pstProName, "dockable") != 0
179                     && stricmp(pstProName, "toolbar") != 0
180                     && stricmp(pstProName, "menubar") != 0
181                     && stricmp(pstProName, "default_axes") != 0
182                     && stricmp(pstProName, "visible") != 0 )
183             {
184                 freeAllocatedSingleString(pstProName);
185                 continue;
186             }
187             //get address of value on stack
188             sciErr = getVarAddressFromPosition(pvApiCtx, i + 1, &piAddrData);
189             if (sciErr.iErr)
190             {
191                 Scierror(999, _("%s: Can not read input argument #%d.\n"), fname, i + 1);
192                 return 1;
193             }
194             if (getAllocatedSingleString(pvApiCtx, piAddrData, (char**)&pstPropVal))
195             {
196                 Scierror(999, _("%s: Wrong size for input argument #%d: A single string expected.\n"), fname, 3);
197                 return 1;
198             }
199             //check property value to compatibility
200             if (stricmp(pstProName, "dockable") == 0)
201             {
202                 if (stricmp(pstPropVal, "on") == 0)
203                 {
204                     bDockable = TRUE;
205                 }
206                 else if (stricmp(pstPropVal, "off") == 0)
207                 {
208                     bDockable = FALSE;
209                 }
210                 else
211                 {
212                     Scierror(999, _("Wrong value for '%s' property: '%s' or '%s' expected."), "dockable", "on", "off");
213                     freeAllocatedSingleString(pstProName);
214                     freeAllocatedSingleString(pstPropVal);
215                     return 1;
216                 }
217             }
218             else if (stricmp(pstProName, "toolbar") == 0)
219             {
220                 if (stricmp(pstPropVal, "none") == 0)
221                 {
222                     iToolbarType = 0;
223                 }
224                 else if (stricmp(pstPropVal, "figure") == 0)
225                 {
226                     iToolbarType = 1;
227                 }
228                 else
229                 {
230                     Scierror(999, _("Wrong value for '%s' property: '%s' or '%s' expected."), "toolbar", "none", "figure");
231                     freeAllocatedSingleString(pstProName);
232                     freeAllocatedSingleString(pstPropVal);
233                     return 1;
234                 }
235             }
236             else if (stricmp(pstProName, "menubar") == 0)
237             {
238                 if (stricmp(pstPropVal, "none") == 0)
239                 {
240                     iMenubarType = 0;
241                 }
242                 else if (stricmp(pstPropVal, "figure") == 0)
243                 {
244                     iMenubarType = 1;
245                 }
246                 else
247                 {
248                     Scierror(999, _("Wrong value for '%s' property: '%s' or '%s' expected."), "menubar", "none", "figure");
249                     freeAllocatedSingleString(pstProName);
250                     freeAllocatedSingleString(pstPropVal);
251                     return 1;
252                 }
253             }
254             else if (stricmp(pstProName, "default_axes") == 0)
255             {
256                 if (stricmp(pstPropVal, "on") == 0)
257                 {
258                     bDefaultAxes = TRUE;
259                 }
260                 else if (stricmp(pstPropVal, "off") == 0)
261                 {
262                     bDefaultAxes = FALSE;
263                 }
264                 else
265                 {
266                     Scierror(999, _("Wrong value for '%s' property: '%s' or '%s' expected."), "default_axes", "on", "off");
267                     freeAllocatedSingleString(pstProName);
268                     freeAllocatedSingleString(pstPropVal);
269                     return 1;
270                 }
271             }
272             else if (stricmp(pstProName, "visible") == 0)
273             {
274                 if (stricmp(pstPropVal, "on") == 0)
275                 {
276                     bVisible = TRUE;
277                 }
278                 else if (stricmp(pstPropVal, "off") == 0)
279                 {
280                     bVisible = FALSE;
281                 }
282                 else
283                 {
284                     Scierror(999, _("Wrong value for '%s' property: '%s' or '%s' expected."), "visible", "on", "off");
285                     freeAllocatedSingleString(pstProName);
286                     freeAllocatedSingleString(pstPropVal);
287                     return 1;
288                 }
289             }
290             freeAllocatedSingleString(pstPropVal);
291         }
292         iFig = createFigure(bDockable, iMenubarType, iToolbarType, bDefaultAxes, bVisible);
293         setGraphicObjectProperty(iFig, __GO_ID__, &iNewId, jni_int, 1);
294         setDefaultProperties(iFig, bDefaultAxes);
295     }
296
297     //set(iFig, iPos, iPos + 1)
298     for (i = iPos + 1 ; i <= iRhs ; i += 2)
299     {
300         int isMatrixOfString = 0;
301         int* piAddrProp = NULL;
302         char* pstProName = NULL;
303         int* piAddrData = NULL;
304         int iRows = 0;
305         int iCols = 0;
306         void* _pvData = NULL;
307         int iType = 0;
308
309         //get property name
310         sciErr = getVarAddressFromPosition(pvApiCtx, i, &piAddrProp);
311         if (sciErr.iErr)
312         {
313             Scierror(999, _("%s: Can not read input argument #%d.\n"), fname, i);
314             return 1;
315         }
316
317         if (getAllocatedSingleString(pvApiCtx, piAddrProp, &pstProName))
318         {
319             Scierror(999, _("%s: Wrong size for input argument #%d: A single string expected.\n"), fname, i);
320             return 1;
321         }
322
323         if (bDoCreation &&
324                 (stricmp(pstProName, "dockable") == 0 ||
325                  stricmp(pstProName, "menubar") == 0 ||
326                  stricmp(pstProName, "toolbar") == 0))
327         {
328             // Already set creating new figure
329             // but let the set_ function fail if figure already exists
330             continue;
331         }
332
333         //get address of value on stack
334         sciErr = getVarAddressFromPosition(pvApiCtx, i + 1, &piAddrData);
335         if (sciErr.iErr)
336         {
337             Scierror(999, _("%s: Can not read input argument #%d.\n"), fname, i + 1);
338             return 1;
339         }
340
341         getVarType(pvApiCtx, piAddrData, &iType);
342
343         if ((strcmp(pstProName, "user_data") == 0) || (stricmp(pstProName, "userdata") == 0))
344         {
345             /* in this case set_user_data_property
346              * directly uses the  third position in the stack
347              * to get the variable which is to be set in
348              * the user_data property (any data type is allowed) S. Steer */
349             _pvData = (void*)piAddrData;         /*position in the stack */
350             iRows = -1;   /*unused */
351             iCols = -1;   /*unused */
352             iType = -1;
353         }
354         else
355         {
356             switch (iType)
357             {
358                 case sci_matrix :
359                     getMatrixOfDouble(pvApiCtx, piAddrData, &iRows, &iCols, (double**)&_pvData);
360                     break;
361                 case sci_boolean :
362                     getMatrixOfBoolean(pvApiCtx, piAddrData, &iRows, &iCols, (int**)&_pvData);
363                     break;
364                 case sci_handles :
365                     getMatrixOfHandle(pvApiCtx, piAddrData, &iRows, &iCols, (long long**)&_pvData);
366                     break;
367                 case sci_strings :
368                     if (   strcmp(pstProName, "tics_labels") != 0 && strcmp(pstProName, "auto_ticks") != 0 &&
369                             strcmp(pstProName, "axes_visible") != 0 && strcmp(pstProName, "axes_reverse") != 0 &&
370                             strcmp(pstProName, "text") != 0 && stricmp(pstProName, "string") != 0 &&
371                             stricmp(pstProName, "tooltipstring") != 0) /* Added for uicontrols */
372                     {
373                         if (getAllocatedSingleString(pvApiCtx, piAddrData, (char**)&_pvData))
374                         {
375                             Scierror(999, _("%s: Wrong size for input argument #%d: A single string expected.\n"), fname, 3);
376                             return 1;
377                         }
378                         iRows = (int)strlen((char*)_pvData);
379                         iCols = 1;
380                     }
381                     else
382                     {
383                         isMatrixOfString = 1;
384                         getAllocatedMatrixOfString(pvApiCtx, piAddrData, &iRows, &iCols, (char***)&_pvData);
385                     }
386                     break;
387                 case sci_list :
388                     iCols = 1;
389                     getListItemNumber(pvApiCtx, piAddrData, &iRows);
390                     _pvData = (void*)piAddrData;         /* In this case l3 is the list position in stack */
391                     break;
392                 default :
393                     _pvData = (void*)piAddrData;         /* In this case l3 is the list position in stack */
394                     break;
395             }
396         }
397
398         callSetProperty(pvApiCtx, iFig, _pvData, iType, iRows, iCols, pstProName);
399
400         // If backgroundcolor is set :
401         // * add it to colormap => performed by callSetProperty
402         // * set background to index => performed by callSetProperty
403         // * copy value into axes background property
404         if (stricmp(pstProName, "backgroundcolor") == 0 && iAxes > 0)
405         {
406             int iBackground = 0;
407             int *piBackground = &iBackground;
408
409             getGraphicObjectProperty(iFig, __GO_BACKGROUND__, jni_int, (void **)&piBackground);
410             setGraphicObjectProperty(iAxes, __GO_BACKGROUND__, piBackground, jni_int, 1);
411         }
412
413         if (iType == sci_strings)
414         {
415             //free allacted data
416             if (isMatrixOfString == 1)
417             {
418                 freeAllocatedMatrixOfString(iRows, iCols, (char**)_pvData);
419             }
420             else
421             {
422                 freeAllocatedSingleString((char*)_pvData);
423             }
424         }
425     }
426
427     //return new created fig
428     createScalarHandle(pvApiCtx, iRhs + 1, getHandle(iFig));
429     AssignOutputVariable(pvApiCtx, 1) = iRhs + 1;
430     ReturnArguments(pvApiCtx);
431     return 0;
432 }
433 /*--------------------------------------------------------------------------*/
434 int setDefaultProperties(int _iFig, BOOL _bDefaultAxes)
435 {
436     //get figure axes
437     int iAxes = -1;
438     int iDrawing = 0;
439     int iColorIndex = 0;
440     int iFilled = 0;
441     int iAxesVisible = 0;
442     double pdblNewColor[COLOR_COMPONENT] = {0.8, 0.8, 0.8};
443
444     setGraphicObjectProperty(_iFig, __GO_IMMEDIATE_DRAWING__, &iDrawing, jni_bool, 1);
445
446     iColorIndex = addColor(_iFig, pdblNewColor);
447
448     setGraphicObjectProperty(_iFig, __GO_BACKGROUND__, &iColorIndex, jni_int, 1);
449     if (_bDefaultAxes)
450     {
451         iAxes = getOrCreateDefaultSubwin();
452         //set background in figure and axes to new ( or existting ) color
453         setGraphicObjectProperty(iAxes, __GO_BACKGROUND__, &iColorIndex, jni_int, 1);
454
455         //a.filled = "off"
456         setGraphicObjectProperty(iAxes, __GO_FILLED__, &iFilled, jni_bool, 1);
457
458         //a.axes_visible = "off"
459         setGraphicObjectProperty(iAxes, __GO_X_AXIS_VISIBLE__, &iAxesVisible, jni_bool, 1);
460         setGraphicObjectProperty(iAxes, __GO_Y_AXIS_VISIBLE__, &iAxesVisible, jni_bool, 1);
461         setGraphicObjectProperty(iAxes, __GO_Z_AXIS_VISIBLE__, &iAxesVisible, jni_bool, 1);
462     }
463     //f.immediate_drawing = "on"
464     iDrawing = 1;
465     setGraphicObjectProperty(_iFig, __GO_IMMEDIATE_DRAWING__, &iDrawing, jni_bool, 1);
466
467     return iAxes;
468 }
469 /*--------------------------------------------------------------------------*/