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