1 /*
2  *  KCemu -- The emulator for the KC85 homecomputer series and much more.
3  *  Copyright (C) 1997-2010 Torsten Paul
4  *
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License along
16  *  with this program; if not, write to the Free Software Foundation, Inc.,
17  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  */
19 
20 #include <string>
21 
22 #include "kc/kc.h"
23 
24 #include "ui/gtk/window.h"
25 
26 #include "ui/gtk/cmd.h"
27 
28 using namespace std;
29 
30 bool UI_Gtk_Window::_static_init = false;
31 string UI_Gtk_Window::_icon_path;
32 string UI_Gtk_Window::_image_path;
33 
UI_Gtk_Window(void)34 UI_Gtk_Window::UI_Gtk_Window(void)
35 {
36   static_init();
37 
38   _window = 0;
39   _visible = false;
40   _gtk_builder = NULL;
41   _help_args = new CMD_Args();
42 }
43 
UI_Gtk_Window(const char * ui_xml_file)44 UI_Gtk_Window::UI_Gtk_Window(const char *ui_xml_file)
45 {
46   static_init();
47 
48   _window = 0;
49   _visible = false;
50   _help_args = new CMD_Args();
51 
52   string ui_xml_file_path = _image_path + ui_xml_file;
53   _gtk_builder = gtk_builder_new();
54   gtk_builder_set_translation_domain(_gtk_builder, PACKAGE);
55   gtk_builder_add_from_file(_gtk_builder, ui_xml_file_path.c_str(), NULL);
56 }
57 
~UI_Gtk_Window(void)58 UI_Gtk_Window::~UI_Gtk_Window(void)
59 {
60   delete _help_args;
61 }
62 
63 void
static_init(void)64 UI_Gtk_Window::static_init(void)
65 {
66   if (_static_init)
67     return;
68 
69   _static_init = true;
70 
71   string datadir(kcemu_datadir);
72   _icon_path = datadir + "/icons/";
73   _image_path = datadir + "/images/";
74 
75   GtkSettings *settings = gtk_settings_get_default();
76   gtk_settings_set_long_property(settings, "gtk-can-change-accels", 1, "UI_Gtk_Window::static_init");
77   gtk_settings_set_string_property(settings, "gtk-menu-bar-accel", "", "UI_Gtk_Window::static_init");
78 
79   GdkPixbuf *pixbuf16 = get_icon("kcemu-winicon_16x16.png");
80   GdkPixbuf *pixbuf32 = get_icon("kcemu-winicon_32x32.png");
81   GdkPixbuf *pixbuf48 = get_icon("kcemu-winicon_48x48.png");
82 
83   GList *icon_list = NULL;
84   if (pixbuf16 != NULL)
85     icon_list = g_list_append(icon_list, pixbuf16);
86   if (pixbuf32 != NULL)
87     icon_list = g_list_append(icon_list, pixbuf32);
88   if (pixbuf48 != NULL)
89     icon_list = g_list_append(icon_list, pixbuf48);
90 
91   if (icon_list != NULL)
92     gtk_window_set_default_icon_list(icon_list);
93 }
94 
95 void
show(void)96 UI_Gtk_Window::show(void)
97 {
98   if (_visible)
99     return;
100 
101   if (_window == NULL)
102     init();
103 
104   gtk_widget_show(_window);
105   _visible = true;
106 }
107 
108 void
hide(void)109 UI_Gtk_Window::hide(void)
110 {
111   if (!_visible)
112     return;
113 
114   gtk_widget_hide(_window);
115   _visible = false;
116 }
117 
118 void
toggle(void)119 UI_Gtk_Window::toggle(void)
120 {
121   if (_visible)
122     hide();
123   else
124     show();
125 }
126 
127 bool
is_visible(void)128 UI_Gtk_Window::is_visible(void)
129 {
130   return _visible;
131 }
132 
133 GtkWidget *
get_window(void)134 UI_Gtk_Window::get_window(void)
135 {
136   return _window;
137 }
138 
139 GdkPixbuf *
get_pixbuf(string path)140 UI_Gtk_Window::get_pixbuf(string path)
141 {
142     GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file(path.c_str(), NULL);
143     return pixbuf;
144 }
145 
146 GdkPixbuf *
get_icon(const char * name)147 UI_Gtk_Window::get_icon(const char *name)
148 {
149     return get_pixbuf(_icon_path + name);
150 }
151 
152 GdkPixbuf *
get_image(const char * name)153 UI_Gtk_Window::get_image(const char *name)
154 {
155     return get_pixbuf(_image_path + name);
156 }
157 
158 GtkWidget *
get_widget_or_null(const char * name)159 UI_Gtk_Window::get_widget_or_null(const char *name)
160 {
161   g_assert(_gtk_builder != NULL);
162 
163   GtkWidget *widget = GTK_WIDGET(gtk_builder_get_object(_gtk_builder, name));
164   return widget;
165 }
166 
167 GtkWidget *
get_widget(const char * name)168 UI_Gtk_Window::get_widget(const char *name)
169 {
170   GtkWidget *widget = get_widget_or_null(name);
171 
172   if (widget == NULL)
173       g_error("widget with name '%s' not found!", name);
174 
175   return widget;
176 }
177 
178 GtkWidget *
get_widget(const char * name,int nr)179 UI_Gtk_Window::get_widget(const char *name, int nr)
180 {
181   char widget_name[80];
182   snprintf(widget_name, sizeof(widget_name), "%s%d", name, nr);
183   return get_widget(widget_name);
184 }
185 
186 GtkCellRenderer *
bind_list_model_column(GtkComboBox * combobox,int column,...)187 UI_Gtk_Window::bind_list_model_column(GtkComboBox *combobox, int column, ...)
188 {
189     GtkCellRenderer *renderer = gtk_cell_renderer_text_new();
190     gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combobox), renderer, TRUE);
191     gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(combobox), renderer, "text", column, NULL);
192 
193     va_list ap;
194     va_start(ap, column);
195 
196     while (242) {
197         const char *attr = va_arg(ap, const char *);
198         if (attr == NULL)
199             break;
200 
201         int index = va_arg(ap, int);
202         gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(combobox), renderer, attr, index);
203     }
204 
205     va_end(ap);
206 
207     return renderer;
208 }
209 
210 GtkCellRenderer *
add_text_renderer(GtkTreeView * treeview,GtkTreeViewColumn * column,const char * title,...)211 UI_Gtk_Window::add_text_renderer(GtkTreeView *treeview, GtkTreeViewColumn *column, const char *title, ...) {
212     GtkCellRenderer *renderer = gtk_cell_renderer_text_new();
213 
214     gtk_tree_view_column_set_title(column, title);
215     gtk_tree_view_column_pack_end(column, renderer, TRUE);
216     gtk_tree_view_column_set_resizable(column, TRUE);
217     gtk_tree_view_column_set_expand(column, TRUE);
218 
219     va_list ap;
220     va_start(ap, title);
221 
222     while (242) {
223         const char *attr = va_arg(ap, const char *);
224         if (attr == NULL)
225             break;
226 
227         int index = va_arg(ap, int);
228         gtk_tree_view_column_add_attribute(column, renderer, attr, index);
229     }
230 
231     va_end(ap);
232 
233     return renderer;
234 }
235 
236 GtkCellRenderer *
add_icon_renderer(GtkTreeView * treeview,GtkTreeViewColumn * column,const char * title,...)237 UI_Gtk_Window::add_icon_renderer(GtkTreeView *treeview, GtkTreeViewColumn *column, const char *title, ...) {
238     GtkCellRenderer *renderer = gtk_cell_renderer_pixbuf_new();
239 
240     gtk_tree_view_column_set_title(column, title);
241     gtk_tree_view_column_pack_start(column, renderer, FALSE);
242     gtk_tree_view_column_set_resizable(column, FALSE);
243     gtk_tree_view_column_set_expand(column, FALSE);
244 
245     va_list ap;
246     va_start(ap, title);
247 
248     while (242) {
249         const char *attr = va_arg(ap, const char *);
250         if (attr == NULL)
251             break;
252 
253         int index = va_arg(ap, int);
254         gtk_tree_view_column_add_attribute(column, renderer, attr, index);
255     }
256 
257     va_end(ap);
258 
259     return renderer;
260 }
261 
262 void
sf_help(GtkWidget * widget,gpointer data)263 UI_Gtk_Window::sf_help(GtkWidget *widget, gpointer data)
264 {
265   UI_Gtk_Window *w = (UI_Gtk_Window *)data;
266 
267   char *help_topic = (char *)g_object_get_data(G_OBJECT(widget), "help-topic");
268   if (help_topic == NULL)
269     return;
270 
271   w->_help_args->set_string_arg("help-topic", help_topic);
272 
273   CMD_EXEC_ARGS("ui-help-window-show", w->_help_args);
274 }
275 
276 void
sf_help_recursive(GtkWidget * widget,gpointer data)277 UI_Gtk_Window::sf_help_recursive(GtkWidget *widget, gpointer data)
278 {
279   UI_Gtk_Window *w = (UI_Gtk_Window *)data;
280 
281   while (widget != NULL)
282     {
283       char *help_topic = (char *)g_object_get_data(G_OBJECT(widget), "help-topic");
284       if (help_topic != NULL)
285 	{
286 	  w->_help_args->set_string_arg("help-topic", help_topic);
287 	  CMD_EXEC_ARGS("ui-help-window-show", w->_help_args);
288 	  break;
289 	}
290 
291       widget = gtk_widget_get_parent(widget);
292     }
293 }
294 
295 void
init_dialog(const char * close_button_func,const char * help_topic)296 UI_Gtk_Window::init_dialog(const char *close_button_func, const char *help_topic)
297 {
298   g_object_set_data(G_OBJECT(_window), "help-topic", (gpointer)help_topic);
299 
300   if (close_button_func != NULL)
301     {
302       GtkWidget *button_close = get_widget("dialog_button_close");
303       g_assert(GTK_IS_BUTTON(button_close));
304 
305       g_signal_connect(G_OBJECT(button_close), "clicked",
306 		       G_CALLBACK(cmd_exec_sf),
307 		       (gpointer)close_button_func);
308 
309       GTK_WIDGET_SET_FLAGS(button_close, GTK_CAN_DEFAULT);
310       gtk_widget_grab_default(button_close);
311     }
312 
313   if (help_topic != NULL)
314     {
315       GtkWidget *button_help = get_widget("dialog_button_help");
316       g_assert(GTK_IS_BUTTON(button_help));
317 
318       g_object_set_data(G_OBJECT(button_help), "help-topic", (gpointer)help_topic);
319 
320       g_signal_connect(G_OBJECT(button_help), "clicked", G_CALLBACK(sf_help), (gpointer)this);
321     }
322 
323   GtkWidget *header_label = get_widget("header_label");
324   g_assert(GTK_IS_LABEL(header_label));
325 
326   PangoFontDescription *font_desc = pango_font_description_from_string("Sans 16");
327   gtk_widget_modify_font(header_label, font_desc);
328   pango_font_description_free(font_desc);
329 }
330