]> git.xonotic.org Git - xonotic/netradiant.git/blob - radiant/treemodel.cpp
Wrap GtkTreePath
[xonotic/netradiant.git] / radiant / treemodel.cpp
1 /*
2    Copyright (C) 2001-2006, William Joseph.
3    All Rights Reserved.
4
5    This file is part of GtkRadiant.
6
7    GtkRadiant is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11
12    GtkRadiant is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with GtkRadiant; if not, write to the Free Software
19    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20  */
21
22 #include "treemodel.h"
23
24 #include "debugging/debugging.h"
25
26 #include <map>
27 #include <gtk/gtktreemodel.h>
28 #include <gtk/gtktreednd.h>
29 #include <gtk/gtkmain.h>
30 #include <uilib/uilib.h>
31
32 #include "iscenegraph.h"
33 #include "nameable.h"
34
35 #include "generic/callback.h"
36 #include "scenelib.h"
37 #include "string/string.h"
38 #include "generic/reference.h"
39
40 inline Nameable* Node_getNameable( scene::Node& node ){
41         return NodeTypeCast<Nameable>::cast( node );
42 }
43
44 #if 0
45
46 #include "gtkutil/gtktreestore.h"
47
48 template<typename value_type>
49 inline void gtk_tree_model_get_pointer( GtkTreeModel* model, GtkTreeIter* iter, gint column, value_type** pointer ){
50         GValue value = GValue_default();
51         gtk_tree_model_get_value( model, iter, column, &value );
52         *pointer = (value_type*)g_value_get_pointer( &value );
53 }
54
55
56 typedef GtkTreeStore GraphTreeModel;
57
58 GtkTreeStore* graph_tree_model_new( graph_type* graph ){
59         return gtk_tree_store_new( 2, G_TYPE_POINTER, G_TYPE_POINTER );
60 }
61
62 void graph_tree_model_delete( GraphTreeModel* model ){
63         g_object_unref( G_OBJECT( model ) );
64 }
65
66
67 bool graph_tree_model_subtree_find_node( GraphTreeModel* model, GtkTreeIter* parent, const scene::Node& node, GtkTreeIter* iter ){
68         for ( gboolean success = gtk_tree_model_iter_children( GTK_TREE_MODEL( model ), iter, parent );
69                   success != FALSE;
70                   success = gtk_tree_model_iter_next( GTK_TREE_MODEL( model ), iter ) )
71         {
72                 scene::Node* current;
73                 gtk_tree_model_get_pointer( GTK_TREE_MODEL( model ), iter, 0, &current );
74                 if ( current == node ) {
75                         return true;
76                 }
77         }
78         return false;
79 }
80
81 typedef GtkTreeIter DoubleGtkTreeIter[2];
82
83 bool graph_tree_model_find_top( GraphTreeModel* model, const scene::Path& path, GtkTreeIter& iter ){
84         int swap = 0;
85         GtkTreeIter* parent_pointer = NULL;
86         GtkTreeIter parent;
87         for ( scene::Path::const_iterator i = path.begin(); i != path.end(); ++i )
88         {
89                 if ( !graph_tree_model_subtree_find_node( model, parent_pointer, *i, &iter ) ) {
90                         return false;
91                 }
92                 parent = iter;
93                 parent_pointer = &parent;
94         }
95         return true;
96 }
97
98 bool graph_tree_model_find_parent( GraphTreeModel* model, const scene::Path& path, GtkTreeIter& iter ){
99         int swap = 0;
100         GtkTreeIter* parent_pointer = NULL;
101         ASSERT_MESSAGE( path.size() > 1, "path too short" );
102         for ( scene::Path::const_iterator i = path.begin(); i != path.end() - 1; ++i )
103         {
104                 GtkTreeIter child;
105                 if ( !graph_tree_model_subtree_find_node( model, parent_pointer, *i, &child ) ) {
106                         return false;
107                 }
108                 iter = child;
109                 parent_pointer = &iter;
110         }
111         return true;
112 }
113
114 void node_attach_name_changed_callback( scene::Node& node, const Callback& callback ){
115         if ( node != 0 ) {
116                 Nameable* nameable = Node_getNameable( node );
117                 if ( nameable != 0 ) {
118                         nameable->attach( callback );
119                 }
120         }
121 }
122 void node_detach_name_changed_callback( scene::Node& node, const Callback& callback ){
123         if ( node != 0 ) {
124                 Nameable* nameable = Node_getNameable( node );
125                 if ( nameable != 0 ) {
126                         nameable->detach( callback );
127                 }
128         }
129 }
130
131 GraphTreeModel* scene_graph_get_tree_model(); // temp hack
132
133 void graph_tree_model_row_changed( const scene::Instance& instance ){
134         GraphTreeModel* model = scene_graph_get_tree_model();
135
136         GtkTreeIter child;
137         ASSERT_MESSAGE( graph_tree_model_find_top( model, instance.path(), child ), "RUNTIME ERROR" );
138
139         gtk_tree_store_set( GTK_TREE_STORE( model ), &child, 0, instance.path().top(), -1 );
140 }
141
142 void graph_tree_model_row_inserted( GraphTreeModel* model, const scene::Instance& instance ){
143         GtkTreeIter parent;
144         GtkTreeIter* parent_pointer = NULL;
145         if ( instance.path().size() != 1 ) {
146                 ASSERT_MESSAGE( graph_tree_model_find_parent( model, instance.path(), parent ), "RUNTIME ERROR" );
147                 parent_pointer = &parent;
148         }
149
150         gpointer node = instance.path().top();
151         gconstpointer selectable = Instance_getSelectable( instance );
152
153         GtkTreeIter child;
154         gtk_tree_store_append( GTK_TREE_STORE( model ), &child, parent_pointer );
155         gtk_tree_store_set( GTK_TREE_STORE( model ), &child, 0, node, 1, selectable, -1 );
156
157         node_attach_name_changed_callback( instance.path().top(), ConstReferenceCaller<scene::Instance, graph_tree_model_row_changed>( instance ) );
158 }
159
160 void graph_tree_model_row_deleted( GraphTreeModel* model, const scene::Instance& instance ){
161         GtkTreeIter child;
162         ASSERT_MESSAGE( graph_tree_model_find_top( model, instance.path(), child ), "RUNTIME ERROR" );
163
164         node_detach_name_changed_callback( instance.path().top(), ConstReferenceCaller<scene::Instance, graph_tree_model_row_changed>( instance ) );
165
166         gtk_tree_store_remove( GTK_TREE_STORE( model ), &child );
167 }
168
169 #elif 0
170
171 const char* node_get_name( scene::Node& node );
172
173 typedef scene::Node* NodePointer;
174
175 class NodeNameLess
176 {
177 public:
178 bool operator()( const NodePointer& self, const NodePointer& other ) const {
179         if ( self == 0 ) {
180                 return true;
181         }
182         if ( other == 0 ) {
183                 return false;
184         }
185         int result = string_compare( node_get_name( self ), node_get_name( other ) );
186         if ( result == 0 ) {
187                 return self < other;
188         }
189         return result < 0;
190 }
191 };
192
193 class PathNameLess
194 {
195 public:
196 bool operator()( const PathConstReference& self, const PathConstReference& other ) const {
197         return std::lexicographical_compare( self.get().begin(), self.get().end(), other.get().begin(), other.get().end(), NodeNameLess() );
198 }
199 };
200
201 typedef std::map<PathConstReference, scene::Instance*, PathNameLess> graph_type;
202
203 struct GraphTreeModel
204 {
205         GObject parent;
206
207         graph_type* graph;
208 };
209
210 struct GraphTreeModelClass
211 {
212         GObjectClass parent_class;
213 };
214
215 #define GRAPH_TREE_MODEL( p ) ( reinterpret_cast<GraphTreeModel*>( p ) )
216
217 static GtkTreeModelFlags graph_tree_model_get_flags( GtkTreeModel* tree_model ){
218         return GTK_TREE_MODEL_ITERS_PERSIST;
219 }
220
221 static gint graph_tree_model_get_n_columns( GtkTreeModel* tree_model ){
222         ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
223         GraphTreeModel* graph_tree_model = (GraphTreeModel*) tree_model;
224
225         return 2;
226 }
227
228 static const gint c_stamp = 0xabcdef;
229
230 inline graph_type::iterator graph_iterator_read_tree_iter( GtkTreeIter* iter ){
231         ASSERT_MESSAGE( iter != 0,  "tree model error" );
232         ASSERT_MESSAGE( iter->user_data != 0,  "tree model error" );
233         ASSERT_MESSAGE( iter->stamp == c_stamp,  "tree model error" );
234         return *reinterpret_cast<graph_type::iterator*>( &iter->user_data );
235 }
236
237 inline void graph_iterator_write_tree_iter( graph_type::iterator i, GtkTreeIter* iter ){
238         ASSERT_MESSAGE( iter != 0,  "tree model error" );
239         iter->stamp = c_stamp;
240         *reinterpret_cast<graph_type::iterator*>( &iter->user_data ) = i;
241         ASSERT_MESSAGE( iter->user_data != 0,  "tree model error" );
242 }
243
244 static GType graph_tree_model_get_column_type( GtkTreeModel *tree_model, gint index ){
245         ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
246         GraphTreeModel *graph_tree_model = (GraphTreeModel *) tree_model;
247
248         return G_TYPE_POINTER;
249 }
250
251 static gboolean graph_tree_model_get_iter( GtkTreeModel* tree_model, GtkTreeIter* iter, GtkTreePath* path ){
252         ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
253         gint* indices = gtk_tree_path_get_indices( path );
254         gint depth = gtk_tree_path_get_depth( path );
255
256         g_return_val_if_fail( depth > 0, FALSE );
257
258         graph_type& graph = *GRAPH_TREE_MODEL( tree_model )->graph;
259
260         if ( graph.empty() ) {
261                 return FALSE;
262         }
263
264         GtkTreeIter tmp;
265         GtkTreeIter* parent = 0;
266
267         for ( gint i = 0; i < depth; i++ )
268         {
269                 if ( !gtk_tree_model_iter_nth_child( tree_model, iter, parent, indices[i] ) ) {
270                         return FALSE;
271                 }
272                 tmp = *iter;
273                 parent = &tmp;
274         }
275
276         return TRUE;
277 }
278
279 static GtkTreePath* graph_tree_model_get_path( GtkTreeModel* tree_model, GtkTreeIter* iter ){
280         ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
281         graph_type& graph = *GRAPH_TREE_MODEL( tree_model )->graph;
282         graph_type::iterator i = graph_iterator_read_tree_iter( iter );
283
284         GtkTreePath* path = ui::TreePath();
285
286         for ( std::size_t depth = ( *i ).first.get().size(); depth != 0; --depth )
287         {
288                 std::size_t index = 0;
289
290                 while ( i != graph.begin() && ( *i ).first.get().size() >= depth )
291                 {
292                         --i;
293                         if ( ( *i ).first.get().size() == depth ) {
294                                 ++index;
295                         }
296                 }
297
298                 gtk_tree_path_prepend_index( path, index );
299         }
300
301         return path;
302 }
303
304
305 static void graph_tree_model_get_value( GtkTreeModel *tree_model, GtkTreeIter  *iter, gint column, GValue *value ){
306         ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
307         ASSERT_MESSAGE( column == 0 || column == 1, "tree model error" );
308
309         graph_type::iterator i = graph_iterator_read_tree_iter( iter );
310
311         g_value_init( value, G_TYPE_POINTER );
312
313         if ( column == 0 ) {
314                 g_value_set_pointer( value, reinterpret_cast<gpointer>( ( *i ).first.get().top() ) );
315         }
316         else{
317                 g_value_set_pointer( value, reinterpret_cast<gpointer>( Instance_getSelectable( *( *i ).second ) ) );
318         }
319 }
320
321 static gboolean graph_tree_model_iter_next( GtkTreeModel  *tree_model, GtkTreeIter   *iter ){
322         ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
323         graph_type& graph = *GRAPH_TREE_MODEL( tree_model )->graph;
324         graph_type::iterator i = graph_iterator_read_tree_iter( iter );
325         std::size_t depth = ( *i ).first.get().size();
326
327         ++i;
328
329         while ( i != graph.end() && ( *i ).first.get().size() > depth )
330         {
331                 ++i;
332         }
333
334         if ( i == graph.end() || ( *i ).first.get().size() != depth ) {
335                 return FALSE;
336         }
337
338         graph_iterator_write_tree_iter( i, iter );
339
340         return TRUE;
341 }
342
343 static gboolean graph_tree_model_iter_children( GtkTreeModel *tree_model, GtkTreeIter  *iter, GtkTreeIter  *parent ){
344         ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
345         graph_type& graph = *GRAPH_TREE_MODEL( tree_model )->graph;
346         graph_type::iterator i = ( parent == 0 ) ? graph.begin() : graph_iterator_read_tree_iter( parent );
347         std::size_t depth = ( parent == 0 ) ? 1 : ( *i ).first.get().size() + 1;
348
349         if ( parent != 0 ) {
350                 ++i;
351         }
352
353         if ( i != graph.end() && ( *i ).first.get().size() == depth ) {
354                 graph_iterator_write_tree_iter( i, iter );
355                 return TRUE;
356         }
357
358         return FALSE;
359 }
360
361 static gboolean graph_tree_model_iter_has_child( GtkTreeModel *tree_model, GtkTreeIter  *iter ){
362         ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
363         graph_type& graph = *GRAPH_TREE_MODEL( tree_model )->graph;
364         graph_type::iterator i = graph_iterator_read_tree_iter( iter );
365         std::size_t depth = ( *i ).first.get().size() + 1;
366
367         return ++i != graph.end() && ( *i ).first.get().size() == depth;
368 }
369
370 static gint graph_tree_model_iter_n_children( GtkTreeModel *tree_model, GtkTreeIter *parent ){
371         ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
372         graph_type& graph = *GRAPH_TREE_MODEL( tree_model )->graph;
373         graph_type::iterator i = ( parent == 0 ) ? graph.begin() : graph_iterator_read_tree_iter( parent );
374         std::size_t depth = ( parent == 0 ) ? 1 : ( *i ).first.get().size() + 1;
375
376         if ( parent != 0 ) {
377                 ++i;
378         }
379
380         gint count = 0;
381         while ( i != graph.end() && ( *i ).first.get().size() >= depth )
382         {
383                 ++count;
384                 ++i;
385         }
386
387         return count;
388 }
389
390 static gboolean graph_tree_model_iter_nth_child( GtkTreeModel *tree_model, GtkTreeIter  *iter, GtkTreeIter  *parent, gint n ){
391         ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
392         graph_type& graph = *GRAPH_TREE_MODEL( tree_model )->graph;
393         graph_type::iterator i = ( parent == 0 ) ? graph.begin() : graph_iterator_read_tree_iter( parent );
394         std::size_t depth = ( parent == 0 ) ? 1 : ( *i ).first.get().size() + 1;
395
396         if ( parent != 0 ) {
397                 ++i;
398         }
399
400         while ( i != graph.end() && ( *i ).first.get().size() >= depth )
401         {
402                 if ( ( *i ).first.get().size() == depth && n-- == 0 ) {
403                         graph_iterator_write_tree_iter( i, iter );
404                         return TRUE;
405                 }
406                 ++i;
407         }
408
409         return FALSE;
410 }
411
412 static gboolean graph_tree_model_iter_parent( GtkTreeModel *tree_model, GtkTreeIter  *iter, GtkTreeIter  *child ){
413         ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
414         graph_type& graph = *GRAPH_TREE_MODEL( tree_model )->graph;
415         graph_type::iterator i = graph_iterator_read_tree_iter( child );
416         std::size_t depth = ( *i ).first.get().size();
417         if ( depth == 1 ) {
418                 return FALSE;
419         }
420         else
421         {
422                 do
423                 {
424                         --i;
425                 }
426                 while ( ( *i ).first.get().size() >= depth );
427                 graph_iterator_write_tree_iter( i, iter );
428                 return TRUE;
429         }
430 }
431
432 static GObjectClass *g_parent_class = 0;
433
434 static void graph_tree_model_init( GraphTreeModel *graph_tree_model ){
435         graph_tree_model->graph = 0;
436 }
437
438 static void graph_tree_model_finalize( GObject* object ){
439         GraphTreeModel* graph_tree_model = GRAPH_TREE_MODEL( object );
440
441         /* must chain up */
442         ( *g_parent_class->finalize )( object );
443 }
444
445 static void graph_tree_model_class_init( GraphTreeModelClass *class_ ){
446         GObjectClass *object_class;
447
448         g_parent_class = (GObjectClass*)g_type_class_peek_parent( class_ );
449         object_class = (GObjectClass *) class_;
450
451         object_class->finalize = graph_tree_model_finalize;
452 }
453
454 static void graph_tree_model_tree_model_init( GtkTreeModelIface *iface ){
455         iface->get_flags = graph_tree_model_get_flags;
456         iface->get_n_columns = graph_tree_model_get_n_columns;
457         iface->get_column_type = graph_tree_model_get_column_type;
458         iface->get_iter = graph_tree_model_get_iter;
459         iface->get_path = graph_tree_model_get_path;
460         iface->get_value = graph_tree_model_get_value;
461         iface->iter_next = graph_tree_model_iter_next;
462         iface->iter_children = graph_tree_model_iter_children;
463         iface->iter_has_child = graph_tree_model_iter_has_child;
464         iface->iter_n_children = graph_tree_model_iter_n_children;
465         iface->iter_nth_child = graph_tree_model_iter_nth_child;
466         iface->iter_parent = graph_tree_model_iter_parent;
467 }
468
469 static gboolean graph_tree_model_row_draggable( GtkTreeDragSource *drag_source, GtkTreePath *path ){
470 #ifdef _DEBUG
471         gint depth = gtk_tree_path_get_depth( path );
472 #endif
473         return gtk_tree_path_get_depth( path ) > 1;
474 }
475
476 static gboolean graph_tree_model_drag_data_delete( GtkTreeDragSource *drag_source, GtkTreePath *path ){
477         GtkTreeIter iter;
478
479         if ( gtk_tree_model_get_iter( GTK_TREE_MODEL( drag_source ), &iter, path ) ) {
480                 graph_type::iterator i = graph_iterator_read_tree_iter( &iter );
481                 Path_deleteTop( ( *i ).first );
482                 return TRUE;
483         }
484         else
485         {
486                 return FALSE;
487         }
488 }
489
490 static gboolean graph_tree_model_drag_data_get( GtkTreeDragSource *drag_source, GtkTreePath *path, GtkSelectionData *selection_data ){
491         if ( gtk_tree_set_row_drag_data( selection_data, GTK_TREE_MODEL( drag_source ), path ) ) {
492                 return TRUE;
493         }
494         else
495         {
496                 /* FIXME handle text targets at least. */
497         }
498
499         return FALSE;
500 }
501
502 static void graph_tree_model_drag_source_init( GtkTreeDragSourceIface *iface ){
503         iface->row_draggable = graph_tree_model_row_draggable;
504         iface->drag_data_delete = graph_tree_model_drag_data_delete;
505         iface->drag_data_get = graph_tree_model_drag_data_get;
506 }
507
508 static gboolean graph_tree_model_drag_data_received( GtkTreeDragDest *drag_dest, GtkTreePath *dest, GtkSelectionData *selection_data ){
509         GtkTreeModel *tree_model = GTK_TREE_MODEL( drag_dest );
510
511         GtkTreeModel *src_model = 0;
512         GtkTreePath *src_path = 0;
513         if ( gtk_tree_get_row_drag_data( selection_data, &src_model, &src_path )
514                  && src_model == tree_model ) {
515                 /* Copy the given row to a new position */
516                 GtkTreeIter iter;
517
518                 if ( gtk_tree_model_get_iter( src_model, &iter, src_path ) ) {
519                         int bleh = 0;
520                 }
521         }
522         else
523         {
524                 /* FIXME maybe add some data targets eventually, or handle text
525                  * targets in the simple case.
526                  */
527         }
528
529         return FALSE;
530 }
531
532 static gboolean graph_tree_model_row_drop_possible( GtkTreeDragDest *drag_dest, GtkTreePath *dest_path, GtkSelectionData *selection_data ){
533         gboolean retval = FALSE;
534
535         GtkTreeModel *src_model = 0;
536         GtkTreePath *src_path = 0;
537         if ( gtk_tree_get_row_drag_data( selection_data, &src_model, &src_path ) != FALSE ) {
538                 /* can only drag to ourselves */
539                 if ( src_model == GTK_TREE_MODEL( drag_dest ) ) {
540                         /* Can't drop into ourself. */
541                         if ( !gtk_tree_path_is_ancestor( src_path, dest_path ) ) {
542                                 /* Can't drop if dest_path's parent doesn't exist */
543                                 if ( gtk_tree_path_get_depth( dest_path ) > 1 ) {
544                                         GtkTreePath* tmp = gtk_tree_path_copy( dest_path );
545                                         gtk_tree_path_up( tmp );
546
547                                         GtkTreeIter iter;
548                                         retval = gtk_tree_model_get_iter( GTK_TREE_MODEL( drag_dest ), &iter, tmp );
549
550                                         gtk_tree_path_free( tmp );
551                                 }
552                         }
553                 }
554
555                 gtk_tree_path_free( src_path );
556         }
557
558         return retval;
559 }
560
561 static void graph_tree_model_drag_dest_init( GtkTreeDragDestIface *iface ){
562         iface->drag_data_received = graph_tree_model_drag_data_received;
563         iface->row_drop_possible = graph_tree_model_row_drop_possible;
564 }
565
566 GType graph_tree_model_get_type( void ){
567         static GType graph_tree_model_type = 0;
568
569         if ( !graph_tree_model_type ) {
570                 static const GTypeInfo graph_tree_model_info =
571                 {
572                         sizeof( GraphTreeModelClass ),
573                         0, /* base_init */
574                         0, /* base_finalize */
575                         (GClassInitFunc) graph_tree_model_class_init,
576                         0, /* class_finalize */
577                         0, /* class_data */
578                         sizeof( GraphTreeModel ),
579                         0,        /* n_preallocs */
580                         (GInstanceInitFunc) graph_tree_model_init
581                 };
582
583                 static const GInterfaceInfo tree_model_info =
584                 {
585                         (GInterfaceInitFunc) graph_tree_model_tree_model_init,
586                         0,
587                         0
588                 };
589
590                 static const GInterfaceInfo drag_source_info =
591                 {
592                         (GInterfaceInitFunc) graph_tree_model_drag_source_init,
593                         0,
594                         0
595                 };
596
597                 static const GInterfaceInfo drag_dest_info =
598                 {
599                         (GInterfaceInitFunc) graph_tree_model_drag_dest_init,
600                         0,
601                         0
602                 };
603
604                 graph_tree_model_type = g_type_register_static( G_TYPE_OBJECT, "GraphTreeModel",
605                                                                                                                 &graph_tree_model_info, (GTypeFlags)0 );
606
607                 g_type_add_interface_static( graph_tree_model_type,
608                                                                          GTK_TYPE_TREE_MODEL,
609                                                                          &tree_model_info );
610                 g_type_add_interface_static( graph_tree_model_type,
611                                                                          GTK_TYPE_TREE_DRAG_SOURCE,
612                                                                          &drag_source_info );
613                 g_type_add_interface_static( graph_tree_model_type,
614                                                                          GTK_TYPE_TREE_DRAG_DEST,
615                                                                          &drag_dest_info );
616         }
617
618         return graph_tree_model_type;
619 }
620
621 GraphTreeModel* graph_tree_model_new(){
622         GraphTreeModel* graph_tree_model = GRAPH_TREE_MODEL( g_object_new( graph_tree_model_get_type(), 0 ) );
623
624         graph_tree_model->graph = new graph_type;
625
626         return graph_tree_model;
627 }
628
629 void graph_tree_model_delete( GraphTreeModel* model ){
630         delete model->graph;
631         g_object_unref( G_OBJECT( model ) );
632 }
633
634
635 class TempNameable : public Nameable
636 {
637 const char* m_name;
638 public:
639 TempNameable( const char* name ) : m_name( name ){
640 }
641 const char* name() const {
642         return m_name;
643 }
644 void attach( const NameCallback& callback ){
645 }
646 void detach( const NameCallback& callback ){
647 }
648 };
649
650 void node_attach_name_changed_callback( scene::Node& node, const NameCallback& callback ){
651         if ( &node != 0 ) {
652                 Nameable* nameable = Node_getNameable( node );
653                 if ( nameable != 0 ) {
654                         nameable->attach( callback );
655                 }
656         }
657 }
658 void node_detach_name_changed_callback( scene::Node& node, const NameCallback& callback ){
659         if ( &node != 0 ) {
660                 Nameable* nameable = Node_getNameable( node );
661                 if ( nameable != 0 ) {
662                         nameable->detach( callback );
663                 }
664         }
665 }
666
667 GraphTreeModel* scene_graph_get_tree_model(); // temp hack
668
669 void graph_tree_model_row_inserted( GraphTreeModel* model, graph_type::iterator i ){
670         GtkTreeIter iter;
671         graph_iterator_write_tree_iter( i, &iter );
672
673         GtkTreePath* tree_path = graph_tree_model_get_path( GTK_TREE_MODEL( model ), &iter );
674
675         gint depth = gtk_tree_path_get_depth( tree_path );
676         gint* indices = gtk_tree_path_get_indices( tree_path );
677
678         gtk_tree_model_row_inserted( GTK_TREE_MODEL( model ), tree_path, &iter );
679
680         gtk_tree_path_free( tree_path );
681 }
682
683 void graph_tree_model_row_deleted( GraphTreeModel* model, graph_type::iterator i ){
684         GtkTreeIter iter;
685         graph_iterator_write_tree_iter( i, &iter );
686
687         GtkTreePath* tree_path = graph_tree_model_get_path( GTK_TREE_MODEL( model ), &iter );
688
689         gtk_tree_model_row_deleted( GTK_TREE_MODEL( model ), tree_path );
690
691         gtk_tree_path_free( tree_path );
692 }
693
694 #include "generic/referencecounted.h"
695
696 void graph_tree_model_set_name( const scene::Instance& instance, const char* name ){
697         GraphTreeModel* model = scene_graph_get_tree_model();
698
699         if ( string_empty( name ) ) { // hack!
700                 graph_type::iterator i = model->graph->find( PathConstReference( instance.path() ) );
701                 ASSERT_MESSAGE( i != model->graph->end(), "ERROR" );
702
703                 graph_tree_model_row_deleted( model, i );
704
705                 model->graph->erase( i );
706         }
707         else
708         {
709                 graph_type::iterator i = model->graph->insert( graph_type::value_type( PathConstReference( instance.path() ), &const_cast<scene::Instance&>( instance ) ) ).first;
710
711                 graph_tree_model_row_inserted( model, i );
712         }
713 }
714
715 void graph_tree_model_insert( GraphTreeModel* model, const scene::Instance& instance ){
716         graph_type::iterator i = model->graph->insert( graph_type::value_type( PathConstReference( instance.path() ), &const_cast<scene::Instance&>( instance ) ) ).first;
717
718         graph_tree_model_row_inserted( model, i );
719
720         node_attach_name_changed_callback( instance.path().top(), ConstReferenceCaller1<scene::Instance, const char*, graph_tree_model_set_name>( instance ) );
721 }
722
723 void graph_tree_model_erase( GraphTreeModel* model, const scene::Instance& instance ){
724         node_detach_name_changed_callback( instance.path().top(), ConstReferenceCaller1<scene::Instance, const char*, graph_tree_model_set_name>( instance ) );
725
726         graph_type::iterator i = model->graph->find( PathConstReference( instance.path() ) );
727         ASSERT_MESSAGE( i != model->graph->end(), "ERROR" );
728
729         graph_tree_model_row_deleted( model, i );
730
731         model->graph->erase( i );
732 }
733
734 #elif 1
735
736 class GraphTreeNode;
737 void graph_tree_model_row_changed( GraphTreeNode& node );
738
739 class GraphTreeNode
740 {
741 typedef std::map<std::pair<std::string, scene::Node*>, GraphTreeNode*> ChildNodes;
742 ChildNodes m_childnodes;
743 public:
744 Reference<scene::Instance> m_instance;
745 GraphTreeNode* m_parent;
746
747 typedef ChildNodes::iterator iterator;
748 typedef ChildNodes::key_type key_type;
749 typedef ChildNodes::value_type value_type;
750 typedef ChildNodes::size_type size_type;
751
752 GraphTreeNode( scene::Instance& instance ) : m_instance( instance ), m_parent( 0 ){
753         m_instance.get().setChildSelectedChangedCallback( RowChangedCaller( *this ) );
754 }
755 ~GraphTreeNode(){
756         m_instance.get().setChildSelectedChangedCallback( Callback() );
757         ASSERT_MESSAGE( empty(), "GraphTreeNode::~GraphTreeNode: memory leak" );
758 }
759
760 iterator begin(){
761         return m_childnodes.begin();
762 }
763 iterator end(){
764         return m_childnodes.end();
765 }
766
767 size_type size() const {
768         return m_childnodes.size();
769 }
770 bool empty() const {
771         return m_childnodes.empty();
772 }
773
774 iterator insert( const value_type& value ){
775         iterator i = m_childnodes.insert( value ).first;
776         ( *i ).second->m_parent = this;
777         return i;
778 }
779 void erase( iterator i ){
780         m_childnodes.erase( i );
781 }
782 iterator find( const key_type& key ){
783         return m_childnodes.find( key );
784 }
785
786 void swap( GraphTreeNode& other ){
787         std::swap( m_parent, other.m_parent );
788         std::swap( m_childnodes, other.m_childnodes );
789         std::swap( m_instance, other.m_instance );
790 }
791
792 void rowChanged(){
793         graph_tree_model_row_changed( *this );
794 }
795 typedef MemberCaller<GraphTreeNode, &GraphTreeNode::rowChanged> RowChangedCaller;
796 };
797
798 struct GraphTreeModel
799 {
800         GObject parent;
801
802         GraphTreeNode* m_graph;
803 };
804
805 struct GraphTreeModelClass
806 {
807         GObjectClass parent_class;
808 };
809
810 #define GRAPH_TREE_MODEL( p ) ( reinterpret_cast<GraphTreeModel*>( p ) )
811
812 static GtkTreeModelFlags graph_tree_model_get_flags( GtkTreeModel* tree_model ){
813         return GTK_TREE_MODEL_ITERS_PERSIST;
814 }
815
816 static gint graph_tree_model_get_n_columns( GtkTreeModel* tree_model ){
817         ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
818         //GraphTreeModel* graph_tree_model = (GraphTreeModel*) tree_model;
819
820         return 2;
821 }
822
823 static const gint c_stamp = 0xabcdef;
824
825 inline GraphTreeNode::iterator graph_iterator_read_tree_iter( GtkTreeIter* iter ){
826         ASSERT_MESSAGE( iter != 0,  "tree model error" );
827         ASSERT_MESSAGE( iter->user_data != 0,  "tree model error" );
828         ASSERT_MESSAGE( iter->stamp == c_stamp,  "tree model error" );
829         return *reinterpret_cast<GraphTreeNode::iterator*>( &iter->user_data );
830 }
831
832 inline void graph_iterator_write_tree_iter( GraphTreeNode::iterator i, GtkTreeIter* iter ){
833         ASSERT_MESSAGE( iter != 0,  "tree model error" );
834         iter->stamp = c_stamp;
835         *reinterpret_cast<GraphTreeNode::iterator*>( &iter->user_data ) = i;
836         ASSERT_MESSAGE( iter->user_data != 0,  "tree model error" );
837 }
838
839 static GType graph_tree_model_get_column_type( GtkTreeModel *tree_model, gint index ){
840         ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
841         //GraphTreeModel *graph_tree_model = (GraphTreeModel *) tree_model;
842
843         return G_TYPE_POINTER;
844 }
845
846 static gboolean graph_tree_model_get_iter( GtkTreeModel* tree_model, GtkTreeIter* iter, GtkTreePath* path ){
847         ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
848         gint* indices = gtk_tree_path_get_indices( path );
849         gint depth = gtk_tree_path_get_depth( path );
850
851         g_return_val_if_fail( depth > 0, FALSE );
852
853         GraphTreeNode* graph = GRAPH_TREE_MODEL( tree_model )->m_graph;
854
855         if ( graph->empty() ) {
856                 return FALSE;
857         }
858
859         GtkTreeIter tmp;
860         GtkTreeIter* parent = 0;
861
862         for ( gint i = 0; i < depth; i++ )
863         {
864                 if ( !gtk_tree_model_iter_nth_child( tree_model, iter, parent, indices[i] ) ) {
865                         return FALSE;
866                 }
867                 tmp = *iter;
868                 parent = &tmp;
869         }
870
871         return TRUE;
872 }
873
874 static GtkTreePath* graph_tree_model_get_path( GtkTreeModel* tree_model, GtkTreeIter* iter ){
875         ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
876         GraphTreeNode* graph = GRAPH_TREE_MODEL( tree_model )->m_graph;
877
878         GtkTreePath* path = ui::TreePath();
879
880         for ( GraphTreeNode* node = ( *graph_iterator_read_tree_iter( iter ) ).second; node != graph; node = node->m_parent )
881         {
882                 std::size_t index = 0;
883                 for ( GraphTreeNode::iterator i = node->m_parent->begin(); i != node->m_parent->end(); ++i, ++index )
884                 {
885                         if ( ( *i ).second == node ) {
886                                 gtk_tree_path_prepend_index( path, gint( index ) );
887                                 break;
888                         }
889                 }
890                 ASSERT_MESSAGE( index != node->m_parent->size(), "error resolving tree path" );
891         }
892
893         return path;
894 }
895
896
897 static void graph_tree_model_get_value( GtkTreeModel *tree_model, GtkTreeIter  *iter, gint column, GValue *value ){
898         ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
899         ASSERT_MESSAGE( column == 0 || column == 1, "tree model error" );
900
901         GraphTreeNode::iterator i = graph_iterator_read_tree_iter( iter );
902
903         g_value_init( value, G_TYPE_POINTER );
904
905         if ( column == 0 ) {
906                 g_value_set_pointer( value, reinterpret_cast<gpointer>( ( *i ).first.second ) );
907         }
908         else
909         {
910                 g_value_set_pointer( value, reinterpret_cast<gpointer>( &( *i ).second->m_instance.get() ) );
911         }
912 }
913
914 static gboolean graph_tree_model_iter_next( GtkTreeModel  *tree_model, GtkTreeIter   *iter ){
915         ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
916         GraphTreeNode::iterator i = graph_iterator_read_tree_iter( iter );
917         GraphTreeNode& parent = *( *i ).second->m_parent;
918
919         ASSERT_MESSAGE( i != parent.end(), "RUNTIME ERROR" );
920
921         if ( ++i == parent.end() ) {
922                 return FALSE;
923         }
924
925         graph_iterator_write_tree_iter( i, iter );
926
927         return TRUE;
928 }
929
930 static gboolean graph_tree_model_iter_children( GtkTreeModel *tree_model, GtkTreeIter  *iter, GtkTreeIter  *parent ){
931         ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
932         GraphTreeNode& node = ( parent == 0 ) ? *GRAPH_TREE_MODEL( tree_model )->m_graph : *( *graph_iterator_read_tree_iter( parent ) ).second;
933         if ( !node.empty() ) {
934                 graph_iterator_write_tree_iter( node.begin(), iter );
935                 return TRUE;
936         }
937
938         return FALSE;
939 }
940
941 static gboolean graph_tree_model_iter_has_child( GtkTreeModel *tree_model, GtkTreeIter  *iter ){
942         ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
943         GraphTreeNode& node = *( *graph_iterator_read_tree_iter( iter ) ).second;
944         return !node.empty();
945 }
946
947 static gint graph_tree_model_iter_n_children( GtkTreeModel *tree_model, GtkTreeIter *parent ){
948         ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
949         GraphTreeNode& node = ( parent == 0 ) ? *GRAPH_TREE_MODEL( tree_model )->m_graph : *( *graph_iterator_read_tree_iter( parent ) ).second;
950         return static_cast<gint>( node.size() );
951 }
952
953 static gboolean graph_tree_model_iter_nth_child( GtkTreeModel *tree_model, GtkTreeIter  *iter, GtkTreeIter  *parent, gint n ){
954         ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
955         GraphTreeNode& node = ( parent == 0 ) ? *GRAPH_TREE_MODEL( tree_model )->m_graph : *( *graph_iterator_read_tree_iter( parent ) ).second;
956         if ( static_cast<std::size_t>( n ) < node.size() ) {
957                 GraphTreeNode::iterator i = node.begin();
958                 std::advance( i, n );
959                 graph_iterator_write_tree_iter( i, iter );
960                 return TRUE;
961         }
962
963         return FALSE;
964 }
965
966 static gboolean graph_tree_model_iter_parent( GtkTreeModel *tree_model, GtkTreeIter  *iter, GtkTreeIter  *child ){
967         ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
968         GraphTreeNode& node = *( *graph_iterator_read_tree_iter( child ) ).second;
969         if ( node.m_parent != GRAPH_TREE_MODEL( tree_model )->m_graph ) {
970                 GraphTreeNode& parentParent = *node.m_parent->m_parent;
971                 for ( GraphTreeNode::iterator i = parentParent.begin(); i != parentParent.end(); ++i )
972                 {
973                         if ( ( *i ).second == node.m_parent ) {
974                                 graph_iterator_write_tree_iter( i, iter );
975                                 return TRUE;
976                         }
977                 }
978         }
979         return FALSE;
980 }
981
982 static GObjectClass *g_parent_class = 0;
983
984 namespace
985 {
986 scene::Node* g_null_node = 0;
987 }
988
989 class NullInstance : public scene::Instance
990 {
991 public:
992 NullInstance() : scene::Instance( scene::Path( makeReference( *g_null_node ) ), 0, 0, Static<InstanceTypeCastTable>::instance() ){
993 }
994 };
995
996 namespace
997 {
998 NullInstance g_null_instance;
999 }
1000
1001 static void graph_tree_model_init( GraphTreeModel *graph_tree_model ){
1002         graph_tree_model->m_graph = new GraphTreeNode( g_null_instance );
1003 }
1004
1005 static void graph_tree_model_finalize( GObject* object ){
1006         GraphTreeModel* graph_tree_model = GRAPH_TREE_MODEL( object );
1007
1008         delete graph_tree_model->m_graph;
1009
1010         /* must chain up */
1011         ( *g_parent_class->finalize )( object );
1012 }
1013
1014 static void graph_tree_model_class_init( GraphTreeModelClass *class_ ){
1015         GObjectClass *object_class;
1016
1017         g_parent_class = (GObjectClass*)g_type_class_peek_parent( class_ );
1018         object_class = (GObjectClass *) class_;
1019
1020         object_class->finalize = graph_tree_model_finalize;
1021 }
1022
1023 static void graph_tree_model_tree_model_init( GtkTreeModelIface *iface ){
1024         iface->get_flags = graph_tree_model_get_flags;
1025         iface->get_n_columns = graph_tree_model_get_n_columns;
1026         iface->get_column_type = graph_tree_model_get_column_type;
1027         iface->get_iter = graph_tree_model_get_iter;
1028         iface->get_path = graph_tree_model_get_path;
1029         iface->get_value = graph_tree_model_get_value;
1030         iface->iter_next = graph_tree_model_iter_next;
1031         iface->iter_children = graph_tree_model_iter_children;
1032         iface->iter_has_child = graph_tree_model_iter_has_child;
1033         iface->iter_n_children = graph_tree_model_iter_n_children;
1034         iface->iter_nth_child = graph_tree_model_iter_nth_child;
1035         iface->iter_parent = graph_tree_model_iter_parent;
1036 }
1037
1038 GType graph_tree_model_get_type( void ){
1039         static GType graph_tree_model_type = 0;
1040
1041         if ( !graph_tree_model_type ) {
1042                 static const GTypeInfo graph_tree_model_info =
1043                 {
1044                         sizeof( GraphTreeModelClass ),
1045                         0, /* base_init */
1046                         0, /* base_finalize */
1047                         (GClassInitFunc) graph_tree_model_class_init,
1048                         0, /* class_finalize */
1049                         0, /* class_data */
1050                         sizeof( GraphTreeModel ),
1051                         0,        /* n_preallocs */
1052                         (GInstanceInitFunc) graph_tree_model_init,
1053                         0
1054                 };
1055
1056                 static const GInterfaceInfo tree_model_info =
1057                 {
1058                         (GInterfaceInitFunc) graph_tree_model_tree_model_init,
1059                         0,
1060                         0
1061                 };
1062
1063                 graph_tree_model_type = g_type_register_static( G_TYPE_OBJECT, "GraphTreeModel",
1064                                                                                                                 &graph_tree_model_info, (GTypeFlags)0 );
1065
1066                 g_type_add_interface_static( graph_tree_model_type,
1067                                                                          GTK_TYPE_TREE_MODEL,
1068                                                                          &tree_model_info );
1069         }
1070
1071         return graph_tree_model_type;
1072 }
1073
1074 GraphTreeModel* graph_tree_model_new(){
1075         GraphTreeModel* graph_tree_model = GRAPH_TREE_MODEL( g_object_new( graph_tree_model_get_type(), 0 ) );
1076
1077         return graph_tree_model;
1078 }
1079
1080 void graph_tree_model_delete( GraphTreeModel* model ){
1081         g_object_unref( G_OBJECT( model ) );
1082 }
1083
1084 void graph_tree_model_row_changed( GraphTreeModel* model, GraphTreeNode::iterator i ){
1085         GtkTreeIter iter;
1086         graph_iterator_write_tree_iter( i, &iter );
1087
1088         GtkTreePath* tree_path = graph_tree_model_get_path( GTK_TREE_MODEL( model ), &iter );
1089
1090         gtk_tree_model_row_changed( GTK_TREE_MODEL( model ), tree_path, &iter );
1091
1092         gtk_tree_path_free( tree_path );
1093 }
1094
1095 void graph_tree_model_row_inserted( GraphTreeModel* model, GraphTreeNode::iterator i ){
1096         GtkTreeIter iter;
1097         graph_iterator_write_tree_iter( i, &iter );
1098
1099         GtkTreePath* tree_path = graph_tree_model_get_path( GTK_TREE_MODEL( model ), &iter );
1100
1101         gtk_tree_model_row_inserted( GTK_TREE_MODEL( model ), tree_path, &iter );
1102
1103         gtk_tree_path_free( tree_path );
1104 }
1105
1106 void graph_tree_model_row_deleted( GraphTreeModel* model, GraphTreeNode::iterator i ){
1107         GtkTreeIter iter;
1108         graph_iterator_write_tree_iter( i, &iter );
1109
1110         GtkTreePath* tree_path = graph_tree_model_get_path( GTK_TREE_MODEL( model ), &iter );
1111
1112         gtk_tree_model_row_deleted( GTK_TREE_MODEL( model ), tree_path );
1113
1114         gtk_tree_path_free( tree_path );
1115 }
1116
1117 void graph_tree_model_row_inserted( GraphTreeModel& model, GraphTreeNode::iterator i ){
1118         graph_tree_model_row_inserted( &model, i );
1119 }
1120
1121 void graph_tree_model_row_deleted( GraphTreeModel& model, GraphTreeNode::iterator i ){
1122         graph_tree_model_row_deleted( &model, i );
1123 }
1124
1125 const char* node_get_name( scene::Node& node );
1126
1127 const char* node_get_name_safe( scene::Node& node ){
1128         if ( &node == 0 ) {
1129                 return "";
1130         }
1131         return node_get_name( node );
1132 }
1133
1134 GraphTreeNode* graph_tree_model_find_parent( GraphTreeModel* model, const scene::Path& path ){
1135         GraphTreeNode* parent = model->m_graph;
1136         for ( scene::Path::const_iterator i = path.begin(); i != path.end() - 1; ++i )
1137         {
1138                 GraphTreeNode::iterator child = parent->find( GraphTreeNode::key_type( node_get_name_safe( ( *i ).get() ), ( *i ).get_pointer() ) );
1139                 ASSERT_MESSAGE( child != parent->end(), "ERROR" );
1140                 parent = ( *child ).second;
1141         }
1142         return parent;
1143 }
1144
1145 void node_attach_name_changed_callback( scene::Node& node, const NameCallback& callback ){
1146         if ( &node != 0 ) {
1147                 Nameable* nameable = Node_getNameable( node );
1148                 if ( nameable != 0 ) {
1149                         nameable->attach( callback );
1150                 }
1151         }
1152 }
1153 void node_detach_name_changed_callback( scene::Node& node, const NameCallback& callback ){
1154         if ( &node != 0 ) {
1155                 Nameable* nameable = Node_getNameable( node );
1156                 if ( nameable != 0 ) {
1157                         nameable->detach( callback );
1158                 }
1159         }
1160 }
1161
1162 GraphTreeModel* scene_graph_get_tree_model(); // temp hack
1163
1164 void graph_tree_node_foreach_pre( GraphTreeNode::iterator root, const Callback1<GraphTreeNode::iterator>& callback ){
1165         callback( root );
1166         for ( GraphTreeNode::iterator i = ( *root ).second->begin(); i != ( *root ).second->end(); ++i )
1167         {
1168                 graph_tree_node_foreach_pre( i, callback );
1169         }
1170 }
1171
1172 void graph_tree_node_foreach_post( GraphTreeNode::iterator root, const Callback1<GraphTreeNode::iterator>& callback ){
1173         for ( GraphTreeNode::iterator i = ( *root ).second->begin(); i != ( *root ).second->end(); ++i )
1174         {
1175                 graph_tree_node_foreach_post( i, callback );
1176         }
1177         callback( root );
1178 }
1179
1180 void graph_tree_model_row_changed( GraphTreeNode& node ){
1181         GraphTreeModel* model = scene_graph_get_tree_model();
1182         const scene::Instance& instance = node.m_instance.get();
1183
1184         GraphTreeNode::iterator i = node.m_parent->find( GraphTreeNode::key_type( node_get_name_safe( instance.path().top().get() ), instance.path().top().get_pointer() ) );
1185
1186         graph_tree_model_row_changed( model, i );
1187 }
1188
1189 void graph_tree_model_set_name( const scene::Instance& instance, const char* name ){
1190         GraphTreeModel* model = scene_graph_get_tree_model();
1191         GraphTreeNode* parent = graph_tree_model_find_parent( model, instance.path() );
1192
1193         GraphTreeNode::iterator oldNode = parent->find( GraphTreeNode::key_type( node_get_name_safe( instance.path().top().get() ), instance.path().top().get_pointer() ) );
1194         graph_tree_node_foreach_post( oldNode, ReferenceCaller1<GraphTreeModel, GraphTreeNode::iterator, graph_tree_model_row_deleted>( *model ) );
1195         GraphTreeNode* node( ( *oldNode ).second );
1196         parent->erase( oldNode );
1197
1198         GraphTreeNode::iterator newNode = parent->insert( GraphTreeNode::value_type( GraphTreeNode::key_type( name, &instance.path().top().get() ), node ) );
1199         graph_tree_node_foreach_pre( newNode, ReferenceCaller1<GraphTreeModel, GraphTreeNode::iterator, graph_tree_model_row_inserted>( *model ) );
1200 }
1201
1202 void graph_tree_model_insert( GraphTreeModel* model, const scene::Instance& instance ){
1203         GraphTreeNode* parent = graph_tree_model_find_parent( model, instance.path() );
1204
1205         GraphTreeNode::iterator i = parent->insert( GraphTreeNode::value_type( GraphTreeNode::key_type( node_get_name_safe( instance.path().top().get() ), instance.path().top().get_pointer() ), new GraphTreeNode( const_cast<scene::Instance&>( instance ) ) ) );
1206
1207         graph_tree_model_row_inserted( model, i );
1208
1209         node_attach_name_changed_callback( instance.path().top(), ConstReferenceCaller1<scene::Instance, const char*, graph_tree_model_set_name>( instance ) );
1210 }
1211
1212 void graph_tree_model_erase( GraphTreeModel* model, const scene::Instance& instance ){
1213         node_detach_name_changed_callback( instance.path().top(), ConstReferenceCaller1<scene::Instance, const char*, graph_tree_model_set_name>( instance ) );
1214
1215         GraphTreeNode* parent = graph_tree_model_find_parent( model, instance.path() );
1216
1217         GraphTreeNode::iterator i = parent->find( GraphTreeNode::key_type( node_get_name_safe( instance.path().top().get() ), instance.path().top().get_pointer() ) );
1218
1219         graph_tree_model_row_deleted( model, i );
1220
1221         GraphTreeNode* node( ( *i ).second );
1222         parent->erase( i );
1223         delete node;
1224 }
1225
1226
1227
1228 #endif
1229
1230
1231
1232
1233 #if 0
1234 class TestGraphTreeModel
1235 {
1236 public:
1237 TestGraphTreeModel(){
1238         gtk_init( 0, 0 );
1239
1240         graph_type graph;
1241
1242         scene::Node* root = *(scene::Node*)0xa0000000;
1243         scene::Node* node1 = (scene::Node*)0xa0000001;
1244         scene::Node* node2 = (scene::Node*)0xa0000002;
1245         scene::Node* node3 = (scene::Node*)0xa0000003;
1246         scene::Node* node4 = (scene::Node*)0xa0000004;
1247         scene::Instance* instance = (scene::Instance*)0xaaaaaaaa;
1248
1249         scene::Path rootpath( root );
1250
1251         graph.insert( graph_type::value_type( rootpath, instance ) );
1252
1253         rootpath.push( node1 );
1254         graph.insert( graph_type::value_type( rootpath, instance ) );
1255         rootpath.pop();
1256
1257         rootpath.push( node2 );
1258         graph.insert( graph_type::value_type( rootpath, instance ) );
1259         rootpath.push( node3 );
1260         graph.insert( graph_type::value_type( rootpath, instance ) );
1261         rootpath.pop();
1262         rootpath.push( node4 );
1263         graph.insert( graph_type::value_type( rootpath, instance ) );
1264         rootpath.pop();
1265         rootpath.pop();
1266
1267         GtkTreeModel* model = GTK_TREE_MODEL( graph_tree_model_new( &graph ) );
1268
1269         {
1270                 gint n_columns = gtk_tree_model_get_n_columns( model );
1271                 ASSERT_MESSAGE( n_columns == 2, "test failed!" );
1272         }
1273
1274         {
1275                 GType type = gtk_tree_model_get_column_type( model, 0 );
1276                 ASSERT_MESSAGE( type == G_TYPE_POINTER, "test failed!" );
1277         }
1278
1279         {
1280                 GType type = gtk_tree_model_get_column_type( model, 1 );
1281                 ASSERT_MESSAGE( type == G_TYPE_POINTER, "test failed!" );
1282         }
1283
1284
1285         {
1286                 GtkTreeIter iter;
1287                 gtk_tree_model_get_iter_first( model, &iter );
1288
1289                 graph_type::iterator i = graph_iterator_read_tree_iter( &iter );
1290                 ASSERT_MESSAGE( ( *i ).first.get().size() == 2 && ( *i ).first.get().top() == node1, "test failed!" );
1291         }
1292
1293         {
1294                 GtkTreeIter iter;
1295                 gtk_tree_model_get_iter_first( model, &iter );
1296
1297                 ASSERT_MESSAGE( gtk_tree_model_iter_has_child( model, &iter ) == FALSE, "test failed!" );
1298
1299                 ASSERT_MESSAGE( gtk_tree_model_iter_n_children( model, &iter ) == 0, "test failed!" );
1300
1301                 gtk_tree_model_iter_next( model, &iter );
1302
1303                 ASSERT_MESSAGE( gtk_tree_model_iter_has_child( model, &iter ) != FALSE, "test failed!" );
1304
1305                 ASSERT_MESSAGE( gtk_tree_model_iter_n_children( model, &iter ) == 2, "test failed!" );
1306
1307                 {
1308                         GtkTreeIter child;
1309                         gtk_tree_model_iter_nth_child( model, &child, &iter, 0 );
1310
1311                         scene::Node* test;
1312                         gtk_tree_model_get_value( model, &child, 0, (GValue*)&test );
1313                         ASSERT_MESSAGE( test == node3, "test failed!" );
1314
1315                         {
1316                                 GtkTreeIter parent;
1317                                 gtk_tree_model_iter_parent( model, &parent, &child );
1318
1319                                 scene::Node* test;
1320                                 gtk_tree_model_get_value( model, &parent, 0, (GValue*)&test );
1321                                 ASSERT_MESSAGE( test == node2, "test failed!" );
1322                         }
1323                 }
1324
1325                 {
1326                         GtkTreeIter child;
1327                         gtk_tree_model_iter_nth_child( model, &child, &iter, 1 );
1328
1329                         scene::Node* test;
1330                         gtk_tree_model_get_value( model, &child, 0, (GValue*)&test );
1331                         ASSERT_MESSAGE( test == node4, "test failed!" );
1332                 }
1333         }
1334
1335         {
1336                 GtkTreeIter iter;
1337                 std::size_t count = 0;
1338                 for ( gboolean good = gtk_tree_model_get_iter_first( model, &iter ); good; good = gtk_tree_model_iter_next( model, &iter ) )
1339                 {
1340                         scene::Node* test;
1341                         gtk_tree_model_get_value( model, &iter, 0, (GValue*)&test );
1342
1343                         ASSERT_MESSAGE( ( count == 0 && test == node1 ) || ( count == 1 && test == node2 ), "test failed!" );
1344                         ++count;
1345                 }
1346
1347                 ASSERT_MESSAGE( count == 2, "test failed!" );
1348
1349         }
1350
1351         {
1352                 GtkTreeIter iter;
1353                 gtk_tree_model_get_iter_first( model, &iter );
1354
1355                 scene::Node* test;
1356                 gtk_tree_model_get_value( model, &iter, 0, (GValue*)&test );
1357                 ASSERT_MESSAGE( test == node1, "test failed!" );
1358         }
1359
1360         {
1361                 GtkTreeIter iter;
1362                 GtkTreePath* path = ui::TreePath( "0" );
1363                 gtk_tree_model_get_iter( model, &iter, path );
1364                 gtk_tree_path_free( path );
1365
1366                 graph_type::iterator i = graph_iterator_read_tree_iter( &iter );
1367                 ASSERT_MESSAGE( ( *i ).first.get().size() == 2 && ( *i ).first.get().top() == node1, "test failed!" );
1368         }
1369
1370         {
1371                 GtkTreeIter iter;
1372                 GtkTreePath* path = ui::TreePath( "1" );
1373                 gtk_tree_model_get_iter( model, &iter, path );
1374                 gtk_tree_path_free( path );
1375
1376                 graph_type::iterator i = graph_iterator_read_tree_iter( &iter );
1377                 ASSERT_MESSAGE( ( *i ).first.get().size() == 2 && ( *i ).first.get().top() == node2, "test failed!" );
1378         }
1379
1380         {
1381                 GtkTreeIter iter;
1382                 graph_type::iterator i = graph.begin();
1383                 ++i;
1384                 graph_iterator_write_tree_iter( i, &iter );
1385
1386                 GtkTreePath* path = gtk_tree_model_get_path( model, &iter );
1387
1388                 gint depth = gtk_tree_path_get_depth( path );
1389                 gint* indices = gtk_tree_path_get_indices( path );
1390
1391                 ASSERT_MESSAGE( depth == 1 && indices[0] == 0, "test failed!" );
1392
1393                 gtk_tree_path_free( path );
1394         }
1395
1396         {
1397                 GtkTreeIter iter;
1398                 graph_type::iterator i = graph.begin();
1399                 ++i;
1400                 ++i;
1401                 graph_iterator_write_tree_iter( i, &iter );
1402
1403                 GtkTreePath* path = gtk_tree_model_get_path( model, &iter );
1404
1405                 gint depth = gtk_tree_path_get_depth( path );
1406                 gint* indices = gtk_tree_path_get_indices( path );
1407
1408                 ASSERT_MESSAGE( depth == 1 && indices[0] == 1, "test failed!" );
1409
1410                 gtk_tree_path_free( path );
1411         }
1412 }
1413 };
1414
1415
1416 TestGraphTreeModel g_TestGraphTreeModel;
1417
1418 #endif