/***************************************************************************
 *   Copyright (C) 2005 by Thierry CHARLES   *
 *   thierry@les-charles.net   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program 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 General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

#include "mainwindow_cfg.h"

#include <wx/arrstr.h>

#include "components/framework/tapplication.h"
#include "components/framework/tapplicationpanel.h"
#include "components/stdgui/tbitmap.h"

#include "xpe_components/mainwindow.h"

#include "lib/lib_logging.h"
#include "lib/lib_string.h"

#include "xpe.h"

#include "bmp_id.h"

int wxCALLBACK _EltMetaInfCompareFunction(long iItem1Data, long iItem2Data, long iSortData);


MainWindowConfigPanelElement::MainWindowConfigPanelElement(XPEMainWindow * mainWindow, TApplicationPanel * _owner, int iID)
    :TConfigPanelElement(_owner, (iID < 0) ? static_cast<XPE *>(CurrentApplication())->getUPEID() : iID),
    mainWindow(mainWindow),
    contentPanel(NULL),
    reinitBtn(NULL),
    panelCombo(NULL),
    elementsCombo(NULL),
    addBtn(NULL),
    renameBtn(NULL),
    changePanelBtn(NULL),
    removeBtn(NULL),
    selectedElementsList(NULL),
    imagesList(16,16),
    moveUpBtn(NULL),
    moveDownBtn(NULL)
{
    this->setName(wxTr("Panels"));
    this->sTopPanel = wxTr("top");
    this->sLeftPanel = wxTr("left");
    this->sRightPanel = wxTr("right");
    this->sBottomPanel = wxTr("bottom");
}

void MainWindowConfigPanelElement::buttonActivated(TGenButton * btn)
{
    if(btn == this->reinitBtn)
    {
        this->init();
    }
    else if(btn == this->addBtn)
    {
        TPanelElementInfo & eltTypeInfo = this->availableElts[this->elementsCombo->GetValue()];
        if(!eltTypeInfo.canAdd())
        {
            wxMessageBox(wxString::Format(wxTr("No more element of this type can be added (max %d)"), eltTypeInfo.getMaxOccurs()), wxTr("Error"), wxOK | wxICON_ERROR,  this->contentPanel);
            return;
        }

        TEltsMetaList & eltsList = this->panelEltsMap[this->panelCombo->GetValue()];

        eltsList.insert(EltMetaInf(eltTypeInfo.getType(), eltTypeInfo.getTypeName(), eltsList.size()));
        eltTypeInfo.inc();

        this->updatePanel();
    }
    else if(btn == this->renameBtn)
    {
        if(!this->selectedElementsList->GetSelectedItemCount())
            return;

        long iSelItem = this->selectedElementsList->GetNextItem(-1,wxLIST_NEXT_ALL,wxLIST_STATE_SELECTED);
        if(iSelItem < 0)
            return;

        EltMetaInf * eltSel = (EltMetaInf *)this->selectedElementsList->GetItemData(iSelItem);

        wxString sNewName = wxGetTextFromUser(wxT("Rename to (<space> for no-name) : _"),wxTr("Rename"),eltSel->sName);

        if(sNewName.length())
        {
            eltSel->sName = sNewName;
            this->selectedElementsList->SetItemText(iSelItem,sNewName);
        }
    }
    else if(btn == this->changePanelBtn)
    {
        if(!this->selectedElementsList->GetSelectedItemCount())
            return;

        long iSelItem = this->selectedElementsList->GetNextItem(-1,wxLIST_NEXT_ALL,wxLIST_STATE_SELECTED);
        if(iSelItem < 0)
            return;

        wxArrayString availablePanels;
        if(this->panelCombo->GetValue() != this->sTopPanel)
            availablePanels.Add(this->sTopPanel);
        if(this->panelCombo->GetValue() != this->sLeftPanel)
            availablePanels.Add(this->sLeftPanel);
        if(this->panelCombo->GetValue() != this->sRightPanel)
            availablePanels.Add(this->sRightPanel);
        if(this->panelCombo->GetValue() != this->sBottomPanel)
            availablePanels.Add(this->sBottomPanel);

        wxString sDestPanel = wxGetSingleChoice(wxTr("Select the destination panel"), wxTr("Change panel"),
                                                availablePanels, this->contentPanel);

        if(sDestPanel.length())
        {
            EltMetaInf eltSel = *(EltMetaInf *)this->selectedElementsList->GetItemData(iSelItem);

            TEltsMetaList & eltsList = this->panelEltsMap[sDestPanel];
            eltSel.iDisplayOrder = eltsList.size();
            eltsList.insert(eltSel);
            this->availableEltsByType[ISO2WX(eltSel.szType)]->inc();

            this->buttonActivated(this->removeBtn);
        }
    }
    else if(btn == this->removeBtn)
    {
        if(!this->selectedElementsList->GetSelectedItemCount())
            return;

        long iSelItem = this->selectedElementsList->GetNextItem(-1,wxLIST_NEXT_ALL,wxLIST_STATE_SELECTED);
        if(iSelItem < 0)
            return;

        EltMetaInf * eltSel = (EltMetaInf *)this->selectedElementsList->GetItemData(iSelItem);

        TPanelElementInfo * eltInfo = this->availableEltsByType[ISO2WX(eltSel->szType)];
        if(!eltInfo->canDel())
        {
            wxMessageBox(wxString::Format(wxTr("No more element of this type can be removed (min %d)"), eltInfo->getMinOccurs()), wxTr("Error"), wxOK | wxICON_ERROR,  this->contentPanel);
            return;
        }

        TEltsMetaList & eltsList = this->panelEltsMap[this->panelCombo->GetValue()];

        for( int i = iSelItem + 1 ; i < this->selectedElementsList->GetItemCount() ; i++)
            ((EltMetaInf*)this->selectedElementsList->GetItemData(i))->iDisplayOrder--;

        this->selectedElementsList->DeleteItem(iSelItem);

        eltsList.erase(*eltSel);
        eltInfo->dec();
    }
    else if(btn == this->moveUpBtn)
    {
        if(!this->selectedElementsList->GetSelectedItemCount())
            return;

        long iSelItem = this->selectedElementsList->GetNextItem(-1,wxLIST_NEXT_ALL,wxLIST_STATE_SELECTED);
        if(iSelItem <= 0)
            return;
        long iAboveItem = iSelItem - 1;
        if(iAboveItem < 0)
            return;

        EltMetaInf * eltSel = (EltMetaInf *)this->selectedElementsList->GetItemData(iSelItem);
        EltMetaInf * eltAbove = (EltMetaInf *)this->selectedElementsList->GetItemData(iAboveItem);

        eltSel->iDisplayOrder--;
        eltAbove->iDisplayOrder++;
        this->selectedElementsList->SortItems(&_EltMetaInfCompareFunction,0);

        this->selectedElementsList->SetItemState(iSelItem,0,wxLIST_STATE_SELECTED);
        this->selectedElementsList->SetItemState(iAboveItem,wxLIST_STATE_SELECTED,wxLIST_STATE_SELECTED);
    }
    else if(btn == this->moveDownBtn)
    {
        if(!this->selectedElementsList->GetSelectedItemCount())
            return;

        long iSelItem = this->selectedElementsList->GetNextItem(-1,wxLIST_NEXT_ALL,wxLIST_STATE_SELECTED);
        if(iSelItem < 0 || iSelItem == (this->selectedElementsList->GetItemCount()-1))
            return;
        long iBelowItem = iSelItem + 1;
        if(iBelowItem < 0)
            return;

        EltMetaInf * eltSel = (EltMetaInf *)this->selectedElementsList->GetItemData(iSelItem);
        EltMetaInf * eltBelow = (EltMetaInf *)this->selectedElementsList->GetItemData(iBelowItem);

        eltSel->iDisplayOrder++;
        eltBelow->iDisplayOrder--;
        this->selectedElementsList->SortItems(&_EltMetaInfCompareFunction,0);

        this->selectedElementsList->SetItemState(iSelItem,0,wxLIST_STATE_SELECTED);
        this->selectedElementsList->SetItemState(iBelowItem,wxLIST_STATE_SELECTED,wxLIST_STATE_SELECTED);
    }
}

/** initialise le panneau avec les parametres actuels de l'application */
void MainWindowConfigPanelElement::init()
{
    this->availableElts = this->mainWindow->createAvailableElementsInfoList();
    this->availableEltsByType.erase(this->availableEltsByType.begin(),this->availableEltsByType.end());
    this->eltsIconMap.erase(this->eltsIconMap.begin(),this->eltsIconMap.end());
    this->imagesList.RemoveAll();
    if(this->elementsCombo)
        this->elementsCombo->Clear();

    TAvailableEltsList::iterator it = this->availableElts.begin();
    while(it != this->availableElts.end())
    {
        const char * szType = (*it).second.getType();
        TPanelElementInfo * eltInfoPtr = &(*it).second;
        this->availableEltsByType.insert(TAvailableEltsTypeList::value_type(ISO2WX(szType),eltInfoPtr));

        if((*it).second.getIcon())
            this->eltsIconMap.insert(TEltsIconIdxMap::value_type(
                    ISO2WX((*it).second.getType()),
                    this->imagesList.Add(*((*it).second.getIcon()))));
        else
            this->eltsIconMap.insert(TEltsIconIdxMap::value_type(
                    ISO2WX((*it).second.getType()),-1));

        if(this->elementsCombo)
            this->elementsCombo->Append((*it).first);
        it++;
    }

    this->panelEltsMap.erase(this->panelEltsMap.begin(),this->panelEltsMap.end());
    this->initPanel(this->sTopPanel, this->mainWindow->getTopPanel());
    this->initPanel(this->sLeftPanel, this->mainWindow->getLeftPanel());
    this->initPanel(this->sRightPanel, this->mainWindow->getRightPanel());
    this->initPanel(this->sBottomPanel, this->mainWindow->getBottomPanel());

    this->updatePanel();
}

/** initialise les metas donnees concernant un panneau */
void MainWindowConfigPanelElement::initPanel(const wxString & sPanel, TApplicationPanel * panel)
{
    if(!panel)
        return;

    TEltsMetaList & eltsList = this->panelEltsMap[sPanel];

    for(int i = 0 ; i < panel->getElementsCount() ; i++)
    {
        TPanelElement * elt = panel->getElementAt( i );
        eltsList.insert(EltMetaInf(elt->getElementType(), elt->getName(), i, elt->getID(), panel));

        this->availableEltsByType[ISO2WX(elt->getElementType())]->inc();
    }
}

/** mets a jour l'affichage */
void MainWindowConfigPanelElement::updatePanel()
{
    this->selectedElementsList->DeleteAllItems();

    TEltsMetaList & eltsList = this->panelEltsMap[this->panelCombo->GetValue()];
    TEltsMetaList::iterator it  = eltsList.begin();
    while(it != eltsList.end())
    {
        long iItemId = this->selectedElementsList->InsertItem(0,(*it).sName);
        this->selectedElementsList->SetItemData(iItemId, (long)&(*it));
        this->selectedElementsList->SetItemImage(iItemId,this->eltsIconMap[ISO2WX((*it).szType)]);

        it++;
    }

    this->selectedElementsList->SortItems(&_EltMetaInfCompareFunction,0);
}

/** enleve les elements qui ont �t� supprim�s */
void MainWindowConfigPanelElement::commitPanelEltsDeletion(TApplicationPanel * panel, const std::set<int> & idsList)
{
    for(int i = panel->getElementsCount()-1 ; i >= 0  ; i--)
    {
        TPanelElement * elt = panel->getElementAt( i );

        if(idsList.find(elt->getID()) == idsList.end())
            panel->removeElement( elt->getID(), true );
    }
}

/** cr�e / trans�re les elements ajout�s / conserv�s */
void MainWindowConfigPanelElement::commitPanelElts(TApplicationPanel * panel, const TEltsMetaList & eltsList)
{
    TEltsMetaList::const_iterator it = eltsList.begin();
    while(it != eltsList.end())
    {
        TPanelElement * elt = NULL;
        if((*it).origin == NULL)
        {
            // cr�ation d'un nouveau composant
            elt = CurrentApplication()->builElement( (*it).szType, panel, (*it).iID );
        }
        else if((*it).origin != panel)
        {
            // transfert d'un �l�ment
            elt = (*it).origin->getElement( (*it).iID );
            panel->addElement( elt );
            (*it).origin->removeElement( (*it).iID, false );
        }
        else
            elt = panel->getElement( (*it).iID );

        if(elt)
        {
            wxString sName = (*it).sName;
            sName.Trim();
            elt->setName(sName);
            panel->setElementDisplayOrder( elt, (*it).iDisplayOrder, true );
        }
        else
            LOG_DEBUG(wxString::Format(wxT("Impossible de gerer l'element %s %d"),(*it).sName.c_str(),(*it).iID));

        it++;
    }
}


/** valide les modifications */
void MainWindowConfigPanelElement::commit()
{
    // on commence par supprimer les �l�ments qui n'existent plus
    // construction de la liste des ID
    typedef std::set<int> TIntList;
    TIntList idsList;
    TPanelEltsMap::iterator itP = this->panelEltsMap.begin();
    while(itP != this->panelEltsMap.end())
    {
        TEltsMetaList & eltsList = (*itP).second;
        TEltsMetaList::iterator it  = eltsList.begin();
        while(it != eltsList.end())
        {
            idsList.insert((*it).iID);
            it++;
        }
        itP++;
    }
    this->commitPanelEltsDeletion(this->mainWindow->getTopPanel(), idsList);
    this->commitPanelEltsDeletion(this->mainWindow->getLeftPanel(), idsList);
    this->commitPanelEltsDeletion(this->mainWindow->getRightPanel(), idsList);
    this->commitPanelEltsDeletion(this->mainWindow->getBottomPanel(), idsList);

    // puis cr�er les nouveaux �l�ments et transf�rer les �l�ments qui ont chang� de panneau
    this->commitPanelElts(this->mainWindow->getTopPanel(), this->panelEltsMap[this->sTopPanel]);
    this->commitPanelElts(this->mainWindow->getLeftPanel(), this->panelEltsMap[this->sLeftPanel]);
    this->commitPanelElts(this->mainWindow->getRightPanel(), this->panelEltsMap[this->sRightPanel]);
    this->commitPanelElts(this->mainWindow->getBottomPanel(), this->panelEltsMap[this->sBottomPanel]);


}

/** indique si le panneau est dans un �tat valide */
bool MainWindowConfigPanelElement::canCommit()
{
    TAvailableEltsList::iterator it = this->availableElts.begin();
    bool bOk = true;
    while(it != this->availableElts.end())
    {
        if(!(*it).second.checkConstraints())
        {
            wxString sMessage = wxString::Format(wxTr("The element %s doesn't respect it's constraints (min=%d, max=%d)"), (*it).first.c_str(), (*it).second.getMinOccurs(), (*it).second.getMaxOccurs());
            wxMessageBox(sMessage,wxTr("Error"), wxOK | wxICON_EXCLAMATION,  this->contentPanel);
            bOk = false;
        }
        it++;
    }
    return bOk;
}

void MainWindowConfigPanelElement::onListViewSize(wxSizeEvent & evt)
{
    evt.Skip();
    if(this->selectedElementsList && this->selectedElementsList->GetClientSize().GetWidth()>0)
    {
        this->selectedElementsList->SetColumnWidth( 0, this->selectedElementsList->GetClientSize().GetWidth() - 2 );
    }
}

void MainWindowConfigPanelElement::onComboBox(wxCommandEvent & evt)
{
    if(evt.GetEventObject() == this->panelCombo)
    {
        this->updatePanel();
    }
    else // element type
    {
    }
}

/** construit le panneau conteneur et son contenu (appell� automatiquement par getContentPanel et d�truit automatiquement par le destructeur) */
TPanel * MainWindowConfigPanelElement::buildContentPanel()
{
    if(this->contentPanel)
        return this->contentPanel;

    this->contentPanel = new TPanel(dynamic_cast<wxWindow *>(this->getOwner()->getOwner()));
    wxBoxSizer * mainSizer = new wxBoxSizer( wxVERTICAL);
    contentPanel->SetSizer(mainSizer);

    mainSizer->AddSpacer(5);

    this->reinitBtn = new TGenButton(this->contentPanel);
    this->reinitBtn->setBitmap( GET_BMP(BMP_REFRESH_ID) );
    this->reinitBtn->setText(wxTr("Reload"));
    this->reinitBtn->addButtonListener( this );
    mainSizer->Add(this->reinitBtn,0,wxALIGN_RIGHT|wxLEFT|wxRIGHT,5);

    TPanel * panel = new TPanel(this->contentPanel);
    wxBoxSizer * sizer = new wxBoxSizer( wxHORIZONTAL );
    panel->SetSizer(sizer);
    wxStaticText * label = new wxStaticText(panel,-1,wxTr("Panel :"));
    sizer->Add(label,0,wxALIGN_CENTER);
    sizer->AddSpacer(3);
    wxArrayString choices;
    choices.Add(this->sTopPanel);
    choices.Add(this->sLeftPanel);
    choices.Add(this->sRightPanel);
    choices.Add(this->sBottomPanel);
    this->panelCombo = new wxComboBox(panel, -1, choices[0], wxDefaultPosition, wxDefaultSize, choices, wxCB_READONLY);
    this->panelCombo->Connect(wxEVT_COMMAND_COMBOBOX_SELECTED,wxCommandEventHandler(MainWindowConfigPanelElement::onComboBox), NULL, this);
    sizer->Add(this->panelCombo,0,wxEXPAND);
    sizer->AddStretchSpacer(1);
    mainSizer->Add(panel,0,wxEXPAND|wxLEFT|wxRIGHT,5);
    mainSizer->AddSpacer(5);

    TPanel * panelB = new TPanel(this->contentPanel);
    wxBoxSizer * sizerB = new wxBoxSizer( wxHORIZONTAL );
    panelB->SetSizer(sizerB);

    panel = new TPanel(panelB);
    sizer = new wxBoxSizer( wxVERTICAL );
    panel->SetSizer(sizer);
    label = new wxStaticText(panel,-1,wxTr("Available elements :"));
    sizer->Add(label,0,wxALIGN_CENTER);
    sizer->AddSpacer(3);
    wxArrayString eltsChoices;
    eltsChoices.Add(wxT("-"));
    this->elementsCombo = new wxComboBox(panel, -1, eltsChoices[0], wxDefaultPosition, wxDefaultSize, eltsChoices, wxCB_READONLY);
    sizer->Add(this->elementsCombo,0,wxEXPAND);
    this->elementsCombo->Connect(wxEVT_COMMAND_COMBOBOX_SELECTED,wxCommandEventHandler(MainWindowConfigPanelElement::onComboBox), NULL, this);

    sizer->AddSpacer(3);
    this->addBtn = new TGenButton(panel);
    this->addBtn->setBitmap( GET_BMP(BMP_ADD_ID) );
    this->addBtn->setText(wxTr("Add to panel"));
    this->addBtn->addButtonListener( this );
    sizer->Add(this->addBtn,0,wxEXPAND);

    sizer->AddStretchSpacer(1);
    this->renameBtn = new TGenButton(panel);
    this->renameBtn->setText(wxTr("Rename"));
    this->renameBtn->setBitmap( GET_BMP(BMP_EDITQUESTION_ID) );
    this->renameBtn->addButtonListener( this );
    sizer->Add(this->renameBtn,0,wxEXPAND);

    sizer->AddSpacer(3);
    this->removeBtn = new TGenButton(panel);
    this->removeBtn->setText(wxTr("Remove"));
    this->removeBtn->setBitmap( GET_BMP(BMP_REMOVE_ID) );
    this->removeBtn->addButtonListener( this );
    sizer->Add(this->removeBtn,0,wxEXPAND);

    sizer->AddSpacer(3);
    this->changePanelBtn = new TGenButton(panel);
    this->changePanelBtn->setText(wxTr("Change panel"));
    this->changePanelBtn->setBitmap( GET_BMP(BMP_EXCHANGE_ID) );
    this->changePanelBtn->addButtonListener( this );
    sizer->Add(this->changePanelBtn,0,wxEXPAND);

    sizerB->Add(panel,0,wxEXPAND|wxLEFT,5);
    sizerB->AddSpacer(5);

    TPanel * panelC = new TPanel(panelB);
    wxBoxSizer * sizerC = new wxBoxSizer( wxVERTICAL );
    panelC->SetSizer(sizerC);

    label = new wxStaticText(panelC,-1,wxTr("Panel elements :"));
    sizerC->Add(label,0,wxEXPAND|wxLEFT|wxRIGHT,5);
    sizerC->AddSpacer(3);

    TPanel * panelD = new TPanel(panelC);
    wxBoxSizer * sizerD = new wxBoxSizer( wxHORIZONTAL );
    panelD->SetSizer(sizerD);

    this->selectedElementsList = new TListCtrl(panelD, -1, wxDefaultPosition, wxDefaultSize,
                                wxLC_REPORT | wxLC_NO_HEADER | wxLC_SINGLE_SEL | wxSUNKEN_BORDER );
    this->selectedElementsList->SetImageList(&this->imagesList,wxIMAGE_LIST_SMALL);
    sizerD->Add(this->selectedElementsList,1,wxEXPAND);
    sizerD->AddSpacer(3);

    // entetes des colonnes (cach�es)
    wxListItem itemCol;
    itemCol.SetText(wxT(" "));
    itemCol.SetImage(-1);
    this->selectedElementsList->InsertColumn(0, itemCol);

    this->selectedElementsList->Connect(wxEVT_SIZE,wxSizeEventHandler(MainWindowConfigPanelElement::onListViewSize), NULL, this);


    panel = new TPanel(panelD);
    sizer = new wxBoxSizer( wxVERTICAL );
    panel->SetSizer(sizer);

    sizer->AddStretchSpacer(1);

    this->moveUpBtn = new TGenButton(panel);
    this->moveUpBtn->setBitmap( GET_BMP(BMP_UP_ID) );
    this->moveUpBtn->addButtonListener( this );
    sizer->Add(this->moveUpBtn,0,wxEXPAND);

    sizer->AddSpacer(30);

    this->moveDownBtn = new TGenButton(panel);
    this->moveDownBtn->setBitmap( GET_BMP(BMP_DOWN_ID) );
    this->moveDownBtn->addButtonListener( this );
    sizer->Add(this->moveDownBtn,0,wxEXPAND);

    sizer->AddStretchSpacer(1);

    sizerD->Add(panel,0,wxEXPAND);

    sizerC->Add(panelD,1,wxEXPAND);

    sizerB->Add(panelC,1,wxEXPAND|wxRIGHT,5);

    mainSizer->Add(panelB,1,wxEXPAND|wxLEFT|wxRIGHT,5);

    return this->contentPanel;
}

MainWindowConfigPanelElement::EltMetaInf::EltMetaInf(const char * _szType, wxString _sName, int _iDisplayOrder, int _iID, TApplicationPanel * _origin)
    : szType(_szType), sName(_sName), iDisplayOrder(_iDisplayOrder), iID(_iID), origin(_origin)
{
    if(!sName.length())
        sName = wxT(" ");
    if(this->iID < 0)
    {
        this->iID = static_cast<XPE *>(CurrentApplication())->getUPEID();
    }
}

bool operator <  (const MainWindowConfigPanelElement::EltMetaInf &A,const MainWindowConfigPanelElement::EltMetaInf &B)
{
    return A.iID < B.iID;
}

bool operator >  (const MainWindowConfigPanelElement::EltMetaInf &A,const MainWindowConfigPanelElement::EltMetaInf &B)
{
    return A.iID > B.iID;
}

bool operator <= (const MainWindowConfigPanelElement::EltMetaInf &A,const MainWindowConfigPanelElement::EltMetaInf &B)
{
    return A.iID <= B.iID;
}

bool operator >= (const MainWindowConfigPanelElement::EltMetaInf &A,const MainWindowConfigPanelElement::EltMetaInf &B)
{
    return A.iID >= B.iID;
}

bool operator == (const MainWindowConfigPanelElement::EltMetaInf &A,const MainWindowConfigPanelElement::EltMetaInf &B)
{
    return A.iID == B.iID;
}

bool operator != (const MainWindowConfigPanelElement::EltMetaInf &A,const MainWindowConfigPanelElement::EltMetaInf &B)
{
    return !(A == B);
}

int wxCALLBACK _EltMetaInfCompareFunction(long iItem1Data, long iItem2Data, long iSortData)
{
    MainWindowConfigPanelElement::EltMetaInf * elt1 = (MainWindowConfigPanelElement::EltMetaInf *)(iItem1Data);
    MainWindowConfigPanelElement::EltMetaInf * elt2 = (MainWindowConfigPanelElement::EltMetaInf *)(iItem2Data);

    return elt1->iDisplayOrder - elt2->iDisplayOrder;
}

