#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); }