/*
 *  $Id: selection-rectangle.c 27855 2025-04-18 09:57:38Z yeti-dn $
 *  Copyright (C) 2024 David Necas (Yeti).
 *  E-mail: yeti@gwyddion.net.
 *
 *  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 Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

#include "config.h"

#include "libgwyddion/macros.h"
#include "libgwyddion/math.h"
#include "libgwyddion/selection-rectangle.h"

enum {
    OBJECT_SIZE = 4
};

static gboolean crop_object(GwySelection *selection,
                            gint i,
                            gpointer user_data);
static void     crop       (GwySelection *selection,
                            gdouble xmin,
                            gdouble ymin,
                            gdouble xmax,
                            gdouble ymax);
static void     move       (GwySelection *selection,
                            gdouble vx,
                            gdouble vy);

static GObjectClass *parent_class = NULL;

G_DEFINE_TYPE(GwySelectionRectangle, gwy_selection_rectangle, GWY_TYPE_SELECTION)

static void
gwy_selection_rectangle_class_init(GwySelectionRectangleClass *klass)
{
    GwySelectionClass *sel_class = GWY_SELECTION_CLASS(klass);

    parent_class = gwy_selection_rectangle_parent_class;

    sel_class->object_size = OBJECT_SIZE;
    sel_class->crop = crop;
    sel_class->move = move;
}

static void
gwy_selection_rectangle_init(G_GNUC_UNUSED GwySelectionRectangle *selection)
{
}

/* FIXME: We just filter the rectangles. With some effort, we could also really crop them. */
static gboolean
crop_object(GwySelection *selection, gint i, gpointer user_data)
{
    const gdouble *minmax = (const gdouble*)user_data;
    gdouble xy[OBJECT_SIZE];

    gwy_selection_get_object(selection, i, xy);
    return (fmin(xy[0], xy[2]) >= minmax[0]
            && fmin(xy[1], xy[3]) >= minmax[1]
            && fmax(xy[0], xy[2]) <= minmax[2]
            && fmax(xy[1], xy[3]) <= minmax[3]);
}

static void
crop(GwySelection *selection, gdouble xmin, gdouble ymin, gdouble xmax, gdouble ymax)
{
    gdouble minmax[4] = { xmin, ymin, xmax, ymax };

    gwy_selection_filter(selection, crop_object, minmax);
}

static void
move(GwySelection *selection, gdouble vx, gdouble vy)
{
    gdouble v[OBJECT_SIZE] = { vx, vy, vx, vy };
    gwy_selection_move_objects(selection, v);
}

/**
 * gwy_selection_rectangle_new:
 *
 * Creates a new rectangle selection.
 *
 * Returns: A new selection object.
 **/
GwySelection*
gwy_selection_rectangle_new(void)
{
    return (GwySelection*)g_object_new(GWY_TYPE_SELECTION_RECTANGLE, NULL);
}

/**
 * SECTION:selection-rectangle
 * @title: GwySelectionRectangle
 * @short_description: Rectangle selection
 *
 * #GwySelectionRectangle represents rectangles. Selection data consist of quadruples of coordinates (x₀, y₀, x₁, y₁),
 * where 0 and 1 denote two opposite corners of the rectangle. It may any pair corners, as long as the two are
 * opposite.
 **/

/* vim: set cin columns=120 tw=118 et ts=4 sw=4 cino=>1s,e0,n0,f0,{0,}0,^0,\:1s,=0,g1s,h0,t0,+1s,c3,(0,u0 : */
