#pragma once
/*
 *  $Id: vector-layer.h 30090 2026-06-18 18:22:29Z yeti-dn $
 *  Copyright (C) 2003-2026 David Necas (Yeti), Petr Klapetek.
 *  E-mail: yeti@gwyddion.net, klapetek@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.
 */

#ifndef __GWYUI_VECTOR_LAYER_H__
#define __GWYUI_VECTOR_LAYER_H__

#include <cairo/cairo.h>
#include <gdk/gdk.h>
#include <libgwyddion/selection.h>
#include <libgwyui/data-view-layer.h>

G_BEGIN_DECLS

typedef gint (*GwyVectorLayerSearchFunc)(gdouble x,
                                         gdouble y,
                                         gdouble *mindistance,
                                         const gdouble *coords,
                                         gint n,
                                         const gdouble *metric);

#define GWY_TYPE_VECTOR_LAYER            (gwy_vector_layer_get_type())
#define GWY_VECTOR_LAYER(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), GWY_TYPE_VECTOR_LAYER, GwyVectorLayer))
#define GWY_VECTOR_LAYER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), GWY_TYPE_VECTOR_LAYER, GwyVectorLayerClass))
#define GWY_IS_VECTOR_LAYER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), GWY_TYPE_VECTOR_LAYER))
#define GWY_IS_VECTOR_LAYER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GWY_TYPE_VECTOR_LAYER))
#define GWY_VECTOR_LAYER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), GWY_TYPE_VECTOR_LAYER, GwyVectorLayerClass))

typedef struct _GwyVectorLayer             GwyVectorLayer;
typedef struct _GwyVectorLayerClass        GwyVectorLayerClass;
typedef struct _GwyVectorLayerPrivate      GwyVectorLayerPrivate;
typedef struct _GwyVectorLayerClassPrivate GwyVectorLayerClassPrivate;

struct _GwyVectorLayer {
    GwyDataViewLayer parent_instance;
    GwyVectorLayerPrivate *priv;
};

/* FIXME GTK3 cairo_surface_t does not have ‘canvas’ (or, more precisely, only some Cairo surfaces do, like images,
 * but others are basically infinite). But we do not have any native size either; we only have a bunch of nanometre
 * scale coordinates (or even weirder coordinates, like for FFT images).
 *
 * For rendering to screen it is fine because we just ask the widget for its pixel region. But for other potential
 * targets? Can we, for instance, require the caller to do cairo_clip() and then assume the region we get from
 * cairo_clip_extents() is the region we should transform the physical coordinates to?
 *
 * Since rendering to other targets than screen was unused anyway as imgexport does its own rendering, we might not
 * care much initially. */
struct _GwyVectorLayerClass {
    GwyDataViewLayerClass parent_class;
    GwyVectorLayerClassPrivate *priv;

    GType selection_type;

    /* Signals */
    gboolean (*object_chosen)(GwyVectorLayer *layer,
                              gint id);

    /* Virtual table */
    void (*draw)(GwyVectorLayer *layer,
                 cairo_t *cr);
    void (*invalidate_object)(GwyVectorLayer *layer,
                              cairo_region_t *cr,
                              const gdouble *xy);
    void (*selection_notify)(GwyVectorLayer *layer,
                             const GParamSpec *spec);
    void (*cancel_editing)(GwyVectorLayer *layer);
    void (*key_press)(GwyVectorLayer *layer,
                      guint keyval);
    void (*key_release)(GwyVectorLayer *layer,
                        guint keyval);
    void (*enter)(GwyVectorLayer *layer,
                  gdouble x,
                  gdouble y);
    void (*motion)(GwyVectorLayer *layer,
                   gdouble x,
                   gdouble y);
    void (*leave)(GwyVectorLayer *layer);
    void (*button_press)(GwyVectorLayer *layer,
                         gdouble x,
                         gdouble y);
    void (*button_release)(GwyVectorLayer *layer,
                           gdouble x,
                           gdouble y);
    gboolean (*set_focus)(GwyVectorLayer *layer,
                          gint i);

    /*<private>*/
    void (*reserved1)(void);
    void (*reserved2)(void);
    void (*reserved3)(void);
    void (*reserved4)(void);
    void (*reserved5)(void);
    void (*reserved6)(void);
};

#define gwy_vector_layer_get_selection_type(layer) \
    gwy_vector_layer_class_get_selection_type(GWY_VECTOR_LAYER_GET_CLASS(layer))

GType           gwy_vector_layer_get_type                (void)                            G_GNUC_CONST;
GType           gwy_vector_layer_class_get_selection_type(GwyVectorLayerClass *klass);
GwySelection*   gwy_vector_layer_ensure_selection        (GwyVectorLayer *layer);
GwySelection*   gwy_vector_layer_get_selection           (GwyVectorLayer *layer);
void            gwy_vector_layer_set_selection           (GwyVectorLayer *layer,
                                                          GwySelection *selection);
gint            gwy_vector_layer_get_focus               (GwyVectorLayer *layer);
gboolean        gwy_vector_layer_set_focus               (GwyVectorLayer *layer,
                                                          gint focus);
gboolean        gwy_vector_layer_get_editable            (GwyVectorLayer *layer);
void            gwy_vector_layer_set_editable            (GwyVectorLayer *layer,
                                                          gboolean editable);
gboolean        gwy_vector_layer_queue_draw_parent       (GwyVectorLayer *layer);
void            gwy_vector_layer_draw                    (GwyVectorLayer *layer,
                                                          cairo_t *cr);
PangoLayout*    gwy_vector_layer_ensure_layout           (GwyVectorLayer *layer);
GdkModifierType gwy_vector_layer_get_modifiers           (GwyVectorLayer *layer);
gint            gwy_vector_layer_get_current_button      (GwyVectorLayer *layer);
gint            gwy_vector_layer_get_current_object      (GwyVectorLayer *layer);
void            gwy_vector_layer_set_current_object      (GwyVectorLayer *layer,
                                                          gint i);
gint            gwy_vector_layer_update_object           (GwyVectorLayer *layer,
                                                          gint i,
                                                          const gdouble *xy);
gint            gwy_vector_layer_find_nearest            (GwyVectorLayer *layer,
                                                          GwyVectorLayerSearchFunc search,
                                                          gint subdivision,
                                                          gdouble x,
                                                          gdouble y,
                                                          gdouble *mindistance);

G_END_DECLS

#endif

/* 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 : */
