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.
#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
#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.