/* * Copyright (c) 2005-2023 Julien Nadeau Carriere * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * A subclass of AG_Combo(3) for selecting an element in a VFS of AG_Objects. */ #include #if defined(AG_WIDGETS) #include #include #include #include #include #include #include AG_ObjectSelector * AG_ObjectSelectorNew(void *parent, int flags, void *pobj, void *root, const char *fmt, ...) { char *label; AG_ObjectSelector *os; va_list ap; os = Malloc(sizeof(AG_ObjectSelector)); AG_ObjectInit(os, &agObjectSelectorClass); os->flags |= flags; os->pobj = pobj; os->root = root; va_start(ap, fmt); Vasprintf(&label, fmt, ap); va_end(ap); AG_TextboxSetLabelS(os->com.tbox, label); free(label); AG_ObjectAttach(parent, os); return (os); } /* Select an object in the list. */ AG_TlistItem * AG_ObjectSelectorSelect(AG_ObjectSelector *os, void *p) { return (AG_ComboSelectPointer(&os->com, p)); } static void FindObjects(AG_ObjectSelector *os, AG_Tlist *tl, AG_Object *pob, int depth) { AG_Object *cob; AG_TlistItem *it; int nosel = 0; if (!AG_OfClass(pob, os->type_mask)) { if (!TAILQ_EMPTY(&pob->children)) { nosel++; } else { return; } } it = AG_TlistAddS(tl, NULL, pob->name); it->depth = depth; it->cat = "object"; it->p1 = pob; if (nosel) { it->flags |= AG_TLIST_NO_SELECT; } if (!TAILQ_EMPTY(&pob->children)) { it->flags |= AG_TLIST_HAS_CHILDREN; if (pob->parent == NULL) it->flags |= AG_TLIST_ITEM_EXPANDED; } if ((it->flags & AG_TLIST_HAS_CHILDREN)) { TAILQ_FOREACH(cob, &pob->children, cobjs) FindObjects(os, tl, cob, depth+1); } } static void ExpandObjects(AG_Event *event) { AG_Tlist *tl = AG_TLIST_SELF(); AG_ObjectSelector *os = AG_OBJECTSELECTOR_PTR(1); AG_ObjectLock(os); AG_LockVFS(os->root); FindObjects(os, tl, os->root, 0); AG_UnlockVFS(os->root); AG_ObjectUnlock(os); } static void SelectObject(AG_Event *event) { AG_ObjectSelector *os = AG_OBJECTSELECTOR_PTR(1); const AG_TlistItem *it = AG_TLISTITEM_PTR(2); AG_Variable *V; void **object; V = AG_GetVariable(os, "object", (void *)&object); *object = it->p1; AG_UnlockVariable(V); } static void Bound(AG_Event *event) { AG_ObjectSelector *os = AG_OBJECTSELECTOR_SELF(); const AG_Variable *V = AG_PTR(1); if (strcmp(V->name, "object") == 0) { void **object = V->data.p; if (*object != NULL) AG_ComboSelectPointer(&os->com, *object); } } static void Init(void *obj) { AG_Combo *com = obj; AG_ObjectSelector *os = obj; WIDGET(os)->flags |= AG_WIDGET_HFILL; com->flags |= AG_COMBO_POLL; os->object = NULL; os->flags = 0; os->pobj = NULL; os->root = NULL; os->type_mask[0] = '*'; os->type_mask[1] = '\0'; AG_BindPointer(os, "object", &os->object); AG_SetEvent(&os->com, "combo-expand", ExpandObjects, "%p", os); AG_SetEvent(&os->com, "combo-selected", SelectObject, "%p", os); AG_SetEvent(os, "bound", Bound, NULL); OBJECT(os)->flags |= AG_OBJECT_BOUND_EVENTS; } void AG_ObjectSelectorMaskType(AG_ObjectSelector *os, const char *type) { AG_OBJECT_ISA(os, "AG_Widget:AG_Combo:AG_ObjectSelector:*"); AG_ObjectLock(os); Strlcpy(os->type_mask, type, sizeof(os->type_mask)); AG_ObjectUnlock(os); } AG_WidgetClass agObjectSelectorClass = { { "Agar(Widget:Combo:ObjectSelector)", sizeof(AG_ObjectSelector), { 1,0, AGC_OBJECT_SELECTOR, 0xE063 }, Init, NULL, /* reset */ NULL, /* destroy */ NULL, /* load */ NULL, /* save */ NULL /* edit */ }, NULL, /* draw */ NULL, /* size_request */ NULL, /* size_allocate */ NULL, /* mouse_button_down */ NULL, /* mouse_button_up */ NULL, /* mouse_motion */ NULL, /* key_down */ NULL, /* key_up */ NULL, /* touch */ NULL, /* ctrl */ NULL /* joy */ }; #endif /* AG_WIDGETS */