libyui-gtk  2.42.2
 All Classes
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 static void ygtk_text_view_populate_popup (GtkTextView *view, GtkMenu *menu)
43 {
44  if (gtk_text_view_get_editable (view))
45  return;
46  GtkTextBuffer *buffer = gtk_text_view_get_buffer (view);
47 
48  GList *items = gtk_container_get_children (GTK_CONTAINER (menu)), *i;
49  for (i = items; i; i = i->next)
50  gtk_container_remove (GTK_CONTAINER (menu), i->data);
51  g_list_free (items);
52 
53  GtkWidget *item;
54  item = gtk_image_menu_item_new_from_stock (GTK_STOCK_COPY, NULL);
55  gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
56  if (gtk_text_buffer_get_has_selection (buffer))
57  g_signal_connect (item, "activate", G_CALLBACK (copy_activate_cb), buffer);
58  else
59  gtk_widget_set_sensitive (item, FALSE);
60  item = gtk_separator_menu_item_new();
61  gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
62  item = gtk_image_menu_item_new_from_stock (GTK_STOCK_SELECT_ALL, NULL);
63  gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
64  g_signal_connect (item, "activate", G_CALLBACK (select_all_activate_cb), buffer);
65  gtk_widget_show_all (GTK_WIDGET (menu));
66 }
67 
68 static inline gboolean is_space (gunichar ch)
69 { return g_unichar_isspace (ch) || ch == 0xfffc; }
70 
71 static gboolean ygtk_text_view_button_press_event (GtkWidget *widget, GdkEventButton *event)
72 { // on right-click, select word under cursor if there is no selection
73  if (event->button == 3) {
74  GtkTextView *view = GTK_TEXT_VIEW (widget);
75  GtkTextBuffer *buffer = gtk_text_view_get_buffer (view);
76  if (!gtk_text_buffer_get_has_selection (buffer)) {
77  gint buffer_x, buffer_y;
78  gtk_text_view_window_to_buffer_coords (view,
79  GTK_TEXT_WINDOW_WIDGET, (gint) event->x, (gint) event->y, &buffer_x, &buffer_y);
80  GtkTextIter iter;
81  gtk_text_view_get_iter_at_location (view, &iter, buffer_x, buffer_y);
82 
83  if (!is_space (gtk_text_iter_get_char (&iter))) {
84  GtkTextIter start, end = iter, temp = iter;
85  do {
86  start = temp;
87  if (!gtk_text_iter_backward_char (&temp))
88  break;
89  } while (!is_space (gtk_text_iter_get_char (&temp)));
90  do {
91  if (!gtk_text_iter_forward_char (&end))
92  break;
93  } while (!is_space (gtk_text_iter_get_char (&end)));
94 
95  gtk_text_buffer_select_range (buffer, &start, &end);
96  }
97  }
98  }
99  return GTK_WIDGET_CLASS (ygtk_text_view_parent_class)->button_press_event (widget, event);
100 }
101 
102 GtkWidget *ygtk_text_view_new (gboolean editable)
103 { return g_object_new (YGTK_TYPE_TEXT_VIEW, "editable", editable, NULL); }
104 
105 static void ygtk_text_view_class_init (YGtkTextViewClass *klass)
106 {
107  GtkTextViewClass *gtktextview_class = GTK_TEXT_VIEW_CLASS (klass);
108  gtktextview_class->populate_popup = ygtk_text_view_populate_popup;
109 
110  GtkWidgetClass *gtkwidget_class = GTK_WIDGET_CLASS (klass);
111  gtkwidget_class->realize = ygtk_text_view_realize;
112  gtkwidget_class->button_press_event = ygtk_text_view_button_press_event;
113 }
114