/* PIKA - Photo and Image Kooker Application
 * a rebranding of The GNU Image Manipulation Program (created with heckimp)
 * A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
 *
 * Original copyright, applying to most contents (license remains unchanged): 
 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
 *
 * 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 3 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, see <https://www.gnu.org/licenses/>.
 */

#ifndef __PIKA_ITEM_H__
#define __PIKA_ITEM_H__


#include "pikafilter.h"


#define PIKA_TYPE_ITEM            (pika_item_get_type ())
#define PIKA_ITEM(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), PIKA_TYPE_ITEM, PikaItem))
#define PIKA_ITEM_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), PIKA_TYPE_ITEM, PikaItemClass))
#define PIKA_IS_ITEM(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PIKA_TYPE_ITEM))
#define PIKA_IS_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PIKA_TYPE_ITEM))
#define PIKA_ITEM_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), PIKA_TYPE_ITEM, PikaItemClass))


typedef struct _PikaItemClass PikaItemClass;

struct _PikaItem
{
  PikaFilter  parent_instance;
};

struct _PikaItemClass
{
  PikaFilterClass  parent_class;

  /*  signals  */
  void            (* removed)               (PikaItem            *item);
  void            (* visibility_changed)    (PikaItem            *item);
  void            (* color_tag_changed)     (PikaItem            *item);
  void            (* lock_content_changed)  (PikaItem            *item);
  void            (* lock_position_changed) (PikaItem            *item);
  void            (* lock_visibility_changed) (PikaItem            *item);

  /*  virtual functions  */
  void            (* unset_removed)      (PikaItem               *item);
  gboolean        (* is_attached)        (PikaItem               *item);
  gboolean        (* is_content_locked)  (PikaItem               *item,
                                          PikaItem              **locked_item);
  gboolean        (* is_position_locked) (PikaItem               *item,
                                          PikaItem              **locked_item,
                                          gboolean                checking_children);
  gboolean        (* is_visibility_locked) (PikaItem               *item,
                                            PikaItem              **locked_item);
  PikaItemTree  * (* get_tree)           (PikaItem               *item);
  gboolean        (* bounds)             (PikaItem               *item,
                                          gdouble                *x,
                                          gdouble                *y,
                                          gdouble                *width,
                                          gdouble                *height);
  PikaItem      * (* duplicate)          (PikaItem               *item,
                                          GType                   new_type);
  void            (* convert)            (PikaItem               *item,
                                          PikaImage              *dest_image,
                                          GType                   old_type);
  gboolean        (* rename)             (PikaItem               *item,
                                          const gchar            *new_name,
                                          const gchar            *undo_desc,
                                          GError                **error);
  void            (* start_move)         (PikaItem               *item,
                                          gboolean                push_undo);
  void            (* end_move)           (PikaItem               *item,
                                          gboolean                push_undo);
  void            (* start_transform)    (PikaItem               *item,
                                          gboolean                push_undo);
  void            (* end_transform)      (PikaItem               *item,
                                          gboolean                push_undo);
  void            (* translate)          (PikaItem               *item,
                                          gdouble                 offset_x,
                                          gdouble                 offset_y,
                                          gboolean                push_undo);
  void            (* scale)              (PikaItem               *item,
                                          gint                    new_width,
                                          gint                    new_height,
                                          gint                    new_offset_x,
                                          gint                    new_offset_y,
                                          PikaInterpolationType   interpolation_type,
                                          PikaProgress           *progress);
  void            (* resize)             (PikaItem               *item,
                                          PikaContext            *context,
                                          PikaFillType            fill_type,
                                          gint                    new_width,
                                          gint                    new_height,
                                          gint                    offset_x,
                                          gint                    offset_y);
  void            (* flip)               (PikaItem               *item,
                                          PikaContext            *context,
                                          PikaOrientationType     flip_type,
                                          gdouble                 axis,
                                          gboolean                clip_result);
  void            (* rotate)             (PikaItem               *item,
                                          PikaContext            *context,
                                          PikaRotationType        rotate_type,
                                          gdouble                 center_x,
                                          gdouble                 center_y,
                                          gboolean                clip_result);
  void            (* transform)          (PikaItem               *item,
                                          PikaContext            *context,
                                          const PikaMatrix3      *matrix,
                                          PikaTransformDirection  direction,
                                          PikaInterpolationType   interpolation_type,
                                          PikaTransformResize     clip_result,
                                          PikaProgress           *progress);
  PikaTransformResize (* get_clip)       (PikaItem               *item,
                                          PikaTransformResize     clip_result);
  gboolean        (* fill)               (PikaItem               *item,
                                          PikaDrawable           *drawable,
                                          PikaFillOptions        *fill_options,
                                          gboolean                push_undo,
                                          PikaProgress           *progress,
                                          GError                **error);
  gboolean        (* stroke)             (PikaItem               *item,
                                          PikaDrawable           *drawable,
                                          PikaStrokeOptions      *stroke_options,
                                          gboolean                push_undo,
                                          PikaProgress           *progress,
                                          GError                **error);
  void            (* to_selection)       (PikaItem               *item,
                                          PikaChannelOps          op,
                                          gboolean                antialias,
                                          gboolean                feather,
                                          gdouble                 feather_radius_x,
                                          gdouble                 feather_radius_y);

  const gchar *default_name;
  const gchar *rename_desc;
  const gchar *translate_desc;
  const gchar *scale_desc;
  const gchar *resize_desc;
  const gchar *flip_desc;
  const gchar *rotate_desc;
  const gchar *transform_desc;
  const gchar *to_selection_desc;
  const gchar *fill_desc;
  const gchar *stroke_desc;

  const gchar *reorder_desc;
  const gchar *raise_desc;
  const gchar *raise_to_top_desc;
  const gchar *lower_desc;
  const gchar *lower_to_bottom_desc;

  const gchar *raise_failed;
  const gchar *lower_failed;
};


GType           pika_item_get_type           (void) G_GNUC_CONST;

PikaItem      * pika_item_new                (GType               type,
                                              PikaImage          *image,
                                              const gchar        *name,
                                              gint                offset_x,
                                              gint                offset_y,
                                              gint                width,
                                              gint                height);

void            pika_item_removed            (PikaItem           *item);
gboolean        pika_item_is_removed         (PikaItem           *item);
void            pika_item_unset_removed      (PikaItem           *item);

gboolean        pika_item_is_attached        (PikaItem           *item);

PikaItem      * pika_item_get_parent         (PikaItem           *item);

PikaItemTree  * pika_item_get_tree           (PikaItem           *item);
PikaContainer * pika_item_get_container      (PikaItem           *item);
GList         * pika_item_get_container_iter (PikaItem           *item);
gint            pika_item_get_index          (PikaItem           *item);
GList         * pika_item_get_path           (PikaItem           *item);

gboolean        pika_item_bounds             (PikaItem           *item,
                                              gint               *x,
                                              gint               *y,
                                              gint               *width,
                                              gint               *height);
gboolean        pika_item_bounds_f           (PikaItem           *item,
                                              gdouble            *x,
                                              gdouble            *y,
                                              gdouble            *width,
                                              gdouble            *height);

PikaItem      * pika_item_duplicate          (PikaItem           *item,
                                              GType               new_type);
PikaItem      * pika_item_convert            (PikaItem           *item,
                                              PikaImage          *dest_image,
                                              GType               new_type);

gboolean        pika_item_rename             (PikaItem           *item,
                                              const gchar        *new_name,
                                              GError            **error);

gint            pika_item_get_width          (PikaItem           *item);
gint            pika_item_get_height         (PikaItem           *item);
void            pika_item_set_size           (PikaItem           *item,
                                              gint                width,
                                              gint                height);

void            pika_item_get_offset         (PikaItem           *item,
                                              gint               *offset_x,
                                              gint               *offset_y);
void            pika_item_set_offset         (PikaItem           *item,
                                              gint                offset_x,
                                              gint                offset_y);
gint            pika_item_get_offset_x       (PikaItem           *item);
gint            pika_item_get_offset_y       (PikaItem           *item);

void            pika_item_start_move         (PikaItem           *item,
                                              gboolean            push_undo);
void            pika_item_end_move           (PikaItem           *item,
                                              gboolean            push_undo);

void            pika_item_start_transform    (PikaItem           *item,
                                              gboolean            push_undo);
void            pika_item_end_transform      (PikaItem           *item,
                                              gboolean            push_undo);

void            pika_item_translate          (PikaItem           *item,
                                              gdouble             offset_x,
                                              gdouble             offset_y,
                                              gboolean            push_undo);

gboolean        pika_item_check_scaling      (PikaItem           *item,
                                              gint                new_width,
                                              gint                new_height);
void            pika_item_scale              (PikaItem           *item,
                                              gint                new_width,
                                              gint                new_height,
                                              gint                new_offset_x,
                                              gint                new_offset_y,
                                              PikaInterpolationType interpolation,
                                              PikaProgress       *progress);
gboolean        pika_item_scale_by_factors   (PikaItem           *item,
                                              gdouble             w_factor,
                                              gdouble             h_factor,
                                              PikaInterpolationType interpolation,
                                              PikaProgress       *progress);
gboolean
      pika_item_scale_by_factors_with_origin (PikaItem           *item,
                                              gdouble             w_factor,
                                              gdouble             h_factor,
                                              gint                origin_x,
                                              gint                origin_y,
                                              gint                new_origin_x,
                                              gint                new_origin_y,
                                              PikaInterpolationType interpolation,
                                              PikaProgress       *progress);
void            pika_item_scale_by_origin    (PikaItem           *item,
                                              gint                new_width,
                                              gint                new_height,
                                              PikaInterpolationType interpolation,
                                              PikaProgress       *progress,
                                              gboolean            local_origin);
void            pika_item_resize             (PikaItem           *item,
                                              PikaContext        *context,
                                              PikaFillType        fill_type,
                                              gint                new_width,
                                              gint                new_height,
                                              gint                offset_x,
                                              gint                offset_y);
void            pika_item_resize_to_image    (PikaItem           *item);

void            pika_item_flip               (PikaItem           *item,
                                              PikaContext        *context,
                                              PikaOrientationType flip_type,
                                              gdouble             axis,
                                              gboolean            clip_result);
void            pika_item_rotate             (PikaItem           *item,
                                              PikaContext        *context,
                                              PikaRotationType    rotate_type,
                                              gdouble             center_x,
                                              gdouble             center_y,
                                              gboolean            clip_result);
void            pika_item_transform          (PikaItem           *item,
                                              PikaContext        *context,
                                              const PikaMatrix3  *matrix,
                                              PikaTransformDirection direction,
                                              PikaInterpolationType interpolation_type,
                                              PikaTransformResize clip_result,
                                              PikaProgress       *progress);
PikaTransformResize   pika_item_get_clip     (PikaItem           *item,
                                              PikaTransformResize clip_result);

gboolean        pika_item_fill               (PikaItem           *item,
                                              GList              *drawables,
                                              PikaFillOptions    *fill_options,
                                              gboolean            push_undo,
                                              PikaProgress       *progress,
                                              GError            **error);
gboolean        pika_item_stroke             (PikaItem           *item,
                                              GList              *drawables,
                                              PikaContext        *context,
                                              PikaStrokeOptions  *stroke_options,
                                              PikaPaintOptions   *paint_options,
                                              gboolean            push_undo,
                                              PikaProgress       *progress,
                                              GError            **error);

void            pika_item_to_selection       (PikaItem           *item,
                                              PikaChannelOps      op,
                                              gboolean            antialias,
                                              gboolean            feather,
                                              gdouble             feather_radius_x,
                                              gdouble             feather_radius_y);

void            pika_item_add_offset_node    (PikaItem           *item,
                                              GeglNode           *node);
void            pika_item_remove_offset_node (PikaItem           *item,
                                              GeglNode           *node);

gint            pika_item_get_id             (PikaItem           *item);
PikaItem      * pika_item_get_by_id          (Pika               *pika,
                                              gint                id);

PikaTattoo      pika_item_get_tattoo         (PikaItem           *item);
void            pika_item_set_tattoo         (PikaItem           *item,
                                              PikaTattoo          tattoo);

PikaImage     * pika_item_get_image          (PikaItem           *item);
void            pika_item_set_image          (PikaItem           *item,
                                              PikaImage          *image);

void            pika_item_replace_item       (PikaItem           *item,
                                              PikaItem           *replace);

void               pika_item_set_parasites   (PikaItem           *item,
                                              PikaParasiteList   *parasites);
PikaParasiteList * pika_item_get_parasites   (PikaItem           *item);

gboolean        pika_item_parasite_validate  (PikaItem           *item,
                                              const PikaParasite *parasite,
                                              GError            **error);
void            pika_item_parasite_attach    (PikaItem           *item,
                                              const PikaParasite *parasite,
                                              gboolean            push_undo);
void            pika_item_parasite_detach    (PikaItem           *item,
                                              const gchar        *name,
                                              gboolean            push_undo);
const PikaParasite * pika_item_parasite_find (PikaItem           *item,
                                              const gchar        *name);
gchar        ** pika_item_parasite_list      (PikaItem           *item);

gboolean        pika_item_set_visible        (PikaItem           *item,
                                              gboolean            visible,
                                              gboolean            push_undo);
gboolean        pika_item_get_visible        (PikaItem           *item);
gboolean        pika_item_is_visible         (PikaItem           *item);

void        pika_item_bind_visible_to_active (PikaItem           *item,
                                              gboolean            bind);

void            pika_item_set_color_tag      (PikaItem           *item,
                                              PikaColorTag        color_tag,
                                              gboolean            push_undo);
PikaColorTag    pika_item_get_color_tag      (PikaItem           *item);
PikaColorTag  pika_item_get_merged_color_tag (PikaItem           *item);

void            pika_item_set_lock_content   (PikaItem           *item,
                                              gboolean            lock_content,
                                              gboolean            push_undo);
gboolean        pika_item_get_lock_content   (PikaItem           *item);
gboolean        pika_item_can_lock_content   (PikaItem           *item);
gboolean        pika_item_is_content_locked  (PikaItem           *item,
                                              PikaItem          **locked_item);

void            pika_item_set_lock_position  (PikaItem          *item,
                                              gboolean           lock_position,
                                              gboolean           push_undo);
gboolean        pika_item_get_lock_position  (PikaItem          *item);
gboolean        pika_item_can_lock_position  (PikaItem          *item);
gboolean        pika_item_is_position_locked (PikaItem          *item,
                                              PikaItem         **locked_item);

void            pika_item_set_lock_visibility  (PikaItem        *item,
                                                gboolean         lock_visibility,
                                                gboolean         push_undo);
gboolean        pika_item_get_lock_visibility  (PikaItem        *item);
gboolean        pika_item_can_lock_visibility  (PikaItem        *item);
gboolean        pika_item_is_visibility_locked (PikaItem        *item,
                                                PikaItem       **locked_item);

gboolean        pika_item_mask_bounds        (PikaItem           *item,
                                              gint               *x1,
                                              gint               *y1,
                                              gint               *x2,
                                              gint               *y2);
gboolean        pika_item_mask_intersect     (PikaItem           *item,
                                              gint               *x,
                                              gint               *y,
                                              gint               *width,
                                              gint               *height);

gboolean        pika_item_is_in_set          (PikaItem           *item,
                                              PikaItemSet         set);


#endif /* __PIKA_ITEM_H__ */
