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