1 /*
2 * e-focus-tracker.c
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License as published by
6 * the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
10 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11 * for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program; if not, see <http://www.gnu.org/licenses/>.
15 *
16 *
17 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
18 *
19 */
20
21 #include "evolution-config.h"
22
23 #include "e-focus-tracker.h"
24
25 #include <glib/gi18n-lib.h>
26
27 #include "e-selectable.h"
28 #include "e-widget-undo.h"
29 #include "e-content-editor.h"
30
31 #define E_FOCUS_TRACKER_GET_PRIVATE(obj) \
32 (G_TYPE_INSTANCE_GET_PRIVATE \
33 ((obj), E_TYPE_FOCUS_TRACKER, EFocusTrackerPrivate))
34
35 struct _EFocusTrackerPrivate {
36 GtkWidget *focus; /* not referenced */
37 GtkWindow *window;
38
39 GtkAction *cut_clipboard;
40 GtkAction *copy_clipboard;
41 GtkAction *paste_clipboard;
42 GtkAction *delete_selection;
43 GtkAction *select_all;
44 GtkAction *undo;
45 GtkAction *redo;
46 };
47
48 enum {
49 PROP_0,
50 PROP_FOCUS,
51 PROP_WINDOW,
52 PROP_CUT_CLIPBOARD_ACTION,
53 PROP_COPY_CLIPBOARD_ACTION,
54 PROP_PASTE_CLIPBOARD_ACTION,
55 PROP_DELETE_SELECTION_ACTION,
56 PROP_SELECT_ALL_ACTION,
57 PROP_UNDO_ACTION,
58 PROP_REDO_ACTION
59 };
60
G_DEFINE_TYPE(EFocusTracker,e_focus_tracker,G_TYPE_OBJECT)61 G_DEFINE_TYPE (
62 EFocusTracker,
63 e_focus_tracker,
64 G_TYPE_OBJECT)
65
66 static void
67 focus_tracker_disable_actions (EFocusTracker *focus_tracker)
68 {
69 GtkAction *action;
70
71 action = e_focus_tracker_get_cut_clipboard_action (focus_tracker);
72 if (action != NULL)
73 gtk_action_set_sensitive (action, FALSE);
74
75 action = e_focus_tracker_get_copy_clipboard_action (focus_tracker);
76 if (action != NULL)
77 gtk_action_set_sensitive (action, FALSE);
78
79 action = e_focus_tracker_get_paste_clipboard_action (focus_tracker);
80 if (action != NULL)
81 gtk_action_set_sensitive (action, FALSE);
82
83 action = e_focus_tracker_get_delete_selection_action (focus_tracker);
84 if (action != NULL)
85 gtk_action_set_sensitive (action, FALSE);
86
87 action = e_focus_tracker_get_select_all_action (focus_tracker);
88 if (action != NULL)
89 gtk_action_set_sensitive (action, FALSE);
90
91 action = e_focus_tracker_get_undo_action (focus_tracker);
92 if (action != NULL)
93 gtk_action_set_sensitive (action, FALSE);
94
95 action = e_focus_tracker_get_redo_action (focus_tracker);
96 if (action != NULL)
97 gtk_action_set_sensitive (action, FALSE);
98 }
99
100 static gboolean
focus_tracker_get_has_undo(GtkWidget * widget)101 focus_tracker_get_has_undo (GtkWidget *widget)
102 {
103 if (!widget)
104 return FALSE;
105
106 if (e_widget_undo_is_attached (widget))
107 return e_widget_undo_has_undo (widget);
108
109 if (E_IS_CONTENT_EDITOR (widget))
110 return e_content_editor_can_undo (E_CONTENT_EDITOR (widget));
111
112 return FALSE;
113 }
114
115 static gboolean
focus_tracker_get_has_redo(GtkWidget * widget)116 focus_tracker_get_has_redo (GtkWidget *widget)
117 {
118 if (!widget)
119 return FALSE;
120
121 if (e_widget_undo_is_attached (widget))
122 return e_widget_undo_has_redo (widget);
123
124 if (E_IS_CONTENT_EDITOR (widget))
125 return e_content_editor_can_redo (E_CONTENT_EDITOR (widget));
126
127 return FALSE;
128 }
129
130 static void
focus_tracker_update_undo_redo(EFocusTracker * focus_tracker,GtkWidget * widget,gboolean can_edit_text)131 focus_tracker_update_undo_redo (EFocusTracker *focus_tracker,
132 GtkWidget *widget,
133 gboolean can_edit_text)
134 {
135 GtkAction *action;
136 gboolean sensitive;
137
138 action = e_focus_tracker_get_undo_action (focus_tracker);
139 if (action != NULL) {
140 sensitive = can_edit_text && focus_tracker_get_has_undo (widget);
141 gtk_action_set_sensitive (action, sensitive);
142
143 if (sensitive) {
144 gchar *description;
145
146 description = e_widget_undo_describe_undo (widget);
147 gtk_action_set_tooltip (action, description && *description ? description : _("Undo"));
148 g_free (description);
149 } else {
150 gtk_action_set_tooltip (action, _("Undo"));
151 }
152 }
153
154 action = e_focus_tracker_get_redo_action (focus_tracker);
155 if (action != NULL) {
156 sensitive = can_edit_text && focus_tracker_get_has_redo (widget);
157 gtk_action_set_sensitive (action, sensitive);
158
159 if (sensitive) {
160 gchar *description;
161
162 description = e_widget_undo_describe_redo (widget);
163 gtk_action_set_tooltip (action, description && *description ? description : _("Redo"));
164 g_free (description);
165 } else {
166 gtk_action_set_tooltip (action, _("Redo"));
167 }
168 }
169 }
170
171 static void
focus_tracker_editable_update_actions(EFocusTracker * focus_tracker,GtkEditable * editable,GdkAtom * targets,gint n_targets)172 focus_tracker_editable_update_actions (EFocusTracker *focus_tracker,
173 GtkEditable *editable,
174 GdkAtom *targets,
175 gint n_targets)
176 {
177 GtkAction *action;
178 gboolean can_edit_text;
179 gboolean clipboard_has_text;
180 gboolean text_is_selected;
181 gboolean sensitive;
182
183 can_edit_text =
184 gtk_editable_get_editable (editable);
185
186 clipboard_has_text = (targets != NULL) &&
187 gtk_targets_include_text (targets, n_targets);
188
189 text_is_selected =
190 gtk_editable_get_selection_bounds (editable, NULL, NULL);
191
192 action = e_focus_tracker_get_cut_clipboard_action (focus_tracker);
193 if (action != NULL) {
194 sensitive = can_edit_text && text_is_selected;
195 gtk_action_set_sensitive (action, sensitive);
196 gtk_action_set_tooltip (action, _("Cut the selection"));
197 }
198
199 action = e_focus_tracker_get_copy_clipboard_action (focus_tracker);
200 if (action != NULL) {
201 sensitive = text_is_selected;
202 gtk_action_set_sensitive (action, sensitive);
203 gtk_action_set_tooltip (action, _("Copy the selection"));
204 }
205
206 action = e_focus_tracker_get_paste_clipboard_action (focus_tracker);
207 if (action != NULL) {
208 sensitive = can_edit_text && clipboard_has_text;
209 gtk_action_set_sensitive (action, sensitive);
210 gtk_action_set_tooltip (action, _("Paste the clipboard"));
211 }
212
213 action = e_focus_tracker_get_delete_selection_action (focus_tracker);
214 if (action != NULL) {
215 sensitive = can_edit_text && text_is_selected;
216 gtk_action_set_sensitive (action, sensitive);
217 gtk_action_set_tooltip (action, _("Delete the selection"));
218 }
219
220 action = e_focus_tracker_get_select_all_action (focus_tracker);
221 if (action != NULL) {
222 sensitive = TRUE; /* always enabled */
223 gtk_action_set_sensitive (action, sensitive);
224 gtk_action_set_tooltip (action, _("Select all text"));
225 }
226
227 focus_tracker_update_undo_redo (focus_tracker, GTK_WIDGET (editable), can_edit_text);
228 }
229
230 static void
focus_tracker_text_view_update_actions(EFocusTracker * focus_tracker,GtkTextView * text_view,GdkAtom * targets,gint n_targets)231 focus_tracker_text_view_update_actions (EFocusTracker *focus_tracker,
232 GtkTextView *text_view,
233 GdkAtom *targets,
234 gint n_targets)
235 {
236 GtkAction *action;
237 GtkTextBuffer *buffer;
238 gboolean can_edit_text;
239 gboolean clipboard_has_text;
240 gboolean text_is_selected;
241 gboolean sensitive;
242
243 buffer = gtk_text_view_get_buffer (text_view);
244 can_edit_text = gtk_text_view_get_editable (text_view);
245 clipboard_has_text = (targets != NULL) && gtk_targets_include_text (targets, n_targets);
246 text_is_selected = gtk_text_buffer_get_selection_bounds (buffer, NULL, NULL);
247
248 action = e_focus_tracker_get_cut_clipboard_action (focus_tracker);
249 if (action != NULL) {
250 sensitive = can_edit_text && text_is_selected;
251 gtk_action_set_sensitive (action, sensitive);
252 gtk_action_set_tooltip (action, _("Cut the selection"));
253 }
254
255 action = e_focus_tracker_get_copy_clipboard_action (focus_tracker);
256 if (action != NULL) {
257 sensitive = text_is_selected;
258 gtk_action_set_sensitive (action, sensitive);
259 gtk_action_set_tooltip (action, _("Copy the selection"));
260 }
261
262 action = e_focus_tracker_get_paste_clipboard_action (focus_tracker);
263 if (action != NULL) {
264 sensitive = can_edit_text && clipboard_has_text;
265 gtk_action_set_sensitive (action, sensitive);
266 gtk_action_set_tooltip (action, _("Paste the clipboard"));
267 }
268
269 action = e_focus_tracker_get_delete_selection_action (focus_tracker);
270 if (action != NULL) {
271 sensitive = can_edit_text && text_is_selected;
272 gtk_action_set_sensitive (action, sensitive);
273 gtk_action_set_tooltip (action, _("Delete the selection"));
274 }
275
276 action = e_focus_tracker_get_select_all_action (focus_tracker);
277 if (action != NULL) {
278 sensitive = TRUE; /* always enabled */
279 gtk_action_set_sensitive (action, sensitive);
280 gtk_action_set_tooltip (action, _("Select all text"));
281 }
282
283 focus_tracker_update_undo_redo (focus_tracker, GTK_WIDGET (text_view), can_edit_text);
284 }
285
286 static void
focus_tracker_editor_update_actions(EFocusTracker * focus_tracker,EContentEditor * cnt_editor,GdkAtom * targets,gint n_targets)287 focus_tracker_editor_update_actions (EFocusTracker *focus_tracker,
288 EContentEditor *cnt_editor,
289 GdkAtom *targets,
290 gint n_targets)
291 {
292 GtkAction *action;
293 gboolean can_copy;
294 gboolean can_cut;
295 gboolean can_paste;
296
297 g_object_get (cnt_editor,
298 "can-copy", &can_copy,
299 "can-cut", &can_cut,
300 "can-paste", &can_paste,
301 NULL);
302
303 action = e_focus_tracker_get_cut_clipboard_action (focus_tracker);
304 if (action != NULL) {
305 gtk_action_set_sensitive (action, can_cut);
306 gtk_action_set_tooltip (action, _("Cut the selection"));
307 }
308
309 action = e_focus_tracker_get_copy_clipboard_action (focus_tracker);
310 if (action != NULL) {
311 gtk_action_set_sensitive (action, can_copy);
312 gtk_action_set_tooltip (action, _("Copy the selection"));
313 }
314
315 action = e_focus_tracker_get_paste_clipboard_action (focus_tracker);
316 if (action != NULL) {
317 gtk_action_set_sensitive (action, can_paste);
318 gtk_action_set_tooltip (action, _("Paste the clipboard"));
319 }
320
321 focus_tracker_update_undo_redo (focus_tracker, GTK_WIDGET (cnt_editor),
322 e_content_editor_is_editable (cnt_editor));
323 }
324
325 static void
focus_tracker_selectable_update_actions(EFocusTracker * focus_tracker,ESelectable * selectable,GdkAtom * targets,gint n_targets)326 focus_tracker_selectable_update_actions (EFocusTracker *focus_tracker,
327 ESelectable *selectable,
328 GdkAtom *targets,
329 gint n_targets)
330 {
331 ESelectableInterface *iface;
332 GtkAction *action;
333
334 iface = E_SELECTABLE_GET_INTERFACE (selectable);
335
336 e_selectable_update_actions (
337 selectable, focus_tracker, targets, n_targets);
338
339 /* Disable actions for which the corresponding method is not
340 * implemented. This allows update_actions() implementations
341 * to simply skip the actions they don't support, which in turn
342 * allows us to add new actions without disturbing the existing
343 * ESelectable implementations. */
344
345 action = e_focus_tracker_get_cut_clipboard_action (focus_tracker);
346 if (action != NULL && iface->cut_clipboard == NULL)
347 gtk_action_set_sensitive (action, FALSE);
348
349 action = e_focus_tracker_get_copy_clipboard_action (focus_tracker);
350 if (action != NULL && iface->copy_clipboard == NULL)
351 gtk_action_set_sensitive (action, FALSE);
352
353 action = e_focus_tracker_get_paste_clipboard_action (focus_tracker);
354 if (action != NULL && iface->paste_clipboard == NULL)
355 gtk_action_set_sensitive (action, FALSE);
356
357 action = e_focus_tracker_get_delete_selection_action (focus_tracker);
358 if (action != NULL && iface->delete_selection == NULL)
359 gtk_action_set_sensitive (action, FALSE);
360
361 action = e_focus_tracker_get_select_all_action (focus_tracker);
362 if (action != NULL && iface->select_all == NULL)
363 gtk_action_set_sensitive (action, FALSE);
364
365 action = e_focus_tracker_get_undo_action (focus_tracker);
366 if (action != NULL && iface->undo == NULL)
367 gtk_action_set_sensitive (action, FALSE);
368
369 action = e_focus_tracker_get_redo_action (focus_tracker);
370 if (action != NULL && iface->redo == NULL)
371 gtk_action_set_sensitive (action, FALSE);
372 }
373
374 static void
focus_tracker_targets_received_cb(GtkClipboard * clipboard,GdkAtom * targets,gint n_targets,EFocusTracker * focus_tracker)375 focus_tracker_targets_received_cb (GtkClipboard *clipboard,
376 GdkAtom *targets,
377 gint n_targets,
378 EFocusTracker *focus_tracker)
379 {
380 GtkWidget *focus;
381
382 focus = e_focus_tracker_get_focus (focus_tracker);
383
384 if (focus == NULL)
385 focus_tracker_disable_actions (focus_tracker);
386
387 else if (E_IS_SELECTABLE (focus))
388 focus_tracker_selectable_update_actions (
389 focus_tracker, E_SELECTABLE (focus),
390 targets, n_targets);
391
392 else if (GTK_IS_EDITABLE (focus))
393 focus_tracker_editable_update_actions (
394 focus_tracker, GTK_EDITABLE (focus),
395 targets, n_targets);
396
397 else if (GTK_IS_TEXT_VIEW (focus))
398 focus_tracker_text_view_update_actions (
399 focus_tracker, GTK_TEXT_VIEW (focus),
400 targets, n_targets);
401
402 else if (E_IS_CONTENT_EDITOR (focus))
403 focus_tracker_editor_update_actions (
404 focus_tracker, E_CONTENT_EDITOR (focus),
405 targets, n_targets);
406
407 g_object_unref (focus_tracker);
408 }
409
410 static void
focus_tracker_set_focus_cb(GtkWindow * window,GtkWidget * focus,EFocusTracker * focus_tracker)411 focus_tracker_set_focus_cb (GtkWindow *window,
412 GtkWidget *focus,
413 EFocusTracker *focus_tracker)
414 {
415 while (focus != NULL) {
416 if (E_IS_SELECTABLE (focus))
417 break;
418
419 if (GTK_IS_EDITABLE (focus))
420 break;
421
422 if (GTK_IS_TEXT_VIEW (focus))
423 break;
424
425 if (E_IS_CONTENT_EDITOR (focus))
426 break;
427
428 focus = gtk_widget_get_parent (focus);
429 }
430
431 if (focus == focus_tracker->priv->focus)
432 return;
433
434 focus_tracker->priv->focus = focus;
435 g_object_notify (G_OBJECT (focus_tracker), "focus");
436
437 e_focus_tracker_update_actions (focus_tracker);
438 }
439
440 static void
focus_tracker_set_window(EFocusTracker * focus_tracker,GtkWindow * window)441 focus_tracker_set_window (EFocusTracker *focus_tracker,
442 GtkWindow *window)
443 {
444 g_return_if_fail (GTK_IS_WINDOW (window));
445 g_return_if_fail (focus_tracker->priv->window == NULL);
446
447 focus_tracker->priv->window = g_object_ref (window);
448
449 g_signal_connect (
450 window, "set-focus",
451 G_CALLBACK (focus_tracker_set_focus_cb), focus_tracker);
452 }
453
454 static void
focus_tracker_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)455 focus_tracker_set_property (GObject *object,
456 guint property_id,
457 const GValue *value,
458 GParamSpec *pspec)
459 {
460 switch (property_id) {
461 case PROP_WINDOW:
462 focus_tracker_set_window (
463 E_FOCUS_TRACKER (object),
464 g_value_get_object (value));
465 return;
466
467 case PROP_CUT_CLIPBOARD_ACTION:
468 e_focus_tracker_set_cut_clipboard_action (
469 E_FOCUS_TRACKER (object),
470 g_value_get_object (value));
471 return;
472
473 case PROP_COPY_CLIPBOARD_ACTION:
474 e_focus_tracker_set_copy_clipboard_action (
475 E_FOCUS_TRACKER (object),
476 g_value_get_object (value));
477 return;
478
479 case PROP_PASTE_CLIPBOARD_ACTION:
480 e_focus_tracker_set_paste_clipboard_action (
481 E_FOCUS_TRACKER (object),
482 g_value_get_object (value));
483 return;
484
485 case PROP_DELETE_SELECTION_ACTION:
486 e_focus_tracker_set_delete_selection_action (
487 E_FOCUS_TRACKER (object),
488 g_value_get_object (value));
489 return;
490
491 case PROP_SELECT_ALL_ACTION:
492 e_focus_tracker_set_select_all_action (
493 E_FOCUS_TRACKER (object),
494 g_value_get_object (value));
495 return;
496
497 case PROP_UNDO_ACTION:
498 e_focus_tracker_set_undo_action (
499 E_FOCUS_TRACKER (object),
500 g_value_get_object (value));
501 return;
502
503 case PROP_REDO_ACTION:
504 e_focus_tracker_set_redo_action (
505 E_FOCUS_TRACKER (object),
506 g_value_get_object (value));
507 return;
508 }
509
510 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
511 }
512
513 static void
focus_tracker_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)514 focus_tracker_get_property (GObject *object,
515 guint property_id,
516 GValue *value,
517 GParamSpec *pspec)
518 {
519 switch (property_id) {
520 case PROP_FOCUS:
521 g_value_set_object (
522 value,
523 e_focus_tracker_get_focus (
524 E_FOCUS_TRACKER (object)));
525 return;
526
527 case PROP_WINDOW:
528 g_value_set_object (
529 value,
530 e_focus_tracker_get_window (
531 E_FOCUS_TRACKER (object)));
532 return;
533
534 case PROP_CUT_CLIPBOARD_ACTION:
535 g_value_set_object (
536 value,
537 e_focus_tracker_get_cut_clipboard_action (
538 E_FOCUS_TRACKER (object)));
539 return;
540
541 case PROP_COPY_CLIPBOARD_ACTION:
542 g_value_set_object (
543 value,
544 e_focus_tracker_get_copy_clipboard_action (
545 E_FOCUS_TRACKER (object)));
546 return;
547
548 case PROP_PASTE_CLIPBOARD_ACTION:
549 g_value_set_object (
550 value,
551 e_focus_tracker_get_paste_clipboard_action (
552 E_FOCUS_TRACKER (object)));
553 return;
554
555 case PROP_DELETE_SELECTION_ACTION:
556 g_value_set_object (
557 value,
558 e_focus_tracker_get_delete_selection_action (
559 E_FOCUS_TRACKER (object)));
560 return;
561
562 case PROP_SELECT_ALL_ACTION:
563 g_value_set_object (
564 value,
565 e_focus_tracker_get_select_all_action (
566 E_FOCUS_TRACKER (object)));
567 return;
568
569 case PROP_UNDO_ACTION:
570 g_value_set_object (
571 value,
572 e_focus_tracker_get_undo_action (
573 E_FOCUS_TRACKER (object)));
574 return;
575
576 case PROP_REDO_ACTION:
577 g_value_set_object (
578 value,
579 e_focus_tracker_get_redo_action (
580 E_FOCUS_TRACKER (object)));
581 return;
582 }
583
584 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
585 }
586
587 static void
focus_tracker_dispose(GObject * object)588 focus_tracker_dispose (GObject *object)
589 {
590 EFocusTrackerPrivate *priv;
591
592 priv = E_FOCUS_TRACKER_GET_PRIVATE (object);
593
594 g_signal_handlers_disconnect_matched (
595 gtk_clipboard_get (GDK_SELECTION_PRIMARY),
596 G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, object);
597
598 g_signal_handlers_disconnect_matched (
599 gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
600 G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, object);
601
602 if (priv->window != NULL) {
603 g_signal_handlers_disconnect_matched (
604 priv->window, G_SIGNAL_MATCH_DATA,
605 0, 0, NULL, NULL, object);
606 g_object_unref (priv->window);
607 priv->window = NULL;
608 }
609
610 if (priv->cut_clipboard != NULL) {
611 g_signal_handlers_disconnect_matched (
612 priv->cut_clipboard, G_SIGNAL_MATCH_DATA,
613 0, 0, NULL, NULL, object);
614 g_object_unref (priv->cut_clipboard);
615 priv->cut_clipboard = NULL;
616 }
617
618 if (priv->copy_clipboard != NULL) {
619 g_signal_handlers_disconnect_matched (
620 priv->copy_clipboard, G_SIGNAL_MATCH_DATA,
621 0, 0, NULL, NULL, object);
622 g_object_unref (priv->copy_clipboard);
623 priv->copy_clipboard = NULL;
624 }
625
626 if (priv->paste_clipboard != NULL) {
627 g_signal_handlers_disconnect_matched (
628 priv->paste_clipboard, G_SIGNAL_MATCH_DATA,
629 0, 0, NULL, NULL, object);
630 g_object_unref (priv->paste_clipboard);
631 priv->paste_clipboard = NULL;
632 }
633
634 if (priv->delete_selection != NULL) {
635 g_signal_handlers_disconnect_matched (
636 priv->delete_selection, G_SIGNAL_MATCH_DATA,
637 0, 0, NULL, NULL, object);
638 g_object_unref (priv->delete_selection);
639 priv->delete_selection = NULL;
640 }
641
642 if (priv->select_all != NULL) {
643 g_signal_handlers_disconnect_matched (
644 priv->select_all, G_SIGNAL_MATCH_DATA,
645 0, 0, NULL, NULL, object);
646 g_object_unref (priv->select_all);
647 priv->select_all = NULL;
648 }
649
650 /* Chain up to parent's dispose() method. */
651 G_OBJECT_CLASS (e_focus_tracker_parent_class)->dispose (object);
652 }
653
654 static void
focus_tracker_constructed(GObject * object)655 focus_tracker_constructed (GObject *object)
656 {
657 GtkClipboard *clipboard;
658
659 /* Listen for "owner-change" signals from the primary selection
660 * clipboard to learn when text selections change in GtkEditable
661 * widgets. It's a bit of an overkill, but I don't know of any
662 * other notification mechanism. */
663
664 clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
665
666 g_signal_connect_swapped (
667 clipboard, "owner-change",
668 G_CALLBACK (e_focus_tracker_update_actions), object);
669
670 /* Listen for "owner-change" signals from the default clipboard
671 * so we can update the paste action when the user cuts or copies
672 * something. This is how GEdit does it. */
673
674 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
675
676 g_signal_connect_swapped (
677 clipboard, "owner-change",
678 G_CALLBACK (e_focus_tracker_update_actions), object);
679
680 /* Chain up to parent's constructed() method. */
681 G_OBJECT_CLASS (e_focus_tracker_parent_class)->constructed (object);
682 }
683
684 static void
e_focus_tracker_class_init(EFocusTrackerClass * class)685 e_focus_tracker_class_init (EFocusTrackerClass *class)
686 {
687 GObjectClass *object_class;
688
689 g_type_class_add_private (class, sizeof (EFocusTrackerPrivate));
690
691 object_class = G_OBJECT_CLASS (class);
692 object_class->set_property = focus_tracker_set_property;
693 object_class->get_property = focus_tracker_get_property;
694 object_class->dispose = focus_tracker_dispose;
695 object_class->constructed = focus_tracker_constructed;
696
697 g_object_class_install_property (
698 object_class,
699 PROP_FOCUS,
700 g_param_spec_object (
701 "focus",
702 "Focus",
703 NULL,
704 GTK_TYPE_WIDGET,
705 G_PARAM_READABLE));
706
707 g_object_class_install_property (
708 object_class,
709 PROP_WINDOW,
710 g_param_spec_object (
711 "window",
712 "Window",
713 NULL,
714 GTK_TYPE_WINDOW,
715 G_PARAM_READWRITE |
716 G_PARAM_CONSTRUCT_ONLY));
717
718 g_object_class_install_property (
719 object_class,
720 PROP_CUT_CLIPBOARD_ACTION,
721 g_param_spec_object (
722 "cut-clipboard-action",
723 "Cut Clipboard Action",
724 NULL,
725 GTK_TYPE_ACTION,
726 G_PARAM_READWRITE));
727
728 g_object_class_install_property (
729 object_class,
730 PROP_COPY_CLIPBOARD_ACTION,
731 g_param_spec_object (
732 "copy-clipboard-action",
733 "Copy Clipboard Action",
734 NULL,
735 GTK_TYPE_ACTION,
736 G_PARAM_READWRITE));
737
738 g_object_class_install_property (
739 object_class,
740 PROP_PASTE_CLIPBOARD_ACTION,
741 g_param_spec_object (
742 "paste-clipboard-action",
743 "Paste Clipboard Action",
744 NULL,
745 GTK_TYPE_ACTION,
746 G_PARAM_READWRITE));
747
748 g_object_class_install_property (
749 object_class,
750 PROP_DELETE_SELECTION_ACTION,
751 g_param_spec_object (
752 "delete-selection-action",
753 "Delete Selection Action",
754 NULL,
755 GTK_TYPE_ACTION,
756 G_PARAM_READWRITE));
757
758 g_object_class_install_property (
759 object_class,
760 PROP_SELECT_ALL_ACTION,
761 g_param_spec_object (
762 "select-all-action",
763 "Select All Action",
764 NULL,
765 GTK_TYPE_ACTION,
766 G_PARAM_READWRITE));
767
768 g_object_class_install_property (
769 object_class,
770 PROP_UNDO_ACTION,
771 g_param_spec_object (
772 "undo-action",
773 "Undo Action",
774 NULL,
775 GTK_TYPE_ACTION,
776 G_PARAM_READWRITE));
777
778 g_object_class_install_property (
779 object_class,
780 PROP_REDO_ACTION,
781 g_param_spec_object (
782 "redo-action",
783 "Redo Action",
784 NULL,
785 GTK_TYPE_ACTION,
786 G_PARAM_READWRITE));
787 }
788
789 static void
e_focus_tracker_init(EFocusTracker * focus_tracker)790 e_focus_tracker_init (EFocusTracker *focus_tracker)
791 {
792 GtkAction *action;
793
794 focus_tracker->priv = E_FOCUS_TRACKER_GET_PRIVATE (focus_tracker);
795
796 /* Define dummy actions. These will most likely be overridden,
797 * but for cases where they're not it ensures ESelectable objects
798 * will always get a valid GtkAction when they ask us for one. */
799
800 action = gtk_action_new (
801 "cut-clipboard", _("Cu_t"),
802 _("Cut the selection"), "edit-cut");
803 focus_tracker->priv->cut_clipboard = action;
804
805 action = gtk_action_new (
806 "copy-clipboard", _("_Copy"),
807 _("Copy the selection"), "edit-copy");
808 focus_tracker->priv->copy_clipboard = action;
809
810 action = gtk_action_new (
811 "paste-clipboard", _("_Paste"),
812 _("Paste the clipboard"), "edit-paste");
813 focus_tracker->priv->paste_clipboard = action;
814
815 action = gtk_action_new (
816 "delete-selection", _("_Delete"),
817 _("Delete the selection"), "edit-delete");
818 focus_tracker->priv->delete_selection = action;
819
820 action = gtk_action_new (
821 "select-all", _("Select _All"),
822 _("Select all text"), "edit-select-all");
823 focus_tracker->priv->select_all = action;
824 }
825
826 EFocusTracker *
e_focus_tracker_new(GtkWindow * window)827 e_focus_tracker_new (GtkWindow *window)
828 {
829 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
830
831 return g_object_new (E_TYPE_FOCUS_TRACKER, "window", window, NULL);
832 }
833
834 GtkWidget *
e_focus_tracker_get_focus(EFocusTracker * focus_tracker)835 e_focus_tracker_get_focus (EFocusTracker *focus_tracker)
836 {
837 g_return_val_if_fail (E_IS_FOCUS_TRACKER (focus_tracker), NULL);
838
839 return focus_tracker->priv->focus;
840 }
841
842 GtkWindow *
e_focus_tracker_get_window(EFocusTracker * focus_tracker)843 e_focus_tracker_get_window (EFocusTracker *focus_tracker)
844 {
845 g_return_val_if_fail (E_IS_FOCUS_TRACKER (focus_tracker), NULL);
846
847 return focus_tracker->priv->window;
848 }
849
850 GtkAction *
e_focus_tracker_get_cut_clipboard_action(EFocusTracker * focus_tracker)851 e_focus_tracker_get_cut_clipboard_action (EFocusTracker *focus_tracker)
852 {
853 g_return_val_if_fail (E_IS_FOCUS_TRACKER (focus_tracker), NULL);
854
855 return focus_tracker->priv->cut_clipboard;
856 }
857
858 void
e_focus_tracker_set_cut_clipboard_action(EFocusTracker * focus_tracker,GtkAction * cut_clipboard)859 e_focus_tracker_set_cut_clipboard_action (EFocusTracker *focus_tracker,
860 GtkAction *cut_clipboard)
861 {
862 g_return_if_fail (E_IS_FOCUS_TRACKER (focus_tracker));
863
864 if (cut_clipboard != NULL) {
865 g_return_if_fail (GTK_IS_ACTION (cut_clipboard));
866 g_object_ref (cut_clipboard);
867 }
868
869 if (focus_tracker->priv->cut_clipboard != NULL) {
870 g_signal_handlers_disconnect_matched (
871 focus_tracker->priv->cut_clipboard,
872 G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL,
873 focus_tracker);
874 g_object_unref (focus_tracker->priv->cut_clipboard);
875 }
876
877 focus_tracker->priv->cut_clipboard = cut_clipboard;
878
879 if (cut_clipboard != NULL)
880 g_signal_connect_swapped (
881 cut_clipboard, "activate",
882 G_CALLBACK (e_focus_tracker_cut_clipboard),
883 focus_tracker);
884
885 g_object_notify (G_OBJECT (focus_tracker), "cut-clipboard-action");
886 }
887
888 GtkAction *
e_focus_tracker_get_copy_clipboard_action(EFocusTracker * focus_tracker)889 e_focus_tracker_get_copy_clipboard_action (EFocusTracker *focus_tracker)
890 {
891 g_return_val_if_fail (E_IS_FOCUS_TRACKER (focus_tracker), NULL);
892
893 return focus_tracker->priv->copy_clipboard;
894 }
895
896 void
e_focus_tracker_set_copy_clipboard_action(EFocusTracker * focus_tracker,GtkAction * copy_clipboard)897 e_focus_tracker_set_copy_clipboard_action (EFocusTracker *focus_tracker,
898 GtkAction *copy_clipboard)
899 {
900 g_return_if_fail (E_IS_FOCUS_TRACKER (focus_tracker));
901
902 if (copy_clipboard != NULL) {
903 g_return_if_fail (GTK_IS_ACTION (copy_clipboard));
904 g_object_ref (copy_clipboard);
905 }
906
907 if (focus_tracker->priv->copy_clipboard != NULL) {
908 g_signal_handlers_disconnect_matched (
909 focus_tracker->priv->copy_clipboard,
910 G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL,
911 focus_tracker);
912 g_object_unref (focus_tracker->priv->copy_clipboard);
913 }
914
915 focus_tracker->priv->copy_clipboard = copy_clipboard;
916
917 if (copy_clipboard != NULL)
918 g_signal_connect_swapped (
919 copy_clipboard, "activate",
920 G_CALLBACK (e_focus_tracker_copy_clipboard),
921 focus_tracker);
922
923 g_object_notify (G_OBJECT (focus_tracker), "copy-clipboard-action");
924 }
925
926 GtkAction *
e_focus_tracker_get_paste_clipboard_action(EFocusTracker * focus_tracker)927 e_focus_tracker_get_paste_clipboard_action (EFocusTracker *focus_tracker)
928 {
929 g_return_val_if_fail (E_IS_FOCUS_TRACKER (focus_tracker), NULL);
930
931 return focus_tracker->priv->paste_clipboard;
932 }
933
934 void
e_focus_tracker_set_paste_clipboard_action(EFocusTracker * focus_tracker,GtkAction * paste_clipboard)935 e_focus_tracker_set_paste_clipboard_action (EFocusTracker *focus_tracker,
936 GtkAction *paste_clipboard)
937 {
938 g_return_if_fail (E_IS_FOCUS_TRACKER (focus_tracker));
939
940 if (paste_clipboard != NULL) {
941 g_return_if_fail (GTK_IS_ACTION (paste_clipboard));
942 g_object_ref (paste_clipboard);
943 }
944
945 if (focus_tracker->priv->paste_clipboard != NULL) {
946 g_signal_handlers_disconnect_matched (
947 focus_tracker->priv->paste_clipboard,
948 G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL,
949 focus_tracker);
950 g_object_unref (focus_tracker->priv->paste_clipboard);
951 }
952
953 focus_tracker->priv->paste_clipboard = paste_clipboard;
954
955 if (paste_clipboard != NULL)
956 g_signal_connect_swapped (
957 paste_clipboard, "activate",
958 G_CALLBACK (e_focus_tracker_paste_clipboard),
959 focus_tracker);
960
961 g_object_notify (G_OBJECT (focus_tracker), "paste-clipboard-action");
962 }
963
964 GtkAction *
e_focus_tracker_get_delete_selection_action(EFocusTracker * focus_tracker)965 e_focus_tracker_get_delete_selection_action (EFocusTracker *focus_tracker)
966 {
967 g_return_val_if_fail (E_IS_FOCUS_TRACKER (focus_tracker), NULL);
968
969 return focus_tracker->priv->delete_selection;
970 }
971
972 void
e_focus_tracker_set_delete_selection_action(EFocusTracker * focus_tracker,GtkAction * delete_selection)973 e_focus_tracker_set_delete_selection_action (EFocusTracker *focus_tracker,
974 GtkAction *delete_selection)
975 {
976 g_return_if_fail (E_IS_FOCUS_TRACKER (focus_tracker));
977
978 if (delete_selection != NULL) {
979 g_return_if_fail (GTK_IS_ACTION (delete_selection));
980 g_object_ref (delete_selection);
981 }
982
983 if (focus_tracker->priv->delete_selection != NULL) {
984 g_signal_handlers_disconnect_matched (
985 focus_tracker->priv->delete_selection,
986 G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL,
987 focus_tracker);
988 g_object_unref (focus_tracker->priv->delete_selection);
989 }
990
991 focus_tracker->priv->delete_selection = delete_selection;
992
993 if (delete_selection != NULL)
994 g_signal_connect_swapped (
995 delete_selection, "activate",
996 G_CALLBACK (e_focus_tracker_delete_selection),
997 focus_tracker);
998
999 g_object_notify (G_OBJECT (focus_tracker), "delete-selection-action");
1000 }
1001
1002 GtkAction *
e_focus_tracker_get_select_all_action(EFocusTracker * focus_tracker)1003 e_focus_tracker_get_select_all_action (EFocusTracker *focus_tracker)
1004 {
1005 g_return_val_if_fail (E_IS_FOCUS_TRACKER (focus_tracker), NULL);
1006
1007 return focus_tracker->priv->select_all;
1008 }
1009
1010 void
e_focus_tracker_set_select_all_action(EFocusTracker * focus_tracker,GtkAction * select_all)1011 e_focus_tracker_set_select_all_action (EFocusTracker *focus_tracker,
1012 GtkAction *select_all)
1013 {
1014 g_return_if_fail (E_IS_FOCUS_TRACKER (focus_tracker));
1015
1016 if (select_all != NULL) {
1017 g_return_if_fail (GTK_IS_ACTION (select_all));
1018 g_object_ref (select_all);
1019 }
1020
1021 if (focus_tracker->priv->select_all != NULL) {
1022 g_signal_handlers_disconnect_matched (
1023 focus_tracker->priv->select_all,
1024 G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL,
1025 focus_tracker);
1026 g_object_unref (focus_tracker->priv->select_all);
1027 }
1028
1029 focus_tracker->priv->select_all = select_all;
1030
1031 if (select_all != NULL)
1032 g_signal_connect_swapped (
1033 select_all, "activate",
1034 G_CALLBACK (e_focus_tracker_select_all),
1035 focus_tracker);
1036
1037 g_object_notify (G_OBJECT (focus_tracker), "select-all-action");
1038 }
1039
1040 GtkAction *
e_focus_tracker_get_undo_action(EFocusTracker * focus_tracker)1041 e_focus_tracker_get_undo_action (EFocusTracker *focus_tracker)
1042 {
1043 g_return_val_if_fail (E_IS_FOCUS_TRACKER (focus_tracker), NULL);
1044
1045 return focus_tracker->priv->undo;
1046 }
1047
1048 void
e_focus_tracker_set_undo_action(EFocusTracker * focus_tracker,GtkAction * undo)1049 e_focus_tracker_set_undo_action (EFocusTracker *focus_tracker,
1050 GtkAction *undo)
1051 {
1052 g_return_if_fail (E_IS_FOCUS_TRACKER (focus_tracker));
1053
1054 if (undo != NULL) {
1055 g_return_if_fail (GTK_IS_ACTION (undo));
1056 g_object_ref (undo);
1057 }
1058
1059 if (focus_tracker->priv->undo != NULL) {
1060 g_signal_handlers_disconnect_matched (
1061 focus_tracker->priv->undo,
1062 G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL,
1063 focus_tracker);
1064 g_object_unref (focus_tracker->priv->undo);
1065 }
1066
1067 focus_tracker->priv->undo = undo;
1068
1069 if (undo != NULL)
1070 g_signal_connect_swapped (
1071 undo, "activate",
1072 G_CALLBACK (e_focus_tracker_undo),
1073 focus_tracker);
1074
1075 g_object_notify (G_OBJECT (focus_tracker), "undo-action");
1076 }
1077
1078 GtkAction *
e_focus_tracker_get_redo_action(EFocusTracker * focus_tracker)1079 e_focus_tracker_get_redo_action (EFocusTracker *focus_tracker)
1080 {
1081 g_return_val_if_fail (E_IS_FOCUS_TRACKER (focus_tracker), NULL);
1082
1083 return focus_tracker->priv->redo;
1084 }
1085
1086 void
e_focus_tracker_set_redo_action(EFocusTracker * focus_tracker,GtkAction * redo)1087 e_focus_tracker_set_redo_action (EFocusTracker *focus_tracker,
1088 GtkAction *redo)
1089 {
1090 g_return_if_fail (E_IS_FOCUS_TRACKER (focus_tracker));
1091
1092 if (redo != NULL) {
1093 g_return_if_fail (GTK_IS_ACTION (redo));
1094 g_object_ref (redo);
1095 }
1096
1097 if (focus_tracker->priv->redo != NULL) {
1098 g_signal_handlers_disconnect_matched (
1099 focus_tracker->priv->redo,
1100 G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL,
1101 focus_tracker);
1102 g_object_unref (focus_tracker->priv->redo);
1103 }
1104
1105 focus_tracker->priv->redo = redo;
1106
1107 if (redo != NULL)
1108 g_signal_connect_swapped (
1109 redo, "activate",
1110 G_CALLBACK (e_focus_tracker_redo),
1111 focus_tracker);
1112
1113 g_object_notify (G_OBJECT (focus_tracker), "redo-action");
1114 }
1115
1116 void
e_focus_tracker_update_actions(EFocusTracker * focus_tracker)1117 e_focus_tracker_update_actions (EFocusTracker *focus_tracker)
1118 {
1119 GtkClipboard *clipboard;
1120
1121 g_return_if_fail (E_IS_FOCUS_TRACKER (focus_tracker));
1122
1123 /* Request clipboard targets asynchronously. */
1124
1125 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
1126
1127 gtk_clipboard_request_targets (
1128 clipboard, (GtkClipboardTargetsReceivedFunc)
1129 focus_tracker_targets_received_cb,
1130 g_object_ref (focus_tracker));
1131 }
1132
1133 void
e_focus_tracker_cut_clipboard(EFocusTracker * focus_tracker)1134 e_focus_tracker_cut_clipboard (EFocusTracker *focus_tracker)
1135 {
1136 GtkWidget *focus;
1137
1138 g_return_if_fail (E_IS_FOCUS_TRACKER (focus_tracker));
1139
1140 focus = e_focus_tracker_get_focus (focus_tracker);
1141
1142 if (E_IS_SELECTABLE (focus)) {
1143 e_selectable_cut_clipboard (E_SELECTABLE (focus));
1144
1145 } else if (GTK_IS_EDITABLE (focus)) {
1146 gtk_editable_cut_clipboard (GTK_EDITABLE (focus));
1147
1148 } else if (GTK_IS_TEXT_VIEW (focus)) {
1149 GtkClipboard *clipboard;
1150 GtkTextView *text_view;
1151 GtkTextBuffer *buffer;
1152 gboolean is_editable;
1153
1154 clipboard = gtk_widget_get_clipboard (
1155 focus, GDK_SELECTION_CLIPBOARD);
1156
1157 text_view = GTK_TEXT_VIEW (focus);
1158 buffer = gtk_text_view_get_buffer (text_view);
1159 is_editable = gtk_text_view_get_editable (text_view);
1160
1161 gtk_text_buffer_cut_clipboard (buffer, clipboard, is_editable);
1162
1163 } else if (E_IS_CONTENT_EDITOR (focus)) {
1164 e_content_editor_cut (E_CONTENT_EDITOR (focus));
1165 }
1166 }
1167
1168 void
e_focus_tracker_copy_clipboard(EFocusTracker * focus_tracker)1169 e_focus_tracker_copy_clipboard (EFocusTracker *focus_tracker)
1170 {
1171 GtkWidget *focus;
1172
1173 g_return_if_fail (E_IS_FOCUS_TRACKER (focus_tracker));
1174
1175 focus = e_focus_tracker_get_focus (focus_tracker);
1176
1177 if (E_IS_SELECTABLE (focus)) {
1178 e_selectable_copy_clipboard (E_SELECTABLE (focus));
1179
1180 } else if (GTK_IS_EDITABLE (focus)) {
1181 gtk_editable_copy_clipboard (GTK_EDITABLE (focus));
1182
1183 } else if (GTK_IS_TEXT_VIEW (focus)) {
1184 GtkClipboard *clipboard;
1185 GtkTextView *text_view;
1186 GtkTextBuffer *buffer;
1187
1188 clipboard = gtk_widget_get_clipboard (
1189 focus, GDK_SELECTION_CLIPBOARD);
1190
1191 text_view = GTK_TEXT_VIEW (focus);
1192 buffer = gtk_text_view_get_buffer (text_view);
1193
1194 gtk_text_buffer_copy_clipboard (buffer, clipboard);
1195
1196 } else if (E_IS_CONTENT_EDITOR (focus)) {
1197 e_content_editor_copy (E_CONTENT_EDITOR (focus));
1198 }
1199 }
1200
1201 void
e_focus_tracker_paste_clipboard(EFocusTracker * focus_tracker)1202 e_focus_tracker_paste_clipboard (EFocusTracker *focus_tracker)
1203 {
1204 GtkWidget *focus;
1205
1206 g_return_if_fail (E_IS_FOCUS_TRACKER (focus_tracker));
1207
1208 focus = e_focus_tracker_get_focus (focus_tracker);
1209
1210 if (E_IS_SELECTABLE (focus)) {
1211 e_selectable_paste_clipboard (E_SELECTABLE (focus));
1212
1213 } else if (GTK_IS_EDITABLE (focus)) {
1214 gtk_editable_paste_clipboard (GTK_EDITABLE (focus));
1215
1216 } else if (GTK_IS_TEXT_VIEW (focus)) {
1217 GtkClipboard *clipboard;
1218 GtkTextView *text_view;
1219 GtkTextBuffer *buffer;
1220 gboolean is_editable;
1221
1222 clipboard = gtk_widget_get_clipboard (
1223 focus, GDK_SELECTION_CLIPBOARD);
1224
1225 text_view = GTK_TEXT_VIEW (focus);
1226 buffer = gtk_text_view_get_buffer (text_view);
1227 is_editable = gtk_text_view_get_editable (text_view);
1228
1229 gtk_text_buffer_paste_clipboard (
1230 buffer, clipboard, NULL, is_editable);
1231
1232 } else if (E_IS_CONTENT_EDITOR (focus)) {
1233 e_content_editor_paste (E_CONTENT_EDITOR (focus));
1234 }
1235 }
1236
1237 void
e_focus_tracker_delete_selection(EFocusTracker * focus_tracker)1238 e_focus_tracker_delete_selection (EFocusTracker *focus_tracker)
1239 {
1240 GtkWidget *focus;
1241
1242 g_return_if_fail (E_IS_FOCUS_TRACKER (focus_tracker));
1243
1244 focus = e_focus_tracker_get_focus (focus_tracker);
1245
1246 if (E_IS_SELECTABLE (focus)) {
1247 e_selectable_delete_selection (E_SELECTABLE (focus));
1248
1249 } else if (GTK_IS_EDITABLE (focus)) {
1250 gtk_editable_delete_selection (GTK_EDITABLE (focus));
1251
1252 } else if (GTK_IS_TEXT_VIEW (focus)) {
1253 GtkTextView *text_view;
1254 GtkTextBuffer *buffer;
1255 gboolean is_editable;
1256
1257 text_view = GTK_TEXT_VIEW (focus);
1258 buffer = gtk_text_view_get_buffer (text_view);
1259 is_editable = gtk_text_view_get_editable (text_view);
1260
1261 gtk_text_buffer_delete_selection (buffer, TRUE, is_editable);
1262 }
1263 }
1264
1265 void
e_focus_tracker_select_all(EFocusTracker * focus_tracker)1266 e_focus_tracker_select_all (EFocusTracker *focus_tracker)
1267 {
1268 GtkWidget *focus;
1269
1270 g_return_if_fail (E_IS_FOCUS_TRACKER (focus_tracker));
1271
1272 focus = e_focus_tracker_get_focus (focus_tracker);
1273
1274 if (E_IS_SELECTABLE (focus)) {
1275 e_selectable_select_all (E_SELECTABLE (focus));
1276
1277 } else if (GTK_IS_EDITABLE (focus)) {
1278 gtk_editable_select_region (GTK_EDITABLE (focus), 0, -1);
1279
1280 } else if (GTK_IS_TEXT_VIEW (focus)) {
1281 GtkTextView *text_view;
1282 GtkTextBuffer *buffer;
1283 GtkTextIter start, end;
1284
1285 text_view = GTK_TEXT_VIEW (focus);
1286 buffer = gtk_text_view_get_buffer (text_view);
1287
1288 gtk_text_buffer_get_bounds (buffer, &start, &end);
1289 gtk_text_buffer_select_range (buffer, &start, &end);
1290
1291 } else if (E_IS_CONTENT_EDITOR (focus)) {
1292 e_content_editor_select_all (E_CONTENT_EDITOR (focus));
1293 }
1294 }
1295
1296 void
e_focus_tracker_undo(EFocusTracker * focus_tracker)1297 e_focus_tracker_undo (EFocusTracker *focus_tracker)
1298 {
1299 GtkWidget *focus;
1300
1301 g_return_if_fail (E_IS_FOCUS_TRACKER (focus_tracker));
1302
1303 focus = e_focus_tracker_get_focus (focus_tracker);
1304
1305 if (E_IS_SELECTABLE (focus))
1306 e_selectable_undo (E_SELECTABLE (focus));
1307 else
1308 e_widget_undo_do_undo (focus);
1309 }
1310
1311 void
e_focus_tracker_redo(EFocusTracker * focus_tracker)1312 e_focus_tracker_redo (EFocusTracker *focus_tracker)
1313 {
1314 GtkWidget *focus;
1315
1316 g_return_if_fail (E_IS_FOCUS_TRACKER (focus_tracker));
1317
1318 focus = e_focus_tracker_get_focus (focus_tracker);
1319
1320 if (E_IS_SELECTABLE (focus))
1321 e_selectable_redo (E_SELECTABLE (focus));
1322 else
1323 e_widget_undo_do_redo (focus);
1324 }
1325