/*
 *                            COPYRIGHT
 *
 *  cschem - modular/flexible schematics editor - libcschem (core library)
 *  Copyright (C) 2024 Tibor 'Igor2' Palinkas
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 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
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 31 Milk Street, # 960789 Boston, MA 02196 USA
 *
 *  Contact:
 *    Project page: http://repo.hu/projects/sch-rnd
 *    contact lead developer: http://www.repo.hu/projects/sch-rnd/contact.html
 *    mailing list: http://www.repo.hu/projects/sch-rnd/contact.html
 */

#include <libcschem/concrete.h>

struct csch_extobj_impl_s {
	const char *name;   /* also the hash key */

	void (*attr_edit_pre)(csch_cgrp_t *grp, const char *key);     /* called before an attribute change */
	void (*attr_edit_post)(csch_cgrp_t *grp, const char *key);    /* called after an attribute change */
	void (*floater_edit_post)(csch_cgrp_t *grp, csch_chdr_t *flt);/* called after a floater has been edited (optional) */
	void (*update)(csch_cgrp_t *grp);       /* recompute graphics */
	void (*gui_edit_dlg)(csch_cgrp_t *grp); /* present the object-specific editor dialog */
	void (*conv_from)(vtp0_t *objs);        /* remove one or more objects from objs and convert them into extended object(s) */
};

extern htsp_t extobjs_impls;

void csch_extobj_impl_reg(const csch_extobj_impl_t *impl);
void csch_extobj_impl_unreg(const csch_extobj_impl_t *impl);


/* Force re-reder the object (if it is an ext-object); safe to call on any cgrp */
RND_INLINE void csch_extobj_update(csch_cgrp_t *grp);

/* let extobj decide if an update is needed (and do the update); safe to call
   on any cgrp */
RND_INLINE void csch_extrobj_attr_edit_pre(csch_cgrp_t *grp, const char *key);
RND_INLINE void csch_extrobj_attr_edit_post(csch_cgrp_t *grp, const char *key);

/* Invoke the extobj-specific GUI dialog for editing object properties, if
   present. Returns 0 on success (dialog invoked). */
RND_INLINE int csch_extobj_gui_edit_dlg(csch_cgrp_t *grp);


/* Convert objects to extended object of type eo. All objects in objs shall
   be on the same sheet. Object converted are removed from objs. */
void csch_extobj_conv_from(vtp0_t *objs, const csch_extobj_impl_t *eo);

/*** for implementing extended objects ***/

/* return the extobj-gfx group within grp or NULL if not found */
csch_cgrp_t *csch_extobj_gfx_lookup(csch_cgrp_t *grp);

/* return the extobj-gfx group within grp after making sure it is empty
   (creating or clearing it) */
csch_cgrp_t *csch_extobj_gfx_clear(csch_sheet_t *sheet, csch_cgrp_t *grp);


/*** internal, do not call ***/
void csch_extobj_init(void);
void csch_extobj_uninit(void);
const csch_extobj_impl_t *csch_extobj_lookup(const char *name);

/*** implementation ***/
RND_INLINE void csch_extobj_update(csch_cgrp_t *grp)
{
	if ((grp->extobj_inhibit == 0) && (grp->extobj != NULL) && (grp->extobj->update != NULL))
		grp->extobj->update(grp);
}

RND_INLINE void csch_extrobj_attr_edit_pre(csch_cgrp_t *grp, const char *key)
{
	if ((grp->extobj_inhibit == 0) && (grp->extobj != NULL) && (grp->extobj->attr_edit_pre != NULL))
		grp->extobj->attr_edit_pre(grp, key);
}

RND_INLINE void csch_extrobj_attr_edit_post(csch_cgrp_t *grp, const char *key)
{
	if ((grp->extobj_inhibit == 0) && (grp->extobj != NULL) && (grp->extobj->attr_edit_post != NULL))
		grp->extobj->attr_edit_post(grp, key);
}

RND_INLINE void csch_extrobj_floater_edit_post(csch_cgrp_t *grp, csch_chdr_t *flt)
{
	if ((grp->extobj_inhibit == 0) && (grp->extobj != NULL) && (grp->extobj->floater_edit_post != NULL))
		grp->extobj->floater_edit_post(grp, flt);
}

RND_INLINE int csch_extobj_gui_edit_dlg(csch_cgrp_t *grp)
{
	if ((grp->extobj_inhibit == 0) && (grp->extobj != NULL) && (grp->extobj->gui_edit_dlg != NULL)) {
		grp->extobj->gui_edit_dlg(grp);
		return 0;
	}

	return 1;
}

