/*
 * Twin - A Tiny Window System
 * Copyright © 2004 Keith Packard <keithp@keithp.com>
 * All rights reserved.
 *
 * This Library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * This Library 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with the Twin Library; see the file COPYING.  If not,
 * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

#include <twin_demospline.h>
#include <twinint.h>
#include <stdio.h>

#define D(x) twin_double_to_fixed(x)

#define _twin_demospline_pixmap(demospline)   ((demospline)->widget.window->pixmap)

void
_twin_demospline_paint (twin_demospline_t *demospline)
{
    twin_path_t	*path;
    int		i;

    path = twin_path_create ();
    twin_path_set_cap_style (path, demospline->cap_style);
    twin_path_move (path, demospline->points[0].x, demospline->points[0].y);
    twin_path_curve (path, 
		     demospline->points[1].x, demospline->points[1].y,
		     demospline->points[2].x, demospline->points[2].y,
		     demospline->points[3].x, demospline->points[3].y);
    twin_paint_stroke (_twin_demospline_pixmap(demospline), 0xff404040, path,
		       demospline->line_width);
    twin_path_set_cap_style (path, TwinCapButt);
    twin_paint_stroke (_twin_demospline_pixmap(demospline), 0xffffff00, path,
		       twin_int_to_fixed (2));
    
    twin_path_empty (path);
    twin_path_move (path, demospline->points[0].x, demospline->points[0].y);
    twin_path_draw (path, demospline->points[1].x, demospline->points[1].y);
    twin_paint_stroke (_twin_demospline_pixmap(demospline), 0xc08000c0, path,
		       twin_int_to_fixed (2));
    twin_path_empty (path);
    twin_path_move (path, demospline->points[3].x, demospline->points[3].y);
    twin_path_draw (path, demospline->points[2].x, demospline->points[2].y);
    twin_paint_stroke (_twin_demospline_pixmap(demospline), 0xc08000c0, path,
		       twin_int_to_fixed (2));
    twin_path_empty (path);
    for (i = 0; i < NPT; i++)
    {
	twin_path_empty (path);
	twin_path_circle (path, demospline->points[i].x, demospline->points[i].y,
			  twin_int_to_fixed (10));
	twin_paint_path (_twin_demospline_pixmap(demospline), 0x40004020, path);
    }
    twin_path_destroy (path);
}

static twin_dispatch_result_t
_twin_demospline_update_pos (twin_demospline_t *demospline, twin_event_t *event)
{
    if (demospline->which < 0)
	return TwinDispatchContinue;
    demospline->points[demospline->which].x = twin_int_to_fixed (event->u.pointer.x);
    demospline->points[demospline->which].y = twin_int_to_fixed (event->u.pointer.y);
    _twin_widget_queue_paint (&demospline->widget);
    return TwinDispatchDone;
}

#define twin_fixed_abs(f)   ((f) < 0 ? -(f) : (f))

static int
_twin_demospline_hit (twin_demospline_t *demospline, twin_fixed_t x, twin_fixed_t y)
{
    int	i;

    for (i = 0; i < NPT; i++)
	if (twin_fixed_abs (x - demospline->points[i].x) < demospline->line_width / 2 &&
	    twin_fixed_abs (y - demospline->points[i].y) < demospline->line_width / 2)
	    return i;
    return -1;
}

twin_dispatch_result_t
_twin_demospline_dispatch (twin_widget_t *widget, twin_event_t *event)
{
    twin_demospline_t    *demospline = (twin_demospline_t *) widget;

    if (_twin_widget_dispatch (widget, event) == TwinDispatchDone)
	return TwinDispatchDone;
    switch (event->kind) {
    case TwinEventPaint:
	_twin_demospline_paint (demospline);
	break;
    case TwinEventButtonDown:
	demospline->which = _twin_demospline_hit (demospline,
					      twin_int_to_fixed (event->u.pointer.x),
					      twin_int_to_fixed (event->u.pointer.y));
	return _twin_demospline_update_pos (demospline, event);
	break;
    case TwinEventMotion:
	return _twin_demospline_update_pos (demospline, event);
	break;
    case TwinEventButtonUp:
	if (demospline->which < 0)
	    return TwinDispatchContinue;
	_twin_demospline_update_pos (demospline, event);
	demospline->which = -1;
	return TwinDispatchDone;
	break;
    default:
	break;
    }
    return TwinDispatchContinue;
}

void
_twin_demospline_init (twin_demospline_t		*demospline, 
		  twin_box_t		*parent,
		  twin_dispatch_proc_t	dispatch)
{
    static const twin_widget_layout_t	preferred = { 0, 0, 1, 1 };
    _twin_widget_init (&demospline->widget, parent, 0, preferred, dispatch);
    twin_widget_set (&demospline->widget, 0xffffffff);
    demospline->line_width = twin_int_to_fixed (100);
    demospline->cap_style = TwinCapButt;
    demospline->points[0].x = twin_int_to_fixed (100);
    demospline->points[0].y = twin_int_to_fixed (100);
    demospline->points[1].x = twin_int_to_fixed (300);
    demospline->points[1].y = twin_int_to_fixed (300);
    demospline->points[2].x = twin_int_to_fixed (100);
    demospline->points[2].y = twin_int_to_fixed (300);
    demospline->points[3].x = twin_int_to_fixed (300);
    demospline->points[3].y = twin_int_to_fixed (100);
}
    
twin_demospline_t *
twin_demospline_create (twin_box_t *parent)
{
    twin_demospline_t    *demospline = malloc (sizeof (twin_demospline_t));
    
    _twin_demospline_init(demospline, parent, _twin_demospline_dispatch);
    return demospline;
}

void
twin_demospline_start (twin_screen_t *screen, const char *name, int x, int y, int w, int h)
{
    twin_toplevel_t *toplevel = twin_toplevel_create (screen, TWIN_ARGB32,
						      TwinWindowApplication,
						      x, y, w, h, name);
    twin_demospline_t    *demospline = twin_demospline_create (&toplevel->box);
    (void) demospline;
    twin_toplevel_show (toplevel);
}
