GTK eradication -- the build chain.
[sxemacs] / src / ui / Gtk / native-gtk-toolbar.c
1 /* toolbar implementation -- GTK interface.
2    Copyright (C) 2000 Aaron Lehmann
3
4 This file is part of SXEmacs
5
6 SXEmacs 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 SXEmacs 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, see <http://www.gnu.org/licenses/>. */
18
19
20 /* Synched up with: Not in FSF. */
21
22 #include <config.h>
23 #include "lisp.h"
24
25 #include "console-gtk.h"
26 #include "glyphs-gtk.h"
27 #include "objects-gtk.h"
28
29 #include "ui/faces.h"
30 #include "ui/frame.h"
31 #include "ui/toolbar.h"
32 #include "ui/window.h"
33
34 #define SET_TOOLBAR_WAS_VISIBLE_FLAG(frame, pos, flag)                  \
35   do {                                                                  \
36     switch (pos)                                                        \
37       {                                                                 \
38       case TOP_TOOLBAR:                                                 \
39         (frame)->top_toolbar_was_visible = flag;                        \
40         break;                                                          \
41       case BOTTOM_TOOLBAR:                                              \
42         (frame)->bottom_toolbar_was_visible = flag;                     \
43         break;                                                          \
44       case LEFT_TOOLBAR:                                                \
45         (frame)->left_toolbar_was_visible = flag;                       \
46         break;                                                          \
47       case RIGHT_TOOLBAR:                                               \
48         (frame)->right_toolbar_was_visible = flag;                      \
49         break;                                                          \
50       default:                                                          \
51         abort ();                                                       \
52       }                                                                 \
53   } while (0)
54
55 static void gtk_clear_toolbar(struct frame *f, enum toolbar_pos pos);
56
57 static void gtk_toolbar_callback(GtkWidget * w, gpointer user_data)
58 {
59         struct toolbar_button *tb = (struct toolbar_button *)user_data;
60
61         call0(tb->callback);
62 }
63
64 static void gtk_output_toolbar(struct frame *f, enum toolbar_pos pos)
65 {
66         GtkWidget *toolbar;
67         Lisp_Object button, window, glyph, instance;
68         unsigned int checksum = 0;
69         struct window *w;
70         int x, y, bar_width, bar_height, vert;
71         int cur_x, cur_y;
72
73         window = FRAME_LAST_NONMINIBUF_WINDOW(f);
74         w = XWINDOW(window);
75
76         get_toolbar_coords(f, pos, &x, &y, &bar_width, &bar_height, &vert, 0);
77
78         /* Get the toolbar and delete the old widgets in it */
79         button = FRAME_TOOLBAR_BUTTONS(f, pos);
80
81         /* First loop over all of the buttons to determine how many there
82            are. This loop will also make sure that all instances are
83            instantiated so when we actually output them they will come up
84            immediately. */
85         while (!NILP(button)) {
86                 struct toolbar_button *tb = XTOOLBAR_BUTTON(button);
87                 checksum = HASH4(checksum,
88                                  internal_hash(get_toolbar_button_glyph(w, tb),
89                                                0), internal_hash(tb->callback,
90                                                                  0),
91                                  0 /* width */ );
92                 button = tb->next;
93         }
94
95         /* Only do updates if the toolbar has changed, or this is the first
96            time we have drawn it in this position
97          */
98         if (FRAME_GTK_TOOLBAR_WIDGET(f)[pos] &&
99             FRAME_GTK_TOOLBAR_CHECKSUM(f, pos) == checksum) {
100                 return;
101         }
102
103         /* Loop through buttons and add them to our toolbar.
104            This code ignores the button dimensions as we let GTK handle that :)
105            Attach the toolbar_button struct to the toolbar button so we know what
106            function to use as a callback. */
107
108         {
109                 gtk_clear_toolbar(f, pos);
110                 FRAME_GTK_TOOLBAR_WIDGET(f)[pos] = toolbar =
111                     gtk_toolbar_new(((pos == TOP_TOOLBAR)
112                                      || (pos ==
113                                          BOTTOM_TOOLBAR)) ?
114                                     GTK_ORIENTATION_HORIZONTAL :
115                                     GTK_ORIENTATION_VERTICAL, GTK_TOOLBAR_BOTH);
116         }
117
118         if (NILP(w->toolbar_buttons_captioned_p))
119                 gtk_toolbar_set_style(toolbar, GTK_TOOLBAR_ICONS);
120         else
121                 gtk_toolbar_set_style(toolbar, GTK_TOOLBAR_BOTH);
122
123         FRAME_GTK_TOOLBAR_CHECKSUM(f, pos) = checksum;
124         button = FRAME_TOOLBAR_BUTTONS(f, pos);
125
126         cur_x = 0;
127         cur_y = 0;
128
129         while (!NILP(button)) {
130                 struct toolbar_button *tb = XTOOLBAR_BUTTON(button);
131
132                 if (tb->blank) {
133                         /* It is a blank space... we do not pay attention to the
134                            size, because the GTK toolbar does not allow us to
135                            specify different spacings.  *sigh*
136                          */
137                         gtk_toolbar_append_space(GTK_TOOLBAR(toolbar));
138                 } else {
139                         /* It actually has a glyph associated with it!  What WILL
140                            they think of next?
141                          */
142                         glyph = tb->up_glyph;
143
144                         /* #### It is currently possible for users to trash us by directly
145                            changing the toolbar glyphs.  Avoid crashing in that case. */
146                         if (GLYPHP(glyph))
147                                 instance =
148                                     glyph_image_instance(glyph, window,
149                                                          ERROR_ME_NOT, 1);
150                         else
151                                 instance = Qnil;
152
153                         if (IMAGE_INSTANCEP(instance)) {
154                                 GtkWidget *pixmapwid;
155                                 GdkPixmap *pixmap;
156                                 GdkBitmap *mask;
157                                 char *tooltip = NULL;
158
159                                 if (STRINGP(tb->help_string))
160                                         tooltip = XSTRING_DATA(tb->help_string);
161
162                                 pixmap = XIMAGE_INSTANCE_GTK_PIXMAP(instance);
163                                 mask = XIMAGE_INSTANCE_GTK_MASK(instance);
164                                 pixmapwid = gtk_pixmap_new(pixmap, mask);
165
166                                 gtk_widget_set_usize(pixmapwid, tb->width,
167                                                      tb->height);
168
169                                 gtk_toolbar_append_item(GTK_TOOLBAR(toolbar),
170                                                         NULL, tooltip, NULL,
171                                                         pixmapwid,
172                                                         gtk_toolbar_callback,
173                                                         (gpointer) tb);
174                         }
175                 }
176                 cur_x += vert ? 0 : tb->width;
177                 cur_y += vert ? tb->height : 0;
178                 /* Who's idea was it to use a linked list for toolbar buttons? */
179                 button = tb->next;
180         }
181
182         SET_TOOLBAR_WAS_VISIBLE_FLAG(f, pos, 1);
183
184         x -= vert ? 3 : 2;
185         y -= vert ? 2 : 3;
186
187         gtk_fixed_put(GTK_FIXED(FRAME_GTK_TEXT_WIDGET(f)),
188                       FRAME_GTK_TOOLBAR_WIDGET(f)[pos], x, y);
189         gtk_widget_show_all(FRAME_GTK_TOOLBAR_WIDGET(f)[pos]);
190 }
191
192 static void gtk_clear_toolbar(struct frame *f, enum toolbar_pos pos)
193 {
194         FRAME_GTK_TOOLBAR_CHECKSUM(f, pos) = 0;
195         SET_TOOLBAR_WAS_VISIBLE_FLAG(f, pos, 0);
196         if (FRAME_GTK_TOOLBAR_WIDGET(f)[pos])
197                 gtk_widget_destroy(FRAME_GTK_TOOLBAR_WIDGET(f)[pos]);
198 }
199
200 static void gtk_output_frame_toolbars(struct frame *f)
201 {
202         if (FRAME_REAL_TOP_TOOLBAR_VISIBLE(f))
203                 gtk_output_toolbar(f, TOP_TOOLBAR);
204         else if (f->top_toolbar_was_visible)
205                 gtk_clear_toolbar(f, TOP_TOOLBAR);
206
207         if (FRAME_REAL_BOTTOM_TOOLBAR_VISIBLE(f))
208                 gtk_output_toolbar(f, BOTTOM_TOOLBAR);
209         else if (f->bottom_toolbar_was_visible)
210                 gtk_clear_toolbar(f, LEFT_TOOLBAR);
211
212         if (FRAME_REAL_LEFT_TOOLBAR_VISIBLE(f))
213                 gtk_output_toolbar(f, LEFT_TOOLBAR);
214         else if (f->left_toolbar_was_visible)
215                 gtk_clear_toolbar(f, LEFT_TOOLBAR);
216
217         if (FRAME_REAL_RIGHT_TOOLBAR_VISIBLE(f))
218                 gtk_output_toolbar(f, RIGHT_TOOLBAR);
219         else if (f->right_toolbar_was_visible)
220                 gtk_clear_toolbar(f, RIGHT_TOOLBAR);
221 }
222
223 static void gtk_initialize_frame_toolbars(struct frame *f)
224 {
225         stderr_out("We should draw toolbars\n");
226 }
227 \f
228 /************************************************************************/
229 /*                            initialization                            */
230 /************************************************************************/
231
232 void console_type_create_toolbar_gtk(void)
233 {
234         CONSOLE_HAS_METHOD(gtk, output_frame_toolbars);
235         CONSOLE_HAS_METHOD(gtk, initialize_frame_toolbars);
236 }