/*****************************************************************************
 * $CAMITK_LICENCE_BEGIN$
 *
 * CamiTK - Computer Assisted Medical Intervention ToolKit
 * (c) 2001-2025 Univ. Grenoble Alpes, CNRS, Grenoble INP - UGA, TIMC, 38000 Grenoble, France
 *
 * Visit http://camitk.imag.fr for more information
 *
 * This file is part of CamiTK.
 *
 * CamiTK is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * CamiTK 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 version 3 for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with CamiTK.  If not, see <http://www.gnu.org/licenses/>.
 *
 * $CAMITK_LICENCE_END$
 ****************************************************************************/

#ifndef INTERFACENODE_H
#define INTERFACENODE_H

#include "CamiTKAPI.h"

// -- QT stuff classes
class QPixmap;
class QMenu;
class QWidget;

namespace camitk {

/**
 * @ingroup group_sdk_libraries_core_component
 *
 * @brief
 * This class describe what are the methods to implement for a hierarchical tree node.
 *
 * An InterfaceNode can only have one parent, even if it is a child of more than
 * one InterfaceNodes.
 *
 * Consequence: an InterfaceNode can be present many times in the hierarchy, but
 * can only depends from one parent.
 * To add an InterfaceNode as a child and change its parent to this use addChild().
 * To add an InterfaceNode as a child without modifying its parent, use attachChild().
 *
 * This class defines an "interface" (in the OOP/java meaning of the term).
 * See the introduction of GoF: "Program to an interface, not an implementation."
 * To see what Erich Gamma has to say about it: http://www.artima.com/lejava/articles/designprinciplesP.html
 * To see what Bjarne Stroustrup has to say about it: http://www.artima.com/intv/modern.html
 *
 */
class InterfaceNode {
public:
    /// empty virtual destructor, to avoid memory leak
    virtual ~InterfaceNode() = default;

    /// get the name to be displayed
    virtual QString getName() const = 0;

    /// set the name to be displayed
    virtual void setName(const QString&) = 0;

    /// get the list of the InterfaceNode children (sub items in the hierarchy)
    virtual const ComponentList& getChildren() const = 0;

    /** add a child Component (sub item in the hierarchy), and modify the child's parent to be equal to this instance
     *
     *  This is to be used with care. The preferred method to add a child component is
     *  to use the Component's constructor with the parent parameter: Component(Component *, const QString &, Representation rep) .
     *
     *  @see attachChild()
     */
    virtual void addChild(InterfaceNode*) = 0;

    /** add a child Component (but leave its parent unchanged)
     *
     * There can be some refresh problem, see the note in addChild()
     */
    virtual void attachChild(InterfaceNode*) = 0;

    /// remove a sub Component (only the top-level component has the right to do that)
    virtual void removeChild(InterfaceNode*) = 0;

    /// delete all sub Component, but do not delete the pointer (only the top-level component has the right to do that)
    virtual void deleteChildren() = 0;

    /// get the parent Component
    virtual InterfaceNode* getParent() = 0;

    /// set the parent Component
    virtual void setParent(InterfaceNode*) = 0;

    /// should the name be displayed in italic?
    virtual bool inItalic() const = 0;

    /** this method is called each time the InterfaceNode is double clicked by
      * the user.
      * @return a boolean telling if there was modification made in the Component due to this double click
      */
    virtual bool doubleClicked() = 0;

    /** Get the pixmap that will be displayed for this node.
      * If you want your component to have a nice pixmap displayed in the explorer, for example, you just need to
      * 1. declare a new static member and redefines the getIcon() method (in MyComponent.h):
      * \code
      * public:
      *   virtual QPixmap getIcon();
      * private:
      *   static QPixmap * myPixmap; // declare a ptr here (it is static for optimization)
      * \endcode
      *
      * 2. add these lines in your code (in MyComponent.cpp):
      *
      * \code
      * // use this two lines or better use a Qt resource bundle (recommanded!)
      * #include "myComponent_pixmap.xpm" // include the pixmap resource file or use a Qt resource bundle
      * QPixmap * MyComponent::myPixmap = nullptr; // static initialization
      *
      * QPixmap MyComponent::getIcon() {
      *   // check if the class instance was already used somewhere
      *   if (!myPixmap) {
      *     // create the pixmap from the data like this (or using the Qt resource bundle, see Qt documentation)
      *     myPixmap = new QPixmap(myComponent_pixmap); // myComponent_pixmap is the name of the char[] found in the .xpm file
      *   }
      *   // return the object (not the pointer
      *   return (*myPixmap);
      * }
      * \endcode
      * And that all folks! A nice icon will be now used to display your component!
      *
      * \note Recommanded pixmap size is 20x20 (not nice, but efficient)...
      */
    virtual QPixmap getIcon() = 0;

    /// get the popup menu to display (or nullptr if inexistant)
    virtual QMenu* getPopupMenu(QWidget* parent = nullptr) = 0;

    /// Set up the node modification flag. This means that the name(s) or children hierarchy were modified
    /// This can be useful information when a viewer, such as the Explorer viewer, needs to know what to refresh
    virtual void setNodeModified(bool) = 0;

    /// Get the current modification flag
    virtual bool getNodeModified() const = 0;
};


}

#endif
