/*
 * Copyright (c) 2003, 2004 Jean-Yves Lefort
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of Jean-Yves Lefort nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include <gtk/gtk.h>
#include "sg-util.h"
#include "st-settings.h"

/*** cpp *********************************************************************/

#define STRING_PTR		"st-preferences-string-ptr"

/*** function declarations ***************************************************/

static void st_preferences_toggle_toggled_h	  (GtkToggleButton  *toggle,
						   gpointer	    data);
static gboolean st_preferences_entry_focus_out_h  (GtkWidget	    *widget,
						   GdkEventFocus    *event,
						   gpointer	    data);
static void st_preferences_spin_value_changed_h   (GtkSpinButton    *spin,
						   gpointer         data);
static void st_preferences_radio_toggled_h        (GtkToggleButton  *toggle,
						   gpointer         data);

/*** implementation **********************************************************/

void
st_preferences_bind_boolean (GtkToggleButton *toggle, gboolean *ptr)
{
  g_return_if_fail(GTK_IS_TOGGLE_BUTTON(toggle));
  g_return_if_fail(ptr != NULL);

  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toggle), *ptr);

  g_signal_connect(toggle, "toggled", G_CALLBACK(st_preferences_toggle_toggled_h), ptr);
}

static void
st_preferences_toggle_toggled_h (GtkToggleButton *toggle, gpointer data)
{
  gboolean *ptr = data;

  g_return_if_fail(GTK_IS_TOGGLE_BUTTON(toggle));
  g_return_if_fail(ptr != NULL);

  G_LOCK(st_settings);
  *ptr = gtk_toggle_button_get_active(toggle);
  G_UNLOCK(st_settings);
}

void
st_preferences_bind_string (GtkEntry *entry, char **ptr)
{
  g_return_if_fail(GTK_IS_ENTRY(entry));
  g_return_if_fail(ptr != NULL);

  gtk_entry_set_text(entry, *ptr ? *ptr : "");
  g_object_set_data(G_OBJECT(entry), STRING_PTR, ptr);

  g_signal_connect(entry, "focus-out-event", G_CALLBACK(st_preferences_entry_focus_out_h), NULL);
}

void
st_preferences_commit_string (GtkEntry *entry)
{
  char **ptr;
  const char *str;

  g_return_if_fail(GTK_IS_ENTRY(entry));

  ptr = g_object_get_data(G_OBJECT(entry), STRING_PTR);
  g_return_if_fail(ptr != NULL);

  str = gtk_entry_get_text(entry);

  G_LOCK(st_settings);
  g_free(*ptr);
  *ptr = str[0] ? g_strdup(str) : NULL;
  G_UNLOCK(st_settings);
}

static gboolean
st_preferences_entry_focus_out_h (GtkWidget *widget,
				  GdkEventFocus *event,
				  gpointer data)
{
  st_preferences_commit_string(GTK_ENTRY(widget));

  return FALSE;			/* propagate event */
}

void
st_preferences_bind_int_spin (GtkSpinButton *spin, int *ptr)
{
  g_return_if_fail(GTK_IS_SPIN_BUTTON(spin));
  g_return_if_fail(ptr != NULL);

  gtk_spin_button_set_value(spin, *ptr);
  g_signal_connect(spin, "value-changed", G_CALLBACK(st_preferences_spin_value_changed_h), ptr);
}

static void
st_preferences_spin_value_changed_h (GtkSpinButton *spin, gpointer data)
{
  int *ptr = data;

  g_return_if_fail(GTK_IS_SPIN_BUTTON(spin));
  g_return_if_fail(ptr != NULL);

  G_LOCK(st_settings);
  *ptr = gtk_spin_button_get_value_as_int(spin);
  G_UNLOCK(st_settings);
}

void
st_preferences_bind_int_radio (GtkRadioButton *radio, int *ptr, int value)
{
  g_return_if_fail(GTK_IS_RADIO_BUTTON(radio));
  g_return_if_fail(ptr != NULL);

  g_object_set_data(G_OBJECT(radio), "value", GINT_TO_POINTER(value));
  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio), value == *ptr);
  g_signal_connect(radio, "toggled", G_CALLBACK(st_preferences_radio_toggled_h), ptr);
}

static void
st_preferences_radio_toggled_h (GtkToggleButton *toggle, gpointer data)
{ 
  g_return_if_fail(GTK_IS_TOGGLE_BUTTON(toggle));

  if (gtk_toggle_button_get_active(toggle))
    {
      int *ptr = data;
      
      g_return_if_fail(ptr != NULL);
      
      G_LOCK(st_settings);
      *ptr = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(toggle), "value"));
      G_UNLOCK(st_settings);
    }
}
