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"
23 #include "globaldefs.h"
25 #include "debugging/debugging.h"
29 #include <uilib/uilib.h>
31 #include "iscenegraph.h"
34 #include "generic/callback.h"
36 #include "string/string.h"
37 #include "generic/reference.h"
39 inline Nameable *Node_getNameable(scene::Node &node)
41 return NodeTypeCast<Nameable>::cast(node);
46 #include "gtkutil/gtktreestore.h"
48 template<typename value_type>
49 inline void gtk_tree_model_get_pointer( ui::TreeModel model, GtkTreeIter* iter, gint column, value_type** pointer ){
50 GValue value = GValue_default();
51 gtk_tree_model_get_value( model, iter, column, &value );
52 *pointer = (value_type*)g_value_get_pointer( &value );
56 typedef GtkTreeStore GraphTreeModel;
58 ui::TreeStore graph_tree_model_new( graph_type* graph ){
59 return gtk_tree_store_new( 2, G_TYPE_POINTER, G_TYPE_POINTER );
62 void graph_tree_model_delete( GraphTreeModel* model ){
63 g_object_unref( G_OBJECT( model ) );
67 bool graph_tree_model_subtree_find_node( GraphTreeModel* model, GtkTreeIter* parent, const scene::Node& node, GtkTreeIter* iter ){
68 for ( gboolean success = gtk_tree_model_iter_children( model, iter, parent );
70 success = gtk_tree_model_iter_next( model, iter ) )
73 gtk_tree_model_get_pointer( model, iter, 0, ¤t );
74 if ( current == node ) {
81 typedef GtkTreeIter DoubleGtkTreeIter[2];
83 bool graph_tree_model_find_top( GraphTreeModel* model, const scene::Path& path, GtkTreeIter& iter ){
85 GtkTreeIter* parent_pointer = NULL;
87 for ( scene::Path::const_iterator i = path.begin(); i != path.end(); ++i )
89 if ( !graph_tree_model_subtree_find_node( model, parent_pointer, *i, &iter ) ) {
93 parent_pointer = &parent;
98 bool graph_tree_model_find_parent( GraphTreeModel* model, const scene::Path& path, GtkTreeIter& iter ){
100 GtkTreeIter* parent_pointer = NULL;
101 ASSERT_MESSAGE( path.size() > 1, "path too short" );
102 for ( scene::Path::const_iterator i = path.begin(); i != path.end() - 1; ++i )
105 if ( !graph_tree_model_subtree_find_node( model, parent_pointer, *i, &child ) ) {
109 parent_pointer = &iter;
114 void node_attach_name_changed_callback( scene::Node& node, const Callback<void()>& callback ){
116 Nameable* nameable = Node_getNameable( node );
117 if ( nameable != 0 ) {
118 nameable->attach( callback );
122 void node_detach_name_changed_callback( scene::Node& node, const Callback<void()>& callback ){
124 Nameable* nameable = Node_getNameable( node );
125 if ( nameable != 0 ) {
126 nameable->detach( callback );
131 GraphTreeModel* scene_graph_get_tree_model(); // temp hack
133 void graph_tree_model_row_changed( const scene::Instance& instance ){
134 GraphTreeModel* model = scene_graph_get_tree_model();
137 ASSERT_MESSAGE( graph_tree_model_find_top( model, instance.path(), child ), "RUNTIME ERROR" );
139 gtk_tree_store_set( GTK_TREE_STORE( model ), &child, 0, instance.path().top(), -1 );
142 void graph_tree_model_row_inserted( GraphTreeModel* model, const scene::Instance& instance ){
144 GtkTreeIter* parent_pointer = NULL;
145 if ( instance.path().size() != 1 ) {
146 ASSERT_MESSAGE( graph_tree_model_find_parent( model, instance.path(), parent ), "RUNTIME ERROR" );
147 parent_pointer = &parent;
150 gpointer node = instance.path().top();
151 gconstpointer selectable = Instance_getSelectable( instance );
154 gtk_tree_store_append( GTK_TREE_STORE( model ), &child, parent_pointer );
155 gtk_tree_store_set( GTK_TREE_STORE( model ), &child, 0, node, 1, selectable, -1 );
157 node_attach_name_changed_callback( instance.path().top(), ConstReferenceCaller<scene::Instance, void(), graph_tree_model_row_changed>( instance ) );
160 void graph_tree_model_row_deleted( GraphTreeModel* model, const scene::Instance& instance ){
162 ASSERT_MESSAGE( graph_tree_model_find_top( model, instance.path(), child ), "RUNTIME ERROR" );
164 node_detach_name_changed_callback( instance.path().top(), ConstReferenceCaller<scene::Instance, void(), graph_tree_model_row_changed>( instance ) );
166 gtk_tree_store_remove( GTK_TREE_STORE( model ), &child );
171 const char* node_get_name( scene::Node& node );
173 typedef scene::Node* NodePointer;
178 bool operator()( const NodePointer& self, const NodePointer& other ) const {
185 int result = string_compare( node_get_name( self ), node_get_name( other ) );
196 bool operator()( const PathConstReference& self, const PathConstReference& other ) const {
197 return std::lexicographical_compare( self.get().begin(), self.get().end(), other.get().begin(), other.get().end(), NodeNameLess() );
201 typedef std::map<PathConstReference, scene::Instance*, PathNameLess> graph_type;
203 struct GraphTreeModel
210 struct GraphTreeModelClass
212 GObjectClass parent_class;
215 #define GRAPH_TREE_MODEL( p ) ( reinterpret_cast<GraphTreeModel*>( p ) )
217 static GtkTreeModelFlags graph_tree_model_get_flags( GtkTreeModel* tree_model ){
218 return GTK_TREE_MODEL_ITERS_PERSIST;
221 static gint graph_tree_model_get_n_columns( ui::TreeModel tree_model ){
222 ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
223 GraphTreeModel* graph_tree_model = (GraphTreeModel*) tree_model;
228 static const gint c_stamp = 0xabcdef;
230 inline graph_type::iterator graph_iterator_read_tree_iter( GtkTreeIter* iter ){
231 ASSERT_MESSAGE( iter != 0, "tree model error" );
232 ASSERT_MESSAGE( iter->user_data != 0, "tree model error" );
233 ASSERT_MESSAGE( iter->stamp == c_stamp, "tree model error" );
234 return *reinterpret_cast<graph_type::iterator*>( &iter->user_data );
237 inline void graph_iterator_write_tree_iter( graph_type::iterator i, GtkTreeIter* iter ){
238 ASSERT_MESSAGE( iter != 0, "tree model error" );
239 iter->stamp = c_stamp;
240 *reinterpret_cast<graph_type::iterator*>( &iter->user_data ) = i;
241 ASSERT_MESSAGE( iter->user_data != 0, "tree model error" );
244 static GType graph_tree_model_get_column_type( ui::TreeModel tree_model, gint index ){
245 ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
246 GraphTreeModel *graph_tree_model = (GraphTreeModel *) tree_model;
248 return G_TYPE_POINTER;
251 static gboolean graph_tree_model_get_iter( ui::TreeModel tree_model, GtkTreeIter* iter, ui::TreePath path ){
252 ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
253 gint* indices = gtk_tree_path_get_indices( path );
254 gint depth = gtk_tree_path_get_depth( path );
256 g_return_val_if_fail( depth > 0, FALSE );
258 graph_type& graph = *GRAPH_TREE_MODEL( tree_model )->graph;
260 if ( graph.empty() ) {
265 GtkTreeIter* parent = 0;
267 for ( gint i = 0; i < depth; i++ )
269 if ( !gtk_tree_model_iter_nth_child( tree_model, iter, parent, indices[i] ) ) {
279 static ui::TreePath graph_tree_model_get_path( ui::TreeModel tree_model, GtkTreeIter* iter ){
280 ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
281 graph_type& graph = *GRAPH_TREE_MODEL( tree_model )->graph;
282 graph_type::iterator i = graph_iterator_read_tree_iter( iter );
284 auto path = ui::TreePath();
286 for ( std::size_t depth = ( *i ).first.get().size(); depth != 0; --depth )
288 std::size_t index = 0;
290 while ( i != graph.begin() && ( *i ).first.get().size() >= depth )
293 if ( ( *i ).first.get().size() == depth ) {
298 gtk_tree_path_prepend_index( path, index );
305 static void graph_tree_model_get_value( ui::TreeModel tree_model, GtkTreeIter *iter, gint column, GValue *value ){
306 ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
307 ASSERT_MESSAGE( column == 0 || column == 1, "tree model error" );
309 graph_type::iterator i = graph_iterator_read_tree_iter( iter );
311 g_value_init( value, G_TYPE_POINTER );
314 g_value_set_pointer( value, reinterpret_cast<gpointer>( ( *i ).first.get().top() ) );
317 g_value_set_pointer( value, reinterpret_cast<gpointer>( Instance_getSelectable( *( *i ).second ) ) );
321 static gboolean graph_tree_model_iter_next( ui::TreeModel tree_model, GtkTreeIter *iter ){
322 ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
323 graph_type& graph = *GRAPH_TREE_MODEL( tree_model )->graph;
324 graph_type::iterator i = graph_iterator_read_tree_iter( iter );
325 std::size_t depth = ( *i ).first.get().size();
329 while ( i != graph.end() && ( *i ).first.get().size() > depth )
334 if ( i == graph.end() || ( *i ).first.get().size() != depth ) {
338 graph_iterator_write_tree_iter( i, iter );
343 static gboolean graph_tree_model_iter_children( ui::TreeModel tree_model, GtkTreeIter *iter, GtkTreeIter *parent ){
344 ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
345 graph_type& graph = *GRAPH_TREE_MODEL( tree_model )->graph;
346 graph_type::iterator i = ( parent == 0 ) ? graph.begin() : graph_iterator_read_tree_iter( parent );
347 std::size_t depth = ( parent == 0 ) ? 1 : ( *i ).first.get().size() + 1;
353 if ( i != graph.end() && ( *i ).first.get().size() == depth ) {
354 graph_iterator_write_tree_iter( i, iter );
361 static gboolean graph_tree_model_iter_has_child( ui::TreeModel tree_model, GtkTreeIter *iter ){
362 ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
363 graph_type& graph = *GRAPH_TREE_MODEL( tree_model )->graph;
364 graph_type::iterator i = graph_iterator_read_tree_iter( iter );
365 std::size_t depth = ( *i ).first.get().size() + 1;
367 return ++i != graph.end() && ( *i ).first.get().size() == depth;
370 static gint graph_tree_model_iter_n_children( ui::TreeModel tree_model, GtkTreeIter *parent ){
371 ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
372 graph_type& graph = *GRAPH_TREE_MODEL( tree_model )->graph;
373 graph_type::iterator i = ( parent == 0 ) ? graph.begin() : graph_iterator_read_tree_iter( parent );
374 std::size_t depth = ( parent == 0 ) ? 1 : ( *i ).first.get().size() + 1;
381 while ( i != graph.end() && ( *i ).first.get().size() >= depth )
390 static gboolean graph_tree_model_iter_nth_child( ui::TreeModel tree_model, GtkTreeIter *iter, GtkTreeIter *parent, gint n ){
391 ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
392 graph_type& graph = *GRAPH_TREE_MODEL( tree_model )->graph;
393 graph_type::iterator i = ( parent == 0 ) ? graph.begin() : graph_iterator_read_tree_iter( parent );
394 std::size_t depth = ( parent == 0 ) ? 1 : ( *i ).first.get().size() + 1;
400 while ( i != graph.end() && ( *i ).first.get().size() >= depth )
402 if ( ( *i ).first.get().size() == depth && n-- == 0 ) {
403 graph_iterator_write_tree_iter( i, iter );
412 static gboolean graph_tree_model_iter_parent( ui::TreeModel tree_model, GtkTreeIter *iter, GtkTreeIter *child ){
413 ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
414 graph_type& graph = *GRAPH_TREE_MODEL( tree_model )->graph;
415 graph_type::iterator i = graph_iterator_read_tree_iter( child );
416 std::size_t depth = ( *i ).first.get().size();
426 while ( ( *i ).first.get().size() >= depth );
427 graph_iterator_write_tree_iter( i, iter );
432 static GObjectClass *g_parent_class = 0;
434 static void graph_tree_model_init( GraphTreeModel *graph_tree_model ){
435 graph_tree_model->graph = 0;
438 static void graph_tree_model_finalize( GObject* object ){
439 GraphTreeModel* graph_tree_model = GRAPH_TREE_MODEL( object );
442 ( *g_parent_class->finalize )( object );
445 static void graph_tree_model_class_init( GraphTreeModelClass *class_ ){
446 GObjectClass *object_class;
448 g_parent_class = (GObjectClass*)g_type_class_peek_parent( class_ );
449 object_class = (GObjectClass *) class_;
451 object_class->finalize = graph_tree_model_finalize;
454 static void graph_tree_model_tree_model_init( GtkTreeModelIface *iface ){
455 iface->get_flags = graph_tree_model_get_flags;
456 iface->get_n_columns = graph_tree_model_get_n_columns;
457 iface->get_column_type = graph_tree_model_get_column_type;
458 iface->get_iter = graph_tree_model_get_iter;
459 iface->get_path = graph_tree_model_get_path;
460 iface->get_value = graph_tree_model_get_value;
461 iface->iter_next = graph_tree_model_iter_next;
462 iface->iter_children = graph_tree_model_iter_children;
463 iface->iter_has_child = graph_tree_model_iter_has_child;
464 iface->iter_n_children = graph_tree_model_iter_n_children;
465 iface->iter_nth_child = graph_tree_model_iter_nth_child;
466 iface->iter_parent = graph_tree_model_iter_parent;
469 static gboolean graph_tree_model_row_draggable( GtkTreeDragSource *drag_source, ui::TreePath path ){
471 gint depth = gtk_tree_path_get_depth( path );
473 return gtk_tree_path_get_depth( path ) > 1;
476 static gboolean graph_tree_model_drag_data_delete( GtkTreeDragSource *drag_source, ui::TreePath path ){
479 if ( gtk_tree_model_get_iter( drag_source, &iter, path ) ) {
480 graph_type::iterator i = graph_iterator_read_tree_iter( &iter );
481 Path_deleteTop( ( *i ).first );
490 static gboolean graph_tree_model_drag_data_get( GtkTreeDragSource *drag_source, ui::TreePath path, GtkSelectionData *selection_data ){
491 if ( gtk_tree_set_row_drag_data( selection_data, drag_source, path ) ) {
496 /* FIXME handle text targets at least. */
502 static void graph_tree_model_drag_source_init( GtkTreeDragSourceIface *iface ){
503 iface->row_draggable = graph_tree_model_row_draggable;
504 iface->drag_data_delete = graph_tree_model_drag_data_delete;
505 iface->drag_data_get = graph_tree_model_drag_data_get;
508 static gboolean graph_tree_model_drag_data_received( GtkTreeDragDest *drag_dest, ui::TreePath dest, GtkSelectionData *selection_data ){
509 auto tree_model = drag_dest;
511 GtkTreeModel *src_model = 0;
512 GtkTreePath *src_path = 0;
513 if ( gtk_tree_get_row_drag_data( selection_data, &src_model, &src_path )
514 && src_model == tree_model ) {
515 /* Copy the given row to a new position */
518 if ( gtk_tree_model_get_iter( src_model, &iter, src_path ) ) {
524 /* FIXME maybe add some data targets eventually, or handle text
525 * targets in the simple case.
532 static gboolean graph_tree_model_row_drop_possible( GtkTreeDragDest *drag_dest, ui::TreePath dest_path, GtkSelectionData *selection_data ){
533 gboolean retval = FALSE;
535 GtkTreeModel *src_model = 0;
536 GtkTreePath *src_path = 0;
537 if ( gtk_tree_get_row_drag_data( selection_data, &src_model, &src_path ) != FALSE ) {
538 /* can only drag to ourselves */
539 if ( src_model == drag_dest ) {
540 /* Can't drop into ourself. */
541 if ( !gtk_tree_path_is_ancestor( src_path, dest_path ) ) {
542 /* Can't drop if dest_path's parent doesn't exist */
543 if ( gtk_tree_path_get_depth( dest_path ) > 1 ) {
544 auto tmp = gtk_tree_path_copy( dest_path );
545 gtk_tree_path_up( tmp );
548 retval = gtk_tree_model_get_iter( drag_dest, &iter, tmp );
550 gtk_tree_path_free( tmp );
555 gtk_tree_path_free( src_path );
561 static void graph_tree_model_drag_dest_init( GtkTreeDragDestIface *iface ){
562 iface->drag_data_received = graph_tree_model_drag_data_received;
563 iface->row_drop_possible = graph_tree_model_row_drop_possible;
566 GType graph_tree_model_get_type( void ){
567 static GType graph_tree_model_type = 0;
569 if ( !graph_tree_model_type ) {
570 static const GTypeInfo graph_tree_model_info =
572 sizeof( GraphTreeModelClass ),
574 0, /* base_finalize */
575 (GClassInitFunc) graph_tree_model_class_init,
576 0, /* class_finalize */
578 sizeof( GraphTreeModel ),
580 (GInstanceInitFunc) graph_tree_model_init
583 static const GInterfaceInfo tree_model_info =
585 (GInterfaceInitFunc) graph_tree_model_tree_model_init,
590 static const GInterfaceInfo drag_source_info =
592 (GInterfaceInitFunc) graph_tree_model_drag_source_init,
597 static const GInterfaceInfo drag_dest_info =
599 (GInterfaceInitFunc) graph_tree_model_drag_dest_init,
604 graph_tree_model_type = g_type_register_static( G_TYPE_OBJECT, "GraphTreeModel",
605 &graph_tree_model_info, (GTypeFlags)0 );
607 g_type_add_interface_static( graph_tree_model_type,
610 g_type_add_interface_static( graph_tree_model_type,
611 GTK_TYPE_TREE_DRAG_SOURCE,
613 g_type_add_interface_static( graph_tree_model_type,
614 GTK_TYPE_TREE_DRAG_DEST,
618 return graph_tree_model_type;
621 GraphTreeModel* graph_tree_model_new(){
622 GraphTreeModel* graph_tree_model = GRAPH_TREE_MODEL( g_object_new( graph_tree_model_get_type(), 0 ) );
624 graph_tree_model->graph = new graph_type;
626 return graph_tree_model;
629 void graph_tree_model_delete( GraphTreeModel* model ){
631 g_object_unref( G_OBJECT( model ) );
635 class TempNameable : public Nameable
639 TempNameable( const char* name ) : m_name( name ){
641 const char* name() const {
644 void attach( const NameCallback& callback ){
646 void detach( const NameCallback& callback ){
650 void node_attach_name_changed_callback( scene::Node& node, const NameCallback& callback ){
651 // Reference cannot be bound to dereferenced null pointer in well-defined
652 // C++ code, and Clang will assume that comparison below always evaluates
653 // to true, resulting in a segmentation fault. Use a dirty hack to force
654 // Clang to check those "bad" references for null nonetheless.
655 volatile intptr_t n = (intptr_t)&node;
658 Nameable* nameable = Node_getNameable( node );
659 if ( nameable != 0 ) {
660 nameable->attach( callback );
664 void node_detach_name_changed_callback( scene::Node& node, const NameCallback& callback ){
665 volatile intptr_t n = (intptr_t)&node; // see the comment on line 650
668 Nameable* nameable = Node_getNameable( node );
669 if ( nameable != 0 ) {
670 nameable->detach( callback );
675 GraphTreeModel* scene_graph_get_tree_model(); // temp hack
677 void graph_tree_model_row_inserted( GraphTreeModel* model, graph_type::iterator i ){
679 graph_iterator_write_tree_iter( i, &iter );
681 auto tree_path = graph_tree_model_get_path( model, &iter );
683 gint depth = gtk_tree_path_get_depth( tree_path );
684 gint* indices = gtk_tree_path_get_indices( tree_path );
686 gtk_tree_model_row_inserted( model, tree_path, &iter );
688 gtk_tree_path_free( tree_path );
691 void graph_tree_model_row_deleted( GraphTreeModel* model, graph_type::iterator i ){
693 graph_iterator_write_tree_iter( i, &iter );
695 auto tree_path = graph_tree_model_get_path( model, &iter );
697 gtk_tree_model_row_deleted( model, tree_path );
699 gtk_tree_path_free( tree_path );
702 #include "generic/referencecounted.h"
704 void graph_tree_model_set_name( const scene::Instance& instance, const char* name ){
705 GraphTreeModel* model = scene_graph_get_tree_model();
707 if ( string_empty( name ) ) { // hack!
708 graph_type::iterator i = model->graph->find( PathConstReference( instance.path() ) );
709 ASSERT_MESSAGE( i != model->graph->end(), "ERROR" );
711 graph_tree_model_row_deleted( model, i );
713 model->graph->erase( i );
717 graph_type::iterator i = model->graph->insert( graph_type::value_type( PathConstReference( instance.path() ), &const_cast<scene::Instance&>( instance ) ) ).first;
719 graph_tree_model_row_inserted( model, i );
723 void graph_tree_model_insert( GraphTreeModel* model, const scene::Instance& instance ){
724 graph_type::iterator i = model->graph->insert( graph_type::value_type( PathConstReference( instance.path() ), &const_cast<scene::Instance&>( instance ) ) ).first;
726 graph_tree_model_row_inserted( model, i );
728 node_attach_name_changed_callback( instance.path().top(), ConstReferenceCaller<scene::Instance, void(const char*), graph_tree_model_set_name>( instance ) );
731 void graph_tree_model_erase( GraphTreeModel* model, const scene::Instance& instance ){
732 node_detach_name_changed_callback( instance.path().top(), ConstReferenceCaller<scene::Instance, void(const char*), graph_tree_model_set_name>( instance ) );
734 graph_type::iterator i = model->graph->find( PathConstReference( instance.path() ) );
735 ASSERT_MESSAGE( i != model->graph->end(), "ERROR" );
737 graph_tree_model_row_deleted( model, i );
739 model->graph->erase( i );
746 void graph_tree_model_row_changed(GraphTreeNode &node);
748 class GraphTreeNode {
749 typedef std::map<std::pair<CopiedString, scene::Node *>, GraphTreeNode *> ChildNodes;
750 ChildNodes m_childnodes;
752 Reference<scene::Instance> m_instance;
753 GraphTreeNode *m_parent;
755 typedef ChildNodes::iterator iterator;
756 typedef ChildNodes::key_type key_type;
757 typedef ChildNodes::value_type value_type;
758 typedef ChildNodes::size_type size_type;
760 GraphTreeNode(scene::Instance &instance) : m_instance(instance), m_parent(0)
762 m_instance.get().setChildSelectedChangedCallback(RowChangedCaller(*this));
767 m_instance.get().setChildSelectedChangedCallback(Callback<void()>());
768 ASSERT_MESSAGE(empty(), "GraphTreeNode::~GraphTreeNode: memory leak");
773 return m_childnodes.begin();
778 return m_childnodes.end();
781 size_type size() const
783 return m_childnodes.size();
788 return m_childnodes.empty();
791 iterator insert(const value_type &value)
793 iterator i = m_childnodes.insert(value).first;
794 (*i).second->m_parent = this;
798 void erase(iterator i)
800 m_childnodes.erase(i);
803 iterator find(const key_type &key)
805 return m_childnodes.find(key);
808 void swap(GraphTreeNode &other)
810 std::swap(m_parent, other.m_parent);
811 std::swap(m_childnodes, other.m_childnodes);
812 std::swap(m_instance, other.m_instance);
817 graph_tree_model_row_changed(*this);
820 typedef MemberCaller<GraphTreeNode, void(), &GraphTreeNode::rowChanged> RowChangedCaller;
823 struct GraphTreeModel {
826 GraphTreeNode *m_graph;
829 struct GraphTreeModelClass {
830 GObjectClass parent_class;
833 static GtkTreeModelFlags graph_tree_model_get_flags(ui::TreeModel tree_model)
835 return GTK_TREE_MODEL_ITERS_PERSIST;
838 static gint graph_tree_model_get_n_columns(ui::TreeModel tree_model)
840 ASSERT_MESSAGE(tree_model, "RUNTIME ERROR");
841 //GraphTreeModel* graph_tree_model = (GraphTreeModel*) tree_model;
846 static const gint c_stamp = 0xabcdef;
848 inline GraphTreeNode::iterator graph_iterator_read_tree_iter(GtkTreeIter *iter)
850 ASSERT_MESSAGE(iter != 0, "tree model error");
851 ASSERT_MESSAGE(iter->user_data != 0, "tree model error");
852 ASSERT_MESSAGE(iter->stamp == c_stamp, "tree model error");
853 return *reinterpret_cast<GraphTreeNode::iterator *>( &iter->user_data );
856 inline void graph_iterator_write_tree_iter(GraphTreeNode::iterator i, GtkTreeIter *iter)
858 ASSERT_MESSAGE(iter != 0, "tree model error");
859 iter->stamp = c_stamp;
860 *reinterpret_cast<GraphTreeNode::iterator *>( &iter->user_data ) = i;
861 ASSERT_MESSAGE(iter->user_data != 0, "tree model error");
864 static GType graph_tree_model_get_column_type(ui::TreeModel tree_model, gint index)
866 ASSERT_MESSAGE(tree_model, "RUNTIME ERROR");
867 //GraphTreeModel *graph_tree_model = (GraphTreeModel *) tree_model;
869 return G_TYPE_POINTER;
872 static gboolean graph_tree_model_get_iter(GraphTreeModel *tree_model, GtkTreeIter *iter, ui::TreePath path)
874 ASSERT_MESSAGE(tree_model != 0, "RUNTIME ERROR");
875 gint *indices = gtk_tree_path_get_indices(path);
876 gint depth = gtk_tree_path_get_depth(path);
878 g_return_val_if_fail(depth > 0, FALSE);
880 GraphTreeNode *graph = tree_model->m_graph;
882 if (graph->empty()) {
887 GtkTreeIter *parent = 0;
889 for (gint i = 0; i < depth; i++) {
890 if (!gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(tree_model), iter, parent, indices[i])) {
900 static ui::TreePath graph_tree_model_get_path(GraphTreeModel *tree_model, GtkTreeIter *iter)
902 ASSERT_MESSAGE(tree_model, "RUNTIME ERROR");
903 GraphTreeNode *graph = tree_model->m_graph;
905 auto path = ui::TreePath(ui::New);
907 for (GraphTreeNode *node = (*graph_iterator_read_tree_iter(iter)).second; node != graph; node = node->m_parent) {
908 std::size_t index = 0;
909 for (GraphTreeNode::iterator i = node->m_parent->begin(); i != node->m_parent->end(); ++i, ++index) {
910 if ((*i).second == node) {
911 gtk_tree_path_prepend_index(path, gint(index));
915 ASSERT_MESSAGE(index != node->m_parent->size(), "error resolving tree path");
922 static void graph_tree_model_get_value(ui::TreeModel tree_model, GtkTreeIter *iter, gint column, GValue *value)
924 ASSERT_MESSAGE(tree_model, "RUNTIME ERROR");
925 ASSERT_MESSAGE(column == 0 || column == 1, "tree model error");
927 GraphTreeNode::iterator i = graph_iterator_read_tree_iter(iter);
929 g_value_init(value, G_TYPE_POINTER);
932 g_value_set_pointer(value, reinterpret_cast<gpointer>((*i).first.second ));
934 g_value_set_pointer(value, reinterpret_cast<gpointer>( &(*i).second->m_instance.get()));
938 static gboolean graph_tree_model_iter_next(ui::TreeModel tree_model, GtkTreeIter *iter)
940 ASSERT_MESSAGE(tree_model, "RUNTIME ERROR");
941 GraphTreeNode::iterator i = graph_iterator_read_tree_iter(iter);
942 GraphTreeNode &parent = *(*i).second->m_parent;
944 ASSERT_MESSAGE(i != parent.end(), "RUNTIME ERROR");
946 if (++i == parent.end()) {
950 graph_iterator_write_tree_iter(i, iter);
955 static gboolean graph_tree_model_iter_children(GraphTreeModel *tree_model, GtkTreeIter *iter, GtkTreeIter *parent)
957 ASSERT_MESSAGE(tree_model != 0, "RUNTIME ERROR");
958 GraphTreeNode &node = (parent == 0) ? *tree_model->m_graph : *(*graph_iterator_read_tree_iter(parent)).second;
960 graph_iterator_write_tree_iter(node.begin(), iter);
967 static gboolean graph_tree_model_iter_has_child(ui::TreeModel tree_model, GtkTreeIter *iter)
969 ASSERT_MESSAGE(tree_model, "RUNTIME ERROR");
970 GraphTreeNode &node = *(*graph_iterator_read_tree_iter(iter)).second;
971 return !node.empty();
974 static gint graph_tree_model_iter_n_children(GraphTreeModel *tree_model, GtkTreeIter *parent)
976 ASSERT_MESSAGE(tree_model != 0, "RUNTIME ERROR");
977 GraphTreeNode &node = (parent == 0) ? *tree_model->m_graph : *(*graph_iterator_read_tree_iter(parent)).second;
978 return static_cast<gint>( node.size());
982 graph_tree_model_iter_nth_child(GraphTreeModel *tree_model, GtkTreeIter *iter, GtkTreeIter *parent, gint n)
984 ASSERT_MESSAGE(tree_model != 0, "RUNTIME ERROR");
985 GraphTreeNode &node = (parent == 0) ? *tree_model->m_graph : *(*graph_iterator_read_tree_iter(parent)).second;
986 if (static_cast<std::size_t>( n ) < node.size()) {
987 GraphTreeNode::iterator i = node.begin();
989 graph_iterator_write_tree_iter(i, iter);
996 static gboolean graph_tree_model_iter_parent(GraphTreeModel *tree_model, GtkTreeIter *iter, GtkTreeIter *child)
998 ASSERT_MESSAGE(tree_model != 0, "RUNTIME ERROR");
999 GraphTreeNode &node = *(*graph_iterator_read_tree_iter(child)).second;
1000 if (node.m_parent != tree_model->m_graph) {
1001 GraphTreeNode &parentParent = *node.m_parent->m_parent;
1002 for (GraphTreeNode::iterator i = parentParent.begin(); i != parentParent.end(); ++i) {
1003 if ((*i).second == node.m_parent) {
1004 graph_iterator_write_tree_iter(i, iter);
1012 static GObjectClass *g_parent_class = 0;
1015 scene::Node *g_null_node = 0;
1018 class NullInstance : public scene::Instance {
1020 NullInstance() : scene::Instance(scene::Path(makeReference(*g_null_node)), 0, 0,
1021 Static<InstanceTypeCastTable>::instance())
1027 NullInstance g_null_instance;
1030 static void graph_tree_model_init(GraphTreeModel *graph_tree_model)
1032 graph_tree_model->m_graph = new GraphTreeNode(g_null_instance);
1035 static void graph_tree_model_finalize(GObject *object)
1037 auto graph_tree_model = reinterpret_cast<GraphTreeModel *>(object);
1039 delete graph_tree_model->m_graph;
1042 (*g_parent_class->finalize)(object);
1045 static void graph_tree_model_class_init(GraphTreeModelClass *class_)
1047 GObjectClass *object_class;
1049 g_parent_class = (GObjectClass *) g_type_class_peek_parent(class_);
1050 object_class = (GObjectClass *) class_;
1052 object_class->finalize = graph_tree_model_finalize;
1055 static void graph_tree_model_tree_model_init(GtkTreeModelIface *iface)
1057 iface->get_flags = reinterpret_cast<GtkTreeModelFlags (*)(GtkTreeModel *)>(graph_tree_model_get_flags);
1058 iface->get_n_columns = reinterpret_cast<gint (*)(GtkTreeModel *)>(graph_tree_model_get_n_columns);
1059 iface->get_column_type = reinterpret_cast<GType (*)(GtkTreeModel *, gint)>(graph_tree_model_get_column_type);
1060 iface->get_iter = reinterpret_cast<gboolean (*)(GtkTreeModel *, GtkTreeIter *,
1061 GtkTreePath *)>(graph_tree_model_get_iter);
1062 iface->get_path = reinterpret_cast<GtkTreePath *(*)(GtkTreeModel *, GtkTreeIter *)>(graph_tree_model_get_path);
1063 iface->get_value = reinterpret_cast<void (*)(GtkTreeModel *, GtkTreeIter *, gint,
1064 GValue *)>(graph_tree_model_get_value);
1065 iface->iter_next = reinterpret_cast<gboolean (*)(GtkTreeModel *, GtkTreeIter *)>(graph_tree_model_iter_next);
1066 iface->iter_children = reinterpret_cast<gboolean (*)(GtkTreeModel *, GtkTreeIter *,
1067 GtkTreeIter *)>(graph_tree_model_iter_children);
1068 iface->iter_has_child = reinterpret_cast<gboolean (*)(GtkTreeModel *,
1069 GtkTreeIter *)>(graph_tree_model_iter_has_child);
1070 iface->iter_n_children = reinterpret_cast<gint (*)(GtkTreeModel *,
1071 GtkTreeIter *)>(graph_tree_model_iter_n_children);
1072 iface->iter_nth_child = reinterpret_cast<gboolean (*)(GtkTreeModel *, GtkTreeIter *, GtkTreeIter *,
1073 gint)>(graph_tree_model_iter_nth_child);
1074 iface->iter_parent = reinterpret_cast<gboolean (*)(GtkTreeModel *, GtkTreeIter *,
1075 GtkTreeIter *)>(graph_tree_model_iter_parent);
1078 GType graph_tree_model_get_type(void)
1080 static GType graph_tree_model_type = 0;
1082 if (!graph_tree_model_type) {
1083 static const GTypeInfo graph_tree_model_info =
1085 sizeof(GraphTreeModelClass),
1087 0, /* base_finalize */
1088 (GClassInitFunc) graph_tree_model_class_init,
1089 0, /* class_finalize */
1091 sizeof(GraphTreeModel),
1092 0, /* n_preallocs */
1093 (GInstanceInitFunc) graph_tree_model_init,
1097 static const GInterfaceInfo tree_model_info =
1099 (GInterfaceInitFunc) graph_tree_model_tree_model_init,
1104 graph_tree_model_type = g_type_register_static(G_TYPE_OBJECT, "GraphTreeModel",
1105 &graph_tree_model_info, (GTypeFlags) 0);
1107 g_type_add_interface_static(graph_tree_model_type,
1108 GTK_TYPE_TREE_MODEL,
1112 return graph_tree_model_type;
1115 GraphTreeModel *graph_tree_model_new()
1117 auto graph_tree_model = reinterpret_cast<GraphTreeModel *>(g_object_new(graph_tree_model_get_type(), 0));
1119 return graph_tree_model;
1122 void graph_tree_model_delete(GraphTreeModel *model)
1124 g_object_unref(G_OBJECT(model));
1127 void graph_tree_model_row_changed(GraphTreeModel *model, GraphTreeNode::iterator i)
1130 graph_iterator_write_tree_iter(i, &iter);
1132 auto tree_path = graph_tree_model_get_path(model, &iter);
1134 gtk_tree_model_row_changed(GTK_TREE_MODEL(model), tree_path, &iter);
1136 gtk_tree_path_free(tree_path);
1139 void graph_tree_model_row_inserted(GraphTreeModel *model, GraphTreeNode::iterator i)
1142 graph_iterator_write_tree_iter(i, &iter);
1144 auto tree_path = graph_tree_model_get_path(model, &iter);
1146 gtk_tree_model_row_inserted(GTK_TREE_MODEL(model), tree_path, &iter);
1148 gtk_tree_path_free(tree_path);
1151 void graph_tree_model_row_deleted(GraphTreeModel *model, GraphTreeNode::iterator i)
1154 graph_iterator_write_tree_iter(i, &iter);
1156 auto tree_path = graph_tree_model_get_path(model, &iter);
1158 gtk_tree_model_row_deleted(GTK_TREE_MODEL(model), tree_path);
1160 gtk_tree_path_free(tree_path);
1163 void graph_tree_model_row_inserted(GraphTreeModel &model, GraphTreeNode::iterator i)
1165 graph_tree_model_row_inserted(&model, i);
1168 void graph_tree_model_row_deleted(GraphTreeModel &model, GraphTreeNode::iterator i)
1170 graph_tree_model_row_deleted(&model, i);
1173 const char *node_get_name(scene::Node &node);
1175 const char *node_get_name_safe(scene::Node &node)
1177 volatile intptr_t n = (intptr_t) &node; // see the comment on line 650
1181 return node_get_name(node);
1184 GraphTreeNode *graph_tree_model_find_parent(GraphTreeModel *model, const scene::Path &path)
1186 GraphTreeNode *parent = model->m_graph;
1187 for (scene::Path::const_iterator i = path.begin(); i != path.end() - 1; ++i) {
1188 GraphTreeNode::iterator child = parent->find(
1189 GraphTreeNode::key_type(node_get_name_safe((*i).get()), (*i).get_pointer()));
1190 ASSERT_MESSAGE(child != parent->end(), "ERROR");
1191 parent = (*child).second;
1196 void node_attach_name_changed_callback(scene::Node &node, const NameCallback &callback)
1198 volatile intptr_t n = (intptr_t) &node; // see the comment on line 650
1200 Nameable *nameable = Node_getNameable(node);
1201 if (nameable != 0) {
1202 nameable->attach(callback);
1207 void node_detach_name_changed_callback(scene::Node &node, const NameCallback &callback)
1209 volatile intptr_t n = (intptr_t) &node; // see the comment on line 650
1211 Nameable *nameable = Node_getNameable(node);
1212 if (nameable != 0) {
1213 nameable->detach(callback);
1218 GraphTreeModel *scene_graph_get_tree_model(); // temp hack
1220 void graph_tree_node_foreach_pre(GraphTreeNode::iterator root, const Callback<void(GraphTreeNode::iterator)> &callback)
1223 for (GraphTreeNode::iterator i = (*root).second->begin(); i != (*root).second->end(); ++i) {
1224 graph_tree_node_foreach_pre(i, callback);
1228 void graph_tree_node_foreach_post(GraphTreeNode::iterator root, const Callback<void(GraphTreeNode::iterator)> &callback)
1230 for (GraphTreeNode::iterator i = (*root).second->begin(); i != (*root).second->end(); ++i) {
1231 graph_tree_node_foreach_post(i, callback);
1236 void graph_tree_model_row_changed(GraphTreeNode &node)
1238 GraphTreeModel *model = scene_graph_get_tree_model();
1239 const scene::Instance &instance = node.m_instance.get();
1241 GraphTreeNode::iterator i = node.m_parent->find(
1242 GraphTreeNode::key_type(node_get_name_safe(instance.path().top().get()),
1243 instance.path().top().get_pointer()));
1245 graph_tree_model_row_changed(model, i);
1248 void graph_tree_model_set_name(const scene::Instance &instance, const char *name)
1250 GraphTreeModel *model = scene_graph_get_tree_model();
1251 GraphTreeNode *parent = graph_tree_model_find_parent(model, instance.path());
1253 GraphTreeNode::iterator oldNode = parent->find(
1254 GraphTreeNode::key_type(node_get_name_safe(instance.path().top().get()),
1255 instance.path().top().get_pointer()));
1256 graph_tree_node_foreach_post(oldNode, ReferenceCaller<GraphTreeModel, void(
1257 GraphTreeNode::iterator), graph_tree_model_row_deleted>(*model));
1258 GraphTreeNode *node((*oldNode).second);
1259 parent->erase(oldNode);
1261 GraphTreeNode::iterator newNode = parent->insert(
1262 GraphTreeNode::value_type(GraphTreeNode::key_type(name, &instance.path().top().get()), node));
1263 graph_tree_node_foreach_pre(newNode, ReferenceCaller<GraphTreeModel, void(
1264 GraphTreeNode::iterator), graph_tree_model_row_inserted>(*model));
1267 void graph_tree_model_insert(GraphTreeModel *model, const scene::Instance &instance)
1269 GraphTreeNode *parent = graph_tree_model_find_parent(model, instance.path());
1271 GraphTreeNode::iterator i = parent->insert(GraphTreeNode::value_type(
1272 GraphTreeNode::key_type(node_get_name_safe(instance.path().top().get()),
1273 instance.path().top().get_pointer()),
1274 new GraphTreeNode(const_cast<scene::Instance &>( instance ))));
1276 graph_tree_model_row_inserted(model, i);
1278 node_attach_name_changed_callback(instance.path().top(), ConstReferenceCaller<scene::Instance, void(
1279 const char *), graph_tree_model_set_name>(instance));
1282 void graph_tree_model_erase(GraphTreeModel *model, const scene::Instance &instance)
1284 node_detach_name_changed_callback(instance.path().top(), ConstReferenceCaller<scene::Instance, void(
1285 const char *), graph_tree_model_set_name>(instance));
1287 GraphTreeNode *parent = graph_tree_model_find_parent(model, instance.path());
1289 GraphTreeNode::iterator i = parent->find(GraphTreeNode::key_type(node_get_name_safe(instance.path().top().get()),
1290 instance.path().top().get_pointer()));
1292 graph_tree_model_row_deleted(model, i);
1294 GraphTreeNode *node((*i).second);
1304 class TestGraphTreeModel
1307 TestGraphTreeModel(){
1312 scene::Node* root = *(scene::Node*)0xa0000000;
1313 scene::Node* node1 = (scene::Node*)0xa0000001;
1314 scene::Node* node2 = (scene::Node*)0xa0000002;
1315 scene::Node* node3 = (scene::Node*)0xa0000003;
1316 scene::Node* node4 = (scene::Node*)0xa0000004;
1317 scene::Instance* instance = (scene::Instance*)0xaaaaaaaa;
1319 scene::Path rootpath( root );
1321 graph.insert( graph_type::value_type( rootpath, instance ) );
1323 rootpath.push( node1 );
1324 graph.insert( graph_type::value_type( rootpath, instance ) );
1327 rootpath.push( node2 );
1328 graph.insert( graph_type::value_type( rootpath, instance ) );
1329 rootpath.push( node3 );
1330 graph.insert( graph_type::value_type( rootpath, instance ) );
1332 rootpath.push( node4 );
1333 graph.insert( graph_type::value_type( rootpath, instance ) );
1337 auto model = graph_tree_model_new( &graph );
1340 gint n_columns = gtk_tree_model_get_n_columns( model );
1341 ASSERT_MESSAGE( n_columns == 2, "test failed!" );
1345 GType type = gtk_tree_model_get_column_type( model, 0 );
1346 ASSERT_MESSAGE( type == G_TYPE_POINTER, "test failed!" );
1350 GType type = gtk_tree_model_get_column_type( model, 1 );
1351 ASSERT_MESSAGE( type == G_TYPE_POINTER, "test failed!" );
1357 gtk_tree_model_get_iter_first( model, &iter );
1359 graph_type::iterator i = graph_iterator_read_tree_iter( &iter );
1360 ASSERT_MESSAGE( ( *i ).first.get().size() == 2 && ( *i ).first.get().top() == node1, "test failed!" );
1365 gtk_tree_model_get_iter_first( model, &iter );
1367 ASSERT_MESSAGE( gtk_tree_model_iter_has_child( model, &iter ) == FALSE, "test failed!" );
1369 ASSERT_MESSAGE( gtk_tree_model_iter_n_children( model, &iter ) == 0, "test failed!" );
1371 gtk_tree_model_iter_next( model, &iter );
1373 ASSERT_MESSAGE( gtk_tree_model_iter_has_child( model, &iter ) != FALSE, "test failed!" );
1375 ASSERT_MESSAGE( gtk_tree_model_iter_n_children( model, &iter ) == 2, "test failed!" );
1379 gtk_tree_model_iter_nth_child( model, &child, &iter, 0 );
1382 gtk_tree_model_get_value( model, &child, 0, (GValue*)&test );
1383 ASSERT_MESSAGE( test == node3, "test failed!" );
1387 gtk_tree_model_iter_parent( model, &parent, &child );
1390 gtk_tree_model_get_value( model, &parent, 0, (GValue*)&test );
1391 ASSERT_MESSAGE( test == node2, "test failed!" );
1397 gtk_tree_model_iter_nth_child( model, &child, &iter, 1 );
1400 gtk_tree_model_get_value( model, &child, 0, (GValue*)&test );
1401 ASSERT_MESSAGE( test == node4, "test failed!" );
1407 std::size_t count = 0;
1408 for ( gboolean good = gtk_tree_model_get_iter_first( model, &iter ); good; good = gtk_tree_model_iter_next( model, &iter ) )
1411 gtk_tree_model_get_value( model, &iter, 0, (GValue*)&test );
1413 ASSERT_MESSAGE( ( count == 0 && test == node1 ) || ( count == 1 && test == node2 ), "test failed!" );
1417 ASSERT_MESSAGE( count == 2, "test failed!" );
1423 gtk_tree_model_get_iter_first( model, &iter );
1426 gtk_tree_model_get_value( model, &iter, 0, (GValue*)&test );
1427 ASSERT_MESSAGE( test == node1, "test failed!" );
1432 auto path = ui::TreePath( "0" );
1433 gtk_tree_model_get_iter( model, &iter, path );
1434 gtk_tree_path_free( path );
1436 graph_type::iterator i = graph_iterator_read_tree_iter( &iter );
1437 ASSERT_MESSAGE( ( *i ).first.get().size() == 2 && ( *i ).first.get().top() == node1, "test failed!" );
1442 auto path = ui::TreePath( "1" );
1443 gtk_tree_model_get_iter( model, &iter, path );
1444 gtk_tree_path_free( path );
1446 graph_type::iterator i = graph_iterator_read_tree_iter( &iter );
1447 ASSERT_MESSAGE( ( *i ).first.get().size() == 2 && ( *i ).first.get().top() == node2, "test failed!" );
1452 graph_type::iterator i = graph.begin();
1454 graph_iterator_write_tree_iter( i, &iter );
1456 auto path = gtk_tree_model_get_path( model, &iter );
1458 gint depth = gtk_tree_path_get_depth( path );
1459 gint* indices = gtk_tree_path_get_indices( path );
1461 ASSERT_MESSAGE( depth == 1 && indices[0] == 0, "test failed!" );
1463 gtk_tree_path_free( path );
1468 graph_type::iterator i = graph.begin();
1471 graph_iterator_write_tree_iter( i, &iter );
1473 auto path = gtk_tree_model_get_path( model, &iter );
1475 gint depth = gtk_tree_path_get_depth( path );
1476 gint* indices = gtk_tree_path_get_indices( path );
1478 ASSERT_MESSAGE( depth == 1 && indices[0] == 1, "test failed!" );
1480 gtk_tree_path_free( path );
1486 TestGraphTreeModel g_TestGraphTreeModel;