From 1f68d362dbc2db754d4b26fcc12cf73117359867 Mon Sep 17 00:00:00 2001 From: leo Date: Mon, 11 Feb 2013 19:28:53 +0000 Subject: [PATCH] Support drag and drop from piece list on Linux. --- common/project.cpp | 13 +++++++++++ linux/glwindow.cpp | 55 ++++++++++++++++++++++++++++++++++++++++++++++ linux/main.cpp | 3 +++ linux/main.h | 5 +++++ linux/toolbar.cpp | 22 +++++++++++++++++++ 5 files changed, 98 insertions(+) diff --git a/common/project.cpp b/common/project.cpp index 523759ab..f6d3de15 100644 --- a/common/project.cpp +++ b/common/project.cpp @@ -6886,6 +6886,19 @@ bool Project::StopTracking(bool bAccept) } else { + if (m_nCurAction == LC_ACTION_INSERT) + { + m_pCurPiece->Release(); + m_pCurPiece = m_PreviousPiece; + m_PreviousPiece = NULL; + + if (m_RestoreAction) + { + SetAction(m_PreviousAction); + m_RestoreAction = false; + } + } + DeleteContents (true); FileLoad (m_pTrackFile, true, false); delete m_pTrackFile; diff --git a/linux/glwindow.cpp b/linux/glwindow.cpp index 4a8e58b7..61e8b962 100644 --- a/linux/glwindow.cpp +++ b/linux/glwindow.cpp @@ -2,9 +2,12 @@ #include #include #include "lc_global.h" +#include "lc_application.h" #include "opengl.h" #include "glwindow.h" #include "defines.h" +#include "main.h" +#include "project.h" #include "system.h" struct GLWindowPrivate @@ -19,6 +22,7 @@ static XVisualInfo* WindowXVisualInfo = NULL; static bool WindowMultisample = false; static GLXContext WindowContext; static int WindowContextCount; +static bool dragging; // ============================================================================= // static functions @@ -119,6 +123,52 @@ static gint pointer_motion_event(GtkWidget *widget, GdkEventMotion *event, gpoin return TRUE; } +static gboolean drag_drop(GtkWidget *widget, GdkDragContext *context, gint x, gint y, guint time, gpointer data) +{ + if (!dragged_piece) + { + return FALSE; + } + + GLWindow *wnd = (GLWindow*)data; + y = widget->allocation.height - y - 1; + lcGetActiveProject()->BeginPieceDrop(dragged_piece); + wnd->OnLeftButtonUp(x, y, FALSE, FALSE); + gtk_drag_finish(context, TRUE, FALSE, time); + return TRUE; +} + +static void drag_leave(GtkWidget *widget, GdkDragContext *context, guint time, gpointer data) +{ + if (dragging) + { + dragging = false; + lcGetActiveProject()->HandleNotify(LC_CAPTURE_LOST, 0); + } +} + +static gboolean drag_motion(GtkWidget *widget, GdkDragContext *context, gint x, gint y, guint time, gpointer data) +{ + if (!dragged_piece) + { + return FALSE; + } + + GLWindow *wnd = (GLWindow*)data; + y = widget->allocation.height - y - 1; + + if (!dragging) + { + dragging = true; + lcGetActiveProject()->BeginPieceDrop(dragged_piece); + } + + wnd->OnMouseMove(x, y, FALSE, FALSE); + + gdk_drag_status(context, GDK_ACTION_COPY, time); + return TRUE; +} + static gboolean scroll_event(GtkWidget *widget, GdkEventScroll *event, gpointer data) { GLWindow *wnd = (GLWindow*)data; @@ -258,6 +308,8 @@ bool GLWindow::CreateFromWindow(void *data) gtk_widget_set_events(GTK_WIDGET(prv->widget), GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK); + gtk_drag_dest_set(prv->widget, GTK_DEST_DEFAULT_MOTION, drag_target_list, 1, GDK_ACTION_COPY); + // Connect signal handlers gtk_signal_connect(GTK_OBJECT(prv->widget), "expose_event", GTK_SIGNAL_FUNC(expose_event), this); // gtk_signal_connect(GTK_OBJECT(prv->widget), "destroy", GTK_SIGNAL_FUNC(destroy_event), this); @@ -265,6 +317,9 @@ bool GLWindow::CreateFromWindow(void *data) gtk_signal_connect(GTK_OBJECT(prv->widget), "motion_notify_event", GTK_SIGNAL_FUNC(pointer_motion_event), this); gtk_signal_connect(GTK_OBJECT(prv->widget), "button_press_event", GTK_SIGNAL_FUNC(button_press_event), this); gtk_signal_connect(GTK_OBJECT(prv->widget), "button_release_event", GTK_SIGNAL_FUNC(button_release_event), this); + gtk_signal_connect(GTK_OBJECT(prv->widget), "drag_drop", GTK_SIGNAL_FUNC(drag_drop), this); + gtk_signal_connect(GTK_OBJECT(prv->widget), "drag_leave", GTK_SIGNAL_FUNC(drag_leave), this); + gtk_signal_connect(GTK_OBJECT(prv->widget), "drag_motion", GTK_SIGNAL_FUNC(drag_motion), this); gtk_signal_connect(GTK_OBJECT(prv->widget), "scroll_event", GTK_SIGNAL_FUNC(scroll_event), this); gtk_signal_connect(GTK_OBJECT(prv->widget), "realize", GTK_SIGNAL_FUNC(realize_event), this); diff --git a/linux/main.cpp b/linux/main.cpp index 8804c75c..2e0d0b42 100644 --- a/linux/main.cpp +++ b/linux/main.cpp @@ -44,6 +44,9 @@ static char app_path[PATH_MAX]; static char lib_path[] = LC_INSTALL_PREFIX"/share/leocad/"; bool ignore_commands = false; +PieceInfo *dragged_piece; +const GtkTargetEntry drag_target_list[] = {{ (gchar*)"application/x-leocat", GTK_TARGET_SAME_APP, 0}}; + static void update_window_layout (); static gint main_quit (GtkWidget *widget, GdkEvent* event, gpointer data); diff --git a/linux/main.h b/linux/main.h index 6a63cda9..ed7fabe2 100644 --- a/linux/main.h +++ b/linux/main.h @@ -12,6 +12,11 @@ extern bool ignore_commands; void OnCommand(GtkWidget *w, gpointer data); void OnCommandDirect(GtkWidget *w, gpointer data); +class PieceInfo; +extern PieceInfo *dragged_piece; +extern bool dragging_color; +extern const GtkTargetEntry drag_target_list[]; + #define ID_FILE_RECENT1 1 #define ID_FILE_RECENT2 2 #define ID_FILE_RECENT3 3 diff --git a/linux/toolbar.cpp b/linux/toolbar.cpp index e4918b47..fd7e9fe4 100644 --- a/linux/toolbar.cpp +++ b/linux/toolbar.cpp @@ -285,6 +285,11 @@ void create_toolbars(GtkWidget *window, GtkWidget *vbox) new_pixmap (window, an_key), GTK_SIGNAL_FUNC (OnCommandDirect), (void*)LC_TOOLBAR_ADDKEYS); } +static void drag_end(GtkWidget *widget, GdkDragContext *context, gpointer data) +{ + dragged_piece = NULL; +} + // ========================================================= // Pieces toolbar @@ -398,6 +403,18 @@ static void piecetree_changed(GtkTreeSelection* selection, gpointer data) } } +static void piecetree_drag_begin(GtkWidget *widget, GdkDragContext *context, gpointer data) +{ + GtkTreeIter iter; + GtkTreeModel *model; + + dragged_piece = NULL; + if (gtk_tree_selection_get_selected(gtk_tree_view_get_selection(GTK_TREE_VIEW(widget)), &model, &iter)) + { + gtk_tree_model_get(model, &iter, 1, &dragged_piece, -1); + } +} + static void piececombo_popup_position (GtkMenu *menu, gint *x, gint *y, gboolean* push, gpointer data) { gdk_window_get_origin (pieceentry->window, x, y); @@ -1007,6 +1024,10 @@ GtkWidget* create_piecebar(GtkWidget *window, GLWindow *share) gtk_tree_selection_set_mode(select, GTK_SELECTION_SINGLE); g_signal_connect(G_OBJECT(select), "changed", G_CALLBACK(piecetree_changed), NULL); + gtk_drag_source_set(GTK_WIDGET(piecetree), GDK_BUTTON1_MASK, drag_target_list, 1, GDK_ACTION_COPY); + g_signal_connect(G_OBJECT(piecetree), "drag_begin", G_CALLBACK(piecetree_drag_begin), NULL); + g_signal_connect(G_OBJECT(piecetree), "drag_end", G_CALLBACK(drag_end), NULL); + gtk_container_add(GTK_CONTAINER(scroll_win), piecetree); gtk_widget_show(piecetree); @@ -1044,6 +1065,7 @@ GtkWidget* create_piecebar(GtkWidget *window, GLWindow *share) gtk_signal_connect(GTK_OBJECT(colorlist), "realize", GTK_SIGNAL_FUNC(colorlist_realize), NULL); gtk_signal_connect(GTK_OBJECT(colorlist), "unrealize", GTK_SIGNAL_FUNC(colorlist_unrealize), NULL); gtk_signal_connect(GTK_OBJECT(colorlist), "query-tooltip", GTK_SIGNAL_FUNC(colorlist_tooltip), NULL); + gtk_signal_connect(GTK_OBJECT(colorlist), "drag_end", G_CALLBACK(drag_end), NULL); gtk_widget_show(colorlist);