libyui-gtk  2.44.10
ygtktextview.c
1 /********************************************************************
2  * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
3  ********************************************************************/
4 
5 /* YGtkTextView widget */
6 // check the header file for information about this widget
7 
8 #include <yui/Libyui_config.h>
9 #include "ygtktextview.h"
10 #include <gtk/gtk.h>
11 
12 G_DEFINE_TYPE (YGtkTextView, ygtk_text_view, GTK_TYPE_TEXT_VIEW)
13 
14 static void ygtk_text_view_init (YGtkTextView *view)
15 {
16 }
17 
18 static void ygtk_text_view_realize (GtkWidget *widget)
19 {
20  GTK_WIDGET_CLASS (ygtk_text_view_parent_class)->realize (widget);
21 
22  GtkTextView *view = GTK_TEXT_VIEW (widget);
23  if (!gtk_text_view_get_editable (view)) {
24  gtk_text_view_set_cursor_visible (view, FALSE);
25  GdkWindow *window = gtk_text_view_get_window (view, GTK_TEXT_WINDOW_TEXT);
26  gdk_window_set_cursor (window, NULL);
27  }
28 }
29 
30 // popup utilities
31 static void copy_activate_cb (GtkMenuItem *item, GtkTextBuffer *buffer)
32 {
33  gtk_text_buffer_copy_clipboard (buffer, gtk_clipboard_get (GDK_SELECTION_CLIPBOARD));
34 }
35 static void select_all_activate_cb (GtkMenuItem *item, GtkTextBuffer *buffer)
36 {
37  GtkTextIter start, end;
38  gtk_text_buffer_get_bounds (buffer, &start, &end);
39  gtk_text_buffer_select_range (buffer, &start, &end);
40 }
41 
42 #if GTK_CHECK_VERSION(3, 8, 0)
43 static void ygtk_text_view_populate_popup (GtkTextView *view, GtkWidget *menu)
44 #else
45 static void ygtk_text_view_populate_popup (GtkTextView *view, GtkMenu *menu)
46 #endif
47 {
48  if (gtk_text_view_get_editable (view))
49  return;
50  GtkTextBuffer *buffer = gtk_text_view_get_buffer (view);
51 
52  GList *items = gtk_container_get_children (GTK_CONTAINER (menu)), *i;
53  for (i = items; i; i = i->next)
54  gtk_container_remove (GTK_CONTAINER (menu), i->data);
55  g_list_free (items);
56 
57  GtkWidget *item;
58  item = gtk_menu_item_new();
59  gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
60  if (gtk_text_buffer_get_has_selection (buffer))
61  g_signal_connect (item, "activate", G_CALLBACK (copy_activate_cb), buffer);
62  else
63  gtk_widget_set_sensitive (item, FALSE);
64  item = gtk_separator_menu_item_new();
65  gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
66  item = gtk_menu_item_new();
67  gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
68  g_signal_connect (item, "activate", G_CALLBACK (select_all_activate_cb), buffer);
69  gtk_widget_show_all (GTK_WIDGET (menu));
70 }
71 
72 static inline gboolean is_space (gunichar ch)
73 { return g_unichar_isspace (ch) || ch == 0xfffc; }
74 
75 static gboolean ygtk_text_view_button_press_event (GtkWidget *widget, GdkEventButton *event)
76 { // on right-click, select word under cursor if there is no selection
77  if (event->button == 3) {
78  GtkTextView *view = GTK_TEXT_VIEW (widget);
79  GtkTextBuffer *buffer = gtk_text_view_get_buffer (view);
80  if (!gtk_text_buffer_get_has_selection (buffer)) {
81  gint buffer_x, buffer_y;
82  gtk_text_view_window_to_buffer_coords (view,
83  GTK_TEXT_WINDOW_WIDGET, (gint) event->x, (gint) event->y, &buffer_x, &buffer_y);
84  GtkTextIter iter;
85  gtk_text_view_get_iter_at_location (view, &iter, buffer_x, buffer_y);
86 
87  if (!is_space (gtk_text_iter_get_char (&iter))) {
88  GtkTextIter start, end = iter, temp = iter;
89  do {
90  start = temp;
91  if (!gtk_text_iter_backward_char (&temp))
92  break;
93  } while (!is_space (gtk_text_iter_get_char (&temp)));
94  do {
95  if (!gtk_text_iter_forward_char (&end))
96  break;
97  } while (!is_space (gtk_text_iter_get_char (&end)));
98 
99  gtk_text_buffer_select_range (buffer, &start, &end);
100  }
101  }
102  }
103  return GTK_WIDGET_CLASS (ygtk_text_view_parent_class)->button_press_event (widget, event);
104 }
105 
106 GtkWidget *ygtk_text_view_new (gboolean editable)
107 { return g_object_new (YGTK_TYPE_TEXT_VIEW, "editable", editable, NULL); }
108 
109 static void ygtk_text_view_class_init (YGtkTextViewClass *klass)
110 {
111  GtkTextViewClass *gtktextview_class = GTK_TEXT_VIEW_CLASS (klass);
112  gtktextview_class->populate_popup = ygtk_text_view_populate_popup;
113 
114  GtkWidgetClass *gtkwidget_class = GTK_WIDGET_CLASS (klass);
115  gtkwidget_class->realize = ygtk_text_view_realize;
116  gtkwidget_class->button_press_event = ygtk_text_view_button_press_event;
117 }
118