gtk+ r21846 - in trunk: . gtk tests



Author: mitch
Date: Fri Dec  5 11:31:30 2008
New Revision: 21846
URL: http://svn.gnome.org/viewvc/gtk+?rev=21846&view=rev

Log:
2008-12-05  Michael Natterer  <mitch imendio com>

	Bug 546285 â Allow GtkEntry to draw progress

	* gtk/gtkentry.[ch]: add new API similar to GtkProgressBar which
	allows to set the entry's progress_fraction, its progress_pulse_step
	and to let the entry's progress pulse.

	* gtk/gtk.symbols: updated.

	* tests/testgtk.c: add progress demo code to the "Entry" window.



Modified:
   trunk/ChangeLog
   trunk/gtk/gtk.symbols
   trunk/gtk/gtkentry.c
   trunk/gtk/gtkentry.h
   trunk/tests/testgtk.c

Modified: trunk/gtk/gtk.symbols
==============================================================================
--- trunk/gtk/gtk.symbols	(original)
+++ trunk/gtk/gtk.symbols	Fri Dec  5 11:31:30 2008
@@ -1282,6 +1282,8 @@
 gtk_entry_get_layout_offsets
 gtk_entry_get_max_length
 gtk_entry_get_overwrite_mode
+gtk_entry_get_progress_fraction
+gtk_entry_get_progress_pulse_step
 gtk_entry_get_text
 gtk_entry_get_text_length
 gtk_entry_get_type G_GNUC_CONST
@@ -1293,6 +1295,7 @@
 gtk_entry_new_with_max_length
 gtk_entry_append_text
 gtk_entry_prepend_text
+gtk_entry_progress_pulse
 gtk_entry_select_region
 gtk_entry_set_position
 gtk_entry_set_editable
@@ -1305,6 +1308,8 @@
 gtk_entry_set_invisible_char
 gtk_entry_set_max_length
 gtk_entry_set_overwrite_mode
+gtk_entry_set_progress_fraction
+gtk_entry_set_progress_pulse_step
 gtk_entry_set_text
 gtk_entry_set_visibility
 gtk_entry_set_width_chars

Modified: trunk/gtk/gtkentry.c
==============================================================================
--- trunk/gtk/gtkentry.c	(original)
+++ trunk/gtk/gtkentry.c	Fri Dec  5 11:31:30 2008
@@ -26,6 +26,8 @@
  */
 
 #include "config.h"
+
+#include <math.h>
 #include <string.h>
 
 #include "gdk/gdkkeysyms.h"
@@ -86,14 +88,20 @@
   gfloat xalign;
   gint insert_pos;
   guint blink_time;  /* time in msec the cursor has blinked since last user event */
-  guint interior_focus : 1;
-  guint real_changed   : 1;
-  guint invisible_char_set : 1;
-  guint caps_lock_warning : 1;
-  guint change_count   : 8;
+  guint interior_focus          : 1;
+  guint real_changed            : 1;
+  guint invisible_char_set      : 1;
+  guint caps_lock_warning       : 1;
+  guint change_count            : 8;
+  guint progress_pulse_mode     : 1;
+  guint progress_pulse_way_back : 1;
 
   gint focus_width;
   GtkShadowType shadow_type;
+
+  gdouble progress_fraction;
+  gdouble progress_pulse_fraction;
+  gdouble progress_pulse_current;
 };
 
 typedef struct _GtkEntryPasswordHint GtkEntryPasswordHint;
@@ -149,7 +157,9 @@
   PROP_OVERWRITE_MODE,
   PROP_TEXT_LENGTH,
   PROP_INVISIBLE_CHAR_SET,
-  PROP_CAPS_LOCK_WARNING
+  PROP_CAPS_LOCK_WARNING,
+  PROP_PROGRESS_FRACTION,
+  PROP_PROGRESS_PULSE_STEP
 };
 
 static guint signals[LAST_SIGNAL] = { 0 };
@@ -184,6 +194,8 @@
 					      GtkAllocation    *allocation);
 static void   gtk_entry_draw_frame           (GtkWidget        *widget,
                                               GdkRectangle     *area);
+static void   gtk_entry_draw_progress        (GtkWidget        *widget,
+                                              GdkEventExpose   *event);
 static gint   gtk_entry_expose               (GtkWidget        *widget,
 					      GdkEventExpose   *event);
 static gint   gtk_entry_button_press         (GtkWidget        *widget,
@@ -668,6 +680,7 @@
                                                          P_("Whether new text overwrites existing text"),
                                                          FALSE,
                                                          GTK_PARAM_READWRITE));
+
   /**
    * GtkEntry:text-length:
    *
@@ -699,8 +712,6 @@
                                                          FALSE,
                                                          GTK_PARAM_READWRITE));
 
-
-
   /**
    * GtkEntry:caps-lock-warning
    *
@@ -717,7 +728,41 @@
                                                          TRUE,
                                                          GTK_PARAM_READWRITE));
 
- 
+  /**
+   * GtkEntry:progress-fraction:
+   *
+   * The current fraction of the task that's been completed.
+   *
+   * Since: 2.16
+   */
+  g_object_class_install_property (gobject_class,
+                                   PROP_PROGRESS_FRACTION,
+                                   g_param_spec_double ("progress-fraction",
+                                                        P_("Progress Fraction"),
+                                                        P_("The current fraction of the task that's been completed"),
+                                                        0.0,
+                                                        1.0,
+                                                        0.0,
+                                                        GTK_PARAM_READWRITE));
+
+  /**
+   * GtkEntry:progress-pulse-step:
+   *
+   * The fraction of total entry width to move the progress
+   * bouncing block for each call to gtk_entry_progress_pulse().
+   *
+   * Since: 2.16
+   */
+  g_object_class_install_property (gobject_class,
+                                   PROP_PROGRESS_PULSE_STEP,
+                                   g_param_spec_double ("progress-pulse-step",
+                                                        P_("Progress Pulse Step"),
+                                                        P_("The fraction of total entry width to move the progress bouncing block for each call to gtk_entry_progress_pulse()"),
+                                                        0.0,
+                                                        1.0,
+                                                        0.1,
+                                                        GTK_PARAM_READWRITE));
+
   signals[POPULATE_POPUP] =
     g_signal_new (I_("populate-popup"),
 		  G_OBJECT_CLASS_TYPE (gobject_class),
@@ -1142,6 +1187,14 @@
       priv->caps_lock_warning = g_value_get_boolean (value);
       break;
 
+    case PROP_PROGRESS_FRACTION:
+      gtk_entry_set_progress_fraction (entry, g_value_get_double (value));
+      break;
+
+    case PROP_PROGRESS_PULSE_STEP:
+      gtk_entry_set_progress_pulse_step (entry, g_value_get_double (value));
+      break;
+
     case PROP_SCROLL_OFFSET:
     case PROP_CURSOR_POSITION:
     default:
@@ -1218,6 +1271,13 @@
     case PROP_CAPS_LOCK_WARNING:
       g_value_set_boolean (value, priv->caps_lock_warning);
       break;
+    case PROP_PROGRESS_FRACTION:
+      g_value_set_double (value, priv->progress_fraction);
+      break;
+    case PROP_PROGRESS_PULSE_STEP:
+      g_value_set_double (value, priv->progress_pulse_fraction);
+      break;
+
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -1289,6 +1349,8 @@
   priv->shadow_type = GTK_SHADOW_IN;
   priv->xalign = 0.0;
   priv->caps_lock_warning = TRUE;
+  priv->progress_fraction = 0.0;
+  priv->progress_pulse_fraction = 0.1;
 
   gtk_drag_dest_set (GTK_WIDGET (entry),
                      GTK_DEST_DEFAULT_HIGHLIGHT,
@@ -1784,6 +1846,52 @@
     }
 }
 
+static void
+gtk_entry_draw_progress (GtkWidget      *widget,
+                         GdkEventExpose *event)
+{
+  GtkEntryPrivate *private = GTK_ENTRY_GET_PRIVATE (widget);
+  GtkEntry *entry = GTK_ENTRY (widget);
+
+  if (private->progress_pulse_mode)
+    {
+      gdouble value = private->progress_pulse_current;
+      gint    area_width, area_height;
+
+      gdk_drawable_get_size (entry->text_area, &area_width, &area_height);
+
+      gtk_paint_box (widget->style, entry->text_area,
+                     GTK_STATE_SELECTED, GTK_SHADOW_OUT,
+                     &event->area, widget, "entry-progress",
+                     value * area_width, 0,
+                     private->progress_pulse_fraction * area_width, area_height);
+    }
+  else if (private->progress_fraction > 0)
+    {
+      gdouble value = private->progress_fraction;
+      gint    area_width, area_height;
+
+      gdk_drawable_get_size (entry->text_area, &area_width, &area_height);
+
+      if (gtk_widget_get_direction (GTK_WIDGET (entry)) == GTK_TEXT_DIR_RTL)
+        {
+          gtk_paint_box (widget->style, entry->text_area,
+                         GTK_STATE_SELECTED, GTK_SHADOW_OUT,
+                         &event->area, widget, "entry-progress",
+                         area_width - value * area_width, 0,
+                         value * area_width, area_height);
+        }
+      else
+        {
+          gtk_paint_box (widget->style, entry->text_area,
+                         GTK_STATE_SELECTED, GTK_SHADOW_OUT,
+                         &event->area, widget, "entry-progress",
+                         0, 0,
+                         value * area_width, area_height);
+        }
+    }
+}
+
 static gint
 gtk_entry_expose (GtkWidget      *widget,
 		  GdkEventExpose *event)
@@ -1811,6 +1919,8 @@
 			  &event->area, widget, "entry_bg",
 			  0, 0, area_width, area_height);
 
+      gtk_entry_draw_progress (widget, event);
+
       if (entry->dnd_position != -1)
 	gtk_entry_draw_cursor (GTK_ENTRY (widget), CURSOR_DND);
       
@@ -6628,6 +6738,179 @@
   return g_object_get_qdata (G_OBJECT (entry), quark_cursor_hadjustment);
 }
 
+/**
+ * gtk_entry_set_progress_fraction:
+ * @entry: a #GtkEntry
+ * @fraction: fraction of the task that's been completed
+ *
+ * Causes the entry's progress indicator to "fill in" the given
+ * fraction of the bar. The fraction should be between 0.0 and 1.0,
+ * inclusive.
+ *
+ * Since: 2.16
+ */
+void
+gtk_entry_set_progress_fraction (GtkEntry *entry,
+                                 gdouble   fraction)
+{
+  GtkEntryPrivate *private;
+  gdouble          old_fraction;
+
+  g_return_if_fail (GTK_IS_ENTRY (entry));
+
+  private = GTK_ENTRY_GET_PRIVATE (entry);
+
+  if (private->progress_pulse_mode)
+    old_fraction = -1;
+  else
+    old_fraction = private->progress_fraction;
+
+  fraction = CLAMP (fraction, 0.0, 1.0);
+
+  private->progress_fraction = fraction;
+  private->progress_pulse_mode = FALSE;
+  private->progress_pulse_current = 0.0;
+
+  if (fabs (fraction - old_fraction) > 0.0001)
+    gtk_entry_queue_draw (entry);
+
+  if (fraction != old_fraction)
+    g_object_notify (G_OBJECT (entry), "progress-fraction");
+}
+
+/**
+ * gtk_entry_get_progress_fraction:
+ * @entry: a #GtkEntry
+ *
+ * Returns the current fraction of the task that's been completed.
+ * See gtk_entry_set_progress_fraction().
+ *
+ * Return value: a fraction from 0.0 to 1.0
+ *
+ * Since: 2.16
+ */
+gdouble
+gtk_entry_get_progress_fraction (GtkEntry *entry)
+{
+  GtkEntryPrivate *private;
+
+  g_return_val_if_fail (GTK_IS_ENTRY (entry), 0.0);
+
+  private = GTK_ENTRY_GET_PRIVATE (entry);
+
+  return private->progress_fraction;
+}
+
+/**
+ * gtk_entry_set_progress_pulse_step:
+ * @entry: a #GtkEntry
+ * @fraction: fraction between 0.0 and 1.0
+ *
+ * Sets the fraction of total entry width to move the progress
+ * bouncing block for each call to gtk_entry_progress_pulse().
+ *
+ * Since: 2.16
+ */
+void
+gtk_entry_set_progress_pulse_step (GtkEntry *entry,
+                                   gdouble   fraction)
+{
+  GtkEntryPrivate *private;
+
+  g_return_if_fail (GTK_IS_ENTRY (entry));
+
+  private = GTK_ENTRY_GET_PRIVATE (entry);
+
+  fraction = CLAMP (fraction, 0.0, 1.0);
+
+  if (fraction != private->progress_pulse_fraction)
+    {
+      private->progress_pulse_fraction = fraction;
+
+      gtk_entry_queue_draw (entry);
+
+      g_object_notify (G_OBJECT (entry), "progress-pulse-step");
+    }
+}
+
+/**
+ * gtk_entry_get_progress_pulse_step:
+ * @entry: a #GtkEntry
+ *
+ * Retrieves the pulse step set with gtk_entry_set_progress_pulse_step().
+ *
+ * Return value: a fraction from 0.0 to 1.0
+ *
+ * Since: 2.16
+ */
+gdouble
+gtk_entry_get_progress_pulse_step (GtkEntry *entry)
+{
+  GtkEntryPrivate *private;
+
+  g_return_val_if_fail (GTK_IS_ENTRY (entry), 0.0);
+
+  private = GTK_ENTRY_GET_PRIVATE (entry);
+
+  return private->progress_pulse_fraction;
+}
+
+/**
+ * gtk_entry_progress_pulse:
+ * @entry: a #GtkEntry
+ *
+ * Indicates that some progress is made, but you don't know how much.
+ * Causes the entry's progress indicator to enter "activity mode,"
+ * where a block bounces back and forth. Each call to
+ * gtk_entry_progress_pulse() causes the block to move by a little bit
+ * (the amount of movement per pulse is determined by
+ * gtk_entry_set_progress_pulse_step()).
+ *
+ * Since: 2.16
+ */
+void
+gtk_entry_progress_pulse (GtkEntry *entry)
+{
+  GtkEntryPrivate *private;
+
+  g_return_if_fail (GTK_IS_ENTRY (entry));
+
+  private = GTK_ENTRY_GET_PRIVATE (entry);
+
+  if (private->progress_pulse_mode)
+    {
+      if (private->progress_pulse_way_back)
+        {
+          private->progress_pulse_current -= private->progress_pulse_fraction;
+
+          if (private->progress_pulse_current < 0.0)
+            {
+              private->progress_pulse_current = 0.0;
+              private->progress_pulse_way_back = FALSE;
+            }
+        }
+      else
+        {
+          private->progress_pulse_current += private->progress_pulse_fraction;
+
+          if (private->progress_pulse_current > 1.0 - private->progress_pulse_fraction)
+            {
+              private->progress_pulse_current = 1.0 - private->progress_pulse_fraction;
+              private->progress_pulse_way_back = TRUE;
+            }
+        }
+    }
+  else
+    {
+      private->progress_fraction = 0.0;
+      private->progress_pulse_mode = TRUE;
+      private->progress_pulse_way_back = FALSE;
+      private->progress_pulse_current = 0.0;
+    }
+
+  gtk_entry_queue_draw (entry);
+}
+
 /* Caps Lock warning for password entries */
 
 static void
@@ -6793,6 +7076,5 @@
     remove_capslock_feedback (entry);
 }
 
-
 #define __GTK_ENTRY_C__
 #include "gtkaliasdef.c"

Modified: trunk/gtk/gtkentry.h
==============================================================================
--- trunk/gtk/gtkentry.h	(original)
+++ trunk/gtk/gtkentry.h	Fri Dec  5 11:31:30 2008
@@ -212,6 +212,18 @@
                                                  GtkAdjustment *adjustment);
 GtkAdjustment* gtk_entry_get_cursor_hadjustment (GtkEntry      *entry);
 
+/* Progress API
+ */
+void           gtk_entry_set_progress_fraction   (GtkEntry     *entry,
+                                                  gdouble       fraction);
+gdouble        gtk_entry_get_progress_fraction   (GtkEntry     *entry);
+
+void           gtk_entry_set_progress_pulse_step (GtkEntry     *entry,
+                                                  gdouble       fraction);
+gdouble        gtk_entry_get_progress_pulse_step (GtkEntry     *entry);
+
+void           gtk_entry_progress_pulse          (GtkEntry     *entry);
+
 /* Deprecated compatibility functions
  */
 

Modified: trunk/tests/testgtk.c
==============================================================================
--- trunk/tests/testgtk.c	(original)
+++ trunk/tests/testgtk.c	Fri Dec  5 11:31:30 2008
@@ -5193,6 +5193,65 @@
    gtk_widget_set_sensitive (entry, GTK_TOGGLE_BUTTON(checkbutton)->active);
 }
 
+static gboolean
+entry_progress_timeout (gpointer data)
+{
+  if (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (data), "progress-pulse")))
+    {
+      gtk_entry_progress_pulse (GTK_ENTRY (data));
+    }
+  else
+    {
+      gdouble fraction;
+
+      fraction = gtk_entry_get_progress_fraction (GTK_ENTRY (data));
+
+      fraction += 0.05;
+      if (fraction > 1.0001)
+        fraction = 0.0;
+
+      gtk_entry_set_progress_fraction (GTK_ENTRY (data), fraction);
+    }
+
+  return TRUE;
+}
+
+static void
+entry_remove_timeout (gpointer data)
+{
+  g_source_remove (GPOINTER_TO_UINT (data));
+}
+
+static void
+entry_toggle_progress (GtkWidget *checkbutton,
+                       GtkWidget *entry)
+{
+  if (GTK_TOGGLE_BUTTON (checkbutton)->active)
+    {
+      guint timeout = gdk_threads_add_timeout (100,
+                                               entry_progress_timeout,
+                                               entry);
+      g_object_set_data_full (G_OBJECT (entry), "timeout-id",
+                              GUINT_TO_POINTER (timeout),
+                              entry_remove_timeout);
+    }
+  else
+    {
+      g_object_set_data (G_OBJECT (entry), "timeout-id",
+                         GUINT_TO_POINTER (0));
+
+      gtk_entry_set_progress_fraction (GTK_ENTRY (entry), 0.0);
+    }
+}
+
+static void
+entry_toggle_pulse (GtkWidget *checkbutton,
+                    GtkWidget *entry)
+{
+  g_object_set_data (G_OBJECT (entry), "progress-pulse",
+                     GINT_TO_POINTER (GTK_TOGGLE_BUTTON (checkbutton)->active));
+}
+
 static void
 entry_props_clicked (GtkWidget *button,
 		     GObject   *entry)
@@ -5211,6 +5270,7 @@
   GtkWidget *hbox;
   GtkWidget *has_frame_check;
   GtkWidget *sensitive_check;
+  GtkWidget *progress_check;
   GtkWidget *entry, *cb;
   GtkWidget *button;
   GtkWidget *separator;
@@ -5281,7 +5341,17 @@
       g_signal_connect (has_frame_check, "toggled",
 			G_CALLBACK (entry_toggle_frame), entry);
       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (has_frame_check), TRUE);
-      
+
+      progress_check = gtk_check_button_new_with_label("Show Progress");
+      gtk_box_pack_start (GTK_BOX (box2), progress_check, FALSE, TRUE, 0);
+      g_signal_connect (progress_check, "toggled",
+			G_CALLBACK (entry_toggle_progress), entry);
+
+      progress_check = gtk_check_button_new_with_label("Pulse Progress");
+      gtk_box_pack_start (GTK_BOX (box2), progress_check, FALSE, TRUE, 0);
+      g_signal_connect (progress_check, "toggled",
+			G_CALLBACK (entry_toggle_pulse), entry);
+
       separator = gtk_hseparator_new ();
       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
 



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