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 }