// -*- c++ -*-
/* $Id: colorselection.ccg,v 1.7 2006/05/11 11:40:24 murrayc Exp $ */

/* Copyright 1998-2002 The gtkmm Development Team
 *
 * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include <gtk/gtkcolorsel.h>
#include <gtk/gtkcolorseldialog.h>


namespace
{

static Gtk::ColorSelection::SlotChangePaletteHook* global_change_palette_hook = 0;

static void global_change_palette_hook_callback(GdkScreen* screen, const GdkColor* colors, int n_colors)
{
  g_return_if_fail(global_change_palette_hook != 0);

  #ifdef GLIBMM_EXCEPTIONS_ENABLED
  try
  {
  #endif //GLIBMM_EXCEPTIONS_ENABLED
    (*global_change_palette_hook)(
        Glib::wrap(screen, true),
        Gdk::ArrayHandle_Color(colors, n_colors, Glib::OWNERSHIP_NONE));
  #ifdef GLIBMM_EXCEPTIONS_ENABLED
  }
  catch(...)
  {
    Glib::exception_handlers_invoke();
  }
  #endif //GLIBMM_EXCEPTIONS_ENABLED
}

static void old_change_palette_hook_callback(const Glib::RefPtr<Gdk::Screen>& screen,
                                      const Gdk::ArrayHandle_Color&    colors,
                                      GtkColorSelectionChangePaletteWithScreenFunc func)
{
  g_return_if_fail(func != 0);

  (*func)(Glib::unwrap(screen), colors.data(), colors.size());
}

} // anonymous namespace


namespace Gtk
{

Gdk::Color ColorSelection::get_current_color() const
{
  Gdk::Color color; //GdkColor Just a simple struct.
  gtk_color_selection_get_current_color(const_cast<GtkColorSelection*>(gobj()), color.gobj());
  return color;
}

Gdk::Color ColorSelection::get_previous_color() const
{
  Gdk::Color color; //GdkColor Just a simple struct.
  gtk_color_selection_get_previous_color(const_cast<GtkColorSelection*>(gobj()), color.gobj());
  return color;
}

// static
Gdk::ArrayHandle_Color ColorSelection::palette_from_string(const Glib::ustring& str)
{
  GdkColor* colors = 0;
  int     n_colors = 0;

  gtk_color_selection_palette_from_string(str.c_str(), &colors, &n_colors);

  return Gdk::ArrayHandle_Color(colors, n_colors, Glib::OWNERSHIP_SHALLOW);
}

// static
Glib::ustring ColorSelection::palette_to_string(const Gdk::ArrayHandle_Color& colors)
{
  if(char *const str = gtk_color_selection_palette_to_string(colors.data(), colors.size()))
    return Glib::ustring(Glib::ScopedPtr<char>(str).get());
  else
    return Glib::ustring();
}

// static
ColorSelection::SlotChangePaletteHook
ColorSelection::set_change_palette_hook(const ColorSelection::SlotChangePaletteHook& slot)
{
  GtkColorSelectionChangePaletteWithScreenFunc new_func = 0;
  SlotChangePaletteHook* new_slot = 0;
  SlotChangePaletteHook  old_slot;

  if(slot)
  {
    new_func = &global_change_palette_hook_callback;
    new_slot = new SlotChangePaletteHook(slot);
  }

  const GtkColorSelectionChangePaletteWithScreenFunc old_func =
      gtk_color_selection_set_change_palette_with_screen_hook(new_func);

  if(old_func)
  {
    #ifdef GLIBMM_EXCEPTIONS_ENABLED
    try
    {
    #endif //GLIBMM_EXCEPTIONS_ENABLED
      if(old_func != &global_change_palette_hook_callback)
        old_slot = sigc::bind<-1>(sigc::ptr_fun(&old_change_palette_hook_callback), old_func);
      else if(global_change_palette_hook)
        old_slot = *global_change_palette_hook;
    #ifdef GLIBMM_EXCEPTIONS_ENABLED
    }
    catch(...)
    {
      gtk_color_selection_set_change_palette_with_screen_hook(old_func);
      delete new_slot;
      throw;
    }
    #endif //GLIBMM_EXCEPTIONS_ENABLED
  }

  delete global_change_palette_hook;
  global_change_palette_hook = new_slot;

  return old_slot;
}

} // namespace Gtk

