1 /*
2  * This file is part of gtkD.
3  *
4  * gtkD is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU Lesser General Public License
6  * as published by the Free Software Foundation; either version 3
7  * of the License, or (at your option) any later version, with
8  * some exceptions, please read the COPYING file.
9  *
10  * gtkD is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public License
16  * along with gtkD; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
18  */
19  
20 // generated automatically - do not change
21 // find conversion definition on APILookup.txt
22 // implement new conversion functionalities on the wrap.utils pakage
23 
24 /*
25  * Conversion parameters:
26  * inFile  = 
27  * outPack = gtk
28  * outFile = TreeIter
29  * strct   = GtkTreeIter
30  * realStrct=
31  * ctorStrct=
32  * clss    = TreeIter
33  * interf  = 
34  * class Code: Yes
35  * interface Code: No
36  * template for:
37  * extend  = 
38  * implements:
39  * prefixes:
40  * 	- gtk_tree_iter_
41  * omit structs:
42  * omit prefixes:
43  * omit code:
44  * 	- gtk_tree_iter_copy
45  * 	- gtk_tree_iter_free
46  * omit signals:
47  * 	- row-changed
48  * 	- row-deleted
49  * 	- row-has-child-toggled
50  * 	- row-inserted
51  * 	- rows-reordered
52  * imports:
53  * 	- glib.Str
54  * 	- gobject.Value
55  * 	- gtk.TreeIterError
56  * 	- gtk.TreeModelIF
57  * 	- gtk.TreePath
58  * structWrap:
59  * 	- GtkTreeIter* -> TreeIter
60  * module aliases:
61  * local aliases:
62  * overrides:
63  */
64 
65 module gtk.TreeIter;
66 
67 public  import gtkc.gtktypes;
68 
69 private import gtkc.gtk;
70 private import glib.ConstructionException;
71 private import gobject.ObjectG;
72 
73 private import gobject.Signals;
74 public  import gtkc.gdktypes;
75 private import glib.Str;
76 private import gobject.Value;
77 private import gtk.TreeIterError;
78 private import gtk.TreeModelIF;
79 private import gtk.TreePath;
80 
81 
82 
83 /**
84  * The GtkTreeModel interface defines a generic tree interface for
85  * use by the GtkTreeView widget. It is an abstract interface, and
86  * is designed to be usable with any appropriate data structure. The
87  * programmer just has to implement this interface on their own data
88  * type for it to be viewable by a GtkTreeView widget.
89  *
90  * The model is represented as a hierarchical tree of strongly-typed,
91  * columned data. In other words, the model can be seen as a tree where
92  * every node has different values depending on which column is being
93  * queried. The type of data found in a column is determined by using
94  * the GType system (ie. G_TYPE_INT, GTK_TYPE_BUTTON, G_TYPE_POINTER,
95  * etc). The types are homogeneous per column across all nodes. It is
96  * important to note that this interface only provides a way of examining
97  * a model and observing changes. The implementation of each individual
98  * model decides how and if changes are made.
99  *
100  * In order to make life simpler for programmers who do not need to
101  * write their own specialized model, two generic models are provided
102  * — the GtkTreeStore and the GtkListStore. To use these, the
103  * developer simply pushes data into these models as necessary. These
104  * models provide the data structure as well as all appropriate tree
105  * interfaces. As a result, implementing drag and drop, sorting, and
106  * storing data is trivial. For the vast majority of trees and lists,
107  * these two models are sufficient.
108  *
109  * Models are accessed on a node/column level of granularity. One can
110  * query for the value of a model at a certain node and a certain
111  * column on that node. There are two structures used to reference
112  * a particular node in a model. They are the GtkTreePath and the
113  * GtkTreeIter[4]. Most of the interface
114  * consists of operations on a GtkTreeIter.
115  *
116  * A path is essentially a potential node. It is a location on a model
117  * that may or may not actually correspond to a node on a specific
118  * model. The GtkTreePath struct can be converted into either an
119  * array of unsigned integers or a string. The string form is a list
120  * of numbers separated by a colon. Each number refers to the offset
121  * at that level. Thus, the path “0” refers to the root
122  * node and the path “2:4” refers to the fifth child of
123  * the third node.
124  *
125  * By contrast, a GtkTreeIter is a reference to a specific node on
126  * a specific model. It is a generic struct with an integer and three
127  * generic pointers. These are filled in by the model in a model-specific
128  * way. One can convert a path to an iterator by calling
129  * gtk_tree_model_get_iter(). These iterators are the primary way
130  * of accessing a model and are similar to the iterators used by
131  * GtkTextBuffer. They are generally statically allocated on the
132  * stack and only used for a short time. The model interface defines
133  * a set of operations using them for navigating the model.
134  *
135  * It is expected that models fill in the iterator with private data.
136  * For example, the GtkListStore model, which is internally a simple
137  * linked list, stores a list node in one of the pointers. The
138  * GtkTreeModelSort stores an array and an offset in two of the
139  * pointers. Additionally, there is an integer field. This field is
140  * generally filled with a unique stamp per model. This stamp is for
141  * catching errors resulting from using invalid iterators with a model.
142  *
143  * The lifecycle of an iterator can be a little confusing at first.
144  * Iterators are expected to always be valid for as long as the model
145  * is unchanged (and doesn't emit a signal). The model is considered
146  * to own all outstanding iterators and nothing needs to be done to
147  * free them from the user's point of view. Additionally, some models
148  * guarantee that an iterator is valid for as long as the node it refers
149  * to is valid (most notably the GtkTreeStore and GtkListStore).
150  * Although generally uninteresting, as one always has to allow for
151  * the case where iterators do not persist beyond a signal, some very
152  * important performance enhancements were made in the sort model.
153  * As a result, the GTK_TREE_MODEL_ITERS_PERSIST flag was added to
154  * indicate this behavior.
155  *
156  * To help show some common operation of a model, some examples are
157  * provided. The first example shows three ways of getting the iter at
158  * the location “3:2:5”. While the first method shown is
159  * easier, the second is much more common, as you often get paths from
160  * callbacks.
161  *
162  * $(DDOC_COMMENT example)
163  *
164  * This second example shows a quick way of iterating through a list
165  * and getting a string and an integer from each row. The
166  * populate_model function used below is not
167  * shown, as it is specific to the GtkListStore. For information on
168  * how to write such a function, see the GtkListStore documentation.
169  *
170  * $(DDOC_COMMENT example)
171  *
172  * The GtkTreeModel interface contains two methods for reference
173  * counting: gtk_tree_model_ref_node() and gtk_tree_model_unref_node().
174  * These two methods are optional to implement. The reference counting
175  * is meant as a way for views to let models know when nodes are being
176  * displayed. GtkTreeView will take a reference on a node when it is
177  * visible, which means the node is either in the toplevel or expanded.
178  * Being displayed does not mean that the node is currently directly
179  * visible to the user in the viewport. Based on this reference counting
180  * scheme a caching model, for example, can decide whether or not to cache
181  * a node based on the reference count. A file-system based model would
182  * not want to keep the entire file hierarchy in memory, but just the
183  * folders that are currently expanded in every current view.
184  *
185  * When working with reference counting, the following rules must be taken
186  * into account:
187  *
188  * Never take a reference on a node without owning a
189  * reference on its parent. This means that all parent nodes of a referenced
190  * node must be referenced as well.
191  *
192  * Outstanding references on a deleted node are not released.
193  * This is not possible because the node has already been deleted by the
194  * time the row-deleted signal is received.
195  *
196  * Models are not obligated to emit a signal on rows of
197  * which none of its siblings are referenced. To phrase this differently,
198  * signals are only required for levels in which nodes are referenced. For
199  * the root level however, signals must be emitted at all times (however the
200  * root level is always referenced when any view is attached).
201  */
202 public class TreeIter
203 {
204 	
205 	/** the main Gtk struct */
206 	protected GtkTreeIter* gtkTreeIter;
207 	
208 	
209 	/** Get the main Gtk struct */
210 	public GtkTreeIter* getTreeIterStruct()
211 	{
212 		return gtkTreeIter;
213 	}
214 	
215 	
216 	/** the main Gtk struct as a void* */
217 	protected void* getStruct()
218 	{
219 		return cast(void*)gtkTreeIter;
220 	}
221 	
222 	/**
223 	 * Sets our main struct and passes it to the parent class
224 	 */
225 	public this (GtkTreeIter* gtkTreeIter)
226 	{
227 		this.gtkTreeIter = gtkTreeIter;
228 	}
229 	
230 	/**
231 	 * this will be set only when the iter
232 	 * is created from the model.
233 	 */
234 	GtkTreeModel* gtkTreeModel;
235 	
236 	/** */
237 	public void setModel(GtkTreeModel* gtkTreeModel)
238 	{
239 		this.gtkTreeModel = gtkTreeModel;
240 	}
241 	
242 	/** */
243 	public void setModel(TreeModelIF treeModel)
244 	{
245 		this.gtkTreeModel = treeModel.getTreeModelTStruct();
246 	}
247 	
248 	/**
249 	 * Throws: ConstructionException GTK+ fails to create the object.
250 	 */
251 	public this(TreeModelIF treeModel, string treePath)
252 	{
253 		this(treeModel, new TreePath(treePath));
254 	}
255 	
256 	/**
257 	 * Throws: ConstructionException GTK+ fails to create the object.
258 	 */
259 	public this(TreeModelIF treeModel, TreePath treePath)
260 	{
261 		this();
262 		setModel(treeModel);
263 		if ( !gtk_tree_model_get_iter_from_string(
264 		treeModel.getTreeModelTStruct(),
265 		getTreeIterStruct(), Str.toStringz(treePath.toString())) )
266 		{
267 			throw new ConstructionException("null returned by gtk_tree_model_get_iter_from_string");
268 		}
269 	}
270 	
271 	/**
272 	 * creates a new tree iteractor.
273 	 * used TreeView.createIter and TreeView.append() to create iteractor for a tree or list
274 	 */
275 	this()
276 	{
277 		this(new GtkTreeIter);
278 	}
279 	
280 	/**
281 	 * Creates a dynamically allocated tree iterator as a copy of iter.
282 	 */
283 	TreeIter copy(TreeIter iter)
284 	{
285 		TreeIter cp = new TreeIter();
286 		 *(cp.gtkTreeIter) = *(iter.gtkTreeIter);
287 		
288 		return cp;
289 	}
290 	
291 	/**
292 	 * Get Value
293 	 * Params:
294 	 *  column =
295 	 *  value =
296 	 */
297 	void getValue(int column, Value value)
298 	{
299 		if ( gtkTreeModel  is  null )
300 		{
301 			throw new TreeIterError("getValue","Tree model not set");
302 		}
303 		gtk_tree_model_get_value(gtkTreeModel, gtkTreeIter, column, value.getValueStruct());
304 	}
305 	
306 	/**
307 	 * Get the value of a column as a string
308 	 * Params:
309 	 *  column = the column number
310 	 * Returns: a string representing the value of the column
311 	 */
312 	string getValueString(int column)
313 	{
314 		if ( gtkTreeModel  is  null )
315 		{
316 			throw new TreeIterError("getValueString","Tree model not set");
317 		}
318 		Value value = new Value();
319 		gtk_tree_model_get_value(gtkTreeModel, gtkTreeIter, column, value.getValueStruct());
320 		//printf("TreeIter.getValuaString = %.*s\n", value.getString().toString());
321 		return value.getString();
322 	}
323 	
324 	/**
325 	 * Get the value of a column as an int
326 	 * Params:
327 	 *  column = the column number
328 	 * Returns: a string representing the value of the column
329 	 */
330 	int getValueInt(int column)
331 	{
332 		if ( gtkTreeModel  is  null )
333 		{
334 			throw new TreeIterError("getValueInt", "Tree model not set");
335 		}
336 		Value value = new Value();
337 		gtk_tree_model_get_value(gtkTreeModel, gtkTreeIter, column, value.getValueStruct());
338 		return value.getInt();
339 	}
340 	
341 	/** */
342 	TreePath getTreePath()
343 	{
344 		if ( gtkTreeModel  is  null )
345 		{
346 			throw new TreeIterError("getTreePath","Tree model not set");
347 		}
348 		return new TreePath(gtk_tree_model_get_path(gtkTreeModel, gtkTreeIter));
349 	}
350 	
351 	/**
352 	 * This return the path visible to the user.
353 	 */
354 	string getVisiblePath(string separator)
355 	{
356 		string vPath;
357 		if ( gtkTreeModel  is  null )
358 		{
359 			throw new TreeIterError("getVisiblePath", "Tree model not set");
360 		}
361 		
362 		vPath = getValueString(0);
363 		TreeIter parent = getParent();
364 		while ( parent !is  null )
365 		{
366 			//printf("TreeIter.getVisiblePath parent = %.*s\n",parent.getValueString(0).toString());
367 			vPath = parent.getValueString(0) ~ separator ~ vPath;
368 			parent = parent.getParent();
369 		}
370 		
371 		//printf("TreeIter.getVisiblePath = %.*s\n", vPath.toString());
372 		
373 		return vPath;
374 	}
375 	
376 	/**
377 	 * Gets the parent of this iter
378 	 * Returns: the parent iter or null if can't get parent or an error occured
379 	 */
380 	TreeIter getParent()
381 	{
382 		if ( gtkTreeModel  is  null )
383 		{
384 			throw new TreeIterError("getParent", "Tree model not set");
385 		}
386 		TreeIter parent = new TreeIter();
387 		bool gotParent = gtk_tree_model_iter_parent(gtkTreeModel, parent.getTreeIterStruct(), gtkTreeIter) == 0 ? false : true;
388 		if ( !gotParent )
389 		{
390 			return null;
391 		}
392 		parent.setModel(gtkTreeModel);
393 		return parent;
394 	}
395 	
396 	/** */
397 	TreeIter getGrandParent()
398 	{
399 		if ( gtkTreeModel  is  null )
400 		{
401 			throw new TreeIterError("getGrandParent", "Tree model not set");
402 		}
403 		TreeIter grandParent = this;
404 		TreeIter parent = grandParent.getParent();
405 		while ( parent !is null )
406 		{
407 			grandParent = parent;
408 			parent = grandParent.getParent();
409 		}
410 		
411 		return grandParent;
412 	}
413 	
414 	/** A unique stamp to catch invalid iterators */
415 	public int stamp()
416 	{
417 		return gtkTreeIter.stamp;
418 	}
419 	
420 	/** Ditto */
421 	public void stamp(int stamp)
422 	{
423 		gtkTreeIter.stamp = stamp;
424 	}
425 	
426 	/** Model specific data */
427 	public void* userData()
428 	{
429 		return gtkTreeIter.userData;
430 	}
431 	
432 	/** Ditto */
433 	public void userData(void* data)
434 	{
435 		gtkTreeIter.userData = data;
436 	}
437 	
438 	public struct IterData
439 	{
440 		/// Data fields.
441 		union
442 		{
443 			int     dataInt;
444 			long    dataLong;
445 			double  dataFloat;
446 			double  dataDouble;
447 			string  dataString;
448 			
449 			void*   dataUser;
450 		}
451 		
452 		TypeInfo type = typeid(void);
453 	}
454 	
455 	/**
456 	 * setUserData and getUserData provide simple boxing
457 	 * around the userData field in the TreeIter struct.
458 	 * Throws: TreeIterError for unsuported types or a type mismatch.
459 	 * Example:
460 	 * ---
461 	 * Treeiter iter = new TreeIter();
462 	 *
463 	 * iter.setUserData(20);
464 	 * int i = iter.getUserData!(int)();
465 	 * ---
466 	 */
467 	public void setUserData(T)(T data)
468 	{
469 		IterData* itData = new IterData;
470 		itData.type = typeid(T);
471 		
472 		static if(is(T == int))
473 		{
474 			itData.dataInt = data;
475 		}
476 		else static if(is(T == long))
477 		{
478 			itData.dataLong = data;
479 		}
480 		else static if(is(T == float))
481 		{
482 			itData.dataFloat = data;
483 		}
484 		else static if(is(T == double))
485 		{
486 			itData.dataDouble = data;
487 		}
488 		else static if(is(T == string))
489 		{
490 			itData.dataString = data;
491 		}
492 		else static if(is(T == void*))
493 		{
494 			itData.dataUser = data;
495 		}
496 		else
497 		{
498 			pragma(msg, "IterData Type not Suported");
499 			
500 			throw new TreeIterError("getUserData", "IterData Type not Suported");
501 		}
502 		
503 		gtkTreeIter.userData = itData;
504 	}
505 	
506 	/** Ditto */
507 	public T getUserData(T)()
508 	{
509 		IterData* itData = cast(IterData*)gtkTreeIter.userData;
510 		
511 		static if(is(T == int))
512 		{
513 			if(itData.type is typeid(T))
514 			{
515 				return itData.dataInt;
516 			}
517 			else
518 			{
519 				throw new TreeIterError("getUserData", "IterData is not: int");
520 			}
521 		}
522 		else static if(is(T == long))
523 		{
524 			if(itData.type is typeid(T))
525 			{
526 				return itData.dataLong;
527 			}
528 			else
529 			{
530 				throw new TreeIterError("getUserData", "IterData is not: long");
531 			}
532 		}
533 		else static if(is(T == float))
534 		{
535 			if(itData.type is typeid(T))
536 			{
537 				return itData.dataFloat;
538 			}
539 			else
540 			{
541 				throw new TreeIterError("getUserData", "IterData is not: float");
542 			}
543 		}
544 		else static if(is(T == double))
545 		{
546 			if(itData.type is typeid(T))
547 			{
548 				return itData.dataDouble;
549 			}
550 			else
551 			{
552 				throw new TreeIterError("getUserData", "IterData is not: double");
553 			}
554 		}
555 		else static if(is(T == string))
556 		{
557 			if(itData.type is typeid(T))
558 			{
559 				return itData.dataString;
560 			}
561 			else
562 			{
563 				throw new TreeIterError("getUserData", "IterData is not: string");
564 			}
565 		}
566 		else static if(is(T == void*))
567 		{
568 			if(itData.type is typeid(T))
569 			{
570 				return itData.dataUser;
571 			}
572 			else
573 			{
574 				throw new TreeIterError("getUserData", "IterData is not: void*");
575 			}
576 		}
577 		else
578 		{
579 			pragma(msg, "IterData Type not Suported");
580 			
581 			throw new TreeIterError("getUserData", "IterData Type not Suported");
582 		}
583 	}
584 	
585 	/**
586 	 */
587 }