]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - radiant/treemodel.cpp
Remove some dead/debug code
[xonotic/netradiant.git] / radiant / treemodel.cpp
1 /*
2    Copyright (C) 2001-2006, William Joseph.
3    All Rights Reserved.
4
5    This file is part of GtkRadiant.
6
7    GtkRadiant is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11
12    GtkRadiant is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with GtkRadiant; if not, write to the Free Software
19    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20  */
21
22 #include "treemodel.h"
23
24 #include "debugging/debugging.h"
25
26 #include <map>
27 #include <gtk/gtktreemodel.h>
28 #include <gtk/gtktreednd.h>
29 #include <gtk/gtkmain.h>
30
31 #include "iscenegraph.h"
32 #include "nameable.h"
33
34 #include "generic/callback.h"
35 #include "scenelib.h"
36 #include "string/string.h"
37 #include "generic/reference.h"
38
39 inline Nameable* Node_getNameable( scene::Node& node ){
40         return NodeTypeCast<Nameable>::cast( node );
41 }
42
43 class GraphTreeNode;
44 void graph_tree_model_row_changed( GraphTreeNode& node );
45
46 class GraphTreeNode
47 {
48 typedef std::map<std::pair<CopiedString, scene::Node*>, GraphTreeNode*> ChildNodes;
49 ChildNodes m_childnodes;
50 public:
51 Reference<scene::Instance> m_instance;
52 GraphTreeNode* m_parent;
53
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;
58
59 GraphTreeNode( scene::Instance& instance ) : m_instance( instance ), m_parent( 0 ){
60         m_instance.get().setChildSelectedChangedCallback( RowChangedCaller( *this ) );
61 }
62 ~GraphTreeNode(){
63         m_instance.get().setChildSelectedChangedCallback( Callback() );
64         ASSERT_MESSAGE( empty(), "GraphTreeNode::~GraphTreeNode: memory leak" );
65 }
66
67 iterator begin(){
68         return m_childnodes.begin();
69 }
70 iterator end(){
71         return m_childnodes.end();
72 }
73
74 size_type size() const {
75         return m_childnodes.size();
76 }
77 bool empty() const {
78         return m_childnodes.empty();
79 }
80
81 iterator insert( const value_type& value ){
82         iterator i = m_childnodes.insert( value ).first;
83         ( *i ).second->m_parent = this;
84         return i;
85 }
86 void erase( iterator i ){
87         m_childnodes.erase( i );
88 }
89 iterator find( const key_type& key ){
90         return m_childnodes.find( key );
91 }
92
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 );
97 }
98
99 void rowChanged(){
100         graph_tree_model_row_changed( *this );
101 }
102 typedef MemberCaller<GraphTreeNode, &GraphTreeNode::rowChanged> RowChangedCaller;
103 };
104
105 struct GraphTreeModel
106 {
107         GObject parent;
108
109         GraphTreeNode* m_graph;
110 };
111
112 struct GraphTreeModelClass
113 {
114         GObjectClass parent_class;
115 };
116
117 #define GRAPH_TREE_MODEL( p ) ( reinterpret_cast<GraphTreeModel*>( p ) )
118
119 static GtkTreeModelFlags graph_tree_model_get_flags( GtkTreeModel* tree_model ){
120         return GTK_TREE_MODEL_ITERS_PERSIST;
121 }
122
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;
126
127         return 2;
128 }
129
130 static const gint c_stamp = 0xabcdef;
131
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 );
137 }
138
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" );
144 }
145
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;
149
150         return G_TYPE_POINTER;
151 }
152
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 );
157
158         g_return_val_if_fail( depth > 0, FALSE );
159
160         GraphTreeNode* graph = GRAPH_TREE_MODEL( tree_model )->m_graph;
161
162         if ( graph->empty() ) {
163                 return FALSE;
164         }
165
166         GtkTreeIter tmp;
167         GtkTreeIter* parent = 0;
168
169         for ( gint i = 0; i < depth; i++ )
170         {
171                 if ( !gtk_tree_model_iter_nth_child( tree_model, iter, parent, indices[i] ) ) {
172                         return FALSE;
173                 }
174                 tmp = *iter;
175                 parent = &tmp;
176         }
177
178         return TRUE;
179 }
180
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;
184
185         GtkTreePath* path = gtk_tree_path_new();
186
187         for ( GraphTreeNode* node = ( *graph_iterator_read_tree_iter( iter ) ).second; node != graph; node = node->m_parent )
188         {
189                 std::size_t index = 0;
190                 for ( GraphTreeNode::iterator i = node->m_parent->begin(); i != node->m_parent->end(); ++i, ++index )
191                 {
192                         if ( ( *i ).second == node ) {
193                                 gtk_tree_path_prepend_index( path, gint( index ) );
194                                 break;
195                         }
196                 }
197                 ASSERT_MESSAGE( index != node->m_parent->size(), "error resolving tree path" );
198         }
199
200         return path;
201 }
202
203
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" );
207
208         GraphTreeNode::iterator i = graph_iterator_read_tree_iter( iter );
209
210         g_value_init( value, G_TYPE_POINTER );
211
212         if ( column == 0 ) {
213                 g_value_set_pointer( value, reinterpret_cast<gpointer>( ( *i ).first.second ) );
214         }
215         else
216         {
217                 g_value_set_pointer( value, reinterpret_cast<gpointer>( &( *i ).second->m_instance.get() ) );
218         }
219 }
220
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;
225
226         ASSERT_MESSAGE( i != parent.end(), "RUNTIME ERROR" );
227
228         if ( ++i == parent.end() ) {
229                 return FALSE;
230         }
231
232         graph_iterator_write_tree_iter( i, iter );
233
234         return TRUE;
235 }
236
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 );
242                 return TRUE;
243         }
244
245         return FALSE;
246 }
247
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();
252 }
253
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() );
258 }
259
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 );
267                 return TRUE;
268         }
269
270         return FALSE;
271 }
272
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 )
279                 {
280                         if ( ( *i ).second == node.m_parent ) {
281                                 graph_iterator_write_tree_iter( i, iter );
282                                 return TRUE;
283                         }
284                 }
285         }
286         return FALSE;
287 }
288
289 static GObjectClass *g_parent_class = 0;
290
291 namespace
292 {
293 scene::Node* g_null_node = 0;
294 }
295
296 class NullInstance : public scene::Instance
297 {
298 public:
299 NullInstance() : scene::Instance( scene::Path( makeReference( *g_null_node ) ), 0, 0, Static<InstanceTypeCastTable>::instance() ){
300 }
301 };
302
303 namespace
304 {
305 NullInstance g_null_instance;
306 }
307
308 static void graph_tree_model_init( GraphTreeModel *graph_tree_model ){
309         graph_tree_model->m_graph = new GraphTreeNode( g_null_instance );
310 }
311
312 static void graph_tree_model_finalize( GObject* object ){
313         GraphTreeModel* graph_tree_model = GRAPH_TREE_MODEL( object );
314
315         delete graph_tree_model->m_graph;
316
317         /* must chain up */
318         ( *g_parent_class->finalize )( object );
319 }
320
321 static void graph_tree_model_class_init( GraphTreeModelClass *class_ ){
322         GObjectClass *object_class;
323
324         g_parent_class = (GObjectClass*)g_type_class_peek_parent( class_ );
325         object_class = (GObjectClass *) class_;
326
327         object_class->finalize = graph_tree_model_finalize;
328 }
329
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;
343 }
344
345 GType graph_tree_model_get_type( void ){
346         static GType graph_tree_model_type = 0;
347
348         if ( !graph_tree_model_type ) {
349                 static const GTypeInfo graph_tree_model_info =
350                 {
351                         sizeof( GraphTreeModelClass ),
352                         0, /* base_init */
353                         0, /* base_finalize */
354                         (GClassInitFunc) graph_tree_model_class_init,
355                         0, /* class_finalize */
356                         0, /* class_data */
357                         sizeof( GraphTreeModel ),
358                         0,        /* n_preallocs */
359                         (GInstanceInitFunc) graph_tree_model_init,
360                         0
361                 };
362
363                 static const GInterfaceInfo tree_model_info =
364                 {
365                         (GInterfaceInitFunc) graph_tree_model_tree_model_init,
366                         0,
367                         0
368                 };
369
370                 graph_tree_model_type = g_type_register_static( G_TYPE_OBJECT, "GraphTreeModel",
371                                                                                                                 &graph_tree_model_info, (GTypeFlags)0 );
372
373                 g_type_add_interface_static( graph_tree_model_type,
374                                                                          GTK_TYPE_TREE_MODEL,
375                                                                          &tree_model_info );
376         }
377
378         return graph_tree_model_type;
379 }
380
381 GraphTreeModel* graph_tree_model_new(){
382         GraphTreeModel* graph_tree_model = GRAPH_TREE_MODEL( g_object_new( graph_tree_model_get_type(), 0 ) );
383
384         return graph_tree_model;
385 }
386
387 void graph_tree_model_delete( GraphTreeModel* model ){
388         g_object_unref( G_OBJECT( model ) );
389 }
390
391 void graph_tree_model_row_changed( GraphTreeModel* model, GraphTreeNode::iterator i ){
392         GtkTreeIter iter;
393         graph_iterator_write_tree_iter( i, &iter );
394
395         GtkTreePath* tree_path = graph_tree_model_get_path( GTK_TREE_MODEL( model ), &iter );
396
397         gtk_tree_model_row_changed( GTK_TREE_MODEL( model ), tree_path, &iter );
398
399         gtk_tree_path_free( tree_path );
400 }
401
402 void graph_tree_model_row_inserted( GraphTreeModel* model, GraphTreeNode::iterator i ){
403         GtkTreeIter iter;
404         graph_iterator_write_tree_iter( i, &iter );
405
406         GtkTreePath* tree_path = graph_tree_model_get_path( GTK_TREE_MODEL( model ), &iter );
407
408         gtk_tree_model_row_inserted( GTK_TREE_MODEL( model ), tree_path, &iter );
409
410         gtk_tree_path_free( tree_path );
411 }
412
413 void graph_tree_model_row_deleted( GraphTreeModel* model, GraphTreeNode::iterator i ){
414         GtkTreeIter iter;
415         graph_iterator_write_tree_iter( i, &iter );
416
417         GtkTreePath* tree_path = graph_tree_model_get_path( GTK_TREE_MODEL( model ), &iter );
418
419         gtk_tree_model_row_deleted( GTK_TREE_MODEL( model ), tree_path );
420
421         gtk_tree_path_free( tree_path );
422 }
423
424 void graph_tree_model_row_inserted( GraphTreeModel& model, GraphTreeNode::iterator i ){
425         graph_tree_model_row_inserted( &model, i );
426 }
427
428 void graph_tree_model_row_deleted( GraphTreeModel& model, GraphTreeNode::iterator i ){
429         graph_tree_model_row_deleted( &model, i );
430 }
431
432 const char* node_get_name( scene::Node& node );
433
434 const char* node_get_name_safe( scene::Node& node ){
435         volatile intptr_t n = (intptr_t)&node;  // see the comment on line 650
436         if ( n == 0 ) {
437                 return "";
438         }
439         return node_get_name( node );
440 }
441
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 )
445         {
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;
449         }
450         return parent;
451 }
452
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
455         if ( n != 0 ) {
456                 Nameable* nameable = Node_getNameable( node );
457                 if ( nameable != 0 ) {
458                         nameable->attach( callback );
459                 }
460         }
461 }
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
464         if ( n != 0 ) {
465                 Nameable* nameable = Node_getNameable( node );
466                 if ( nameable != 0 ) {
467                         nameable->detach( callback );
468                 }
469         }
470 }
471
472 GraphTreeModel* scene_graph_get_tree_model(); // temp hack
473
474 void graph_tree_node_foreach_pre( GraphTreeNode::iterator root, const Callback1<GraphTreeNode::iterator>& callback ){
475         callback( root );
476         for ( GraphTreeNode::iterator i = ( *root ).second->begin(); i != ( *root ).second->end(); ++i )
477         {
478                 graph_tree_node_foreach_pre( i, callback );
479         }
480 }
481
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 )
484         {
485                 graph_tree_node_foreach_post( i, callback );
486         }
487         callback( root );
488 }
489
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();
493
494         GraphTreeNode::iterator i = node.m_parent->find( GraphTreeNode::key_type( node_get_name_safe( instance.path().top().get() ), instance.path().top().get_pointer() ) );
495
496         graph_tree_model_row_changed( model, i );
497 }
498
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() );
502
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 );
507
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 ) );
510 }
511
512 void graph_tree_model_insert( GraphTreeModel* model, const scene::Instance& instance ){
513         GraphTreeNode* parent = graph_tree_model_find_parent( model, instance.path() );
514
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 ) ) ) );
516
517         graph_tree_model_row_inserted( model, i );
518
519         node_attach_name_changed_callback( instance.path().top(), ConstReferenceCaller1<scene::Instance, const char*, graph_tree_model_set_name>( instance ) );
520 }
521
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 ) );
524
525         GraphTreeNode* parent = graph_tree_model_find_parent( model, instance.path() );
526
527         GraphTreeNode::iterator i = parent->find( GraphTreeNode::key_type( node_get_name_safe( instance.path().top().get() ), instance.path().top().get_pointer() ) );
528
529         graph_tree_model_row_deleted( model, i );
530
531         GraphTreeNode* node( ( *i ).second );
532         parent->erase( i );
533         delete node;
534 }