Search
lxdream.org :: lxdream/src/gtkui/gtk_ctrl.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/gtkui/gtk_ctrl.c
changeset 1124:aacaae9812ea
prev1072:d82e04e6d497
author nkeynes
date Fri May 29 18:47:05 2015 +1000 (8 years ago)
permissions -rw-r--r--
last change Fix test case
file annotate diff log raw
nkeynes@447
     1
/**
nkeynes@561
     2
 * $Id$
nkeynes@447
     3
 *
nkeynes@447
     4
 * Define the main (emu) GTK window, along with its menubars,
nkeynes@447
     5
 * toolbars, etc.
nkeynes@447
     6
 *
nkeynes@447
     7
 * Copyright (c) 2005 Nathan Keynes.
nkeynes@447
     8
 *
nkeynes@447
     9
 * This program is free software; you can redistribute it and/or modify
nkeynes@447
    10
 * it under the terms of the GNU General Public License as published by
nkeynes@447
    11
 * the Free Software Foundation; either version 2 of the License, or
nkeynes@447
    12
 * (at your option) any later version.
nkeynes@447
    13
 *
nkeynes@447
    14
 * This program is distributed in the hope that it will be useful,
nkeynes@447
    15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
nkeynes@447
    16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
nkeynes@447
    17
 * GNU General Public License for more details.
nkeynes@447
    18
 */
nkeynes@447
    19
nkeynes@447
    20
#include <assert.h>
nkeynes@669
    21
#include <string.h>
nkeynes@1034
    22
#include <errno.h>
nkeynes@447
    23
#include <gtk/gtk.h>
nkeynes@460
    24
#include <gdk/gdkkeysyms.h>
nkeynes@447
    25
nkeynes@614
    26
#include "lxdream.h"
nkeynes@614
    27
#include "display.h"
nkeynes@537
    28
#include "gtkui/gtkui.h"
nkeynes@447
    29
#include "maple/maple.h"
nkeynes@1034
    30
#include "vmu/vmulist.h"
nkeynes@447
    31
nkeynes@447
    32
#define MAX_DEVICES 4
nkeynes@447
    33
nkeynes@1034
    34
#define LOAD_VMU_TAG ((void *)-1)
nkeynes@1034
    35
#define CREATE_VMU_TAG ((void *)-2)
nkeynes@1034
    36
nkeynes@1034
    37
static void maple_set_device_selection( GtkWidget *combo, maple_device_t device );
nkeynes@455
    38
nkeynes@455
    39
struct maple_config_class {
nkeynes@455
    40
    const char *name;
nkeynes@455
    41
    void (*config_func)(maple_device_t device);
nkeynes@455
    42
};
nkeynes@455
    43
nkeynes@447
    44
typedef struct maple_slot_data {
nkeynes@447
    45
    maple_device_t old_device;
nkeynes@447
    46
    maple_device_t new_device;
nkeynes@447
    47
    GtkWidget *button;
nkeynes@447
    48
    GtkWidget *combo;
nkeynes@1034
    49
    gboolean primarySlot;
nkeynes@447
    50
} *maple_slot_data_t;
nkeynes@447
    51
nkeynes@1034
    52
nkeynes@1034
    53
static struct maple_slot_data maple_data[MAPLE_MAX_DEVICES];
nkeynes@447
    54
nkeynes@1057
    55
/**
nkeynes@1057
    56
 * Flag set when changing the selection on one of the combo boxes manually -
nkeynes@1057
    57
 * avoids the followup changed event.
nkeynes@1057
    58
 */
nkeynes@1057
    59
static gboolean maple_device_adjusting = FALSE;
nkeynes@1057
    60
nkeynes@1034
    61
static gboolean maple_properties_activated( GtkButton *button, gpointer user_data )
nkeynes@447
    62
{
nkeynes@447
    63
    maple_slot_data_t data = (maple_slot_data_t)user_data;
nkeynes@455
    64
    if( data->new_device != NULL ) {
nkeynes@736
    65
        int i;
nkeynes@1072
    66
        lxdream_config_group_t config = data->new_device->get_config(data->new_device);
nkeynes@1072
    67
        if( config != NULL ) {
nkeynes@1072
    68
nkeynes@1072
    69
            if( data->new_device == data->old_device ) {
nkeynes@1072
    70
            // Make a copy at this point if we haven't already
nkeynes@1072
    71
                data->new_device = data->old_device->clone(data->old_device);
nkeynes@736
    72
            }
nkeynes@1072
    73
nkeynes@1072
    74
            gtk_configuration_panel_run(_("Controller Configuration"), config);
nkeynes@736
    75
        }
nkeynes@455
    76
    }
nkeynes@455
    77
    return TRUE;
nkeynes@447
    78
}
nkeynes@447
    79
nkeynes@1034
    80
static gboolean maple_device_changed( GtkComboBox *combo, gpointer user_data )
nkeynes@447
    81
{
nkeynes@1057
    82
    if( maple_device_adjusting ) {
nkeynes@1057
    83
        return TRUE;
nkeynes@1057
    84
    }
nkeynes@1057
    85
    
nkeynes@447
    86
    maple_slot_data_t data = (maple_slot_data_t)user_data;
nkeynes@1034
    87
    int active = gtk_combo_box_get_active(combo), i;
nkeynes@608
    88
    gboolean has_config = FALSE;
nkeynes@1034
    89
    gboolean set_selection = FALSE;
nkeynes@1034
    90
    int has_slots = 0;
nkeynes@447
    91
    if( active != 0 ) {
nkeynes@1034
    92
        GtkTreeIter iter;
nkeynes@1034
    93
        maple_device_class_t devclz;
nkeynes@1034
    94
        const gchar *vmu_filename;
nkeynes@1034
    95
        
nkeynes@1034
    96
        GtkTreeModel *model = gtk_combo_box_get_model(combo);
nkeynes@1034
    97
        gtk_combo_box_get_active_iter(combo, &iter);
nkeynes@1034
    98
        gtk_tree_model_get(model, &iter, 1, &devclz, 2, &vmu_filename, -1 );
nkeynes@1034
    99
        
nkeynes@1034
   100
        if( devclz == LOAD_VMU_TAG ) {
nkeynes@1034
   101
            devclz = NULL;
nkeynes@1036
   102
            vmu_filename = open_file_dialog( _("Load VMU"), "*.vmu", "VMU Files",
nkeynes@1036
   103
                    CONFIG_VMU_PATH );
nkeynes@1034
   104
            if( vmu_filename != NULL ) {
nkeynes@1034
   105
                vmu_volume_t vol = vmu_volume_load( vmu_filename );
nkeynes@1034
   106
                if( vol != NULL ) {
nkeynes@1034
   107
                    devclz = &vmu_class;
nkeynes@1034
   108
                    vmulist_add_vmu(vmu_filename, vol);
nkeynes@1034
   109
                    set_selection = TRUE;
nkeynes@1034
   110
                } else {
nkeynes@1034
   111
                    ERROR( "Unable to load VMU file (not a valid VMU)" );
nkeynes@1034
   112
                }
nkeynes@1034
   113
            }
nkeynes@1034
   114
        } else if( devclz == CREATE_VMU_TAG ) {
nkeynes@1034
   115
            devclz = NULL;
nkeynes@1124
   116
            vmu_filename = save_file_dialog( _("Create VMU"), "*.vmu", "VMU Files", ".vmu",
nkeynes@1036
   117
                    CONFIG_VMU_PATH );
nkeynes@1034
   118
            if( vmu_filename != NULL ) {
nkeynes@1034
   119
                devclz = &vmu_class;
nkeynes@1034
   120
                set_selection = TRUE;
nkeynes@1034
   121
                int idx = vmulist_create_vmu( vmu_filename, FALSE );
nkeynes@1034
   122
                if( idx == -1 ) {
nkeynes@1034
   123
                    ERROR( "Unable to save VMU file: %s", strerror(errno) );
nkeynes@1034
   124
                }
nkeynes@1034
   125
            }
nkeynes@1034
   126
        } else if( vmu_filename != NULL ) {
nkeynes@1034
   127
            devclz = &vmu_class;
nkeynes@1034
   128
        }
nkeynes@1034
   129
nkeynes@1034
   130
        if( devclz == NULL ) {
nkeynes@1034
   131
            maple_set_device_selection(data->combo, data->new_device);
nkeynes@1034
   132
            return TRUE;
nkeynes@1034
   133
        }
nkeynes@1034
   134
nkeynes@736
   135
        if( data->new_device != NULL ) {
nkeynes@736
   136
            if( data->new_device->device_class != devclz ) {
nkeynes@736
   137
                if( data->new_device != data->old_device ) {
nkeynes@736
   138
                    data->new_device->destroy(data->new_device);
nkeynes@736
   139
                }
nkeynes@1034
   140
                data->new_device = devclz->new_device();
nkeynes@736
   141
            }
nkeynes@736
   142
        } else {
nkeynes@1034
   143
            data->new_device = devclz->new_device();
nkeynes@736
   144
        }
nkeynes@1043
   145
        has_config = data->new_device != NULL && data->new_device->get_config != NULL && !MAPLE_IS_VMU(data->new_device);
nkeynes@1034
   146
        has_slots = data->new_device == NULL ? 0 : MAPLE_SLOTS(devclz);
nkeynes@1034
   147
        if( MAPLE_IS_VMU(data->new_device) ) {
nkeynes@1043
   148
            for( i=0; i<MAPLE_MAX_DEVICES; i++ ) {
nkeynes@1043
   149
                if( maple_data[i].new_device != NULL && MAPLE_IS_VMU(maple_data[i].new_device) &&
nkeynes@1043
   150
                        MAPLE_VMU_HAS_NAME(maple_data[i].new_device, vmu_filename) ) {
nkeynes@1043
   151
                    maple_data[i].new_device->destroy(maple_data[i].new_device);
nkeynes@1043
   152
                    maple_data[i].new_device = NULL;
nkeynes@1072
   153
                    gtk_combo_box_set_active(GTK_COMBO_BOX(maple_data[i].combo),0);
nkeynes@1043
   154
                }
nkeynes@1043
   155
            }
nkeynes@1034
   156
            MAPLE_SET_VMU_NAME(data->new_device,vmu_filename);
nkeynes@1034
   157
        }
nkeynes@1034
   158
        
nkeynes@1034
   159
        if( set_selection ) {
nkeynes@1034
   160
            maple_set_device_selection(data->combo, data->new_device);
nkeynes@1034
   161
        }
nkeynes@447
   162
    } else {
nkeynes@736
   163
        if( data->new_device != NULL && data->new_device != data->old_device ) {
nkeynes@736
   164
            data->new_device->destroy(data->new_device);
nkeynes@736
   165
        }
nkeynes@736
   166
        data->new_device = NULL;
nkeynes@447
   167
    }
nkeynes@608
   168
    gtk_widget_set_sensitive(data->button, has_config);
nkeynes@1034
   169
nkeynes@1034
   170
    if( data->primarySlot ) {
nkeynes@1034
   171
        for( i=0; i<MAPLE_USER_SLOTS; i++ ) {
nkeynes@1034
   172
            /* This is a little morally dubious... */
nkeynes@1034
   173
            maple_slot_data_t subdata = data + MAPLE_DEVID(0,(i+1));
nkeynes@1034
   174
            gtk_widget_set_sensitive(subdata->combo, i < has_slots );
nkeynes@1043
   175
            gtk_widget_set_sensitive(subdata->button, i < has_slots && subdata->new_device != NULL && subdata->new_device->get_config != NULL && !MAPLE_IS_VMU(subdata->new_device) );
nkeynes@1034
   176
        }
nkeynes@1034
   177
    }
nkeynes@455
   178
    return TRUE;
nkeynes@447
   179
}
nkeynes@447
   180
nkeynes@1034
   181
static void maple_build_device_model( GtkListStore *dev_model )
nkeynes@447
   182
{
nkeynes@1034
   183
    const struct maple_device_class **devices = maple_get_device_classes();
nkeynes@1034
   184
    int i;
nkeynes@1034
   185
    
nkeynes@1034
   186
    gtk_list_store_clear(dev_model);
nkeynes@1034
   187
    gtk_list_store_insert_with_values( dev_model, NULL, 0, 0, _("<empty>"), 1, NULL, 2, NULL, -1 );
nkeynes@1034
   188
    for( i=0; devices[i] != NULL; i++ ) {
nkeynes@1034
   189
        if( devices[i]->flags & MAPLE_TYPE_PRIMARY ) {
nkeynes@1034
   190
            gtk_list_store_insert_with_values( dev_model, NULL, i+1, 0, devices[i]->name, 1, devices[i], 2, NULL, -1 );
nkeynes@1034
   191
        }
nkeynes@1034
   192
    }
nkeynes@1034
   193
    
nkeynes@1034
   194
}
nkeynes@1034
   195
nkeynes@1034
   196
/**
nkeynes@1034
   197
 * (Re)build the subdevice combo-box model. 
nkeynes@1034
   198
 */
nkeynes@1034
   199
static void maple_build_subdevice_model( GtkListStore *subdev_model )
nkeynes@1034
   200
{
nkeynes@1034
   201
    int i, j;
nkeynes@1034
   202
    const struct maple_device_class **devices = maple_get_device_classes();
nkeynes@1034
   203
    
nkeynes@1034
   204
    gtk_list_store_clear(subdev_model);
nkeynes@1034
   205
    gtk_list_store_insert_with_values( subdev_model, NULL, 0, 0, _("<empty>"), 1, NULL, 2, NULL, -1 );
nkeynes@1034
   206
    for( i=0; devices[i] != NULL; i++ ) {
nkeynes@1034
   207
        if( !(devices[i]->flags & MAPLE_TYPE_PRIMARY) && !MAPLE_IS_VMU_CLASS(devices[i]) ) {
nkeynes@1034
   208
            gtk_list_store_insert_with_values( subdev_model, NULL, i+1, 0, devices[i]->name, 1, devices[i], 2, NULL, -1 );
nkeynes@1034
   209
        }
nkeynes@1034
   210
    }
nkeynes@1034
   211
    for( j=0; j < vmulist_get_size(); j++ ) {
nkeynes@1034
   212
        gtk_list_store_insert_with_values( subdev_model, NULL, i+j+1, 0, vmulist_get_name(j), 1, NULL, 2, vmulist_get_filename(j), -1 );
nkeynes@1034
   213
    }
nkeynes@1034
   214
    gtk_list_store_insert_with_values( subdev_model, NULL, i+j+1, 0, _("Load VMU..."), 1, LOAD_VMU_TAG, 2, NULL, -1 );
nkeynes@1034
   215
    gtk_list_store_insert_with_values( subdev_model, NULL, i+j+2, 0, _("Create VMU..."), 1, CREATE_VMU_TAG, 2, NULL, -1 );
nkeynes@1034
   216
}
nkeynes@1034
   217
nkeynes@1034
   218
static gboolean maple_vmulist_changed( vmulist_change_type_t type, int idx, void *data )
nkeynes@1034
   219
{
nkeynes@1034
   220
    GtkListStore *list = (GtkListStore *)data;
nkeynes@1034
   221
    GtkTreeIter iter;
nkeynes@1034
   222
    int i,j;
nkeynes@1034
   223
    
nkeynes@1034
   224
    /* Search for the row and update accordingly. There's probably better ways
nkeynes@1034
   225
     * to do this 
nkeynes@1034
   226
     */
nkeynes@1034
   227
    
nkeynes@1034
   228
    gboolean valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(list), &iter);
nkeynes@1034
   229
    while( valid ) {
nkeynes@1034
   230
        gchar *vmu_filename;
nkeynes@1057
   231
        gpointer devclz;
nkeynes@1057
   232
        gtk_tree_model_get(GTK_TREE_MODEL(list), &iter, 1, &devclz, 2, &vmu_filename, -1 );
nkeynes@1057
   233
        if( vmu_filename != NULL || devclz == LOAD_VMU_TAG || devclz == CREATE_VMU_TAG )
nkeynes@1034
   234
            break;
nkeynes@1034
   235
        valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(list), &iter);
nkeynes@1034
   236
    }
nkeynes@1034
   237
    if( valid ) {
nkeynes@1034
   238
        for( i=0; i<idx && valid; i++ ) {
nkeynes@1034
   239
            valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(list), &iter);
nkeynes@1034
   240
        }
nkeynes@1034
   241
    }
nkeynes@1034
   242
    if( valid ) {
nkeynes@1034
   243
        if( type == VMU_ADDED ) {
nkeynes@1034
   244
            GtkTreeIter newiter;
nkeynes@1034
   245
            gtk_list_store_insert_before(list, &newiter, &iter);
nkeynes@1034
   246
            gtk_list_store_set(list, &newiter, 0, vmulist_get_name(idx), 1, NULL, 2, vmulist_get_filename(idx), -1 );
nkeynes@1034
   247
        } else if( type == VMU_REMOVED ) {
nkeynes@1034
   248
            gtk_list_store_remove(list, &iter );
nkeynes@1034
   249
        }
nkeynes@1034
   250
    }
nkeynes@1034
   251
    return TRUE;
nkeynes@1034
   252
}
nkeynes@1034
   253
nkeynes@1034
   254
/**
nkeynes@1034
   255
 * Set the device popup selection based on the device (works for both primary
nkeynes@1034
   256
 * and secondary devices)
nkeynes@1034
   257
 */
nkeynes@1034
   258
static void maple_set_device_selection( GtkWidget *combo, maple_device_t device )
nkeynes@1034
   259
{
nkeynes@1034
   260
    GtkTreeModel *model = gtk_combo_box_get_model(GTK_COMBO_BOX(combo));
nkeynes@1034
   261
    GtkTreeIter iter;
nkeynes@1034
   262
nkeynes@1057
   263
    maple_device_adjusting = TRUE;
nkeynes@1034
   264
    if( device == NULL ) {
nkeynes@1034
   265
        gtk_combo_box_set_active( GTK_COMBO_BOX(combo), 0 );
nkeynes@1057
   266
    } else {
nkeynes@1057
   267
        gboolean valid = gtk_tree_model_get_iter_first(model, &iter);
nkeynes@1057
   268
        while( valid ) {
nkeynes@1057
   269
            const struct maple_device_class *clz;
nkeynes@1057
   270
            const gchar *vmu_filename;
nkeynes@1057
   271
nkeynes@1057
   272
            gtk_tree_model_get(model, &iter, 1, &clz, 2, &vmu_filename, -1 );
nkeynes@1057
   273
nkeynes@1057
   274
            if( device->device_class == clz ) {
nkeynes@1057
   275
                gtk_combo_box_set_active_iter( GTK_COMBO_BOX(combo), &iter );
nkeynes@1057
   276
                break;
nkeynes@1057
   277
            } else if( vmu_filename != NULL && MAPLE_IS_VMU(device) && 
nkeynes@1057
   278
                    MAPLE_VMU_HAS_NAME(device, vmu_filename) ) {
nkeynes@1057
   279
                gtk_combo_box_set_active_iter( GTK_COMBO_BOX(combo), &iter );
nkeynes@1057
   280
                break;
nkeynes@1057
   281
            }
nkeynes@1057
   282
nkeynes@1057
   283
            valid = gtk_tree_model_iter_next(model, &iter);
nkeynes@1057
   284
        }
nkeynes@1057
   285
        if( !valid ) {
nkeynes@1057
   286
            gtk_combo_box_set_active(GTK_COMBO_BOX(combo), 0);
nkeynes@1057
   287
        }
nkeynes@1034
   288
    }
nkeynes@1057
   289
    maple_device_adjusting = FALSE;
nkeynes@1034
   290
}
nkeynes@1034
   291
nkeynes@1034
   292
static void maple_dialog_done( GtkWidget *panel, gboolean isOK )
nkeynes@1034
   293
{
nkeynes@1034
   294
    void *p = g_object_get_data( G_OBJECT(panel), "subdev_model" );
nkeynes@1034
   295
    unregister_vmulist_change_hook( maple_vmulist_changed, p );
nkeynes@1034
   296
    
nkeynes@460
   297
    if( isOK ) {
nkeynes@736
   298
        int i;
nkeynes@1034
   299
        for( i=0; i<MAPLE_MAX_DEVICES; i++ ) {
nkeynes@736
   300
            if( maple_data[i].new_device != maple_data[i].old_device ) {
nkeynes@736
   301
                if( maple_data[i].old_device != NULL ) {
nkeynes@1034
   302
                    maple_detach_device(MAPLE_DEVID_PORT(i),MAPLE_DEVID_SLOT(i));
nkeynes@736
   303
                }
nkeynes@736
   304
                if( maple_data[i].new_device != NULL ) {
nkeynes@1034
   305
                    maple_attach_device(maple_data[i].new_device, MAPLE_DEVID_PORT(i), MAPLE_DEVID_SLOT(i) );
nkeynes@736
   306
                }
nkeynes@736
   307
            }
nkeynes@736
   308
        }
nkeynes@736
   309
        lxdream_save_config();
nkeynes@460
   310
    } else {
nkeynes@736
   311
        int i;
nkeynes@1034
   312
        for( i=0; i<MAPLE_MAX_DEVICES; i++ ) {
nkeynes@736
   313
            if( maple_data[i].new_device != NULL && 
nkeynes@736
   314
                    maple_data[i].new_device != maple_data[i].old_device ) {
nkeynes@736
   315
                maple_data[i].new_device->destroy(maple_data[i].new_device);
nkeynes@736
   316
            }
nkeynes@736
   317
        }
nkeynes@447
   318
    }
nkeynes@447
   319
nkeynes@447
   320
}
nkeynes@447
   321
nkeynes@1034
   322
static GtkWidget *maple_panel_new()
nkeynes@447
   323
{
nkeynes@1034
   324
    GtkWidget *table = gtk_table_new( MAPLE_PORTS * (MAPLE_USER_SLOTS+1), 3, TRUE);
nkeynes@1034
   325
    int i,j,k;
nkeynes@447
   326
    const struct maple_device_class **devices = maple_get_device_classes();
nkeynes@1057
   327
    
nkeynes@1034
   328
    gtk_table_set_row_spacings(GTK_TABLE(table), 3);
nkeynes@1034
   329
    gtk_table_set_col_spacings(GTK_TABLE(table), 5);
nkeynes@1057
   330
    maple_device_adjusting = FALSE;
nkeynes@1034
   331
    
nkeynes@1034
   332
    /* Device models */
nkeynes@1034
   333
    GtkListStore *dev_model = gtk_list_store_new(3, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_STRING);
nkeynes@1034
   334
    maple_build_device_model(dev_model);
nkeynes@1034
   335
    
nkeynes@1034
   336
    GtkListStore *subdev_model = gtk_list_store_new(3, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_STRING);
nkeynes@1034
   337
    maple_build_subdevice_model(subdev_model);
nkeynes@1034
   338
    g_object_set_data( G_OBJECT(table), "subdev_model", subdev_model ); 
nkeynes@1034
   339
    register_vmulist_change_hook( maple_vmulist_changed, subdev_model );
nkeynes@1034
   340
    
nkeynes@1034
   341
    int y =0;
nkeynes@1034
   342
    for( i=0; i< MAPLE_PORTS; i++ ) {
nkeynes@764
   343
        char buf[16];
nkeynes@736
   344
        GtkWidget *combo, *button;
nkeynes@1057
   345
        int length = 1;
nkeynes@736
   346
        maple_device_t device = maple_get_device(i,0);
nkeynes@1034
   347
        int has_slots = device == NULL ? 0 : MAPLE_SLOTS(device->device_class);
nkeynes@1034
   348
nkeynes@1034
   349
        snprintf( buf, sizeof(buf), _("Port %c."), 'A'+i );
nkeynes@1034
   350
        gtk_table_attach_defaults( GTK_TABLE(table), gtk_label_new(buf), 0, 1, y, y+1 );
nkeynes@1034
   351
nkeynes@1034
   352
        combo = gtk_combo_box_new_with_model(GTK_TREE_MODEL(dev_model));
nkeynes@1034
   353
        GtkCellRenderer *rend = gtk_cell_renderer_text_new();
nkeynes@1034
   354
        gtk_cell_layout_pack_start( GTK_CELL_LAYOUT(combo), rend, TRUE);
nkeynes@1034
   355
        gtk_cell_layout_add_attribute( GTK_CELL_LAYOUT(combo), rend, "text", 0 );
nkeynes@1034
   356
        maple_set_device_selection(combo,device);
nkeynes@1034
   357
        gtk_table_attach_defaults( GTK_TABLE(table), combo, 1, 2, y, y+1 );
nkeynes@1034
   358
nkeynes@736
   359
        button = gtk_button_new_from_stock( GTK_STOCK_PROPERTIES );
nkeynes@1057
   360
        gtk_widget_set_sensitive(button, device != NULL && device->get_config != NULL);
nkeynes@1034
   361
        gtk_table_attach_defaults( GTK_TABLE(table), button, 2, 3, y, y+1 );
nkeynes@447
   362
nkeynes@1034
   363
        maple_data[MAPLE_DEVID(i,0)].old_device = device;
nkeynes@1034
   364
        maple_data[MAPLE_DEVID(i,0)].new_device = device;
nkeynes@1034
   365
        maple_data[MAPLE_DEVID(i,0)].combo = combo;
nkeynes@1034
   366
        maple_data[MAPLE_DEVID(i,0)].button = button;
nkeynes@1034
   367
        maple_data[MAPLE_DEVID(i,0)].primarySlot = TRUE;
nkeynes@736
   368
        g_signal_connect( button, "clicked", 
nkeynes@1034
   369
                          G_CALLBACK( maple_properties_activated ), &maple_data[MAPLE_DEVID(i,0)] );
nkeynes@736
   370
        g_signal_connect( combo, "changed", 
nkeynes@1034
   371
                          G_CALLBACK( maple_device_changed ), &maple_data[MAPLE_DEVID(i,0)] );
nkeynes@1034
   372
        y++;
nkeynes@1034
   373
        
nkeynes@1034
   374
        for( k=0; k< MAPLE_USER_SLOTS; k++ ) {
nkeynes@1034
   375
            char tmp[32] = "        ";
nkeynes@1034
   376
            device = maple_get_device(i,k+1);
nkeynes@1034
   377
            snprintf( tmp+8, sizeof(tmp)-8, _("VMU %d."), (k+1) );
nkeynes@1034
   378
            gtk_table_attach_defaults( GTK_TABLE(table), gtk_label_new(tmp), 0, 1, y, y+1 );
nkeynes@1034
   379
            combo = gtk_combo_box_new_with_model(GTK_TREE_MODEL(subdev_model));
nkeynes@1034
   380
            GtkCellRenderer *rend = gtk_cell_renderer_text_new();
nkeynes@1034
   381
            gtk_cell_layout_pack_start( GTK_CELL_LAYOUT(combo), rend, TRUE);
nkeynes@1034
   382
            gtk_cell_layout_add_attribute( GTK_CELL_LAYOUT(combo), rend, "text", 0 );
nkeynes@1034
   383
            maple_set_device_selection(combo, device);
nkeynes@1034
   384
            
nkeynes@1034
   385
            gtk_table_attach_defaults( GTK_TABLE(table), combo, 1, 2, y, y+1 );
nkeynes@1034
   386
            button = gtk_button_new_from_stock( GTK_STOCK_PROPERTIES );
nkeynes@1034
   387
            gtk_table_attach_defaults( GTK_TABLE(table), button, 2, 3, y, y+1 );
nkeynes@1034
   388
            if( k >= has_slots ) {
nkeynes@1034
   389
                gtk_widget_set_sensitive(combo, FALSE);
nkeynes@1034
   390
                gtk_widget_set_sensitive(button, FALSE);
nkeynes@1034
   391
            } else {
nkeynes@1034
   392
                gtk_widget_set_sensitive(button, device != NULL && device->get_config != NULL && !MAPLE_IS_VMU(device));
nkeynes@1034
   393
            }            
nkeynes@1034
   394
            
nkeynes@1034
   395
            maple_data[MAPLE_DEVID(i,k+1)].old_device = device;
nkeynes@1034
   396
            maple_data[MAPLE_DEVID(i,k+1)].new_device = device;
nkeynes@1034
   397
            maple_data[MAPLE_DEVID(i,k+1)].combo = combo;
nkeynes@1034
   398
            maple_data[MAPLE_DEVID(i,k+1)].button = button;
nkeynes@1034
   399
            maple_data[MAPLE_DEVID(i,k+1)].primarySlot = FALSE;
nkeynes@1034
   400
            g_signal_connect( button, "clicked", 
nkeynes@1034
   401
                              G_CALLBACK( maple_properties_activated ), &maple_data[MAPLE_DEVID(i,k+1)] );
nkeynes@1034
   402
            g_signal_connect( combo, "changed", 
nkeynes@1034
   403
                              G_CALLBACK( maple_device_changed ), &maple_data[MAPLE_DEVID(i,k+1)] );
nkeynes@1034
   404
            y++;
nkeynes@1034
   405
        }
nkeynes@1034
   406
        gtk_table_set_row_spacing( GTK_TABLE(table), y-1, 10 );
nkeynes@447
   407
    }
nkeynes@447
   408
    return table;
nkeynes@447
   409
}
nkeynes@447
   410
nkeynes@460
   411
void maple_dialog_run( )
nkeynes@447
   412
{
nkeynes@508
   413
    gtk_gui_run_property_dialog( _("Controller Settings"), maple_panel_new(), maple_dialog_done );
nkeynes@447
   414
}
.