diff options
author | Pixel <pixel@nobis-crew.org> | 2010-06-15 00:59:57 -0700 |
---|---|---|
committer | Pixel <pixel@nobis-crew.org> | 2010-06-15 00:59:57 -0700 |
commit | eed0eb6a476d54ce19aeff137984aa981d9e3976 (patch) | |
tree | 807891636efd2f87dcbd261e971216269973ae07 /iup/src/gtk/iupgtk_tree.c | |
parent | ccc8261e4d48de89da4ddfe7b55e378ae0cd6f47 (diff) |
Upgrading to iup 3.1
Diffstat (limited to 'iup/src/gtk/iupgtk_tree.c')
-rwxr-xr-x | iup/src/gtk/iupgtk_tree.c | 1533 |
1 files changed, 810 insertions, 723 deletions
diff --git a/iup/src/gtk/iupgtk_tree.c b/iup/src/gtk/iupgtk_tree.c index d408f27..9595ada 100755 --- a/iup/src/gtk/iupgtk_tree.c +++ b/iup/src/gtk/iupgtk_tree.c @@ -31,33 +31,50 @@ #include "iup_drvinfo.h" #include "iupgtk_drv.h" + +/* IMPORTANT: + + GtkTreeStore uses the "user_data" field of the GtkTreeIter + to store the node pointer that is position independent. + So we use it as a reference to the node in the cache, just like in Motif and Windows. + + BUT if GTK change its implementation this must be changed also. See "gtk_tree_store.c". + + ABOUT SELECTIONS: + + From the GTK documentation on GtkTreeSelection + + "Additionally, you cannot change the selection of a row on the model + that is not currently displayed by the view without expanding its parents first." +*/ + enum { - IUPGTK_TREE_IMAGE, + IUPGTK_TREE_IMAGE, /* "pixbuf", "pixbuf-expander-closed" */ IUPGTK_TREE_HAS_IMAGE, - IUPGTK_TREE_IMAGE_EXPANDED, + IUPGTK_TREE_IMAGE_EXPANDED, /* "pixbuf-expander-open" */ IUPGTK_TREE_HAS_IMAGE_EXPANDED, - IUPGTK_TREE_TITLE, - IUPGTK_TREE_KIND, - IUPGTK_TREE_COLOR, - IUPGTK_TREE_FONT, - IUPGTK_TREE_USERDATA + IUPGTK_TREE_TITLE, /* "text" */ + IUPGTK_TREE_KIND, /* "is-expander" */ + IUPGTK_TREE_COLOR, /* "foreground-gdk" */ + IUPGTK_TREE_FONT, /* "font-desc" */ + IUPGTK_TREE_SELECT, + IUPGTK_TREE_LAST_DATA /* used as a count */ }; -static GtkTreeIter gtkTreeInvalidIter = {0,0,0,0}; +static void gtkTreeRebuildNodeCache(Ihandle* ih, int id, GtkTreeIter iterItem); /*****************************************************************************/ /* COPYING ITEMS (Branches and its children) */ /*****************************************************************************/ /* Insert the copied item in a new location. Returns the new item. */ -static void gtkTreeCopyItem(GtkTreeModel* model, GtkTreeIter* iterItem, GtkTreeIter* iterParent, int position, GtkTreeIter *iterNewItem, int full_copy) +static void gtkTreeCopyItem(Ihandle* ih, GtkTreeModel* model, GtkTreeIter* iterItem, GtkTreeIter* iterParent, int position, GtkTreeIter *iterNewItem) { GtkTreeStore* store = GTK_TREE_STORE(model); int kind; char* title; gboolean has_image, has_image_expanded; PangoFontDescription* font; - void* userdata; GdkColor *color; GdkPixbuf* image, *image_expanded; @@ -69,9 +86,10 @@ static void gtkTreeCopyItem(GtkTreeModel* model, GtkTreeIter* iterItem, GtkTreeI IUPGTK_TREE_KIND, &kind, IUPGTK_TREE_COLOR, &color, IUPGTK_TREE_FONT, &font, - IUPGTK_TREE_USERDATA, &userdata, -1); + /* Add the new node */ + ih->data->node_count++; if (position == 2) gtk_tree_store_append(store, iterNewItem, iterParent); else if (position == 1) /* copy as first child of expanded branch */ @@ -79,9 +97,6 @@ static void gtkTreeCopyItem(GtkTreeModel* model, GtkTreeIter* iterItem, GtkTreeI else /* copy as next brother of item or collapsed branch */ gtk_tree_store_insert_after(store, iterNewItem, NULL, iterParent); /* iterParent is sibling of the new item */ - if (full_copy) /* during a full copy the userdata reference is not copied */ - userdata = NULL; - gtk_tree_store_set(store, iterNewItem, IUPGTK_TREE_IMAGE, image, IUPGTK_TREE_HAS_IMAGE, has_image, IUPGTK_TREE_IMAGE_EXPANDED, image_expanded, @@ -90,21 +105,21 @@ static void gtkTreeCopyItem(GtkTreeModel* model, GtkTreeIter* iterItem, GtkTreeI IUPGTK_TREE_KIND, kind, IUPGTK_TREE_COLOR, color, IUPGTK_TREE_FONT, font, - IUPGTK_TREE_USERDATA, userdata, + IUPGTK_TREE_SELECT, 0, -1); } -static void gtkTreeCopyChildren(Ihandle* ih, GtkTreeModel* model, GtkTreeIter *iterItemSrc, GtkTreeIter *iterItemDst, int full_copy) +static void gtkTreeCopyChildren(Ihandle* ih, GtkTreeModel* model, GtkTreeIter *iterItemSrc, GtkTreeIter *iterItemDst) { GtkTreeIter iterChildSrc; int hasItem = gtk_tree_model_iter_children(model, &iterChildSrc, iterItemSrc); /* get the firstchild */ while(hasItem) { GtkTreeIter iterNewItem; - gtkTreeCopyItem(model, &iterChildSrc, iterItemDst, 2, &iterNewItem, full_copy); /* append always */ + gtkTreeCopyItem(ih, model, &iterChildSrc, iterItemDst, 2, &iterNewItem); /* append always */ /* Recursively transfer all the items */ - gtkTreeCopyChildren(ih, model, &iterChildSrc, &iterNewItem, full_copy); + gtkTreeCopyChildren(ih, model, &iterChildSrc, &iterNewItem); /* Go to next sibling item */ hasItem = gtk_tree_model_iter_next(model, &iterChildSrc); @@ -112,9 +127,17 @@ static void gtkTreeCopyChildren(Ihandle* ih, GtkTreeModel* model, GtkTreeIter *i } /* Copies all items in a branch to a new location. Returns the new branch node. */ -static void gtkTreeCopyNode(Ihandle* ih, GtkTreeModel* model, GtkTreeIter *iterItemSrc, GtkTreeIter *iterItemDst, GtkTreeIter* iterNewItem, int full_copy) +static void gtkTreeCopyMoveNode(Ihandle* ih, GtkTreeModel* model, GtkTreeIter *iterItemSrc, GtkTreeIter *iterItemDst, GtkTreeIter* iterNewItem, int is_copy) { int kind, position = 0; /* insert after iterItemDst */ + int id_new, count, id_src, id_dst; + + int old_count = ih->data->node_count; + + id_src = iupTreeFindNodeId(ih, iterItemSrc); + id_dst = iupTreeFindNodeId(ih, iterItemDst); + id_new = id_dst+1; /* contains the position for a copy operation */ + gtk_tree_model_get(model, iterItemDst, IUPGTK_TREE_KIND, &kind, -1); if (kind == ITREE_BRANCH) @@ -122,346 +145,311 @@ static void gtkTreeCopyNode(Ihandle* ih, GtkTreeModel* model, GtkTreeIter *iterI GtkTreePath* path = gtk_tree_model_get_path(model, iterItemDst); if (gtk_tree_view_row_expanded(GTK_TREE_VIEW(ih->handle), path)) position = 1; /* insert as first child of iterItemDst */ + else + { + int child_count = iupdrvTreeTotalChildCount(ih, iterItemDst); + id_new += child_count; + } gtk_tree_path_free(path); } - gtkTreeCopyItem(model, iterItemSrc, iterItemDst, position, iterNewItem, full_copy); + /* move to the same place does nothing */ + if (!is_copy && id_new == id_src) + { + iterNewItem->stamp = 0; + return; + } - gtkTreeCopyChildren(ih, model, iterItemSrc, iterNewItem, full_copy); -} + gtkTreeCopyItem(ih, model, iterItemSrc, iterItemDst, position, iterNewItem); -/*****************************************************************************/ -/* FINDING ITEMS */ -/*****************************************************************************/ + gtkTreeCopyChildren(ih, model, iterItemSrc, iterNewItem); -static void gtkTreeInvertAllNodeMarking(Ihandle* ih, GtkTreeModel* model, GtkTreeSelection* selection, GtkTreeIter* iterItem) -{ - GtkTreeIter iterChild; - int hasItem = TRUE; + count = ih->data->node_count - old_count; + iupTreeCopyMoveCache(ih, id_src, id_new, count, is_copy); - while(hasItem) + if (!is_copy) { - if(gtk_tree_selection_iter_is_selected(selection, iterItem)) - gtk_tree_selection_unselect_iter(selection, iterItem); - else - gtk_tree_selection_select_iter(selection, iterItem); + /* Deleting the node of its old position */ + iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", "1"); + gtk_tree_store_remove(GTK_TREE_STORE(model), iterItemSrc); + iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", NULL); - /* Check whether we have child items */ - if(gtk_tree_model_iter_has_child(model, iterItem)) - { - gtk_tree_model_iter_children(model, &iterChild, iterItem); /* get the firstchild */ - gtkTreeInvertAllNodeMarking(ih, model, selection, &iterChild); - } + /* restore count, because we remove src */ + ih->data->node_count = old_count; - /* Go to next sibling item */ - hasItem = gtk_tree_model_iter_next(model, iterItem); + /* compensate position for a move */ + if (id_new > id_src) + id_new -= count; } + + gtkTreeRebuildNodeCache(ih, id_new, *iterNewItem); } -static GtkTreeIter gtkTreeFindVisibleNodeId(Ihandle* ih, GtkTreeModel* model, GtkTreeIter iterItem, GtkTreeIter iterNode) +/*****************************************************************************/ +/* FINDING ITEMS */ +/*****************************************************************************/ + +static void gtkTreeIterInit(Ihandle* ih, GtkTreeIter* iterItem, InodeHandle* node_handle) { - GtkTreeIter iterChild; - GtkTreePath* path; - int hasItem = TRUE; + iterItem->stamp = ih->data->stamp; + iterItem->user_data = node_handle; + iterItem->user_data2 = NULL; + iterItem->user_data3 = NULL; +} - while(hasItem) - { - /* ID control to traverse items */ - ih->data->id_control++; /* not the real id since it counts only the visible ones */ +static int gtkTreeIsNodeSelected(GtkTreeModel* model, GtkTreeIter *iterItem) +{ + gboolean selected = 0; + gtk_tree_model_get(model, iterItem, IUPGTK_TREE_SELECT, &selected, -1); + return selected; +} - /* StateID founded! */ - if(iterItem.user_data == iterNode.user_data) - return iterItem; +static void gtkTreeSelectNodeRaw(GtkTreeModel* model, GtkTreeIter *iterItem, int select) +{ + /* Cannot change the selection of a row on the model that is not currently displayed. + So we store the selection state here. And update the actual state when the node becames visible. */ + gtk_tree_store_set(GTK_TREE_STORE(model), iterItem, IUPGTK_TREE_SELECT, select, -1); +} - path = gtk_tree_model_get_path(model, &iterItem); +static void gtkTreeSelectNode(GtkTreeModel* model, GtkTreeSelection* selection, GtkTreeIter *iterItem, int select) +{ + if (select == -1) + select = !gtkTreeIsNodeSelected(model, iterItem); /* toggle */ - /* Check whether we have child items and it is expanded (visible) */ - if (gtk_tree_model_iter_has_child(model, &iterItem) && gtk_tree_view_row_expanded(GTK_TREE_VIEW(ih->handle), path)) - { - gtk_tree_model_iter_children(model, &iterChild, &iterItem); /* get the firstchild */ - iterChild = gtkTreeFindVisibleNodeId(ih, model, iterChild, iterNode); + gtkTreeSelectNodeRaw(model, iterItem, select); - /* StateID founded! */ - if(iterChild.user_data) - { - gtk_tree_path_free(path); - return iterChild; - } - } + if (select) + gtk_tree_selection_select_iter(selection, iterItem); + else + gtk_tree_selection_unselect_iter(selection, iterItem); +} - gtk_tree_path_free(path); - /* Go to next sibling item */ - hasItem = gtk_tree_model_iter_next(model, &iterItem); +static void gtkTreeSelectAll(Ihandle* ih, GtkTreeModel* model, GtkTreeSelection* selection, int selected) +{ + int i; + GtkTreeIter iterItem; + + for (i = 0; i < ih->data->node_count; i++) + { + gtkTreeIterInit(ih, &iterItem, ih->data->node_cache[i].node_handle); + gtkTreeSelectNodeRaw(model, &iterItem, selected); } - return gtkTreeInvalidIter; /* invalid since gtk_tree_model_iter_next returned false */ + if (selected) + gtk_tree_selection_select_all(selection); + else + gtk_tree_selection_unselect_all(selection); } -static GtkTreeIter gtkTreeFindVisibleNodeFromId(Ihandle* ih, GtkTreeModel* model, GtkTreeIter iterItem) +static void gtkTreeInvertAllNodeMarking(Ihandle* ih, GtkTreeModel* model, GtkTreeSelection* selection) { - GtkTreeIter iterChild; - GtkTreePath* path; - int hasItem = TRUE; + int i; + GtkTreeIter iterItem; - while(hasItem) + for (i = 0; i < ih->data->node_count; i++) { - /* ID control to traverse items */ - ih->data->id_control--; /* not the real id since it counts only the visible ones */ + gtkTreeIterInit(ih, &iterItem, ih->data->node_cache[i].node_handle); + gtkTreeSelectNode(model, selection, &iterItem, -1); + } +} - /* StateID founded! */ - if(ih->data->id_control < 0) - return iterItem; +static void gtkTreeSelectRange(Ihandle* ih, GtkTreeModel* model, GtkTreeSelection* selection, GtkTreeIter *iterItem1, GtkTreeIter *iterItem2, int clear) +{ + int i; + int id1 = iupTreeFindNodeId(ih, iterItem1->user_data); + int id2 = iupTreeFindNodeId(ih, iterItem2->user_data); + GtkTreeIter iterItem; - path = gtk_tree_model_get_path(model, &iterItem); + if (id1 > id2) + { + int tmp = id1; + id1 = id2; + id2 = tmp; + } - /* Check whether we have child items and it is expanded (visible) */ - if(gtk_tree_model_iter_has_child(model, &iterItem) && gtk_tree_view_row_expanded(GTK_TREE_VIEW(ih->handle), path)) + for (i = 0; i < ih->data->node_count; i++) + { + gtkTreeIterInit(ih, &iterItem, ih->data->node_cache[i].node_handle); + if (i < id1 || i > id2) { - gtk_tree_model_iter_children(model, &iterChild, &iterItem); /* get the firstchild */ - iterChild = gtkTreeFindVisibleNodeFromId(ih, model, iterChild); - - /* StateID founded! */ - if(ih->data->id_control < 0) - { - gtk_tree_path_free(path); - return iterChild; - } + if (clear) + gtkTreeSelectNode(model, selection, &iterItem, 0); } - - gtk_tree_path_free(path); - /* Go to next sibling item */ - hasItem = gtk_tree_model_iter_next(model, &iterItem); + else + gtkTreeSelectNode(model, selection, &iterItem, 1); } - - return gtkTreeInvalidIter; /* invalid since gtk_tree_model_iter_next returned false */ } -static GtkTreeIter gtkTreeGetLastVisibleNode(Ihandle* ih, GtkTreeModel* model, GtkTreeIter iterItem) +static int gtkTreeIsNodeVisible(Ihandle* ih, GtkTreeModel* model, InodeHandle* node_handle, InodeHandle* *nodeLastParent) { - GtkTreeIter iterChild, iterPrev = gtkTreeInvalidIter; - GtkTreePath* path = gtk_tree_model_get_path(model, &iterItem); - - /* Check whether we have child items and it is expanded (visible) */ - if(gtk_tree_model_iter_has_child(model, &iterItem) && gtk_tree_view_row_expanded(GTK_TREE_VIEW(ih->handle), path)) - { - int hasItem = TRUE; - gtk_tree_model_iter_children(model, &iterChild, &iterItem); /* get the firstchild */ + GtkTreeIter iterItem, iterParent; + GtkTreePath* path; + int is_visible; - while(hasItem) - { - iterPrev = iterChild; + gtkTreeIterInit(ih, &iterItem, node_handle); - /* Go to next sibling item */ - hasItem = gtk_tree_model_iter_next(model, &iterChild); - } + if (!gtk_tree_model_iter_parent(model, &iterParent, &iterItem) || + iterParent.user_data == *nodeLastParent) + return 1; - iterItem = gtkTreeGetLastVisibleNode(ih, model, iterPrev); - } + path = gtk_tree_model_get_path(model, &iterParent); + is_visible = gtk_tree_view_row_expanded(GTK_TREE_VIEW(ih->handle), path); gtk_tree_path_free(path); - return iterItem; + if (!is_visible) + return 0; + + /* save last parent */ + *nodeLastParent = iterParent.user_data; + return 1; } -static GtkTreeIter gtkTreeFindNodeID(Ihandle* ih, GtkTreeModel* model, GtkTreeIter iterItem, GtkTreeIter iterNode) +static void gtkTreeGetLastVisibleNode(Ihandle* ih, GtkTreeModel* model, GtkTreeIter *iterItem) { - GtkTreeIter iterChild; - int hasItem = TRUE; + int i; + InodeHandle* nodeLastParent = NULL; - while(hasItem) + for (i = ih->data->node_count-1; i >= 0; i--) { - /* ID control to traverse items */ - ih->data->id_control++; - - /* StateID founded! */ - if (iterItem.user_data == iterNode.user_data) - return iterItem; - - /* Check whether we have child items */ - if (gtk_tree_model_iter_has_child(model, &iterItem)) + if (gtkTreeIsNodeVisible(ih, model, ih->data->node_cache[i].node_handle, &nodeLastParent)) { - gtk_tree_model_iter_children(model, &iterChild, &iterItem); /* get the firstchild */ - iterChild = gtkTreeFindNodeID(ih, model, iterChild, iterNode); - - /* StateID founded! */ - if(iterChild.user_data) - return iterChild; + gtkTreeIterInit(ih, iterItem, ih->data->node_cache[i].node_handle); + return; } - - /* Go to next sibling item */ - hasItem = gtk_tree_model_iter_next(model, &iterItem); } - return gtkTreeInvalidIter; /* invalid since gtk_tree_model_iter_next returned false */ + gtkTreeIterInit(ih, iterItem, ih->data->node_cache[0].node_handle); /* root is always visible */ } -static int gtkTreeGetNodeId(Ihandle* ih, GtkTreeIter iterItem) +static void gtkTreeGetNextVisibleNode(Ihandle* ih, GtkTreeModel* model, GtkTreeIter *iterItem, int count) { - GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle)); - GtkTreeIter iterRoot; - gtk_tree_model_get_iter_first(model, &iterRoot); - - ih->data->id_control = -1; - iterItem = gtkTreeFindNodeID(ih, model, iterRoot, iterItem); - if (iterItem.user_data) - return ih->data->id_control; - else - return -1; -} + int i, id; + InodeHandle* nodeLastParent = NULL; -static GtkTreeIter gtkTreeFindUserData(Ihandle* ih, GtkTreeModel* model, GtkTreeIter iterItem, void* userdata) -{ - GtkTreeIter iterChild; - int hasItem = TRUE; - void* node_userdata; + id = iupTreeFindNodeId(ih, iterItem->user_data); + id += count; - while(hasItem) + for (i = id; i < ih->data->node_count; i++) { - /* ID control to traverse items */ - ih->data->id_control++; + if (gtkTreeIsNodeVisible(ih, model, ih->data->node_cache[i].node_handle, &nodeLastParent)) + { + gtkTreeIterInit(ih, iterItem, ih->data->node_cache[i].node_handle); + return; + } + } - gtk_tree_model_get(model, &iterItem, IUPGTK_TREE_USERDATA, &node_userdata, -1); + gtkTreeIterInit(ih, iterItem, ih->data->node_cache[0].node_handle); /* root is always visible */ +} - /* userdata founded! */ - if (node_userdata == userdata) - return iterItem; +static void gtkTreeGetPreviousVisibleNode(Ihandle* ih, GtkTreeModel* model, GtkTreeIter *iterItem, int count) +{ + int i, id; + InodeHandle* nodeLastParent = NULL; - /* Check whether we have child items */ - if (gtk_tree_model_iter_has_child(model, &iterItem)) - { - gtk_tree_model_iter_children(model, &iterChild, &iterItem); /* get the firstchild */ - iterChild = gtkTreeFindUserData(ih, model, iterChild, userdata); + id = iupTreeFindNodeId(ih, iterItem->user_data); + id -= count; - /* userdata founded! */ - if (iterChild.user_data) - return iterChild; + for (i = id; i >= 0; i--) + { + if (gtkTreeIsNodeVisible(ih, model, ih->data->node_cache[i].node_handle, &nodeLastParent)) + { + gtkTreeIterInit(ih, iterItem, ih->data->node_cache[i].node_handle); + return; } - - /* Go to next sibling item */ - hasItem = gtk_tree_model_iter_next(model, &iterItem); } - return gtkTreeInvalidIter; /* invalid since gtk_tree_model_iter_next returned false */ + gtkTreeGetLastVisibleNode(ih, model, iterItem); } -static int gtkTreeGetUserDataId(Ihandle* ih, GtkTreeModel* model, void* userdata) +static int gtkTreeFindNodeId(Ihandle* ih, GtkTreeIter* iterItem) { - GtkTreeIter iterRoot, iterItem; - gtk_tree_model_get_iter_first(model, &iterRoot); - - ih->data->id_control = -1; - iterItem = gtkTreeFindUserData(ih, model, iterRoot, userdata); - if (iterItem.user_data) - return ih->data->id_control; - else - return -1; + return iupTreeFindNodeId(ih, iterItem->user_data); } -static void gtkTreeCallNodeRemovedRec(Ihandle* ih, GtkTreeModel* model, GtkTreeIter iterItem, IFnis cb) +static void gtkTreeCallNodeRemovedRec(Ihandle* ih, GtkTreeModel* model, GtkTreeIter *iterItem, IFns cb, int *id) { GtkTreeIter iterChild; - int hasItem = TRUE; - void* node_userdata; + int hasItem; + int old_id = *id; + /* Check whether we have child items */ + /* remove from children first */ + hasItem = gtk_tree_model_iter_children(model, &iterChild, iterItem); /* get the firstchild */ while(hasItem) { - /* ID control to traverse items */ - ih->data->id_control++; - - gtk_tree_model_get(model, &iterItem, IUPGTK_TREE_USERDATA, &node_userdata, -1); - - cb(ih, ih->data->id_control, (char*)node_userdata); - - /* Check whether we have child items */ - if (gtk_tree_model_iter_has_child(model, &iterItem)) - { - gtk_tree_model_iter_children(model, &iterChild, &iterItem); /* get the firstchild */ - gtkTreeCallNodeRemovedRec(ih, model, iterChild, cb); - } + /* go recursive to children */ + gtkTreeCallNodeRemovedRec(ih, model, &iterChild, cb, id); /* Go to next sibling item */ - hasItem = gtk_tree_model_iter_next(model, &iterItem); + hasItem = gtk_tree_model_iter_next(model, &iterChild); } + + /* actually do it for the node */ + ih->data->node_count--; + (*id)++; + + cb(ih, (char*)ih->data->node_cache[old_id].userdata); } static void gtkTreeCallNodeRemoved(Ihandle* ih, GtkTreeModel* model, GtkTreeIter *iterItem) { - IFnis cb = (IFnis)IupGetCallback(ih, "NODEREMOVED_CB"); + int old_count = ih->data->node_count; + int id = iupTreeFindNodeId(ih, iterItem->user_data); + int old_id = id; + + IFns cb = (IFns)IupGetCallback(ih, "NODEREMOVED_CB"); if (cb) + gtkTreeCallNodeRemovedRec(ih, model, iterItem, cb, &id); + else { - ih->data->id_control = gtkTreeGetNodeId(ih, *iterItem)-1; - gtkTreeCallNodeRemovedRec(ih, model, *iterItem, cb); + int removed_count = iupdrvTreeTotalChildCount(ih, iterItem->user_data)+1; + ih->data->node_count -= removed_count; } + + iupTreeDelFromCache(ih, old_id, old_count-ih->data->node_count); } -static gboolean gtkTreeFindNodeFromID(Ihandle* ih, GtkTreeModel* model, GtkTreeIter *iterItem, int *id) +static void gtkTreeCallNodeRemovedAll(Ihandle* ih) { - GtkTreeIter iterChild; - int hasItem = TRUE; + IFns cb = (IFns)IupGetCallback(ih, "NODEREMOVED_CB"); + int i, old_count = ih->data->node_count; - while(hasItem) + if (cb) { - /* ID control to traverse items */ - (*id)--; - - /* StateID founded! */ - if (*id < 0) - return TRUE; - - /* Check whether we have child items */ - if (gtk_tree_model_iter_has_child(model, iterItem)) + for (i = 0; i < ih->data->node_count; i++) { - gtk_tree_model_iter_children(model, &iterChild, iterItem); /* get the firstchild */ - - if (gtkTreeFindNodeFromID(ih, model, &iterChild, id)) - { - *iterItem = iterChild; - return TRUE; - } + cb(ih, (char*)ih->data->node_cache[i].userdata); } - - /* Go to next sibling item */ - hasItem = gtk_tree_model_iter_next(model, iterItem); } - return FALSE; + ih->data->node_count = 0; + + iupTreeDelFromCache(ih, 0, old_count); } -static gboolean gtkTreeFindNodeFromString(Ihandle* ih, GtkTreeModel* model, const char* name_id, GtkTreeIter *iterItem) +static gboolean gtkTreeFindNodeFromString(Ihandle* ih, const char* name_id, GtkTreeIter *iterItem) { - if (name_id[0]) - { - int id; - if (iupStrToInt(name_id, &id)) - { - gtk_tree_model_get_iter_first(model, iterItem); - return gtkTreeFindNodeFromID(ih, model, iterItem, &id); - } - } - else - { - GtkTreePath* path = NULL; - gtk_tree_view_get_cursor(GTK_TREE_VIEW(ih->handle), &path, NULL); - if (path) - { - gtk_tree_model_get_iter(model, iterItem, path); - gtk_tree_path_free(path); - return TRUE; - } - } - return FALSE; + InodeHandle* node_handle = iupTreeGetNodeFromString(ih, name_id); + if (!node_handle) + return FALSE; + + gtkTreeIterInit(ih, iterItem, node_handle); + return TRUE; } /*****************************************************************************/ /* MANIPULATING IMAGES */ /*****************************************************************************/ -static void gtkTreeUpdateImages(Ihandle* ih, GtkTreeModel* model, GtkTreeIter iterItem, int mode) +static void gtkTreeUpdateImages(Ihandle* ih, int mode) { - GtkTreeIter iterChild; - int hasItem = TRUE; - int kind; + GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle)); + GtkTreeIter iterItem; + int i, kind; - while(hasItem) + for (i=0; i<ih->data->node_count; i++) { + gtkTreeIterInit(ih, &iterItem, ih->data->node_cache[i].node_handle); + gtk_tree_model_get(model, &iterItem, IUPGTK_TREE_KIND, &kind, -1); if (kind == ITREE_BRANCH) @@ -480,14 +468,6 @@ static void gtkTreeUpdateImages(Ihandle* ih, GtkTreeModel* model, GtkTreeIter it if (!has_image) gtk_tree_store_set(GTK_TREE_STORE(model), &iterItem, IUPGTK_TREE_IMAGE, ih->data->def_image_collapsed, -1); } - - if (gtk_tree_model_iter_has_child(model, &iterItem)) - { - - /* Recursively traverse child items */ - gtk_tree_model_iter_children(model, &iterChild, &iterItem); - gtkTreeUpdateImages(ih, model, iterChild, mode); - } } else { @@ -499,9 +479,6 @@ static void gtkTreeUpdateImages(Ihandle* ih, GtkTreeModel* model, GtkTreeIter it gtk_tree_store_set(GTK_TREE_STORE(model), &iterItem, IUPGTK_TREE_IMAGE, ih->data->def_image_leaf, -1); } } - - /* Go to next sibling item */ - hasItem = gtk_tree_model_iter_next(model, &iterItem); } } @@ -536,26 +513,49 @@ void iupdrvTreeAddNode(Ihandle* ih, const char* name_id, int kind, const char* t GtkTreeIter iterPrev, iterNewItem, iterParent; GtkTreePath* path; GdkColor color = {0L,0,0,0}; - int kindPrev; - - if (!gtkTreeFindNodeFromString(ih, GTK_TREE_MODEL(store), name_id, &iterPrev)) - return; + int kindPrev = -1; - gtk_tree_model_get(GTK_TREE_MODEL(store), &iterPrev, IUPGTK_TREE_KIND, &kindPrev, -1); + if (!gtkTreeFindNodeFromString(ih, name_id, &iterPrev)) + { + /* check if the root was really specified */ + int id = 0; + if (!iupStrToInt(name_id, &id) || id != -1) + return; + } + else + gtk_tree_model_get(GTK_TREE_MODEL(store), &iterPrev, IUPGTK_TREE_KIND, &kindPrev, -1); - if (kindPrev == ITREE_BRANCH && add) - gtk_tree_store_insert(store, &iterNewItem, &iterPrev, 0); /* iterPrev is parent of the new item (firstchild of it) */ + if (kindPrev != -1) + { + /* Add the new node */ + if (kindPrev == ITREE_BRANCH && add) + gtk_tree_store_insert(store, &iterNewItem, &iterPrev, 0); /* iterPrev is parent of the new item (firstchild of it) */ + else + gtk_tree_store_insert_after(store, &iterNewItem, NULL, &iterPrev); /* iterPrev is sibling of the new item */ + iupTreeAddToCache(ih, add, kindPrev, iterPrev.user_data, iterNewItem.user_data); + } else - gtk_tree_store_insert_after(store, &iterNewItem, NULL, &iterPrev); /* iterPrev is sibling of the new item */ + { + gtk_tree_store_append(store, &iterNewItem, NULL); /* root node */ + iupTreeAddToCache(ih, 0, 0, NULL, iterNewItem.user_data); + + /* store the stamp for the tree */ + ih->data->stamp = iterNewItem.stamp; + } iupgtkGetColor(iupAttribGetStr(ih, "FGCOLOR"), &color); + if (!title) + title = ""; + /* set the attributes of the new node */ gtk_tree_store_set(store, &iterNewItem, IUPGTK_TREE_HAS_IMAGE, FALSE, IUPGTK_TREE_HAS_IMAGE_EXPANDED, FALSE, IUPGTK_TREE_TITLE, iupgtkStrConvertToUTF8(title), IUPGTK_TREE_KIND, kind, - IUPGTK_TREE_COLOR, &color, -1); + IUPGTK_TREE_COLOR, &color, + IUPGTK_TREE_SELECT, 0, + -1); if (kind == ITREE_LEAF) gtk_tree_store_set(store, &iterNewItem, IUPGTK_TREE_IMAGE, ih->data->def_image_leaf, -1); @@ -563,56 +563,113 @@ void iupdrvTreeAddNode(Ihandle* ih, const char* name_id, int kind, const char* t gtk_tree_store_set(store, &iterNewItem, IUPGTK_TREE_IMAGE, ih->data->def_image_collapsed, IUPGTK_TREE_IMAGE_EXPANDED, ih->data->def_image_expanded, -1); - if (kindPrev == ITREE_BRANCH && add) - iterParent = iterPrev; - else - gtk_tree_model_iter_parent(GTK_TREE_MODEL(store), &iterParent, &iterNewItem); + if (kindPrev != -1) + { + if (kindPrev == ITREE_BRANCH && add) + iterParent = iterPrev; + else if (!gtk_tree_model_iter_parent(GTK_TREE_MODEL(store), &iterParent, &iterNewItem)) + return; - /* If this is the first child of the parent, then handle the ADDEXPANDED attribute */ - if (gtk_tree_model_iter_n_children(GTK_TREE_MODEL(store), &iterParent) == 1) + /* If this is the first child of the parent, then handle the ADDEXPANDED attribute */ + if (gtk_tree_model_iter_n_children(GTK_TREE_MODEL(store), &iterParent) == 1) + { + path = gtk_tree_model_get_path(GTK_TREE_MODEL(store), &iterParent); + iupAttribSetStr(ih, "_IUPTREE_IGNORE_BRANCH_CB", "1"); + if (ih->data->add_expanded) + gtk_tree_view_expand_row(GTK_TREE_VIEW(ih->handle), path, FALSE); + else + gtk_tree_view_collapse_row(GTK_TREE_VIEW(ih->handle), path); + iupAttribSetStr(ih, "_IUPTREE_IGNORE_BRANCH_CB", NULL); + gtk_tree_path_free(path); + } + } + else { - int depth; - path = gtk_tree_model_get_path(GTK_TREE_MODEL(store), &iterParent); - depth = gtk_tree_path_get_depth(path)-1; - if (ih->data->add_expanded || depth==0) /* if this is the first child of the root, expand always */ + if (ih->data->node_count == 1) { - iupAttribSetStr(ih, "_IUPTREE_IGNORE_BRANCHOPEN_CB", "1"); - gtk_tree_view_expand_row(GTK_TREE_VIEW(ih->handle), path, FALSE); + /* MarkStart node */ + iupAttribSetStr(ih, "_IUPTREE_MARKSTART_NODE", (char*)iterNewItem.user_data); + + /* Set the default VALUE */ + path = gtk_tree_model_get_path(GTK_TREE_MODEL(store), &iterNewItem); + gtk_tree_view_set_cursor(GTK_TREE_VIEW(ih->handle), path, NULL, FALSE); + gtk_tree_path_free(path); } - else - gtk_tree_view_collapse_row(GTK_TREE_VIEW(ih->handle), path); - gtk_tree_path_free(path); } } -static void gtkTreeAddRootNode(Ihandle* ih) + +/*****************************************************************************/ +/* AUXILIAR FUNCTIONS */ +/*****************************************************************************/ + + +static void gtkTreeChildRebuildCacheRec(Ihandle* ih, GtkTreeModel *model, GtkTreeIter *iterItem, int *id) { - GtkTreeStore* store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle))); - GtkTreePath* path; - GtkTreeIter iterRoot; - GdkColor color = {0L,0,0,0}; + GtkTreeIter iterChild; + int hasItem = gtk_tree_model_iter_children(model, &iterChild, iterItem); /* get the firstchild */ + while(hasItem) + { + (*id)++; + ih->data->node_cache[*id].node_handle = iterChild.user_data; - iupgtkGetColor(iupAttribGetStr(ih, "FGCOLOR"), &color); + /* go recursive to children */ + gtkTreeChildRebuildCacheRec(ih, model, &iterChild, id); + + /* Go to next sibling item */ + hasItem = gtk_tree_model_iter_next(model, &iterChild); + } +} - gtk_tree_store_append(store, &iterRoot, NULL); /* root node */ - gtk_tree_store_set(store, &iterRoot, IUPGTK_TREE_IMAGE, ih->data->def_image_collapsed, - IUPGTK_TREE_HAS_IMAGE, FALSE, - IUPGTK_TREE_IMAGE_EXPANDED, ih->data->def_image_expanded, - IUPGTK_TREE_HAS_IMAGE_EXPANDED, FALSE, - IUPGTK_TREE_KIND, ITREE_BRANCH, - IUPGTK_TREE_COLOR, &color, -1); +static void gtkTreeRebuildNodeCache(Ihandle* ih, int id, GtkTreeIter iterItem) +{ + GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle)); + ih->data->node_cache[id].node_handle = iterItem.user_data; + gtkTreeChildRebuildCacheRec(ih, model, &iterItem, &id); +} + +static void gtkTreeChildCountRec(GtkTreeModel *model, GtkTreeIter *iterItem, int *count) +{ + GtkTreeIter iterChild; + int hasItem = gtk_tree_model_iter_children(model, &iterChild, iterItem); /* get the firstchild */ + while(hasItem) + { + (*count)++; - path = gtk_tree_model_get_path(GTK_TREE_MODEL(store), &iterRoot); - /* MarkStart node */ - iupAttribSetStr(ih, "_IUPTREE_MARKSTART_NODE", (char*)path); + /* go recursive to children */ + gtkTreeChildCountRec(model, &iterChild, count); - /* Set the default VALUE */ - gtk_tree_view_set_cursor(GTK_TREE_VIEW(ih->handle), path, NULL, FALSE); + /* Go to next sibling item */ + hasItem = gtk_tree_model_iter_next(model, &iterChild); + } +} + +int iupdrvTreeTotalChildCount(Ihandle* ih, InodeHandle* node_handle) +{ + int count = 0; + GtkTreeIter iterItem; + GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle)); + gtkTreeIterInit(ih, &iterItem, node_handle); + gtkTreeChildCountRec(model, &iterItem, &count); + return count; +} + +InodeHandle* iupdrvTreeGetFocusNode(Ihandle* ih) +{ + GtkTreePath* path = NULL; + gtk_tree_view_get_cursor(GTK_TREE_VIEW(ih->handle), &path, NULL); + if (path) + { + GtkTreeIter iterItem; + GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle)); + gtk_tree_model_get_iter(model, &iterItem, path); + gtk_tree_path_free(path); + return iterItem.user_data; + } + + return NULL; } -/*****************************************************************************/ -/* AUXILIAR FUNCTIONS */ -/*****************************************************************************/ static void gtkTreeOpenCloseEvent(Ihandle* ih) { GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle)); @@ -620,7 +677,7 @@ static void gtkTreeOpenCloseEvent(Ihandle* ih) GtkTreePath* path; int kind; - if (!gtkTreeFindNodeFromString(ih, model, "", &iterItem)) + if (!gtkTreeFindNodeFromString(ih, "", &iterItem)) return; path = gtk_tree_model_get_path(model, &iterItem); @@ -637,27 +694,22 @@ static void gtkTreeOpenCloseEvent(Ihandle* ih) } } -static gboolean gtkTreeSelected_Foreach_Func(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, GList **rowref_list) +typedef struct _gtkTreeSelectMinMax { - GtkTreeRowReference *rowref; - - rowref = gtk_tree_row_reference_new(model, path); - *rowref_list = g_list_append(*rowref_list, rowref); + Ihandle* ih; + int id1, id2; +} gtkTreeSelectMinMax; - (void)iter; - return FALSE; /* do not stop walking the store, call us with next row */ -} - -static gboolean gtkTreeSelected_Iter_Func(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, GList **rowref_list) +static gboolean gtkTreeSelected_Foreach_Func(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iterItem, gtkTreeSelectMinMax *minmax) { - GtkTreeRowReference *rowref; - GtkTreeIter iterParent; - if (!gtk_tree_model_iter_parent(model, &iterParent, iter)) /* the root node can't be deleted */ - return FALSE; /* do not stop walking the store, call us with next row */ - - rowref = gtk_tree_row_reference_new(model, path); - *rowref_list = g_list_append(*rowref_list, rowref); + int id = iupTreeFindNodeId(minmax->ih, iterItem->user_data); + if (id < minmax->id1) + minmax->id1 = id; + if (id > minmax->id2) + minmax->id2 = id; + (void)model; + (void)path; return FALSE; /* do not stop walking the store, call us with next row */ } @@ -672,45 +724,48 @@ static void gtkTreeCallMultiSelectionCb(Ihandle* ih) { GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle)); GtkTreeSelection* selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(ih->handle)); - GtkTreeIter iterRoot; - GList *rr_list = NULL; - GList *node; - int* id_rowItem; - int count_selected_rows, i = 0; + GtkTreeIter iterItem; + int i = 0, countItems; + gtkTreeSelectMinMax minmax; - gtk_tree_model_get_iter_first(model, &iterRoot); + minmax.ih = ih; + minmax.id1 = ih->data->node_count; + minmax.id2 = -1; - gtk_tree_selection_selected_foreach(selection, (GtkTreeSelectionForeachFunc)gtkTreeSelected_Foreach_Func, &rr_list); - count_selected_rows = g_list_length(rr_list); - id_rowItem = malloc(sizeof(int) * count_selected_rows); + gtk_tree_selection_selected_foreach(selection, (GtkTreeSelectionForeachFunc)gtkTreeSelected_Foreach_Func, &minmax); + if (minmax.id2 == -1) + return; - for(node = rr_list; node != NULL; node = node->next) + /* interactive selection of several nodes will NOT select hidden nodes, + so make sure that they are selected. */ + for(i = minmax.id1; i <= minmax.id2; i++) { - GtkTreePath* path = gtk_tree_row_reference_get_path(node->data); - if (path) - { - GtkTreeIter iterItem; - gtk_tree_model_get_iter(model, &iterItem, path); - - id_rowItem[i] = gtkTreeGetNodeId(ih, iterItem); - i++; - - gtk_tree_path_free(path); - } + gtkTreeIterInit(ih, &iterItem, ih->data->node_cache[i].node_handle); + if (!gtkTreeIsNodeSelected(model, &iterItem)) + gtkTreeSelectNodeRaw(model, &iterItem, 1); } - g_list_foreach(rr_list, (GFunc) gtk_tree_row_reference_free, NULL); - g_list_free(rr_list); + /* if last selected item is a branch, then select its children */ + iupTreeSelectLastCollapsedBranch(ih, &(minmax.id2)); + + countItems = minmax.id2-minmax.id1+1; if (cbMulti) - cbMulti(ih, id_rowItem, count_selected_rows); - else { - for (i=0; i<count_selected_rows; i++) - cbSelec(ih, id_rowItem[i], 1); - } + int* id_rowItem = malloc(sizeof(int) * countItems); + + for(i = 0; i < countItems; i++) + id_rowItem[i] = minmax.id1+i; - free(id_rowItem); + cbMulti(ih, id_rowItem, countItems); + + free(id_rowItem); + } + else if (cbSelec) + { + for (i=0; i<countItems; i++) + cbSelec(ih, minmax.id1+i, 1); + } } } @@ -747,14 +802,22 @@ static int gtkTreeSetTopItemAttrib(Ihandle* ih, const char* value) GtkTreeStore* store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle))); GtkTreeIter iterItem; GtkTreePath* path; + int kind; - if (!gtkTreeFindNodeFromString(ih, GTK_TREE_MODEL(store), value, &iterItem)) + if (!gtkTreeFindNodeFromString(ih, value, &iterItem)) return 0; path = gtk_tree_model_get_path(GTK_TREE_MODEL(store), &iterItem); - if (!gtk_tree_view_row_expanded(GTK_TREE_VIEW(ih->handle), path)) + gtk_tree_model_get(GTK_TREE_MODEL(store), &iterItem, IUPGTK_TREE_KIND, &kind, -1); + if (kind == ITREE_LEAF) + gtk_tree_view_expand_to_path(GTK_TREE_VIEW(ih->handle), path); + else + { + int expanded = gtk_tree_view_row_expanded(GTK_TREE_VIEW(ih->handle), path); gtk_tree_view_expand_to_path(GTK_TREE_VIEW(ih->handle), path); + if (!expanded) gtk_tree_view_collapse_row(GTK_TREE_VIEW(ih->handle), path); + } gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(ih->handle), path, NULL, FALSE, 0, 0); /* scroll to visible */ @@ -788,34 +851,23 @@ static int gtkTreeSetExpandAllAttrib(Ihandle* ih, const char* value) if (iupStrBoolean(value)) gtk_tree_view_expand_all(GTK_TREE_VIEW(ih->handle)); else - { - GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle)); - GtkTreeIter iterRoot; - GtkTreePath* pathRoot; - gtk_tree_view_collapse_all(GTK_TREE_VIEW(ih->handle)); - /* The root node is always expanded */ - gtk_tree_model_get_iter_first(model, &iterRoot); - pathRoot = gtk_tree_model_get_path(model, &iterRoot); - gtk_tree_view_expand_row(GTK_TREE_VIEW(ih->handle), pathRoot, FALSE); - gtk_tree_path_free(pathRoot); - } - return 0; } static char* gtkTreeGetDepthAttrib(Ihandle* ih, const char* name_id) { - char* depth; + char* str; GtkTreeStore* store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle))); GtkTreeIter iterItem; - if (!gtkTreeFindNodeFromString(ih, GTK_TREE_MODEL(store), name_id, &iterItem)) + + if (!gtkTreeFindNodeFromString(ih, name_id, &iterItem)) return NULL; - depth = iupStrGetMemory(10); - sprintf(depth, "%d", gtk_tree_store_iter_depth(store, &iterItem)); - return depth; + str = iupStrGetMemory(10); + sprintf(str, "%d", gtk_tree_store_iter_depth(store, &iterItem)); + return str; } static int gtkTreeSetMoveNodeAttrib(Ihandle* ih, const char* name_id, const char* value) @@ -824,14 +876,14 @@ static int gtkTreeSetMoveNodeAttrib(Ihandle* ih, const char* name_id, const char GtkTreeIter iterItemSrc, iterItemDst, iterNewItem; GtkTreeIter iterParent, iterNextParent; - if (!ih->handle) /* do not store the action before map */ + if (!ih->handle) /* do not do the action before map */ return 0; model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle)); - if (!gtkTreeFindNodeFromString(ih, model, name_id, &iterItemSrc)) + if (!gtkTreeFindNodeFromString(ih, name_id, &iterItemSrc)) return 0; - if (!gtkTreeFindNodeFromString(ih, model, value, &iterItemDst)) + if (!gtkTreeFindNodeFromString(ih, value, &iterItemDst)) return 0; /* If Drag item is an ancestor of Drop item then return */ @@ -843,12 +895,8 @@ static int gtkTreeSetMoveNodeAttrib(Ihandle* ih, const char* name_id, const char iterParent = iterNextParent; } - /* Copying the node and its children to the new position */ - gtkTreeCopyNode(ih, model, &iterItemSrc, &iterItemDst, &iterNewItem, 0); /* not a full copy, preserve user data */ - - /* Deleting the node of its old position */ - /* do not delete the user data, we copy the references in CopyNode */ - gtk_tree_store_remove(GTK_TREE_STORE(model), &iterItemSrc); + /* Move the node and its children to the new position */ + gtkTreeCopyMoveNode(ih, model, &iterItemSrc, &iterItemDst, &iterNewItem, 0); return 0; } @@ -859,14 +907,14 @@ static int gtkTreeSetCopyNodeAttrib(Ihandle* ih, const char* name_id, const char GtkTreeIter iterItemSrc, iterItemDst, iterNewItem; GtkTreeIter iterParent, iterNextParent; - if (!ih->handle) /* do not store the action before map */ + if (!ih->handle) /* do not do the action before map */ return 0; model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle)); - if (!gtkTreeFindNodeFromString(ih, model, name_id, &iterItemSrc)) + if (!gtkTreeFindNodeFromString(ih, name_id, &iterItemSrc)) return 0; - if (!gtkTreeFindNodeFromString(ih, model, value, &iterItemDst)) + if (!gtkTreeFindNodeFromString(ih, value, &iterItemDst)) return 0; /* If Drag item is an ancestor of Drop item then return */ @@ -878,8 +926,8 @@ static int gtkTreeSetCopyNodeAttrib(Ihandle* ih, const char* name_id, const char iterParent = iterNextParent; } - /* Copying the node and its children to the new position */ - gtkTreeCopyNode(ih, model, &iterItemSrc, &iterItemDst, &iterNewItem, 1); + /* Copy the node and its children to the new position */ + gtkTreeCopyMoveNode(ih, model, &iterItemSrc, &iterItemDst, &iterNewItem, 1); return 0; } @@ -891,7 +939,7 @@ static char* gtkTreeGetColorAttrib(Ihandle* ih, const char* name_id) GtkTreeIter iterItem; GdkColor *color; - if (!gtkTreeFindNodeFromString(ih, model, name_id, &iterItem)) + if (!gtkTreeFindNodeFromString(ih, name_id, &iterItem)) return NULL; gtk_tree_model_get(model, &iterItem, IUPGTK_TREE_COLOR, &color, -1); @@ -912,7 +960,7 @@ static int gtkTreeSetColorAttrib(Ihandle* ih, const char* name_id, const char* v GdkColor color; unsigned char r, g, b; - if (!gtkTreeFindNodeFromString(ih, GTK_TREE_MODEL(store), name_id, &iterItem)) + if (!gtkTreeFindNodeFromString(ih, name_id, &iterItem)) return 0; if (!iupStrToRGB(value, &r, &g, &b)) @@ -931,14 +979,14 @@ static char* gtkTreeGetParentAttrib(Ihandle* ih, const char* name_id) GtkTreeIter iterParent; char* str; - if (!gtkTreeFindNodeFromString(ih, model, name_id, &iterItem)) + if (!gtkTreeFindNodeFromString(ih, name_id, &iterItem)) return NULL; if (!gtk_tree_model_iter_parent(model, &iterParent, &iterItem)) return NULL; str = iupStrGetMemory(10); - sprintf(str, "%d", gtkTreeGetNodeId(ih, iterParent)); + sprintf(str, "%d", gtkTreeFindNodeId(ih, &iterParent)); return str; } @@ -948,7 +996,7 @@ static char* gtkTreeGetChildCountAttrib(Ihandle* ih, const char* name_id) GtkTreeIter iterItem; char* str; - if (!gtkTreeFindNodeFromString(ih, model, name_id, &iterItem)) + if (!gtkTreeFindNodeFromString(ih, name_id, &iterItem)) return NULL; str = iupStrGetMemory(10); @@ -956,40 +1004,13 @@ static char* gtkTreeGetChildCountAttrib(Ihandle* ih, const char* name_id) return str; } -static int gtkTreeCount(GtkTreeModel* model, GtkTreeIter iterBranch) -{ - GtkTreeIter iterChild; - int count = 0; - int hasItem = gtk_tree_model_iter_children(model, &iterChild, &iterBranch); /* get the firstchild */ - count++; - while(hasItem) - { - count += gtkTreeCount(model, iterChild); - - /* Go to next sibling item */ - hasItem = gtk_tree_model_iter_next(model, &iterChild); - } - - return count; -} - -static char* gtkTreeGetCountAttrib(Ihandle* ih) -{ - GtkTreeIter iterRoot; - GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle)); - char* str = iupStrGetMemory(10); - gtk_tree_model_get_iter_first(model, &iterRoot); - sprintf(str, "%d", gtkTreeCount(model, iterRoot)); - return str; -} - static char* gtkTreeGetKindAttrib(Ihandle* ih, const char* name_id) { GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle)); GtkTreeIter iterItem; int kind; - if (!gtkTreeFindNodeFromString(ih, model, name_id, &iterItem)) + if (!gtkTreeFindNodeFromString(ih, name_id, &iterItem)) return NULL; gtk_tree_model_get(model, &iterItem, IUPGTK_TREE_KIND, &kind, -1); @@ -1005,7 +1026,7 @@ static char* gtkTreeGetStateAttrib(Ihandle* ih, const char* name_id) GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle)); GtkTreeIter iterItem; - if (!gtkTreeFindNodeFromString(ih, model, name_id, &iterItem)) + if (!gtkTreeFindNodeFromString(ih, name_id, &iterItem)) return NULL; if (gtk_tree_model_iter_has_child(model, &iterItem)) @@ -1028,13 +1049,20 @@ static int gtkTreeSetStateAttrib(Ihandle* ih, const char* name_id, const char* v GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle)); GtkTreeIter iterItem; GtkTreePath* path; + int kind; - if (!gtkTreeFindNodeFromString(ih, model, name_id, &iterItem)) + if (!gtkTreeFindNodeFromString(ih, name_id, &iterItem)) return 0; - path = gtk_tree_model_get_path(model, &iterItem); - gtkTreeExpandItem(ih, path, iupStrEqualNoCase(value, "EXPANDED")); - gtk_tree_path_free(path); + gtk_tree_model_get(model, &iterItem, IUPGTK_TREE_KIND, &kind, -1); + if (kind == ITREE_BRANCH) + { + path = gtk_tree_model_get_path(model, &iterItem); + iupAttribSetStr(ih, "_IUPTREE_IGNORE_BRANCH_CB", "1"); + gtkTreeExpandItem(ih, path, iupStrEqualNoCase(value, "EXPANDED")); + iupAttribSetStr(ih, "_IUPTREE_IGNORE_BRANCH_CB", NULL); + gtk_tree_path_free(path); + } return 0; } @@ -1050,7 +1078,7 @@ static char* gtkTreeGetTitleAttrib(Ihandle* ih, const char* name_id) { GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle)); GtkTreeIter iterItem; - if (!gtkTreeFindNodeFromString(ih, model, name_id, &iterItem)) + if (!gtkTreeFindNodeFromString(ih, name_id, &iterItem)) return NULL; return gtkTreeGetTitle(model, iterItem); } @@ -1059,8 +1087,10 @@ static int gtkTreeSetTitleAttrib(Ihandle* ih, const char* name_id, const char* v { GtkTreeStore* store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle))); GtkTreeIter iterItem; - if (!gtkTreeFindNodeFromString(ih, GTK_TREE_MODEL(store), name_id, &iterItem)) + if (!gtkTreeFindNodeFromString(ih, name_id, &iterItem)) return 0; + if (!value) + value = ""; gtk_tree_store_set(store, &iterItem, IUPGTK_TREE_TITLE, iupgtkStrConvertToUTF8(value), -1); return 0; } @@ -1070,7 +1100,7 @@ static int gtkTreeSetTitleFontAttrib(Ihandle* ih, const char* name_id, const cha PangoFontDescription* fontdesc = NULL; GtkTreeStore* store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle))); GtkTreeIter iterItem; - if (!gtkTreeFindNodeFromString(ih, GTK_TREE_MODEL(store), name_id, &iterItem)) + if (!gtkTreeFindNodeFromString(ih, name_id, &iterItem)) return 0; if (value) fontdesc = iupgtkGetPangoFontDesc(value); @@ -1083,49 +1113,12 @@ static char* gtkTreeGetTitleFontAttrib(Ihandle* ih, const char* name_id) PangoFontDescription* fontdesc; GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle)); GtkTreeIter iterItem; - if (!gtkTreeFindNodeFromString(ih, model, name_id, &iterItem)) + if (!gtkTreeFindNodeFromString(ih, name_id, &iterItem)) return NULL; gtk_tree_model_get(model, &iterItem, IUPGTK_TREE_FONT, &fontdesc, -1); return pango_font_description_to_string(fontdesc); } -static char* gtkTreeGetFindUserDataAttrib(Ihandle* ih, const char* name_id) -{ - GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle)); - int id; - char* str = (char*)(name_id+1); /* skip ':' */ - void* userdata = NULL; - if (sscanf(str, "%p", &userdata)!=1) - return NULL; - id = gtkTreeGetUserDataId(ih, model, userdata); - if (id == -1) - return NULL; - str = iupStrGetMemory(16); - sprintf(str, "%d", id); - return str; -} - -static char* gtkTreeGetUserDataAttrib(Ihandle* ih, const char* name_id) -{ - GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle)); - GtkTreeIter iterItem; - char* userdata; - if (!gtkTreeFindNodeFromString(ih, model, name_id, &iterItem)) - return NULL; - gtk_tree_model_get(model, &iterItem, IUPGTK_TREE_USERDATA, &userdata, -1); - return userdata; -} - -static int gtkTreeSetUserDataAttrib(Ihandle* ih, const char* name_id, const char* value) -{ - GtkTreeStore* store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle))); - GtkTreeIter iterItem; - if (!gtkTreeFindNodeFromString(ih, GTK_TREE_MODEL(store), name_id, &iterItem)) - return 0; - gtk_tree_store_set(store, &iterItem, IUPGTK_TREE_USERDATA, value, -1); - return 0; -} - static char* gtkTreeGetValueAttrib(Ihandle* ih) { GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle)); @@ -1140,67 +1133,117 @@ static char* gtkTreeGetValueAttrib(Ihandle* ih) gtk_tree_path_free(path); str = iupStrGetMemory(16); - sprintf(str, "%d", gtkTreeGetNodeId(ih, iterItem)); + sprintf(str, "%d", gtkTreeFindNodeId(ih, &iterItem)); return str; } - return "0"; /* default VALUE is root */ + if (ih->data->node_count) + return "0"; /* default VALUE is root */ + else + return "-1"; +} + +static char* gtkTreeGetMarkedNodesAttrib(Ihandle* ih) +{ + char* str = iupStrGetMemory(ih->data->node_count+1); + GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle)); + GtkTreeIter iterItem; + int i; + + for (i=0; i<ih->data->node_count; i++) + { + gtkTreeIterInit(ih, &iterItem, ih->data->node_cache[i].node_handle); + if (gtkTreeIsNodeSelected(model, &iterItem)) + str[i] = '+'; + else + str[i] = '-'; + } + + str[ih->data->node_count] = 0; + return str; +} + +static int gtkTreeSetMarkedNodesAttrib(Ihandle* ih, const char* value) +{ + int count, i; + GtkTreeModel* model; + GtkTreeIter iterItem; + GtkTreeSelection* selection; + + if (ih->data->mark_mode==ITREE_MARK_SINGLE || !value) + return 0; + + count = strlen(value); + if (count > ih->data->node_count) + count = ih->data->node_count; + + selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(ih->handle)); + model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle)); + + iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", "1"); + + for (i=0; i<count; i++) + { + gtkTreeIterInit(ih, &iterItem, ih->data->node_cache[i].node_handle); + if (value[i] == '+') + gtkTreeSelectNode(model, selection, &iterItem, 1); + else + gtkTreeSelectNode(model, selection, &iterItem, 0); + } + + iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", NULL); + + return 0; } static int gtkTreeSetMarkAttrib(Ihandle* ih, const char* value) { GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle)); GtkTreeSelection* selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(ih->handle)); - GtkTreeIter iterRoot; if (ih->data->mark_mode==ITREE_MARK_SINGLE) return 0; - gtk_tree_model_get_iter_first(model, &iterRoot); - if(iupStrEqualNoCase(value, "BLOCK")) { + GtkTreeIter iterItem1, iterItem2; GtkTreePath* pathFocus; gtk_tree_view_get_cursor(GTK_TREE_VIEW(ih->handle), &pathFocus, NULL); - gtk_tree_selection_select_range(selection, (GtkTreePath*)iupAttribGet(ih, "_IUPTREE_MARKSTART_NODE"), pathFocus); + gtk_tree_model_get_iter(model, &iterItem1, pathFocus); gtk_tree_path_free(pathFocus); + + gtkTreeIterInit(ih, &iterItem2, iupAttribGet(ih, "_IUPTREE_MARKSTART_NODE")); + + gtkTreeSelectRange(ih, model, selection, &iterItem1, &iterItem2, 0); } else if(iupStrEqualNoCase(value, "CLEARALL")) - gtk_tree_selection_unselect_all(selection); + gtkTreeSelectAll(ih, model, selection, 0); else if(iupStrEqualNoCase(value, "MARKALL")) - gtk_tree_selection_select_all(selection); + gtkTreeSelectAll(ih, model, selection, 1); else if(iupStrEqualNoCase(value, "INVERTALL")) /* INVERTALL *MUST* appear before INVERT, or else INVERTALL will never be called. */ - gtkTreeInvertAllNodeMarking(ih, model, selection, &iterRoot); + gtkTreeInvertAllNodeMarking(ih, model, selection); else if(iupStrEqualPartial(value, "INVERT")) { /* iupStrEqualPartial allows the use of "INVERTid" form */ GtkTreeIter iterItem; - if (!gtkTreeFindNodeFromString(ih, model, &value[strlen("INVERT")], &iterItem)) + if (!gtkTreeFindNodeFromString(ih, &value[strlen("INVERT")], &iterItem)) return 0; - if(gtk_tree_selection_iter_is_selected(selection, &iterItem)) - gtk_tree_selection_unselect_iter(selection, &iterItem); - else - gtk_tree_selection_select_iter(selection, &iterItem); + gtkTreeSelectNode(model, selection, &iterItem, -1); /* toggle */ } else { - GtkTreePath *path1, *path2; GtkTreeIter iterItem1, iterItem2; char str1[50], str2[50]; if (iupStrToStrStr(value, str1, str2, '-')!=2) return 0; - if (!gtkTreeFindNodeFromString(ih, model, str1, &iterItem1)) + if (!gtkTreeFindNodeFromString(ih, str1, &iterItem1)) return 0; - if (!gtkTreeFindNodeFromString(ih, model, str2, &iterItem2)) + if (!gtkTreeFindNodeFromString(ih, str2, &iterItem2)) return 0; - path1 = gtk_tree_model_get_path(model, &iterItem1); - path2 = gtk_tree_model_get_path(model, &iterItem2); - gtk_tree_selection_select_range(selection, path1, path2); - gtk_tree_path_free(path1); - gtk_tree_path_free(path2); + gtkTreeSelectRange(ih, model, selection, &iterItem1, &iterItem2, 0); } return 1; @@ -1210,148 +1253,112 @@ static int gtkTreeSetValueAttrib(Ihandle* ih, const char* value) { GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle)); GtkTreeSelection* selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(ih->handle)); - GtkTreeIter iterRoot, iterItem; + GtkTreeIter iterItem; GtkTreePath* path; + int kind; if (gtkTreeSetMarkAttrib(ih, value)) return 0; - gtk_tree_model_get_iter_first(model, &iterRoot); - - if (iupStrEqualNoCase(value, "ROOT")) - iterItem = iterRoot; + if (iupStrEqualNoCase(value, "ROOT") || iupStrEqualNoCase(value, "FIRST")) + gtk_tree_model_get_iter_first(model, &iterItem); else if(iupStrEqualNoCase(value, "LAST")) - iterItem = gtkTreeGetLastVisibleNode(ih, model, iterRoot); + gtkTreeGetLastVisibleNode(ih, model, &iterItem); else if(iupStrEqualNoCase(value, "PGUP")) { - GtkTreeIter iterPrev; - GtkTreePath* pathFocus; gtk_tree_view_get_cursor(GTK_TREE_VIEW(ih->handle), &pathFocus, NULL); - gtk_tree_model_get_iter(model, &iterPrev, pathFocus); + gtk_tree_model_get_iter(model, &iterItem, pathFocus); gtk_tree_path_free(pathFocus); - ih->data->id_control = -1; - gtkTreeFindVisibleNodeId(ih, model, iterRoot, iterPrev); - 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 */ - - iterItem = gtkTreeFindVisibleNodeFromId(ih, model, iterRoot); + gtkTreeGetPreviousVisibleNode(ih, model, &iterItem, 10); } else if(iupStrEqualNoCase(value, "PGDN")) { - GtkTreeIter iterNext; - GtkTreePath* pathFocus; gtk_tree_view_get_cursor(GTK_TREE_VIEW(ih->handle), &pathFocus, NULL); - gtk_tree_model_get_iter(model, &iterNext, pathFocus); + gtk_tree_model_get_iter(model, &iterItem, pathFocus); gtk_tree_path_free(pathFocus); - ih->data->id_control = -1; - gtkTreeFindVisibleNodeId(ih, model, iterRoot, iterNext); - ih->data->id_control += 10; /* more 10 visible nodes */ - - iterNext = gtkTreeFindVisibleNodeFromId(ih, model, iterRoot); - - if (ih->data->id_control >= 0) - iterNext = gtkTreeGetLastVisibleNode(ih, model, iterRoot); - - iterItem = iterNext; + gtkTreeGetNextVisibleNode(ih, model, &iterItem, 10); } else if(iupStrEqualNoCase(value, "NEXT")) { - GtkTreeIter iterNext; - GtkTreePath* pathFocus; gtk_tree_view_get_cursor(GTK_TREE_VIEW(ih->handle), &pathFocus, NULL); - gtk_tree_model_get_iter(model, &iterNext, pathFocus); + gtk_tree_model_get_iter(model, &iterItem, pathFocus); gtk_tree_path_free(pathFocus); - ih->data->id_control = -1; - gtkTreeFindVisibleNodeId(ih, model, iterRoot, iterNext); - ih->data->id_control++; /* more 1 visible node */ - - iterNext = gtkTreeFindVisibleNodeFromId(ih, model, iterRoot); - - if (ih->data->id_control >= 0) - iterNext = gtkTreeGetLastVisibleNode(ih, model, iterRoot); - - iterItem = iterNext; + gtkTreeGetNextVisibleNode(ih, model, &iterItem, 1); } else if(iupStrEqualNoCase(value, "PREVIOUS")) { - GtkTreeIter iterPrev; - GtkTreePath* pathFocus; gtk_tree_view_get_cursor(GTK_TREE_VIEW(ih->handle), &pathFocus, NULL); - gtk_tree_model_get_iter(model, &iterPrev, pathFocus); + gtk_tree_model_get_iter(model, &iterItem, pathFocus); gtk_tree_path_free(pathFocus); - ih->data->id_control = -1; - gtkTreeFindVisibleNodeId(ih, model, iterRoot, iterPrev); - ih->data->id_control--; /* less 1 visible node */ - - if (ih->data->id_control < 0) - ih->data->id_control = 0; - - iterItem = gtkTreeFindVisibleNodeFromId(ih, model, iterRoot); - if (!iterItem.user_data) - return 0; + gtkTreeGetPreviousVisibleNode(ih, model, &iterItem, 1); } else { - if (!gtkTreeFindNodeFromString(ih, model, value, &iterItem)) + if (!gtkTreeFindNodeFromString(ih, value, &iterItem)) return 0; } /* select */ if (ih->data->mark_mode==ITREE_MARK_SINGLE) { - iupAttribSetStr(ih, "_IUP_IGNORE_SELECTION", "1"); - gtk_tree_selection_select_iter(selection, &iterItem); + iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", "1"); + gtkTreeSelectNode(model, selection, &iterItem, 1); + iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", NULL); } path = gtk_tree_model_get_path(model, &iterItem); + + /* make it visible */ + gtk_tree_model_get(model, &iterItem, IUPGTK_TREE_KIND, &kind, -1); + if (kind == ITREE_LEAF) + gtk_tree_view_expand_to_path(GTK_TREE_VIEW(ih->handle), path); + else + { + int expanded = gtk_tree_view_row_expanded(GTK_TREE_VIEW(ih->handle), path); + gtk_tree_view_expand_to_path(GTK_TREE_VIEW(ih->handle), path); + if (!expanded) gtk_tree_view_collapse_row(GTK_TREE_VIEW(ih->handle), path); + } + gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(ih->handle), path, NULL, FALSE, 0, 0); /* scroll to visible */ + iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", "1"); gtk_tree_view_set_cursor(GTK_TREE_VIEW(ih->handle), path, NULL, FALSE); /* set focus */ + iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", NULL); + gtk_tree_path_free(path); - iupAttribSetInt(ih, "_IUPTREE_OLDVALUE", gtkTreeGetNodeId(ih, iterItem)); + iupAttribSetInt(ih, "_IUPTREE_OLDVALUE", gtkTreeFindNodeId(ih, &iterItem)); return 0; } static int gtkTreeSetMarkStartAttrib(Ihandle* ih, const char* name_id) { - GtkTreePath *pathMarkStart, *pathMarkStartPrev; - GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle)); GtkTreeIter iterItem; - if (!gtkTreeFindNodeFromString(ih, model, name_id, &iterItem)) + if (!gtkTreeFindNodeFromString(ih, name_id, &iterItem)) return 0; - pathMarkStart = gtk_tree_model_get_path(model, &iterItem); - - pathMarkStartPrev = (GtkTreePath*)iupAttribGet(ih, "_IUPTREE_MARKSTART_NODE"); - if (pathMarkStartPrev) - gtk_tree_path_free(pathMarkStartPrev); - - iupAttribSetStr(ih, "_IUPTREE_MARKSTART_NODE", (char*)pathMarkStart); + iupAttribSetStr(ih, "_IUPTREE_MARKSTART_NODE", (char*)iterItem.user_data); return 1; } static char* gtkTreeGetMarkedAttrib(Ihandle* ih, const char* name_id) { - GtkTreeSelection* selection; - GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle)); + GtkTreeModel* model; GtkTreeIter iterItem; - if (!gtkTreeFindNodeFromString(ih, model, name_id, &iterItem)) + if (!gtkTreeFindNodeFromString(ih, name_id, &iterItem)) return 0; - selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(ih->handle)); - if (gtk_tree_selection_iter_is_selected(selection, &iterItem)) + model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle)); + if (gtkTreeIsNodeSelected(model, &iterItem)) return "YES"; else return "NO"; @@ -1359,87 +1366,99 @@ static char* gtkTreeGetMarkedAttrib(Ihandle* ih, const char* name_id) static int gtkTreeSetMarkedAttrib(Ihandle* ih, const char* name_id, const char* value) { + GtkTreeModel* model; GtkTreeSelection* selection; - GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle)); GtkTreeIter iterItem; - if (!gtkTreeFindNodeFromString(ih, model, name_id, &iterItem)) + if (!gtkTreeFindNodeFromString(ih, name_id, &iterItem)) return 0; - iupAttribSetStr(ih, "_IUP_IGNORE_SELECTION", "1"); + iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", "1"); selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(ih->handle)); + model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle)); if (iupStrBoolean(value)) - gtk_tree_selection_select_iter(selection, &iterItem); + gtkTreeSelectNode(model, selection, &iterItem, 1); else - gtk_tree_selection_unselect_iter(selection, &iterItem); + gtkTreeSelectNode(model, selection, &iterItem, 0); + + iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", NULL); return 0; } static int gtkTreeSetDelNodeAttrib(Ihandle* ih, const char* name_id, const char* value) { - if (!ih->handle) /* do not store the action before map */ + if (!ih->handle) /* do not do the action before map */ return 0; - if (iupStrEqualNoCase(value, "SELECTED")) /* selected here means the specified one */ + if (iupStrEqualNoCase(value, "ALL")) { GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle)); - GtkTreeIter iterItem; - GtkTreeIter iterParent; + gtkTreeCallNodeRemovedAll(ih); - if (!gtkTreeFindNodeFromString(ih, model, name_id, &iterItem)) - return 0; + /* deleting the reference node (and it's children) */ + iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", "1"); + gtk_tree_store_clear(GTK_TREE_STORE(model)); + iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", NULL); + return 0; + } + if (iupStrEqualNoCase(value, "SELECTED")) /* selected here means the reference node */ + { + GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle)); + GtkTreeIter iterItem; - if (!gtk_tree_model_iter_parent(model, &iterParent, &iterItem)) /* the root node can't be deleted */ + if (!gtkTreeFindNodeFromString(ih, name_id, &iterItem)) return 0; gtkTreeCallNodeRemoved(ih, model, &iterItem); - /* deleting the specified node (and it's children) */ + /* deleting the reference node (and it's children) */ + iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", "1"); gtk_tree_store_remove(GTK_TREE_STORE(model), &iterItem); + iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", NULL); } - else if(iupStrEqualNoCase(value, "CHILDREN")) /* children of the specified one */ + else if(iupStrEqualNoCase(value, "CHILDREN")) /* children of the reference node */ { GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle)); GtkTreeIter iterItem, iterChild; int hasChildren; - if (!gtkTreeFindNodeFromString(ih, model, name_id, &iterItem)) + if (!gtkTreeFindNodeFromString(ih, name_id, &iterItem)) return 0; hasChildren = gtk_tree_model_iter_children(model, &iterChild, &iterItem); - /* deleting the selected node's children */ + iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", "1"); + + /* deleting the reference node children */ while(hasChildren) { gtkTreeCallNodeRemoved(ih, model, &iterChild); hasChildren = gtk_tree_store_remove(GTK_TREE_STORE(model), &iterChild); } + + iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", NULL); } else if(iupStrEqualNoCase(value, "MARKED")) /* Delete the array of marked nodes */ { + int i; GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle)); - GtkTreeSelection* selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(ih->handle)); - GList *rr_list = NULL; - GList *node; + GtkTreeIter iterItem; - gtk_tree_selection_selected_foreach(selection, (GtkTreeSelectionForeachFunc)gtkTreeSelected_Iter_Func, &rr_list); + iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", "1"); - for(node = rr_list; node != NULL; node = node->next) + for(i = 1; i < ih->data->node_count; /* increment only if not removed */) { - GtkTreePath* path = gtk_tree_row_reference_get_path(node->data); - if (path) + gtkTreeIterInit(ih, &iterItem, ih->data->node_cache[i].node_handle); + if (gtkTreeIsNodeSelected(model, &iterItem)) { - GtkTreeIter iterItem; - if (gtk_tree_model_get_iter(model, &iterItem, path)) - { - gtkTreeCallNodeRemoved(ih, model, &iterItem); - gtk_tree_store_remove(GTK_TREE_STORE(model), &iterItem); - } - gtk_tree_path_free(path); + gtkTreeCallNodeRemoved(ih, model, &iterItem); + gtk_tree_store_remove(GTK_TREE_STORE(model), &iterItem); } - gtk_tree_row_reference_free(node->data); + else + i++; } - g_list_free(rr_list); + + iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", NULL); } return 0; @@ -1450,36 +1469,11 @@ static int gtkTreeSetRenameAttrib(Ihandle* ih, const char* value) if (ih->data->show_rename) { GtkTreePath* path; - IFni cbShowRename = (IFni)IupGetCallback(ih, "SHOWRENAME_CB"); GtkTreeViewColumn *focus_column; - gtk_tree_view_get_cursor(GTK_TREE_VIEW(ih->handle), &path, &focus_column); - - if (cbShowRename) - { - GtkTreeIter iterItem; - GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle)); - gtk_tree_model_get_iter(model, &iterItem, path); - cbShowRename(ih, gtkTreeGetNodeId(ih, iterItem)); - } - gtk_tree_view_set_cursor(GTK_TREE_VIEW(ih->handle), path, focus_column, TRUE); gtk_tree_path_free(path); } - else - { - IFnis cbRenameNode = (IFnis)IupGetCallback(ih, "RENAMENODE_CB"); - if (cbRenameNode) - { - GtkTreePath* path; - GtkTreeIter iterItem; - GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle)); - gtk_tree_view_get_cursor(GTK_TREE_VIEW(ih->handle), &path, NULL); - gtk_tree_model_get_iter(model, &iterItem, path); - gtk_tree_path_free(path); - cbRenameNode(ih, gtkTreeGetNodeId(ih, iterItem), gtkTreeGetTitle(model, iterItem)); - } - } (void)value; return 0; @@ -1491,7 +1485,7 @@ static int gtkTreeSetImageExpandedAttrib(Ihandle* ih, const char* name_id, const GtkTreeStore* store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle))); GdkPixbuf* pixExpand = iupImageGetImage(value, ih, 0); GtkTreeIter iterItem; - if (!gtkTreeFindNodeFromString(ih, GTK_TREE_MODEL(store), name_id, &iterItem)) + if (!gtkTreeFindNodeFromString(ih, name_id, &iterItem)) return 0; gtk_tree_model_get(GTK_TREE_MODEL(store), &iterItem, IUPGTK_TREE_KIND, &kind, -1); @@ -1514,7 +1508,7 @@ static int gtkTreeSetImageAttrib(Ihandle* ih, const char* name_id, const char* v GtkTreeStore* store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle))); GdkPixbuf* pixImage = iupImageGetImage(value, ih, 0); GtkTreeIter iterItem; - if (!gtkTreeFindNodeFromString(ih, GTK_TREE_MODEL(store), name_id, &iterItem)) + if (!gtkTreeFindNodeFromString(ih, name_id, &iterItem)) return 0; if (pixImage) @@ -1539,42 +1533,30 @@ static int gtkTreeSetImageAttrib(Ihandle* ih, const char* name_id, const char* v static int gtkTreeSetImageBranchExpandedAttrib(Ihandle* ih, const char* value) { - GtkTreeIter iterRoot; - GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle)); ih->data->def_image_expanded = iupImageGetImage(value, ih, 0); - gtk_tree_model_get_iter_first(model, &iterRoot); - - /* Update all images, starting at root node */ - gtkTreeUpdateImages(ih, model, iterRoot, ITREE_UPDATEIMAGE_EXPANDED); + /* Update all images */ + gtkTreeUpdateImages(ih, ITREE_UPDATEIMAGE_EXPANDED); return 1; } static int gtkTreeSetImageBranchCollapsedAttrib(Ihandle* ih, const char* value) { - GtkTreeIter iterRoot; - GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle)); ih->data->def_image_collapsed = iupImageGetImage(value, ih, 0); - gtk_tree_model_get_iter_first(model, &iterRoot); - - /* Update all images, starting at root node */ - gtkTreeUpdateImages(ih, model, iterRoot, ITREE_UPDATEIMAGE_COLLAPSED); + /* Update all images */ + gtkTreeUpdateImages(ih, ITREE_UPDATEIMAGE_COLLAPSED); return 1; } static int gtkTreeSetImageLeafAttrib(Ihandle* ih, const char* value) { - GtkTreeIter iterRoot; - GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle)); ih->data->def_image_leaf = iupImageGetImage(value, ih, 0); - gtk_tree_model_get_iter_first(model, &iterRoot); - - /* Update all images, starting at root node */ - gtkTreeUpdateImages(ih, model, iterRoot, ITREE_UPDATEIMAGE_LEAF); + /* Update all images */ + gtkTreeUpdateImages(ih, ITREE_UPDATEIMAGE_LEAF); return 1; } @@ -1655,6 +1637,7 @@ void iupdrvTreeUpdateMarkMode(Ihandle *ih) if (ih->data->mark_mode==ITREE_MARK_MULTIPLE && !ih->data->show_dragdrop) { #if GTK_CHECK_VERSION(2, 10, 0) + if (iupAttribGetInt(ih, "RUBBERBAND")) gtk_tree_view_set_rubber_banding(GTK_TREE_VIEW(ih->handle), TRUE); #endif } @@ -1704,6 +1687,19 @@ static void gtkTreeCellTextEditingStarted(GtkCellRenderer *cell, GtkCellEditable PangoFontDescription* fontdesc = NULL; GdkColor *color = NULL; GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle)); + IFni cbShowRename; + + gtk_tree_model_get_iter_from_string(model, &iterItem, path_string); + + cbShowRename = (IFni)IupGetCallback(ih, "SHOWRENAME_CB"); + if (cbShowRename && cbShowRename(ih, gtkTreeFindNodeId(ih, &iterItem))==IUP_IGNORE) + { + /* TODO: non of these worked: + gtk_cell_renderer_stop_editing(cell, TRUE); + gtk_cell_editable_editing_done(editable); */ + gtk_editable_set_editable(GTK_EDITABLE(editable), FALSE); + return; + } value = iupAttribGetStr(ih, "RENAMECARET"); if (value) @@ -1713,7 +1709,6 @@ static void gtkTreeCellTextEditingStarted(GtkCellRenderer *cell, GtkCellEditable if (value) gtkTreeSetRenameSelectionPos(editable, value); - gtk_tree_model_get_iter_from_string(model, &iterItem, path_string); gtk_tree_model_get(model, &iterItem, IUPGTK_TREE_FONT, &fontdesc, -1); if (fontdesc) gtk_widget_modify_font(GTK_WIDGET(editable), fontdesc); @@ -1732,7 +1727,7 @@ static void gtkTreeCellTextEdited(GtkCellRendererText *cell, gchar *path_string, IFnis cbRename; if (!new_text) - return; + new_text = ""; model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle)); if (!gtk_tree_model_get_iter_from_string(model, &iterItem, path_string)) @@ -1741,7 +1736,7 @@ static void gtkTreeCellTextEdited(GtkCellRendererText *cell, gchar *path_string, cbRename = (IFnis)IupGetCallback(ih, "RENAME_CB"); if (cbRename) { - if (cbRename(ih, gtkTreeGetNodeId(ih, iterItem), iupgtkStrConvertFromUTF8(new_text)) == IUP_IGNORE) + if (cbRename(ih, gtkTreeFindNodeId(ih, &iterItem), iupgtkStrConvertFromUTF8(new_text)) == IUP_IGNORE) return; } @@ -1766,8 +1761,8 @@ static int gtkTreeCallDragDropCb(Ihandle* ih, GtkTreeIter *iterDrag, GtkTreeIter if (cbDragDrop) { - int drag_id = gtkTreeGetNodeId(ih, *iterDrag); - int drop_id = gtkTreeGetNodeId(ih, *iterDrop); + int drag_id = gtkTreeFindNodeId(ih, iterDrag); + int drop_id = gtkTreeFindNodeId(ih, iterDrop); return cbDragDrop(ih, drag_id, drop_id, is_shift, *is_ctrl); } @@ -1804,22 +1799,17 @@ static void gtkTreeDragDataReceived(GtkWidget *widget, GdkDragContext *context, { GtkTreeIter iterNewItem; - /* Copy the dragged item to the new position. */ - gtkTreeCopyNode(ih, model, &iterDrag, &iterDrop, &iterNewItem, is_ctrl); - - if (!is_ctrl) - { - /* do not delete the user data, we copy the references in CopyNode */ - gtk_tree_store_remove(GTK_TREE_STORE(model), &iterDrag); - } + /* Copy or move the dragged item to the new position. */ + gtkTreeCopyMoveNode(ih, model, &iterDrag, &iterDrop, &iterNewItem, is_ctrl); /* set focus and selection */ + if (iterNewItem.stamp) { GtkTreePath *pathNew; GtkTreeSelection* selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(ih->handle)); pathNew = gtk_tree_model_get_path(model, &iterNewItem); - gtk_tree_selection_select_path(selection, pathNew); + gtkTreeSelectNode(model, selection, &iterNewItem, 1); gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(ih->handle), pathNew, NULL, FALSE, 0, 0); gtk_tree_view_set_cursor(GTK_TREE_VIEW(ih->handle), pathNew, NULL, FALSE); @@ -1927,10 +1917,24 @@ static void gtkTreeDragBegin(GtkWidget *widget, GdkDragContext *context, Ihandle (void)widget; } +static gboolean gtkTreeSelectionFunc(GtkTreeSelection *selection, GtkTreeModel *model, GtkTreePath *path, gboolean selected, Ihandle* ih) +{ + GtkTreeIter iterItem; + gtk_tree_model_get_iter(model, &iterItem, path); + gtkTreeSelectNodeRaw(model, &iterItem, !selected); + (void)ih; + (void)selection; + return TRUE; +} + static void gtkTreeSelectionChanged(GtkTreeSelection* selection, Ihandle* ih) { IFnii cbSelec; int is_ctrl = 0; + (void)selection; + + if (iupAttribGet(ih, "_IUPTREE_IGNORE_SELECTION_CB")) + return; if (ih->data->mark_mode == ITREE_MARK_MULTIPLE) { @@ -1953,25 +1957,17 @@ static void gtkTreeSelectionChanged(GtkTreeSelection* selection, Ihandle* ih) if (cbSelec) { int curpos = -1, is_selected = 0; + GtkTreeIter iterFocus; + GtkTreePath* pathFocus; + GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle)); - if (iupAttribGet(ih, "_IUP_IGNORE_SELECTION")) - { - iupAttribSetStr(ih, "_IUP_IGNORE_SELECTION", NULL); - return; - } - + gtk_tree_view_get_cursor(GTK_TREE_VIEW(ih->handle), &pathFocus, NULL); + if (pathFocus) { - GtkTreeIter iterFocus; - GtkTreePath* pathFocus; - GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle)); - gtk_tree_view_get_cursor(GTK_TREE_VIEW(ih->handle), &pathFocus, NULL); - if (pathFocus) - { - gtk_tree_model_get_iter(model, &iterFocus, pathFocus); - gtk_tree_path_free(pathFocus); - curpos = gtkTreeGetNodeId(ih, iterFocus); - is_selected = gtk_tree_selection_iter_is_selected(selection, &iterFocus); - } + gtk_tree_model_get_iter(model, &iterFocus, pathFocus); + gtk_tree_path_free(pathFocus); + curpos = gtkTreeFindNodeId(ih, &iterFocus); + is_selected = gtkTreeIsNodeSelected(model, &iterFocus); } if (curpos == -1) @@ -1993,18 +1989,52 @@ static void gtkTreeSelectionChanged(GtkTreeSelection* selection, Ihandle* ih) } } +static void gtkTreeUpdateSelectionChildren(Ihandle* ih, GtkTreeModel* model, GtkTreeSelection* selection, GtkTreeIter *iterItem) +{ + int expanded; + GtkTreeIter iterChild; + int hasItem = gtk_tree_model_iter_children(model, &iterChild, iterItem); /* get the firstchild */ + while(hasItem) + { + if (gtkTreeIsNodeSelected(model, &iterChild)) + gtk_tree_selection_select_iter(selection, &iterChild); + + expanded = 0; + if (gtk_tree_model_iter_has_child(model, &iterChild)) + { + GtkTreePath* path = gtk_tree_model_get_path(model, &iterChild); + expanded = gtk_tree_view_row_expanded(GTK_TREE_VIEW(ih->handle), path); + gtk_tree_path_free(path); + } + + /* Recursive only if expanded */ + if (expanded) + gtkTreeUpdateSelectionChildren(ih, model, selection, &iterChild); + + /* Go to next sibling item */ + hasItem = gtk_tree_model_iter_next(model, &iterChild); + } +} + +static void gtkTreeRowExpanded(GtkTreeView* tree_view, GtkTreeIter *iterItem, GtkTreePath *path, Ihandle* ih) +{ + GtkTreeSelection* selection = gtk_tree_view_get_selection(tree_view); + GtkTreeModel* model = gtk_tree_view_get_model(tree_view); + iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", "1"); + gtkTreeUpdateSelectionChildren(ih, model, selection, iterItem); + iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", NULL); + (void)path; +} + static gboolean gtkTreeTestExpandRow(GtkTreeView* tree_view, GtkTreeIter *iterItem, GtkTreePath *path, Ihandle* ih) { IFni cbBranchOpen = (IFni)IupGetCallback(ih, "BRANCHOPEN_CB"); if (cbBranchOpen) { - if (iupAttribGet(ih, "_IUPTREE_IGNORE_BRANCHOPEN_CB")) - { - iupAttribSetStr(ih, "_IUPTREE_IGNORE_BRANCHOPEN_CB", NULL); + if (iupAttribGet(ih, "_IUPTREE_IGNORE_BRANCH_CB")) return FALSE; - } - if (cbBranchOpen(ih, gtkTreeGetNodeId(ih, *iterItem)) == IUP_IGNORE) + if (cbBranchOpen(ih, gtkTreeFindNodeId(ih, iterItem)) == IUP_IGNORE) return TRUE; /* prevent the change */ } @@ -2018,7 +2048,10 @@ static gboolean gtkTreeTestCollapseRow(GtkTreeView* tree_view, GtkTreeIter *iter IFni cbBranchClose = (IFni)IupGetCallback(ih, "BRANCHCLOSE_CB"); if (cbBranchClose) { - if (cbBranchClose(ih, gtkTreeGetNodeId(ih, *iterItem)) == IUP_IGNORE) + if (iupAttribGet(ih, "_IUPTREE_IGNORE_BRANCH_CB")) + return FALSE; + + if (cbBranchClose(ih, gtkTreeFindNodeId(ih, iterItem)) == IUP_IGNORE) return TRUE; } @@ -2042,7 +2075,7 @@ static void gtkTreeRowActived(GtkTreeView* tree_view, GtkTreePath *path, GtkTree /* just to leaf nodes */ if(gtk_tree_model_iter_has_child(model, &iterItem) == 0 && kind == ITREE_LEAF) - cbExecuteLeaf(ih, gtkTreeGetNodeId(ih, iterItem)); + cbExecuteLeaf(ih, gtkTreeFindNodeId(ih, &iterItem)); (void)column; (void)tree_view; @@ -2057,11 +2090,57 @@ static int gtkTreeConvertXYToPos(Ihandle* ih, int x, int y) GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle)); gtk_tree_model_get_iter(model, &iterItem, path); gtk_tree_path_free (path); - return gtkTreeGetNodeId(ih, iterItem); + return gtkTreeFindNodeId(ih, &iterItem); } return -1; } +static Iarray* gtkTreeGetSelectedArrayId(Ihandle* ih) +{ + Iarray* selarray = iupArrayCreate(1, sizeof(int)); + int i; + GtkTreeIter iterItem; + GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle)); + + for (i = 0; i < ih->data->node_count; i++) + { + gtkTreeIterInit(ih, &iterItem, ih->data->node_cache[i].node_handle); + if (gtkTreeIsNodeSelected(model, &iterItem)) + { + int* id_hitem = (int*)iupArrayInc(selarray); + int j = iupArrayCount(selarray); + id_hitem[j-1] = i; + } + } + + return selarray; +} + +static void gtkTreeCallMultiUnSelectionCb(Ihandle* ih) +{ + IFnIi cbMulti = (IFnIi)IupGetCallback(ih, "MULTIUNSELECTION_CB"); + IFnii cbSelec = (IFnii)IupGetCallback(ih, "SELECTION_CB"); + if (cbSelec || cbMulti) + { + Iarray* markedArray = gtkTreeGetSelectedArrayId(ih); + int* id_hitem = (int*)iupArrayGetData(markedArray); + int i, count = iupArrayCount(markedArray); + + if (count > 1) + { + if (cbMulti) + cbMulti(ih, id_hitem, iupArrayCount(markedArray)); + else + { + for (i=0; i<count; i++) + cbSelec(ih, id_hitem[i], 0); + } + } + + iupArrayDestroy(markedArray); + } +} + static gboolean gtkTreeButtonEvent(GtkWidget *treeview, GdkEventButton *evt, Ihandle* ih) { if (iupgtkButtonEvent(treeview, evt, ih) == TRUE) @@ -2097,6 +2176,18 @@ static gboolean gtkTreeButtonEvent(GtkWidget *treeview, GdkEventButton *evt, Iha gtk_tree_path_free(path); } } + else if (evt->type == GDK_BUTTON_PRESS && evt->button == 1) /* left single press */ + { + iupAttribSetInt(ih, "_IUPTREE_DRAG_X", (int)evt->x); + iupAttribSetInt(ih, "_IUPTREE_DRAG_Y", (int)evt->y); + + if (ih->data->mark_mode==ITREE_MARK_MULTIPLE && + !(evt->state & GDK_SHIFT_MASK) && !(evt->state & GDK_CONTROL_MASK)) + { + gtkTreeCallMultiUnSelectionCb(ih); + iupAttribSetStr(ih, "_IUPTREE_EXTENDSELECT", "1"); + } + } else if (evt->type == GDK_BUTTON_RELEASE && evt->button == 1) /* left single release */ { if (ih->data->mark_mode==ITREE_MARK_MULTIPLE && (evt->state & GDK_SHIFT_MASK)) @@ -2109,16 +2200,7 @@ static gboolean gtkTreeButtonEvent(GtkWidget *treeview, GdkEventButton *evt, Iha iupAttribSetStr(ih, "_IUPTREE_EXTENDSELECT", "2"); } } - else if (evt->type == GDK_BUTTON_PRESS && evt->button == 1) /* left single press */ - { - iupAttribSetInt(ih, "_IUPTREE_DRAG_X", (int)evt->x); - iupAttribSetInt(ih, "_IUPTREE_DRAG_Y", (int)evt->y); - if (ih->data->mark_mode==ITREE_MARK_MULTIPLE && - !(evt->state & GDK_SHIFT_MASK) && !(evt->state & GDK_CONTROL_MASK)) - iupAttribSetStr(ih, "_IUPTREE_EXTENDSELECT", "1"); - } - return FALSE; } @@ -2159,29 +2241,14 @@ static void gtkTreeEnableDragDrop(Ihandle* ih) { "GTK_TREE_MODEL_ROW", GTK_TARGET_SAME_WIDGET, 0 } }; - if (iupAttribGetBoolean(ih, "AUTODRAGDROP")) - { - gtk_tree_view_enable_model_drag_source (GTK_TREE_VIEW(ih->handle), - GDK_BUTTON1_MASK, - row_targets, - G_N_ELEMENTS(row_targets), - GDK_ACTION_MOVE|GDK_ACTION_COPY); - gtk_tree_view_enable_model_drag_dest (GTK_TREE_VIEW(ih->handle), - row_targets, - G_N_ELEMENTS(row_targets), - GDK_ACTION_MOVE|GDK_ACTION_COPY); - } - else - { - gtk_drag_source_set(ih->handle, GDK_BUTTON1_MASK, row_targets, G_N_ELEMENTS(row_targets), GDK_ACTION_MOVE|GDK_ACTION_COPY); - gtk_drag_dest_set(ih->handle, GDK_BUTTON1_MASK, row_targets, G_N_ELEMENTS(row_targets), GDK_ACTION_MOVE|GDK_ACTION_COPY); + gtk_drag_source_set(ih->handle, GDK_BUTTON1_MASK, row_targets, G_N_ELEMENTS(row_targets), GDK_ACTION_MOVE|GDK_ACTION_COPY); + gtk_drag_dest_set(ih->handle, GDK_BUTTON1_MASK, row_targets, G_N_ELEMENTS(row_targets), GDK_ACTION_MOVE|GDK_ACTION_COPY); - g_signal_connect(G_OBJECT(ih->handle), "drag-begin", G_CALLBACK(gtkTreeDragBegin), ih); - g_signal_connect(G_OBJECT(ih->handle), "drag-motion", G_CALLBACK(gtkTreeDragMotion), ih); - g_signal_connect(G_OBJECT(ih->handle), "drag-leave", G_CALLBACK(gtkTreeDragLeave), NULL); - g_signal_connect(G_OBJECT(ih->handle), "drag-drop", G_CALLBACK(gtkTreeDragDrop), ih); - g_signal_connect(G_OBJECT(ih->handle), "drag-data-received", G_CALLBACK(gtkTreeDragDataReceived), ih); - } + g_signal_connect(G_OBJECT(ih->handle), "drag-begin", G_CALLBACK(gtkTreeDragBegin), ih); + g_signal_connect(G_OBJECT(ih->handle), "drag-motion", G_CALLBACK(gtkTreeDragMotion), ih); + g_signal_connect(G_OBJECT(ih->handle), "drag-leave", G_CALLBACK(gtkTreeDragLeave), NULL); + g_signal_connect(G_OBJECT(ih->handle), "drag-drop", G_CALLBACK(gtkTreeDragDrop), ih); + g_signal_connect(G_OBJECT(ih->handle), "drag-data-received", G_CALLBACK(gtkTreeDragDataReceived), ih); } /*****************************************************************************/ @@ -2194,8 +2261,16 @@ static int gtkTreeMapMethod(Ihandle* ih) GtkTreeSelection* selection; GtkTreeViewColumn *column; - store = gtk_tree_store_new(9, GDK_TYPE_PIXBUF, G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF, G_TYPE_BOOLEAN, - G_TYPE_STRING, G_TYPE_INT, GDK_TYPE_COLOR, PANGO_TYPE_FONT_DESCRIPTION, G_TYPE_POINTER); + store = gtk_tree_store_new(IUPGTK_TREE_LAST_DATA, + GDK_TYPE_PIXBUF, /* IUPGTK_TREE_IMAGE */ + G_TYPE_BOOLEAN, /* IUPGTK_TREE_HAS_IMAGE */ + GDK_TYPE_PIXBUF, /* IUPGTK_TREE_IMAGE_EXPANDED */ + G_TYPE_BOOLEAN, /* IUPGTK_TREE_HAS_IMAGE_EXPANDED */ + G_TYPE_STRING, /* IUPGTK_TREE_TITLE */ + G_TYPE_INT, /* IUPGTK_TREE_KIND */ + GDK_TYPE_COLOR, /* IUPGTK_TREE_COLOR */ + PANGO_TYPE_FONT_DESCRIPTION, /* IUPGTK_TREE_FONT */ + G_TYPE_BOOLEAN); /* IUPGTK_TREE_SELECT */ ih->handle = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); @@ -2262,8 +2337,9 @@ static int gtkTreeMapMethod(Ihandle* ih) gtk_scrolled_window_set_policy(scrolled_window, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(ih->handle)); - gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE); + gtk_tree_selection_set_select_function(selection, (GtkTreeSelectionFunc)gtkTreeSelectionFunc, ih, NULL); + gtk_tree_view_set_reorderable(GTK_TREE_VIEW(ih->handle), FALSE); /* callbacks */ @@ -2279,6 +2355,7 @@ static int gtkTreeMapMethod(Ihandle* ih) g_signal_connect(G_OBJECT(ih->handle), "show-help", G_CALLBACK(iupgtkShowHelp), ih); g_signal_connect(G_OBJECT(ih->handle), "motion-notify-event",G_CALLBACK(iupgtkMotionNotifyEvent), ih); + g_signal_connect(G_OBJECT(ih->handle), "row-expanded", G_CALLBACK(gtkTreeRowExpanded), ih); g_signal_connect(G_OBJECT(ih->handle), "test-expand-row", G_CALLBACK(gtkTreeTestExpandRow), ih); g_signal_connect(G_OBJECT(ih->handle), "test-collapse-row", G_CALLBACK(gtkTreeTestCollapseRow), ih); g_signal_connect(G_OBJECT(ih->handle), "row-activated", G_CALLBACK(gtkTreeRowActived), ih); @@ -2301,7 +2378,8 @@ static int gtkTreeMapMethod(Ihandle* ih) ih->data->def_image_collapsed = iupImageGetImage("IMGCOLLAPSED", ih, 0); ih->data->def_image_expanded = iupImageGetImage("IMGEXPANDED", ih, 0); - gtkTreeAddRootNode(ih); + if (iupAttribGetInt(ih, "ADDROOT")) + iupdrvTreeAddNode(ih, "-1", ITREE_BRANCH, "", 0); /* configure for DRAG&DROP of files */ if (IupGetCallback(ih, "DROPFILES_CB")) @@ -2309,13 +2387,23 @@ static int gtkTreeMapMethod(Ihandle* ih) IupSetCallback(ih, "_IUP_XY2POS_CB", (Icallback)gtkTreeConvertXYToPos); + iupdrvTreeUpdateMarkMode(ih); + return IUP_NOERROR; } +static void gtkTreeUnMapMethod(Ihandle* ih) +{ + ih->data->node_count = 0; + + iupdrvBaseUnMapMethod(ih); +} + void iupdrvTreeInitClass(Iclass* ic) { /* Driver Dependent Class functions */ ic->Map = gtkTreeMapMethod; + ic->UnMap = gtkTreeUnMapMethod; /* Visual */ iupClassRegisterAttribute(ic, "BGCOLOR", NULL, gtkTreeSetBgColorAttrib, IUPAF_SAMEASSYSTEM, "TXTBGCOLOR", IUPAF_DEFAULT); @@ -2324,7 +2412,6 @@ void iupdrvTreeInitClass(Iclass* ic) /* IupTree Attributes - GENERAL */ iupClassRegisterAttribute(ic, "EXPANDALL", NULL, gtkTreeSetExpandAllAttrib, NULL, NULL, IUPAF_WRITEONLY|IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "INDENTATION", gtkTreeGetIndentationAttrib, gtkTreeSetIndentationAttrib, NULL, NULL, IUPAF_DEFAULT); - iupClassRegisterAttribute(ic, "COUNT", gtkTreeGetCountAttrib, NULL, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_READONLY|IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "DRAGDROP", NULL, iupgtkSetDragDropAttrib, NULL, NULL, IUPAF_NO_INHERIT); iupClassRegisterAttribute(ic, "SPACING", iupTreeGetSpacingAttrib, gtkTreeSetSpacingAttrib, NULL, NULL, IUPAF_NOT_MAPPED); iupClassRegisterAttribute(ic, "TOPITEM", NULL, gtkTreeSetTopItemAttrib, NULL, NULL, IUPAF_WRITEONLY|IUPAF_NO_INHERIT); @@ -2345,7 +2432,6 @@ void iupdrvTreeInitClass(Iclass* ic) iupClassRegisterAttributeId(ic, "COLOR", gtkTreeGetColorAttrib, gtkTreeSetColorAttrib, IUPAF_NO_INHERIT); iupClassRegisterAttributeId(ic, "NAME", gtkTreeGetTitleAttrib, gtkTreeSetTitleAttrib, IUPAF_NO_INHERIT); iupClassRegisterAttributeId(ic, "TITLE", gtkTreeGetTitleAttrib, gtkTreeSetTitleAttrib, IUPAF_NO_INHERIT); - iupClassRegisterAttributeId(ic, "USERDATA", gtkTreeGetUserDataAttrib, gtkTreeSetUserDataAttrib, IUPAF_NO_STRING|IUPAF_NO_INHERIT); iupClassRegisterAttributeId(ic, "CHILDCOUNT", gtkTreeGetChildCountAttrib, NULL, IUPAF_READONLY|IUPAF_NO_INHERIT); iupClassRegisterAttributeId(ic, "TITLEFONT", gtkTreeGetTitleFontAttrib, gtkTreeSetTitleFontAttrib, IUPAF_NO_INHERIT); @@ -2355,6 +2441,7 @@ void iupdrvTreeInitClass(Iclass* ic) iupClassRegisterAttribute (ic, "MARK", NULL, gtkTreeSetMarkAttrib, NULL, NULL, IUPAF_WRITEONLY|IUPAF_NO_INHERIT); iupClassRegisterAttribute (ic, "STARTING", NULL, gtkTreeSetMarkStartAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT); iupClassRegisterAttribute (ic, "MARKSTART", NULL, gtkTreeSetMarkStartAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT); + iupClassRegisterAttribute (ic, "MARKEDNODES", gtkTreeGetMarkedNodesAttrib, gtkTreeSetMarkedNodesAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT); iupClassRegisterAttribute (ic, "VALUE", gtkTreeGetValueAttrib, gtkTreeSetValueAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT); @@ -2363,7 +2450,7 @@ void iupdrvTreeInitClass(Iclass* ic) iupClassRegisterAttribute(ic, "RENAME", NULL, gtkTreeSetRenameAttrib, NULL, NULL, IUPAF_WRITEONLY|IUPAF_NO_INHERIT); iupClassRegisterAttributeId(ic, "MOVENODE", NULL, gtkTreeSetMoveNodeAttrib, IUPAF_NOT_MAPPED|IUPAF_WRITEONLY|IUPAF_NO_INHERIT); iupClassRegisterAttributeId(ic, "COPYNODE", NULL, gtkTreeSetCopyNodeAttrib, IUPAF_NOT_MAPPED|IUPAF_WRITEONLY|IUPAF_NO_INHERIT); - iupClassRegisterAttributeId(ic, "FINDUSERDATA", gtkTreeGetFindUserDataAttrib, NULL, IUPAF_READONLY|IUPAF_NO_INHERIT); - iupClassRegisterAttribute (ic, "AUTODRAGDROP", NULL, NULL, NULL, NULL, IUPAF_DEFAULT); + /* IupTree Attributes - GTK Only */ + iupClassRegisterAttribute (ic, "RUBBERBAND", NULL, NULL, IUPAF_SAMEASSYSTEM, "YES", IUPAF_NO_INHERIT); } |