/*
* Copyright (c) 2008 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
#include "font_selector.h"
#include
#include
#include
#include "icons.h"
#include "primitive.h"
AG_FontSelector *
AG_FontSelectorNew(void *parent, Uint flags)
{
AG_FontSelector *fs;
fs = Malloc(sizeof(AG_FontSelector));
AG_ObjectInit(fs, &agFontSelectorClass);
fs->flags |= flags;
if (flags & AG_FONTSELECTOR_HFILL) { AG_ExpandHoriz(fs); }
if (flags & AG_FONTSELECTOR_VFILL) { AG_ExpandVert(fs); }
AG_ObjectAttach(parent, fs);
return (fs);
}
static void
Bound(AG_Event *event)
{
AG_FontSelector *fs = AG_SELF();
AG_Variable *b = AG_PTR(1);
AG_Font **pFont;
if (strcmp(b->name, "font") != 0)
return;
AG_ObjectLock(fs);
pFont = b->data.p;
AG_SetPointer(fs, "font", *pFont);
Strlcpy(fs->curFace, OBJECT(*pFont)->name, sizeof(fs->curFace));
fs->curSize = (*pFont)->size;
fs->curStyle = (*pFont)->flags;
fs->tlFaces->flags |= AG_TLIST_SCROLLTOSEL;
fs->tlSizes->flags |= AG_TLIST_SCROLLTOSEL;
AG_ObjectUnlock(fs);
}
static void
UpdateFontSelection(AG_FontSelector *fs)
{
AG_Variable *bFont;
AG_Font *font, **pFont;
font = AG_FetchFont(fs->curFace, fs->curSize, fs->curStyle);
if (font == NULL) {
AG_TextError(_("Error opening font: %s"), AG_GetError());
return;
}
bFont = AG_GetVariable(fs, "font", &pFont);
*pFont = font;
AG_UnlockVariable(bFont);
}
static void
UpdatePreview(AG_FontSelector *fs)
{
AG_Variable *bFont;
AG_Font **pFont;
AG_Surface *s;
bFont = AG_GetVariable(fs, "font", &pFont);
AG_PushTextState();
if (*pFont != NULL) {
AG_TextFont(*pFont);
}
s = AG_TextRender(_("The Quick Brown Fox Jumps Over The Lazy Dog"));
if (fs->sPreview == -1) {
fs->sPreview = AG_WidgetMapSurfaceNODUP(fs, s);
} else {
AG_WidgetReplaceSurfaceNODUP(fs, fs->sPreview, s);
}
AG_PopTextState();
AG_UnlockVariable(bFont);
}
static void
UpdateFaces(AG_Event *event)
{
AG_Variable *bFont;
AG_Font **pFont;
AG_FontSelector *fs = AG_SELF();
char fontPath[AG_SEARCHPATH_MAX], *pFontPath = &fontPath[0];
AG_TlistItem *ti;
char *s;
int i;
const int stdSizes[] = { 4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,
22,24,26,28,32,48,64 };
const int nStdSizes = sizeof(stdSizes) / sizeof(stdSizes[0]);
bFont = AG_GetVariable(fs, "font", &pFont);
AG_PushTextState();
fs->flags &= ~(AG_FONTSELECTOR_UPDATE);
for (i = 0; i < agBuiltinFontCount; i++) {
AG_StaticFont *font = agBuiltinFonts[i];
ti = AG_TlistAdd(fs->tlFaces, NULL, "_%s", font->name);
ti->p1 = font;
if (*pFont != NULL &&
strcmp(ti->text, OBJECT(*pFont)->name) == 0)
ti->selected++;
}
AG_CopyCfgString("font-path", fontPath, sizeof(fontPath));
while ((s = AG_Strsep(&pFontPath, ":")) != NULL) {
AG_Dir *dir;
int i;
if ((dir = AG_OpenDir(s)) == NULL) {
AG_Verbose(_("Ignoring: %s\n"), AG_GetError());
continue;
}
for (i = 0; i < dir->nents; i++) {
char path[AG_FILENAME_MAX];
AG_FileInfo info;
char *file = dir->ents[i], *pExt;
if (file[0] == '.' ||
(pExt = strrchr(file, '.')) == NULL) {
continue;
}
if (strcmp(pExt, ".ttf") != 0 &&
strcmp(pExt, ".TTF") != 0)
continue;
Strlcpy(path, s, sizeof(path));
Strlcat(path, AG_PATHSEP, sizeof(path));
Strlcat(path, file, sizeof(path));
if (AG_GetFileInfo(path, &info) == -1 ||
info.type != AG_FILE_REGULAR) {
continue;
}
ti = AG_TlistAdd(fs->tlFaces, NULL, "%s", file);
if (*pFont != NULL &&
strcmp(file, OBJECT(*pFont)->name) == 0)
ti->selected++;
}
AG_CloseDir(dir);
}
/* XXX */
for (i = 0; i < nStdSizes; i++) {
ti = AG_TlistAdd(fs->tlSizes, NULL, "%d", stdSizes[i]);
if (*pFont != NULL &&
stdSizes[i] == (*pFont)->size)
ti->selected++;
}
ti = AG_TlistAdd(fs->tlStyles, NULL, _("Regular"));
if (*pFont != NULL && (*pFont)->flags == 0) { ti->selected++; }
ti = AG_TlistAdd(fs->tlStyles, NULL, _("Italic"));
if (*pFont != NULL && (*pFont)->flags == AG_FONT_ITALIC) { ti->selected++; }
ti = AG_TlistAdd(fs->tlStyles, NULL, _("Bold"));
if (*pFont != NULL && (*pFont)->flags == AG_FONT_BOLD) { ti->selected++; }
ti = AG_TlistAdd(fs->tlStyles, NULL, _("Bold Italic"));
if (*pFont != NULL && (*pFont)->flags == (AG_FONT_BOLD|AG_FONT_ITALIC)) { ti->selected++; }
UpdatePreview(fs);
AG_UnlockVariable(bFont);
}
static void
SelectedFace(AG_Event *event)
{
AG_FontSelector *fs = AG_PTR(1);
AG_TlistItem *it = AG_PTR(2);
Strlcpy(fs->curFace, it->text, sizeof(fs->curFace));
UpdateFontSelection(fs);
UpdatePreview(fs);
}
static void
SelectedStyle(AG_Event *event)
{
AG_FontSelector *fs = AG_PTR(1);
AG_TlistItem *it = AG_PTR(2);
Uint flags = 0;
if (!strcmp(it->text, _("Italic")))
flags |= AG_FONT_ITALIC;
if (!strcmp(it->text, _("Bold")))
flags |= AG_FONT_BOLD;
if (!strcmp(it->text, _("Bold Italic")))
flags |= (AG_FONT_BOLD|AG_FONT_ITALIC);
fs->curStyle = flags;
UpdateFontSelection(fs);
UpdatePreview(fs);
}
static void
SelectedSize(AG_Event *event)
{
AG_FontSelector *fs = AG_PTR(1);
AG_TlistItem *it = AG_PTR(2);
fs->curSize = atoi(it->text);
UpdateFontSelection(fs);
UpdatePreview(fs);
}
static void
Init(void *obj)
{
AG_FontSelector *fs = obj;
fs->flags = AG_FONTSELECTOR_UPDATE;
fs->hPane = AG_PaneNewHoriz(fs, AG_PANE_EXPAND);
fs->tlFaces = AG_TlistNew(fs->hPane->div[0], AG_TLIST_EXPAND);
fs->hPane2 = AG_PaneNewHoriz(fs->hPane->div[1], AG_PANE_EXPAND);
fs->tlStyles = AG_TlistNew(fs->hPane2->div[0], AG_TLIST_EXPAND);
fs->sizeBox = AG_BoxNewVert(fs->hPane2->div[1], AG_BOX_EXPAND);
fs->tlSizes = AG_TlistNew(fs->sizeBox, AG_TLIST_EXPAND);
fs->font = NULL;
fs->curFace[0] = '\0';
fs->curStyle = 0;
fs->curSize = 0;
fs->rPreview = AG_RECT(0,0,0,64);
fs->sPreview = -1;
AG_TlistSizeHint(fs->tlFaces, "XXXXXXXXXXXXXXX", 8);
AG_TlistSizeHint(fs->tlStyles, "XXXXXXXXX", 8);
AG_TlistSizeHint(fs->tlSizes, "100", 8);
AG_BindPointer(fs, "font", (void *)&fs->font);
AG_SetEvent(fs, "bound", Bound, NULL);
AG_SetEvent(fs, "widget-shown", UpdateFaces, NULL);
AG_SetEvent(fs->tlFaces, "tlist-selected", SelectedFace, "%p", fs);
AG_SetEvent(fs->tlStyles, "tlist-selected", SelectedStyle, "%p", fs);
AG_SetEvent(fs->tlSizes, "tlist-selected", SelectedSize, "%p", fs);
}
static void
Draw(void *obj)
{
AG_FontSelector *fs = obj;
AG_Widget *chld;
WIDGET_FOREACH_CHILD(chld, obj)
AG_WidgetDraw(chld);
AG_DrawBox(fs, fs->rPreview, -1, AG_COLOR(FIXED_BOX_COLOR));
if (fs->sPreview != -1) {
AG_Surface *su = WSURFACE(fs,fs->sPreview);
AG_WidgetBlitSurface(fs, fs->sPreview,
fs->rPreview.x + fs->rPreview.w/2 - su->w/2,
fs->rPreview.y + fs->rPreview.h/2 - su->h/2);
}
}
static void
SizeRequest(void *obj, AG_SizeReq *r)
{
AG_FontSelector *fs = obj;
AG_SizeReq rChld;
AG_WidgetSizeReq(fs->hPane, &rChld);
r->w = rChld.w;
r->h = rChld.h + fs->rPreview.h;
}
static int
SizeAllocate(void *obj, const AG_SizeAlloc *a)
{
AG_FontSelector *fs = obj;
AG_SizeAlloc aChld;
/* Size horizontal pane */
aChld.x = 0;
aChld.y = 0;
aChld.w = a->w;
aChld.h = a->h - fs->rPreview.h;
AG_WidgetSizeAlloc(fs->hPane, &aChld);
fs->rPreview.x = 0;
fs->rPreview.y = a->h - fs->rPreview.h;
fs->rPreview.w = a->w;
return (0);
}
AG_WidgetClass agFontSelectorClass = {
{
"Agar(Widget:FontSelector)",
sizeof(AG_FontSelector),
{ 0,0 },
Init,
NULL, /* free */
NULL, /* destroy */
NULL, /* load */
NULL, /* save */
NULL /* edit */
},
Draw,
SizeRequest,
SizeAllocate
};