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 }