1 /*
2  * palettes.c
3  *
4  * Copyright 2013 Richard Shann <rshann@virgin.net>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19  * MA 02110-1301, USA.
20  */
21 #include "ui/palettes.h"
22 #include "core/view.h"
23 #include "core/utils.h"
24 #include "ui/texteditors.h"
25 #include <librsvg/rsvg.h>
26 
27 
28 #if GTK_MAJOR_VERSION==2
29 #define gtk_grid_new() (pal->rows?gtk_hbox_new (FALSE, 1):gtk_vbox_new (FALSE, 1))
30 #define gtk_grid_attach(widget, obj, a,b,c,d) gtk_box_pack_start(widget, obj, FALSE, TRUE, 0)
31 #define GTK_GRID(a) a
32 #endif
hide_palette_widget(GtkWidget * w)33 static void hide_palette_widget (GtkWidget *w) {
34     GtkWidget *parent = gtk_widget_get_parent (w);
35     if(GTK_IS_WINDOW(parent))
36         gtk_widget_hide (parent);
37     else
38        gtk_widget_hide (w);
39 }
hide_docked_palettes(void)40 static void hide_docked_palettes (void) {
41     GList *g;
42     for (g=Denemo.palettes;g;g=g->next)
43     {
44             DenemoPalette *pal = g->data;
45             if(pal->docked)
46                 hide_palette_widget (pal->box);
47     }
48 }
49 
hide_all_palettes(void)50 static void hide_all_palettes (void) {
51     GList *g;
52     for (g=Denemo.palettes;g;g=g->next)
53     {
54             DenemoPalette *pal = g->data;
55             hide_palette_widget (pal->box);
56     }
57 }
58 
destroy_all_palettes(void)59 static void destroy_all_palettes (void) {
60     if(confirm(_("Destroy All Palettes"), _("Get rid of all palettes permanently?")))
61     {
62         hide_all_palettes();
63         Denemo.palettes = NULL;//on exit an empty palettes.xml will be written
64     }
65 }
66 
popupmenu(GtkWidget * menu)67 static void popupmenu (GtkWidget *menu) {
68       g_signal_connect (menu, "selection-done", gtk_main_quit, NULL);
69       gtk_widget_show_all (menu);
70       gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, 0, gtk_get_current_event_time ());
71       gtk_main ();
72 }
73 
repack_palette(DenemoPalette * pal)74 void repack_palette (DenemoPalette *pal)
75 {
76     gint i;
77     GList *g;
78     GtkWidget *parent = gtk_widget_get_parent(pal->box);
79     for(g=pal->buttons;g;g=g->next)
80     {
81         if(gtk_widget_get_parent(g->data))
82             gtk_container_remove(GTK_CONTAINER(pal->box), g->data);
83     }
84     gtk_widget_destroy (pal->box);
85     pal->box = gtk_grid_new();
86     gchar *tooltip = g_strdup_printf("The \"%s\" Palette:\n%s", pal->name, _("To edit this palette, dock/undock, hide etc, right click on a button and choose Edit Palette."));
87     gtk_widget_set_tooltip_text (pal->box, tooltip);
88     g_free(tooltip);
89     for (i=0, g=pal->buttons;g;i++, g=g->next)
90     {
91         if(pal->rows)
92             gtk_grid_attach (GTK_GRID(pal->box), g->data, i/pal->limit, i%pal->limit, 1, 1);
93         else
94             gtk_grid_attach (GTK_GRID(pal->box), g->data, i%pal->limit, i/pal->limit, 1, 1);
95         gtk_widget_show (GTK_WIDGET(g->data));
96     }
97     gtk_container_add (GTK_CONTAINER (parent), pal->box);
98     if(pal->docked)
99     {
100         gtk_widget_hide (pal->window);
101         pal->rows? gtk_widget_reparent (pal->box, Denemo.vpalettes):gtk_widget_reparent (pal->box, Denemo.hpalettes);
102     }
103     else
104     {
105         gtk_window_resize (GTK_WINDOW(pal->window), 1, 1);
106         gtk_widget_show (pal->window);
107         gtk_widget_set_can_focus (pal->window, FALSE);
108         switch_back_to_main_window ();
109     }
110     gtk_widget_show(pal->box);
111 
112 }
113 
114 
toggle_rows(DenemoPalette * pal)115 static void toggle_rows (DenemoPalette *pal) {
116     pal->rows = !pal->rows;
117     repack_palette (pal);
118 }
toggle_dock(DenemoPalette * pal)119 static void toggle_dock (DenemoPalette *pal) {
120     if(pal->docked)
121         gtk_widget_reparent (pal->box, pal->window), gtk_window_set_keep_above  (GTK_WINDOW (pal->window), TRUE);
122     else
123         pal->rows? gtk_widget_reparent (pal->box, Denemo.vpalettes):gtk_widget_reparent (pal->box, Denemo.hpalettes);
124     pal->docked = !pal->docked;
125     pal->docked?
126         gtk_widget_hide (pal->window):
127         gtk_widget_show (pal->window);
128 }
set_limit(DenemoPalette * pal)129 static void set_limit (DenemoPalette *pal) {
130     gchar *initial = g_strdup_printf("%d", pal->limit);
131     gchar *response = string_dialog_entry (Denemo.project, "Palette Layout", _("Give Limit"), initial);
132     g_free(initial);
133     if(response && atoi(response))
134     {
135         pal->limit = atoi(response);
136         repack_palette (pal);
137     } else g_warning("Cancelled %s", response);
138 }
139 
140 
get_palette_menu(DenemoPalette * pal)141 static GtkWidget *get_palette_menu(DenemoPalette *pal) {
142   GtkWidget *menu = gtk_menu_new ();
143   GtkWidget *item = gtk_menu_item_new_with_label (_("Hide"));
144   gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
145   g_signal_connect_swapped (G_OBJECT (item), "activate", G_CALLBACK (hide_palette_widget), (gpointer) pal->box);
146     if(!pal->rows)
147   {
148     item = gtk_menu_item_new_with_label (_("Make Horizontal"));
149     gtk_widget_set_tooltip_text (item, _("Arrange the buttons extending horizontally"));
150     //gtk_widget_add_events (item, GDK_ENTER_NOTIFY_MASK);
151     //g_signal_connect (item, "enter-notify-event", show_tooltip, _("Arrange the buttons extending horizontally"));
152 
153 
154 
155     gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
156     g_signal_connect_swapped (G_OBJECT (item), "activate", G_CALLBACK (toggle_rows), (gpointer) pal);
157   } else
158   {
159     item = gtk_menu_item_new_with_label (_("Make Vertical"));
160     gtk_widget_set_tooltip_text (item, _("Arrange the buttons extending vertically"));
161     gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
162     g_signal_connect_swapped (G_OBJECT (item), "activate", G_CALLBACK (toggle_rows), (gpointer) pal);
163   }
164 
165     {
166     item = gtk_menu_item_new_with_label (pal->rows?_("Vertical Limit"): _("Horizontal Limit"));
167     gtk_widget_set_tooltip_text (item, pal->rows? _("Set maximum extent vertically") : _("Set maximum extent horizontally") );
168     gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
169     g_signal_connect_swapped (G_OBJECT (item), "activate", G_CALLBACK (set_limit), (gpointer) pal);
170     }
171     {
172     item = gtk_menu_item_new_with_label ( pal->docked?_("Undock"):_("Dock"));
173     gtk_widget_set_tooltip_text (item,  pal->docked?_("Dock this palette in the main display"):_("Undock this palette from the main display") );
174     gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
175     g_signal_connect_swapped (G_OBJECT (item), "activate", G_CALLBACK (toggle_dock), (gpointer) pal);
176     }
177     if (pal->docked)    {
178     item = gtk_menu_item_new_with_label ( _("Hide All Docked"));
179     gtk_widget_set_tooltip_text (item, _("Hide all the docked palettes"));
180     gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
181     g_signal_connect_swapped (G_OBJECT (item), "activate", G_CALLBACK (hide_docked_palettes), (gpointer) pal);
182     }
183     {
184     item = gtk_menu_item_new_with_label ( _("Hide All Palettes"));
185     gtk_widget_set_tooltip_text (item, _("Hide all the palettes"));
186     gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
187     g_signal_connect_swapped (G_OBJECT (item), "activate", G_CALLBACK (hide_all_palettes), (gpointer) pal);
188     }
189         {
190     item = gtk_menu_item_new_with_label ( _("Destroy All Palettes"));
191     gtk_widget_set_tooltip_text (item, _("Destroy all the palettes - this will save time at startup, and shorten the palette menu."));
192     gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
193     g_signal_connect_swapped (G_OBJECT (item), "activate", G_CALLBACK (destroy_all_palettes), (gpointer) pal);
194     }
195   return menu;
196 }
197 
get_script_for_button(GtkWidget * button)198 static void get_script_for_button (GtkWidget *button) {
199     gchar *script = g_object_get_data (G_OBJECT(button), "script");
200     appendSchemeText (script);
201     gboolean sensitive = gtk_widget_get_visible (gtk_widget_get_toplevel (Denemo.script_view));
202     if(!sensitive) activate_action ("/MainMenu/ViewMenu/ToggleScript");
203 }
204 
put_script_for_button(GtkWidget * button)205 static void put_script_for_button (GtkWidget *button) {
206     gchar *text = g_strdup_printf(_("Overwrite script for button \"%s\"?"), gtk_button_get_label(GTK_BUTTON(button)));
207     if(confirm (_("Re-write Script"), text))
208     {
209     gchar *script = get_script_view_text ();
210     gchar *oldscript = (gchar*) g_object_get_data (G_OBJECT(button), "script");
211     g_object_set_data (G_OBJECT(button), "script", script);
212     g_signal_handlers_block_by_func(G_OBJECT(button), G_CALLBACK (call_out_to_guile), oldscript);
213     g_free(oldscript);
214     g_signal_connect_swapped ( G_OBJECT (button), "clicked", G_CALLBACK (call_out_to_guile), script);
215     }
216     else
217     infodialog (_("Cancelled"));
218     g_free(text);
219 }
220 
set_image_for_button(GtkWidget * button,gchar * name)221 static void set_image_for_button (GtkWidget *button, gchar *name)
222 {
223     gchar *icon = find_denemo_file (DENEMO_DIR_PIXMAPS, name);
224     GtkWidget *child_widget = gtk_bin_get_child(GTK_BIN(button));
225     if(GTK_IS_LABEL(child_widget)) {
226         gtk_button_set_label (GTK_BUTTON(button), "");
227         //g_debug("destroy %p, \n", child_widget);
228         child_widget = gtk_bin_get_child(GTK_BIN(button));
229         //g_debug("or rather destroy %p, is %d \n", child_widget, GTK_IS_WIDGET(child_widget));
230         gtk_widget_destroy (child_widget);
231     }
232     GdkPixbuf *pb = //gdk_pixbuf_new_from_file(icon, NULL); Works on GNU/Linux but not windows - pixbuf loader not working...
233                     rsvg_pixbuf_from_file (icon, NULL);
234     if(pb)
235         gtk_button_set_image(GTK_BUTTON(button),gtk_image_new_from_pixbuf(pb));
236     else
237         gtk_button_set_label (GTK_BUTTON(button), name);
238             //gtk_button_set_always_show_image (button, TRUE);
239     g_object_set_data (G_OBJECT(button), "icon", (gpointer)g_strdup(name));
240     g_type_class_unref (g_type_class_ref (GTK_TYPE_BUTTON));
241     g_object_set (gtk_settings_get_default (), "gtk-button-images", TRUE, NULL);
242     gtk_widget_show_all(button);
243     g_free (icon);
244 }
245 
edit_label_for_button(GtkWidget * button)246 static void edit_label_for_button (GtkWidget *button) {
247     const gchar *label;
248     label = g_object_get_data (G_OBJECT(button), "icon");
249     if(label==NULL)
250         label = gtk_button_get_label (GTK_BUTTON(button));
251     gchar *newlabel = string_dialog_entry (Denemo.project, _("Write Label"), _("Write a label for this button"), (gchar*)label);
252 
253     if(newlabel && *newlabel) {
254         gchar *icon = find_denemo_file (DENEMO_DIR_PIXMAPS, newlabel);
255         if(icon) {
256             set_image_for_button (button, newlabel);
257             g_free (icon);
258         }
259         else
260         {
261         gtk_button_set_label (GTK_BUTTON(button), newlabel); //setting the label changes the widget: this works around a bizarre bug, if you just set the markup on the label the button has two labels
262         GtkWidget *label_widget = gtk_bin_get_child(GTK_BIN(button));
263         gtk_label_set_use_markup (GTK_LABEL(label_widget), TRUE);
264         gtk_label_set_markup (GTK_LABEL (label_widget), newlabel);
265         }
266     }
267     g_free(newlabel);
268 
269 }
edit_tooltip_for_button(GtkWidget * button)270 static void edit_tooltip_for_button (GtkWidget *button) {
271     const gchar *tooltip = gtk_widget_get_tooltip_text (button);
272     gchar *newtooltip = string_dialog_entry (Denemo.project, _("Write Tooltip"), _("Write a tooltip for this button"), (gchar*)tooltip);
273     if(newtooltip) {
274         gtk_widget_set_tooltip_text (button, newtooltip);
275     }
276     g_free(newtooltip);
277 }
help_for_button(GtkWidget * button)278 static void help_for_button (GtkWidget *button) {
279     gchar *tooltip = gtk_widget_get_tooltip_text (button);
280     if (tooltip)
281         infodialog (tooltip);
282 }
remove_button(GtkWidget * button)283 static void remove_button (GtkWidget *button) {
284     DenemoPalette *pal = g_object_get_data (G_OBJECT(button), "palette");
285     palette_delete_button (pal, button);
286 
287 }
288 
move_button_to_start(GtkWidget * button)289 static void move_button_to_start (GtkWidget *button) {
290     DenemoPalette *pal = g_object_get_data (G_OBJECT(button), "palette");
291     pal->buttons = g_list_remove (pal->buttons, button);
292     pal->buttons = g_list_prepend (pal->buttons, button);
293     repack_palette (pal);
294 }
move_button_to_end(GtkWidget * button)295 static void move_button_to_end (GtkWidget *button) {
296     DenemoPalette *pal = g_object_get_data (G_OBJECT(button), "palette");
297     pal->buttons = g_list_remove (pal->buttons, button);
298     pal->buttons = g_list_append (pal->buttons, button);
299     repack_palette (pal);
300 }
copy_button(GtkWidget * button)301 static void copy_button (GtkWidget *button) {
302     gchar *tooltip =  gtk_widget_get_tooltip_text (button);
303     gchar *label = (gchar*)gtk_button_get_label (GTK_BUTTON(button));
304     gchar *script = g_object_get_data (G_OBJECT(button), "script");
305     gchar *name = get_palette_name (TRUE);
306     if(name)
307     {
308         DenemoPalette *pal = get_palette (name);
309         if(pal==NULL)
310             pal = create_palette (name, FALSE, TRUE);
311         palette_add_button (pal, label, tooltip, script);
312     }
313 }
duplicate_button(GtkWidget * button)314 static void duplicate_button (GtkWidget *button) {
315     DenemoPalette *pal = g_object_get_data (G_OBJECT(button), "palette");
316     gchar *tooltip =  gtk_widget_get_tooltip_text (button);
317     gchar *label = _("Duplicate Button");
318     gchar *script = g_object_get_data (G_OBJECT(button), "script");
319     palette_add_button (pal, label, tooltip, script);
320 }
popup_button_menu(DenemoPalette * pal,GtkWidget * button)321 static void popup_button_menu(DenemoPalette *pal, GtkWidget *button) {
322   GtkWidget *menu = gtk_menu_new ();
323   GtkWidget *item;
324   gboolean sensitive = gtk_widget_get_visible (gtk_widget_get_toplevel (Denemo.script_view));//some menu items should be insensitive if the Scheme window is not visible
325   item = gtk_menu_item_new_with_label (_("Help"));
326   gtk_widget_set_tooltip_text (item, _("Show the help for this button"));
327   gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
328   g_signal_connect_swapped (G_OBJECT (item), "activate", G_CALLBACK (help_for_button), (gpointer) button);
329 
330   item = gtk_menu_item_new_with_label (_("Edit Label"));
331   gtk_widget_set_tooltip_text (item, _("Edit the label of this button"));
332   gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
333   g_signal_connect_swapped (G_OBJECT (item), "activate", G_CALLBACK (edit_label_for_button), (gpointer) button);
334 
335     item = gtk_menu_item_new_with_label (_("Edit Tooltip"));
336   gtk_widget_set_tooltip_text (item, _("Edit the tooltip of this button"));
337   gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
338   g_signal_connect_swapped (G_OBJECT (item), "activate", G_CALLBACK (edit_tooltip_for_button), (gpointer) button);
339 
340 
341 
342   item = gtk_menu_item_new_with_label (_("Copy to another Palette"));
343   gtk_widget_set_tooltip_text (item, _("Copy this button to another palette"));
344   gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
345   g_signal_connect_swapped (G_OBJECT (item), "activate", G_CALLBACK (copy_button), (gpointer) button);
346 
347   item = gtk_menu_item_new_with_label (_("Duplicate this button"));
348   gtk_widget_set_tooltip_text (item, _("Create a new button with the same effect"));
349   gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
350   g_signal_connect_swapped (G_OBJECT (item), "activate", G_CALLBACK (duplicate_button), (gpointer) button);
351 
352   item = gtk_menu_item_new_with_label (_("Remove from Palette"));
353   gtk_widget_set_tooltip_text (item, _("Remove this button from this palette"));
354   gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
355   g_signal_connect_swapped (G_OBJECT (item), "activate", G_CALLBACK (remove_button), (gpointer) button);
356 
357   item = gtk_menu_item_new_with_label (_("Get Script into Scheme Window"));
358   gtk_widget_set_tooltip_text (item, _("Places the script that this button executes into the Scheme window"));
359   gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
360   g_signal_connect_swapped (G_OBJECT (item), "activate", G_CALLBACK (get_script_for_button), (gpointer) button);
361 
362   item = gtk_menu_item_new_with_label (_("Save Script from Scheme Window"));
363   gtk_widget_set_tooltip_text (item, _("Uses the script in the Scheme Window as the one that this button executes when clicked"));
364   gtk_widget_set_sensitive (item, sensitive);
365   gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
366   g_signal_connect_swapped (G_OBJECT (item), "activate", G_CALLBACK (put_script_for_button), (gpointer) button);
367 
368   item = gtk_menu_item_new_with_label (_("Move to Start"));
369   gtk_widget_set_tooltip_text (item, _("Moves this button to the start of the palette"));
370   gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
371   g_signal_connect_swapped (G_OBJECT (item), "activate", G_CALLBACK (move_button_to_start), (gpointer) button);
372 
373   item = gtk_menu_item_new_with_label (_("Move to End"));
374   gtk_widget_set_tooltip_text (item, _("Moves this button to the end of the palette"));
375   gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
376   g_signal_connect_swapped (G_OBJECT (item), "activate", G_CALLBACK (move_button_to_end), (gpointer) button);
377 
378   item = gtk_menu_item_new_with_label (_("Edit this Palette"));
379   gtk_widget_set_tooltip_text (item, _("Edits the palette containing this button"));
380   gtk_menu_item_set_submenu (GTK_MENU_ITEM(item), (gpointer)get_palette_menu(pal));
381   gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
382 
383 
384 
385   g_signal_connect (menu, "selection-done", gtk_main_quit, NULL);
386   gtk_widget_show_all (menu);
387   gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, 0, gtk_get_current_event_time ());
388   gtk_main ();
389 }
new_palette(gchar * name,gboolean by_row)390 static DenemoPalette *new_palette (gchar *name, gboolean by_row)
391 {
392     DenemoPalette *pal = g_malloc0(sizeof (DenemoPalette));
393     pal->name = g_strdup(_(name));
394     pal->limit = 1;
395     pal->rows = by_row;
396     pal->box =  gtk_grid_new();
397     Denemo.palettes = g_list_append(Denemo.palettes, (gpointer)pal);
398     return pal;
399 }
400 
get_palette(gchar * name)401 DenemoPalette *get_palette (gchar *name)
402 {
403     GList *g;
404     for( g = Denemo.palettes; g; g = g->next)
405     {
406         DenemoPalette *pal = (DenemoPalette*)g->data;
407         if (!strcmp(name, pal->name))
408             return pal;
409     }
410     return NULL;
411 }
412 
button_pressed(GtkWidget * button,GdkEventButton * event,DenemoPalette * pal)413 static gboolean button_pressed (GtkWidget *button, GdkEventButton  *event, DenemoPalette *pal)
414 {
415     Denemo.currentpalette = pal;
416     if (event->button == 1)
417         return FALSE;
418     popup_button_menu(pal, button);
419     return TRUE;
420 }
already_present(DenemoPalette * pal,gchar * label)421 static gboolean already_present (DenemoPalette *pal, gchar *label) {
422     GList *g;
423     for(g=pal->buttons;g;g=g->next) {
424         gchar *icon = g_object_get_data (G_OBJECT(g->data), "icon");
425         if (!strcmp(label, gtk_button_get_label (GTK_BUTTON(g->data))) || (icon && !strcmp(icon, label)))
426             return TRUE;
427     }
428     return FALSE;
429 }
430 
fixup_image(GtkWidget * button,gchar * label)431 static void fixup_image (GtkWidget *button, gchar *label) {
432     //g_debug("Fixing up image");
433     set_image_for_button (button, label);
434 }
palette_add_button(DenemoPalette * pal,gchar * label,const gchar * tooltip,gchar * script)435 gboolean palette_add_button (DenemoPalette *pal, gchar *label, const gchar *tooltip, gchar *script)
436 {
437     if (already_present(pal, label))
438         return FALSE;
439     gchar *thescript = g_strdup(script);
440     GtkWidget *button = gtk_button_new_with_label (label);
441     gchar *icon = find_denemo_file (DENEMO_DIR_PIXMAPS, label);
442     if(icon)
443     {
444         g_signal_connect (button, "realize", G_CALLBACK (fixup_image), label);
445     } else
446     {
447         GtkWidget *label_widget = gtk_bin_get_child(GTK_BIN(button));//g_debug("is %s\n", g_type_name(G_TYPE_FROM_INSTANCE(label_widget)));
448         gtk_label_set_use_markup (GTK_LABEL(label_widget), TRUE);
449     }
450     //put button in a list pal->buttons and then call repack_palette.
451     //REF it for repacking
452     g_object_ref (button);
453     pal->buttons = g_list_append(pal->buttons, (gpointer)button);
454     repack_palette (pal);
455 
456     gtk_widget_set_tooltip_text (button, _(tooltip));
457     g_object_set_data (G_OBJECT(button), "script", thescript);
458     g_object_set_data (G_OBJECT(button), "palette", pal);
459     g_signal_connect_swapped ( G_OBJECT (button), "clicked", G_CALLBACK (call_out_to_guile), thescript);
460     g_signal_connect_after ( G_OBJECT (button), "clicked", G_CALLBACK (switch_back_to_main_window), NULL);
461     g_signal_connect (G_OBJECT (button), "button-press-event", G_CALLBACK (button_pressed), (gpointer)pal);
462     Denemo.currentpalette = pal;
463 
464     return TRUE;
465 }
466 
palette_delete_button(DenemoPalette * pal,GtkWidget * button)467 void palette_delete_button (DenemoPalette *pal, GtkWidget *button)
468 {
469     g_free( g_object_get_data (G_OBJECT(button), "script"));
470     pal->buttons = g_list_remove (pal->buttons, button);
471     gtk_widget_destroy(button);
472 }
473 
palette_action_button(DenemoPalette * pal,gchar * label)474 gboolean palette_action_button (DenemoPalette *pal, gchar *label)
475 {
476     gboolean ret = FALSE;
477     GList *g;
478     for (g=pal->buttons;g;g=g->next)
479     {
480         GtkWidget *button = g->data;
481         const gchar *this = gtk_button_get_label (GTK_BUTTON(button));
482         if (*this=='<')
483            {
484             while (*this && *this != '>')
485                 this++;
486             if(*this) this++;
487             }
488            // g_print ("this %s and %s %d\n", this, label,  g_str_has_prefix (this, label));
489         if(*this && g_str_has_prefix (this, label))
490             {
491             ret = gtk_widget_activate (button);
492             break;
493             }
494     }
495     Denemo.currentpalette = pal;
496     return ret;
497 }
create_palette(gchar * name,gboolean docked,gboolean rows)498 DenemoPalette *create_palette (gchar *name, gboolean docked, gboolean rows) {
499     DenemoPalette *pal = get_palette (name);
500 
501     if(pal==NULL)
502     {
503         pal = new_palette (name, TRUE);
504         pal->window =  gtk_window_new (GTK_WINDOW_TOPLEVEL);
505         gtk_window_set_title (GTK_WINDOW (pal->window), pal->name);
506         if(!docked)
507             {
508              gtk_window_set_default_size (GTK_WINDOW (pal->window), 200, 100);//try and get folk to notice it!
509              gtk_window_present (GTK_WINDOW (pal->window));
510          gtk_window_set_transient_for (GTK_WINDOW(pal->window), GTK_WINDOW(Denemo.window));
511              gtk_window_set_keep_above  (GTK_WINDOW (pal->window), TRUE);
512          }
513 
514         g_signal_connect (G_OBJECT (pal->window), "delete-event", G_CALLBACK (gtk_widget_hide_on_delete), NULL);
515         pal->rows = rows;
516         if(docked)
517             {
518              pal->docked = TRUE;
519              pal->rows?
520              gtk_box_pack_start (GTK_BOX(Denemo.vpalettes), pal->box, FALSE, TRUE, 0):
521              gtk_box_pack_start (GTK_BOX(Denemo.hpalettes), pal->box, FALSE, TRUE, 0);
522             }
523         else
524             {
525             gtk_widget_show (pal->window);
526             gtk_container_add (GTK_CONTAINER (pal->window), pal->box);
527         }
528     }
529     Denemo.currentpalette = pal;
530     return pal;
531 }
532 
set_palate_shape(gchar * name,gboolean row_wise,gint limit)533 DenemoPalette *set_palate_shape (gchar *name, gboolean row_wise, gint limit)
534 {
535  DenemoPalette *pal = create_palette (name, FALSE, row_wise);
536     if (limit>0) {
537         pal->limit = limit;
538         pal->rows = row_wise;
539         repack_palette (pal);
540         //gtk_window_resize (GTK_WINDOW (window), 1, 1);
541         Denemo.currentpalette = pal;
542         return pal;
543     }
544   return NULL;
545 }
546 
delete_palette(DenemoPalette * pal)547 void delete_palette (DenemoPalette *pal) {
548     GList *g;
549     for(g=pal->buttons;g;g=g->next)
550         palette_delete_button (pal, GTK_WIDGET(g->data));
551     gtk_widget_destroy (gtk_widget_get_parent (pal->box));//FIXME if docked this will not be a toplevel
552     Denemo.palettes = g_list_remove (Denemo.palettes, pal);
553     Denemo.currentpalette = NULL;
554 }
555 
556 static gchar *selected_palette_name = NULL;
palette_selected(gchar * name)557 static void palette_selected (gchar *name)
558 {
559     selected_palette_name = name;
560 }
user_palette_name(void)561 static void user_palette_name (void)
562 {
563     gchar *name;
564     name = string_dialog_entry (Denemo.project, _("Palette Name"), _("Give name for Palette: "), _("MyPalette"));
565     selected_palette_name = name;
566 }
567 
568 
choose_palette_by_name(gboolean allow_custom,gboolean non_showing)569 gchar *choose_palette_by_name (gboolean allow_custom, gboolean non_showing)
570 {
571 
572   GtkWidget *menu = gtk_menu_new ();
573   GtkWidget *item;
574   GList *g;
575   selected_palette_name = NULL;
576   if(Denemo.palettes) {
577   if(allow_custom) {
578     item = gtk_menu_item_new_with_label (_("Create Custom Palette"));
579     gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
580     }
581     //g_signal_connect_swapped (G_OBJECT (item), "activate", G_CALLBACK (user_palette_name), NULL);
582   for (g=Denemo.palettes;g;g=g->next)
583     {
584     DenemoPalette *pal = (DenemoPalette *)g->data;
585     if(non_showing && pal->docked && gtk_widget_get_visible (pal->box))
586         continue;//g_debug("palette %s is %d\n", pal->name,  gtk_widget_get_visible (pal->box));//continue;
587     if(non_showing && (!pal->docked) && gtk_widget_get_visible (gtk_widget_get_parent(pal->box)))
588         continue;
589     item = gtk_menu_item_new_with_label (pal->name);
590     gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
591     g_signal_connect_swapped (G_OBJECT (item), "activate", G_CALLBACK (palette_selected), (gpointer) pal->name);
592     }
593 
594     popupmenu (menu);
595 }
596     if(allow_custom && (selected_palette_name==NULL))
597         {
598             user_palette_name ();
599         }
600     return selected_palette_name;
601 }
602 
get_palette_name(gboolean allow_custom)603 gchar *get_palette_name (gboolean allow_custom)
604 {
605     return choose_palette_by_name (allow_custom, FALSE);
606 }
607 
place_action_in_palette(gint idx,const gchar * name)608 void place_action_in_palette (gint idx, const gchar *name)
609 {
610      gchar *label = (gchar *) lookup_label_from_idx (Denemo.map, idx);
611      if(name==NULL)
612         name = lookup_name_from_idx (Denemo.map, idx);
613       gchar *script = g_strdup_printf ("(d-%s)", name);
614       const gchar *tooltip = lookup_tooltip_from_idx (Denemo.map, idx);
615       gchar *palette_name = get_palette_name (TRUE);g_print("palette name %s\n", palette_name);
616       if(palette_name) {
617         DenemoPalette *pal = get_palette (palette_name);
618         if(pal==NULL)
619             {
620             pal = set_palate_shape (palette_name, TRUE, 1);
621         }
622         if(pal)
623             palette_add_button (pal, label, tooltip, script);
624         }
625       g_free (script);
626 
627 }
628 
629 
630 
631