/*
 *  $Id: map_dialog.c,v 1.16 2000/07/23 00:55:29 remlali Exp $
 *
 *  GXSNMP -- An snmp management application
 *  Copyright 1999, Gregory McLean
 *
 *  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, Cambridge, MA 02139, USA.
 *
 *  The map_dialog widget is used to handle adding/editing maps.
 */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <gnome.h>
#include "gnome-property-dialog.h"
#include "main.h"
#include "dbapi.h"
#include "gxsnmp/gxsnmp_dbapi.h"
#include "map_dialog.h"
#include "map_panel.h"
#include "gxsnmp_window.h"

#include "debug.h"

extern gxsnmp *app_info;

/****************************************************************************
** Static data
****************************************************************************/

#define CLIST_COLUMNS 2

static char *titles[] = {
  N_("Map Name"),
  N_("Notebook Tab") 
};
static char *tips[] = {
  N_("The name of this map."),
  N_("What should be shown in the notebook tab.")
};

static gint title_widths[] = { 16, 8 };

/****************************************************************************
** Forward declarations and callback functions 
****************************************************************************/

static void   map_dialog_class_init      (GXsnmp_map_dialogClass   *klass);
static void   map_dialog_init            (GXsnmp_map_dialog        *dialog);
static void   map_refresh_cb             (G_sqldb_table            *table,
					  gpointer                 row,
					  G_sqldb_cb_type          type,
					  gpointer                 data);
static void   map_refresh_row            (GXsnmp_map_dialog        *dialog,
					  DB_map                   *dbm);
static void   map_select_row_cb          (GtkWidget                *widget,
					  gint                     row,
					  gint                     column,
					  GdkEventButton           *event,
					  gpointer                 data);
static void   map_changed_cb             (GtkWidget                *widget,
					  gpointer                 data);
static void   map_renamed_cb             (GtkWidget                *widget,
					  gpointer                 data);
static void   map_tag_renamed_cb         (GtkWidget                *widget,
					  gpointer                 data);
static void   map_apply_cb               (GtkWidget                *widget,
					  gpointer                 data);
static int    map_close_cb               (GtkWidget                *widget,
					  gpointer                 data);
static void   map_destroy_object         (DB_map                   *dbm);

/****************************************************************************
 * gxsnmp_map_dialog_get_type
 ***************************************************************************/

GtkType
gxsnmp_map_dialog_get_type ()
{
  static GtkType map_type = 0;
  if (!map_type)
    {
      GtkTypeInfo map_info = 
      {
	"GXsnmp_map_dialog",
	sizeof (GXsnmp_map_dialog),
	sizeof (GXsnmp_map_dialogClass),
	(GtkClassInitFunc) map_dialog_class_init,
	(GtkObjectInitFunc) map_dialog_init,
	/* Reserved 1 */ NULL, 
	/* Reserved 2 */ NULL,
	(GtkClassInitFunc) NULL,
      };
      map_type = gtk_type_unique (gnome_property_dialog_get_type(), &map_info);
    }
  return map_type;
}

/****************************************************************************
 * Class initialization
 ****************************************************************************/
static void
map_dialog_class_init (GXsnmp_map_dialogClass *klass)
{
  d_print (DEBUG_TRACE, "\n");
}

/**************************************************************************
 * Widget initialization 
 *************************************************************************/
static void
map_dialog_init (GXsnmp_map_dialog *dialog)
{
  GtkWidget *table;
  GtkWidget *vbox;
  GtkWidget * button_box;
  GtkWidget * pixmap;


  gint      i, c_width, c_height;
  gint      clist_width;
  D_FUNC_START;
/*
**  First build the widget structure
*/

  table = gtk_table_new (2, 2, FALSE);
  gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (dialog)->vbox),
		      table, TRUE, TRUE, 0);

  c_width  = gdk_string_width (table->style->font, "xW") / 2;
  c_height = table->style->font->ascent +
             table->style->font->descent;

  vbox = gtk_vbox_new (FALSE, 8);
  gtk_table_attach (GTK_TABLE (table), vbox, 0, 1, 0, 1,
		    0, GTK_EXPAND | GTK_FILL, 8, 8);

  dialog->scrolled = gtk_scrolled_window_new (NULL, NULL);
  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (dialog->scrolled),
				  GTK_POLICY_AUTOMATIC,
				  GTK_POLICY_ALWAYS);
  gtk_box_pack_start (GTK_BOX (vbox), dialog->scrolled, TRUE, TRUE, 0);

  dialog->map_clist = gtk_clist_new_with_titles (CLIST_COLUMNS, titles);
  gtk_clist_set_selection_mode (GTK_CLIST (dialog->map_clist), 
				GTK_SELECTION_BROWSE);
  gtk_clist_column_titles_passive (GTK_CLIST (dialog->map_clist));
  clist_width = 0;
  for (i = 0; i < CLIST_COLUMNS; i++)
    {
      clist_width += title_widths[i] + 2;
      gtk_clist_set_column_width (GTK_CLIST (dialog->map_clist), i, 
				c_width * title_widths[i]);
    }

  gtk_widget_set_usize (dialog->map_clist, clist_width * c_width,
			c_height * 8);
  gtk_container_add (GTK_CONTAINER (dialog->scrolled), dialog->map_clist);


  button_box = gtk_hbutton_box_new ();
  gtk_table_attach (GTK_TABLE (table), button_box, 0, 1, 1, 2,
		    0, GTK_EXPAND | GTK_FILL, 8, 8);

  pixmap = gnome_stock_pixmap_widget (GTK_WIDGET(dialog),
                                      "gxsnmp/add_host.xpm");
  dialog->add_button = gnome_pixmap_button (pixmap, "Add");
  gtk_box_pack_start (GTK_BOX (button_box), dialog->add_button,
                      TRUE, TRUE, 0);

  pixmap = gnome_stock_pixmap_widget (GTK_WIDGET(dialog),
                                      "gxsnmp/del_host.xpm");
  dialog->delete_button = gnome_pixmap_button (pixmap, "Delete");
  gtk_box_pack_start (GTK_BOX (button_box), dialog->delete_button,
                      TRUE, TRUE, 0);

  /*
   * Now the map info of the current map 
   */

  /* map_panel.... */
  dialog->map_panel = gxsnmp_map_panel_new ();
  gtk_table_attach (GTK_TABLE (table), dialog->map_panel, 1, 2, 0, 1,
		    0, 0, 8, 8);
  /* Signals */

  gtk_signal_connect (GTK_OBJECT (dialog), "apply",
		      (GtkSignalFunc) map_apply_cb, dialog);
  gtk_signal_connect (GTK_OBJECT (dialog), "close",
		      (GtkSignalFunc) map_close_cb, dialog);
  gtk_signal_connect (GTK_OBJECT (dialog->map_clist), "select_row",
		      (GtkSignalFunc) map_select_row_cb, dialog);
  gtk_signal_connect (GTK_OBJECT (GXSNMP_MAP_PANEL(dialog->map_panel)->name), 
		      "changed", (GtkSignalFunc) map_renamed_cb, dialog);
  gtk_signal_connect (GTK_OBJECT (GXSNMP_MAP_PANEL(dialog->map_panel)->tab),
		      "changed", (GtkSignalFunc) map_tag_renamed_cb, dialog);
  gtk_signal_connect (GTK_OBJECT (dialog->map_panel), "changed", 
		      (GtkSignalFunc) map_changed_cb, dialog);
  /* Show the whole mess */
  gtk_widget_show_all (table);
  D_FUNC_END;
}

/****************************************************************************
 * Callback function to refresh the entire widget contents.
 ***************************************************************************/

static void
map_refresh_cb (G_sqldb_table *table, gpointer row, G_sqldb_cb_type type,
		gpointer data)
{
  GXsnmp_map_dialog    *dialog;
  GtkCList             *clist;
  GList                *gl;
  GtkAdjustment        *adjustment;
  double               old_upper, old_value;
  D_FUNC_START;
  g_return_if_fail (data != NULL);
  g_return_if_fail (table != NULL);

  dialog = GXSNMP_MAP_DIALOG (data);
  clist  = GTK_CLIST (dialog->map_clist);
  adjustment = gtk_scrolled_window_get_vadjustment 
    (GTK_SCROLLED_WINDOW (dialog->scrolled));
  old_upper = adjustment->upper;
  old_value = adjustment->value;
  
  gtk_clist_freeze (clist);
  gtk_clist_clear (clist);
  gtk_signal_handler_block_by_data (GTK_OBJECT (clist), dialog);
  gl = g_sqldb_table_list (map_sqldb);
  while (gl)
    {
      map_refresh_row (dialog, (DB_map *)gl->data);
      gl = gl->next;
    }
  if (dialog->selected_map->rowid == 0)
    {
      map_refresh_row (dialog, dialog->selected_map);
      gtk_adjustment_set_value (adjustment, old_upper);
    }
  else
    gtk_adjustment_set_value (adjustment, old_value);
  gtk_signal_handler_unblock_by_data (GTK_OBJECT (clist), dialog);
  gtk_clist_thaw (clist);
  D_FUNC_END;
}
/****************************************************************************
 * map_refresh_row ()
 ***************************************************************************/
static void
map_refresh_row (GXsnmp_map_dialog *dialog, DB_map *dbm)
{
  GtkCList  *clist;
  gchar     *entry[2];
  gint      row;
  D_FUNC_START;
  g_return_if_fail (dialog != NULL);
  g_return_if_fail (dbm != NULL);

  clist = GTK_CLIST (dialog->map_clist);
  g_return_if_fail (clist != NULL);
  g_return_if_fail (GTK_IS_CLIST (clist));
  entry[0] = dbm->name;
  entry[1] = dbm->tab;
  row = gtk_clist_append (clist, entry);
  gtk_clist_set_row_data (clist, row, GINT_TO_POINTER (dbm->rowid));
  if (dialog->selected_map == dbm)
    {
      gtk_signal_handler_unblock_by_data (GTK_OBJECT (clist), dialog);
      gtk_clist_select_row (clist, row, 0);
      gtk_signal_handler_block_by_data (GTK_OBJECT (clist), dialog);
    }
  D_FUNC_END;
}
/****************************************************************************
 * map_select_row_cb
 ***************************************************************************/
static void
map_select_row_cb (GtkWidget *widget, gint row, gint column, 
		   GdkEventButton *event, gpointer data)
{
  GXsnmp_map_dialog     *dialog;
  GtkCList              *clist;
  guint                 rowid;
  DB_map                *dbm;

  D_FUNC_START;
  g_return_if_fail (widget != NULL);
  g_return_if_fail (data != NULL);
  
  dialog = GXSNMP_MAP_DIALOG (data);
  clist  = GTK_CLIST(widget);
  dialog->row = row;
  rowid = GPOINTER_TO_INT (gtk_clist_get_row_data (clist, row));
  if (rowid)
    {
      dbm = g_sqldb_row_find (map_sqldb, "_rowid", &rowid);
      if (dbm)
	{
	  dialog->selected_map = dbm;
	}
      else
	dialog->selected_map = NULL;
    }
  else
    dbm = dialog->selected_map;
  gtk_signal_handler_block_by_data (GTK_OBJECT (dialog->map_panel), dialog);
  gxsnmp_map_panel_put_data (GXSNMP_MAP_PANEL (dialog->map_panel), dbm);
  gtk_signal_handler_unblock_by_data (GTK_OBJECT (dialog->map_panel), dialog);
  D_FUNC_END;
}
/****************************************************************************
 * map_changed_cb
 ***************************************************************************/
static void
map_changed_cb (GtkWidget *widget, gpointer data)
{
  gnome_property_dialog_changed (data);
}
/****************************************************************************
 * map_renamed_cb
 ***************************************************************************/
static void
map_renamed_cb (GtkWidget *widget, gpointer data)
{
  GXsnmp_map_dialog   *dialog;
  GtkCList            *clist;

  D_FUNC_START;
  g_return_if_fail (data != NULL);

  dialog = GXSNMP_MAP_DIALOG (data);
  clist  = GTK_CLIST (dialog->map_clist);
  g_return_if_fail (clist != NULL);
  g_return_if_fail (GTK_IS_CLIST (clist));
  gtk_clist_set_text (clist, dialog->row, 0,
   gtk_entry_get_text (GTK_ENTRY (GXSNMP_MAP_PANEL(dialog->map_panel)->name)));
  map_changed_cb (widget, data);
  D_FUNC_END;
}
/****************************************************************************
 * map_tag_renamed_cb
 ***************************************************************************/
static void
map_tag_renamed_cb (GtkWidget *widget, gpointer data)
{
  GXsnmp_map_dialog    *dialog;
  GtkCList             *clist;

  D_FUNC_START;
  g_return_if_fail (data != NULL);
  dialog = GXSNMP_MAP_DIALOG (data);
  clist  = GTK_CLIST (dialog->map_clist);
  g_return_if_fail (clist != NULL);
  g_return_if_fail (GTK_IS_CLIST (clist));
  gtk_clist_set_text (clist, dialog->row, 1,
   gtk_entry_get_text (GTK_ENTRY (GXSNMP_MAP_PANEL (dialog->map_panel)->tab)));
  map_changed_cb (widget, data);
  D_FUNC_END;
}
/****************************************************************************
 * map_apply_cb
 ***************************************************************************/
static void
map_apply_cb (GtkWidget *widget, gpointer data)
{
  GXsnmp_map_dialog   *dialog;
  DB_map              *dbm;
  GXsnmp_map          *map;
  gboolean            changed;
  D_FUNC_START;
  g_return_if_fail (data != NULL);
  dialog = GXSNMP_MAP_DIALOG (data);
  dbm    = dialog->selected_map;
  if (!dbm)
    {
      g_warning ("map_apply_cb: dbm !NULL");
      D_FUNC_END;
      return;
    }
  changed = gxsnmp_map_panel_get_data (GXSNMP_MAP_PANEL (dialog->map_panel), 
				       dbm);
  if (dbm->rowid == 0)             /* Hey A new map! */
    {
      map_add (dbm);
      map = dbm->application = gxsnmp_map_new ();
      map->DB_map = dbm;
      gxsnmp_map_set_name (GXSNMP_MAP (dbm->application), dbm->tab);
      gxsnmp_window_add_map (GXSNMP_WINDOW (app_info->window),
			     GXSNMP_MAP (dbm->application));
      gtk_widget_show_all (GTK_WIDGET (dbm->application));
    }
  if (changed)
    {
      map_update (dbm);
      gxsnmp_map_set_name (GXSNMP_MAP (dbm->application), dbm->tab);
    }
  D_FUNC_END;
}
/****************************************************************************
 * Close callback.
 * If the selected map has a rowid of 0 then the user canceled addeding 
 * a new map. so just discard the data.
 ***************************************************************************/
static gint
map_close_cb (GtkWidget *widget, gpointer data)
{
  GXsnmp_map_dialog *dialog;
  D_FUNC_START;
  g_return_val_if_fail (widget != NULL, FALSE);
  dialog = GXSNMP_MAP_DIALOG (widget);
  if (dialog->selected_map->rowid == 0)
    map_destroy_object (dialog->selected_map);
  D_FUNC_END;
  return FALSE;
}
/****************************************************************************
 * map_destroy_object
 ***************************************************************************/
static void 
map_destroy_object (DB_map *dbm)
{
  D_FUNC_START;
  if (dbm)
    {
      if (dbm->created)     g_free (dbm->created);
      if (dbm->modified)    g_free (dbm->modified);
      if (dbm->name)        g_free (dbm->name);
      if (dbm->tab)         g_free (dbm->tab);
      if (dbm->description) g_free (dbm->description);
      g_free (dbm);
    }
  D_FUNC_END;
}
/****************************************************************************
 * gxsnmp_map_dialog_new 
 ***************************************************************************/
GtkWidget *
gxsnmp_map_dialog_new (gpointer data)
{
  GXsnmp_map_dialog * dialog;
  DB_map            * dbm;
  D_FUNC_START;
  dialog = gtk_type_new (gxsnmp_map_dialog_get_type ());
  dbm = (DB_map *)data;
  if (!dbm)
    {
      dbm = map_create ();
      dbm->name = g_strdup (_("<New Map>"));
      dbm->tab  = g_strdup (_("<New>"));
    }
  dialog->selected_map = dbm;
  map_refresh_cb (map_sqldb, dbm, G_SQLDB_CB_UPDATE, dialog);
  D_FUNC_END;
  return GTK_WIDGET (dialog);
}
/* EOF */

