1 
2 /*
3  * The Real SoundTracker - GUI support routines (header)
4  *
5  * Copyright (C) 1998-2019 Michael Krause
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20  */
21 
22 #ifndef _GUI_SUBS_H
23 #define _GUI_SUBS_H
24 
25 #include <gtk/gtk.h>
26 
27 /* values for status bar messages */
28 enum {
29     STATUS_IDLE = 0,
30     STATUS_PLAYING_SONG,
31     STATUS_PLAYING_PATTERN,
32     STATUS_LOADING_MODULE,
33     STATUS_MODULE_LOADED,
34     STATUS_SAVING_MODULE,
35     STATUS_MODULE_SAVED,
36     STATUS_LOADING_SAMPLE,
37     STATUS_SAMPLE_LOADED,
38     STATUS_SAVING_SAMPLE,
39     STATUS_SAMPLE_SAVED,
40     STATUS_LOADING_INSTRUMENT,
41     STATUS_INSTRUMENT_LOADED,
42     STATUS_SAVING_INSTRUMENT,
43     STATUS_INSTRUMENT_SAVED,
44     STATUS_SAVING_SONG,
45     STATUS_SONG_SAVED,
46 };
47 
48 struct menu_callback {
49     const gchar* widget_name;
50     void (*fn)();
51     gpointer data;
52 };
53 
54 extern const gint SIZES_MENU_TOOLBOX[];
55 extern const gint SIZES_MENU[];
56 
57 typedef struct
58 {
59     const gchar *gui_name, *file_name;
60     const gint* sizes; /* 0-terminated */
61 } icon_set;
62 
63 int find_current_toggle(GtkWidget** widgets,
64     int count);
65 
66 void add_empty_hbox(GtkWidget* tobox);
67 void add_empty_vbox(GtkWidget* tobox);
68 
69 void make_radio_group_full_num(const char* labels[],
70     GtkWidget* tobox,
71     GtkWidget* saveptr[],
72     gint t1,
73     gint t2,
74     void (*sigfunc)(),
75     gpointer data,
76     gboolean end,
77     guint num);
78 
79 #define make_radio_group_full_ext(labels, tobox, saveptr, t1, t2, sigfunc, data, end) \
80 make_radio_group_full_num(labels, tobox, saveptr, t1, t2, sigfunc, data, end, sizeof(labels) / sizeof(labels[0]))
81 
82 #define make_radio_group_full(labels, tobox, saveptr, t1, t2, sigfunc, data) \
83 make_radio_group_full_num(labels, tobox, saveptr, t1, t2, sigfunc, data, FALSE, sizeof(labels) / sizeof(labels[0]))
84 
85 #define make_radio_group(labels, tobox, saveptr, t1, t2, sigfunc) \
86 make_radio_group_full_num(labels, tobox, saveptr, t1, t2, sigfunc, NULL, FALSE, sizeof(labels) / sizeof(labels[0]))
87 
88 GtkWidget*
89 make_labelled_radio_group_box_full_num(const char* title,
90     const char* labels[],
91     GtkWidget* saveptr[],
92     void (*sigfunc)(),
93     gpointer data,
94     guint num);
95 
96 #define make_labelled_radio_group_box_full(title, labels, saveptr, sigfunc, data) \
97 make_labelled_radio_group_box_full_num(title, labels, saveptr, sigfunc, data, sizeof(labels) / sizeof(labels[0]))
98 
99 #define make_labelled_radio_group_box(title, labels, saveptr, sigfunc) \
100 make_labelled_radio_group_box_full_num(title, labels, saveptr, sigfunc, NULL, sizeof(labels) / sizeof(labels[0]))
101 
102 GtkWidget*
103 gui_labelled_spin_button_new(const char* title,
104     int min,
105     int max,
106     GtkWidget** spin,
107     void (*callback)(),
108     void* callbackdata,
109     gboolean in_mainwindow,
110     gint* handler_id);
111 
112 static inline gint
gui_put_labelled_spin_button(GtkWidget * destbox,const char * title,int min,int max,GtkWidget ** spin,void (* callback)(),void * callbackdata,gboolean in_mainwindow)113 gui_put_labelled_spin_button(GtkWidget* destbox,
114     const char* title,
115     int min,
116     int max,
117     GtkWidget** spin,
118     void (*callback)(),
119     void* callbackdata,
120     gboolean in_mainwindow)
121 {
122     gint handler_id;
123     GtkWidget *hbox = gui_labelled_spin_button_new(title, min, max, spin,
124         callback, callbackdata, in_mainwindow, &handler_id);
125 
126     gtk_box_pack_start(GTK_BOX(destbox), hbox, FALSE, TRUE, 0);
127     return handler_id;
128 }
129 
130 static inline void
gui_set_radio_active(GtkWidget ** radiobutton,guint i)131 gui_set_radio_active(GtkWidget** radiobutton, guint i)
132 {
133     if (gtk_widget_is_sensitive(radiobutton[i]))
134         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radiobutton[i]), TRUE);
135 }
136 
137 GtkWidget*
138 gui_subs_create_slider_full(const gchar* title,
139     const gdouble min,
140     const gdouble max,
141     void (*changedfunc)(),
142     GtkAdjustment** adj,
143     gboolean in_mainwindow,
144     gint* tag);
145 
146 static inline GtkWidget*
gui_subs_create_slider(const gchar * title,const gdouble min,const gdouble max,void (* changedfunc)(),GtkAdjustment ** adj,gboolean in_mainwindow)147 gui_subs_create_slider(const gchar* title,
148     const gdouble min,
149     const gdouble max,
150     void (*changedfunc)(),
151     GtkAdjustment** adj,
152     gboolean in_mainwindow)
153 {
154     return gui_subs_create_slider_full(title, min, max, changedfunc, adj, in_mainwindow, NULL);
155 }
156 
157 GtkWidget* gui_combo_new(GtkListStore* ls);
158 
159 gboolean gui_set_active_combo_item(GtkWidget* combobox,
160     GtkTreeModel* model,
161     guint item);
162 
163 void gui_combo_box_prepend_text_or_set_active(GtkComboBoxText* combobox,
164     const gchar* text,
165     gboolean force_active);
166 
167 GtkWidget* gui_list_in_scrolled_window_full(const int n,
168     const gchar* const* tp,
169     GtkWidget* hbox,
170     GType* types,
171     const gfloat* alignments,
172     const gboolean* expands,
173     GtkSelectionMode mode,
174     gboolean expand,
175     gboolean fill,
176     GtkWidget** scrolledwindow,
177     GtkPolicyType hpolicy,
178     GtkPolicyType vpolicy);
179 
gui_list_in_scrolled_window(const int n,const gchar * const * tp,GtkWidget * hbox,GType * types,const gfloat * alignments,const gboolean * expands,GtkSelectionMode mode,gboolean expand,gboolean fill)180 static inline GtkWidget* gui_list_in_scrolled_window(const int n,
181     const gchar* const* tp,
182     GtkWidget* hbox,
183     GType* types,
184     const gfloat* alignments,
185     const gboolean* expands,
186     GtkSelectionMode mode,
187     gboolean expand,
188     gboolean fill)
189 {
190     return gui_list_in_scrolled_window_full(n, tp, hbox, types,
191         alignments, expands, mode, expand, fill, NULL,
192         GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
193 }
194 
195 GtkWidget* gui_stringlist_in_scrolled_window(const int n,
196     const gchar* const* tp,
197     GtkWidget* hbox, gboolean expandfill);
198 
199 void gui_list_clear(GtkWidget* list);
200 void gui_list_clear_with_model(GtkTreeModel* model);
201 GtkTreeModel* gui_list_freeze(GtkWidget* list);
202 void gui_list_thaw(GtkWidget* list,
203     GtkTreeModel* model);
204 
205 #define GUI_GET_LIST_STORE(list) GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(list)))
206 
207 void gui_list_handle_selection(GtkWidget* list,
208     GCallback handler,
209     gpointer data);
210 gint gui_list_get_selection_index(GtkTreeSelection* sel);
211 
212 static inline gboolean
gui_list_get_iter(guint n,GtkListStore * tree_model,GtkTreeIter * iter)213 gui_list_get_iter(guint n, GtkListStore* tree_model, GtkTreeIter* iter)
214 {
215     gchar* path;
216     gboolean result;
217 
218     path = g_strdup_printf("%u", n);
219     result = gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(tree_model), iter, path);
220     g_free(path);
221     return result;
222 }
223 
224 void gui_string_list_set_text(GtkWidget* list,
225     guint row,
226     guint col,
227     const gchar* string);
228 
229 void gui_list_select(GtkWidget* list,
230     guint row,
231     gboolean use_align,
232     gfloat align);
233 
234 GtkWidget* gui_button(GtkWidget* win,
235     char* stock,
236     void* callback,
237     gpointer userdata,
238     GtkWidget* box);
239 
240 gboolean gui_delete_noop(void);
241 void gui_set_escape_close(GtkWidget* window);
242 gboolean gui_ok_cancel_modal(GtkWidget* window, const gchar* text);
243 void gui_errno_dialog (GtkWidget* window, const gchar* text, const int err);
244 void gui_message_dialog(GtkWidget** dialog, const gchar* text, GtkMessageType type, const gchar* title, gboolean need_update);
245 #define gui_warning_dialog(dialog, text, need_update) gui_message_dialog(dialog, text, GTK_MESSAGE_WARNING, N_("Warning"), need_update)
246 #define gui_error_dialog(dialog, text, need_update) gui_message_dialog(dialog, text, GTK_MESSAGE_ERROR, N_("Error!"), need_update)
247 #define gui_info_dialog(dialog, text, need_update) gui_message_dialog(dialog, text, GTK_MESSAGE_INFO, N_("Information"), need_update)
248 void gui_dialog_adjust(GtkWidget* dialog, gint default_id);
249 FILE* gui_fopen(const gchar* name, const gchar* utf_name, const gchar* mode);
250 void gui_oom_error(void);
251 
252 static inline void
gui_dialog_connect(GtkWidget * dialog,GCallback resp_cb)253 gui_dialog_connect(GtkWidget* dialog, GCallback resp_cb)
254 {
255     g_signal_connect(dialog, "delete_event",
256         G_CALLBACK(gui_delete_noop), NULL);
257     g_signal_connect(dialog, "response",
258         resp_cb ? resp_cb : G_CALLBACK(gtk_widget_hide), NULL);
259 }
260 
261 static inline void
gui_dialog_connect_data(GtkWidget * dialog,GCallback resp_cb,gpointer data)262 gui_dialog_connect_data(GtkWidget* dialog, GCallback resp_cb, gpointer data)
263 {
264     g_signal_connect(dialog, "delete_event",
265         G_CALLBACK(gui_delete_noop), NULL);
266     g_signal_connect(dialog, "response",
267         resp_cb ? resp_cb : G_CALLBACK(gtk_widget_hide), data);
268 }
269 
270 gchar* gui_filename_to_utf8(const gchar* old_name);
271 gchar* gui_filename_from_utf8(const gchar* old_name);
272 
273 GtkBuilder* gui_builder_from_file(const gchar* name, const struct menu_callback cb[]);
274 
275 gint gui_get_text_entry(int length,
276     void (*changedfunc)(),
277     GtkWidget** widget);
278 GtkWidget* gui_get_widget(GtkBuilder *builder, const gchar* name, const gchar* file);
279 void gui_popup_menu_attach(GtkWidget* menu, GtkWidget* widget, gpointer* user_data);
280 void gui_get_pixel_size(GtkWidget* w, const char* text, gint* width, gint* height);
281 GdkPixbuf* gui_pixbuf_new_from_file(const gchar* path);
282 /* icon_set should be NULL-terminated */
283 void gui_add_icons(const icon_set* icons);
284 
285 static inline void
_gui_block_signals(GObject * objs[],const gint tags[],const gint number,gboolean block)286 _gui_block_signals(GObject* objs[], const gint tags[], const gint number, gboolean block)
287 {
288     gint i;
289 
290     for (i = 0; i < number; i++)
291         (block ? g_signal_handler_block : g_signal_handler_unblock)(objs[i], tags[i]);
292 }
293 #define gui_block_signals(objs, tags, block)\
294     _gui_block_signals((GObject **)objs, tags, sizeof(objs) / sizeof(objs[0]), block)
295 
296 #endif /* _GUI_SUBS_H */
297