2 Copyright (C) 2001-2006, William Joseph.
5 This file is part of GtkRadiant.
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.
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.
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
22 #include "treemodel.h"
24 #include "debugging/debugging.h"
28 #include <uilib/uilib.h>
30 #include "iscenegraph.h"
33 #include "generic/callback.h"
35 #include "string/string.h"
36 #include "generic/reference.h"
38 inline Nameable* Node_getNameable( scene::Node& node ){
39 return NodeTypeCast<Nameable>::cast( node );
44 #include "gtkutil/gtktreestore.h"
46 template<typename value_type>
47 inline void gtk_tree_model_get_pointer( GtkTreeModel* model, GtkTreeIter* iter, gint column, value_type** pointer ){
48 GValue value = GValue_default();
49 gtk_tree_model_get_value( model, iter, column, &value );
50 *pointer = (value_type*)g_value_get_pointer( &value );
54 typedef GtkTreeStore GraphTreeModel;
56 GtkTreeStore* graph_tree_model_new( graph_type* graph ){
57 return gtk_tree_store_new( 2, G_TYPE_POINTER, G_TYPE_POINTER );
60 void graph_tree_model_delete( GraphTreeModel* model ){
61 g_object_unref( G_OBJECT( model ) );
65 bool graph_tree_model_subtree_find_node( GraphTreeModel* model, GtkTreeIter* parent, const scene::Node& node, GtkTreeIter* iter ){
66 for ( gboolean success = gtk_tree_model_iter_children( GTK_TREE_MODEL( model ), iter, parent );
68 success = gtk_tree_model_iter_next( GTK_TREE_MODEL( model ), iter ) )
71 gtk_tree_model_get_pointer( GTK_TREE_MODEL( model ), iter, 0, ¤t );
72 if ( current == node ) {
79 typedef GtkTreeIter DoubleGtkTreeIter[2];
81 bool graph_tree_model_find_top( GraphTreeModel* model, const scene::Path& path, GtkTreeIter& iter ){
83 GtkTreeIter* parent_pointer = NULL;
85 for ( scene::Path::const_iterator i = path.begin(); i != path.end(); ++i )
87 if ( !graph_tree_model_subtree_find_node( model, parent_pointer, *i, &iter ) ) {
91 parent_pointer = &parent;
96 bool graph_tree_model_find_parent( GraphTreeModel* model, const scene::Path& path, GtkTreeIter& iter ){
98 GtkTreeIter* parent_pointer = NULL;
99 ASSERT_MESSAGE( path.size() > 1, "path too short" );
100 for ( scene::Path::const_iterator i = path.begin(); i != path.end() - 1; ++i )
103 if ( !graph_tree_model_subtree_find_node( model, parent_pointer, *i, &child ) ) {
107 parent_pointer = &iter;
112 void node_attach_name_changed_callback( scene::Node& node, const Callback& callback ){
114 Nameable* nameable = Node_getNameable( node );
115 if ( nameable != 0 ) {
116 nameable->attach( callback );
120 void node_detach_name_changed_callback( scene::Node& node, const Callback& callback ){
122 Nameable* nameable = Node_getNameable( node );
123 if ( nameable != 0 ) {
124 nameable->detach( callback );
129 GraphTreeModel* scene_graph_get_tree_model(); // temp hack
131 void graph_tree_model_row_changed( const scene::Instance& instance ){
132 GraphTreeModel* model = scene_graph_get_tree_model();
135 ASSERT_MESSAGE( graph_tree_model_find_top( model, instance.path(), child ), "RUNTIME ERROR" );
137 gtk_tree_store_set( GTK_TREE_STORE( model ), &child, 0, instance.path().top(), -1 );
140 void graph_tree_model_row_inserted( GraphTreeModel* model, const scene::Instance& instance ){
142 GtkTreeIter* parent_pointer = NULL;
143 if ( instance.path().size() != 1 ) {
144 ASSERT_MESSAGE( graph_tree_model_find_parent( model, instance.path(), parent ), "RUNTIME ERROR" );
145 parent_pointer = &parent;
148 gpointer node = instance.path().top();
149 gconstpointer selectable = Instance_getSelectable( instance );
152 gtk_tree_store_append( GTK_TREE_STORE( model ), &child, parent_pointer );
153 gtk_tree_store_set( GTK_TREE_STORE( model ), &child, 0, node, 1, selectable, -1 );
155 node_attach_name_changed_callback( instance.path().top(), ConstReferenceCaller<scene::Instance, graph_tree_model_row_changed>( instance ) );
158 void graph_tree_model_row_deleted( GraphTreeModel* model, const scene::Instance& instance ){
160 ASSERT_MESSAGE( graph_tree_model_find_top( model, instance.path(), child ), "RUNTIME ERROR" );
162 node_detach_name_changed_callback( instance.path().top(), ConstReferenceCaller<scene::Instance, graph_tree_model_row_changed>( instance ) );
164 gtk_tree_store_remove( GTK_TREE_STORE( model ), &child );
169 const char* node_get_name( scene::Node& node );
171 typedef scene::Node* NodePointer;
176 bool operator()( const NodePointer& self, const NodePointer& other ) const {
183 int result = string_compare( node_get_name( self ), node_get_name( other ) );
194 bool operator()( const PathConstReference& self, const PathConstReference& other ) const {
195 return std::lexicographical_compare( self.get().begin(), self.get().end(), other.get().begin(), other.get().end(), NodeNameLess() );
199 typedef std::map<PathConstReference, scene::Instance*, PathNameLess> graph_type;
201 struct GraphTreeModel
208 struct GraphTreeModelClass
210 GObjectClass parent_class;
213 #define GRAPH_TREE_MODEL( p ) ( reinterpret_cast<GraphTreeModel*>( p ) )
215 static GtkTreeModelFlags graph_tree_model_get_flags( GtkTreeModel* tree_model ){
216 return GTK_TREE_MODEL_ITERS_PERSIST;
219 static gint graph_tree_model_get_n_columns( GtkTreeModel* tree_model ){
220 ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
221 GraphTreeModel* graph_tree_model = (GraphTreeModel*) tree_model;
226 static const gint c_stamp = 0xabcdef;
228 inline graph_type::iterator graph_iterator_read_tree_iter( GtkTreeIter* iter ){
229 ASSERT_MESSAGE( iter != 0, "tree model error" );
230 ASSERT_MESSAGE( iter->user_data != 0, "tree model error" );
231 ASSERT_MESSAGE( iter->stamp == c_stamp, "tree model error" );
232 return *reinterpret_cast<graph_type::iterator*>( &iter->user_data );
235 inline void graph_iterator_write_tree_iter( graph_type::iterator i, GtkTreeIter* iter ){
236 ASSERT_MESSAGE( iter != 0, "tree model error" );
237 iter->stamp = c_stamp;
238 *reinterpret_cast<graph_type::iterator*>( &iter->user_data ) = i;
239 ASSERT_MESSAGE( iter->user_data != 0, "tree model error" );
242 static GType graph_tree_model_get_column_type( GtkTreeModel *tree_model, gint index ){
243 ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
244 GraphTreeModel *graph_tree_model = (GraphTreeModel *) tree_model;
246 return G_TYPE_POINTER;
249 static gboolean graph_tree_model_get_iter( GtkTreeModel* tree_model, GtkTreeIter* iter, GtkTreePath* path ){
250 ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
251 gint* indices = gtk_tree_path_get_indices( path );
252 gint depth = gtk_tree_path_get_depth( path );
254 g_return_val_if_fail( depth > 0, FALSE );
256 graph_type& graph = *GRAPH_TREE_MODEL( tree_model )->graph;
258 if ( graph.empty() ) {
263 GtkTreeIter* parent = 0;
265 for ( gint i = 0; i < depth; i++ )
267 if ( !gtk_tree_model_iter_nth_child( tree_model, iter, parent, indices[i] ) ) {
277 static GtkTreePath* graph_tree_model_get_path( GtkTreeModel* tree_model, GtkTreeIter* iter ){
278 ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
279 graph_type& graph = *GRAPH_TREE_MODEL( tree_model )->graph;
280 graph_type::iterator i = graph_iterator_read_tree_iter( iter );
282 GtkTreePath* path = ui::TreePath();
284 for ( std::size_t depth = ( *i ).first.get().size(); depth != 0; --depth )
286 std::size_t index = 0;
288 while ( i != graph.begin() && ( *i ).first.get().size() >= depth )
291 if ( ( *i ).first.get().size() == depth ) {
296 gtk_tree_path_prepend_index( path, index );
303 static void graph_tree_model_get_value( GtkTreeModel *tree_model, GtkTreeIter *iter, gint column, GValue *value ){
304 ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
305 ASSERT_MESSAGE( column == 0 || column == 1, "tree model error" );
307 graph_type::iterator i = graph_iterator_read_tree_iter( iter );
309 g_value_init( value, G_TYPE_POINTER );
312 g_value_set_pointer( value, reinterpret_cast<gpointer>( ( *i ).first.get().top() ) );
315 g_value_set_pointer( value, reinterpret_cast<gpointer>( Instance_getSelectable( *( *i ).second ) ) );
319 static gboolean graph_tree_model_iter_next( GtkTreeModel *tree_model, GtkTreeIter *iter ){
320 ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
321 graph_type& graph = *GRAPH_TREE_MODEL( tree_model )->graph;
322 graph_type::iterator i = graph_iterator_read_tree_iter( iter );
323 std::size_t depth = ( *i ).first.get().size();
327 while ( i != graph.end() && ( *i ).first.get().size() > depth )
332 if ( i == graph.end() || ( *i ).first.get().size() != depth ) {
336 graph_iterator_write_tree_iter( i, iter );
341 static gboolean graph_tree_model_iter_children( GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreeIter *parent ){
342 ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
343 graph_type& graph = *GRAPH_TREE_MODEL( tree_model )->graph;
344 graph_type::iterator i = ( parent == 0 ) ? graph.begin() : graph_iterator_read_tree_iter( parent );
345 std::size_t depth = ( parent == 0 ) ? 1 : ( *i ).first.get().size() + 1;
351 if ( i != graph.end() && ( *i ).first.get().size() == depth ) {
352 graph_iterator_write_tree_iter( i, iter );
359 static gboolean graph_tree_model_iter_has_child( GtkTreeModel *tree_model, GtkTreeIter *iter ){
360 ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
361 graph_type& graph = *GRAPH_TREE_MODEL( tree_model )->graph;
362 graph_type::iterator i = graph_iterator_read_tree_iter( iter );
363 std::size_t depth = ( *i ).first.get().size() + 1;
365 return ++i != graph.end() && ( *i ).first.get().size() == depth;
368 static gint graph_tree_model_iter_n_children( GtkTreeModel *tree_model, GtkTreeIter *parent ){
369 ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
370 graph_type& graph = *GRAPH_TREE_MODEL( tree_model )->graph;
371 graph_type::iterator i = ( parent == 0 ) ? graph.begin() : graph_iterator_read_tree_iter( parent );
372 std::size_t depth = ( parent == 0 ) ? 1 : ( *i ).first.get().size() + 1;
379 while ( i != graph.end() && ( *i ).first.get().size() >= depth )
388 static gboolean graph_tree_model_iter_nth_child( GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreeIter *parent, gint n ){
389 ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
390 graph_type& graph = *GRAPH_TREE_MODEL( tree_model )->graph;
391 graph_type::iterator i = ( parent == 0 ) ? graph.begin() : graph_iterator_read_tree_iter( parent );
392 std::size_t depth = ( parent == 0 ) ? 1 : ( *i ).first.get().size() + 1;
398 while ( i != graph.end() && ( *i ).first.get().size() >= depth )
400 if ( ( *i ).first.get().size() == depth && n-- == 0 ) {
401 graph_iterator_write_tree_iter( i, iter );
410 static gboolean graph_tree_model_iter_parent( GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreeIter *child ){
411 ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
412 graph_type& graph = *GRAPH_TREE_MODEL( tree_model )->graph;
413 graph_type::iterator i = graph_iterator_read_tree_iter( child );
414 std::size_t depth = ( *i ).first.get().size();
424 while ( ( *i ).first.get().size() >= depth );
425 graph_iterator_write_tree_iter( i, iter );
430 static GObjectClass *g_parent_class = 0;
432 static void graph_tree_model_init( GraphTreeModel *graph_tree_model ){
433 graph_tree_model->graph = 0;
436 static void graph_tree_model_finalize( GObject* object ){
437 GraphTreeModel* graph_tree_model = GRAPH_TREE_MODEL( object );
440 ( *g_parent_class->finalize )( object );
443 static void graph_tree_model_class_init( GraphTreeModelClass *class_ ){
444 GObjectClass *object_class;
446 g_parent_class = (GObjectClass*)g_type_class_peek_parent( class_ );
447 object_class = (GObjectClass *) class_;
449 object_class->finalize = graph_tree_model_finalize;
452 static void graph_tree_model_tree_model_init( GtkTreeModelIface *iface ){
453 iface->get_flags = graph_tree_model_get_flags;
454 iface->get_n_columns = graph_tree_model_get_n_columns;
455 iface->get_column_type = graph_tree_model_get_column_type;
456 iface->get_iter = graph_tree_model_get_iter;
457 iface->get_path = graph_tree_model_get_path;
458 iface->get_value = graph_tree_model_get_value;
459 iface->iter_next = graph_tree_model_iter_next;
460 iface->iter_children = graph_tree_model_iter_children;
461 iface->iter_has_child = graph_tree_model_iter_has_child;
462 iface->iter_n_children = graph_tree_model_iter_n_children;
463 iface->iter_nth_child = graph_tree_model_iter_nth_child;
464 iface->iter_parent = graph_tree_model_iter_parent;
467 static gboolean graph_tree_model_row_draggable( GtkTreeDragSource *drag_source, GtkTreePath *path ){
469 gint depth = gtk_tree_path_get_depth( path );
471 return gtk_tree_path_get_depth( path ) > 1;
474 static gboolean graph_tree_model_drag_data_delete( GtkTreeDragSource *drag_source, GtkTreePath *path ){
477 if ( gtk_tree_model_get_iter( GTK_TREE_MODEL( drag_source ), &iter, path ) ) {
478 graph_type::iterator i = graph_iterator_read_tree_iter( &iter );
479 Path_deleteTop( ( *i ).first );
488 static gboolean graph_tree_model_drag_data_get( GtkTreeDragSource *drag_source, GtkTreePath *path, GtkSelectionData *selection_data ){
489 if ( gtk_tree_set_row_drag_data( selection_data, GTK_TREE_MODEL( drag_source ), path ) ) {
494 /* FIXME handle text targets at least. */
500 static void graph_tree_model_drag_source_init( GtkTreeDragSourceIface *iface ){
501 iface->row_draggable = graph_tree_model_row_draggable;
502 iface->drag_data_delete = graph_tree_model_drag_data_delete;
503 iface->drag_data_get = graph_tree_model_drag_data_get;
506 static gboolean graph_tree_model_drag_data_received( GtkTreeDragDest *drag_dest, GtkTreePath *dest, GtkSelectionData *selection_data ){
507 GtkTreeModel *tree_model = GTK_TREE_MODEL( drag_dest );
509 GtkTreeModel *src_model = 0;
510 GtkTreePath *src_path = 0;
511 if ( gtk_tree_get_row_drag_data( selection_data, &src_model, &src_path )
512 && src_model == tree_model ) {
513 /* Copy the given row to a new position */
516 if ( gtk_tree_model_get_iter( src_model, &iter, src_path ) ) {
522 /* FIXME maybe add some data targets eventually, or handle text
523 * targets in the simple case.
530 static gboolean graph_tree_model_row_drop_possible( GtkTreeDragDest *drag_dest, GtkTreePath *dest_path, GtkSelectionData *selection_data ){
531 gboolean retval = FALSE;
533 GtkTreeModel *src_model = 0;
534 GtkTreePath *src_path = 0;
535 if ( gtk_tree_get_row_drag_data( selection_data, &src_model, &src_path ) != FALSE ) {
536 /* can only drag to ourselves */
537 if ( src_model == GTK_TREE_MODEL( drag_dest ) ) {
538 /* Can't drop into ourself. */
539 if ( !gtk_tree_path_is_ancestor( src_path, dest_path ) ) {
540 /* Can't drop if dest_path's parent doesn't exist */
541 if ( gtk_tree_path_get_depth( dest_path ) > 1 ) {
542 GtkTreePath* tmp = gtk_tree_path_copy( dest_path );
543 gtk_tree_path_up( tmp );
546 retval = gtk_tree_model_get_iter( GTK_TREE_MODEL( drag_dest ), &iter, tmp );
548 gtk_tree_path_free( tmp );
553 gtk_tree_path_free( src_path );
559 static void graph_tree_model_drag_dest_init( GtkTreeDragDestIface *iface ){
560 iface->drag_data_received = graph_tree_model_drag_data_received;
561 iface->row_drop_possible = graph_tree_model_row_drop_possible;
564 GType graph_tree_model_get_type( void ){
565 static GType graph_tree_model_type = 0;
567 if ( !graph_tree_model_type ) {
568 static const GTypeInfo graph_tree_model_info =
570 sizeof( GraphTreeModelClass ),
572 0, /* base_finalize */
573 (GClassInitFunc) graph_tree_model_class_init,
574 0, /* class_finalize */
576 sizeof( GraphTreeModel ),
578 (GInstanceInitFunc) graph_tree_model_init
581 static const GInterfaceInfo tree_model_info =
583 (GInterfaceInitFunc) graph_tree_model_tree_model_init,
588 static const GInterfaceInfo drag_source_info =
590 (GInterfaceInitFunc) graph_tree_model_drag_source_init,
595 static const GInterfaceInfo drag_dest_info =
597 (GInterfaceInitFunc) graph_tree_model_drag_dest_init,
602 graph_tree_model_type = g_type_register_static( G_TYPE_OBJECT, "GraphTreeModel",
603 &graph_tree_model_info, (GTypeFlags)0 );
605 g_type_add_interface_static( graph_tree_model_type,
608 g_type_add_interface_static( graph_tree_model_type,
609 GTK_TYPE_TREE_DRAG_SOURCE,
611 g_type_add_interface_static( graph_tree_model_type,
612 GTK_TYPE_TREE_DRAG_DEST,
616 return graph_tree_model_type;
619 GraphTreeModel* graph_tree_model_new(){
620 GraphTreeModel* graph_tree_model = GRAPH_TREE_MODEL( g_object_new( graph_tree_model_get_type(), 0 ) );
622 graph_tree_model->graph = new graph_type;
624 return graph_tree_model;
627 void graph_tree_model_delete( GraphTreeModel* model ){
629 g_object_unref( G_OBJECT( model ) );
633 class TempNameable : public Nameable
637 TempNameable( const char* name ) : m_name( name ){
639 const char* name() const {
642 void attach( const NameCallback& callback ){
644 void detach( const NameCallback& callback ){
648 void node_attach_name_changed_callback( scene::Node& node, const NameCallback& callback ){
650 Nameable* nameable = Node_getNameable( node );
651 if ( nameable != 0 ) {
652 nameable->attach( callback );
656 void node_detach_name_changed_callback( scene::Node& node, const NameCallback& callback ){
658 Nameable* nameable = Node_getNameable( node );
659 if ( nameable != 0 ) {
660 nameable->detach( callback );
665 GraphTreeModel* scene_graph_get_tree_model(); // temp hack
667 void graph_tree_model_row_inserted( GraphTreeModel* model, graph_type::iterator i ){
669 graph_iterator_write_tree_iter( i, &iter );
671 GtkTreePath* tree_path = graph_tree_model_get_path( GTK_TREE_MODEL( model ), &iter );
673 gint depth = gtk_tree_path_get_depth( tree_path );
674 gint* indices = gtk_tree_path_get_indices( tree_path );
676 gtk_tree_model_row_inserted( GTK_TREE_MODEL( model ), tree_path, &iter );
678 gtk_tree_path_free( tree_path );
681 void graph_tree_model_row_deleted( GraphTreeModel* model, graph_type::iterator i ){
683 graph_iterator_write_tree_iter( i, &iter );
685 GtkTreePath* tree_path = graph_tree_model_get_path( GTK_TREE_MODEL( model ), &iter );
687 gtk_tree_model_row_deleted( GTK_TREE_MODEL( model ), tree_path );
689 gtk_tree_path_free( tree_path );
692 #include "generic/referencecounted.h"
694 void graph_tree_model_set_name( const scene::Instance& instance, const char* name ){
695 GraphTreeModel* model = scene_graph_get_tree_model();
697 if ( string_empty( name ) ) { // hack!
698 graph_type::iterator i = model->graph->find( PathConstReference( instance.path() ) );
699 ASSERT_MESSAGE( i != model->graph->end(), "ERROR" );
701 graph_tree_model_row_deleted( model, i );
703 model->graph->erase( i );
707 graph_type::iterator i = model->graph->insert( graph_type::value_type( PathConstReference( instance.path() ), &const_cast<scene::Instance&>( instance ) ) ).first;
709 graph_tree_model_row_inserted( model, i );
713 void graph_tree_model_insert( GraphTreeModel* model, const scene::Instance& instance ){
714 graph_type::iterator i = model->graph->insert( graph_type::value_type( PathConstReference( instance.path() ), &const_cast<scene::Instance&>( instance ) ) ).first;
716 graph_tree_model_row_inserted( model, i );
718 node_attach_name_changed_callback( instance.path().top(), ConstReferenceCaller1<scene::Instance, const char*, graph_tree_model_set_name>( instance ) );
721 void graph_tree_model_erase( GraphTreeModel* model, const scene::Instance& instance ){
722 node_detach_name_changed_callback( instance.path().top(), ConstReferenceCaller1<scene::Instance, const char*, graph_tree_model_set_name>( instance ) );
724 graph_type::iterator i = model->graph->find( PathConstReference( instance.path() ) );
725 ASSERT_MESSAGE( i != model->graph->end(), "ERROR" );
727 graph_tree_model_row_deleted( model, i );
729 model->graph->erase( i );
735 void graph_tree_model_row_changed( GraphTreeNode& node );
739 typedef std::map<std::pair<std::string, scene::Node*>, GraphTreeNode*> ChildNodes;
740 ChildNodes m_childnodes;
742 Reference<scene::Instance> m_instance;
743 GraphTreeNode* m_parent;
745 typedef ChildNodes::iterator iterator;
746 typedef ChildNodes::key_type key_type;
747 typedef ChildNodes::value_type value_type;
748 typedef ChildNodes::size_type size_type;
750 GraphTreeNode( scene::Instance& instance ) : m_instance( instance ), m_parent( 0 ){
751 m_instance.get().setChildSelectedChangedCallback( RowChangedCaller( *this ) );
754 m_instance.get().setChildSelectedChangedCallback( Callback() );
755 ASSERT_MESSAGE( empty(), "GraphTreeNode::~GraphTreeNode: memory leak" );
759 return m_childnodes.begin();
762 return m_childnodes.end();
765 size_type size() const {
766 return m_childnodes.size();
769 return m_childnodes.empty();
772 iterator insert( const value_type& value ){
773 iterator i = m_childnodes.insert( value ).first;
774 ( *i ).second->m_parent = this;
777 void erase( iterator i ){
778 m_childnodes.erase( i );
780 iterator find( const key_type& key ){
781 return m_childnodes.find( key );
784 void swap( GraphTreeNode& other ){
785 std::swap( m_parent, other.m_parent );
786 std::swap( m_childnodes, other.m_childnodes );
787 std::swap( m_instance, other.m_instance );
791 graph_tree_model_row_changed( *this );
793 typedef MemberCaller<GraphTreeNode, &GraphTreeNode::rowChanged> RowChangedCaller;
796 struct GraphTreeModel
800 GraphTreeNode* m_graph;
803 struct GraphTreeModelClass
805 GObjectClass parent_class;
808 #define GRAPH_TREE_MODEL( p ) ( reinterpret_cast<GraphTreeModel*>( p ) )
810 static GtkTreeModelFlags graph_tree_model_get_flags( GtkTreeModel* tree_model ){
811 return GTK_TREE_MODEL_ITERS_PERSIST;
814 static gint graph_tree_model_get_n_columns( GtkTreeModel* tree_model ){
815 ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
816 //GraphTreeModel* graph_tree_model = (GraphTreeModel*) tree_model;
821 static const gint c_stamp = 0xabcdef;
823 inline GraphTreeNode::iterator graph_iterator_read_tree_iter( GtkTreeIter* iter ){
824 ASSERT_MESSAGE( iter != 0, "tree model error" );
825 ASSERT_MESSAGE( iter->user_data != 0, "tree model error" );
826 ASSERT_MESSAGE( iter->stamp == c_stamp, "tree model error" );
827 return *reinterpret_cast<GraphTreeNode::iterator*>( &iter->user_data );
830 inline void graph_iterator_write_tree_iter( GraphTreeNode::iterator i, GtkTreeIter* iter ){
831 ASSERT_MESSAGE( iter != 0, "tree model error" );
832 iter->stamp = c_stamp;
833 *reinterpret_cast<GraphTreeNode::iterator*>( &iter->user_data ) = i;
834 ASSERT_MESSAGE( iter->user_data != 0, "tree model error" );
837 static GType graph_tree_model_get_column_type( GtkTreeModel *tree_model, gint index ){
838 ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
839 //GraphTreeModel *graph_tree_model = (GraphTreeModel *) tree_model;
841 return G_TYPE_POINTER;
844 static gboolean graph_tree_model_get_iter( GtkTreeModel* tree_model, GtkTreeIter* iter, GtkTreePath* path ){
845 ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
846 gint* indices = gtk_tree_path_get_indices( path );
847 gint depth = gtk_tree_path_get_depth( path );
849 g_return_val_if_fail( depth > 0, FALSE );
851 GraphTreeNode* graph = GRAPH_TREE_MODEL( tree_model )->m_graph;
853 if ( graph->empty() ) {
858 GtkTreeIter* parent = 0;
860 for ( gint i = 0; i < depth; i++ )
862 if ( !gtk_tree_model_iter_nth_child( tree_model, iter, parent, indices[i] ) ) {
872 static GtkTreePath* graph_tree_model_get_path( GtkTreeModel* tree_model, GtkTreeIter* iter ){
873 ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
874 GraphTreeNode* graph = GRAPH_TREE_MODEL( tree_model )->m_graph;
876 GtkTreePath* path = ui::TreePath();
878 for ( GraphTreeNode* node = ( *graph_iterator_read_tree_iter( iter ) ).second; node != graph; node = node->m_parent )
880 std::size_t index = 0;
881 for ( GraphTreeNode::iterator i = node->m_parent->begin(); i != node->m_parent->end(); ++i, ++index )
883 if ( ( *i ).second == node ) {
884 gtk_tree_path_prepend_index( path, gint( index ) );
888 ASSERT_MESSAGE( index != node->m_parent->size(), "error resolving tree path" );
895 static void graph_tree_model_get_value( GtkTreeModel *tree_model, GtkTreeIter *iter, gint column, GValue *value ){
896 ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
897 ASSERT_MESSAGE( column == 0 || column == 1, "tree model error" );
899 GraphTreeNode::iterator i = graph_iterator_read_tree_iter( iter );
901 g_value_init( value, G_TYPE_POINTER );
904 g_value_set_pointer( value, reinterpret_cast<gpointer>( ( *i ).first.second ) );
908 g_value_set_pointer( value, reinterpret_cast<gpointer>( &( *i ).second->m_instance.get() ) );
912 static gboolean graph_tree_model_iter_next( GtkTreeModel *tree_model, GtkTreeIter *iter ){
913 ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
914 GraphTreeNode::iterator i = graph_iterator_read_tree_iter( iter );
915 GraphTreeNode& parent = *( *i ).second->m_parent;
917 ASSERT_MESSAGE( i != parent.end(), "RUNTIME ERROR" );
919 if ( ++i == parent.end() ) {
923 graph_iterator_write_tree_iter( i, iter );
928 static gboolean graph_tree_model_iter_children( GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreeIter *parent ){
929 ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
930 GraphTreeNode& node = ( parent == 0 ) ? *GRAPH_TREE_MODEL( tree_model )->m_graph : *( *graph_iterator_read_tree_iter( parent ) ).second;
931 if ( !node.empty() ) {
932 graph_iterator_write_tree_iter( node.begin(), iter );
939 static gboolean graph_tree_model_iter_has_child( GtkTreeModel *tree_model, GtkTreeIter *iter ){
940 ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
941 GraphTreeNode& node = *( *graph_iterator_read_tree_iter( iter ) ).second;
942 return !node.empty();
945 static gint graph_tree_model_iter_n_children( GtkTreeModel *tree_model, GtkTreeIter *parent ){
946 ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
947 GraphTreeNode& node = ( parent == 0 ) ? *GRAPH_TREE_MODEL( tree_model )->m_graph : *( *graph_iterator_read_tree_iter( parent ) ).second;
948 return static_cast<gint>( node.size() );
951 static gboolean graph_tree_model_iter_nth_child( GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreeIter *parent, gint n ){
952 ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
953 GraphTreeNode& node = ( parent == 0 ) ? *GRAPH_TREE_MODEL( tree_model )->m_graph : *( *graph_iterator_read_tree_iter( parent ) ).second;
954 if ( static_cast<std::size_t>( n ) < node.size() ) {
955 GraphTreeNode::iterator i = node.begin();
956 std::advance( i, n );
957 graph_iterator_write_tree_iter( i, iter );
964 static gboolean graph_tree_model_iter_parent( GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreeIter *child ){
965 ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
966 GraphTreeNode& node = *( *graph_iterator_read_tree_iter( child ) ).second;
967 if ( node.m_parent != GRAPH_TREE_MODEL( tree_model )->m_graph ) {
968 GraphTreeNode& parentParent = *node.m_parent->m_parent;
969 for ( GraphTreeNode::iterator i = parentParent.begin(); i != parentParent.end(); ++i )
971 if ( ( *i ).second == node.m_parent ) {
972 graph_iterator_write_tree_iter( i, iter );
980 static GObjectClass *g_parent_class = 0;
984 scene::Node* g_null_node = 0;
987 class NullInstance : public scene::Instance
990 NullInstance() : scene::Instance( scene::Path( makeReference( *g_null_node ) ), 0, 0, Static<InstanceTypeCastTable>::instance() ){
996 NullInstance g_null_instance;
999 static void graph_tree_model_init( GraphTreeModel *graph_tree_model ){
1000 graph_tree_model->m_graph = new GraphTreeNode( g_null_instance );
1003 static void graph_tree_model_finalize( GObject* object ){
1004 GraphTreeModel* graph_tree_model = GRAPH_TREE_MODEL( object );
1006 delete graph_tree_model->m_graph;
1009 ( *g_parent_class->finalize )( object );
1012 static void graph_tree_model_class_init( GraphTreeModelClass *class_ ){
1013 GObjectClass *object_class;
1015 g_parent_class = (GObjectClass*)g_type_class_peek_parent( class_ );
1016 object_class = (GObjectClass *) class_;
1018 object_class->finalize = graph_tree_model_finalize;
1021 static void graph_tree_model_tree_model_init( GtkTreeModelIface *iface ){
1022 iface->get_flags = graph_tree_model_get_flags;
1023 iface->get_n_columns = graph_tree_model_get_n_columns;
1024 iface->get_column_type = graph_tree_model_get_column_type;
1025 iface->get_iter = graph_tree_model_get_iter;
1026 iface->get_path = graph_tree_model_get_path;
1027 iface->get_value = graph_tree_model_get_value;
1028 iface->iter_next = graph_tree_model_iter_next;
1029 iface->iter_children = graph_tree_model_iter_children;
1030 iface->iter_has_child = graph_tree_model_iter_has_child;
1031 iface->iter_n_children = graph_tree_model_iter_n_children;
1032 iface->iter_nth_child = graph_tree_model_iter_nth_child;
1033 iface->iter_parent = graph_tree_model_iter_parent;
1036 GType graph_tree_model_get_type( void ){
1037 static GType graph_tree_model_type = 0;
1039 if ( !graph_tree_model_type ) {
1040 static const GTypeInfo graph_tree_model_info =
1042 sizeof( GraphTreeModelClass ),
1044 0, /* base_finalize */
1045 (GClassInitFunc) graph_tree_model_class_init,
1046 0, /* class_finalize */
1048 sizeof( GraphTreeModel ),
1049 0, /* n_preallocs */
1050 (GInstanceInitFunc) graph_tree_model_init,
1054 static const GInterfaceInfo tree_model_info =
1056 (GInterfaceInitFunc) graph_tree_model_tree_model_init,
1061 graph_tree_model_type = g_type_register_static( G_TYPE_OBJECT, "GraphTreeModel",
1062 &graph_tree_model_info, (GTypeFlags)0 );
1064 g_type_add_interface_static( graph_tree_model_type,
1065 GTK_TYPE_TREE_MODEL,
1069 return graph_tree_model_type;
1072 GraphTreeModel* graph_tree_model_new(){
1073 GraphTreeModel* graph_tree_model = GRAPH_TREE_MODEL( g_object_new( graph_tree_model_get_type(), 0 ) );
1075 return graph_tree_model;
1078 void graph_tree_model_delete( GraphTreeModel* model ){
1079 g_object_unref( G_OBJECT( model ) );
1082 void graph_tree_model_row_changed( GraphTreeModel* model, GraphTreeNode::iterator i ){
1084 graph_iterator_write_tree_iter( i, &iter );
1086 GtkTreePath* tree_path = graph_tree_model_get_path( GTK_TREE_MODEL( model ), &iter );
1088 gtk_tree_model_row_changed( GTK_TREE_MODEL( model ), tree_path, &iter );
1090 gtk_tree_path_free( tree_path );
1093 void graph_tree_model_row_inserted( GraphTreeModel* model, GraphTreeNode::iterator i ){
1095 graph_iterator_write_tree_iter( i, &iter );
1097 GtkTreePath* tree_path = graph_tree_model_get_path( GTK_TREE_MODEL( model ), &iter );
1099 gtk_tree_model_row_inserted( GTK_TREE_MODEL( model ), tree_path, &iter );
1101 gtk_tree_path_free( tree_path );
1104 void graph_tree_model_row_deleted( GraphTreeModel* model, GraphTreeNode::iterator i ){
1106 graph_iterator_write_tree_iter( i, &iter );
1108 GtkTreePath* tree_path = graph_tree_model_get_path( GTK_TREE_MODEL( model ), &iter );
1110 gtk_tree_model_row_deleted( GTK_TREE_MODEL( model ), tree_path );
1112 gtk_tree_path_free( tree_path );
1115 void graph_tree_model_row_inserted( GraphTreeModel& model, GraphTreeNode::iterator i ){
1116 graph_tree_model_row_inserted( &model, i );
1119 void graph_tree_model_row_deleted( GraphTreeModel& model, GraphTreeNode::iterator i ){
1120 graph_tree_model_row_deleted( &model, i );
1123 const char* node_get_name( scene::Node& node );
1125 const char* node_get_name_safe( scene::Node& node ){
1129 return node_get_name( node );
1132 GraphTreeNode* graph_tree_model_find_parent( GraphTreeModel* model, const scene::Path& path ){
1133 GraphTreeNode* parent = model->m_graph;
1134 for ( scene::Path::const_iterator i = path.begin(); i != path.end() - 1; ++i )
1136 GraphTreeNode::iterator child = parent->find( GraphTreeNode::key_type( node_get_name_safe( ( *i ).get() ), ( *i ).get_pointer() ) );
1137 ASSERT_MESSAGE( child != parent->end(), "ERROR" );
1138 parent = ( *child ).second;
1143 void node_attach_name_changed_callback( scene::Node& node, const NameCallback& callback ){
1145 Nameable* nameable = Node_getNameable( node );
1146 if ( nameable != 0 ) {
1147 nameable->attach( callback );
1151 void node_detach_name_changed_callback( scene::Node& node, const NameCallback& callback ){
1153 Nameable* nameable = Node_getNameable( node );
1154 if ( nameable != 0 ) {
1155 nameable->detach( callback );
1160 GraphTreeModel* scene_graph_get_tree_model(); // temp hack
1162 void graph_tree_node_foreach_pre( GraphTreeNode::iterator root, const Callback1<GraphTreeNode::iterator>& callback ){
1164 for ( GraphTreeNode::iterator i = ( *root ).second->begin(); i != ( *root ).second->end(); ++i )
1166 graph_tree_node_foreach_pre( i, callback );
1170 void graph_tree_node_foreach_post( GraphTreeNode::iterator root, const Callback1<GraphTreeNode::iterator>& callback ){
1171 for ( GraphTreeNode::iterator i = ( *root ).second->begin(); i != ( *root ).second->end(); ++i )
1173 graph_tree_node_foreach_post( i, callback );
1178 void graph_tree_model_row_changed( GraphTreeNode& node ){
1179 GraphTreeModel* model = scene_graph_get_tree_model();
1180 const scene::Instance& instance = node.m_instance.get();
1182 GraphTreeNode::iterator i = node.m_parent->find( GraphTreeNode::key_type( node_get_name_safe( instance.path().top().get() ), instance.path().top().get_pointer() ) );
1184 graph_tree_model_row_changed( model, i );
1187 void graph_tree_model_set_name( const scene::Instance& instance, const char* name ){
1188 GraphTreeModel* model = scene_graph_get_tree_model();
1189 GraphTreeNode* parent = graph_tree_model_find_parent( model, instance.path() );
1191 GraphTreeNode::iterator oldNode = parent->find( GraphTreeNode::key_type( node_get_name_safe( instance.path().top().get() ), instance.path().top().get_pointer() ) );
1192 graph_tree_node_foreach_post( oldNode, ReferenceCaller1<GraphTreeModel, GraphTreeNode::iterator, graph_tree_model_row_deleted>( *model ) );
1193 GraphTreeNode* node( ( *oldNode ).second );
1194 parent->erase( oldNode );
1196 GraphTreeNode::iterator newNode = parent->insert( GraphTreeNode::value_type( GraphTreeNode::key_type( name, &instance.path().top().get() ), node ) );
1197 graph_tree_node_foreach_pre( newNode, ReferenceCaller1<GraphTreeModel, GraphTreeNode::iterator, graph_tree_model_row_inserted>( *model ) );
1200 void graph_tree_model_insert( GraphTreeModel* model, const scene::Instance& instance ){
1201 GraphTreeNode* parent = graph_tree_model_find_parent( model, instance.path() );
1203 GraphTreeNode::iterator i = parent->insert( GraphTreeNode::value_type( GraphTreeNode::key_type( node_get_name_safe( instance.path().top().get() ), instance.path().top().get_pointer() ), new GraphTreeNode( const_cast<scene::Instance&>( instance ) ) ) );
1205 graph_tree_model_row_inserted( model, i );
1207 node_attach_name_changed_callback( instance.path().top(), ConstReferenceCaller1<scene::Instance, const char*, graph_tree_model_set_name>( instance ) );
1210 void graph_tree_model_erase( GraphTreeModel* model, const scene::Instance& instance ){
1211 node_detach_name_changed_callback( instance.path().top(), ConstReferenceCaller1<scene::Instance, const char*, graph_tree_model_set_name>( instance ) );
1213 GraphTreeNode* parent = graph_tree_model_find_parent( model, instance.path() );
1215 GraphTreeNode::iterator i = parent->find( GraphTreeNode::key_type( node_get_name_safe( instance.path().top().get() ), instance.path().top().get_pointer() ) );
1217 graph_tree_model_row_deleted( model, i );
1219 GraphTreeNode* node( ( *i ).second );
1232 class TestGraphTreeModel
1235 TestGraphTreeModel(){
1240 scene::Node* root = *(scene::Node*)0xa0000000;
1241 scene::Node* node1 = (scene::Node*)0xa0000001;
1242 scene::Node* node2 = (scene::Node*)0xa0000002;
1243 scene::Node* node3 = (scene::Node*)0xa0000003;
1244 scene::Node* node4 = (scene::Node*)0xa0000004;
1245 scene::Instance* instance = (scene::Instance*)0xaaaaaaaa;
1247 scene::Path rootpath( root );
1249 graph.insert( graph_type::value_type( rootpath, instance ) );
1251 rootpath.push( node1 );
1252 graph.insert( graph_type::value_type( rootpath, instance ) );
1255 rootpath.push( node2 );
1256 graph.insert( graph_type::value_type( rootpath, instance ) );
1257 rootpath.push( node3 );
1258 graph.insert( graph_type::value_type( rootpath, instance ) );
1260 rootpath.push( node4 );
1261 graph.insert( graph_type::value_type( rootpath, instance ) );
1265 GtkTreeModel* model = GTK_TREE_MODEL( graph_tree_model_new( &graph ) );
1268 gint n_columns = gtk_tree_model_get_n_columns( model );
1269 ASSERT_MESSAGE( n_columns == 2, "test failed!" );
1273 GType type = gtk_tree_model_get_column_type( model, 0 );
1274 ASSERT_MESSAGE( type == G_TYPE_POINTER, "test failed!" );
1278 GType type = gtk_tree_model_get_column_type( model, 1 );
1279 ASSERT_MESSAGE( type == G_TYPE_POINTER, "test failed!" );
1285 gtk_tree_model_get_iter_first( model, &iter );
1287 graph_type::iterator i = graph_iterator_read_tree_iter( &iter );
1288 ASSERT_MESSAGE( ( *i ).first.get().size() == 2 && ( *i ).first.get().top() == node1, "test failed!" );
1293 gtk_tree_model_get_iter_first( model, &iter );
1295 ASSERT_MESSAGE( gtk_tree_model_iter_has_child( model, &iter ) == FALSE, "test failed!" );
1297 ASSERT_MESSAGE( gtk_tree_model_iter_n_children( model, &iter ) == 0, "test failed!" );
1299 gtk_tree_model_iter_next( model, &iter );
1301 ASSERT_MESSAGE( gtk_tree_model_iter_has_child( model, &iter ) != FALSE, "test failed!" );
1303 ASSERT_MESSAGE( gtk_tree_model_iter_n_children( model, &iter ) == 2, "test failed!" );
1307 gtk_tree_model_iter_nth_child( model, &child, &iter, 0 );
1310 gtk_tree_model_get_value( model, &child, 0, (GValue*)&test );
1311 ASSERT_MESSAGE( test == node3, "test failed!" );
1315 gtk_tree_model_iter_parent( model, &parent, &child );
1318 gtk_tree_model_get_value( model, &parent, 0, (GValue*)&test );
1319 ASSERT_MESSAGE( test == node2, "test failed!" );
1325 gtk_tree_model_iter_nth_child( model, &child, &iter, 1 );
1328 gtk_tree_model_get_value( model, &child, 0, (GValue*)&test );
1329 ASSERT_MESSAGE( test == node4, "test failed!" );
1335 std::size_t count = 0;
1336 for ( gboolean good = gtk_tree_model_get_iter_first( model, &iter ); good; good = gtk_tree_model_iter_next( model, &iter ) )
1339 gtk_tree_model_get_value( model, &iter, 0, (GValue*)&test );
1341 ASSERT_MESSAGE( ( count == 0 && test == node1 ) || ( count == 1 && test == node2 ), "test failed!" );
1345 ASSERT_MESSAGE( count == 2, "test failed!" );
1351 gtk_tree_model_get_iter_first( model, &iter );
1354 gtk_tree_model_get_value( model, &iter, 0, (GValue*)&test );
1355 ASSERT_MESSAGE( test == node1, "test failed!" );
1360 GtkTreePath* path = ui::TreePath( "0" );
1361 gtk_tree_model_get_iter( model, &iter, path );
1362 gtk_tree_path_free( path );
1364 graph_type::iterator i = graph_iterator_read_tree_iter( &iter );
1365 ASSERT_MESSAGE( ( *i ).first.get().size() == 2 && ( *i ).first.get().top() == node1, "test failed!" );
1370 GtkTreePath* path = ui::TreePath( "1" );
1371 gtk_tree_model_get_iter( model, &iter, path );
1372 gtk_tree_path_free( path );
1374 graph_type::iterator i = graph_iterator_read_tree_iter( &iter );
1375 ASSERT_MESSAGE( ( *i ).first.get().size() == 2 && ( *i ).first.get().top() == node2, "test failed!" );
1380 graph_type::iterator i = graph.begin();
1382 graph_iterator_write_tree_iter( i, &iter );
1384 GtkTreePath* path = gtk_tree_model_get_path( model, &iter );
1386 gint depth = gtk_tree_path_get_depth( path );
1387 gint* indices = gtk_tree_path_get_indices( path );
1389 ASSERT_MESSAGE( depth == 1 && indices[0] == 0, "test failed!" );
1391 gtk_tree_path_free( path );
1396 graph_type::iterator i = graph.begin();
1399 graph_iterator_write_tree_iter( i, &iter );
1401 GtkTreePath* path = gtk_tree_model_get_path( model, &iter );
1403 gint depth = gtk_tree_path_get_depth( path );
1404 gint* indices = gtk_tree_path_get_indices( path );
1406 ASSERT_MESSAGE( depth == 1 && indices[0] == 1, "test failed!" );
1408 gtk_tree_path_free( path );
1414 TestGraphTreeModel g_TestGraphTreeModel;