1 /** \file   drivemodelwidget.c
2  * \brief   Drive model selection widget
3  *
4  * \author  Bas Wassink <b.wassink@ziggo.nl>
5  */
6 
7 /*
8  * $VICERES Drive8Type      -vsid
9  * $VICERES Drive9Type      -vsid
10  * $VICERES Drive10Type     -vsid
11  * $VICERES Drive11Type     -vsid
12  */
13 
14 /*
15  * This file is part of VICE, the Versatile Commodore Emulator.
16  * See README for copyright notice.
17  *
18  *  This program is free software; you can redistribute it and/or modify
19  *  it under the terms of the GNU General Public License as published by
20  *  the Free Software Foundation; either version 2 of the License, or
21  *  (at your option) any later version.
22  *
23  *  This program is distributed in the hope that it will be useful,
24  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
25  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
26  *  GNU General Public License for more details.
27  *
28  *  You should have received a copy of the GNU General Public License
29  *  along with this program; if not, write to the Free Software
30  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
31  *  02111-1307  USA.
32  *
33  */
34 
35 #include "vice.h"
36 
37 #include <gtk/gtk.h>
38 
39 #include "widgethelpers.h"
40 #include "debug_gtk3.h"
41 #include "machine-drive.h"
42 #include "resources.h"
43 #include "drive.h"
44 #include "drive-check.h"
45 #include "driveparallelcablewidget.h"
46 #include "drivewidgethelpers.h"
47 #include "driveoptionswidget.h"
48 
49 #include "drivemodelwidget.h"
50 
51 
52 /** \brief  Handler for the "toggled" event of the radio buttons
53  *
54  * \param[in]   widget      radio button
55  * \param[in]   user_data   unit number
56  */
on_radio_toggled(GtkWidget * widget,gpointer user_data)57 static void on_radio_toggled(GtkWidget *widget, gpointer user_data)
58 {
59     if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) {
60         GtkWidget *parent;
61         int unit;
62         int new_type;
63         int old_type;
64 
65         parent = gtk_widget_get_parent(widget);
66         unit = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(parent), "UnitNumber"));
67         new_type = GPOINTER_TO_INT(user_data);
68         old_type = ui_get_drive_type(unit);
69 
70 
71         /* prevent drive reset when switching unit number and updating the
72          * drive type widget */
73         if (new_type != old_type) {
74             void (*cb_func)(GtkWidget *, gpointer);
75             gpointer cb_data;
76 
77             debug_gtk3("setting Drive%dType to %d.", unit, new_type);
78             resources_set_int_sprintf("Drive%dType", new_type, unit);
79 
80             /* check for a custom callback */
81             parent = gtk_widget_get_parent(widget);
82             cb_func = g_object_get_data(G_OBJECT(parent), "CallbackFunc");
83             if (cb_func != NULL) {
84                 /* get callback data */
85                 cb_data = g_object_get_data(G_OBJECT(parent), "CallbackData");
86                 /* trigger callback */
87                 cb_func(widget, cb_data);
88             }
89 
90         }
91 
92         /* this should be handled by signal handlers in uidrivesettings.c now */
93 #if 0
94         /* enable/disable 40-track settings widget */
95         if (drive_extend_widget != NULL) {
96              tgtk_widget_set_sensitive(drive_extend_widget,
97                     drive_check_extend_policy(new_type));
98         }
99         /* update expansions widget */
100         if (drive_expansion_widget != NULL) {
101             drive_expansion_widget_update(drive_expansion_widget, unit_number);
102         }
103         /* update parallel cable widget */
104         if (drive_parallel_cable_widget != NULL) {
105             drive_parallel_cable_widget_update(drive_parallel_cable_widget,
106                     unit_number);
107         }
108         if (drive_options_widget != NULL) {
109             drive_options_widget_update(drive_options_widget, unit_number);
110         }
111 #endif
112     }
113 }
114 
115 
116 /** \brief  Create a drive unit selection widget
117  *
118  * Creates a widget with four radio buttons, horizontally aligned, to select
119  * a drive unit (8-11)
120  *
121  * \param[in]   unit    default drive unit
122  *
123  * \return  GtkGrid
124  */
drive_model_widget_create(int unit)125 GtkWidget *drive_model_widget_create(int unit)
126 {
127     GtkWidget *grid;
128     drive_type_info_t *list;
129     GtkRadioButton *last = NULL;
130     GSList *group = NULL;
131     size_t i;
132     int type;
133     int num;
134     int row;
135 
136     resources_get_int_sprintf("Drive%dType", &type, unit);
137 
138     grid = uihelpers_create_grid_with_label("Drive type", 2);
139     /* store unit number as a property in the widget */
140     g_object_set_data(G_OBJECT(grid), "UnitNumber", GINT_TO_POINTER(unit));
141 
142     list = machine_drive_get_type_info_list();
143     for (i = 0; list[i].name != NULL; i++) {
144         /* NOP */
145     }
146     num = i;
147 
148     for (i = 0; list[i].name != NULL && i < num / 2; i++) {
149         GtkWidget *radio = gtk_radio_button_new_with_label(group, list[i].name);
150         gtk_radio_button_join_group(GTK_RADIO_BUTTON(radio), last);
151         g_object_set(radio, "margin-left", 16, NULL);
152         g_object_set_data(G_OBJECT(radio), "ModelID",
153                 GINT_TO_POINTER(list[i].id));
154 
155         if (list[i].id == type) {
156             gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio), TRUE);
157         }
158 
159         g_signal_connect(radio, "toggled", G_CALLBACK(on_radio_toggled),
160                 GINT_TO_POINTER(list[i].id));
161 
162         gtk_grid_attach(GTK_GRID(grid), radio, 0, i + 1, 1, 1);
163         last = GTK_RADIO_BUTTON(radio);
164     }
165 
166     row = 1;
167     while (list[i].name != NULL) {
168         GtkWidget *radio = gtk_radio_button_new_with_label(group, list[i].name);
169         gtk_radio_button_join_group(GTK_RADIO_BUTTON(radio), last);
170         g_object_set(radio, "margin-left", 16, NULL);
171         g_object_set_data(G_OBJECT(radio), "ModelID",
172                 GINT_TO_POINTER(list[i].id));
173         if (list[i].id == type) {
174             gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio), TRUE);
175         }
176 
177         g_signal_connect(radio, "toggled", G_CALLBACK(on_radio_toggled),
178                 GINT_TO_POINTER(list[i].id));
179 
180         gtk_grid_attach(GTK_GRID(grid), radio, 1, row, 1, 1);
181         row++;
182         last = GTK_RADIO_BUTTON(radio);
183         i++;
184     }
185 
186     drive_model_widget_update(grid);
187 
188     gtk_widget_show_all(grid);
189     return grid;
190 }
191 
192 
193 /** \brief  Update the drive type widget
194  *
195  * This reiterates the drive info list to see if any setting changes made drive
196  * types available/unavailable.
197  *
198  * \param[in,out]   widget  drive type widget
199  * \param[in]       unit    new unit number
200  */
drive_model_widget_update(GtkWidget * widget)201 void drive_model_widget_update(GtkWidget *widget)
202 {
203     drive_type_info_t *list;
204     size_t i;
205     int unit;
206     int type;
207     int num;
208     int row;
209 
210     unit = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), "UnitNumber"));
211     type = ui_get_drive_type(unit);
212 
213     list = machine_drive_get_type_info_list();
214     debug_gtk3("updating drive type list.");
215 
216     for (i = 0; list[i].name != NULL; i++) {
217         /* NOP */
218     }
219     num = i;
220 
221 
222     for (i = 0; list[i].name != NULL && i < num / 2; i++) {
223 
224         GtkWidget *radio = gtk_grid_get_child_at(GTK_GRID(widget), 0, i + 1);
225         if (radio != NULL && GTK_IS_RADIO_BUTTON(radio)) {
226             debug_gtk3("row 0: checking drive ID %d", list[i].id);
227             gtk_widget_set_sensitive(radio, drive_check_type(
228                         (unsigned int)(list[i].id), (unsigned int)(unit - 8)));
229             if (list[i].id == type) {
230                 /* TODO: temporary block the resource-set callback */
231                 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio), TRUE);
232             }
233         }
234     }
235 
236     row = 1;
237     while (list[i].name != NULL) {
238         GtkWidget *radio = gtk_grid_get_child_at(GTK_GRID(widget), 1, row);
239         if (radio != NULL && GTK_IS_RADIO_BUTTON(radio)) {
240             debug_gtk3("row 1: checking drive ID %d", list[i].id);
241             gtk_widget_set_sensitive(radio, drive_check_type(
242                         (unsigned int)(list[i].id),
243                         (unsigned int)(unit - 8)));
244             if (list[i].id == type) {
245                 /* TODO: temporary block the resource-set callback */
246                 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio), TRUE);
247             }
248         }
249         row++;
250         i++;
251     }
252 }
253 
254 
drive_model_widget_add_callback(GtkWidget * widget,void (* cb_func)(GtkWidget *,gpointer),gpointer cb_data)255 void drive_model_widget_add_callback(GtkWidget *widget,
256                                      void (*cb_func)(GtkWidget *, gpointer),
257                                      gpointer cb_data)
258 {
259     g_object_set_data(G_OBJECT(widget), "CallbackFunc", (gpointer)cb_func);
260     g_object_set_data(G_OBJECT(widget), "CallbackData", cb_data);
261 }
262