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