Merge remote-tracking branch 'origin/5.4'
[scilab.git] / scilab / modules / gui / sci_gateway / c / sci_uicontrol.c
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2007 - INRIA - Allan CORNET
4  * Copyright (C) 2007 - INRIA - Vincent COUVERT
5  * Copyright (C) 2010 - DIGITEO - Yann COLLETTE
6  * Copyright (C) 2011 - DIGITEO - Vincent COUVERT
7  *
8  * This file must be used under the terms of the CeCILL.
9  * This source file is licensed as described in the file COPYING, which
10  * you should have received as part of this distribution.  The terms
11  * are also available at
12  * http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
13  *
14  */
15
16 #include "gw_gui.h"
17 /*--------------------------------------------------------------------------*/
18 #include "CreateUIControl.h"
19 #include "HandleManagement.h"
20 #include "MALLOC.h"             /* MALLOC */
21 #include "localization.h"
22 #include "stricmp.h"
23 #include "stack-c.h"
24 #include "SetPropertyStatus.h"
25 #include "SetHashTable.h"
26 #include "Scierror.h"
27 #include "FigureList.h"         /* getFigureFromIndex */
28 #include "Widget.h"             /* requestWidgetFocus */
29 #include "freeArrayOfString.h"
30 #include "setGraphicObjectProperty.h"
31 #include "getGraphicObjectProperty.h"
32 #include "graphicObjectProperties.h"
33 #include "CurrentFigure.h"
34 #include "BuildObjects.h"
35 #include "api_scilab.h"
36
37 /* DO NOT CHANGE ORDER !! */
38 static const char* propertiesNames[] =
39 {
40     "style",
41     "parent",
42     "backgroundcolor",
43     "foregroundcolor",
44     "string",
45     "units",
46     "fontweight",
47     "min",
48     "max",
49     "tag",
50     "position",
51     "relief",
52     "horizontalalignment",
53     "verticalalignment",
54     "sliderstep",
55     "fontname",
56     "callback",
57     "fontangle",
58     "fontunits",
59     "fontsize",
60     "listboxtop",
61     "user_data",
62     "value",
63     "userdata",
64     "visible",
65     "enable",
66     "callback_type",
67     "tooltipstring"
68 };
69
70 /*--------------------------------------------------------------------------*/
71 //#define NBPROPERTIES 28
72 //#define MAXPROPERTYNAMELENGTH 20
73 /*--------------------------------------------------------------------------*/
74 // callSetProperty get a stack pointer in input argument.
75 /*--------------------------------------------------------------------------*/
76 int sci_uicontrol(char *fname, unsigned long fname_len)
77 {
78     SciErr sciErr;
79
80     int nbRow = 0, nbCol = 0, k = 0;
81     int setStatus = SET_PROPERTY_SUCCEED;
82     int NOT_FOUND = -1;
83     int inputIndex = 0, beginIndex = 0;
84     char *propertyName = NULL;
85     char *styleProperty = NULL;
86     char *pParentUID = NULL;
87     char *pUicontrol = NULL;
88
89     int iPropertiesCount = sizeof(propertiesNames) / sizeof(char**);
90     unsigned long GraphicHandle = 0;
91
92     int found = 0;              /* Does the property exists ? */
93
94     int *propertiesValuesIndices = NULL;
95
96     int iParentType = -1;
97     int *piParentType = &iParentType;
98     int iParentStyle = -1;
99     int *piParentStyle = &iParentStyle;
100     char const* pstCurrentFigure = NULL;
101
102     CheckOutputArgument(pvApiCtx, 0, 1);
103
104     if (nbInputArgument(pvApiCtx) == 0)
105     {
106         /* Create a pushbutton in current figure */
107
108         /* Create a new pushbutton */
109         GraphicHandle = getHandle(CreateUIControl(NULL));
110
111         /* Set current figure as parent */
112         pstCurrentFigure = getCurrentFigure();
113         if (pstCurrentFigure == NULL)
114         {
115             pstCurrentFigure = createNewFigureWithAxes();
116         }
117         setGraphicObjectRelationship(pstCurrentFigure, (char*)getObjectFromHandle(GraphicHandle));
118         pUicontrol = (char*)getObjectFromHandle(GraphicHandle);
119     }
120     else if (nbInputArgument(pvApiCtx) == 1)
121     {
122         /* Create a pushbutton in figure given as parameter */
123         /* Or give focus to the uicontrol given as parameter */
124
125         if ((!checkInputArgumentType(pvApiCtx, 1, sci_handles)))
126         {
127             OverLoad(1);
128             return FALSE;
129         }
130         else /* Get parent ID */
131         {
132             int* piAddr = NULL;
133             long long hParent = 0;
134             sciErr = getVarAddressFromPosition(pvApiCtx, 1, &piAddr);
135             if (sciErr.iErr)
136             {
137                 printError(&sciErr, 0);
138                 return 1;
139             }
140
141             if (isScalar(pvApiCtx, piAddr) == 0)
142             {
143                 Scierror(999, _("%s: Wrong size for input argument #%d: A graphic handle expected.\n"), fname, 1);
144                 return FALSE;
145             }
146
147             if (getScalarHandle(pvApiCtx, piAddr, &hParent))
148             {
149                 Scierror(202, _("%s: Wrong type for argument %d: Handle matrix expected.\n"), fname, 1);
150                 return 1;
151             }
152
153             pParentUID = (char*)getObjectFromHandle((long)hParent);
154             if (pParentUID != NULL)
155             {
156                 getGraphicObjectProperty(pParentUID, __GO_TYPE__, jni_int, (void **)&piParentType);
157                 if (iParentType == __GO_UICONTROL__)  /* Focus management */
158                 {
159                     GraphicHandle = (unsigned long)hParent;
160                     requestFocus(pParentUID);
161                 }
162                 else if (iParentType == __GO_FIGURE__ || iParentType == __GO_UIMENU__)  /* PushButton creation */
163                 {
164                     /* Create a new pushbutton */
165                     GraphicHandle = getHandle(CreateUIControl(NULL));
166
167                     /* First parameter is the parent */
168                     setGraphicObjectRelationship(pParentUID, getObjectFromHandle(GraphicHandle));
169                     setStatus = callSetProperty(pvApiCtx, (char*)getObjectFromHandle(GraphicHandle), &hParent, sci_handles, 1, 1, (char*)propertiesNames[1]);
170                     if (setStatus == SET_PROPERTY_ERROR)
171                     {
172                         Scierror(999, _("%s: Could not set property '%s'.\n"), fname, propertyName);
173                         return FALSE;
174                     }
175                 }
176                 else
177                 {
178                     Scierror(999, _("%s: Wrong type for input argument #%d: A '%s', '%s' or '%s' handle expected.\n"), fname, 1, "Uicontrol",
179                              "Figure", "Uimenu");
180                     return FALSE;
181                 }
182             }
183             else
184             {
185                 Scierror(999, _("%s: Wrong type for input argument #%d: A '%s', '%s' or '%s' handle expected.\n"), fname, 1, "Uicontrol", "Figure",
186                          "Uimenu");
187                 return FALSE;
188             }
189             pUicontrol = (char*)getObjectFromHandle(GraphicHandle);
190         }
191     }
192     else
193     {
194         if (!checkInputArgumentType(pvApiCtx, 1, sci_handles) && !checkInputArgumentType(pvApiCtx, 1, sci_strings))
195         {
196             OverLoad(1);
197             return FALSE;
198         }
199
200         /* Allocate memory to store the position of properties in uicontrol call */
201         if ((propertiesValuesIndices = (int*)MALLOC(sizeof(int) * iPropertiesCount)) == NULL)
202         {
203             Scierror(999, _("%s: No more memory.\n"), fname);
204             return FALSE;
205         }
206
207         /* Init all positions to NOT_FOUND */
208         for (inputIndex = 0; inputIndex < iPropertiesCount; inputIndex++)
209         {
210             propertiesValuesIndices[inputIndex] = NOT_FOUND;    /* Property initialized as not found */
211         }
212
213         /**
214          * Odd number of input arguments
215          * First input is the parent ID
216          * All event inputs are property names
217          * All odd (except first) inputs are property values
218          */
219         if (nbInputArgument(pvApiCtx) % 2 == 1)
220         {
221             if ((!checkInputArgumentType(pvApiCtx, 1, sci_handles)))
222             {
223                 if ((checkInputArgumentType(pvApiCtx, 1, sci_matrix)))
224                 {
225                     int* piAddr = NULL;
226                     double dblValue = 0;
227
228                     sciErr = getVarAddressFromPosition(pvApiCtx, 1, &piAddr);
229                     if (sciErr.iErr)
230                     {
231                         printError(&sciErr, 0);
232                         return 1;
233                     }
234
235                     if (isScalar(pvApiCtx, piAddr) == 0)
236                     {
237                         Scierror(999, _("%s: Wrong size for input argument #%d: A graphic handle expected.\n"), fname, 1);
238                         return FALSE;
239                     }
240
241                     if (getScalarDouble(pvApiCtx, piAddr, &dblValue))
242                     {
243                         Scierror(202, _("%s: Wrong type for argument %d: A real expected.\n"), fname, 1);
244                         return 1;
245                     }
246
247                     pParentUID = (char*)getFigureFromIndex((int)dblValue);
248
249                     if (pParentUID == NULL)
250                     {
251                         Scierror(999, _("%s: Wrong type for input argument #%d: A '%s' or a '%s' handle expected.\n"), fname, 1, "Figure",
252                                  "Frame uicontrol");
253                         return FALSE;
254                     }
255
256                     getGraphicObjectProperty(pParentUID, __GO_TYPE__, jni_int, (void **)&piParentType);
257                     if (iParentType != __GO_FIGURE__)
258                     {
259                         getGraphicObjectProperty(pParentUID, __GO_STYLE__, jni_int, (void **)&piParentStyle);
260                         if (iParentType != __GO_UICONTROL__ || iParentStyle != __GO_UI_FRAME__)
261                         {
262                             Scierror(999, _("%s: Wrong type for input argument #%d: A '%s' or a '%s' handle expected.\n"), fname, 1, "Figure",
263                                      "Frame uicontrol");
264                             return FALSE;
265                         }
266                     }
267                     /* First parameter is the parent */
268                     propertiesValuesIndices[1] = 1;
269                 }
270                 else
271                 {
272                     Scierror(999, _("%s: Wrong type for input argument #%d: A '%s' or a '%s' handle expected.\n"), fname, 1, "Figure",
273                              "Frame uicontrol");
274                     return FALSE;
275                 }
276             }
277             else /* Get parent ID */
278             {
279                 int* piAddr = NULL;
280                 long long hParent = 0;
281                 sciErr = getVarAddressFromPosition(pvApiCtx, 1, &piAddr);
282                 if (sciErr.iErr)
283                 {
284                     printError(&sciErr, 0);
285                     return 1;
286                 }
287
288                 if (isScalar(pvApiCtx, piAddr) == 0)
289                 {
290                     Scierror(999, _("%s: Wrong size for input argument #%d: A '%s' or a '%s' handle expected.\n"), fname, 1, "Figure",
291                              "Frame uicontrol");
292                     return FALSE;
293                 }
294
295                 if (getScalarHandle(pvApiCtx, piAddr, &hParent))
296                 {
297                     Scierror(202, _("%s: Wrong type for argument %d: Handle matrix expected.\n"), fname, 1);
298                     return 1;
299                 }
300
301                 pParentUID = (char*)getObjectFromHandle((long)hParent);
302                 if (pParentUID == NULL)
303                 {
304                     Scierror(999, _("%s: Wrong type for input argument #%d: A '%s' or a '%s' handle expected.\n"), fname, 1, "Figure",
305                              "Frame uicontrol");
306                     return FALSE;
307                 }
308                 getGraphicObjectProperty(pParentUID, __GO_TYPE__, jni_int, (void **)&piParentType);
309                 if (iParentType != __GO_FIGURE__)
310                 {
311                     getGraphicObjectProperty(pParentUID, __GO_STYLE__, jni_int, (void **)&piParentStyle);
312                     if (iParentType != __GO_UICONTROL__ || iParentStyle != __GO_UI_FRAME__)
313                     {
314                         Scierror(999, _("%s: Wrong type for input argument #%d: A '%s' or a '%s' handle expected.\n"), fname, 1, "Figure",
315                                  "Frame uicontrol");
316                         return FALSE;
317                     }
318                 }
319                 /* First parameter is the parent */
320                 propertiesValuesIndices[1] = 1;
321             }
322
323             // First input parameter which is a property name
324             beginIndex = 2;
325         }
326         /**
327          * Even number of input arguments
328          * All odd inputs are property names
329          * All even inputs are property values
330          */
331         else
332         {
333             // First input parameter which is a property name
334             beginIndex = 1;
335         }
336
337         /* Get all properties positions */
338         for (inputIndex = beginIndex; inputIndex < Rhs; inputIndex = inputIndex + 2)
339         {
340             /* Read property name */
341             if ((!checkInputArgumentType(pvApiCtx, inputIndex, sci_strings)))
342             {
343                 Scierror(999, _("%s: Wrong type for input argument #%d: A string expected.\n"), fname, inputIndex);
344                 return FALSE;
345             }
346             else
347             {
348                 int* piAddr = NULL;
349                 sciErr = getVarAddressFromPosition(pvApiCtx, inputIndex, &piAddr);
350                 if (sciErr.iErr)
351                 {
352                     printError(&sciErr, 0);
353                     return 1;
354                 }
355
356                 if (getAllocatedSingleString(pvApiCtx, piAddr, &propertyName))
357                 {
358                     Scierror(202, _("%s: Wrong type for argument #%d: A string expected.\n"), fname, inputIndex);
359                     return 1;
360                 }
361
362
363                 /* Bug 3031 */
364                 /* We only want to compare propertyName along its length */
365                 /* 'posi' must be matched to 'position' */
366                 found = 0;
367                 for (k = 0; k < iPropertiesCount ; k++)
368                 {
369                     if (strlen(propertyName) <= strlen(propertiesNames[k]))
370                     {
371                         if (strnicmp(propertyName, propertiesNames[k], strlen(propertyName)) == 0)
372                         {
373                             propertiesValuesIndices[k] = inputIndex + 1;    /* Position of value for property */
374                             found = 1;
375                             break;
376                         }
377                     }
378                 }
379
380                 if (found == 0)
381                 {
382                     Scierror(999, _("%s: Unknown property: %s for '%s' handles.\n"), fname, propertyName, "Uicontrol");
383                     return FALSE;
384                 }
385             }
386         }
387
388         if (propertiesValuesIndices[0] != NOT_FOUND)    /* Style found */
389         {
390             if ((checkInputArgumentType(pvApiCtx, propertiesValuesIndices[0], sci_strings)))
391             {
392                 int* piAddr = NULL;
393                 sciErr = getVarAddressFromPosition(pvApiCtx, propertiesValuesIndices[0], &piAddr);
394                 if (sciErr.iErr)
395                 {
396                     printError(&sciErr, 0);
397                     return 1;
398                 }
399
400                 if (getAllocatedSingleString(pvApiCtx, piAddr, &styleProperty))
401                 {
402                     Scierror(202, _("%s: Wrong type for argument #%d: A string expected.\n"), fname, propertiesValuesIndices[0]);
403                     return 1;
404                 }
405             }
406             else
407             {
408                 Scierror(999, _("%s: Wrong type for input argument #%d: A string expected.\n"), fname, propertiesValuesIndices[0]);
409                 return FALSE;
410             }
411         }
412
413         /* Create a new uicontrol */
414         pUicontrol = CreateUIControl(styleProperty);
415         freeAllocatedSingleString(styleProperty);
416         if (pUicontrol == NULL) /* Error in creation */
417         {
418             Scierror(999, _("%s: Could not create 'Uicontrol' handle.\n"), fname);
419             return FALSE;
420         }
421         GraphicHandle = getHandle(pUicontrol);
422
423         /* If no parent given then the current figure is the parent */
424         if (propertiesValuesIndices[1] == NOT_FOUND)
425         {
426             char *graphicObjectUID = (char*)getObjectFromHandle(GraphicHandle);
427
428             /* Set the parent */
429             pstCurrentFigure = (char*)getCurrentFigure();
430
431             if (pstCurrentFigure == NULL)
432             {
433                 pstCurrentFigure = createNewFigureWithAxes();
434             }
435             setGraphicObjectRelationship(pstCurrentFigure, graphicObjectUID);
436         }
437
438         /* Read and set all properties */
439         for (inputIndex = 1; inputIndex < iPropertiesCount; inputIndex++)   /* Style has already been set */
440         {
441             if (propertiesValuesIndices[inputIndex] != NOT_FOUND)
442             {
443                 int* piAddr = NULL;
444                 sciErr = getVarAddressFromPosition(pvApiCtx, propertiesValuesIndices[inputIndex], &piAddr);
445                 if (sciErr.iErr)
446                 {
447                     printError(&sciErr, 0);
448                     return 1;
449                 }
450
451                 if (inputIndex == 21 || inputIndex == 23)   /* User data settings */
452                 {
453                     nbRow = -1;
454                     nbCol = -1;
455                     setStatus = callSetProperty(pvApiCtx, (char*)getObjectFromHandle(GraphicHandle), piAddr, 0, 0, 0, (char*)propertiesNames[inputIndex]);
456                 }
457                 else            /* All other properties */
458                 {
459                     /* Read property value */
460                     switch (getInputArgumentType(pvApiCtx, propertiesValuesIndices[inputIndex]))
461                     {
462                         case sci_matrix:
463                         {
464                             double* pdblValue = NULL;
465                             sciErr = getMatrixOfDouble(pvApiCtx, piAddr, &nbRow, &nbCol, &pdblValue);
466                             if (sciErr.iErr)
467                             {
468                                 printError(&sciErr, 0);
469                                 Scierror(202, _("%s: Wrong type for argument %d: A real expected.\n"), fname, propertiesValuesIndices[inputIndex]);
470                                 return 1;
471                             }
472
473                             setStatus = callSetProperty(pvApiCtx, (char*)getObjectFromHandle(GraphicHandle), pdblValue, sci_matrix, nbRow, nbCol, (char*)propertiesNames[inputIndex]);
474                             break;
475                         }
476                         case sci_strings:
477                             /* Index for String & TooltipString properties: Can be more than one character string */
478                             if ((inputIndex == 4) || (inputIndex == 27))
479                             {
480                                 char** pstValue = NULL;
481                                 if (getAllocatedMatrixOfString(pvApiCtx, piAddr, &nbRow, &nbCol, &pstValue))
482                                 {
483                                     Scierror(202, _("%s: Wrong type for argument #%d: String matrix expected.\n"), fname, propertiesValuesIndices[inputIndex]);
484                                     return 1;
485                                 }
486
487                                 setStatus = callSetProperty(pvApiCtx, (char*)getObjectFromHandle(GraphicHandle), pstValue, sci_strings, nbRow, nbCol, (char*)propertiesNames[inputIndex]);
488                                 freeAllocatedMatrixOfString(nbRow, nbCol, pstValue);
489                             }
490                             else
491                             {
492                                 char* pstValue = NULL;
493                                 if (getAllocatedSingleString(pvApiCtx, piAddr, &pstValue))
494                                 {
495                                     Scierror(202, _("%s: Wrong type for argument #%d: A string expected.\n"), fname, propertiesValuesIndices[inputIndex]);
496                                     return 1;
497                                 }
498
499                                 nbRow = (int)strlen(pstValue);
500                                 nbCol = 1;
501                                 setStatus = callSetProperty(pvApiCtx, (char*)getObjectFromHandle(GraphicHandle), pstValue, sci_strings, nbRow, nbCol, (char*)propertiesNames[inputIndex]);
502                                 freeAllocatedSingleString(pstValue);
503                             }
504                             break;
505                         case sci_handles:
506                         {
507                             long long* pHandles = NULL;
508                             sciErr = getMatrixOfHandle(pvApiCtx, piAddr, &nbRow, &nbCol, &pHandles);
509                             if (sciErr.iErr)
510                             {
511                                 printError(&sciErr, 0);
512                                 Scierror(202, _("%s: Wrong type for argument %d: Handle matrix expected.\n"), fname, propertiesValuesIndices[inputIndex]);
513                                 return 1;
514                             }
515
516                             setStatus = callSetProperty(pvApiCtx, (char*)getObjectFromHandle(GraphicHandle), pHandles, sci_handles, nbRow, nbCol, (char*)propertiesNames[inputIndex]);
517                             break;
518                         }
519                         default:
520                             setStatus = SET_PROPERTY_ERROR;
521                             break;
522                     }
523                 }
524                 if (setStatus == SET_PROPERTY_ERROR)
525                 {
526                     Scierror(999, _("%s: Could not set property '%s'.\n"), fname, (char*)propertiesNames[inputIndex]);
527                     return FALSE;
528                 }
529             }
530         }
531     }
532
533     if ((nbInputArgument(pvApiCtx) < 2) || (propertiesValuesIndices[24] == NOT_FOUND))    /* Visible property not set */
534     {
535         /* Force the uicontrol to be visible because is invisible by default in the model (See bug #10346) */
536         int b = (int)TRUE;
537         setGraphicObjectProperty(pUicontrol, __GO_VISIBLE__, &b, jni_bool, 1);
538     }
539
540     if ((nbInputArgument(pvApiCtx) < 2) || (propertiesValuesIndices[14] == NOT_FOUND))    /* SliderStep property not set */
541     {
542         /* Set SliderStep property to [1/100*(Max-Min) 1/10*(Max-Min)] */
543         double maxValue = 0;
544         double* pdblMaxValue = &maxValue;
545         double minValue = 0;
546         double* pdblMinValue = &minValue;
547         double pdblStep[2];
548
549         getGraphicObjectProperty(pUicontrol, __GO_UI_MIN__, jni_double, (void**) &pdblMinValue);
550         getGraphicObjectProperty(pUicontrol, __GO_UI_MAX__, jni_double, (void**) &pdblMaxValue);
551
552         pdblStep[0] = 0.01 * (maxValue - minValue);
553         pdblStep[1] = 0.1 * (maxValue - minValue);
554
555         setGraphicObjectProperty(pUicontrol, __GO_UI_SLIDERSTEP__, pdblStep, jni_double_vector, 2);
556     }
557
558     if ((Rhs < 2) || (propertiesValuesIndices[10] == NOT_FOUND))    /* Position property not set */
559     {
560         double* pdblPosition = NULL;
561
562         getGraphicObjectProperty(pUicontrol, __GO_POSITION__, jni_double_vector, (void**) &pdblPosition);
563         setGraphicObjectProperty(pUicontrol, __GO_POSITION__, pdblPosition, jni_double_vector, 4);
564     }
565
566     FREE(propertiesValuesIndices);
567
568     /* Create return variable */
569     if (createScalarHandle(pvApiCtx, nbInputArgument(pvApiCtx) + 1, GraphicHandle))
570     {
571         Scierror(999, _("%s: Memory allocation error.\n"), fname);
572         return 1;
573     }
574
575     AssignOutputVariable(pvApiCtx, 1) = nbInputArgument(pvApiCtx) + 1;
576     ReturnArguments(pvApiCtx);
577     return TRUE;
578 }
579
580 /*--------------------------------------------------------------------------*/