]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - radiant/treemodel.cpp
Merge branch 'dpkdir' into 'master'
[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         // Reference cannot be bound to dereferenced null pointer in well-defined
651         // C++ code, and Clang will assume that comparison below always evaluates
652         // to true, resulting in a segmentation fault.  Use a dirty hack to force
653         // Clang to check those "bad" references for null nonetheless.
654         volatile intptr_t n = (intptr_t)&node;
655
656         if ( n != 0 ) {
657                 Nameable* nameable = Node_getNameable( node );
658                 if ( nameable != 0 ) {
659                         nameable->attach( callback );
660                 }
661         }
662 }
663 void node_detach_name_changed_callback( scene::Node& node, const NameCallback& callback ){
664         volatile intptr_t n = (intptr_t)&node;  // see the comment on line 650
665
666         if ( n != 0 ) {
667                 Nameable* nameable = Node_getNameable( node );
668                 if ( nameable != 0 ) {
669                         nameable->detach( callback );
670                 }
671         }
672 }
673
674 GraphTreeModel* scene_graph_get_tree_model(); // temp hack
675
676 void graph_tree_model_row_inserted( GraphTreeModel* model, graph_type::iterator i ){
677         GtkTreeIter iter;
678         graph_iterator_write_tree_iter( i, &iter );
679
680         GtkTreePath* tree_path = graph_tree_model_get_path( GTK_TREE_MODEL( model ), &iter );
681
682         gint depth = gtk_tree_path_get_depth( tree_path );
683         gint* indices = gtk_tree_path_get_indices( tree_path );
684
685         gtk_tree_model_row_inserted( GTK_TREE_MODEL( model ), tree_path, &iter );
686
687         gtk_tree_path_free( tree_path );
688 }
689
690 void graph_tree_model_row_deleted( GraphTreeModel* model, graph_type::iterator i ){
691         GtkTreeIter iter;
692         graph_iterator_write_tree_iter( i, &iter );
693
694         GtkTreePath* tree_path = graph_tree_model_get_path( GTK_TREE_MODEL( model ), &iter );
695
696         gtk_tree_model_row_deleted( GTK_TREE_MODEL( model ), tree_path );
697
698         gtk_tree_path_free( tree_path );
699 }
700
701 #include "generic/referencecounted.h"
702
703 void graph_tree_model_set_name( const scene::Instance& instance, const char* name ){
704         GraphTreeModel* model = scene_graph_get_tree_model();
705
706         if ( string_empty( name ) ) { // hack!
707                 graph_type::iterator i = model->graph->find( PathConstReference( instance.path() ) );
708                 ASSERT_MESSAGE( i != model->graph->end(), "ERROR" );
709
710                 graph_tree_model_row_deleted( model, i );
711
712                 model->graph->erase( i );
713         }
714         else
715         {
716                 graph_type::iterator i = model->graph->insert( graph_type::value_type( PathConstReference( instance.path() ), &const_cast<scene::Instance&>( instance ) ) ).first;
717
718                 graph_tree_model_row_inserted( model, i );
719         }
720 }
721
722 void graph_tree_model_insert( GraphTreeModel* model, const scene::Instance& instance ){
723         graph_type::iterator i = model->graph->insert( graph_type::value_type( PathConstReference( instance.path() ), &const_cast<scene::Instance&>( instance ) ) ).first;
724
725         graph_tree_model_row_inserted( model, i );
726
727         node_attach_name_changed_callback( instance.path().top(), ConstReferenceCaller1<scene::Instance, const char*, graph_tree_model_set_name>( instance ) );
728 }
729
730 void graph_tree_model_erase( GraphTreeModel* model, const scene::Instance& instance ){
731         node_detach_name_changed_callback( instance.path().top(), ConstReferenceCaller1<scene::Instance, const char*, graph_tree_model_set_name>( instance ) );
732
733         graph_type::iterator i = model->graph->find( PathConstReference( instance.path() ) );
734         ASSERT_MESSAGE( i != model->graph->end(), "ERROR" );
735
736         graph_tree_model_row_deleted( model, i );
737
738         model->graph->erase( i );
739 }
740
741 #elif 1
742
743 class GraphTreeNode;
744 void graph_tree_model_row_changed( GraphTreeNode& node );
745
746 class GraphTreeNode
747 {
748 typedef std::map<std::pair<CopiedString, scene::Node*>, GraphTreeNode*> ChildNodes;
749 ChildNodes m_childnodes;
750 public:
751 Reference<scene::Instance> m_instance;
752 GraphTreeNode* m_parent;
753
754 typedef ChildNodes::iterator iterator;
755 typedef ChildNodes::key_type key_type;
756 typedef ChildNodes::value_type value_type;
757 typedef ChildNodes::size_type size_type;
758
759 GraphTreeNode( scene::Instance& instance ) : m_instance( instance ), m_parent( 0 ){
760         m_instance.get().setChildSelectedChangedCallback( RowChangedCaller( *this ) );
761 }
762 ~GraphTreeNode(){
763         m_instance.get().setChildSelectedChangedCallback( Callback() );
764         ASSERT_MESSAGE( empty(), "GraphTreeNode::~GraphTreeNode: memory leak" );
765 }
766
767 iterator begin(){
768         return m_childnodes.begin();
769 }
770 iterator end(){
771         return m_childnodes.end();
772 }
773
774 size_type size() const {
775         return m_childnodes.size();
776 }
777 bool empty() const {
778         return m_childnodes.empty();
779 }
780
781 iterator insert( const value_type& value ){
782         iterator i = m_childnodes.insert( value ).first;
783         ( *i ).second->m_parent = this;
784         return i;
785 }
786 void erase( iterator i ){
787         m_childnodes.erase( i );
788 }
789 iterator find( const key_type& key ){
790         return m_childnodes.find( key );
791 }
792
793 void swap( GraphTreeNode& other ){
794         std::swap( m_parent, other.m_parent );
795         std::swap( m_childnodes, other.m_childnodes );
796         std::swap( m_instance, other.m_instance );
797 }
798
799 void rowChanged(){
800         graph_tree_model_row_changed( *this );
801 }
802 typedef MemberCaller<GraphTreeNode, &GraphTreeNode::rowChanged> RowChangedCaller;
803 };
804
805 struct GraphTreeModel
806 {
807         GObject parent;
808
809         GraphTreeNode* m_graph;
810 };
811
812 struct GraphTreeModelClass
813 {
814         GObjectClass parent_class;
815 };
816
817 #define GRAPH_TREE_MODEL( p ) ( reinterpret_cast<GraphTreeModel*>( p ) )
818
819 static GtkTreeModelFlags graph_tree_model_get_flags( GtkTreeModel* tree_model ){
820         return GTK_TREE_MODEL_ITERS_PERSIST;
821 }
822
823 static gint graph_tree_model_get_n_columns( GtkTreeModel* tree_model ){
824         ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
825         //GraphTreeModel* graph_tree_model = (GraphTreeModel*) tree_model;
826
827         return 2;
828 }
829
830 static const gint c_stamp = 0xabcdef;
831
832 inline GraphTreeNode::iterator graph_iterator_read_tree_iter( GtkTreeIter* iter ){
833         ASSERT_MESSAGE( iter != 0,  "tree model error" );
834         ASSERT_MESSAGE( iter->user_data != 0,  "tree model error" );
835         ASSERT_MESSAGE( iter->stamp == c_stamp,  "tree model error" );
836         return *reinterpret_cast<GraphTreeNode::iterator*>( &iter->user_data );
837 }
838
839 inline void graph_iterator_write_tree_iter( GraphTreeNode::iterator i, GtkTreeIter* iter ){
840         ASSERT_MESSAGE( iter != 0,  "tree model error" );
841         iter->stamp = c_stamp;
842         *reinterpret_cast<GraphTreeNode::iterator*>( &iter->user_data ) = i;
843         ASSERT_MESSAGE( iter->user_data != 0,  "tree model error" );
844 }
845
846 static GType graph_tree_model_get_column_type( GtkTreeModel *tree_model, gint index ){
847         ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
848         //GraphTreeModel *graph_tree_model = (GraphTreeModel *) tree_model;
849
850         return G_TYPE_POINTER;
851 }
852
853 static gboolean graph_tree_model_get_iter( GtkTreeModel* tree_model, GtkTreeIter* iter, GtkTreePath* path ){
854         ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
855         gint* indices = gtk_tree_path_get_indices( path );
856         gint depth = gtk_tree_path_get_depth( path );
857
858         g_return_val_if_fail( depth > 0, FALSE );
859
860         GraphTreeNode* graph = GRAPH_TREE_MODEL( tree_model )->m_graph;
861
862         if ( graph->empty() ) {
863                 return FALSE;
864         }
865
866         GtkTreeIter tmp;
867         GtkTreeIter* parent = 0;
868
869         for ( gint i = 0; i < depth; i++ )
870         {
871                 if ( !gtk_tree_model_iter_nth_child( tree_model, iter, parent, indices[i] ) ) {
872                         return FALSE;
873                 }
874                 tmp = *iter;
875                 parent = &tmp;
876         }
877
878         return TRUE;
879 }
880
881 static GtkTreePath* graph_tree_model_get_path( GtkTreeModel* tree_model, GtkTreeIter* iter ){
882         ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
883         GraphTreeNode* graph = GRAPH_TREE_MODEL( tree_model )->m_graph;
884
885         GtkTreePath* path = gtk_tree_path_new();
886
887         for ( GraphTreeNode* node = ( *graph_iterator_read_tree_iter( iter ) ).second; node != graph; node = node->m_parent )
888         {
889                 std::size_t index = 0;
890                 for ( GraphTreeNode::iterator i = node->m_parent->begin(); i != node->m_parent->end(); ++i, ++index )
891                 {
892                         if ( ( *i ).second == node ) {
893                                 gtk_tree_path_prepend_index( path, gint( index ) );
894                                 break;
895                         }
896                 }
897                 ASSERT_MESSAGE( index != node->m_parent->size(), "error resolving tree path" );
898         }
899
900         return path;
901 }
902
903
904 static void graph_tree_model_get_value( GtkTreeModel *tree_model, GtkTreeIter  *iter, gint column, GValue *value ){
905         ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
906         ASSERT_MESSAGE( column == 0 || column == 1, "tree model error" );
907
908         GraphTreeNode::iterator i = graph_iterator_read_tree_iter( iter );
909
910         g_value_init( value, G_TYPE_POINTER );
911
912         if ( column == 0 ) {
913                 g_value_set_pointer( value, reinterpret_cast<gpointer>( ( *i ).first.second ) );
914         }
915         else
916         {
917                 g_value_set_pointer( value, reinterpret_cast<gpointer>( &( *i ).second->m_instance.get() ) );
918         }
919 }
920
921 static gboolean graph_tree_model_iter_next( GtkTreeModel  *tree_model, GtkTreeIter   *iter ){
922         ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
923         GraphTreeNode::iterator i = graph_iterator_read_tree_iter( iter );
924         GraphTreeNode& parent = *( *i ).second->m_parent;
925
926         ASSERT_MESSAGE( i != parent.end(), "RUNTIME ERROR" );
927
928         if ( ++i == parent.end() ) {
929                 return FALSE;
930         }
931
932         graph_iterator_write_tree_iter( i, iter );
933
934         return TRUE;
935 }
936
937 static gboolean graph_tree_model_iter_children( GtkTreeModel *tree_model, GtkTreeIter  *iter, GtkTreeIter  *parent ){
938         ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
939         GraphTreeNode& node = ( parent == 0 ) ? *GRAPH_TREE_MODEL( tree_model )->m_graph : *( *graph_iterator_read_tree_iter( parent ) ).second;
940         if ( !node.empty() ) {
941                 graph_iterator_write_tree_iter( node.begin(), iter );
942                 return TRUE;
943         }
944
945         return FALSE;
946 }
947
948 static gboolean graph_tree_model_iter_has_child( GtkTreeModel *tree_model, GtkTreeIter  *iter ){
949         ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
950         GraphTreeNode& node = *( *graph_iterator_read_tree_iter( iter ) ).second;
951         return !node.empty();
952 }
953
954 static gint graph_tree_model_iter_n_children( GtkTreeModel *tree_model, GtkTreeIter *parent ){
955         ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
956         GraphTreeNode& node = ( parent == 0 ) ? *GRAPH_TREE_MODEL( tree_model )->m_graph : *( *graph_iterator_read_tree_iter( parent ) ).second;
957         return static_cast<gint>( node.size() );
958 }
959
960 static gboolean graph_tree_model_iter_nth_child( GtkTreeModel *tree_model, GtkTreeIter  *iter, GtkTreeIter  *parent, gint n ){
961         ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
962         GraphTreeNode& node = ( parent == 0 ) ? *GRAPH_TREE_MODEL( tree_model )->m_graph : *( *graph_iterator_read_tree_iter( parent ) ).second;
963         if ( static_cast<std::size_t>( n ) < node.size() ) {
964                 GraphTreeNode::iterator i = node.begin();
965                 std::advance( i, n );
966                 graph_iterator_write_tree_iter( i, iter );
967                 return TRUE;
968         }
969
970         return FALSE;
971 }
972
973 static gboolean graph_tree_model_iter_parent( GtkTreeModel *tree_model, GtkTreeIter  *iter, GtkTreeIter  *child ){
974         ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
975         GraphTreeNode& node = *( *graph_iterator_read_tree_iter( child ) ).second;
976         if ( node.m_parent != GRAPH_TREE_MODEL( tree_model )->m_graph ) {
977                 GraphTreeNode& parentParent = *node.m_parent->m_parent;
978                 for ( GraphTreeNode::iterator i = parentParent.begin(); i != parentParent.end(); ++i )
979                 {
980                         if ( ( *i ).second == node.m_parent ) {
981                                 graph_iterator_write_tree_iter( i, iter );
982                                 return TRUE;
983                         }
984                 }
985         }
986         return FALSE;
987 }
988
989 static GObjectClass *g_parent_class = 0;
990
991 namespace
992 {
993 scene::Node* g_null_node = 0;
994 }
995
996 class NullInstance : public scene::Instance
997 {
998 public:
999 NullInstance() : scene::Instance( scene::Path( makeReference( *g_null_node ) ), 0, 0, Static<InstanceTypeCastTable>::instance() ){
1000 }
1001 };
1002
1003 namespace
1004 {
1005 NullInstance g_null_instance;
1006 }
1007
1008 static void graph_tree_model_init( GraphTreeModel *graph_tree_model ){
1009         graph_tree_model->m_graph = new GraphTreeNode( g_null_instance );
1010 }
1011
1012 static void graph_tree_model_finalize( GObject* object ){
1013         GraphTreeModel* graph_tree_model = GRAPH_TREE_MODEL( object );
1014
1015         delete graph_tree_model->m_graph;
1016
1017         /* must chain up */
1018         ( *g_parent_class->finalize )( object );
1019 }
1020
1021 static void graph_tree_model_class_init( GraphTreeModelClass *class_ ){
1022         GObjectClass *object_class;
1023
1024         g_parent_class = (GObjectClass*)g_type_class_peek_parent( class_ );
1025         object_class = (GObjectClass *) class_;
1026
1027         object_class->finalize = graph_tree_model_finalize;
1028 }
1029
1030 static void graph_tree_model_tree_model_init( GtkTreeModelIface *iface ){
1031         iface->get_flags = graph_tree_model_get_flags;
1032         iface->get_n_columns = graph_tree_model_get_n_columns;
1033         iface->get_column_type = graph_tree_model_get_column_type;
1034         iface->get_iter = graph_tree_model_get_iter;
1035         iface->get_path = graph_tree_model_get_path;
1036         iface->get_value = graph_tree_model_get_value;
1037         iface->iter_next = graph_tree_model_iter_next;
1038         iface->iter_children = graph_tree_model_iter_children;
1039         iface->iter_has_child = graph_tree_model_iter_has_child;
1040         iface->iter_n_children = graph_tree_model_iter_n_children;
1041         iface->iter_nth_child = graph_tree_model_iter_nth_child;
1042         iface->iter_parent = graph_tree_model_iter_parent;
1043 }
1044
1045 GType graph_tree_model_get_type( void ){
1046         static GType graph_tree_model_type = 0;
1047
1048         if ( !graph_tree_model_type ) {
1049                 static const GTypeInfo graph_tree_model_info =
1050                 {
1051                         sizeof( GraphTreeModelClass ),
1052                         0, /* base_init */
1053                         0, /* base_finalize */
1054                         (GClassInitFunc) graph_tree_model_class_init,
1055                         0, /* class_finalize */
1056                         0, /* class_data */
1057                         sizeof( GraphTreeModel ),
1058                         0,        /* n_preallocs */
1059                         (GInstanceInitFunc) graph_tree_model_init,
1060                         0
1061                 };
1062
1063                 static const GInterfaceInfo tree_model_info =
1064                 {
1065                         (GInterfaceInitFunc) graph_tree_model_tree_model_init,
1066                         0,
1067                         0
1068                 };
1069
1070                 graph_tree_model_type = g_type_register_static( G_TYPE_OBJECT, "GraphTreeModel",
1071                                                                                                                 &graph_tree_model_info, (GTypeFlags)0 );
1072
1073                 g_type_add_interface_static( graph_tree_model_type,
1074                                                                          GTK_TYPE_TREE_MODEL,
1075                                                                          &tree_model_info );
1076         }
1077
1078         return graph_tree_model_type;
1079 }
1080
1081 GraphTreeModel* graph_tree_model_new(){
1082         GraphTreeModel* graph_tree_model = GRAPH_TREE_MODEL( g_object_new( graph_tree_model_get_type(), 0 ) );
1083
1084         return graph_tree_model;
1085 }
1086
1087 void graph_tree_model_delete( GraphTreeModel* model ){
1088         g_object_unref( G_OBJECT( model ) );
1089 }
1090
1091 void graph_tree_model_row_changed( GraphTreeModel* model, GraphTreeNode::iterator i ){
1092         GtkTreeIter iter;
1093         graph_iterator_write_tree_iter( i, &iter );
1094
1095         GtkTreePath* tree_path = graph_tree_model_get_path( GTK_TREE_MODEL( model ), &iter );
1096
1097         gtk_tree_model_row_changed( GTK_TREE_MODEL( model ), tree_path, &iter );
1098
1099         gtk_tree_path_free( tree_path );
1100 }
1101
1102 void graph_tree_model_row_inserted( GraphTreeModel* model, GraphTreeNode::iterator i ){
1103         GtkTreeIter iter;
1104         graph_iterator_write_tree_iter( i, &iter );
1105
1106         GtkTreePath* tree_path = graph_tree_model_get_path( GTK_TREE_MODEL( model ), &iter );
1107
1108         gtk_tree_model_row_inserted( GTK_TREE_MODEL( model ), tree_path, &iter );
1109
1110         gtk_tree_path_free( tree_path );
1111 }
1112
1113 void graph_tree_model_row_deleted( GraphTreeModel* model, GraphTreeNode::iterator i ){
1114         GtkTreeIter iter;
1115         graph_iterator_write_tree_iter( i, &iter );
1116
1117         GtkTreePath* tree_path = graph_tree_model_get_path( GTK_TREE_MODEL( model ), &iter );
1118
1119         gtk_tree_model_row_deleted( GTK_TREE_MODEL( model ), tree_path );
1120
1121         gtk_tree_path_free( tree_path );
1122 }
1123
1124 void graph_tree_model_row_inserted( GraphTreeModel& model, GraphTreeNode::iterator i ){
1125         graph_tree_model_row_inserted( &model, i );
1126 }
1127
1128 void graph_tree_model_row_deleted( GraphTreeModel& model, GraphTreeNode::iterator i ){
1129         graph_tree_model_row_deleted( &model, i );
1130 }
1131
1132 const char* node_get_name( scene::Node& node );
1133
1134 const char* node_get_name_safe( scene::Node& node ){
1135         volatile intptr_t n = (intptr_t)&node;  // see the comment on line 650
1136         if ( n == 0 ) {
1137                 return "";
1138         }
1139         return node_get_name( node );
1140 }
1141
1142 GraphTreeNode* graph_tree_model_find_parent( GraphTreeModel* model, const scene::Path& path ){
1143         GraphTreeNode* parent = model->m_graph;
1144         for ( scene::Path::const_iterator i = path.begin(); i != path.end() - 1; ++i )
1145         {
1146                 GraphTreeNode::iterator child = parent->find( GraphTreeNode::key_type( node_get_name_safe( ( *i ).get() ), ( *i ).get_pointer() ) );
1147                 ASSERT_MESSAGE( child != parent->end(), "ERROR" );
1148                 parent = ( *child ).second;
1149         }
1150         return parent;
1151 }
1152
1153 void node_attach_name_changed_callback( scene::Node& node, const NameCallback& callback ){
1154         volatile intptr_t n = (intptr_t)&node;  // see the comment on line 650
1155         if ( n != 0 ) {
1156                 Nameable* nameable = Node_getNameable( node );
1157                 if ( nameable != 0 ) {
1158                         nameable->attach( callback );
1159                 }
1160         }
1161 }
1162 void node_detach_name_changed_callback( scene::Node& node, const NameCallback& callback ){
1163         volatile intptr_t n = (intptr_t)&node;  // see the comment on line 650
1164         if ( n != 0 ) {
1165                 Nameable* nameable = Node_getNameable( node );
1166                 if ( nameable != 0 ) {
1167                         nameable->detach( callback );
1168                 }
1169         }
1170 }
1171
1172 GraphTreeModel* scene_graph_get_tree_model(); // temp hack
1173
1174 void graph_tree_node_foreach_pre( GraphTreeNode::iterator root, const Callback1<GraphTreeNode::iterator>& callback ){
1175         callback( root );
1176         for ( GraphTreeNode::iterator i = ( *root ).second->begin(); i != ( *root ).second->end(); ++i )
1177         {
1178                 graph_tree_node_foreach_pre( i, callback );
1179         }
1180 }
1181
1182 void graph_tree_node_foreach_post( GraphTreeNode::iterator root, const Callback1<GraphTreeNode::iterator>& callback ){
1183         for ( GraphTreeNode::iterator i = ( *root ).second->begin(); i != ( *root ).second->end(); ++i )
1184         {
1185                 graph_tree_node_foreach_post( i, callback );
1186         }
1187         callback( root );
1188 }
1189
1190 void graph_tree_model_row_changed( GraphTreeNode& node ){
1191         GraphTreeModel* model = scene_graph_get_tree_model();
1192         const scene::Instance& instance = node.m_instance.get();
1193
1194         GraphTreeNode::iterator i = node.m_parent->find( GraphTreeNode::key_type( node_get_name_safe( instance.path().top().get() ), instance.path().top().get_pointer() ) );
1195
1196         graph_tree_model_row_changed( model, i );
1197 }
1198
1199 void graph_tree_model_set_name( const scene::Instance& instance, const char* name ){
1200         GraphTreeModel* model = scene_graph_get_tree_model();
1201         GraphTreeNode* parent = graph_tree_model_find_parent( model, instance.path() );
1202
1203         GraphTreeNode::iterator oldNode = parent->find( GraphTreeNode::key_type( node_get_name_safe( instance.path().top().get() ), instance.path().top().get_pointer() ) );
1204         graph_tree_node_foreach_post( oldNode, ReferenceCaller1<GraphTreeModel, GraphTreeNode::iterator, graph_tree_model_row_deleted>( *model ) );
1205         GraphTreeNode* node( ( *oldNode ).second );
1206         parent->erase( oldNode );
1207
1208         GraphTreeNode::iterator newNode = parent->insert( GraphTreeNode::value_type( GraphTreeNode::key_type( name, &instance.path().top().get() ), node ) );
1209         graph_tree_node_foreach_pre( newNode, ReferenceCaller1<GraphTreeModel, GraphTreeNode::iterator, graph_tree_model_row_inserted>( *model ) );
1210 }
1211
1212 void graph_tree_model_insert( GraphTreeModel* model, const scene::Instance& instance ){
1213         GraphTreeNode* parent = graph_tree_model_find_parent( model, instance.path() );
1214
1215         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 ) ) ) );
1216
1217         graph_tree_model_row_inserted( model, i );
1218
1219         node_attach_name_changed_callback( instance.path().top(), ConstReferenceCaller1<scene::Instance, const char*, graph_tree_model_set_name>( instance ) );
1220 }
1221
1222 void graph_tree_model_erase( GraphTreeModel* model, const scene::Instance& instance ){
1223         node_detach_name_changed_callback( instance.path().top(), ConstReferenceCaller1<scene::Instance, const char*, graph_tree_model_set_name>( instance ) );
1224
1225         GraphTreeNode* parent = graph_tree_model_find_parent( model, instance.path() );
1226
1227         GraphTreeNode::iterator i = parent->find( GraphTreeNode::key_type( node_get_name_safe( instance.path().top().get() ), instance.path().top().get_pointer() ) );
1228
1229         graph_tree_model_row_deleted( model, i );
1230
1231         GraphTreeNode* node( ( *i ).second );
1232         parent->erase( i );
1233         delete node;
1234 }
1235
1236
1237
1238 #endif
1239
1240
1241
1242
1243 #if 0
1244 class TestGraphTreeModel
1245 {
1246 public:
1247 TestGraphTreeModel(){
1248         gtk_init( 0, 0 );
1249
1250         graph_type graph;
1251
1252         scene::Node* root = *(scene::Node*)0xa0000000;
1253         scene::Node* node1 = (scene::Node*)0xa0000001;
1254         scene::Node* node2 = (scene::Node*)0xa0000002;
1255         scene::Node* node3 = (scene::Node*)0xa0000003;
1256         scene::Node* node4 = (scene::Node*)0xa0000004;
1257         scene::Instance* instance = (scene::Instance*)0xaaaaaaaa;
1258
1259         scene::Path rootpath( root );
1260
1261         graph.insert( graph_type::value_type( rootpath, instance ) );
1262
1263         rootpath.push( node1 );
1264         graph.insert( graph_type::value_type( rootpath, instance ) );
1265         rootpath.pop();
1266
1267         rootpath.push( node2 );
1268         graph.insert( graph_type::value_type( rootpath, instance ) );
1269         rootpath.push( node3 );
1270         graph.insert( graph_type::value_type( rootpath, instance ) );
1271         rootpath.pop();
1272         rootpath.push( node4 );
1273         graph.insert( graph_type::value_type( rootpath, instance ) );
1274         rootpath.pop();
1275         rootpath.pop();
1276
1277         GtkTreeModel* model = GTK_TREE_MODEL( graph_tree_model_new( &graph ) );
1278
1279         {
1280                 gint n_columns = gtk_tree_model_get_n_columns( model );
1281                 ASSERT_MESSAGE( n_columns == 2, "test failed!" );
1282         }
1283
1284         {
1285                 GType type = gtk_tree_model_get_column_type( model, 0 );
1286                 ASSERT_MESSAGE( type == G_TYPE_POINTER, "test failed!" );
1287         }
1288
1289         {
1290                 GType type = gtk_tree_model_get_column_type( model, 1 );
1291                 ASSERT_MESSAGE( type == G_TYPE_POINTER, "test failed!" );
1292         }
1293
1294
1295         {
1296                 GtkTreeIter iter;
1297                 gtk_tree_model_get_iter_first( model, &iter );
1298
1299                 graph_type::iterator i = graph_iterator_read_tree_iter( &iter );
1300                 ASSERT_MESSAGE( ( *i ).first.get().size() == 2 && ( *i ).first.get().top() == node1, "test failed!" );
1301         }
1302
1303         {
1304                 GtkTreeIter iter;
1305                 gtk_tree_model_get_iter_first( model, &iter );
1306
1307                 ASSERT_MESSAGE( gtk_tree_model_iter_has_child( model, &iter ) == FALSE, "test failed!" );
1308
1309                 ASSERT_MESSAGE( gtk_tree_model_iter_n_children( model, &iter ) == 0, "test failed!" );
1310
1311                 gtk_tree_model_iter_next( model, &iter );
1312
1313                 ASSERT_MESSAGE( gtk_tree_model_iter_has_child( model, &iter ) != FALSE, "test failed!" );
1314
1315                 ASSERT_MESSAGE( gtk_tree_model_iter_n_children( model, &iter ) == 2, "test failed!" );
1316
1317                 {
1318                         GtkTreeIter child;
1319                         gtk_tree_model_iter_nth_child( model, &child, &iter, 0 );
1320
1321                         scene::Node* test;
1322                         gtk_tree_model_get_value( model, &child, 0, (GValue*)&test );
1323                         ASSERT_MESSAGE( test == node3, "test failed!" );
1324
1325                         {
1326                                 GtkTreeIter parent;
1327                                 gtk_tree_model_iter_parent( model, &parent, &child );
1328
1329                                 scene::Node* test;
1330                                 gtk_tree_model_get_value( model, &parent, 0, (GValue*)&test );
1331                                 ASSERT_MESSAGE( test == node2, "test failed!" );
1332                         }
1333                 }
1334
1335                 {
1336                         GtkTreeIter child;
1337                         gtk_tree_model_iter_nth_child( model, &child, &iter, 1 );
1338
1339                         scene::Node* test;
1340                         gtk_tree_model_get_value( model, &child, 0, (GValue*)&test );
1341                         ASSERT_MESSAGE( test == node4, "test failed!" );
1342                 }
1343         }
1344
1345         {
1346                 GtkTreeIter iter;
1347                 std::size_t count = 0;
1348                 for ( gboolean good = gtk_tree_model_get_iter_first( model, &iter ); good; good = gtk_tree_model_iter_next( model, &iter ) )
1349                 {
1350                         scene::Node* test;
1351                         gtk_tree_model_get_value( model, &iter, 0, (GValue*)&test );
1352
1353                         ASSERT_MESSAGE( ( count == 0 && test == node1 ) || ( count == 1 && test == node2 ), "test failed!" );
1354                         ++count;
1355                 }
1356
1357                 ASSERT_MESSAGE( count == 2, "test failed!" );
1358
1359         }
1360
1361         {
1362                 GtkTreeIter iter;
1363                 gtk_tree_model_get_iter_first( model, &iter );
1364
1365                 scene::Node* test;
1366                 gtk_tree_model_get_value( model, &iter, 0, (GValue*)&test );
1367                 ASSERT_MESSAGE( test == node1, "test failed!" );
1368         }
1369
1370         {
1371                 GtkTreeIter iter;
1372                 GtkTreePath* path = gtk_tree_path_new_from_string( "0" );
1373                 gtk_tree_model_get_iter( model, &iter, path );
1374                 gtk_tree_path_free( path );
1375
1376                 graph_type::iterator i = graph_iterator_read_tree_iter( &iter );
1377                 ASSERT_MESSAGE( ( *i ).first.get().size() == 2 && ( *i ).first.get().top() == node1, "test failed!" );
1378         }
1379
1380         {
1381                 GtkTreeIter iter;
1382                 GtkTreePath* path = gtk_tree_path_new_from_string( "1" );
1383                 gtk_tree_model_get_iter( model, &iter, path );
1384                 gtk_tree_path_free( path );
1385
1386                 graph_type::iterator i = graph_iterator_read_tree_iter( &iter );
1387                 ASSERT_MESSAGE( ( *i ).first.get().size() == 2 && ( *i ).first.get().top() == node2, "test failed!" );
1388         }
1389
1390         {
1391                 GtkTreeIter iter;
1392                 graph_type::iterator i = graph.begin();
1393                 ++i;
1394                 graph_iterator_write_tree_iter( i, &iter );
1395
1396                 GtkTreePath* path = gtk_tree_model_get_path( model, &iter );
1397
1398                 gint depth = gtk_tree_path_get_depth( path );
1399                 gint* indices = gtk_tree_path_get_indices( path );
1400
1401                 ASSERT_MESSAGE( depth == 1 && indices[0] == 0, "test failed!" );
1402
1403                 gtk_tree_path_free( path );
1404         }
1405
1406         {
1407                 GtkTreeIter iter;
1408                 graph_type::iterator i = graph.begin();
1409                 ++i;
1410                 ++i;
1411                 graph_iterator_write_tree_iter( i, &iter );
1412
1413                 GtkTreePath* path = gtk_tree_model_get_path( model, &iter );
1414
1415                 gint depth = gtk_tree_path_get_depth( path );
1416                 gint* indices = gtk_tree_path_get_indices( path );
1417
1418                 ASSERT_MESSAGE( depth == 1 && indices[0] == 1, "test failed!" );
1419
1420                 gtk_tree_path_free( path );
1421         }
1422 }
1423 };
1424
1425
1426 TestGraphTreeModel g_TestGraphTreeModel;
1427
1428 #endif