/src/wrappers/gtk/library/gtk_tree_model.e
Specman e | 615 lines | 252 code | 82 blank | 281 comment | 9 complexity | d06473649b6db42984f8dea851583a92 MD5 | raw file
1indexing 2 description: "GtkTreeModel -- The tree interface used by GtkTreeView." 3 copyright: "[ 4 Copyright (C) 2006 eiffel-libraries team, GTK+ team 5 6 This library is free software; you can redistribute it and/or 7 modify it under the terms of the GNU Lesser General Public License 8 as published by the Free Software Foundation; either version 2.1 of 9 the License, or (at your option) any later version. 10 11 This library is distributed in the hope that it will be useful, but 12 WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 Lesser General Public License for more details. 15 16 You should have received a copy of the GNU Lesser General Public 17 License along with this library; if not, write to the Free Software 18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19 02110-1301 USA 20 ]" 21 22deferred class GTK_TREE_MODEL 23 -- The GtkTreeModel interface defines a generic tree interface for use by the 24 -- GtkTreeView widget. It is an abstract interface, and is designed to be 25 -- usable with any appropriate data structure. The programmer just has to 26 -- implement this interface on their own data type for it to be viewable by a 27 -- GtkTreeView widget. 28 29 -- The model is represented as a hierarchical tree of strongly-typed, 30 -- columned data. In other words, the model can be seen as a tree where every 31 -- node has different values depending on which column is being queried. The 32 -- type of data found in a column is determined by using the GType system 33 -- (ie. `g_type_int,' `gtk_type_button,' `g_type_pointer,' etc.). The types 34 -- are homogeneous per column across all nodes. It is important to note that 35 -- this interface only provides a way of examining a model and observing 36 -- changes. The implementation of each individual model decides how and if 37 -- changes are made. 38 39 -- In order to make life simpler for programmers who do not need to write 40 -- their own specialized model, two generic models are provided: the 41 -- GtkTreeStore and the GtkListStore. To use these, the developer simply 42 -- pushes data into these models as necessary. These models provide the data 43 -- structure as well as all appropriate tree interfaces. As a result, 44 -- implementing drag and drop, sorting, and storing data is trivial. For the 45 -- vast majority of trees and lists, these two models are sufficient. 46 47 -- Models are accessed on a node/column level of granularity. One can query 48 -- for the value of a model at a certain node and a certain column on that 49 -- node. There are two structures used to reference a particular node in a 50 -- model. They are the GtkTreePath and the GtkTreeIter. Most of the interface 51 -- consists of operations on a GtkTreeIter. 52 53 -- A path is essentially a potential node. It is a location on a model that 54 -- may or may not actually correspond to a node on a specific model. The 55 -- GtkTreePath struct can be converted into either an array of unsigned 56 -- integers or a string. The string form is a list of numbers separated by a 57 -- colon. Each number refers to the offset at that level. Thus, the path 0: 58 -- refers to the root node and the path "refers" to the fifth child of 59 -- the third node. 60 61 -- By contrast, a GtkTreeIter is a reference to a specific node on 62 -- a specific model. It is a generic struct with an integer and 63 -- three generic pointers. These are filled in by the model in a 64 -- model-specific way. One can convert a path to an iterator by 65 -- calling `get_new_iterator'. These iterators are the primary way 66 -- of accessing a model and are similar to the iterators used by 67 -- GtkTextBuffer. They are generally statically allocated on the 68 -- stack and only used for a short time. The model interface 69 -- defines a set of operations using them for navigating the model. 70 71 -- It is expected that models fill in the iterator with private 72 -- data. For example, the GtkListStore model, which is internally a 73 -- simple linked list, stores a list node in one of the 74 -- pointers. The GtkTreeModelSort stores an array and an offset in 75 -- two of the pointers. Additionally, there is an integer 76 -- field. This field is generally filled with a unique stamp per 77 -- model. This stamp is for catching errors resulting from using 78 -- invalid iterators with a model. 79 80 -- The lifecycle of an iterator can be a little confusing at 81 -- first. Iterators are expected to always be valid for as long as 82 -- the model is unchanged (and doesn't emit a signal). The model is 83 -- considered to own all outstanding iterators and nothing needs to 84 -- be done to free them from the user's point of 85 -- view. Additionally, some models guarantee that an iterator is 86 -- valid for as long as the node it refers to is valid (most 87 -- notably the GtkTreeStore and GtkListStore). Although generally 88 -- uninteresting, as one always has to allow for the case where 89 -- iterators do not persist beyond a signal, some very important 90 -- performance enhancements were made in the sort model. As a 91 -- result, the GTK_TREE_MODEL_ITERS_PERSIST flag was added to 92 -- indicate this behavior. 93 94inherit 95 -- G_INTERFACE 96 -- Prerequisites: GtkTreeModel requires GObject. 97 G_OBJECT 98 99 -- Known Derived Interfaces: GtkTreeModel is required by 100 -- GtkTreeSortable. 101 102 -- Known Implementations: GtkTreeModel is implemented by 103 -- GtkTreeModelSort, GtkTreeStore, GtkListStore and 104 -- GtkTreeModelFilter. 105 106insert 107 GTK 108 GTK_TREE_MODEL_EXTERNALS 109 GTK_TREE_MODEL_FLAGS 110 111feature 112 flags: INTEGER is 113 -- The set of flags supported by Current's interface. The 114 -- flags are a bitwise combination of GtkTreeModelFlags. The 115 -- flags supported should not change during the lifecycle of 116 -- the tree_model. 117 do 118 Result := gtk_tree_model_get_flags (handle) 119 ensure are_valid_tree_model_flags (Result) 120 end 121 122 n_columns, columns_count: INTEGER is 123 -- the number of columns supported by tree_model. 124 do 125 Result := gtk_tree_model_get_n_columns (handle) 126 end 127 128 column_type (a_column_number: INTEGER): INTEGER is 129 -- the type of the column; it is a G_TYPE integer 130 -- TODO: require: valid_column_number: a_column_number.in_range (0,columns_count) 131 do 132 Result := gtk_tree_model_get_column_type (handle, a_column_number) 133 -- TODO: ensure is_g_type (Result) 134 end 135 136 get_new_iterator (a_path: GTK_TREE_PATH): GTK_TREE_ITER is 137 -- Gets a new iterator pointing to `a_path'. If it cannot be 138 -- valid it will be Void (i.e. if `a_path' refers to a not 139 -- existing row) 140 require valid_path: a_path /= Void 141 local gbool: INTEGER 142 do 143 create Result.from_model(Current) 144 gbool := gtk_tree_model_get_iter (handle, Result.handle, a_path.handle) 145 if (gbool = 0) then 146 -- Should be also called by Eiffel's garbage collector but 147 -- it is nevertheless worth to call it: it is safe and avoid a 148 -- memory leak in the case you compile without a GC 149 Result.dispose 150 Result := Void 151 end 152 end 153 154 get_iterator_from_string (a_path_string: STRING): GTK_TREE_ITER is 155 -- Gets a new iterator pointing to `a_path_string', if it exists. If it cannot be 156 -- valid it will be Void 157 require valid_path_string: a_path_string/=Void 158 local gbool: INTEGER 159 do 160 create Result.make 161 gbool := gtk_tree_model_get_iter_from_string (handle, Result.handle, a_path_string.to_external); 162 if (gbool = 0) then 163 Result.dispose -- See get_new_iterator for info 164 Result := Void 165 end 166 end 167 168 get_iterator_first: GTK_TREE_ITER is 169 -- Gets an first iterator to the first element in the tree 170 -- (the one at the path "0"). Void if the tree is empty. 171 local gbool: INTEGER 172 do 173 create Result.from_model (Current) 174 gbool := gtk_tree_model_get_iter_first (handle, Result.handle) 175 if (gbool = 0) then 176 Result.dispose -- See get_new_iterator for info 177 Result := Void 178 end 179 end 180 181 path (an_iterator: GTK_TREE_ITER): GTK_TREE_PATH is 182 -- A newly-created GtkTreePath referenced by `an_iterator'. 183 require valid_iterator: an_iterator/=Void 184 do 185 create Result.from_external_pointer (gtk_tree_model_get_path (handle, an_iterator.handle)) 186 end 187 188 value_at,value (an_iterator: GTK_TREE_ITER; a_column: INTEGER): G_VALUE is 189 -- The value at `a_column' on the row referred by `an_iterator'. 190 do 191 create Result.make 192 gtk_tree_model_get_value (handle, an_iterator.handle, a_column, Result.handle) 193 -- Note: When done with value, g_value_unset() needs to be 194 -- called to free any allocated memory. This should be 195 -- already implemented into G_VALUE 196 end 197 198 ref_node (an_iter: GTK_TREE_ITER) is 199 -- Lets the tree ref the node referred by `an_iter'. This is 200 -- an optional method for models to implement. To be more 201 -- specific, models may ignore this call as it exists 202 -- primarily for performance reasons. 203 204 -- This feature is primarily meant as a way for views to let 205 -- caching model know when nodes are being displayed (and 206 -- hence, whether or not to cache that node.) For example, a 207 -- file-system based model would not want to keep the entire 208 -- file-hierarchy in memory, just the sections that are 209 -- currently being displayed by every current view. 210 211 -- A model should be expected to be able to get an iter independent 212 -- of its reffed state. 213 require iter_not_void: an_iter /= Void 214 do 215 gtk_tree_model_ref_node (handle, an_iter.handle) 216 end 217 218 unref_node (an_iter: GTK_TREE_ITER) is 219 -- Lets the tree unref the node referred by `an_iter'. This 220 -- is an optional method for models to implement. To be more 221 -- specific, models may ignore this call as it exists 222 -- primarily for performance reasons. 223 224 -- For more information on what this means, see 225 -- `ref_node'. Please note that nodes that are deleted are 226 -- not unreffed. 227 require iter_not_void: an_iter /= Void 228 do 229 gtk_tree_model_unref_node (handle, an_iter.handle) 230 end 231 232 233 -- Note: gtk_tree_model_get and gtk_tree_model_get_valist are 234 -- unwrappable since variadic or valist-using. They are implemented 235 -- in C as a tight loop around a gtk_tree_model_get_value call. We 236 -- reimplement it 237 238 values, get (an_iter: GTK_TREE_ITER; some_columns: COLLECTION[INTEGER]): COLLECTION[G_VALUE] is 239 -- the value of one or more cells in the row referenced by 240 -- `an_iter'. `some_columns' are the integer column 241 -- numbers. 242 243 -- TODO: decide which name is better among `values' and `get' 244 require 245 iter_not_void: an_iter /= Void 246 valid_columns: some_columns /= Void 247 -- TODO: correct_columns: some_columns.forall 248 -- (is_valid_g_value (?)) 249 local columns_iterator: ITERATOR[INTEGER]; col_n: INTEGER 250 do 251 create {LINKED_LIST[G_VALUE]} Result.make 252 columns_iterator:=some_columns.get_new_iterator 253 from columns_iterator.start 254 until columns_iterator.is_off 255 loop 256 col_n:=columns_iterator.item 257 Result.add_last(value(an_iter, col_n)) 258 columns_iterator.next 259 end 260 ensure 261 Result /= Void 262 Result.count = some_columns.count 263 end 264 265 for_each (a_test: FUNCTION[TUPLE[GTK_TREE_MODEL, GTK_TREE_PATH, GTK_TREE_ITER], BOOLEAN]) is 266 -- Calls `a_test' on each node in model in a depth-first 267 -- fashion. When `a_test' is True, then the tree ceases to 268 -- be walked. 269 local a_path: GTK_TREE_PATH; an_iter: GTK_TREE_ITER; a_bool: BOOLEAN 270 do 271 -- Note: implementation paraphrased from the original C 272 create a_path.first 273 an_iter := get_new_iterator (a_path) 274 if an_iter = Void then a_path.dispose 275 else 276 a_bool:=for_each_helper(a_path,an_iter,a_test) 277 -- for_each_helper ultimate result is thrown away 278 end 279 end 280 281 row_changed (a_path: GTK_TREE_PATH; an_iter: GTK_TREE_ITER) is 282 -- Emits the "row_changed" signal on tree_model. `a_path' 283 -- points to the changed row, `an_iter' is a valid 284 -- GtkTreeIter pointing to the changed row 285 require 286 valid_path: a_path/=Void 287 valid_iter: an_iter/=Void 288 -- TODO: path_and_iter_refers_to_the_same_row 289 do 290 gtk_tree_model_row_changed (handle,a_path.handle,an_iter.handle) 291 end 292 293 row_inserted (a_path: GTK_TREE_PATH; an_iter: GTK_TREE_ITER) is 294 -- Emits the "row_inserted" signal on Current GTK_TREE_MODEL; 295 -- `a_path' points to the inserted row, `an_iter' is a valid 296 -- GtkTreeIter pointing to the inserted row 297 require 298 valid_path: a_path/=Void 299 valid_iter: an_iter/=Void 300 -- TODO: path_and_iter_refers_to_the_same_row 301 do 302 gtk_tree_model_row_inserted (handle,a_path.handle,an_iter.handle) 303 end 304 305 row_has_child_toggled (a_path: GTK_TREE_PATH; an_iter: GTK_TREE_ITER) is 306 -- Emits the "row_has_child_toggled" signal on Current. This 307 -- should be called by models after the child state of a node 308 -- changes. 309 310 -- `a_path' is a GtkTreePath pointing to the changed row 311 312 -- `a_iter' is a valid GtkTreeIter pointing to the changed 313 -- row 314 require 315 valid_path: a_path/=Void 316 valid_iter: an_iter/=Void 317 -- TODO: path_and_iter_refers_to_the_same_row 318 do 319 gtk_tree_model_row_has_child_toggled (handle,a_path.handle,an_iter.handle) 320 end 321 322 row_deleted (a_path: GTK_TREE_PATH) is 323 -- Emits the "row_deleted" signal on tree_model. This should 324 -- be called by models after a row has been removed. The 325 -- location pointed to by path should be the location that 326 -- the row previously was at. It may not be a valid location 327 -- anymore. `a_path' is a GtkTreePath pointing to the 328 -- previous location of the deleted row. 329 require valid_path: a_path/=Void 330 do 331 gtk_tree_model_row_deleted (handle, a_path.handle) 332 end 333 334 rows_reordered (a_path: GTK_TREE_PATH; an_iter: GTK_TREE_ITER; a_new_order: ARRAY[INTEGER]) is 335 -- Emits the "rows_reordered" signal on tree_model. This 336 -- should be called by models when their rows have been 337 -- reordered. 338 339 -- `a_path' is a GtkTreePath pointing to the tree node whose 340 -- children have been reordered 341 342 -- `an_iter' is a valid GtkTreeIter pointing to the node 343 -- whose children have been reordered; Void if the depth of 344 -- path is 0. 345 346 -- a_new_order: an array of integers mapping the current 347 -- position of each child to its old position before the 348 -- re-ordering, i.e. new_order[newpos] = oldpos. 349 require 350 valid_path: a_path/=Void 351 valid_order: a_new_order /= Void 352 do 353 if an_iter /= Void then 354 gtk_tree_model_rows_reordered (handle, a_path.handle, an_iter.handle, 355 a_new_order.to_external) 356 else gtk_tree_model_rows_reordered (handle, a_path.handle, default_pointer, 357 a_new_order.to_external) 358 end 359 end 360 361feature -- The "row-changed" signal 362 363 -- void user_function (GtkTreeModel *treemodel, GtkTreePath *arg1, 364 -- GtkTreeIter *arg2, gpointer user_data) : Run last 365 366 -- treemodel : the object which received the signal. 367 -- arg1 : 368 -- arg2 : 369 -- user_data : user data set when the signal handler was 370 -- connected. 371 372 row_changed_signal_name: STRING is "row-changed" 373 enable_on_row_changed is 374 -- Connects "row-changed" signal to `on_row_changed' feature. 375 do 376 connect (Current, row_changed_signal_name, $on_row_changed) 377 end 378 379 on_row_changed (a_path: GTK_TREE_PATH; an_iter: GTK_TREE_ITER) is 380 -- Built-in "row-changed" signal handler; empty by design; 381 -- redefine it. 382 do 383 end 384 385 connect_agent_to_row_changed_signal (a_procedure: PROCEDURE [ANY, TUPLE[GTK_TREE_MODEL,GTK_TREE_PATH,GTK_TREE_ITER]]) is 386 require valid_procedure: a_procedure /= Void 387 local 388 row_changed_callback: ROW_CHANGED_CALLBACK 389 do 390 create row_changed_callback.make 391 row_changed_callback.connect (Current, a_procedure) 392 end 393 394feature -- The "row-deleted" signal 395 396 row_deleted_signal_name: STRING is "row-deleted" 397 -- void user_function (GtkTreeModel *treemodel, GtkTreePath 398 -- *arg1, gpointer user_data) : Run first 399 400 on_row_deleted is 401 -- Built-in row_deleted signal handler; empty by design; redefine it. 402 do 403 end 404 405 enable_on_row_deleted is 406 -- Connects "row_deleted" signal to `on_row_deleted' feature. 407 do 408 connect (Current, row_deleted_signal_name, $on_row_deleted) 409 end 410 411 connect_agent_to_row_deleted_signal (a_procedure: PROCEDURE [ANY, 412 TUPLE[GTK_TREE_PATH, GTK_TREE_MODEL]]) is 413 -- treemodel : the object which received the signal. 414 -- arg1 : 415 -- user_data : user data set when the signal handler was connected. 416 require valid_procedure: a_procedure /= Void 417 local row_deleted_callback: ROW_DELETED_CALLBACK 418 do 419 create row_deleted_callback.make 420 row_deleted_callback.connect (Current, a_procedure) 421 end 422 423feature -- TODO: "row-has-child-toggled" signal 424 row_has_child_toggled_signal_name: STRING is "row-has-child-toggled" 425 -- void user_function (GtkTreeModel *treemodel, GtkTreePath 426 -- *arg1, GtkTreeIter *arg2, gpointer user_data) : Run last 427 428 on_row_has_child_toggled is 429 -- Built-in row_has_child_toggled signal handler; empty by design; redefine it. 430 do 431 end 432 433 enable_on_row_has_child_toggled is 434 -- Connects "row_has_child_toggled" signal to `on_row_has_child_toggled' feature. 435 do 436 connect (Current, row_has_child_toggled_signal_name, $on_row_has_child_toggled) 437 end 438 connect_agent_to_row_has_child_toggled_signal (a_procedure: PROCEDURE [ANY, TUPLE[GTK_TREE_MODEL, GTK_TREE_PATH, GTK_TREE_ITER]]) is 439 -- treemodel : the object which received the signal. 440 -- arg1 : 441 -- user_data : user data set when the signal handler was connected. 442 require valid_procedure: a_procedure /= Void 443 local row_has_child_toggled_callback: ROW_HAS_CHILD_TOGGLED_CALLBACK 444 do 445 create row_has_child_toggled_callback.make 446 row_has_child_toggled_callback.connect (Current, a_procedure) 447 end 448 449feature -- The "row-inserted" signal 450 451 row_inserted_signal_name: STRING is "row-inserted" 452 -- "row-inserted" 453 -- void user_function (GtkTreeModel *treemodel, 454 -- GtkTreePath *arg1, 455 -- GtkTreeIter *arg2, 456 -- gpointer user_data) : Run first 457 458 on_row_inserted is 459 -- Built-in row_inserted signal handler; empty by design; redefine it. 460 do 461 end 462 463 enable_on_row_inserted is 464 -- Connects "row_inserted" signal to `on_row_inserted' feature. 465 do 466 connect (Current, row_inserted_signal_name, $on_row_inserted) 467 end 468 469 connect_agent_to_row_inserted_signal (a_procedure: PROCEDURE [ANY, 470 TUPLE[GTK_TREE_PATH, GTK_TREE_ITER, GTK_TREE_MODEL]]) is 471 -- treemodel : the object which received the signal. 472 -- arg1 : 473 -- arg2 : 474 -- user_data : user data set when the signal handler was connected. 475 require valid_procedure: a_procedure /= Void 476 local row_inserted_callback: ROW_INSERTED_CALLBACK 477 do 478 create row_inserted_callback.make 479 row_inserted_callback.connect (Current, a_procedure) 480 end 481 482feature -- The "rows-reordered" signal 483 484-- void user_function (GtkTreeModel *treemodel, 485-- GtkTreePath *arg1, 486-- GtkTreeIter *arg2, 487-- gpointer arg3, 488-- gpointer user_data) : Run first 489 490-- treemodel : the object which received the signal. 491-- arg1 : 492-- arg2 : 493-- arg3 : 494-- user_data : user data set when the signal handler was connected. 495 496feature {} -- Moved here from top - unwrapped code 497 498-- GtkTreeModel 499 500-- typedef struct _GtkTreeModel GtkTreeModel; 501 502-- GtkTreeIter 503 504-- typedef struct { 505-- gint stamp; 506-- gpointer user_data; 507-- gpointer user_data2; 508-- gpointer user_data3; 509-- } GtkTreeIter; 510 511-- The GtkTreeIter is the primary structure for accessing a structure. Models are expected to put a unique integer in the stamp member, and put model-specific data in the three user_data members. 512-- gint stamp; A unique stamp to catch invalid iterators 513-- gpointer user_data; Model specific data 514-- gpointer user_data2; Model specific data 515-- gpointer user_data3; Model specific data 516-- GtkTreePath 517 518-- typedef struct _GtkTreePath GtkTreePath; 519 520-- GtkTreeRowReference 521 522-- typedef struct _GtkTreeRowReference GtkTreeRowReference; 523 524-- GtkTreeModelIface 525 526-- typedef struct { 527-- GTypeInterface g_iface; 528 529-- /* Signals */ 530-- void (* row_changed) (GtkTreeModel *tree_model, 531-- GtkTreePath *path, 532-- GtkTreeIter *iter); 533-- void (* row_inserted) (GtkTreeModel *tree_model, 534-- GtkTreePath *path, 535-- GtkTreeIter *iter); 536-- void (* row_has_child_toggled) (GtkTreeModel *tree_model, 537-- GtkTreePath *path, 538-- GtkTreeIter *iter); 539-- void (* row_deleted) (GtkTreeModel *tree_model, 540-- GtkTreePath *path); 541-- void (* rows_reordered) (GtkTreeModel *tree_model, 542-- GtkTreePath *path, 543-- GtkTreeIter *iter, 544-- gint *new_order); 545 546-- /* Virtual Table */ 547-- GtkTreeModelFlags (* get_flags) (GtkTreeModel *tree_model); 548 549-- gint (* get_n_columns) (GtkTreeModel *tree_model); 550-- GType (* get_column_type) (GtkTreeModel *tree_model, 551-- gint index_); 552-- gboolean (* get_iter) (GtkTreeModel *tree_model, 553-- GtkTreeIter *iter, 554-- GtkTreePath *path); 555-- GtkTreePath *(* get_path) (GtkTreeModel *tree_model, 556-- GtkTreeIter *iter); 557-- void (* get_value) (GtkTreeModel *tree_model, 558-- GtkTreeIter *iter, 559-- gint column, 560-- GValue *value); 561-- gboolean (* iter_next) (GtkTreeModel *tree_model, 562-- GtkTreeIter *iter); 563-- gboolean (* iter_children) (GtkTreeModel *tree_model, 564-- GtkTreeIter *iter, 565-- GtkTreeIter *parent); 566-- gboolean (* iter_has_child) (GtkTreeModel *tree_model, 567-- GtkTreeIter *iter); 568-- gint (* iter_n_children) (GtkTreeModel *tree_model, 569-- GtkTreeIter *iter); 570-- gboolean (* iter_nth_child) (GtkTreeModel *tree_model, 571-- GtkTreeIter *iter, 572-- GtkTreeIter *parent, 573-- gint n); 574-- gboolean (* iter_parent) (GtkTreeModel *tree_model, 575-- GtkTreeIter *iter, 576-- GtkTreeIter *child); 577-- void (* ref_node) (GtkTreeModel *tree_model, 578-- GtkTreeIter *iter); 579-- void (* unref_node) (GtkTreeModel *tree_model, 580-- GtkTreeIter *iter); 581-- } GtkTreeModelIface; 582 583feature {} -- Implementation 584 for_each_helper (a_path: GTK_TREE_PATH; an_iter: GTK_TREE_ITER; 585 a_test: FUNCTION[TUPLE[GTK_TREE_MODEL, GTK_TREE_PATH, GTK_TREE_ITER], BOOLEAN]): BOOLEAN is 586 -- Helper function of the `for_each' feature. 587 588 -- Calls `a_test' on node referred by `an_iter' and `a_path', 589 -- then recursively on all its children. When `a_test' is 590 -- True, then the tree ceases to be walked. 591 require 592 iter_not_void: an_iter /= Void 593 path_not_void: a_path /= Void 594 test_not_void: a_test /= Void 595 valid_iter: an_iter.is_valid 596 -- TODO: iter and path refer the same node 597 local a_child: GTK_TREE_ITER; continue: BOOLEAN 598 do 599 check Result_must_be_initially_false: Result=False end 600 from 601 until Result = False and then an_iter.is_valid 602 loop 603 Result := a_test.item([Current, a_path, an_iter]) 604 605 if not Result and then an_iter.has_children then 606 create a_child.as_children_of(an_iter) 607 a_path.down 608 Result:= for_each_helper (a_path, a_child, a_test) 609 a_path.up 610 end 611 a_path.next 612 an_iter.next 613 end 614 end 615end