get search results faster (by redisplaying less often)
[disorder] / disobedience / choose.c
index b7f77c4..dc86412 100644 (file)
@@ -138,6 +138,7 @@ static int nsearchvisible;      /**< @brief number of search results visible */
 static struct hash *searchhash;         /**< @brief hash of search results */
 static struct progress_window *spw;     /**< @brief progress window */
 static struct choosenode **searchnodes; /**< @brief choosenodes of search results */
+static int suppress_redisplay;          /**< @brief suppress redisplay */
 
 /* Forward Declarations */
 
@@ -156,12 +157,13 @@ static void got_dirs(void *v, int nvec, char **vec);
 
 static void expand_node(struct choosenode *cn, int contingent);
 static void contract_node(struct choosenode *cn);
-static void updated_node(struct choosenode *cn, int redisplay);
+static void updated_node(struct choosenode *cn, int redisplay,
+                         const char *why);
 
 static void display_selection(struct choosenode *cn);
 static void clear_selection(struct choosenode *cn);
 
-static void redisplay_tree(void);
+static void redisplay_tree(const char *why);
 static struct displaydata display_tree(struct choosenode *cn, int x, int y);
 static void undisplay_tree(struct choosenode *cn);
 static void initiate_search(void);
@@ -396,7 +398,7 @@ static void got_resolved_file(void *v, const char *track) {
   /* Only bother updating when we've got the lot */
   if(--cn->pending == 0) {
     cn->flags &= ~CN_RESOLVING_FILES;
-    updated_node(cn, 1);
+    updated_node(cn, 1, "got_resolved_file");
     if(!(cn->flags & CN_GETTING_ANY))
       filled(cn);
   }
@@ -422,7 +424,7 @@ static void got_dirs(void *v, int nvec, char **vec) {
             trackname_transform("dir", vec[n], "display"),
             trackname_transform("dir", vec[n], "sort"),
             CN_EXPANDABLE, fill_directory_node);
-  updated_node(cn, 1);
+  updated_node(cn, 1, "got_dirs");
   cn->flags &= ~CN_GETTING_DIRS;
   if(!(cn->flags & CN_GETTING_ANY))
     filled(cn);
@@ -506,6 +508,10 @@ static void expand_from(struct choosenode *cn) {
     ++nsearchvisible;
     progress_window_progress(spw, nsearchvisible, nsearchresults);
     if(nsearchvisible == nsearchresults) {
+      if(suppress_redisplay) {
+        suppress_redisplay = 0;
+        redisplay_tree("all search results visible");
+      }
       /* We've got the lot.  We make sure the first result is visible. */
       cn = first_search_result(root);
       gtk_adjustment_clamp_page(vadjust, cn->ymin, cn->ymax);
@@ -539,7 +545,7 @@ static void contract_node(struct choosenode *cn) {
    * anyone complains we can make it an option. */
   clear_children(cn);
   /* We can contract a node immediately. */
-  redisplay_tree();
+  redisplay_tree("contract_node");
 }
 
 /** @brief qsort() callback for ordering choosenodes */
@@ -553,7 +559,8 @@ static int compare_choosenode(const void *av, const void *bv) {
 }
 
 /** @brief Called when an expandable node is updated.   */
-static void updated_node(struct choosenode *cn, int redisplay) {
+static void updated_node(struct choosenode *cn, int redisplay,
+                         const char *why) {
   D(("updated_node %s", cn->path));
   assert(cn->flags & CN_EXPANDABLE);
   /* It might be that the node has been de-expanded since we requested the
@@ -562,8 +569,12 @@ static void updated_node(struct choosenode *cn, int redisplay) {
   /* Sort children */
   qsort(cn->children.vec, cn->children.nvec, sizeof (struct choosenode *),
         compare_choosenode);
-  if(redisplay)
-    redisplay_tree();
+  if(redisplay) {
+    char whywhy[1024];
+
+    snprintf(whywhy, sizeof whywhy, "updated_node %s", why);
+    redisplay_tree(whywhy);
+  }
 }
 
 /* Searching --------------------------------------------------------------- */
@@ -609,7 +620,9 @@ static void search_completed(void attribute((unused)) *v,
   search_in_flight = 0;
   /* Contract any choosenodes that were only expanded to show search
    * results */
+  suppress_redisplay = 1;
   contract_contingent(root);
+  suppress_redisplay = 0;
   if(search_obsolete) {
     /* This search has been obsoleted by user input since it started.
      * Therefore we throw away the result and search again. */
@@ -650,9 +663,10 @@ static void search_completed(void attribute((unused)) *v,
       /* The search results buttons are usable */
       gtk_widget_set_sensitive(nextsearch, 1);
       gtk_widget_set_sensitive(prevsearch, 1);
+      suppress_redisplay = 1;           /* avoid lots of redisplays */
     } else {
       searchhash = 0;                   /* for the gc */
-      redisplay_tree();                 /* remove search markers */
+      redisplay_tree("no search results"); /* remove search markers */
       /* The search results buttons are not usable */
       gtk_widget_set_sensitive(nextsearch, 0);
       gtk_widget_set_sensitive(prevsearch, 0);
@@ -761,11 +775,16 @@ static void delete_widgets(struct choosenode *cn) {
 }
 
 /** @brief Update the display */
-static void redisplay_tree(void) {
+static void redisplay_tree(const char *why) {
   struct displaydata d;
   guint oldwidth, oldheight;
 
-  D(("redisplay_tree"));
+  D(("redisplay_tree %s", why));
+  if(suppress_redisplay) {
+    /*fprintf(stderr, "redisplay_tree %s suppressed\n", why);*/
+    return;
+  }
+  /*fprintf(stderr, "redisplay_tree %s   *** NOT SUPPRESSED ***\n", why);*/
   /* We'll count these up empirically each time */
   files_selected = 0;
   files_visible = 0;
@@ -805,7 +824,6 @@ static struct displaydata display_tree(struct choosenode *cn, int x, int y) {
   GtkRequisition req;
   struct displaydata d, cd;
   GdkPixbuf *pb;
-  const char *name;
   const int search_result = is_search_result(cn->path);
   
   D(("display_tree %s %d,%d", cn->path, x, y));
@@ -857,12 +875,16 @@ static struct displaydata display_tree(struct choosenode *cn, int x, int y) {
     MTAG_POP();
   }
   assert(cn->container);
-  /* Make sure the widget name is right */
-  name = (cn->flags & CN_EXPANDABLE
-          ? "choose-dir"
-          : search_result ? "choose-search" : "choose");
-  gtk_widget_set_name(cn->label, name);
-  gtk_widget_set_name(cn->container, name);
+  /* Set colors */
+  if(search_result)
+    gtk_widget_modify_bg(cn->container, GTK_STATE_NORMAL, &search_bg);
+  else
+    gtk_widget_modify_bg(cn->container, GTK_STATE_NORMAL, &layout_bg);
+  gtk_widget_modify_bg(cn->container, GTK_STATE_SELECTED, &selected_bg);
+  gtk_widget_modify_bg(cn->container, GTK_STATE_PRELIGHT, &selected_bg);
+  gtk_widget_modify_fg(cn->label, GTK_STATE_NORMAL, &item_fg);
+  gtk_widget_modify_fg(cn->label, GTK_STATE_SELECTED, &selected_fg);
+  gtk_widget_modify_fg(cn->label, GTK_STATE_PRELIGHT, &selected_fg);
   /* Make sure the icon is right */
   if(cn->flags & CN_EXPANDABLE)
     gtk_arrow_set(GTK_ARROW(cn->arrow),
@@ -1077,6 +1099,7 @@ static void clicked_choosenode(GtkWidget attribute((unused)) *widget,
       menuitems[n].handlerid = g_signal_connect
         (menuitems[n].w, "activate", G_CALLBACK(menuitems[n].activate), cn);
     }
+    set_tool_colors(menu);
     /* Pop up the menu */
     gtk_widget_show_all(menu);
     gtk_menu_popup(GTK_MENU(menu), 0, 0, 0, 0,
@@ -1288,6 +1311,15 @@ static const struct tabtype tabtype_choose = {
 
 /* Public entry points ----------------------------------------------------- */
 
+/** @brief Called to entirely reset the choose screen */
+static void choose_reset(void) {
+  if(root)
+    undisplay_tree(root);
+  root = newnode(0/*parent*/, "<root>", "All files", "",
+                 CN_EXPANDABLE, fill_root_node);
+  expand_node(root, 0);                 /* will call redisplay_tree */
+}
+
 /** @brief Create a track choice widget */
 GtkWidget *choose_widget(void) {
   int n;
@@ -1323,6 +1355,10 @@ GtkWidget *choose_widget(void) {
   /* Cancel button to clear the search */
   NW(button);
   clearsearch = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
+  gtk_widget_modify_bg(clearsearch, GTK_STATE_NORMAL, &tool_bg);
+  gtk_widget_modify_bg(clearsearch, GTK_STATE_ACTIVE, &tool_active);
+  gtk_widget_modify_bg(clearsearch, GTK_STATE_PRELIGHT, &tool_active);
+  gtk_widget_modify_bg(clearsearch, GTK_STATE_SELECTED, &tool_active);
   g_signal_connect(G_OBJECT(clearsearch), "clicked",
                    G_CALLBACK(clearsearch_clicked), 0);
   gtk_tooltips_set_tip(tips, clearsearch, "Clear search terms", "");
@@ -1333,10 +1369,20 @@ GtkWidget *choose_widget(void) {
   g_signal_connect(G_OBJECT(prevsearch), "clicked",
                    G_CALLBACK(prev_clicked), 0);
   gtk_widget_set_sensitive(prevsearch, 0);
+  gtk_widget_modify_bg(prevsearch, GTK_STATE_NORMAL, &tool_bg);
+  gtk_widget_modify_bg(prevsearch, GTK_STATE_ACTIVE, &tool_active);
+  gtk_widget_modify_bg(prevsearch, GTK_STATE_PRELIGHT, &tool_active);
+  gtk_widget_modify_bg(prevsearch, GTK_STATE_SELECTED, &tool_active);
+  gtk_widget_modify_bg(prevsearch, GTK_STATE_INSENSITIVE, &tool_active);
   nextsearch = iconbutton("down.png", "Next search result");
   g_signal_connect(G_OBJECT(nextsearch), "clicked",
                    G_CALLBACK(next_clicked), 0);
   gtk_widget_set_sensitive(nextsearch, 0);
+  gtk_widget_modify_bg(nextsearch, GTK_STATE_NORMAL, &tool_bg);
+  gtk_widget_modify_bg(nextsearch, GTK_STATE_ACTIVE, &tool_active);
+  gtk_widget_modify_bg(nextsearch, GTK_STATE_PRELIGHT, &tool_active);
+  gtk_widget_modify_bg(nextsearch, GTK_STATE_SELECTED, &tool_active);
+  gtk_widget_modify_bg(nextsearch, GTK_STATE_INSENSITIVE, &tool_active);
 
   /* hbox packs the search tools button together on a line */
   NW(hbox);
@@ -1354,9 +1400,9 @@ GtkWidget *choose_widget(void) {
    * namespace */
   NW(layout);
   chooselayout = gtk_layout_new(0, 0);
-  root = newnode(0/*parent*/, "<root>", "All files", "",
-                 CN_EXPANDABLE, fill_root_node);
-  expand_node(root, 0);                 /* will call redisplay_tree */
+  gtk_widget_modify_bg(chooselayout, GTK_STATE_NORMAL, &layout_bg);
+  choose_reset();
+  register_reset(choose_reset);
   /* Create the popup menus */
   NW(menu);
   track_menu = gtk_menu_new();
@@ -1381,7 +1427,7 @@ GtkWidget *choose_widget(void) {
                     0, 1, n, n + 1);
   }
   /* The layout is scrollable */
-  scrolled = scroll_widget(chooselayout, "choose");
+  scrolled = scroll_widget(chooselayout);
   vadjust = gtk_layout_get_vadjustment(GTK_LAYOUT(chooselayout));
 
   /* The scrollable layout and the search hbox go together in a vbox */
@@ -1398,7 +1444,7 @@ GtkWidget *choose_widget(void) {
 
 /** @brief Called when something we care about here might have changed */
 void choose_update(void) {
-  redisplay_tree();
+  redisplay_tree("choose_update");
 }
 
 /*