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