]> git.xonotic.org Git - xonotic/netradiant.git/commitdiff
Merge commit 'e8686a54bfc307bb810c8a724f914bfff28d7351' into garux-merge
authorThomas Debesse <dev@illwieckz.net>
Mon, 25 May 2020 18:21:45 +0000 (20:21 +0200)
committerThomas Debesse <dev@illwieckz.net>
Mon, 25 May 2020 18:21:45 +0000 (20:21 +0200)
1  2 
radiant/selection.cpp
radiant/xywindow.cpp

diff --combined radiant/selection.cpp
index 1ecd3624affb4cc1ec256850548d85b9cbe58cc7,7f4cdf7a1d0eebadde55ee7fec4de2c29a3e54ad..18334c2090369753e01f1b5f9132e587424f3db8
@@@ -20,7 -20,6 +20,7 @@@
   */
  
  #include "selection.h"
 +#include "globaldefs.h"
  
  #include "debugging/debugging.h"
  
@@@ -157,7 -156,7 +157,7 @@@ inline float angle_between( const Vecto
  }
  
  
 -#if defined( _DEBUG )
 +#if GDEF_DEBUG
  class test_quat
  {
  public:
@@@ -207,7 -206,6 +207,7 @@@ void transform_local2object( Matrix4& o
  class Rotatable
  {
  public:
 +virtual ~Rotatable() = default;
  virtual void rotate( const Quaternion& rotation ) = 0;
  };
  
@@@ -272,7 -270,6 +272,7 @@@ void translation_local2object( Vector3
  class Translatable
  {
  public:
 +virtual ~Translatable() = default;
  virtual void translate( const Vector3& translation ) = 0;
  };
  
@@@ -332,7 -329,6 +332,7 @@@ void Transform( const Matrix4& manip2ob
  class Scalable
  {
  public:
 +virtual ~Scalable() = default;
  virtual void scale( const Vector3& scaling ) = 0;
  };
  
@@@ -467,7 -463,7 +467,7 @@@ void add_one()
  }
  };
  
 -#if defined( _DEBUG )
 +#if GDEF_DEBUG
  #define DEBUG_SELECTION
  #endif
  
@@@ -1723,7 -1719,7 +1723,7 @@@ void insert( const Plane3& plane )
  bool contains( const Plane3& plane ) const {
        return PlaneSet_contains( m_selectedPlanes, plane );
  }
 -typedef MemberCaller1<SelectedPlaneSet, const Plane3&, &SelectedPlaneSet::insert> InsertCaller;
 +typedef MemberCaller<SelectedPlaneSet, void(const Plane3&), &SelectedPlaneSet::insert> InsertCaller;
  };
  
  
@@@ -1982,7 -1978,7 +1982,7 @@@ void TestQuadStrip( const VertexPointer
  class SelectionCounter
  {
  public:
 -typedef const Selectable& first_argument_type;
 +using func = void(const Selectable &);
  
  SelectionCounter( const SelectionChangeCallback& onchanged )
        : m_count( 0 ), m_onchanged( onchanged ){
@@@ -2605,11 -2601,11 +2605,11 @@@ void pivotChanged() const 
        m_pivotChanged = true;
        SceneChangeNotify();
  }
 -typedef ConstMemberCaller<RadiantSelectionSystem, &RadiantSelectionSystem::pivotChanged> PivotChangedCaller;
 +typedef ConstMemberCaller<RadiantSelectionSystem, void(), &RadiantSelectionSystem::pivotChanged> PivotChangedCaller;
  void pivotChangedSelection( const Selectable& selectable ){
        pivotChanged();
  }
 -typedef MemberCaller1<RadiantSelectionSystem, const Selectable&, &RadiantSelectionSystem::pivotChangedSelection> PivotChangedSelectionCaller;
 +typedef MemberCaller<RadiantSelectionSystem, void(const Selectable&), &RadiantSelectionSystem::pivotChangedSelection> PivotChangedSelectionCaller;
  
  void SetMode( EMode mode ){
        if ( m_mode != mode ) {
@@@ -2644,11 -2640,11 +2644,11 @@@ EManipulatorMode ManipulatorMode() cons
  
  SelectionChangeCallback getObserver( EMode mode ){
        if ( mode == ePrimitive ) {
 -              return makeCallback1( m_count_primitive );
 +              return makeCallback( m_count_primitive );
        }
        else
        {
 -              return makeCallback1( m_count_component );
 +              return makeCallback( m_count_component );
        }
  }
  std::size_t countSelected() const {
@@@ -2721,7 -2717,7 +2721,7 @@@ void addSelectionChangeCallback( const 
  void selectionChanged( const Selectable& selectable ){
        m_selectionChanged_callbacks( selectable );
  }
 -typedef MemberCaller1<RadiantSelectionSystem, const Selectable&, &RadiantSelectionSystem::selectionChanged> SelectionChangedCaller;
 +typedef MemberCaller<RadiantSelectionSystem, void(const Selectable&), &RadiantSelectionSystem::selectionChanged> SelectionChangedCaller;
  
  
  void startMove(){
@@@ -2787,13 -2783,8 +2787,8 @@@ void deselectComponentsOrAll( bool comp
  
  void SelectPoint( const View& view, const float device_point[2], const float device_epsilon[2], RadiantSelectionSystem::EModifier modifier, bool face ){
        //globalOutputStream() << device_point[0] << "   " << device_point[1] << "\n";
- #ifdef _DEBUG
        ASSERT_MESSAGE( fabs( device_point[0] ) <= 1.0f && fabs( device_point[1] ) <= 1.0f, "point-selection error" );
- #else
-       if( fabs( device_point[0] ) >= 1.0f || fabs( device_point[1] ) >= 1.0f ){
-               return;
-       }
- #endif
        if ( modifier == eReplace ) {
                deselectComponentsOrAll( face );
        }
                        break;
                        case RadiantSelectionSystem::eSelect:
                        {
-                               ( *selector.begin() ).second->setSelected( true );
+                               if( !( *selector.begin() ).second->isSelected() ){
+                                       ( *selector.begin() ).second->setSelected( true );
+                               }
                        }
                        break;
                        case RadiantSelectionSystem::eDeselect:
                        {
-                               ( *selector.begin() ).second->setSelected( false );
+                               if( ( *selector.begin() ).second->isSelected() ){
+                                       ( *selector.begin() ).second->setSelected( false );
+                               }
                        }
                        break;
                        default:
  }
  
  bool SelectPoint_InitPaint( const View& view, const float device_point[2], const float device_epsilon[2], bool face ){
- #ifdef _DEBUG
        ASSERT_MESSAGE( fabs( device_point[0] ) <= 1.0f && fabs( device_point[1] ) <= 1.0f, "point-selection error" );
- #else
-       if( fabs( device_point[0] ) >= 1.0f || fabs( device_point[1] ) >= 1.0f ){
-               return true;
-       }
- #endif
    #if defined ( DEBUG_SELECTION )
        g_render_clipped.destroy();
    #endif
@@@ -3474,7 -3463,7 +3467,7 @@@ void SelectionSystem_Construct()
  
        g_RadiantSelectionSystem = new RadiantSelectionSystem;
  
 -      SelectionSystem_boundsChanged = GlobalSceneGraph().addBoundsChangedCallback( FreeCaller<SelectionSystem_OnBoundsChanged>() );
 +      SelectionSystem_boundsChanged = GlobalSceneGraph().addBoundsChangedCallback( FreeCaller<void(), SelectionSystem_OnBoundsChanged>() );
  
        GlobalShaderCache().attachRenderable( getSelectionSystem() );
  }
@@@ -3518,7 -3507,7 +3511,7 @@@ inline WindowVector window_constrained
        return WindowVector( window_constrained( window.x(), x, width ), window_constrained( window.y(), y, height ) );
  }
  
 -typedef Callback1<DeviceVector> MouseEventCallback;
 +typedef Callback<void(DeviceVector)> MouseEventCallback;
  
  Single<MouseEventCallback> g_mouseMovedCallback;
  Single<MouseEventCallback> g_mouseUpCallback;
@@@ -3578,12 -3567,13 +3571,13 @@@ DeviceVector m_current
  DeviceVector m_epsilon;
  ModifierFlags m_state;
  bool m_mouse2;
- bool m_paintInitialized;
+ bool m_mouseMoved;
+ bool m_mouseMovedWhilePressed;
  bool m_paintSelect;
  const View* m_view;
  RectangleCallback m_window_update;
  
- Selector_() : m_start( 0.0f, 0.0f ), m_current( 0.0f, 0.0f ), m_state( c_modifierNone ), m_mouse2( false ){
+ Selector_() : m_start( 0.0f, 0.0f ), m_current( 0.0f, 0.0f ), m_state( c_modifierNone ), m_mouse2( false ), m_mouseMoved( false ), m_mouseMovedWhilePressed( false ){
  }
  
  void draw_area(){
@@@ -3596,11 -3586,11 +3590,11 @@@ void testSelect( DeviceVector position 
                DeviceVector delta( position - m_start );
                if ( fabs( delta.x() ) > m_epsilon.x() && fabs( delta.y() ) > m_epsilon.y() ) {
                        DeviceVector delta( position - m_start );
-                       getSelectionSystem().SelectArea( *m_view, &m_start[0], &delta[0], modifier, ( m_state & c_modifier_face ) != c_modifierNone );
+                       //getSelectionSystem().SelectArea( *m_view, &m_start[0], &delta[0], modifier, ( m_state & c_modifier_face ) != c_modifierNone );
+                       getSelectionSystem().SelectArea( *m_view, &m_start[0], &delta[0], RadiantSelectionSystem::eToggle, ( m_state & c_modifier_face ) != c_modifierNone );
                }
-               else
-               {
-                       if ( modifier == RadiantSelectionSystem::eReplace ) {
+               else if( !m_mouseMovedWhilePressed ){
+                       if ( modifier == RadiantSelectionSystem::eReplace && !m_mouseMoved ) {
                                modifier = RadiantSelectionSystem::eCycle;
                        }
                        getSelectionSystem().SelectPoint( *m_view, &position[0], &m_epsilon[0], modifier, ( m_state & c_modifier_face ) != c_modifierNone );
  }
  
  void testSelect_simpleM1( DeviceVector position ){
-       RadiantSelectionSystem::EModifier modifier = RadiantSelectionSystem::eReplace;
+       /*RadiantSelectionSystem::EModifier modifier = RadiantSelectionSystem::eReplace;
        DeviceVector delta( position - m_start );
        if ( fabs( delta.x() ) < m_epsilon.x() && fabs( delta.y() ) < m_epsilon.y() ) {
                modifier = RadiantSelectionSystem::eCycle;
        }
-       getSelectionSystem().SelectPoint( *m_view, &position[0], &m_epsilon[0], modifier, false );
+       getSelectionSystem().SelectPoint( *m_view, &position[0], &m_epsilon[0], modifier, false );*/
+       getSelectionSystem().SelectPoint( *m_view, &position[0], &m_epsilon[0], m_mouseMoved ? RadiantSelectionSystem::eReplace : RadiantSelectionSystem::eCycle, false );
        m_start = m_current = device_constrained( position );
  }
  
  
  bool selecting() const {
-       return m_state != c_modifier_manipulator && !m_mouse2;
+       return m_state != c_modifier_manipulator && m_mouse2;
  }
  
  void setState( ModifierFlags state ){
@@@ -3647,31 -3638,27 +3642,27 @@@ void modifierDisable( ModifierFlags typ
  
  void mouseDown( DeviceVector position ){
        m_start = m_current = device_constrained( position );
-       m_paintInitialized = false;
+       if( !m_mouse2 && m_state != c_modifierNone ){
+               m_paintSelect = getSelectionSystem().SelectPoint_InitPaint( *m_view, &position[0], &m_epsilon[0], ( m_state & c_modifier_face ) != c_modifierNone );
+       }
  }
  
  void mouseMoved( DeviceVector position ){
        m_current = device_constrained( position );
-       if( !m_mouse2 ){
+       m_mouseMovedWhilePressed = true;
+       if( m_mouse2 ){
                draw_area();
        }
-       else if( m_paintInitialized ){
-               getSelectionSystem().SelectPoint( *m_view, &position[0], &m_epsilon[0],
+       else if( m_state != c_modifier_manipulator ){
+               getSelectionSystem().SelectPoint( *m_view, &m_current[0], &m_epsilon[0],
                                                                                m_paintSelect ? RadiantSelectionSystem::eSelect : RadiantSelectionSystem::eDeselect,
                                                                                ( m_state & c_modifier_face ) != c_modifierNone );
        }
-       else{
-               DeviceVector delta( position - m_start );
-               if ( fabs( delta.x() ) > m_epsilon.x() || fabs( delta.y() ) > m_epsilon.y() ) {
-                       m_paintSelect = getSelectionSystem().SelectPoint_InitPaint( *m_view, &position[0], &m_epsilon[0], ( m_state & c_modifier_face ) != c_modifierNone );
-                       m_paintInitialized = true;
-               }
-       }
  }
 -typedef MemberCaller1<Selector_, DeviceVector, &Selector_::mouseMoved> MouseMovedCaller;
 +typedef MemberCaller<Selector_, void(DeviceVector), &Selector_::mouseMoved> MouseMovedCaller;
  
  void mouseUp( DeviceVector position ){
-       if( !m_paintInitialized ){
+       if( m_mouse2 ){
                testSelect( device_constrained( position ) );
        }
        else{
        g_mouseMovedCallback.clear();
        g_mouseUpCallback.clear();
  }
 -typedef MemberCaller1<Selector_, DeviceVector, &Selector_::mouseUp> MouseUpCaller;
 +typedef MemberCaller<Selector_, void(DeviceVector), &Selector_::mouseUp> MouseUpCaller;
  };
  
  
@@@ -3698,14 -3685,14 +3689,14 @@@ bool mouseDown( DeviceVector position )
  void mouseMoved( DeviceVector position ){
        getSelectionSystem().MoveSelected( *m_view, &position[0] );
  }
 -typedef MemberCaller1<Manipulator_, DeviceVector, &Manipulator_::mouseMoved> MouseMovedCaller;
 +typedef MemberCaller<Manipulator_, void(DeviceVector), &Manipulator_::mouseMoved> MouseMovedCaller;
  
  void mouseUp( DeviceVector position ){
        getSelectionSystem().endMove();
        g_mouseMovedCallback.clear();
        g_mouseUpCallback.clear();
  }
 -typedef MemberCaller1<Manipulator_, DeviceVector, &Manipulator_::mouseUp> MouseUpCaller;
 +typedef MemberCaller<Manipulator_, void(DeviceVector), &Manipulator_::mouseUp> MouseUpCaller;
  };
  
  void Scene_copyClosestTexture( SelectionTest& test );
@@@ -3748,6 -3735,7 +3739,7 @@@ void onSizeChanged( int width, int heig
  void onMouseDown( const WindowVector& position, ButtonIdentifier button, ModifierFlags modifiers ){
        if ( button == c_button_select || ( button == c_button_select2 && modifiers != c_modifierNone ) ) {
                m_mouse_down = true;
+               //m_selector.m_mouseMoved = false;
  
                DeviceVector devicePosition( window_to_normalised_device( position, m_width, m_height ) );
                if ( modifiers == c_modifier_manipulator && m_manipulator.mouseDown( devicePosition ) ) {
                }
                else
                {
-                       m_selector.mouseDown( devicePosition );
                        if ( button == c_button_select ) {
                                m_selector.m_mouse2 = false;
                        }
                        else{
                                m_selector.m_mouse2 = true;
                        }
+                       m_selector.mouseDown( devicePosition );
                        g_mouseMovedCallback.insert( MouseEventCallback( Selector_::MouseMovedCaller( m_selector ) ) );
                        g_mouseUpCallback.insert( MouseEventCallback( Selector_::MouseUpCaller( m_selector ) ) );
                }
        }
  }
  void onMouseMotion( const WindowVector& position, ModifierFlags modifiers ){
+       m_selector.m_mouseMoved = true;
        if ( m_mouse_down && !g_mouseMovedCallback.empty() ) {
                g_mouseMovedCallback.get() ( window_to_normalised_device( position, m_width, m_height ) );
        }
@@@ -3795,10 -3784,13 +3788,13 @@@ void onMouseUp( const WindowVector& pos
        }
        //L button w/o scene changed = tunnel selection
        if( !getSelectionSystem().m_undo_begun && modifiers == c_modifierNone && button == c_button_select &&
+               //( !m_selector.m_mouseMoved || !m_mouse_down ) &&
                ( GlobalSelectionSystem().Mode() != SelectionSystem::eComponent || GlobalSelectionSystem().ManipulatorMode() != SelectionSystem::eDrag ) ){
-               m_selector.testSelect_simpleM1( window_to_normalised_device( position, m_width, m_height ) );
+               m_selector.testSelect_simpleM1( device_constrained( window_to_normalised_device( position, m_width, m_height ) ) );
        }
        getSelectionSystem().m_undo_begun = false;
+       m_selector.m_mouseMoved = false;
+       m_selector.m_mouseMovedWhilePressed = false;
  }
  void onModifierDown( ModifierFlags type ){
        m_selector.modifierEnable( type );
diff --combined radiant/xywindow.cpp
index 85f77eb531d5e9b0a2b3700eb6c2edc90e1ef63c,9ab1861e06771d56d159115f6c76dbca7f5abd08..f1cb57fdbf8a47203516ebe0294d1bf850f1b915
@@@ -27,8 -27,6 +27,8 @@@
  
  #include "xywindow.h"
  
 +#include <gtk/gtk.h>
 +
  #include "debugging/debugging.h"
  
  #include "ientity.h"
@@@ -41,8 -39,8 +41,8 @@@
  #include "image.h"
  #include "gtkutil/messagebox.h"
  
 -#include <gtk/gtklabel.h>
 -#include <gtk/gtkmenuitem.h>
 +#include <uilib/uilib.h>
 +#include <gdk/gdkkeysyms.h>
  
  #include "generic/callback.h"
  #include "string/string.h"
@@@ -357,8 -355,6 +357,8 @@@ struct xywindow_globals_private_
        bool m_bChaseMouse;
        bool m_bSizePaint;
  
 +      bool g_bCrossHairs;
 +
        xywindow_globals_private_t() :
                d_showgrid( true ),
  
  
                m_bCamXYUpdate( true ),
                m_bChaseMouse( true ),
 -              m_bSizePaint( true ){
 +              m_bSizePaint( true ),
 +
 +              g_bCrossHairs( false ){
        }
  
  };
@@@ -425,7 -419,6 +425,7 @@@ inline unsigned int buttons_for_button_
  
        switch ( button.get() )
        {
 +    case ButtonEnumeration::INVALID: break;
        case ButtonEnumeration::LEFT: buttons |= RAD_LBUTTON; break;
        case ButtonEnumeration::MIDDLE: buttons |= RAD_MBUTTON; break;
        case ButtonEnumeration::RIGHT: buttons |= RAD_RBUTTON; break;
@@@ -564,7 -557,9 +564,7 @@@ VIEWTYPE GlobalXYWnd_getCurrentViewType
  // =============================================================================
  // variables
  
 -bool g_bCrossHairs = false;
 -
 -GtkMenu* XYWnd::m_mnuDrop = 0;
 +ui::Menu XYWnd::m_mnuDrop(ui::null);
  
  // this is disabled, and broken
  // http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=394
@@@ -576,7 -571,7 +576,7 @@@ void WXY_Print()
        unsigned char* img;
        const char* filename;
  
 -      filename = file_dialog( GTK_WIDGET( MainFrame_getWindow() ), FALSE, "Save Image", 0, FILTER_BMP );
 +      filename = ui::file_dialog( MainFrame_getWindow( ), FALSE, "Save Image", 0, FILTER_BMP );
        if ( !filename ) {
                return;
        }
@@@ -733,7 -728,7 +733,7 @@@ bool XYWnd::chaseMouseMotion( int point
  Shader* XYWnd::m_state_selected = 0;
  
  void xy_update_xor_rectangle( XYWnd& self, rect_t area ){
 -      if ( GTK_WIDGET_VISIBLE( self.GetWidget() ) ) {
 +      if ( self.GetWidget().visible() ) {
                rectangle_t rect = rectangle_from_area( area.min, area.max, self.Width(), self.Height() );
                int nDim1 = ( self.GetViewType() == YZ ) ? 1 : 0;
                int nDim2 = ( self.GetViewType() == XY ) ? 1 : 2;
        }
  }
  
 -gboolean xywnd_button_press( GtkWidget* widget, GdkEventButton* event, XYWnd* xywnd ){
 +gboolean xywnd_button_press( ui::Widget widget, GdkEventButton* event, XYWnd* xywnd ){
        if ( event->type == GDK_BUTTON_PRESS ) {
                g_pParentWnd->SetActiveXY( xywnd );
  
        return FALSE;
  }
  
 -gboolean xywnd_button_release( GtkWidget* widget, GdkEventButton* event, XYWnd* xywnd ){
 +gboolean xywnd_button_release( ui::Widget widget, GdkEventButton* event, XYWnd* xywnd ){
        if ( event->type == GDK_BUTTON_RELEASE ) {
                xywnd->XY_MouseUp( static_cast<int>( event->x ), static_cast<int>( event->y ), buttons_for_event_button( event ) );
  
        return FALSE;
  }
  
 -gboolean xywnd_focus_in( GtkWidget* widget, GdkEventFocus* event, XYWnd* xywnd ){
 +gboolean xywnd_focus_in( ui::Widget widget, GdkEventFocus* event, XYWnd* xywnd ){
        if ( event->type == GDK_FOCUS_CHANGE ) {
                if ( event->in ) {
                        g_pParentWnd->SetActiveXY( xywnd );
@@@ -783,7 -778,7 +783,7 @@@ void xywnd_motion( gdouble x, gdouble y
        reinterpret_cast<XYWnd*>( data )->XY_MouseMoved( static_cast<int>( x ), static_cast<int>( y ), buttons_for_state( state ) );
  }
  
 -gboolean xywnd_wheel_scroll( GtkWidget* widget, GdkEventScroll* event, XYWnd* xywnd ){
 +gboolean xywnd_wheel_scroll( ui::Widget widget, GdkEventScroll* event, XYWnd* xywnd ){
        if ( event->direction == GDK_SCROLL_UP ) {
                xywnd->ZoomInWithMouse( (int)event->x, (int)event->y );
        }
        return FALSE;
  }
  
 -gboolean xywnd_size_allocate( GtkWidget* widget, GtkAllocation* allocation, XYWnd* xywnd ){
 +gboolean xywnd_size_allocate( ui::Widget widget, GtkAllocation* allocation, XYWnd* xywnd ){
        xywnd->m_nWidth = allocation->width;
        xywnd->m_nHeight = allocation->height;
        xywnd->updateProjection();
        return FALSE;
  }
  
 -gboolean xywnd_expose( GtkWidget* widget, GdkEventExpose* event, XYWnd* xywnd ){
 +gboolean xywnd_expose( ui::Widget widget, GdkEventExpose* event, XYWnd* xywnd ){
        if ( glwidget_make_current( xywnd->GetWidget() ) != FALSE ) {
                if ( Map_Valid( g_map ) && ScreenUpdates_Enabled() ) {
                        GlobalOpenGL_debugAssertNoErrors();
@@@ -824,9 -819,9 +824,9 @@@ void XYWnd_CameraMoved( XYWnd& xywnd )
  
  XYWnd::XYWnd() :
        m_gl_widget( glwidget_new( FALSE ) ),
 -      m_deferredDraw( WidgetQueueDrawCaller( *m_gl_widget ) ),
 +      m_deferredDraw( WidgetQueueDrawCaller( m_gl_widget ) ),
        m_deferred_motion( xywnd_motion, this ),
 -      m_parent( 0 ),
 +      m_parent( ui::null ),
        m_window_observer( NewWindowObserver() ),
        m_XORRectangle( m_gl_widget ),
        m_chasemouse_handler( 0 ){
  
        m_entityCreate = false;
  
 -      m_mnuDrop = 0;
 +      m_mnuDrop = ui::Menu(ui::null);
  
        GlobalWindowObservers_add( m_window_observer );
        GlobalWindowObservers_connectWidget( m_gl_widget );
  
 -      m_window_observer->setRectangleDrawCallback( ReferenceCaller1<XYWnd, rect_t, xy_update_xor_rectangle>( *this ) );
 +      m_window_observer->setRectangleDrawCallback( ReferenceCaller<XYWnd, void(rect_t), xy_update_xor_rectangle>( *this ) );
        m_window_observer->setView( m_view );
  
 -      gtk_widget_ref( m_gl_widget );
 +      g_object_ref( m_gl_widget._handle );
  
        gtk_widget_set_events( m_gl_widget, GDK_DESTROY | GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK | GDK_SCROLL_MASK );
 -      GTK_WIDGET_SET_FLAGS( m_gl_widget, GTK_CAN_FOCUS );
 +      gtk_widget_set_can_focus( m_gl_widget, true );
  
 -      m_sizeHandler = g_signal_connect( G_OBJECT( m_gl_widget ), "size_allocate", G_CALLBACK( xywnd_size_allocate ), this );
 -      m_exposeHandler = g_signal_connect( G_OBJECT( m_gl_widget ), "expose_event", G_CALLBACK( xywnd_expose ), this );
 +      m_sizeHandler = m_gl_widget.connect( "size_allocate", G_CALLBACK( xywnd_size_allocate ), this );
 +      m_exposeHandler = m_gl_widget.on_render( G_CALLBACK( xywnd_expose ), this );
  
 -      g_signal_connect( G_OBJECT( m_gl_widget ), "button_press_event", G_CALLBACK( xywnd_button_press ), this );
 -      g_signal_connect( G_OBJECT( m_gl_widget ), "button_release_event", G_CALLBACK( xywnd_button_release ), this );
 -      g_signal_connect( G_OBJECT( m_gl_widget ), "focus_in_event", G_CALLBACK( xywnd_focus_in ), this );
 -      g_signal_connect( G_OBJECT( m_gl_widget ), "motion_notify_event", G_CALLBACK( DeferredMotion::gtk_motion ), &m_deferred_motion );
 +      m_gl_widget.connect( "button_press_event", G_CALLBACK( xywnd_button_press ), this );
 +      m_gl_widget.connect( "button_release_event", G_CALLBACK( xywnd_button_release ), this );
 +      m_gl_widget.connect( "focus_in_event", G_CALLBACK( xywnd_focus_in ), this );
 +      m_gl_widget.connect( "motion_notify_event", G_CALLBACK( DeferredMotion::gtk_motion ), &m_deferred_motion );
  
 -      g_signal_connect( G_OBJECT( m_gl_widget ), "scroll_event", G_CALLBACK( xywnd_wheel_scroll ), this );
 +      m_gl_widget.connect( "scroll_event", G_CALLBACK( xywnd_wheel_scroll ), this );
  
        Map_addValidCallback( g_map, DeferredDrawOnMapValidChangedCaller( m_deferredDraw ) );
  
        updateProjection();
        updateModelview();
  
 -      AddSceneChangeCallback( ReferenceCaller<XYWnd, &XYWnd_Update>( *this ) );
 -      AddCameraMovedCallback( ReferenceCaller<XYWnd, &XYWnd_CameraMoved>( *this ) );
 +      AddSceneChangeCallback( ReferenceCaller<XYWnd, void(), &XYWnd_Update>( *this ) );
 +      AddCameraMovedCallback( ReferenceCaller<XYWnd, void(), &XYWnd_CameraMoved>( *this ) );
  
        PressedButtons_connect( g_pressedButtons, m_gl_widget );
  
  XYWnd::~XYWnd(){
        onDestroyed();
  
 -      if ( m_mnuDrop != 0 ) {
 -              gtk_widget_destroy( GTK_WIDGET( m_mnuDrop ) );
 -              m_mnuDrop = 0;
 +      if ( m_mnuDrop ) {
 +              m_mnuDrop.destroy();
 +              m_mnuDrop = ui::Menu(ui::null);
        }
  
        g_signal_handler_disconnect( G_OBJECT( m_gl_widget ), m_sizeHandler );
        g_signal_handler_disconnect( G_OBJECT( m_gl_widget ), m_exposeHandler );
  
 -      gtk_widget_unref( m_gl_widget );
 +      m_gl_widget.unref();
  
        m_window_observer->release();
  }
@@@ -938,7 -933,7 +938,7 @@@ unsigned int Clipper_buttons()
  }
  
  unsigned int Clipper_quick_buttons(){
-       return RAD_RBUTTON | RAD_CONTROL;
+       return RAD_LBUTTON | RAD_CONTROL;
  }
  
  void XYWnd::DropClipPoint( int pointx, int pointy ){
@@@ -985,12 -980,12 +985,12 @@@ void XYWnd::Clipper_Crosshair_OnMouseMo
        if ( ClipMode() && GlobalClipPoints_Find( mousePosition, (VIEWTYPE)m_viewType, m_fScale ) != 0 ) {
                GdkCursor *cursor;
                cursor = gdk_cursor_new( GDK_CROSSHAIR );
 -              gdk_window_set_cursor( m_gl_widget->window, cursor );
 +              gdk_window_set_cursor( gtk_widget_get_window(m_gl_widget), cursor );
                gdk_cursor_unref( cursor );
        }
        else
        {
 -              gdk_window_set_cursor( m_gl_widget->window, 0 );
 +              gdk_window_set_cursor( gtk_widget_get_window(m_gl_widget), 0 );
        }
  }
  
@@@ -1099,15 -1094,15 +1099,15 @@@ void XYWnd::NewBrushDrag( int x, int y 
                                                                "textures/common/caulk" : TextureBrowser_GetSelectedShader( GlobalTextureBrowser() ) );
  }
  
 -void entitycreate_activated( GtkWidget* item ){
 +void entitycreate_activated( ui::Widget item ){
        scene::Node* world_node = Map_FindWorldspawn( g_map );
 -      const char* entity_name = gtk_label_get_text( GTK_LABEL( GTK_BIN( item )->child ) );
 +      const char* entity_name = gtk_label_get_text( GTK_LABEL( gtk_bin_get_child(GTK_BIN( item )) ) );
  
        if ( !( world_node && string_equal( entity_name, "worldspawn" ) ) ) {
                g_pParentWnd->ActiveXY()->OnEntityCreate( entity_name );
        }
        else {
 -              GlobalRadiant().m_pfnMessageBox( GTK_WIDGET( MainFrame_getWindow() ), "There's already a worldspawn in your map!"
 +              GlobalRadiant().m_pfnMessageBox( MainFrame_getWindow(), "There's already a worldspawn in your map!"
                                                                                                                                                          "",
                                                                                 "Info",
                                                                                 eMB_OK,
        }
  }
  
 -void EntityClassMenu_addItem( GtkMenu* menu, const char* name ){
 -      GtkMenuItem* item = GTK_MENU_ITEM( gtk_menu_item_new_with_label( name ) );
 -      g_signal_connect( G_OBJECT( item ), "activate", G_CALLBACK( entitycreate_activated ), item );
 -      gtk_widget_show( GTK_WIDGET( item ) );
 +void EntityClassMenu_addItem( ui::Menu menu, const char* name ){
 +      auto item = ui::MenuItem( name );
 +      item.connect( "activate", G_CALLBACK( entitycreate_activated ), item );
 +      item.show();
        menu_add_item( menu, item );
  }
  
  class EntityClassMenuInserter : public EntityClassVisitor
  {
 -typedef std::pair<GtkMenu*, CopiedString> MenuPair;
 +typedef std::pair<ui::Menu, CopiedString> MenuPair;
  typedef std::vector<MenuPair> MenuStack;
  MenuStack m_stack;
  CopiedString m_previous;
  public:
 -EntityClassMenuInserter( GtkMenu* menu ){
 +EntityClassMenuInserter( ui::Menu menu ){
        m_stack.reserve( 2 );
        m_stack.push_back( MenuPair( menu, "" ) );
  }
@@@ -1146,12 -1141,12 +1146,12 @@@ void visit( EntityClass* e )
        m_previous = e->name();
  }
  void pushMenu( const CopiedString& name ){
 -      GtkMenuItem* item = GTK_MENU_ITEM( gtk_menu_item_new_with_label( name.c_str() ) );
 -      gtk_widget_show( GTK_WIDGET( item ) );
 -      container_add_widget( GTK_CONTAINER( m_stack.back().first ), GTK_WIDGET( item ) );
 +      auto item = ui::MenuItem( name.c_str() );
 +      item.show();
 +      m_stack.back().first.add(item);
  
 -      GtkMenu* submenu = GTK_MENU( gtk_menu_new() );
 -      gtk_menu_item_set_submenu( item, GTK_WIDGET( submenu ) );
 +      auto submenu = ui::Menu(ui::New);
 +      gtk_menu_item_set_submenu( item, submenu  );
  
        m_stack.push_back( MenuPair( submenu, name ) );
  }
@@@ -1192,8 -1187,8 +1192,8 @@@ void XYWnd::OnContextMenu()
                return;
        }
  
 -      if ( m_mnuDrop == 0 ) { // first time, load it up
 -              GtkMenu* menu = m_mnuDrop = GTK_MENU( gtk_menu_new() );
 +      if ( !m_mnuDrop ) { // first time, load it up
 +              auto menu = m_mnuDrop = ui::Menu(ui::New);
  
                EntityClassMenuInserter inserter( menu );
                GlobalEntityClassManager().forEach( inserter );
@@@ -1213,7 -1208,7 +1213,7 @@@ void XYWnd_moveDelta( int x, int y, uns
        reinterpret_cast<XYWnd*>( data )->Scroll( -x, y );
  }
  
 -gboolean XYWnd_Move_focusOut( GtkWidget* widget, GdkEventFocus* event, XYWnd* xywnd ){
 +gboolean XYWnd_Move_focusOut( ui::Widget widget, GdkEventFocus* event, XYWnd* xywnd ){
        xywnd->Move_End();
        return FALSE;
  }
@@@ -1223,13 -1218,13 +1223,13 @@@ void XYWnd::Move_Begin()
                Move_End();
        }
        m_move_started = true;
 -      g_xywnd_freezePointer.freeze_pointer( m_parent != 0 ? m_parent : MainFrame_getWindow(), m_gl_widget, XYWnd_moveDelta, this );
 -      m_move_focusOut = g_signal_connect( G_OBJECT( m_gl_widget ), "focus_out_event", G_CALLBACK( XYWnd_Move_focusOut ), this );
 +      g_xywnd_freezePointer.freeze_pointer( m_parent  ? m_parent : MainFrame_getWindow(), m_gl_widget, XYWnd_moveDelta, this );
 +      m_move_focusOut = m_gl_widget.connect( "focus_out_event", G_CALLBACK( XYWnd_Move_focusOut ), this );
  }
  
  void XYWnd::Move_End(){
        m_move_started = false;
 -      g_xywnd_freezePointer.unfreeze_pointer( m_parent != 0 ? m_parent : MainFrame_getWindow() );
 +      g_xywnd_freezePointer.unfreeze_pointer( m_parent ? m_parent : MainFrame_getWindow() );
        g_signal_handler_disconnect( G_OBJECT( m_gl_widget ), m_move_focusOut );
  }
  
@@@ -1257,7 -1252,7 +1257,7 @@@ void XYWnd_zoomDelta( int x, int y, uns
        }
  }
  
 -gboolean XYWnd_Zoom_focusOut( GtkWidget* widget, GdkEventFocus* event, XYWnd* xywnd ){
 +gboolean XYWnd_Zoom_focusOut( ui::Widget widget, GdkEventFocus* event, XYWnd* xywnd ){
        xywnd->Zoom_End();
        return FALSE;
  }
@@@ -1268,13 -1263,13 +1268,13 @@@ void XYWnd::Zoom_Begin()
        }
        m_zoom_started = true;
        g_dragZoom = 0;
 -      g_xywnd_freezePointer.freeze_pointer( m_parent != 0 ? m_parent : MainFrame_getWindow(), m_gl_widget, XYWnd_zoomDelta, this );
 -      m_zoom_focusOut = g_signal_connect( G_OBJECT( m_gl_widget ), "focus_out_event", G_CALLBACK( XYWnd_Zoom_focusOut ), this );
 +      g_xywnd_freezePointer.freeze_pointer( m_parent ? m_parent : MainFrame_getWindow(), m_gl_widget, XYWnd_zoomDelta, this );
 +      m_zoom_focusOut = m_gl_widget.connect( "focus_out_event", G_CALLBACK( XYWnd_Zoom_focusOut ), this );
  }
  
  void XYWnd::Zoom_End(){
        m_zoom_started = false;
 -      g_xywnd_freezePointer.unfreeze_pointer( m_parent != 0 ? m_parent : MainFrame_getWindow() );
 +      g_xywnd_freezePointer.unfreeze_pointer( m_parent ? m_parent : MainFrame_getWindow() );
        g_signal_handler_disconnect( G_OBJECT( m_gl_widget ), m_zoom_focusOut );
  }
  
@@@ -1295,7 -1290,7 +1295,7 @@@ void XYWnd::SetViewType( VIEWTYPE viewT
        m_viewType = viewType;
        updateModelview();
  
 -      if ( m_parent != 0 ) {
 +      if ( m_parent ) {
                gtk_window_set_title( m_parent, ViewType_getTitle( m_viewType ) );
        }
  }
@@@ -1406,7 -1401,7 +1406,7 @@@ void XYWnd::XY_MouseMoved( int x, int y
                           << "  z:: " << FloatFormat( m_mousePosition[2], 6, 1 );
                g_pParentWnd->SetStatusText( g_pParentWnd->m_position_status, status.c_str() );
  
 -              if ( g_bCrossHairs ) {
 +              if ( g_xywindow_globals_private.g_bCrossHairs ) {
                        XYWnd_Update( *this );
                }
  
@@@ -1534,12 -1529,12 +1534,12 @@@ void XYWnd::XY_DisableBackground( void 
  void WXY_BackgroundSelect( void ){
        bool brushesSelected = Scene_countSelectedBrushes( GlobalSceneGraph() ) != 0;
        if ( !brushesSelected ) {
 -              gtk_MessageBox( 0, "You have to select some brushes to get the bounding box for.\n",
 -                                              "No selection", eMB_OK, eMB_ICONERROR );
 +              ui::alert( ui::root, "You have to select some brushes to get the bounding box for.\n",
 +                                              "No selection", ui::alert_type::OK, ui::alert_icon::Error );
                return;
        }
  
 -      const char *filename = file_dialog( GTK_WIDGET( MainFrame_getWindow() ), TRUE, "Background Image", NULL, NULL );
 +      const char *filename = MainFrame_getWindow().file_dialog( TRUE, "Background Image", NULL, NULL );
        g_pParentWnd->ActiveXY()->XY_DisableBackground();
        if ( filename ) {
                g_pParentWnd->ActiveXY()->XY_LoadBackgroundImage( filename );
@@@ -2113,7 -2108,7 +2113,7 @@@ void SetState( Shader* state, EStyle st
                m_state_stack.back().m_state = state;
        }
  }
 -const EStyle getStyle() const {
 +EStyle getStyle() const {
        return eWireframeOnly;
  }
  void PushState(){
@@@ -2340,7 -2335,7 +2340,7 @@@ void XYWnd::XY_Draw()
                PaintSizeInfo( nDim1, nDim2, min, max );
        }
  
 -      if ( g_bCrossHairs ) {
 +      if ( g_xywindow_globals_private.g_bCrossHairs ) {
                glColor4f( 0.2f, 0.9f, 0.2f, 0.8f );
                glBegin( GL_LINES );
                if ( m_viewType == XY ) {
@@@ -2570,7 -2565,7 +2570,7 @@@ void XY_ZoomOut()
  
  
  void ToggleShowCrosshair(){
 -      g_bCrossHairs ^= 1;
 +      g_xywindow_globals_private.g_bCrossHairs ^= 1;
        XY_UpdateAllWindows();
  }
  
@@@ -2586,20 -2581,20 +2586,20 @@@ void ToggleShowGrid()
  
  ToggleShown g_xy_top_shown( true );
  
 -void XY_Top_Shown_Construct( GtkWindow* parent ){
 -      g_xy_top_shown.connect( GTK_WIDGET( parent ) );
 +void XY_Top_Shown_Construct( ui::Window parent ){
 +      g_xy_top_shown.connect( parent );
  }
  
  ToggleShown g_yz_side_shown( false );
  
 -void YZ_Side_Shown_Construct( GtkWindow* parent ){
 -      g_yz_side_shown.connect( GTK_WIDGET( parent ) );
 +void YZ_Side_Shown_Construct( ui::Window parent ){
 +      g_yz_side_shown.connect( parent );
  }
  
  ToggleShown g_xz_front_shown( false );
  
 -void XZ_Front_Shown_Construct( GtkWindow* parent ){
 -      g_xz_front_shown.connect( GTK_WIDGET( parent ) );
 +void XZ_Front_Shown_Construct( ui::Window parent ){
 +      g_xz_front_shown.connect( parent );
  }
  
  
@@@ -2615,9 -2610,9 +2615,9 @@@ void realise()
  }
  void unrealise(){
        if ( ++m_unrealised == 1 ) {
 -              if ( XYWnd::m_mnuDrop != 0 ) {
 -                      gtk_widget_destroy( GTK_WIDGET( XYWnd::m_mnuDrop ) );
 -                      XYWnd::m_mnuDrop = 0;
 +              if ( XYWnd::m_mnuDrop ) {
 +                      XYWnd::m_mnuDrop.destroy();
 +                      XYWnd::m_mnuDrop = ui::Menu(ui::null);
                }
        }
  }
@@@ -2632,98 -2627,98 +2632,98 @@@ void ShowNamesToggle()
        GlobalEntityCreator().setShowNames( !GlobalEntityCreator().getShowNames() );
        XY_UpdateAllWindows();
  }
 -typedef FreeCaller<ShowNamesToggle> ShowNamesToggleCaller;
 -void ShowNamesExport( const BoolImportCallback& importer ){
 +typedef FreeCaller<void(), ShowNamesToggle> ShowNamesToggleCaller;
 +void ShowNamesExport( const Callback<void(bool)> & importer ){
        importer( GlobalEntityCreator().getShowNames() );
  }
 -typedef FreeCaller1<const BoolImportCallback&, ShowNamesExport> ShowNamesExportCaller;
 +typedef FreeCaller<void(const Callback<void(bool)> &), ShowNamesExport> ShowNamesExportCaller;
  
  void ShowAnglesToggle(){
        GlobalEntityCreator().setShowAngles( !GlobalEntityCreator().getShowAngles() );
        XY_UpdateAllWindows();
  }
 -typedef FreeCaller<ShowAnglesToggle> ShowAnglesToggleCaller;
 -void ShowAnglesExport( const BoolImportCallback& importer ){
 +typedef FreeCaller<void(), ShowAnglesToggle> ShowAnglesToggleCaller;
 +void ShowAnglesExport( const Callback<void(bool)> & importer ){
        importer( GlobalEntityCreator().getShowAngles() );
  }
 -typedef FreeCaller1<const BoolImportCallback&, ShowAnglesExport> ShowAnglesExportCaller;
 +typedef FreeCaller<void(const Callback<void(bool)> &), ShowAnglesExport> ShowAnglesExportCaller;
  
  void ShowBlocksToggle(){
        g_xywindow_globals_private.show_blocks ^= 1;
        XY_UpdateAllWindows();
  }
 -typedef FreeCaller<ShowBlocksToggle> ShowBlocksToggleCaller;
 -void ShowBlocksExport( const BoolImportCallback& importer ){
 +typedef FreeCaller<void(), ShowBlocksToggle> ShowBlocksToggleCaller;
 +void ShowBlocksExport( const Callback<void(bool)> & importer ){
        importer( g_xywindow_globals_private.show_blocks );
  }
 -typedef FreeCaller1<const BoolImportCallback&, ShowBlocksExport> ShowBlocksExportCaller;
 +typedef FreeCaller<void(const Callback<void(bool)> &), ShowBlocksExport> ShowBlocksExportCaller;
  
  void ShowCoordinatesToggle(){
        g_xywindow_globals_private.show_coordinates ^= 1;
        XY_UpdateAllWindows();
  }
 -typedef FreeCaller<ShowCoordinatesToggle> ShowCoordinatesToggleCaller;
 -void ShowCoordinatesExport( const BoolImportCallback& importer ){
 +typedef FreeCaller<void(), ShowCoordinatesToggle> ShowCoordinatesToggleCaller;
 +void ShowCoordinatesExport( const Callback<void(bool)> & importer ){
        importer( g_xywindow_globals_private.show_coordinates );
  }
 -typedef FreeCaller1<const BoolImportCallback&, ShowCoordinatesExport> ShowCoordinatesExportCaller;
 +typedef FreeCaller<void(const Callback<void(bool)> &), ShowCoordinatesExport> ShowCoordinatesExportCaller;
  
  void ShowOutlineToggle(){
        g_xywindow_globals_private.show_outline ^= 1;
        XY_UpdateAllWindows();
  }
 -typedef FreeCaller<ShowOutlineToggle> ShowOutlineToggleCaller;
 -void ShowOutlineExport( const BoolImportCallback& importer ){
 +typedef FreeCaller<void(), ShowOutlineToggle> ShowOutlineToggleCaller;
 +void ShowOutlineExport( const Callback<void(bool)> & importer ){
        importer( g_xywindow_globals_private.show_outline );
  }
 -typedef FreeCaller1<const BoolImportCallback&, ShowOutlineExport> ShowOutlineExportCaller;
 +typedef FreeCaller<void(const Callback<void(bool)> &), ShowOutlineExport> ShowOutlineExportCaller;
  
  void ShowAxesToggle(){
        g_xywindow_globals_private.show_axis ^= 1;
        XY_UpdateAllWindows();
  }
 -typedef FreeCaller<ShowAxesToggle> ShowAxesToggleCaller;
 -void ShowAxesExport( const BoolImportCallback& importer ){
 +typedef FreeCaller<void(), ShowAxesToggle> ShowAxesToggleCaller;
 +void ShowAxesExport( const Callback<void(bool)> & importer ){
        importer( g_xywindow_globals_private.show_axis );
  }
 -typedef FreeCaller1<const BoolImportCallback&, ShowAxesExport> ShowAxesExportCaller;
 +typedef FreeCaller<void(const Callback<void(bool)> &), ShowAxesExport> ShowAxesExportCaller;
  
  void ShowWorkzoneToggle(){
        g_xywindow_globals_private.d_show_work ^= 1;
        XY_UpdateAllWindows();
  }
 -typedef FreeCaller<ShowWorkzoneToggle> ShowWorkzoneToggleCaller;
 -void ShowWorkzoneExport( const BoolImportCallback& importer ){
 +typedef FreeCaller<void(), ShowWorkzoneToggle> ShowWorkzoneToggleCaller;
 +void ShowWorkzoneExport( const Callback<void(bool)> & importer ){
        importer( g_xywindow_globals_private.d_show_work );
  }
 -typedef FreeCaller1<const BoolImportCallback&, ShowWorkzoneExport> ShowWorkzoneExportCaller;
 +typedef FreeCaller<void(const Callback<void(bool)> &), ShowWorkzoneExport> ShowWorkzoneExportCaller;
  
  ShowNamesExportCaller g_show_names_caller;
 -BoolExportCallback g_show_names_callback( g_show_names_caller );
 +Callback<void(const Callback<void(bool)> &)> g_show_names_callback( g_show_names_caller );
  ToggleItem g_show_names( g_show_names_callback );
  
  ShowAnglesExportCaller g_show_angles_caller;
 -BoolExportCallback g_show_angles_callback( g_show_angles_caller );
 +Callback<void(const Callback<void(bool)> &)> g_show_angles_callback( g_show_angles_caller );
  ToggleItem g_show_angles( g_show_angles_callback );
  
  ShowBlocksExportCaller g_show_blocks_caller;
 -BoolExportCallback g_show_blocks_callback( g_show_blocks_caller );
 +Callback<void(const Callback<void(bool)> &)> g_show_blocks_callback( g_show_blocks_caller );
  ToggleItem g_show_blocks( g_show_blocks_callback );
  
  ShowCoordinatesExportCaller g_show_coordinates_caller;
 -BoolExportCallback g_show_coordinates_callback( g_show_coordinates_caller );
 +Callback<void(const Callback<void(bool)> &)> g_show_coordinates_callback( g_show_coordinates_caller );
  ToggleItem g_show_coordinates( g_show_coordinates_callback );
  
  ShowOutlineExportCaller g_show_outline_caller;
 -BoolExportCallback g_show_outline_callback( g_show_outline_caller );
 +Callback<void(const Callback<void(bool)> &)> g_show_outline_callback( g_show_outline_caller );
  ToggleItem g_show_outline( g_show_outline_callback );
  
  ShowAxesExportCaller g_show_axes_caller;
 -BoolExportCallback g_show_axes_callback( g_show_axes_caller );
 +Callback<void(const Callback<void(bool)> &)> g_show_axes_callback( g_show_axes_caller );
  ToggleItem g_show_axes( g_show_axes_callback );
  
  ShowWorkzoneExportCaller g_show_workzone_caller;
 -BoolExportCallback g_show_workzone_callback( g_show_workzone_caller );
 +Callback<void(const Callback<void(bool)> &)> g_show_workzone_callback( g_show_workzone_caller );
  ToggleItem g_show_workzone( g_show_workzone_callback );
  
  void XYShow_registerCommands(){
@@@ -2754,7 -2749,7 +2754,7 @@@ void Orthographic_constructPage( Prefer
        Orthographic_constructPreferences( page );
  }
  void Orthographic_registerPreferencesPage(){
 -      PreferencesDialog_addSettingsPage( FreeCaller1<PreferenceGroup&, Orthographic_constructPage>() );
 +      PreferencesDialog_addSettingsPage( makeCallbackF(Orthographic_constructPage) );
  }
  
  void Clipper_constructPreferences( PreferencesPage& page ){
@@@ -2765,7 -2760,7 +2765,7 @@@ void Clipper_constructPage( PreferenceG
        Clipper_constructPreferences( page );
  }
  void Clipper_registerPreferencesPage(){
 -      PreferencesDialog_addSettingsPage( FreeCaller1<PreferenceGroup&, Clipper_constructPage>() );
 +      PreferencesDialog_addSettingsPage( makeCallbackF(Clipper_constructPage) );
  }
  
  
  #include "stringio.h"
  
  
 +struct ToggleShown_Bool {
 +      static void Export(const ToggleShown &self, const Callback<void(bool)> &returnz) {
 +              returnz(self.active());
 +      }
  
 -
 -void ToggleShown_importBool( ToggleShown& self, bool value ){
 -      self.set( value );
 -}
 -typedef ReferenceCaller1<ToggleShown, bool, ToggleShown_importBool> ToggleShownImportBoolCaller;
 -void ToggleShown_exportBool( const ToggleShown& self, const BoolImportCallback& importer ){
 -      importer( self.active() );
 -}
 -typedef ConstReferenceCaller1<ToggleShown, const BoolImportCallback&, ToggleShown_exportBool> ToggleShownExportBoolCaller;
 +      static void Import(ToggleShown &self, bool value) {
 +              self.set(value);
 +      }
 +};
  
  
  void XYWindow_Construct(){
 -      GlobalCommands_insert( "ToggleCrosshairs", FreeCaller<ToggleShowCrosshair>(), Accelerator( 'X', (GdkModifierType)GDK_SHIFT_MASK ) );
 -      GlobalCommands_insert( "ToggleSizePaint", FreeCaller<ToggleShowSizeInfo>(), Accelerator( 'J' ) );
 -      GlobalCommands_insert( "ToggleGrid", FreeCaller<ToggleShowGrid>(), Accelerator( '0' ) );
 +      GlobalCommands_insert( "ToggleCrosshairs", makeCallbackF(ToggleShowCrosshair), Accelerator( 'X', (GdkModifierType)GDK_SHIFT_MASK ) );
 +      GlobalCommands_insert( "ToggleSizePaint", makeCallbackF(ToggleShowSizeInfo), Accelerator( 'J' ) );
 +      GlobalCommands_insert( "ToggleGrid", makeCallbackF(ToggleShowGrid), Accelerator( '0' ) );
  
        GlobalToggles_insert( "ToggleView", ToggleShown::ToggleCaller( g_xy_top_shown ), ToggleItem::AddCallbackCaller( g_xy_top_shown.m_item ), Accelerator( 'V', (GdkModifierType)( GDK_SHIFT_MASK | GDK_CONTROL_MASK ) ) );
        GlobalToggles_insert( "ToggleSideView", ToggleShown::ToggleCaller( g_yz_side_shown ), ToggleItem::AddCallbackCaller( g_yz_side_shown.m_item ) );
        GlobalToggles_insert( "ToggleFrontView", ToggleShown::ToggleCaller( g_xz_front_shown ), ToggleItem::AddCallbackCaller( g_xz_front_shown.m_item ) );
 -      GlobalCommands_insert( "NextView", FreeCaller<XY_Next>(), Accelerator( GDK_Tab, (GdkModifierType)GDK_CONTROL_MASK ) );
 -      GlobalCommands_insert( "ZoomIn", FreeCaller<XY_ZoomIn>(), Accelerator( GDK_Delete ) );
 -      GlobalCommands_insert( "ZoomOut", FreeCaller<XY_ZoomOut>(), Accelerator( GDK_Insert ) );
 -      GlobalCommands_insert( "ViewTop", FreeCaller<XY_Top>(), Accelerator( GDK_KP_Home ) );
 -      GlobalCommands_insert( "ViewSide", FreeCaller<XY_Side>(), Accelerator( GDK_KP_Page_Down ) );
 -      GlobalCommands_insert( "ViewFront", FreeCaller<XY_Front>(), Accelerator( GDK_KP_End ) );
 -      GlobalCommands_insert( "Zoom100", FreeCaller<XY_Zoom100>() );
 -      GlobalCommands_insert( "CenterXYView", FreeCaller<XY_Focus>(), Accelerator( GDK_Tab, (GdkModifierType)( GDK_SHIFT_MASK | GDK_CONTROL_MASK ) ) );
 -
 -      GlobalPreferenceSystem().registerPreference( "ClipCaulk", BoolImportStringCaller( g_clip_useCaulk ), BoolExportStringCaller( g_clip_useCaulk ) );
 -
 -      GlobalPreferenceSystem().registerPreference( "NewRightClick", BoolImportStringCaller( g_xywindow_globals.m_bRightClick ), BoolExportStringCaller( g_xywindow_globals.m_bRightClick ) );
 -      GlobalPreferenceSystem().registerPreference( "ImprovedWheelZoom", BoolImportStringCaller( g_xywindow_globals.m_bImprovedWheelZoom ), BoolExportStringCaller( g_xywindow_globals.m_bImprovedWheelZoom ) );
 -      GlobalPreferenceSystem().registerPreference( "ChaseMouse", BoolImportStringCaller( g_xywindow_globals_private.m_bChaseMouse ), BoolExportStringCaller( g_xywindow_globals_private.m_bChaseMouse ) );
 -      GlobalPreferenceSystem().registerPreference( "SizePainting", BoolImportStringCaller( g_xywindow_globals_private.m_bSizePaint ), BoolExportStringCaller( g_xywindow_globals_private.m_bSizePaint ) );
 -      GlobalPreferenceSystem().registerPreference( "ShowCrosshair", BoolImportStringCaller( g_bCrossHairs ), BoolExportStringCaller( g_bCrossHairs ) );
 -      GlobalPreferenceSystem().registerPreference( "NoStipple", BoolImportStringCaller( g_xywindow_globals.m_bNoStipple ), BoolExportStringCaller( g_xywindow_globals.m_bNoStipple ) );
 -      GlobalPreferenceSystem().registerPreference( "SI_ShowCoords", BoolImportStringCaller( g_xywindow_globals_private.show_coordinates ), BoolExportStringCaller( g_xywindow_globals_private.show_coordinates ) );
 -      GlobalPreferenceSystem().registerPreference( "SI_ShowOutlines", BoolImportStringCaller( g_xywindow_globals_private.show_outline ), BoolExportStringCaller( g_xywindow_globals_private.show_outline ) );
 -      GlobalPreferenceSystem().registerPreference( "SI_ShowAxis", BoolImportStringCaller( g_xywindow_globals_private.show_axis ), BoolExportStringCaller( g_xywindow_globals_private.show_axis ) );
 -      GlobalPreferenceSystem().registerPreference( "CamXYUpdate", BoolImportStringCaller( g_xywindow_globals_private.m_bCamXYUpdate ), BoolExportStringCaller( g_xywindow_globals_private.m_bCamXYUpdate ) );
 -      GlobalPreferenceSystem().registerPreference( "ShowWorkzone", BoolImportStringCaller( g_xywindow_globals_private.d_show_work ), BoolExportStringCaller( g_xywindow_globals_private.d_show_work ) );
 -
 -      GlobalPreferenceSystem().registerPreference( "SI_AxisColors0", Vector3ImportStringCaller( g_xywindow_globals.AxisColorX ), Vector3ExportStringCaller( g_xywindow_globals.AxisColorX ) );
 -      GlobalPreferenceSystem().registerPreference( "SI_AxisColors1", Vector3ImportStringCaller( g_xywindow_globals.AxisColorY ), Vector3ExportStringCaller( g_xywindow_globals.AxisColorY ) );
 -      GlobalPreferenceSystem().registerPreference( "SI_AxisColors2", Vector3ImportStringCaller( g_xywindow_globals.AxisColorZ ), Vector3ExportStringCaller( g_xywindow_globals.AxisColorZ ) );
 -      GlobalPreferenceSystem().registerPreference( "SI_Colors1", Vector3ImportStringCaller( g_xywindow_globals.color_gridback ), Vector3ExportStringCaller( g_xywindow_globals.color_gridback ) );
 -      GlobalPreferenceSystem().registerPreference( "SI_Colors2", Vector3ImportStringCaller( g_xywindow_globals.color_gridminor ), Vector3ExportStringCaller( g_xywindow_globals.color_gridminor ) );
 -      GlobalPreferenceSystem().registerPreference( "SI_Colors3", Vector3ImportStringCaller( g_xywindow_globals.color_gridmajor ), Vector3ExportStringCaller( g_xywindow_globals.color_gridmajor ) );
 -      GlobalPreferenceSystem().registerPreference( "SI_Colors6", Vector3ImportStringCaller( g_xywindow_globals.color_gridblock ), Vector3ExportStringCaller( g_xywindow_globals.color_gridblock ) );
 -      GlobalPreferenceSystem().registerPreference( "SI_Colors7", Vector3ImportStringCaller( g_xywindow_globals.color_gridtext ), Vector3ExportStringCaller( g_xywindow_globals.color_gridtext ) );
 -      GlobalPreferenceSystem().registerPreference( "SI_Colors8", Vector3ImportStringCaller( g_xywindow_globals.color_brushes ), Vector3ExportStringCaller( g_xywindow_globals.color_brushes ) );
 -      GlobalPreferenceSystem().registerPreference( "SI_Colors14", Vector3ImportStringCaller( g_xywindow_globals.color_gridmajor_alt ), Vector3ExportStringCaller( g_xywindow_globals.color_gridmajor_alt ) );
 -
 -
 -      GlobalPreferenceSystem().registerPreference( "XZVIS", makeBoolStringImportCallback( ToggleShownImportBoolCaller( g_xz_front_shown ) ), makeBoolStringExportCallback( ToggleShownExportBoolCaller( g_xz_front_shown ) ) );
 -      GlobalPreferenceSystem().registerPreference( "YZVIS", makeBoolStringImportCallback( ToggleShownImportBoolCaller( g_yz_side_shown ) ), makeBoolStringExportCallback( ToggleShownExportBoolCaller( g_yz_side_shown ) ) );
 +      GlobalCommands_insert( "NextView", makeCallbackF(XY_Next), Accelerator( GDK_KEY_Tab, (GdkModifierType)GDK_CONTROL_MASK ) ); // fixme: doesn't show its shortcut
 +      GlobalCommands_insert( "ZoomIn", makeCallbackF(XY_ZoomIn), Accelerator( GDK_KEY_Delete ) );
 +      GlobalCommands_insert( "ZoomOut", makeCallbackF(XY_ZoomOut), Accelerator( GDK_KEY_Insert ) );
 +      GlobalCommands_insert( "ViewTop", makeCallbackF(XY_Top), Accelerator( GDK_KEY_KP_Home ) );
 +      GlobalCommands_insert( "ViewSide", makeCallbackF(XY_Side), Accelerator( GDK_KEY_KP_Page_Down ) );
 +      GlobalCommands_insert( "ViewFront", makeCallbackF(XY_Front), Accelerator( GDK_KEY_KP_End ) );
 +      GlobalCommands_insert( "Zoom100", makeCallbackF(XY_Zoom100) );
 +      GlobalCommands_insert( "CenterXYView", makeCallbackF(XY_Focus), Accelerator( GDK_KEY_Tab, (GdkModifierType)( GDK_SHIFT_MASK | GDK_CONTROL_MASK ) ) );
 +
 +      GlobalPreferenceSystem().registerPreference( "ClipCaulk", make_property_string( g_clip_useCaulk ) );
 +
 +      GlobalPreferenceSystem().registerPreference( "NewRightClick", make_property_string( g_xywindow_globals.m_bRightClick ) );
 +      GlobalPreferenceSystem().registerPreference( "ImprovedWheelZoom", make_property_string( g_xywindow_globals.m_bImprovedWheelZoom ) );
 +      GlobalPreferenceSystem().registerPreference( "ChaseMouse", make_property_string( g_xywindow_globals_private.m_bChaseMouse ) );
 +      GlobalPreferenceSystem().registerPreference( "SizePainting", make_property_string( g_xywindow_globals_private.m_bSizePaint ) );
 +      GlobalPreferenceSystem().registerPreference( "ShowCrosshair", make_property_string( g_xywindow_globals_private.g_bCrossHairs ) );
 +      GlobalPreferenceSystem().registerPreference( "NoStipple", make_property_string( g_xywindow_globals.m_bNoStipple ) );
 +      GlobalPreferenceSystem().registerPreference( "SI_ShowCoords", make_property_string( g_xywindow_globals_private.show_coordinates ) );
 +      GlobalPreferenceSystem().registerPreference( "SI_ShowOutlines", make_property_string( g_xywindow_globals_private.show_outline ) );
 +      GlobalPreferenceSystem().registerPreference( "SI_ShowAxis", make_property_string( g_xywindow_globals_private.show_axis ) );
 +      GlobalPreferenceSystem().registerPreference( "CamXYUpdate", make_property_string( g_xywindow_globals_private.m_bCamXYUpdate ) );
 +      GlobalPreferenceSystem().registerPreference( "ShowWorkzone", make_property_string( g_xywindow_globals_private.d_show_work ) );
 +
 +      GlobalPreferenceSystem().registerPreference( "SI_AxisColors0", make_property_string( g_xywindow_globals.AxisColorX ) );
 +      GlobalPreferenceSystem().registerPreference( "SI_AxisColors1", make_property_string( g_xywindow_globals.AxisColorY ) );
 +      GlobalPreferenceSystem().registerPreference( "SI_AxisColors2", make_property_string( g_xywindow_globals.AxisColorZ ) );
 +      GlobalPreferenceSystem().registerPreference( "SI_Colors1", make_property_string( g_xywindow_globals.color_gridback ) );
 +      GlobalPreferenceSystem().registerPreference( "SI_Colors2", make_property_string( g_xywindow_globals.color_gridminor ) );
 +      GlobalPreferenceSystem().registerPreference( "SI_Colors3", make_property_string( g_xywindow_globals.color_gridmajor ) );
 +      GlobalPreferenceSystem().registerPreference( "SI_Colors6", make_property_string( g_xywindow_globals.color_gridblock ) );
 +      GlobalPreferenceSystem().registerPreference( "SI_Colors7", make_property_string( g_xywindow_globals.color_gridtext ) );
 +      GlobalPreferenceSystem().registerPreference( "SI_Colors8", make_property_string( g_xywindow_globals.color_brushes ) );
 +      GlobalPreferenceSystem().registerPreference( "SI_Colors14", make_property_string( g_xywindow_globals.color_gridmajor_alt ) );
 +
 +
 +      GlobalPreferenceSystem().registerPreference( "XZVIS", make_property_string<ToggleShown_Bool>( g_xz_front_shown ) );
 +      GlobalPreferenceSystem().registerPreference( "YZVIS", make_property_string<ToggleShown_Bool>( g_yz_side_shown ) );
  
        Orthographic_registerPreferencesPage();
        Clipper_registerPreferencesPage();