/* $Id: guppi-pie-tool.c,v 1.13 2001/08/26 03:04:35 trow Exp $ */
/*
* guppi-pie-tool.c
*
* Copyright (C) 2000 EMC Capital Management, Inc.
*
* Developed by Jon Trowbridge <trow@gnu.org>.
*
* 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 <config.h>
#include <gdk/gdkkeysyms.h>
#include <libgnome/gnome-defs.h>
#include <libgnome/gnome-config.h>
#include <libgnome/gnome-i18n.h>
#include <math.h>
#include <guppi-memory.h>
#include <guppi-metrics.h>
#include "guppi-pie-tool.h"
#include "guppi-pie-state.h"
#include "guppi-pie-view.h"
#include "guppi-pie-item.h"
static void
explode_all_first_cb (GuppiPlotTool *tool, GuppiCanvasItem *gci)
{
guppi_element_state_get (guppi_canvas_item_state (gci),
"base_offset", &tool->arg1,
NULL);
}
static void
explode_all_cb (GuppiPlotTool *tool, GuppiCanvasItem *gci)
{
gint cx0, cy0, cx1, cy1;
double cx, cy, dx, dy;
double ux, uy;
double r, t;
guppi_canvas_item_get_bbox_c (gci, &cx0, &cy0, &cx1, &cy1);
cx = (cx0 + cx1) / 2.0;
cy = (cy0 + cy1) / 2.0;
ux = tool->raw_start_x - cx;
uy = tool->raw_start_y - cy;
r = sqrt (ux * ux + uy * uy);
ux /= r;
uy /= r;
dx = tool->raw_x - tool->raw_start_x;
dy = tool->raw_y - tool->raw_start_y;
t = (dx * ux + dy * uy);
t = (guppi_x_px2pt (t) + guppi_y_px2pt (t)) / 2;
guppi_element_state_set (guppi_canvas_item_state (gci),
"base_offset", tool->arg1 + t,
NULL);
}
GuppiPlotTool *
guppi_pie_tool_new_explode_all (void)
{
GuppiPlotTool *tool;
tool = guppi_plot_tool_new ();
tool->name = guppi_strdup (_("Explode All"));
tool->supported_type = GUPPI_TYPE_PIE_ITEM;
tool->cursor = gdk_cursor_new (GDK_FLEUR);
tool->tracks_motion = TRUE;
tool->repeating = FALSE;
tool->first = explode_all_first_cb;
tool->middle = explode_all_cb;
return tool;
}
/***************************************************************************/
static void
pick_slice (GuppiPlotTool *tool, GuppiCanvasItem *gci)
{
gint slice;
if (tool->int_arg1)
return;
if (guppi_pie_item_in_slice (GUPPI_PIE_ITEM (gci),
tool->raw_x, tool->raw_y, &slice)) {
GuppiPieState *state = GUPPI_PIE_STATE (guppi_canvas_item_state (gci));
tool->int_arg1 = 1;
tool->int_arg2 = slice;
tool->arg1 = guppi_pie_state_slice_offset (state, slice);
}
}
static void
explode_slice_first_cb (GuppiPlotTool * tool, GuppiCanvasItem * gci)
{
tool->int_arg1 = 0;
pick_slice (tool, gci);
}
static void
explode_slice_cb (GuppiPlotTool * tool, GuppiCanvasItem * gci)
{
GuppiPieState *state = GUPPI_PIE_STATE (guppi_canvas_item_state (gci));
gint cx0, cy0, cx1, cy1;
double cx, cy, dx, dy;
double ux, uy;
double r, t;
if (tool->int_arg1 == 0) {
pick_slice (tool, gci);
return;
}
guppi_canvas_item_get_bbox_c (gci, &cx0, &cy0, &cx1, &cy1);
cx = (cx0 + cx1) / 2.0;
cy = (cy0 + cy1) / 2.0;
ux = tool->raw_start_x - cx;
uy = tool->raw_start_y - cy;
r = sqrt (ux * ux + uy * uy);
ux /= r;
uy /= r;
dx = tool->raw_x - tool->raw_start_x;
dy = tool->raw_y - tool->raw_start_y;
t = (dx * ux + dy * uy);
t = (guppi_x_px2pt (t) + guppi_y_px2pt (t)) / 2;
guppi_pie_state_set_slice_offset (state, tool->int_arg2, tool->arg1 + t);
guppi_element_state_changed (GUPPI_ELEMENT_STATE (state));
}
GuppiPlotTool *
guppi_pie_tool_new_explode_slice (void)
{
GuppiPlotTool *tool;
tool = guppi_plot_tool_new ();
tool->name = guppi_strdup (_("Explode Slice"));
tool->supported_type = GUPPI_TYPE_PIE_ITEM;
tool->cursor = gdk_cursor_new (GDK_FLEUR);
tool->tracks_motion = TRUE;
tool->repeating = FALSE;
tool->first = explode_slice_first_cb;
tool->middle = explode_slice_cb;
return tool;
}
/***************************************************************************/
static void
change_radius_first_cb (GuppiPlotTool * tool, GuppiCanvasItem * gci)
{
GuppiPieView *view = GUPPI_PIE_VIEW (guppi_canvas_item_view (gci));
guppi_element_state_get (guppi_canvas_item_state (gci),
"radius", &tool->arg1,
NULL);
tool->arg2 = guppi_pie_view_max_radius (view);
}
static void
change_radius_cb (GuppiPlotTool * tool, GuppiCanvasItem * gci)
{
gint cx0, cy0, cx1, cy1;
double cx, cy, dx, dy;
double ux, uy;
double r, t;
guppi_canvas_item_get_bbox_c (gci, &cx0, &cy0, &cx1, &cy1);
cx = (cx0 + cx1) / 2.0;
cy = (cy0 + cy1) / 2.0;
ux = tool->raw_start_x - cx;
uy = tool->raw_start_y - cy;
r = sqrt (ux * ux + uy * uy);
ux /= r;
uy /= r;
dx = tool->raw_x - tool->raw_start_x;
dy = tool->raw_y - tool->raw_start_y;
t = (dx * ux + dy * uy);
t = (guppi_x_px2pt (t) + guppi_y_px2pt (t)) / 2;
guppi_element_state_set (guppi_canvas_item_state (gci),
"radius", CLAMP (tool->arg1 + t, 72 / 8.0, tool->arg2),
NULL);
}
GuppiPlotTool *
guppi_pie_tool_new_change_radius (void)
{
GuppiPlotTool *tool;
tool = guppi_plot_tool_new ();
tool->name = guppi_strdup (_("Change Radius"));
tool->supported_type = GUPPI_TYPE_PIE_ITEM;
tool->cursor = gdk_cursor_new (GDK_SIZING);
tool->tracks_motion = TRUE;
tool->repeating = FALSE;
tool->first = change_radius_first_cb;
tool->middle = change_radius_cb;
return tool;
}
/***************************************************************************/
static void
spin_first_cb (GuppiPlotTool *tool, GuppiCanvasItem *gci)
{
gint cx0, cy0, cx1, cy1, cx, cy;
guppi_canvas_item_get_bbox_c (gci, &cx0, &cy0, &cx1, &cy1);
cx = (cx0 + cx1) / 2.0;
cy = (cy0 + cy1) / 2.0;
guppi_element_state_get (guppi_canvas_item_state (gci),
"base_angle", &tool->arg1,
NULL);
tool->arg2 = atan2 (tool->raw_start_y - cy, tool->raw_start_x - cx);
}
static void
spin_cb (GuppiPlotTool *tool, GuppiCanvasItem *gci)
{
gint cx0, cy0, cx1, cy1, cx, cy;
double theta;
guppi_canvas_item_get_bbox_c (gci, &cx0, &cy0, &cx1, &cy1);
cx = (cx0 + cx1) / 2.0;
cy = (cy0 + cy1) / 2.0;
theta = atan2 (tool->raw_y - cy, tool->raw_x - cx);
guppi_element_state_set (guppi_canvas_item_state (gci),
"base_angle", tool->arg1 + theta - tool->arg2,
NULL);
}
GuppiPlotTool *
guppi_pie_tool_new_spin (void)
{
GuppiPlotTool *tool;
tool = guppi_plot_tool_new ();
tool->name = guppi_strdup (_("Rotate Pie Chart"));
tool->supported_type = GUPPI_TYPE_PIE_ITEM;
tool->cursor = gdk_cursor_new (GDK_EXCHANGE);
tool->tracks_motion = TRUE;
tool->repeating = FALSE;
tool->first = spin_first_cb;
tool->middle = spin_cb;
return tool;
}
/***************************************************************************/
static void
fixed_spin_cb (GuppiPlotTool * tool, GuppiCanvasItem * item)
{
GuppiElementState *state = guppi_canvas_item_state (item);
double th;
guppi_element_state_get (state,
"base_angle", &th,
NULL);
th += tool->arg1;
guppi_element_state_set (state,
"base_angle", th,
NULL);
}
GuppiPlotTool *
guppi_pie_tool_new_fixed_spin (double theta_degrees)
{
GuppiPlotTool *tool;
tool = guppi_plot_tool_new ();
tool->name = guppi_strdup_printf (_("Rotate Pie Chart %g degrees"),
theta_degrees);
tool->supported_type = GUPPI_TYPE_PIE_ITEM;
tool->arg1 = theta_degrees * (M_PI / 180); /* convert to radians */
tool->cursor = gdk_cursor_new (GDK_EXCHANGE);
tool->tracks_motion = FALSE;
tool->repeating = TRUE;
tool->repeat_interval = 100;
tool->first = fixed_spin_cb;
tool->repeat = fixed_spin_cb;
return tool;
}
/***************************************************************************/
static void
slice_callback_cb (GuppiPlotTool * tool, GuppiCanvasItem * gci)
{
gint slice;
/* If the pointer is inside of a slice, execute the callback
with the slice # as an argument. */
if (guppi_pie_item_in_slice (GUPPI_PIE_ITEM (gci),
tool->raw_x, tool->raw_y, &slice)) {
GuppiPieSliceFunc func = tool->ptr_arg1;
func (slice, tool->ptr_arg2 /* == user data */ );
}
}
GuppiPlotTool *
guppi_pie_tool_new_slice_callback (GuppiPieSliceFunc func,
const gchar * name, gpointer user_data)
{
GuppiPlotTool *tool;
g_return_val_if_fail (func != NULL, NULL);
tool = guppi_plot_tool_new ();
tool->name = guppi_strdup (name);
tool->tracks_motion = FALSE;
tool->repeating = FALSE;
tool->first = slice_callback_cb;
tool->ptr_arg1 = (gpointer) func;
tool->ptr_arg2 = user_data;
return tool;
}
/**************************************************************************/
GuppiPlotToolkit *
guppi_pie_toolkit_default (void)
{
GuppiPlotToolkit *tk = guppi_plot_toolkit_new (_("Default"));
guppi_plot_toolkit_set_button_tool (tk, 1, 0,
guppi_pie_tool_new_explode_slice ());
guppi_plot_toolkit_set_button_tool (tk, 1, GDK_SHIFT_MASK,
guppi_pie_tool_new_explode_slice ());
guppi_plot_toolkit_set_button_tool (tk, 3, 0, guppi_pie_tool_new_spin ());
guppi_plot_toolkit_set_button_tool (tk, 4, 0,
guppi_pie_tool_new_fixed_spin (15));
guppi_plot_toolkit_set_button_tool (tk, 5, 0,
guppi_pie_tool_new_fixed_spin (-15));
guppi_plot_toolkit_set_key_tool (tk, GDK_Right, 0,
guppi_pie_tool_new_fixed_spin (12));
guppi_plot_toolkit_set_key_tool (tk, GDK_Left, 0,
guppi_pie_tool_new_fixed_spin (-12));
return tk;
}
GuppiPlotToolkit *
guppi_pie_toolkit_explode (void)
{
GuppiPlotToolkit *tk = guppi_plot_toolkit_new (_("Explode"));
tk->toolbar_button_image = "pie-explode.png";
guppi_plot_toolkit_set_button_tool (tk, 1, 0,
guppi_pie_tool_new_explode_slice ());
guppi_plot_toolkit_set_button_tool (tk, 3, 0,
guppi_pie_tool_new_explode_all ());
return tk;
}
GuppiPlotToolkit *
guppi_pie_toolkit_spin (void)
{
GuppiPlotToolkit *tk = guppi_plot_toolkit_new (_("Spin"));
tk->toolbar_button_image = "pie-spin.png";
guppi_plot_toolkit_set_button_tool (tk, 1, 0, guppi_pie_tool_new_spin ());
return tk;
}
/* $Id: guppi-pie-tool.c,v 1.13 2001/08/26 03:04:35 trow Exp $ */
syntax highlighted by Code2HTML, v. 0.9.1