Always have fallback element colors; Remove annotations from native method as there...
[SquirrelJME.git] / nanocoat / lib / scritchui / scritchCore.c
blob59ea0be2156c84b2458ca02012e010bfd956e059
1 /* -*- Mode: C; indent-tabs-mode: t; tab-width: 4 -*-
2 // ---------------------------------------------------------------------------
3 // SquirrelJME
4 // Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
5 // ---------------------------------------------------------------------------
6 // SquirrelJME is under the Mozilla Public License Version 2.0.
7 // See license.mkd for licensing and copyright information.
8 // -------------------------------------------------------------------------*/
10 #include <string.h>
12 #include "lib/scritchui/core/core.h"
13 #include "lib/scritchui/core/coreSerial.h"
14 #include "lib/scritchui/scritchuiTypes.h"
15 #include "sjme/alloc.h"
16 #include "lib/scritchui/framebuffer/fb.h"
17 #include "lib/scritchui/core/coreGeneric.h"
19 /** Window manager information. */
20 static const sjme_scritchui_wmInfo sjme_scritchUI_coreWmInfo =
22 .defaultTitle = "SquirrelJME",
23 .xwsClass = "squirreljme",
26 /** Core dispatch functions for serial calls. */
27 static const sjme_scritchui_apiFunctions sjme_scritchUI_serialFunctions =
29 /* As normal. */
30 .apiFlags = NULL,
31 .choiceGetSelectedIndex = sjme_scritchui_coreSerial_choiceGetSelectedIndex,
32 .choiceItemGet = sjme_scritchui_coreSerial_choiceItemGet,
33 .choiceItemInsert = sjme_scritchui_coreSerial_choiceItemInsert,
34 .choiceItemRemove = sjme_scritchui_coreSerial_choiceItemRemove,
35 .choiceItemRemoveAll = sjme_scritchui_coreSerial_choiceItemRemoveAll,
36 .choiceItemSetEnabled = sjme_scritchui_coreSerial_choiceItemSetEnabled,
37 .choiceItemSetImage = sjme_scritchui_coreSerial_choiceItemSetImage,
38 .choiceItemSetSelected = sjme_scritchui_coreSerial_choiceItemSetSelected,
39 .choiceItemSetString = sjme_scritchui_coreSerial_choiceItemSetString,
40 .choiceLength = sjme_scritchui_coreSerial_choiceLength,
41 .componentFocusGrab = sjme_scritchui_coreSerial_componentFocusGrab,
42 .componentFocusHas = sjme_scritchui_coreSerial_componentFocusHas,
43 .componentGetParent = sjme_scritchui_coreSerial_componentGetParent,
44 .componentPosition = sjme_scritchui_coreSerial_componentPosition,
45 .componentRepaint = sjme_scritchui_coreSerial_componentRepaint,
46 .componentRevalidate = sjme_scritchui_coreSerial_componentRevalidate,
47 .componentSetActivateListener =
48 sjme_scritchui_coreSerial_componentSetActivateListener,
49 .componentSetInputListener =
50 sjme_scritchui_coreSerial_componentSetInputListener,
51 .componentSetPaintListener =
52 sjme_scritchui_coreSerial_componentSetPaintListener,
53 .componentSetSizeListener =
54 sjme_scritchui_coreSerial_componentSetSizeListener,
55 .componentSetValueUpdateListener =
56 sjme_scritchui_coreSerial_componentSetValueUpdateListener,
57 .componentSetVisibleListener =
58 sjme_scritchui_coreSerial_componentSetVisibleListener,
59 .componentSize = sjme_scritchui_coreSerial_componentSize,
60 .containerAdd = sjme_scritchui_coreSerial_containerAdd,
61 .containerRemove = sjme_scritchui_coreSerial_containerRemove,
62 .containerRemoveAll = sjme_scritchui_coreSerial_containerRemoveAll,
63 .containerSetBounds = sjme_scritchui_coreSerial_containerSetBounds,
64 .fontBuiltin = sjme_scritchui_coreSerial_fontBuiltin,
65 .fontDerive = sjme_scritchui_coreSerial_fontDerive,
66 .hardwareGraphics = sjme_scritchui_coreSerial_hardwareGraphics,
67 .labelSetString = sjme_scritchui_coreSerial_labelSetString,
68 .listNew = sjme_scritchui_coreSerial_listNew,
69 .lafElementColor = sjme_scritchui_coreSerial_lafElementColor,
71 /* Loops are unchanged. */
72 .loopExecute = sjme_scritchui_core_loopExecute,
73 .loopExecuteLater = sjme_scritchui_core_loopExecuteLater,
74 .loopExecuteWait = sjme_scritchui_core_loopExecuteWait,
75 .loopIsInThread = sjme_scritchui_core_loopIsInThread,
76 .loopIterate = sjme_scritchui_core_loopIterate,
78 /* As normal. */
79 .menuBarNew = sjme_scritchui_coreSerial_menuBarNew,
80 .menuInsert = sjme_scritchui_coreSerial_menuInsert,
81 .menuItemNew = sjme_scritchui_coreSerial_menuItemNew,
82 .menuNew = sjme_scritchui_coreSerial_menuNew,
83 .menuRemove = sjme_scritchui_coreSerial_menuRemove,
84 .menuRemoveAll = sjme_scritchui_coreSerial_menuRemoveAll,
85 .objectDelete = sjme_scritchui_coreSerial_objectDelete,
86 .panelEnableFocus = sjme_scritchui_coreSerial_panelEnableFocus,
87 .panelNew = sjme_scritchui_coreSerial_panelNew,
88 .screenSetListener = sjme_scritchui_coreSerial_screenSetListener,
89 .screens = sjme_scritchui_coreSerial_screens,
90 .scrollPanelNew = sjme_scritchui_coreSerial_scrollPanelNew,
91 .viewGetView = sjme_scritchui_coreSerial_viewGetView,
92 .viewSetArea = sjme_scritchui_coreSerial_viewSetArea,
93 .viewSetSizeSuggestListener =
94 sjme_scritchui_coreSerial_viewSetSizeSuggestListener,
95 .viewSetView = sjme_scritchui_coreSerial_viewSetView,
96 .viewSetViewListener = sjme_scritchui_coreSerial_viewSetViewListener,
97 .windowContentMinimumSize =
98 sjme_scritchui_coreSerial_windowContentMinimumSize,
99 .windowNew = sjme_scritchui_coreSerial_windowNew,
100 .windowSetCloseListener = sjme_scritchui_coreSerial_windowSetCloseListener,
101 .windowSetMenuBar = sjme_scritchui_coreSerial_windowSetMenuBar,
102 .windowSetMenuItemActivateListener =
103 sjme_scritchui_coreSerial_windowSetMenuItemActivateListener,
104 .windowSetVisible = sjme_scritchui_coreSerial_windowSetVisible,
107 /** Core Function set for ScritchUI. */
108 static const sjme_scritchui_apiFunctions sjme_scritchUI_coreFunctions =
110 .apiFlags = NULL,
111 .choiceGetSelectedIndex = sjme_scritchui_core_choiceGetSelectedIndex,
112 .choiceItemGet = sjme_scritchui_core_choiceItemGet,
113 .choiceItemInsert = sjme_scritchui_core_choiceItemInsert,
114 .choiceItemRemove = sjme_scritchui_core_choiceItemRemove,
115 .choiceItemRemoveAll = sjme_scritchui_core_choiceItemRemoveAll,
116 .choiceItemSetEnabled = sjme_scritchui_core_choiceItemSetEnabled,
117 .choiceItemSetImage = sjme_scritchui_core_choiceItemSetImage,
118 .choiceItemSetSelected = sjme_scritchui_core_choiceItemSetSelected,
119 .choiceItemSetString = sjme_scritchui_core_choiceItemSetString,
120 .choiceLength = sjme_scritchui_core_choiceLength,
121 .componentFocusGrab = sjme_scritchui_core_componentFocusGrab,
122 .componentFocusHas = sjme_scritchui_core_componentFocusHas,
123 .componentGetParent = sjme_scritchui_core_componentGetParent,
124 .componentPosition = sjme_scritchui_core_componentPosition,
125 .componentRepaint = sjme_scritchui_core_componentRepaint,
126 .componentRevalidate = sjme_scritchui_core_componentRevalidate,
127 .componentSetActivateListener =
128 sjme_scritchui_core_componentSetActivateListener,
129 .componentSetInputListener = sjme_scritchui_core_componentSetInputListener,
130 .componentSetPaintListener = sjme_scritchui_core_componentSetPaintListener,
131 .componentSetSizeListener = sjme_scritchui_core_componentSetSizeListener,
132 .componentSetValueUpdateListener =
133 sjme_scritchui_core_componentSetValueUpdateListener,
134 .componentSetVisibleListener =
135 sjme_scritchui_core_componentSetVisibleListener,
136 .componentSize = sjme_scritchui_core_componentSize,
137 .containerAdd = sjme_scritchui_core_containerAdd,
138 .containerRemove = sjme_scritchui_core_containerRemove,
139 .containerRemoveAll = sjme_scritchui_core_containerRemoveAll,
140 .containerSetBounds = sjme_scritchui_core_containerSetBounds,
141 .fontBuiltin = sjme_scritchui_core_fontBuiltin,
142 .fontDerive = sjme_scritchui_core_fontDerive,
143 .hardwareGraphics = sjme_scritchpen_core_hardwareGraphics,
144 .labelSetString = sjme_scritchui_core_labelSetString,
145 .lafElementColor = sjme_scritchui_core_lafElementColor,
146 .listNew = sjme_scritchui_core_listNew,
147 .loopExecute = sjme_scritchui_core_loopExecute,
148 .loopExecuteLater = sjme_scritchui_core_loopExecuteLater,
149 .loopExecuteWait = sjme_scritchui_core_loopExecuteWait,
150 .loopIsInThread = sjme_scritchui_core_loopIsInThread,
151 .loopIterate = sjme_scritchui_core_loopIterate,
152 .menuBarNew = sjme_scritchui_core_menuBarNew,
153 .menuInsert = sjme_scritchui_core_menuInsert,
154 .menuItemNew = sjme_scritchui_core_menuItemNew,
155 .menuNew = sjme_scritchui_core_menuNew,
156 .menuRemove = sjme_scritchui_core_menuRemove,
157 .menuRemoveAll = sjme_scritchui_core_menuRemoveAll,
158 .objectDelete = sjme_scritchui_core_objectDelete,
159 .panelEnableFocus = sjme_scritchui_core_panelEnableFocus,
160 .panelNew = sjme_scritchui_core_panelNew,
161 .screenSetListener = sjme_scritchui_core_screenSetListener,
162 .screens = sjme_scritchui_core_screens,
163 .scrollPanelNew = sjme_scritchui_core_scrollPanelNew,
164 .viewGetView = sjme_scritchui_core_viewGetView,
165 .viewSetArea = sjme_scritchui_core_viewSetArea,
166 .viewSetView = sjme_scritchui_core_viewSetView,
167 .viewSetSizeSuggestListener =
168 sjme_scritchui_core_viewSetSizeSuggestListener,
169 .viewSetViewListener = sjme_scritchui_core_viewSetViewListener,
170 .windowContentMinimumSize = sjme_scritchui_core_windowContentMinimumSize,
171 .windowNew = sjme_scritchui_core_windowNew,
172 .windowSetCloseListener = sjme_scritchui_core_windowSetCloseListener,
173 .windowSetMenuBar = sjme_scritchui_core_windowSetMenuBar,
174 .windowSetMenuItemActivateListener =
175 sjme_scritchui_core_windowSetMenuItemActivateListener,
176 .windowSetVisible = sjme_scritchui_core_windowSetVisible,
179 /** Internal functions for ScritchUI implementations. */
180 static const sjme_scritchui_internFunctions sjme_scritchUI_coreIntern =
182 .bindFocus = sjme_scritchui_core_intern_bindFocus,
183 .fontBuiltin = sjme_scritchui_core_intern_fontBuiltin,
184 .getChoice = sjme_scritchui_core_intern_getChoice,
185 .getContainer = sjme_scritchui_core_intern_getContainer,
186 .getLabeled = sjme_scritchui_core_intern_getLabeled,
187 .getMenuHasChildren = sjme_scritchui_core_intern_getMenuHasChildren,
188 .getMenuHasParent = sjme_scritchui_core_intern_getMenuHasParent,
189 .getPaintable = sjme_scritchui_core_intern_getPaintable,
190 .getView = sjme_scritchui_core_intern_getView,
191 .initCommon = sjme_scritchui_core_intern_initCommon,
192 .initComponent = sjme_scritchui_core_intern_initComponent,
193 .mapScreen = sjme_scritchui_core_intern_mapScreen,
194 .menuItemActivate = sjme_scritchui_intern_menuItemActivate,
195 .menuItemActivateById = sjme_scritchui_intern_menuItemActivateById,
196 .setSimpleListener = sjme_scritchui_core_intern_setSimpleListener,
197 .updateVisibleContainer =
198 sjme_scritchui_core_intern_updateVisibleContainer,
199 .updateVisibleComponent =
200 sjme_scritchui_core_intern_updateVisibleComponent,
201 .updateVisibleWindow = sjme_scritchui_core_intern_updateVisibleWindow,
202 .viewSuggest = sjme_scritchui_core_intern_viewSuggest,
205 static sjme_thread_result sjme_attrThreadCall sjme_scritchui_core_fbBelay(
206 sjme_attrInNullable sjme_thread_parameter anything)
208 sjme_scritchui topState;
209 sjme_scritchui wrappedState;
211 if (anything == NULL)
212 return SJME_THREAD_RESULT(SJME_ERROR_NULL_ARGUMENTS);
214 /* Recover wrapped state, which is calling this one. */
215 wrappedState = (sjme_scritchui)anything;
217 /* Debug. */
218 sjme_message("Waiting for top state to become mapped...");
220 /* Recover wrapped state. */
221 topState = NULL;
222 while (topState == NULL)
224 /* Barrier for other thread to run. */
225 sjme_thread_barrier();
226 sjme_thread_yield();
227 sjme_thread_barrier();
229 /* Read it in. */
230 topState = sjme_atomic_sjme_pointer_get(
231 &wrappedState->topState);
234 /* Debug. */
235 sjme_message("Calling top initializer, if applicable...");
237 /* Call the intended wrapper in this event thread? */
238 if (topState->loopThreadInit != NULL)
239 topState->loopThreadInit(topState);
241 /* Debug. */
242 sjme_message("Marking framebuffer as ready!");
244 /* Mark as ready so initialization continues and gets finished. */
245 sjme_atomic_sjme_jint_set(&topState->loopThreadReady, 1);
247 /* Success! */
248 return SJME_THREAD_RESULT(SJME_ERROR_NONE);
251 static sjme_errorCode sjme_scritchui_core_apiInitActual(
252 sjme_attrInNotNull sjme_alloc_pool* inPool,
253 sjme_attrInOutNotNull sjme_scritchui* outState,
254 sjme_attrInNotNull const sjme_scritchui_implFunctions* inImplFunc,
255 sjme_attrInNullable sjme_thread_mainFunc loopExecute,
256 sjme_attrInNullable sjme_frontEnd* initFrontEnd,
257 sjme_attrInNullable sjme_scritchui wrappedState)
259 sjme_errorCode error;
260 sjme_scritchui state;
262 if (inPool == NULL || inImplFunc == NULL || outState == NULL)
263 return SJME_ERROR_NULL_ARGUMENTS;
265 if (inImplFunc->apiInit == NULL)
266 return sjme_error_notImplemented(0);
268 /* Allocate state. */
269 state = NULL;
270 if (sjme_error_is(error = sjme_alloc_weakNew(inPool, sizeof(*state),
271 NULL, NULL, &state, NULL)) || state == NULL)
272 goto fail_alloc;
274 /* Seed state. */
275 state->pool = inPool;
276 state->api = &sjme_scritchUI_serialFunctions;
277 state->apiInThread = &sjme_scritchUI_coreFunctions;
278 state->intern = &sjme_scritchUI_coreIntern;
279 state->impl = inImplFunc;
280 state->wmInfo = &sjme_scritchUI_coreWmInfo;
281 state->nanoTime = sjme_nal_default_nanoTime;
283 /* Common initialize. */
284 if (sjme_error_is(error = state->intern->initCommon(state,
285 state, SJME_JNI_FALSE,
286 SJME_SCRITCHUI_TYPE_ROOT_STATE)))
287 goto fail_commonInit;
289 /* By default, everything is panel only. */
290 state->isPanelOnly = SJME_JNI_TRUE;
292 /* Loop initialization. */
293 if (wrappedState != NULL)
294 state->loopThread = wrappedState->loopThread;
295 else
296 state->loopThread = SJME_THREAD_NULL;
297 state->loopThreadInit = loopExecute;
299 /* Use provided front end if a core interface. */
300 if (initFrontEnd != NULL)
301 memmove(&state->common.frontEnd, initFrontEnd,
302 sizeof(*initFrontEnd));
304 /* Perform API specific initialization. */
305 if (sjme_error_is(error = state->impl->apiInit(state)))
306 goto fail_apiInit;
308 /* Link back states. */
309 if (wrappedState != NULL)
311 /* Debug. */
312 sjme_message("Linking in wrapped state (%p -> %p)...",
313 state, wrappedState);
315 /* Link together. */
316 state->wrappedState = wrappedState;
317 sjme_atomic_sjme_pointer_set(&wrappedState->topState,
318 state);
320 /* Barrier here for wrapped init. */
321 sjme_thread_barrier();
322 sjme_thread_yield();
323 sjme_thread_barrier();
326 /* Debug. */
327 sjme_message("Waiting for thread ready (%p)...",
328 state);
330 /* Wait for the ready signal, but only if required. */
331 if (state->loopThread == SJME_THREAD_NULL)
332 sjme_atomic_sjme_jint_set(&state->loopThreadReady, 1);
333 else
335 while (0 == sjme_atomic_sjme_jint_get(&state->loopThreadReady))
337 sjme_thread_barrier();
338 sjme_thread_yield();
339 sjme_thread_barrier();
343 /* Return resultant state. */
344 *outState = state;
345 return SJME_ERROR_NONE;
347 fail_apiInit:
348 fail_commonInit:
349 fail_alloc:
350 if (state != NULL)
352 sjme_alloc_free(state);
353 state = NULL;
356 return sjme_error_default(error);
359 sjme_errorCode sjme_scritchui_core_apiInit(
360 sjme_attrInNotNull sjme_alloc_pool* inPool,
361 sjme_attrInOutNotNull sjme_scritchui* outState,
362 sjme_attrInNotNull const sjme_scritchui_implFunctions* inImplFunc,
363 sjme_attrInNullable sjme_thread_mainFunc loopExecute,
364 sjme_attrInNullable sjme_frontEnd* initFrontEnd)
366 sjme_errorCode error;
367 sjme_jboolean isFbWrapper;
368 sjme_jboolean needFbWrapper;
369 sjme_scritchui state;
370 sjme_scritchui wrappedState;
372 if (inPool == NULL || inImplFunc == NULL || outState == NULL)
373 return SJME_ERROR_NULL_ARGUMENTS;
375 if (inImplFunc->apiInit == NULL)
376 return sjme_error_notImplemented(0);
378 /* Do we need the framebuffer wrapper? */
379 isFbWrapper = (inImplFunc == &sjme_scritchui_fbFunctions);
380 needFbWrapper = !isFbWrapper;
382 /* Normal top-level initialization. */
383 if (!needFbWrapper)
385 return sjme_scritchui_core_apiInitActual(inPool, outState,
386 inImplFunc, loopExecute, initFrontEnd, NULL);
389 /* Initialize API we are going to wrap. */
390 wrappedState = NULL;
391 if (sjme_error_is(error = sjme_scritchui_core_apiInitActual(inPool,
392 &wrappedState,
393 inImplFunc, NULL,
394 NULL, NULL)) ||
395 wrappedState == NULL)
396 return sjme_error_default(error);
398 /* Debug. */
399 sjme_message("Pre-call init loop belay...");
401 /* We need to initialize our wrapper in the event thread. */
402 if (sjme_error_is(error = wrappedState->api->loopExecuteLater(
403 wrappedState, sjme_scritchui_core_fbBelay,
404 wrappedState)))
405 return sjme_error_default(error);
407 /* Debug. */
408 sjme_message("Now performing framebuffer init...");
410 /* Wrap this with the framebuffer call. */
411 state = NULL;
412 if (sjme_error_is(error = sjme_scritchui_core_apiInitActual(inPool,
413 &state,
414 &sjme_scritchui_fbFunctions,
415 loopExecute, initFrontEnd, wrappedState)) ||
416 state == NULL)
417 return sjme_error_default(error);
419 /* Success! */
420 *outState = state;
421 return SJME_ERROR_NONE;
424 sjme_errorCode sjme_scritchui_core_objectDelete(
425 sjme_attrInNotNull sjme_scritchui inState,
426 sjme_attrInOutNotNull sjme_scritchui_uiCommon* inOutObject)
428 if (inState == NULL || inOutObject == NULL)
429 return SJME_ERROR_NULL_ARGUMENTS;
431 /* Already free? */
432 if (*inOutObject == NULL)
433 return SJME_ERROR_NONE;
435 sjme_todo("Impl?");
436 return sjme_error_notImplemented(0);
439 sjme_errorCode sjme_scritchui_coreGeneric_commonNew(
440 sjme_attrInNotNull sjme_scritchui inState,
441 sjme_attrInOutNotNull sjme_scritchui_uiCommon* outCommon,
442 sjme_attrInPositiveNonZero sjme_jint outCommonSize,
443 sjme_attrInRange(0, SJME_NUM_SCRITCHUI_UI_TYPES)
444 sjme_scritchui_uiType uiType,
445 sjme_attrInNotNull sjme_scritchui_coreGeneric_commonNewImplFunc implNew,
446 sjme_attrInNullable sjme_pointer inData)
448 sjme_errorCode error;
449 sjme_scritchui_uiCommon result;
451 if (inState == NULL || outCommon == NULL)
452 return SJME_ERROR_NULL_ARGUMENTS;
454 if (outCommonSize <= 0)
455 return SJME_ERROR_INVALID_ARGUMENT;
457 /* Missing? */
458 if (implNew == NULL)
459 return sjme_error_notImplemented(uiType);
461 /* Allocate result. */
462 result = NULL;
463 if (sjme_error_is(error = sjme_alloc_weakNew(inState->pool,
464 outCommonSize, NULL, NULL, &result, NULL)) || result == NULL)
465 goto fail_alloc;
467 /* Pre-initialize. */
468 if (sjme_error_is(error = inState->intern->initCommon(inState,
469 result, SJME_JNI_FALSE, uiType)))
470 goto fail_preInit;
472 /* Setup common item. */
473 if (sjme_error_is(error = implNew(inState, result,
474 inData)))
475 goto fail_new;
477 /* Post-initialize. */
478 if (sjme_error_is(error = inState->intern->initCommon(inState,
479 result, SJME_JNI_TRUE, uiType)))
480 goto fail_postInit;
482 /* Success! */
483 *outCommon = result;
484 return SJME_ERROR_NONE;
486 fail_postInit:
487 fail_new:
488 fail_alloc:
489 fail_preInit:
490 if (result != NULL)
491 sjme_alloc_free(result);
493 return sjme_error_default(error);
496 sjme_errorCode sjme_scritchui_coreGeneric_componentNew(
497 sjme_attrInNotNull sjme_scritchui inState,
498 sjme_attrInOutNotNull sjme_scritchui_uiComponent* outComponent,
499 sjme_attrInPositiveNonZero sjme_jint outComponentSize,
500 sjme_attrInRange(0, SJME_NUM_SCRITCHUI_UI_TYPES)
501 sjme_scritchui_uiType uiType,
502 sjme_attrInNotNull sjme_scritchui_coreGeneric_componentNewImplFunc implNew,
503 sjme_attrInNullable sjme_pointer inData)
505 sjme_scritchui_uiComponent result;
506 sjme_errorCode error;
508 if (inState == NULL || outComponent == NULL)
509 return SJME_ERROR_NULL_ARGUMENTS;
511 if (outComponentSize <= 0)
512 return SJME_ERROR_INVALID_ARGUMENT;
514 /* Missing? */
515 if (implNew == NULL)
516 return sjme_error_notImplemented(uiType);
518 /* Allocate result. */
519 result = NULL;
520 if (sjme_error_is(error = sjme_alloc_weakNew(inState->pool,
521 outComponentSize, NULL, NULL, &result, NULL)) || result == NULL)
522 goto fail_alloc;
524 /* Pre-initialize. */
525 if (sjme_error_is(error = inState->intern->initComponent(inState,
526 result, SJME_JNI_FALSE, uiType)))
527 goto fail_preInit;
529 /* Setup native widget. */
530 if (sjme_error_is(error = implNew(inState,
531 result, inData)) ||
532 result->common.handle[0] == NULL)
533 goto fail_newWidget;
535 /* Post-initialize. */
536 if (sjme_error_is(error = inState->intern->initComponent(inState,
537 result, SJME_JNI_TRUE, uiType)))
538 goto fail_postInit;
540 /* Success! */
541 *outComponent = result;
542 return SJME_ERROR_NONE;
544 fail_postInit:
545 fail_newWidget:
546 fail_alloc:
547 fail_preInit:
548 if (result != NULL)
549 sjme_alloc_free(result);
551 return sjme_error_default(error);
554 sjme_pointer sjme_scritchui_checkCast(sjme_scritchui_uiType inType,
555 sjme_pointer inPtr)
557 sjme_scritchui_uiCommon common;
559 if (inPtr == NULL)
560 return NULL;
562 /* Check type. */
563 common = inPtr;
564 if (common->type != inType)
566 sjme_debug_abort();
567 return NULL;
570 /* Return passed value. */
571 return inPtr;
575 * Check cast of a given type against a menu kind.
577 * @param inPtr The input pointer.
578 * @return Always @c inPtr .
579 * @since 2024/07/23
581 sjme_pointer sjme_scritchui_checkCast_menuKind(sjme_pointer inPtr)
583 sjme_scritchui_uiCommon common;
585 if (inPtr == NULL)
586 return NULL;
588 /* Check type. */
589 common = inPtr;
590 if (common->type != SJME_SCRITCHUI_TYPE_MENU &&
591 common->type != SJME_SCRITCHUI_TYPE_MENU_BAR &&
592 common->type != SJME_SCRITCHUI_TYPE_MENU_ITEM)
594 sjme_debug_abort();
595 return NULL;
598 /* Return passed value. */
599 return inPtr;