/* $Id: xfce-mcs-dialog.c 24269 2007-01-04 19:07:03Z nick $ */
/*-
* Copyright (c) 2002 Jasper Huijsmans <jasper@xfce.org>
* Copyright (c) 2006 Benedikt Meurer <benny@xfce.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#ifdef HAVE_MATH_H
#include <math.h>
#endif
#ifdef HAVE_MEMORY_H
#include <memory.h>
#endif
#include <stdio.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <gdk/gdkx.h>
#include <gmodule.h>
#include <gtk/gtk.h>
#include <libxfce4util/libxfce4util.h>
#include <libxfcegui4/libxfcegui4.h>
#include <xfce-mcs-manager/manager-plugin.h>
#include <xfce-mcs-manager/xfce-mcs-dialog.h>
/* this seems to be the standard border width gtk uses for the action
* area, so the dialog looks best using the same border width */
#define BORDER 6
#define MAX_COLUMNS 4
/*
* To improve the responsiveness of the UI
*/
static gboolean
delayed_run_plugin_dialog (McsPlugin *plugin)
{
plugin->run_dialog (plugin);
return FALSE;
}
static void
run_plugin_dialog (GtkWidget *b, McsPlugin *plugin)
{
g_idle_add ((GSourceFunc) delayed_run_plugin_dialog, (gpointer)plugin);
}
/* this is the dialog currently open. FIXME Maybe do that per screen though. */
static GtkWidget *dlg = NULL;
static void close_dialog(GtkWidget *xdlg)
{
if (xdlg == dlg)
dlg = NULL;
gtk_widget_destroy (xdlg);
}
static int plugincmp (McsPlugin *a, McsPlugin *b)
{
if (!a || !b || !(a->caption) || !(b->caption))
return -1;
return strcoll (a->caption, b->caption);
}
static GtkWidget*
create_settings_button (GdkPixbuf *pb,
const gchar *text)
{
const gchar *icon_name;
GtkWidget *button;
GtkWidget *vbox;
GtkWidget *image;
GtkWidget *label;
g_return_val_if_fail (text != NULL, NULL);
button = gtk_button_new ();
gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
vbox = gtk_vbox_new (FALSE, 0);
gtk_widget_show (vbox);
gtk_container_add (GTK_CONTAINER (button), vbox);
if (G_LIKELY (pb != NULL))
{
/* well, our MCS plugin API is rather messy, so we use
* a weird trick here to pass a named icon from the
* plugin to the manager and still stay backward
* compatible with older plugins.
*/
icon_name = g_object_get_data (G_OBJECT (pb), "mcs-plugin-icon-name");
if (G_LIKELY (icon_name != NULL))
{
/* use the named icon */
image = gtk_image_new_from_icon_name (icon_name, GTK_ICON_SIZE_DIALOG);
}
else
{
/* old plugins */
image = gtk_image_new_from_pixbuf (pb);
}
/* add the image */
gtk_box_pack_start (GTK_BOX (vbox), image, TRUE, TRUE, 0);
gtk_widget_show (image);
}
label = gtk_label_new (text);
gtk_widget_show (label);
gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_CENTER);
gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
return button;
}
static GtkWidget*
create_settings_table (GSList *plugins)
{
int n, rows, columns, i, j;
GSList *li = plugins;
GtkWidget *table, *button;
McsPlugin *plugin;
gboolean need_scrollbar = FALSE;
n = g_slist_length (plugins);
/* this should never happen */
if (G_UNLIKELY (n == 0))
{
g_critical ("No plugins available");
return NULL;
}
columns = sqrt (n);
if (columns > MAX_COLUMNS)
{
columns = MAX_COLUMNS;
need_scrollbar = TRUE;
}
rows = n / columns;
if (n % columns)
rows += 1;
table = gtk_table_new (rows, columns, TRUE);
gtk_table_set_row_spacings (GTK_TABLE (table), 6);
for (i = 0; i < rows; ++i)
{
for (j = 0; j < columns; ++j)
{
plugin = li->data;
button = create_settings_button (plugin->icon, plugin->caption);
gtk_widget_show (button);
g_signal_connect(button, "clicked",
G_CALLBACK(run_plugin_dialog), plugin);
gtk_table_attach_defaults (GTK_TABLE (table), button,
j, j+1, i, i+1);
li = li->next;
if (!li)
goto out;
}
}
out:
if (need_scrollbar)
{
GtkWidget *sw;
sw = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), GTK_SHADOW_NONE);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);
gtk_container_set_border_width (GTK_CONTAINER (sw), BORDER);
gtk_widget_set_size_request (sw, -1, 400);
gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (sw), table);
gtk_widget_show (table);
return sw;
}
else
{
return table;
}
}
void
run_manager_dialog (GSList *plugin_list)
{
GtkWidget *table;
GtkWidget *align;
GSList *sorted_list;
/* check if we already have a dialog */
if (G_LIKELY (dlg != NULL))
{
gtk_window_present (GTK_WINDOW (dlg));
gtk_window_set_focus (GTK_WINDOW (dlg), NULL);
return;
}
/* allocate a new dialog */
dlg = xfce_titled_dialog_new_with_buttons (_("Xfce Settings Manager"), NULL,
GTK_DIALOG_NO_SEPARATOR,
GTK_STOCK_CLOSE, GTK_RESPONSE_OK,
NULL);
gtk_window_set_icon_name (GTK_WINDOW (dlg), "xfce4-settings");
xfce_titled_dialog_set_subtitle (XFCE_TITLED_DIALOG (dlg), _("Customize your Xfce desktop"));
g_signal_connect_swapped (dlg, "response", G_CALLBACK (close_dialog), dlg);
g_signal_connect_swapped (dlg, "delete-event", G_CALLBACK (close_dialog), dlg);
/* buttons */
sorted_list = g_slist_copy (plugin_list);
sorted_list = g_slist_sort (sorted_list, (GCompareFunc) plugincmp);
table = create_settings_table (sorted_list);
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dlg)->vbox), table, TRUE, TRUE, 0);
gtk_widget_show (table);
g_slist_free (sorted_list);
align = gtk_alignment_new (0,0,0,0);
gtk_widget_set_size_request (align, 6, 6);
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dlg)->vbox), align, FALSE, FALSE, 0);
gtk_widget_show (align);
gtk_widget_realize (dlg);
xfce_gtk_window_center_on_monitor_with_pointer (GTK_WINDOW (dlg));
gdk_x11_window_set_user_time (GTK_WIDGET (dlg)->window, gdk_x11_get_server_time (GTK_WIDGET (dlg)->window));
gtk_widget_show (dlg);
}
syntax highlighted by Code2HTML, v. 0.9.1