[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

gEDA-cvs: pcb.git: branch: master updated (94bad9f93afb9c18e314519d9e943ba2164f3571)



The branch, master has been updated
       via  94bad9f93afb9c18e314519d9e943ba2164f3571 (commit)
       via  6fc0a418fb9f209b01a9525a8f762fb560bc897d (commit)
      from  e26a2968ba2419a4c55fb68ae9c92f0278322acb (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.


=========
 Summary
=========

 src/autoroute.c           |   39 ++++++++-
 src/hid/gtk/gtkhid-main.c |  208 ++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 243 insertions(+), 4 deletions(-)


=================
 Commit Messages
=================

commit 94bad9f93afb9c18e314519d9e943ba2164f3571
Author: Peter Clifton <pcjc2@xxxxxxxxx>
Commit: Peter Clifton <pcjc2@xxxxxxxxx>

    autoroute.c: Provide a progress update for the autorouter
    
    Provide a completion metric related to what pass the auto-router
    is processing, how many objects on its heap within a given pass
    it has processed, and how many sub-nets it has routed from the total.
    
    The progress isn't entirely linear, but the subdivision of process
    steps means it does at least march along without too many pauses.
    
    It is now possible to cancel the autorouting with a non-zero response
    code from the gui's progress dialog.
    
    Tested with the GTK HID, Lesstif doesn't yet have an implementation
    for HID->progress()

:100644 100644 1669a36... 8aca7d0... M	src/autoroute.c

commit 6fc0a418fb9f209b01a9525a8f762fb560bc897d
Author: Peter Clifton <pcjc2@xxxxxxxxx>
Commit: Peter Clifton <pcjc2@xxxxxxxxx>

    hid/gtk: Provide a simple progress dialog implementation

:100644 100644 fd092c6... 963a691... M	src/hid/gtk/gtkhid-main.c

=========
 Changes
=========

commit 94bad9f93afb9c18e314519d9e943ba2164f3571
Author: Peter Clifton <pcjc2@xxxxxxxxx>
Commit: Peter Clifton <pcjc2@xxxxxxxxx>

    autoroute.c: Provide a progress update for the autorouter
    
    Provide a completion metric related to what pass the auto-router
    is processing, how many objects on its heap within a given pass
    it has processed, and how many sub-nets it has routed from the total.
    
    The progress isn't entirely linear, but the subdivision of process
    steps means it does at least march along without too many pauses.
    
    It is now possible to cancel the autorouting with a non-zero response
    code from the gui's progress dialog.
    
    Tested with the GTK HID, Lesstif doesn't yet have an implementation
    for HID->progress()

diff --git a/src/autoroute.c b/src/autoroute.c
index 1669a36..8aca7d0 100644
--- a/src/autoroute.c
+++ b/src/autoroute.c
@@ -4644,12 +4644,28 @@ struct routeall_status
   int ripped;
   int total_nets_routed;
 };
+
+static double
+calculate_progress (double this_heap_item, double this_heap_size,
+                    struct routeall_status *ras)
+{
+  double total_passes = passes + smoothes + 1;      /* + 1 is the refinement pass */
+  double this_pass = AutoRouteParameters.pass - 1; /* Number passes from zero */
+  double heap_fraction = (double)(ras->routed_subnets + ras->conflict_subnets + ras->failed) /
+                         (double)ras->total_subnets;
+  double pass_fraction = (this_heap_item + heap_fraction ) / this_heap_size;
+  double process_fraction = (this_pass + pass_fraction) / total_passes;
+
+  return process_fraction;
+}
+
 struct routeall_status
 RouteAll (routedata_t * rd)
 {
   struct routeall_status ras;
   struct routeone_status ros;
   bool rip;
+  int request_cancel;
 #ifdef NET_HEAP
   heap_t *net_heap;
 #endif
@@ -4657,6 +4673,8 @@ RouteAll (routedata_t * rd)
   routebox_t *net, *p, *pp;
   cost_t total_net_cost, last_cost = 0, this_cost = 0;
   int i;
+  int this_heap_size;
+  int this_heap_item;
 
   /* initialize heap for first pass; 
    * do smallest area first; that makes
@@ -4698,7 +4716,8 @@ RouteAll (routedata_t * rd)
 	ras.failed = ras.ripped = 0;
       assert (heap_is_empty (next_pass));
 
-      while (!heap_is_empty (this_pass))
+      this_heap_size = heap_size (this_pass);
+      for (this_heap_item = 0; !heap_is_empty (this_pass); this_heap_item++)
 	{
 #ifdef ROUTE_DEBUG
 	  if (aabort)
@@ -4822,6 +4841,8 @@ RouteAll (routedata_t * rd)
 
 	      while (!ros.net_completely_routed)
 		{
+		  double percent;
+
 		  assert (no_expansion_boxes (rd));
 		  /* FIX ME: the number of edges to examine should be in autoroute parameters
 		   * i.e. the 2000 and 800 hard-coded below should be controllable by the user
@@ -4857,6 +4878,16 @@ RouteAll (routedata_t * rd)
 		   * on the number of calls to RouteOne, because we may be unable
 		   * to route a net from a particular starting point, but perfectly
 		   * able to route it from some other. */
+		  percent = calculate_progress (this_heap_item, this_heap_size, &ras);
+		  request_cancel = gui->progress (percent * 100., 100,
+						  _("Autorouting tracks"));
+		  if (request_cancel)
+		    {
+		      ras.total_nets_routed = 0;
+		      ras.conflict_subnets = 0;
+		      Message ("Autorouting cancelled\n");
+		      goto out;
+		    }
 		}
 	    }
 #ifndef NET_HEAP
@@ -4887,7 +4918,6 @@ RouteAll (routedata_t * rd)
       tmp = this_pass;
       this_pass = next_pass;
       next_pass = tmp;
-      /* XXX: here we should update a status bar */
 #if defined(ROUTE_DEBUG) || defined (ROUTE_VERBOSE)
       printf
 	("END OF PASS %d: %d/%d subnets routed without conflicts at cost %.0f, %d conflicts, %d failed %d ripped\n",
@@ -4908,9 +4938,11 @@ RouteAll (routedata_t * rd)
       last_cost = this_cost;
       this_cost = 0;
     }
+
   Message ("%d of %d nets successfully routed.\n",
 	   ras.routed_subnets, ras.total_subnets);
 
+out:
   heap_destroy (&this_pass);
   heap_destroy (&next_pass);
 #ifdef NET_HEAP
@@ -5286,7 +5318,8 @@ AutoRoute (bool selected)
   /* auto-route all nets */
   changed = (RouteAll (rd).total_nets_routed > 0) || changed;
 donerouting:
-  if (changed && TEST_FLAG (LIVEROUTEFLAG, PCB))
+  gui->progress (0, 0, NULL);
+  if (TEST_FLAG (LIVEROUTEFLAG, PCB))
     {
       int i;
       BoxType big = {0, 0, MAX_COORD, MAX_COORD};

commit 6fc0a418fb9f209b01a9525a8f762fb560bc897d
Author: Peter Clifton <pcjc2@xxxxxxxxx>
Commit: Peter Clifton <pcjc2@xxxxxxxxx>

    hid/gtk: Provide a simple progress dialog implementation

diff --git a/src/hid/gtk/gtkhid-main.c b/src/hid/gtk/gtkhid-main.c
index fd092c6..963a691 100644
--- a/src/hid/gtk/gtkhid-main.c
+++ b/src/hid/gtk/gtkhid-main.c
@@ -739,10 +739,216 @@ ghid_beep ()
   gdk_beep ();
 }
 
+struct progress_dialog
+{
+  GtkWidget *dialog;
+  GtkWidget *message;
+  GtkWidget *progress;
+  gint response_id;
+  GMainLoop *loop;
+  gboolean destroyed;
+  gboolean stop_loop;
+  gboolean started;
+  GTimer *timer;
+
+  gulong response_handler;
+  gulong unmap_handler;
+  gulong destroy_handler;
+  gulong delete_handler;
+};
+
+static void
+run_unmap_handler (GtkDialog *dialog, gpointer data)
+{
+  struct progress_dialog *pd = data;
+
+  pd->stop_loop = TRUE;
+}
+
+static void
+run_response_handler (GtkDialog *dialog,
+                      gint response_id,
+                      gpointer data)
+{
+  struct progress_dialog *pd = data;
+
+  pd->response_id = response_id;
+  pd->stop_loop = TRUE;
+}
+
+static gint
+run_delete_handler (GtkDialog *dialog,
+                    GdkEventAny *event,
+                    gpointer data)
+{
+  struct progress_dialog *pd = data;
+
+  pd->stop_loop = TRUE;
+
+  return TRUE; /* Do not destroy */
+}
+
+static void
+run_destroy_handler (GtkDialog *dialog, gpointer data)
+{
+  struct progress_dialog *pd = data;
+
+  /* stop_loop will be set by run_unmap_handler */
+
+  pd->destroyed = TRUE;
+}
+
+static struct progress_dialog *
+make_progress_dialog (void)
+{
+  struct progress_dialog *pd;
+  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 (false, 0);
+  gtk_box_pack_start (GTK_BOX (vbox), pd->message, true, true, 8);
+  gtk_box_pack_start (GTK_BOX (vbox), pd->progress, false, 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);
+
+  gtk_box_pack_start (GTK_BOX (GTK_DIALOG (pd->dialog)->vbox),
+                      alignment, true, 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->unmap_handler =
+    g_signal_connect (pd->dialog, "unmap",
+                      G_CALLBACK (run_unmap_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->unmap_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)
 {
-  return 0;
+  static struct progress_dialog *pd = NULL;
+  int retval = 0;
+
+  /* If we are finished, destroy any dialog */
+  if (so_far == 0 && total == 0 && message == NULL)
+    {
+      destroy_progress_dialog (pd);
+      pd = NULL;
+      return retval;
+    }
+
+  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;
+
+  if (pd->stop_loop)
+    {
+      retval = (pd->response_id == GTK_RESPONSE_CANCEL ||
+                pd->response_id == GTK_RESPONSE_DELETE_EVENT ||
+                pd->response_id == GTK_RESPONSE_NONE);
+      destroy_progress_dialog (pd);
+      pd = NULL;
+    }
+
+  return retval;
 }
 
 /* ---------------------------------------------------------------------- */




_______________________________________________
geda-cvs mailing list
geda-cvs@xxxxxxxxxxxxxx
http://www.seul.org/cgi-bin/mailman/listinfo/geda-cvs