]> de.git.xonotic.org Git - xonotic/netradiant.git/blobdiff - radiant/treemodel.cpp
do not remember game was switched when selected at startup, <3 @Garux
[xonotic/netradiant.git] / radiant / treemodel.cpp
index 4d2f82384d8e62415ca44f9ac41644701bf063d6..12441f0e7ee0f5523f005c79dc8c8c1642902011 100644 (file)
  */
 
 #include "treemodel.h"
+#include "globaldefs.h"
 
 #include "debugging/debugging.h"
 
 #include <map>
-#include <gtk/gtktreemodel.h>
-#include <gtk/gtktreednd.h>
-#include <gtk/gtkmain.h>
+#include <gtk/gtk.h>
+#include <uilib/uilib.h>
 
 #include "iscenegraph.h"
 #include "nameable.h"
@@ -45,7 +45,7 @@ inline Nameable* Node_getNameable( scene::Node& node ){
 #include "gtkutil/gtktreestore.h"
 
 template<typename value_type>
-inline void gtk_tree_model_get_pointer( GtkTreeModel* model, GtkTreeIter* iter, gint column, value_type** pointer ){
+inline void gtk_tree_model_get_pointer( ui::TreeModel model, GtkTreeIter* iter, gint column, value_type** pointer ){
        GValue value = GValue_default();
        gtk_tree_model_get_value( model, iter, column, &value );
        *pointer = (value_type*)g_value_get_pointer( &value );
@@ -54,7 +54,7 @@ inline void gtk_tree_model_get_pointer( GtkTreeModel* model, GtkTreeIter* iter,
 
 typedef GtkTreeStore GraphTreeModel;
 
-GtkTreeStore* graph_tree_model_new( graph_type* graph ){
+ui::TreeStore graph_tree_model_new( graph_type* graph ){
        return gtk_tree_store_new( 2, G_TYPE_POINTER, G_TYPE_POINTER );
 }
 
@@ -64,12 +64,12 @@ void graph_tree_model_delete( GraphTreeModel* model ){
 
 
 bool graph_tree_model_subtree_find_node( GraphTreeModel* model, GtkTreeIter* parent, const scene::Node& node, GtkTreeIter* iter ){
-       for ( gboolean success = gtk_tree_model_iter_children( GTK_TREE_MODEL( model ), iter, parent );
+       for ( gboolean success = gtk_tree_model_iter_children( model, iter, parent );
                  success != FALSE;
-                 success = gtk_tree_model_iter_next( GTK_TREE_MODEL( model ), iter ) )
+                 success = gtk_tree_model_iter_next( model, iter ) )
        {
                scene::Node* current;
-               gtk_tree_model_get_pointer( GTK_TREE_MODEL( model ), iter, 0, &current );
+               gtk_tree_model_get_pointer( model, iter, 0, &current );
                if ( current == node ) {
                        return true;
                }
@@ -110,7 +110,7 @@ bool graph_tree_model_find_parent( GraphTreeModel* model, const scene::Path& pat
        return true;
 }
 
-void node_attach_name_changed_callback( scene::Node& node, const Callback& callback ){
+void node_attach_name_changed_callback( scene::Node& node, const Callback<void()>& callback ){
        if ( node != 0 ) {
                Nameable* nameable = Node_getNameable( node );
                if ( nameable != 0 ) {
@@ -118,7 +118,7 @@ void node_attach_name_changed_callback( scene::Node& node, const Callback& callb
                }
        }
 }
-void node_detach_name_changed_callback( scene::Node& node, const Callback& callback ){
+void node_detach_name_changed_callback( scene::Node& node, const Callback<void()>& callback ){
        if ( node != 0 ) {
                Nameable* nameable = Node_getNameable( node );
                if ( nameable != 0 ) {
@@ -153,14 +153,14 @@ void graph_tree_model_row_inserted( GraphTreeModel* model, const scene::Instance
        gtk_tree_store_append( GTK_TREE_STORE( model ), &child, parent_pointer );
        gtk_tree_store_set( GTK_TREE_STORE( model ), &child, 0, node, 1, selectable, -1 );
 
-       node_attach_name_changed_callback( instance.path().top(), ConstReferenceCaller<scene::Instance, graph_tree_model_row_changed>( instance ) );
+       node_attach_name_changed_callback( instance.path().top(), ConstReferenceCaller<scene::Instance, void(), graph_tree_model_row_changed>( instance ) );
 }
 
 void graph_tree_model_row_deleted( GraphTreeModel* model, const scene::Instance& instance ){
        GtkTreeIter child;
        ASSERT_MESSAGE( graph_tree_model_find_top( model, instance.path(), child ), "RUNTIME ERROR" );
 
-       node_detach_name_changed_callback( instance.path().top(), ConstReferenceCaller<scene::Instance, graph_tree_model_row_changed>( instance ) );
+       node_detach_name_changed_callback( instance.path().top(), ConstReferenceCaller<scene::Instance, void(), graph_tree_model_row_changed>( instance ) );
 
        gtk_tree_store_remove( GTK_TREE_STORE( model ), &child );
 }
@@ -217,7 +217,7 @@ static GtkTreeModelFlags graph_tree_model_get_flags( GtkTreeModel* tree_model ){
        return GTK_TREE_MODEL_ITERS_PERSIST;
 }
 
-static gint graph_tree_model_get_n_columns( GtkTreeModel* tree_model ){
+static gint graph_tree_model_get_n_columns( ui::TreeModel tree_model ){
        ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
        GraphTreeModel* graph_tree_model = (GraphTreeModel*) tree_model;
 
@@ -240,14 +240,14 @@ inline void graph_iterator_write_tree_iter( graph_type::iterator i, GtkTreeIter*
        ASSERT_MESSAGE( iter->user_data != 0,  "tree model error" );
 }
 
-static GType graph_tree_model_get_column_type( GtkTreeModel *tree_model, gint index ){
+static GType graph_tree_model_get_column_type( ui::TreeModel tree_model, gint index ){
        ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
        GraphTreeModel *graph_tree_model = (GraphTreeModel *) tree_model;
 
        return G_TYPE_POINTER;
 }
 
-static gboolean graph_tree_model_get_iter( GtkTreeModel* tree_model, GtkTreeIter* iter, GtkTreePath* path ){
+static gboolean graph_tree_model_get_iter( ui::TreeModel tree_model, GtkTreeIter* iter, ui::TreePath path ){
        ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
        gint* indices = gtk_tree_path_get_indices( path );
        gint depth = gtk_tree_path_get_depth( path );
@@ -275,12 +275,12 @@ static gboolean graph_tree_model_get_iter( GtkTreeModel* tree_model, GtkTreeIter
        return TRUE;
 }
 
-static GtkTreePath* graph_tree_model_get_path( GtkTreeModel* tree_model, GtkTreeIter* iter ){
+static ui::TreePath graph_tree_model_get_path( ui::TreeModel tree_model, GtkTreeIter* iter ){
        ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
        graph_type& graph = *GRAPH_TREE_MODEL( tree_model )->graph;
        graph_type::iterator i = graph_iterator_read_tree_iter( iter );
 
-       GtkTreePath* path = gtk_tree_path_new();
+       auto path = ui::TreePath();
 
        for ( std::size_t depth = ( *i ).first.get().size(); depth != 0; --depth )
        {
@@ -301,7 +301,7 @@ static GtkTreePath* graph_tree_model_get_path( GtkTreeModel* tree_model, GtkTree
 }
 
 
-static void graph_tree_model_get_value( GtkTreeModel *tree_model, GtkTreeIter  *iter, gint column, GValue *value ){
+static void graph_tree_model_get_value( ui::TreeModel tree_model, GtkTreeIter  *iter, gint column, GValue *value ){
        ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
        ASSERT_MESSAGE( column == 0 || column == 1, "tree model error" );
 
@@ -317,7 +317,7 @@ static void graph_tree_model_get_value( GtkTreeModel *tree_model, GtkTreeIter  *
        }
 }
 
-static gboolean graph_tree_model_iter_next( GtkTreeModel  *tree_model, GtkTreeIter   *iter ){
+static gboolean graph_tree_model_iter_next( ui::TreeModel  tree_model, GtkTreeIter   *iter ){
        ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
        graph_type& graph = *GRAPH_TREE_MODEL( tree_model )->graph;
        graph_type::iterator i = graph_iterator_read_tree_iter( iter );
@@ -339,7 +339,7 @@ static gboolean graph_tree_model_iter_next( GtkTreeModel  *tree_model, GtkTreeIt
        return TRUE;
 }
 
-static gboolean graph_tree_model_iter_children( GtkTreeModel *tree_model, GtkTreeIter  *iter, GtkTreeIter  *parent ){
+static gboolean graph_tree_model_iter_children( ui::TreeModel tree_model, GtkTreeIter  *iter, GtkTreeIter  *parent ){
        ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
        graph_type& graph = *GRAPH_TREE_MODEL( tree_model )->graph;
        graph_type::iterator i = ( parent == 0 ) ? graph.begin() : graph_iterator_read_tree_iter( parent );
@@ -357,7 +357,7 @@ static gboolean graph_tree_model_iter_children( GtkTreeModel *tree_model, GtkTre
        return FALSE;
 }
 
-static gboolean graph_tree_model_iter_has_child( GtkTreeModel *tree_model, GtkTreeIter  *iter ){
+static gboolean graph_tree_model_iter_has_child( ui::TreeModel tree_model, GtkTreeIter  *iter ){
        ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
        graph_type& graph = *GRAPH_TREE_MODEL( tree_model )->graph;
        graph_type::iterator i = graph_iterator_read_tree_iter( iter );
@@ -366,7 +366,7 @@ static gboolean graph_tree_model_iter_has_child( GtkTreeModel *tree_model, GtkTr
        return ++i != graph.end() && ( *i ).first.get().size() == depth;
 }
 
-static gint graph_tree_model_iter_n_children( GtkTreeModel *tree_model, GtkTreeIter *parent ){
+static gint graph_tree_model_iter_n_children( ui::TreeModel tree_model, GtkTreeIter *parent ){
        ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
        graph_type& graph = *GRAPH_TREE_MODEL( tree_model )->graph;
        graph_type::iterator i = ( parent == 0 ) ? graph.begin() : graph_iterator_read_tree_iter( parent );
@@ -386,7 +386,7 @@ static gint graph_tree_model_iter_n_children( GtkTreeModel *tree_model, GtkTreeI
        return count;
 }
 
-static gboolean graph_tree_model_iter_nth_child( GtkTreeModel *tree_model, GtkTreeIter  *iter, GtkTreeIter  *parent, gint n ){
+static gboolean graph_tree_model_iter_nth_child( ui::TreeModel tree_model, GtkTreeIter  *iter, GtkTreeIter  *parent, gint n ){
        ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
        graph_type& graph = *GRAPH_TREE_MODEL( tree_model )->graph;
        graph_type::iterator i = ( parent == 0 ) ? graph.begin() : graph_iterator_read_tree_iter( parent );
@@ -408,7 +408,7 @@ static gboolean graph_tree_model_iter_nth_child( GtkTreeModel *tree_model, GtkTr
        return FALSE;
 }
 
-static gboolean graph_tree_model_iter_parent( GtkTreeModel *tree_model, GtkTreeIter  *iter, GtkTreeIter  *child ){
+static gboolean graph_tree_model_iter_parent( ui::TreeModel tree_model, GtkTreeIter  *iter, GtkTreeIter  *child ){
        ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
        graph_type& graph = *GRAPH_TREE_MODEL( tree_model )->graph;
        graph_type::iterator i = graph_iterator_read_tree_iter( child );
@@ -465,17 +465,17 @@ static void graph_tree_model_tree_model_init( GtkTreeModelIface *iface ){
        iface->iter_parent = graph_tree_model_iter_parent;
 }
 
-static gboolean graph_tree_model_row_draggable( GtkTreeDragSource *drag_source, GtkTreePath *path ){
-#ifdef _DEBUG
+static gboolean graph_tree_model_row_draggable( GtkTreeDragSource *drag_source, ui::TreePath path ){
+#if GDEF_DEBUG
        gint depth = gtk_tree_path_get_depth( path );
 #endif
        return gtk_tree_path_get_depth( path ) > 1;
 }
 
-static gboolean graph_tree_model_drag_data_delete( GtkTreeDragSource *drag_source, GtkTreePath *path ){
+static gboolean graph_tree_model_drag_data_delete( GtkTreeDragSource *drag_source, ui::TreePath path ){
        GtkTreeIter iter;
 
-       if ( gtk_tree_model_get_iter( GTK_TREE_MODEL( drag_source ), &iter, path ) ) {
+       if ( gtk_tree_model_get_iter( drag_source, &iter, path ) ) {
                graph_type::iterator i = graph_iterator_read_tree_iter( &iter );
                Path_deleteTop( ( *i ).first );
                return TRUE;
@@ -486,8 +486,8 @@ static gboolean graph_tree_model_drag_data_delete( GtkTreeDragSource *drag_sourc
        }
 }
 
-static gboolean graph_tree_model_drag_data_get( GtkTreeDragSource *drag_source, GtkTreePath *path, GtkSelectionData *selection_data ){
-       if ( gtk_tree_set_row_drag_data( selection_data, GTK_TREE_MODEL( drag_source ), path ) ) {
+static gboolean graph_tree_model_drag_data_get( GtkTreeDragSource *drag_source, ui::TreePath path, GtkSelectionData *selection_data ){
+       if ( gtk_tree_set_row_drag_data( selection_data, drag_source, path ) ) {
                return TRUE;
        }
        else
@@ -504,8 +504,8 @@ static void graph_tree_model_drag_source_init( GtkTreeDragSourceIface *iface ){
        iface->drag_data_get = graph_tree_model_drag_data_get;
 }
 
-static gboolean graph_tree_model_drag_data_received( GtkTreeDragDest *drag_dest, GtkTreePath *dest, GtkSelectionData *selection_data ){
-       GtkTreeModel *tree_model = GTK_TREE_MODEL( drag_dest );
+static gboolean graph_tree_model_drag_data_received( GtkTreeDragDest *drag_dest, ui::TreePath dest, GtkSelectionData *selection_data ){
+       auto tree_model = drag_dest;
 
        GtkTreeModel *src_model = 0;
        GtkTreePath *src_path = 0;
@@ -528,23 +528,23 @@ static gboolean graph_tree_model_drag_data_received( GtkTreeDragDest *drag_dest,
        return FALSE;
 }
 
-static gboolean graph_tree_model_row_drop_possible( GtkTreeDragDest *drag_dest, GtkTreePath *dest_path, GtkSelectionData *selection_data ){
+static gboolean graph_tree_model_row_drop_possible( GtkTreeDragDest *drag_dest, ui::TreePath dest_path, GtkSelectionData *selection_data ){
        gboolean retval = FALSE;
 
        GtkTreeModel *src_model = 0;
        GtkTreePath *src_path = 0;
        if ( gtk_tree_get_row_drag_data( selection_data, &src_model, &src_path ) != FALSE ) {
                /* can only drag to ourselves */
-               if ( src_model == GTK_TREE_MODEL( drag_dest ) ) {
+               if ( src_model == drag_dest ) {
                        /* Can't drop into ourself. */
                        if ( !gtk_tree_path_is_ancestor( src_path, dest_path ) ) {
                                /* Can't drop if dest_path's parent doesn't exist */
                                if ( gtk_tree_path_get_depth( dest_path ) > 1 ) {
-                                       GtkTreePath* tmp = gtk_tree_path_copy( dest_path );
+                                       auto tmp = gtk_tree_path_copy( dest_path );
                                        gtk_tree_path_up( tmp );
 
                                        GtkTreeIter iter;
-                                       retval = gtk_tree_model_get_iter( GTK_TREE_MODEL( drag_dest ), &iter, tmp );
+                                       retval = gtk_tree_model_get_iter( drag_dest, &iter, tmp );
 
                                        gtk_tree_path_free( tmp );
                                }
@@ -647,7 +647,13 @@ void detach( const NameCallback& callback ){
 };
 
 void node_attach_name_changed_callback( scene::Node& node, const NameCallback& callback ){
-       if ( &node != 0 ) {
+       // Reference cannot be bound to dereferenced null pointer in well-defined
+       // C++ code, and Clang will assume that comparison below always evaluates
+       // to true, resulting in a segmentation fault.  Use a dirty hack to force
+       // Clang to check those "bad" references for null nonetheless.
+       volatile intptr_t n = (intptr_t)&node;
+
+       if ( n != 0 ) {
                Nameable* nameable = Node_getNameable( node );
                if ( nameable != 0 ) {
                        nameable->attach( callback );
@@ -655,7 +661,9 @@ void node_attach_name_changed_callback( scene::Node& node, const NameCallback& c
        }
 }
 void node_detach_name_changed_callback( scene::Node& node, const NameCallback& callback ){
-       if ( &node != 0 ) {
+       volatile intptr_t n = (intptr_t)&node;  // see the comment on line 650
+
+       if ( n != 0 ) {
                Nameable* nameable = Node_getNameable( node );
                if ( nameable != 0 ) {
                        nameable->detach( callback );
@@ -669,12 +677,12 @@ void graph_tree_model_row_inserted( GraphTreeModel* model, graph_type::iterator
        GtkTreeIter iter;
        graph_iterator_write_tree_iter( i, &iter );
 
-       GtkTreePath* tree_path = graph_tree_model_get_path( GTK_TREE_MODEL( model ), &iter );
+       auto tree_path = graph_tree_model_get_path( model, &iter );
 
        gint depth = gtk_tree_path_get_depth( tree_path );
        gint* indices = gtk_tree_path_get_indices( tree_path );
 
-       gtk_tree_model_row_inserted( GTK_TREE_MODEL( model ), tree_path, &iter );
+       gtk_tree_model_row_inserted( model, tree_path, &iter );
 
        gtk_tree_path_free( tree_path );
 }
@@ -683,9 +691,9 @@ void graph_tree_model_row_deleted( GraphTreeModel* model, graph_type::iterator i
        GtkTreeIter iter;
        graph_iterator_write_tree_iter( i, &iter );
 
-       GtkTreePath* tree_path = graph_tree_model_get_path( GTK_TREE_MODEL( model ), &iter );
+       auto tree_path = graph_tree_model_get_path( model, &iter );
 
-       gtk_tree_model_row_deleted( GTK_TREE_MODEL( model ), tree_path );
+       gtk_tree_model_row_deleted( model, tree_path );
 
        gtk_tree_path_free( tree_path );
 }
@@ -716,11 +724,11 @@ void graph_tree_model_insert( GraphTreeModel* model, const scene::Instance& inst
 
        graph_tree_model_row_inserted( model, i );
 
-       node_attach_name_changed_callback( instance.path().top(), ConstReferenceCaller1<scene::Instance, const char*, graph_tree_model_set_name>( instance ) );
+       node_attach_name_changed_callback( instance.path().top(), ConstReferenceCaller<scene::Instance, void(const char*), graph_tree_model_set_name>( instance ) );
 }
 
 void graph_tree_model_erase( GraphTreeModel* model, const scene::Instance& instance ){
-       node_detach_name_changed_callback( instance.path().top(), ConstReferenceCaller1<scene::Instance, const char*, graph_tree_model_set_name>( instance ) );
+       node_detach_name_changed_callback( instance.path().top(), ConstReferenceCaller<scene::Instance, void(const char*), graph_tree_model_set_name>( instance ) );
 
        graph_type::iterator i = model->graph->find( PathConstReference( instance.path() ) );
        ASSERT_MESSAGE( i != model->graph->end(), "ERROR" );
@@ -752,7 +760,7 @@ GraphTreeNode( scene::Instance& instance ) : m_instance( instance ), m_parent( 0
        m_instance.get().setChildSelectedChangedCallback( RowChangedCaller( *this ) );
 }
 ~GraphTreeNode(){
-       m_instance.get().setChildSelectedChangedCallback( Callback() );
+       m_instance.get().setChildSelectedChangedCallback( Callback<void()>() );
        ASSERT_MESSAGE( empty(), "GraphTreeNode::~GraphTreeNode: memory leak" );
 }
 
@@ -791,7 +799,7 @@ void swap( GraphTreeNode& other ){
 void rowChanged(){
        graph_tree_model_row_changed( *this );
 }
-typedef MemberCaller<GraphTreeNode, &GraphTreeNode::rowChanged> RowChangedCaller;
+typedef MemberCaller<GraphTreeNode, void(), &GraphTreeNode::rowChanged> RowChangedCaller;
 };
 
 struct GraphTreeModel
@@ -806,14 +814,12 @@ struct GraphTreeModelClass
        GObjectClass parent_class;
 };
 
-#define GRAPH_TREE_MODEL( p ) ( reinterpret_cast<GraphTreeModel*>( p ) )
-
-static GtkTreeModelFlags graph_tree_model_get_flags( GtkTreeModel* tree_model ){
+static GtkTreeModelFlags graph_tree_model_get_flags( ui::TreeModel tree_model ){
        return GTK_TREE_MODEL_ITERS_PERSIST;
 }
 
-static gint graph_tree_model_get_n_columns( GtkTreeModel* tree_model ){
-       ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
+static gint graph_tree_model_get_n_columns( ui::TreeModel tree_model ){
+       ASSERT_MESSAGE( tree_model, "RUNTIME ERROR" );
        //GraphTreeModel* graph_tree_model = (GraphTreeModel*) tree_model;
 
        return 2;
@@ -835,21 +841,21 @@ inline void graph_iterator_write_tree_iter( GraphTreeNode::iterator i, GtkTreeIt
        ASSERT_MESSAGE( iter->user_data != 0,  "tree model error" );
 }
 
-static GType graph_tree_model_get_column_type( GtkTreeModel *tree_model, gint index ){
-       ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
+static GType graph_tree_model_get_column_type( ui::TreeModel tree_model, gint index ){
+       ASSERT_MESSAGE( tree_model, "RUNTIME ERROR" );
        //GraphTreeModel *graph_tree_model = (GraphTreeModel *) tree_model;
 
        return G_TYPE_POINTER;
 }
 
-static gboolean graph_tree_model_get_iter( GtkTreeModel* tree_model, GtkTreeIter* iter, GtkTreePath* path ){
+static gboolean graph_tree_model_get_iter( GraphTreeModel* tree_model, GtkTreeIter* iter, ui::TreePath path ){
        ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
        gint* indices = gtk_tree_path_get_indices( path );
        gint depth = gtk_tree_path_get_depth( path );
 
        g_return_val_if_fail( depth > 0, FALSE );
 
-       GraphTreeNode* graph = GRAPH_TREE_MODEL( tree_model )->m_graph;
+       GraphTreeNode *graph = tree_model->m_graph;
 
        if ( graph->empty() ) {
                return FALSE;
@@ -860,7 +866,7 @@ static gboolean graph_tree_model_get_iter( GtkTreeModel* tree_model, GtkTreeIter
 
        for ( gint i = 0; i < depth; i++ )
        {
-               if ( !gtk_tree_model_iter_nth_child( tree_model, iter, parent, indices[i] ) ) {
+               if ( !gtk_tree_model_iter_nth_child( GTK_TREE_MODEL(tree_model), iter, parent, indices[i] ) ) {
                        return FALSE;
                }
                tmp = *iter;
@@ -870,11 +876,11 @@ static gboolean graph_tree_model_get_iter( GtkTreeModel* tree_model, GtkTreeIter
        return TRUE;
 }
 
-static GtkTreePath* graph_tree_model_get_path( GtkTreeModel* tree_model, GtkTreeIter* iter ){
-       ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
-       GraphTreeNode* graph = GRAPH_TREE_MODEL( tree_model )->m_graph;
+static ui::TreePath graph_tree_model_get_path( GraphTreeModel *tree_model, GtkTreeIter* iter ){
+       ASSERT_MESSAGE( tree_model, "RUNTIME ERROR" );
+       GraphTreeNode* graph = tree_model->m_graph;
 
-       GtkTreePath* path = gtk_tree_path_new();
+    auto path = ui::TreePath(ui::New);
 
        for ( GraphTreeNode* node = ( *graph_iterator_read_tree_iter( iter ) ).second; node != graph; node = node->m_parent )
        {
@@ -893,8 +899,8 @@ static GtkTreePath* graph_tree_model_get_path( GtkTreeModel* tree_model, GtkTree
 }
 
 
-static void graph_tree_model_get_value( GtkTreeModel *tree_model, GtkTreeIter  *iter, gint column, GValue *value ){
-       ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
+static void graph_tree_model_get_value( ui::TreeModel tree_model, GtkTreeIter  *iter, gint column, GValue *value ){
+       ASSERT_MESSAGE( tree_model, "RUNTIME ERROR" );
        ASSERT_MESSAGE( column == 0 || column == 1, "tree model error" );
 
        GraphTreeNode::iterator i = graph_iterator_read_tree_iter( iter );
@@ -910,8 +916,8 @@ static void graph_tree_model_get_value( GtkTreeModel *tree_model, GtkTreeIter  *
        }
 }
 
-static gboolean graph_tree_model_iter_next( GtkTreeModel  *tree_model, GtkTreeIter   *iter ){
-       ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
+static gboolean graph_tree_model_iter_next( ui::TreeModel  tree_model, GtkTreeIter   *iter ){
+       ASSERT_MESSAGE( tree_model, "RUNTIME ERROR" );
        GraphTreeNode::iterator i = graph_iterator_read_tree_iter( iter );
        GraphTreeNode& parent = *( *i ).second->m_parent;
 
@@ -926,9 +932,9 @@ static gboolean graph_tree_model_iter_next( GtkTreeModel  *tree_model, GtkTreeIt
        return TRUE;
 }
 
-static gboolean graph_tree_model_iter_children( GtkTreeModel *tree_model, GtkTreeIter  *iter, GtkTreeIter  *parent ){
+static gboolean graph_tree_model_iter_children( GraphTreeModel *tree_model, GtkTreeIter  *iter, GtkTreeIter  *parent ){
        ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
-       GraphTreeNode& node = ( parent == 0 ) ? *GRAPH_TREE_MODEL( tree_model )->m_graph : *( *graph_iterator_read_tree_iter( parent ) ).second;
+       GraphTreeNode& node = ( parent == 0 ) ? *tree_model->m_graph : *( *graph_iterator_read_tree_iter( parent ) ).second;
        if ( !node.empty() ) {
                graph_iterator_write_tree_iter( node.begin(), iter );
                return TRUE;
@@ -937,21 +943,21 @@ static gboolean graph_tree_model_iter_children( GtkTreeModel *tree_model, GtkTre
        return FALSE;
 }
 
-static gboolean graph_tree_model_iter_has_child( GtkTreeModel *tree_model, GtkTreeIter  *iter ){
-       ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
+static gboolean graph_tree_model_iter_has_child( ui::TreeModel tree_model, GtkTreeIter  *iter ){
+       ASSERT_MESSAGE( tree_model, "RUNTIME ERROR" );
        GraphTreeNode& node = *( *graph_iterator_read_tree_iter( iter ) ).second;
        return !node.empty();
 }
 
-static gint graph_tree_model_iter_n_children( GtkTreeModel *tree_model, GtkTreeIter *parent ){
+static gint graph_tree_model_iter_n_children( GraphTreeModel *tree_model, GtkTreeIter *parent ){
        ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
-       GraphTreeNode& node = ( parent == 0 ) ? *GRAPH_TREE_MODEL( tree_model )->m_graph : *( *graph_iterator_read_tree_iter( parent ) ).second;
+       GraphTreeNode& node = ( parent == 0 ) ? *tree_model->m_graph : *( *graph_iterator_read_tree_iter( parent ) ).second;
        return static_cast<gint>( node.size() );
 }
 
-static gboolean graph_tree_model_iter_nth_child( GtkTreeModel *tree_model, GtkTreeIter  *iter, GtkTreeIter  *parent, gint n ){
+static gboolean graph_tree_model_iter_nth_child( GraphTreeModel *tree_model, GtkTreeIter  *iter, GtkTreeIter  *parent, gint n ){
        ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
-       GraphTreeNode& node = ( parent == 0 ) ? *GRAPH_TREE_MODEL( tree_model )->m_graph : *( *graph_iterator_read_tree_iter( parent ) ).second;
+       GraphTreeNode& node = ( parent == 0 ) ? *tree_model->m_graph : *( *graph_iterator_read_tree_iter( parent ) ).second;
        if ( static_cast<std::size_t>( n ) < node.size() ) {
                GraphTreeNode::iterator i = node.begin();
                std::advance( i, n );
@@ -962,10 +968,10 @@ static gboolean graph_tree_model_iter_nth_child( GtkTreeModel *tree_model, GtkTr
        return FALSE;
 }
 
-static gboolean graph_tree_model_iter_parent( GtkTreeModel *tree_model, GtkTreeIter  *iter, GtkTreeIter  *child ){
+static gboolean graph_tree_model_iter_parent( GraphTreeModel *tree_model, GtkTreeIter  *iter, GtkTreeIter  *child ){
        ASSERT_MESSAGE( tree_model != 0, "RUNTIME ERROR" );
        GraphTreeNode& node = *( *graph_iterator_read_tree_iter( child ) ).second;
-       if ( node.m_parent != GRAPH_TREE_MODEL( tree_model )->m_graph ) {
+       if ( node.m_parent != tree_model->m_graph ) {
                GraphTreeNode& parentParent = *node.m_parent->m_parent;
                for ( GraphTreeNode::iterator i = parentParent.begin(); i != parentParent.end(); ++i )
                {
@@ -1002,7 +1008,7 @@ static void graph_tree_model_init( GraphTreeModel *graph_tree_model ){
 }
 
 static void graph_tree_model_finalize( GObject* object ){
-       GraphTreeModel* graph_tree_model = GRAPH_TREE_MODEL( object );
+       auto graph_tree_model = reinterpret_cast<GraphTreeModel*>(object);
 
        delete graph_tree_model->m_graph;
 
@@ -1020,18 +1026,18 @@ static void graph_tree_model_class_init( GraphTreeModelClass *class_ ){
 }
 
 static void graph_tree_model_tree_model_init( GtkTreeModelIface *iface ){
-       iface->get_flags = graph_tree_model_get_flags;
-       iface->get_n_columns = graph_tree_model_get_n_columns;
-       iface->get_column_type = graph_tree_model_get_column_type;
-       iface->get_iter = graph_tree_model_get_iter;
-       iface->get_path = graph_tree_model_get_path;
-       iface->get_value = graph_tree_model_get_value;
-       iface->iter_next = graph_tree_model_iter_next;
-       iface->iter_children = graph_tree_model_iter_children;
-       iface->iter_has_child = graph_tree_model_iter_has_child;
-       iface->iter_n_children = graph_tree_model_iter_n_children;
-       iface->iter_nth_child = graph_tree_model_iter_nth_child;
-       iface->iter_parent = graph_tree_model_iter_parent;
+       iface->get_flags = reinterpret_cast<GtkTreeModelFlags (*)(GtkTreeModel *)>(graph_tree_model_get_flags);
+       iface->get_n_columns = reinterpret_cast<gint (*)(GtkTreeModel *)>(graph_tree_model_get_n_columns);
+       iface->get_column_type = reinterpret_cast<GType (*)(GtkTreeModel *, gint)>(graph_tree_model_get_column_type);
+       iface->get_iter = reinterpret_cast<gboolean (*)(GtkTreeModel *, GtkTreeIter *, GtkTreePath *)>(graph_tree_model_get_iter);
+       iface->get_path = reinterpret_cast<GtkTreePath *(*)(GtkTreeModel *, GtkTreeIter *)>(graph_tree_model_get_path);
+       iface->get_value = reinterpret_cast<void (*)(GtkTreeModel *, GtkTreeIter *, gint, GValue *)>(graph_tree_model_get_value);
+       iface->iter_next = reinterpret_cast<gboolean (*)(GtkTreeModel *, GtkTreeIter *)>(graph_tree_model_iter_next);
+       iface->iter_children = reinterpret_cast<gboolean (*)(GtkTreeModel *, GtkTreeIter *, GtkTreeIter *)>(graph_tree_model_iter_children);
+       iface->iter_has_child = reinterpret_cast<gboolean (*)(GtkTreeModel *, GtkTreeIter *)>(graph_tree_model_iter_has_child);
+       iface->iter_n_children = reinterpret_cast<gint (*)(GtkTreeModel *, GtkTreeIter *)>(graph_tree_model_iter_n_children);
+       iface->iter_nth_child = reinterpret_cast<gboolean (*)(GtkTreeModel *, GtkTreeIter *, GtkTreeIter *, gint)>(graph_tree_model_iter_nth_child);
+       iface->iter_parent = reinterpret_cast<gboolean (*)(GtkTreeModel *, GtkTreeIter *, GtkTreeIter *)>(graph_tree_model_iter_parent);
 }
 
 GType graph_tree_model_get_type( void ){
@@ -1071,7 +1077,7 @@ GType graph_tree_model_get_type( void ){
 }
 
 GraphTreeModel* graph_tree_model_new(){
-       GraphTreeModel* graph_tree_model = GRAPH_TREE_MODEL( g_object_new( graph_tree_model_get_type(), 0 ) );
+       auto graph_tree_model = reinterpret_cast<GraphTreeModel*>(g_object_new( graph_tree_model_get_type(), 0 ));
 
        return graph_tree_model;
 }
@@ -1084,7 +1090,7 @@ void graph_tree_model_row_changed( GraphTreeModel* model, GraphTreeNode::iterato
        GtkTreeIter iter;
        graph_iterator_write_tree_iter( i, &iter );
 
-       GtkTreePath* tree_path = graph_tree_model_get_path( GTK_TREE_MODEL( model ), &iter );
+    auto tree_path = graph_tree_model_get_path(model, &iter );
 
        gtk_tree_model_row_changed( GTK_TREE_MODEL( model ), tree_path, &iter );
 
@@ -1095,7 +1101,7 @@ void graph_tree_model_row_inserted( GraphTreeModel* model, GraphTreeNode::iterat
        GtkTreeIter iter;
        graph_iterator_write_tree_iter( i, &iter );
 
-       GtkTreePath* tree_path = graph_tree_model_get_path( GTK_TREE_MODEL( model ), &iter );
+    auto tree_path = graph_tree_model_get_path(model, &iter );
 
        gtk_tree_model_row_inserted( GTK_TREE_MODEL( model ), tree_path, &iter );
 
@@ -1106,7 +1112,7 @@ void graph_tree_model_row_deleted( GraphTreeModel* model, GraphTreeNode::iterato
        GtkTreeIter iter;
        graph_iterator_write_tree_iter( i, &iter );
 
-       GtkTreePath* tree_path = graph_tree_model_get_path( GTK_TREE_MODEL( model ), &iter );
+    auto tree_path = graph_tree_model_get_path(model, &iter );
 
        gtk_tree_model_row_deleted( GTK_TREE_MODEL( model ), tree_path );
 
@@ -1124,7 +1130,8 @@ void graph_tree_model_row_deleted( GraphTreeModel& model, GraphTreeNode::iterato
 const char* node_get_name( scene::Node& node );
 
 const char* node_get_name_safe( scene::Node& node ){
-       if ( &node == 0 ) {
+       volatile intptr_t n = (intptr_t)&node;  // see the comment on line 650
+       if ( n == 0 ) {
                return "";
        }
        return node_get_name( node );
@@ -1142,7 +1149,8 @@ GraphTreeNode* graph_tree_model_find_parent( GraphTreeModel* model, const scene:
 }
 
 void node_attach_name_changed_callback( scene::Node& node, const NameCallback& callback ){
-       if ( &node != 0 ) {
+       volatile intptr_t n = (intptr_t)&node;  // see the comment on line 650
+       if ( n != 0 ) {
                Nameable* nameable = Node_getNameable( node );
                if ( nameable != 0 ) {
                        nameable->attach( callback );
@@ -1150,7 +1158,8 @@ void node_attach_name_changed_callback( scene::Node& node, const NameCallback& c
        }
 }
 void node_detach_name_changed_callback( scene::Node& node, const NameCallback& callback ){
-       if ( &node != 0 ) {
+       volatile intptr_t n = (intptr_t)&node;  // see the comment on line 650
+       if ( n != 0 ) {
                Nameable* nameable = Node_getNameable( node );
                if ( nameable != 0 ) {
                        nameable->detach( callback );
@@ -1160,7 +1169,7 @@ void node_detach_name_changed_callback( scene::Node& node, const NameCallback& c
 
 GraphTreeModel* scene_graph_get_tree_model(); // temp hack
 
-void graph_tree_node_foreach_pre( GraphTreeNode::iterator root, const Callback1<GraphTreeNode::iterator>& callback ){
+void graph_tree_node_foreach_pre( GraphTreeNode::iterator root, const Callback<void(GraphTreeNode::iterator)>& callback ){
        callback( root );
        for ( GraphTreeNode::iterator i = ( *root ).second->begin(); i != ( *root ).second->end(); ++i )
        {
@@ -1168,7 +1177,7 @@ void graph_tree_node_foreach_pre( GraphTreeNode::iterator root, const Callback1<
        }
 }
 
-void graph_tree_node_foreach_post( GraphTreeNode::iterator root, const Callback1<GraphTreeNode::iterator>& callback ){
+void graph_tree_node_foreach_post( GraphTreeNode::iterator root, const Callback<void(GraphTreeNode::iterator)>& callback ){
        for ( GraphTreeNode::iterator i = ( *root ).second->begin(); i != ( *root ).second->end(); ++i )
        {
                graph_tree_node_foreach_post( i, callback );
@@ -1190,12 +1199,12 @@ void graph_tree_model_set_name( const scene::Instance& instance, const char* nam
        GraphTreeNode* parent = graph_tree_model_find_parent( model, instance.path() );
 
        GraphTreeNode::iterator oldNode = parent->find( GraphTreeNode::key_type( node_get_name_safe( instance.path().top().get() ), instance.path().top().get_pointer() ) );
-       graph_tree_node_foreach_post( oldNode, ReferenceCaller1<GraphTreeModel, GraphTreeNode::iterator, graph_tree_model_row_deleted>( *model ) );
+       graph_tree_node_foreach_post( oldNode, ReferenceCaller<GraphTreeModel, void(GraphTreeNode::iterator), graph_tree_model_row_deleted>( *model ) );
        GraphTreeNode* node( ( *oldNode ).second );
        parent->erase( oldNode );
 
        GraphTreeNode::iterator newNode = parent->insert( GraphTreeNode::value_type( GraphTreeNode::key_type( name, &instance.path().top().get() ), node ) );
-       graph_tree_node_foreach_pre( newNode, ReferenceCaller1<GraphTreeModel, GraphTreeNode::iterator, graph_tree_model_row_inserted>( *model ) );
+       graph_tree_node_foreach_pre( newNode, ReferenceCaller<GraphTreeModel, void(GraphTreeNode::iterator), graph_tree_model_row_inserted>( *model ) );
 }
 
 void graph_tree_model_insert( GraphTreeModel* model, const scene::Instance& instance ){
@@ -1205,11 +1214,11 @@ void graph_tree_model_insert( GraphTreeModel* model, const scene::Instance& inst
 
        graph_tree_model_row_inserted( model, i );
 
-       node_attach_name_changed_callback( instance.path().top(), ConstReferenceCaller1<scene::Instance, const char*, graph_tree_model_set_name>( instance ) );
+       node_attach_name_changed_callback( instance.path().top(), ConstReferenceCaller<scene::Instance, void(const char*), graph_tree_model_set_name>( instance ) );
 }
 
 void graph_tree_model_erase( GraphTreeModel* model, const scene::Instance& instance ){
-       node_detach_name_changed_callback( instance.path().top(), ConstReferenceCaller1<scene::Instance, const char*, graph_tree_model_set_name>( instance ) );
+       node_detach_name_changed_callback( instance.path().top(), ConstReferenceCaller<scene::Instance, void(const char*), graph_tree_model_set_name>( instance ) );
 
        GraphTreeNode* parent = graph_tree_model_find_parent( model, instance.path() );
 
@@ -1263,7 +1272,7 @@ TestGraphTreeModel(){
        rootpath.pop();
        rootpath.pop();
 
-       GtkTreeModel* model = GTK_TREE_MODEL( graph_tree_model_new( &graph ) );
+       auto model = graph_tree_model_new( &graph );
 
        {
                gint n_columns = gtk_tree_model_get_n_columns( model );
@@ -1358,7 +1367,7 @@ TestGraphTreeModel(){
 
        {
                GtkTreeIter iter;
-               GtkTreePath* path = gtk_tree_path_new_from_string( "0" );
+               auto path = ui::TreePath( "0" );
                gtk_tree_model_get_iter( model, &iter, path );
                gtk_tree_path_free( path );
 
@@ -1368,7 +1377,7 @@ TestGraphTreeModel(){
 
        {
                GtkTreeIter iter;
-               GtkTreePath* path = gtk_tree_path_new_from_string( "1" );
+               auto path = ui::TreePath( "1" );
                gtk_tree_model_get_iter( model, &iter, path );
                gtk_tree_path_free( path );
 
@@ -1382,7 +1391,7 @@ TestGraphTreeModel(){
                ++i;
                graph_iterator_write_tree_iter( i, &iter );
 
-               GtkTreePath* path = gtk_tree_model_get_path( model, &iter );
+               auto path = gtk_tree_model_get_path( model, &iter );
 
                gint depth = gtk_tree_path_get_depth( path );
                gint* indices = gtk_tree_path_get_indices( path );
@@ -1399,7 +1408,7 @@ TestGraphTreeModel(){
                ++i;
                graph_iterator_write_tree_iter( i, &iter );
 
-               GtkTreePath* path = gtk_tree_model_get_path( model, &iter );
+               auto path = gtk_tree_model_get_path( model, &iter );
 
                gint depth = gtk_tree_path_get_depth( path );
                gint* indices = gtk_tree_path_get_indices( path );