progress API




Hi,

GtkProgress/GtkProgressBar have serious problems.

 - Only 3 or 4 functions are really needed for 95% of progress  
   interfaces; GtkProgress[Bar] has about 25 functions, and 
   doesn't even include these 3 or 4. This means a steep 
   learning curve.
 - In activity mode, the API involves setting the adjustment 
   to any random value, just to have the side effect of 
   calling the progress bar update function - the adjustment
   is totally ignored in activity mode
 - You set the activity step as a pixel value, which means to 
   set the activity step you basically need to connect to 
   size_allocate
 - There are ctree_set_expander_style() functions, to randomly 
   change look-and-feel for no good reason
 - The split between GtkProgress and GtkProgressBar makes no sense 
   to me whatsoever.
 
This is a big wart on GTK and makes people waste lots of time, both
learning and using the interface.

So, I have added what I feel is the correct API, and marked all the
rest deprecated. However, the changes are 100% backward-compatible and
should break no existing code.

New API:

void       gtk_progress_bar_pulse                (GtkProgressBar *pbar);
void       gtk_progress_bar_set_fraction         (GtkProgressBar *pbar,
                                                  gfloat          fraction);
void       gtk_progress_bar_set_text             (GtkProgressBar *pbar,
                                                  const gchar    *text);
void       gtk_progress_bar_set_pulse_frequency  (GtkProgressBar *pbar,
                                                  gfloat          fraction);
void       gtk_progress_bar_set_orientation      (GtkProgressBar *pbar,
						  GtkProgressBarOrientation orientation);

Rationale:

 - pulse() means "I have made progress but don't know how much."
   Activity mode is entered, and if we're already in activity mode
   the little block moves.
 - set_fraction() means "I have between 0.0 and 1.0 of the task
   finished" and automatically leaves activity mode.
 - set_pulse_frequency() controls the fraction of distance each 
   pulse() moves the activity block; useful to tune the speed of 
   your progress bar
 - set_text() sets any text you want, NOT a format string. 
   If you want a format, just do g_strdup_printf () or something,
   then set the text. This way people don't have to worry about 
   escaping strings, and they can do custom formatting easily.
 - set_orientation() seems pretty questionable to me (since a vertical
   bar is probably not a progress bar, it's probably a range indicator
   of some kind), but is a "why not" sort of thing. I'm willing 
   to take this out.

To know why this patch should go in GTK, just look at the current
GtkProgress/GtkProgressBar docs, and then imagine the same docs
fitting on a single, easy-to-understand page with this new API. Then
try to think of a progress-indication case where this new API is
insufficient or even particularly inconvenient. Can we say "gratuitous
complexity"?

Patch appended.

Havoc

Index: gtkprogress.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkprogress.c,v
retrieving revision 1.8
diff -u -u -r1.8 gtkprogress.c
--- gtkprogress.c	2000/03/14 19:57:24	1.8
+++ gtkprogress.c	2000/03/29 20:10:46
@@ -196,6 +196,7 @@
   progress->y_align = 0.5;
   progress->show_text = FALSE;
   progress->activity_mode = FALSE;
+  progress->use_text_format = TRUE;
 }
 
 static void
@@ -355,6 +356,13 @@
   gchar fmt[10];
 
   src = progress->format;
+
+  /* This is the new supported version of this function */
+  if (!progress->use_text_format)
+    return g_strdup (src);
+
+  /* And here's all the deprecated goo. */
+  
   dest = buf;
  
   while (src && *src)
@@ -609,6 +617,10 @@
   g_return_if_fail (progress != NULL);
   g_return_if_fail (GTK_IS_PROGRESS (progress));
 
+  /* Turn on format, in case someone called
+     gtk_progress_bar_set_text() and turned it off. */
+  progress->use_text_format = TRUE;
+  
   if (format)
     {
       if (progress->format)
Index: gtkprogress.h
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkprogress.h,v
retrieving revision 1.6
diff -u -u -r1.6 gtkprogress.h
--- gtkprogress.h	2000/03/14 19:57:24	1.6
+++ gtkprogress.h	2000/03/29 20:10:46
@@ -62,6 +62,7 @@
 
   guint          show_text : 1;
   guint          activity_mode : 1;
+  guint          use_text_format : 1;
 };
 
 struct _GtkProgressClass
@@ -73,6 +74,9 @@
   void (* act_mode_enter)   (GtkProgress *progress);
 };
 
+
+/* This entire interface is deprecated. Use GtkProgressBar
+   directly. */
 
 GtkType    gtk_progress_get_type            (void);
 void       gtk_progress_set_show_text       (GtkProgress   *progress,
Index: gtkprogressbar.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkprogressbar.c,v
retrieving revision 1.16
diff -u -u -r1.16 gtkprogressbar.c
--- gtkprogressbar.c	1999/02/24 07:35:55	1.16
+++ gtkprogressbar.c	2000/03/29 20:10:46
@@ -52,7 +52,9 @@
   ARG_BAR_STYLE,
   ARG_ACTIVITY_STEP,
   ARG_ACTIVITY_BLOCKS,
-  ARG_DISCRETE_BLOCKS
+  ARG_DISCRETE_BLOCKS,
+  ARG_FRACTION,
+  ARG_PULSE_FREQUENCY
 };
 
 static void gtk_progress_bar_class_init    (GtkProgressBarClass *klass);
@@ -130,7 +132,15 @@
 			   GTK_TYPE_UINT,
 			   GTK_ARG_READWRITE,
 			   ARG_DISCRETE_BLOCKS);
-
+  gtk_object_add_arg_type ("GtkProgressBar::fraction",
+			   GTK_TYPE_FLOAT,
+			   GTK_ARG_READWRITE,
+			   ARG_FRACTION);
+  gtk_object_add_arg_type ("GtkProgressBar::pulse_frequency",
+			   GTK_TYPE_FLOAT,
+			   GTK_ARG_READWRITE,
+			   ARG_FRACTION);
+  
   object_class->set_arg = gtk_progress_bar_set_arg;
   object_class->get_arg = gtk_progress_bar_get_arg;
 
@@ -148,6 +158,7 @@
   pbar->blocks = 10;
   pbar->in_block = -1;
   pbar->orientation = GTK_PROGRESS_LEFT_TO_RIGHT;
+  pbar->pulse_fraction = 0.1;
   pbar->activity_pos = 0;
   pbar->activity_dir = 1;
   pbar->activity_step = 3;
@@ -183,6 +194,12 @@
     case ARG_DISCRETE_BLOCKS:
       gtk_progress_bar_set_discrete_blocks (pbar, GTK_VALUE_UINT (*arg));
       break;
+    case ARG_FRACTION:
+      gtk_progress_bar_set_fraction (pbar, GTK_VALUE_FLOAT (*arg));
+      break;
+    case ARG_PULSE_FREQUENCY:
+      gtk_progress_bar_set_pulse_frequency (pbar, GTK_VALUE_FLOAT (*arg));
+      break;
     default:
       break;
     }
@@ -217,6 +234,12 @@
     case ARG_DISCRETE_BLOCKS:
       GTK_VALUE_UINT (*arg) = pbar->blocks;
       break;
+    case ARG_FRACTION:
+      GTK_VALUE_FLOAT (*arg) = gtk_progress_get_current_percentage (GTK_PROGRESS (pbar));
+      break;
+    case ARG_PULSE_FREQUENCY:
+      GTK_VALUE_FLOAT (*arg) = pbar->pulse_fraction;
+      break;
     default:
       arg->type = GTK_TYPE_INVALID;
       break;
@@ -266,12 +289,16 @@
       if (GTK_PROGRESS (pbar)->activity_mode)
 	{
 	  guint size;
-
+          
 	  /* advance the block */
 
 	  if (pbar->orientation == GTK_PROGRESS_LEFT_TO_RIGHT ||
 	      pbar->orientation == GTK_PROGRESS_RIGHT_TO_LEFT)
 	    {
+              /* Update our activity step. */
+              
+              pbar->activity_step = widget->allocation.width * pbar->pulse_fraction;
+              
 	      size = MAX (2, widget->allocation.width / pbar->activity_blocks);
 
 	      if (pbar->activity_dir == 0)
@@ -298,6 +325,10 @@
 	    }
 	  else
 	    {
+              /* Update our activity step. */
+              
+              pbar->activity_step = widget->allocation.height * pbar->pulse_fraction;
+              
 	      size = MAX (2, widget->allocation.height / pbar->activity_blocks);
 
 	      if (pbar->activity_dir == 0)
@@ -744,6 +775,67 @@
 /*******************************************************************/
 
 void
+gtk_progress_bar_set_fraction (GtkProgressBar *pbar,
+                               gfloat          fraction)
+{
+  g_return_if_fail (pbar != NULL);
+  g_return_if_fail (GTK_IS_PROGRESS_BAR (pbar));
+
+  /* If we know the percentage, we don't want activity mode. */
+  gtk_progress_set_activity_mode (GTK_PROGRESS (pbar), FALSE);
+
+  /* We use the deprecated GtkProgress interface internally.
+     Once everything's been deprecated for a good long time,
+     we can clean up all this code. */
+  gtk_progress_set_percentage (GTK_PROGRESS (pbar), fraction);
+}
+
+void
+gtk_progress_bar_pulse (GtkProgressBar *pbar)
+{  
+  g_return_if_fail (pbar != NULL);
+  g_return_if_fail (GTK_IS_PROGRESS_BAR (pbar));
+
+  /* If we don't know the percentage, we must want activity mode. */
+  gtk_progress_set_activity_mode (GTK_PROGRESS (pbar), TRUE);
+
+  /* Sigh. */
+  gtk_progress_bar_real_update (GTK_PROGRESS (pbar));
+}
+
+void
+gtk_progress_bar_set_text (GtkProgressBar *pbar,
+                           const gchar *text)
+{
+  g_return_if_fail (pbar != NULL);
+  g_return_if_fail (GTK_IS_PROGRESS_BAR (pbar));
+  
+  /* We don't support formats in this interface */
+  GTK_PROGRESS (pbar)->use_text_format = FALSE;
+  
+  if (text && *text)
+    {
+      gtk_progress_set_show_text (GTK_PROGRESS (pbar), TRUE);
+      gtk_progress_set_format_string (GTK_PROGRESS (pbar), text);
+    }
+  else
+    {
+      gtk_progress_set_show_text (GTK_PROGRESS (pbar), FALSE);
+      gtk_progress_set_format_string (GTK_PROGRESS (pbar), "");
+    }
+}
+
+void
+gtk_progress_bar_set_pulse_frequency   (GtkProgressBar *pbar,
+                                        gfloat          fraction)
+{
+  g_return_if_fail (pbar != NULL);
+  g_return_if_fail (GTK_IS_PROGRESS_BAR (pbar));
+  
+  pbar->pulse_fraction = fraction;
+}
+
+void
 gtk_progress_bar_update (GtkProgressBar *pbar,
 			 gfloat          percentage)
 {
@@ -752,7 +844,7 @@
 
   /***********************************************************************
    *          Use of gtk_progress_bar_update() is deprecated !	         * 
-   * Use gtk_progress_set_value or gtk_progress_set_percentage instead.  *
+   * Use gtk_progress_bar_set_percentage ()
    ***********************************************************************/
 
   gtk_progress_set_percentage (GTK_PROGRESS (pbar), percentage);
Index: gtkprogressbar.h
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkprogressbar.h,v
retrieving revision 1.8
diff -u -u -r1.8 gtkprogressbar.h
--- gtkprogressbar.h	2000/02/13 08:16:47	1.8
+++ gtkprogressbar.h	2000/03/29 20:10:46
@@ -75,6 +75,9 @@
   gint  activity_pos;
   guint activity_step;
   guint activity_blocks;
+
+  gfloat pulse_fraction;
+  
   guint activity_dir : 1;
 };
 
@@ -86,20 +89,37 @@
 
 GtkType    gtk_progress_bar_get_type             (void);
 GtkWidget* gtk_progress_bar_new                  (void);
+
+/* The progress API now has only these five supported functions, all
+   the rest is confusing, near-useless cruft and should be removed
+   from the docs.
+*/
+void       gtk_progress_bar_pulse                (GtkProgressBar *pbar);
+void       gtk_progress_bar_set_text             (GtkProgressBar *pbar,
+                                                  const gchar    *text);
+void       gtk_progress_bar_set_fraction         (GtkProgressBar *pbar,
+                                                  gfloat          fraction);
+
+void       gtk_progress_bar_set_pulse_frequency  (GtkProgressBar *pbar,
+                                                  gfloat          fraction);
+void       gtk_progress_bar_set_orientation      (GtkProgressBar *pbar,
+						  GtkProgressBarOrientation orientation);
+
+/* Everything below here is deprecated */
 GtkWidget* gtk_progress_bar_new_with_adjustment  (GtkAdjustment  *adjustment);
 void       gtk_progress_bar_set_bar_style        (GtkProgressBar *pbar,
 						  GtkProgressBarStyle style);
 void       gtk_progress_bar_set_discrete_blocks  (GtkProgressBar *pbar,
 						  guint           blocks);
+/* set_activity_step() is not only deprecated, it doesn't even work.
+   (Of course, it wasn't usable anyway, you had to set it from a size_allocate
+   handler or something) */
 void       gtk_progress_bar_set_activity_step    (GtkProgressBar *pbar,
                                                   guint           step);
 void       gtk_progress_bar_set_activity_blocks  (GtkProgressBar *pbar,
 						  guint           blocks);
-void       gtk_progress_bar_set_orientation      (GtkProgressBar *pbar,
-						  GtkProgressBarOrientation orientation);
 void       gtk_progress_bar_update               (GtkProgressBar *pbar,
 						  gfloat          percentage);
-
 
 #ifdef __cplusplus
 }



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