/* * Copyright (c) 2005-2007 Hypertriton, Inc. * 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. */ #include #include "objsel.h" #include "window.h" #include "primitive.h" #include "label.h" #include #include AG_ObjectSelector * AG_ObjectSelectorNew(void *parent, int flags, void *pobj, void *root, const char *fmt, ...) { AG_ObjectSelector *os; va_list ap; os = Malloc(sizeof(AG_ObjectSelector)); AG_ObjectInit(os, &agObjectSelectorClass); os->flags |= flags; os->pobj = pobj; os->root = root; if (fmt != NULL) { char label[AG_LABEL_MAX]; va_start(ap, fmt); Vsnprintf(label, sizeof(label), fmt, ap); va_end(ap); AG_TextboxSetLabel(os->com.tbox, "%s", 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_TlistAdd(tl, AG_ObjectIcon(pob), "%s", 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_VISIBLE_CHILDREN; } if ((it->flags & AG_TLIST_HAS_CHILDREN)) { TAILQ_FOREACH(cob, &pob->children, cobjs) FindObjects(os, tl, cob, depth+1); } } static void PollObjects(AG_Event *event) { AG_Tlist *tl = AG_SELF(); AG_ObjectSelector *os = AG_PTR(1); AG_TlistClear(tl); AG_ObjectLock(os); AG_LockVFS(os->root); FindObjects(os, tl, os->root, 0); AG_UnlockVFS(os->root); AG_ObjectUnlock(os); AG_TlistRestore(tl); } static void SelectObject(AG_Event *event) { AG_ObjectSelector *os = AG_PTR(1); AG_TlistItem *it = AG_PTR(2); AG_Variable *objectb; void **object; objectb = AG_GetVariable(os, "object", &object); if (*object != NULL) { if (os->flags & AG_OBJSEL_PAGE_DATA) { AG_ObjectPageOut(*object); } AG_ObjectDelDep(os->pobj, *object); } *object = it->p1; AG_ObjectAddDep(os->pobj, *object, 1); if (os->flags & AG_OBJSEL_PAGE_DATA) { AG_ObjectPageIn(*object); } AG_UnlockVariable(objectb); } static void Bound(AG_Event *event) { AG_ObjectSelector *os = AG_SELF(); AG_Variable *b = AG_PTR(1); if (strcmp(b->name, "object") == 0) { void **object = b->data.p; if (*object != NULL) AG_ComboSelectPointer(&os->com, *object); } } static void Init(void *obj) { AG_Combo *com = obj; AG_ObjectSelector *os = obj; AG_ExpandHoriz(os); com->flags |= AG_COMBO_POLL; com->list->flags |= AG_TLIST_POLL|AG_TLIST_TREE; 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.list, "tlist-poll", PollObjects, "%p", os); AG_SetEvent(&os->com, "combo-selected", SelectObject, "%p", os); AG_SetEvent(os, "bound", Bound, NULL); } void AG_ObjectSelectorMaskType(AG_ObjectSelector *os, const char *type) { 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), { 0,0 }, Init, NULL, /* free */ NULL, /* destroy */ NULL, /* load */ NULL, /* save */ NULL /* edit */ }, AG_WidgetInheritDraw, AG_WidgetInheritSizeRequest, AG_WidgetInheritSizeAllocate };