/* property.c
 * Copyright (C) 2002-2004 Pascal Eberhard <pascal.ebo@netcourrier.com>
 *
 * 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 "common.h"

static void property_refresh_app(property_t *prop);
static void property_refresh_no_app(property_t *prop);

static void property_build_interface(property_t *prop);

static void prop_cmdline_changed(GtkWidget *entry, property_t *prop);
static void prop_path_changed(GtkWidget *entry, property_t *prop);
static void prop_icon_changed(GtkWidget *entry, property_t *prop);
//static void property_refreshed(Cereimg *cell, gchar *path_str, gchar *new_text,
//                            property_t *prop);
//static void cereimg_clicked(Cereimg *cell, gchar *path_str,
//                            property_t *prop);

static void prop_cmdline_clicked(GtkWidget *entry, property_t *prop);
static void prop_path_clicked(GtkWidget *entry, property_t *prop);
static void prop_icon_clicked(GtkWidget *entry, property_t *prop);
static void prop_cmdline_compute(const char *old_val, const char *new_val,
                                 void *data);
static void prop_path_compute(const char *old_val, const char *new_val,
                              void *data);
static void property_remove_clicked(GtkWidget *button, property_t *prop);
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
property_t *property_new(apwalapp_t *apwal)
{
  property_t        *prop;
  g_assert(apwal != NULL);
  g_assert(apwal->property_frame != NULL);

  prop = (property_t*) malloc(sizeof(property_t));
  g_assert(prop != NULL);

  prop->apwal = apwal;
  property_build_interface(prop);
  property_refresh_no_app(prop);

  return prop;
}
// ----------------------------------------------------------------------------
void property_refresh(property_t *prop)
{
  g_assert(prop != NULL);
  g_assert(prop->apwal != NULL);

  if (prop->apwal->selected_app != NULL)
    property_refresh_app(prop);
  else
    property_refresh_no_app(prop);
}
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
static void property_refresh_app(property_t *prop)
{
  app_t      *app;
//GError     *err;
  GdkPixbuf  *pix, *pix_scaled;
  int         scale_width, scale_height;

  g_assert(prop != NULL);
  g_assert(prop->apwal != NULL);
  g_assert(prop->apwal->apps != NULL);
  g_assert(prop->apwal->selected_app != NULL);
  app = prop->apwal->selected_app;
  TRACE("app:%p", app);
  app_dumpln(app);
  // block the "changed" signal to maintain coherency
  g_signal_handlers_block_by_func(GTK_OBJECT(prop->entry_cmdline),
                                  prop_cmdline_changed, prop);
  g_signal_handlers_block_by_func(GTK_OBJECT(prop->entry_path),
                                  prop_path_changed, prop);
  g_signal_handlers_block_by_func(GTK_OBJECT(prop->entry_icon),
                                  prop_icon_changed, prop);
  // it is safe now, modifying the data
  gtk_entry_set_text(GTK_ENTRY(prop->entry_cmdline), app_get_cmdline(app));
  
  //change the color of the cmdline entry if cmdline is not valid
  if (app_is_executable(app))
    gtk_widget_set_text_color_default(GTK_WIDGET(prop->entry_cmdline));
  else
    gtk_widget_set_text_color_invalid(GTK_WIDGET(prop->entry_cmdline));

  //change the color of the path entry if path is not valid
  if (app_path_is_valid(app))
    gtk_widget_set_text_color_default(GTK_WIDGET(prop->entry_path));
  else
    gtk_widget_set_text_color_invalid(GTK_WIDGET(prop->entry_path));

  //change the color of the icon entry if icon is not valid
  if (app_icon_is_valid(app))
    gtk_widget_set_text_color_default(GTK_WIDGET(prop->entry_icon));
  else
    gtk_widget_set_text_color_invalid(GTK_WIDGET(prop->entry_icon));

  gtk_entry_set_text(GTK_ENTRY(prop->entry_path), app_get_path(app));
  gtk_entry_set_text(GTK_ENTRY(prop->entry_icon), app_get_icon(app));
  // unblock the "changed" signal
  g_signal_handlers_unblock_by_func(GTK_OBJECT(prop->entry_cmdline),
                                    prop_cmdline_changed, prop);
  g_signal_handlers_unblock_by_func(GTK_OBJECT(prop->entry_path),
                                    prop_path_changed, prop);
  g_signal_handlers_unblock_by_func(GTK_OBJECT(prop->entry_icon),
                                    prop_icon_changed, prop);

  pix = gdk_pixbuf_new_from_apwal((char*)app_get_icon(app), NULL, NULL);
  //GTK_ICON_SIZE_SMALL_TOOLBAR 18x18
  //GTK_ICON_SIZE_LARGE_TOOLBAR 20x20
  //GTK_ICON_SIZE_BUTTON        22x22
  gtk_icon_size_lookup(GTK_ICON_SIZE_SMALL_TOOLBAR,
                       &scale_width, &scale_height);
  pix_scaled = gdk_pixbuf_scale_simple(pix, scale_width, scale_height,
                                     /*GDK_INTERP_BILINEAR*/ GDK_INTERP_HYPER);
  gtk_image_set_from_pixbuf(GTK_IMAGE(prop->img_icon), pix_scaled);
  g_object_unref(pix);
  g_object_unref(pix_scaled);
  
  // set the frame sensitive again so the user will be able to modify the data.
  gtk_widget_set_sensitive(prop->apwal->property_frame, TRUE);
}
// ----------------------------------------------------------------------------
static void property_refresh_no_app(property_t *prop)
{
  g_assert(prop != NULL);
  g_assert(prop->apwal != NULL);
  g_assert(prop->apwal->selected_app == NULL);
  TRACE("%s", "");
  // set the frame insensitive so the user won't be able to modify the data.
  gtk_widget_set_sensitive(prop->apwal->property_frame, FALSE);

  // block the "changed" signal to maintain coherency
  g_signal_handlers_block_by_func(GTK_OBJECT(prop->entry_cmdline),
                                  prop_cmdline_changed, prop);
  g_signal_handlers_block_by_func(GTK_OBJECT(prop->entry_path),
                                  prop_path_changed, prop);
  g_signal_handlers_block_by_func(GTK_OBJECT(prop->entry_icon),
                                  prop_icon_changed, prop);
  // it is safe now, modifying the data
  gtk_entry_set_text(GTK_ENTRY(prop->entry_cmdline), "");
  gtk_entry_set_text(GTK_ENTRY(prop->entry_path), "");
  gtk_entry_set_text(GTK_ENTRY(prop->entry_icon), "");
  // unblock the "changed" signal
  g_signal_handlers_unblock_by_func(GTK_OBJECT(prop->entry_cmdline),
                                    prop_cmdline_changed, prop);
  g_signal_handlers_unblock_by_func(GTK_OBJECT(prop->entry_path),
                                    prop_path_changed, prop);
  g_signal_handlers_unblock_by_func(GTK_OBJECT(prop->entry_icon),
                                    prop_icon_changed, prop);
}
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
static void property_build_interface(property_t *prop)
{
//          *apwal->property_frame;
  GtkWidget   *hbox;
  GtkWidget     *vbox_entries;
  GtkWidget       *hbox_cmdline;
  GtkWidget         *label_cmdline;
//                  *prop->entry_cmdline;
  GtkWidget         *btn_cmdline;
  GtkWidget           *img_cmdline;
  GtkWidget       *hbox_path;
  GtkWidget         *label_path;
//                  *prop->entry_path;
  GtkWidget         *btn_path;
  GtkWidget           *img_path;
  GtkWidget       *hbox_icon;
  GtkWidget         *label_icon;
//                  *prop->entry_icon;
  GtkWidget         *btn_icon;
//                    *img_icon;
  GtkWidget   *vbox;
//              *prop->btn_remove;
  GtkSizeGroup  *group_entries;
  GtkSizeGroup  *group_buttons;

  g_assert(prop != NULL);
  g_assert(prop->apwal != NULL);
  g_assert(prop->apwal->property_frame != NULL);

  //group entries & buttons
  group_entries = gtk_size_group_new(GTK_SIZE_GROUP_BOTH);
  group_buttons = gtk_size_group_new(GTK_SIZE_GROUP_BOTH);
  
  // horizontal box
  hbox = gtk_hbox_new(FALSE, 0);
  gtk_container_set_border_width(GTK_CONTAINER(hbox), 4);
  gtk_container_add(GTK_CONTAINER(prop->apwal->property_frame), hbox);
  gtk_widget_show(hbox);

  //vbox entries
  vbox_entries = gtk_vbox_new(FALSE, 0);
  gtk_container_set_border_width(GTK_CONTAINER(vbox_entries), 2);
  gtk_box_pack_start(GTK_BOX(hbox), vbox_entries, TRUE, TRUE, 0);
  gtk_widget_show(vbox_entries);

  //hbox cmdline
  hbox_cmdline = gtk_hbox_new(FALSE, 0);
  gtk_container_set_border_width(GTK_CONTAINER(hbox_cmdline), 0);
  gtk_box_pack_start(GTK_BOX(vbox_entries), hbox_cmdline, TRUE, TRUE, 0);
  gtk_widget_show(hbox_cmdline);

  //label cmdline
  label_cmdline = gtk_label_new("Command Line ");
  gtk_size_group_add_widget(group_entries, label_cmdline);
  gtk_box_pack_start(GTK_BOX(hbox_cmdline), label_cmdline, FALSE, FALSE, 0);
  gtk_widget_show(label_cmdline);
  
  //entry cmdline
  prop->entry_cmdline = gtk_entry_new();
  gtk_entry_set_text(GTK_ENTRY(prop->entry_cmdline), "");
  gtk_box_pack_start(GTK_BOX(hbox_cmdline), prop->entry_cmdline, TRUE, TRUE, 0);
  gtk_widget_show(prop->entry_cmdline);
  g_signal_connect(G_OBJECT(prop->entry_cmdline), "changed",
                   G_CALLBACK(prop_cmdline_changed), prop);

  //btn cmdline
  btn_cmdline = gtk_button_new();
  g_signal_connect(G_OBJECT(btn_cmdline), "clicked",
                   G_CALLBACK(prop_cmdline_clicked), prop);
  gtk_size_group_add_widget(group_buttons, btn_cmdline);
  gtk_box_pack_start(GTK_BOX(hbox_cmdline), btn_cmdline, FALSE, FALSE, 0);
  gtk_widget_show(btn_cmdline);
  //img cmdline
  img_cmdline = gtk_image_new_from_stock(GTK_STOCK_OPEN,
                                         GTK_ICON_SIZE_SMALL_TOOLBAR);
  gtk_tooltips_set_tip(prop->apwal->tips, btn_cmdline, "Cmdline Browse...\nShow the File Selection Dialog Box which allow to select the executable to launch", NULL);
  gtk_widget_show(img_cmdline);
  gtk_container_add(GTK_CONTAINER(btn_cmdline), img_cmdline);

  //hbox path
  hbox_path = gtk_hbox_new(FALSE, 0);
  gtk_container_set_border_width(GTK_CONTAINER(hbox_path), 0);
  gtk_box_pack_start(GTK_BOX(vbox_entries), hbox_path, TRUE, TRUE, 0);
  gtk_widget_show(hbox_path);

  //label path
  label_path = gtk_label_new("Execute Path ");
  gtk_size_group_add_widget(group_entries, label_path);
  gtk_misc_set_alignment(GTK_MISC(label_path), 0.0, 0.5);
  gtk_box_pack_start(GTK_BOX(hbox_path), label_path, FALSE, FALSE, 0);
  gtk_widget_show(label_path);
  
  //entry path
  prop->entry_path = gtk_entry_new();
  gtk_entry_set_text(GTK_ENTRY(prop->entry_path), "");
  gtk_box_pack_start(GTK_BOX(hbox_path), prop->entry_path, TRUE, TRUE, 0);
  gtk_widget_show(prop->entry_path);
  g_signal_connect(G_OBJECT(prop->entry_path), "changed",
                   G_CALLBACK(prop_path_changed), prop);

  //btn path
  btn_path = gtk_button_new();
  g_signal_connect(G_OBJECT(btn_path), "clicked",
                   G_CALLBACK(prop_path_clicked), prop);
  gtk_size_group_add_widget(group_buttons, btn_path);
  gtk_box_pack_start(GTK_BOX(hbox_path), btn_path, FALSE, FALSE, 0);
  gtk_widget_show(btn_path);
  //img_path 
  img_path = gtk_image_new_from_stock(GTK_STOCK_OPEN,
                                      GTK_ICON_SIZE_SMALL_TOOLBAR);
  gtk_widget_show(img_path);
  gtk_container_add(GTK_CONTAINER(btn_path), img_path);
  gtk_tooltips_set_tip(prop->apwal->tips, btn_path, "Path Browse...\nShow the Directory Selection Dialog Box which allow to select the execution path of the currently selected application", NULL);

  //hbox icon
  hbox_icon = gtk_hbox_new(FALSE, 0);
  gtk_container_set_border_width(GTK_CONTAINER(hbox_icon), 0);
  gtk_box_pack_start(GTK_BOX(vbox_entries), hbox_icon, TRUE, TRUE, 0);
  gtk_widget_show(hbox_icon);

  //label icon
  label_icon = gtk_label_new("Icon ");
  gtk_size_group_add_widget(group_entries, label_icon);
  gtk_misc_set_alignment(GTK_MISC(label_icon), 0.0, 0.5);
  gtk_box_pack_start(GTK_BOX(hbox_icon), label_icon, FALSE, FALSE, 0);
  gtk_widget_show(label_icon);
  
  //entry icon
  prop->entry_icon = gtk_entry_new();
  gtk_label_set_justify(GTK_LABEL(label_icon), GTK_JUSTIFY_LEFT);
  gtk_entry_set_text(GTK_ENTRY(prop->entry_icon), "");
  gtk_box_pack_start(GTK_BOX(hbox_icon), prop->entry_icon, TRUE, TRUE, 0);
  gtk_widget_show(prop->entry_icon);
  g_signal_connect(G_OBJECT(prop->entry_icon), "changed",
                   G_CALLBACK(prop_icon_changed), prop);

  //btn icon
  btn_icon = gtk_button_new();
  g_signal_connect(G_OBJECT(btn_icon), "clicked",
                   G_CALLBACK(prop_icon_clicked), prop);
  gtk_size_group_add_widget(group_buttons, btn_icon);
  gtk_box_pack_start(GTK_BOX(hbox_icon), btn_icon, FALSE, FALSE, 0);
  gtk_widget_show(btn_icon);
  //img_icon 
  prop->img_icon = gtk_image_new();
  gtk_widget_show(prop->img_icon);
  gtk_container_add(GTK_CONTAINER(btn_icon), prop->img_icon);
  gtk_tooltips_set_tip(prop->apwal->tips, btn_icon, "Icon Browse...\nShow the Icon Selection Window to select a new icon for the currently selected application", NULL);

  //GdkPixbuf *pix1;
  //prop->pixbuf_open = gtk_widget_render_icon(prop->apwal->window, "gtk-open", 
  //                                           GTK_ICON_SIZE_MENU, NULL);
  //prop->pixbuf_open = gdk_pixbuf_new_from_apwal("relief", NULL, NULL);
  //pix1 = gtk_widget_render_icon(prop->apwal->window, "gtk-open",
  //                              GTK_ICON_SIZE_MENU, NULL);
  //gdk_pixbuf_append(prop->pixbuf_open, pix1);

  // vbox
  vbox = gtk_vbox_new(FALSE, 0);
  gtk_container_set_border_width(GTK_CONTAINER(vbox), 2);
  gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 0);
  gtk_widget_show(vbox);

  // btn_remove
  prop->btn_remove = gtk_button_new_from_stock(GTK_STOCK_REMOVE);
  g_signal_connect(G_OBJECT(prop->btn_remove), "clicked",
                   G_CALLBACK(property_remove_clicked), prop);
  gtk_box_pack_end(GTK_BOX(vbox), prop->btn_remove, FALSE, FALSE, 0);
  gtk_tooltips_set_tip(prop->apwal->tips, prop->btn_remove, "Remove\nRemove the application currently selected", NULL);
  gtk_widget_show(prop->btn_remove);

}

// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
static void prop_cmdline_clicked(GtkWidget *button, property_t *prop)
{
  app_t      *app;
  g_assert((button != NULL) && (prop != NULL));
  g_assert(prop->apwal != NULL);
  g_assert(prop->apwal->selected_app != NULL);
  app = prop->apwal->selected_app;
  TRACE_APP(app, "%s", "");
  filesel_select(prop->apwal->filesel, app_get_cmdline(app), FALSE/*dir_only*/,
                 prop_cmdline_compute, prop);
}
// ----------------------------------------------------------------------------
static void prop_path_clicked(GtkWidget *button, property_t *prop)
{
  app_t      *app;
  g_assert((button != NULL) && (prop != NULL));
  g_assert(prop->apwal != NULL);
  g_assert(prop->apwal->selected_app != NULL);
  app = prop->apwal->selected_app;
  TRACE_APP(app, "%s", "");
  filesel_select(prop->apwal->filesel, app_get_path(app), TRUE/*dir_only*/,
                 prop_path_compute, prop);
}
// ----------------------------------------------------------------------------
static void prop_icon_clicked(GtkWidget *button, property_t *prop)
{
  app_t      *app;
  g_assert((button != NULL) && (prop != NULL));
  g_assert(prop->apwal != NULL);
  g_assert(prop->apwal->selected_app != NULL);
  app = prop->apwal->selected_app;
  TRACE_APP(app, "%s", "");
  apwalapp_goto_iconsel(prop->apwal);
}
// ----------------------------------------------------------------------------
static void prop_cmdline_compute(const char *old_val, const char *new_val,
                                 void *data)
{
  app_t      *app;
  property_t *prop = (property_t *) data;
  g_assert(prop != NULL);
  g_assert(prop->apwal != NULL);
  g_assert(prop->apwal->selected_app != NULL);
  app = prop->apwal->selected_app;
  TRACE_APP(app, "old val:%s, new val:%s", old_val, new_val);
  if (new_val != NULL)
  {
    app_set_cmdline(app, new_val);
    apwalapp_selected_app_modified(prop->apwal);
  }
}
// ----------------------------------------------------------------------------
static void prop_path_compute(const char *old_val, const char *new_val,
                              void *data)
{
  app_t      *app;
  property_t *prop = (property_t *) data;
  g_assert(prop != NULL);
  g_assert(prop->apwal != NULL);
  g_assert(prop->apwal->selected_app != NULL);
  app = prop->apwal->selected_app;
  TRACE_APP(app, "old val:%s, new val:%s", old_val, new_val);
  if (new_val != NULL)
  {
    app_set_path(app, new_val);
    apwalapp_selected_app_modified(prop->apwal);
  }
}
// ----------------------------------------------------------------------------
static void prop_cmdline_changed(GtkWidget *entry, property_t *prop)
{
  app_t      *app;
  const char *value;
  g_assert((entry != NULL) && (prop != NULL));
  g_assert(prop->apwal != NULL);
  g_assert(prop->apwal->selected_app != NULL);
  app = prop->apwal->selected_app;
  TRACE("app:%p", app);
  value = gtk_entry_get_text(GTK_ENTRY(entry));
  app_set_cmdline(app, value);
  //change the color of the cmdline entry if cmdline is not valid
  if (app_is_executable(app))
    gtk_widget_set_text_color_default(GTK_WIDGET(prop->entry_cmdline));
  else
    gtk_widget_set_text_color_invalid(GTK_WIDGET(prop->entry_cmdline));

  apwalapp_selected_app_modified(prop->apwal);
}
// ----------------------------------------------------------------------------
static void prop_path_changed(GtkWidget *entry, property_t *prop)
{
  app_t      *app;
  const char *value;
  g_assert((entry != NULL) && (prop != NULL));
  g_assert(prop->apwal != NULL);
  g_assert(prop->apwal->selected_app != NULL);
  app = prop->apwal->selected_app;
  TRACE("app:%p", app);
  value = gtk_entry_get_text(GTK_ENTRY(entry));
  app_set_path(app, value);
  //change the color of the path entry if path is not valid
  if (app_path_is_valid(app))
    gtk_widget_set_text_color_default(GTK_WIDGET(prop->entry_path));
  else
    gtk_widget_set_text_color_invalid(GTK_WIDGET(prop->entry_path));

  apwalapp_selected_app_modified(prop->apwal);
}
// ----------------------------------------------------------------------------
static void prop_icon_changed(GtkWidget *entry, property_t *prop)
{
  app_t      *app;
  const char *value;
  g_assert((entry != NULL) && (prop != NULL));
  g_assert(prop->apwal != NULL);
  g_assert(prop->apwal->selected_app != NULL);
  app = prop->apwal->selected_app;
  TRACE("app:%p", app);
  value = gtk_entry_get_text(GTK_ENTRY(entry));
  app_set_icon(app, value);
  //change the color of the icon entry if icon is not valid
  if (app_icon_is_valid(app))
    gtk_widget_set_text_color_default(GTK_WIDGET(prop->entry_icon));
  else
    gtk_widget_set_text_color_invalid(GTK_WIDGET(prop->entry_icon));

  apwalapp_selected_app_modified(prop->apwal);
}
// ----------------------------------------------------------------------------
static void property_remove_clicked(GtkWidget *button, property_t *prop)
{
  app_t *app;
  g_assert((button != NULL) && (prop != NULL));
  g_assert(prop->apwal != NULL);
  g_assert(prop->apwal->selected_app != NULL);
  app = prop->apwal->selected_app;
  TRACE("app:%p", app);
  app_list_remove(prop->apwal->apps, app);
  prop->apwal->selected_app = NULL;
  apwalapp_selected_app_modified(prop->apwal);
}
// ----------------------------------------------------------------------------
