1 /*
2 * xed-statusbar.c
3 * This file is part of xed
4 *
5 * Copyright (C) 2005 - Paolo Borelli
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
21 */
22
23 /*
24 * Modified by the xed Team, 2005. See the AUTHORS file for a
25 * list of people on the xed Team.
26 * See the ChangeLog files for a list of changes.
27 *
28 * $Id$
29 */
30
31 #include <config.h>
32 #include <string.h>
33 #include <glib/gi18n.h>
34 #include <gtk/gtk.h>
35
36 #include "xed-statusbar.h"
37
38 struct _XedStatusbarPrivate
39 {
40 GtkWidget *overwrite_mode_label;
41 GtkWidget *cursor_position_label;
42
43 GtkWidget *state_frame;
44 GtkWidget *load_image;
45 GtkWidget *save_image;
46 GtkWidget *print_image;
47
48 GtkWidget *error_frame;
49 GtkWidget *error_event_box;
50
51 /* tmp flash timeout data */
52 guint flash_timeout;
53 guint flash_context_id;
54 guint flash_message_id;
55 };
56
G_DEFINE_TYPE_WITH_PRIVATE(XedStatusbar,xed_statusbar,GTK_TYPE_STATUSBAR)57 G_DEFINE_TYPE_WITH_PRIVATE (XedStatusbar, xed_statusbar, GTK_TYPE_STATUSBAR)
58
59
60 static gchar *
61 get_overwrite_mode_string (gboolean overwrite)
62 {
63 return g_strconcat (" ", overwrite ? _("OVR") : _("INS"), NULL);
64 }
65
66 static gint
get_overwrite_mode_length(void)67 get_overwrite_mode_length (void)
68 {
69 return 2 + MAX (g_utf8_strlen (_("OVR"), -1), g_utf8_strlen (_("INS"), -1));
70 }
71
72 static void
xed_statusbar_dispose(GObject * object)73 xed_statusbar_dispose (GObject *object)
74 {
75 XedStatusbar *statusbar = XED_STATUSBAR (object);
76
77 if (statusbar->priv->flash_timeout > 0)
78 {
79 g_source_remove (statusbar->priv->flash_timeout);
80 statusbar->priv->flash_timeout = 0;
81 }
82
83 G_OBJECT_CLASS (xed_statusbar_parent_class)->dispose (object);
84 }
85
86 static void
xed_statusbar_class_init(XedStatusbarClass * klass)87 xed_statusbar_class_init (XedStatusbarClass *klass)
88 {
89 GObjectClass *object_class = G_OBJECT_CLASS (klass);
90
91 object_class->dispose = xed_statusbar_dispose;
92 }
93
94 #define CURSOR_POSITION_LABEL_WIDTH_CHARS 18
95
96 static void
xed_statusbar_init(XedStatusbar * statusbar)97 xed_statusbar_init (XedStatusbar *statusbar)
98 {
99 GtkWidget *hbox;
100 GtkWidget *error_image;
101
102 statusbar->priv = xed_statusbar_get_instance_private (statusbar);
103
104 gtk_widget_set_margin_top (GTK_WIDGET (statusbar), 0);
105 gtk_widget_set_margin_bottom (GTK_WIDGET (statusbar), 0);
106
107 statusbar->priv->overwrite_mode_label = gtk_label_new (NULL);
108 gtk_label_set_width_chars (GTK_LABEL (statusbar->priv->overwrite_mode_label), get_overwrite_mode_length ());
109 gtk_widget_show (statusbar->priv->overwrite_mode_label);
110 gtk_box_pack_end (GTK_BOX (statusbar), statusbar->priv->overwrite_mode_label, FALSE, TRUE, 0);
111 gtk_widget_set_margin_end (GTK_WIDGET (statusbar->priv->overwrite_mode_label), 6);
112
113 statusbar->priv->cursor_position_label = gtk_label_new (NULL);
114 gtk_label_set_width_chars (GTK_LABEL (statusbar->priv->cursor_position_label), CURSOR_POSITION_LABEL_WIDTH_CHARS);
115 gtk_widget_show (statusbar->priv->cursor_position_label);
116 gtk_box_pack_end (GTK_BOX (statusbar), statusbar->priv->cursor_position_label, FALSE, TRUE, 0);
117
118 statusbar->priv->state_frame = gtk_frame_new (NULL);
119 gtk_frame_set_shadow_type (GTK_FRAME (statusbar->priv->state_frame), GTK_SHADOW_IN);
120
121 hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
122 gtk_container_add (GTK_CONTAINER (statusbar->priv->state_frame), hbox);
123
124 statusbar->priv->load_image = gtk_image_new_from_icon_name ("document-open-symbolic", GTK_ICON_SIZE_MENU);
125 statusbar->priv->save_image = gtk_image_new_from_icon_name ("document-save-symbolic", GTK_ICON_SIZE_MENU);
126 statusbar->priv->print_image = gtk_image_new_from_icon_name ("printer-symbolic", GTK_ICON_SIZE_MENU);
127
128 gtk_widget_show (hbox);
129
130 gtk_box_pack_start (GTK_BOX (hbox), statusbar->priv->load_image, FALSE, TRUE, 4);
131 gtk_box_pack_start (GTK_BOX (hbox), statusbar->priv->save_image, FALSE, TRUE, 4);
132 gtk_box_pack_start (GTK_BOX (hbox), statusbar->priv->print_image, FALSE, TRUE, 4);
133
134 gtk_box_pack_start (GTK_BOX (statusbar), statusbar->priv->state_frame, FALSE, TRUE, 0);
135
136 statusbar->priv->error_frame = gtk_frame_new (NULL);
137 gtk_frame_set_shadow_type (GTK_FRAME (statusbar->priv->error_frame), GTK_SHADOW_IN);
138
139 error_image = gtk_image_new_from_icon_name ("dialog-error", GTK_ICON_SIZE_MENU);
140
141 gtk_widget_set_margin_start (error_image, 4);
142 gtk_widget_set_margin_end (error_image, 4);
143 gtk_widget_set_margin_top (error_image, 0);
144 gtk_widget_set_margin_bottom (error_image, 0);
145
146 statusbar->priv->error_event_box = gtk_event_box_new ();
147 gtk_event_box_set_visible_window (GTK_EVENT_BOX (statusbar->priv->error_event_box), FALSE);
148 gtk_widget_show (statusbar->priv->error_event_box);
149
150 gtk_container_add (GTK_CONTAINER (statusbar->priv->error_frame), statusbar->priv->error_event_box);
151 gtk_container_add (GTK_CONTAINER (statusbar->priv->error_event_box), error_image);
152
153 gtk_box_pack_start (GTK_BOX (statusbar), statusbar->priv->error_frame, FALSE, TRUE, 0);
154
155 gtk_style_context_add_class (gtk_widget_get_style_context GTK_WIDGET (statusbar), "xed-statusbar");
156 }
157
158 /**
159 * xed_statusbar_new:
160 *
161 * Creates a new #XedStatusbar.
162 *
163 * Return value: the new #XedStatusbar object
164 **/
165 GtkWidget *
xed_statusbar_new(void)166 xed_statusbar_new (void)
167 {
168 return GTK_WIDGET (g_object_new (XED_TYPE_STATUSBAR, NULL));
169 }
170
171 /**
172 * xed_statusbar_set_overwrite:
173 * @statusbar: a #XedStatusbar
174 * @overwrite: if the overwrite mode is set
175 *
176 * Sets the overwrite mode on the statusbar.
177 **/
178 void
xed_statusbar_set_overwrite(XedStatusbar * statusbar,gboolean overwrite)179 xed_statusbar_set_overwrite (XedStatusbar *statusbar,
180 gboolean overwrite)
181 {
182 gchar *msg;
183
184 g_return_if_fail (XED_IS_STATUSBAR (statusbar));
185
186 msg = get_overwrite_mode_string (overwrite);
187
188 gtk_label_set_text (GTK_LABEL (statusbar->priv->overwrite_mode_label), msg);
189
190 g_free (msg);
191 }
192
193 void
xed_statusbar_clear_overwrite(XedStatusbar * statusbar)194 xed_statusbar_clear_overwrite (XedStatusbar *statusbar)
195 {
196 g_return_if_fail (XED_IS_STATUSBAR (statusbar));
197
198 gtk_label_set_text (GTK_LABEL (statusbar->priv->overwrite_mode_label), NULL);
199 }
200
201 /**
202 * xed_statusbar_cursor_position:
203 * @statusbar: an #XedStatusbar
204 * @line: line position
205 * @col: column position
206 *
207 * Sets the cursor position on the statusbar.
208 **/
209 void
xed_statusbar_set_cursor_position(XedStatusbar * statusbar,gint line,gint col)210 xed_statusbar_set_cursor_position (XedStatusbar *statusbar,
211 gint line,
212 gint col)
213 {
214 gchar *msg = NULL;
215
216 g_return_if_fail (XED_IS_STATUSBAR (statusbar));
217
218 if ((line >= 0) || (col >= 0))
219 {
220 /* Translators: "Ln" is an abbreviation for "Line", Col is an abbreviation for "Column". Please,
221 use abbreviations if possible to avoid space problems. */
222 msg = g_strdup_printf (_(" Ln %d, Col %d"), line, col);
223 }
224
225 gtk_label_set_text (GTK_LABEL (statusbar->priv->cursor_position_label), msg);
226
227 g_free (msg);
228 }
229
230 static gboolean
remove_message_timeout(XedStatusbar * statusbar)231 remove_message_timeout (XedStatusbar *statusbar)
232 {
233 gtk_statusbar_remove (GTK_STATUSBAR (statusbar),
234 statusbar->priv->flash_context_id,
235 statusbar->priv->flash_message_id);
236
237 /* remove the timeout */
238 statusbar->priv->flash_timeout = 0;
239 return FALSE;
240 }
241
242 /* FIXME this is an issue for introspection */
243 /**
244 * xed_statusbar_flash_message:
245 * @statusbar: a #XedStatusbar
246 * @context_id: message context_id
247 * @format: message to flash on the statusbar
248 * @...: format arguments
249 *
250 * Flash a temporary message on the statusbar.
251 */
252 void
xed_statusbar_flash_message(XedStatusbar * statusbar,guint context_id,const gchar * format,...)253 xed_statusbar_flash_message (XedStatusbar *statusbar,
254 guint context_id,
255 const gchar *format, ...)
256 {
257 const guint32 flash_length = 3000; /* three seconds */
258 va_list args;
259 gchar *msg;
260
261 g_return_if_fail (XED_IS_STATUSBAR (statusbar));
262 g_return_if_fail (format != NULL);
263
264 va_start (args, format);
265 msg = g_strdup_vprintf (format, args);
266 va_end (args);
267
268 /* remove a currently ongoing flash message */
269 if (statusbar->priv->flash_timeout > 0)
270 {
271 g_source_remove (statusbar->priv->flash_timeout);
272 statusbar->priv->flash_timeout = 0;
273
274 gtk_statusbar_remove (GTK_STATUSBAR (statusbar),
275 statusbar->priv->flash_context_id,
276 statusbar->priv->flash_message_id);
277 }
278
279 statusbar->priv->flash_context_id = context_id;
280 statusbar->priv->flash_message_id = gtk_statusbar_push (GTK_STATUSBAR (statusbar), context_id, msg);
281
282 statusbar->priv->flash_timeout = g_timeout_add (flash_length,
283 (GSourceFunc) remove_message_timeout,
284 statusbar);
285
286 g_free (msg);
287 }
288
289 void
xed_statusbar_set_window_state(XedStatusbar * statusbar,XedWindowState state,gint num_of_errors)290 xed_statusbar_set_window_state (XedStatusbar *statusbar,
291 XedWindowState state,
292 gint num_of_errors)
293 {
294 g_return_if_fail (XED_IS_STATUSBAR (statusbar));
295
296 gtk_widget_hide (statusbar->priv->state_frame);
297 gtk_widget_hide (statusbar->priv->save_image);
298 gtk_widget_hide (statusbar->priv->load_image);
299 gtk_widget_hide (statusbar->priv->print_image);
300
301 if (state & XED_WINDOW_STATE_SAVING)
302 {
303 gtk_widget_show (statusbar->priv->state_frame);
304 gtk_widget_show (statusbar->priv->save_image);
305 }
306 if (state & XED_WINDOW_STATE_LOADING)
307 {
308 gtk_widget_show (statusbar->priv->state_frame);
309 gtk_widget_show (statusbar->priv->load_image);
310 }
311
312 if (state & XED_WINDOW_STATE_PRINTING)
313 {
314 gtk_widget_show (statusbar->priv->state_frame);
315 gtk_widget_show (statusbar->priv->print_image);
316 }
317
318 if (state & XED_WINDOW_STATE_ERROR)
319 {
320 gchar *tip;
321
322 tip = g_strdup_printf (ngettext("There is a tab with errors",
323 "There are %d tabs with errors",
324 num_of_errors),
325 num_of_errors);
326
327 gtk_widget_set_tooltip_text (statusbar->priv->error_event_box, tip);
328 g_free (tip);
329
330 gtk_widget_show (statusbar->priv->error_frame);
331 }
332 else
333 {
334 gtk_widget_hide (statusbar->priv->error_frame);
335 }
336 }
337
338
339