]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - radiant/treemodel.cpp
Merge branch 'NateEag-master-patch-12920' 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 #include "globaldefs.h"
24
25 #include "debugging/debugging.h"
26
27 #include <map>
28 #include <gtk/gtk.h>
29 #include <uilib/uilib.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( ui::TreeModel 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 ui::TreeStore 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( model, iter, parent );
68                   success != FALSE;
69                   success = gtk_tree_model_iter_next( model, iter ) )
70         {
71                 scene::Node* current;
72                 gtk_tree_model_get_pointer( 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<void()>& 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<void()>& 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, void(), 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, void(), 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( ui::TreeModel 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( ui::TreeModel 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( ui::TreeModel tree_model, GtkTreeIter* iter, ui::TreePath 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 ui::TreePath graph_tree_model_get_path( ui::TreeModel 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         auto path = ui::TreePath();
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( ui::TreeModel 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( ui::TreeModel  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( ui::TreeModel 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( ui::TreeModel 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( ui::TreeModel 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( ui::TreeModel 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( ui::TreeModel 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, ui::TreePath path ){
469 #if GDEF_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, ui::TreePath path ){
476         GtkTreeIter iter;
477
478         if ( gtk_tree_model_get_iter( 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, ui::TreePath path, GtkSelectionData *selection_data ){
490         if ( gtk_tree_set_row_drag_data( selection_data, 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, ui::TreePath dest, GtkSelectionData *selection_data ){
508         auto 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, ui::TreePath 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 == 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                                         auto tmp = gtk_tree_path_copy( dest_path );
544                                         gtk_tree_path_up( tmp );
545
546                                         GtkTreeIter iter;
547                                         retval = gtk_tree_model_get_iter( 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         auto tree_path = graph_tree_model_get_path( 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( 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         auto tree_path = graph_tree_model_get_path( model, &iter );
695
696         gtk_tree_model_row_deleted( 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(), ConstReferenceCaller<scene::Instance, void(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(), ConstReferenceCaller<scene::Instance, void(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<void()>() );
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, void(), &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 static GtkTreeModelFlags graph_tree_model_get_flags( ui::TreeModel tree_model ){
818         return GTK_TREE_MODEL_ITERS_PERSIST;
819 }
820
821 static gint graph_tree_model_get_n_columns( ui::TreeModel tree_model ){
822         ASSERT_MESSAGE( tree_model, "RUNTIME ERROR" );
823         //GraphTreeModel* graph_tree_model = (GraphTreeModel*) tree_model;
824
825         return 2;
826 }
827
828 static const gint c_stamp = 0xabcdef;
829
830 inline GraphTreeNode::iterator graph_iterator_read_tree_iter( GtkTreeIter* iter ){
831         ASSERT_MESSAGE( iter != 0,  "tree model error" );
832         ASSERT_MESSAGE( iter->user_data != 0,  "tree model error" );
833         ASSERT_MESSAGE( iter->stamp == c_stamp,  "tree model error" );
834         return *reinterpret_cast<GraphTreeNode::iterator*>( &iter->user_data );
835 }
836
837 inline void graph_iterator_write_tree_iter( GraphTreeNode::iterator i, GtkTreeIter* iter ){
838         ASSERT_MESSAGE( iter != 0,  "tree model error" );
839         iter->stamp = c_stamp;
840         *reinterpret_cast<GraphTreeNode::iterator*>( &iter->user_data ) = i;
841         ASSERT_MESSAGE( iter->user_data != 0,  "tree model error" );
842 }
843
844 static GType graph_tree_model_get_column_type( ui::TreeModel tree_model, gint index ){
845         ASSERT_MESSAGE( tree_model, "RUNTIME ERROR" );
846         //GraphTreeModel *graph_tree_model = (GraphTreeModel *) tree_model;
847
848         return G_TYPE_POINTER;
849 }
850
851 static gboolean graph_tree_model_get_iter( GraphTreeModel* tree_model, GtkTreeIter* iter, ui::TreePath path ){
852         ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
853         gint* indices = gtk_tree_path_get_indices( path );
854         gint depth = gtk_tree_path_get_depth( path );
855
856         g_return_val_if_fail( depth > 0, FALSE );
857
858         GraphTreeNode *graph = tree_model->m_graph;
859
860         if ( graph->empty() ) {
861                 return FALSE;
862         }
863
864         GtkTreeIter tmp;
865         GtkTreeIter* parent = 0;
866
867         for ( gint i = 0; i < depth; i++ )
868         {
869                 if ( !gtk_tree_model_iter_nth_child( GTK_TREE_MODEL(tree_model), iter, parent, indices[i] ) ) {
870                         return FALSE;
871                 }
872                 tmp = *iter;
873                 parent = &tmp;
874         }
875
876         return TRUE;
877 }
878
879 static ui::TreePath graph_tree_model_get_path( GraphTreeModel *tree_model, GtkTreeIter* iter ){
880         ASSERT_MESSAGE( tree_model, "RUNTIME ERROR" );
881         GraphTreeNode* graph = tree_model->m_graph;
882
883     auto path = ui::TreePath(ui::New);
884
885         for ( GraphTreeNode* node = ( *graph_iterator_read_tree_iter( iter ) ).second; node != graph; node = node->m_parent )
886         {
887                 std::size_t index = 0;
888                 for ( GraphTreeNode::iterator i = node->m_parent->begin(); i != node->m_parent->end(); ++i, ++index )
889                 {
890                         if ( ( *i ).second == node ) {
891                                 gtk_tree_path_prepend_index( path, gint( index ) );
892                                 break;
893                         }
894                 }
895                 ASSERT_MESSAGE( index != node->m_parent->size(), "error resolving tree path" );
896         }
897
898         return path;
899 }
900
901
902 static void graph_tree_model_get_value( ui::TreeModel tree_model, GtkTreeIter  *iter, gint column, GValue *value ){
903         ASSERT_MESSAGE( tree_model, "RUNTIME ERROR" );
904         ASSERT_MESSAGE( column == 0 || column == 1, "tree model error" );
905
906         GraphTreeNode::iterator i = graph_iterator_read_tree_iter( iter );
907
908         g_value_init( value, G_TYPE_POINTER );
909
910         if ( column == 0 ) {
911                 g_value_set_pointer( value, reinterpret_cast<gpointer>( ( *i ).first.second ) );
912         }
913         else
914         {
915                 g_value_set_pointer( value, reinterpret_cast<gpointer>( &( *i ).second->m_instance.get() ) );
916         }
917 }
918
919 static gboolean graph_tree_model_iter_next( ui::TreeModel  tree_model, GtkTreeIter   *iter ){
920         ASSERT_MESSAGE( tree_model, "RUNTIME ERROR" );
921         GraphTreeNode::iterator i = graph_iterator_read_tree_iter( iter );
922         GraphTreeNode& parent = *( *i ).second->m_parent;
923
924         ASSERT_MESSAGE( i != parent.end(), "RUNTIME ERROR" );
925
926         if ( ++i == parent.end() ) {
927                 return FALSE;
928         }
929
930         graph_iterator_write_tree_iter( i, iter );
931
932         return TRUE;
933 }
934
935 static gboolean graph_tree_model_iter_children( GraphTreeModel *tree_model, GtkTreeIter  *iter, GtkTreeIter  *parent ){
936         ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
937         GraphTreeNode& node = ( parent == 0 ) ? *tree_model->m_graph : *( *graph_iterator_read_tree_iter( parent ) ).second;
938         if ( !node.empty() ) {
939                 graph_iterator_write_tree_iter( node.begin(), iter );
940                 return TRUE;
941         }
942
943         return FALSE;
944 }
945
946 static gboolean graph_tree_model_iter_has_child( ui::TreeModel tree_model, GtkTreeIter  *iter ){
947         ASSERT_MESSAGE( tree_model, "RUNTIME ERROR" );
948         GraphTreeNode& node = *( *graph_iterator_read_tree_iter( iter ) ).second;
949         return !node.empty();
950 }
951
952 static gint graph_tree_model_iter_n_children( GraphTreeModel *tree_model, GtkTreeIter *parent ){
953         ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
954         GraphTreeNode& node = ( parent == 0 ) ? *tree_model->m_graph : *( *graph_iterator_read_tree_iter( parent ) ).second;
955         return static_cast<gint>( node.size() );
956 }
957
958 static gboolean graph_tree_model_iter_nth_child( GraphTreeModel *tree_model, GtkTreeIter  *iter, GtkTreeIter  *parent, gint n ){
959         ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
960         GraphTreeNode& node = ( parent == 0 ) ? *tree_model->m_graph : *( *graph_iterator_read_tree_iter( parent ) ).second;
961         if ( static_cast<std::size_t>( n ) < node.size() ) {
962                 GraphTreeNode::iterator i = node.begin();
963                 std::advance( i, n );
964                 graph_iterator_write_tree_iter( i, iter );
965                 return TRUE;
966         }
967
968         return FALSE;
969 }
970
971 static gboolean graph_tree_model_iter_parent( GraphTreeModel *tree_model, GtkTreeIter  *iter, GtkTreeIter  *child ){
972         ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
973         GraphTreeNode& node = *( *graph_iterator_read_tree_iter( child ) ).second;
974         if ( node.m_parent != tree_model->m_graph ) {
975                 GraphTreeNode& parentParent = *node.m_parent->m_parent;
976                 for ( GraphTreeNode::iterator i = parentParent.begin(); i != parentParent.end(); ++i )
977                 {
978                         if ( ( *i ).second == node.m_parent ) {
979                                 graph_iterator_write_tree_iter( i, iter );
980                                 return TRUE;
981                         }
982                 }
983         }
984         return FALSE;
985 }
986
987 static GObjectClass *g_parent_class = 0;
988
989 namespace
990 {
991 scene::Node* g_null_node = 0;
992 }
993
994 class NullInstance : public scene::Instance
995 {
996 public:
997 NullInstance() : scene::Instance( scene::Path( makeReference( *g_null_node ) ), 0, 0, Static<InstanceTypeCastTable>::instance() ){
998 }
999 };
1000
1001 namespace
1002 {
1003 NullInstance g_null_instance;
1004 }
1005
1006 static void graph_tree_model_init( GraphTreeModel *graph_tree_model ){
1007         graph_tree_model->m_graph = new GraphTreeNode( g_null_instance );
1008 }
1009
1010 static void graph_tree_model_finalize( GObject* object ){
1011         auto graph_tree_model = reinterpret_cast<GraphTreeModel*>(object);
1012
1013         delete graph_tree_model->m_graph;
1014
1015         /* must chain up */
1016         ( *g_parent_class->finalize )( object );
1017 }
1018
1019 static void graph_tree_model_class_init( GraphTreeModelClass *class_ ){
1020         GObjectClass *object_class;
1021
1022         g_parent_class = (GObjectClass*)g_type_class_peek_parent( class_ );
1023         object_class = (GObjectClass *) class_;
1024
1025         object_class->finalize = graph_tree_model_finalize;
1026 }
1027
1028 static void graph_tree_model_tree_model_init( GtkTreeModelIface *iface ){
1029         iface->get_flags = reinterpret_cast<GtkTreeModelFlags (*)(GtkTreeModel *)>(graph_tree_model_get_flags);
1030         iface->get_n_columns = reinterpret_cast<gint (*)(GtkTreeModel *)>(graph_tree_model_get_n_columns);
1031         iface->get_column_type = reinterpret_cast<GType (*)(GtkTreeModel *, gint)>(graph_tree_model_get_column_type);
1032         iface->get_iter = reinterpret_cast<gboolean (*)(GtkTreeModel *, GtkTreeIter *, GtkTreePath *)>(graph_tree_model_get_iter);
1033         iface->get_path = reinterpret_cast<GtkTreePath *(*)(GtkTreeModel *, GtkTreeIter *)>(graph_tree_model_get_path);
1034         iface->get_value = reinterpret_cast<void (*)(GtkTreeModel *, GtkTreeIter *, gint, GValue *)>(graph_tree_model_get_value);
1035         iface->iter_next = reinterpret_cast<gboolean (*)(GtkTreeModel *, GtkTreeIter *)>(graph_tree_model_iter_next);
1036         iface->iter_children = reinterpret_cast<gboolean (*)(GtkTreeModel *, GtkTreeIter *, GtkTreeIter *)>(graph_tree_model_iter_children);
1037         iface->iter_has_child = reinterpret_cast<gboolean (*)(GtkTreeModel *, GtkTreeIter *)>(graph_tree_model_iter_has_child);
1038         iface->iter_n_children = reinterpret_cast<gint (*)(GtkTreeModel *, GtkTreeIter *)>(graph_tree_model_iter_n_children);
1039         iface->iter_nth_child = reinterpret_cast<gboolean (*)(GtkTreeModel *, GtkTreeIter *, GtkTreeIter *, gint)>(graph_tree_model_iter_nth_child);
1040         iface->iter_parent = reinterpret_cast<gboolean (*)(GtkTreeModel *, GtkTreeIter *, GtkTreeIter *)>(graph_tree_model_iter_parent);
1041 }
1042
1043 GType graph_tree_model_get_type( void ){
1044         static GType graph_tree_model_type = 0;
1045
1046         if ( !graph_tree_model_type ) {
1047                 static const GTypeInfo graph_tree_model_info =
1048                 {
1049                         sizeof( GraphTreeModelClass ),
1050                         0, /* base_init */
1051                         0, /* base_finalize */
1052                         (GClassInitFunc) graph_tree_model_class_init,
1053                         0, /* class_finalize */
1054                         0, /* class_data */
1055                         sizeof( GraphTreeModel ),
1056                         0,        /* n_preallocs */
1057                         (GInstanceInitFunc) graph_tree_model_init,
1058                         0
1059                 };
1060
1061                 static const GInterfaceInfo tree_model_info =
1062                 {
1063                         (GInterfaceInitFunc) graph_tree_model_tree_model_init,
1064                         0,
1065                         0
1066                 };
1067
1068                 graph_tree_model_type = g_type_register_static( G_TYPE_OBJECT, "GraphTreeModel",
1069                                                                                                                 &graph_tree_model_info, (GTypeFlags)0 );
1070
1071                 g_type_add_interface_static( graph_tree_model_type,
1072                                                                          GTK_TYPE_TREE_MODEL,
1073                                                                          &tree_model_info );
1074         }
1075
1076         return graph_tree_model_type;
1077 }
1078
1079 GraphTreeModel* graph_tree_model_new(){
1080         auto graph_tree_model = reinterpret_cast<GraphTreeModel*>(g_object_new( graph_tree_model_get_type(), 0 ));
1081
1082         return graph_tree_model;
1083 }
1084
1085 void graph_tree_model_delete( GraphTreeModel* model ){
1086         g_object_unref( G_OBJECT( model ) );
1087 }
1088
1089 void graph_tree_model_row_changed( GraphTreeModel* model, GraphTreeNode::iterator i ){
1090         GtkTreeIter iter;
1091         graph_iterator_write_tree_iter( i, &iter );
1092
1093     auto tree_path = graph_tree_model_get_path(model, &iter );
1094
1095         gtk_tree_model_row_changed( GTK_TREE_MODEL( model ), tree_path, &iter );
1096
1097         gtk_tree_path_free( tree_path );
1098 }
1099
1100 void graph_tree_model_row_inserted( GraphTreeModel* model, GraphTreeNode::iterator i ){
1101         GtkTreeIter iter;
1102         graph_iterator_write_tree_iter( i, &iter );
1103
1104     auto tree_path = graph_tree_model_get_path(model, &iter );
1105
1106         gtk_tree_model_row_inserted( GTK_TREE_MODEL( model ), tree_path, &iter );
1107
1108         gtk_tree_path_free( tree_path );
1109 }
1110
1111 void graph_tree_model_row_deleted( GraphTreeModel* model, GraphTreeNode::iterator i ){
1112         GtkTreeIter iter;
1113         graph_iterator_write_tree_iter( i, &iter );
1114
1115     auto tree_path = graph_tree_model_get_path(model, &iter );
1116
1117         gtk_tree_model_row_deleted( GTK_TREE_MODEL( model ), tree_path );
1118
1119         gtk_tree_path_free( tree_path );
1120 }
1121
1122 void graph_tree_model_row_inserted( GraphTreeModel& model, GraphTreeNode::iterator i ){
1123         graph_tree_model_row_inserted( &model, i );
1124 }
1125
1126 void graph_tree_model_row_deleted( GraphTreeModel& model, GraphTreeNode::iterator i ){
1127         graph_tree_model_row_deleted( &model, i );
1128 }
1129
1130 const char* node_get_name( scene::Node& node );
1131
1132 const char* node_get_name_safe( scene::Node& node ){
1133         volatile intptr_t n = (intptr_t)&node;  // see the comment on line 650
1134         if ( n == 0 ) {
1135                 return "";
1136         }
1137         return node_get_name( node );
1138 }
1139
1140 GraphTreeNode* graph_tree_model_find_parent( GraphTreeModel* model, const scene::Path& path ){
1141         GraphTreeNode* parent = model->m_graph;
1142         for ( scene::Path::const_iterator i = path.begin(); i != path.end() - 1; ++i )
1143         {
1144                 GraphTreeNode::iterator child = parent->find( GraphTreeNode::key_type( node_get_name_safe( ( *i ).get() ), ( *i ).get_pointer() ) );
1145                 ASSERT_MESSAGE( child != parent->end(), "ERROR" );
1146                 parent = ( *child ).second;
1147         }
1148         return parent;
1149 }
1150
1151 void node_attach_name_changed_callback( scene::Node& node, const NameCallback& callback ){
1152         volatile intptr_t n = (intptr_t)&node;  // see the comment on line 650
1153         if ( n != 0 ) {
1154                 Nameable* nameable = Node_getNameable( node );
1155                 if ( nameable != 0 ) {
1156                         nameable->attach( callback );
1157                 }
1158         }
1159 }
1160 void node_detach_name_changed_callback( scene::Node& node, const NameCallback& callback ){
1161         volatile intptr_t n = (intptr_t)&node;  // see the comment on line 650
1162         if ( n != 0 ) {
1163                 Nameable* nameable = Node_getNameable( node );
1164                 if ( nameable != 0 ) {
1165                         nameable->detach( callback );
1166                 }
1167         }
1168 }
1169
1170 GraphTreeModel* scene_graph_get_tree_model(); // temp hack
1171
1172 void graph_tree_node_foreach_pre( GraphTreeNode::iterator root, const Callback<void(GraphTreeNode::iterator)>& callback ){
1173         callback( root );
1174         for ( GraphTreeNode::iterator i = ( *root ).second->begin(); i != ( *root ).second->end(); ++i )
1175         {
1176                 graph_tree_node_foreach_pre( i, callback );
1177         }
1178 }
1179
1180 void graph_tree_node_foreach_post( GraphTreeNode::iterator root, const Callback<void(GraphTreeNode::iterator)>& callback ){
1181         for ( GraphTreeNode::iterator i = ( *root ).second->begin(); i != ( *root ).second->end(); ++i )
1182         {
1183                 graph_tree_node_foreach_post( i, callback );
1184         }
1185         callback( root );
1186 }
1187
1188 void graph_tree_model_row_changed( GraphTreeNode& node ){
1189         GraphTreeModel* model = scene_graph_get_tree_model();
1190         const scene::Instance& instance = node.m_instance.get();
1191
1192         GraphTreeNode::iterator i = node.m_parent->find( GraphTreeNode::key_type( node_get_name_safe( instance.path().top().get() ), instance.path().top().get_pointer() ) );
1193
1194         graph_tree_model_row_changed( model, i );
1195 }
1196
1197 void graph_tree_model_set_name( const scene::Instance& instance, const char* name ){
1198         GraphTreeModel* model = scene_graph_get_tree_model();
1199         GraphTreeNode* parent = graph_tree_model_find_parent( model, instance.path() );
1200
1201         GraphTreeNode::iterator oldNode = parent->find( GraphTreeNode::key_type( node_get_name_safe( instance.path().top().get() ), instance.path().top().get_pointer() ) );
1202         graph_tree_node_foreach_post( oldNode, ReferenceCaller<GraphTreeModel, void(GraphTreeNode::iterator), graph_tree_model_row_deleted>( *model ) );
1203         GraphTreeNode* node( ( *oldNode ).second );
1204         parent->erase( oldNode );
1205
1206         GraphTreeNode::iterator newNode = parent->insert( GraphTreeNode::value_type( GraphTreeNode::key_type( name, &instance.path().top().get() ), node ) );
1207         graph_tree_node_foreach_pre( newNode, ReferenceCaller<GraphTreeModel, void(GraphTreeNode::iterator), graph_tree_model_row_inserted>( *model ) );
1208 }
1209
1210 void graph_tree_model_insert( GraphTreeModel* model, const scene::Instance& instance ){
1211         GraphTreeNode* parent = graph_tree_model_find_parent( model, instance.path() );
1212
1213         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 ) ) ) );
1214
1215         graph_tree_model_row_inserted( model, i );
1216
1217         node_attach_name_changed_callback( instance.path().top(), ConstReferenceCaller<scene::Instance, void(const char*), graph_tree_model_set_name>( instance ) );
1218 }
1219
1220 void graph_tree_model_erase( GraphTreeModel* model, const scene::Instance& instance ){
1221         node_detach_name_changed_callback( instance.path().top(), ConstReferenceCaller<scene::Instance, void(const char*), graph_tree_model_set_name>( instance ) );
1222
1223         GraphTreeNode* parent = graph_tree_model_find_parent( model, instance.path() );
1224
1225         GraphTreeNode::iterator i = parent->find( GraphTreeNode::key_type( node_get_name_safe( instance.path().top().get() ), instance.path().top().get_pointer() ) );
1226
1227         graph_tree_model_row_deleted( model, i );
1228
1229         GraphTreeNode* node( ( *i ).second );
1230         parent->erase( i );
1231         delete node;
1232 }
1233
1234
1235
1236 #endif
1237
1238
1239
1240
1241 #if 0
1242 class TestGraphTreeModel
1243 {
1244 public:
1245 TestGraphTreeModel(){
1246         gtk_init( 0, 0 );
1247
1248         graph_type graph;
1249
1250         scene::Node* root = *(scene::Node*)0xa0000000;
1251         scene::Node* node1 = (scene::Node*)0xa0000001;
1252         scene::Node* node2 = (scene::Node*)0xa0000002;
1253         scene::Node* node3 = (scene::Node*)0xa0000003;
1254         scene::Node* node4 = (scene::Node*)0xa0000004;
1255         scene::Instance* instance = (scene::Instance*)0xaaaaaaaa;
1256
1257         scene::Path rootpath( root );
1258
1259         graph.insert( graph_type::value_type( rootpath, instance ) );
1260
1261         rootpath.push( node1 );
1262         graph.insert( graph_type::value_type( rootpath, instance ) );
1263         rootpath.pop();
1264
1265         rootpath.push( node2 );
1266         graph.insert( graph_type::value_type( rootpath, instance ) );
1267         rootpath.push( node3 );
1268         graph.insert( graph_type::value_type( rootpath, instance ) );
1269         rootpath.pop();
1270         rootpath.push( node4 );
1271         graph.insert( graph_type::value_type( rootpath, instance ) );
1272         rootpath.pop();
1273         rootpath.pop();
1274
1275         auto model = graph_tree_model_new( &graph );
1276
1277         {
1278                 gint n_columns = gtk_tree_model_get_n_columns( model );
1279                 ASSERT_MESSAGE( n_columns == 2, "test failed!" );
1280         }
1281
1282         {
1283                 GType type = gtk_tree_model_get_column_type( model, 0 );
1284                 ASSERT_MESSAGE( type == G_TYPE_POINTER, "test failed!" );
1285         }
1286
1287         {
1288                 GType type = gtk_tree_model_get_column_type( model, 1 );
1289                 ASSERT_MESSAGE( type == G_TYPE_POINTER, "test failed!" );
1290         }
1291
1292
1293         {
1294                 GtkTreeIter iter;
1295                 gtk_tree_model_get_iter_first( model, &iter );
1296
1297                 graph_type::iterator i = graph_iterator_read_tree_iter( &iter );
1298                 ASSERT_MESSAGE( ( *i ).first.get().size() == 2 && ( *i ).first.get().top() == node1, "test failed!" );
1299         }
1300
1301         {
1302                 GtkTreeIter iter;
1303                 gtk_tree_model_get_iter_first( model, &iter );
1304
1305                 ASSERT_MESSAGE( gtk_tree_model_iter_has_child( model, &iter ) == FALSE, "test failed!" );
1306
1307                 ASSERT_MESSAGE( gtk_tree_model_iter_n_children( model, &iter ) == 0, "test failed!" );
1308
1309                 gtk_tree_model_iter_next( model, &iter );
1310
1311                 ASSERT_MESSAGE( gtk_tree_model_iter_has_child( model, &iter ) != FALSE, "test failed!" );
1312
1313                 ASSERT_MESSAGE( gtk_tree_model_iter_n_children( model, &iter ) == 2, "test failed!" );
1314
1315                 {
1316                         GtkTreeIter child;
1317                         gtk_tree_model_iter_nth_child( model, &child, &iter, 0 );
1318
1319                         scene::Node* test;
1320                         gtk_tree_model_get_value( model, &child, 0, (GValue*)&test );
1321                         ASSERT_MESSAGE( test == node3, "test failed!" );
1322
1323                         {
1324                                 GtkTreeIter parent;
1325                                 gtk_tree_model_iter_parent( model, &parent, &child );
1326
1327                                 scene::Node* test;
1328                                 gtk_tree_model_get_value( model, &parent, 0, (GValue*)&test );
1329                                 ASSERT_MESSAGE( test == node2, "test failed!" );
1330                         }
1331                 }
1332
1333                 {
1334                         GtkTreeIter child;
1335                         gtk_tree_model_iter_nth_child( model, &child, &iter, 1 );
1336
1337                         scene::Node* test;
1338                         gtk_tree_model_get_value( model, &child, 0, (GValue*)&test );
1339                         ASSERT_MESSAGE( test == node4, "test failed!" );
1340                 }
1341         }
1342
1343         {
1344                 GtkTreeIter iter;
1345                 std::size_t count = 0;
1346                 for ( gboolean good = gtk_tree_model_get_iter_first( model, &iter ); good; good = gtk_tree_model_iter_next( model, &iter ) )
1347                 {
1348                         scene::Node* test;
1349                         gtk_tree_model_get_value( model, &iter, 0, (GValue*)&test );
1350
1351                         ASSERT_MESSAGE( ( count == 0 && test == node1 ) || ( count == 1 && test == node2 ), "test failed!" );
1352                         ++count;
1353                 }
1354
1355                 ASSERT_MESSAGE( count == 2, "test failed!" );
1356
1357         }
1358
1359         {
1360                 GtkTreeIter iter;
1361                 gtk_tree_model_get_iter_first( model, &iter );
1362
1363                 scene::Node* test;
1364                 gtk_tree_model_get_value( model, &iter, 0, (GValue*)&test );
1365                 ASSERT_MESSAGE( test == node1, "test failed!" );
1366         }
1367
1368         {
1369                 GtkTreeIter iter;
1370                 auto path = ui::TreePath( "0" );
1371                 gtk_tree_model_get_iter( model, &iter, path );
1372                 gtk_tree_path_free( path );
1373
1374                 graph_type::iterator i = graph_iterator_read_tree_iter( &iter );
1375                 ASSERT_MESSAGE( ( *i ).first.get().size() == 2 && ( *i ).first.get().top() == node1, "test failed!" );
1376         }
1377
1378         {
1379                 GtkTreeIter iter;
1380                 auto path = ui::TreePath( "1" );
1381                 gtk_tree_model_get_iter( model, &iter, path );
1382                 gtk_tree_path_free( path );
1383
1384                 graph_type::iterator i = graph_iterator_read_tree_iter( &iter );
1385                 ASSERT_MESSAGE( ( *i ).first.get().size() == 2 && ( *i ).first.get().top() == node2, "test failed!" );
1386         }
1387
1388         {
1389                 GtkTreeIter iter;
1390                 graph_type::iterator i = graph.begin();
1391                 ++i;
1392                 graph_iterator_write_tree_iter( i, &iter );
1393
1394                 auto path = gtk_tree_model_get_path( model, &iter );
1395
1396                 gint depth = gtk_tree_path_get_depth( path );
1397                 gint* indices = gtk_tree_path_get_indices( path );
1398
1399                 ASSERT_MESSAGE( depth == 1 && indices[0] == 0, "test failed!" );
1400
1401                 gtk_tree_path_free( path );
1402         }
1403
1404         {
1405                 GtkTreeIter iter;
1406                 graph_type::iterator i = graph.begin();
1407                 ++i;
1408                 ++i;
1409                 graph_iterator_write_tree_iter( i, &iter );
1410
1411                 auto path = gtk_tree_model_get_path( model, &iter );
1412
1413                 gint depth = gtk_tree_path_get_depth( path );
1414                 gint* indices = gtk_tree_path_get_indices( path );
1415
1416                 ASSERT_MESSAGE( depth == 1 && indices[0] == 1, "test failed!" );
1417
1418                 gtk_tree_path_free( path );
1419         }
1420 }
1421 };
1422
1423
1424 TestGraphTreeModel g_TestGraphTreeModel;
1425
1426 #endif