/*
* 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.
*/
/*
* This tool allows the user to browse through the widget tree
* and manipulate generic Widget and Window parameters.
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "dev.h"
#include
static void
FindWidgets(AG_Widget *wid, AG_Tlist *widtl, int depth)
{
char text[AG_TLIST_LABEL_MAX];
AG_TlistItem *it;
Strlcpy(text, OBJECT(wid)->name, sizeof(text));
if (AG_OfClass(wid, "AG_Widget:AG_Window:*")) {
AG_Window *win = (AG_Window *)wid;
Strlcat(text, " (", sizeof(text));
Strlcat(text, win->caption, sizeof(text));
Strlcat(text, ")", sizeof(text));
}
it = AG_TlistAddPtr(widtl, NULL, text, wid);
it->depth = depth;
it->cat = "widget";
if (!TAILQ_EMPTY(&OBJECT(wid)->children)) {
it->flags |= AG_TLIST_HAS_CHILDREN;
}
if ((it->flags & AG_TLIST_HAS_CHILDREN) &&
AG_TlistVisibleChildren(widtl, it)) {
AG_Widget *cwid;
OBJECT_FOREACH_CHILD(cwid, wid, ag_widget)
FindWidgets(cwid, widtl, depth+1);
}
}
static void
FindWindows(AG_Tlist *tl, AG_Window *win, int depth)
{
char text[AG_TLIST_LABEL_MAX];
AG_Window *wSub;
AG_Widget *wChild;
AG_TlistItem *it;
if (strcmp(win->caption, "win-popup") == 0)
return;
Strlcpy(text, win->caption, sizeof(text));
it = AG_TlistAdd(tl, NULL, "%s (%s)", win->caption,
OBJECT(win)->name);
it->p1 = win;
it->depth = depth;
it->cat = "window";
if (!TAILQ_EMPTY(&OBJECT(win)->children) ||
!TAILQ_EMPTY(&win->subwins)) {
it->flags |= AG_TLIST_HAS_CHILDREN;
}
if ((it->flags & AG_TLIST_HAS_CHILDREN) &&
AG_TlistVisibleChildren(tl, it)) {
TAILQ_FOREACH(wSub, &win->subwins, swins)
FindWindows(tl, wSub, depth+1);
OBJECT_FOREACH_CHILD(wChild, win, ag_widget)
FindWidgets(wChild, tl, depth+1);
}
}
static void
PollWindows(AG_Event *event)
{
AG_Tlist *tl = AG_SELF();
AG_Window *win;
AG_TlistClear(tl);
AG_LockVFS(agView);
TAILQ_FOREACH_REVERSE(win, &agView->windows, ag_windowq, windows) {
FindWindows(tl, win, 0);
}
AG_UnlockVFS(agView);
AG_TlistRestore(tl);
}
static void
ShowWindow(AG_Event *event)
{
AG_Window *win = AG_PTR(1);
AG_WindowShow(win);
}
static void
HideWindow(AG_Event *event)
{
AG_Window *win = AG_PTR(1);
AG_WindowHide(win);
}
static void
PollSurfaces(AG_Event *event)
{
AG_Tlist *tl = AG_SELF();
AG_Widget *wid = AG_PTR(1);
Uint i;
AG_TlistBegin(tl);
for (i = 0; i < wid->nsurfaces; i++) {
AG_Surface *su = WSURFACE(wid,i);
AG_TlistAdd(tl, su, "Surface%u (%ux%u, %ubpp)",
i, su->w, su->h, su->format->BitsPerPixel);
}
AG_TlistEnd(tl);
}
static void
UpdateWindow(AG_Event *event)
{
AG_Window *win = AG_PTR(1);
AG_WindowUpdate(win);
}
static void
UpdateWindowCaption(AG_Event *event)
{
AG_Window *win = AG_PTR(1);
AG_WindowUpdateCaption(win);
}
static void
EditWidgetParams(AG_Event *event)
{
AG_TlistItem *ti = AG_PTR(2);
AG_Widget *wid = ti->p1;
AG_Window *win;
AG_Notebook *nb;
AG_NotebookTab *nTab;
AG_Textbox *tb;
AG_Label *lbl;
AG_MSpinbutton *msb;
win = AG_WindowNew(0);
AG_WindowSetCaption(win, _("GUI Debugger: <%s>"), OBJECT(wid)->name);
nb = AG_NotebookNew(win, AG_NOTEBOOK_EXPAND);
nTab = AG_NotebookAddTab(nb, _("Widget"), AG_BOX_VERT);
{
static const AG_FlagDescr flagDescr[] = {
{ AG_WIDGET_FOCUSABLE, "FOCUSABLE",1 },
{ AG_WIDGET_FOCUSED, "FOCUSED",0 },
{ AG_WIDGET_UNFOCUSED_MOTION, "UNFOCUSED_MOTION",1 },
{ AG_WIDGET_UNFOCUSED_BUTTONUP, "UNFOCUSED_BUTTONUP",1 },
{ AG_WIDGET_UNFOCUSED_BUTTONDOWN, "UNFOCUSED_BUTTONDOWN",1},
{ AG_WIDGET_HFILL, "HFILL",1 },
{ AG_WIDGET_VFILL, "VFILL",1 },
{ AG_WIDGET_HIDE, "HIDE",1 },
{ AG_WIDGET_DISABLED, "DISABLED",1 },
{ AG_WIDGET_CATCH_TAB, "CATCH_TAB",1 },
{ AG_WIDGET_PRIO_MOTION, "PRIO_MOTION",1 },
{ AG_WIDGET_UNDERSIZE, "UNDERSIZE",0 },
{ AG_WIDGET_NOSPACING, "NOSPACING",1 },
{ 0, NULL,0 }
};
tb = AG_TextboxNew(nTab, 0, _("Name: "));
AG_TextboxBindUTF8(tb, OBJECT(wid)->name,
sizeof(OBJECT(wid)->name));
AG_LabelNew(nTab, 0, _("Class: %s"), OBJECT(wid)->cls->name);
AG_SeparatorNewHoriz(nTab);
AG_CheckboxSetFromFlags(nTab, 0, &wid->flags, flagDescr);
}
if (AG_OfClass(wid, "AG_Widget:AG_Window:*")) {
AG_Window *ww = (AG_Window *)wid;
static const AG_FlagDescr flagDescr[] = {
{ AG_WINDOW_MODAL, "MODAL",1 },
{ AG_WINDOW_MAXIMIZED, "MAXIMIZED",1 },
{ AG_WINDOW_MINIMIZED, "MINIMIZED",1 },
{ AG_WINDOW_KEEPABOVE, "KEEPABOVE",1 },
{ AG_WINDOW_KEEPBELOW, "KEEPBELOW",1 },
{ AG_WINDOW_DENYFOCUS, "DENYFOCUS",1 },
{ AG_WINDOW_NOBORDERS, "NOBORDERS",1 },
{ AG_WINDOW_NOHRESIZE, "NOHRESIZE",1 },
{ AG_WINDOW_NOVRESIZE, "NOVRESIZE",1 },
{ AG_WINDOW_NOBACKGROUND, "NOBACKGROUND",1 },
{ AG_WINDOW_NOUPDATERECT, "NOUPDATERECT",1 },
{ 0, NULL,0 }
};
AG_Numerical *nums[4];
int i;
nTab = AG_NotebookAddTab(nb, _("Window"), AG_BOX_VERT);
tb = AG_TextboxNew(nTab, 0, _("Caption: "));
AG_TextboxBindUTF8(tb, ww->caption, sizeof(ww->caption));
AG_SetEvent(tb, "textbox-postchg", UpdateWindowCaption,
"%p", ww);
#ifdef AG_THREADS
lbl = AG_LabelNewPolledMT(nTab, AG_LABEL_HFILL,
&OBJECT(ww)->lock,
"Flags: <%[flags]>", &ww->flags);
#else
lbl = AG_LabelNewPolled(nTab, AG_LABEL_HFILL,
"Flags: <%[flags]>", &ww->flags);
#endif
AG_SeparatorNewHoriz(nTab);
AG_CheckboxSetFromFlags(nTab, 0, &ww->flags, flagDescr);
AG_SeparatorNewHoriz(nTab);
nums[0] = AG_NumericalNewIntR(nTab, 0, "px",
_("Widget spacing: "), &ww->spacing, 0, 255);
nums[1] = AG_NumericalNewIntR(nTab, 0, "px",
_("Top padding: "), &ww->tPad, 0, 255);
nums[2] = AG_NumericalNewIntR(nTab, 0, "px",
_("Bottom padding: "), &ww->bPad, 0, 255);
nums[3] = AG_NumericalNewIntR(nTab, 0, "px",
_("Left padding: "), &ww->lPad, 0, 255);
nums[4] = AG_NumericalNewIntR(nTab, 0, "px",
_("Right padding: "), &ww->rPad, 0, 255);
for (i = 0; i < 4; i++) {
AG_SetEvent(nums[i], "numerical-changed",
UpdateWindow, "%p", ww);
}
}
if (AG_OfClass(wid, "AG_Widget:AG_Box:*")) {
AG_Box *box = (AG_Box *)wid;
AG_Window *wp = AG_ParentWindow(box);
AG_Numerical *num;
nTab = AG_NotebookAddTab(nb, _("Box"), AG_BOX_VERT);
num = AG_NumericalNewIntR(nTab, 0, "px", _("Padding: "),
&box->padding, 0, 255);
AG_SetEvent(num, "numerical-changed", UpdateWindow, "%p", wp);
num = AG_NumericalNewIntR(nTab, 0, "px", _("Spacing: "),
&box->spacing, 0, 255);
AG_SetEvent(num, "numerical-changed", UpdateWindow, "%p", wp);
AG_CheckboxNewFlag(nTab, 0, _("Homogenous"),
&box->flags, AG_BOX_HOMOGENOUS);
AG_CheckboxNewFlag(nTab, 0, _("Visual frame"),
&box->flags, AG_BOX_FRAME);
}
if (AG_OfClass(wid, "AG_Widget:AG_Editable:*")) {
AG_Editable *ed = (AG_Editable *)wid;
nTab = AG_NotebookAddTab(nb, _("Editable"), AG_BOX_VERT);
AG_NumericalNewInt(nTab, 0, "px", "x: ", &ed->x);
AG_NumericalNewInt(nTab, 0, "px", "xMax: ", &ed->xMax);
AG_NumericalNewInt(nTab, 0, "px", "y: ", &ed->y);
AG_NumericalNewInt(nTab, 0, "px", "yMax: ", &ed->yMax);
AG_NumericalNewInt(nTab, 0, "px", "yVis: ", &ed->yVis);
AG_SeparatorNewHoriz(nTab);
AG_NumericalNewInt(nTab, 0, "px", "pos: ", &ed->pos);
AG_NumericalNewInt(nTab, 0, "px", "xCurs: ", &ed->xCurs);
AG_NumericalNewInt(nTab, 0, "px", "yCurs: ", &ed->yCurs);
}
nTab = AG_NotebookAddTab(nb, _("Geometry"), AG_BOX_VERT);
{
msb = AG_MSpinbuttonNew(nTab, 0, ",", "Container coords: ");
AG_BindInt(msb, "xvalue", &wid->x);
AG_BindInt(msb, "yvalue", &wid->y);
msb = AG_MSpinbuttonNew(nTab, 0, "x", "Geometry: ");
AG_BindInt(msb, "xvalue", &wid->w);
AG_BindInt(msb, "yvalue", &wid->h);
msb = AG_MSpinbuttonNew(nTab, 0, ",", "View coords (UL): ");
AG_BindInt(msb, "xvalue", &wid->rView.x1);
AG_BindInt(msb, "yvalue", &wid->rView.y1);
msb = AG_MSpinbuttonNew(nTab, 0, ",", "View coords (LR): ");
AG_BindInt(msb, "xvalue", &wid->rView.x2);
AG_BindInt(msb, "yvalue", &wid->rView.y2);
}
nTab = AG_NotebookAddTab(nb, _("Surfaces"), AG_BOX_VERT);
{
AG_Tlist *tlSurf;
tlSurf = AG_TlistNewPolled(nTab, AG_TLIST_EXPAND,
PollSurfaces, "%p", wid);
AG_TlistSetItemHeight(tlSurf, 16);
}
AG_WindowShow(win);
}
static void
CreateWindowMenu(AG_Event *event)
{
AG_MenuItem *mi = AG_SENDER();
AG_Tlist *tl = AG_PTR(1);
AG_TlistItem *ti = AG_TlistSelectedItem(tl);
AG_Window *win;
if (ti == NULL || !AG_OfClass(ti->p1, "AG_Widget:AG_Window:*")) {
return;
}
win = ti->p1;
if (win->visible) {
AG_MenuAction(mi, _("Hide window"), NULL,
HideWindow, "%p", win);
} else {
AG_MenuAction(mi, _("Show window"), NULL,
ShowWindow, "%p", win);
}
}
AG_Window *
DEV_GuiDebugger(void)
{
AG_Window *win;
AG_Tlist *tl;
AG_MenuItem *mi;
if ((win = AG_WindowNewNamed(0, "DEV_GuiDebugger")) == NULL) {
return (NULL);
}
AG_WindowSetCaption(win, _("GUI Debugger"));
AG_WindowSetCloseAction(win, AG_WINDOW_DETACH);
tl = AG_TlistNewPolled(win, AG_TLIST_EXPAND, PollWindows, NULL);
AG_SetEvent(tl, "tlist-dblclick", EditWidgetParams, "%p", tl);
AG_WidgetFocus(tl);
mi = AG_TlistSetPopup(tl, "window");
AG_MenuSetPollFn(mi, CreateWindowMenu, "%p", tl);
AG_WindowSetGeometry(win, agView->w/4, agView->h/3, agView->w/2,
agView->h/4);
return (win);
}