-/* Called when the cancel search button is clicked */
-static void clearsearch_clicked(GtkButton attribute((unused)) *button,
- gpointer attribute((unused)) userdata) {
- gtk_entry_set_text(GTK_ENTRY(searchentry), "");
-}
-
-/* Display functions ------------------------------------------------------- */
-
-/* Delete all the widgets in the tree */
-static void delete_widgets(struct choosenode *cn) {
- int n;
-
- if(cn->container) {
- gtk_widget_destroy(cn->container);
- cn->container = 0;
- }
- for(n = 0; n < cn->children.nvec; ++n)
- delete_widgets(cn->children.vec[n]);
- cn->flags &= ~(CN_DISPLAYED|CN_SELECTED);
- files_selected = 0;
-}
-
-/* Update the display */
-static void redisplay_tree(void) {
- struct displaydata d;
- guint oldwidth, oldheight;
-
- D(("redisplay_tree"));
- /* We'll count these up empirically each time */
- files_selected = 0;
- files_visible = 0;
- /* Correct the layout and find out how much space it uses */
- d = display_tree(root, 0, 0);
- /* We must set the total size or scrolling will not work (it wouldn't be hard
- * for GtkLayout to figure it out for itself but presumably you're supposed
- * to be able to have widgets off the edge of the layuot.)
- *
- * There is a problem: if we shrink the size then the part of the screen that
- * is outside the new size but inside the old one is not updated. I think
- * this is arguably bug in GTK+ but it's easy to force a redraw if this
- * region is nonempty.
- */
- gtk_layout_get_size(GTK_LAYOUT(chooselayout), &oldwidth, &oldheight);
- if(oldwidth > d.width || oldheight > d.height)
- gtk_widget_queue_draw(chooselayout);
- gtk_layout_set_size(GTK_LAYOUT(chooselayout), d.width, d.height);
- /* Notify the main menu of any recent changes */
- menu_update(-1);
-}
-
-/* Make sure all displayed widgets from CN down exist and are in their proper
- * place and return the vertical space used. */
-static struct displaydata display_tree(struct choosenode *cn, int x, int y) {
- int n, aw;
- GtkRequisition req;
- struct displaydata d, cd;
- GdkPixbuf *pb;
-
- D(("display_tree %s %d,%d", cn->path, x, y));
-
- /* An expandable item contains an arrow and a text label. When you press the
- * button it flips its expand state.
- *
- * A non-expandable item has just a text label and no arrow.
- */
- if(!cn->container) {
- /* Widgets need to be created */
- cn->hbox = gtk_hbox_new(FALSE, 1);
- if(cn->flags & CN_EXPANDABLE) {
- cn->arrow = gtk_arrow_new(cn->flags & CN_EXPANDED ? GTK_ARROW_DOWN
- : GTK_ARROW_RIGHT,
- GTK_SHADOW_NONE);
- cn->marker = 0;
- } else {
- cn->arrow = 0;
- if((pb = find_image("notes.png")))
- cn->marker = gtk_image_new_from_pixbuf(pb);
- }
- cn->label = gtk_label_new(cn->display);
- if(cn->arrow)
- gtk_container_add(GTK_CONTAINER(cn->hbox), cn->arrow);
- gtk_container_add(GTK_CONTAINER(cn->hbox), cn->label);
- if(cn->marker)
- gtk_container_add(GTK_CONTAINER(cn->hbox), cn->marker);
- cn->container = gtk_event_box_new();
- gtk_container_add(GTK_CONTAINER(cn->container), cn->hbox);
- g_signal_connect(cn->container, "button-release-event",
- G_CALLBACK(clicked_choosenode), cn);
- g_signal_connect(cn->container, "button-press-event",
- G_CALLBACK(clicked_choosenode), cn);
- g_object_ref(cn->container);
- gtk_widget_set_name(cn->label, "choose");
- gtk_widget_set_name(cn->container, "choose");
- /* Show everything by default */
- gtk_widget_show_all(cn->container);
- }
- assert(cn->container);
- /* Make sure the icon is right */
- if(cn->flags & CN_EXPANDABLE)
- gtk_arrow_set(GTK_ARROW(cn->arrow),
- cn->flags & CN_EXPANDED ? GTK_ARROW_DOWN : GTK_ARROW_RIGHT,
- GTK_SHADOW_NONE);
- else if(cn->marker)
- /* Make sure the queued marker is right */
- /* TODO: doesn't always work */
- (queued(cn->path) ? gtk_widget_show : gtk_widget_hide)(cn->marker);
- /* Put the widget in the right place */
- if(cn->flags & CN_DISPLAYED)
- gtk_layout_move(GTK_LAYOUT(chooselayout), cn->container, x, y);
- else {
- gtk_layout_put(GTK_LAYOUT(chooselayout), cn->container, x, y);
- cn->flags |= CN_DISPLAYED;
- }
- /* Set the widget's selection status */
- if(!(cn->flags & CN_EXPANDABLE))
- display_selection(cn);
- /* Find the size used so we can get vertical positioning right. */
- gtk_widget_size_request(cn->container, &req);
- d.width = x + req.width;
- d.height = y + req.height;
- if(cn->flags & CN_EXPANDED) {
- /* We'll offset children by the size of the arrow whatever it might be. */
- assert(cn->arrow);
- gtk_widget_size_request(cn->arrow, &req);
- aw = req.width;
- for(n = 0; n < cn->children.nvec; ++n) {
- cd = display_tree(cn->children.vec[n], x + aw, d.height);
- if(cd.width > d.width)
- d.width = cd.width;
- d.height = cd.height;
- }
- } else {
- for(n = 0; n < cn->children.nvec; ++n)
- undisplay_tree(cn->children.vec[n]);
- }
- if(!(cn->flags & CN_EXPANDABLE)) {
- ++files_visible;
- if(cn->flags & CN_SELECTED)
- ++files_selected;