/*
 * 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.
 *
 * See the COPYING file for license information.
 *
 * Guillaume Chazarain <guichaz@gmail.com>
 */

/************************************
 * The zoom frame with funky colors *
 ************************************/

#include "gliv.h"
#include "zoom_frame.h"
#include "options.h"
#include "rendering.h"
#include "matrix.h"
#include "opengl.h"

extern rt_struct *rt;
extern GtkWidget *gl_widget;

/* Dimensions of the zoom frame. */
static gint zoom_frame_x, zoom_frame_y;
static gint zoom_frame_width, zoom_frame_height;

static gboolean zoom_frame_cleared = FALSE;

#define TARGET_SIZE 10

/* This the box with the cross and the circle in it. */
static void draw_zoom_box(GdkDrawable * d, GdkGC * gc,
                          gint x, gint y, gint w, gint h, gboolean clear)
{
    static gint target = 0;

    gdk_draw_rectangle(d, gc, FALSE, x, y, w, h);

    if (w > TARGET_SIZE * 2 && h > TARGET_SIZE * 2) {
        gint x_middle = x + w / 2;
        gint y_middle = y + h / 2;

        /* If we are clearing, we must reuse the same parameters. */
        if (clear == FALSE) {
            target += 320;
            if (target == 180 * 64)
                target = 0;
        }

        gdk_draw_line(d, gc, x_middle, y_middle - TARGET_SIZE / 3,
                      x_middle, y_middle + TARGET_SIZE / 3);

        gdk_draw_line(d, gc, x_middle - TARGET_SIZE / 3, y_middle,
                      x_middle + TARGET_SIZE / 3, y_middle);

        gdk_draw_arc(d, gc, FALSE,
                     x_middle - TARGET_SIZE, y_middle - TARGET_SIZE,
                     TARGET_SIZE * 2, TARGET_SIZE * 2, target, 90 * 64);

        gdk_draw_arc(d, gc, FALSE,
                     x_middle - TARGET_SIZE, y_middle - TARGET_SIZE,
                     TARGET_SIZE * 2, TARGET_SIZE * 2,
                     target + 180 * 64, 90 * 64);
    }
}

void draw_zoom_frame(void)
{
    /*
     * We keep the coordinates of the previous
     * frame to erase it with a XOR.
     */
    static gint x = 0;
    static gint y = 0;
    static gint width = 0;
    static gint height = 0;
    static GdkGC *gc = NULL;
    GdkDrawable *d;

    d = gl_widget->window;
    if (gc == NULL) {
        /* First time. */
        gc = gdk_gc_new(d);
        gdk_gc_set_foreground(gc, &(gl_widget->style->white));
        gdk_gc_set_function(gc, GDK_XOR);
    }

    /* Erase the previous frame. */
    draw_zoom_box(d, gc, x, y, width, height, TRUE);

    /* Update saved coordinates. */
    x = zoom_frame_x;
    y = zoom_frame_y;
    width = zoom_frame_width;
    height = zoom_frame_height;

    /* Draw the new frame. */
    draw_zoom_box(d, gc, x, y, width, height, FALSE);

    zoom_frame_cleared = FALSE;

    gdk_gl_drawable_wait_gdk(gtk_widget_get_gl_drawable(gl_widget));
}

void set_zoom_frame(gint x, gint y, gint width, gint height)
{
    if (width < 0) {
        zoom_frame_x = x + width;
        zoom_frame_width = -width;
    } else {
        zoom_frame_x = x;
        zoom_frame_width = width;
    }

    if (height < 0) {
        zoom_frame_y = y + height;
        zoom_frame_height = -height;
    } else {
        zoom_frame_y = y;
        zoom_frame_height = height;
    }
}

void clear_zoom_frame(void)
{
    if (zoom_frame_cleared == FALSE) {
        set_zoom_frame(-1, -1, 0, 0);
        draw_zoom_frame();
        zoom_frame_cleared = TRUE;
    }
}

void zoom_frame(void)
{
    gfloat x, y, zoom;

    if (zoom_frame_width == 0 || zoom_frame_height == 0) {
        /* To avoid division by zero. */
        set_zoom_frame(-1, -1, 0, 0);
        draw_zoom_frame();
        return;
    }

    zoom = MIN((gfloat) rt->wid_size->width / zoom_frame_width,
               (gfloat) rt->wid_size->height / zoom_frame_height);

    x = zoom_frame_x + zoom_frame_width / 2.0;
    y = zoom_frame_y + zoom_frame_height / 2.0;

    /* zoom. */
    matrix_zoom(zoom, x, y);

    /* center. */
    matrix_move(rt->wid_size->width / 2.0 - x, rt->wid_size->height / 2.0 - y);

    refresh(REFRESH_IMAGE | REFRESH_STATUS | APPEND_HISTORY);
}
