1 /*****************************************************************
2  * gmerlin - a general purpose multimedia framework and applications
3  *
4  * Copyright (c) 2001 - 2011 Members of the Gmerlin project
5  * gmerlin-general@lists.sourceforge.net
6  * http://gmerlin.sourceforge.net
7  *
8  * This program is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
20  * *****************************************************************/
21 
22 #include <stdlib.h>
23 #include <string.h>
24 #include <gtk/gtk.h>
25 
26 #include <gmerlin/tree.h>
27 #include <gmerlin/utils.h>
28 
29 #include <gui_gtk/tree.h>
30 #include <gui_gtk/gtkutils.h>
31 
32 /* This is missing in the gtk headers */
33 
34 extern void
35 gtk_decorated_window_move_resize_window(GtkWindow*, int, int, int, int);
36 
37 struct bg_gtk_album_window_s
38   {
39   bg_gtk_album_widget_t * widget;
40   bg_gtk_tree_widget_t * tree_widget;
41   GtkWidget * window;
42 
43   int x, y, width, height;
44 
45   bg_cfg_section_t * cfg_section;
46 
47   /* Notebook stuff */
48 
49   GtkWidget * tab_close_button;
50   GtkWidget * tab_label;
51   GtkWidget * tab_widget;
52 
53   GtkWidget * notebook;
54   int name_len;
55   GtkAccelGroup * accel_group;
56   };
57 
58 /* Configuration stuff */
59 
60 static const bg_parameter_info_t parameters[] =
61   {
62     {
63       .name = "x",
64       .long_name = "X",
65       .type = BG_PARAMETER_INT,
66       .val_default = { .val_i = 100 }
67     },
68     {
69       .name = "y",
70       .long_name = "Y",
71       .type = BG_PARAMETER_INT,
72       .val_default = { .val_i = 100 }
73     },
74     {
75       .name = "width",
76       .long_name = "Width",
77       .type = BG_PARAMETER_INT,
78       .val_default = { .val_i = 200 }
79     },
80     {
81       .name = "height",
82       .long_name = "Height",
83       .type = BG_PARAMETER_INT,
84       .val_default = { .val_i = 300 }
85     },
86     { /* End of parameters */ }
87   };
88 
set_parameter(void * data,const char * name,const bg_parameter_value_t * val)89 static void set_parameter(void * data, const char * name,
90                           const bg_parameter_value_t * val)
91   {
92   bg_gtk_album_window_t * win;
93   win = (bg_gtk_album_window_t*)data;
94   if(!name)
95     return;
96   else if(!strcmp(name, "x"))
97     {
98     win->x = val->val_i;
99     }
100   else if(!strcmp(name, "y"))
101     {
102     win->y = val->val_i;
103     }
104   else if(!strcmp(name, "width"))
105     {
106     win->width = val->val_i;
107     }
108   else if(!strcmp(name, "height"))
109     {
110     win->height = val->val_i;
111     }
112   }
113 
get_parameter(void * data,const char * name,bg_parameter_value_t * val)114 static int get_parameter(void * data, const char * name,
115                          bg_parameter_value_t * val)
116   {
117   bg_gtk_album_window_t * win;
118   win = (bg_gtk_album_window_t*)data;
119   if(!name)
120     return 1;
121   else if(!strcmp(name, "x"))
122     {
123     val->val_i = win->x;
124     return 1;
125     }
126   else if(!strcmp(name, "y"))
127     {
128     val->val_i = win->y;
129     return 1;
130     }
131   else if(!strcmp(name, "width"))
132     {
133     val->val_i = win->width;
134     return 1;
135     }
136   else if(!strcmp(name, "height"))
137     {
138     val->val_i = win->height;
139     return 1;
140     }
141   return 0;
142   }
143 
delete_callback(GtkWidget * w,GdkEventAny * event,gpointer data)144 static gboolean delete_callback(GtkWidget * w, GdkEventAny * event,
145                                 gpointer data)
146   {
147   bg_gtk_album_window_t * win;
148   win = (bg_gtk_album_window_t*)data;
149   bg_gtk_album_window_destroy(win, 1);
150   return TRUE;
151   }
152 
close_callback(GtkWidget * w,gpointer data)153 static void close_callback(GtkWidget * w, gpointer data)
154   {
155   bg_gtk_album_window_t * win;
156   win = (bg_gtk_album_window_t*)data;
157   bg_gtk_album_window_destroy(win, 1);
158   }
159 
widget_close_callback(bg_gtk_album_widget_t * w,gpointer data)160 static void widget_close_callback(bg_gtk_album_widget_t * w, gpointer data)
161   {
162   bg_gtk_album_window_t * win;
163   win = (bg_gtk_album_window_t*)data;
164   bg_gtk_album_window_destroy(win, 1);
165   }
166 
167 
name_change_callback(bg_album_t * a,const char * name,void * data)168 static void name_change_callback(bg_album_t * a,
169                                  const char * name,
170                                  void * data)
171   {
172   bg_gtk_album_window_t * win = (bg_gtk_album_window_t *)data;
173   win->name_len = strlen(name);
174   if(win->notebook)
175     {
176     gtk_label_set_text(GTK_LABEL(win->tab_label), name);
177     }
178   else if(win->window)
179     {
180     gtk_window_set_title(GTK_WINDOW(win->window), name);
181     }
182   }
183 
184 bg_gtk_album_window_t *
bg_gtk_album_window_create(bg_album_t * album,bg_gtk_tree_widget_t * tree_widget,GtkAccelGroup * accel_group)185 bg_gtk_album_window_create(bg_album_t * album,
186                            bg_gtk_tree_widget_t * tree_widget, GtkAccelGroup * accel_group)
187   {
188 
189   bg_gtk_album_window_t * ret;
190   ret = calloc(1, sizeof(*ret));
191   ret->tree_widget = tree_widget;
192 
193   ret->accel_group = accel_group;
194 
195   bg_album_set_name_change_callback(album, name_change_callback, ret);
196 
197   ret->widget = bg_gtk_album_widget_create(album, ret->window);
198   bg_gtk_album_widget_set_close_callback(ret->widget,
199                                          widget_close_callback,
200                                          ret);
201 
202 
203   g_object_ref(G_OBJECT(bg_gtk_album_widget_get_widget(ret->widget)));
204 
205   /* Set config stuff */
206 
207   ret->cfg_section =
208     bg_cfg_section_find_subsection(bg_album_get_cfg_section(album), "gtk_albumwindow");
209 
210   bg_cfg_section_apply(ret->cfg_section, parameters, set_parameter, ret);
211 
212   return ret;
213   }
214 
bg_gtk_album_window_destroy(bg_gtk_album_window_t * w,int notify)215 void bg_gtk_album_window_destroy(bg_gtk_album_window_t * w, int notify)
216   {
217   int page_num;
218 
219   /* Get the window coordinates */
220 
221   if(w->window && w->window->window)
222     {
223     gdk_window_get_geometry(w->window->window,
224                             NULL, NULL, &w->width, &w->height,
225                             NULL);
226 
227     gdk_window_get_root_origin(w->window->window, &w->x, &w->y);
228 
229     bg_cfg_section_get(w->cfg_section, parameters, get_parameter, w);
230     }
231 
232   bg_gtk_album_widget_put_config(w->widget);
233 
234   if(w->tree_widget && notify)
235     {
236     bg_gtk_tree_widget_close_album(w->tree_widget, w);
237     }
238   if(w->window)
239     gtk_widget_destroy(w->window);
240 
241   if(w->notebook)
242     {
243     page_num = gtk_notebook_page_num(GTK_NOTEBOOK(w->notebook), bg_gtk_album_widget_get_widget(w->widget));
244     gtk_notebook_remove_page(GTK_NOTEBOOK(w->notebook), page_num);
245     }
246 
247   if(w->widget)
248     {
249     bg_album_set_name_change_callback(bg_gtk_album_widget_get_album(w->widget),
250                                                                 NULL, NULL);
251 
252     g_object_unref(G_OBJECT(bg_gtk_album_widget_get_widget(w->widget)));
253     bg_gtk_album_widget_destroy(w->widget);
254     }
255   free(w);
256   }
257 
bg_gtk_album_window_get_album(bg_gtk_album_window_t * w)258 bg_album_t * bg_gtk_album_window_get_album(bg_gtk_album_window_t*w)
259   {
260   return bg_gtk_album_widget_get_album(w->widget);
261   }
262 
bg_gtk_album_window_raise(bg_gtk_album_window_t * w)263 void bg_gtk_album_window_raise(bg_gtk_album_window_t* w)
264   {
265   int page_num;
266 
267   if(w->window && w->window->window)
268     gtk_window_present(GTK_WINDOW(w->window));
269 
270   else if(w->notebook)
271     {
272     page_num = gtk_notebook_page_num(GTK_NOTEBOOK(w->notebook), bg_gtk_album_widget_get_widget(w->widget));
273     gtk_notebook_set_current_page(GTK_NOTEBOOK(w->notebook), page_num);
274 
275     }
276   }
277 
278 
279 
create_close_button(bg_gtk_album_window_t * w)280 static GtkWidget * create_close_button(bg_gtk_album_window_t * w)
281   {
282   GtkWidget * button;
283   GtkWidget * image;
284   char * path;
285   path = bg_search_file_read("icons", "tab_close.png");
286   if(path)
287     {
288     image = gtk_image_new_from_file(path);
289     free(path);
290     }
291   else
292     image = gtk_image_new();
293 
294   gtk_widget_show(image);
295   button = gtk_button_new();
296   gtk_container_add(GTK_CONTAINER(button), image);
297 
298   g_signal_connect(G_OBJECT(button), "clicked",
299                    G_CALLBACK(close_callback), w);
300 
301   gtk_widget_show(button);
302   return button;
303   }
304 
305 
bg_gtk_album_window_attach(bg_gtk_album_window_t * w,GtkWidget * notebook)306 void bg_gtk_album_window_attach(bg_gtk_album_window_t * w, GtkWidget * notebook)
307   {
308   const char * name;
309   int page_num;
310 
311   bg_album_t * album;
312 
313   /* Remove widget from container and delete window */
314 
315   if(w->window)
316     {
317     gtk_container_remove(GTK_CONTAINER(w->window), bg_gtk_album_widget_get_widget(w->widget));
318     gtk_widget_destroy(w->window);
319     w->window = NULL;
320     }
321   /* Attach stuff to notebook */
322 
323   album = bg_gtk_album_widget_get_album(w->widget);
324 
325   name = bg_album_get_label(album);
326 
327   w->tab_label = gtk_label_new(name);
328   w->name_len = strlen(name);
329 
330   gtk_widget_show(w->tab_label);
331 
332   w->tab_close_button = create_close_button(w);
333   w->tab_widget = gtk_hbox_new(0, 2);
334   bg_gtk_box_pack_start_defaults(GTK_BOX(w->tab_widget), w->tab_label);
335   gtk_box_pack_start(GTK_BOX(w->tab_widget), w->tab_close_button, FALSE, FALSE, 0);
336   gtk_widget_show(w->tab_widget);
337 
338   page_num = gtk_notebook_get_n_pages(GTK_NOTEBOOK(notebook));
339   gtk_notebook_append_page(GTK_NOTEBOOK(notebook), bg_gtk_album_widget_get_widget(w->widget),
340                            w->tab_widget);
341   gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), page_num);
342 
343 #if 0
344 #if GTK_CHECK_VERSION(2,20,0)
345   g_object_set(notebook, "tab-fill", FALSE, NULL);
346 #else
347   gtk_notebook_set_tab_label_packing(GTK_NOTEBOOK(notebook),
348                                      bg_gtk_album_widget_get_widget(w->widget),
349                                      FALSE, FALSE, GTK_PACK_START);
350 #endif
351 #endif
352   gtk_notebook_set_menu_label_text(GTK_NOTEBOOK(notebook),
353                                    bg_gtk_album_widget_get_widget(w->widget),
354                                    bg_album_get_label(album));
355 
356 
357   w->notebook = notebook;
358   if(bg_album_is_current(album))
359     bg_gtk_album_window_set_current(w, 1);
360   }
361 
bg_gtk_album_window_detach(bg_gtk_album_window_t * w)362 void bg_gtk_album_window_detach(bg_gtk_album_window_t * w)
363   {
364   int page_num;
365   bg_album_t * album;
366 
367   album = bg_gtk_album_widget_get_album(w->widget);
368 
369   if(w->notebook)
370     {
371     page_num = gtk_notebook_page_num(GTK_NOTEBOOK(w->notebook), bg_gtk_album_widget_get_widget(w->widget));
372     gtk_notebook_remove_page(GTK_NOTEBOOK(w->notebook), page_num);
373     w->notebook = NULL;
374     }
375 
376   w->window = bg_gtk_window_new(GTK_WINDOW_TOPLEVEL);
377   gtk_window_add_accel_group(GTK_WINDOW (w->window), w->accel_group);
378   gtk_window_add_accel_group(GTK_WINDOW (w->window), bg_gtk_album_widget_get_accel_group(w->widget));
379 
380   g_signal_connect(G_OBJECT(w->window), "delete-event",
381                    G_CALLBACK(delete_callback),
382                    w);
383   gtk_window_set_title(GTK_WINDOW(w->window), bg_album_get_label(album));
384 
385   gtk_container_add(GTK_CONTAINER(w->window),
386                     bg_gtk_album_widget_get_widget(w->widget));
387 
388   gtk_widget_show(w->window);
389 
390   gtk_decorated_window_move_resize_window(GTK_WINDOW(w->window),
391                                           w->x, w->y, w->width, w->height);
392 
393   }
394 
bg_gtk_album_window_set_current(bg_gtk_album_window_t * w,int current)395 void bg_gtk_album_window_set_current(bg_gtk_album_window_t * w, int current)
396   {
397   PangoAttribute *attr;
398   PangoAttrList *attr_list;
399 
400 
401   if(!w->notebook)
402     return;
403   attr_list = pango_attr_list_new();
404   attr = pango_attr_weight_new(current ? PANGO_WEIGHT_BOLD: PANGO_WEIGHT_NORMAL);
405   attr->start_index = 0;
406   attr->end_index = w->name_len;
407 
408   pango_attr_list_insert(attr_list,attr);
409   gtk_label_set_attributes(GTK_LABEL(w->tab_label), attr_list);
410   pango_attr_list_unref(attr_list);
411   }
412 
bg_gtk_album_window_goto_current(bg_gtk_album_window_t * w)413 void bg_gtk_album_window_goto_current(bg_gtk_album_window_t * w)
414   {
415   bg_gtk_album_window_raise(w);
416   bg_gtk_album_widget_goto_current(w->widget);
417   }
418 
bg_gtk_album_window_get_accel_group(bg_gtk_album_window_t * w)419 GtkAccelGroup * bg_gtk_album_window_get_accel_group(bg_gtk_album_window_t * w)
420   {
421   return bg_gtk_album_widget_get_accel_group(w->widget);
422   }
423