/* * Copyright (c) 2007-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. */ /* * Drag-and-Drop icon widget. Used with AG_Socket(3). */ #include #ifdef AG_WIDGETS #include #include #include #include #include AG_Icon * AG_IconNew(void *parent, Uint flags) { AG_Icon *icon; icon = Malloc(sizeof(AG_Icon)); AG_ObjectInit(icon, &agIconClass); icon->flags |= flags; AG_ObjectAttach(parent, icon); return (icon); } AG_Icon * AG_IconFromSurface(AG_Surface *su) { AG_Icon *icon; icon = Malloc(sizeof(AG_Icon)); AG_ObjectInit(icon, &agIconClass); AG_IconSetSurface(icon, su); return (icon); } AG_Icon * AG_IconFromBMP(const char *bmpfile) { AG_Icon *icon; AG_Surface *bmp; if ((bmp = AG_SurfaceFromBMP(bmpfile)) == NULL) { return (NULL); } icon = Malloc(sizeof(AG_Icon)); AG_ObjectInit(icon, &agIconClass); AG_IconSetSurfaceNODUP(icon, bmp); return (icon); } static void Init(void *_Nonnull obj) { AG_Icon *icon = obj; WIDGET(icon)->flags |= AG_WIDGET_FOCUSABLE | AG_WIDGET_USE_TEXT; icon->flags = 0; icon->surface = -1; icon->wDND = NULL; icon->sock = NULL; icon->labelTxt[0] = '\0'; icon->labelSurface = -1; icon->xSaved = -1; icon->ySaved = -1; icon->wSaved = -1; icon->hSaved = -1; AG_ColorNone(&icon->cBackground); AG_InitTimer(&icon->toDblClick, "dblClick", 0); } static void SizeRequest(void *_Nonnull obj, AG_SizeReq *_Nonnull r) { AG_Icon *icon = obj; const int paddingHoriz = WIDGET(icon)->paddingLeft + WIDGET(icon)->paddingRight; int wLbl, hLbl, su; r->w = paddingHoriz; r->h = WIDGET(icon)->paddingTop + WIDGET(icon)->paddingBottom; if ((su = icon->surface) != -1) { r->w += WSURFACE(icon,su)->w; r->h += WSURFACE(icon,su)->h; } if (icon->labelTxt[0] != '\0') { if (icon->labelSurface == -1) { AG_TextSize(icon->labelTxt, &wLbl, &hLbl); } else { wLbl = WSURFACE(icon,icon->labelSurface)->w; hLbl = WSURFACE(icon,icon->labelSurface)->h; } r->h += WIDGET(icon)->spacingVert + hLbl; r->w = MAX(r->w, wLbl + paddingHoriz); } } static void Draw(void *_Nonnull obj) { AG_Icon *icon = obj; AG_Surface *S; AG_Rect r; int w_2; if (icon->surface == -1) { return; } S = WSURFACE(icon, icon->surface); r.w = WIDTH(icon); w_2 = r.w >> 1; AG_PushBlendingMode(icon, AG_ALPHA_SRC, AG_ALPHA_ONE_MINUS_SRC); AG_WidgetBlitSurface(icon, icon->surface, w_2 - (S->w >> 1), 0); if (icon->labelTxt[0] != '\0') { if (icon->labelSurface != -1 && icon->flags & AG_ICON_REGEN_LABEL) { AG_WidgetUnmapSurface(icon, icon->labelSurface); icon->labelSurface = -1; } if (icon->labelSurface == -1) { icon->labelSurface = AG_WidgetMapSurface(icon, AG_TextRender(icon->labelTxt)); } if (icon->flags & AG_ICON_BGFILL) { r.x = 0; r.y = S->h; r.h = HEIGHT(icon) - r.y; AG_DrawRect(icon, &r, &icon->cBackground); } AG_WidgetBlitSurface(icon, icon->labelSurface, w_2 - (WSURFACE(icon,icon->labelSurface)->w >> 1), S->h + WIDGET(icon)->spacingVert); } AG_PopBlendingMode(icon); } void AG_IconSetBackgroundFill(AG_Icon *icon, int enable, const AG_Color *c) { AG_OBJECT_ISA(icon, "AG_Widget:AG_Icon:*"); AG_ObjectLock(icon); AG_SETFLAGS(icon->flags, AG_ICON_BGFILL, enable); memcpy(&icon->cBackground, c, sizeof(AG_Color)); AG_Redraw(icon); AG_ObjectUnlock(icon); } void AG_IconSetSurface(AG_Icon *icon, const AG_Surface *S) { AG_Surface *Sdup = (S != NULL) ? AG_SurfaceDup(S) : NULL; AG_OBJECT_ISA(icon, "AG_Widget:AG_Icon:*"); AG_ObjectLock(icon); if (icon->surface != -1) { AG_WidgetReplaceSurface(icon, icon->surface, Sdup); } else { icon->surface = AG_WidgetMapSurface(icon, Sdup); } AG_Redraw(icon); AG_ObjectUnlock(icon); } void AG_IconSetSurfaceNODUP(AG_Icon *icon, AG_Surface *su) { AG_OBJECT_ISA(icon, "AG_Widget:AG_Icon:*"); AG_ObjectLock(icon); if (icon->surface != -1) { AG_WidgetReplaceSurfaceNODUP(icon, icon->surface, su); } else { icon->surface = AG_WidgetMapSurfaceNODUP(icon, su); } AG_Redraw(icon); AG_ObjectUnlock(icon); } void AG_IconSetText(AG_Icon *icon, const char *fmt, ...) { va_list ap; AG_OBJECT_ISA(icon, "AG_Widget:AG_Icon:*"); AG_ObjectLock(icon); if (fmt[0] == '\0') { if (icon->labelSurface != -1) { AG_WidgetUnmapSurface(icon, icon->labelSurface); icon->labelSurface = -1; } icon->labelTxt[0] = '\0'; } else { va_start(ap, fmt); Vsnprintf(icon->labelTxt, sizeof(icon->labelTxt), fmt, ap); va_end(ap); icon->flags |= AG_ICON_REGEN_LABEL; } AG_Redraw(icon); AG_ObjectUnlock(icon); } void AG_IconSetTextS(AG_Icon *icon, const char *s) { AG_OBJECT_ISA(icon, "AG_Widget:AG_Icon:*"); AG_ObjectLock(icon); if (s == NULL || s[0] == '\0') { if (icon->labelSurface != -1) { AG_WidgetUnmapSurface(icon, icon->labelSurface); icon->labelSurface = -1; } icon->labelTxt[0] = '\0'; } else { Strlcpy(icon->labelTxt, s, sizeof(icon->labelTxt)); icon->flags |= AG_ICON_REGEN_LABEL; } AG_Redraw(icon); AG_ObjectUnlock(icon); } AG_WidgetClass agIconClass = { { "Agar(Widget:Icon)", sizeof(AG_Icon), { 1,0, AGC_ICON, 0xE02E }, Init, NULL, /* reset */ NULL, /* destroy */ NULL, /* load */ NULL, /* save */ NULL /* edit */ }, Draw, SizeRequest, 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 */