1 /* stock.c: 'standard' GTK widgets etc
2    Copyright (c) 2004 Darren Salt, Philip Kendall
3    Copyright (c) 2015 Stuart Brady
4    Copyright (c) 2015 Sergio Baldoví
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 2 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 along
17    with this program; if not, write to the Free Software Foundation, Inc.,
18    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 
20    Author contact information:
21 
22    Philip Kendall <philip-fuse@shadowmagic.org.uk>
23 
24 */
25 
26 #include <config.h>
27 
28 #include <string.h>
29 
30 #include <gdk/gdkkeysyms.h>
31 #include <gtk/gtk.h>
32 
33 #include "compat.h"
34 #include "gtkcompat.h"
35 #include "gtkinternals.h"
36 
37 GtkAccelGroup*
gtkstock_add_accel_group(GtkWidget * widget)38 gtkstock_add_accel_group( GtkWidget *widget )
39 {
40   GtkAccelGroup *accel = gtk_accel_group_new();
41   gtk_window_add_accel_group( GTK_WINDOW( widget ), accel );
42   return accel;
43 }
44 
45 static void
add_click(GtkWidget * btn,const gtkstock_button * button,GtkAccelGroup * accel,guint key1,GdkModifierType mod1,guint key2,GdkModifierType mod2)46 add_click( GtkWidget *btn, const gtkstock_button *button, GtkAccelGroup *accel,
47 	   guint key1, GdkModifierType mod1, guint key2, GdkModifierType mod2 )
48 {
49   if( button->shortcut ) {
50     if( button->shortcut != GDK_KEY_VoidSymbol )
51       gtk_widget_add_accelerator( btn, "clicked", accel, button->shortcut,
52 				  button->modifier, 0 );
53   } else if( key1 ) {
54     gtk_widget_add_accelerator( btn, "clicked", accel, key1, mod1, 0 );
55   }
56 
57   if( button->shortcut_alt ) {
58     if( button->shortcut_alt != GDK_KEY_VoidSymbol )
59       gtk_widget_add_accelerator( btn, "clicked", accel, button->shortcut_alt,
60 				  button->modifier_alt, 0 );
61   }
62   else if( key2 ) {
63     gtk_widget_add_accelerator( btn, "clicked", accel, key2, mod2, 0 );
64   }
65 
66 }
67 
68 GtkWidget*
gtkstock_create_button(GtkWidget * widget,GtkAccelGroup * accel,const gtkstock_button * button)69 gtkstock_create_button( GtkWidget *widget, GtkAccelGroup *accel,
70 			const gtkstock_button *button )
71 {
72   GtkWidget *btn;
73   gboolean link_object = ( button->label[0] == '!' );
74   const gchar *button_label = button->label + link_object;
75 
76   if( !accel ) accel = gtkstock_add_accel_group (widget);
77 
78   if( GTK_IS_DIALOG( widget ) ) {
79     btn = gtk_dialog_add_button( GTK_DIALOG( widget ), button_label,
80                                  button->response_id );
81   } else {
82     btn = gtk_button_new_with_mnemonic( button_label );
83     gtk_container_add( GTK_CONTAINER( widget ), btn );
84   }
85 
86   if( button->action ) {
87     if( link_object ) {
88       g_signal_connect_swapped( G_OBJECT( btn ), "clicked",
89 				button->action,
90 				G_OBJECT( button->actiondata ) );
91     } else {
92       g_signal_connect( G_OBJECT( btn ), "clicked", button->action,
93 			button->actiondata );
94     }
95   }
96 
97   if( button->destroy )
98     g_signal_connect_swapped( G_OBJECT( btn ), "clicked", button->destroy,
99 			      G_OBJECT( widget ) );
100 
101   GtkWidget *icon = NULL;
102   if( !strcmp( button->label, "_Close" ) )
103     icon = gtk_image_new_from_icon_name( "window-close", GTK_ICON_SIZE_BUTTON );
104   else if( !strcmp( button->label, "_Open" ) )
105     icon = gtk_image_new_from_icon_name( "document-open",GTK_ICON_SIZE_BUTTON );
106   else if( !strcmp( button->label, "_Save" ) )
107     icon = gtk_image_new_from_icon_name( "document-save",GTK_ICON_SIZE_BUTTON );
108   else if( !strcmp( button->label, "_Add" ) )
109     icon = gtk_image_new_from_icon_name( "list-add", GTK_ICON_SIZE_BUTTON );
110 
111 #if !GTK_CHECK_VERSION( 3, 0, 0 )
112   /* Note: ok/cancel/yes/no icons are not covered by freedesktop's Icon Naming
113      Specification 0.8.90 */
114   else if( !strcmp( button->label, "_OK" ) )
115     icon = gtk_image_new_from_icon_name( GTK_STOCK_OK, GTK_ICON_SIZE_BUTTON );
116   else if( !strcmp( button->label, "_Cancel" ) )
117     icon = gtk_image_new_from_icon_name( GTK_STOCK_CANCEL,
118                                          GTK_ICON_SIZE_BUTTON );
119   else if( !strcmp( button->label, "_Yes" ) )
120     icon = gtk_image_new_from_icon_name( GTK_STOCK_YES, GTK_ICON_SIZE_BUTTON );
121   else if( !strcmp( button->label, "_No" ) )
122     icon = gtk_image_new_from_icon_name( GTK_STOCK_NO, GTK_ICON_SIZE_BUTTON );
123 #endif
124 
125   if( icon ) gtk_button_set_image( GTK_BUTTON( btn ), icon );
126 
127   add_click( btn, button, accel, 0, 0, 0, 0 );
128 
129   return btn;
130 }
131 
132 GtkAccelGroup*
gtkstock_create_buttons(GtkWidget * widget,GtkAccelGroup * accel,const gtkstock_button * buttons,size_t count)133 gtkstock_create_buttons( GtkWidget *widget, GtkAccelGroup *accel,
134 			 const gtkstock_button *buttons, size_t count )
135 {
136   if( !accel ) accel = gtkstock_add_accel_group( widget );
137 
138   for( ; count; buttons++, count-- )
139     gtkstock_create_button( widget, accel, buttons );
140 
141   return accel;
142 }
143 
144 GtkAccelGroup*
gtkstock_create_ok_cancel(GtkWidget * widget,GtkAccelGroup * accel,GCallback action,gpointer actiondata,GCallback destroy_ok,GCallback destroy_cancel)145 gtkstock_create_ok_cancel( GtkWidget *widget, GtkAccelGroup *accel,
146                            GCallback action, gpointer actiondata,
147                            GCallback destroy_ok, GCallback destroy_cancel )
148 {
149   gtkstock_button btn[] = {
150     { "_Cancel", NULL, NULL, NULL, GDK_KEY_Escape, 0, 0, 0, GTK_RESPONSE_CANCEL},
151     { "_OK", NULL, NULL, NULL, 0, 0, 0, 0, GTK_RESPONSE_OK},
152   };
153   btn[0].destroy = destroy_cancel ? destroy_cancel : NULL;
154   btn[1].destroy = destroy_ok ? destroy_ok : NULL;
155   btn[1].action = action;
156   btn[1].actiondata = actiondata;
157 
158   return gtkstock_create_buttons( widget, accel, btn,
159 				  ARRAY_SIZE( btn ) );
160 }
161 
162 GtkAccelGroup*
gtkstock_create_close(GtkWidget * widget,GtkAccelGroup * accel,GCallback destroy,gboolean esconly)163 gtkstock_create_close( GtkWidget *widget, GtkAccelGroup *accel,
164 		       GCallback destroy, gboolean esconly )
165 {
166   gtkstock_button btn = {
167     "_Close", NULL, NULL, (destroy ? destroy : DEFAULT_DESTROY),
168     (esconly ? GDK_KEY_VoidSymbol : GDK_KEY_Return), 0, GDK_KEY_Escape, 0,
169     GTK_RESPONSE_CLOSE
170   };
171   return gtkstock_create_buttons( widget, accel, &btn, 1 );
172 }
173 
174 GtkWidget*
gtkstock_dialog_new(const gchar * title,GCallback destroy)175 gtkstock_dialog_new( const gchar *title, GCallback destroy )
176 {
177   GtkWidget *dialog = gtk_dialog_new();
178   if( title ) gtk_window_set_title( GTK_WINDOW( dialog ), title );
179   /* TODO: allow to keep the dialog after closing for gtk_dialog_run() */
180   g_signal_connect( G_OBJECT( dialog ), "delete-event",
181 		    destroy ? destroy : DEFAULT_DESTROY, NULL );
182   if( destroy == NULL ) gtk_window_set_modal( GTK_WINDOW( dialog ), TRUE );
183   gtk_window_set_transient_for( GTK_WINDOW( dialog ),
184                                 GTK_WINDOW( gtkui_window ) );
185 
186   return dialog;
187 }
188