/*
 *  Notes - panel plugin for Xfce Desktop Environment
 *  Copyright (C) 2003  Jakob Henriksson <b0kaj+dev@lysator.liu.se>
 *
 *  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 "notes.h"

static void notes_free_note(_note *note);
static void notes_free(Control *ctrl);
static void notes_delete_note_dialog(GtkWidget *widget, gpointer data);
static void notes_read_config(Control *ctrl, xmlNodePtr parent);
static void notes_write_config(Control *ctrl, xmlNodePtr parent);
static gboolean notes_control_new(Control *ctrl);
static void notes_create_options (Control *ctrl, GtkContainer *con, 
				  GtkWidget *done);

_note_applet *notes_applet;

void 
notes_update_note_colors(_note *note)
{
    GtkRcStyle *rc_style;
    GtkRcStyle *rc_style_base;
    GtkRcStyle *rc_style_bg;

    GdkColor note_color_off;

    /* make note_color_off same as note_color but a bit more dark, 
       a bit more off */
    note_color_off.red = (notes_applet->note_color.red * 8) / 10;
    note_color_off.green = (notes_applet->note_color.green * 8)/10;
    note_color_off.blue = (notes_applet->note_color.blue * 8) / 10;

    /* system color */
    if (notes_applet->system_colors == TRUE) {
	  rc_style = gtk_rc_style_new();
	  gtk_widget_modify_style(note->note_w, rc_style);
	  gtk_widget_modify_style(note->entry_title, rc_style);
	  gtk_widget_modify_style(note->label_title, rc_style);
	  gtk_widget_modify_style(note->button_close, rc_style);
	  gtk_widget_modify_style(note->text_view, rc_style);
	  gtk_widget_modify_style(note->event_box_top_left, rc_style);
	  gtk_widget_modify_style(note->event_box_top_middle, rc_style);
	  gtk_widget_modify_style(note->event_box_top_right, rc_style);
	  gtk_widget_modify_style(note->event_box_middle_left, rc_style);
	  gtk_widget_modify_style(note->event_box_middle_right, rc_style);
	  gtk_widget_modify_style(note->event_box_bottom_left, rc_style);
	  gtk_widget_modify_style(note->event_box_bottom_middle, rc_style);
	  gtk_widget_modify_style(note->event_box_bottom_right, rc_style);

	  gtk_rc_style_unref(rc_style);
    } 
    /* user color */
    else {
	  
	  rc_style_base = gtk_rc_style_new();
	  rc_style_bg = gtk_rc_style_new();
	  /* base */
	  rc_style_base->base[GTK_STATE_NORMAL] = notes_applet->note_color;
	  rc_style_base->bg[GTK_STATE_NORMAL] = note_color_off;
	  rc_style_base->color_flags[GTK_STATE_NORMAL] = GTK_RC_BASE|GTK_RC_BG;
	  /* bg */
	  rc_style_bg->bg[GTK_STATE_NORMAL] = note_color_off;
	  rc_style_bg->bg_pixmap_name[GTK_STATE_NORMAL] = g_strdup("<none>");
	  
	  rc_style_bg->bg[GTK_STATE_PRELIGHT] = note_color_off;
	  rc_style_bg->bg[GTK_STATE_ACTIVE] = notes_applet->note_color;
	  
	  rc_style_bg->color_flags[GTK_STATE_NORMAL] = GTK_RC_BG;
	  rc_style_bg->color_flags[GTK_STATE_PRELIGHT] = GTK_RC_BG;
	  rc_style_bg->color_flags[GTK_STATE_ACTIVE] = GTK_RC_BG;
	  
	  gtk_widget_modify_style(note->note_w, rc_style_bg);
	  gtk_widget_modify_style(note->entry_title, rc_style_base);
	  gtk_widget_modify_style(note->label_title, rc_style_base);
	  gtk_widget_modify_style(note->button_close, rc_style_bg);
	  gtk_widget_modify_style(note->text_view, rc_style_base);
	  gtk_widget_modify_style(note->event_box_top_left, rc_style_bg);
	  gtk_widget_modify_style(note->event_box_top_middle, rc_style_bg);
	  gtk_widget_modify_style(note->event_box_top_right, rc_style_bg);
	  gtk_widget_modify_style(note->event_box_middle_left, rc_style_bg);
	  gtk_widget_modify_style(note->event_box_middle_right, rc_style_bg);
	  gtk_widget_modify_style(note->event_box_bottom_left, rc_style_bg);
	  gtk_widget_modify_style(note->event_box_bottom_middle, rc_style_bg);
	  gtk_widget_modify_style(note->event_box_bottom_right, rc_style_bg);
	  
	  gtk_rc_style_unref(rc_style_base);
	  gtk_rc_style_unref(rc_style_bg);
    }

    return;
}

void
notes_update_colors(void)
{
    GList *list;
    _note *note;

    if (notes_applet->notes != NULL) {
	  list = g_list_first(notes_applet->notes);
	  while (list != NULL) {
	    note = list->data;
	    /* update */
	    notes_update_note_colors(note);
	    list = g_list_next(list);
	  }
    }
	
    return;
}

/* set new tooltips */
void
notes_set_tooltips(void)
{
    gchar *tooltips;
    gint length = g_list_length(notes_applet->notes);

    tooltips = g_malloc(sizeof(gchar) * 100);
    
    if (length == 0) {
	  sprintf(tooltips, 
			  "Create note - double click or mouse button 3");
    } else {
      sprintf(tooltips, "%d note(s)",
			  length);
    }
	
    gtk_tooltips_set_tip(notes_applet->tooltips, notes_applet->applet_button,
						 tooltips, NULL);
    g_free(tooltips);
    
    return;
}

/* update all notes to set their sticky state */
void
notes_update_sticky(void)
{
    GList *list;
    _note *note;

    if (notes_applet->notes != NULL) {
	  list = g_list_first(notes_applet->notes);
	  while (list != NULL) {
	    note = list->data;
	    /* update */
	    if (notes_applet->notes_sticky == TRUE) {
		  gtk_window_stick(GTK_WINDOW(note->note_w));
	    } else {
		  gtk_window_unstick(GTK_WINDOW(note->note_w));
	    }
	    list = g_list_next(list);
	  }
    }
	
    return;
}

/* update all notes to set their "on top" property state */
void
notes_update_on_top(void)
{
    GList *list;
    _note *note;

    if (notes_applet->notes != NULL) {
	  list = g_list_first(notes_applet->notes);
	  while (list != NULL) {
	    note = list->data;
	    /* update */
	    if (notes_applet->notes_on_top == TRUE) {
		  gtk_window_set_keep_above(GTK_WINDOW(note->note_w), TRUE);
	    } else {
		  gtk_window_set_keep_above(GTK_WINDOW(note->note_w), FALSE);
	    }
	    list = g_list_next(list);
	  }
    }

    return;
}

/* iterates over notes and if notes_applet->show_notes is TRUE then
   display all notes otherwise hide them, of course */
void
notes_update_visibility(void)
{
  GList *list;
  _note *note;
  
  list = g_list_first(notes_applet->notes);
  while (list != NULL) {
    note = list->data;
    /* update visibility */
    if (notes_applet->show_notes == TRUE) {
      /* only show if not already visibile */
      /* use gtk_window_present? */
      if (gdk_window_is_visible((note->note_w)->window) == FALSE) {
		/* move window to position */
		gtk_window_move(GTK_WINDOW(note->note_w), 
						note->x, note->y);
		gtk_widget_show(note->note_w);
      }
    } else {
      /* store window position */
      if (gdk_window_is_visible((note->note_w)->window) == TRUE) {
		gtk_window_get_position(GTK_WINDOW(note->note_w),
								&note->x, &note->y);
		gtk_widget_hide(note->note_w);
      }
    }
    list = g_list_next(list);
  }
  
  return;
}

gboolean
timeout_button_press(int *id)
{
    /* reset id */
    *id = 0;
    
    notes_applet->show_notes = (notes_applet->show_notes == FALSE);
	
    notes_update_visibility();
    notes_update_sticky();
	notes_update_on_top();

    return FALSE;
}

gboolean
cb_applet_button_press_event(GtkWidget *widget, gpointer data)
{
  notes_applet->show_notes = (notes_applet->show_notes == FALSE);
  
  notes_update_visibility();
  notes_update_sticky();
  notes_update_on_top();
      
  return FALSE;
}


gboolean
cb_applet_button_press_event_advanced(GtkWidget *widget, GdkEventButton *event,
				      gpointer data)
{
    _note* note;
    static int timeout_id = 0;

    /* Double click event sequence:
     * GDK_BUTTON_PRESS, GDK_BUTTON_RELEASE, GDK_BUTTON_PRESS,
     * GDK_2BUTTON_PRESS, GDK_BUTTON_RELEASE
     */
    
    /* single button press and button 1 */
    if ((event->type == GDK_BUTTON_PRESS) && (event->button == 1)) {
	  /* hide or show */
	  if (timeout_id <= 0)
		{
		  timeout_id = g_timeout_add(250, 
									 (GSourceFunc)timeout_button_press,
									 &timeout_id);
		}
    }
    /* double button click and button 1  or button 2 */
    else if ((event->type == GDK_BUTTON_PRESS && event->button == 2) || 
			 (event->type == GDK_2BUTTON_PRESS && event->button == 1))
	  {
		if (timeout_id > 0)
		  {
			g_source_remove(timeout_id);
			timeout_id = 0;
		  }
		
		/* show the other notes */
		notes_applet->show_notes = TRUE;
		notes_update_visibility();
		
		/* create a new note, it will be added to list of notes */
		note = notes_new_note();
		
		/* store window position */
		gtk_widget_show(note->note_w);
		
		gtk_window_get_position(GTK_WINDOW(note->note_w),
								&note->x, &note->y);
		
		/* update colors */
		notes_update_note_colors(note);
		notes_update_sticky();
		notes_update_on_top();
		
		DBG("Note added\n");
	  }  
    
    return FALSE;
}

gboolean
notes_load_config(void)
{
  xmlNodePtr cur;
  xmlDocPtr doc;
  
  gchar *filename;
  gchar *error_str;
  /* note info in config file */
  xmlChar *x, *y, *w, *h, *title, *text; 
  
  error_str = g_malloc(sizeof(char) * 256);
  
  /* set config file name */
  filename = xfce_resource_lookup (XFCE_RESOURCE_CONFIG,
								   "xfce4" G_DIR_SEPARATOR_S "notes.xml");
  
  if (!filename)
	filename = xfce_get_userfile("notes.xml", NULL);
  
  if (!g_file_test(filename, G_FILE_TEST_EXISTS)) {
	g_free(error_str);
	g_free(filename);
	return FALSE;
  }
  
  /* parse the file */
  doc = xmlParseFile(filename);
  if (doc == NULL) {
	sprintf(error_str, "Error parsing config file '%s'", filename);
	xfce_info(_(error_str));
	g_free(error_str);
	return FALSE;
  }
  cur = xmlDocGetRootElement(doc);
  
  if (xmlStrcmp(cur->name, (const xmlChar *)"notes")) {
	sprintf(error_str, "Config file '%s' of wrong type", filename);
	g_free(error_str);
	xmlFreeDoc(doc);
	xfce_info(_(error_str));
	return FALSE;
  }

  cur = cur->xmlChildrenNode;
  while (cur != NULL) {
	/* NOTE */
	if ((!xmlStrcmp(cur->name, (const xmlChar *)"note"))) {
	  x = xmlGetProp(cur, (xmlChar *)"x");
	  y = xmlGetProp(cur, (xmlChar *)"y");
	  w = xmlGetProp(cur, (xmlChar *)"w");
	  h = xmlGetProp(cur, (xmlChar *)"h");
	  title = xmlGetProp(cur, (xmlChar *)"title");
	  text = xmlNodeGetContent(cur);
	  /* recreate the note */
	  notes_new_note_with_attr((gchar *)text, (gchar *)title,
							   atoi((char *)x), atoi((char *)y),
							   atoi((char *)w), atoi((char *)h));
	}
	cur = cur->next;
  }
  
  /* prevent from saving loaded notes */
  notes_applet->notes_saved = TRUE;
  
  g_free(error_str);
  
  return TRUE;
}

void
notes_store_config(void)
{
    GList *list;
    _note *note;
    
    GtkTextIter start, end;
    GtkTextBuffer *buffer;
    gchar *text;

    gchar *filename;

    /* note info in config file */
    xmlChar x[5], y[5], w[5], h[5];

    filename = xfce_resource_save_location (XFCE_RESOURCE_CONFIG,
                                     "xfce4" G_DIR_SEPARATOR_S "notes.xml",
                                     TRUE);

    list = g_list_first(notes_applet->notes);
    while (list != NULL) {
	  note = list->data;
	  /* get info about note to store */
	  /* only get it if the windows are visible, otherwise x and y will
		 be 0 */
	  if (notes_applet->show_notes == TRUE) {
	    gtk_window_get_position(GTK_WINDOW(note->note_w),
								&note->x, &note->y);
	  }
	  gtk_window_get_size(GTK_WINDOW(note->note_w), &note->w, &note->h);
	  /* convert info */
	  sprintf((char *)x, "%d", note->x);
	  sprintf((char *)y, "%d", note->y);
	  sprintf((char *)w, "%d", note->w);
	  sprintf((char *)h, "%d", note->h);

	  xmlSetProp(note->xml_tag, (xmlChar *)"x", x);
	  xmlSetProp(note->xml_tag, (xmlChar *)"y", y);
	  xmlSetProp(note->xml_tag, (xmlChar *)"w", w);
	  xmlSetProp(note->xml_tag, (xmlChar *)"h", h);
	  
	  /* title */
	  xmlSetProp(note->xml_tag, (xmlChar *)"title", 
				 (xmlChar *)gtk_label_get_text(GTK_LABEL(note->label_title)));
	  
	  /* get text from text view */
	  buffer 
	    = gtk_text_view_get_buffer(GTK_TEXT_VIEW(note->text_view));
	  gtk_text_buffer_get_bounds (buffer, &start, &end);
	  text = gtk_text_iter_get_text (&start, &end);
	  
	  /* set it */
	  xmlNodeSetContent(note->xml_tag, (xmlChar *)text);
	  
	  g_free(text);
	  
	  list = g_list_next(list);
    }
	
    /* deleting old config file */
    unlink(filename);
    /* saving new config file */
    xmlSaveFile(filename, notes_applet->doc);

    return;
}

void
notes_new_note_with_attr(gchar *text, gchar *title, 
						 gint x, gint y, gint w, gint h)
{
  GtkTextBuffer *buffer;
  _note *note;
  
  note = notes_new_note();
  /* set attribs */
  note->x = x;
  note->y = y;
  note->w = w;
  note->h = h;
  gtk_label_set_text(GTK_LABEL(note->label_title), title);
  gtk_window_resize(GTK_WINDOW(note->note_w), w, h);
  gtk_window_move(GTK_WINDOW(note->note_w), x, y);
  /* set text */
  buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(note->text_view));
  gtk_text_buffer_set_text(buffer, text, strlen(text));
  gtk_text_view_set_buffer(GTK_TEXT_VIEW(note->text_view), buffer);
  
  /* display note */
  if (notes_applet->show_notes == TRUE) {
	gtk_widget_show(note->note_w);
  }
  
  return;
}

void
notes_note_changed(GtkEditable *editable, gpointer data)
{
    /* set flag */
    notes_applet->notes_saved = FALSE;
    return;
}

/* the caller of notes_new_node have to show the note->note_w widget,
   i.e. it is not done here */
_note*
notes_new_note(void)
{
    GtkTextBuffer *text_buffer;
    _note *note;
    xmlNodePtr xmlptr;
    static gint note_id_count = 0;
    
    note = notes_create_note();

    /* id count */
    note->id = note_id_count;
    note_id_count++;

    /* connect close button on the note */
    g_signal_connect(G_OBJECT(note->button_close), "clicked",
		     G_CALLBACK(notes_delete_note_dialog), (gpointer)note);
    /* notify if something was changed */
    text_buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(note->text_view));
    g_signal_connect(G_OBJECT(text_buffer), "changed",
		     G_CALLBACK(notes_note_changed), (gpointer)note);

    /* setup the xml */
    xmlptr = xmlDocGetRootElement(notes_applet->doc);
    note->xml_tag = xmlNewTextChild(xmlptr, NULL, (xmlChar *)"note", NULL);

    /* add to list */
    notes_applet->notes = g_list_append(notes_applet->notes, note);

    /* set new tooltips */
    notes_set_tooltips();
    
    return note;
}

static void
notes_free_note(_note *note)
{
    /* by destroying the note_w, close_button will also be destroyed */
    gtk_widget_destroy(note->note_w);

    xmlUnlinkNode(note->xml_tag);

    return;
}

static void
notes_free(Control *ctrl)
{
    GList *cur;
    _note *note;

    /* save notes */
    notes_store_config();
    
    g_return_if_fail(ctrl != NULL);
    g_return_if_fail(ctrl->data != NULL);

    cur = g_list_first(notes_applet->notes);
    while (cur) {
	note = cur->data;
	/* get rid of the widgets */
	notes_free_note(note);
	cur = g_list_next(cur);
    }
    g_list_free(notes_applet->notes);
    return;
    
}

void
notes_delete_note(_note *note)
{
  GList *li;
  _note *cur;
  

  li = g_list_first(notes_applet->notes);
  while (li != NULL) {
    cur = (_note *)li->data;
    /* note found */
    if (cur != NULL) {
      if (cur->id == note->id) {
		notes_applet->notes = g_list_remove_link(notes_applet->notes, li);
		notes_free_note(note);
		g_list_free(li);
		
		/* set new tooltips */
		notes_set_tooltips();
		/* save notes */
		notes_store_config();
      }
    }
	
    li = g_list_next(li);
  }
  return;
}


static void
notes_delete_note_dialog(GtkWidget *widget, gpointer data)
{
    _note *note;

    GtkWidget *dialog, *hbox, *dialog_label, *dialog_image;
    GtkTextIter start, end;
    GtkTextBuffer *buffer;
    gchar *text;
    gint dialog_response;

    note = (_note *)data;

    if (note != NULL) {
      /* get text from note */
      buffer 
	= gtk_text_view_get_buffer(GTK_TEXT_VIEW(note->text_view));
      gtk_text_buffer_get_bounds (buffer, &start, &end);
      text = gtk_text_iter_get_text (&start, &end);
      
      /* only as for confirmation if there is text in note */ 
      if (strlen(g_strstrip(text)) != 0) {
	
	/* create dialog for delete confirmation */
	dialog = 
	  gtk_dialog_new_with_buttons("Delete Note?",
				      GTK_WINDOW(note->note_w),
				      GTK_DIALOG_MODAL |
				      GTK_DIALOG_NO_SEPARATOR,
				      GTK_STOCK_DELETE,
				      GTK_RESPONSE_ACCEPT,
				      GTK_STOCK_CANCEL,
				      GTK_RESPONSE_REJECT,
				      NULL);
	
	hbox = gtk_hbox_new(FALSE, 0);
	gtk_widget_show(hbox);
	gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox),
			  hbox);
	
	dialog_image = 
	  gtk_image_new_from_stock(GTK_STOCK_DIALOG_QUESTION,
				   GTK_ICON_SIZE_DIALOG);
	gtk_widget_show(dialog_image);
	gtk_box_pack_start_defaults(GTK_BOX(hbox), dialog_image);
	
	dialog_label = gtk_label_new("Really delete note?");
	gtk_widget_show(dialog_label);
	gtk_box_pack_start_defaults(GTK_BOX(hbox), dialog_label);
	
	/* run the dialog */
	dialog_response = gtk_dialog_run(GTK_DIALOG(dialog));
	
	if (dialog_response == GTK_RESPONSE_ACCEPT) {
	  notes_delete_note(note);
	}
	
	gtk_widget_destroy(dialog);
	
	
      } else {
	/* delete the note without user interaction if the note 
	   was empty */
	notes_delete_note(note);
	
      }
    }
    
    return;
}


static void
notes_read_config(Control *ctrl, xmlNodePtr parent)
{
  xmlNodePtr cur, node;
  xmlChar *user_color;
  GdkColor *colors;
  GdkPixbuf *pixbuf_orig;
  gint n_colors;
    
  
  /* parse */
  node = parent->children;
  while (node != NULL) {
	if (xmlStrEqual(node->name, (const xmlChar *)"notes")) {
	  cur = node->children;
	  while (cur != NULL) {
		/* show notes */
		if (xmlStrEqual(cur->name, (const xmlChar *)"show_notes")) {
		  if (xmlStrEqual(xmlNodeGetContent(cur), 
						  (const xmlChar *)"true")) {
			notes_applet->show_notes = TRUE;
		  } else {
			notes_applet->show_notes = FALSE;
		  }
		}
		/* user color */
		else if (xmlStrEqual(cur->name, (const xmlChar *)"user_color")) {
		  user_color = xmlNodeGetContent(cur);
		  /* if successfully parsed */
		  if (gtk_color_selection_palette_from_string((gchar *)user_color,
													  &colors,
													  &n_colors)) {
			/* the first in the array is the user color */
			notes_applet->note_color = colors[0];
		  }
		} 
		/* sticky notes */
		else if (xmlStrEqual(cur->name, (const xmlChar *)"notes_sticky")) {
		  if (xmlStrEqual(xmlNodeGetContent(cur),
						  (const xmlChar *)"true")) {
			notes_applet->notes_sticky = TRUE;
		  } else {
			notes_applet->notes_sticky = FALSE;
		  }
		}
		/* notes on top */
		else if (xmlStrEqual(cur->name, (const xmlChar *)"notes_on_top")) {
		  if (xmlStrEqual(xmlNodeGetContent(cur),
						  (const xmlChar *)"true")) {
			notes_applet->notes_on_top = TRUE;
		  } else {
			notes_applet->notes_on_top = FALSE;
		  }
		}
		/* system color boolean */
		else if (xmlStrEqual(cur->name, (const xmlChar *)"system_colors")) {
		  if (xmlStrEqual(xmlNodeGetContent(cur), 
						  (const xmlChar *)"true")) {
			notes_applet->system_colors = TRUE;
		  } else {
			notes_applet->system_colors = FALSE;
		  }
		}
		
		cur = cur->next;
	  }
	}
	node = node->next;
  }
  
  /* load config file, i.e. this constructs old notes which have
	 been stored on disk */
  notes_load_config();
  
  /* do some updating */
  notes_update_visibility();
  notes_update_colors();
  notes_update_sticky();
  notes_update_on_top();
  
  /* set tooltips */
  notes_set_tooltips();
  
  return;
}

static void
notes_write_config(Control *ctrl, xmlNodePtr parent)
{
  xmlNodePtr cur;
  GdkColor colors[1];
  gchar *color_palette;
  
  cur = xmlNewTextChild(parent, NULL, (xmlChar *)"notes", NULL);
  /* show notes */
  xmlNewTextChild(cur, NULL, (xmlChar *)"show_notes",
				  (xmlChar *)((notes_applet->show_notes == TRUE) ? 
							  "true" : "false"));
  /* user color */
  /* make an array of colors but use only first item, i.e. index 0 */
  colors[0] = notes_applet->note_color;
  color_palette = 
	gtk_color_selection_palette_to_string(colors, 1);
  xmlNewTextChild(cur, NULL, (xmlChar *)"user_color", 
				  (xmlChar *)color_palette);
  /* sticky notes */
  xmlNewTextChild(cur, NULL, (xmlChar *)"notes_sticky",
				  (xmlChar *)((notes_applet->notes_sticky == TRUE) ? 
							  "true" : "false"));
  /* notes on top */
  xmlNewTextChild(cur, NULL, (xmlChar *)"notes_on_top",
				  (xmlChar *)((notes_applet->notes_on_top == TRUE) ? 
							  "true" : "false"));
  /* system color boolean */
  xmlNewTextChild(cur, NULL, (xmlChar *)"system_colors",
				  (xmlChar *)((notes_applet->system_colors == TRUE) ? 
							  "true" : "false"));
  
  return;
}

static void
notes_attach_callback(Control *ctrl, const gchar *signal, GCallback cb,
		gpointer data)
{

  g_signal_connect(notes_applet->applet_event_box, signal, cb, data);
  g_signal_connect(notes_applet->applet_button, signal, cb, data);
  
  return;
}

void 
notes_destroy_cb(GtkWidget *widget, _note_applet *notes)
{
    if (notes->save_id > 0)
    {
        g_source_remove (notes->save_id);
        notes->save_id = 0;
    }
}

gboolean
notes_save_notes_timeout(gpointer data)
{
    if (notes_applet->notes_saved == FALSE) {
	notes_store_config();
	DBG("notes saved\n");
	notes_applet->notes_saved = TRUE;
    }
    /* return tree to keep timeout active */
    return TRUE;
}

static gboolean
notes_control_new(Control *ctrl)
{
  GdkPixbuf *pixbuf;
  
  xmlNodePtr xmlptr;

  notes_applet = g_new(_note_applet, 1);

  /* create applet event box */
  notes_applet->applet_event_box = gtk_event_box_new();
  gtk_widget_show(notes_applet->applet_event_box);

  /* create applet button */
  notes_applet->applet_button = gtk_button_new();
  gtk_button_set_relief(GTK_BUTTON(notes_applet->applet_button), 
						GTK_RELIEF_NONE);
  gtk_widget_show(notes_applet->applet_button);
  
  /* connect main applet button */
  g_signal_connect(G_OBJECT(notes_applet->applet_button), 
				   "button-press-event",
				   G_CALLBACK(cb_applet_button_press_event_advanced),
				   NULL);
  
  gtk_container_add(GTK_CONTAINER(notes_applet->applet_event_box), 
  		    notes_applet->applet_button);

  gtk_container_add(GTK_CONTAINER(ctrl->base), 
  		    notes_applet->applet_event_box);

  /* tooltips */
  notes_applet->tooltips = gtk_tooltips_new();


  /* icon for applet */
  notes_applet->icon_filename = APPLET_PIXMAP;
  pixbuf = gdk_pixbuf_new_from_file(APPLET_PIXMAP, NULL);
  notes_applet->pixbuf = pixbuf;

  notes_applet->icon = gtk_image_new();
  /* will be updated in set_size */
  gtk_container_add(GTK_CONTAINER(notes_applet->applet_button), 
  		    notes_applet->icon);
  gtk_widget_show(notes_applet->icon);
  
  ctrl->data = (gpointer)notes_applet;
  ctrl->with_popup = FALSE;
  
  /* init */
  notes_applet->show_notes = FALSE;
  /* GList of _note:s */
  notes_applet->notes = NULL;
  notes_applet->system_colors = TRUE;
  notes_applet->notes_saved = TRUE;
  /* make a default user color, yellow */
  gdk_color_parse("yellow", &notes_applet->note_color);
  
  /* create a root elmt  */
  notes_applet->doc = xmlNewDoc((xmlChar *)"1.0");
  xmlptr = xmlNewNode(NULL, (xmlChar *)"notes");
  xmlDocSetRootElement(notes_applet->doc, xmlptr);
  
  /* initialize tooltips */
  notes_set_tooltips();
  
  /* add timeout to save notes if required */
  /* call notes_save_notes_timeout every 5 seconds */
  notes_applet->save_id = g_timeout_add(5000, notes_save_notes_timeout, NULL);
  
  gtk_widget_set_size_request(ctrl->base, -1, -1);
  
  return TRUE;
}

void
notes_set_size(Control *ctrl, int size)
{
    GList *list;
    GtkWidget *img;
    GdkPixbuf *pix;

    if (ctrl != NULL) {
      
      if (size == TINY) {
	notes_applet->applet_icon_size = ICON_SIZE_SMALL;
      } else if (size == SMALL) {
	notes_applet->applet_icon_size = ICON_SIZE_MEDIUM;
      } else if (size == MEDIUM) {      
	notes_applet->applet_icon_size = ICON_SIZE_LARGE;
      } else {
	notes_applet->applet_icon_size = ICON_SIZE_HUGE;
      }
      
      //notes_applet->applet_size = size;

      /* icon */
      notes_applet->pixbuf = 
	gdk_pixbuf_new_from_file(notes_applet->icon_filename, NULL);

      pix = gdk_pixbuf_scale_simple(notes_applet->pixbuf, 
				    notes_applet->applet_icon_size,
				    notes_applet->applet_icon_size - 
				    (int) (notes_applet->applet_icon_size/3),
				    GDK_INTERP_BILINEAR);
      
      g_object_ref(G_OBJECT(notes_applet->icon));

      gtk_image_set_from_pixbuf(GTK_IMAGE(notes_applet->icon), pix);

      gtk_widget_set_size_request(notes_applet->applet_button, 
				  notes_applet->applet_icon_size + 10, 
				  -1);
    }
    
    return;
}

static void
notes_create_options (Control *ctrl, GtkContainer *con, GtkWidget *done)
{
    GtkWidget *widget;

    widget = notes_create_applet_options(con);
    gtk_container_add(con, widget);

    return;
}

/* initialization */
G_MODULE_EXPORT void
xfce_control_class_init(ControlClass *cc)
{

    cc->name		= "notes";
    cc->caption		= _("Notes");
    
    cc->create_control	= (CreateControlFunc)notes_control_new;
    
    cc->free		= notes_free;
    cc->attach_callback	= notes_attach_callback;
    
    cc->read_config	= notes_read_config;
    cc->write_config	= notes_write_config;
    cc->create_options  = notes_create_options;
    
    cc->set_size	= notes_set_size;
    
    /* unused
     * cc->set_orientation
     * cc->set_theme
     */

    return;
}

/* required! defined in panel/plugins.h */
XFCE_PLUGIN_CHECK_INIT
