From d577d991b97ae2b5ee1af23641bcffc3f83af5b2 Mon Sep 17 00:00:00 2001 From: Pixel Date: Wed, 4 Nov 2009 11:56:41 -0800 Subject: Initial import. Contains the im, cd and iup librairies, and a "working" Makefile for them under linux. --- iup/src/mot/iupmot_tree.c | 2848 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 2848 insertions(+) create mode 100755 iup/src/mot/iupmot_tree.c (limited to 'iup/src/mot/iupmot_tree.c') diff --git a/iup/src/mot/iupmot_tree.c b/iup/src/mot/iupmot_tree.c new file mode 100755 index 0000000..eb230af --- /dev/null +++ b/iup/src/mot/iupmot_tree.c @@ -0,0 +1,2848 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "iup.h" +#include "iupcbs.h" + +#include "iup_object.h" +#include "iup_childtree.h" +#include "iup_dialog.h" +#include "iup_layout.h" +#include "iup_attrib.h" +#include "iup_str.h" +#include "iup_drv.h" +#include "iup_drvinfo.h" +#include "iup_drvfont.h" +#include "iup_stdcontrols.h" +#include "iup_key.h" +#include "iup_image.h" +#include "iup_array.h" +#include "iup_tree.h" + +#include "iupmot_drv.h" +#include "iupmot_color.h" + + +typedef struct _motTreeItemData +{ + Pixmap image, image_mask; + Pixmap image_expanded, image_expanded_mask; + unsigned char kind; + void* userdata; +} motTreeItemData; + + +static void motTreeShowEditField(Ihandle* ih, Widget wItem); +static int motTreeGetNodeId(Ihandle* ih, Widget wItem); + +typedef int (*motTreeNodeFunc)(Ihandle* ih, Widget wItem, void* userdata); + +static int motTreeForEach(Ihandle* ih, Widget wItem, motTreeNodeFunc func, void* userdata) +{ + WidgetList wItemChildList = NULL; + int i, numChild; + + if (!wItem) + wItem = (Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM"); + + if (!func(ih, wItem, userdata)) + return 0; + + numChild = XmContainerGetItemChildren(ih->handle, wItem, &wItemChildList); + for (i=0; idata->spacing); + iupmotSetArg(args, num_args, XmNmarginWidth, 0); + iupmotSetArg(args, num_args, XmNviewType, XmSMALL_ICON); + iupmotSetArg(args, num_args, XmNnavigationType, XmTAB_GROUP); + iupmotSetArg(args, num_args, XmNtraversalOn, True); + iupmotSetArg(args, num_args, XmNshadowThickness, 0); + + /* Get values to copy */ + XtVaGetValues(wItem, XmNlabelString, &title, + XmNuserData, &itemData, + XmNforeground, &fgcolor, + XmNsmallIconPixmap, &image, + XmNsmallIconMask, &mask, + XmNoutlineState, &state, + NULL); + + if (full_copy) /* during a full copy the userdata reference is not copied */ + { + /* create a new one */ + motTreeItemData* itemDataNew = malloc(sizeof(motTreeItemData)); + memcpy(itemDataNew, itemData, sizeof(motTreeItemData)); + itemDataNew->userdata = NULL; + itemData = itemDataNew; + } + + iupmotSetArg(args, num_args, XmNlabelString, title); + iupmotSetArg(args, num_args, XmNuserData, itemData); + iupmotSetArg(args, num_args, XmNforeground, fgcolor); + iupmotSetArg(args, num_args, XmNsmallIconPixmap, image); + iupmotSetArg(args, num_args, XmNsmallIconMask, mask); + iupmotSetArg(args, num_args, XmNoutlineState, state); + + iupmotSetArg(args, num_args, XmNentryParent, wParent); + iupmotSetArg(args, num_args, XmNpositionIndex, pos); + + XtVaGetValues(ih->handle, XmNbackground, &bgcolor, NULL); + iupmotSetArg(args, num_args, XmNbackground, bgcolor); + + wNewItem = XtCreateManagedWidget("icon", xmIconGadgetClass, ih->handle, args, num_args); + + /* Root always expanded */ + XtVaSetValues((Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM"), XmNoutlineState, XmEXPANDED, NULL); + + XtRealizeWidget(wNewItem); + + return wNewItem; +} + +static void motTreeCopyChildren(Ihandle* ih, Widget wItemSrc, Widget wItemDst, int full_copy) +{ + WidgetList wItemChildList = NULL; + int i = 0; + int numChild = XmContainerGetItemChildren(ih->handle, wItemSrc, &wItemChildList); + while(i != numChild) + { + Widget wNewItem = motTreeCopyItem(ih, wItemChildList[i], wItemDst, i, full_copy); /* Use the same order they where enumerated */ + + /* Recursively transfer all the items */ + motTreeCopyChildren(ih, wItemChildList[i], wNewItem, full_copy); + + /* Go to next sibling item */ + i++; + } + + if (wItemChildList) XtFree((char*)wItemChildList); +} + +/* Copies all items in a branch to a new location. Returns the new branch node. */ +static Widget motTreeCopyNode(Ihandle* ih, Widget wItemSrc, Widget wItemDst, int full_copy) +{ + Widget wNewItem, wParent; + motTreeItemData *itemDataDst; + unsigned char stateDst; + int pos; + + XtVaGetValues(wItemDst, XmNoutlineState, &stateDst, + XmNuserData, &itemDataDst, + NULL); + + if (itemDataDst->kind == ITREE_BRANCH && stateDst == XmEXPANDED) + { + /* copy as first child of expanded branch */ + wParent = wItemDst; + pos = 0; + } + else + { + /* copy as next brother of item or collapsed branch */ + XtVaGetValues(wItemDst, XmNentryParent, &wParent, NULL); + XtVaGetValues(wItemDst, XmNpositionIndex, &pos, NULL); + pos++; + } + + wNewItem = motTreeCopyItem(ih, wItemSrc, wParent, pos, full_copy); + + motTreeCopyChildren(ih, wItemSrc, wNewItem, full_copy); + + return wNewItem; +} + +static void motTreeContainerDeselectAll(Ihandle *ih) +{ + XKeyEvent ev; + + memset(&ev, 0, sizeof(XKeyEvent)); + ev.type = KeyPress; + ev.display = XtDisplay(ih->handle); + ev.send_event = True; + ev.root = RootWindow(iupmot_display, iupmot_screen); + ev.time = clock()*CLOCKS_PER_SEC; + ev.window = XtWindow(ih->handle); + ev.state = ControlMask; + ev.keycode = XK_backslash; + ev.same_screen = True; + + XtCallActionProc(ih->handle, "ContainerDeselectAll", (XEvent*)&ev, 0, 0); +} + +static void motTreeContainerSelectAll(Ihandle *ih) +{ + XKeyEvent ev; + + memset(&ev, 0, sizeof(XKeyEvent)); + ev.type = KeyPress; + ev.display = XtDisplay(ih->handle); + ev.send_event = True; + ev.root = RootWindow(iupmot_display, iupmot_screen); + ev.time = clock()*CLOCKS_PER_SEC; + ev.window = XtWindow(ih->handle); + ev.state = ControlMask; + ev.keycode = XK_slash; + ev.same_screen = True; + + XtCallActionProc(ih->handle, "ContainerSelectAll", (XEvent*)&ev, 0, 0); +} + +static Widget motTreeGetLastVisibleNode(Ihandle* ih, Widget wItem) +{ + unsigned char itemState; + + XtVaGetValues(wItem, XmNoutlineState, &itemState, NULL); + + if (itemState == XmEXPANDED) + { + WidgetList wChildrenTree = NULL; + int numChildren = XmContainerGetItemChildren(ih->handle, wItem, &wChildrenTree); + if(numChildren) + wItem = motTreeGetLastVisibleNode(ih, wChildrenTree[numChildren - 1]); + if (wChildrenTree) XtFree((char*)wChildrenTree); + } + + return wItem; +} + +static Widget motTreeFindVisibleNodeId(Ihandle* ih, WidgetList itemList, int numItems, Widget itemNode) +{ + Widget itemChild; + WidgetList itemChildList; + int i = 0; + int numChild; + unsigned char itemState; + + while(i != numItems) + { + /* ID control to traverse items */ + ih->data->id_control++; /* not the real id since it counts only the visible ones */ + + /* StateID founded! */ + if(itemList[i] == itemNode) + return itemList[i]; + + /* Check whether we have child items */ + itemChildList = NULL; + numChild = XmContainerGetItemChildren(ih->handle, itemList[i], &itemChildList); + XtVaGetValues(itemList[i], XmNoutlineState, &itemState, NULL); + + /* The itemWidget has child and it is expanded (visible) */ + if (numChild && itemState == XmEXPANDED) + { + /* pass the list of children of this item */ + itemChild = motTreeFindVisibleNodeId(ih, itemChildList, numChild, itemNode); + + /* StateID founded! */ + if(itemChild) + { + XtFree((char*)itemChildList); + return itemChild; + } + } + + if (itemChildList) XtFree((char*)itemChildList); + /* Go to next sibling item */ + i++; + } + + return NULL; +} + +static Widget motTreeFindVisibleNodeFromId(Ihandle* ih, WidgetList itemList, int numItems) +{ + Widget itemChild; + WidgetList itemChildList; + int i = 0; + int numChild; + unsigned char itemState; + + while(i != numItems) + { + /* ID control to traverse items */ + ih->data->id_control--; /* not the real id since it counts only the visible ones */ + + /* StateID founded! */ + if(ih->data->id_control < 0) + return itemList[i]; + + /* Check whether we have child items */ + itemChildList = NULL; + numChild = XmContainerGetItemChildren(ih->handle, itemList[i], &itemChildList); + XtVaGetValues(itemList[i], XmNoutlineState, &itemState, NULL); + + /* The itemWidget has child and it is expanded (visible) */ + if (numChild && itemState == XmEXPANDED) + { + /* pass the list of children of this item */ + itemChild = motTreeFindVisibleNodeFromId(ih, itemChildList, numChild); + + /* StateID founded! */ + if(ih->data->id_control < 0) + { + if (itemChildList) XtFree((char*)itemChildList); + return itemChild; + } + } + + if (itemChildList) XtFree((char*)itemChildList); + /* Go to next sibling item */ + i++; + } + + return NULL; +} + +static Widget motTreeGetNextVisibleNode(Ihandle* ih, Widget wRoot, Widget wItem) +{ + Widget wNext; + + ih->data->id_control = -1; + motTreeFindVisibleNodeId(ih, &wRoot, 1, wItem); + ih->data->id_control++; /* more 1 visible node */ + + wNext = motTreeFindVisibleNodeFromId(ih, &wRoot, 1); + + if (ih->data->id_control >= 0) + wNext = motTreeGetLastVisibleNode(ih, wRoot); + + return wNext; +} + +static Widget motTreeGetPreviousVisibleNode(Ihandle* ih, Widget wRoot, Widget wItem) +{ + ih->data->id_control = -1; + motTreeFindVisibleNodeId(ih, &wRoot, 1, wItem); + ih->data->id_control--; /* less 1 visible node */ + + if (ih->data->id_control < 0) + ih->data->id_control = 0; /* Begin of tree = Root id */ + + return motTreeFindVisibleNodeFromId(ih, &wRoot, 1); +} + +static void motTreeUpdateBgColor(Ihandle* ih, WidgetList itemList, int numItems, Pixel bgcolor) +{ + WidgetList itemChildList; + int i = 0; + int numChild; + + while(i != numItems) + { + XtVaSetValues(itemList[i], XmNbackground, bgcolor, NULL); + + /* Check whether we have child items */ + itemChildList = NULL; + numChild = XmContainerGetItemChildren(ih->handle, itemList[i], &itemChildList); + if(numChild) + motTreeUpdateBgColor(ih, itemChildList, numChild, bgcolor); + if (itemChildList) XtFree((char*)itemChildList); + + /* Go to next sibling item */ + i++; + } +} + +static void motTreeUpdateImages(Ihandle* ih, WidgetList itemList, int numItems, int mode) +{ + motTreeItemData *itemData; + int i = 0; + + /* called when one of the default images is changed */ + + while(i != numItems) + { + /* Get node attributes */ + XtVaGetValues(itemList[i], XmNuserData, &itemData, NULL); + + if (itemData->kind == ITREE_BRANCH) + { + unsigned char itemState; + XtVaGetValues(itemList[i], XmNoutlineState, &itemState, NULL); + + if (itemState == XmEXPANDED) + { + if (mode == ITREE_UPDATEIMAGE_EXPANDED) + { + XtVaSetValues(itemList[i], XmNsmallIconPixmap, (itemData->image_expanded!=XmUNSPECIFIED_PIXMAP)? itemData->image_expanded: (Pixmap)ih->data->def_image_expanded, NULL); + XtVaSetValues(itemList[i], XmNsmallIconMask, (itemData->image_expanded_mask!=XmUNSPECIFIED_PIXMAP)? itemData->image_expanded_mask: (Pixmap)ih->data->def_image_expanded_mask, NULL); + } + } + else + { + if (mode == ITREE_UPDATEIMAGE_COLLAPSED) + { + XtVaSetValues(itemList[i], XmNsmallIconPixmap, (itemData->image!=XmUNSPECIFIED_PIXMAP)? itemData->image: (Pixmap)ih->data->def_image_collapsed, NULL); + XtVaSetValues(itemList[i], XmNsmallIconMask, (itemData->image_mask!=XmUNSPECIFIED_PIXMAP)? itemData->image_mask: (Pixmap)ih->data->def_image_collapsed_mask, NULL); + } + } + + /* Recursively traverse child items */ + { + WidgetList itemChildList; + int numChild; + itemChildList = NULL; + numChild = XmContainerGetItemChildren(ih->handle, itemList[i], &itemChildList); + motTreeUpdateImages(ih, itemChildList, numChild, mode); + if (itemChildList) XtFree((char*)itemChildList); + } + } + else + { + if (mode == ITREE_UPDATEIMAGE_LEAF) + { + XtVaSetValues(itemList[i], XmNsmallIconPixmap, (itemData->image!=XmUNSPECIFIED_PIXMAP)? itemData->image: (Pixmap)ih->data->def_image_leaf, NULL); + XtVaSetValues(itemList[i], XmNsmallIconMask, (itemData->image_mask!=XmUNSPECIFIED_PIXMAP)? itemData->image_mask: (Pixmap)ih->data->def_image_leaf_mask, NULL); + } + } + + /* Go to next sibling node */ + i++; + } +} + +static int motTreeSelectFunc(Ihandle* ih, Widget wItem, int *select) +{ + int do_select = *select; + if (do_select == -1) + { + unsigned char isSelected; + XtVaGetValues(wItem, XmNvisualEmphasis, &isSelected, NULL); + do_select = (isSelected == XmSELECTED)? 0: 1; /* toggle */ + } + + if (do_select) + XtVaSetValues(wItem, XmNvisualEmphasis, XmSELECTED, NULL); + else + XtVaSetValues(wItem, XmNvisualEmphasis, XmNOT_SELECTED, NULL); + + (void)ih; + return 1; +} + +static void motTreeInvertAllNodeMarking(Ihandle* ih) +{ + int select = -1; + motTreeForEach(ih, NULL, (motTreeNodeFunc)motTreeSelectFunc, &select); +} + +typedef struct _motTreeRange{ + Widget wItem1, wItem2; + char inside, clear; +}motTreeRange; + +static int motTreeSelectRangeFunc(Ihandle* ih, Widget wItem, motTreeRange* range) +{ + int end_range = 0; + + if (range->inside == 0) /* detect the range start */ + { + if (range->wItem1 == wItem) range->inside=1; + else if (range->wItem2 == wItem) range->inside=1; + } + else if (range->inside == 1) /* detect the range end */ + { + if (range->wItem1 == wItem) end_range=1; + else if (range->wItem2 == wItem) end_range=1; + } + + if (range->inside == 1) /* if inside, select */ + XtVaSetValues(wItem, XmNvisualEmphasis, XmSELECTED, NULL); + else if (range->clear) /* if outside and clear, unselect */ + XtVaSetValues(wItem, XmNvisualEmphasis, XmNOT_SELECTED, NULL); + + if (end_range || (range->inside && range->wItem1==range->wItem2)) + range->inside=-1; /* update after selecting the node */ + + (void)ih; + return 1; +} + +static void motTreeSelectRange(Ihandle* ih, Widget wItem1, Widget wItem2, int clear) +{ + motTreeRange range; + range.wItem1 = wItem1; + range.wItem2 = wItem2; + range.inside = 0; + range.clear = (char)clear; + motTreeForEach(ih, NULL, (motTreeNodeFunc)motTreeSelectRangeFunc, &range); +} + +void motTreeExpandCollapseAllNodes(Ihandle* ih, WidgetList itemList, int numItems, unsigned char itemState) +{ + WidgetList itemChildList; + int numChild; + int i = 0; + + while(i != numItems) + { + /* Check whether we have child items */ + itemChildList = NULL; + numChild = XmContainerGetItemChildren(ih->handle, itemList[i], &itemChildList); + + if(numChild) + { + XtVaSetValues(itemList[i], XmNoutlineState, itemState, NULL); + motTreeExpandCollapseAllNodes(ih, itemChildList, numChild, itemState); + } + + if (itemChildList) XtFree((char*)itemChildList); + /* Go to next sibling item */ + i++; + } +} + +static void motTreeDestroyItemData(Ihandle* ih, Widget wItem) +{ + motTreeItemData *itemData = NULL; + XtVaGetValues(wItem, XmNuserData, &itemData, NULL); + if (itemData) + { + IFnis cb = (IFnis)IupGetCallback(ih, "NODEREMOVED_CB"); + if (cb) cb(ih, motTreeGetNodeId(ih, wItem), (char*)itemData->userdata); + free(itemData); + XtVaSetValues(wItem, XmNuserData, NULL, NULL); + } +} + +static void motTreeRemoveChildren(Ihandle* ih, WidgetList itemList, int numItems, int del_userdata) +{ + WidgetList itemChildList; + int numChild; + int i = 0; + + while(i != numItems) + { + /* Check whether we have child items */ + itemChildList = NULL; + numChild = XmContainerGetItemChildren(ih->handle, itemList[i], &itemChildList); + if (numChild) + motTreeRemoveChildren(ih, itemChildList, numChild, del_userdata); + + if (del_userdata) + motTreeDestroyItemData(ih, itemList[i]); + + XtDestroyWidget(itemList[i]); + + if (itemChildList) XtFree((char*)itemChildList); + /* Go to next sibling item */ + i++; + } +} + +static void motTreeRemoveNode(Ihandle* ih, Widget wItem, int del_userdata) +{ + WidgetList wChildList = NULL; + int numChild = XmContainerGetItemChildren(ih->handle, wItem, &wChildList); + if (numChild) + motTreeRemoveChildren(ih, wChildList, numChild, del_userdata); + if (del_userdata) + motTreeDestroyItemData(ih, wItem); + XtDestroyWidget(wItem); + if (wChildList) XtFree((char*)wChildList); +} + +static Widget motTreeFindNodeID(Ihandle* ih, WidgetList itemList, int numItems, Widget itemNode) +{ + Widget itemChild; + WidgetList itemChildList; + int i = 0; + int numChild; + + while(i != numItems) + { + /* ID control to traverse items */ + ih->data->id_control++; + + /* StateID founded! */ + if(itemList[i] == itemNode) + return itemList[i]; + + /* Check whether we have child items */ + itemChildList = NULL; + numChild = XmContainerGetItemChildren(ih->handle, itemList[i], &itemChildList); + if(numChild) + { + /* pass the list of children of this item */ + itemChild = motTreeFindNodeID(ih, itemChildList, numChild, itemNode); + + /* StateID founded! */ + if(itemChild) + { + if (itemChildList) XtFree((char*)itemChildList); + return itemChild; + } + } + + if (itemChildList) XtFree((char*)itemChildList); + /* Go to next sibling item */ + i++; + } + + return NULL; +} + +static Widget motTreeFindNodeFromID(Ihandle* ih, WidgetList itemList, int numItems) +{ + Widget itemChild; + WidgetList itemChildList; + int i = 0; + int numChild; + + while(i != numItems) + { + /* ID control to traverse items */ + ih->data->id_control--; + + /* StateID founded! */ + if(ih->data->id_control < 0) + return itemList[i]; + + /* Check whether we have child items */ + itemChildList = NULL; + numChild = XmContainerGetItemChildren(ih->handle, itemList[i], &itemChildList); + if(numChild) + { + /* pass the list of children of this item */ + itemChild = motTreeFindNodeFromID(ih, itemChildList, numChild); + + /* StateID founded! */ + if(ih->data->id_control < 0) + { + if (itemChildList) XtFree((char*)itemChildList); + return itemChild; + } + } + + if (itemChildList) XtFree((char*)itemChildList); + /* Go to next sibling item */ + i++; + } + + return NULL; +} + +static int motTreeGetNodeId(Ihandle* ih, Widget wItem) +{ + Widget wRoot = (Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM"); + ih->data->id_control = -1; + if (motTreeFindNodeID(ih, &wRoot, 1, wItem)) + return ih->data->id_control; + else + return -1; +} + +static Widget motTreeFindUserDataID(Ihandle* ih, WidgetList itemList, int numItems, void* userdata) +{ + Widget itemChild; + WidgetList itemChildList; + motTreeItemData *itemData; + int i = 0; + int numChild; + + while(i != numItems) + { + /* ID control to traverse items */ + ih->data->id_control++; + + XtVaGetValues(itemList[i], XmNuserData, &itemData, NULL); + + /* StateID founded! */ + if(itemData->userdata == userdata) + return itemList[i]; + + /* Check whether we have child items */ + itemChildList = NULL; + numChild = XmContainerGetItemChildren(ih->handle, itemList[i], &itemChildList); + if(numChild) + { + /* pass the list of children of this item */ + itemChild = motTreeFindUserDataID(ih, itemChildList, numChild, userdata); + + /* StateID founded! */ + if (itemChild) + { + if (itemChildList) XtFree((char*)itemChildList); + return itemChild; + } + } + + if (itemChildList) XtFree((char*)itemChildList); + /* Go to next sibling item */ + i++; + } + + return NULL; +} + +static int motTreeGetUserDataId(Ihandle* ih, void* userdata) +{ + Widget wRoot = (Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM"); + ih->data->id_control = -1; + if (motTreeFindUserDataID(ih, &wRoot, 1, userdata)) + return ih->data->id_control; + else + return -1; +} + +static void motTreeSetFocusNode(Ihandle* ih, Widget wItem) +{ + iupAttribSetStr(ih, "_IUPTREE_LAST_FOCUS", (char*)wItem); + XmProcessTraversal(wItem, XmTRAVERSE_CURRENT); +} + +static Widget motTreeGetFocusNode(Ihandle* ih) +{ + Widget wItem = XmGetFocusWidget(ih->handle); /* returns the focus in the dialog */ + if (wItem && XtParent(wItem) == ih->handle) /* is a node */ + return wItem; + + return (Widget)iupAttribGet(ih, "_IUPTREE_LAST_FOCUS"); +} + +static Widget motTreeFindNodeFromString(Ihandle* ih, const char* name_id) +{ + if (name_id[0]) + { + Widget wRoot = (Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM"); + iupStrToInt(name_id, &ih->data->id_control); + return motTreeFindNodeFromID(ih, &wRoot, 1); + } + else + return motTreeGetFocusNode(ih); +} + +static void motTreeEnterLeaveWindowEvent(Widget w, Ihandle *ih, XEvent *evt, Boolean *cont) +{ + if (iupAttribGet(ih, "_IUPTREE_EDITFIELD")) + return; + + /* usually when one Gadget is selected different than the previous one, + leave/enter events are generated. But we could not find the exact condition, + so this is a workaround. Some leave events will be lost. */ + if (evt->type == EnterNotify) + { + if (iupAttribGet(ih, "_IUPTREE_IGNORE_ENTERLEAVE")) + { + iupAttribSetStr(ih, "_IUPTREE_IGNORE_ENTERLEAVE", NULL); + return; + } + } + else if (evt->type == LeaveNotify) + { + if (iupAttribGet(ih, "_IUPTREE_IGNORE_ENTERLEAVE")) + return; + } + + iupmotEnterLeaveWindowEvent(w, ih, evt, cont); +} + +static void motTreeFocusChangeEvent(Widget w, Ihandle *ih, XEvent *evt, Boolean *cont) +{ + unsigned char selpol; + Widget wItem = XmGetFocusWidget(w); /* returns the focus in the dialog */ + Widget wRoot = (Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM"); + + if (XtParent(wItem) == w) /* is a node */ + iupAttribSetStr(ih, "_IUPTREE_LAST_FOCUS", (char*)wItem); + + if (wItem == NULL || wItem == wRoot) + { + iupmotFocusChangeEvent(w, ih, evt, cont); + return; + } + + XtVaGetValues(w, XmNselectionPolicy, &selpol, NULL); + if (selpol != XmSINGLE_SELECT) + return; + + if (evt->type == FocusIn && !iupStrBoolean(IupGetGlobal("CONTROLKEY"))) + { + XtVaSetValues(w, XmNselectedObjects, NULL, NULL); + XtVaSetValues(w, XmNselectedObjectCount, 0, NULL); + XtVaSetValues(wItem, XmNvisualEmphasis, XmSELECTED, NULL); + } +} + +void iupdrvTreeAddNode(Ihandle* ih, const char* name_id, int kind, const char* title, int add) +{ + Widget wItemPrev = motTreeFindNodeFromString(ih, name_id); + Widget wNewItem; + XmString itemTitle; + motTreeItemData *itemData, *itemDataPrev; + Pixel bgcolor, fgcolor; + int kindPrev, num_args = 0; + Arg args[30]; + + if (!wItemPrev) + return; + + itemData = calloc(1, sizeof(motTreeItemData)); + itemData->image = XmUNSPECIFIED_PIXMAP; + itemData->image_expanded = XmUNSPECIFIED_PIXMAP; + itemData->image_mask = XmUNSPECIFIED_PIXMAP; + itemData->image_expanded_mask = XmUNSPECIFIED_PIXMAP; + itemData->kind = (unsigned char)kind; + + itemTitle = XmStringCreateLocalized((String)title); + + /* Get default colors */ + XtVaGetValues(ih->handle, XmNforeground, &fgcolor, NULL); + XtVaGetValues(ih->handle, XmNbackground, &bgcolor, NULL); + + /* Get the kind of previous item */ + XtVaGetValues(wItemPrev, XmNuserData, &itemDataPrev, NULL); + kindPrev = itemDataPrev->kind; + + if (kindPrev == ITREE_BRANCH && add) + { + /* wItemPrev is parent of the new item (firstchild of it) */ + iupmotSetArg(args, num_args, XmNentryParent, wItemPrev); + iupmotSetArg(args, num_args, XmNpositionIndex, 0); + } + else + { + /* wItemPrev is sibling of the new item (set its parent to the new item) */ + Widget wItemParent; + int pos; + + XtVaGetValues(wItemPrev, XmNentryParent, &wItemParent, NULL); + XtVaGetValues(wItemPrev, XmNpositionIndex, &pos, NULL); + + iupmotSetArg(args, num_args, XmNentryParent, wItemParent); + iupmotSetArg(args, num_args, XmNpositionIndex, pos+1); + } + + iupmotSetArg(args, num_args, XmNuserData, itemData); + iupmotSetArg(args, num_args, XmNforeground, fgcolor); + iupmotSetArg(args, num_args, XmNbackground, bgcolor); + iupmotSetArg(args, num_args, XmNmarginHeight, ih->data->spacing); + iupmotSetArg(args, num_args, XmNmarginWidth, 0); + iupmotSetArg(args, num_args, XmNviewType, XmSMALL_ICON); + iupmotSetArg(args, num_args, XmNnavigationType, XmTAB_GROUP); + iupmotSetArg(args, num_args, XmNtraversalOn, True); + iupmotSetArg(args, num_args, XmNshadowThickness, 0); + iupmotSetArg(args, num_args, XmNlabelString, itemTitle); + + if (kind == ITREE_BRANCH) + { + if (ih->data->add_expanded) + { + iupmotSetArg(args, num_args, XmNsmallIconPixmap, ih->data->def_image_expanded); + iupmotSetArg(args, num_args, XmNsmallIconMask, ih->data->def_image_expanded_mask); + } + else + { + iupmotSetArg(args, num_args, XmNsmallIconPixmap, ih->data->def_image_collapsed); + iupmotSetArg(args, num_args, XmNsmallIconMask, ih->data->def_image_collapsed_mask); + } + } + else + { + iupmotSetArg(args, num_args, XmNsmallIconPixmap, ih->data->def_image_leaf); + iupmotSetArg(args, num_args, XmNsmallIconMask, ih->data->def_image_leaf_mask); + } + + + wNewItem = XtCreateManagedWidget("icon", xmIconGadgetClass, ih->handle, args, num_args); + + if (kind == ITREE_BRANCH) + { + if (ih->data->add_expanded) + { + iupAttribSetStr(ih, "_IUP_IGNORE_BRANCHOPEN", "1"); + XtVaSetValues(wNewItem, XmNoutlineState, XmEXPANDED, NULL); + } + else + XtVaSetValues(wNewItem, XmNoutlineState, XmCOLLAPSED, NULL); + } + + /* Root always expanded */ + XtVaSetValues((Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM"), XmNoutlineState, XmEXPANDED, NULL); + + XtRealizeWidget(wNewItem); + XmStringFree(itemTitle); +} + +static void motTreeAddRootNode(Ihandle* ih) +{ + Widget wRootItem; + motTreeItemData *itemData; + Pixel bgcolor, fgcolor; + int num_args = 0; + Arg args[30]; + + itemData = calloc(1, sizeof(motTreeItemData)); + itemData->image = XmUNSPECIFIED_PIXMAP; + itemData->image_expanded = XmUNSPECIFIED_PIXMAP; + itemData->image_mask = XmUNSPECIFIED_PIXMAP; + itemData->image_expanded_mask = XmUNSPECIFIED_PIXMAP; + itemData->kind = ITREE_BRANCH; + + /* Get default foreground color */ + XtVaGetValues(ih->handle, XmNforeground, &fgcolor, NULL); + XtVaGetValues(ih->handle, XmNbackground, &bgcolor, NULL); + + iupmotSetArg(args, num_args, XmNentryParent, NULL); + iupmotSetArg(args, num_args, XmNuserData, itemData); + iupmotSetArg(args, num_args, XmNforeground, fgcolor); + iupmotSetArg(args, num_args, XmNbackground, bgcolor); + iupmotSetArg(args, num_args, XmNoutlineState, XmEXPANDED); + iupmotSetArg(args, num_args, XmNmarginHeight, ih->data->spacing); + iupmotSetArg(args, num_args, XmNmarginWidth, 0); + iupmotSetArg(args, num_args, XmNviewType, XmSMALL_ICON); + iupmotSetArg(args, num_args, XmNnavigationType, XmTAB_GROUP); + iupmotSetArg(args, num_args, XmNtraversalOn, True); + iupmotSetArg(args, num_args, XmNshadowThickness, 0); + iupmotSetArg(args, num_args, XmNsmallIconPixmap, ih->data->def_image_expanded); + iupmotSetArg(args, num_args, XmNsmallIconMask, ih->data->def_image_expanded_mask); + + wRootItem = XtCreateManagedWidget("icon", xmIconGadgetClass, ih->handle, args, num_args); + + /* Select the new item */ + XtVaSetValues(wRootItem, XmNvisualEmphasis, XmSELECTED, NULL); + + XtRealizeWidget(wRootItem); + + /* Save the root node for later use */ + iupAttribSetStr(ih, "_IUPTREE_ROOTITEM", (char*)wRootItem); + + /* MarkStart node */ + iupAttribSetStr(ih, "_IUPTREE_MARKSTART_NODE", (char*)wRootItem); + + /* Set the default VALUE */ + /* In Motif this will set also the current focus */ + motTreeSetFocusNode(ih, wRootItem); +} + +/*****************************************************************************/ + +static int motTreeSetImageExpandedAttrib(Ihandle* ih, const char* name_id, const char* value) +{ + motTreeItemData *itemData; + unsigned char itemState; + Widget wItem = motTreeFindNodeFromString(ih, name_id); + if (!wItem) + return 0; + + XtVaGetValues(wItem, XmNuserData, &itemData, NULL); + XtVaGetValues(wItem, XmNoutlineState, &itemState, NULL); + itemData->image_expanded = (Pixmap)iupImageGetImage(value, ih, 0); + if (!itemData->image_expanded) + { + itemData->image_expanded = XmUNSPECIFIED_PIXMAP; + itemData->image_expanded_mask = XmUNSPECIFIED_PIXMAP; + } + else + { + itemData->image_expanded_mask = (Pixmap)iupImageGetMask(value); + if (!itemData->image_expanded_mask) itemData->image_expanded_mask = XmUNSPECIFIED_PIXMAP; + } + + if (itemData->kind == ITREE_BRANCH && itemState == XmEXPANDED) + { + if (itemData->image_expanded == XmUNSPECIFIED_PIXMAP) + XtVaSetValues(wItem, XmNsmallIconPixmap, (Pixmap)ih->data->def_image_expanded, + XmNsmallIconMask, (Pixmap)ih->data->def_image_expanded_mask, + NULL); + else + XtVaSetValues(wItem, XmNsmallIconPixmap, itemData->image_expanded, + XmNsmallIconMask, itemData->image_expanded_mask, + NULL); + } + + return 1; +} + +static int motTreeSetImageAttrib(Ihandle* ih, const char* name_id, const char* value) +{ + motTreeItemData *itemData; + Widget wItem = motTreeFindNodeFromString(ih, name_id); + if (!wItem) + return 0; + + XtVaGetValues(wItem, XmNuserData, &itemData, NULL); + itemData->image = (Pixmap)iupImageGetImage(value, ih, 0); + if (!itemData->image) + { + itemData->image = XmUNSPECIFIED_PIXMAP; + itemData->image_mask = XmUNSPECIFIED_PIXMAP; + } + else + { + itemData->image_mask = (Pixmap)iupImageGetMask(value); + if (!itemData->image_mask) itemData->image_mask = XmUNSPECIFIED_PIXMAP; + } + + if (itemData->kind == ITREE_BRANCH) + { + unsigned char itemState; + XtVaGetValues(wItem, XmNoutlineState, &itemState, NULL); + if (itemState == XmCOLLAPSED) + { + if (itemData->image == XmUNSPECIFIED_PIXMAP) + XtVaSetValues(wItem, XmNsmallIconPixmap, (Pixmap)ih->data->def_image_collapsed, + XmNsmallIconMask, (Pixmap)ih->data->def_image_collapsed_mask, + NULL); + else + XtVaSetValues(wItem, XmNsmallIconPixmap, itemData->image, + XmNsmallIconMask, itemData->image_mask, + NULL); + } + } + else + { + if (itemData->image == XmUNSPECIFIED_PIXMAP) + XtVaSetValues(wItem, XmNsmallIconPixmap, (Pixmap)ih->data->def_image_leaf, + XmNsmallIconMask, (Pixmap)ih->data->def_image_leaf_mask, + NULL); + else + XtVaSetValues(wItem, XmNsmallIconPixmap, itemData->image, + XmNsmallIconMask, itemData->image_mask, + NULL); + } + + return 1; +} + +static int motTreeSetImageBranchExpandedAttrib(Ihandle* ih, const char* value) +{ + Widget wRoot = (Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM"); + ih->data->def_image_expanded = iupImageGetImage(value, ih, 0); + if (!ih->data->def_image_expanded) + { + ih->data->def_image_expanded = (void*)XmUNSPECIFIED_PIXMAP; + ih->data->def_image_expanded_mask = (void*)XmUNSPECIFIED_PIXMAP; + } + else + { + ih->data->def_image_expanded_mask = iupImageGetMask(value); + if (!ih->data->def_image_expanded_mask) ih->data->def_image_expanded_mask = (void*)XmUNSPECIFIED_PIXMAP; + } + + /* Update all images, starting at root node */ + motTreeUpdateImages(ih, &wRoot, 1, ITREE_UPDATEIMAGE_EXPANDED); + + return 1; +} + +static int motTreeSetImageBranchCollapsedAttrib(Ihandle* ih, const char* value) +{ + Widget wRoot = (Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM"); + ih->data->def_image_collapsed = iupImageGetImage(value, ih, 0); + if (!ih->data->def_image_collapsed) + { + ih->data->def_image_collapsed = (void*)XmUNSPECIFIED_PIXMAP; + ih->data->def_image_collapsed_mask = (void*)XmUNSPECIFIED_PIXMAP; + } + else + { + ih->data->def_image_collapsed_mask = iupImageGetMask(value); + if (!ih->data->def_image_collapsed_mask) ih->data->def_image_collapsed_mask = (void*)XmUNSPECIFIED_PIXMAP; + } + + /* Update all images, starting at root node */ + motTreeUpdateImages(ih, &wRoot, 1, ITREE_UPDATEIMAGE_COLLAPSED); + + return 1; +} + +static int motTreeSetImageLeafAttrib(Ihandle* ih, const char* value) +{ + Widget wRoot = (Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM"); + ih->data->def_image_leaf = iupImageGetImage(value, ih, 0); + if (!ih->data->def_image_leaf) + { + ih->data->def_image_leaf = (void*)XmUNSPECIFIED_PIXMAP; + ih->data->def_image_leaf_mask = (void*)XmUNSPECIFIED_PIXMAP; + } + else + { + ih->data->def_image_leaf_mask = iupImageGetMask(value); + if (!ih->data->def_image_leaf_mask) ih->data->def_image_leaf_mask = (void*)XmUNSPECIFIED_PIXMAP; + } + + /* Update all images, starting at root node */ + motTreeUpdateImages(ih, &wRoot, 1, ITREE_UPDATEIMAGE_LEAF); + + return 1; +} + +static char* motTreeGetStateAttrib(Ihandle* ih, const char* name_id) +{ + int hasChildren; + unsigned char itemState; + Widget wItem = motTreeFindNodeFromString(ih, name_id); + if (!wItem) + return 0; + + XtVaGetValues(wItem, XmNnumChildren, &hasChildren, NULL); + XtVaGetValues(wItem, XmNoutlineState, &itemState, NULL); + + if (hasChildren) + { + if(itemState == XmEXPANDED) + return "EXPANDED"; + else + return "COLLAPSED"; + } + + return NULL; +} + +static int motTreeSetStateAttrib(Ihandle* ih, const char* name_id, const char* value) +{ + Widget wItem = motTreeFindNodeFromString(ih, name_id); + if (!wItem) + return 0; + + if (iupStrEqualNoCase(value, "EXPANDED")) + XtVaSetValues(wItem, XmNoutlineState, XmEXPANDED, NULL); + else + XtVaSetValues(wItem, XmNoutlineState, XmCOLLAPSED, NULL); + + return 0; +} + +static char* motTreeGetColorAttrib(Ihandle* ih, const char* name_id) +{ + unsigned char r, g, b; + Pixel color; + char* str; + Widget wItem = motTreeFindNodeFromString(ih, name_id); + if (!wItem) + return NULL; + + XtVaGetValues(wItem, XmNforeground, &color, NULL); + iupmotColorGetRGB(color, &r, &g, &b); + + str = iupStrGetMemory(20); + sprintf(str, "%d %d %d", (int)r, (int)g, (int)b); + return str; +} + +static int motTreeSetColorAttrib(Ihandle* ih, const char* name_id, const char* value) +{ + Pixel color; + Widget wItem = motTreeFindNodeFromString(ih, name_id); + if (!wItem) + return 0; + + color = iupmotColorGetPixelStr(value); + if (color != (Pixel)-1) + XtVaSetValues(wItem, XmNforeground, color, NULL); + return 0; +} + +static char* motTreeGetDepthAttrib(Ihandle* ih, const char* name_id) +{ + Widget wRoot; + int dep = 0; + char* depth; + Widget wItem = motTreeFindNodeFromString(ih, name_id); + if (!wItem) + return NULL; + + wRoot = (Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM"); + + while((wRoot != wItem) && (wItem != NULL)) + { + XtVaGetValues(wItem, XmNentryParent, &wItem, NULL); + dep++; + } + + depth = iupStrGetMemory(10); + sprintf(depth, "%d", dep); + return depth; +} + +static int motTreeSetMoveNodeAttrib(Ihandle* ih, const char* name_id, const char* value) +{ + Widget wItemDst, wParent, wItemSrc; + + if (!ih->handle) /* do not store the action before map */ + return 0; + wItemSrc = motTreeFindNodeFromString(ih, name_id); + if (!wItemSrc) + return 0; + wItemDst = motTreeFindNodeFromString(ih, value); + if (!wItemDst) + return 0; + + /* If Drag item is an ancestor of Drop item then return */ + wParent = wItemDst; + while(wParent) + { + XtVaGetValues(wParent, XmNentryParent, &wParent, NULL); + if (wParent == wItemSrc) + return 0; + } + + /* Copying the node and its children to the new position */ + motTreeCopyNode(ih, wItemSrc, wItemDst, 0); /* not a full copy, preserve user data */ + + /* Deleting the node (and its children) inserted into the old position */ + motTreeRemoveNode(ih, wItemSrc, 0); /* do not delete the user data, we copy the references in CopyNode */ + + return 0; +} + +static int motTreeSetCopyNodeAttrib(Ihandle* ih, const char* name_id, const char* value) +{ + Widget wItemDst, wParent, wItemSrc; + + if (!ih->handle) /* do not store the action before map */ + return 0; + wItemSrc = motTreeFindNodeFromString(ih, name_id); + if (!wItemSrc) + return 0; + wItemDst = motTreeFindNodeFromString(ih, value); + if (!wItemDst) + return 0; + + /* If Drag item is an ancestor of Drop item then return */ + wParent = wItemDst; + while(wParent) + { + XtVaGetValues(wParent, XmNentryParent, &wParent, NULL); + if (wParent == wItemSrc) + return 0; + } + + /* Copying the node and its children to the new position */ + motTreeCopyNode(ih, wItemSrc, wItemDst, 1); + + return 0; +} + +static char* motTreeGetParentAttrib(Ihandle* ih, const char* name_id) +{ + Widget wItemParent; + char* str; + Widget wItem = motTreeFindNodeFromString(ih, name_id); + if (!wItem) + return NULL; + + /* get the parent item */ + XtVaGetValues(wItem, XmNentryParent, &wItemParent, NULL); + if (!wItemParent) + return NULL; + + str = iupStrGetMemory(10); + sprintf(str, "%d", motTreeGetNodeId(ih, wItemParent)); + return str; +} + +static char* motTreeGetChildCountAttrib(Ihandle* ih, const char* name_id) +{ + char* str; + WidgetList wList = NULL; + Widget wItem = motTreeFindNodeFromString(ih, name_id); + if (!wItem) + return NULL; + + str = iupStrGetMemory(10); + sprintf(str, "%d", XmContainerGetItemChildren(ih->handle, wItem, &wList)); + if (wList) XtFree((char*)wList); + return str; +} + +static int motTreeCount(Ihandle* ih, Widget wItem) +{ + WidgetList wList = NULL; + int i, count = 0; + int childCount = XmContainerGetItemChildren(ih->handle, wItem, &wList); + count++; + for (i=0; ikind == ITREE_BRANCH) + return "BRANCH"; + else + return "LEAF"; +} + +static char* motTreeGetValueAttrib(Ihandle* ih) +{ + char* str; + Widget wItem = motTreeGetFocusNode(ih); + if (!wItem) + return "0"; /* default VALUE is root */ + + str = iupStrGetMemory(10); + sprintf(str, "%d", motTreeGetNodeId(ih, wItem)); + return str; +} + +static int motTreeSetMarkAttrib(Ihandle* ih, const char* value) +{ + if (ih->data->mark_mode==ITREE_MARK_SINGLE) + return 0; + + if(iupStrEqualNoCase(value, "CLEARALL")) + motTreeContainerDeselectAll(ih); + else if(iupStrEqualNoCase(value, "MARKALL")) + motTreeContainerSelectAll(ih); + else if(iupStrEqualNoCase(value, "INVERTALL")) /* INVERTALL *MUST* appear before INVERT, or else INVERTALL will never be called. */ + motTreeInvertAllNodeMarking(ih); + else if(iupStrEqualPartial(value, "INVERT")) + { + unsigned char isSelected; + Widget wItem = motTreeFindNodeFromString(ih, &value[strlen("INVERT")]); + if (!wItem) + return 0; + + XtVaGetValues(wItem, XmNvisualEmphasis, &isSelected, NULL); + if (isSelected == XmSELECTED) + XtVaSetValues(wItem, XmNvisualEmphasis, XmNOT_SELECTED, NULL); + else + XtVaSetValues(wItem, XmNvisualEmphasis, XmSELECTED, NULL); + } + else if(iupStrEqualNoCase(value, "BLOCK")) + { + Widget wItem = (Widget)iupAttribGet(ih, "_IUPTREE_MARKSTART_NODE"); + Widget wFocusItem = motTreeGetFocusNode(ih); + if(!wFocusItem || !wItem) + return 0; + motTreeSelectRange(ih, wFocusItem, wItem, 0); + } + else + { + Widget wItem1, wItem2; + char str1[50], str2[50]; + if (iupStrToStrStr(value, str1, str2, '-')!=2) + return 0; + + wItem1 = motTreeFindNodeFromString(ih, str1); + if (!wItem1) + return 0; + wItem2 = motTreeFindNodeFromString(ih, str2); + if (!wItem2) + return 0; + + motTreeSelectRange(ih, wItem1, wItem2, 0); + } + + return 1; +} + +static int motTreeSetValueAttrib(Ihandle* ih, const char* value) +{ + Widget wRoot, wItem; + + if (motTreeSetMarkAttrib(ih, value)) + return 0; + + wRoot = (Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM"); + + if (iupStrEqualNoCase(value, "ROOT")) + wItem = wRoot; + else if(iupStrEqualNoCase(value, "LAST")) + wItem = motTreeGetLastVisibleNode(ih, wRoot); + else if(iupStrEqualNoCase(value, "PGUP")) + { + Widget wItemFocus = motTreeGetFocusNode(ih); + if(!wItemFocus) + return 0; + + ih->data->id_control = -1; + motTreeFindVisibleNodeId(ih, &wRoot, 1, wItemFocus); + ih->data->id_control -= 10; /* less 10 visible nodes */ + + if(ih->data->id_control < 0) + ih->data->id_control = 0; /* Begin of tree = Root id */ + + wItem = motTreeFindVisibleNodeFromId(ih, &wRoot, 1); + } + else if(iupStrEqualNoCase(value, "PGDN")) + { + Widget wNext, wItemFocus; + + wItemFocus = motTreeGetFocusNode(ih); + if(!wItemFocus) + return 0; + + ih->data->id_control = -1; + motTreeFindVisibleNodeId(ih, &wRoot, 1, wItemFocus); + ih->data->id_control += 10; /* more 10 visible nodes */ + + wNext = motTreeFindVisibleNodeFromId(ih, &wRoot, 1); + + if (ih->data->id_control >= 0) + wNext = motTreeGetLastVisibleNode(ih, wRoot); + + wItem = wNext; + } + else if(iupStrEqualNoCase(value, "NEXT")) + { + Widget wItemFocus = motTreeGetFocusNode(ih); + if (!wItemFocus) + return 0; + + wItem = motTreeGetNextVisibleNode(ih, wRoot, wItemFocus); + } + else if(iupStrEqualNoCase(value, "PREVIOUS")) + { + Widget wItemFocus = motTreeGetFocusNode(ih); + if(!wItemFocus) + return 0; + + wItem = motTreeGetPreviousVisibleNode(ih, wRoot, wItemFocus); + } + else + wItem = motTreeFindNodeFromString(ih, value); + + if (!wItem) + return 0; + + /* select */ + if (ih->data->mark_mode==ITREE_MARK_SINGLE) + { + /* clear previous selection */ + XtVaSetValues(ih->handle, XmNselectedObjects, NULL, NULL); + XtVaSetValues(ih->handle, XmNselectedObjectCount, 0, NULL); + + XtVaSetValues(wItem, XmNvisualEmphasis, XmSELECTED, NULL); + } + + /* set focus (will scroll to visible) */ + motTreeSetFocusNode(ih, wItem); + + iupAttribSetInt(ih, "_IUPTREE_OLDVALUE", motTreeGetNodeId(ih, wItem)); + + return 0; +} + +static int motTreeSetMarkStartAttrib(Ihandle* ih, const char* name_id) +{ + Widget wItem = motTreeFindNodeFromString(ih, name_id); + if (!wItem) + return 0; + + iupAttribSetStr(ih, "_IUPTREE_MARKSTART_NODE", (char*)wItem); + + return 1; +} + +static char* motTreeGetMarkedAttrib(Ihandle* ih, const char* name_id) +{ + unsigned char isSelected; + Widget wItem = motTreeFindNodeFromString(ih, name_id); + if (!wItem) + return NULL; + + XtVaGetValues(wItem, XmNvisualEmphasis, &isSelected, NULL); + + if(isSelected == XmSELECTED) + return "YES"; + else + return "NO"; +} + +static int motTreeSetMarkedAttrib(Ihandle* ih, const char* name_id, const char* value) +{ + Widget wItem = motTreeFindNodeFromString(ih, name_id); + if (!wItem) + return 0; + + if (iupStrBoolean(value)) + XtVaSetValues(wItem, XmNvisualEmphasis, XmSELECTED, NULL); + else + XtVaSetValues(wItem, XmNvisualEmphasis, XmNOT_SELECTED, NULL); + + return 0; +} + +static char* motTreeGetTitle(Widget wItem) +{ + char *title; + XmString itemTitle; + XtVaGetValues(wItem, XmNlabelString, &itemTitle, NULL); + title = iupmotConvertString(itemTitle); + XmStringFree(itemTitle); + return title; +} + +static char* motTreeGetTitleAttrib(Ihandle* ih, const char* name_id) +{ + Widget wItem = motTreeFindNodeFromString(ih, name_id); + if (!wItem) + return NULL; + return motTreeGetTitle(wItem); +} + +static int motTreeSetTitleAttrib(Ihandle* ih, const char* name_id, const char* value) +{ + Widget wItem = motTreeFindNodeFromString(ih, name_id); + if (!wItem) + return 0; + + iupmotSetString(wItem, XmNlabelString, value); + + return 0; +} + +static int motTreeSetTitleFontAttrib(Ihandle* ih, const char* name_id, const char* value) +{ + XmFontList fontlist = NULL; + Widget wItem = motTreeFindNodeFromString(ih, name_id); + if (!wItem) + return 0; + + if (value) + { + char attr[20]; + sprintf(attr, "TITLEFOUNDRY%s", name_id); + fontlist = iupmotGetFontList(iupAttribGet(ih, attr), value); + } + XtVaSetValues(wItem, XmNrenderTable, fontlist, NULL); + + return 0; +} + +static char* motTreeGetTitleFontAttrib(Ihandle* ih, const char* name_id) +{ + XmFontList fontlist; + Widget wItem = motTreeFindNodeFromString(ih, name_id); + if (!wItem) + return NULL; + + XtVaGetValues(wItem, XmNrenderTable, &fontlist, NULL); + return iupmotFindFontList(fontlist); +} + +static char* motTreeGetFindUserDataAttrib(Ihandle* ih, const char* name_id) +{ + int id; + char* str = (char*)(name_id+1); /* skip ':' */ + void* userdata = NULL; + if (sscanf(str, "%p", &userdata)!=1) + return NULL; + id = motTreeGetUserDataId(ih, userdata); + if (id == -1) + return NULL; + str = iupStrGetMemory(16); + sprintf(str, "%d", id); + return str; +} + +static char* motTreeGetUserDataAttrib(Ihandle* ih, const char* name_id) +{ + motTreeItemData *itemData; + Widget wItem = motTreeFindNodeFromString(ih, name_id); + if (!wItem) + return NULL; + + XtVaGetValues(wItem, XmNuserData, &itemData, NULL); + + return itemData->userdata; +} + +static int motTreeSetUserDataAttrib(Ihandle* ih, const char* name_id, const char* value) +{ + motTreeItemData *itemData; + Widget wItem = motTreeFindNodeFromString(ih, name_id); + if (!wItem) + return 0; + + XtVaGetValues(wItem, XmNuserData, &itemData, NULL); + itemData->userdata = (void*)value; + + return 0; +} + +static int motTreeSetRenameAttrib(Ihandle* ih, const char* value) +{ + if (ih->data->show_rename) + { + IFni cbShowRename = (IFni)IupGetCallback(ih, "SHOWRENAME_CB"); + Widget wItemFocus = motTreeGetFocusNode(ih); + if (cbShowRename) + cbShowRename(ih, motTreeGetNodeId(ih, wItemFocus)); + motTreeShowEditField(ih, wItemFocus); + } + else + { + IFnis cbRenameNode = (IFnis)IupGetCallback(ih, "RENAMENODE_CB"); + if (cbRenameNode) + { + Widget wItemFocus = motTreeGetFocusNode(ih); + cbRenameNode(ih, motTreeGetNodeId(ih, wItemFocus), motTreeGetTitle(wItemFocus)); + } + } + + (void)value; + return 0; +} + +static int motTreeSetDelNodeAttrib(Ihandle* ih, const char* name_id, const char* value) +{ + if (!ih->handle) /* do not store the action before map */ + return 0; + if(iupStrEqualNoCase(value, "SELECTED")) /* selected here means the specified one */ + { + Widget wItem = motTreeFindNodeFromString(ih, name_id); + Widget wRoot = (Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM"); + + /* the root node can't be deleted */ + if(!wItem || wItem == wRoot) /* root is the unique child */ + return 0; + + /* deleting the specified node (and it's children) */ + motTreeRemoveNode(ih, wItem, 1); + } + else if(iupStrEqualNoCase(value, "CHILDREN")) /* children of the specified one */ + { + Widget wItem = motTreeFindNodeFromString(ih, name_id); + + if(!wItem) + return 0; + + { + /* deleting the selected node's children only */ + WidgetList wItemList = NULL; + int numChild = XmContainerGetItemChildren(ih->handle, wItem, &wItemList); + if(numChild) + motTreeRemoveChildren(ih, wItemList, numChild, 1); + if (wItemList) XtFree((char*)wItemList); + } + } + else if(iupStrEqualNoCase(value, "MARKED")) /* Delete the array of marked nodes */ + { + WidgetList wSelectedItemList = NULL; + Widget wRoot; + int countItems, i; + + XtVaGetValues(ih->handle, XmNselectedObjects, &wSelectedItemList, + XmNselectedObjectCount, &countItems, NULL); + + wRoot = (Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM"); + + for(i = 0; i < countItems; i++) + { + int ok = XmIsIconGadget(wSelectedItemList[i]); + if ((wSelectedItemList[i] != wRoot) && ok) /* the root node can't be deleted */ + motTreeRemoveNode(ih, wSelectedItemList[i], 1); + } + } + + return 0; +} + +static char* motTreeGetIndentationAttrib(Ihandle* ih) +{ + char* str = iupStrGetMemory(255); + Dimension indent; + XtVaGetValues(ih->handle, XmNoutlineIndentation, &indent, NULL); + sprintf(str, "%d", (int)indent); + return str; +} + +static int motTreeSetIndentationAttrib(Ihandle* ih, const char* value) +{ + int indent; + if (iupStrToInt(value, &indent)) + XtVaSetValues(ih->handle, XmNoutlineIndentation, (Dimension)indent, NULL); + return 0; +} + +static int motTreeSetTopItemAttrib(Ihandle* ih, const char* value) +{ + Widget wItem = motTreeFindNodeFromString(ih, value); + Widget sb_win; + Widget wItemParent; + + if (!wItem) + return 0; + + /* expand all parents */ + XtVaGetValues(wItem, XmNentryParent, &wItemParent, NULL); + while(wItemParent) + { + XtVaSetValues(wItemParent, XmNoutlineState, XmEXPANDED, NULL); + XtVaGetValues(wItemParent, XmNentryParent, &wItemParent, NULL); + } + + sb_win = (Widget)iupAttribGet(ih, "_IUP_EXTRAPARENT"); + XmScrollVisible(sb_win, wItem, 0, 0); + + return 0; +} + +static int motTreeSpacingFunc(Ihandle* ih, Widget wItem, void *data) +{ + XtVaSetValues(wItem, XmNmarginHeight, ih->data->spacing, NULL); + (void)data; + return 1; +} + +static int motTreeSetSpacingAttrib(Ihandle* ih, const char* value) +{ + if (!iupStrToInt(value, &ih->data->spacing)) + ih->data->spacing = 1; + + if (ih->data->spacing < 1) + ih->data->spacing = 1; + + if (ih->handle) + { + motTreeForEach(ih, NULL, (motTreeNodeFunc)motTreeSpacingFunc, 0); + return 0; + } + else + return 1; /* store until not mapped, when mapped will be set again */ +} + +static int motTreeSetExpandAllAttrib(Ihandle* ih, const char* value) +{ + Widget wRoot = (Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM"); + + if (iupStrBoolean(value)) + motTreeExpandCollapseAllNodes(ih, &wRoot, 1, XmEXPANDED); + else + { + motTreeExpandCollapseAllNodes(ih, &wRoot, 1, XmCOLLAPSED); + + /* The root node is always expanded */ + XtVaSetValues((Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM"), XmNoutlineState, XmEXPANDED, NULL); + } + + return 0; +} + +static int motTreeSetBgColorAttrib(Ihandle* ih, const char* value) +{ + Widget sb_win = (Widget)iupAttribGet(ih, "_IUP_EXTRAPARENT"); + Pixel color; + + /* ignore given value for the scrollbars, must use only from parent */ + char* parent_value = iupBaseNativeParentGetBgColor(ih); + + color = iupmotColorGetPixelStr(parent_value); + if (color != (Pixel)-1) + { + Widget sb = NULL; + + iupmotSetBgColor(sb_win, color); + + XtVaGetValues(sb_win, XmNverticalScrollBar, &sb, NULL); + if (sb) iupmotSetBgColor(sb, color); + + XtVaGetValues(sb_win, XmNhorizontalScrollBar, &sb, NULL); + if (sb) iupmotSetBgColor(sb, color); + } + + color = iupmotColorGetPixelStr(value); + if (color != (Pixel)-1) + { + Widget wRoot; + Widget clipwin = NULL; + + XtVaGetValues(sb_win, XmNclipWindow, &clipwin, NULL); + if (clipwin) iupmotSetBgColor(clipwin, color); + + wRoot = (Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM"); + + /* Update all children, starting at root node */ + motTreeUpdateBgColor(ih, &wRoot, 1, color); + } + + iupdrvBaseSetBgColorAttrib(ih, value); /* use given value for contents */ + + /* update internal image cache */ + iupTreeUpdateImages(ih); + + return 1; +} + +static int motTreeSetFgColorAttrib(Ihandle* ih, const char* value) +{ + Pixel color = iupmotColorGetPixelStr(value); + if (color != (Pixel)-1) + XtVaSetValues(ih->handle, XmNforeground, color, NULL); + + return 1; +} + +void iupdrvTreeUpdateMarkMode(Ihandle *ih) +{ + XtVaSetValues(ih->handle, XmNselectionPolicy, (ih->data->mark_mode==ITREE_MARK_SINGLE)? XmSINGLE_SELECT: XmEXTENDED_SELECT, NULL); +} + +/************************************************************************************************/ + + +static void motTreeSetRenameCaretPos(Widget cbEdit, const char* value) +{ + int pos = 1; + + if (iupStrToInt(value, &pos)) + { + if (pos < 1) pos = 1; + pos--; /* IUP starts at 1 */ + + XtVaSetValues(cbEdit, XmNcursorPosition, pos, NULL); + } +} + +static void motTreeSetRenameSelectionPos(Widget cbEdit, const char* value) +{ + int start = 1, end = 1; + + if (iupStrToIntInt(value, &start, &end, ':') != 2) + return; + + if(start < 1 || end < 1) + return; + + start--; /* IUP starts at 1 */ + end--; + + XmTextSetSelection(cbEdit, start, end, CurrentTime); +} + +/*****************************************************************************/ + +static int motTreeCallBranchCloseCb(Ihandle* ih, Widget wItem) +{ + IFni cbBranchClose = (IFni)IupGetCallback(ih, "BRANCHCLOSE_CB"); + + if(cbBranchClose) + return cbBranchClose(ih, motTreeGetNodeId(ih, wItem)); + + return IUP_DEFAULT; +} + +static int motTreeCallBranchOpenCb(Ihandle* ih, Widget wItem) +{ + IFni cbBranchOpen; + + if (iupAttribGet(ih, "_IUP_IGNORE_BRANCHOPEN")) + { + iupAttribSetStr(ih, "_IUP_IGNORE_BRANCHOPEN", NULL); + return IUP_DEFAULT; + } + + cbBranchOpen = (IFni)IupGetCallback(ih, "BRANCHOPEN_CB"); + if (cbBranchOpen) + return cbBranchOpen(ih, motTreeGetNodeId(ih, wItem)); + + return IUP_DEFAULT; +} + +static void motTreeCallMultiSelectionCb(Ihandle* ih) +{ + IFnIi cbMulti = (IFnIi)IupGetCallback(ih, "MULTISELECTION_CB"); + IFnii cbSelec = (IFnii)IupGetCallback(ih, "SELECTION_CB"); + WidgetList wSelectedItemList = NULL; + Widget wRoot; + int countItems; + + wRoot = (Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM"); + + XtVaGetValues(ih->handle, XmNselectedObjects, &wSelectedItemList, + XmNselectedObjectCount, &countItems, NULL); + if (countItems == 0) + return; + + if (cbMulti || cbSelec) + { + int* id_rowItem = malloc(sizeof(int) * countItems); + int i = 0; + + for(i = 0; i < countItems; i++) + id_rowItem[i] = motTreeGetNodeId(ih, wSelectedItemList[i]); + + if (cbMulti) + cbMulti(ih, id_rowItem, countItems); + else + { + for (i=0; ihandle, (Position)x, (Position)y); + if (wItem) + return motTreeGetNodeId(ih, wItem); + return -1; +} + +static void motTreeCallRightClickCb(Ihandle* ih, int x, int y) +{ + IFni cbRightClick = (IFni)IupGetCallback(ih, "RIGHTCLICK_CB"); + if (cbRightClick) + { + int id = motTreeConvertXYToPos(ih, x, y); + if (id != -1) + cbRightClick(ih, id); + } +} + +static void motTreeCallRenameCb(Ihandle* ih) +{ + IFnis cbRename; + Widget wItem, wEdit; + int ignore = 0; + String title = NULL; + + wItem = (Widget)iupAttribGet(ih, "_IUPTREE_SELECTED"); + wEdit = (Widget)iupAttribGet(ih, "_IUPTREE_EDITFIELD"); + + XtVaGetValues((Widget)iupAttribGet(ih, "_IUPTREE_EDITFIELD"), XmNvalue, &title, NULL); + + cbRename = (IFnis)IupGetCallback(ih, "RENAME_CB"); + if (cbRename) + { + if (cbRename(ih, motTreeGetNodeId(ih, wItem), title) == IUP_IGNORE) + ignore = 1; + } + + if (!ignore) + iupmotSetString(wItem, XmNlabelString, title); + + XtDestroyWidget(wEdit); + + iupAttribSetStr(ih, "_IUPTREE_EDITFIELD", NULL); + iupAttribSetStr(ih, "_IUPTREE_SELECTED", NULL); +} + +static int motTreeCallDragDropCb(Ihandle* ih, Widget wItemDrag, Widget wItemDrop, int *is_ctrl) +{ + IFniiii cbDragDrop = (IFniiii)IupGetCallback(ih, "DRAGDROP_CB"); + int is_shift = 0; + char key[5]; + iupdrvGetKeyState(key); + if (key[0] == 'S') + is_shift = 1; + if (key[1] == 'C') + *is_ctrl = 1; + else + *is_ctrl = 0; + + if (cbDragDrop) + { + int drag_id = motTreeGetNodeId(ih, wItemDrag); + int drop_id = motTreeGetNodeId(ih, wItemDrop); + return cbDragDrop(ih, drag_id, drop_id, is_shift, *is_ctrl); + } + + return IUP_CONTINUE; /* allow to move by default if callback not defined */ +} + +static void motTreeEditFocusChangeEvent(Widget w, Ihandle *ih, XEvent *evt, Boolean *cont) +{ + if (evt->type == FocusOut) + motTreeCallRenameCb(ih); + + (void)cont; + (void)w; +} + +static void motTreeEditKeyPressEvent(Widget w, Ihandle *ih, XKeyEvent *evt, Boolean *cont) +{ + KeySym motcode = XKeycodeToKeysym(iupmot_display, evt->keycode, 0); + if (motcode == XK_Return) + { + Widget wItem = (Widget)iupAttribGet(ih, "_IUPTREE_SELECTED"); + motTreeCallRenameCb(ih); + motTreeSetFocusNode(ih, wItem); + } + else if (motcode == XK_Escape) + { + Widget wEdit = (Widget)iupAttribGet(ih, "_IUPTREE_EDITFIELD"); + Widget wItem = (Widget)iupAttribGet(ih, "_IUPTREE_SELECTED"); + + XtDestroyWidget(wEdit); + motTreeSetFocusNode(ih, wItem); + + iupAttribSetStr(ih, "_IUPTREE_EDITFIELD", NULL); + iupAttribSetStr(ih, "_IUPTREE_SELECTED", NULL); + } + + (void)cont; + (void)w; +} + +static void motTreeScrollbarOffset(Widget sb_win, Position *x, Position *y) +{ + Widget sb_horiz, sb_vert; + XtVaGetValues(sb_win, XmNhorizontalScrollBar, &sb_horiz, NULL); + if (sb_horiz) + { + int pos; + XtVaGetValues(sb_horiz, XmNvalue, &pos, NULL); + *x = *x - (Position)pos; + } + XtVaGetValues(sb_win, XmNverticalScrollBar, &sb_vert, NULL); + if (sb_vert) + { + int pos; + XtVaGetValues(sb_vert, XmNvalue, &pos, NULL); + *y = *y - (Position)pos; + } +} + +static void motTreeShowEditField(Ihandle* ih, Widget wItem) +{ + int num_args = 0, w_img = 0; + Arg args[30]; + Position x, y; + Dimension w, h; + char* child_id = iupDialogGetChildIdStr(ih); + Widget cbEdit; + XmString title; + char* value; + Pixel color; + Pixmap image = XmUNSPECIFIED_PIXMAP; + XmFontList fontlist; + Widget sb_win = (Widget)iupAttribGet(ih, "_IUP_EXTRAPARENT"); + + XtVaGetValues(wItem, XmNx, &x, + XmNy, &y, + XmNwidth, &w, + XmNheight, &h, + XmNlabelString, &title, + XmNsmallIconPixmap, &image, + XmNforeground, &color, + XmNrenderTable, &fontlist, + NULL); + + motTreeScrollbarOffset(sb_win, &x, &y); + iupdrvImageGetInfo((void*)image, &w_img, NULL, NULL); + w_img += 3; /* add some room for borders */ + + iupmotSetArg(args, num_args, XmNx, x+w_img); /* x-position */ + iupmotSetArg(args, num_args, XmNy, y); /* y-position */ + iupmotSetArg(args, num_args, XmNwidth, w-w_img); /* default width to avoid 0 */ + iupmotSetArg(args, num_args, XmNheight, h); /* default height to avoid 0 */ + iupmotSetArg(args, num_args, XmNmarginHeight, ih->data->spacing); /* default padding */ + iupmotSetArg(args, num_args, XmNmarginWidth, 0); + iupmotSetArg(args, num_args, XmNforeground, color); + iupmotSetArg(args, num_args, XmNrenderTable, fontlist); + iupmotSetArg(args, num_args, XmNvalue, iupmotConvertString(title)); + iupmotSetArg(args, num_args, XmNtraversalOn, True); + + cbEdit = XtCreateManagedWidget( + child_id, /* child identifier */ + xmTextWidgetClass, /* widget class */ + sb_win, + args, num_args); + + /* Disable Drag Source */ + iupmotDisableDragSource(cbEdit); + + XtAddEventHandler(cbEdit, EnterWindowMask, False, (XtEventHandler)iupmotEnterLeaveWindowEvent, (XtPointer)ih); + XtAddEventHandler(cbEdit, LeaveWindowMask, False, (XtEventHandler)iupmotEnterLeaveWindowEvent, (XtPointer)ih); + XtAddEventHandler(cbEdit, FocusChangeMask, False, (XtEventHandler)motTreeEditFocusChangeEvent, (XtPointer)ih); + XtAddEventHandler(cbEdit, KeyPressMask, False, (XtEventHandler)motTreeEditKeyPressEvent, (XtPointer)ih); + + iupAttribSetStr(ih, "_IUPTREE_SELECTED", (char*)wItem); + iupAttribSetStr(ih, "_IUPTREE_EDITFIELD", (char*)cbEdit); + + XmProcessTraversal(cbEdit, XmTRAVERSE_CURRENT); + + XmTextSetSelection(cbEdit, (XmTextPosition)0, (XmTextPosition)XmTextGetLastPosition(cbEdit), CurrentTime); + + value = iupAttribGetStr(ih, "RENAMECARET"); + if (value) + motTreeSetRenameCaretPos(cbEdit, value); + + value = iupAttribGetStr(ih, "RENAMESELECTION"); + if (value) + motTreeSetRenameSelectionPos(cbEdit, value); + + /* the parents callbacks can be called while editing + so we must avoid their processing if _IUPTREE_EDITFIELD is defined. */ +} + +static void motTreeSelectionCallback(Widget w, Ihandle* ih, XmContainerSelectCallbackStruct *nptr) +{ + IFnii cbSelec; + int is_ctrl = 0; + (void)w; + (void)nptr; + +printf("SelectionCallback(%d)\n", nptr->selected_item_count); + + if (ih->data->mark_mode == ITREE_MARK_MULTIPLE) + { + char key[5]; + iupdrvGetKeyState(key); + if (key[0] == 'S') + return; + else if (key[1] == 'C') + is_ctrl = 1; + + if (nptr->selected_item_count>1 && !is_ctrl) + { + if (IupGetCallback(ih, "MULTISELECTION_CB")) + { + if (nptr->auto_selection_type==XmAUTO_NO_CHANGE) + motTreeCallMultiSelectionCb(ih); + } + else + { + if (nptr->auto_selection_type==XmAUTO_MOTION) + motTreeCallMultiSelectionCb(ih); + } + return; + } + } + + cbSelec = (IFnii)IupGetCallback(ih, "SELECTION_CB"); + if (cbSelec) + { + Widget wItemFocus = motTreeGetFocusNode(ih); + int curpos = motTreeGetNodeId(ih, wItemFocus); + if (is_ctrl) + { + unsigned char isSelected; + XtVaGetValues(wItemFocus, XmNvisualEmphasis, &isSelected, NULL); + cbSelec(ih, curpos, isSelected == XmSELECTED? 1: 0); + } + else + { + int oldpos = iupAttribGetInt(ih, "_IUPTREE_OLDVALUE"); + if (oldpos != curpos) + { + cbSelec(ih, oldpos, 0); /* unselected */ + cbSelec(ih, curpos, 1); /* selected */ + + iupAttribSetInt(ih, "_IUPTREE_OLDVALUE", curpos); + } + } + } +} + +static void motTreeDefaultActionCallback(Widget w, Ihandle* ih, XmContainerSelectCallbackStruct *nptr) +{ + unsigned char itemState; + WidgetList wSelectedItemList = NULL; + int countItems; + motTreeItemData *itemData; + Widget wItem; + (void)w; + + wSelectedItemList = nptr->selected_items; + countItems = nptr->selected_item_count; + + if (!countItems || (Widget)iupAttribGet(ih, "_IUPTREE_EDITFIELD")) + return; + + /* this works also when using multiple selection */ + wItem = wSelectedItemList[0]; + + XtVaGetValues(wItem, XmNoutlineState, &itemState, + XmNuserData, &itemData, NULL); + + if (itemData->kind == ITREE_BRANCH) + { + if (itemState == XmEXPANDED) + XtVaSetValues(wItem, XmNoutlineState, XmCOLLAPSED, NULL); + else + XtVaSetValues(wItem, XmNoutlineState, XmEXPANDED, NULL); + } + else + { + IFni cbExecuteLeaf = (IFni)IupGetCallback(ih, "EXECUTELEAF_CB"); + if (cbExecuteLeaf) + cbExecuteLeaf(ih, motTreeGetNodeId(ih, wItem)); + } +} + +static void motTreeOutlineChangedCallback(Widget w, Ihandle* ih, XmContainerOutlineCallbackStruct *nptr) +{ + motTreeItemData *itemData; + XtVaGetValues(nptr->item, XmNuserData, &itemData, NULL); + + if (nptr->reason == XmCR_EXPANDED) + { + if (motTreeCallBranchOpenCb(ih, nptr->item) == IUP_IGNORE) + nptr->new_outline_state = XmCOLLAPSED; /* prevent the change */ + else + { + XtVaSetValues(nptr->item, XmNsmallIconPixmap, (itemData->image_expanded!=XmUNSPECIFIED_PIXMAP)? itemData->image_expanded: (Pixmap)ih->data->def_image_expanded, NULL); + XtVaSetValues(nptr->item, XmNsmallIconMask, (itemData->image_expanded_mask!=XmUNSPECIFIED_PIXMAP)? itemData->image_expanded_mask: (Pixmap)ih->data->def_image_expanded_mask, NULL); + } + } + else if (nptr->reason == XmCR_COLLAPSED) + { + if (motTreeCallBranchCloseCb(ih, nptr->item) == IUP_IGNORE) + nptr->new_outline_state = XmEXPANDED; /* prevent the change */ + else + { + XtVaSetValues(nptr->item, XmNsmallIconPixmap, (itemData->image!=XmUNSPECIFIED_PIXMAP)? itemData->image: (Pixmap)ih->data->def_image_collapsed, NULL); + XtVaSetValues(nptr->item, XmNsmallIconMask, (itemData->image_mask!=XmUNSPECIFIED_PIXMAP)? itemData->image_mask: (Pixmap)ih->data->def_image_collapsed_mask, NULL); + } + } + + (void)w; +} + +static void motTreeTraverseObscuredCallback(Widget widget, Ihandle* ih, XmTraverseObscuredCallbackStruct *cbs) +{ + (void)ih; + /* allow to do automatic scroll when navigating in the tree */ + XmScrollVisible(widget, cbs->traversal_destination, 10, 10); +} + +static void motTreeKeyReleaseEvent(Widget w, Ihandle *ih, XKeyEvent *evt, Boolean *cont) +{ + KeySym motcode; + + if (iupAttribGet(ih, "_IUPTREE_EDITFIELD")) + return; + + motcode = XKeycodeToKeysym(iupmot_display, evt->keycode, 0); + if (motcode == XK_Down || motcode == XK_U || motcode == XK_Home || motcode == XK_End) + { + if (ih->data->mark_mode==ITREE_MARK_MULTIPLE && (evt->state & ShiftMask)) + motTreeCallMultiSelectionCb(ih); + } + + (void)w; + (void)cont; +} + +static void motTreeKeyPressEvent(Widget w, Ihandle *ih, XKeyEvent *evt, Boolean *cont) +{ + KeySym motcode; + + if (iupAttribGet(ih, "_IUPTREE_EDITFIELD")) + return; + + *cont = True; + iupmotKeyPressEvent(w, ih, (XEvent*)evt, cont); + if (*cont == False) + return; + + motcode = XKeycodeToKeysym(iupmot_display, evt->keycode, 0); + if (motcode == XK_F2) + motTreeSetRenameAttrib(ih, NULL); + else if (motcode == XK_F1) + iupmotHelpCallback(w, ih, NULL); + else if ((motcode == XK_Down || motcode == XK_Up) && (evt->state & ControlMask)) + { + Widget wRoot = (Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM"); + Widget wItem; + Widget wItemFocus = motTreeGetFocusNode(ih); + + /* Ctrl+Arrows move only focus */ + if (motcode == XK_Down) + wItem = motTreeGetNextVisibleNode(ih, wRoot, wItemFocus); + else + wItem = motTreeGetPreviousVisibleNode(ih, wRoot, wItemFocus); + + motTreeSetFocusNode(ih, wItem); + *cont = False; + } + else if(motcode == XK_Home || motcode == XK_End) + { + Widget wRoot = (Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM"); + Widget wItem; + + /* Not processed by Motif */ + + if (motcode == XK_Home) + wItem = wRoot; + else + wItem = motTreeGetLastVisibleNode(ih, wRoot); + + /* Ctrl+Arrows move only focus */ + if (!(evt->state & ControlMask)) + { + /* Shift+Arrows select block */ + if (evt->state & ShiftMask) + { + Widget wItemFocus = motTreeGetFocusNode(ih); + if (!wItemFocus) + return; + motTreeSelectRange(ih, wItemFocus, wItem, 1); + } + else + { + /* clear previous selection */ + XtVaSetValues(ih->handle, XmNselectedObjects, NULL, NULL); + XtVaSetValues(ih->handle, XmNselectedObjectCount, 0, NULL); + + XtVaSetValues(wItem, XmNvisualEmphasis, XmSELECTED, NULL); + } + } + + motTreeSetFocusNode(ih, wItem); + *cont = False; + } + else if(motcode == XK_space && (evt->state & ControlMask)) + { + Widget wItemFocus = motTreeGetFocusNode(ih); + if (wItemFocus) + { + unsigned char isSelected; + XtVaGetValues(wItemFocus, XmNvisualEmphasis, &isSelected, NULL); + if (isSelected == XmSELECTED) + XtVaSetValues(wItemFocus, XmNvisualEmphasis, XmNOT_SELECTED, NULL); + else + XtVaSetValues(wItemFocus, XmNvisualEmphasis, XmSELECTED, NULL); + } + } +} + +static void motTreeButtonEvent(Widget w, Ihandle* ih, XButtonEvent* evt, Boolean* cont) +{ + (void)w; + (void)cont; + + if (iupAttribGet(ih, "_IUPTREE_EDITFIELD")) + return; + + *cont = True; + iupmotButtonPressReleaseEvent(w, ih, (XEvent*)evt, cont); + if (*cont == False) + return; + + if (evt->type==ButtonPress) + { + iupAttribSetStr(ih, "_IUPTREE_IGNORE_ENTERLEAVE", "1"); + + if (evt->button==Button1) + { + Widget wItemFocus = motTreeGetFocusNode(ih); + static Widget wLastItem = NULL; + static Time last = 0; + int clicktwice = 0, doubleclicktime = XtGetMultiClickTime(iupmot_display); + int elapsed = (int)(evt->time - last); + last = evt->time; + + /* stay away from double click and leave some room for clicks */ + if (elapsed > (3*doubleclicktime)/2 && elapsed <= 3*doubleclicktime) + clicktwice = 1; + + if (clicktwice && wLastItem && wLastItem==wItemFocus) + { + motTreeSetRenameAttrib(ih, NULL); + *cont = False; + } + wLastItem = wItemFocus; + } + else if (evt->button==Button3) + motTreeCallRightClickCb(ih, evt->x, evt->y); + } + else if (evt->type==ButtonRelease) + { + if (evt->button==Button1) + { + if (ih->data->mark_mode==ITREE_MARK_MULTIPLE && (evt->state & ShiftMask)) + motTreeCallMultiSelectionCb(ih); + } + } +} + +static void motTreeTransferProc(Widget drop_context, XtPointer client_data, Atom *seltype, Atom *type, XtPointer value, unsigned long *length, int format) +{ + Atom atomTreeItem = XInternAtom(iupmot_display, "TREE_ITEM", False); + Widget wItemDrop = (Widget)client_data; + Widget wItemDrag = (Widget)value; + + if (*type == atomTreeItem) + { + Widget wParent; + Ihandle* ih = NULL; + int is_ctrl; + + if (!wItemDrop || wItemDrag == wItemDrop) + return; + + wParent = wItemDrop; + while(wParent) + { + XtVaGetValues(wParent, XmNentryParent, &wParent, NULL); + if (wParent == wItemDrag) + return; + } + + XtVaGetValues(XtParent(wItemDrag), XmNuserData, &ih, NULL); + + if (motTreeCallDragDropCb(ih, wItemDrag, wItemDrop, &is_ctrl) == IUP_CONTINUE) + { + /* Copy the dragged item to the new position. */ + Widget wNewItem = motTreeCopyNode(ih, wItemDrag, wItemDrop, is_ctrl); + + if (!is_ctrl) + { + /* do not delete the user data, we copy the references in CopyNode */ + motTreeRemoveNode(ih, wItemDrag, 0); + } + + /* Select the dragged item */ + XtVaSetValues(ih->handle, XmNselectedObjects, NULL, NULL); + XtVaSetValues(ih->handle, XmNselectedObjectCount, 0, NULL); + XtVaSetValues(wNewItem, XmNvisualEmphasis, XmSELECTED, NULL); + + motTreeSetFocusNode(ih, wNewItem); + } + } + + (void)drop_context; + (void)seltype; + (void)format; + (void)length; +} + +static void motTreeDropProc(Widget w, XtPointer client_data, XmDropProcCallbackStruct* drop_data) +{ + Atom atomTreeItem = XInternAtom(iupmot_display, "TREE_ITEM", False); + XmDropTransferEntryRec transferList[2]; + Arg args[10]; + int i, num_args = 0; + Widget wItemDrop, drop_context; + Cardinal numExportTargets; + Atom *exportTargets; + Boolean found = False; + (void)client_data; + + drop_context = drop_data->dragContext; + + /* retrieve the data targets */ + iupmotSetArg(args, num_args, XmNexportTargets, &exportTargets); + iupmotSetArg(args, num_args, XmNnumExportTargets, &numExportTargets); + XtGetValues(drop_context, args, num_args); + + for (i = 0; i < (int)numExportTargets; i++) + { + if (exportTargets[i] == atomTreeItem) + { + found = True; + break; + } + } + + wItemDrop = XmObjectAtPoint(w, drop_data->x, drop_data->y); + if (!wItemDrop) + found = False; + + num_args = 0; + if ((!found) || (drop_data->dropAction != XmDROP) || (drop_data->operation != XmDROP_COPY && drop_data->operation != XmDROP_MOVE)) + { + iupmotSetArg(args, num_args, XmNtransferStatus, XmTRANSFER_FAILURE); + iupmotSetArg(args, num_args, XmNnumDropTransfers, 0); + } + else + { + /* set up transfer requests for drop site */ + transferList[0].target = atomTreeItem; + transferList[0].client_data = (XtPointer)wItemDrop; + iupmotSetArg(args, num_args, XmNdropTransfers, transferList); + iupmotSetArg(args, num_args, XmNnumDropTransfers, 1); + iupmotSetArg(args, num_args, XmNtransferProc, motTreeTransferProc); + } + + XmDropTransferStart(drop_context, args, num_args); +} + +static void motTreeDragDropFinishCallback(Widget drop_context, XtPointer client_data, XtPointer call_data) +{ + Widget source_icon = NULL; + XtVaGetValues(drop_context, XmNsourceCursorIcon, &source_icon, NULL); + if (source_icon) + XtDestroyWidget(source_icon); + (void)call_data; + (void)client_data; +} + +static void motTreeDragMotionCallback(Widget drop_context, Widget wItemDrag, XmDragMotionCallbackStruct* drag_motion) +{ + Ihandle* ih = NULL; + XtVaGetValues(XtParent(wItemDrag), XmNuserData, &ih, NULL); + if (!iupAttribGet(ih, "NODRAGFEEDBACK")) + { + Widget wItem; + int x = drag_motion->x; + int y = drag_motion->y; + iupdrvScreenToClient(ih, &x, &y); + wItem = XmObjectAtPoint(ih->handle, (Position)x, (Position)y); + if (wItem) + { + XtVaSetValues(ih->handle, XmNselectedObjects, NULL, NULL); + XtVaSetValues(ih->handle, XmNselectedObjectCount, 0, NULL); + XtVaSetValues(wItem, XmNvisualEmphasis, XmSELECTED, NULL); + } + } + (void)drop_context; +} + +static Boolean motTreeConvertProc(Widget drop_context, Atom *selection, Atom *target, Atom *type_return, + XtPointer *value_return, unsigned long *length_return, int *format_return) +{ + Atom atomMotifDrop = XInternAtom(iupmot_display, "_MOTIF_DROP", False); + Atom atomTreeItem = XInternAtom(iupmot_display, "TREE_ITEM", False); + Widget wItemDrag = NULL; + + /* check if we are dealing with a drop */ + if (*selection != atomMotifDrop || *target != atomTreeItem) + return False; + + XtVaGetValues(drop_context, XmNclientData, &wItemDrag, NULL); + if (!wItemDrag) + return False; + + /* format the value for transfer */ + *type_return = atomTreeItem; + *value_return = (XtPointer)wItemDrag; + *length_return = 1; + *format_return = 32; + return True; +} + +static void motTreeStartDrag(Widget w, XButtonEvent* evt, String* params, Cardinal* num_params) +{ + Atom atomTreeItem = XInternAtom(iupmot_display, "TREE_ITEM", False); + Atom exportList[1]; + Widget drag_icon, drop_context; + Pixmap pixmap = 0, mask = 0; + int num_args = 0; + Arg args[40]; + Pixel fg, bg; + Widget wItemDrag = XmObjectAtPoint(w, (Position)evt->x, (Position)evt->y); + if (!wItemDrag) + return; + + XtVaGetValues(wItemDrag, XmNsmallIconPixmap, &pixmap, + XmNsmallIconMask, &mask, + XmNbackground, &bg, + XmNforeground, &fg, + NULL); + + iupmotSetArg(args, num_args, XmNpixmap, pixmap); + iupmotSetArg(args, num_args, XmNmask, mask); + drag_icon = XmCreateDragIcon(w, "drag_icon", args, num_args); + + exportList[0] = atomTreeItem; + + /* specify resources for DragContext for the transfer */ + num_args = 0; + iupmotSetArg(args, num_args, XmNcursorBackground, bg); + iupmotSetArg(args, num_args, XmNcursorForeground, fg); + /* iupmotSetArg(args, num_args, XmNsourcePixmapIcon, drag_icon); works, but only outside the dialog, inside disapears */ + iupmotSetArg(args, num_args, XmNsourceCursorIcon, drag_icon); /* does not work, shows the default cursor */ + iupmotSetArg(args, num_args, XmNexportTargets, exportList); + iupmotSetArg(args, num_args, XmNnumExportTargets, 1); + iupmotSetArg(args, num_args, XmNdragOperations, XmDROP_MOVE|XmDROP_COPY); + iupmotSetArg(args, num_args, XmNconvertProc, motTreeConvertProc); + iupmotSetArg(args, num_args, XmNclientData, wItemDrag); + + /* start the drag and register a callback to clean up when done */ + drop_context = XmDragStart(w, (XEvent*)evt, args, num_args); + XtAddCallback(drop_context, XmNdragDropFinishCallback, (XtCallbackProc)motTreeDragDropFinishCallback, NULL); + XtAddCallback(drop_context, XmNdragMotionCallback, (XtCallbackProc)motTreeDragMotionCallback, (XtPointer)wItemDrag); + + (void)params; + (void)num_params; +} + +static void motTreeEnableDragDrop(Widget w) +{ + Atom atomTreeItem = XInternAtom(iupmot_display, "TREE_ITEM", False); + Atom importList[1]; + Arg args[40]; + int num_args = 0; + char dragTranslations[] = "#override : StartDrag()"; + static int do_rec = 0; + if (!do_rec) + { + XtActionsRec rec = {"StartDrag", (XtActionProc)motTreeStartDrag}; + XtAppAddActions(iupmot_appcontext, &rec, 1); + do_rec = 1; + } + XtOverrideTranslations(w, XtParseTranslationTable(dragTranslations)); + + importList[0] = atomTreeItem; + iupmotSetArg(args, num_args, XmNimportTargets, importList); + iupmotSetArg(args, num_args, XmNnumImportTargets, 1); + iupmotSetArg(args, num_args, XmNdropSiteOperations, XmDROP_MOVE|XmDROP_COPY); + iupmotSetArg(args, num_args, XmNdropProc, motTreeDropProc); + XmDropSiteUpdate(w, args, num_args); + + XtVaSetValues(XmGetXmDisplay(iupmot_display), XmNenableDragIcon, True, NULL); +} + +static int motTreeMapMethod(Ihandle* ih) +{ + int num_args = 0; + Arg args[40]; + Widget parent = iupChildTreeGetNativeParentHandle(ih); + char* child_id = iupDialogGetChildIdStr(ih); + Widget sb_win; + + /******************************/ + /* Create the scrolled window */ + /******************************/ + iupmotSetArg(args, num_args, XmNmappedWhenManaged, False); /* not visible when managed */ + iupmotSetArg(args, num_args, XmNscrollingPolicy, XmAUTOMATIC); + iupmotSetArg(args, num_args, XmNvisualPolicy, XmVARIABLE); + iupmotSetArg(args, num_args, XmNscrollBarDisplayPolicy, XmAS_NEEDED); + iupmotSetArg(args, num_args, XmNspacing, 0); /* no space between scrollbars and text */ + iupmotSetArg(args, num_args, XmNborderWidth, 0); + iupmotSetArg(args, num_args, XmNshadowThickness, 2); + + sb_win = XtCreateManagedWidget( + child_id, /* child identifier */ + xmScrolledWindowWidgetClass, /* widget class */ + parent, /* widget parent */ + args, num_args); + + if (!sb_win) + return IUP_ERROR; + + XtAddCallback (sb_win, XmNtraverseObscuredCallback, (XtCallbackProc)motTreeTraverseObscuredCallback, (XtPointer)ih); + + parent = sb_win; + child_id = "container"; + + num_args = 0; + + iupmotSetArg(args, num_args, XmNx, 0); /* x-position */ + iupmotSetArg(args, num_args, XmNy, 0); /* y-position */ + iupmotSetArg(args, num_args, XmNwidth, 10); /* default width to avoid 0 */ + iupmotSetArg(args, num_args, XmNheight, 10); /* default height to avoid 0 */ + + iupmotSetArg(args, num_args, XmNmarginHeight, 0); /* default padding */ + iupmotSetArg(args, num_args, XmNmarginWidth, 0); + + if (iupAttribGetBoolean(ih, "CANFOCUS")) + iupmotSetArg(args, num_args, XmNtraversalOn, True); + else + iupmotSetArg(args, num_args, XmNtraversalOn, False); + + iupmotSetArg(args, num_args, XmNnavigationType, XmTAB_GROUP); + iupmotSetArg(args, num_args, XmNhighlightThickness, 2); + iupmotSetArg(args, num_args, XmNshadowThickness, 0); + + iupmotSetArg(args, num_args, XmNlayoutType, XmOUTLINE); + iupmotSetArg(args, num_args, XmNentryViewType, XmSMALL_ICON); + iupmotSetArg(args, num_args, XmNselectionPolicy, XmSINGLE_SELECT); + iupmotSetArg(args, num_args, XmNoutlineIndentation, 20); + + if (iupAttribGetBoolean(ih, "HIDELINES")) + iupmotSetArg(args, num_args, XmNoutlineLineStyle, XmNO_LINE); + else + iupmotSetArg(args, num_args, XmNoutlineLineStyle, XmSINGLE); + + if (iupAttribGetBoolean(ih, "HIDEBUTTONS")) + iupmotSetArg(args, num_args, XmNoutlineButtonPolicy, XmOUTLINE_BUTTON_ABSENT); + else + iupmotSetArg(args, num_args, XmNoutlineButtonPolicy, XmOUTLINE_BUTTON_PRESENT); + + ih->handle = XtCreateManagedWidget( + child_id, /* child identifier */ + xmContainerWidgetClass, /* widget class */ + parent, /* widget parent */ + args, num_args); + + if (!ih->handle) + return IUP_ERROR; + + ih->serial = iupDialogGetChildId(ih); /* must be after using the string */ + + iupAttribSetStr(ih, "_IUP_EXTRAPARENT", (char*)parent); + + XtAddEventHandler(ih->handle, EnterWindowMask, False, (XtEventHandler)motTreeEnterLeaveWindowEvent, (XtPointer)ih); + XtAddEventHandler(ih->handle, LeaveWindowMask, False, (XtEventHandler)motTreeEnterLeaveWindowEvent, (XtPointer)ih); + XtAddEventHandler(ih->handle, FocusChangeMask, False, (XtEventHandler)motTreeFocusChangeEvent, (XtPointer)ih); + XtAddEventHandler(ih->handle, KeyPressMask, False, (XtEventHandler)motTreeKeyPressEvent, (XtPointer)ih); + XtAddEventHandler(ih->handle, KeyReleaseMask, False, (XtEventHandler)motTreeKeyReleaseEvent, (XtPointer)ih); + XtAddEventHandler(ih->handle, ButtonPressMask|ButtonReleaseMask, False, (XtEventHandler)motTreeButtonEvent, (XtPointer)ih); + XtAddEventHandler(ih->handle, PointerMotionMask, False, (XtEventHandler)iupmotPointerMotionEvent, (XtPointer)ih); + + /* Callbacks */ + /* XtAddCallback(ih->handle, XmNhelpCallback, (XtCallbackProc)iupmotHelpCallback, (XtPointer)ih); NOT WORKING */ + XtAddCallback(ih->handle, XmNoutlineChangedCallback, (XtCallbackProc)motTreeOutlineChangedCallback, (XtPointer)ih); + XtAddCallback(ih->handle, XmNdefaultActionCallback, (XtCallbackProc)motTreeDefaultActionCallback, (XtPointer)ih); + XtAddCallback(ih->handle, XmNselectionCallback, (XtCallbackProc)motTreeSelectionCallback, (XtPointer)ih); + + XtRealizeWidget(parent); + + if (ih->data->show_dragdrop) + { + motTreeEnableDragDrop(ih->handle); + XtVaSetValues(ih->handle, XmNuserData, ih, NULL); /* to be used in motTreeTransferProc */ + } + else + iupmotDisableDragSource(ih->handle); + + /* Force background update before setting the images */ + { + char* value = iupAttribGet(ih, "BGCOLOR"); + if (value) + { + motTreeSetBgColorAttrib(ih, value); + iupAttribSetStr(ih, "BGCOLOR", NULL); + } + } + + /* Initialize the default images */ + ih->data->def_image_leaf = iupImageGetImage("IMGLEAF", ih, 0); + if (!ih->data->def_image_leaf) + { + ih->data->def_image_leaf = (void*)XmUNSPECIFIED_PIXMAP; + ih->data->def_image_leaf_mask = (void*)XmUNSPECIFIED_PIXMAP; + } + else + { + ih->data->def_image_leaf_mask = iupImageGetMask("IMGLEAF"); + if (!ih->data->def_image_leaf_mask) ih->data->def_image_leaf_mask = (void*)XmUNSPECIFIED_PIXMAP; + } + + ih->data->def_image_collapsed = iupImageGetImage("IMGCOLLAPSED", ih, 0); + if (!ih->data->def_image_collapsed) + { + ih->data->def_image_collapsed = (void*)XmUNSPECIFIED_PIXMAP; + ih->data->def_image_collapsed_mask = (void*)XmUNSPECIFIED_PIXMAP; + } + else + { + ih->data->def_image_collapsed_mask = iupImageGetMask("IMGCOLLAPSED"); + if (!ih->data->def_image_collapsed_mask) ih->data->def_image_collapsed_mask = (void*)XmUNSPECIFIED_PIXMAP; + } + + ih->data->def_image_expanded = iupImageGetImage("IMGEXPANDED", ih, 0); + if (!ih->data->def_image_expanded) + { + ih->data->def_image_expanded = (void*)XmUNSPECIFIED_PIXMAP; + ih->data->def_image_expanded_mask = (void*)XmUNSPECIFIED_PIXMAP; + } + else + { + ih->data->def_image_expanded_mask = iupImageGetMask("IMGEXPANDED"); + if (!ih->data->def_image_expanded_mask) ih->data->def_image_expanded_mask = (void*)XmUNSPECIFIED_PIXMAP; + } + + motTreeAddRootNode(ih); + + IupSetCallback(ih, "_IUP_XY2POS_CB", (Icallback)motTreeConvertXYToPos); + + return IUP_NOERROR; +} + +void iupdrvTreeInitClass(Iclass* ic) +{ + /* Driver Dependent Class functions */ + ic->Map = motTreeMapMethod; + + /* Visual */ + iupClassRegisterAttribute(ic, "BGCOLOR", NULL, motTreeSetBgColorAttrib, "TXTBGCOLOR", NULL, IUPAF_DEFAULT); + iupClassRegisterAttribute(ic, "FGCOLOR", NULL, motTreeSetFgColorAttrib, IUPAF_SAMEASSYSTEM, "TXTFGCOLOR", IUPAF_DEFAULT); + + /* IupTree Attributes - GENERAL */ + iupClassRegisterAttribute(ic, "EXPANDALL", NULL, motTreeSetExpandAllAttrib, NULL, NULL, IUPAF_WRITEONLY||IUPAF_NO_INHERIT); + iupClassRegisterAttribute(ic, "INDENTATION", motTreeGetIndentationAttrib, motTreeSetIndentationAttrib, NULL, NULL, IUPAF_DEFAULT); + iupClassRegisterAttribute(ic, "COUNT", motTreeGetCountAttrib, NULL, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_READONLY|IUPAF_NO_INHERIT); + iupClassRegisterAttribute(ic, "SPACING", iupTreeGetSpacingAttrib, motTreeSetSpacingAttrib, NULL, NULL, IUPAF_NOT_MAPPED); + iupClassRegisterAttribute(ic, "TOPITEM", NULL, motTreeSetTopItemAttrib, NULL, NULL, IUPAF_WRITEONLY|IUPAF_NO_INHERIT); + + /* IupTree Attributes - IMAGES */ + iupClassRegisterAttributeId(ic, "IMAGE", NULL, motTreeSetImageAttrib, IUPAF_WRITEONLY|IUPAF_NO_INHERIT); + iupClassRegisterAttributeId(ic, "IMAGEEXPANDED", NULL, motTreeSetImageExpandedAttrib, IUPAF_WRITEONLY|IUPAF_NO_INHERIT); + + iupClassRegisterAttribute(ic, "IMAGELEAF", NULL, motTreeSetImageLeafAttrib, IUPAF_SAMEASSYSTEM, "IMGLEAF", IUPAF_NO_INHERIT); + iupClassRegisterAttribute(ic, "IMAGEBRANCHCOLLAPSED", NULL, motTreeSetImageBranchCollapsedAttrib, IUPAF_SAMEASSYSTEM, "IMGCOLLAPSED", IUPAF_NO_INHERIT); + iupClassRegisterAttribute(ic, "IMAGEBRANCHEXPANDED", NULL, motTreeSetImageBranchExpandedAttrib, IUPAF_SAMEASSYSTEM, "IMGEXPANDED", IUPAF_NO_INHERIT); + + /* IupTree Attributes - NODES */ + iupClassRegisterAttributeId(ic, "STATE", motTreeGetStateAttrib, motTreeSetStateAttrib, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT); + iupClassRegisterAttributeId(ic, "DEPTH", motTreeGetDepthAttrib, NULL, IUPAF_READONLY|IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT); + iupClassRegisterAttributeId(ic, "KIND", motTreeGetKindAttrib, NULL, IUPAF_READONLY|IUPAF_NO_INHERIT); + iupClassRegisterAttributeId(ic, "PARENT", motTreeGetParentAttrib, NULL, IUPAF_READONLY|IUPAF_NO_INHERIT); + iupClassRegisterAttributeId(ic, "COLOR", motTreeGetColorAttrib, motTreeSetColorAttrib, IUPAF_NO_INHERIT); + iupClassRegisterAttributeId(ic, "NAME", motTreeGetTitleAttrib, motTreeSetTitleAttrib, IUPAF_NO_INHERIT); + iupClassRegisterAttributeId(ic, "TITLE", motTreeGetTitleAttrib, motTreeSetTitleAttrib, IUPAF_NO_INHERIT); + iupClassRegisterAttributeId(ic, "USERDATA", motTreeGetUserDataAttrib, motTreeSetUserDataAttrib, IUPAF_NO_STRING|IUPAF_NO_INHERIT); + iupClassRegisterAttributeId(ic, "CHILDCOUNT", motTreeGetChildCountAttrib, NULL, IUPAF_READONLY|IUPAF_NO_INHERIT); + iupClassRegisterAttributeId(ic, "TITLEFONT", motTreeGetTitleFontAttrib, motTreeSetTitleFontAttrib, IUPAF_NO_INHERIT); + + /* IupTree Attributes - MARKS */ + iupClassRegisterAttributeId(ic, "MARKED", motTreeGetMarkedAttrib, motTreeSetMarkedAttrib, IUPAF_NO_INHERIT); + iupClassRegisterAttribute (ic, "MARK", NULL, motTreeSetMarkAttrib, NULL, NULL, IUPAF_WRITEONLY|IUPAF_NO_INHERIT); + iupClassRegisterAttribute (ic, "STARTING", NULL, motTreeSetMarkStartAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT); + iupClassRegisterAttribute (ic, "MARKSTART", NULL, motTreeSetMarkStartAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT); + + iupClassRegisterAttribute (ic, "VALUE", motTreeGetValueAttrib, motTreeSetValueAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT); + + /* IupTree Attributes - ACTION */ + iupClassRegisterAttributeId(ic, "DELNODE", NULL, motTreeSetDelNodeAttrib, IUPAF_NOT_MAPPED|IUPAF_WRITEONLY|IUPAF_NO_INHERIT); + iupClassRegisterAttribute(ic, "RENAME", NULL, motTreeSetRenameAttrib, NULL, NULL, IUPAF_WRITEONLY|IUPAF_NO_INHERIT); + iupClassRegisterAttributeId(ic, "MOVENODE", NULL, motTreeSetMoveNodeAttrib, IUPAF_NOT_MAPPED|IUPAF_WRITEONLY|IUPAF_NO_INHERIT); + iupClassRegisterAttributeId(ic, "COPYNODE", NULL, motTreeSetCopyNodeAttrib, IUPAF_NOT_MAPPED|IUPAF_WRITEONLY|IUPAF_NO_INHERIT); + iupClassRegisterAttributeId(ic, "FINDUSERDATA", motTreeGetFindUserDataAttrib, NULL, IUPAF_READONLY|IUPAF_NO_INHERIT); +} -- cgit v1.2.3