Commit e26259dd authored by Matthias Clasen's avatar Matthias Clasen
Browse files

Add DND support to GtkCalendar. The selected date is dragged as text,

	* gtk/gtkcalendar.c: Add DND support to GtkCalendar. The selected date is dragged
	as text, formatted via strftime %x. Text drops are accepted if g_date_set_parse()
	can make sense of the text. A dedicated data format for date DND has not been
	introduced yet, since there didn't seem to be sufficient consensus on such a format
	on xdg-list.  (#117297)
parent 6e1e7d30
...@@ -12,6 +12,12 @@ ...@@ -12,6 +12,12 @@
the locale using another instance of the "magic translated string" technique. the locale using another instance of the "magic translated string" technique.
Ignore the display option GTK_CALENDAR_WEEK_START_MONDAY with a warning. (#87977) Ignore the display option GTK_CALENDAR_WEEK_START_MONDAY with a warning. (#87977)
* gtk/gtkcalendar.c: Add DND support to GtkCalendar. The selected date is dragged
as text, formatted via strftime %x. Text drops are accepted if g_date_set_parse()
can make sense of the text. A dedicated data format for date DND has not been
introduced yet, since there didn't seem to be sufficient consensus on such a format
on xdg-list. (#117297)
2003-08-08 Matthias Clasen <maclas@gmx.de> 2003-08-08 Matthias Clasen <maclas@gmx.de>
* gdk/gdkregion-generic.c (gdk_region_spans_intersect_foreach): Fix * gdk/gdkregion-generic.c (gdk_region_spans_intersect_foreach): Fix
......
...@@ -12,6 +12,12 @@ ...@@ -12,6 +12,12 @@
the locale using another instance of the "magic translated string" technique. the locale using another instance of the "magic translated string" technique.
Ignore the display option GTK_CALENDAR_WEEK_START_MONDAY with a warning. (#87977) Ignore the display option GTK_CALENDAR_WEEK_START_MONDAY with a warning. (#87977)
* gtk/gtkcalendar.c: Add DND support to GtkCalendar. The selected date is dragged
as text, formatted via strftime %x. Text drops are accepted if g_date_set_parse()
can make sense of the text. A dedicated data format for date DND has not been
introduced yet, since there didn't seem to be sufficient consensus on such a format
on xdg-list. (#117297)
2003-08-08 Matthias Clasen <maclas@gmx.de> 2003-08-08 Matthias Clasen <maclas@gmx.de>
* gdk/gdkregion-generic.c (gdk_region_spans_intersect_foreach): Fix * gdk/gdkregion-generic.c (gdk_region_spans_intersect_foreach): Fix
......
...@@ -12,6 +12,12 @@ ...@@ -12,6 +12,12 @@
the locale using another instance of the "magic translated string" technique. the locale using another instance of the "magic translated string" technique.
Ignore the display option GTK_CALENDAR_WEEK_START_MONDAY with a warning. (#87977) Ignore the display option GTK_CALENDAR_WEEK_START_MONDAY with a warning. (#87977)
* gtk/gtkcalendar.c: Add DND support to GtkCalendar. The selected date is dragged
as text, formatted via strftime %x. Text drops are accepted if g_date_set_parse()
can make sense of the text. A dedicated data format for date DND has not been
introduced yet, since there didn't seem to be sufficient consensus on such a format
on xdg-list. (#117297)
2003-08-08 Matthias Clasen <maclas@gmx.de> 2003-08-08 Matthias Clasen <maclas@gmx.de>
* gdk/gdkregion-generic.c (gdk_region_spans_intersect_foreach): Fix * gdk/gdkregion-generic.c (gdk_region_spans_intersect_foreach): Fix
......
...@@ -12,6 +12,12 @@ ...@@ -12,6 +12,12 @@
the locale using another instance of the "magic translated string" technique. the locale using another instance of the "magic translated string" technique.
Ignore the display option GTK_CALENDAR_WEEK_START_MONDAY with a warning. (#87977) Ignore the display option GTK_CALENDAR_WEEK_START_MONDAY with a warning. (#87977)
* gtk/gtkcalendar.c: Add DND support to GtkCalendar. The selected date is dragged
as text, formatted via strftime %x. Text drops are accepted if g_date_set_parse()
can make sense of the text. A dedicated data format for date DND has not been
introduced yet, since there didn't seem to be sufficient consensus on such a format
on xdg-list. (#117297)
2003-08-08 Matthias Clasen <maclas@gmx.de> 2003-08-08 Matthias Clasen <maclas@gmx.de>
* gdk/gdkregion-generic.c (gdk_region_spans_intersect_foreach): Fix * gdk/gdkregion-generic.c (gdk_region_spans_intersect_foreach): Fix
......
...@@ -12,6 +12,12 @@ ...@@ -12,6 +12,12 @@
the locale using another instance of the "magic translated string" technique. the locale using another instance of the "magic translated string" technique.
Ignore the display option GTK_CALENDAR_WEEK_START_MONDAY with a warning. (#87977) Ignore the display option GTK_CALENDAR_WEEK_START_MONDAY with a warning. (#87977)
* gtk/gtkcalendar.c: Add DND support to GtkCalendar. The selected date is dragged
as text, formatted via strftime %x. Text drops are accepted if g_date_set_parse()
can make sense of the text. A dedicated data format for date DND has not been
introduced yet, since there didn't seem to be sufficient consensus on such a format
on xdg-list. (#117297)
2003-08-08 Matthias Clasen <maclas@gmx.de> 2003-08-08 Matthias Clasen <maclas@gmx.de>
* gdk/gdkregion-generic.c (gdk_region_spans_intersect_foreach): Fix * gdk/gdkregion-generic.c (gdk_region_spans_intersect_foreach): Fix
......
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
#include <glib/gprintf.h> #include <glib/gprintf.h>
#include "gtkcalendar.h" #include "gtkcalendar.h"
#include "gtkdnd.h"
#include "gtkintl.h" #include "gtkintl.h"
#include "gtkmain.h" #include "gtkmain.h"
#include "gtkmarshalers.h" #include "gtkmarshalers.h"
...@@ -273,10 +274,16 @@ struct _GtkCalendarPrivateData ...@@ -273,10 +274,16 @@ struct _GtkCalendarPrivateData
guint need_timer : 1; guint need_timer : 1;
guint in_drag : 1;
guint drag_highlight : 1;
guint32 timer; guint32 timer;
gint click_child; gint click_child;
gint week_start; gint week_start;
gint drag_start_x;
gint drag_start_y;
}; };
#define GTK_CALENDAR_PRIVATE_DATA(widget) (((GtkCalendarPrivateData*)(GTK_CALENDAR (widget)->private_data))) #define GTK_CALENDAR_PRIVATE_DATA(widget) (((GtkCalendarPrivateData*)(GTK_CALENDAR (widget)->private_data)))
...@@ -346,6 +353,32 @@ static gint left_x_for_column (GtkCalendar *calendar, ...@@ -346,6 +353,32 @@ static gint left_x_for_column (GtkCalendar *calendar,
static gint top_y_for_row (GtkCalendar *calendar, static gint top_y_for_row (GtkCalendar *calendar,
gint row); gint row);
static void gtk_calendar_drag_data_get (GtkWidget *widget,
GdkDragContext *context,
GtkSelectionData *selection_data,
guint info,
guint time);
static void gtk_calendar_drag_data_received (GtkWidget *widget,
GdkDragContext *context,
gint x,
gint y,
GtkSelectionData *selection_data,
guint info,
guint time);
static gboolean gtk_calendar_drag_motion (GtkWidget *widget,
GdkDragContext *context,
gint x,
gint y,
guint time);
static void gtk_calendar_drag_leave (GtkWidget *widget,
GdkDragContext *context,
guint time);
static gboolean gtk_calendar_drag_drop (GtkWidget *widget,
GdkDragContext *context,
gint x,
gint y,
guint time);
static char *default_abbreviated_dayname[7]; static char *default_abbreviated_dayname[7];
static char *default_monthname[12]; static char *default_monthname[12];
...@@ -411,6 +444,12 @@ gtk_calendar_class_init (GtkCalendarClass *class) ...@@ -411,6 +444,12 @@ gtk_calendar_class_init (GtkCalendarClass *class)
widget_class->state_changed = gtk_calendar_state_changed; widget_class->state_changed = gtk_calendar_state_changed;
widget_class->grab_notify = gtk_calendar_grab_notify; widget_class->grab_notify = gtk_calendar_grab_notify;
widget_class->drag_data_get = gtk_calendar_drag_data_get;
widget_class->drag_motion = gtk_calendar_drag_motion;
widget_class->drag_leave = gtk_calendar_drag_leave;
widget_class->drag_drop = gtk_calendar_drag_drop;
widget_class->drag_data_received = gtk_calendar_drag_data_received;
class->month_changed = NULL; class->month_changed = NULL;
class->day_selected = NULL; class->day_selected = NULL;
class->day_selected_double_click = NULL; class->day_selected_double_click = NULL;
...@@ -558,6 +597,17 @@ gtk_calendar_class_init (GtkCalendarClass *class) ...@@ -558,6 +597,17 @@ gtk_calendar_class_init (GtkCalendarClass *class)
G_TYPE_NONE, 0); G_TYPE_NONE, 0);
} }
enum
{
TARGET_TEXT,
};
static const GtkTargetEntry target_table[] = {
{ "TEXT", 0, TARGET_TEXT },
{ "STRING", 0, TARGET_TEXT },
{ "UTF8_STRING", 0, TARGET_TEXT },
};
static void static void
gtk_calendar_init (GtkCalendar *calendar) gtk_calendar_init (GtkCalendar *calendar)
{ {
...@@ -637,6 +687,14 @@ gtk_calendar_init (GtkCalendar *calendar) ...@@ -637,6 +687,14 @@ gtk_calendar_init (GtkCalendar *calendar)
private_data->timer = 0; private_data->timer = 0;
private_data->click_child = -1; private_data->click_child = -1;
private_data->in_drag = 0;
private_data->drag_highlight = 0;
gtk_drag_dest_set (widget,
0,
target_table, G_N_ELEMENTS (target_table),
GDK_ACTION_COPY);
private_data->year_before = 0; private_data->year_before = 0;
/* Translate to calendar:YM if you want years to be displayed /* Translate to calendar:YM if you want years to be displayed
...@@ -968,12 +1026,14 @@ gtk_calendar_main_button (GtkWidget *widget, ...@@ -968,12 +1026,14 @@ gtk_calendar_main_button (GtkWidget *widget,
GdkEventButton *event) GdkEventButton *event)
{ {
GtkCalendar *calendar; GtkCalendar *calendar;
GtkCalendarPrivateData *private_data;
gint x, y; gint x, y;
gint row, col; gint row, col;
gint day_month; gint day_month;
gint day; gint day;
calendar = GTK_CALENDAR (widget); calendar = GTK_CALENDAR (widget);
private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
x = (gint) (event->x); x = (gint) (event->x);
y = (gint) (event->y); y = (gint) (event->y);
...@@ -1001,9 +1061,13 @@ gtk_calendar_main_button (GtkWidget *widget, ...@@ -1001,9 +1061,13 @@ gtk_calendar_main_button (GtkWidget *widget,
gtk_calendar_select_and_focus_day (calendar, day); gtk_calendar_select_and_focus_day (calendar, day);
private_data->in_drag = 1;
private_data->drag_start_x = x;
private_data->drag_start_y = y;
} }
else if (event->type == GDK_2BUTTON_PRESS) else if (event->type == GDK_2BUTTON_PRESS)
{ {
private_data->in_drag = 0;
if (day_month == MONTH_CURRENT) if (day_month == MONTH_CURRENT)
g_signal_emit (calendar, g_signal_emit (calendar,
gtk_calendar_signals[DAY_SELECTED_DOUBLE_CLICK_SIGNAL], gtk_calendar_signals[DAY_SELECTED_DOUBLE_CLICK_SIGNAL],
...@@ -2741,9 +2805,20 @@ static gboolean ...@@ -2741,9 +2805,20 @@ static gboolean
gtk_calendar_button_release (GtkWidget *widget, gtk_calendar_button_release (GtkWidget *widget,
GdkEventButton *event) GdkEventButton *event)
{ {
GtkCalendar *calendar;
GtkCalendarPrivateData *private_data;
calendar = GTK_CALENDAR (widget);
private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
if (event->button == 1) if (event->button == 1)
{
stop_spinning (widget); stop_spinning (widget);
if (private_data->in_drag)
private_data->in_drag = 0;
}
return TRUE; return TRUE;
} }
...@@ -2765,6 +2840,26 @@ gtk_calendar_motion_notify (GtkWidget *widget, ...@@ -2765,6 +2840,26 @@ gtk_calendar_motion_notify (GtkWidget *widget,
if (event->window == private_data->main_win) if (event->window == private_data->main_win)
{ {
if (private_data->in_drag)
{
if (gtk_drag_check_threshold (widget,
private_data->drag_start_x, private_data->drag_start_y,
event->x, event->y))
{
GdkDragContext *context;
GtkTargetList *target_list = gtk_target_list_new (target_table, G_N_ELEMENTS (target_table));
context = gtk_drag_begin (widget, target_list, GDK_ACTION_COPY,
1, (GdkEvent *)event);
private_data->in_drag = 0;
gtk_target_list_unref (target_list);
gtk_drag_set_icon_default (context);
}
}
else
{
row = row_from_y (calendar, event_y); row = row_from_y (calendar, event_y);
col = column_from_x (calendar, event_x); col = column_from_x (calendar, event_x);
...@@ -2786,6 +2881,7 @@ gtk_calendar_motion_notify (GtkWidget *widget, ...@@ -2786,6 +2881,7 @@ gtk_calendar_motion_notify (GtkWidget *widget,
gtk_calendar_paint_day (widget, row, col); gtk_calendar_paint_day (widget, row, col);
} }
} }
}
return TRUE; return TRUE;
} }
...@@ -3287,3 +3383,181 @@ gtk_calendar_get_property (GObject *object, ...@@ -3287,3 +3383,181 @@ gtk_calendar_get_property (GObject *object,
} }
} }
static void
gtk_calendar_drag_data_get (GtkWidget *widget,
GdkDragContext *context,
GtkSelectionData *selection_data,
guint info,
guint time)
{
GtkCalendar *calendar = GTK_CALENDAR (widget);
GDate *date;
gchar str[128];
gsize len;
date = g_date_new_dmy (calendar->selected_day, calendar->month, calendar->year);
len = g_date_strftime (str, 127, "%x", date);
gtk_selection_data_set_text (selection_data, str, len);
g_free (date);
}
/* Get/set whether drag_motion requested the drag data and
* drag_data_received should thus not actually insert the data,
* since the data doesn't result from a drop.
*/
static void
set_status_pending (GdkDragContext *context,
GdkDragAction suggested_action)
{
g_object_set_data (G_OBJECT (context),
"gtk-calendar-status-pending",
GINT_TO_POINTER (suggested_action));
}
static GdkDragAction
get_status_pending (GdkDragContext *context)
{
return GPOINTER_TO_INT (g_object_get_data (G_OBJECT (context),
"gtk-calendar-status-pending"));
}
static void
gtk_calendar_drag_leave (GtkWidget *widget,
GdkDragContext *context,
guint time)
{
GtkCalendarPrivateData *private_data;
private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
private_data->drag_highlight = 0;
gtk_drag_unhighlight (widget);
}
static gboolean
gtk_calendar_drag_motion (GtkWidget *widget,
GdkDragContext *context,
gint x,
gint y,
guint time)
{
GtkCalendarPrivateData *private_data;
GdkAtom target;
private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
if (!private_data->drag_highlight)
{
private_data->drag_highlight = 1;
gtk_drag_highlight (widget);
}
target = gtk_drag_dest_find_target (widget, context, NULL);
if (target == GDK_NONE)
gdk_drag_status (context, 0, time);
else {
set_status_pending (context, context->suggested_action);
gtk_drag_get_data (widget, context, target, time);
}
return TRUE;
}
static gboolean
gtk_calendar_drag_drop (GtkWidget *widget,
GdkDragContext *context,
gint x,
gint y,
guint time)
{
GdkAtom target;
target = gtk_drag_dest_find_target (widget, context, NULL);
if (target != GDK_NONE)
{
gtk_drag_get_data (widget, context,
target,
time);
return TRUE;
}
return FALSE;
}
static void
gtk_calendar_drag_data_received (GtkWidget *widget,
GdkDragContext *context,
gint x,
gint y,
GtkSelectionData *selection_data,
guint info,
guint time)
{
GtkCalendar *calendar = GTK_CALENDAR (widget);
guint day, month, year;
gchar *str;
GDate *date;
GdkDragAction suggested_action;
suggested_action = get_status_pending (context);
if (suggested_action)
{
set_status_pending (context, 0);
/* We are getting this data due to a request in drag_motion,
* rather than due to a request in drag_drop, so we are just
* supposed to call drag_status, not actually paste in the
* data.
*/
str = gtk_selection_data_get_text (selection_data);
if (str)
{
date = g_date_new ();
g_date_set_parse (date, str);
if (!g_date_valid (date))
suggested_action = 0;
g_date_free (date);
g_free (str);
}
else
suggested_action = 0;
gdk_drag_status (context, suggested_action, time);
return;
}
date = g_date_new ();
str = gtk_selection_data_get_text (selection_data);
if (str)
{
g_date_set_parse (date, str);
g_free (str);
}
if (!g_date_valid (date))
{
g_warning ("Received invalid date data\n");
g_date_free (date);
gtk_drag_finish (context, FALSE, FALSE, time);
return;
}
day = g_date_get_day (date);
month = g_date_get_month (date);
year = g_date_get_year (date);
g_date_free (date);
gtk_drag_finish (context, TRUE, FALSE, time);
g_object_freeze_notify (G_OBJECT (calendar));
if (!(calendar->display_flags & GTK_CALENDAR_NO_MONTH_CHANGE)
&& (calendar->display_flags & GTK_CALENDAR_SHOW_HEADING))
gtk_calendar_select_month (calendar, month, year);
gtk_calendar_select_day (calendar, day);
g_object_thaw_notify (G_OBJECT (calendar));
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment