diff options
Diffstat (limited to 'liblogdiag/ld-diagram-view.c')
| -rw-r--r-- | liblogdiag/ld-diagram-view.c | 138 | 
1 files changed, 138 insertions, 0 deletions
| diff --git a/liblogdiag/ld-diagram-view.c b/liblogdiag/ld-diagram-view.c index 1d2764c..55a60c0 100644 --- a/liblogdiag/ld-diagram-view.c +++ b/liblogdiag/ld-diagram-view.c @@ -129,6 +129,9 @@ Color;   * @y: the Y coordinate of the center of view.   * @zoom: the current zoom.   * @show_grid: whether to show the grid. + * @dnd_symbol: currently dragged symbol. + * @dnd_last_position: last cursor movement position. + * @dnd_left: whether the user has stopped dragging.   * @terminal: position of the highlighted terminal.   * @terminal_hovered: whether a terminal is hovered.   * @drag_start_pos: position of the mouse pointer when dragging started. @@ -152,6 +155,10 @@ struct _LdDiagramViewPrivate  	gboolean show_grid; +	LdDiagramObject *dnd_symbol; +	LdPoint dnd_last_position; +	guint dnd_left : 1; +  	LdPoint terminal;  	gboolean terminal_hovered; @@ -343,6 +350,16 @@ static gboolean on_button_release (GtkWidget *widget, GdkEventButton *event,  static gboolean on_scroll (GtkWidget *widget, GdkEventScroll *event,  	gpointer user_data); +static gboolean on_drag_motion (GtkWidget *widget, GdkDragContext *drag_ctx, +	gint x, gint y, guint time, gpointer user_data); +static gboolean on_drag_drop (GtkWidget *widget, GdkDragContext *drag_ctx, +	gint x, gint y, guint time, gpointer user_data); +static void on_drag_data_received (GtkWidget *widget, GdkDragContext *drag_ctx, +	gint x, gint y, GtkSelectionData *data, guint info, +	guint time, gpointer user_data); +static void on_drag_leave (GtkWidget *widget, GdkDragContext *drag_ctx, +	guint time, gpointer user_data); +  static gboolean on_expose_event (GtkWidget *widget, GdkEventExpose *event,  	gpointer user_data);  static void draw_grid (GtkWidget *widget, DrawData *data); @@ -486,6 +503,8 @@ ld_diagram_view_class_init (LdDiagramViewClass *klass)  static void  ld_diagram_view_init (LdDiagramView *self)  { +	GtkTargetEntry target = {"ld-symbol", GTK_TARGET_SAME_APP, 0}; +  	self->priv = G_TYPE_INSTANCE_GET_PRIVATE  		(self, LD_TYPE_DIAGRAM_VIEW, LdDiagramViewPrivate); @@ -517,12 +536,23 @@ ld_diagram_view_init (LdDiagramView *self)  	g_signal_connect (self, "scroll-event",  		G_CALLBACK (on_scroll), NULL); +	g_signal_connect (self, "drag-motion", +		G_CALLBACK (on_drag_motion), NULL); +	g_signal_connect (self, "drag-leave", +		G_CALLBACK (on_drag_leave), NULL); +	g_signal_connect (self, "drag-drop", +		G_CALLBACK (on_drag_drop), NULL); +	g_signal_connect (self, "drag-data-received", +		G_CALLBACK (on_drag_data_received), NULL); +  	g_object_set (self, "can-focus", TRUE, NULL);  	gtk_widget_add_events (GTK_WIDGET (self),  		GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK  		| GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK  		| GDK_LEAVE_NOTIFY_MASK); + +	gtk_drag_dest_set (GTK_WIDGET (self), 0, &target, 1, GDK_ACTION_COPY);  }  static void @@ -541,6 +571,8 @@ ld_diagram_view_finalize (GObject *gobject)  	}  	if (self->priv->library)  		g_object_unref (self->priv->library); +	if (self->priv->dnd_symbol) +		g_object_unref (self->priv->dnd_symbol);  	/* Chain up to the parent class. */  	G_OBJECT_CLASS (ld_diagram_view_parent_class)->finalize (gobject); @@ -2425,6 +2457,109 @@ on_scroll (GtkWidget *widget, GdkEventScroll *event, gpointer user_data)  }  static gboolean +on_drag_motion (GtkWidget *widget, GdkDragContext *drag_ctx, +	gint x, gint y, guint time, gpointer user_data) +{ +	LdDiagramView *self; +	GdkAtom target; + +	self = LD_DIAGRAM_VIEW (widget); +	target = gtk_drag_dest_find_target (widget, drag_ctx, NULL); +	if (target == GDK_NONE) +	{ +		gdk_drag_status (drag_ctx, 0, time); +		return TRUE; +	} + +	gdk_drag_status (drag_ctx, +		gdk_drag_context_get_suggested_action (drag_ctx), time); + +	/* Discard leftovers from any previous unsuccessful drag. */ +	if (self->priv->dnd_left) +	{ +		g_object_unref (self->priv->dnd_symbol); +		self->priv->dnd_symbol = NULL; +		self->priv->dnd_left = FALSE; +	} + +	self->priv->dnd_last_position.x = x; +	self->priv->dnd_last_position.y = y; + +	if (!self->priv->dnd_symbol) +		gtk_drag_get_data (widget, drag_ctx, target, time); +	else +	{ +		queue_object_draw (self, self->priv->dnd_symbol); +		move_object_to_point (self, self->priv->dnd_symbol, +			&self->priv->dnd_last_position); +		queue_object_draw (self, self->priv->dnd_symbol); +	} + +	return TRUE; +} + +static void +on_drag_data_received (GtkWidget *widget, GdkDragContext *drag_ctx, +	gint x, gint y, GtkSelectionData *data, guint info, guint time, +	gpointer user_data) +{ +	LdDiagramView *self; +	LdDiagramSymbol *symbol; +	const gchar *klass; + +	self = LD_DIAGRAM_VIEW (widget); + +	g_return_if_fail (gtk_selection_data_get_length (data) >= 0); +	g_return_if_fail (self->priv->dnd_symbol == NULL); + +	klass = (const gchar *) gtk_selection_data_get_data (data); +	symbol = ld_diagram_symbol_new (NULL); +	ld_diagram_symbol_set_class (symbol, klass); +	self->priv->dnd_symbol = LD_DIAGRAM_OBJECT (symbol); + +	move_object_to_point (self, self->priv->dnd_symbol, +		&self->priv->dnd_last_position); +	queue_object_draw (self, self->priv->dnd_symbol); +} + +static void +on_drag_leave (GtkWidget *widget, GdkDragContext *drag_ctx, +	guint time, gpointer user_data) +{ +	LdDiagramView *self; + +	self = LD_DIAGRAM_VIEW (widget); +	self->priv->dnd_left = TRUE; +	queue_object_draw (self, self->priv->dnd_symbol); +} + +static gboolean +on_drag_drop (GtkWidget *widget, GdkDragContext *drag_ctx, +	gint x, gint y, guint time, gpointer user_data) +{ +	LdDiagramView *self; +	gboolean del; + +	del = gdk_drag_context_get_suggested_action (drag_ctx) +		== GDK_ACTION_MOVE; + +	self = LD_DIAGRAM_VIEW (widget); +	if (!self->priv->dnd_symbol) +		gtk_drag_finish (drag_ctx, FALSE, del, time); +	else +	{ +		gtk_drag_finish (drag_ctx, TRUE,  del, time); + +		ld_diagram_insert_object (self->priv->diagram, +			self->priv->dnd_symbol, -1); +		g_object_unref (self->priv->dnd_symbol); +		self->priv->dnd_symbol = NULL; +		self->priv->dnd_left = FALSE; +	} +	return TRUE; +} + +static gboolean  on_expose_event (GtkWidget *widget, GdkEventExpose *event, gpointer user_data)  {  	DrawData data; @@ -2572,6 +2707,9 @@ draw_diagram (GtkWidget *widget, DrawData *data)  		break;  	} +	if (data->self->priv->dnd_symbol && !data->self->priv->dnd_left) +		draw_object (data->self->priv->dnd_symbol, data); +  	cairo_restore (data->cr);  } | 
