Re: CList "keyfocus" (patch)



Index: gtkclist.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkclist.c,v
retrieving revision 1.169
diff -u -b -B -r1.169 gtkclist.c
--- gtkclist.c	2000/06/02 03:13:57	1.169
+++ gtkclist.c	2000/06/11 12:05:23
@@ -55,6 +55,12 @@
 /* used for auto-scrolling */
 #define SCROLL_TIME  100
 
+/* used for keypress string concat */
+#define KEYFOCUS_TIMEOUT 300
+
+/* key_press not handled when mask in event->state */
+#define KEYFOCUS_MASK (GDK_CONTROL_MASK | GDK_MOD1_MASK)
+
 /* gives the top pixel of the given row in context of
  * the clist's voffset */
 #define ROW_TOP_YPIXEL(clist, row) (((clist)->row_height * (row)) + \
@@ -453,6 +459,18 @@
 				       gint              y,
 				       GtkCListDestInfo *dest_info);
 
+/* Private for now */
+static
+gint
+gtk_clist_find_row_from_text (GtkCList	  *clist,
+			      const gchar *match,
+			      gint 	  start_row, 
+			      gint 	  column);
+static 
+void
+gtk_clist_moveto_with_focus  (GtkCList *clist,
+			      gint     row,
+			      gint     column);
 
 
 static GtkContainerClass *parent_class = NULL;
@@ -990,6 +1008,9 @@
   clist->compare = default_compare;
   clist->sort_type = GTK_SORT_ASCENDING;
   clist->sort_column = 0;
+
+  clist->keyfocus_string = NULL;
+  clist->keyfocus_lasttime = 0;
 }
 
 /* Constructors */
@@ -2995,6 +3016,36 @@
     move_vertical (clist, row, row_align);
 }
 
+/*
+ * Like gtk_clist_moveto - But sets target as new row with focus
+ */
+static void 
+gtk_clist_moveto_with_focus (GtkCList *clist, 
+			     gint row, 
+			     gint column)
+{
+  g_return_if_fail (clist != NULL);
+  g_return_if_fail (GTK_IS_CLIST (clist));
+  
+  if (row < -1 || row >= clist->rows)
+    return;
+  if (column < -1 || column >= clist->columns)
+    return;
+
+  gtk_clist_freeze (clist);
+	
+  clist->focus_row = row;
+
+  if (ROW_TOP_YPIXEL(clist, row) < 0)
+    gtk_clist_moveto (clist, row, column, 0, 0);
+  else if (ROW_TOP_YPIXEL(clist, row) + clist->row_height 
+	    > clist->clist_window_height)
+    gtk_clist_moveto (clist, row, column, 1, 0);
+
+  gtk_clist_thaw (clist);
+
+}
+
 void
 gtk_clist_set_row_height (GtkCList *clist,
 			  guint     height)
@@ -4418,6 +4469,8 @@
 
   clist = GTK_CLIST (object);
 
+  g_free (clist->keyfocus_string);
+
   columns_delete (clist);
 
   g_mem_chunk_destroy (clist->cell_mem_chunk);
@@ -4814,7 +4867,7 @@
 	  if (!clist->column[i].visible)
 	    continue;
 	  if (clist->column[i].button &&
-	      gtk_widget_intersect(clist->column[i].button, area,
&child_area))
+	      gtk_widget_intersect (clist->column[i].button, area,
&child_area))
 	    gtk_widget_draw (clist->column[i].button, &child_area);
 	}
     }
@@ -4897,6 +4950,49 @@
     }
 }
 
+/*
+ * TODO: rc enable/disable via setting of keyfocus_timeout
+ */
+static void
+handle_keyfocus (GtkCList    *clist, 
+		 GdkEventKey *event)
+{
+  char *str;
+  int row;
+  int row_cont;
+  	  
+  row_cont = (clist->focus_row >= 0) ? clist->focus_row : 0;
+  
+  if (clist->keyfocus_string != NULL)
+    {
+      if ( event->time > clist->keyfocus_lasttime + KEYFOCUS_TIMEOUT) 
+	{
+          g_free (clist->keyfocus_string);
+          clist->keyfocus_string = NULL;
+      	  row_cont++;
+      	}
+    }
+
+  if (clist->keyfocus_string == NULL) 
+    clist->keyfocus_string = g_strdup (event->string);
+  else 
+    {	
+      str = g_strconcat (clist->keyfocus_string, event->string, NULL);
+      g_free (clist->keyfocus_string);
+      clist->keyfocus_string = str;
+    }
+
+  row = gtk_clist_find_row_from_text (clist, 
+          clist->keyfocus_string, row_cont, -1);
+
+  if (row != -1) 
+    gtk_clist_moveto_with_focus (clist, row, -1);	
+
+  clist->keyfocus_lasttime = event->time;
+
+}
+
+
 static gint
 gtk_clist_key_press (GtkWidget   *widget,
 		     GdkEventKey *event)
@@ -4920,6 +5016,11 @@
 	return gtk_container_focus (GTK_CONTAINER (widget),
 				    GTK_DIR_TAB_FORWARD);
     default:
+      if (event->length > 0 && (event->state & KEYFOCUS_MASK) == 0) 
+        {
+          handle_keyfocus (GTK_CLIST (widget), event);
+          return TRUE;
+        }
       break;
     }
   return FALSE;
@@ -7124,7 +7225,7 @@
 
   value = CLAMP (clist->hadjustment->value + diff, 0.0,
 		 clist->hadjustment->upper - clist->hadjustment->page_size);
-  gtk_adjustment_set_value(clist->hadjustment, value);
+  gtk_adjustment_set_value (clist->hadjustment, value);
 }
 
 static void
@@ -7144,7 +7245,7 @@
   if (value + clist->vadjustment->page_size >
clist->vadjustment->upper)
     value = clist->vadjustment->upper - clist->vadjustment->page_size;
 
-  gtk_adjustment_set_value(clist->vadjustment, value);
+  gtk_adjustment_set_value (clist->vadjustment, value);
 }
 
 static gint
@@ -7928,4 +8029,70 @@
 
       clist->button_actions[button] = button_actions;
     }
+}
+
+
+/*
+ * TODO: 
+ * - make public (?)
+ * - regex version? no.
+ * - binary search on sorted list
+ */
+static
+gint
+gtk_clist_find_row_from_text (GtkCList 	  *clist,
+			      const gchar *match, 
+			      gint        start_row, 
+			      gint        column)
+{
+  GList *list;
+  GtkCListRow *clist_row;
+  gint n;
+  gchar *text;
+  gint mlen;
+    
+  g_return_val_if_fail (clist != NULL, -1);
+  g_return_val_if_fail (GTK_IS_CLIST (clist), -1);
+
+  if (column == -1) 
+    column = clist->sort_column;
+  if (start_row < 0 || start_row >= clist->rows)
+    return -1;
+  if (column < 0 || column >= clist->columns)
+    return -1;
+  
+  mlen = strlen (match);
+  
+  for (n = start_row, list = g_list_nth (clist->row_list, n); list; 
+       n++, list = list->next) {
+
+    clist_row = g_list_nth (clist, n)->data; /* ROW_ELEMENT */
+
+    switch (clist_row->cell[column].type)
+      {
+      case GTK_CELL_TEXT:
+        text = GTK_CELL_TEXT (clist_row->cell[column])->text;
+        if (!strncmp (text, match, mlen))
+          {
+            {
+	      return n;
+            }
+          }
+      	break;
+      case GTK_CELL_PIXTEXT:
+        text = GTK_CELL_PIXTEXT (clist_row->cell[column])->text;        
+        if (!strncmp (text, match, mlen))
+          {
+            {
+	      return n;
+	    }
+	  }
+      	break;
+      default:
+        break;
+      }
+  }
+    
+  return -1;
+
 }
Index: gtkclist.h
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkclist.h,v
retrieving revision 1.51
diff -u -b -B -r1.51 gtkclist.h
--- gtkclist.h	2000/06/02 03:13:58	1.51
+++ gtkclist.h	2000/06/11 12:05:23
@@ -236,6 +236,10 @@
   GtkSortType sort_type;
   GtkCListCompareFunc compare;
   gint sort_column;
+
+  /* keyboard focus navigation */
+  gchar *keyfocus_string;
+  gint keyfocus_lasttime;
 };
 
 struct _GtkCListClass




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