/* * Copyright (c) 2002-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 "ucombo.h" #include "primitive.h" AG_UCombo * AG_UComboNew(void *parent, Uint flags) { AG_UCombo *com; com = Malloc(sizeof(AG_UCombo)); AG_ObjectInit(com, &agUComboClass); com->flags |= flags; if (flags & AG_UCOMBO_HFILL) { AG_ExpandHoriz(com); } if (flags & AG_UCOMBO_VFILL) { AG_ExpandVert(com); } if (flags & AG_UCOMBO_SCROLLTOSEL) com->list->flags |= AG_TLIST_SCROLLTOSEL; AG_ObjectAttach(parent, com); return (com); } AG_UCombo * AG_UComboNewPolled(void *parent, Uint flags, AG_EventFn fn, const char *fmt, ...) { AG_UCombo *com; AG_Event *ev; com = AG_UComboNew(parent, flags); AG_ObjectLock(com); com->list->flags |= AG_TLIST_POLL; ev = AG_SetEvent(com->list, "tlist-poll", fn, NULL); AG_EVENT_GET_ARGS(ev, fmt); AG_ObjectUnlock(com); return (com); } /* The UCombo must be locked. */ static void Collapse(AG_UCombo *com) { if (com->panel == NULL) { return; } com->wSaved = WIDGET(com->panel)->w; com->hSaved = WIDGET(com->panel)->h; AG_WindowHide(com->panel); AG_ObjectDetach(com->list); AG_ViewDetach(com->panel); com->panel = NULL; AG_SetInt(com->button, "state", 0); } static void ModalClose(AG_Event *event) { AG_UCombo *com = AG_PTR(1); AG_ObjectLock(com); if (com->panel != NULL) { Collapse(com); } AG_ObjectUnlock(com); } static void Expand(AG_Event *event) { AG_UCombo *com = AG_PTR(1); int expand = AG_INT(2); AG_SizeReq rList; int x, y, w, h; AG_ObjectLock(com); if (expand) { com->panel = AG_WindowNew(AG_WINDOW_MODAL|AG_WINDOW_NOTITLE); AG_WindowSetPadding(com->panel, 0, 0, 0, 0); AG_ObjectAttach(com->panel, com->list); if (com->wSaved > 0) { w = com->wSaved; h = com->hSaved; } else { AG_TlistSizeHintPixels(com->list, com->wPreList, com->hPreList); AG_WidgetSizeReq(com->list, &rList); w = rList.w + com->panel->wBorderSide*2; h = rList.h + com->panel->wBorderBot; } x = WIDGET(com)->rView.x2 - w; y = WIDGET(com)->rView.y1; AG_SetEvent(com->panel, "window-modal-close", ModalClose, "%p", com); AG_WindowSetGeometry(com->panel, x, y, w, h); AG_WindowShow(com->panel); } else { Collapse(com); } AG_ObjectUnlock(com); } static void SelectedItem(AG_Event *event) { AG_Tlist *tl = AG_SELF(); AG_UCombo *com = AG_PTR(1); AG_TlistItem *it; AG_ObjectLock(com); AG_ObjectLock(tl); if ((it = AG_TlistSelectedItem(tl)) != NULL) { it->selected++; AG_ButtonText(com->button, "%s", it->text); AG_PostEvent(NULL, com, "ucombo-selected", "%p", it); } Collapse(com); AG_ObjectUnlock(tl); AG_ObjectUnlock(com); } static void Init(void *obj) { AG_UCombo *com = obj; WIDGET(com)->flags |= AG_WIDGET_UNFOCUSED_BUTTONUP; com->flags = 0; com->panel = NULL; com->wSaved = 0; com->hSaved = 0; com->hPreList = 4; AG_TextSize("XXXXXXXX", &com->wPreList, NULL); com->button = AG_ButtonNew(com, AG_BUTTON_STICKY, _("...")); AG_ButtonSetPadding(com->button, 1,1,1,1); AG_WidgetSetFocusable(com->button, 0); AG_SetEvent(com->button, "button-pushed", Expand, "%p", com); com->list = Malloc(sizeof(AG_Tlist)); AG_ObjectInit(com->list, &agTlistClass); AG_Expand(com->list); AG_SetEvent(com->list, "tlist-changed", SelectedItem, "%p", com); AG_WidgetForwardFocus(com, com->button); } void AG_UComboSizeHint(AG_UCombo *com, const char *text, int h) { AG_ObjectLock(com); AG_TextSize(text, &com->wPreList, NULL); com->hPreList = h; AG_ObjectUnlock(com); } void AG_UComboSizeHintPixels(AG_UCombo *com, int w, int h) { AG_ObjectLock(com); com->wPreList = w; com->hPreList = h; AG_ObjectUnlock(com); } static void Destroy(void *p) { AG_UCombo *com = p; if (com->panel != NULL) { AG_WindowHide(com->panel); AG_ObjectDetach(com->list); AG_ViewDetach(com->panel); } AG_ObjectDestroy(com->list); } static void Draw(void *obj) { AG_UCombo *com = obj; AG_WidgetDraw(com->button); } static void SizeRequest(void *obj, AG_SizeReq *r) { AG_UCombo *com = obj; AG_SizeReq rButton; AG_WidgetSizeReq(com->button, &rButton); r->w = rButton.w; r->h = rButton.h; } static int SizeAllocate(void *obj, const AG_SizeAlloc *a) { AG_UCombo *com = obj; AG_SizeAlloc aButton; aButton.x = 0; aButton.y = 0; aButton.w = a->w; aButton.h = a->h; AG_WidgetSizeAlloc(com->button, &aButton); return (0); } AG_WidgetClass agUComboClass = { { "Agar(Widget:UCombo)", sizeof(AG_UCombo), { 0,0 }, Init, NULL, /* free */ Destroy, NULL, /* load */ NULL, /* save */ NULL /* edit */ }, Draw, SizeRequest, SizeAllocate };