Voilà j'ai codé ça cet après-midi donc je partage.

C'est un nouveau GUIElement qui se presente sous forme de boite avec une barre de titre et qui a la particularité de pouvoir se rétracter et prendre une forme compacte (seule la barre de titre reste visible). Elle possède aussi le nécessaire pour chainer plusieurs boites les une aux autres afin que lorsque qu'une boite se rétracte elle tire la boite qui lui est associée qui elle-même tire la boite qui lui est associée...
Pour les avantages, inconvénients et l'utilisation, j'ai mis ce qu'il faut dans le .h. Si quelqu'un a des idées pour améliorer, ou si quelqu'un l'améliore de son côté qu'il poste ça, on pourrait avoir quelque chose de sympa.

Voici des screenshots :




GUI_BoxRetractable.hGUI_BoxRetractable.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#ifndef GUI_BOXRETRACTABLE_H_INCLUDED
#define GUI_BOXRETRACTABLE_H_INCLUDED

#include "IGUIElement.h"
#include "IGUICheckBox.h"
#include "IGUIImage.h"
#include "IGUIStaticText.h"
#include "ITexture.h"

using namespace irr;
using namespace gui;
using namespace core;
using namespace video;

/**
Avantages :

    - Ces boxs peuvent être une alternative au scrollbars.
    - Il est possible de les chainées, ainsi une box rétractée attire les box suivantes vers elle.
    - Il est possible d'insérer les boxs à taille fixe (dans la chaine ou séparement).

Inconvénients :

    - La taille ne doit pas être changé après la création.

Utilisation :

    #include "GUI_BoxRetractable.h"
    /// création
    BoxRetractable* BoxEssai = new BoxRetractable(recti(10,10,290,110), L"Box retractable", mGUI, "../include/GUI_BoxRetractable/", element_parent);
    BoxRetractable* BoxEssaiSuivant = new BoxRetractable(recti(10,115,290,265), L"Box retractable Suivante", mGUI, "../include/GUI_BoxRetractable/", element_parent);
    /// insertion d'une box fixe
    BoxRetractable* BoxEssaiTailleFixe = new BoxRetractable(recti(10,270,290,320), L"Box non retractable", mGUI, "../include/GUI_BoxRetractable/", element_parent, NULL, false);
    BoxRetractable* BoxEssaiSuivant2 = new BoxRetractable(recti(10,325,290,525), L"Box retractable Suivante2", mGUI, "../include/GUI_BoxRetractable/", element_parent);
    /// liaison des boxs (chainage)
    BoxEssai->setSuivant(BoxEssaiSuivant);
    BoxEssaiSuivant->setSuivant(BoxEssaiTailleFixe);
    BoxEssaiTailleFixe->setSuivant(BoxEssaiSuivant2);

    /// destruction
    BoxEssai->remove();
    BoxEssaiSuivant->remove();
    BoxEssaiTailleFixe->remove();
    BoxEssaiSuivant2->remove();


**/


class BoxRetractable : public IGUIElement
{
    public :
        BoxRetractable(rect<s32> rectangle, stringw titre, IGUIEnvironment* environment, stringw pathImage="../include/GUI_BoxRetractable/", IGUIElement* parent=0, BoxRetractable* suivant=NULL, bool retractable=true, s32 id=-1);
        ~BoxRetractable();

        bool OnEvent(const SEvent& event);
        void moveRequest(s32 decalageY);

        void setSuivant(BoxRetractable* suivant);

    protected :
        IGUIEnvironment* mGUI;
        ///
        BoxRetractable* Suivant; // pointeur vers la BoxRetractable suivante
        void setExtend(bool extend);
        void moveSuivant(s32 decalage);
        s32 mDecalage;
        ///
        bool mRetractable;
        recti mExtendSize;
        recti mRetractSize;
        position2di ExtendSize, RetractSize;
        IGUICheckBox* CBExtend; IGUIStaticText* STExtend;
        IGUIImage* ICaption;
        IGUIImage *IDroite, *IGauche, *IBasse;

    private :
        static int compteurInstance;
        static ITexture *TCaption;
        static ITexture *TBordure;

};

#endif // GUI_BOXRETRACTABLE_H_INCLUDED
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
#include "GUI_BoxRetractable.h"

#include "IGUIEnvironment.h"
#include "IVideoDriver.h"
#include "IGUISkin.h"

/// initilisation des membres statiques
int BoxRetractable::compteurInstance=0;
ITexture* BoxRetractable::TCaption=NULL;
ITexture* BoxRetractable::TBordure=NULL;

/**
rectangle : position et taille maximale de l'objet
title : texte affiché dans la barre de titre de la box
suivant : permet de faire une chaine de boxretractable, lorsque qu'une boite est rétractée les boites en dessous sont relevées
retractable : si dans une chaine une boite doit ne pas être rétractable
**/

BoxRetractable::BoxRetractable(rect<s32> rectangle, stringw title, IGUIEnvironment* gui, stringw pathImage, IGUIElement* parent, BoxRetractable* suivant, bool retractable, s32 id)
: IGUIElement(EGUIET_ELEMENT, gui, (parent!=0)?parent:gui->getRootGUIElement(), id, rectangle), mGUI(gui), Suivant(suivant), mRetractable(retractable)
{
    #ifdef _DEBUG
    setDebugName("../include/GUI_BoxRetractable/");
    #endif

    /// si c'est la première instance on charge les textures
    if(compteurInstance < 1)
    {
        TCaption = mGUI->getVideoDriver()->getTexture(pathImage+"BoxRetractable");
        TBordure = mGUI->getVideoDriver()->getTexture(pathImage+"BoxRetractable_caption.jpg");
    }
    /// incrémente le compteur d'instance
    compteurInstance++;
    #ifdef _DEBUG
    printf("BoxRetractable_bord.jpg", compteurInstance);
    #endif
    /// récupère le skin
    IGUISkin* skin = mGUI->getSkin();
    /// les tailles etendue et rétractée
    mExtendSize = rectangle;
    mRetractSize = mExtendSize;
    mRetractSize.LowerRightCorner.Y = rectangle.UpperLeftCorner.Y + skin->getSize(EGDS_CHECK_BOX_WIDTH) + 2;
    /// dimension relatives
    ExtendSize = position2di(rectangle.LowerRightCorner.X-rectangle.UpperLeftCorner.X,rectangle.LowerRightCorner.Y-rectangle.UpperLeftCorner.Y);
    RetractSize = position2di(ExtendSize.X,skin->getSize(EGDS_CHECK_BOX_WIDTH) + 2);
    /// image de fond du titre
    recti CaptionSize(position2di(0,0),RetractSize);
    ICaption = mGUI->addImage(CaptionSize, this);
    ICaption->setImage(TCaption);
    ICaption->setScaleImage(true);
    /// choix entre retractable ou non
    if(retractable)
    {
        STExtend = NULL;
        /// bouton "extend" pour le pliage et le dépliage et titre de l'élément
        CBExtend = mGUI->addCheckBox(true, recti(position2di(1,1), CaptionSize.LowerRightCorner), this, -1, title.c_str());
    }
    else
    {
        CBExtend = NULL;
        /// affiche le titre mais pas la box
        STExtend = mGUI->addStaticText(title.c_str(), recti(position2di(skin->getSize(EGDS_CHECK_BOX_WIDTH)+6, 1), CaptionSize.LowerRightCorner), false, false, this);
        STExtend->setTextAlignment(EGUIA_UPPERLEFT, EGUIA_CENTER);
    }
    /// cadre entourant la box
    // bordure gauche
    recti bordure_gauche(0,CaptionSize.LowerRightCorner.Y,1,ExtendSize.Y);
    IGauche = mGUI->addImage(bordure_gauche, this);
    IGauche->setImage(TBordure);
    IGauche->setScaleImage(true);
    // bordure droite
    recti bordure_droite(ExtendSize.X-1,CaptionSize.LowerRightCorner.Y,ExtendSize.X,ExtendSize.Y);
    IDroite = mGUI->addImage(bordure_droite, this);
    IDroite->setImage(TBordure);
    IDroite->setScaleImage(true);
    // bordure basse
    recti bordure_basse(0,ExtendSize.Y-1,ExtendSize.X,ExtendSize.Y);
    IBasse = mGUI->addImage(bordure_basse, this);
    IBasse->setImage(TBordure);
    IBasse->setScaleImage(true);
    /// calcule le décalage
    mDecalage = mExtendSize.LowerRightCorner.Y - mRetractSize.LowerRightCorner.Y;
}

BoxRetractable::~BoxRetractable()
{
    /// décrémente le compteur d'instance
    compteurInstance--;
    #ifdef _DEBUG
    printf("Nb d'instances : %i\n", compteurInstance);
    #endif
    /// libération des ressources
    if(STExtend)    STExtend->remove();
    if(ICaption)    ICaption->remove();
    if(IGauche)     IGauche->remove();
    if(IDroite)     IDroite->remove();
    if(IBasse)      IBasse->remove();
    if(compteurInstance < 1)
    {
        if(TCaption)  { mGUI->getVideoDriver()->removeTexture(TCaption); TCaption = NULL; }
        if(TBordure) { mGUI->getVideoDriver()->removeTexture(TBordure); TBordure = NULL; }
    }
}

bool BoxRetractable::OnEvent(const SEvent& event)
{
    /// événements de la gui
    if (event.EventType == EET_GUI_EVENT)
    {
        if (event.GUIEvent.EventType == EGET_CHECKBOX_CHANGED)
        {
            if(mRetractable)
            {
                if(event.GUIEvent.Caller == CBExtend)
                {
                    if(CBExtend->isChecked())
                    {
                        setExtend(true);
                        moveSuivant(mDecalage);
                    }
                    else
                    {
                        setExtend(false);
                        moveSuivant(-mDecalage);
                    }
                }
            }
        }
    }
    /// si aucun événement n'a été traité par BoxRetractable
    return  IGUIElement::OnEvent(event);
}

void BoxRetractable::setSuivant(BoxRetractable* suivant)
{
    Suivant = suivant;
}

void BoxRetractable::setExtend(bool extend)
{
    /// récupère la position
    recti newPos = getRelativePosition();
    /// modifie la taille de l'élément
    if(extend) newPos.LowerRightCorner = newPos.UpperLeftCorner + ExtendSize;
    else newPos.LowerRightCorner = newPos.UpperLeftCorner + RetractSize;
    /// applique la nouvelle taille
    setRelativePosition(newPos);
}

void BoxRetractable::moveSuivant(s32 decalage)
{
    if(Suivant != NULL) Suivant->moveRequest(decalage);
}

void BoxRetractable::moveRequest(s32 decalage)
{
    move(position2di(0,decalage));
    moveSuivant(decalage);
}


Les 2 fichiers images qui servent de shin à la box : (ces fichiers sont nécessaires et il faut donner le chemin d'accès à la création de la box)
Pour les enregistrer "clic droit" sur le lien, "enregistrer la cible sous" car les fichiers sont tout petits.
BoxRetractable_bord.jpg
BoxRetractable_caption.jpg

Voilà!

Màj 1 : chargement unique des textures et destruction automatique grace à un compteur d'instance.

Prochaines fonctionnalités à implémenter :
- ajout et chainage avec des positions relatives entre les maillons; FAIT dans la v2