/*
* Copyright (c) 2005-2008 Hypertriton, Inc.
*
* 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.
*/
/*
* Graphical interface for edition of SK(3) objects.
*/
#include
#include
#include "sk.h"
#include "sk_gui.h"
#include
#include
#ifdef EDITION
static void SK_NodeEditGeneric(SK_Node *, AG_Widget *, SK_View *);
extern SK_ToolOps skSelectToolOps;
extern SK_ToolOps skPointToolOps;
extern SK_ToolOps skLineToolOps;
extern SK_ToolOps skPolygonToolOps;
extern SK_ToolOps skCircleToolOps;
extern SK_ToolOps skDimensionToolOps;
extern SK_ToolOps skPixmapToolOps;
extern SK_ToolOps skMeasureToolOps;
SK_ToolOps *skToolkit[] = {
&skSelectToolOps,
&skPointToolOps,
&skLineToolOps,
&skPolygonToolOps,
&skCircleToolOps,
&skDimensionToolOps,
&skPixmapToolOps,
&skMeasureToolOps,
};
Uint skToolkitCount = sizeof(skToolkit) / sizeof(skToolkit[0]);
#if 0
static int
CompareClass(const char *pat, const char *cname)
{
const char *c;
if (pat[0] == '*' && pat[1] == '\0') {
return (0);
}
for (c = &pat[0]; *c != '\0'; c++) {
if (c[0] == ':' && c[1] == '*' && c[2] == '\0') {
if (c == &pat[0])
return (0);
if (strncmp(cname, pat, c - &pat[0] + 1) == 0)
return (0);
}
}
return (1);
}
static void
ListLibraryItems(AG_Tlist *tl, const char *cname, int depth)
{
char subname[SK_TYPE_NAME_MAX];
const char *c;
AG_TlistItem *it;
int i, j;
for (i = 0; i < skElementsCnt; i++) {
SK_NodeOps *ops = skElements[i];
if (CompareClass(cname, ops->name) != 0) {
continue;
}
for (c = ops->name, j = 0; *c != '\0'; c++) {
if (*c == ':')
j++;
}
if (j == depth) {
it = AG_TlistAddS(tl, NULL, ops->name);
it->p1 = ops;
it->depth = depth;
Strlcpy(subname, ops->name, sizeof(subname));
Strlcat(subname, ":*", sizeof(subname));
ListLibraryItems(tl, subname, depth+1);
}
}
}
#endif
static void
ImportSketchDlg(AG_Event *event)
{
AG_Window *win;
AG_FileDlg *dlg;
win = AG_WindowNew(0);
dlg = AG_FileDlgNewMRU(win, "sg.mru.sketches",
AG_FILEDLG_LOAD|AG_FILEDLG_CLOSEWIN|AG_FILEDLG_EXPAND);
#if 0
AG_FileDlgAddType(dlg, _("SVG Format"), "*.svg",
ImportFromSVG, "%p", sk);
AG_FileDlgAddType(dlg, _("DXF Format"), "*.dxf",
ImportFromDXF, "%p", sk);
AG_FileDlgAddType(dlg, _("PDF Format"), "*.pdf",
ImportFromPDF, "%p", sk);
#endif
AG_WindowShow(win);
}
static void
NodeDelete(AG_Event *event)
{
SK_Node *node = AG_PTR(1);
SK_View *skv = AG_PTR(2);
SK_ViewClearEditPane(skv);
if (node->ops->del != NULL) {
if (node->ops->del(node) == -1)
AG_TextMsgFromError();
} else {
AG_TextMsg(AG_MSG_ERROR, _("Entity cannot be deleted"));
}
}
static void NodeMoveUp(AG_Event *event) { SK_NodeMoveUp(AG_PTR(1)); }
static void NodeMoveDown(AG_Event *event) { SK_NodeMoveDown(AG_PTR(1)); }
/*
* Generate a plot of the proximity to a given node from every visible
* pixel. This is useful for debugging proximity tests.
*/
static void
PlotProximityMap(AG_Event *event)
{
SK_Node *node = AG_PTR(1);
SK_View *skv = AG_PTR(2);
SK *sk = skv->sk;
SK_Pixmap *px;
AG_Surface *s;
int x, y;
Uint8 *p, color;
Uint32 c;
M_Vector3 v, vC;
M_Real prox, proxMax = 0.0;
M_Matrix44 Ti;
M_Real *map;
if ((s = AG_SurfaceStdRGB(AGWIDGET(skv)->w, AGWIDGET(skv)->h))
== NULL) {
AG_FatalError(NULL);
}
p = (Uint8 *)s->pixels;
map = Malloc(s->w*s->h*sizeof(M_Real));
Ti = M_MatInvert44p(&skv->mView);
v.z = 0.0;
for (y = 0; y < s->h; y++) {
for (x = 0; x < s->w; x++) {
v.y = SK_VIEW_Y(skv, y);
v.x = SK_VIEW_X(skv, x);
M_MatMult44Vector3v(&v, &Ti);
prox = node->ops->proximity(node, &v, &vC);
if (prox != M_INFINITY && prox > proxMax) {
proxMax = prox;
}
map[y*s->w + x] = node->ops->proximity(node, &v, &vC);
}
}
for (y = 0; y < s->h; y++) {
for (x = 0; x < s->w; x++) {
M_Real m = map[y*s->w + (s->w - x)];
if (m < 2.0) {
color = (Uint8)(m*255.0/2.0);
c = AG_MapPixelRGB(s->format, 255-color, 0, 0);
} else {
color = (Uint8)(m*255.0/proxMax);
c = AG_MapPixelRGB(s->format, color, color, color);
}
AG_PUT_PIXEL(s, p, c);
p += s->format->BytesPerPixel;
}
}
px = SK_PixmapNew(sk->root, NULL);
SK_PixmapDimensions(px, s->w*skv->wPixel, s->h*skv->hPixel);
SK_PixmapSurface(px, s);
SK_NodeMoveHead(px);
Free(map);
}
static void
PlotCluster(SK *sk, AG_Graph *gf, SK_Cluster *cl)
{
SK_Constraint *ct;
AG_GraphVertex *v1, *v2;
AG_GraphEdge *edge;
AG_GraphFreeVertices(gf);
TAILQ_FOREACH(ct, &cl->edges, constraints) {
if ((v1 = AG_GraphVertexFind(gf, ct->n1)) == NULL) {
v1 = AG_GraphVertexNew(gf, ct->n1);
AG_GraphVertexLabelS(v1, ct->n1->name);
}
if ((v2 = AG_GraphVertexFind(gf, ct->n2)) == NULL) {
v2 = AG_GraphVertexNew(gf, ct->n2);
AG_GraphVertexLabelS(v2, ct->n2->name);
}
edge = AG_GraphEdgeNew(gf, v1, v2, ct);
AG_GraphEdgeLabelS(edge,
(ct->type == SK_DISTANCE && ct->ct_distance == 0.0) ?
"Incidence" : skConstraintNames[ct->type]);
}
AG_GraphAutoPlace(gf, 800, 800);
}
static void
SelectCluster(AG_Event *event)
{
SK *sk = AG_PTR(1);
AG_Graph *gf = AG_PTR(2);
AG_TlistItem *ti = AG_PTR(3);
SK_Cluster *cluster = ti->p1;
PlotCluster(sk, gf, cluster);
}
static void
PollClusters(AG_Event *event)
{
AG_Tlist *tl = AG_SELF();
SK *sk = AG_PTR(1);
SK_Cluster *cl;
AG_TlistItem *ti;
AG_TlistBegin(tl);
AG_TlistAddPtr(tl, NULL, "Original", &sk->ctGraph);
TAILQ_FOREACH(cl, &sk->clusters, clusters) {
ti = AG_TlistAdd(tl, NULL, "Cluster%d", cl->name);
ti->p1 = cl;
}
AG_TlistEnd(tl);
}
static void
ViewConstraintGraphs(AG_Event *event)
{
AG_Window *winParent = AG_PTR(1);
SK *sk = AG_PTR(2);
AG_Graph *gf;
AG_Window *win;
AG_Pane *pane;
AG_Tlist *tl;
win = AG_WindowNew(0);
AG_WindowSetCaption(win, _("Constraint graph of <%s>"),
OBJECT(sk)->name);
pane = AG_PaneNew(win, AG_PANE_HORIZ, AG_PANE_EXPAND);
gf = AG_GraphNew(pane->div[1], AG_GRAPH_EXPAND);
tl = AG_TlistNewPolled(pane->div[0], AG_TLIST_EXPAND,
PollClusters, "%p", sk);
AG_TlistSizeHint(tl, "", 6);
AG_TlistSetDblClickFn(tl, SelectCluster, "%p,%p", sk, gf);
PlotCluster(sk, gf, &sk->ctGraph);
AG_WindowShow(win);
AG_WindowAttach(winParent, win);
}
static void
ProcessDebugMsg(void *obj, void *cons, const char *msg)
{
AG_ConsoleMsgS(cons, msg);
}
static void
DebugConsole(AG_Event *event)
{
AG_Window *winParent = AG_PTR(1);
SK_View *skv = AG_PTR(2);
AG_Window *win;
AG_Console *cons;
win = AG_WindowNew(0);
AG_WindowSetCaption(win, _("Debug console for <%s>"),
OBJECT(skv->sk)->name);
cons = AG_ConsoleNew(win, AG_CONSOLE_EXPAND);
AG_ObjectSetDebugFn(skv, ProcessDebugMsg, cons);
AG_ObjectSetDebugFn(skv->sk, ProcessDebugMsg, cons);
AG_WindowAttach(winParent, win);
AG_WindowSetGeometryAlignedPct(win, AG_WINDOW_BC, 80, 30);
AG_WindowShow(win);
}
static void
CreateNewView(AG_Event *event)
{
AG_Window *winParent = AG_PTR(1);
SK *sk = AG_PTR(2);
SK_View *skv;
AG_Window *win;
win = AG_WindowNew(0);
AG_WindowSetCaptionS(win, OBJECT(sk)->name);
AG_WindowSetPaddingTop(win, 0);
AG_WindowSetSpacing(win, 0);
skv = SK_ViewNew(win, sk, SK_VIEW_EXPAND);
AG_WindowSetGeometryAlignedPct(win, AG_WINDOW_TR, 40, 30);
AG_WidgetFocus(skv);
AG_WindowAttach(winParent, win);
AG_WindowShow(win);
}
static void
NodeMenu(AG_Event *event)
{
AG_Tlist *tl = AG_SELF();
SK_Node *node = AG_TlistSelectedItemPtr(tl);
SK_View *skv = AG_PTR(1);
AG_PopupMenu *pm;
pm = AG_PopupNew(skv);
AG_MenuAction(pm->item, _("Delete entity"), agIconTrash.s,
NodeDelete, "%p,%p", node, skv);
AG_MenuAction(pm->item, _("Move up"), NULL,
NodeMoveUp, "%p", node);
AG_MenuAction(pm->item, _("Move down"), NULL,
NodeMoveDown, "%p", node);
AG_MenuAction(pm->item, _("Plot proximity map"), NULL,
PlotProximityMap, "%p,%p", node, skv);
AG_PopupShowAt(pm,
WIDGET(tl)->drv->mouse->x,
WIDGET(tl)->drv->mouse->y);
}
static void
FindNodes(AG_Tlist *tl, SK_Node *node, int depth)
{
AG_TlistItem *it;
SK_Node *cnode;
it = AG_TlistAddS(tl, NULL, node->name);
it->depth = depth;
it->p1 = node;
it->selected = (node->flags & SK_NODE_SELECTED);
if (!TAILQ_EMPTY(&node->cnodes)) {
it->flags |= AG_TLIST_HAS_CHILDREN;
}
if ((it->flags & AG_TLIST_HAS_CHILDREN) &&
AG_TlistVisibleChildren(tl, it)) {
TAILQ_FOREACH(cnode, &node->cnodes, sknodes)
FindNodes(tl, cnode, depth+1);
}
}
static void
PollNodes(AG_Event *event)
{
AG_Tlist *tl = AG_SELF();
SK *sk = AG_PTR(1);
AG_TlistBegin(tl);
FindNodes(tl, (SK_Node *)sk->root, 0);
AG_TlistEnd(tl);
}
static void
NodeSelect(AG_Event *event)
{
AG_TlistItem *it = AG_PTR(1);
int state = AG_INT(2);
SK_Node *node = it->p1;
if (state) {
node->flags |= SK_NODE_SELECTED;
} else {
node->flags &= ~(SK_NODE_SELECTED);
}
}
static void
SelectTool(AG_Event *event)
{
SK_View *skv = AG_PTR(1);
AG_TlistItem *it = AG_PTR(2);
SK_Tool *tool = it->p1;
SK_ViewSelectTool(skv, tool, NULL);
}
static void
NodeEdit(AG_Event *event)
{
SK_View *skv = AG_PTR(1);
AG_TlistItem *ti = AG_PTR(2);
SK_Node *node = ti->p1;
SK_ViewClearEditPane(skv);
if (node->ops->edit == NULL) {
return;
}
skv->editBox = (AG_Widget *)
AG_BoxNew(skv->editPane->div[1], AG_BOX_VERT, AG_BOX_EXPAND);
node->ops->edit(node, skv->editBox, skv);
SK_NodeEditGeneric(node, skv->editBox, skv);
SK_ViewResizePanes(skv);
}
static void
PollConstraints(AG_Event *event)
{
AG_Tlist *tl = AG_SELF();
SK *sk = AG_PTR(1);
SK_Node *node = AG_PTR(2);
SK_Constraint *ct;
AG_TlistItem *it;
AG_TlistBegin(tl);
TAILQ_FOREACH(ct, &sk->ctGraph.edges, constraints) {
char ctArgs[64];
if (node != NULL) {
if (node != ct->n1 && node != ct->n2)
continue;
}
switch (ct->uType) {
case SK_DISTANCE:
AG_Snprintf(ctArgs, sizeof(ctArgs), "(%.03f %s)",
ct->ct_distance, sk->uLen->abbr);
break;
case SK_ANGLE:
AG_Snprintf(ctArgs, sizeof(ctArgs), "(%.02f\xc2\xb0)",
Degrees(ct->ct_angle));
break;
default:
ctArgs[0] = '\0';
break;
}
it = AG_TlistAdd(tl, NULL, "%s%s: %s,%s",
skConstraintNames[ct->uType], ctArgs,
ct->n1->name, ct->n2->name);
it->p1 = ct;
}
AG_TlistEnd(tl);
}
static void
UpdateConstraint(AG_Event *event)
{
SK_View *skv = AG_PTR(1);
SK_Update(skv->sk);
}
static void
ConstraintEdit(AG_Event *event)
{
SK_View *skv = AG_PTR(1);
AG_TlistItem *it = AG_PTR(2);
SK_Constraint *ct = it->p1;
AG_Numerical *num;
SK_ViewClearEditPane(skv);
skv->editBox = (AG_Widget *)
AG_BoxNew(skv->editPane->div[1], AG_BOX_VERT, AG_BOX_EXPAND);
AG_LabelNew(skv->editBox, AG_LABEL_HFILL, _("Type: %s"),
skConstraintNames[ct->uType]);
switch (ct->uType) {
case SK_DISTANCE:
num = AG_NumericalNew(skv->editBox, AG_NUMERICAL_HFILL, "m",
_("Distance: "));
AG_NumericalSetIncrement(num, 0.1);
AG_NumericalSetMin(num, 0.0);
M_BindReal(num, "value", &ct->ct_distance);
AG_WidgetSetFocusable(num, 0);
AG_SetEvent(num, "numerical-changed",
UpdateConstraint, "%p,%p", skv, ct);
break;
case SK_ANGLE:
num = AG_NumericalNew(skv->editBox, AG_NUMERICAL_HFILL,
"deg", _("Angle: "));
AG_NumericalSetIncrement(num, 1.0);
M_BindReal(num, "value", &ct->ct_angle);
AG_WidgetSetFocusable(num, 0);
AG_SetEvent(num, "numerical-changed",
UpdateConstraint, "%p,%p", skv, ct);
break;
default:
break;
}
SK_ViewResizePanes(skv);
}
static void
ConstraintDelete(AG_Event *event)
{
SK_Constraint *ct = AG_PTR(1);
SK_View *skv = AG_PTR(2);
SK *sk = skv->sk;
SK_ViewClearEditPane(skv);
SK_NodeDelConstraint(ct->n1, ct);
SK_NodeDelConstraint(ct->n2, ct);
SK_DelConstraint(&sk->ctGraph, ct);
SK_Update(sk);
}
static void
ConstraintMenu(AG_Event *event)
{
AG_Tlist *tl = AG_SELF();
SK_Constraint *ct = AG_TlistSelectedItemPtr(tl);
SK_View *skv = AG_PTR(2);
AG_PopupMenu *pm;
pm = AG_PopupNew(skv);
AG_MenuAction(pm->item, _("Delete constraint"), agIconTrash.s,
ConstraintDelete, "%p,%p", ct, skv);
AG_PopupShowAt(pm,
WIDGET(tl)->drv->mouse->x,
WIDGET(tl)->drv->mouse->y);
}
static void
PollInsns(AG_Event *event)
{
AG_Table *tbl = AG_SELF();
SK *sk = AG_PTR(1);
SK_Insn *si;
AG_TableBegin(tbl);
TAILQ_FOREACH(si, &sk->insns, insns) {
switch (si->type) {
case SK_COMPOSE_PAIR:
AG_TableAddRow(tbl, "%s:%s:%s:%s", "COMPOSE_PAIR",
si->n[0]->name, si->n[1]->name, "");
break;
case SK_COMPOSE_RING:
AG_TableAddRow(tbl, "%s:%s:%s:%s", "COMPOSE_RING",
si->n[0]->name, si->n[1]->name, si->n[2]->name);
break;
}
}
AG_TableEnd(tbl);
}
static void
ExecSelectedInsns(AG_Event *event)
{
SK *sk = AG_PTR(1);
AG_Table *tbl = AG_PTR(2);
SK_Insn *si;
Uint m = 0;
SK_ClearProgramState(sk);
TAILQ_FOREACH(si, &sk->insns, insns) {
if (!AG_TableRowSelected(tbl, m++)) {
continue;
}
if (SK_ExecInsn(sk, si) == -1) {
AG_TextMsgFromError();
}
break;
}
}
static void
ExecInsns(AG_Event *event)
{
SK *sk = AG_PTR(1);
AG_Table *tbl = AG_PTR(2);
SK_Insn *si;
Uint m = 0;
SK_ClearProgramState(sk);
TAILQ_FOREACH(si, &sk->insns, insns) {
AG_TableSelectRow(tbl, m++);
if (SK_ExecInsn(sk, si) == -1) {
AG_TextMsgFromError();
break;
}
}
}
static void
DrawStatus(AG_Event *event)
{
SK_View *skv = AG_SELF();
AG_Surface *lbl;
int x, y;
AG_PushTextState();
switch (skv->sk->status) {
case SK_WELL_CONSTRAINED:
AG_TextColorRGB(255, 255, 255);
break;
case SK_UNDER_CONSTRAINED:
AG_TextColorRGB(200, 200, 200);
break;
case SK_OVER_CONSTRAINED:
AG_TextColorRGB(255, 255, 0);
break;
default:
AG_TextColorRGB(255, 100, 100);
break;
}
lbl = AG_TextRender(skv->sk->statusText);
x = WIDGET(skv)->w - lbl->w;
y = WIDGET(skv)->h - lbl->h;
if (x < 0) { x = 0; }
if (y < 0) { y = 0; }
AG_PushClipRect(skv,
AG_RECT(0, 0, WIDGET(skv)->w, WIDGET(skv)->h));
AG_WidgetBlit(skv, lbl, x, y);
AG_PopClipRect(skv);
AG_SurfaceFree(lbl);
AG_PopTextState();
}
void *
SK_Edit(void *p)
{
extern SK_ToolOps *skToolkit[];
extern Uint skToolkitCount;
SK *sk = p;
AG_Window *win;
AG_Notebook *nb;
AG_NotebookTab *ntab;
SK_View *skv;
AG_Menu *menu;
AG_MenuItem *pitem;
AG_Pane *hp, *vp, *vp2;
AG_Tlist *tl;
AG_Table *tbl;
SK_Tool *tool;
Uint i;
win = AG_WindowNew(0);
AG_WindowSetCaptionS(win, OBJECT(sk)->name);
AG_WindowSetPaddingTop(win, 0);
AG_WindowSetSpacing(win, 0);
skv = SK_ViewNew(NULL, sk, SK_VIEW_EXPAND);
AG_GLViewOverlayFn(AGGLVIEW(skv), DrawStatus, NULL);
for (i = 0; i < skToolkitCount; i++)
SK_ViewRegTool(skv, skToolkit[i], NULL);
menu = AG_MenuNew(win, AG_MENU_HFILL);
pitem = AG_MenuNode(menu->root, _("File"), NULL);
{
AG_MenuAction(pitem, _("Import from vector image..."), NULL,
ImportSketchDlg, "%p,%p", sk, win);
AG_MenuSeparator(pitem);
AG_MenuActionKb(pitem, _("Close sketch"), NULL,
AG_KEY_W, AG_KEYMOD_CTRL,
AG_WindowCloseGenEv, "%p", win);
}
pitem = AG_MenuNode(menu->root, _("Edit"), NULL);
{
/* TODO */
AG_MenuAction(pitem, _("Undo"), NULL, NULL, "%p", NULL);
AG_MenuAction(pitem, _("Redo"), NULL, NULL, "%p", NULL);
}
pitem = AG_MenuNode(menu->root, _("View"), NULL);
{
AG_MenuAction(pitem, _("New view..."), NULL,
CreateNewView, "%p,%p", win, sk);
AG_MenuAction(pitem, _("Constraint graphs..."), NULL,
ViewConstraintGraphs, "%p,%p", win, sk);
}
pitem = AG_MenuNode(menu->root, _("Geometry"), NULL);
{
SK_GeometryMenu(skv, pitem);
}
pitem = AG_MenuNode(menu->root, _("Debug"), NULL);
{
AG_MenuAction(pitem, _("Debug console..."), NULL,
DebugConsole, "%p,%p", win, skv);
}
hp = AG_PaneNew(win, AG_PANE_HORIZ, AG_PANE_EXPAND);
{
vp = AG_PaneNew(hp->div[0], AG_PANE_VERT,
AG_PANE_EXPAND|AG_PANE_DIV1FILL);
nb = AG_NotebookNew(vp->div[0], AG_NOTEBOOK_EXPAND);
AG_ObjectAttach(hp->div[1], skv);
SK_ViewSetEditPane(skv, vp);
SK_ViewSetViewPane(skv, hp);
ntab = AG_NotebookAddTab(nb, _("Tools"), AG_BOX_VERT);
{
tl = AG_TlistNew(ntab, AG_TLIST_EXPAND);
AG_WidgetSetFocusable(tl, 0);
TAILQ_FOREACH(tool, &skv->tools, tools) {
AG_TlistAddPtr(tl,
(tool->ops->icon != NULL) ?
tool->ops->icon->s : NULL,
_(tool->ops->name), tool);
}
AG_SetEvent(tl, "tlist-selected", SelectTool, "%p",
skv);
}
ntab = AG_NotebookAddTab(nb, _("Nodes"), AG_BOX_VERT);
{
tl = AG_TlistNewPolled(ntab,
AG_TLIST_TREE|AG_TLIST_EXPAND|AG_TLIST_MULTI|
AG_TLIST_NOSELSTATE,
PollNodes, "%p", sk);
AG_TlistSetDblClickFn(tl, NodeEdit, "%p", skv);
AG_TlistSetPopupFn(tl, NodeMenu, "%p", skv);
AG_TlistSetChangedFn(tl, NodeSelect, NULL);
AG_TlistSizeHint(tl, _(""), 4);
/* AG_WidgetSetFocusable(tl, 0); */
}
ntab = AG_NotebookAddTab(nb, _("Constraints"), AG_BOX_VERT);
{
AG_HBox *bCmds;
vp2 = AG_PaneNew(ntab, AG_PANE_VERT,
AG_PANE_EXPAND|AG_PANE_DIV1FILL);
tl = AG_TlistNewPolled(vp2->div[0],
AG_TLIST_TREE|AG_TLIST_EXPAND,
PollConstraints, "%p,%p", sk, NULL);
AG_TlistSetDblClickFn(tl, ConstraintEdit, "%p", skv);
AG_TlistSetPopupFn(tl,
ConstraintMenu, "%p,%p", sk, skv);
AG_TlistSizeHint(tl, _(""), 4);
/* AG_WidgetSetFocusable(tl, 0); */
tbl = AG_TableNewPolled(vp2->div[1],
AG_TABLE_MULTI|AG_TABLE_EXPAND,
PollInsns, "%p,%p", sk, NULL);
AG_TableAddCol(tbl, _("Type"), "", NULL);
AG_TableAddCol(tbl, "n1", "", NULL);
AG_TableAddCol(tbl, "n2", "", NULL);
AG_TableAddCol(tbl, "n3", NULL, NULL);
/* AG_WidgetSetFocusable(tbl, 0); */
bCmds = AG_HBoxNew(vp2->div[1], AG_HBOX_HFILL|
AG_HBOX_HOMOGENOUS);
AG_ButtonNewFn(bCmds, 0, "All",
ExecInsns, "%p,%p", sk, tbl);
AG_ButtonNewFn(bCmds, 0, "Sel",
ExecSelectedInsns, "%p,%p", sk, tbl);
}
}
AG_PaneMoveDividerPct(hp, 40);
AG_WindowSetGeometryAlignedPct(win, AG_WINDOW_MC, 60, 50);
AG_WidgetFocus(skv);
return (win);
}
static void
UpdateNodeName(AG_Event *event)
{
SK_Node *node = AG_PTR(1);
AG_Snprintf(node->name, sizeof(node->name), "%s%u", node->ops->name,
node->handle);
}
static void
SK_NodeEditGeneric(SK_Node *node, AG_Widget *box, SK_View *skv)
{
AG_Tlist *tl;
AG_Numerical *num;
AG_SeparatorNewHoriz(box);
num = AG_NumericalNewUint32(box, 0, NULL, _("Name: "), &node->handle);
AG_SetEvent(num, "numerical-changed", UpdateNodeName, "%p", node);
// lbl = AG_LabelNewPolledMT(box, AG_LABEL_HFILL, &skv->sk->lock,
// "Flags: <%[flags]>", &node->flags);
// AG_LabelFlag(lbl, 0, "SELECTED", SK_NODE_SELECTED);
AG_LabelNewS(box, 0, _("Geometric constraints: "));
tl = AG_TlistNewPolled(box, AG_TLIST_POLL|AG_TLIST_TREE|AG_TLIST_EXPAND,
PollConstraints, "%p,%p", SKNODE(node)->sk, node);
AG_WidgetSetFocusable(tl, 0);
}
#endif /* EDITION */