build git 2.17.1
[AROS-Contrib.git] / bgui / gadgets / TreeView / TVInsert.c
blobee4d2fb89d1b7e5604f2b36df735991e69166c03
1 /*
2 * @(#) $Header$
4 * BGUI Tree List View class
6 * (C) Copyright 1999 Manuel Lemos.
7 * (C) Copyright 1996-1999 Nick Christie.
8 * All Rights Reserved.
10 * $Log$
11 * Revision 42.2 2004/06/16 20:16:49 verhaegs
12 * Use METHODPROTO, METHOD_END and REGFUNCPROTOn where needed.
14 * Revision 42.1 2000/05/15 19:29:08 stegerg
15 * replacements for REG macro
17 * Revision 42.0 2000/05/09 22:21:45 mlemos
18 * Bumped to revision 42.0 before handing BGUI to AROS team
20 * Revision 41.11 2000/05/09 20:35:31 mlemos
21 * Bumped to revision 41.11
23 * Revision 1.2 2000/05/09 20:00:30 mlemos
24 * Merged with the branch Manuel_Lemos_fixes.
26 * Revision 1.1.2.2 1999/05/31 01:12:51 mlemos
27 * Made the method functions take the arguments in the apropriate registers.
29 * Revision 1.1.2.1 1999/02/21 04:07:44 mlemos
30 * Nick Christie sources.
36 /************************************************************************
37 *********************** TREEVIEW CLASS: INSERT ************************
38 ************************************************************************/
40 /************************************************************************
41 ****************************** INCLUDES *******************************
42 ************************************************************************/
44 #include "TreeViewPrivate.h"
45 #include "TVUtil.h"
47 /************************************************************************
48 ************************** LOCAL DEFINITIONS **************************
49 ************************************************************************/
52 /************************************************************************
53 ************************* EXTERNAL REFERENCES *************************
54 ************************************************************************/
57 * Functions from TVUtil are listed in TVUtil.h
60 /************************************************************************
61 ***************************** PROTOTYPES ******************************
62 ************************************************************************/
65 /************************************************************************
66 ***************************** LOCAL DATA ******************************
67 ************************************************************************/
70 /************************************************************************
71 ***************************** TV_INSERT() *****************************
72 *************************************************************************
73 * Insert a new entry into the treeview. In the message structure for
74 * this method, the user includes the entry to insert, a relation entry
75 * to serve as reference for the insertion position, a code to indicate
76 * what kind of relationship there should be between the new entry and
77 * the relation, plus some flags to expand the new node, select it, etc.
78 * This method returns non-zero if successful, zero on failure.
80 * Special values allowed for the relation entry are:
81 * TV_ROOT to represent the root of the tree (a dummy entry).
82 * TV_SELECTED for the (first) currently selected entry.
84 * If the relation entry is TV_SELECTED, but no entry is currently
85 * selected, the entry is not inserted and zero is returned.
87 * Permitted values for the relationship code are as follows:
88 * TVW_CHILD_FIRST first child of relation
89 * TVW_CHILD_LAST last child of relation
90 * TVW_CHILD_SORTED child of relation, sorted
91 * TVW_SIBLING_FIRST first sibling of relation
92 * TVW_SIBLING_LAST last sibling of relation
93 * TVW_SIBLING_NEXT next sibling of relation
94 * TVW_SIBLING_PREV prev. sibling of relation
95 * TVW_SIBLING_SORTED sibling of relation, sorted
97 * If the relation entry is TV_ROOT, only the TVW_CHILD_??? codes are
98 * permitted.
100 * Permitted bits for the flags parameter are:
101 * TVF_SELECT select entry
102 * TVF_MULTISELECT multi-select entry (with TVF_SELECT)
103 * TVF_MAKEVISIBLE make entry visible
104 * TVF_EXPAND expand entry
106 * The new entry will be displayed in the treeview only if all its parents
107 * are expanded, or a flag such as TVF_SELECT is used. In that case,
108 * parents will be expanded as required to bring the new entry into view
109 * and/or select it.
111 *************************************************************************/
113 METHOD(TV_Insert, struct tvInsert *, tvi)
115 TVData *tv;
116 TNPTR tn,prevtn = NULL,par,tr,sr = NULL;
117 LISTPTR list;
118 ULONG rc,tvflags,lvflags,pos;
120 TV_DebugDumpMethod((Msg) tvi);
122 tv = (TVData *) INST_DATA(cl,obj);
123 rc = 0;
124 pos = ~0;
125 tvflags = 0;
126 lvflags = 0;
129 * Set expanded flag if requested
132 if (tvi->tvi_Flags & TVF_EXPAND)
133 tvflags |= TNF_EXPANDED;
136 * Allocate a new node for the entry and initialise it's child list.
139 if ((tn = TV_AllocTreeNode(tv,tvi->tvi_Entry,tvflags)))
142 * Locate the treenode corresponding to the relation entry,
143 * which may be TV_SELECTED for the first selected entry.
146 list = NULL;
147 tr = NULL;
149 if (tvi->tvi_Relation == TV_ROOT)
152 * Relation is the dummy root node, only TVWS_CHILD_? permitted
155 if ((tvi->tvi_Where & TVWC_MASK) == TVWC_CHILD)
156 tr = &tv->tv_RootNode;
158 else if (tvi->tvi_Relation == TV_SELECTED)
159 /* relation is the first selected entry */
160 tr = (TNPTR) DoMethod(tv->tv_Listview,LVM_FIRSTENTRY,NULL,LVGEF_SELECTED);
161 else if (tvi->tvi_Flags & TVF_INTERNAL)
162 /* internal reference, already a TreeNode ptr */
163 tr = tvi->tvi_Relation;
164 else
165 /* a user's entry: find its TreeNode */
166 tr = TV_FindTreeNode(RootList(tv),tvi->tvi_Relation);
168 if (tr)
170 if ((tvi->tvi_Where & TVWC_MASK) == TVWC_CHILD)
171 par = tr; /* parent is relation */
172 else if ((tvi->tvi_Where & TVWC_MASK) == TVWC_SIB)
173 par = ParentOf(tr); /* parent is relation's parent */
174 else
175 par = NULL; /* no other category allowed */
177 if (par)
179 list = ChildListOf(par);
180 pos = ~0;
182 switch(tvi->tvi_Where & TVWS_MASK)
184 case TVWS_FIRST: /* first child/sibling of relation */
185 prevtn = NULL;
186 sr = par;
187 break;
189 case TVWS_LAST: /* last child/sibling of relation */
190 prevtn = LastChildIn(list);
191 sr = TV_LastDisplayedChild(par);
192 break;
194 case TVWS_NEXT: /* next sibling of relation */
195 if ((tvi->tvi_Where & TVWC_MASK) == TVWC_SIB)
197 prevtn = tr;
198 sr = TV_LastDisplayedChild(prevtn);
200 else
201 list = NULL;
202 break;
204 case TVWS_PREV: /* prev. sibling of relation */
205 if ((tvi->tvi_Where & TVWC_MASK) == TVWC_SIB)
207 prevtn = PrevSiblingOf(tr);
208 sr = prevtn ? prevtn : par;
210 else
211 list = NULL;
212 break;
214 case TVWS_SORT: /* sorted child/sibling of relation */
215 prevtn = TV_SortedPrev(tv,list,tn);
216 sr = prevtn ? TV_LastDisplayedChild(prevtn) : par;
217 break;
219 default: /* no other tvi_Where allowed */
220 list = NULL;
221 break;
223 } /* end switch(tvi->tvi_Where & TVWS_MASK) */
225 if (list)
227 if (TV_IsDisplayed(prevtn ? prevtn : par))
228 pos = TV_TreeNodeToIndex(tv,sr) + 1;
231 } /* endif got parent */
233 } /* endif found relation */
235 if (list) /* passed all tests above */
238 * Add the new entry to the child list of the parent node
239 * (the rootlist if there is no parent) and bump up the total
240 * count of entries. If the new entry has a parent, put in
241 * the link to the parent and increment the parent's child count.
244 Insert(list,(NODEPTR) tn,(NODEPTR) prevtn);
245 tv->tv_NumEntries++;
247 if (par)
249 tn->tn_Parent = par;
250 par->tn_NumChildren++;
254 * If we have a position for the entry in the listview,
255 * and the parent is either expanded, or the root entry,
256 * insert the entry in the listview.
259 if ((pos != ~0) && (!par || IsExpanded(par)))
260 rc = DoMethod(tv->tv_Listview,LVM_INSERTSINGLE,tvi->tvi_GInfo,
261 pos, tn, lvflags);
262 else
265 * If tv_NoLeafImage is set, and this new entry is the
266 * first child of its parent, we need to refresh the
267 * parent as the image will be applicable.
270 if (tv->tv_NoLeafImage && par && (par->tn_NumChildren == 1))
271 DoMethod(obj,TVM_REFRESH,tvi->tvi_GInfo);
273 rc = 1;
276 if (rc) /* new entry added to listview */
279 * User wants us to make the new entry visible?
282 if (tvi->tvi_Flags & TVF_MAKEVISIBLE)
283 DoMethod(obj,TVM_VISIBLE,tvi->tvi_GInfo,tn,
284 TVW_ENTRY,TVF_INTERNAL);
286 * User wants us to select the new entry, as well?
289 if (tvi->tvi_Flags & TVF_SELECT)
290 DoMethod(obj,TVM_SELECT,tvi->tvi_GInfo,tn,TVW_ENTRY,
291 TVF_INTERNAL|(tvi->tvi_Flags & TVF_MULTISELECT));
293 else /* failed to add to listview */
295 Remove((NODEPTR) tn);
296 TV_FreeTreeNode(tv,tn);
297 tv->tv_NumEntries--;
298 if (par)
299 par->tn_NumChildren--;
302 } /* endif got list */
303 else
304 TV_FreeTreeNode(tv,tn);
306 } /* endif alloctreenode */
308 return(rc);
310 METHOD_END