/src/wrappers/gtk/library/gtk_tree_model.e

http://github.com/tybor/Liberty · Specman e · 615 lines · 252 code · 82 blank · 281 comment · 9 complexity · d06473649b6db42984f8dea851583a92 MD5 · raw file

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