#include <glib/gi18n-lib.h>
-#include <string.h>
-#include <gtk/gtk.h>
+#include <gtk/gtkwidget.h>
-#include "modest-recpt-view.h"
+#include <modest-text-utils.h>
+#include <modest-recpt-view.h>
+
+#define RECPT_VIEW_CLICK_AREA_THRESHOLD 32
static GObjectClass *parent_class = NULL;
static guint signals[LAST_SIGNAL] = {0};
+/* static functions: GObject */
+static void modest_recpt_view_instance_init (GTypeInstance *instance, gpointer g_class);
+static void modest_recpt_view_finalize (GObject *object);
+static void modest_recpt_view_class_init (ModestRecptViewClass *klass);
+/* static functions: GtkWidget */
+static gint button_press_event (GtkWidget *widget, GdkEventButton *event, gpointer user_data);
+static gint button_release_event (GtkWidget *widget, GdkEventButton *event, gpointer user_data);
+
/**
* modest_recpt_view_new:
*
return GTK_WIDGET (self);
}
-static void
-address_bounds_at_position (const gchar *recipients_list, gint position, gint *start, gint *end)
+void
+modest_recpt_view_set_recipients (ModestRecptView *recpt_view, const gchar *recipients)
{
- gchar *current = NULL;
- gint range_start = 0;
- gint range_end = 0;
- gint index;
- gboolean is_quoted = FALSE;
-
- index = 0;
- for (current = (gchar *) recipients_list; *current != '\0'; current = g_utf8_find_next_char (current, NULL)) {
- gunichar c = g_utf8_get_char (current);
-
- if ((c == ',') && (!is_quoted)) {
- if (index < position) {
- range_start = index + 1;
- } else {
- break;
- }
- } else if (c == '\"') {
- is_quoted = !is_quoted;
- } else if ((c == ' ') &&(range_start == index)) {
- range_start ++;
- }
- index ++;
- range_end = index;
- }
+ const GtkWidget *text_view = NULL;
+ GtkTextBuffer *buffer = NULL;
+
+ text_view = modest_scroll_text_get_text_view (MODEST_SCROLL_TEXT (recpt_view));
+ buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (text_view));
+
+ gtk_text_buffer_set_text (buffer, recipients, -1);
+ if (GTK_WIDGET_REALIZED (recpt_view))
+ gtk_widget_queue_resize (GTK_WIDGET (recpt_view));
- if (start)
- *start = range_start;
- if (end)
- *end = range_end;
}
-static gboolean
+static gint
button_press_event (GtkWidget *widget,
GdkEventButton *event,
gpointer user_data)
{
- ModestRecptViewPriv *priv = MODEST_RECPT_VIEW_GET_PRIVATE (MODEST_RECPT_VIEW (widget));
+ ModestRecptViewPriv *priv = MODEST_RECPT_VIEW_GET_PRIVATE (MODEST_RECPT_VIEW (user_data));
- if (!gtk_label_get_selectable (GTK_LABEL (widget)))
- return FALSE;
-
- if (event->type == GDK_BUTTON_PRESS) {
+ if (event->type == GDK_BUTTON_PRESS && event->button == 1) {
priv->button_pressed = TRUE;
priv->pressed_x = event->x;
priv->pressed_y = event->y;
}
- return FALSE;
+ return TRUE;
}
-static gboolean
+static gint
button_release_event (GtkWidget *widget,
- GdkEventButton *event,
- gpointer user_data)
+ GdkEventButton *event,
+ gpointer user_data)
{
- ModestRecptViewPriv *priv = MODEST_RECPT_VIEW_GET_PRIVATE (MODEST_RECPT_VIEW (widget));
+ ModestRecptViewPriv *priv = MODEST_RECPT_VIEW_GET_PRIVATE (MODEST_RECPT_VIEW (user_data));
+ const GtkWidget *text_view = NULL;
- if (!gtk_label_get_selectable (GTK_LABEL (widget)))
- return TRUE;
+ text_view = modest_scroll_text_get_text_view (MODEST_SCROLL_TEXT (user_data));
if (event->type != GDK_BUTTON_RELEASE)
return TRUE;
if ((priv->button_pressed) &&
- (event->type == GDK_BUTTON_RELEASE) &&
- (priv->pressed_x == event->x) &&
- (priv->pressed_y == event->y)) {
+ (event->type == GDK_BUTTON_RELEASE) &&
+ ((event->x >= priv->pressed_x - RECPT_VIEW_CLICK_AREA_THRESHOLD)&&
+ (event->x <= priv->pressed_x + RECPT_VIEW_CLICK_AREA_THRESHOLD)) &&
+ ((event->y >= priv->pressed_y - RECPT_VIEW_CLICK_AREA_THRESHOLD)&&
+ (event->y <= priv->pressed_y + RECPT_VIEW_CLICK_AREA_THRESHOLD))) {
priv->button_pressed = FALSE;
if (event->button == 1) {
- PangoLayout *layout = NULL;
+ gint buffer_x, buffer_y;
int index;
- layout = gtk_label_get_layout (GTK_LABEL (widget));
- if (pango_layout_xy_to_index (layout, event->x*PANGO_SCALE, event->y*PANGO_SCALE, &index, NULL)) {
- int selection_start, selection_end;
+ GtkTextIter iter;
+ gtk_widget_grab_focus (GTK_WIDGET (text_view));
+ gtk_text_view_window_to_buffer_coords (GTK_TEXT_VIEW (text_view), GTK_TEXT_WINDOW_WIDGET,
+ event->x, event->y, &buffer_x, &buffer_y);
+ gtk_text_view_get_iter_at_location (GTK_TEXT_VIEW (text_view), &iter, buffer_x, buffer_y);
+ index = gtk_text_iter_get_offset (&iter);
+
+ if (!gtk_text_iter_is_end (&iter)) {
+ guint selection_start, selection_end;
gboolean selected = FALSE;
- if (gtk_label_get_selection_bounds (GTK_LABEL (widget),
- &selection_start,
- &selection_end) &&
- (index >= selection_start)&&(index < selection_end)) {
+ GtkTextIter start_iter, end_iter;
+ GtkTextBuffer *buffer;
+
+ buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (text_view));
+ if (gtk_text_buffer_get_selection_bounds (buffer, &start_iter, &end_iter) &&
+ gtk_text_iter_in_range (&iter, &start_iter, &end_iter)) {
selected = TRUE;
+ } else {
+ gchar *text = NULL;
+ GtkTextIter start_iter, end_iter;
+
+ gtk_text_buffer_get_start_iter (buffer, &start_iter);
+ gtk_text_buffer_get_end_iter (buffer, &end_iter);
+ text = gtk_text_buffer_get_text (buffer, &start_iter, &end_iter, FALSE);
+
+ /* text will not be NULL, but source code checkers should be satisfied */
+ if (text) {
+ modest_text_utils_address_range_at_position (text,
+ index,
+ &selection_start, &selection_end);
+ /* TODO: now gtk label tries to select more than the label as usual,
+ * and we force it to recover the selected region for the defined area.
+ * It should be fixed (maybe preventing gtklabel to manage selections
+ * in parallel with us
+ */
+ gtk_text_buffer_get_iter_at_offset (buffer, &start_iter, selection_start);
+ gtk_text_buffer_get_iter_at_offset (buffer, &end_iter, selection_end);
+ gtk_text_buffer_select_range (buffer, &start_iter, &end_iter);
+
+ g_free (text);
+ }
}
-
- address_bounds_at_position (gtk_label_get_text (GTK_LABEL (widget)),
- index,
- &selection_start, &selection_end);
- /* TODO: now gtk label tries to select more than the label as usual,
- * and we force it to recover the selected region for the defined area.
- * It should be fixed (maybe preventing gtklabel to manage selections
- * in parallel with us
- */
- gtk_label_select_region (GTK_LABEL (widget),
- selection_start,
- selection_end);
- if (selected)
- g_signal_emit (G_OBJECT (widget), signals[ACTIVATE_SIGNAL], 0);
+ if (selected) {
+ gchar *selection;
+
+ gtk_text_buffer_get_selection_bounds (buffer, &start_iter, &end_iter);
+ selection = gtk_text_buffer_get_text (buffer, &start_iter, &end_iter, FALSE);
+ g_signal_emit (G_OBJECT (user_data), signals[ACTIVATE_SIGNAL], 0, selection);
+ g_free (selection);
+ }
- return TRUE;
}
+ return TRUE;
}
}
priv->button_pressed = FALSE;
static void
modest_recpt_view_instance_init (GTypeInstance *instance, gpointer g_class)
{
+ const GtkTextView *text_view = NULL;
- gtk_label_set_justify (GTK_LABEL (instance), GTK_JUSTIFY_LEFT);
- gtk_label_set_line_wrap (GTK_LABEL (instance), TRUE);
- gtk_label_set_selectable (GTK_LABEL (instance), TRUE);
+ text_view = GTK_TEXT_VIEW(modest_scroll_text_get_text_view (MODEST_SCROLL_TEXT (instance)));
- g_signal_connect (G_OBJECT (instance), "button-press-event", G_CALLBACK(button_press_event), NULL);
- g_signal_connect (G_OBJECT (instance), "button-release-event", G_CALLBACK(button_release_event), NULL);
+ g_signal_connect (G_OBJECT (text_view), "button-press-event", G_CALLBACK (button_press_event), instance);
+ g_signal_connect_after (G_OBJECT (text_view), "button-release-event", G_CALLBACK (button_release_event), instance);
return;
}
modest_recpt_view_class_init (ModestRecptViewClass *klass)
{
GObjectClass *object_class;
+ GtkWidgetClass *widget_class;
parent_class = g_type_class_peek_parent (klass);
object_class = (GObjectClass*) klass;
+ widget_class = GTK_WIDGET_CLASS (klass);
object_class->finalize = modest_recpt_view_finalize;
G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
G_STRUCT_OFFSET(ModestRecptViewClass, activate),
NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
+ g_cclosure_marshal_VOID__STRING,
+ G_TYPE_NONE, 1, G_TYPE_STRING);
return;
}
modest_recpt_view_instance_init /* instance_init */
};
- type = g_type_register_static (GTK_TYPE_LABEL,
+ type = g_type_register_static (MODEST_TYPE_SCROLL_TEXT,
"ModestRecptView",
&info, 0);