/*
* (SLIK) SimpLIstic sKin functions
* (C) 2006 John Ellis
- * Copyright (C) 2008 - 2009 The Geeqie Team
+ * Copyright (C) 2008 - 2012 The Geeqie Team
*
* Author: John Ellis
*
* #define TAB_COMPLETION_ENABLE_POPUP_MENU
*/
#define TAB_COMPLETION_ENABLE_POPUP_MENU 1
-#define TAB_COMP_POPUP_MAX 500
+#define TAB_COMP_POPUP_MAX 1000
#ifdef TAB_COMPLETION_ENABLE_POPUP_MENU
#include "ui_menu.h"
gpointer enter_data;
gpointer tab_data;
gpointer tab_append_data;
-
+
GtkWidget *combo;
- gint has_history;
+ gboolean has_history;
gchar *history_key;
gint history_levels;
FileDialog *fd;
gchar *fd_title;
- gint fd_folders_only;
+ gboolean fd_folders_only;
GtkWidget *fd_button;
+
+ guint choices;
};
static void tab_completion_select_show(TabCompData *td);
+static gint tab_completion_do(TabCompData *td);
static void tab_completion_free_list(TabCompData *td)
{
pathl = path_from_utf8(path);
dp = opendir(pathl);
- g_free(pathl);
if (!dp)
{
/* dir not found */
+ g_free(pathl);
return;
}
while ((dir = readdir(dp)) != NULL)
gchar *name = dir->d_name;
if (strcmp(name, ".") != 0 && strcmp(name, "..") != 0)
{
- list = g_list_prepend(list, path_to_utf8(name));
+ gchar *abspath = g_build_filename(pathl, name, NULL);
+
+ if (g_file_test(abspath, G_FILE_TEST_IS_DIR))
+ {
+ gchar *dname = g_strconcat(name, G_DIR_SEPARATOR_S, NULL);
+ list = g_list_prepend(list, path_to_utf8(dname));
+ g_free(dname);
+ }
+ else
+ {
+ list = g_list_prepend(list, path_to_utf8(name));
+ }
+ g_free(abspath);
}
}
closedir(dp);
td->dir_path = g_strdup(path);
td->file_list = list;
+ g_free(pathl);
}
static void tab_completion_destroy(GtkWidget *widget, gpointer data)
return text;
}
-static gint tab_completion_emit_enter_signal(TabCompData *td)
+static gboolean tab_completion_emit_enter_signal(TabCompData *td)
{
gchar *text;
if (!td->enter_func) return FALSE;
}
#ifdef TAB_COMPLETION_ENABLE_POPUP_MENU
+void tab_completion_iter_menu_items(GtkWidget *widget, gpointer data)
+{
+ TabCompData *td = data;
+ GtkWidget *child;
-static gint tab_completion_popup_key_press(GtkWidget *widget, GdkEventKey *event, gpointer data)
+ if (!gtk_widget_get_visible(widget)) return;
+
+ child = gtk_bin_get_child(GTK_BIN(widget));
+ if (GTK_IS_LABEL(child)) {
+ const gchar *text = gtk_label_get_text(GTK_LABEL(child));
+ const gchar *entry_text = gtk_entry_get_text(GTK_ENTRY(td->entry));
+ const gchar *prefix = filename_from_path(entry_text);
+ guint prefix_len = strlen(prefix);
+
+ if (strlen(text) < prefix_len || strncmp(text, prefix, prefix_len))
+ {
+ /* Hide menu items not matching */
+ gtk_widget_hide(widget);
+ }
+ else
+ {
+ /* Count how many choices are left in the menu */
+ td->choices++;
+ }
+ }
+}
+
+static gboolean tab_completion_popup_key_press(GtkWidget *widget, GdkEventKey *event, gpointer data)
{
TabCompData *td = data;
- if (event->keyval == GDK_Tab ||
- event->keyval == GDK_BackSpace ||
+ if (event->keyval == GDK_KEY_Tab ||
+ event->keyval == GDK_KEY_BackSpace ||
(event->keyval >= 0x20 && event->keyval <= 0xFF) )
{
if (event->keyval >= 0x20 && event->keyval <= 0xFF)
buf[1] = '\0';
gtk_editable_insert_text(GTK_EDITABLE(td->entry), buf, 1, &p);
gtk_editable_set_position(GTK_EDITABLE(td->entry), -1);
+
+ /* Reduce the number of entries in the menu */
+ td->choices = 0;
+ gtk_container_foreach(GTK_CONTAINER(widget), tab_completion_iter_menu_items, (gpointer) td);
+ if (td->choices > 1) return TRUE; /* multiple choices */
+ if (td->choices > 0) tab_completion_do(td); /* one choice */
}
- /*close the menu */
+ /* close the menu */
gtk_menu_popdown(GTK_MENU(widget));
/* doing this does not emit the "selection done" signal, unref it ourselves */
-#if GTK_CHECK_VERSION(2,12,0)
g_object_unref(widget);
-#else
- gtk_widget_unref(widget);
-#endif
return TRUE;
}
GdkScreen *screen;
gint monitor_num;
GdkRectangle monitor;
+ GtkRequisition requisition;
+ GtkAllocation allocation;
- gdk_window_get_origin(td->entry->window, x, y);
+ gdk_window_get_origin(gtk_widget_get_window(GTK_WIDGET(td->entry)), x, y);
screen = gtk_widget_get_screen(GTK_WIDGET(menu));
- monitor_num = gdk_screen_get_monitor_at_window(screen, td->entry->window);
+ monitor_num = gdk_screen_get_monitor_at_window(screen, gtk_widget_get_window(GTK_WIDGET(td->entry)));
gdk_screen_get_monitor_geometry(screen, monitor_num, &monitor);
gtk_widget_size_request(GTK_WIDGET(menu), &req);
*x += strong_pos.x / PANGO_SCALE + xoffset;
- height = MIN(td->entry->requisition.height, td->entry->allocation.height);
+ gtk_widget_get_requisition(td->entry, &requisition);
+ gtk_widget_get_allocation(td->entry, &allocation);
+
+ height = MIN(requisition.height, allocation.height);
if (req.height > monitor.y + monitor.height - *y - height &&
*y - monitor.y > monitor.y + monitor.height - *y)
#endif
-static gint tab_completion_do(TabCompData *td)
+static gboolean tab_completion_do(TabCompData *td)
{
const gchar *entry_text = gtk_entry_get_text(GTK_ENTRY(td->entry));
const gchar *entry_file;
gchar *entry_dir;
gchar *ptr;
- gint home_exp = FALSE;
+ gboolean home_exp = FALSE;
+
+ if (entry_text[0] == '\0')
+ {
+ entry_dir = g_strdup(G_DIR_SEPARATOR_S); /* FIXME: root directory win32 */
+ gtk_entry_set_text(GTK_ENTRY(td->entry), entry_dir);
+ gtk_editable_set_position(GTK_EDITABLE(td->entry), strlen(entry_dir));
+ g_free(entry_dir);
+ return FALSE;
+ }
/* home dir expansion */
if (entry_text[0] == '~')
entry_dir = g_strdup(entry_text);
}
- entry_file = filename_from_path(entry_text);
-
if (isfile(entry_dir))
{
if (home_exp)
return home_exp;
}
+ entry_file = filename_from_path(entry_text);
+
if (isdir(entry_dir) && strcmp(entry_file, ".") != 0 && strcmp(entry_file, "..") != 0)
{
ptr = entry_dir + strlen(entry_dir) - 1;
tab_completion_read_dir(td, entry_dir);
}
- if (strcmp(entry_dir, G_DIR_SEPARATOR_S) == 0) entry_dir[0] = '\0'; /* FIXME: win32 */
-
list = td->file_list;
while (list)
{
gchar *buf;
buf = g_build_filename(entry_dir, file, NULL);
-
- if (isdir(buf))
- {
- gchar *tmp = g_strconcat(buf, G_DIR_SEPARATOR_S, NULL);
- g_free(buf);
- buf = tmp;
- }
gtk_entry_set_text(GTK_ENTRY(td->entry), buf);
gtk_editable_set_position(GTK_EDITABLE(td->entry), strlen(buf));
g_free(buf);
else
{
gsize c = strlen(entry_file);
- gint done = FALSE;
+ gboolean done = FALSE;
gchar *test_file = poss->data;
while (!done)
return FALSE;
}
-static gint tab_completion_key_pressed(GtkWidget *widget, GdkEventKey *event, gpointer data)
+static gboolean tab_completion_key_pressed(GtkWidget *widget, GdkEventKey *event, gpointer data)
{
TabCompData *td = data;
- gint stop_signal = FALSE;
+ gboolean stop_signal = FALSE;
switch (event->keyval)
{
- case GDK_Tab:
+ case GDK_KEY_Tab:
if (!(event->state & GDK_CONTROL_MASK))
{
if (tab_completion_do(td))
stop_signal = TRUE;
}
break;
- case GDK_Return: case GDK_KP_Enter:
+ case GDK_KEY_Return: case GDK_KEY_KP_Enter:
if (td->fd_button &&
(event->state & GDK_CONTROL_MASK))
{
if (!td) return;
- if (!GTK_WIDGET_HAS_FOCUS(entry))
+ if (!gtk_widget_has_focus(entry))
{
gtk_widget_grab_focus(entry);
}
static void tab_completion_button_size_allocate(GtkWidget *button, GtkAllocation *allocation, gpointer data)
{
GtkWidget *parent = data;
+ GtkAllocation parent_allocation;
+ gtk_widget_get_allocation(parent, &parent_allocation);
- if (allocation->height > parent->allocation.height)
+ if (allocation->height > parent_allocation.height)
{
GtkAllocation button_allocation;
- button_allocation = button->allocation;
- button_allocation.height = parent->allocation.height;
- button_allocation.y = parent->allocation.y +
- (parent->allocation.height - parent->allocation.height) / 2;
+ gtk_widget_get_allocation(button, &button_allocation);
+ button_allocation.height = parent_allocation.height;
+ button_allocation.y = parent_allocation.y +
+ (parent_allocation.height - parent_allocation.height) / 2;
gtk_widget_size_allocate(button, &button_allocation);
}
}
GdkPixbuf *pixbuf;
button = gtk_button_new();
- GTK_WIDGET_UNSET_FLAGS(button, GTK_CAN_FOCUS);
+ gtk_widget_set_can_focus(button, FALSE);
g_signal_connect(G_OBJECT(button), "size_allocate",
G_CALLBACK(tab_completion_button_size_allocate), parent);
g_signal_connect(G_OBJECT(button), "clicked",
box = gtk_hbox_new(FALSE, 0);
- combo = gtk_combo_box_entry_new_text();
+ combo = gtk_combo_box_text_new_with_entry();
gtk_box_pack_start(GTK_BOX(box), combo, TRUE, TRUE, 0);
gtk_widget_show(combo);
- combo_entry = GTK_BIN(combo)->child;
-#if 0
- gtk_combo_set_case_sensitive(GTK_COMBO(combo), TRUE);
- gtk_combo_set_use_arrows(GTK_COMBO(combo), FALSE);
-#endif
+ combo_entry = gtk_bin_get_child(GTK_BIN(combo));
button = tab_completion_create_complete_button(combo_entry, combo);
gtk_box_pack_start(GTK_BOX(box), button, FALSE, FALSE, 0);
work = history_list_get_by_key(history_key);
while (work)
{
- gtk_combo_box_append_text(GTK_COMBO_BOX(combo), (gchar *)work->data);
+ gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), (gchar *)work->data);
work = work->next;
n++;
}
work = history_list_get_by_key(td->history_key);
while (work)
{
- gtk_combo_box_append_text(GTK_COMBO_BOX(td->combo), (gchar *)work->data);
+ gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(td->combo), (gchar *)work->data);
work = work->next;
n++;
}
}
td = g_new0(TabCompData, 1);
+
td->entry = entry;
- td->dir_path = NULL;
- td->file_list = NULL;
td->enter_func = enter_func;
td->enter_data = data;
- td->tab_func = NULL;
- td->tab_data = NULL;
-
- td->has_history = FALSE;
- td->history_key = NULL;
- td->history_levels = 0;
g_object_set_data(G_OBJECT(td->entry), "tab_completion_data", td);
tab_completion_select_show(td);
}
-void tab_completion_add_select_button(GtkWidget *entry, const gchar *title, gint folders_only)
+void tab_completion_add_select_button(GtkWidget *entry, const gchar *title, gboolean folders_only)
{
TabCompData *td;
GtkWidget *parent;