/*
* Copyright (c) 2004-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 "toolbar.h"
#include "window.h"
#include "primitive.h"
#include "separator.h"
AG_Toolbar *
AG_ToolbarNew(void *parent, enum ag_toolbar_type type, int nRows, Uint flags)
{
AG_Toolbar *bar;
int i;
bar = Malloc(sizeof(AG_Toolbar));
AG_ObjectInit(bar, &agToolbarClass);
bar->flags |= flags;
bar->type = type;
for (i = 0; i < nRows && i < AG_TOOLBAR_MAX_ROWS; i++) {
int bflags = 0;
if (flags & AG_TOOLBAR_HOMOGENOUS) {
bflags = AG_BOX_HOMOGENOUS;
}
switch (type) {
case AG_TOOLBAR_HORIZ:
bar->rows[i] = AG_BoxNew(bar, AG_BOX_HORIZ,
AG_BOX_HFILL|bflags);
break;
case AG_TOOLBAR_VERT:
bar->rows[i] = AG_BoxNew(bar, AG_BOX_VERT,
AG_BOX_VFILL|bflags);
break;
}
AG_BoxSetPadding(bar->rows[i], 1);
AG_BoxSetSpacing(bar->rows[i], 1);
bar->nRows++;
}
AG_BoxSetPadding(AGBOX(bar), 0);
AG_BoxSetSpacing(AGBOX(bar), 0);
AG_ObjectAttach(parent, bar);
return (bar);
}
static void
Init(void *obj)
{
AG_Toolbar *bar = obj;
WIDGET(bar)->flags |= AG_WIDGET_NOSPACING;
bar->flags = 0;
bar->type = AG_TOOLBAR_HORIZ;
bar->nRows = 0;
bar->curRow = 0;
bar->nButtons = 0;
}
static void
StickyUpdate(AG_Event *event)
{
AG_Button *selBtn = AG_SELF();
AG_Toolbar *bar = AG_PTR(1);
AG_Variable *stateb;
AG_Button *oBtn;
int i;
AG_ObjectLock(bar);
for (i = 0; i < bar->nRows; i++) {
OBJECT_FOREACH_CHILD(oBtn, bar->rows[i], ag_button) {
int *state;
stateb = AG_GetVariable(oBtn, "state", &state);
if (bar->flags & AG_TOOLBAR_MULTI_STICKY) {
*state = !(*state);
} else {
*state = (oBtn == selBtn);
}
AG_UnlockVariable(stateb);
}
}
AG_ObjectUnlock(bar);
}
void
AG_ToolbarRow(AG_Toolbar *bar, int row)
{
AG_ObjectLock(bar);
#ifdef AG_DEBUG
if (row < 0 || row >= bar->nRows)
AG_FatalError("no such row %d", row);
#endif
bar->curRow = row;
AG_ObjectUnlock(bar);
}
AG_Button *
AG_ToolbarButtonIcon(AG_Toolbar *bar, AG_Surface *icon, int def,
void (*handler)(AG_Event *), const char *fmt, ...)
{
AG_Button *bu;
AG_Event *ev;
AG_LockVFS(agView);
AG_ObjectLock(bar);
bu = AG_ButtonNew(bar->rows[bar->curRow], 0, NULL);
AG_ButtonSurface(bu, icon);
AG_ButtonSetFocusable(bu, 0);
AG_ButtonSetSticky(bu, bar->flags & AG_TOOLBAR_STICKY);
AG_SetInt(bu, "state", def);
bar->nButtons++;
ev = AG_SetEvent(bu, "button-pushed", handler, NULL);
AG_EVENT_GET_ARGS(ev, fmt);
if (bar->flags & (AG_TOOLBAR_STICKY|AG_TOOLBAR_MULTI_STICKY)) {
AG_AddEvent(bu, "button-pushed", StickyUpdate, "%p", bar);
}
AG_ObjectUnlock(bar);
AG_UnlockVFS(agView);
return (bu);
}
AG_Button *
AG_ToolbarButton(AG_Toolbar *bar, const char *text, int def,
void (*handler)(AG_Event *), const char *fmt, ...)
{
AG_Button *bu;
AG_Event *ev;
AG_LockVFS(agView);
AG_ObjectLock(bar);
bu = AG_ButtonNew(bar->rows[bar->curRow], 0, text);
AG_ButtonSetFocusable(bu, 0);
AG_ButtonSetSticky(bu, bar->flags & AG_TOOLBAR_STICKY);
AG_SetInt(bu, "state", def);
bar->nButtons++;
ev = AG_SetEvent(bu, "button-pushed", handler, NULL);
AG_EVENT_GET_ARGS(ev, fmt);
if (bar->flags & (AG_TOOLBAR_STICKY|AG_TOOLBAR_MULTI_STICKY)) {
AG_AddEvent(bu, "button-pushed", StickyUpdate, "%p", bar);
}
AG_ObjectUnlock(bar);
AG_UnlockVFS(agView);
return (bu);
}
void
AG_ToolbarSeparator(AG_Toolbar *bar)
{
AG_LockVFS(agView);
AG_ObjectLock(bar);
AG_SeparatorNew(bar->rows[bar->curRow],
(bar->type == AG_TOOLBAR_HORIZ) ?
AG_SEPARATOR_VERT : AG_SEPARATOR_HORIZ);
AG_ObjectUnlock(bar);
AG_UnlockVFS(agView);
}
void
AG_ToolbarSelect(AG_Toolbar *bar, AG_Button *bSel)
{
AG_SetInt(bSel, "state", 1);
}
void
AG_ToolbarDeselect(AG_Toolbar *bar, AG_Button *bSel)
{
AG_SetInt(bSel, "state", 0);
}
void
AG_ToolbarSelectOnly(AG_Toolbar *bar, AG_Button *bSel)
{
AG_Variable *stateb;
AG_Button *b;
int i, *state;
AG_ObjectLock(bar);
for (i = 0; i < bar->nRows; i++) {
OBJECT_FOREACH_CHILD(b, bar->rows[i], ag_button) {
stateb = AG_GetVariable(b, "state", &state);
*state = (b == bSel);
AG_UnlockVariable(stateb);
}
}
AG_ObjectUnlock(bar);
}
void
AG_ToolbarSelectAll(AG_Toolbar *bar)
{
AG_Variable *stateb;
AG_Button *b;
int i, *state;
AG_ObjectLock(bar);
for (i = 0; i < bar->nRows; i++) {
OBJECT_FOREACH_CHILD(b, bar->rows[i], ag_button) {
stateb = AG_GetVariable(b, "state", &state);
*state = 1;
AG_UnlockVariable(stateb);
}
}
AG_ObjectUnlock(bar);
}
void
AG_ToolbarDeselectAll(AG_Toolbar *bar)
{
AG_Variable *stateb;
AG_Button *b;
int i, *state;
AG_ObjectLock(bar);
for (i = 0; i < bar->nRows; i++) {
OBJECT_FOREACH_CHILD(b, bar->rows[i], ag_button) {
stateb = AG_GetVariable(b, "state", &state);
*state = 0;
AG_UnlockVariable(stateb);
}
}
AG_ObjectUnlock(bar);
}
static void
SizeRequest(void *p, AG_SizeReq *r)
{
AG_Toolbar *tbar = p;
AG_SizeReq rBar;
int i;
WIDGET_SUPER_OPS(tbar)->size_request(tbar, r);
rBar = *r;
rBar.h = (tbar->type == AG_TOOLBAR_HORIZ) ? r->h/tbar->nRows :
r->w/tbar->nRows;
for (i = 0; i < tbar->nRows; i++)
WIDGET_SUPER_OPS(tbar)->size_request(tbar->rows[i], &rBar);
}
AG_WidgetClass agToolbarClass = {
{
"Agar(Widget:Box:Toolbar)",
sizeof(AG_Toolbar),
{ 0,0 },
Init,
NULL, /* free */
NULL, /* destroy */
NULL, /* load */
NULL, /* save */
NULL /* edit */
},
AG_WidgetInheritDraw,
SizeRequest,
AG_WidgetInheritSizeAllocate
};