/* -*-c-*- -------------- mixgtk_fontsel.c :
 * Implementation of the functions declared in mixgtk_fontsel.h
 * ------------------------------------------------------------------
 *  $Id: mixgtk_fontsel.c,v 1.14 2001/09/18 22:51:29 jao Exp $
 * ------------------------------------------------------------------
 * Copyright (C) 2001 Free Software Foundation, Inc.
 *  
 * 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-1307, USA.
 *  
 */

#include <mixlib/mix.h>
#include "mixgtk_widgets.h"
#include "mixgtk_config.h"
#include "mixgtk_fontsel.h"

static GtkWidget *fontsel_dialog_ = NULL;
static mixgtk_widget_id_t widget_;
static GHashTable *winfo_ = NULL;

typedef struct winfo
{
  GtkWidget *widget;
  GtkStyle *style;
  gchar *font;
  const gchar *key;
} winfo;

static mixgtk_widget_id_t widget_ids_[] = {
  MIXGTK_WIDGET_MIXVM,
  MIXGTK_WIDGET_PROMPT,
  MIXGTK_WIDGET_LOG,
  MIXGTK_WIDGET_MIXAL,
  MIXGTK_WIDGET_DEVICE
};

static mixgtk_dialog_id_t dialog_ids_no_split_[] = {
  MIXGTK_MAIN,
  MIXGTK_MAIN,
  MIXGTK_MAIN,
  MIXGTK_MAIN,
  MIXGTK_MAIN,
};

static mixgtk_dialog_id_t dialog_ids_split_[] = {
  MIXGTK_MIXVM_DIALOG,
  MIXGTK_MAIN,
  MIXGTK_MAIN,
  MIXGTK_MIXAL_DIALOG,
  MIXGTK_DEVICES_DIALOG
};

static mixgtk_widget_id_t mixvm_children_[] = {
  MIXGTK_WIDGET_rA,
  MIXGTK_WIDGET_rX,
  MIXGTK_WIDGET_rJ,
  MIXGTK_WIDGET_rI1,
  MIXGTK_WIDGET_rI2,
  MIXGTK_WIDGET_rI3,
  MIXGTK_WIDGET_rI4,
  MIXGTK_WIDGET_rI5,
  MIXGTK_WIDGET_rI6,
  MIXGTK_WIDGET_CMP_L,
  MIXGTK_WIDGET_CMP_E,
  MIXGTK_WIDGET_CMP_G,
  MIXGTK_WIDGET_OVER,
  MIXGTK_WIDGET_CELLS,
  MIXGTK_WIDGET_LAPTIME,
  MIXGTK_WIDGET_PROGTIME,
  MIXGTK_WIDGET_UPTIME,
  MIXGTK_WIDGET_LOC
};

static const int CHILDREN_NO_ =
(sizeof (mixvm_children_) / sizeof (mixvm_children_[0]));

static mixgtk_dialog_id_t *dialog_ids_ = NULL;

static const gchar *keys_[] = {
  "MIX.font", "Prompt.font", "Log.font", "MIXAL.font", "Device.font"
};



#define WIDGET_NO_  (sizeof (widget_ids_) / sizeof (widget_ids_[0]))

static winfo infos_[WIDGET_NO_];

/* initialise the font selection dialog */
static void
init_fontsel_ (void) 
{
  fontsel_dialog_ = mixgtk_widget_factory_get_dialog (MIXGTK_FONTSEL_DIALOG);
  g_assert (fontsel_dialog_ != NULL);
}

void
change_font_ (mixgtk_widget_id_t widget)
{
  winfo *info;
  if (!fontsel_dialog_) init_fontsel_ ();
  info = (winfo *) g_hash_table_lookup (winfo_,	GINT_TO_POINTER (widget));
  g_assert (info);
  widget_ = widget;
  if (info->font)
    gtk_font_selection_dialog_set_font_name
      (GTK_FONT_SELECTION_DIALOG (fontsel_dialog_), info->font);
  
  gtk_widget_show (fontsel_dialog_);

}

void
mixgtk_fontsel_load_defaults (void)
{
  int i;
  const gchar *font = NULL;
  gboolean split = mixgtk_config_is_split ();

  fontsel_dialog_ = NULL;

  if (winfo_) g_hash_table_destroy (winfo_);
  winfo_ = g_hash_table_new (NULL, NULL);
  dialog_ids_ = split? dialog_ids_split_ : dialog_ids_no_split_;
  for (i = 0; i < WIDGET_NO_; ++i)
    {
      infos_[i].widget =
	mixgtk_widget_factory_get (dialog_ids_[i], widget_ids_[i]);
      g_assert (infos_[i].widget != NULL);
      if (infos_[i].style) gtk_style_unref (infos_[i].style);
      infos_[i].style = gtk_style_copy
	(gtk_widget_get_style (infos_[i].widget));
      gtk_widget_set_style (infos_[i].widget, infos_[i].style);
      if (widget_ids_[i] == MIXGTK_WIDGET_MIXVM)
	{
	  int k;
	  for (k = 0; k < CHILDREN_NO_; ++k)
	    gtk_widget_set_style (mixgtk_widget_factory_get
				  (MIXGTK_MIXVM_DIALOG, mixvm_children_[k]),
				  infos_[i].style);
	}
      infos_[i].key = keys_[i];
      g_hash_table_insert (winfo_, GINT_TO_POINTER (widget_ids_[i]),
			   (gpointer)(infos_ + i));

      infos_[i].font = NULL;
      font = mixgtk_config_get (keys_[i]);
      if (font) mixgtk_fontsel_set (widget_ids_[i], font);
    }
}

void
mixgtk_fontsel_set (mixgtk_widget_id_t widget, const gchar *font)
{
  winfo *w = (winfo *)
    g_hash_table_lookup (winfo_, GINT_TO_POINTER (widget));
  if (w != NULL && font != NULL)
    {
      GdkFont *f = gdk_font_load (font);
      if (f != NULL)
	{
	  gdk_font_unref (w->style->font);
	  w->style->font = f;
	  if (w->font) g_free (w->font);
	  w->font = g_strdup (font);
	  gtk_widget_draw (w->widget, NULL);

	  if (widget == MIXGTK_WIDGET_MIXVM)
	    {
	      int k;
	      for (k = 0; k < CHILDREN_NO_; ++k)
		gtk_widget_draw
		  (mixgtk_widget_factory_get (MIXGTK_MIXVM_DIALOG,
					      mixvm_children_[k]),
		   NULL);
	    }
	  mixgtk_config_update (w->key, w->font);
	}
      else
	mixgtk_config_remove (w->key);
    }

}

const gchar *
mixgtk_fontsel_get (mixgtk_widget_id_t widget)
{
  const gchar *result = NULL;
  winfo *w = (winfo *)
    g_hash_table_lookup (winfo_, GINT_TO_POINTER (widget));
  if (w != NULL) result = w->font;
  return result;
}

/* callbacks */
void
on_log_font_activate (void)
{
  change_font_ (MIXGTK_WIDGET_LOG);
}

void
on_mixal_font_activate (void)
{
  change_font_ (MIXGTK_WIDGET_MIXAL);
}

void
on_prompt_font_activate (void)
{
  change_font_ (MIXGTK_WIDGET_PROMPT);
}

void
on_mix_font_activate (void) 
{
  change_font_ (MIXGTK_WIDGET_MIXVM);
}

void
on_devices_font_activate (void) 
{
  change_font_ (MIXGTK_WIDGET_DEVICE);
}

void
on_fontsel_apply_clicked (void)
{
  gchar * name = gtk_font_selection_dialog_get_font_name
    (GTK_FONT_SELECTION_DIALOG (fontsel_dialog_));
  mixgtk_fontsel_set (widget_, name);
  g_free (name);
}

void
on_fontsel_ok_clicked (void)
{
  on_fontsel_apply_clicked ();
  gtk_widget_hide (fontsel_dialog_);
}

void
on_fontsel_cancel_clicked (void)
{
  gtk_widget_hide (fontsel_dialog_);
}