#0 

04-07-2012 21:07:16

johnplayer
Habitué
Date d'inscription: 30-09-2007
Messages: 431

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

Dernière modification par johnplayer (05-07-2012 13:44:48)


core i7 4970K @ 4GHz - 32GB ddr3 19200(2400MHz) - ssd samsung 840 evo 250GB - GTX1080Ti (4K) - Cooler master storm stryker blanc.
"L'alcool, c'est comme Activia, c'est actif à l'intérieur et ça se voit à l'extérieur."

Hors ligne


#1 

05-07-2012 13:44:13

johnplayer
Habitué
Date d'inscription: 30-09-2007
Messages: 431

Voilà la v2, elle permet un chaînage contrôlé et mais plus de fonctions à disposition.
On créé une box , cette box sera la box maîtresse. Puis on peut ajouter des box enfants, en insérer, en retirer, cacher une partie ou la totalité de la chaîne... Pour détruire la chaîne, il suffit de faire un remove() sur la box maîtresse.

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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#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 d'une chaîne de box
    BoxEssai = new BoxRetractable(recti(10,10,290,110), L"Box retractable 1", mGUI, "../MEDIAS/Systeme/GUI/", mTab1);
    BoxRetractable *BoxSuivante1 = BoxEssai->addBoxSuivante(50, L"Box retractable 2", 10, true);
    BoxRetractable *BoxSuivante2 = BoxSuivante1->addBoxSuivante(100, L"Box taille fixe 1", 10, false);
    BoxRetractable *BoxSuivante3 = BoxSuivante2->addBoxSuivante(200, L"Box retractable 3", 10, true);

    /// insertion d'une box au millieu de la chaîne (note : on pourrait aussi utiliser BoxSuivante2->addBoxSuivante(...); )
    BoxRetractable *BoxSuivante2bis = BoxSuivante2->insertBox(40, L"Box retractable 2 bis", 20, true);

    /// destruction : ne detruire que la première box d'une chaîne
    BoxEssai->remove();
**/


class BoxRetractable : public IGUIElement
{
    public :
        BoxRetractable(rect<s32> rectangle, stringw titre, IGUIEnvironment* environment, stringw pathImage, IGUIElement* parent=0, bool retractable=true, s32 id=-1);
        ~BoxRetractable();
        bool OnEvent(const SEvent& event);

        //! ajoute une box "enfant" (chaînage)
        //! A noter que s'il existe déjà une box "enfant", la nouvelle box sera insérée avant "l'enfant" déjà présent.
        BoxRetractable* addBoxSuivante(u32 hauteurBox, stringw titre, u32 espace=5, bool retractable=true);
        //! renvoie le pointeur sur la box "enfant"
        BoxRetractable* getBoxSuivante();
        //! retire la box suivante de la chaîne sans la brisée
        void deleteSuivant();
        //! retire toutes les boxs suivantes de la chaîne
        void deleteAllSuivant();
        //! insère une box dans la chaîne, elle sera "l'enfant" de la box qui sert à l'insertion
        BoxRetractable* insertBox(u32 hauteurBox, stringw titre, u32 espace=5, bool retractable=true);
        //! renvoie true si la boite est dépliée et false si la boite est en mode compact
        bool isExtend();
        //! se détache de son parent et se détruit
        void remove();
        //! affiche ou cache la chaîne
        void setVisible(bool visible);

    protected :
        //! bascule l'élément en mode compact ou complet suivant la demande
        void setExtend(bool extend);
        //! decale "l'enfant" de cette box suivant Y
        void moveSuivant(s32 decalage);
        //! decale cette box suivant Y (qui elle, décale son "enfant")
        void moveRequest(s32 decalage);

        /// MEMBRES ///
        IGUIEnvironment* mGUI;
        /// Suivant
        BoxRetractable* Suivant; // pointeur vers la BoxRetractable suivante
        s32 mDecalage;
        s32 mTrou;
        /// Instances
        bool mExtend;
        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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
#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, bool retractable, s32 id)
: IGUIElement(EGUIET_ELEMENT, gui, (parent!=0)?parent:gui->getRootGUIElement(), id, rectangle), mGUI(gui), Suivant(NULL), mTrou(0), mExtend(true), mRetractable(retractable)
{
    #ifdef _DEBUG
    setDebugName("BoxRetractable");
    #endif

    /// si c'est la première instance on charge les textures
    if(compteurInstance < 1)
    {
        TCaption = mGUI->getVideoDriver()->getTexture(pathImage+"BoxRetractable_caption.jpg");
        TBordure = mGUI->getVideoDriver()->getTexture(pathImage+"BoxRetractable_bord.jpg");
    }
    /// incrémente le compteur d'instance
    compteurInstance++;
    #ifdef _DEBUG
    printf("Nb d'instances : %i\n", 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();
    /// retire les textures si on en a plus besoin
    if(compteurInstance < 1)
    {
        if(TCaption)  { mGUI->getVideoDriver()->removeTexture(TCaption); TCaption = NULL; }
        if(TBordure) { mGUI->getVideoDriver()->removeTexture(TBordure); TBordure = NULL; }
    }
    /// détruit son enfant (qui lui-même va détruire le sien...)
    if(Suivant) Suivant->remove();
}

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);
                    else setExtend(false);
                }
            }
        }
    }
    /// si aucun événement n'a été traité par BoxRetractable
    return  IGUIElement::OnEvent(event);
}

BoxRetractable* BoxRetractable::addBoxSuivante(u32 hauteurBox, stringw titre, u32 espace, bool retractable)
{
    /// s'il y a déjà une box suivante on l'insert dans la chaîne
    if(Suivant != NULL) return insertBox(hauteurBox, titre, espace, retractable);
    /// détermine le rectangle occupé par la box
    recti base = getRelativePosition();
    recti rectangle(position2di(base.UpperLeftCorner.X,base.LowerRightCorner.Y+espace),position2di(base.LowerRightCorner.X,base.LowerRightCorner.Y+espace+hauteurBox));
    /// créé la box suivante
    Suivant = new BoxRetractable(rectangle, titre.c_str(), mGUI, "", Parent, retractable);
    /// calcul la taille du trou
    Suivant->mTrou = hauteurBox + espace;
    /// retourne la box créée
    return Suivant;
}

BoxRetractable* BoxRetractable::getBoxSuivante()
{
    return Suivant;
}

void BoxRetractable::deleteSuivant()
{
    if(Suivant != NULL)
    {
        /// enregistre le "Suivant" de la box à détruire
        BoxRetractable *tmp = Suivant->getBoxSuivante();
        /// on récupère la taille du trou que va créer l'enlèvement de la box
        s32 tailletrou = Suivant->mTrou;
        /// delete la box
        Suivant->remove();
        /// attache le "Suivant" de la box à détruire à elle-même
        Suivant = tmp;
        /// on décale le nouveau "Suivant"
        if(Suivant != NULL) moveSuivant(-tailletrou);
    }
}

void BoxRetractable::deleteAllSuivant()
{
    /// s'il y a encore un suivant, on le détruit
    if(Suivant != NULL)
    {
        Suivant->deleteAllSuivant();
        Suivant->remove();
    }
}

BoxRetractable* BoxRetractable::insertBox(u32 hauteurBox, stringw titre, u32 espace, bool retractable)
{
    /// on sauvegarde le suivant actuel
    BoxRetractable* tmp = Suivant;
    Suivant = NULL;
    /// on créé la nouvelle box
    Suivant = addBoxSuivante(hauteurBox, titre, espace, retractable);
    /// s'il y a des suivants
    if(tmp != NULL)
    {
        /// on y accroche la chaîne
        Suivant->Suivant = tmp;
        /// on décale toute les autres box de la chaîne
        tmp->moveRequest(Suivant->mTrou);
    }
    /// on renvoie un pointeur sur la nouvelle box
    return Suivant;
}

bool BoxRetractable::isExtend()
{
    return mExtend;
}

void BoxRetractable::remove()
{
    if(Parent) Parent->removeChild(this);
    delete this;
}

void BoxRetractable::setVisible(bool visible)
{
    setVisible(visible);
    Suivant->setVisible(visible);
}

void BoxRetractable::setExtend(bool extend)
{
    if(mExtend == !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);
        /// décale son enfant
        if(extend) moveSuivant(mDecalage);
        else moveSuivant(-mDecalage);
        /// change l'état extend de la box
        mExtend = extend;
    }
}

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

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

core i7 4970K @ 4GHz - 32GB ddr3 19200(2400MHz) - ssd samsung 840 evo 250GB - GTX1080Ti (4K) - Cooler master storm stryker blanc.
"L'alcool, c'est comme Activia, c'est actif à l'intérieur et ça se voit à l'extérieur."

Hors ligne


#2 

05-07-2012 20:05:13

johnplayer
Habitué
Date d'inscription: 30-09-2007
Messages: 431

Une nouvelle fonctionnalité! Il me manquait les bouton radio donc je me suis dit que je pouvais utilisé mes BoxRetractables comme GroupBox.
Le principe est simple :
- on créé une BoxRetractable;
- on créé le BoutonRadioControl;
- on ajoute des checkBox qui serviront de bouton radio.

Il y a 2 fonctionnements possible : normal ou atypique.
Normal :
     Seul un bouton est actif. L'activation d'un autre bouton désactive tous les autres.
     Il y a TOUJOURS un bouton actif.
Atypique :
    Seul un bouton peut être actif. L'activation d'un autre bouton désactive tous les autres.
    On peut désactivé TOUS les boutons.

Comme d'habitude, toutes les explications sont données dans les *.h avant la déclaration de la classe.
Je ne remets pas les images, elles sont dans le premier post.

GUI_BoxRetractable.hGUI_BoxRetractable.cppGUI_BoutonRadioControl.h
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
#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;

class BoutonRadioControl;

/**
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 d'une chaîne de box
    BoxEssai = new BoxRetractable(recti(10,10,290,110), L"Box retractable 1", mGUI, "../MEDIAS/Systeme/GUI/", mTab1);
    BoxRetractable *BoxSuivante1 = BoxEssai->addBoxSuivante(50, L"Box retractable 2", 10, true);
    BoxRetractable *BoxSuivante2 = BoxSuivante1->addBoxSuivante(100, L"Box taille fixe 1", 10, false);
    BoxRetractable *BoxSuivante3 = BoxSuivante2->addBoxSuivante(200, L"Box retractable 3", 10, true);

    /// insertion d'une box au millieu de la chaîne (note : on pourrait aussi utiliser BoxSuivante2->addBoxSuivante(...); )
    BoxRetractable *BoxSuivante2bis = BoxSuivante2->insertBox(40, L"Box retractable 2 bis", 20, true);

    /// destruction : ne detruire que la première box d'une chaîne
    BoxEssai->remove();

    /// création du BoutonRadioControl (1 exemplaire par BoxRetractable)
    BoxSuivante2->createBoutonRadioControl(false);
    /// ajout de checkbox à la BoxRetractable (et au BoutonRadioControl)
    BoxSuivante2->addCheckBoxToBoutonRadioControl(recti(5,25,25,45));
    BoxSuivante2->addCheckBoxToBoutonRadioControl(recti(30,25,50,45));
    BoxSuivante2->addCheckBoxToBoutonRadioControl(recti(55,25,75,45));
    BoxSuivante2->addCheckBoxToBoutonRadioControl(recti(80,25,100,45));

**/


class BoxRetractable : public IGUIElement
{
    public :
        BoxRetractable(rect<s32> rectangle, stringw titre, IGUIEnvironment* environment, stringw pathImage, IGUIElement* parent=0, bool retractable=true, s32 id=-1);
        ~BoxRetractable();
        bool OnEvent(const SEvent& event);

        //! ajoute une box "enfant" (chaînage)
        //! A noter que s'il existe déjà une box "enfant", la nouvelle box sera insérée avant "l'enfant" déjà présent.
        BoxRetractable* addBoxSuivante(u32 hauteurBox, stringw titre, u32 espace=5, bool retractable=true);
        //! renvoie le pointeur sur la box "enfant"
        BoxRetractable* getBoxSuivante();
        //! retire la box suivante de la chaîne sans la brisée
        void deleteSuivant();
        //! retire toutes les boxs suivantes de la chaîne
        void deleteAllSuivant();
        //! insère une box dans la chaîne, elle sera "l'enfant" de la box qui sert à l'insertion
        BoxRetractable* insertBox(u32 hauteurBox, stringw titre, u32 espace=5, bool retractable=true);
        //! renvoie true si la boite est dépliée et false si la boite est en mode compact
        bool isExtend();
        //! se détache de son parent et se détruit
        void remove();
        //! affiche ou cache la chaîne
        void setVisible(bool visible);
        //! créé un BoutonRadioControl associée à la BoxRetractable
        void createBoutonRadioControl(bool atypique=false);
        //! ajoute une checkbox à la BoxRetractable, l'assigne au BoutonRadioControl et renvoie un pointeur
        //! index renvoie la position de la nouvelle checkbox dans la liste
        s32 addCheckBoxToBoutonRadioControl(recti rectangle, IGUICheckBox* checkbox=NULL, const wchar_t *text=0);
        //! renvoie un pointeur sur la CheckBox active
        IGUICheckBox* getCheckBoxActive();
        //! renvoie la position dans la liste de la CheckBox active
        s32 getCheckBoxActiveIndex();

    protected :
        //! bascule l'élément en mode compact ou complet suivant la demande
        void setExtend(bool extend);
        //! decale "l'enfant" de cette box suivant Y
        void moveSuivant(s32 decalage);
        //! decale cette box suivant Y (qui elle, décale son "enfant")
        void moveRequest(s32 decalage);

        /// MEMBRES ///
        IGUIEnvironment* mGUI;
        /// Suivant
        BoxRetractable* Suivant; // pointeur vers la BoxRetractable suivante
        s32 mDecalage;
        s32 mTrou;
        /// Instances
        bool mExtend;
        bool mRetractable;
        recti mExtendSize;
        recti mRetractSize;
        position2di ExtendSize, RetractSize;
        IGUICheckBox* CBExtend; IGUIStaticText* STExtend;
        IGUIImage* ICaption;
        IGUIImage *IDroite, *IGauche, *IBasse;
        /// utilisation GroupBox
        BoutonRadioControl *GroupBox;

    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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
#include "GUI_BoxRetractable.h"

#include "GUI_BoutonRadioControl.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, bool retractable, s32 id)
: IGUIElement(EGUIET_ELEMENT, gui, (parent!=0)?parent:gui->getRootGUIElement(), id, rectangle), mGUI(gui), Suivant(NULL), mTrou(0), mExtend(true), mRetractable(retractable), GroupBox(NULL)
{
    #ifdef _DEBUG
    setDebugName("BoxRetractable");
    #endif

    /// si c'est la première instance on charge les textures
    if(compteurInstance < 1)
    {
        TCaption = mGUI->getVideoDriver()->getTexture(pathImage+"BoxRetractable_caption.jpg");
        TBordure = mGUI->getVideoDriver()->getTexture(pathImage+"BoxRetractable_bord.jpg");
    }
    /// incrémente le compteur d'instance
    compteurInstance++;
    #ifdef _DEBUG
    printf("Nb d'instances : %i\n", 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(GroupBox) { GroupBox->removeAllBox(); GroupBox->remove(); }
    /// retire les textures si on en a plus besoin
    if(compteurInstance < 1)
    {
        if(TCaption)  { mGUI->getVideoDriver()->removeTexture(TCaption); TCaption = NULL; }
        if(TBordure) { mGUI->getVideoDriver()->removeTexture(TBordure); TBordure = NULL; }
    }
    /// détruit son enfant (qui lui-même va détruire le sien...)
    if(Suivant) Suivant->remove();
}

bool BoxRetractable::OnEvent(const SEvent& event)
{
    if (isEnabled())
    {
        /// é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);
                        else setExtend(false);
                        return true;
                    }
                }
            }
        }
        if(mExtend)
        {
            if(GroupBox != NULL)
                if(GroupBox->OnEvent(event))
                    return true;
        }
    }
    /// si aucun événement n'a été traité par BoxRetractable
     return IGUIElement::OnEvent(event);
}

BoxRetractable* BoxRetractable::addBoxSuivante(u32 hauteurBox, stringw titre, u32 espace, bool retractable)
{
    /// s'il y a déjà une box suivante on l'insert dans la chaîne
    if(Suivant != NULL) return insertBox(hauteurBox, titre, espace, retractable);
    /// détermine le rectangle occupé par la box
    recti base = getRelativePosition();
    recti rectangle(position2di(base.UpperLeftCorner.X,base.LowerRightCorner.Y+espace),position2di(base.LowerRightCorner.X,base.LowerRightCorner.Y+espace+hauteurBox));
    /// créé la box suivante
    Suivant = new BoxRetractable(rectangle, titre.c_str(), mGUI, "", Parent, retractable);
    /// calcul la taille du trou
    Suivant->mTrou = hauteurBox + espace;
    /// retourne la box créée
    return Suivant;
}

BoxRetractable* BoxRetractable::getBoxSuivante()
{
    return Suivant;
}

void BoxRetractable::deleteSuivant()
{
    if(Suivant != NULL)
    {
        /// enregistre le "Suivant" de la box à détruire
        BoxRetractable *tmp = Suivant->getBoxSuivante();
        /// on récupère la taille du trou que va créer l'enlèvement de la box
        s32 tailletrou = Suivant->mTrou;
        /// delete la box
        Suivant->remove();
        /// attache le "Suivant" de la box à détruire à elle-même
        Suivant = tmp;
        /// on décale le nouveau "Suivant"
        if(Suivant != NULL) moveSuivant(-tailletrou);
    }
}

void BoxRetractable::deleteAllSuivant()
{
    /// s'il y a encore un suivant, on le détruit
    if(Suivant != NULL)
    {
        Suivant->deleteAllSuivant();
        Suivant->remove();
    }
}

BoxRetractable* BoxRetractable::insertBox(u32 hauteurBox, stringw titre, u32 espace, bool retractable)
{
    /// on sauvegarde le suivant actuel
    BoxRetractable* tmp = Suivant;
    Suivant = NULL;
    /// on créé la nouvelle box
    Suivant = addBoxSuivante(hauteurBox, titre, espace, retractable);
    /// s'il y a des suivants
    if(tmp != NULL)
    {
        /// on y accroche la chaîne
        Suivant->Suivant = tmp;
        /// on décale toute les autres box de la chaîne
        tmp->moveRequest(Suivant->mTrou);
    }
    /// on renvoie un pointeur sur la nouvelle box
    return Suivant;
}

bool BoxRetractable::isExtend()
{
    return mExtend;
}

void BoxRetractable::remove()
{
    if(Parent) Parent->removeChild(this);
    delete this;
}

void BoxRetractable::setVisible(bool visible)
{
    setVisible(visible);
    Suivant->setVisible(visible);
}

void BoxRetractable::createBoutonRadioControl(bool atypique)
{
    if(GroupBox == NULL)
        GroupBox = new BoutonRadioControl(atypique);
}

s32 BoxRetractable::addCheckBoxToBoutonRadioControl(recti rectangle, IGUICheckBox* checkbox, const wchar_t *text)
{
    IGUICheckBox *tmp = mGUI->addCheckBox(false, rectangle, this, -1, text);
    checkbox = tmp;
    return GroupBox->addCheckBox(tmp);
}

IGUICheckBox* BoxRetractable::getCheckBoxActive()
{
    return GroupBox->getCheckedBox();
}

s32 BoxRetractable::getCheckBoxActiveIndex()
{
    return GroupBox->getChecked();
}

void BoxRetractable::setExtend(bool extend)
{
    if(mExtend == !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);
        /// décale son enfant
        if(extend) moveSuivant(mDecalage);
        else moveSuivant(-mDecalage);
        /// change l'état extend de la box
        mExtend = extend;
    }
}

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

void BoxRetractable::moveRequest(s32 decalage)
{
    move(position2di(0,decalage));
    moveSuivant(decalage);
}
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
158
159
160
161
162
163
164
165
166
167
168
169
170
#ifndef GUI_BOUTONRADIOCONTROL_H_INCLUDED
#define GUI_BOUTONRADIOCONTROL_H_INCLUDED

#include "IGUICheckBox.h"

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


/**
Cette classe permet de servir des checkBox comme des boutons radio.

Seul un bouton peut être actif.L'activation d'un autre bouton désactive tous les autres.

Elle n'affiche rien elle gère juste les events des checkbox qui lui sont associées.

Si mAtypique=true, BoutonRadioControl autorise la désactivation de toutes les checkboxs.
**/


class BoutonRadioControl
{
    public:

        BoutonRadioControl(bool atypique=false)
        :  mAtypique(atypique)
        {
            /// initilisation des membres
            mActive = 0;
        }

        ~BoutonRadioControl()
        {
            mListe.clear();
        }

        //! détruit le BoutonRadioControl
        void remove()
        {
            delete this;
        }

        //! détruit toutes les checkBox
        void removeAllBox()
        {
            for(u32 a=0; a < mListe.size(); a++)
                mListe[a]->remove();
        }

        //! ajoute une checkbox a la liste
        s32 addCheckBox(IGUICheckBox* newCB)
        {
            /// teste si c'est la première insérée
            if(!mListe.empty())
            {
                /// vérifie qu'elle n'est pas déjà inséré
                for(u32 a=0; a < mListe.size(); a++)
                    if(mListe[a] == newCB) return -1;
                /// elle n'est pas déjà inséré donc on la met dans la liste
                mListe.push_back(newCB);
                /// s'assure que la box n'est pas checké
                newCB->setChecked(false);
            }
            else
            {
                /// on la met dans la liste
                mListe.push_back(newCB);
                /// on l'active puisque c'est la première
                newCB->setChecked(true);
                mActive = 1;
            }
            /// renvoie la position
            return mListe.size() - 1;
        }

        //! supprime une checkbox de la liste
        void deleteCheckBox(IGUICheckBox* oldCB)
        {
            /// s'il y a une checkbox dans la liste
            if(!mListe.empty())
            {
                /// cherche la checkbox dans la liste
                for(u32 a=0; a < mListe.size(); a++)
                {
                    if(mListe[a] == oldCB)
                    {
                        bool changementActif=false;
                        /// si c'est la checkbox active
                        if(a == (mActive-1) ) changementActif=true;
                        /// efface la checkbox de la liste
                        mListe.erase(a);
                        /// si il y a besoin d'un changement de checkbox active
                        if(changementActif) setChecked(1);
                        /// on sort
                        return;
                    }
                }
            }
        }

        //! gère les checkbox
        bool OnEvent(const SEvent& event)
        {
            /// événements de la gui
            if (event.EventType == EET_GUI_EVENT)
            {
                if(event.GUIEvent.EventType == EGET_CHECKBOX_CHANGED)
                {
                    for(u32 a=0; a < mListe.size(); a++)
                        if(event.GUIEvent.Caller == mListe[a])
                        {
                            if(mListe[a]->isChecked()) setChecked(a);
                            else
                            {
                                if(mAtypique)
                                {
                                    mListe[a]->setChecked(false);
                                    mActive = 0;
                                }
                                else mListe[a]->setChecked(true);
                            }
                            return true;
                        }
                }
            }
            /// aucun événement n'a été traité
            return false;
        }

        //! renvoie l'id de la checkbox active et -1 si aucune ne l'est
        s32 getChecked()
        {
            return (mActive - 1);
        }

        //! renvoie un pointeur sur la checkbox active et NULL si aucune ne l'est
        IGUICheckBox* getCheckedBox()
        {
            if(mActive < 1) return NULL;
            return mListe[mActive - 1];
        }

        //! check une checkbox et "décheck" toutes les autres
        void setChecked(u32 IDcheck)
        {
            if(mListe.empty()) mActive = 0;
            else
            /// si la checkbox existe et qu'elle n'est pas déjà active
            if( (IDcheck < mListe.size()) && ((mActive-1) != IDcheck) )
            {
                /// "décheck" l'ancienne checkbox active
                if(mActive > 0) mListe[mActive-1]->setChecked(false);
                /// on met à jour l'index de la checkbox active
                mActive = IDcheck+1;
            }
        }

        //! renvoie le nombre de checkbox assignées au control
        u32 getCheckBoxCount()
        {
            return mListe.size();
        }

    protected:
        /// MEMBRES ///
        array<IGUICheckBox*> mListe;
        u32 mActive; // attention : elle vaut (index_de_la_box + 1) car le 0 est utilisé pour le cas où aucune checkbox n'est checkée
        bool mAtypique;
};

#endif // GUI_BOUTONRADIOCONTROL_H_INCLUDED


Voilà, j'aurais certainement d'autres bouts de code à poster suivant ce que je dois coder pour ma gui.


core i7 4970K @ 4GHz - 32GB ddr3 19200(2400MHz) - ssd samsung 840 evo 250GB - GTX1080Ti (4K) - Cooler master storm stryker blanc.
"L'alcool, c'est comme Activia, c'est actif à l'intérieur et ça se voit à l'extérieur."

Hors ligne


#3 

06-07-2012 02:22:01

Magun
SleekThink Producer
Lieu: Punakha
Date d'inscription: 18-11-2007
Messages: 910
Corrections: 2
Site web

ah, bien super johnplayer
petit code qui en arangerons plus d'un,
sympas pour le partage, j'était passer a coter, merci wink

par contre pourquoi ne pas utiliser l'array présent dans IGUIElement qui contient les childs pour géré le bouton radio ?
avec un bête if(child[i]->getType() == EGT_CHECKBOX) ?

ou plutot je n'aurais pas fait un groupbox, mais j'aurais surment relier les buttonbox par le parent et donc dériver le buttonbox de la checkbox
parent->child[i]->... comme dit présédament, sa évite un obj a instancier après tout ? hmm

bonne soiré wink

Hors ligne


#4 

06-07-2012 09:26:17

johnplayer
Habitué
Date d'inscription: 30-09-2007
Messages: 431

Parce que comme je fais actuellement, je peux limiter les fonctionnalités. Tu remarqueras que j'ai codé le retrait d'une checkbox dans le BoutonRadioControl mais que je n'en permet pas l'utilisation car inutile pour le moment.

De plus, tu remarqueras que BoutonRadioControl n'est pas un GUIElement parce que je lui réserve d'autres utilisations, je voulais que ce control soit indépendant ce qui n'aurai évidemment pas été le cas si je l'avais intégré directement à BoxRetractable. Cela dit rien n'empêche à quiconque de coder une version intégrée et de le poster, plus il y a de version, plus y a de chance de trouver exactement ce que l'on recherche.

Sinon je vais certainement codé un (ou plusieurs versions de) GUI_ButtonRadio par la suite.

Merci pour la critique, si quelqu'un souhaite avoir le BoutonRadioControl intégré à BoxRetractable, tu lui auras donné une piste. Et puis, ça se trouve, je le ferais^^.


core i7 4970K @ 4GHz - 32GB ddr3 19200(2400MHz) - ssd samsung 840 evo 250GB - GTX1080Ti (4K) - Cooler master storm stryker blanc.
"L'alcool, c'est comme Activia, c'est actif à l'intérieur et ça se voit à l'extérieur."

Hors ligne


Options Liens officiels Caractéristiques Statistiques Communauté
Corrections
irrlicht
irrklang
irredit
irrxml
xhtml 1.0
css 2.1
Propulsé par FluxBB
Traduit par FluxBB.fr
882 membres
1429 sujets
11119 messages
Dernier membre inscrit: LiseBuisson96
34 invités en ligne
Aucun membre connecté
RSS Feed