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"
27 #include <gtk/gtktreemodel.h>
28 #include <gtk/gtktreednd.h>
29 #include <gtk/gtkmain.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 ){
40 return NodeTypeCast<Nameable>::cast( node );
44 void graph_tree_model_row_changed( GraphTreeNode& node );
48 typedef std::map<std::pair<CopiedString, scene::Node*>, GraphTreeNode*> ChildNodes;
49 ChildNodes m_childnodes;
51 Reference<scene::Instance> m_instance;
52 GraphTreeNode* m_parent;
54 typedef ChildNodes::iterator iterator;
55 typedef ChildNodes::key_type key_type;
56 typedef ChildNodes::value_type value_type;
57 typedef ChildNodes::size_type size_type;
59 GraphTreeNode( scene::Instance& instance ) : m_instance( instance ), m_parent( 0 ){
60 m_instance.get().setChildSelectedChangedCallback( RowChangedCaller( *this ) );
63 m_instance.get().setChildSelectedChangedCallback( Callback() );
64 ASSERT_MESSAGE( empty(), "GraphTreeNode::~GraphTreeNode: memory leak" );
68 return m_childnodes.begin();
71 return m_childnodes.end();
74 size_type size() const {
75 return m_childnodes.size();
78 return m_childnodes.empty();
81 iterator insert( const value_type& value ){
82 iterator i = m_childnodes.insert( value ).first;
83 ( *i ).second->m_parent = this;
86 void erase( iterator i ){
87 m_childnodes.erase( i );
89 iterator find( const key_type& key ){
90 return m_childnodes.find( key );
93 void swap( GraphTreeNode& other ){
94 std::swap( m_parent, other.m_parent );
95 std::swap( m_childnodes, other.m_childnodes );
96 std::swap( m_instance, other.m_instance );
100 graph_tree_model_row_changed( *this );
102 typedef MemberCaller<GraphTreeNode, &GraphTreeNode::rowChanged> RowChangedCaller;
105 struct GraphTreeModel
109 GraphTreeNode* m_graph;
112 struct GraphTreeModelClass
114 GObjectClass parent_class;
117 #define GRAPH_TREE_MODEL( p ) ( reinterpret_cast<GraphTreeModel*>( p ) )
119 static GtkTreeModelFlags graph_tree_model_get_flags( GtkTreeModel* tree_model ){
120 return GTK_TREE_MODEL_ITERS_PERSIST;
123 static gint graph_tree_model_get_n_columns( GtkTreeModel* tree_model ){
124 ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
125 //GraphTreeModel* graph_tree_model = (GraphTreeModel*) tree_model;
130 static const gint c_stamp = 0xabcdef;
132 inline GraphTreeNode::iterator graph_iterator_read_tree_iter( GtkTreeIter* iter ){
133 ASSERT_MESSAGE( iter != 0, "tree model error" );
134 ASSERT_MESSAGE( iter->user_data != 0, "tree model error" );
135 ASSERT_MESSAGE( iter->stamp == c_stamp, "tree model error" );
136 return *reinterpret_cast<GraphTreeNode::iterator*>( &iter->user_data );
139 inline void graph_iterator_write_tree_iter( GraphTreeNode::iterator i, GtkTreeIter* iter ){
140 ASSERT_MESSAGE( iter != 0, "tree model error" );
141 iter->stamp = c_stamp;
142 *reinterpret_cast<GraphTreeNode::iterator*>( &iter->user_data ) = i;
143 ASSERT_MESSAGE( iter->user_data != 0, "tree model error" );
146 static GType graph_tree_model_get_column_type( GtkTreeModel *tree_model, gint index ){
147 ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
148 //GraphTreeModel *graph_tree_model = (GraphTreeModel *) tree_model;
150 return G_TYPE_POINTER;
153 static gboolean graph_tree_model_get_iter( GtkTreeModel* tree_model, GtkTreeIter* iter, GtkTreePath* path ){
154 ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
155 gint* indices = gtk_tree_path_get_indices( path );
156 gint depth = gtk_tree_path_get_depth( path );
158 g_return_val_if_fail( depth > 0, FALSE );
160 GraphTreeNode* graph = GRAPH_TREE_MODEL( tree_model )->m_graph;
162 if ( graph->empty() ) {
167 GtkTreeIter* parent = 0;
169 for ( gint i = 0; i < depth; i++ )
171 if ( !gtk_tree_model_iter_nth_child( tree_model, iter, parent, indices[i] ) ) {
181 static GtkTreePath* graph_tree_model_get_path( GtkTreeModel* tree_model, GtkTreeIter* iter ){
182 ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
183 GraphTreeNode* graph = GRAPH_TREE_MODEL( tree_model )->m_graph;
185 GtkTreePath* path = gtk_tree_path_new();
187 for ( GraphTreeNode* node = ( *graph_iterator_read_tree_iter( iter ) ).second; node != graph; node = node->m_parent )
189 std::size_t index = 0;
190 for ( GraphTreeNode::iterator i = node->m_parent->begin(); i != node->m_parent->end(); ++i, ++index )
192 if ( ( *i ).second == node ) {
193 gtk_tree_path_prepend_index( path, gint( index ) );
197 ASSERT_MESSAGE( index != node->m_parent->size(), "error resolving tree path" );
204 static void graph_tree_model_get_value( GtkTreeModel *tree_model, GtkTreeIter *iter, gint column, GValue *value ){
205 ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
206 ASSERT_MESSAGE( column == 0 || column == 1, "tree model error" );
208 GraphTreeNode::iterator i = graph_iterator_read_tree_iter( iter );
210 g_value_init( value, G_TYPE_POINTER );
213 g_value_set_pointer( value, reinterpret_cast<gpointer>( ( *i ).first.second ) );
217 g_value_set_pointer( value, reinterpret_cast<gpointer>( &( *i ).second->m_instance.get() ) );
221 static gboolean graph_tree_model_iter_next( GtkTreeModel *tree_model, GtkTreeIter *iter ){
222 ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
223 GraphTreeNode::iterator i = graph_iterator_read_tree_iter( iter );
224 GraphTreeNode& parent = *( *i ).second->m_parent;
226 ASSERT_MESSAGE( i != parent.end(), "RUNTIME ERROR" );
228 if ( ++i == parent.end() ) {
232 graph_iterator_write_tree_iter( i, iter );
237 static gboolean graph_tree_model_iter_children( GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreeIter *parent ){
238 ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
239 GraphTreeNode& node = ( parent == 0 ) ? *GRAPH_TREE_MODEL( tree_model )->m_graph : *( *graph_iterator_read_tree_iter( parent ) ).second;
240 if ( !node.empty() ) {
241 graph_iterator_write_tree_iter( node.begin(), iter );
248 static gboolean graph_tree_model_iter_has_child( GtkTreeModel *tree_model, GtkTreeIter *iter ){
249 ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
250 GraphTreeNode& node = *( *graph_iterator_read_tree_iter( iter ) ).second;
251 return !node.empty();
254 static gint graph_tree_model_iter_n_children( GtkTreeModel *tree_model, GtkTreeIter *parent ){
255 ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
256 GraphTreeNode& node = ( parent == 0 ) ? *GRAPH_TREE_MODEL( tree_model )->m_graph : *( *graph_iterator_read_tree_iter( parent ) ).second;
257 return static_cast<gint>( node.size() );
260 static gboolean graph_tree_model_iter_nth_child( GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreeIter *parent, gint n ){
261 ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
262 GraphTreeNode& node = ( parent == 0 ) ? *GRAPH_TREE_MODEL( tree_model )->m_graph : *( *graph_iterator_read_tree_iter( parent ) ).second;
263 if ( static_cast<std::size_t>( n ) < node.size() ) {
264 GraphTreeNode::iterator i = node.begin();
265 std::advance( i, n );
266 graph_iterator_write_tree_iter( i, iter );
273 static gboolean graph_tree_model_iter_parent( GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreeIter *child ){
274 ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
275 GraphTreeNode& node = *( *graph_iterator_read_tree_iter( child ) ).second;
276 if ( node.m_parent != GRAPH_TREE_MODEL( tree_model )->m_graph ) {
277 GraphTreeNode& parentParent = *node.m_parent->m_parent;
278 for ( GraphTreeNode::iterator i = parentParent.begin(); i != parentParent.end(); ++i )
280 if ( ( *i ).second == node.m_parent ) {
281 graph_iterator_write_tree_iter( i, iter );
289 static GObjectClass *g_parent_class = 0;
293 scene::Node* g_null_node = 0;
296 class NullInstance : public scene::Instance
299 NullInstance() : scene::Instance( scene::Path( makeReference( *g_null_node ) ), 0, 0, Static<InstanceTypeCastTable>::instance() ){
305 NullInstance g_null_instance;
308 static void graph_tree_model_init( GraphTreeModel *graph_tree_model ){
309 graph_tree_model->m_graph = new GraphTreeNode( g_null_instance );
312 static void graph_tree_model_finalize( GObject* object ){
313 GraphTreeModel* graph_tree_model = GRAPH_TREE_MODEL( object );
315 delete graph_tree_model->m_graph;
318 ( *g_parent_class->finalize )( object );
321 static void graph_tree_model_class_init( GraphTreeModelClass *class_ ){
322 GObjectClass *object_class;
324 g_parent_class = (GObjectClass*)g_type_class_peek_parent( class_ );
325 object_class = (GObjectClass *) class_;
327 object_class->finalize = graph_tree_model_finalize;
330 static void graph_tree_model_tree_model_init( GtkTreeModelIface *iface ){
331 iface->get_flags = graph_tree_model_get_flags;
332 iface->get_n_columns = graph_tree_model_get_n_columns;
333 iface->get_column_type = graph_tree_model_get_column_type;
334 iface->get_iter = graph_tree_model_get_iter;
335 iface->get_path = graph_tree_model_get_path;
336 iface->get_value = graph_tree_model_get_value;
337 iface->iter_next = graph_tree_model_iter_next;
338 iface->iter_children = graph_tree_model_iter_children;
339 iface->iter_has_child = graph_tree_model_iter_has_child;
340 iface->iter_n_children = graph_tree_model_iter_n_children;
341 iface->iter_nth_child = graph_tree_model_iter_nth_child;
342 iface->iter_parent = graph_tree_model_iter_parent;
345 GType graph_tree_model_get_type( void ){
346 static GType graph_tree_model_type = 0;
348 if ( !graph_tree_model_type ) {
349 static const GTypeInfo graph_tree_model_info =
351 sizeof( GraphTreeModelClass ),
353 0, /* base_finalize */
354 (GClassInitFunc) graph_tree_model_class_init,
355 0, /* class_finalize */
357 sizeof( GraphTreeModel ),
359 (GInstanceInitFunc) graph_tree_model_init,
363 static const GInterfaceInfo tree_model_info =
365 (GInterfaceInitFunc) graph_tree_model_tree_model_init,
370 graph_tree_model_type = g_type_register_static( G_TYPE_OBJECT, "GraphTreeModel",
371 &graph_tree_model_info, (GTypeFlags)0 );
373 g_type_add_interface_static( graph_tree_model_type,
378 return graph_tree_model_type;
381 GraphTreeModel* graph_tree_model_new(){
382 GraphTreeModel* graph_tree_model = GRAPH_TREE_MODEL( g_object_new( graph_tree_model_get_type(), 0 ) );
384 return graph_tree_model;
387 void graph_tree_model_delete( GraphTreeModel* model ){
388 g_object_unref( G_OBJECT( model ) );
391 void graph_tree_model_row_changed( GraphTreeModel* model, GraphTreeNode::iterator i ){
393 graph_iterator_write_tree_iter( i, &iter );
395 GtkTreePath* tree_path = graph_tree_model_get_path( GTK_TREE_MODEL( model ), &iter );
397 gtk_tree_model_row_changed( GTK_TREE_MODEL( model ), tree_path, &iter );
399 gtk_tree_path_free( tree_path );
402 void graph_tree_model_row_inserted( GraphTreeModel* model, GraphTreeNode::iterator i ){
404 graph_iterator_write_tree_iter( i, &iter );
406 GtkTreePath* tree_path = graph_tree_model_get_path( GTK_TREE_MODEL( model ), &iter );
408 gtk_tree_model_row_inserted( GTK_TREE_MODEL( model ), tree_path, &iter );
410 gtk_tree_path_free( tree_path );
413 void graph_tree_model_row_deleted( GraphTreeModel* model, GraphTreeNode::iterator i ){
415 graph_iterator_write_tree_iter( i, &iter );
417 GtkTreePath* tree_path = graph_tree_model_get_path( GTK_TREE_MODEL( model ), &iter );
419 gtk_tree_model_row_deleted( GTK_TREE_MODEL( model ), tree_path );
421 gtk_tree_path_free( tree_path );
424 void graph_tree_model_row_inserted( GraphTreeModel& model, GraphTreeNode::iterator i ){
425 graph_tree_model_row_inserted( &model, i );
428 void graph_tree_model_row_deleted( GraphTreeModel& model, GraphTreeNode::iterator i ){
429 graph_tree_model_row_deleted( &model, i );
432 const char* node_get_name( scene::Node& node );
434 const char* node_get_name_safe( scene::Node& node ){
435 volatile intptr_t n = (intptr_t)&node; // see the comment on line 650
439 return node_get_name( node );
442 GraphTreeNode* graph_tree_model_find_parent( GraphTreeModel* model, const scene::Path& path ){
443 GraphTreeNode* parent = model->m_graph;
444 for ( scene::Path::const_iterator i = path.begin(); i != path.end() - 1; ++i )
446 GraphTreeNode::iterator child = parent->find( GraphTreeNode::key_type( node_get_name_safe( ( *i ).get() ), ( *i ).get_pointer() ) );
447 ASSERT_MESSAGE( child != parent->end(), "ERROR" );
448 parent = ( *child ).second;
453 void node_attach_name_changed_callback( scene::Node& node, const NameCallback& callback ){
454 volatile intptr_t n = (intptr_t)&node; // see the comment on line 650
456 Nameable* nameable = Node_getNameable( node );
457 if ( nameable != 0 ) {
458 nameable->attach( callback );
462 void node_detach_name_changed_callback( scene::Node& node, const NameCallback& callback ){
463 volatile intptr_t n = (intptr_t)&node; // see the comment on line 650
465 Nameable* nameable = Node_getNameable( node );
466 if ( nameable != 0 ) {
467 nameable->detach( callback );
472 GraphTreeModel* scene_graph_get_tree_model(); // temp hack
474 void graph_tree_node_foreach_pre( GraphTreeNode::iterator root, const Callback1<GraphTreeNode::iterator>& callback ){
476 for ( GraphTreeNode::iterator i = ( *root ).second->begin(); i != ( *root ).second->end(); ++i )
478 graph_tree_node_foreach_pre( i, callback );
482 void graph_tree_node_foreach_post( GraphTreeNode::iterator root, const Callback1<GraphTreeNode::iterator>& callback ){
483 for ( GraphTreeNode::iterator i = ( *root ).second->begin(); i != ( *root ).second->end(); ++i )
485 graph_tree_node_foreach_post( i, callback );
490 void graph_tree_model_row_changed( GraphTreeNode& node ){
491 GraphTreeModel* model = scene_graph_get_tree_model();
492 const scene::Instance& instance = node.m_instance.get();
494 GraphTreeNode::iterator i = node.m_parent->find( GraphTreeNode::key_type( node_get_name_safe( instance.path().top().get() ), instance.path().top().get_pointer() ) );
496 graph_tree_model_row_changed( model, i );
499 void graph_tree_model_set_name( const scene::Instance& instance, const char* name ){
500 GraphTreeModel* model = scene_graph_get_tree_model();
501 GraphTreeNode* parent = graph_tree_model_find_parent( model, instance.path() );
503 GraphTreeNode::iterator oldNode = parent->find( GraphTreeNode::key_type( node_get_name_safe( instance.path().top().get() ), instance.path().top().get_pointer() ) );
504 graph_tree_node_foreach_post( oldNode, ReferenceCaller1<GraphTreeModel, GraphTreeNode::iterator, graph_tree_model_row_deleted>( *model ) );
505 GraphTreeNode* node( ( *oldNode ).second );
506 parent->erase( oldNode );
508 GraphTreeNode::iterator newNode = parent->insert( GraphTreeNode::value_type( GraphTreeNode::key_type( name, &instance.path().top().get() ), node ) );
509 graph_tree_node_foreach_pre( newNode, ReferenceCaller1<GraphTreeModel, GraphTreeNode::iterator, graph_tree_model_row_inserted>( *model ) );
512 void graph_tree_model_insert( GraphTreeModel* model, const scene::Instance& instance ){
513 GraphTreeNode* parent = graph_tree_model_find_parent( model, instance.path() );
515 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 ) ) ) );
517 graph_tree_model_row_inserted( model, i );
519 node_attach_name_changed_callback( instance.path().top(), ConstReferenceCaller1<scene::Instance, const char*, graph_tree_model_set_name>( instance ) );
522 void graph_tree_model_erase( GraphTreeModel* model, const scene::Instance& instance ){
523 node_detach_name_changed_callback( instance.path().top(), ConstReferenceCaller1<scene::Instance, const char*, graph_tree_model_set_name>( instance ) );
525 GraphTreeNode* parent = graph_tree_model_find_parent( model, instance.path() );
527 GraphTreeNode::iterator i = parent->find( GraphTreeNode::key_type( node_get_name_safe( instance.path().top().get() ), instance.path().top().get_pointer() ) );
529 graph_tree_model_row_deleted( model, i );
531 GraphTreeNode* node( ( *i ).second );