Index: trunk/scconfig/Rev.h =================================================================== --- trunk/scconfig/Rev.h (revision 6704) +++ trunk/scconfig/Rev.h (revision 6705) @@ -1 +1 @@ -static const int myrev = 6703; +static const int myrev = 6705; Index: trunk/scconfig/Rev.tab =================================================================== --- trunk/scconfig/Rev.tab (revision 6704) +++ trunk/scconfig/Rev.tab (revision 6705) @@ -1,4 +1,4 @@ -6703 configure gtk splitup +6705 configure gtk splitup 6392 configure draw cross section plugin (gtk and lesstif depend on it) 6365 configure gtk splitup 6111 configure layer vs. layer group code split Index: trunk/src_plugins/hid_gtk/gtkhid-main.c =================================================================== --- trunk/src_plugins/hid_gtk/gtkhid-main.c (revision 6704) +++ trunk/src_plugins/hid_gtk/gtkhid-main.c (revision 6705) @@ -42,6 +42,7 @@ #include "../src_plugins/lib_gtk_common/dlg_input.h" #include "../src_plugins/lib_gtk_common/dlg_message.h" #include "../src_plugins/lib_gtk_common/dlg_print.h" +#include "../src_plugins/lib_gtk_common/dlg_progress.h" #include "../src_plugins/lib_gtk_common/dlg_report.h" #include "../src_plugins/lib_gtk_common/dlg_pinout.h" #include "../src_plugins/lib_gtk_common/dlg_search.h" @@ -241,165 +242,12 @@ gdk_beep(); } -struct progress_dialog { - GtkWidget *dialog; - GtkWidget *message; - GtkWidget *progress; - gint response_id; - GMainLoop *loop; - gboolean destroyed; - gboolean started; - GTimer *timer; - - gulong response_handler; - gulong destroy_handler; - gulong delete_handler; -}; - -static void run_response_handler(GtkDialog * dialog, gint response_id, gpointer data) +int ghid_progress(int so_far, int total, const char *message) { - struct progress_dialog *pd = data; - - pd->response_id = response_id; + return pcb_gtk_dlg_progress(ghid_port.top_window, so_far, total, message); } -static gint run_delete_handler(GtkDialog * dialog, GdkEventAny * event, gpointer data) -{ - struct progress_dialog *pd = data; - pd->response_id = GTK_RESPONSE_DELETE_EVENT; - - return TRUE; /* Do not destroy */ -} - -static void run_destroy_handler(GtkDialog * dialog, gpointer data) -{ - struct progress_dialog *pd = data; - - pd->destroyed = TRUE; -} - -static struct progress_dialog *make_progress_dialog(void) -{ - struct progress_dialog *pd; - GtkWidget *content_area; - GtkWidget *alignment; - GtkWidget *vbox; - - pd = g_new0(struct progress_dialog, 1); - pd->response_id = GTK_RESPONSE_NONE; - - pd->dialog = gtk_dialog_new_with_buttons(_("Progress"), GTK_WINDOW(gport->top_window), - /* Modal so nothing else can get events whilst - the main mainloop isn't running */ - GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, NULL); - - gtk_window_set_deletable(GTK_WINDOW(pd->dialog), FALSE); - gtk_window_set_skip_pager_hint(GTK_WINDOW(pd->dialog), TRUE); - gtk_window_set_skip_taskbar_hint(GTK_WINDOW(pd->dialog), TRUE); - gtk_widget_set_size_request(pd->dialog, 300, -1); - - pd->message = gtk_label_new(NULL); - gtk_misc_set_alignment(GTK_MISC(pd->message), 0., 0.); - - pd->progress = gtk_progress_bar_new(); - gtk_widget_set_size_request(pd->progress, -1, 26); - - vbox = gtk_vbox_new(pcb_false, 0); - gtk_box_pack_start(GTK_BOX(vbox), pd->message, pcb_true, pcb_true, 8); - gtk_box_pack_start(GTK_BOX(vbox), pd->progress, pcb_false, pcb_true, 8); - - alignment = gtk_alignment_new(0., 0., 1., 1.); - gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 8, 8, 8, 8); - gtk_container_add(GTK_CONTAINER(alignment), vbox); - - content_area = gtk_dialog_get_content_area(GTK_DIALOG(pd->dialog)); - gtk_box_pack_start(GTK_BOX(content_area), alignment, pcb_true, pcb_true, 0); - - gtk_widget_show_all(alignment); - - g_object_ref(pd->dialog); - gtk_window_present(GTK_WINDOW(pd->dialog)); - - pd->response_handler = g_signal_connect(pd->dialog, "response", G_CALLBACK(run_response_handler), pd); - pd->delete_handler = g_signal_connect(pd->dialog, "delete-event", G_CALLBACK(run_delete_handler), pd); - pd->destroy_handler = g_signal_connect(pd->dialog, "destroy", G_CALLBACK(run_destroy_handler), pd); - - pd->loop = g_main_loop_new(NULL, FALSE); - pd->timer = g_timer_new(); - - return pd; -} - -static void destroy_progress_dialog(struct progress_dialog *pd) -{ - if (pd == NULL) - return; - - if (!pd->destroyed) { - g_signal_handler_disconnect(pd->dialog, pd->response_handler); - g_signal_handler_disconnect(pd->dialog, pd->delete_handler); - g_signal_handler_disconnect(pd->dialog, pd->destroy_handler); - } - - g_timer_destroy(pd->timer); - g_object_unref(pd->dialog); - g_main_loop_unref(pd->loop); - - gtk_widget_destroy(pd->dialog); - - pd->loop = NULL; - g_free(pd); -} - -static void handle_progress_dialog_events(struct progress_dialog *pd) -{ - GMainContext *context = g_main_loop_get_context(pd->loop); - - /* Process events */ - while (g_main_context_pending(context)) { - g_main_context_iteration(context, FALSE); - } -} - -#define MIN_TIME_SEPARATION (50./1000.) /* 50ms */ -static int ghid_progress(int so_far, int total, const char *message) -{ - static struct progress_dialog *pd = NULL; - - /* If we are finished, destroy any dialog */ - if (so_far == 0 && total == 0 && message == NULL) { - destroy_progress_dialog(pd); - pd = NULL; - return 0; - } - - if (pd == NULL) - pd = make_progress_dialog(); - - /* We don't want to keep the underlying process too busy whilst we - * process events. If we get called quickly after the last progress - * update, wait a little bit before we respond - perhaps the next - * time progress is reported. - - * The exception here is that we always want to process the first - * batch of events after having shown the dialog for the first time - */ - if (pd->started && g_timer_elapsed(pd->timer, NULL) < MIN_TIME_SEPARATION) - return 0; - - gtk_label_set_text(GTK_LABEL(pd->message), message); - gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(pd->progress), (double) so_far / (double) total); - - handle_progress_dialog_events(pd); - g_timer_start(pd->timer); - - pd->started = TRUE; - - return (pd->response_id == GTK_RESPONSE_CANCEL || pd->response_id == GTK_RESPONSE_DELETE_EVENT) ? 1 : 0; -} - /* ---------------------------------------------------------------------- */ static int ghid_propedit_start(void *pe, int num_props, Index: trunk/src_plugins/lib_gtk_common/Plug.tmpasm =================================================================== --- trunk/src_plugins/lib_gtk_common/Plug.tmpasm (revision 6704) +++ trunk/src_plugins/lib_gtk_common/Plug.tmpasm (revision 6705) @@ -21,6 +21,7 @@ $(PLUGDIR)/lib_gtk_common/dlg_message.o $(PLUGDIR)/lib_gtk_common/dlg_pinout.o $(PLUGDIR)/lib_gtk_common/dlg_print.o + $(PLUGDIR)/lib_gtk_common/dlg_progress.o $(PLUGDIR)/lib_gtk_common/dlg_propedit.o $(PLUGDIR)/lib_gtk_common/dlg_report.o $(PLUGDIR)/lib_gtk_common/dlg_search.o Index: trunk/src_plugins/lib_gtk_common/dlg_progress.c =================================================================== --- trunk/src_plugins/lib_gtk_common/dlg_progress.c (nonexistent) +++ trunk/src_plugins/lib_gtk_common/dlg_progress.c (revision 6705) @@ -0,0 +1,187 @@ +/* + * COPYRIGHT + * + * PCB, interactive printed circuit board design + * Copyright (C) 1994,1995,1996 Thomas Nau + * pcb-rnd Copyright (C) 2017 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include "config.h" +#include "dlg_progress.h" + +#include "pcb_bool.h" +#include "compat_nls.h" + +struct progress_dialog { + GtkWidget *dialog; + GtkWidget *message; + GtkWidget *progress; + gint response_id; + GMainLoop *loop; + gboolean destroyed; + gboolean started; + GTimer *timer; + + gulong response_handler; + gulong destroy_handler; + gulong delete_handler; +}; + +static void run_response_handler(GtkDialog * dialog, gint response_id, gpointer data) +{ + struct progress_dialog *pd = data; + + pd->response_id = response_id; +} + +static gint run_delete_handler(GtkDialog * dialog, GdkEventAny * event, gpointer data) +{ + struct progress_dialog *pd = data; + + pd->response_id = GTK_RESPONSE_DELETE_EVENT; + + return TRUE; /* Do not destroy */ +} + +static void run_destroy_handler(GtkDialog * dialog, gpointer data) +{ + struct progress_dialog *pd = data; + + pd->destroyed = TRUE; +} + +static struct progress_dialog *make_progress_dialog(GtkWidget *top_window) +{ + struct progress_dialog *pd; + GtkWidget *content_area; + GtkWidget *alignment; + GtkWidget *vbox; + + pd = g_new0(struct progress_dialog, 1); + pd->response_id = GTK_RESPONSE_NONE; + + pd->dialog = gtk_dialog_new_with_buttons(_("Progress"), GTK_WINDOW(top_window), + /* Modal so nothing else can get events whilst + the main mainloop isn't running */ + GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, NULL); + + gtk_window_set_deletable(GTK_WINDOW(pd->dialog), FALSE); + gtk_window_set_skip_pager_hint(GTK_WINDOW(pd->dialog), TRUE); + gtk_window_set_skip_taskbar_hint(GTK_WINDOW(pd->dialog), TRUE); + gtk_widget_set_size_request(pd->dialog, 300, -1); + + pd->message = gtk_label_new(NULL); + gtk_misc_set_alignment(GTK_MISC(pd->message), 0., 0.); + + pd->progress = gtk_progress_bar_new(); + gtk_widget_set_size_request(pd->progress, -1, 26); + + vbox = gtk_vbox_new(pcb_false, 0); + gtk_box_pack_start(GTK_BOX(vbox), pd->message, pcb_true, pcb_true, 8); + gtk_box_pack_start(GTK_BOX(vbox), pd->progress, pcb_false, pcb_true, 8); + + alignment = gtk_alignment_new(0., 0., 1., 1.); + gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 8, 8, 8, 8); + gtk_container_add(GTK_CONTAINER(alignment), vbox); + + content_area = gtk_dialog_get_content_area(GTK_DIALOG(pd->dialog)); + gtk_box_pack_start(GTK_BOX(content_area), alignment, pcb_true, pcb_true, 0); + + gtk_widget_show_all(alignment); + + g_object_ref(pd->dialog); + gtk_window_present(GTK_WINDOW(pd->dialog)); + + pd->response_handler = g_signal_connect(pd->dialog, "response", G_CALLBACK(run_response_handler), pd); + pd->delete_handler = g_signal_connect(pd->dialog, "delete-event", G_CALLBACK(run_delete_handler), pd); + pd->destroy_handler = g_signal_connect(pd->dialog, "destroy", G_CALLBACK(run_destroy_handler), pd); + + pd->loop = g_main_loop_new(NULL, FALSE); + pd->timer = g_timer_new(); + + return pd; +} + +static void destroy_progress_dialog(struct progress_dialog *pd) +{ + if (pd == NULL) + return; + + if (!pd->destroyed) { + g_signal_handler_disconnect(pd->dialog, pd->response_handler); + g_signal_handler_disconnect(pd->dialog, pd->delete_handler); + g_signal_handler_disconnect(pd->dialog, pd->destroy_handler); + } + + g_timer_destroy(pd->timer); + g_object_unref(pd->dialog); + g_main_loop_unref(pd->loop); + + gtk_widget_destroy(pd->dialog); + + pd->loop = NULL; + g_free(pd); +} + +static void handle_progress_dialog_events(struct progress_dialog *pd) +{ + GMainContext *context = g_main_loop_get_context(pd->loop); + + /* Process events */ + while (g_main_context_pending(context)) { + g_main_context_iteration(context, FALSE); + } +} + +#define MIN_TIME_SEPARATION (50./1000.) /* 50ms */ +int pcb_gtk_dlg_progress(GtkWidget *top_window, int so_far, int total, const char *message) +{ + static struct progress_dialog *pd = NULL; + + /* If we are finished, destroy any dialog */ + if (so_far == 0 && total == 0 && message == NULL) { + destroy_progress_dialog(pd); + pd = NULL; + return 0; + } + + if (pd == NULL) + pd = make_progress_dialog(top_window); + + /* We don't want to keep the underlying process too busy whilst we + * process events. If we get called quickly after the last progress + * update, wait a little bit before we respond - perhaps the next + * time progress is reported. + + * The exception here is that we always want to process the first + * batch of events after having shown the dialog for the first time + */ + if (pd->started && g_timer_elapsed(pd->timer, NULL) < MIN_TIME_SEPARATION) + return 0; + + gtk_label_set_text(GTK_LABEL(pd->message), message); + gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(pd->progress), (double) so_far / (double) total); + + handle_progress_dialog_events(pd); + g_timer_start(pd->timer); + + pd->started = TRUE; + + return (pd->response_id == GTK_RESPONSE_CANCEL || pd->response_id == GTK_RESPONSE_DELETE_EVENT) ? 1 : 0; +} Index: trunk/src_plugins/lib_gtk_common/dlg_progress.h =================================================================== --- trunk/src_plugins/lib_gtk_common/dlg_progress.h (nonexistent) +++ trunk/src_plugins/lib_gtk_common/dlg_progress.h (revision 6705) @@ -0,0 +1,3 @@ +#include + +int pcb_gtk_dlg_progress(GtkWidget *top_window, int so_far, int total, const char *message);