/* $Id: e2_button.c 682 2007-10-28 05:33:18Z tpgww $

Copyright (C) 2004-2007 tooar <tooar@gmx.net>

This file is part of emelFM2.
emelFM2 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 3, or (at your option)
any later version.

emelFM2 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 emelFM2; see the file GPL. If not, contact the Free Software
Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include "emelfm2.h"
#include "e2_button.h"

E2_Button E2_BUTTON_OK =
	{ "",N_("_OK"),GTK_STOCK_OK, NULL,
		E2_BTN_DEFAULT,E2_BTN_DEFAULT,GTK_RESPONSE_OK};
E2_Button E2_BUTTON_CANCEL =
	{ "",N_("_Cancel"),GTK_STOCK_CANCEL,NULL,0,0,GTK_RESPONSE_CANCEL};
E2_Button E2_BUTTON_YES =
	{ "",N_("_Yes"),GTK_STOCK_YES, NULL,
		E2_BTN_DEFAULT,E2_BTN_DEFAULT,GTK_RESPONSE_YES};
E2_Button E2_BUTTON_NO =
	{ "",N_("_No"),GTK_STOCK_NO,NULL,0,0,GTK_RESPONSE_NO};
E2_Button E2_BUTTON_YESTOALL =
//	{ "",N_("Yes to _all"),GTK_STOCK_APPLY,NULL,0,0,E2_RESPONSE_YESTOALL};
	{ "",N_("Yes to _all"),"apply_all_"E2IP".png",NULL,0,0,E2_RESPONSE_YESTOALL};
E2_Button E2_BUTTON_NOTOALL =
	{ "",N_("_Stop"),GTK_STOCK_STOP,NULL,0,0,E2_RESPONSE_NOTOALL};
E2_Button E2_BUTTON_APPLY =
	{ "",N_("_Apply"),GTK_STOCK_APPLY,NULL,0,0,GTK_RESPONSE_APPLY};
E2_Button E2_BUTTON_APPLYTOALL =
//	{ "",N_("_Apply to all"),GTK_STOCK_APPLY,NULL,0,0,E2_RESPONSE_APPLYTOALL};
	{ "",N_("_Apply to all"),"apply_all_"E2IP".png",NULL,0,0,E2_RESPONSE_APPLYTOALL};
E2_Button E2_BUTTON_REFRESH =
	{ "",N_("_Refresh"),GTK_STOCK_REFRESH,NULL,0,0,E2_RESPONSE_REFRESH};
E2_Button E2_BUTTON_CLOSE =
	{ "",N_("_Close"),GTK_STOCK_CLOSE,NULL,0,0,GTK_RESPONSE_CLOSE};
E2_Button E2_BUTTON_CREATE =
	{ "",N_("C_reate"),GTK_STOCK_YES,NULL,0,0,E2_RESPONSE_CREATE};  //co-use with close/cancel
E2_Button E2_BUTTON_REMOVE =
	{ "",N_("_Remove"),GTK_STOCK_REMOVE,NULL,0,0,E2_RESPONSE_REMOVE}; //check no co-use with refresh

void e2_button_setup_labels (void)
{
	E2_BUTTON_OK.label = gettext (E2_BUTTON_OK.default_label);
	E2_BUTTON_CANCEL.label = gettext (E2_BUTTON_CANCEL.default_label);
	E2_BUTTON_YES.label = gettext (E2_BUTTON_YES.default_label);
	E2_BUTTON_NO.label = gettext (E2_BUTTON_NO.default_label);
	E2_BUTTON_YESTOALL.label = gettext (E2_BUTTON_YESTOALL.default_label);
	E2_BUTTON_NOTOALL.label = gettext (E2_BUTTON_NOTOALL.default_label);
	E2_BUTTON_APPLY.label = gettext (E2_BUTTON_APPLY.default_label);
	E2_BUTTON_APPLYTOALL.label = gettext (E2_BUTTON_APPLYTOALL.default_label);
	E2_BUTTON_REFRESH.label = gettext (E2_BUTTON_REFRESH.default_label);
	E2_BUTTON_CLOSE.label = gettext (E2_BUTTON_CLOSE.default_label);
	E2_BUTTON_CREATE.label = gettext (E2_BUTTON_CREATE.default_label);
	E2_BUTTON_REMOVE.label = gettext (E2_BUTTON_REMOVE.default_label);
}

/**
@brief set new (or no) icon for existing button @a button

e2 uses non-standard buttons, containing alignment
containing h/vbox, the latter with image (if any) packed 1st
@a stock may be a gtk stock name or a custom icon filename

@param button the button widget to be updated
@param stock string describing icon or NULL to clear the icon

@return
*/
void e2_button_set_image (GtkWidget *button, gchar *stock)
{
	if (e2_option_bool_get ("dialog-button-icons"))
	{
		GtkWidget *image = (stock != NULL) ?
			e2_widget_get_icon (stock, GTK_ICON_SIZE_BUTTON) : NULL;
		if (stock == NULL || image != NULL)
		{
			GtkWidget *bbox = GTK_BIN (GTK_BIN (button)->child)->child;
			GtkBoxChild *child1 = (GtkBoxChild *) GTK_BOX (bbox)->children->data;
			if (GTK_WIDGET_TYPE (child1->widget) == g_type_from_name ("GtkImage"))
				gtk_container_remove (GTK_CONTAINER (bbox), child1->widget);
			if (image != NULL)
			{
				gtk_box_pack_start (GTK_BOX (bbox), image, FALSE, FALSE, 0);
				gtk_box_reorder_child (GTK_BOX (bbox), image, 0);
				gtk_widget_show (image);
			}
		}
	}
}
/**
@brief get button-button which can be default and focused

@param label button label which may contain markup and/or mnemonic
@param stock string describing icon, or NULL
@param tip tooltip for the button, or NULL
@param callback callback function for "clicked" signal, or NULL
@param data data specified for the callback

@return the button widget
*/
GtkWidget *e2_button_get (gchar *label, gchar *stock, gchar *tip,
	gpointer callback, gpointer data)
{
	GtkWidget *button = e2_button_get_full (label, stock, GTK_ICON_SIZE_BUTTON,
		tip, callback, data, E2_BUTTON_CAN_DEFAULT | E2_BUTTON_CAN_FOCUS);
	gtk_widget_show_all (button);
	return button;
}
/**
@brief create button
This is used for toolbar buttons, and (maybe indirectly) for dialog buttons
@param label button label which may contain markup and/or mnemonic, or NULL
@param stock string describing icon, or NULL
@param size code for size of button-icon
@param tip tooltip for the button, or NULL
@param callback callback function for "clicked" signal, or NULL
@param data data specified for the callback
@param flags flags indicating button properties

@return the button widget
*/
GtkWidget *e2_button_get_full (gchar *label, gchar *stock, GtkIconSize size,
	gchar *tip, gpointer callback, gpointer data, E2_ButtonFlags flags)
{
	GtkWidget *button = gtk_button_new ();
	if (flags & E2_BUTTON_CAN_DEFAULT)
		GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
	else
		GTK_WIDGET_UNSET_FLAGS (button, GTK_CAN_DEFAULT);
	if (flags & E2_BUTTON_CAN_FOCUS)
		GTK_WIDGET_SET_FLAGS (button, GTK_CAN_FOCUS);
	else
		GTK_WIDGET_UNSET_FLAGS (button, GTK_CAN_FOCUS);

	if (tip != NULL)
#ifdef USE_GTK2_12TIPS
	gtk_widget_set_tooltip_text (
#else
	e2_widget_set_tooltip (NULL,
#endif
		button, tip);

	if (callback != NULL)
		g_signal_connect_data (G_OBJECT (button), "clicked",
			G_CALLBACK (callback), data,
			(flags & E2_BUTTON_FREE_DATA) ? (GClosureNotify) g_free : NULL, 0);

	GtkWidget *bbox;
	if (flags & E2_BUTTON_ICON_ABOVE_LABEL)
		bbox = gtk_vbox_new (FALSE, 2);	//fixed gap, not E2_PADDING_XSMALL
	else
		bbox = gtk_hbox_new (FALSE, 2);

	gboolean need_align = FALSE;

	if (stock != NULL)
	{
		GtkWidget *img = e2_widget_get_icon (stock, size);
		if ((flags & E2_BUTTON_SHOW_MISSING_ICON) && (img == NULL))
			img = e2_widget_get_icon (GTK_STOCK_MISSING_IMAGE, size);
		if (img != NULL)
		{
			gtk_box_pack_start (GTK_BOX (bbox),
				img, FALSE, FALSE, 0);
			need_align = TRUE;
		}
	}

	if ((label != NULL) && (*label != '\0'))
	{
		GtkWidget *lab = gtk_label_new ("");
		gtk_label_set_markup_with_mnemonic (GTK_LABEL (lab), label);
		gtk_box_pack_start (GTK_BOX (bbox), lab, TRUE, TRUE, 0);
		need_align = TRUE;
	}

	if (need_align)
	{
		GtkWidget *align = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
		gtk_container_add (GTK_CONTAINER (align), bbox);
		gtk_container_add (GTK_CONTAINER (button), align);
	}
	else	//should never happen
		gtk_container_add (GTK_CONTAINER (button), bbox);

	return button;
}
/**
@brief add button-sized button to the start of @a box

@param box widget to hold the button
@param exp TRUE to make the button expand with @a box
@param pad padding between button and @a box
@param label button label which may contain markup and/or mnemonic
@param stock string describing icon, or NULL
@param tip tooltip for the button, or NULL
@param callback callback function for "clicked" signal, or NULL
@param data data specified for the callback

@return the button widget
*/
GtkWidget *e2_button_add (GtkWidget *box, gboolean exp, guint pad, gchar *label,
	gchar *stock, gchar *tip, gpointer callback, gpointer data)
{
	GtkWidget *button = e2_button_get (label, stock, tip, callback, data);
	gtk_box_pack_start (GTK_BOX (box), button, exp, TRUE, pad);
	gtk_widget_show_all (button);
	return button;
}
/**
@brief add button-sized button to the end of @a box

@param box widget to hold the button
@param exp TRUE to make the button expand with @a box
@param pad padding between button and @a box
@param label button label which may contain markup and/or mnemonic
@param stock string describing icon, or NULL
@param tip tooltip for the button, or NULL
@param callback callback function for "clicked" signal, or NULL
@param data data specified for the callback

@return the button widget
*/
GtkWidget *e2_button_add_end (GtkWidget *box, gboolean exp, guint pad,
	gchar *label, gchar *stock, gchar *tip, gpointer callback, gpointer data)
{
	GtkWidget *button = e2_button_get (label, stock, tip, callback, data);
	gtk_box_pack_end (GTK_BOX (box), button, exp, TRUE, pad);
	gtk_widget_show_all (button);
	return button;
}
/**
@brief create check or toggle button with mmemonic label

@param check TRUE for check button, FALSE for toggle button
@param state initial state of the button
@param label button label which may contain markup and/or mnemonic
@param tip tooltip for the button, or NULL
@param callback callback function for "toggled" signal, or NULL
@param data data specified for the callback

@return the button widget
*/
GtkWidget *e2_button_get_toggle (gboolean check, gboolean state,
	gchar *label, gchar *tip, gpointer callback, gpointer data)
{
	GtkWidget *button;
	if (check)
		button = gtk_check_button_new_with_mnemonic (label);
	else
		button = gtk_toggle_button_new_with_mnemonic (label);
	GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
	GTK_WIDGET_SET_FLAGS (button, GTK_CAN_FOCUS);
	if (state)
		gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
	if (tip != NULL)
#ifdef USE_GTK2_12TIPS
	gtk_widget_set_tooltip_text (
#else
	e2_widget_set_tooltip (NULL,
#endif
		button, tip);
	if (callback != NULL)
		g_signal_connect (G_OBJECT (button), "toggled", G_CALLBACK (callback), data);
	gtk_widget_show (button);

	return button;
}
/**
@brief add check or toggle button with mmemonic label to @a box

@param box widget to hold the button
@param check TRUE for check button, FALSE for toggle button
@param state initial state of the button
@param label button label which may contain mnemonic
@param tip tooltip for the button, or NULL
@param exp TRUE to make the button expand with @a box
@param pad padding between button and @a box
@param callback callback function for "toggled" signal, or NULL
@param data data specified for the callback

@return the button widget
*/
GtkWidget *e2_button_add_toggle (GtkWidget *box, gboolean check, gboolean state,
	gchar *label, gchar *tip, gboolean exp, guint pad, gpointer callback, gpointer data)
{
	GtkWidget *button = e2_button_get_toggle (check, state, label, tip, callback, data);
	gtk_box_pack_start (GTK_BOX (box), button, exp, TRUE, pad);
	return button;
}
/**
@brief add radio button with mmemonic label to @a box

@param box widget to hold the button
@param label button label which may contain mnemonic, or NULL if no label
@param group the radio group, or NULL to start a group
@param state the intitial state of the button
@param exp TRUE to make the button expand with @a box
@param pad padding between button and @a box
@param callback callback function for "toggled" signal, or NULL
@param data data specified for the callback

@return the button widget
*/
GtkWidget *e2_button_add_radio (GtkWidget *box, gchar *label, GSList *group,
	gboolean state, gboolean exp, guint pad, gpointer callback, gpointer data)
{
	GtkWidget *radio_button = (label != NULL) ?
		gtk_radio_button_new_with_mnemonic (group, label):
		gtk_radio_button_new (group);
	if (state)
		gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (radio_button), TRUE);
	if (callback != NULL)
		g_signal_connect (G_OBJECT (radio_button), "toggled",
			G_CALLBACK (callback), data);
	gtk_box_pack_start (GTK_BOX (box), radio_button, exp, TRUE, pad);
	gtk_widget_show (radio_button);

	return radio_button;
}
/**
@brief add button with mmemonic label to @a table

@param table table to hold the button
@param label button label which may contain mnemonic
@param callback callback function for "clicked" signal, or NULL
@param data data specified for the callback
@param left
@param right
@param top
@param bottom

@return the button widget
*/
GtkWidget *e2_button_add_to_table (
	GtkWidget *table,
	gchar *label,
	gpointer callback,
	gpointer data,
	gint left, gint right, gint top, gint bottom)
{
	GtkWidget *button;
	button = gtk_button_new_with_mnemonic (label);
	if (callback != NULL)
		g_signal_connect (G_OBJECT (button), "clicked",
			G_CALLBACK (callback), data);
	gtk_table_attach_defaults (GTK_TABLE (table), button, left, right, top, bottom);
	gtk_widget_show (button);

	return button;
}
/**
@brief add check button with optional mmemonic label to @a table

@param table table to hold the button
@param label button label which may contain mnemonic, or NULL
@param state the intitial state of the button
@param callback callback function for "toggled" signal, or NULL
@param data data specified for the callback
@param left
@param right
@param top
@param bottom

@return the button widget
*/
GtkWidget *e2_button_add_toggle_to_table (
	GtkWidget *table,
	gchar *label,
	gboolean state,
	gpointer callback,
	gpointer data,
	gint left, gint right, gint top, gint bottom)
{
	GtkWidget *check_button;
	check_button = (label == NULL) ? gtk_check_button_new () :
 		gtk_check_button_new_with_mnemonic (label);
	if (state)
		gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button), TRUE);
	if (callback != NULL)
		g_signal_connect (G_OBJECT (check_button), "toggled",
			G_CALLBACK (callback), data);
	gtk_table_attach_defaults (GTK_TABLE (table), check_button,
		                        left, right, top, bottom);
	gtk_widget_show (check_button);

	return check_button;
}
/**
@brief add check button with optional mmemonic label to @a table

@param table table to hold the button
@param label button label which may contain mnemonic
@param group radio group, or NULL to start a group
@param state the intitial state of the button
@param callback callback function for "clicked" signal, or NULL
@param data data specified for the callback
@param left
@param right
@param top
@param bottom

@return the button widget
*/
GtkWidget *e2_button_add_radio_to_table (
	GtkWidget *table,
	gchar *label,
	GSList *group,
	gboolean state,
	gpointer callback,
	gpointer data,
	gint left, gint right, gint top, gint bottom)
{
	GtkWidget *radio_button = gtk_radio_button_new_with_mnemonic (group, label);
	if (state)
		gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (radio_button), TRUE);
	if (callback != NULL)
		g_signal_connect (G_OBJECT (radio_button), "toggled",
			G_CALLBACK (callback), data);
	gtk_table_attach_defaults (GTK_TABLE (table), radio_button,
		                        left, right, top, bottom);
	gtk_widget_show (radio_button);

	return radio_button;
}
