/*
**  GXSNMP - An snmp managment application
**  Copyright (C) 1998 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.
**
**  Network Window widget  (Basically the main application)
**
**
**  o  The ruler scales are sort of meaningless.
**  o  The rulers should scroll along with the canvas.
**  o  Zooming needs to be implemented.
**  o  The rulers should be just a tad shorter, so that they stop just at the
**     edges of the scrollbars
**  o  The ruler position markers should somehow be made to disappear when
**     The mouse leaves the canvas area.
**
*/

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <gnome.h>
#include "dbapi.h"
#include "gxsnmp/gxsnmp_dbapi.h"
#include "gxsnmp_window.h"
#include "menus.h"
#include "gxsnmp_map.h"
#include "gtkled.h"

#include "debug.h"

/*
**  Forward references
*/

static void window_class_init   (GXsnmp_windowClass 	* klass);
static void window_init         (GXsnmp_window	  	* window);

static gint update_mouse_status (GtkWidget 		* widget, 
				 GdkEventMotion 	* e, 
				 gpointer 		  data);

static gint clear_mouse_status  (GtkWidget 		* widget,
				 GdkEventCrossing 	* event,
				 gpointer		  data);
static void page_switch_cb      (GtkWidget               *widget, 
				 GtkNotebookPage         *page,
				 gint                    page_num,
				 gpointer		 data);

/*****************************************************************************
**
**  gxsnmp_window_get_type ()
**
*****************************************************************************/

GtkType
gxsnmp_window_get_type()
{
  static GtkType window_type = 0;

  if (!window_type)
    {
      GtkTypeInfo window_info =
      {
        "GXsnmp_window",
        sizeof (GXsnmp_window),
        sizeof (GXsnmp_windowClass),
        (GtkClassInitFunc) window_class_init,
        (GtkObjectInitFunc) window_init,
        /* reserved 1 */ NULL,
        /* reserved 2 */ NULL,
	(GtkClassInitFunc) NULL,
      };
      window_type = gtk_type_unique (gnome_app_get_type (), &window_info);
    }
  return window_type;
}

/****************************************************************************
**
**  The class initialization subroutine
**
*****************************************************************************/

static void
window_class_init (GXsnmp_windowClass *klass)
{

}

/*****************************************************************************
**
**  The widget initialization subroutine
**
*****************************************************************************/

static void
window_init (GXsnmp_window *window)
{
  GtkWidget	* window_vbox;
  GtkWidget	* window_hbox;
  GtkWidget	* status_hbox;
  gchar         * logo_pixmap_filename;
  gint		  width;
  D_FUNC_START;
/*
**  Do this here, if its done in the new () method GNOME_APP(window)->name,
**  and GTK_WINDOW(window)->title are null. Having them NULL and calling
**  create_menus will cause a seg fault in the tearoff menu code.
*/
  window->map_list = NULL;
  
  gnome_app_construct (GNOME_APP(window), 
		       "GXSNMP", 
		       N_("GXSNMP Network Management Tool"));
/*
**  Create all of the menus and also the toolbar.  See menus.c
*/

  menu_create (GTK_WIDGET (window));

/*
**  The application window is a vbox containing a window hbox and a
**  status hbox.
*/

  window_vbox = gtk_vbox_new (FALSE, 0);
  gtk_container_set_border_width (GTK_CONTAINER (window_vbox), 2);
  gtk_widget_show (window_vbox);

  window_hbox = gtk_hbox_new (FALSE, 0);
  gtk_container_border_width (GTK_CONTAINER (window_hbox), 2);
  gtk_box_pack_start_defaults (GTK_BOX (window_vbox), window_hbox);
  gtk_widget_show (window_hbox);
 
  status_hbox = gtk_hbox_new (FALSE, 0);
  gtk_container_border_width (GTK_CONTAINER (status_hbox), 2);
  gtk_box_pack_start (GTK_BOX (window_vbox), status_hbox, FALSE, FALSE, 0);
  gtk_widget_show (status_hbox);

/*
**  The logo
*/
  
  logo_pixmap_filename = gnome_pixmap_file ("gxsnmp/logo_v.xpm");
  if (logo_pixmap_filename)
    {
      window->logo = gnome_pixmap_new_from_file (logo_pixmap_filename);
      gtk_box_pack_start (GTK_BOX (window_hbox), window->logo,
			  FALSE, FALSE, 0);
      gtk_widget_show (window->logo);
      g_free (logo_pixmap_filename);
    }

/*
**  The map notebook.
*/

  window->map_notebook = gtk_notebook_new ();
  gtk_signal_connect (GTK_OBJECT (window->map_notebook), "switch_page",
		      GTK_SIGNAL_FUNC (page_switch_cb), window);
  gtk_box_pack_start_defaults (GTK_BOX (window_hbox), window->map_notebook);
  gtk_notebook_popup_enable (GTK_NOTEBOOK (window->map_notebook));
  gtk_widget_show (window->map_notebook);

/*
**  Fixed width status area for the mouse
*/

  window->mouse_status = gtk_label_new ("");
  width = gdk_text_width ((window->mouse_status)->style->font,
			  "9999 x 9999", 13);
  gtk_widget_set_usize (window->mouse_status, width, -2);
  gtk_box_pack_start (GTK_BOX (status_hbox), window->mouse_status,
		      FALSE, FALSE, 0);
  gtk_widget_show (window->mouse_status);

/*
**  Status area for the map.  The gtk_statusbar_new stuff is a bit on the
**  overkill side, so I'll just use a label widget for now.
*/

  window->map_statusbar = gtk_label_new ("");     
  gtk_box_pack_start_defaults (GTK_BOX (status_hbox), window->map_statusbar);
  gtk_widget_show (window->map_statusbar);

/*
**  Now add all of this to the gnome_app.
*/

  gnome_app_set_contents (GNOME_APP (window), window_vbox);
  D_FUNC_END;
}

/*****************************************************************************
**
**  Callback function to update the mouse cursor location
**
*****************************************************************************/

static gint
update_mouse_status (GtkWidget *widget, GdkEventMotion *e, gpointer data)
{
  gint              x, y;
  gchar             buf[15];
  GXsnmp_window	    * gxwin;

  D_FUNC_START;
  g_return_val_if_fail (data != NULL, FALSE);
  gxwin = GXSNMP_WINDOW (data);

  if (e->is_hint || (e->window != widget->window) )
    gdk_window_get_pointer (e->window, &x, &y, NULL);
  else
    {
      x     = e->x;
      y     = e->y;
    }
  snprintf (buf, sizeof (buf), "%d x %d", x, y);

  gtk_label_set (GTK_LABEL (gxwin->mouse_status), buf);
  D_FUNC_END;
  return FALSE;
}

/*****************************************************************************
**
**  Callback function to clear the mouse cursor status indicator when the
**  cursor leaves the canvas.
**
*****************************************************************************/

static gint
clear_mouse_status (GtkWidget *widget, GdkEventCrossing *event, gpointer data)
{
  GXsnmp_window     * gxwin;
  D_FUNC_START;
  g_return_val_if_fail (data != NULL, FALSE);
  gxwin = GXSNMP_WINDOW (data);

  gtk_label_set (GTK_LABEL (gxwin->mouse_status), "");
  D_FUNC_END;
  return FALSE;
}

/*****************************************************************************
** 
** Callback function for when we switch to a new map page. Used to update
** The menus to reflect the state of the new, visible map.
**
*****************************************************************************/

static void
page_switch_cb (GtkWidget 	* widget, 
		GtkNotebookPage * page, 
		gint 	          page_num,
		gpointer 	  data)		/* --> GXsnmp_window object */
{
  GXsnmp_window	* window;
  GXsnmp_map    * map;

  D_FUNC_START;

  g_return_if_fail (widget != NULL);
  g_return_if_fail (page != NULL);
  g_return_if_fail (data != NULL);

  window = GXSNMP_WINDOW (data);
  map = gxsnmp_window_get_current_map (window);
  if (map)
    menu_set_snap_state (map->do_snapping);
  D_FUNC_END;
}

/*****************************************************************************
**
**  Public function to create a new widget
**
*****************************************************************************/

GtkWidget *
gxsnmp_window_new (void)
{
  D_FUNC_START;
  return GTK_WIDGET (gtk_type_new (GXSNMP_TYPE_WINDOW));
}

/*******************************************************************************
**
**  Public function to add a page to the map notebook.  A map notebook page  
**  consists of a table, containing horizontal and vertical rulers, and a
**  GtkScrolledWindow, containing a GXsnmp_map widget.
**
*******************************************************************************/

void
gxsnmp_window_add_map (GXsnmp_window * window, 
			  GXsnmp_map * map)
{
  GtkWidget * table;
  GtkWidget * hruler;
  GtkWidget * vruler;
  GtkWidget * scrolled_window;
  GtkWidget * notebook_tab;
  DB_map      *dbm;
  D_FUNC_START;
  g_return_if_fail (window != NULL);
  g_return_if_fail (map != NULL);
  g_return_if_fail (map->DB_map != NULL);

  dbm = (DB_map *)map->DB_map;
  d_print (DEBUG_DUMP, "Adding map to window");
/*
**  The table
*/
  
  table = gtk_table_new (3, 3, FALSE);
 
/*
**  The horizontal ruler
*/

  hruler = gtk_hruler_new ();
  gtk_signal_connect_object (GTK_OBJECT (map),
                             "motion_notify_event",
                             (GtkSignalFunc) GTK_WIDGET_CLASS ( GTK_OBJECT
				 (hruler)->klass)->motion_notify_event,
                             GTK_OBJECT (hruler));
  gtk_table_attach (GTK_TABLE (table), hruler, 1, 3, 0, 1,
                    GTK_EXPAND | GTK_FILL, 0, 0, 0);
  gtk_ruler_set_range (GTK_RULER (hruler), 0, 10, 5, 10);

/*
**  The vertical ruler 
*/

  vruler = gtk_vruler_new ();
  gtk_signal_connect_object (GTK_OBJECT (map),
                             "motion_notify_event",
                             (GtkSignalFunc) GTK_WIDGET_CLASS ( GTK_OBJECT
                                (vruler)->klass)->motion_notify_event,
                             GTK_OBJECT (vruler));
  gtk_table_attach (GTK_TABLE (table), vruler, 0, 1, 1, 3,
                    0, GTK_EXPAND | GTK_FILL, 0, 0);
  gtk_ruler_set_range (GTK_RULER (vruler), 0, 10, 5, 10);

/*
**  The scrolled window that contains the canvas
*/

  scrolled_window = gtk_scrolled_window_new (GTK_LAYOUT (map)->hadjustment,
                      			     GTK_LAYOUT (map)->vadjustment);
  gtk_table_attach (GTK_TABLE (table), scrolled_window, 1, 3, 1, 3,
                    GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
  gtk_container_add (GTK_CONTAINER (scrolled_window), GTK_WIDGET (map));
  gtk_widget_set_usize (scrolled_window, 600, 400);


/*
**  Now create the notebook tab and add the notebook page.  Make sure that
**  the default map (rowid == 1) is the first page.
*/

  notebook_tab = gtk_label_new (dbm->tab);

  if (map->DB_map->rowid == 1)		/* Prepend the default map */
    {
      gtk_notebook_prepend_page (GTK_NOTEBOOK (window->map_notebook),
			         table, 
				 notebook_tab);
      window->map_list = g_list_prepend (window->map_list, map);
      gtk_notebook_set_page (GTK_NOTEBOOK (window->map_notebook), 0);
    }
  else
    {
      gtk_notebook_append_page (GTK_NOTEBOOK (window->map_notebook), 
  			        table,
			        notebook_tab);
      window->map_list = g_list_append (window->map_list, map);
    }

/*
**  The following two signals are used to display the mouse location status
**  and control the display of the ruler position indicators.
*/

  gtk_signal_connect (GTK_OBJECT (map), "motion_notify_event",
                      (GtkSignalFunc) update_mouse_status,
                      window);

  gtk_signal_connect (GTK_OBJECT (map), "leave_notify_event",
                      (GtkSignalFunc) clear_mouse_status,
                      window); 
  gtk_widget_show_all (table);
  D_FUNC_END;
}

/****************************************************************************
**
**  Public function to obtain the current gxsnmp_map object (the selected
**  notebook page).
**
****************************************************************************/

GXsnmp_map *
gxsnmp_window_get_current_map (GXsnmp_window * window)
{
  gint            pageno;
  GList		* gl;
  
  D_FUNC_START;
  g_return_val_if_fail (window != NULL, NULL);
  g_return_val_if_fail (GXSNMP_IS_WINDOW (window), NULL);

  if (!window->map_notebook)
    {
      d_print (DEBUG_TRACE, "window->map_notebook is invaild."
	       " Returning a NULL pointer.");
      D_FUNC_END;
      return NULL;
    }
      
  pageno = gtk_notebook_get_current_page (GTK_NOTEBOOK (window->map_notebook));
  if (pageno < 0)
    {
      d_print (DEBUG_DUMP, "Pageno is %d\n", pageno);
      d_print (DEBUG_TRACE, "Returning a NULL pointer.\n");
      D_FUNC_END;
      return NULL;
    }
  gl = g_list_nth (window->map_list, pageno);
  d_print (DEBUG_TRACE, "Valid pointer being returned.\n");
  D_FUNC_END;
  return GXSNMP_MAP (gl->data);
}

/*****************************************************************************
**
**  Public function to change the contents of the statusbar.
**
*****************************************************************************/

void
gxsnmp_window_set_statusbar_text (GXsnmp_window * window, gchar * string)
{
  gtk_label_set (GTK_LABEL (window->map_statusbar), string);
}

/* EOF */

