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