X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fnetradiant.git;a=blobdiff_plain;f=radiant%2Fdialog.cpp;h=e588f93ff8599d2e0e0552aa77793af936f8afe5;hp=3fdcaee49bce90519f6254a00c0e2cfebeca2514;hb=69b4f74e6c95e22d6c6ce10d0e137c875fd83cc4;hpb=830125fad042fad35dc029b6eb57c8156ad7e176 diff --git a/radiant/dialog.cpp b/radiant/dialog.cpp index 3fdcaee4..e588f93f 100644 --- a/radiant/dialog.cpp +++ b/radiant/dialog.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 1999-2007 id Software, Inc. and contributors. + Copyright (C) 1999-2006 Id Software, Inc. and contributors. For a list of contributors, see the accompanying CONTRIBUTORS file. This file is part of GtkRadiant. @@ -26,270 +26,614 @@ // Leonardo Zide (leo@lokigames.com) // -#include "stdafx.h" +#include "dialog.h" + #include + +#include "debugging/debugging.h" + + +#include "mainframe.h" + #include -#include -typedef struct +#include "stream/stringstream.h" +#include "convert.h" +#include "gtkutil/dialog.h" +#include "gtkutil/button.h" +#include "gtkutil/entry.h" +#include "gtkutil/image.h" + +#include "gtkmisc.h" + + +ui::Entry DialogEntry_new(){ + auto entry = ui::Entry(ui::New); + entry.show(); + gtk_widget_set_size_request( entry , 64, -1 ); + return entry; +} + +class DialogEntryRow +{ +public: +DialogEntryRow( ui::Widget row, ui::Entry entry ) : m_row( row ), m_entry( entry ){ +} +ui::Widget m_row; +ui::Entry m_entry; +}; + +DialogEntryRow DialogEntryRow_new( const char* name ){ + auto alignment = ui::Alignment( 0.0, 0.5, 0.0, 0.0 ); + alignment.show(); + + auto entry = DialogEntry_new(); + alignment.add(entry); + + return DialogEntryRow( ui::Widget(DialogRow_new( name, alignment )), entry ); +} + + +ui::SpinButton DialogSpinner_new( double value, double lower, double upper, int fraction ){ + double step = 1.0 / double(fraction); + unsigned int digits = 0; + for (; fraction > 1; fraction /= 10 ) + { + ++digits; + } + auto spin = ui::SpinButton( ui::Adjustment( value, lower, upper, step, 10, 0 ), step, digits ); + spin.show(); + gtk_widget_set_size_request( spin , 64, -1 ); + return spin; +} + +class DialogSpinnerRow +{ +public: +DialogSpinnerRow( ui::Widget row, GtkSpinButton* spin ) : m_row( row ), m_spin( spin ){ +} +ui::Widget m_row; +ui::SpinButton m_spin; +}; + +DialogSpinnerRow DialogSpinnerRow_new( const char* name, double value, double lower, double upper, int fraction ){ + auto alignment = ui::Alignment( 0.0, 0.5, 0.0, 0.0 ); + alignment.show(); + + auto spin = DialogSpinner_new( value, lower, upper, fraction ); + alignment.add(spin); + + return DialogSpinnerRow( ui::Widget(DialogRow_new( name, alignment )), spin ); +} + + + +template< + typename Type_, + typename Other_, + void( *Import ) ( Type_&, Other_ ), + void( *Export ) ( Type_&, const Callback1& ) + > +class ImportExport +{ +public: +typedef Type_ Type; +typedef Other_ Other; + +typedef ReferenceCaller1 ImportCaller; +typedef ReferenceCaller1&, Export> ExportCaller; +}; + +typedef ImportExport BoolImportExport; +typedef ImportExport IntImportExport; +typedef ImportExport SizeImportExport; +typedef ImportExport FloatImportExport; +typedef ImportExport StringImportExport; + + + +void BoolToggleImport( GtkToggleButton& widget, bool value ){ + gtk_toggle_button_set_active( &widget, value ); +} +void BoolToggleExport( GtkToggleButton& widget, const BoolImportCallback& importCallback ){ + importCallback( gtk_toggle_button_get_active( &widget ) != FALSE ); +} +typedef ImportExport BoolToggleImportExport; + + +void IntRadioImport( GtkRadioButton& widget, int index ){ + radio_button_set_active( ui::RadioButton(&widget), index ); +} +void IntRadioExport( GtkRadioButton& widget, const IntImportCallback& importCallback ){ + importCallback( radio_button_get_active( ui::RadioButton(&widget) ) ); +} +typedef ImportExport IntRadioImportExport; + +void TextEntryImport( GtkEntry& widget, const char* text ){ + ui::Entry(&widget).text(text); +} +void TextEntryExport( GtkEntry& widget, const StringImportCallback& importCallback ){ + importCallback( gtk_entry_get_text( &widget ) ); +} +typedef ImportExport TextEntryImportExport; + + +void IntEntryImport( GtkEntry& widget, int value ){ + entry_set_int( ui::Entry(&widget), value ); +} +void IntEntryExport( GtkEntry& widget, const IntImportCallback& importCallback ){ + importCallback( atoi( gtk_entry_get_text( &widget ) ) ); +} +typedef ImportExport IntEntryImportExport; + + +void SizeEntryImport( GtkEntry& widget, std::size_t value ){ + entry_set_int( ui::Entry(&widget), int(value) ); +} +void SizeEntryExport( GtkEntry& widget, const SizeImportCallback& importCallback ){ + int value = atoi( gtk_entry_get_text( &widget ) ); + if ( value < 0 ) { + value = 0; + } + importCallback( value ); +} +typedef ImportExport SizeEntryImportExport; + + +void FloatEntryImport( GtkEntry& widget, float value ){ + entry_set_float( ui::Entry(&widget), value ); +} +void FloatEntryExport( GtkEntry& widget, const FloatImportCallback& importCallback ){ + importCallback( (float)atof( gtk_entry_get_text( &widget ) ) ); +} +typedef ImportExport FloatEntryImportExport; + + +void FloatSpinnerImport( GtkSpinButton& widget, float value ){ + gtk_spin_button_set_value( &widget, value ); +} +void FloatSpinnerExport( GtkSpinButton& widget, const FloatImportCallback& importCallback ){ + importCallback( float(gtk_spin_button_get_value( &widget ) ) ); +} +typedef ImportExport FloatSpinnerImportExport; + + +void IntSpinnerImport( GtkSpinButton& widget, int value ){ + gtk_spin_button_set_value( &widget, value ); +} +void IntSpinnerExport( GtkSpinButton& widget, const IntImportCallback& importCallback ){ + importCallback( gtk_spin_button_get_value_as_int( &widget ) ); +} +typedef ImportExport IntSpinnerImportExport; + + +void IntAdjustmentImport( GtkAdjustment& widget, int value ){ + gtk_adjustment_set_value( &widget, value ); +} +void IntAdjustmentExport( GtkAdjustment& widget, const IntImportCallback& importCallback ){ + importCallback( (int)gtk_adjustment_get_value( &widget ) ); +} +typedef ImportExport IntAdjustmentImportExport; + + +void IntComboImport( GtkComboBox& widget, int value ){ + gtk_combo_box_set_active( &widget, value ); +} +void IntComboExport( GtkComboBox& widget, const IntImportCallback& importCallback ){ + importCallback( gtk_combo_box_get_active( &widget ) ); +} +typedef ImportExport IntComboImportExport; + + +template +class CallbackDialogData : public DLG_DATA { - GtkObject *object; - void *buffer; - DLG_DATA_TYPE type; -} DLG_DATA; +public: +typedef Callback1 ImportCallback; +typedef Callback1 ExportCallback; + +private: +ImportCallback m_importWidget; +ExportCallback m_exportWidget; +ImportCallback m_importViewer; +ExportCallback m_exportViewer; + +public: +CallbackDialogData( const ImportCallback& importWidget, const ExportCallback& exportWidget, const ImportCallback& importViewer, const ExportCallback& exportViewer ) + : m_importWidget( importWidget ), m_exportWidget( exportWidget ), m_importViewer( importViewer ), m_exportViewer( exportViewer ){ +} +void release(){ + delete this; +} +void importData() const { + m_exportViewer( m_importWidget ); +} +void exportData() const { + m_exportWidget( m_importViewer ); +} +}; + +template +class AddData +{ +DialogDataList& m_data; +public: +AddData( DialogDataList& data ) : m_data( data ){ +} +void apply( typename Widget::Type& widget, typename Viewer::Type& viewer ) const { + m_data.push_back( + new CallbackDialogData( + typename Widget::ImportCaller( widget ), + typename Widget::ExportCaller( widget ), + typename Viewer::ImportCaller( viewer ), + typename Viewer::ExportCaller( viewer ) + ) + ); +} +}; + +template +class AddCustomData +{ +DialogDataList& m_data; +public: +AddCustomData( DialogDataList& data ) : m_data( data ){ +} +void apply( + typename Widget::Type& widget, + const Callback1& importViewer, + const Callback1&>& exportViewer + ) const { + m_data.push_back( + new CallbackDialogData( + typename Widget::ImportCaller( widget ), + typename Widget::ExportCaller( widget ), + importViewer, + exportViewer + ) + ); +} +}; // ============================================================================= // Dialog class -Dialog::Dialog (){ - m_pDataList = (GSList*)NULL; - m_nReturn = IDCANCEL; - m_bNeedBuild = true; - m_nLoop = 0; +Dialog::Dialog() : m_window( 0 ), m_parent( 0 ){ } -Dialog::~Dialog (){ - while ( m_pDataList ) +Dialog::~Dialog(){ + for ( DialogDataList::iterator i = m_data.begin(); i != m_data.end(); ++i ) { - free( m_pDataList->data ); - m_pDataList = g_slist_remove( m_pDataList, m_pDataList->data ); + ( *i )->release(); } - if ( m_pWidget != NULL ) { - gtk_widget_destroy( m_pWidget ); - } + ASSERT_MESSAGE( !m_window, "dialog window not destroyed" ); } -// i suspect that this is redundant - gtk manages to remember the data stored in its widgets across a hide/show void Dialog::ShowDlg(){ - Create(); - UpdateData( FALSE ); - gtk_widget_show( m_pWidget ); + ASSERT_MESSAGE( m_window, "dialog was not constructed" ); + importData(); + m_window.show(); } void Dialog::HideDlg(){ - UpdateData( TRUE ); - gtk_widget_hide( m_pWidget ); + ASSERT_MESSAGE( m_window, "dialog was not constructed" ); + exportData(); + m_window.hide(); } -static gint delete_event_callback( GtkWidget *widget, GdkEvent* event, gpointer data ){ +static gint delete_event_callback( ui::Widget widget, GdkEvent* event, gpointer data ){ reinterpret_cast( data )->HideDlg(); - reinterpret_cast( data )->EndModal( IDCANCEL ); + reinterpret_cast( data )->EndModal( eIDCANCEL ); return TRUE; } void Dialog::Create(){ - if ( m_bNeedBuild ) { - m_pWidget = gtk_window_new( GTK_WINDOW_TOPLEVEL ); - gtk_signal_connect( GTK_OBJECT( m_pWidget ), "delete_event", - GTK_SIGNAL_FUNC( delete_event_callback ), this ); - gtk_signal_connect( GTK_OBJECT( m_pWidget ), "destroy", - GTK_SIGNAL_FUNC( gtk_widget_destroy ), NULL ); - g_object_set_data( G_OBJECT( m_pWidget ), "loop", &m_nLoop ); - g_object_set_data( G_OBJECT( m_pWidget ), "ret", &m_nReturn ); - - BuildDialog(); - m_bNeedBuild = false; - } + ASSERT_MESSAGE( !m_window, "dialog cannot be constructed" ); + + m_window = BuildDialog(); + m_window.connect( "delete_event", G_CALLBACK( delete_event_callback ), this ); } void Dialog::Destroy(){ - if ( m_pWidget != NULL ) { - gtk_widget_destroy( m_pWidget ); - m_pWidget = NULL; + ASSERT_MESSAGE( m_window, "dialog cannot be destroyed" ); + + m_window.destroy(); + m_window = ui::Window{ui::null}; +} + + +void Dialog::AddBoolToggleData( GtkToggleButton& widget, const BoolImportCallback& importViewer, const BoolExportCallback& exportViewer ){ + AddCustomData( m_data ).apply( widget, importViewer, exportViewer ); +} + +void Dialog::AddIntRadioData( GtkRadioButton& widget, const IntImportCallback& importViewer, const IntExportCallback& exportViewer ){ + AddCustomData( m_data ).apply( widget, importViewer, exportViewer ); +} + +void Dialog::AddTextEntryData( GtkEntry& widget, const StringImportCallback& importViewer, const StringExportCallback& exportViewer ){ + AddCustomData( m_data ).apply( widget, importViewer, exportViewer ); +} + +void Dialog::AddIntEntryData( GtkEntry& widget, const IntImportCallback& importViewer, const IntExportCallback& exportViewer ){ + AddCustomData( m_data ).apply( widget, importViewer, exportViewer ); +} + +void Dialog::AddSizeEntryData( GtkEntry& widget, const SizeImportCallback& importViewer, const SizeExportCallback& exportViewer ){ + AddCustomData( m_data ).apply( widget, importViewer, exportViewer ); +} + +void Dialog::AddFloatEntryData( GtkEntry& widget, const FloatImportCallback& importViewer, const FloatExportCallback& exportViewer ){ + AddCustomData( m_data ).apply( widget, importViewer, exportViewer ); +} + +void Dialog::AddFloatSpinnerData( GtkSpinButton& widget, const FloatImportCallback& importViewer, const FloatExportCallback& exportViewer ){ + AddCustomData( m_data ).apply( widget, importViewer, exportViewer ); +} + +void Dialog::AddIntSpinnerData( GtkSpinButton& widget, const IntImportCallback& importViewer, const IntExportCallback& exportViewer ){ + AddCustomData( m_data ).apply( widget, importViewer, exportViewer ); +} + +void Dialog::AddIntAdjustmentData( GtkAdjustment& widget, const IntImportCallback& importViewer, const IntExportCallback& exportViewer ){ + AddCustomData( m_data ).apply( widget, importViewer, exportViewer ); +} + +void Dialog::AddIntComboData( GtkComboBox& widget, const IntImportCallback& importViewer, const IntExportCallback& exportViewer ){ + AddCustomData( m_data ).apply( widget, importViewer, exportViewer ); +} + + +void Dialog::AddDialogData( GtkToggleButton& widget, bool& data ){ + AddData( m_data ).apply( widget, data ); +} +void Dialog::AddDialogData( GtkRadioButton& widget, int& data ){ + AddData( m_data ).apply( widget, data ); +} +void Dialog::AddDialogData( GtkEntry& widget, CopiedString& data ){ + AddData( m_data ).apply( widget, data ); +} +void Dialog::AddDialogData( GtkEntry& widget, int& data ){ + AddData( m_data ).apply( widget, data ); +} +void Dialog::AddDialogData( GtkEntry& widget, std::size_t& data ){ + AddData( m_data ).apply( widget, data ); +} +void Dialog::AddDialogData( GtkEntry& widget, float& data ){ + AddData( m_data ).apply( widget, data ); +} +void Dialog::AddDialogData( GtkSpinButton& widget, float& data ){ + AddData( m_data ).apply( widget, data ); +} +void Dialog::AddDialogData( GtkSpinButton& widget, int& data ){ + AddData( m_data ).apply( widget, data ); +} +void Dialog::AddDialogData( GtkAdjustment& widget, int& data ){ + AddData( m_data ).apply( widget, data ); +} +void Dialog::AddDialogData( GtkComboBox& widget, int& data ){ + AddData( m_data ).apply( widget, data ); +} + +void Dialog::exportData(){ + for ( DialogDataList::iterator i = m_data.begin(); i != m_data.end(); ++i ) + { + ( *i )->exportData(); } } -void Dialog::AddDialogData( GtkObject *object, void *buf, DLG_DATA_TYPE type ){ - DLG_DATA *data; +void Dialog::importData(){ + for ( DialogDataList::iterator i = m_data.begin(); i != m_data.end(); ++i ) + { + ( *i )->importData(); + } +} + +void Dialog::EndModal( EMessageBoxReturn code ){ + m_modal.loop = 0; + m_modal.ret = code; +} + +EMessageBoxReturn Dialog::DoModal(){ + importData(); - data = (DLG_DATA*)qmalloc( sizeof( DLG_DATA ) ); - data->object = object; - data->buffer = buf; - data->type = type; + PreModal(); - m_pDataList = g_slist_append( m_pDataList, data ); + EMessageBoxReturn ret = modal_dialog_show( m_window, m_modal ); + ASSERT_TRUE( (bool) m_window ); + if ( ret == eIDOK ) { + exportData(); + } + + m_window.hide(); + + PostModal( m_modal.ret ); + + return m_modal.ret; } -void Dialog::AddModalButton( GtkWidget *widget, int ret ) { - gtk_signal_connect( GTK_OBJECT( widget ), "clicked", - GTK_SIGNAL_FUNC( dialog_button_callback ), GINT_TO_POINTER( ret ) ); + +ui::CheckButton Dialog::addCheckBox( ui::Widget vbox, const char* name, const char* flag, const BoolImportCallback& importViewer, const BoolExportCallback& exportViewer ){ + auto check = ui::CheckButton( flag ); + check.show(); + AddBoolToggleData( *GTK_TOGGLE_BUTTON( check ), importViewer, exportViewer ); + + DialogVBox_packRow( ui::VBox(GTK_VBOX( vbox )), ui::Widget(DialogRow_new( name, check ) )); + return check; +} + +ui::CheckButton Dialog::addCheckBox( ui::Widget vbox, const char* name, const char* flag, bool& data ){ + return addCheckBox( vbox, name, flag, BoolImportCaller( data ), BoolExportCaller( data ) ); } -void Dialog::UpdateData( bool retrieve ){ - DLG_DATA *data; - GSList *lst; - char buf[32]; +void Dialog::addCombo( ui::Widget vbox, const char* name, StringArrayRange values, const IntImportCallback& importViewer, const IntExportCallback& exportViewer ){ + auto alignment = ui::Alignment( 0.0, 0.5, 0.0, 0.0 ); + alignment.show(); + { + auto combo = ui::ComboBoxText(ui::New); - if ( retrieve ) { - for ( lst = m_pDataList; lst != NULL; lst = g_slist_next( lst ) ) + for ( StringArrayRange::Iterator i = values.first; i != values.last; ++i ) { - data = (DLG_DATA*)lst->data; - - switch ( data->type ) - { - case DLG_CHECK_BOOL: - *(bool*)data->buffer = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( data->object ) ); - break; - case DLG_RADIO_INT: - { - GSList *radio = gtk_radio_button_group( GTK_RADIO_BUTTON( data->object ) ); - *(int*)data->buffer = g_slist_length( radio ) - 1; - for (; radio; radio = g_slist_next( radio ) ) - if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( radio->data ) ) ) { - break; - } - else{ - ( *(int*)data->buffer )--; - } - } break; - case DLG_ENTRY_TEXT: - { - const char *txt; - Str* str; - str = (Str*)data->buffer; - txt = gtk_entry_get_text( GTK_ENTRY( data->object ) ); - *str = txt; - } break; - case DLG_ENTRY_FLOAT: - *(float*)data->buffer = atof( gtk_entry_get_text( GTK_ENTRY( data->object ) ) ); - break; - case DLG_ENTRY_INT: - *(int*)data->buffer = atoi( gtk_entry_get_text( GTK_ENTRY( data->object ) ) ); - break; - case DLG_SPIN_FLOAT: - *(float*)data->buffer = gtk_spin_button_get_value_as_float( GTK_SPIN_BUTTON( data->object ) ); - break; - case DLG_SPIN_INT: - *(int*)data->buffer = gtk_spin_button_get_value_as_int( GTK_SPIN_BUTTON( data->object ) ); - break; - case DLG_ADJ_INT: - *(int*)data->buffer = (int) GTK_ADJUSTMENT( data->object )->value; - break; - case DLG_COMBO_INT: - { - GList *lst = GTK_LIST( GTK_COMBO( data->object )->list )->children; - char *label; - const char *entry; - int i; - - *(int*)data->buffer = -1; - entry = gtk_entry_get_text( GTK_ENTRY( GTK_COMBO( data->object )->entry ) ); - - for ( i = 0; lst != NULL; lst = g_list_next( lst ) ) - { - gtk_label_get( GTK_LABEL( GTK_BIN( lst->data )->child ), &label ); - - if ( strcmp( label, entry ) == 0 ) { - *(int*)data->buffer = i; - break; - } - i++; - } - } - break; - case DLG_COMBO_BOX_INT: { - *(int*)data->buffer = gtk_combo_box_get_active( GTK_COMBO_BOX( data->object ) ); - } - break; - - } + gtk_combo_box_text_append_text( GTK_COMBO_BOX_TEXT( combo ), *i ); } + + AddIntComboData( *GTK_COMBO_BOX( combo ), importViewer, exportViewer ); + + combo.show(); + alignment.add(combo); } - else - { - for ( lst = m_pDataList; lst != NULL; lst = g_slist_next( lst ) ) + + auto row = DialogRow_new( name, alignment ); + DialogVBox_packRow( ui::VBox(GTK_VBOX(vbox)), row ); +} + +void Dialog::addCombo( ui::Widget vbox, const char* name, int& data, StringArrayRange values ){ + addCombo( vbox, name, values, IntImportCaller( data ), IntExportCaller( data ) ); +} + +void Dialog::addSlider( ui::Widget vbox, const char* name, int& data, gboolean draw_value, const char* low, const char* high, double value, double lower, double upper, double step_increment, double page_increment ){ +#if 0 + if ( draw_value == FALSE ) { + auto hbox2 = ui::HBox( FALSE, 0 ); + hbox2.show(); + vbox.pack_start( hbox2 , FALSE, FALSE, 0 ); { - data = (DLG_DATA*)lst->data; - - switch ( data->type ) - { - case DLG_CHECK_BOOL: - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( data->object ), *(bool*)data->buffer ); - break; - case DLG_RADIO_INT: - { - GSList *radio = gtk_radio_button_group( GTK_RADIO_BUTTON( data->object ) ); - gpointer btn = g_slist_nth_data( radio, g_slist_length( radio ) - ( *(int*)data->buffer ) - 1 ); - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( btn ), TRUE ); - } break; - case DLG_ENTRY_TEXT: - { - Str* str; - str = (Str*)data->buffer; - const char *txt = str->GetBuffer(); - gtk_entry_set_text( GTK_ENTRY( data->object ), txt ); - } break; - case DLG_ENTRY_FLOAT: - sprintf( buf, "%g", ( *(float*)data->buffer ) ); - gtk_entry_set_text( GTK_ENTRY( data->object ), buf ); - break; - case DLG_ENTRY_INT: - sprintf( buf, "%d", ( *(int*)data->buffer ) ); - gtk_entry_set_text( GTK_ENTRY( data->object ), buf ); - break; - case DLG_SPIN_FLOAT: - gtk_spin_button_set_value( GTK_SPIN_BUTTON( data->object ), ( *(float*)data->buffer ) ); - break; - case DLG_SPIN_INT: - gtk_spin_button_set_value( GTK_SPIN_BUTTON( data->object ), ( *(int*)data->buffer ) ); - break; - case DLG_ADJ_INT: - gtk_adjustment_set_value( GTK_ADJUSTMENT( data->object ), ( *(int*)data->buffer ) ); - break; - case DLG_COMBO_INT: { - GList *lst = GTK_LIST( GTK_COMBO( data->object )->list )->children; - char *entry = NULL; - - if ( *(int*)data->buffer != -1 ) { - lst = g_list_nth( lst, *(int*)data->buffer ); - if ( lst != NULL ) { - gtk_label_get( GTK_LABEL( GTK_BIN( lst->data )->child ), &entry ); - } - } - if ( entry ) { - gtk_entry_set_text( GTK_ENTRY( GTK_COMBO( data->object )->entry ), entry ); - } - else{ - gtk_entry_set_text( GTK_ENTRY( GTK_COMBO( data->object )->entry ), "" ); - } - } - break; - case DLG_COMBO_BOX_INT: { - gtk_combo_box_set_active( GTK_COMBO_BOX( data->object ), *(int*)data->buffer ); - } - break; - } + ui::Widget label = ui::Label( low ); + label.show(); + hbox2.pack_start( label, FALSE, FALSE, 0 ); + } + { + ui::Widget label = ui::Label( high ); + label.show(); + hbox2.pack_end(label, FALSE, FALSE, 0); } } +#endif + + // adjustment + auto adj = ui::Adjustment( value, lower, upper, step_increment, page_increment, 0 ); + AddIntAdjustmentData( *GTK_ADJUSTMENT(adj), IntImportCaller( data ), IntExportCaller( data ) ); + + // scale + auto alignment = ui::Alignment( 0.0, 0.5, 1.0, 0.0 ); + alignment.show(); + + ui::Widget scale = ui::HScale( adj ); + gtk_scale_set_value_pos( GTK_SCALE( scale ), GTK_POS_LEFT ); + scale.show(); + alignment.add(scale); + + gtk_scale_set_draw_value( GTK_SCALE( scale ), draw_value ); + gtk_scale_set_digits( GTK_SCALE( scale ), 0 ); + + auto row = DialogRow_new( name, alignment ); + DialogVBox_packRow( ui::VBox(GTK_VBOX( vbox )), row ); } -void Dialog::EndModal( int code ) { - m_nLoop = 0; - m_nReturn = code; +void Dialog::addRadio( ui::Widget vbox, const char* name, StringArrayRange names, const IntImportCallback& importViewer, const IntExportCallback& exportViewer ){ + auto alignment = ui::Alignment( 0.0, 0.5, 0.0, 0.0 ); + alignment.show();; + { + RadioHBox radioBox = RadioHBox_new( names ); + alignment.add(radioBox.m_hbox); + AddIntRadioData( *GTK_RADIO_BUTTON( radioBox.m_radio ), importViewer, exportViewer ); + } + + auto row = DialogRow_new( name, alignment ); + DialogVBox_packRow( ui::VBox(GTK_VBOX( vbox )), row ); } -int Dialog::DoModal(){ - Create(); - UpdateData( FALSE ); +void Dialog::addRadio( ui::Widget vbox, const char* name, int& data, StringArrayRange names ){ + addRadio( vbox, name, names, IntImportCaller( data ), IntExportCaller( data ) ); +} - PreModal(); +void Dialog::addRadioIcons( ui::Widget vbox, const char* name, StringArrayRange icons, const IntImportCallback& importViewer, const IntExportCallback& exportViewer ){ + ui::Widget table = ui::Table( 2, icons.last - icons.first, FALSE ); + table.show();; - gtk_grab_add( m_pWidget ); - gtk_widget_show( m_pWidget ); + gtk_table_set_row_spacings( GTK_TABLE( table ), 5 ); + gtk_table_set_col_spacings( GTK_TABLE( table ), 5 ); - m_nLoop = 1; - while ( m_nLoop ) { - gtk_main_iteration(); + GSList* group = 0; + ui::RadioButton radio{ui::null}; + for ( StringArrayRange::Iterator icon = icons.first; icon != icons.last; ++icon ) + { + guint pos = static_cast( icon - icons.first ); + auto image = new_local_image( *icon ); + image.show(); + gtk_table_attach( GTK_TABLE( table ), image , pos, pos + 1, 0, 1, + (GtkAttachOptions) ( 0 ), + (GtkAttachOptions) ( 0 ), 0, 0 ); + + radio = ui::RadioButton(GTK_RADIO_BUTTON(gtk_radio_button_new( group ))); + radio.show(); + gtk_table_attach( GTK_TABLE( table ), radio, pos, pos + 1, 1, 2, + (GtkAttachOptions) ( 0 ), + (GtkAttachOptions) ( 0 ), 0, 0 ); + + group = gtk_radio_button_get_group( GTK_RADIO_BUTTON( radio ) ); } - if ( m_pWidget != NULL ) { - UpdateData( TRUE ); + AddIntRadioData( *GTK_RADIO_BUTTON( radio ), importViewer, exportViewer ); - gtk_grab_remove( m_pWidget ); - gtk_widget_hide( m_pWidget ); - } - PostModal( m_nReturn ); + DialogVBox_packRow( ui::VBox(GTK_VBOX( vbox )), DialogRow_new( name, table ) ); +} + +void Dialog::addRadioIcons( ui::Widget vbox, const char* name, int& data, StringArrayRange icons ){ + addRadioIcons( vbox, name, icons, IntImportCaller( data ), IntExportCaller( data ) ); +} + +ui::Widget Dialog::addIntEntry( ui::Widget vbox, const char* name, const IntImportCallback& importViewer, const IntExportCallback& exportViewer ){ + DialogEntryRow row( DialogEntryRow_new( name ) ); + AddIntEntryData( *GTK_ENTRY(row.m_entry), importViewer, exportViewer ); + DialogVBox_packRow( ui::VBox(GTK_VBOX( vbox )), row.m_row ); + return row.m_row; +} + +ui::Widget Dialog::addSizeEntry( ui::Widget vbox, const char* name, const SizeImportCallback& importViewer, const SizeExportCallback& exportViewer ){ + DialogEntryRow row( DialogEntryRow_new( name ) ); + AddSizeEntryData( *GTK_ENTRY(row.m_entry), importViewer, exportViewer ); + DialogVBox_packRow( ui::VBox(GTK_VBOX( vbox )), row.m_row ); + return row.m_row; +} + +ui::Widget Dialog::addFloatEntry( ui::Widget vbox, const char* name, const FloatImportCallback& importViewer, const FloatExportCallback& exportViewer ){ + DialogEntryRow row( DialogEntryRow_new( name ) ); + AddFloatEntryData( *GTK_ENTRY(row.m_entry), importViewer, exportViewer ); + DialogVBox_packRow( ui::VBox(GTK_VBOX( vbox )), row.m_row ); + return row.m_row; +} + +ui::Widget Dialog::addPathEntry( ui::Widget vbox, const char* name, bool browse_directory, const StringImportCallback& importViewer, const StringExportCallback& exportViewer ){ + PathEntry pathEntry = PathEntry_new(); + pathEntry.m_button.connect( "clicked", G_CALLBACK( browse_directory ? button_clicked_entry_browse_directory : button_clicked_entry_browse_file ), pathEntry.m_entry ); + + AddTextEntryData( *GTK_ENTRY(pathEntry.m_entry), importViewer, exportViewer ); + + auto row = DialogRow_new( name, ui::Widget(pathEntry.m_frame ) ); + DialogVBox_packRow( ui::VBox(GTK_VBOX( vbox )), row ); + + return ui::Widget(row ); +} + +ui::Widget Dialog::addPathEntry( ui::Widget vbox, const char* name, CopiedString& data, bool browse_directory ){ + return addPathEntry( vbox, name, browse_directory, StringImportCallback( StringImportCaller( data ) ), StringExportCallback( StringExportCaller( data ) ) ); +} + +ui::SpinButton Dialog::addSpinner( ui::Widget vbox, const char* name, double value, double lower, double upper, const IntImportCallback& importViewer, const IntExportCallback& exportViewer ){ + DialogSpinnerRow row( DialogSpinnerRow_new( name, value, lower, upper, 1 ) ); + AddIntSpinnerData( *GTK_SPIN_BUTTON(row.m_spin), importViewer, exportViewer ); + DialogVBox_packRow( ui::VBox(GTK_VBOX( vbox )), row.m_row ); + return ui::SpinButton(row.m_spin); +} + +ui::SpinButton Dialog::addSpinner( ui::Widget vbox, const char* name, int& data, double value, double lower, double upper ){ + return addSpinner( vbox, name, value, lower, upper, IntImportCallback( IntImportCaller( data ) ), IntExportCallback( IntExportCaller( data ) ) ); +} - return m_nReturn; +ui::SpinButton Dialog::addSpinner( ui::Widget vbox, const char* name, double value, double lower, double upper, const FloatImportCallback& importViewer, const FloatExportCallback& exportViewer ){ + DialogSpinnerRow row( DialogSpinnerRow_new( name, value, lower, upper, 10 ) ); + AddFloatSpinnerData( *GTK_SPIN_BUTTON(row.m_spin), importViewer, exportViewer ); + DialogVBox_packRow( ui::VBox(GTK_VBOX( vbox )), row.m_row ); + return ui::SpinButton(row.m_spin); }