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