/* window-menu.c: Window Selector applet
 *
 * Copyright (C) 2003 Sun Microsystems, Inc.
 * Copyright (C) 2001 Free Software Foundation, Inc.
 * Copyright (C) 2000 Helix Code, Inc.
 *
 * 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., 51 Franklin St, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 *
 * Authors:
 *      Mark McLoughlin <mark@skynet.ie>
 *      George Lebl <jirka@5z.com>
 *      Jacob Berkman <jacob@helixcode.com>
 */

#ifdef HAVE_CONFIG_H
	#include <config.h>
#endif

#include <string.h>
#include <mate-panel-applet.h>

#include <glib/gi18n.h>
#include <gdk/gdkkeysyms.h>
#if GTK_CHECK_VERSION (3, 0, 0)
#include <gdk/gdkkeysyms-compat.h>
#endif

#include <libmate-desktop/mate-aboutdialog.h>

#define WNCK_I_KNOW_THIS_IS_UNSTABLE
#include <libwnck/libwnck.h>

#include "wncklet.h"
#include "window-menu.h"

#define WINDOW_MENU_ICON "mate-panel-window-menu"

typedef struct {
	GtkWidget* applet;
	GtkWidget* selector;
	int size;
	MatePanelAppletOrient orient;
} WindowMenu;

static void window_menu_help(GtkAction* action, WindowMenu* window_menu)
{
	wncklet_display_help(window_menu->applet, "mate-user-guide", "panel-windowselector", WINDOW_MENU_ICON);
}

static void window_menu_about(GtkAction* action, WindowMenu* window_menu)
{
	static const char* authors[] = {
		"Perberos <perberos@gmail.com>",
		"Steve Zesch <stevezesch2@gmail.com>",
		"Stefano Karapetsas <stefano@karapetsas.com>",
		"Mark McLoughlin <mark@skynet.ie>",
		"George Lebl <jirka@5z.com>",
		"Jacob Berkman <jacob@helixcode.com>",
		NULL
	};

	const char* documenters[] = {
		"Sun GNOME Documentation Team <gdocteam@sun.com>",
		NULL
	};

	char copyright[] = \
		"Copyright \xc2\xa9 2011 Perberos\n"
		"Copyright \xc2\xa9 2003 Sun Microsystems, Inc.\n"
		"Copyright \xc2\xa9 2001 Free Software Foundation, Inc.\n"
		"Copyright \xc2\xa9 2000 Helix Code, Inc.";

	mate_show_about_dialog(GTK_WINDOW(window_menu->applet),
		"program-name", _("Window Selector"),
		"authors", authors,
		"comments", _("The Window Selector shows a list of all windows in a menu and lets you browse them."),
		"copyright", copyright,
		"documenters", documenters,
		"icon-name", WINDOW_MENU_ICON,
		"logo-icon-name", WINDOW_MENU_ICON,
		"translator-credits", _("translator-credits"),
		"version", VERSION,
		"website", "http://www.mate-desktop.org/",
		NULL);
}

static const GtkActionEntry window_menu_actions[] = {
	{
		"WindowMenuHelp",
		GTK_STOCK_HELP,
		N_("_Help"),
		NULL,
		NULL,
		G_CALLBACK(window_menu_help)
	},
	{
		"WindowMenuAbout",
		GTK_STOCK_ABOUT,
		N_("_About"),
		NULL,
		NULL,
		G_CALLBACK(window_menu_about)
	}
};

static void window_menu_destroy(GtkWidget* widget, WindowMenu* window_menu)
{
	g_free(window_menu);
}

#if GTK_CHECK_VERSION (3, 0, 0)
static gboolean window_menu_on_draw (GtkWidget* widget,
				     cairo_t*   cr,
				     gpointer   data)
{
	GtkStyleContext *context;
	GtkStateFlags    state;
	WindowMenu      *window_menu = data;

	if (!gtk_widget_has_focus (window_menu->applet))
		return FALSE;

	state = gtk_widget_get_state_flags (widget);
	context = gtk_widget_get_style_context (widget);
	gtk_style_context_save (context);
	gtk_style_context_set_state (context, state);

	cairo_save (cr);
	gtk_render_focus (context, cr,
			  0., 0.,
			  gtk_widget_get_allocated_width (widget),
			  gtk_widget_get_allocated_height (widget));
			  cairo_restore (cr);

	gtk_style_context_restore (context);

	return FALSE;
}
#else
static gboolean window_menu_on_expose (GtkWidget*      widget,
				       GdkEventExpose* event,
				       gpointer        data)
{
	WindowMenu* window_menu = data;

	if (gtk_widget_has_focus(window_menu->applet))
		gtk_paint_focus(gtk_widget_get_style(widget),
						gtk_widget_get_window(widget),
						gtk_widget_get_state(widget),
						NULL,
						widget,
						"menu-applet",
						0, 0,
						-1, -1);

	return FALSE;
}
#endif

static inline void force_no_focus_padding(GtkWidget* widget)
{
#if GTK_CHECK_VERSION (3, 0, 0)
	GtkCssProvider *provider;

	provider = gtk_css_provider_new ();
	gtk_css_provider_load_from_data (provider,
					 "#window-menu-applet-button {\n"
					 " border-width: 0px;\n"
					 " -GtkWidget-focus-line-width: 0px;\n"
					 " -GtkWidget-focus-padding: 0px; }",
					 -1, NULL);
	gtk_style_context_add_provider (gtk_widget_get_style_context (widget),
					GTK_STYLE_PROVIDER (provider),
					GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
	g_object_unref (provider);
#else
	gboolean first_time = TRUE;

	if (first_time)
	{
		gtk_rc_parse_string("\n"
			"   style \"window-menu-applet-button-style\"\n"
			"   {\n"
			"      GtkWidget::focus-line-width=0\n"
			"      GtkWidget::focus-padding=0\n"
			"   }\n"
			"\n"
			"    widget \"*.PanelApplet-window-menu-applet-button\" style \"window-menu-applet-button-style\"\n"
			"\n");
		first_time = FALSE;
	}
#endif

	gtk_widget_set_name(widget, "PanelApplet-window-menu-applet-button");
}

static void window_menu_size_allocate(MatePanelApplet* applet, GtkAllocation* allocation, WindowMenu* window_menu)
{
	MatePanelAppletOrient orient;
	GList* children;
	GtkWidget* child;

	orient = mate_panel_applet_get_orient(applet);

	children = gtk_container_get_children(GTK_CONTAINER(window_menu->selector));
	child = GTK_WIDGET(children->data);
	g_list_free(children);

	if (orient == MATE_PANEL_APPLET_ORIENT_LEFT || orient == MATE_PANEL_APPLET_ORIENT_RIGHT)
	{
		if (window_menu->size == allocation->width && orient == window_menu->orient)
			return;

		window_menu->size = allocation->width;
		gtk_widget_set_size_request(child, window_menu->size, -1);
	}
	else
	{
		if (window_menu->size == allocation->height && orient == window_menu->orient)
			return;

		window_menu->size = allocation->height;
		gtk_widget_set_size_request(child, -1, window_menu->size);
	}

	window_menu->orient = orient;
}

static gboolean window_menu_key_press_event(GtkWidget* widget, GdkEventKey* event, WindowMenu* window_menu)
{
	GtkMenuShell* menu_shell;
	WnckSelector* selector;

	switch (event->keyval)
	{
		case GDK_KP_Enter:
		case GDK_ISO_Enter:
		case GDK_3270_Enter:
		case GDK_Return:
		case GDK_space:
		case GDK_KP_Space:
			selector = WNCK_SELECTOR(window_menu->selector);
			/*
			 * We need to call _gtk_menu_shell_activate() here as is done in
			 * window_key_press_handler in gtkmenubar.c which pops up menu
			 * when F10 is pressed.
			 *
			 * As that function is private its code is replicated here.
			 */
			menu_shell = GTK_MENU_SHELL(selector);

#if !GTK_CHECK_VERSION (3, 0, 0)
			if (!menu_shell->active)
			{
				gtk_grab_add(GTK_WIDGET(menu_shell));
				menu_shell->have_grab = TRUE;
				menu_shell->active = TRUE;
			}
#endif

			gtk_menu_shell_select_first(menu_shell, FALSE);
			return TRUE;
		default:
			break;
	}

	return FALSE;
}

static gboolean filter_button_press(GtkWidget* widget, GdkEventButton* event, gpointer data)
{
	if (event->button != 1)
		g_signal_stop_emission_by_name(widget, "button_press_event");

	return FALSE;
}

gboolean window_menu_applet_fill(MatePanelApplet* applet)
{
	WindowMenu* window_menu;
	GtkActionGroup* action_group;
	gchar* ui_path;

	window_menu = g_new0(WindowMenu, 1);

	window_menu->applet = GTK_WIDGET(applet);
	force_no_focus_padding(window_menu->applet);
	gtk_widget_set_tooltip_text(window_menu->applet, _("Window Selector"));

	mate_panel_applet_set_flags(applet, MATE_PANEL_APPLET_EXPAND_MINOR);
	window_menu->size = mate_panel_applet_get_size(applet);
	window_menu->orient = mate_panel_applet_get_orient(applet);

	g_signal_connect(window_menu->applet, "destroy", G_CALLBACK(window_menu_destroy), window_menu);

	action_group = gtk_action_group_new("WindowMenu Applet Actions");
	gtk_action_group_set_translation_domain(action_group, GETTEXT_PACKAGE);
	gtk_action_group_add_actions(action_group, window_menu_actions, G_N_ELEMENTS(window_menu_actions), window_menu);
	ui_path = g_build_filename(WNCK_MENU_UI_DIR, "window-menu-menu.xml", NULL);
	mate_panel_applet_setup_menu_from_file(applet, ui_path, action_group);
	g_free(ui_path);
	g_object_unref(action_group);

	window_menu->selector = wnck_selector_new();
	gtk_container_add(GTK_CONTAINER(window_menu->applet), window_menu->selector);

	mate_panel_applet_set_background_widget(MATE_PANEL_APPLET(window_menu->applet), GTK_WIDGET(window_menu->selector));

	g_signal_connect(window_menu->applet, "key_press_event", G_CALLBACK(window_menu_key_press_event), window_menu);
	g_signal_connect(window_menu->applet, "size-allocate", G_CALLBACK(window_menu_size_allocate), window_menu);

	g_signal_connect_after(G_OBJECT(window_menu->applet), "focus-in-event", G_CALLBACK(gtk_widget_queue_draw), window_menu);
	g_signal_connect_after(G_OBJECT(window_menu->applet), "focus-out-event", G_CALLBACK(gtk_widget_queue_draw), window_menu);
#if GTK_CHECK_VERSION (3, 0, 0)
	g_signal_connect_after(G_OBJECT(window_menu->selector), "draw", G_CALLBACK(window_menu_on_draw), window_menu);
#else
	g_signal_connect_after(G_OBJECT(window_menu->selector), "expose-event", G_CALLBACK(window_menu_on_expose), window_menu);
#endif

	g_signal_connect(G_OBJECT(window_menu->selector), "button_press_event", G_CALLBACK(filter_button_press), window_menu);

	gtk_widget_show_all(GTK_WIDGET(window_menu->applet));

	return TRUE;
}