diff --git a/ChangeLog b/ChangeLog index 71f541e5c0..eb837cde54 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,23 @@ +Mon Aug 23 23:25:05 BST 1999 Andy Thomas + + * app/menus.c + * app/nav_window.c + + Nav window code now handles boundary conditions correctly (ie + you can scroll to the edges of the image now). + It also has some key bindings:- + + 1) Arrow keys work as expected + 2) =/- keys perform zoomin/zoomout. Note these keys are hardcoded + at present until (if) I find away of finding out how to get the + current accel. keys for these functions. + 3) Space will raise the display window to the top of the window stack. + It also updates the preview. This will be changed to happen + automatically RSN. + + Tearoff menus are now popped up and down (like other dialogs) when + the tab key is pressed in the image window. + Mon Aug 23 19:55:48 MEST 1999 Sven Neumann * app/measure.c: fixed display of distance in the info window diff --git a/app/display/gimpnavigationeditor.c b/app/display/gimpnavigationeditor.c index 2463b0a83b..0af0458672 100644 --- a/app/display/gimpnavigationeditor.c +++ b/app/display/gimpnavigationeditor.c @@ -16,16 +16,20 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#include +#include "gdk/gdkkeysyms.h" #include "appenv.h" #include "actionarea.h" #include "colormaps.h" #include "cursorutil.h" +#include "dialog_handler.h" #include "info_dialog.h" #include "info_window.h" #include "gdisplay.h" #include "gximage.h" #include "interface.h" #include "scroll.h" +#include "scale.h" #include "libgimp/gimpintl.h" #include "libgimp/gimpunit.h" @@ -47,6 +51,7 @@ typedef struct _NavWinData NavWinData; struct _NavWinData { gboolean showingPreview; + InfoDialog *info_win; GtkWidget *preview; void *gdisp_ptr; /* I'm not happy 'bout this one */ GtkWidget *previewBox; @@ -111,6 +116,16 @@ nav_window_draw_sqr(NavWinData *, static void set_size_data(NavWinData *); +static void +nav_window_destroy_callback (GtkWidget *widget, + gpointer client_data) +{ + InfoDialog *info_win; + + info_win = (InfoDialog *)client_data; + dialog_unregister(info_win->shell); +} + static void nav_window_close_callback (GtkWidget *widget, gpointer client_data) @@ -151,6 +166,7 @@ nav_window_disp_area(NavWinData *iwd,GDisplay *gdisp) (iwd->imageheight > 0 && newheight != iwd->imageheight)) { /* Must change the preview size */ + gtk_window_set_focus(GTK_WINDOW (iwd->info_win->shell),NULL); destroy_preview_widget(iwd); create_preview_widget(iwd); need_update = TRUE; @@ -160,8 +176,8 @@ nav_window_disp_area(NavWinData *iwd,GDisplay *gdisp) iwd->imageheight = newheight; /* Normalise */ - iwd->dispwidth = MIN(iwd->dispwidth, iwd->pwidth-BORDER_PEN_WIDTH); - iwd->dispheight = MIN(iwd->dispheight, iwd->pheight-BORDER_PEN_WIDTH); + iwd->dispwidth = MIN(iwd->dispwidth, iwd->pwidth/*-BORDER_PEN_WIDTH*/); + iwd->dispheight = MIN(iwd->dispheight, iwd->pheight/*-BORDER_PEN_WIDTH*/); if(need_update == TRUE) { @@ -173,6 +189,7 @@ nav_window_disp_area(NavWinData *iwd,GDisplay *gdisp) nav_window_draw_sqr(iwd,FALSE, iwd->dispx,iwd->dispy, iwd->dispwidth,iwd->dispheight); + gtk_window_set_focus(GTK_WINDOW (iwd->info_win->shell),iwd->preview); } } @@ -189,15 +206,14 @@ nav_window_draw_sqr(NavWinData *iwd, gdisp = (GDisplay *) iwd->gdisp_ptr; gdk_gc_set_function (iwd->gc, GDK_INVERT); - - + if(undraw) { /* first undraw from last co-ords */ gdk_draw_rectangle (iwd->preview->window, iwd->gc, FALSE, iwd->dispx,iwd->dispy, - iwd->dispwidth, - iwd->dispheight); + iwd->dispwidth-BORDER_PEN_WIDTH+1, + iwd->dispheight-BORDER_PEN_WIDTH+1); } /* gdk_draw_rectangle (iwd->preview->window, iwd->gc, FALSE, */ @@ -206,8 +222,8 @@ nav_window_draw_sqr(NavWinData *iwd, gdk_draw_rectangle (iwd->preview->window, iwd->gc, FALSE, x,y, - w, - h); + w-BORDER_PEN_WIDTH+1, + h-BORDER_PEN_WIDTH+1); iwd->dispx = x; iwd->dispy = y; @@ -274,11 +290,11 @@ create_preview_widget(NavWinData *iwd) gtk_container_add(GTK_CONTAINER (iwd->previewAlign),hbox); image = gtk_preview_new (GTK_PREVIEW_COLOR); + gtk_widget_set_events( GTK_WIDGET(image), PREVIEW_MASK ); iwd->preview = image; gtk_widget_show (image); gtk_preview_set_dither (GTK_PREVIEW (image), GDK_RGB_DITHER_MAX); - gtk_widget_set_events( GTK_WIDGET(image), PREVIEW_MASK ); set_size_data(iwd); @@ -308,7 +324,7 @@ create_preview_widget(NavWinData *iwd) /* (GtkSignalFunc) nav_window_preview_resized, */ /* iwd); */ - gtk_widget_grab_focus(image); + GTK_WIDGET_SET_FLAGS (image, GTK_CAN_FOCUS); } #if 0 @@ -342,16 +358,29 @@ update_real_view(NavWinData *iwd,gint tx,gint ty) gdouble ratio; gint xoffset; gint yoffset; + gint xpnt; + gint ypnt; gdisp = (GDisplay *) iwd->gdisp_ptr; ratio = ((gdouble)SCALEDEST(gdisp))/((gdouble)SCALESRC(gdisp)); - xoffset = tx - iwd->dispx; - yoffset = ty - iwd->dispy; - - xoffset = (gint)(((gdouble)xoffset*ratio)/iwd->ratio); - yoffset = (gint)(((gdouble)yoffset*ratio)/iwd->ratio); + if((tx + iwd->dispwidth) >= iwd->pwidth) + { + tx = iwd->pwidth; /* Actually should be less... + * but bound check will save us. + */ + } + xpnt = (gint)(((gdouble)(tx)*ratio)/iwd->ratio); + + if((ty + iwd->dispheight) >= iwd->pheight) + ty = iwd->pheight; /* Same comment as for xpnt above. */ + + ypnt = (gint)(((gdouble)(ty)*ratio)/iwd->ratio); + + xoffset = xpnt - gdisp->offset_x; + yoffset = ypnt - gdisp->offset_y; + iwd->block_window_marker = TRUE; scroll_display(iwd->gdisp_ptr,xoffset,yoffset); iwd->block_window_marker = FALSE; @@ -506,6 +535,50 @@ nav_window_preview_resized (GtkWidget *widget, } #endif /* 0 */ +static void +move_to_point(NavWinData *iwd, + gint tx, + gint ty) +{ + if(tx < 0) + { + tx = 0; + } + + if(tx > iwd->pwidth) + { + tx = iwd->pwidth; + } + + if(ty < 0) + { + ty = 0; + } + + if(ty > iwd->pheight) + { + ty = iwd->pwidth; + } + + if((tx + iwd->dispwidth) >= iwd->pwidth) + { + tx = iwd->pwidth - iwd->dispwidth; + } + + if((ty + iwd->dispheight) >= iwd->pheight) + { + ty = iwd->pheight - iwd->dispheight; + } + + /* Update the real display */ + update_real_view(iwd,tx,ty); + + nav_window_draw_sqr(iwd, + TRUE, + tx,ty, + iwd->dispwidth,iwd->dispheight); + +} static gint nav_window_preview_events (GtkWidget *widget, @@ -516,9 +589,11 @@ nav_window_preview_events (GtkWidget *widget, GDisplay *gdisp; GdkEventButton *bevent; GdkEventMotion *mevent; + GdkEventKey *kevent; GdkModifierType mask; - gint tx,ty; + gint tx = 0,ty = 0; /* So compiler complaints */ gint mx,my; + gboolean arrowKey = FALSE; iwd = (NavWinData *)data; @@ -608,7 +683,53 @@ nav_window_preview_events (GtkWidget *widget, break; } break; + case GDK_KEY_PRESS: + /* hack for the update preview... needs to be fixed */ + kevent = (GdkEventKey *) event; + + switch (kevent->keyval) + { + case GDK_space: + gdk_window_raise(gdisp->shell->window); + nav_window_update_preview(iwd); + gtk_widget_draw(iwd->preview, NULL); + break; + case GDK_Up: + arrowKey = TRUE; + tx = iwd->dispx; + ty = iwd->dispy - 1; + break; + case GDK_Left: + arrowKey = TRUE; + tx = iwd->dispx - 1; + ty = iwd->dispy; + break; + case GDK_Right: + arrowKey = TRUE; + tx = iwd->dispx + 1; + ty = iwd->dispy; + break; + case GDK_Down: + arrowKey = TRUE; + tx = iwd->dispx; + ty = iwd->dispy + 1; + break; + case GDK_equal: + change_scale(gdisp,ZOOMIN); + break; + case GDK_minus: + change_scale(gdisp,ZOOMOUT); + break; + default: + break; + } + if(arrowKey) + { + move_to_point(iwd,tx,ty); + return TRUE; + } + break; case GDK_MOTION_NOTIFY: mevent = (GdkEventMotion *) event; @@ -622,44 +743,7 @@ nav_window_preview_events (GtkWidget *widget, tx = tx - iwd->motion_offsetx; ty = ty - iwd->motion_offsety; - if(tx < 0) - { - tx = 0; - } - - if(tx > iwd->pwidth) - { - tx = iwd->pwidth; - } - - if(ty < 0) - { - ty = 0; - } - - if(ty > iwd->pheight) - { - ty = iwd->pwidth; - } - - if((tx + iwd->dispwidth) >= iwd->pwidth) - { - tx = iwd->pwidth - iwd->dispwidth; - } - - if((ty + iwd->dispheight) >= iwd->pheight) - { - ty = iwd->pheight - iwd->dispheight; - } - - /* Update the real display */ - update_real_view(iwd,tx,ty); - - nav_window_draw_sqr(iwd, - TRUE, - tx,ty, - iwd->dispwidth,iwd->dispheight); - + move_to_point(iwd,tx,ty); break; default: @@ -695,11 +779,6 @@ nav_window_expose_events (GtkWidget *widget, iwd->dispx,iwd->dispy, iwd->dispwidth,iwd->dispheight); - break; - case GDK_KEY_PRESS: - /* hack for the update preview... needs to be fixed */ - nav_window_update_preview(iwd); - gtk_widget_draw(iwd->preview, NULL); break; default: break; @@ -767,12 +846,17 @@ nav_window_create (void *gdisp_ptr) /* create the info dialog */ title_buf = g_strdup_printf (_("%s: Window Navigation"), title); info_win = info_dialog_new (title_buf); + dialog_register(info_win->shell); + gtk_signal_connect (GTK_OBJECT (info_win->shell), "destroy", + (GtkSignalFunc) nav_window_destroy_callback, + info_win); g_free (title_buf); /* gtk_window_set_policy (GTK_WINDOW (info_win->shell), */ /* FALSE,FALSE,FALSE); */ iwd = (NavWinData *) g_malloc (sizeof (NavWinData)); info_win->user_data = iwd; + iwd->info_win = info_win; iwd->showingPreview = TRUE; iwd->preview = NULL; iwd->gdisp_ptr = gdisp_ptr; @@ -790,6 +874,8 @@ nav_window_create (void *gdisp_ptr) /* Add preview */ container = info_window_image_preview_new(info_win); +/* gtk_container_set_focus_child(GTK_CONTAINER(container),iwd->preview); */ + gtk_window_set_focus(GTK_WINDOW (info_win->shell),iwd->preview); gtk_table_attach_defaults (GTK_TABLE (info_win->info_table), container, 0, 2, 0, 1); /* Create the action area */ diff --git a/app/display/gimpnavigationview.c b/app/display/gimpnavigationview.c index 2463b0a83b..0af0458672 100644 --- a/app/display/gimpnavigationview.c +++ b/app/display/gimpnavigationview.c @@ -16,16 +16,20 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#include +#include "gdk/gdkkeysyms.h" #include "appenv.h" #include "actionarea.h" #include "colormaps.h" #include "cursorutil.h" +#include "dialog_handler.h" #include "info_dialog.h" #include "info_window.h" #include "gdisplay.h" #include "gximage.h" #include "interface.h" #include "scroll.h" +#include "scale.h" #include "libgimp/gimpintl.h" #include "libgimp/gimpunit.h" @@ -47,6 +51,7 @@ typedef struct _NavWinData NavWinData; struct _NavWinData { gboolean showingPreview; + InfoDialog *info_win; GtkWidget *preview; void *gdisp_ptr; /* I'm not happy 'bout this one */ GtkWidget *previewBox; @@ -111,6 +116,16 @@ nav_window_draw_sqr(NavWinData *, static void set_size_data(NavWinData *); +static void +nav_window_destroy_callback (GtkWidget *widget, + gpointer client_data) +{ + InfoDialog *info_win; + + info_win = (InfoDialog *)client_data; + dialog_unregister(info_win->shell); +} + static void nav_window_close_callback (GtkWidget *widget, gpointer client_data) @@ -151,6 +166,7 @@ nav_window_disp_area(NavWinData *iwd,GDisplay *gdisp) (iwd->imageheight > 0 && newheight != iwd->imageheight)) { /* Must change the preview size */ + gtk_window_set_focus(GTK_WINDOW (iwd->info_win->shell),NULL); destroy_preview_widget(iwd); create_preview_widget(iwd); need_update = TRUE; @@ -160,8 +176,8 @@ nav_window_disp_area(NavWinData *iwd,GDisplay *gdisp) iwd->imageheight = newheight; /* Normalise */ - iwd->dispwidth = MIN(iwd->dispwidth, iwd->pwidth-BORDER_PEN_WIDTH); - iwd->dispheight = MIN(iwd->dispheight, iwd->pheight-BORDER_PEN_WIDTH); + iwd->dispwidth = MIN(iwd->dispwidth, iwd->pwidth/*-BORDER_PEN_WIDTH*/); + iwd->dispheight = MIN(iwd->dispheight, iwd->pheight/*-BORDER_PEN_WIDTH*/); if(need_update == TRUE) { @@ -173,6 +189,7 @@ nav_window_disp_area(NavWinData *iwd,GDisplay *gdisp) nav_window_draw_sqr(iwd,FALSE, iwd->dispx,iwd->dispy, iwd->dispwidth,iwd->dispheight); + gtk_window_set_focus(GTK_WINDOW (iwd->info_win->shell),iwd->preview); } } @@ -189,15 +206,14 @@ nav_window_draw_sqr(NavWinData *iwd, gdisp = (GDisplay *) iwd->gdisp_ptr; gdk_gc_set_function (iwd->gc, GDK_INVERT); - - + if(undraw) { /* first undraw from last co-ords */ gdk_draw_rectangle (iwd->preview->window, iwd->gc, FALSE, iwd->dispx,iwd->dispy, - iwd->dispwidth, - iwd->dispheight); + iwd->dispwidth-BORDER_PEN_WIDTH+1, + iwd->dispheight-BORDER_PEN_WIDTH+1); } /* gdk_draw_rectangle (iwd->preview->window, iwd->gc, FALSE, */ @@ -206,8 +222,8 @@ nav_window_draw_sqr(NavWinData *iwd, gdk_draw_rectangle (iwd->preview->window, iwd->gc, FALSE, x,y, - w, - h); + w-BORDER_PEN_WIDTH+1, + h-BORDER_PEN_WIDTH+1); iwd->dispx = x; iwd->dispy = y; @@ -274,11 +290,11 @@ create_preview_widget(NavWinData *iwd) gtk_container_add(GTK_CONTAINER (iwd->previewAlign),hbox); image = gtk_preview_new (GTK_PREVIEW_COLOR); + gtk_widget_set_events( GTK_WIDGET(image), PREVIEW_MASK ); iwd->preview = image; gtk_widget_show (image); gtk_preview_set_dither (GTK_PREVIEW (image), GDK_RGB_DITHER_MAX); - gtk_widget_set_events( GTK_WIDGET(image), PREVIEW_MASK ); set_size_data(iwd); @@ -308,7 +324,7 @@ create_preview_widget(NavWinData *iwd) /* (GtkSignalFunc) nav_window_preview_resized, */ /* iwd); */ - gtk_widget_grab_focus(image); + GTK_WIDGET_SET_FLAGS (image, GTK_CAN_FOCUS); } #if 0 @@ -342,16 +358,29 @@ update_real_view(NavWinData *iwd,gint tx,gint ty) gdouble ratio; gint xoffset; gint yoffset; + gint xpnt; + gint ypnt; gdisp = (GDisplay *) iwd->gdisp_ptr; ratio = ((gdouble)SCALEDEST(gdisp))/((gdouble)SCALESRC(gdisp)); - xoffset = tx - iwd->dispx; - yoffset = ty - iwd->dispy; - - xoffset = (gint)(((gdouble)xoffset*ratio)/iwd->ratio); - yoffset = (gint)(((gdouble)yoffset*ratio)/iwd->ratio); + if((tx + iwd->dispwidth) >= iwd->pwidth) + { + tx = iwd->pwidth; /* Actually should be less... + * but bound check will save us. + */ + } + xpnt = (gint)(((gdouble)(tx)*ratio)/iwd->ratio); + + if((ty + iwd->dispheight) >= iwd->pheight) + ty = iwd->pheight; /* Same comment as for xpnt above. */ + + ypnt = (gint)(((gdouble)(ty)*ratio)/iwd->ratio); + + xoffset = xpnt - gdisp->offset_x; + yoffset = ypnt - gdisp->offset_y; + iwd->block_window_marker = TRUE; scroll_display(iwd->gdisp_ptr,xoffset,yoffset); iwd->block_window_marker = FALSE; @@ -506,6 +535,50 @@ nav_window_preview_resized (GtkWidget *widget, } #endif /* 0 */ +static void +move_to_point(NavWinData *iwd, + gint tx, + gint ty) +{ + if(tx < 0) + { + tx = 0; + } + + if(tx > iwd->pwidth) + { + tx = iwd->pwidth; + } + + if(ty < 0) + { + ty = 0; + } + + if(ty > iwd->pheight) + { + ty = iwd->pwidth; + } + + if((tx + iwd->dispwidth) >= iwd->pwidth) + { + tx = iwd->pwidth - iwd->dispwidth; + } + + if((ty + iwd->dispheight) >= iwd->pheight) + { + ty = iwd->pheight - iwd->dispheight; + } + + /* Update the real display */ + update_real_view(iwd,tx,ty); + + nav_window_draw_sqr(iwd, + TRUE, + tx,ty, + iwd->dispwidth,iwd->dispheight); + +} static gint nav_window_preview_events (GtkWidget *widget, @@ -516,9 +589,11 @@ nav_window_preview_events (GtkWidget *widget, GDisplay *gdisp; GdkEventButton *bevent; GdkEventMotion *mevent; + GdkEventKey *kevent; GdkModifierType mask; - gint tx,ty; + gint tx = 0,ty = 0; /* So compiler complaints */ gint mx,my; + gboolean arrowKey = FALSE; iwd = (NavWinData *)data; @@ -608,7 +683,53 @@ nav_window_preview_events (GtkWidget *widget, break; } break; + case GDK_KEY_PRESS: + /* hack for the update preview... needs to be fixed */ + kevent = (GdkEventKey *) event; + + switch (kevent->keyval) + { + case GDK_space: + gdk_window_raise(gdisp->shell->window); + nav_window_update_preview(iwd); + gtk_widget_draw(iwd->preview, NULL); + break; + case GDK_Up: + arrowKey = TRUE; + tx = iwd->dispx; + ty = iwd->dispy - 1; + break; + case GDK_Left: + arrowKey = TRUE; + tx = iwd->dispx - 1; + ty = iwd->dispy; + break; + case GDK_Right: + arrowKey = TRUE; + tx = iwd->dispx + 1; + ty = iwd->dispy; + break; + case GDK_Down: + arrowKey = TRUE; + tx = iwd->dispx; + ty = iwd->dispy + 1; + break; + case GDK_equal: + change_scale(gdisp,ZOOMIN); + break; + case GDK_minus: + change_scale(gdisp,ZOOMOUT); + break; + default: + break; + } + if(arrowKey) + { + move_to_point(iwd,tx,ty); + return TRUE; + } + break; case GDK_MOTION_NOTIFY: mevent = (GdkEventMotion *) event; @@ -622,44 +743,7 @@ nav_window_preview_events (GtkWidget *widget, tx = tx - iwd->motion_offsetx; ty = ty - iwd->motion_offsety; - if(tx < 0) - { - tx = 0; - } - - if(tx > iwd->pwidth) - { - tx = iwd->pwidth; - } - - if(ty < 0) - { - ty = 0; - } - - if(ty > iwd->pheight) - { - ty = iwd->pwidth; - } - - if((tx + iwd->dispwidth) >= iwd->pwidth) - { - tx = iwd->pwidth - iwd->dispwidth; - } - - if((ty + iwd->dispheight) >= iwd->pheight) - { - ty = iwd->pheight - iwd->dispheight; - } - - /* Update the real display */ - update_real_view(iwd,tx,ty); - - nav_window_draw_sqr(iwd, - TRUE, - tx,ty, - iwd->dispwidth,iwd->dispheight); - + move_to_point(iwd,tx,ty); break; default: @@ -695,11 +779,6 @@ nav_window_expose_events (GtkWidget *widget, iwd->dispx,iwd->dispy, iwd->dispwidth,iwd->dispheight); - break; - case GDK_KEY_PRESS: - /* hack for the update preview... needs to be fixed */ - nav_window_update_preview(iwd); - gtk_widget_draw(iwd->preview, NULL); break; default: break; @@ -767,12 +846,17 @@ nav_window_create (void *gdisp_ptr) /* create the info dialog */ title_buf = g_strdup_printf (_("%s: Window Navigation"), title); info_win = info_dialog_new (title_buf); + dialog_register(info_win->shell); + gtk_signal_connect (GTK_OBJECT (info_win->shell), "destroy", + (GtkSignalFunc) nav_window_destroy_callback, + info_win); g_free (title_buf); /* gtk_window_set_policy (GTK_WINDOW (info_win->shell), */ /* FALSE,FALSE,FALSE); */ iwd = (NavWinData *) g_malloc (sizeof (NavWinData)); info_win->user_data = iwd; + iwd->info_win = info_win; iwd->showingPreview = TRUE; iwd->preview = NULL; iwd->gdisp_ptr = gdisp_ptr; @@ -790,6 +874,8 @@ nav_window_create (void *gdisp_ptr) /* Add preview */ container = info_window_image_preview_new(info_win); +/* gtk_container_set_focus_child(GTK_CONTAINER(container),iwd->preview); */ + gtk_window_set_focus(GTK_WINDOW (info_win->shell),iwd->preview); gtk_table_attach_defaults (GTK_TABLE (info_win->info_table), container, 0, 2, 0, 1); /* Create the action area */ diff --git a/app/gui/menus.c b/app/gui/menus.c index cec1ad6531..01c191cf94 100644 --- a/app/gui/menus.c +++ b/app/gui/menus.c @@ -21,6 +21,7 @@ #include "channels_dialog.h" #include "colormaps.h" #include "commands.h" +#include "dialog_handler.h" #include "fileops.h" #include "general.h" #include "gimprc.h" @@ -47,12 +48,15 @@ static char* G_GNUC_UNUSED dummyMRU = N_("/File/MRU00 "); static void menus_init (void); static gchar* menu_translate (const gchar *path, gpointer data); +static void tearoff_cmd_callback (GtkWidget *widget, + gpointer callback_data, + guint callback_action); static GSList *last_opened_raw_filenames = NULL; static GtkItemFactoryEntry toolbox_entries[] = { - { N_("/File/tearoff1"), NULL, NULL, 0, "" }, + { N_("/File/tearoff1"), NULL, tearoff_cmd_callback, 0, "" }, { N_("/File/New"), "N", file_new_cmd_callback, 0 }, { N_("/File/Open"), "O", file_open_cmd_callback, 0 }, { N_("/File/About..."), NULL, about_dialog_cmd_callback, 0 }, @@ -70,7 +74,7 @@ static GtkItemFactoryEntry toolbox_entries[] = { N_("/File/Dialogs/Document Index..."), NULL, raise_idea_callback, 0 }, { N_("/File/Dialogs/Error Console..."), NULL, dialogs_error_console_cmd_callback, 0 }, - { N_("/Xtns/tearoff1"), NULL, NULL, 0, "" }, + { N_("/Xtns/tearoff1"), NULL, tearoff_cmd_callback, 0, "" }, { N_("/Xtns/Module Browser"), NULL, dialogs_module_browser_cmd_callback, 0 }, { N_("/File/---"), NULL, NULL, 0, "" }, { N_("/File/---"), NULL, NULL, 0, "" } @@ -83,8 +87,8 @@ static GtkItemFactoryEntry toolbox_end = { N_("/File/Quit"), "Q", file_ static GtkItemFactoryEntry image_entries[] = { - { N_("/tearoff1"), NULL, NULL, 0, "" }, - { N_("/File/tearoff1"), NULL, NULL, 0, "" }, + { N_("/tearoff1"), NULL, tearoff_cmd_callback, 0, "" }, + { N_("/File/tearoff1"), NULL, tearoff_cmd_callback, 0, "" }, { N_("/File/New"), "N", file_new_cmd_callback, 1 }, { N_("/File/Open"), "O", file_open_cmd_callback, 0 }, { N_("/File/Save"), "S", file_save_cmd_callback, 0 }, @@ -97,7 +101,7 @@ static GtkItemFactoryEntry image_entries[] = { N_("/File/Quit"), "Q", file_quit_cmd_callback, 0 }, { N_("/File/---moved"), NULL, NULL, 0, "" }, - { N_("/Edit/tearoff1"), NULL, NULL, 0, "" }, + { N_("/Edit/tearoff1"), NULL, tearoff_cmd_callback, 0, "" }, { N_("/Edit/Cut"), "X", edit_cut_cmd_callback, 0 }, { N_("/Edit/Copy"), "C", edit_copy_cmd_callback, 0 }, { N_("/Edit/Paste"), "V", edit_paste_cmd_callback, 0 }, @@ -115,7 +119,7 @@ static GtkItemFactoryEntry image_entries[] = { N_("/Edit/Paste Named"), "V", edit_named_paste_cmd_callback, 0 }, { N_("/Edit/---"), NULL, NULL, 0, "" }, - { N_("/Select/tearoff1"), NULL, NULL, 0, "" }, + { N_("/Select/tearoff1"), NULL, tearoff_cmd_callback, 0, "" }, { N_("/Select/Invert"), "I", select_invert_cmd_callback, 0 }, { N_("/Select/All"), "A", select_all_cmd_callback, 0 }, { N_("/Select/None"), "A", select_none_cmd_callback, 0 }, @@ -129,7 +133,7 @@ static GtkItemFactoryEntry image_entries[] = { N_("/Select/---"), NULL, NULL, 0, "" }, { N_("/Select/Save To Channel"), NULL, select_save_cmd_callback, 0 }, - { N_("/View/tearoff1"), NULL, NULL, 0, "" }, + { N_("/View/tearoff1"), NULL, tearoff_cmd_callback, 0, "" }, { N_("/View/Zoom In"), "equal", view_zoomin_cmd_callback, 0 }, { N_("/View/Zoom Out"), "minus", view_zoomout_cmd_callback, 0 }, { N_("/View/Zoom/16:1"), NULL, view_zoom_16_1_callback, 0 }, @@ -156,16 +160,16 @@ static GtkItemFactoryEntry image_entries[] = { N_("/View/New View"), NULL, view_new_view_cmd_callback, 0 }, { N_("/View/Shrink Wrap"), "E", view_shrink_wrap_cmd_callback, 0 }, - { N_("/Image/tearoff1"), NULL, NULL, 0, "" }, - { N_("/Image/Colors/tearoff1"), NULL, NULL, 0, "" }, + { N_("/Image/tearoff1"), NULL, tearoff_cmd_callback, 0, "" }, + { N_("/Image/Colors/tearoff1"), NULL, tearoff_cmd_callback, 0, "" }, { N_("/Image/Colors/Equalize"), NULL, image_equalize_cmd_callback, 0 }, { N_("/Image/Colors/Invert"), NULL, image_invert_cmd_callback, 0 }, { N_("/Image/Colors/---"), NULL, NULL, 0, "" }, { N_("/Image/Colors/Desaturate"), NULL, image_desaturate_cmd_callback, 0 }, - { N_("/Image/Channel Ops/tearoff1"), NULL, NULL, 0, "" }, + { N_("/Image/Channel Ops/tearoff1"), NULL, tearoff_cmd_callback, 0, "" }, { N_("/Image/Channel Ops/Duplicate"), "D", channel_ops_duplicate_cmd_callback, 0 }, { N_("/Image/Channel Ops/Offset"), "O", channel_ops_offset_cmd_callback, 0 }, - { N_("/Image/Alpha/tearoff1"), NULL, NULL, 0, "" }, + { N_("/Image/Alpha/tearoff1"), NULL, tearoff_cmd_callback, 0, "" }, { N_("/Image/Alpha/Add Alpha Channel"), NULL, layers_add_alpha_channel_cmd_callback, 0 }, { N_("/Image/---"), NULL, NULL, 0, "" }, @@ -177,9 +181,9 @@ static GtkItemFactoryEntry image_entries[] = { N_("/Image/Scale"), NULL, image_scale_cmd_callback, 0 }, { N_("/Image/---"), NULL, NULL, 0, "" }, - { N_("/Layers/tearoff1"), NULL, NULL, 0, "" }, + { N_("/Layers/tearoff1"), NULL, tearoff_cmd_callback, 0, "" }, { N_("/Layers/Layers & Channels..."), "L", dialogs_lc_cmd_callback, 0 }, - { N_("/Layers/Stack/tearoff1"), NULL, NULL, 0, "" }, + { N_("/Layers/Stack/tearoff1"), NULL, tearoff_cmd_callback, 0, "" }, { N_("/Layers/Stack/Previous Layer"), "Prior", layers_previous_cmd_callback, 0 }, { N_("/Layers/Stack/Next Layer"), "Next", layers_next_cmd_callback, 0 }, { N_("/Layers/Stack/Raise Layer"), "Prior", layers_raise_cmd_callback, 0 }, @@ -195,7 +199,7 @@ static GtkItemFactoryEntry image_entries[] = { N_("/Layers/Add Alpha Channel"), NULL, layers_add_alpha_channel_cmd_callback, 0 }, { N_("/Layers/---"), NULL, NULL, 0, "" }, - { N_("/Tools/tearoff1"), NULL, NULL, 0, "" }, + { N_("/Tools/tearoff1"), NULL, tearoff_cmd_callback, 0, "" }, { N_("/Tools/Toolbox"), NULL, toolbox_raise_callback, 0 }, { N_("/Tools/Default Colors"), "D", tools_default_colors_cmd_callback, 0 }, { N_("/Tools/Swap Colors"), "X", tools_swap_colors_cmd_callback, 0 }, @@ -203,15 +207,15 @@ static GtkItemFactoryEntry image_entries[] = /* the tool entries themselves are built on the fly */ - { N_("/Filters/tearoff1"), NULL, NULL, 0, "" }, + { N_("/Filters/tearoff1"), NULL, tearoff_cmd_callback, 0, "" }, { N_("/Filters/Repeat last"), "F", filters_repeat_cmd_callback, 0x0 }, { N_("/Filters/Re-show last"), "F", filters_repeat_cmd_callback, 0x1 }, { N_("/Filters/---"), NULL, NULL, 0, "" }, - { N_("/Script-Fu/tearoff1"), NULL, NULL, 0, "" }, + { N_("/Script-Fu/tearoff1"), NULL, tearoff_cmd_callback, 0, "" }, { N_("/Script-Fu/"), NULL, NULL, 0 }, - { N_("/Dialogs/tearoff1"), NULL, NULL, 0, "" }, + { N_("/Dialogs/tearoff1"), NULL, tearoff_cmd_callback, 0, "" }, { N_("/Dialogs/Brushes..."), "B", dialogs_brushes_cmd_callback, 0 }, { N_("/Dialogs/Patterns..."), "P", dialogs_patterns_cmd_callback, 0 }, { N_("/Dialogs/Palette..."), "P", dialogs_palette_cmd_callback, 0 }, @@ -426,7 +430,8 @@ menus_create (GtkMenuEntry *entries, { GtkItemFactoryEntry entry = { NULL, NULL, NULL, 0, "" }; entry.path = tearoff_path->str; - gtk_item_factory_create_items (image_factory, 1, &entry, NULL); + entry.callback = tearoff_cmd_callback; + gtk_item_factory_create_items_ac (image_factory, 1, &entry, NULL,2); } p = strchr (p + 1, '/'); @@ -822,3 +827,57 @@ menu_translate (const gchar *path, { return gettext (path); } + +static gint +tearoff_delete_cb (GtkWidget *widget, + GdkEvent *event, + gpointer data) +{ + /* Unregister if dialog is deleted as well */ + dialog_unregister((GtkWidget *)data); + return TRUE; +} + +static void +tearoff_cmd_callback (GtkWidget *widget, + gpointer callback_data, + guint callback_action) +{ + if(GTK_IS_TEAROFF_MENU_ITEM(widget)) + { + GtkTearoffMenuItem *tomi = (GtkTearoffMenuItem *)widget; + + if(tomi->torn_off) + { + GtkWidget *top = gtk_widget_get_toplevel(widget); + + /* This should be a window */ + if(!GTK_IS_WINDOW(top)) + { + g_message(_("tearoff menu not in top level window")); + } + else + { + dialog_register(top); + gtk_signal_connect_object (GTK_OBJECT (top), + "delete_event", + GTK_SIGNAL_FUNC (tearoff_delete_cb), + GTK_OBJECT (top)); + + gtk_object_set_data (GTK_OBJECT (widget),"tearoff_menu_top",top); + } + } + else + { + GtkWidget *top = (GtkWidget *)gtk_object_get_data (GTK_OBJECT (widget),"tearoff_menu_top"); + if(!top) + { + g_message(_("can't unregister tearoff menu top level window")); + } + else + { + dialog_unregister(top); + } + } + } +} diff --git a/app/menus.c b/app/menus.c index cec1ad6531..01c191cf94 100644 --- a/app/menus.c +++ b/app/menus.c @@ -21,6 +21,7 @@ #include "channels_dialog.h" #include "colormaps.h" #include "commands.h" +#include "dialog_handler.h" #include "fileops.h" #include "general.h" #include "gimprc.h" @@ -47,12 +48,15 @@ static char* G_GNUC_UNUSED dummyMRU = N_("/File/MRU00 "); static void menus_init (void); static gchar* menu_translate (const gchar *path, gpointer data); +static void tearoff_cmd_callback (GtkWidget *widget, + gpointer callback_data, + guint callback_action); static GSList *last_opened_raw_filenames = NULL; static GtkItemFactoryEntry toolbox_entries[] = { - { N_("/File/tearoff1"), NULL, NULL, 0, "" }, + { N_("/File/tearoff1"), NULL, tearoff_cmd_callback, 0, "" }, { N_("/File/New"), "N", file_new_cmd_callback, 0 }, { N_("/File/Open"), "O", file_open_cmd_callback, 0 }, { N_("/File/About..."), NULL, about_dialog_cmd_callback, 0 }, @@ -70,7 +74,7 @@ static GtkItemFactoryEntry toolbox_entries[] = { N_("/File/Dialogs/Document Index..."), NULL, raise_idea_callback, 0 }, { N_("/File/Dialogs/Error Console..."), NULL, dialogs_error_console_cmd_callback, 0 }, - { N_("/Xtns/tearoff1"), NULL, NULL, 0, "" }, + { N_("/Xtns/tearoff1"), NULL, tearoff_cmd_callback, 0, "" }, { N_("/Xtns/Module Browser"), NULL, dialogs_module_browser_cmd_callback, 0 }, { N_("/File/---"), NULL, NULL, 0, "" }, { N_("/File/---"), NULL, NULL, 0, "" } @@ -83,8 +87,8 @@ static GtkItemFactoryEntry toolbox_end = { N_("/File/Quit"), "Q", file_ static GtkItemFactoryEntry image_entries[] = { - { N_("/tearoff1"), NULL, NULL, 0, "" }, - { N_("/File/tearoff1"), NULL, NULL, 0, "" }, + { N_("/tearoff1"), NULL, tearoff_cmd_callback, 0, "" }, + { N_("/File/tearoff1"), NULL, tearoff_cmd_callback, 0, "" }, { N_("/File/New"), "N", file_new_cmd_callback, 1 }, { N_("/File/Open"), "O", file_open_cmd_callback, 0 }, { N_("/File/Save"), "S", file_save_cmd_callback, 0 }, @@ -97,7 +101,7 @@ static GtkItemFactoryEntry image_entries[] = { N_("/File/Quit"), "Q", file_quit_cmd_callback, 0 }, { N_("/File/---moved"), NULL, NULL, 0, "" }, - { N_("/Edit/tearoff1"), NULL, NULL, 0, "" }, + { N_("/Edit/tearoff1"), NULL, tearoff_cmd_callback, 0, "" }, { N_("/Edit/Cut"), "X", edit_cut_cmd_callback, 0 }, { N_("/Edit/Copy"), "C", edit_copy_cmd_callback, 0 }, { N_("/Edit/Paste"), "V", edit_paste_cmd_callback, 0 }, @@ -115,7 +119,7 @@ static GtkItemFactoryEntry image_entries[] = { N_("/Edit/Paste Named"), "V", edit_named_paste_cmd_callback, 0 }, { N_("/Edit/---"), NULL, NULL, 0, "" }, - { N_("/Select/tearoff1"), NULL, NULL, 0, "" }, + { N_("/Select/tearoff1"), NULL, tearoff_cmd_callback, 0, "" }, { N_("/Select/Invert"), "I", select_invert_cmd_callback, 0 }, { N_("/Select/All"), "A", select_all_cmd_callback, 0 }, { N_("/Select/None"), "A", select_none_cmd_callback, 0 }, @@ -129,7 +133,7 @@ static GtkItemFactoryEntry image_entries[] = { N_("/Select/---"), NULL, NULL, 0, "" }, { N_("/Select/Save To Channel"), NULL, select_save_cmd_callback, 0 }, - { N_("/View/tearoff1"), NULL, NULL, 0, "" }, + { N_("/View/tearoff1"), NULL, tearoff_cmd_callback, 0, "" }, { N_("/View/Zoom In"), "equal", view_zoomin_cmd_callback, 0 }, { N_("/View/Zoom Out"), "minus", view_zoomout_cmd_callback, 0 }, { N_("/View/Zoom/16:1"), NULL, view_zoom_16_1_callback, 0 }, @@ -156,16 +160,16 @@ static GtkItemFactoryEntry image_entries[] = { N_("/View/New View"), NULL, view_new_view_cmd_callback, 0 }, { N_("/View/Shrink Wrap"), "E", view_shrink_wrap_cmd_callback, 0 }, - { N_("/Image/tearoff1"), NULL, NULL, 0, "" }, - { N_("/Image/Colors/tearoff1"), NULL, NULL, 0, "" }, + { N_("/Image/tearoff1"), NULL, tearoff_cmd_callback, 0, "" }, + { N_("/Image/Colors/tearoff1"), NULL, tearoff_cmd_callback, 0, "" }, { N_("/Image/Colors/Equalize"), NULL, image_equalize_cmd_callback, 0 }, { N_("/Image/Colors/Invert"), NULL, image_invert_cmd_callback, 0 }, { N_("/Image/Colors/---"), NULL, NULL, 0, "" }, { N_("/Image/Colors/Desaturate"), NULL, image_desaturate_cmd_callback, 0 }, - { N_("/Image/Channel Ops/tearoff1"), NULL, NULL, 0, "" }, + { N_("/Image/Channel Ops/tearoff1"), NULL, tearoff_cmd_callback, 0, "" }, { N_("/Image/Channel Ops/Duplicate"), "D", channel_ops_duplicate_cmd_callback, 0 }, { N_("/Image/Channel Ops/Offset"), "O", channel_ops_offset_cmd_callback, 0 }, - { N_("/Image/Alpha/tearoff1"), NULL, NULL, 0, "" }, + { N_("/Image/Alpha/tearoff1"), NULL, tearoff_cmd_callback, 0, "" }, { N_("/Image/Alpha/Add Alpha Channel"), NULL, layers_add_alpha_channel_cmd_callback, 0 }, { N_("/Image/---"), NULL, NULL, 0, "" }, @@ -177,9 +181,9 @@ static GtkItemFactoryEntry image_entries[] = { N_("/Image/Scale"), NULL, image_scale_cmd_callback, 0 }, { N_("/Image/---"), NULL, NULL, 0, "" }, - { N_("/Layers/tearoff1"), NULL, NULL, 0, "" }, + { N_("/Layers/tearoff1"), NULL, tearoff_cmd_callback, 0, "" }, { N_("/Layers/Layers & Channels..."), "L", dialogs_lc_cmd_callback, 0 }, - { N_("/Layers/Stack/tearoff1"), NULL, NULL, 0, "" }, + { N_("/Layers/Stack/tearoff1"), NULL, tearoff_cmd_callback, 0, "" }, { N_("/Layers/Stack/Previous Layer"), "Prior", layers_previous_cmd_callback, 0 }, { N_("/Layers/Stack/Next Layer"), "Next", layers_next_cmd_callback, 0 }, { N_("/Layers/Stack/Raise Layer"), "Prior", layers_raise_cmd_callback, 0 }, @@ -195,7 +199,7 @@ static GtkItemFactoryEntry image_entries[] = { N_("/Layers/Add Alpha Channel"), NULL, layers_add_alpha_channel_cmd_callback, 0 }, { N_("/Layers/---"), NULL, NULL, 0, "" }, - { N_("/Tools/tearoff1"), NULL, NULL, 0, "" }, + { N_("/Tools/tearoff1"), NULL, tearoff_cmd_callback, 0, "" }, { N_("/Tools/Toolbox"), NULL, toolbox_raise_callback, 0 }, { N_("/Tools/Default Colors"), "D", tools_default_colors_cmd_callback, 0 }, { N_("/Tools/Swap Colors"), "X", tools_swap_colors_cmd_callback, 0 }, @@ -203,15 +207,15 @@ static GtkItemFactoryEntry image_entries[] = /* the tool entries themselves are built on the fly */ - { N_("/Filters/tearoff1"), NULL, NULL, 0, "" }, + { N_("/Filters/tearoff1"), NULL, tearoff_cmd_callback, 0, "" }, { N_("/Filters/Repeat last"), "F", filters_repeat_cmd_callback, 0x0 }, { N_("/Filters/Re-show last"), "F", filters_repeat_cmd_callback, 0x1 }, { N_("/Filters/---"), NULL, NULL, 0, "" }, - { N_("/Script-Fu/tearoff1"), NULL, NULL, 0, "" }, + { N_("/Script-Fu/tearoff1"), NULL, tearoff_cmd_callback, 0, "" }, { N_("/Script-Fu/"), NULL, NULL, 0 }, - { N_("/Dialogs/tearoff1"), NULL, NULL, 0, "" }, + { N_("/Dialogs/tearoff1"), NULL, tearoff_cmd_callback, 0, "" }, { N_("/Dialogs/Brushes..."), "B", dialogs_brushes_cmd_callback, 0 }, { N_("/Dialogs/Patterns..."), "P", dialogs_patterns_cmd_callback, 0 }, { N_("/Dialogs/Palette..."), "P", dialogs_palette_cmd_callback, 0 }, @@ -426,7 +430,8 @@ menus_create (GtkMenuEntry *entries, { GtkItemFactoryEntry entry = { NULL, NULL, NULL, 0, "" }; entry.path = tearoff_path->str; - gtk_item_factory_create_items (image_factory, 1, &entry, NULL); + entry.callback = tearoff_cmd_callback; + gtk_item_factory_create_items_ac (image_factory, 1, &entry, NULL,2); } p = strchr (p + 1, '/'); @@ -822,3 +827,57 @@ menu_translate (const gchar *path, { return gettext (path); } + +static gint +tearoff_delete_cb (GtkWidget *widget, + GdkEvent *event, + gpointer data) +{ + /* Unregister if dialog is deleted as well */ + dialog_unregister((GtkWidget *)data); + return TRUE; +} + +static void +tearoff_cmd_callback (GtkWidget *widget, + gpointer callback_data, + guint callback_action) +{ + if(GTK_IS_TEAROFF_MENU_ITEM(widget)) + { + GtkTearoffMenuItem *tomi = (GtkTearoffMenuItem *)widget; + + if(tomi->torn_off) + { + GtkWidget *top = gtk_widget_get_toplevel(widget); + + /* This should be a window */ + if(!GTK_IS_WINDOW(top)) + { + g_message(_("tearoff menu not in top level window")); + } + else + { + dialog_register(top); + gtk_signal_connect_object (GTK_OBJECT (top), + "delete_event", + GTK_SIGNAL_FUNC (tearoff_delete_cb), + GTK_OBJECT (top)); + + gtk_object_set_data (GTK_OBJECT (widget),"tearoff_menu_top",top); + } + } + else + { + GtkWidget *top = (GtkWidget *)gtk_object_get_data (GTK_OBJECT (widget),"tearoff_menu_top"); + if(!top) + { + g_message(_("can't unregister tearoff menu top level window")); + } + else + { + dialog_unregister(top); + } + } + } +} diff --git a/app/menus/menus.c b/app/menus/menus.c index cec1ad6531..01c191cf94 100644 --- a/app/menus/menus.c +++ b/app/menus/menus.c @@ -21,6 +21,7 @@ #include "channels_dialog.h" #include "colormaps.h" #include "commands.h" +#include "dialog_handler.h" #include "fileops.h" #include "general.h" #include "gimprc.h" @@ -47,12 +48,15 @@ static char* G_GNUC_UNUSED dummyMRU = N_("/File/MRU00 "); static void menus_init (void); static gchar* menu_translate (const gchar *path, gpointer data); +static void tearoff_cmd_callback (GtkWidget *widget, + gpointer callback_data, + guint callback_action); static GSList *last_opened_raw_filenames = NULL; static GtkItemFactoryEntry toolbox_entries[] = { - { N_("/File/tearoff1"), NULL, NULL, 0, "" }, + { N_("/File/tearoff1"), NULL, tearoff_cmd_callback, 0, "" }, { N_("/File/New"), "N", file_new_cmd_callback, 0 }, { N_("/File/Open"), "O", file_open_cmd_callback, 0 }, { N_("/File/About..."), NULL, about_dialog_cmd_callback, 0 }, @@ -70,7 +74,7 @@ static GtkItemFactoryEntry toolbox_entries[] = { N_("/File/Dialogs/Document Index..."), NULL, raise_idea_callback, 0 }, { N_("/File/Dialogs/Error Console..."), NULL, dialogs_error_console_cmd_callback, 0 }, - { N_("/Xtns/tearoff1"), NULL, NULL, 0, "" }, + { N_("/Xtns/tearoff1"), NULL, tearoff_cmd_callback, 0, "" }, { N_("/Xtns/Module Browser"), NULL, dialogs_module_browser_cmd_callback, 0 }, { N_("/File/---"), NULL, NULL, 0, "" }, { N_("/File/---"), NULL, NULL, 0, "" } @@ -83,8 +87,8 @@ static GtkItemFactoryEntry toolbox_end = { N_("/File/Quit"), "Q", file_ static GtkItemFactoryEntry image_entries[] = { - { N_("/tearoff1"), NULL, NULL, 0, "" }, - { N_("/File/tearoff1"), NULL, NULL, 0, "" }, + { N_("/tearoff1"), NULL, tearoff_cmd_callback, 0, "" }, + { N_("/File/tearoff1"), NULL, tearoff_cmd_callback, 0, "" }, { N_("/File/New"), "N", file_new_cmd_callback, 1 }, { N_("/File/Open"), "O", file_open_cmd_callback, 0 }, { N_("/File/Save"), "S", file_save_cmd_callback, 0 }, @@ -97,7 +101,7 @@ static GtkItemFactoryEntry image_entries[] = { N_("/File/Quit"), "Q", file_quit_cmd_callback, 0 }, { N_("/File/---moved"), NULL, NULL, 0, "" }, - { N_("/Edit/tearoff1"), NULL, NULL, 0, "" }, + { N_("/Edit/tearoff1"), NULL, tearoff_cmd_callback, 0, "" }, { N_("/Edit/Cut"), "X", edit_cut_cmd_callback, 0 }, { N_("/Edit/Copy"), "C", edit_copy_cmd_callback, 0 }, { N_("/Edit/Paste"), "V", edit_paste_cmd_callback, 0 }, @@ -115,7 +119,7 @@ static GtkItemFactoryEntry image_entries[] = { N_("/Edit/Paste Named"), "V", edit_named_paste_cmd_callback, 0 }, { N_("/Edit/---"), NULL, NULL, 0, "" }, - { N_("/Select/tearoff1"), NULL, NULL, 0, "" }, + { N_("/Select/tearoff1"), NULL, tearoff_cmd_callback, 0, "" }, { N_("/Select/Invert"), "I", select_invert_cmd_callback, 0 }, { N_("/Select/All"), "A", select_all_cmd_callback, 0 }, { N_("/Select/None"), "A", select_none_cmd_callback, 0 }, @@ -129,7 +133,7 @@ static GtkItemFactoryEntry image_entries[] = { N_("/Select/---"), NULL, NULL, 0, "" }, { N_("/Select/Save To Channel"), NULL, select_save_cmd_callback, 0 }, - { N_("/View/tearoff1"), NULL, NULL, 0, "" }, + { N_("/View/tearoff1"), NULL, tearoff_cmd_callback, 0, "" }, { N_("/View/Zoom In"), "equal", view_zoomin_cmd_callback, 0 }, { N_("/View/Zoom Out"), "minus", view_zoomout_cmd_callback, 0 }, { N_("/View/Zoom/16:1"), NULL, view_zoom_16_1_callback, 0 }, @@ -156,16 +160,16 @@ static GtkItemFactoryEntry image_entries[] = { N_("/View/New View"), NULL, view_new_view_cmd_callback, 0 }, { N_("/View/Shrink Wrap"), "E", view_shrink_wrap_cmd_callback, 0 }, - { N_("/Image/tearoff1"), NULL, NULL, 0, "" }, - { N_("/Image/Colors/tearoff1"), NULL, NULL, 0, "" }, + { N_("/Image/tearoff1"), NULL, tearoff_cmd_callback, 0, "" }, + { N_("/Image/Colors/tearoff1"), NULL, tearoff_cmd_callback, 0, "" }, { N_("/Image/Colors/Equalize"), NULL, image_equalize_cmd_callback, 0 }, { N_("/Image/Colors/Invert"), NULL, image_invert_cmd_callback, 0 }, { N_("/Image/Colors/---"), NULL, NULL, 0, "" }, { N_("/Image/Colors/Desaturate"), NULL, image_desaturate_cmd_callback, 0 }, - { N_("/Image/Channel Ops/tearoff1"), NULL, NULL, 0, "" }, + { N_("/Image/Channel Ops/tearoff1"), NULL, tearoff_cmd_callback, 0, "" }, { N_("/Image/Channel Ops/Duplicate"), "D", channel_ops_duplicate_cmd_callback, 0 }, { N_("/Image/Channel Ops/Offset"), "O", channel_ops_offset_cmd_callback, 0 }, - { N_("/Image/Alpha/tearoff1"), NULL, NULL, 0, "" }, + { N_("/Image/Alpha/tearoff1"), NULL, tearoff_cmd_callback, 0, "" }, { N_("/Image/Alpha/Add Alpha Channel"), NULL, layers_add_alpha_channel_cmd_callback, 0 }, { N_("/Image/---"), NULL, NULL, 0, "" }, @@ -177,9 +181,9 @@ static GtkItemFactoryEntry image_entries[] = { N_("/Image/Scale"), NULL, image_scale_cmd_callback, 0 }, { N_("/Image/---"), NULL, NULL, 0, "" }, - { N_("/Layers/tearoff1"), NULL, NULL, 0, "" }, + { N_("/Layers/tearoff1"), NULL, tearoff_cmd_callback, 0, "" }, { N_("/Layers/Layers & Channels..."), "L", dialogs_lc_cmd_callback, 0 }, - { N_("/Layers/Stack/tearoff1"), NULL, NULL, 0, "" }, + { N_("/Layers/Stack/tearoff1"), NULL, tearoff_cmd_callback, 0, "" }, { N_("/Layers/Stack/Previous Layer"), "Prior", layers_previous_cmd_callback, 0 }, { N_("/Layers/Stack/Next Layer"), "Next", layers_next_cmd_callback, 0 }, { N_("/Layers/Stack/Raise Layer"), "Prior", layers_raise_cmd_callback, 0 }, @@ -195,7 +199,7 @@ static GtkItemFactoryEntry image_entries[] = { N_("/Layers/Add Alpha Channel"), NULL, layers_add_alpha_channel_cmd_callback, 0 }, { N_("/Layers/---"), NULL, NULL, 0, "" }, - { N_("/Tools/tearoff1"), NULL, NULL, 0, "" }, + { N_("/Tools/tearoff1"), NULL, tearoff_cmd_callback, 0, "" }, { N_("/Tools/Toolbox"), NULL, toolbox_raise_callback, 0 }, { N_("/Tools/Default Colors"), "D", tools_default_colors_cmd_callback, 0 }, { N_("/Tools/Swap Colors"), "X", tools_swap_colors_cmd_callback, 0 }, @@ -203,15 +207,15 @@ static GtkItemFactoryEntry image_entries[] = /* the tool entries themselves are built on the fly */ - { N_("/Filters/tearoff1"), NULL, NULL, 0, "" }, + { N_("/Filters/tearoff1"), NULL, tearoff_cmd_callback, 0, "" }, { N_("/Filters/Repeat last"), "F", filters_repeat_cmd_callback, 0x0 }, { N_("/Filters/Re-show last"), "F", filters_repeat_cmd_callback, 0x1 }, { N_("/Filters/---"), NULL, NULL, 0, "" }, - { N_("/Script-Fu/tearoff1"), NULL, NULL, 0, "" }, + { N_("/Script-Fu/tearoff1"), NULL, tearoff_cmd_callback, 0, "" }, { N_("/Script-Fu/"), NULL, NULL, 0 }, - { N_("/Dialogs/tearoff1"), NULL, NULL, 0, "" }, + { N_("/Dialogs/tearoff1"), NULL, tearoff_cmd_callback, 0, "" }, { N_("/Dialogs/Brushes..."), "B", dialogs_brushes_cmd_callback, 0 }, { N_("/Dialogs/Patterns..."), "P", dialogs_patterns_cmd_callback, 0 }, { N_("/Dialogs/Palette..."), "P", dialogs_palette_cmd_callback, 0 }, @@ -426,7 +430,8 @@ menus_create (GtkMenuEntry *entries, { GtkItemFactoryEntry entry = { NULL, NULL, NULL, 0, "" }; entry.path = tearoff_path->str; - gtk_item_factory_create_items (image_factory, 1, &entry, NULL); + entry.callback = tearoff_cmd_callback; + gtk_item_factory_create_items_ac (image_factory, 1, &entry, NULL,2); } p = strchr (p + 1, '/'); @@ -822,3 +827,57 @@ menu_translate (const gchar *path, { return gettext (path); } + +static gint +tearoff_delete_cb (GtkWidget *widget, + GdkEvent *event, + gpointer data) +{ + /* Unregister if dialog is deleted as well */ + dialog_unregister((GtkWidget *)data); + return TRUE; +} + +static void +tearoff_cmd_callback (GtkWidget *widget, + gpointer callback_data, + guint callback_action) +{ + if(GTK_IS_TEAROFF_MENU_ITEM(widget)) + { + GtkTearoffMenuItem *tomi = (GtkTearoffMenuItem *)widget; + + if(tomi->torn_off) + { + GtkWidget *top = gtk_widget_get_toplevel(widget); + + /* This should be a window */ + if(!GTK_IS_WINDOW(top)) + { + g_message(_("tearoff menu not in top level window")); + } + else + { + dialog_register(top); + gtk_signal_connect_object (GTK_OBJECT (top), + "delete_event", + GTK_SIGNAL_FUNC (tearoff_delete_cb), + GTK_OBJECT (top)); + + gtk_object_set_data (GTK_OBJECT (widget),"tearoff_menu_top",top); + } + } + else + { + GtkWidget *top = (GtkWidget *)gtk_object_get_data (GTK_OBJECT (widget),"tearoff_menu_top"); + if(!top) + { + g_message(_("can't unregister tearoff menu top level window")); + } + else + { + dialog_unregister(top); + } + } + } +} diff --git a/app/nav_window.c b/app/nav_window.c index 2463b0a83b..0af0458672 100644 --- a/app/nav_window.c +++ b/app/nav_window.c @@ -16,16 +16,20 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#include +#include "gdk/gdkkeysyms.h" #include "appenv.h" #include "actionarea.h" #include "colormaps.h" #include "cursorutil.h" +#include "dialog_handler.h" #include "info_dialog.h" #include "info_window.h" #include "gdisplay.h" #include "gximage.h" #include "interface.h" #include "scroll.h" +#include "scale.h" #include "libgimp/gimpintl.h" #include "libgimp/gimpunit.h" @@ -47,6 +51,7 @@ typedef struct _NavWinData NavWinData; struct _NavWinData { gboolean showingPreview; + InfoDialog *info_win; GtkWidget *preview; void *gdisp_ptr; /* I'm not happy 'bout this one */ GtkWidget *previewBox; @@ -111,6 +116,16 @@ nav_window_draw_sqr(NavWinData *, static void set_size_data(NavWinData *); +static void +nav_window_destroy_callback (GtkWidget *widget, + gpointer client_data) +{ + InfoDialog *info_win; + + info_win = (InfoDialog *)client_data; + dialog_unregister(info_win->shell); +} + static void nav_window_close_callback (GtkWidget *widget, gpointer client_data) @@ -151,6 +166,7 @@ nav_window_disp_area(NavWinData *iwd,GDisplay *gdisp) (iwd->imageheight > 0 && newheight != iwd->imageheight)) { /* Must change the preview size */ + gtk_window_set_focus(GTK_WINDOW (iwd->info_win->shell),NULL); destroy_preview_widget(iwd); create_preview_widget(iwd); need_update = TRUE; @@ -160,8 +176,8 @@ nav_window_disp_area(NavWinData *iwd,GDisplay *gdisp) iwd->imageheight = newheight; /* Normalise */ - iwd->dispwidth = MIN(iwd->dispwidth, iwd->pwidth-BORDER_PEN_WIDTH); - iwd->dispheight = MIN(iwd->dispheight, iwd->pheight-BORDER_PEN_WIDTH); + iwd->dispwidth = MIN(iwd->dispwidth, iwd->pwidth/*-BORDER_PEN_WIDTH*/); + iwd->dispheight = MIN(iwd->dispheight, iwd->pheight/*-BORDER_PEN_WIDTH*/); if(need_update == TRUE) { @@ -173,6 +189,7 @@ nav_window_disp_area(NavWinData *iwd,GDisplay *gdisp) nav_window_draw_sqr(iwd,FALSE, iwd->dispx,iwd->dispy, iwd->dispwidth,iwd->dispheight); + gtk_window_set_focus(GTK_WINDOW (iwd->info_win->shell),iwd->preview); } } @@ -189,15 +206,14 @@ nav_window_draw_sqr(NavWinData *iwd, gdisp = (GDisplay *) iwd->gdisp_ptr; gdk_gc_set_function (iwd->gc, GDK_INVERT); - - + if(undraw) { /* first undraw from last co-ords */ gdk_draw_rectangle (iwd->preview->window, iwd->gc, FALSE, iwd->dispx,iwd->dispy, - iwd->dispwidth, - iwd->dispheight); + iwd->dispwidth-BORDER_PEN_WIDTH+1, + iwd->dispheight-BORDER_PEN_WIDTH+1); } /* gdk_draw_rectangle (iwd->preview->window, iwd->gc, FALSE, */ @@ -206,8 +222,8 @@ nav_window_draw_sqr(NavWinData *iwd, gdk_draw_rectangle (iwd->preview->window, iwd->gc, FALSE, x,y, - w, - h); + w-BORDER_PEN_WIDTH+1, + h-BORDER_PEN_WIDTH+1); iwd->dispx = x; iwd->dispy = y; @@ -274,11 +290,11 @@ create_preview_widget(NavWinData *iwd) gtk_container_add(GTK_CONTAINER (iwd->previewAlign),hbox); image = gtk_preview_new (GTK_PREVIEW_COLOR); + gtk_widget_set_events( GTK_WIDGET(image), PREVIEW_MASK ); iwd->preview = image; gtk_widget_show (image); gtk_preview_set_dither (GTK_PREVIEW (image), GDK_RGB_DITHER_MAX); - gtk_widget_set_events( GTK_WIDGET(image), PREVIEW_MASK ); set_size_data(iwd); @@ -308,7 +324,7 @@ create_preview_widget(NavWinData *iwd) /* (GtkSignalFunc) nav_window_preview_resized, */ /* iwd); */ - gtk_widget_grab_focus(image); + GTK_WIDGET_SET_FLAGS (image, GTK_CAN_FOCUS); } #if 0 @@ -342,16 +358,29 @@ update_real_view(NavWinData *iwd,gint tx,gint ty) gdouble ratio; gint xoffset; gint yoffset; + gint xpnt; + gint ypnt; gdisp = (GDisplay *) iwd->gdisp_ptr; ratio = ((gdouble)SCALEDEST(gdisp))/((gdouble)SCALESRC(gdisp)); - xoffset = tx - iwd->dispx; - yoffset = ty - iwd->dispy; - - xoffset = (gint)(((gdouble)xoffset*ratio)/iwd->ratio); - yoffset = (gint)(((gdouble)yoffset*ratio)/iwd->ratio); + if((tx + iwd->dispwidth) >= iwd->pwidth) + { + tx = iwd->pwidth; /* Actually should be less... + * but bound check will save us. + */ + } + xpnt = (gint)(((gdouble)(tx)*ratio)/iwd->ratio); + + if((ty + iwd->dispheight) >= iwd->pheight) + ty = iwd->pheight; /* Same comment as for xpnt above. */ + + ypnt = (gint)(((gdouble)(ty)*ratio)/iwd->ratio); + + xoffset = xpnt - gdisp->offset_x; + yoffset = ypnt - gdisp->offset_y; + iwd->block_window_marker = TRUE; scroll_display(iwd->gdisp_ptr,xoffset,yoffset); iwd->block_window_marker = FALSE; @@ -506,6 +535,50 @@ nav_window_preview_resized (GtkWidget *widget, } #endif /* 0 */ +static void +move_to_point(NavWinData *iwd, + gint tx, + gint ty) +{ + if(tx < 0) + { + tx = 0; + } + + if(tx > iwd->pwidth) + { + tx = iwd->pwidth; + } + + if(ty < 0) + { + ty = 0; + } + + if(ty > iwd->pheight) + { + ty = iwd->pwidth; + } + + if((tx + iwd->dispwidth) >= iwd->pwidth) + { + tx = iwd->pwidth - iwd->dispwidth; + } + + if((ty + iwd->dispheight) >= iwd->pheight) + { + ty = iwd->pheight - iwd->dispheight; + } + + /* Update the real display */ + update_real_view(iwd,tx,ty); + + nav_window_draw_sqr(iwd, + TRUE, + tx,ty, + iwd->dispwidth,iwd->dispheight); + +} static gint nav_window_preview_events (GtkWidget *widget, @@ -516,9 +589,11 @@ nav_window_preview_events (GtkWidget *widget, GDisplay *gdisp; GdkEventButton *bevent; GdkEventMotion *mevent; + GdkEventKey *kevent; GdkModifierType mask; - gint tx,ty; + gint tx = 0,ty = 0; /* So compiler complaints */ gint mx,my; + gboolean arrowKey = FALSE; iwd = (NavWinData *)data; @@ -608,7 +683,53 @@ nav_window_preview_events (GtkWidget *widget, break; } break; + case GDK_KEY_PRESS: + /* hack for the update preview... needs to be fixed */ + kevent = (GdkEventKey *) event; + + switch (kevent->keyval) + { + case GDK_space: + gdk_window_raise(gdisp->shell->window); + nav_window_update_preview(iwd); + gtk_widget_draw(iwd->preview, NULL); + break; + case GDK_Up: + arrowKey = TRUE; + tx = iwd->dispx; + ty = iwd->dispy - 1; + break; + case GDK_Left: + arrowKey = TRUE; + tx = iwd->dispx - 1; + ty = iwd->dispy; + break; + case GDK_Right: + arrowKey = TRUE; + tx = iwd->dispx + 1; + ty = iwd->dispy; + break; + case GDK_Down: + arrowKey = TRUE; + tx = iwd->dispx; + ty = iwd->dispy + 1; + break; + case GDK_equal: + change_scale(gdisp,ZOOMIN); + break; + case GDK_minus: + change_scale(gdisp,ZOOMOUT); + break; + default: + break; + } + if(arrowKey) + { + move_to_point(iwd,tx,ty); + return TRUE; + } + break; case GDK_MOTION_NOTIFY: mevent = (GdkEventMotion *) event; @@ -622,44 +743,7 @@ nav_window_preview_events (GtkWidget *widget, tx = tx - iwd->motion_offsetx; ty = ty - iwd->motion_offsety; - if(tx < 0) - { - tx = 0; - } - - if(tx > iwd->pwidth) - { - tx = iwd->pwidth; - } - - if(ty < 0) - { - ty = 0; - } - - if(ty > iwd->pheight) - { - ty = iwd->pwidth; - } - - if((tx + iwd->dispwidth) >= iwd->pwidth) - { - tx = iwd->pwidth - iwd->dispwidth; - } - - if((ty + iwd->dispheight) >= iwd->pheight) - { - ty = iwd->pheight - iwd->dispheight; - } - - /* Update the real display */ - update_real_view(iwd,tx,ty); - - nav_window_draw_sqr(iwd, - TRUE, - tx,ty, - iwd->dispwidth,iwd->dispheight); - + move_to_point(iwd,tx,ty); break; default: @@ -695,11 +779,6 @@ nav_window_expose_events (GtkWidget *widget, iwd->dispx,iwd->dispy, iwd->dispwidth,iwd->dispheight); - break; - case GDK_KEY_PRESS: - /* hack for the update preview... needs to be fixed */ - nav_window_update_preview(iwd); - gtk_widget_draw(iwd->preview, NULL); break; default: break; @@ -767,12 +846,17 @@ nav_window_create (void *gdisp_ptr) /* create the info dialog */ title_buf = g_strdup_printf (_("%s: Window Navigation"), title); info_win = info_dialog_new (title_buf); + dialog_register(info_win->shell); + gtk_signal_connect (GTK_OBJECT (info_win->shell), "destroy", + (GtkSignalFunc) nav_window_destroy_callback, + info_win); g_free (title_buf); /* gtk_window_set_policy (GTK_WINDOW (info_win->shell), */ /* FALSE,FALSE,FALSE); */ iwd = (NavWinData *) g_malloc (sizeof (NavWinData)); info_win->user_data = iwd; + iwd->info_win = info_win; iwd->showingPreview = TRUE; iwd->preview = NULL; iwd->gdisp_ptr = gdisp_ptr; @@ -790,6 +874,8 @@ nav_window_create (void *gdisp_ptr) /* Add preview */ container = info_window_image_preview_new(info_win); +/* gtk_container_set_focus_child(GTK_CONTAINER(container),iwd->preview); */ + gtk_window_set_focus(GTK_WINDOW (info_win->shell),iwd->preview); gtk_table_attach_defaults (GTK_TABLE (info_win->info_table), container, 0, 2, 0, 1); /* Create the action area */ diff --git a/app/widgets/gimpitemfactory.c b/app/widgets/gimpitemfactory.c index cec1ad6531..01c191cf94 100644 --- a/app/widgets/gimpitemfactory.c +++ b/app/widgets/gimpitemfactory.c @@ -21,6 +21,7 @@ #include "channels_dialog.h" #include "colormaps.h" #include "commands.h" +#include "dialog_handler.h" #include "fileops.h" #include "general.h" #include "gimprc.h" @@ -47,12 +48,15 @@ static char* G_GNUC_UNUSED dummyMRU = N_("/File/MRU00 "); static void menus_init (void); static gchar* menu_translate (const gchar *path, gpointer data); +static void tearoff_cmd_callback (GtkWidget *widget, + gpointer callback_data, + guint callback_action); static GSList *last_opened_raw_filenames = NULL; static GtkItemFactoryEntry toolbox_entries[] = { - { N_("/File/tearoff1"), NULL, NULL, 0, "" }, + { N_("/File/tearoff1"), NULL, tearoff_cmd_callback, 0, "" }, { N_("/File/New"), "N", file_new_cmd_callback, 0 }, { N_("/File/Open"), "O", file_open_cmd_callback, 0 }, { N_("/File/About..."), NULL, about_dialog_cmd_callback, 0 }, @@ -70,7 +74,7 @@ static GtkItemFactoryEntry toolbox_entries[] = { N_("/File/Dialogs/Document Index..."), NULL, raise_idea_callback, 0 }, { N_("/File/Dialogs/Error Console..."), NULL, dialogs_error_console_cmd_callback, 0 }, - { N_("/Xtns/tearoff1"), NULL, NULL, 0, "" }, + { N_("/Xtns/tearoff1"), NULL, tearoff_cmd_callback, 0, "" }, { N_("/Xtns/Module Browser"), NULL, dialogs_module_browser_cmd_callback, 0 }, { N_("/File/---"), NULL, NULL, 0, "" }, { N_("/File/---"), NULL, NULL, 0, "" } @@ -83,8 +87,8 @@ static GtkItemFactoryEntry toolbox_end = { N_("/File/Quit"), "Q", file_ static GtkItemFactoryEntry image_entries[] = { - { N_("/tearoff1"), NULL, NULL, 0, "" }, - { N_("/File/tearoff1"), NULL, NULL, 0, "" }, + { N_("/tearoff1"), NULL, tearoff_cmd_callback, 0, "" }, + { N_("/File/tearoff1"), NULL, tearoff_cmd_callback, 0, "" }, { N_("/File/New"), "N", file_new_cmd_callback, 1 }, { N_("/File/Open"), "O", file_open_cmd_callback, 0 }, { N_("/File/Save"), "S", file_save_cmd_callback, 0 }, @@ -97,7 +101,7 @@ static GtkItemFactoryEntry image_entries[] = { N_("/File/Quit"), "Q", file_quit_cmd_callback, 0 }, { N_("/File/---moved"), NULL, NULL, 0, "" }, - { N_("/Edit/tearoff1"), NULL, NULL, 0, "" }, + { N_("/Edit/tearoff1"), NULL, tearoff_cmd_callback, 0, "" }, { N_("/Edit/Cut"), "X", edit_cut_cmd_callback, 0 }, { N_("/Edit/Copy"), "C", edit_copy_cmd_callback, 0 }, { N_("/Edit/Paste"), "V", edit_paste_cmd_callback, 0 }, @@ -115,7 +119,7 @@ static GtkItemFactoryEntry image_entries[] = { N_("/Edit/Paste Named"), "V", edit_named_paste_cmd_callback, 0 }, { N_("/Edit/---"), NULL, NULL, 0, "" }, - { N_("/Select/tearoff1"), NULL, NULL, 0, "" }, + { N_("/Select/tearoff1"), NULL, tearoff_cmd_callback, 0, "" }, { N_("/Select/Invert"), "I", select_invert_cmd_callback, 0 }, { N_("/Select/All"), "A", select_all_cmd_callback, 0 }, { N_("/Select/None"), "A", select_none_cmd_callback, 0 }, @@ -129,7 +133,7 @@ static GtkItemFactoryEntry image_entries[] = { N_("/Select/---"), NULL, NULL, 0, "" }, { N_("/Select/Save To Channel"), NULL, select_save_cmd_callback, 0 }, - { N_("/View/tearoff1"), NULL, NULL, 0, "" }, + { N_("/View/tearoff1"), NULL, tearoff_cmd_callback, 0, "" }, { N_("/View/Zoom In"), "equal", view_zoomin_cmd_callback, 0 }, { N_("/View/Zoom Out"), "minus", view_zoomout_cmd_callback, 0 }, { N_("/View/Zoom/16:1"), NULL, view_zoom_16_1_callback, 0 }, @@ -156,16 +160,16 @@ static GtkItemFactoryEntry image_entries[] = { N_("/View/New View"), NULL, view_new_view_cmd_callback, 0 }, { N_("/View/Shrink Wrap"), "E", view_shrink_wrap_cmd_callback, 0 }, - { N_("/Image/tearoff1"), NULL, NULL, 0, "" }, - { N_("/Image/Colors/tearoff1"), NULL, NULL, 0, "" }, + { N_("/Image/tearoff1"), NULL, tearoff_cmd_callback, 0, "" }, + { N_("/Image/Colors/tearoff1"), NULL, tearoff_cmd_callback, 0, "" }, { N_("/Image/Colors/Equalize"), NULL, image_equalize_cmd_callback, 0 }, { N_("/Image/Colors/Invert"), NULL, image_invert_cmd_callback, 0 }, { N_("/Image/Colors/---"), NULL, NULL, 0, "" }, { N_("/Image/Colors/Desaturate"), NULL, image_desaturate_cmd_callback, 0 }, - { N_("/Image/Channel Ops/tearoff1"), NULL, NULL, 0, "" }, + { N_("/Image/Channel Ops/tearoff1"), NULL, tearoff_cmd_callback, 0, "" }, { N_("/Image/Channel Ops/Duplicate"), "D", channel_ops_duplicate_cmd_callback, 0 }, { N_("/Image/Channel Ops/Offset"), "O", channel_ops_offset_cmd_callback, 0 }, - { N_("/Image/Alpha/tearoff1"), NULL, NULL, 0, "" }, + { N_("/Image/Alpha/tearoff1"), NULL, tearoff_cmd_callback, 0, "" }, { N_("/Image/Alpha/Add Alpha Channel"), NULL, layers_add_alpha_channel_cmd_callback, 0 }, { N_("/Image/---"), NULL, NULL, 0, "" }, @@ -177,9 +181,9 @@ static GtkItemFactoryEntry image_entries[] = { N_("/Image/Scale"), NULL, image_scale_cmd_callback, 0 }, { N_("/Image/---"), NULL, NULL, 0, "" }, - { N_("/Layers/tearoff1"), NULL, NULL, 0, "" }, + { N_("/Layers/tearoff1"), NULL, tearoff_cmd_callback, 0, "" }, { N_("/Layers/Layers & Channels..."), "L", dialogs_lc_cmd_callback, 0 }, - { N_("/Layers/Stack/tearoff1"), NULL, NULL, 0, "" }, + { N_("/Layers/Stack/tearoff1"), NULL, tearoff_cmd_callback, 0, "" }, { N_("/Layers/Stack/Previous Layer"), "Prior", layers_previous_cmd_callback, 0 }, { N_("/Layers/Stack/Next Layer"), "Next", layers_next_cmd_callback, 0 }, { N_("/Layers/Stack/Raise Layer"), "Prior", layers_raise_cmd_callback, 0 }, @@ -195,7 +199,7 @@ static GtkItemFactoryEntry image_entries[] = { N_("/Layers/Add Alpha Channel"), NULL, layers_add_alpha_channel_cmd_callback, 0 }, { N_("/Layers/---"), NULL, NULL, 0, "" }, - { N_("/Tools/tearoff1"), NULL, NULL, 0, "" }, + { N_("/Tools/tearoff1"), NULL, tearoff_cmd_callback, 0, "" }, { N_("/Tools/Toolbox"), NULL, toolbox_raise_callback, 0 }, { N_("/Tools/Default Colors"), "D", tools_default_colors_cmd_callback, 0 }, { N_("/Tools/Swap Colors"), "X", tools_swap_colors_cmd_callback, 0 }, @@ -203,15 +207,15 @@ static GtkItemFactoryEntry image_entries[] = /* the tool entries themselves are built on the fly */ - { N_("/Filters/tearoff1"), NULL, NULL, 0, "" }, + { N_("/Filters/tearoff1"), NULL, tearoff_cmd_callback, 0, "" }, { N_("/Filters/Repeat last"), "F", filters_repeat_cmd_callback, 0x0 }, { N_("/Filters/Re-show last"), "F", filters_repeat_cmd_callback, 0x1 }, { N_("/Filters/---"), NULL, NULL, 0, "" }, - { N_("/Script-Fu/tearoff1"), NULL, NULL, 0, "" }, + { N_("/Script-Fu/tearoff1"), NULL, tearoff_cmd_callback, 0, "" }, { N_("/Script-Fu/"), NULL, NULL, 0 }, - { N_("/Dialogs/tearoff1"), NULL, NULL, 0, "" }, + { N_("/Dialogs/tearoff1"), NULL, tearoff_cmd_callback, 0, "" }, { N_("/Dialogs/Brushes..."), "B", dialogs_brushes_cmd_callback, 0 }, { N_("/Dialogs/Patterns..."), "P", dialogs_patterns_cmd_callback, 0 }, { N_("/Dialogs/Palette..."), "P", dialogs_palette_cmd_callback, 0 }, @@ -426,7 +430,8 @@ menus_create (GtkMenuEntry *entries, { GtkItemFactoryEntry entry = { NULL, NULL, NULL, 0, "" }; entry.path = tearoff_path->str; - gtk_item_factory_create_items (image_factory, 1, &entry, NULL); + entry.callback = tearoff_cmd_callback; + gtk_item_factory_create_items_ac (image_factory, 1, &entry, NULL,2); } p = strchr (p + 1, '/'); @@ -822,3 +827,57 @@ menu_translate (const gchar *path, { return gettext (path); } + +static gint +tearoff_delete_cb (GtkWidget *widget, + GdkEvent *event, + gpointer data) +{ + /* Unregister if dialog is deleted as well */ + dialog_unregister((GtkWidget *)data); + return TRUE; +} + +static void +tearoff_cmd_callback (GtkWidget *widget, + gpointer callback_data, + guint callback_action) +{ + if(GTK_IS_TEAROFF_MENU_ITEM(widget)) + { + GtkTearoffMenuItem *tomi = (GtkTearoffMenuItem *)widget; + + if(tomi->torn_off) + { + GtkWidget *top = gtk_widget_get_toplevel(widget); + + /* This should be a window */ + if(!GTK_IS_WINDOW(top)) + { + g_message(_("tearoff menu not in top level window")); + } + else + { + dialog_register(top); + gtk_signal_connect_object (GTK_OBJECT (top), + "delete_event", + GTK_SIGNAL_FUNC (tearoff_delete_cb), + GTK_OBJECT (top)); + + gtk_object_set_data (GTK_OBJECT (widget),"tearoff_menu_top",top); + } + } + else + { + GtkWidget *top = (GtkWidget *)gtk_object_get_data (GTK_OBJECT (widget),"tearoff_menu_top"); + if(!top) + { + g_message(_("can't unregister tearoff menu top level window")); + } + else + { + dialog_unregister(top); + } + } + } +}