/*
* previews.c: Pixmap preview browser
*
* Written by: Ullrich Hafner
*
* Copyright (C) 1998 Ullrich Hafner <hafner@bigfoot.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
*/
/*
* $Date: 1999/10/23 17:44:29 $
* $Author: hafner $
* $Revision: 1.30 $
* $State: Exp $
*/
#include "config.h"
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif /* HAVE_UNISTD_H */
/* unistd.h defines _POSIX_VERSION on POSIX.1 systems. */
#if defined(HAVE_DIRENT_H) || defined(_POSIX_VERSION)
# include <dirent.h>
# define NLENGTH(dirent) (strlen ((dirent)->d_name))
#else
# define dirent direct
# define NLENGTH(dirent) ((dirent)->d_namlen)
# ifdef HAVE_SYS_NDIR_H
# include <sys/ndir.h>
# endif /* HAVE_SYS_NDIR_H */
# ifdef HAVE_SYS_DIR_H
# include <sys/dir.h>
# endif /* HAVE_SYS_DIR_H */
# ifdef HAVE_NDIR_H
# include <ndir.h>
# endif /* HAVE_NDIR_H */
#endif /* not (HAVE_DIRENT_H or _POSIX_VERSION) */
#include <gtk/gtk.h>
#include "proplist_t.h"
#include "previews.h"
#include "window.h"
#include "misc.h"
#include "dialog.h"
#include "texture.h"
#include "error.h"
/*******************************************************************************
global variables
*******************************************************************************/
extern GtkTooltips *tooltips;
extern proplist_t windowmaker; /* window.c */
/*******************************************************************************
local variables
*******************************************************************************/
static GList *file_list = NULL;
static GtkWidget *table = NULL;
static GtkWidget *entry = NULL;
static GtkWidget *main_vbox = NULL;
static GtkWidget *scrolled = NULL;
static GtkWidget *ok_button = NULL;
static wtexture_t *wtexture = NULL;
static GtkWidget *pathomenu = NULL;
static GtkWidget *previewbutton = NULL;
/*******************************************************************************
prototypes
*******************************************************************************/
static void
unlock_filelist (GtkWidget *widget, gpointer ptr);
static void
lock_filelist (GtkWidget *widget, gpointer ptr);
static void
new_scrolled_and_table (void);
static void
destroy_data (gpointer data, gpointer user_data);
static void
preview_new_path (GtkWidget *widget, gpointer ptr);
static void
image_list (const char *path);
static void
make_preview (GtkWidget *entry, char *name);
static gint
set_selection (GtkWidget *widget, GdkEventButton *event, gpointer ptr);
static void
accept_selection (GtkWidget *widget, gpointer ptr);
static void
show_previews (GtkWidget *table);
/*******************************************************************************
public code
*******************************************************************************/
void
preview_browser (GtkWidget *widget, gpointer ptr)
/*
* Open or close pixmap preview image browser dialog window.
* If the window is visible then hide the window and vice versa.
*
* No return value.
*/
{
static GtkWidget *window= NULL;
wtexture = (wtexture_t *) ptr;
if (!window) /* window already created */
{
entry = gtk_entry_new ();
/*
* Make new dialog window
*/
window = gtk_dialog_new ();
gtk_window_set_title (GTK_WINDOW (window), _("Pixmap Browser"));
gtk_window_set_position (GTK_WINDOW (window), GTK_WIN_POS_MOUSE);
gtk_signal_connect (GTK_OBJECT (window), "delete_event",
GTK_SIGNAL_FUNC (gtk_true), NULL);
gtk_signal_connect_object (GTK_OBJECT (window), "delete_event",
GTK_SIGNAL_FUNC (gtk_widget_hide),
GTK_OBJECT (window));
/*
* Optionmenu pixmap path and update button
*/
{
const char **pathlist;
unsigned n;
GtkWidget *box;
GtkWidget *button = gtk_button_new_with_label (_("Update previews"));
GtkWidget *bbox = gtk_hbutton_box_new ();
GtkWidget *hbox = gtk_hbox_new (FALSE, 0);
proplist_t plpath = WMCreatePLString ("PixmapPath");
proplist_t pixmap_path = WMGetFromPLDictionary (windowmaker, plpath);
gtk_signal_connect (GTK_OBJECT (button), "clicked",
GTK_SIGNAL_FUNC (lock_filelist), &file_list);
gtk_signal_connect (GTK_OBJECT (button), "clicked",
GTK_SIGNAL_FUNC (generate_previews), &file_list);
gtk_signal_connect (GTK_OBJECT (button), "clicked",
GTK_SIGNAL_FUNC (unlock_filelist), &file_list);
WMReleasePropList (plpath);
pathlist = Calloc (WMGetPropListItemCount (pixmap_path) + 1,
sizeof (char *));
for (n = 0; n < WMGetPropListItemCount (pixmap_path); n++)
pathlist [n] = WMGetFromPLString (WMGetFromPLArray (pixmap_path, n));
pathlist [n] = NULL;
box = generate_option_menu (NULL, tooltips,
_("Window Maker's searchpath for pixmaps"),
pathlist, pathlist [0], NULL,
preview_new_path, NULL);
image_list (pathlist [0]);
Free (pathlist);
pathomenu = box;
previewbutton = button;
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox),
hbox, FALSE, TRUE, 5);
gtk_box_pack_start (GTK_BOX (hbox), gtk_label_new ("PixmapPath:"),
FALSE, TRUE, 5);
gtk_box_pack_start (GTK_BOX (hbox), box, FALSE, TRUE, 5);
gtk_box_pack_start (GTK_BOX (hbox), bbox, FALSE, TRUE, 5);
gtk_box_pack_start (GTK_BOX (bbox), button, FALSE, TRUE, 0);
}
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox),
main_vbox = gtk_vbox_new (FALSE, 0), TRUE, TRUE, 5);
new_scrolled_and_table ();
/*
* Confirm arean (at bottom)
*/
{
GtkWidget *confirm_area;
GtkWidget *button;
GtkWidget *hbox;
hbox = gtk_hbox_new (FALSE, 5);
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), hbox,
FALSE, TRUE, 0);
gtk_box_pack_start (GTK_BOX (hbox), gtk_label_new (_("Filename:")),
FALSE, TRUE, 0);
gtk_widget_set_usize (entry, 200, 0);
gtk_entry_set_editable (GTK_ENTRY (entry), FALSE);
gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 10);
confirm_area = gtk_hbutton_box_new ();
gtk_box_pack_end (GTK_BOX (hbox), confirm_area, FALSE, TRUE, 10);
gtk_button_box_set_spacing (GTK_BUTTON_BOX (confirm_area), 5);
gtk_button_box_set_layout (GTK_BUTTON_BOX (confirm_area),
GTK_BUTTONBOX_END);
ok_button = gtk_button_new_with_label (_("OK"));
gtk_box_pack_start (GTK_BOX (confirm_area), ok_button, TRUE, TRUE, 0);
gtk_signal_connect (GTK_OBJECT (ok_button), "clicked",
GTK_SIGNAL_FUNC (accept_selection), NULL);
gtk_entry_set_text (GTK_ENTRY (entry), PKGDATADIR "/black.xpm");
GTK_WIDGET_SET_FLAGS (ok_button, GTK_CAN_DEFAULT);
gtk_signal_connect_object (GTK_OBJECT (ok_button), "clicked",
GTK_SIGNAL_FUNC (gtk_widget_hide),
GTK_OBJECT (window));
button = gtk_button_new_with_label (_("Cancel"));
gtk_box_pack_start (GTK_BOX (confirm_area), button, TRUE, TRUE, 0);
gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
GTK_SIGNAL_FUNC (gtk_widget_hide),
GTK_OBJECT (window));
GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
gtk_widget_grab_default (button);
}
show_previews (table);
}
if (!GTK_WIDGET_VISIBLE (window))
gtk_widget_show_all (window);
else
gtk_widget_hide (window);
}
static void
image_list (const char *path)
{
DIR *dir;
struct dirent *file;
char *realpath = expand_tilde (path);
dir = opendir (realpath);
if (!dir)
return;
while ((file = readdir (dir)))
{
if (streq (file->d_name, ".") || streq (file->d_name, ".."))
continue;
/*
* Check whether file is a directory
*/
{
char *subdir = g_strconcat (realpath, "/", file->d_name, NULL);
DIR *tmpdir = opendir (subdir);
if (tmpdir)
{
closedir (tmpdir);
Free (subdir);
continue;
}
make_preview (entry, subdir);
}
}
Free (realpath);
closedir (dir);
}
static void
make_preview (GtkWidget *entry, char *name)
/*
* Make button widget displaying a pixmap with tooltips showing the
* pixmap filename.
* 'image' is the filename of the preview.
*
* Return value:
* button widget
*/
{
previewdata_t *data = Calloc (1, sizeof (previewdata_t));
GtkWidget *pixmap;
data->name = name;
data->button = gtk_button_new ();
gtk_signal_connect (GTK_OBJECT (data->button), "button_press_event",
GTK_SIGNAL_FUNC (set_selection), data);
file_list = g_list_append (file_list, data);
{
char *fname = expand_tilde (name);
char *pname = preview_name (fname);
char *path = get_pixmap_path (pname);
if (path)
{
pixmap = make_pixmap (path, 64, 64, NULL);
Free (path);
}
else
{
pixmap = make_pixmap (PKGDATADIR "/black.xpm", 64, 64, NULL);
make_pixmap (WMAKERDATADIR "/Icons/defaultAppIcon.xpm", 64, 64, pixmap);
}
Free (fname);
Free (pname);
}
gtk_tooltips_set_tip (tooltips, data->button, g_basename (name), NULL);
gtk_container_set_border_width (GTK_CONTAINER (data->button), 2);
gtk_container_add (GTK_CONTAINER (data->button), pixmap);
gtk_widget_show_all (data->button);
gtk_object_set_user_data (GTK_OBJECT (data->button), pixmap);
gtk_object_set_user_data (GTK_OBJECT (pixmap), entry);
}
static gint
set_selection (GtkWidget *widget, GdkEventButton *event, gpointer ptr)
/*
* Change text entry if pixmap button is pressed.
*/
{
GtkWidget *pixmap = gtk_object_get_user_data (GTK_OBJECT (widget));
GtkWidget *entry = gtk_object_get_user_data (GTK_OBJECT (pixmap));
previewdata_t *data = (previewdata_t *) ptr;
gtk_entry_set_text (GTK_ENTRY (entry), g_basename (data->name));
if (event->type == GDK_2BUTTON_PRESS)
gtk_signal_emit_by_name (GTK_OBJECT (ok_button), "clicked");
return TRUE;
}
static void
accept_selection (GtkWidget *widget, gpointer ptr)
/*
* OK button is activated: set pixmap and text entry of texture dialog.
*
* No return value.
*/
{
gtk_entry_set_text (GTK_ENTRY (wtexture->wpixmap [PIXMAP_NAME]),
gtk_entry_get_text (GTK_ENTRY (entry)));
verify_pixmap_name (entry, wtexture);
}
static void
show_previews (GtkWidget *table)
{
unsigned n = 0;
unsigned x = 0;
unsigned y = 0;
for (n = 0; n < g_list_length (file_list); n++)
{
previewdata_t *data = g_list_nth_data (file_list, n);
gtk_table_attach (GTK_TABLE (table), data->button, x, x + 1, y, y + 1,
GTK_FILL | GTK_SHRINK, GTK_FILL | GTK_SHRINK, 0, 0);
x++;
if (x == 8)
{
x = 0;
y++;
}
}
}
static void
preview_new_path (GtkWidget *widget, gpointer ptr)
{
char *text = gtk_object_get_user_data (GTK_OBJECT (widget));
g_list_foreach (file_list, destroy_data, NULL);
g_list_free (file_list);
file_list = NULL;
new_scrolled_and_table ();
image_list (text);
show_previews (table);
}
static void
destroy_data (gpointer data, gpointer user_data)
{
previewdata_t *pd = (previewdata_t *) data;
Free (pd->name);
Free (pd);
}
static void
new_scrolled_and_table (void)
{
if (scrolled)
gtk_widget_destroy (scrolled);
scrolled = gtk_scrolled_window_new (NULL, NULL);
gtk_box_pack_start (GTK_BOX (main_vbox), scrolled, TRUE, TRUE, 5);
table = gtk_table_new (1, 1, TRUE);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled),
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
gtk_widget_set_usize (scrolled, 660, 430);
gtk_container_set_border_width (GTK_CONTAINER (scrolled), 5);
gtk_container_set_border_width (GTK_CONTAINER (table), 5);
gtk_table_set_row_spacings (GTK_TABLE (table), 2);
gtk_table_set_col_spacings (GTK_TABLE (table), 2);
gtk_widget_show (table);
gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled),
table);
gtk_widget_show_all (scrolled);
}
static void
lock_filelist (GtkWidget *widget, gpointer ptr)
{
gtk_widget_set_sensitive (pathomenu, FALSE);
gtk_widget_set_sensitive (previewbutton, FALSE);
}
static void
unlock_filelist (GtkWidget *widget, gpointer ptr)
{
gtk_widget_set_sensitive (pathomenu, TRUE);
gtk_widget_set_sensitive (previewbutton, TRUE);
}
syntax highlighted by Code2HTML, v. 0.9.1