]> git.ipfire.org Git - thirdparty/newt.git/commitdiff
added the start of a checkbox tree widget
authormsw <msw>
Fri, 9 Jul 1999 00:42:51 +0000 (00:42 +0000)
committermsw <msw>
Fri, 9 Jul 1999 00:42:51 +0000 (00:42 +0000)
checkboxtree.c [new file with mode: 0644]
newt.h
peanuts.py
snackmodule.c
testtree.c [new file with mode: 0644]

diff --git a/checkboxtree.c b/checkboxtree.c
new file mode 100644 (file)
index 0000000..debb0bc
--- /dev/null
@@ -0,0 +1,333 @@
+#include <slang.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "newt.h"
+#include "newt_pr.h"
+
+struct items {
+    char * text;
+    const void *data;
+    unsigned char selected;
+    struct items *next;
+    struct items *prev;
+    struct items *branch;
+};
+
+struct CheckboxTree {
+    newtComponent sb;
+    int curWidth;      /* size of text w/o scrollbar or border*/
+    int curHeight;     /* size of text w/o border */
+    int sbAdjust;
+    int bdxAdjust, bdyAdjust;
+    int numBoxes, numSelected;
+    int userHasSetWidth;
+    struct items * currItem, * firstItem, * itemlist;
+    int currPos;
+    int isActive; 
+    int grow;
+    int flags;
+    int pad;
+    char * seq;
+    char * result;
+};
+
+static void ctDraw(newtComponent c);
+static void ctDestroy(newtComponent co);
+static void ctPlace(newtComponent co, int newLeft, int newTop);
+struct eventResult ctEvent(newtComponent co, struct event ev);
+static void ctMapped(newtComponent co, int isMapped);
+
+static struct componentOps ctOps = {
+    ctDraw,
+    ctEvent,
+    ctDestroy,
+    ctPlace,
+    ctMapped,
+} ;
+
+int newtCheckboxTreeAppend(newtComponent co, int selected,
+                          const char * text,
+                          const void * data) {
+    struct CheckboxTree * ct = co->data;
+    struct items *item, *prev;
+
+    if(ct->itemlist) {
+       for (item = ct->itemlist; item->next != NULL; item = item->next);
+       prev = item;
+       item = item->next = malloc(sizeof(struct items));
+       item->prev = prev;
+    } else {
+       item = ct->itemlist = ct->firstItem =
+           ct->currItem = malloc(sizeof(struct items));
+       item->prev = NULL;
+    }
+
+    if ((strlen(text) + 4 + ct->pad) > co->width) {
+       co->width = strlen(text) + 4 + ct->pad;
+    }
+    
+    item->text = strdup(text); item->data = data; item->next = NULL;
+    item->selected = selected;
+    ct->numSelected += selected;
+    ct->numBoxes++;
+    return 0;
+}
+
+void ** newtCheckboxTreeGetSelection(newtComponent co, int *numitems)
+{
+    struct CheckboxTree * ct;
+    int i;
+    void **retval;
+    struct items *item;
+
+    if(!co || !numitems) return NULL;
+
+    ct = co->data;
+    if(!ct || !ct->numSelected) {
+       *numitems = 0;
+       return NULL;
+    }
+    
+    retval = malloc(ct->numSelected * sizeof(void *));
+    for(i = 0, item = ct->itemlist; item != NULL;
+       item = item->next)
+       if(item->selected)
+           retval[i++] = (void *)item->data;
+    *numitems = ct->numSelected;
+    return retval;
+}
+
+newtComponent newtCheckboxTree(int left, int top, int height, int flags) {
+    newtComponent co;
+    struct CheckboxTree * ct;
+
+    co = malloc(sizeof(*co));
+    ct = malloc(sizeof(struct CheckboxTree));
+    co->data = ct;
+    co->ops = &ctOps;
+    co->takesFocus = 1;
+    co->height = height;
+    co->width = 0;
+    co->isMapped = 0;
+    ct->numSelected = 0;
+    ct->currPos = 0;
+    ct->itemlist = NULL;
+    ct->numBoxes = 0;
+    if (flags & NEWT_FLAG_SCROLL) {
+       ct->sb = newtVerticalScrollbar(left, top, height,
+                                      COLORSET_LISTBOX, COLORSET_ACTLISTBOX);
+       ct->pad = 2;
+    } else {
+       ct->sb = NULL;
+       ct->pad = 0;
+    }
+    
+    return co;
+}
+
+static void ctMapped(newtComponent co, int isMapped) {
+    struct CheckboxTree * ct = co->data;
+
+    co->isMapped = isMapped;
+    if (ct->sb)
+       ct->sb->ops->mapped(ct->sb, isMapped);
+}
+
+static void ctPlace(newtComponent co, int newLeft, int newTop) {
+    struct CheckboxTree * ct = co->data;
+
+    co->top = newTop;
+    co->left = newLeft;
+
+    if (ct->sb)
+       ct->sb->ops->place(ct->sb, co->left + co->width - 1, co->top);
+}
+
+int ctSetItem(newtComponent co, struct items *item, enum newtFlagsSense sense)
+{
+    struct CheckboxTree * ct = co->data;
+    
+    if (!item)
+       return 1;
+    
+    if (item->selected)
+       ct->numSelected--;
+
+    switch(sense) {
+       case NEWT_FLAGS_RESET:
+           item->selected = 0;
+           break;
+       case NEWT_FLAGS_SET:
+           item->selected = 1;
+           break;
+       case NEWT_FLAGS_TOGGLE:
+           item->selected = !item->selected;
+           break;
+    }
+
+    if (item->selected)
+       ct->numSelected++;
+    
+    return 0;
+}
+
+
+static void ctDraw(newtComponent co) {
+    struct CheckboxTree * ct = co->data;
+    struct items * item; 
+    int i, curr, pos = 0;
+    
+    item = ct->itemlist;
+    while (item && item != ct->firstItem) {
+       item = item->next;
+       pos++;
+    }
+    
+    i = 0;
+    while (item && i < co->height) {
+       newtGotorc(co->top + i, co->left);
+       if (item == ct->currItem) {
+           SLsmg_set_color(NEWT_COLORSET_ACTLISTBOX);
+           ct->currPos = curr = i;
+       } else
+           SLsmg_set_color(NEWT_COLORSET_LISTBOX);
+       SLsmg_write_string("[");
+       SLsmg_write_string(item->selected ? "*" : " ");
+       SLsmg_write_string("] ");
+       SLsmg_write_nstring(item->text, co->width - 4);
+       item = item->next;
+       i++;
+    }
+    
+    if(ct->sb) {
+       newtScrollbarSet(ct->sb, pos + curr + 1, ct->numBoxes);
+       ct->sb->ops->draw(ct->sb);
+    }
+
+    newtGotorc(co->top + curr, co->left + 1);
+}
+
+static void ctDestroy(newtComponent co) {
+    struct CheckboxTree * ct = co->data;
+    struct items * item, * nextitem;
+
+    nextitem = item = ct->itemlist;
+
+    while (item != NULL) {
+       nextitem = item->next;
+       free(item->text);
+       free(item);
+       item = nextitem;
+    }
+
+    free(ct);
+    free(co);
+}
+
+struct eventResult ctEvent(newtComponent co, struct event ev) {
+    struct CheckboxTree * ct = co->data;
+    struct eventResult er;
+    struct items * item;
+    int i;
+
+    er.result = ER_IGNORED;
+
+    if(ev.when == EV_EARLY || ev.when == EV_LATE) {
+       return er;
+    }
+
+    switch(ev.event) {
+    case EV_KEYPRESS:
+       switch(ev.u.key) {
+       case ' ':
+       case NEWT_KEY_ENTER:
+           if (ct->currItem) {
+               ctSetItem(co, ct->currItem, NEWT_FLAGS_TOGGLE);
+               ctDraw(co);
+               er.result = ER_SWALLOWED;
+           }
+           break;
+       case NEWT_KEY_DOWN:
+           if (ct->currItem && ct->currItem->next) {
+               ct->currItem = ct->currItem->next;
+               er.result = ER_SWALLOWED;
+               /* Check to see if our new position (currPos + 1) is past
+                  the end of the list.  If so, scroll up. */
+               if (ct->currPos + 1 >= co->height) {
+                   if (ct->firstItem->next)
+                       ct->firstItem = ct->firstItem->next;
+                   ct->currPos = co->height;
+               } else
+                   ct->currPos++;
+               ctDraw(co);
+           }
+           break;
+       case NEWT_KEY_UP:
+           if (ct->currItem->prev) {
+               ct->currItem = ct->currItem->prev;
+               er.result = ER_SWALLOWED;
+               /* Check to see if our new position (currPos - 1) is past
+                  the beginning of the list.  If so, scroll down. */
+               if (ct->currPos <= 0) {
+                   if (ct->firstItem->prev)
+                       ct->firstItem = ct->firstItem->prev;
+                   ct->currPos = 0;
+               } else
+                   ct->currPos--;
+               ctDraw(co);
+           }
+           break;
+       case NEWT_KEY_PGUP:
+           item = ct->currItem;
+
+           for (i = 0; i < co->height; i++) {
+               if (item->prev)
+                   item = item->prev;
+               else
+                   break;
+           }
+           ct->currItem = ct->firstItem = item;
+           ct->currPos = 0;
+           ctDraw(co);
+           er.result = ER_SWALLOWED;
+           break;
+       case NEWT_KEY_PGDN:
+           item = ct->currItem;
+
+           for (i = 0; i < co->height; i++) {
+               if (item->next)
+                   item = item->next;
+               else
+                   break;
+           }
+           ct->currItem = item;
+           ct->currPos = co->height;
+                                   
+           /* back up the starting item to the current position */
+           for (i = 0; i < co->height - 1; i++) {
+               if (item->prev)
+                   item = item->prev;
+               else
+                   break;
+           }
+           ct->firstItem = item;
+           ctDraw(co);
+           er.result = ER_SWALLOWED;
+           break;
+       }
+    case EV_FOCUS:
+       ctDraw(co);
+       er.result = ER_SWALLOWED;
+       break;
+       
+    case EV_UNFOCUS:
+       ctDraw(co);
+       er.result = ER_SWALLOWED;
+       break;
+    default:
+       break;
+    }
+
+    return er;
+}
diff --git a/newt.h b/newt.h
index 1bf72030cb8da98aef2179582bb8548dade6fe89..59b9e5210bb450d36c19ad93a00b62082de9a247 100644 (file)
--- a/newt.h
+++ b/newt.h
@@ -161,7 +161,11 @@ void **newtListboxGetSelection(newtComponent co, int *numitems);
 void newtListboxClearSelection(newtComponent co);
 void newtListboxSelectItem(newtComponent co, const void * key,
        enum newtFlagsSense sense);
-
+newtComponent newtCheckboxTree(int left, int top, int height, int flags);
+void ** newtCheckboxTreeGetSelection(newtComponent co, int *numitems);
+int newtCheckboxTreeAppend(newtComponent co, int selected,
+                          const char * text,
+                          const void * data);
     
 newtComponent newtTextboxReflowed(int left, int top, char * text, int width,
                                  int flexDown, int flexUp, int flags);
index 49e56ba95bedf1a68b3f6aa7956b607ff09d1450..c5ec8bfb45a6ca79c91004052b3381bd133fc768 100755 (executable)
@@ -13,12 +13,18 @@ rb = RadioBar(screen, (("This", "this", 0),
                        ("That", "that", 0)))
 bb = ButtonBar(screen, (("Ok", "ok"), ("Cancel", "cancel")))
 
-g = GridForm(screen, "My Test", 1, 3)
+ct = CheckboxTree(height = 5, scroll = 1)
+ct.append("Foo", 1, 1)
+ct.append("Bar", 2, 0)
+ct.append("Bang", 3, 1)
+
+g = GridForm(screen, "My Test", 1, 4)
 g.add(li, 0, 0)
 g.add(rb, 0, 1, (0, 1, 0, 1))
-g.add(bb, 0, 2, growx = 1)
+g.add(ct, 0, 2)
+g.add(bb, 0, 3, growx = 1)
 
-result = g.run_once()
+result = g.runOnce()
 
 screen.finish()
 
@@ -26,3 +32,4 @@ print result
 print "listbox:", li.current()
 print "rb:", rb.getSelection()
 print "bb:", bb.buttonPressed(result)
+print "checkboxtree:", ct.getSelection()
index 34f3d6c704efbfc714f6e060e273679e56b3a37a..a17ec5f913e6c93effc345a5e5f6bff0206791b0 100644 (file)
@@ -44,6 +44,7 @@ static PyObject * setSuspendCallback(PyObject * s, PyObject * args);
 static PyObject * reflowText(PyObject * s, PyObject * args);
 static snackWidget * textWidget(PyObject * s, PyObject * args);
 static PyObject * ternaryWindow(PyObject * s, PyObject * args);
+static snackWidget * checkboxTreeWidget(PyObject * s, PyObject * args);
 
 static PyMethodDef snackModuleMethods[] = {
     { "button", (PyCFunction) buttonWidget, METH_VARARGS, NULL },
@@ -72,6 +73,7 @@ static PyMethodDef snackModuleMethods[] = {
     { "suspendcallback", setSuspendCallback, METH_VARARGS, NULL },
     { "ternary", ternaryWindow, METH_VARARGS, NULL },
     { "textbox", (PyCFunction) textWidget, METH_VARARGS, NULL },
+    { "checkboxtree", (PyCFunction) checkboxTreeWidget, METH_VARARGS, NULL },
     { NULL }
 } ;
 
@@ -151,6 +153,44 @@ struct snackWidget_s {
     int anint;
 } ;
 
+typedef struct cbSelection_t {
+    PyObject_HEAD;
+    void ** selection;
+    int numselected;
+} cbSelection;
+
+static int selectionLength(PyObject * o);
+PyObject * selectionItem(PyObject * o, int n);
+
+static PySequenceMethods selectionAsSeq = {
+       selectionLength,                /* length */
+       0,                              /* concat */
+       0,                              /* repeat */
+       selectionItem,                  /* item */
+       0,                              /* slice */
+       0,                              /* assign item */
+       0,                              /* assign slice */
+};
+
+static void selectionDestructor(PyObject * s);
+
+static PyTypeObject cbTreeSelection = {
+        PyObject_HEAD_INIT(&PyType_Type)
+        0,                              /* ob_size */
+        "cbselection",                  /* tp_name */
+        sizeof(cbSelection),            /* tp_size */
+        0,                              /* tp_itemsize */
+        selectionDestructor,           /* tp_dealloc */
+        0,                              /* tp_print */
+        0,                             /* tp_getattr */
+        0,                              /* tp_setattr */
+        0,                              /* tp_compare */
+        0,                              /* tp_repr */
+        0,                              /* tp_as_number */
+        &selectionAsSeq,                 /* tp_as_sequence */
+        0,                             /* tp_as_mapping */
+};
+
 static PyObject * widgetAddCallback(snackWidget * s, PyObject * args);
 static PyObject * widgetGetAttr(PyObject * s, char * name);
 static PyObject * widgetEntrySetValue(snackWidget * s, PyObject * args);
@@ -161,6 +201,9 @@ static PyObject * widgetListboxIns(snackWidget * s, PyObject * args);
 static PyObject * widgetListboxDel(snackWidget * s, PyObject * args);
 static PyObject * widgetListboxGet(snackWidget * s, PyObject * args);
 static PyObject * widgetTextboxText(snackWidget * s, PyObject * args);
+static PyObject * widgetCheckboxTreeAppend(snackWidget * s, PyObject * args);
+static cbSelection * widgetCheckboxTreeGetSel(snackWidget * s,
+                                             PyObject * args);
 
 static PyMethodDef widgetMethods[] = {
     { "setCallback", (PyCFunction) widgetAddCallback, METH_VARARGS, NULL },
@@ -173,6 +216,10 @@ static PyMethodDef widgetMethods[] = {
     { "listboxSetWidth", (PyCFunction) widgetListboxSetW, METH_VARARGS, NULL },
     { "listboxDeleteItem", (PyCFunction) widgetListboxDel, METH_VARARGS, NULL },
     { "scaleSet", (PyCFunction) scaleSet, METH_VARARGS, NULL },
+    { "checkboxtreeAppend", (PyCFunction) widgetCheckboxTreeAppend,
+      METH_VARARGS, NULL },
+    { "checkboxtreeGetSelection", (PyCFunction) widgetCheckboxTreeGetSel,
+      METH_VARARGS, NULL },
     { NULL }
 };
 
@@ -757,6 +804,78 @@ static PyObject * widgetListboxSetW(snackWidget * s, PyObject * args) {
 static void emptyDestructor(PyObject * s) {
 }
 
+static snackWidget * checkboxTreeWidget(PyObject * s, PyObject * args) {
+    int height;
+    int scrollBar = 0;
+    snackWidget * widget;
+    
+    if (!PyArg_ParseTuple(args, "i|i", &height, &scrollBar))
+       return NULL;
+
+    widget = PyObject_NEW(snackWidget, &snackWidgetType);
+    widget->co = newtCheckboxTree(-1, -1, height,
+                                 scrollBar ? NEWT_FLAG_SCROLL : 0);
+
+    widget->anint = 1;
+
+    return widget;
+}
+
+static PyObject * widgetCheckboxTreeAppend(snackWidget * s, PyObject * args) {
+    char * text;
+    void * key;
+    int selected = 0;
+    
+    if (!PyArg_ParseTuple(args, "s|i", &text, &selected))
+       return NULL;
+
+    newtCheckboxTreeAppend(s->co, selected, text, (void *) s->anint);
+
+    return PyInt_FromLong(s->anint++);
+}
+
+static cbSelection * widgetCheckboxTreeGetSel(snackWidget * s,
+                                             PyObject * args) {
+    void ** selection;
+    int numselected;
+    cbSelection * sel;
+
+    selection = newtCheckboxTreeGetSelection(s->co, &numselected);
+
+    sel = PyObject_NEW(cbSelection, &cbTreeSelection);
+    sel->selection = selection;
+    sel->numselected = numselected;
+    
+    return sel;
+}
+
+static int selectionLength(PyObject * o) {
+    cbSelection * sel = (void *) o;
+
+    return sel->numselected;
+}
+
+PyObject * selectionItem(PyObject * o, int n) {
+    cbSelection * sel = (void *) o;
+    void **result;
+
+    if (n > sel->numselected - 1 || sel->numselected == 0) {
+       PyErr_SetString(PyExc_IndexError, "index out of bounds");
+       return NULL;
+    }
+
+    result = sel->selection[n];
+    
+    return Py_BuildValue("i", (int) result);
+}
+
+static void selectionDestructor(PyObject * o) {
+    cbSelection * sel = (void *) o;
+
+    if (sel->selection != NULL)
+       free(sel->selection);
+}
+
 void init_snack(void) {
     PyObject * d, * m;
 
diff --git a/testtree.c b/testtree.c
new file mode 100644 (file)
index 0000000..b8988e7
--- /dev/null
@@ -0,0 +1,71 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+
+#include "newt.h"
+
+int main(void) {
+    newtGrid grid;
+    newtComponent checktree;
+    newtComponent button;
+    newtComponent form;
+    newtComponent answer;
+    void ** result, **ptr;
+    int numselected, i, j;
+    
+    newtInit();
+    newtCls();
+
+    checktree = newtCheckboxTree(-1, -1, 10, NEWT_FLAG_SCROLL);
+    newtCheckboxTreeAppend(checktree, 0, "Foobar!", (void *) 1);
+    newtCheckboxTreeAppend(checktree, 1, "Baz!", (void *) 2);
+    newtCheckboxTreeAppend(checktree, 0, "Really really long thing",
+                          (void *) 3);
+    newtCheckboxTreeAppend(checktree, 0, "number 4", (void *) 4);
+    newtCheckboxTreeAppend(checktree, 1, "number 5", (void *) 5);
+    newtCheckboxTreeAppend(checktree, 0, "number 6", (void *) 6);
+    newtCheckboxTreeAppend(checktree, 1, "number 7", (void *) 7);
+    newtCheckboxTreeAppend(checktree, 0, "number 8", (void *) 8);
+    newtCheckboxTreeAppend(checktree, 0, "number 9", (void *) 9);
+    newtCheckboxTreeAppend(checktree, 1, "number 10", (void *) 10);
+    newtCheckboxTreeAppend(checktree, 0, "number 11", (void *) 11);
+    newtCheckboxTreeAppend(checktree, 1, "number 12", (void *) 12);
+    button = newtButton(-1, -1, "Exit");
+    
+    grid = newtCreateGrid(1, 2);
+    newtGridSetField(grid, 0, 0, NEWT_GRID_COMPONENT, checktree, 0, 0, 0, 0, 
+                    NEWT_ANCHOR_RIGHT, 0);
+    newtGridSetField(grid, 0, 0, NEWT_GRID_COMPONENT, checktree, 0, 0, 0, 0, 
+                    0, 0);
+    newtGridSetField(grid, 0, 1, NEWT_GRID_COMPONENT, button, 0, 0, 0, 0, 
+                    0, 0);
+
+    newtGridWrappedWindow(grid, "Checkbox Tree Test");
+    newtGridFree(grid, 1);
+
+    form = newtForm(NULL, NULL, 0);
+    newtFormAddComponents(form, checktree, button, NULL);
+
+    answer = newtRunForm(form);
+
+    newtFinished();
+
+    result = newtCheckboxTreeGetSelection(checktree, &numselected);
+    ptr = result;
+    if (!result || !numselected)
+       printf("none selected\n");
+    else
+       printf("Current selection:\n");
+    for (i = 0; i < numselected; i++) {
+       j = (int) *ptr++;
+       printf("%d\n", j);
+    }
+    if (result)
+       free(result);
+    
+    newtFormDestroy(form);
+    
+    return 0;
+}