/* $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