/***************************************************************************
 *   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 "editor_cfg.h"

#include <wx/colordlg.h>
#include <wx/spinctrl.h>

#include "components/framework/tapplication.h"
#include "components/framework/tapplicationpanel.h"
#include "components/stdgui/tbitmap.h"
#include "xpe_components/res_id.h"
#include "xpe_components/editor/stylesres.h"
#include "xpe_components/editor/pov_enlighter.h"
#include "xpe_components/editor/editor_panelelement.h"
#include "lib/tcolor.h"
#include "xpe.h"

#include "bmp_id.h"

EditorConfigPanelElement::EditorConfigPanelElement(TApplicationPanel * _owner, int iID)
    :TConfigPanelElement(_owner, (iID < 0) ? static_cast<XPE *>(CurrentApplication())->getUPEID() : iID),
    contentPanel(NULL),
    reinitBtn(NULL),
    bgColorBtn(NULL)
{
    this->setName(wxTr("Editors style"));
}

void EditorConfigPanelElement::buttonActivated(TGenButton * btn)
{
    if(btn == this->reinitBtn)
    {
        this->init();
    }
    else
    {
        wxColourData colour;
        colour.SetColour(btn->GetBackgroundColour());
        wxColourDialog * dlg = new wxColourDialog(dynamic_cast<wxWindow *>(this->getOwner()->getOwner()), &colour);
        int iRes = dlg->ShowModal();
        if(iRes == wxID_OK)
        {
            colour = dlg->GetColourData();
            btn->SetBackgroundColour(colour.GetColour());
        }
        delete dlg;
    }
}

/** initialise le panneau avec les parametres actuels de l'application */
void EditorConfigPanelElement::init()
{
    StylesRes * styles = static_cast<StylesRes *>(CurrentApplication()->getRessource(STYLES_RESSOURCE_ID));
    if(!styles)
    {
        styles = new StylesRes();
        styles->loadDefaultParameters();
        CurrentApplication()->publishRessource(STYLES_RESSOURCE_ID,styles);
    }

    this->fontSizeSpin->SetValue(styles->getFontSize());
    this->bgColorBtn->SetBackgroundColour(styles->getBgColor().toWxColour());

    this->defaultStyle.init(styles,DEFAULT_STYLE);
    this->identStyle.init(styles,STYLE_IDENT);
    this->keywordStyle.init(styles,STYLE_KEYWORD);
    this->numberStyle.init(styles,STYLE_NUMBER);
    this->stringStyle.init(styles,STYLE_STRING);
    this->charStyle.init(styles,STYLE_CHAR);
    this->commentStyle.init(styles,STYLE_COMMENT);
    this->selectedStyle.init(styles,SELECTED_STYLE);
    this->bracketStyle.init(styles,STYLE_BRACKET);

    this->canCommit();
}

/** initialise les composents avec les parametres actuels de l'application */
void EditorConfigPanelElement::StyleCmps::init(StylesRes * stylesRes, int iStyleId)
{
    TStyle style = stylesRes->getStyle( iStyleId );

    this->fgColorBtn->SetBackgroundColour(style.getFgColor().toWxColour());
    this->bgChk->SetValue(style.hasBgColor());
    this->bgColorBtn->Enable(style.hasBgColor());
    if(style.hasBgColor())
        this->bgColorBtn->SetBackgroundColour(style.getBgColor().toWxColour());
    this->boldChk->SetValue(style.isBold());
    this->italicChk->SetValue(style.isItalic());
    this->underlinedChk->SetValue(style.isUnderlined());
}

/** valide les modifications */
void EditorConfigPanelElement::commit()
{
    StylesRes * styles = static_cast<StylesRes *>(CurrentApplication()->getRessource(STYLES_RESSOURCE_ID));

    if(styles)
    {
        styles->setFontSize( this->fontSizeSpin->GetValue() );
        styles->setBgColor(TColor(this->bgColorBtn->GetBackgroundColour()));

        this->defaultStyle.commit(styles,DEFAULT_STYLE);
        this->identStyle.commit(styles,STYLE_IDENT);
        this->keywordStyle.commit(styles,STYLE_KEYWORD);
        this->numberStyle.commit(styles,STYLE_NUMBER);
        this->stringStyle.commit(styles,STYLE_STRING);
        this->charStyle.commit(styles,STYLE_CHAR);
        this->commentStyle.commit(styles,STYLE_COMMENT);
        this->selectedStyle.commit(styles,SELECTED_STYLE);
        this->bracketStyle.commit(styles,STYLE_BRACKET);
    }
}

/** valide les modifications */
void EditorConfigPanelElement::StyleCmps::commit(StylesRes * stylesRes, int iStyleId)
{
    TStyle style = stylesRes->getStyle( iStyleId );

    style.setFgColor(TColor(this->fgColorBtn->GetBackgroundColour()));
    if(this->bgChk->GetValue())
        style.setBgColor(TColor(this->bgColorBtn->GetBackgroundColour()));
    else
        style.removeBgColor();
    style.setBold( this->boldChk->GetValue() );
    style.setItalic( this->italicChk->GetValue() );
    style.setUnderlined( this->underlinedChk->GetValue() );

    stylesRes->setStyle( iStyleId, style );
}


/** indique si le panneau est dans un état valide */
bool EditorConfigPanelElement::canCommit()
{
    return true;
}

/** construit le panneau conteneur et son contenu (appellé automatiquement par getContentPanel et détruit automatiquement par le destructeur) */
TPanel * EditorConfigPanelElement::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);
    wxSizer * sizer = new wxBoxSizer( wxHORIZONTAL );
    panel->SetSizer(sizer);

    wxStaticText * label = new wxStaticText(panel,-1,wxTr("Font size :"));
    sizer->Add(label,0,wxALIGN_CENTER);
    sizer->AddSpacer(5);
    this->fontSizeSpin = new wxSpinCtrl(panel,-1);
    this->fontSizeSpin->SetRange(4,32);
    sizer->Add(this->fontSizeSpin,0,wxEXPAND);

    mainSizer->Add(panel,0,wxALIGN_LEFT|wxLEFT|wxRIGHT,5);
    mainSizer->AddSpacer(5);

    panel = new TPanel(this->contentPanel);
    sizer = new wxBoxSizer( wxHORIZONTAL );
    panel->SetSizer(sizer);

    label = new wxStaticText(panel,-1,wxTr("Background color :"));
    sizer->Add(label,0,wxALIGN_CENTER);
    sizer->AddSpacer(5);
    this->bgColorBtn = new TGenButton(panel);
    this->bgColorBtn->setText( wxT("...") );
    this->bgColorBtn->addButtonListener( this );
    sizer->Add(this->bgColorBtn,0,wxEXPAND);

    mainSizer->Add(panel,0,wxALIGN_LEFT|wxLEFT|wxRIGHT,5);
    mainSizer->AddSpacer(5);


    panel = new TPanel(this->contentPanel);
    sizer = new wxFlexGridSizer( 2, 5, 3 );
    panel->SetSizer(sizer);

    this->buildStyleCmps(panel,&this->defaultStyle,wxTr("Default style :"));
    this->buildStyleCmps(panel,&this->identStyle,wxTr("Identifier :"));
    this->buildStyleCmps(panel,&this->keywordStyle,wxTr("Keyword :"));
    this->buildStyleCmps(panel,&this->numberStyle,wxTr("Number :"));
    this->buildStyleCmps(panel,&this->stringStyle,wxTr("String :"));
    this->buildStyleCmps(panel,&this->charStyle,wxTr("Character :"));
    this->buildStyleCmps(panel,&this->commentStyle,wxTr("Comment :"));
    this->buildStyleCmps(panel,&this->selectedStyle,wxTr("Selection :"));
    this->buildStyleCmps(panel,&this->bracketStyle,wxTr("Brackets :"));

    mainSizer->Add(panel,0,wxALIGN_LEFT|wxLEFT|wxRIGHT,5);

    mainSizer->AddStretchSpacer(10);

    return this->contentPanel;
}

/** construit la partie concernant une struc StyleCmps */
void EditorConfigPanelElement::buildStyleCmps(TPanel * mainPanel, StyleCmps * sc, const wxString & sLabel)
{
    wxStaticText * label = new wxStaticText(mainPanel,-1,sLabel);
    mainPanel->GetSizer()->Add(label,0,wxALIGN_CENTER_VERTICAL|wxALIGN_LEFT);

    TPanel * panel = new TPanel(mainPanel);
    wxBoxSizer * sizer = new wxBoxSizer( wxHORIZONTAL );

    sc->fgColorBtn = new TGenButton(panel);
    sc->fgColorBtn->setText( wxT("txt") );
    sc->fgColorBtn->SetToolTip( wxTr("Click here to select the text color") );
    sc->fgColorBtn->addButtonListener( this );
    sizer->Add(sc->fgColorBtn,0,wxEXPAND);

    sizer->AddSpacer(25);

    sc->bgChk = new wxCheckBox(panel,-1,wxT(""));
    sc->bgChk->SetToolTip( wxTr("Click here to activate background color. If unchecked, the default background color will be used.") );
    sizer->Add(sc->bgChk,0,wxEXPAND);
    sc->bgColorBtn = new TGenButton(panel);
    sc->bgColorBtn->setText( wxT("BG") );
    sc->bgColorBtn->SetToolTip( wxTr("Click here to select the background color") );
    sc->bgColorBtn->addButtonListener( this );
    sizer->Add(sc->bgColorBtn,0,wxEXPAND);
    this->bgChkBtnMap[sc->bgChk] = sc->bgColorBtn;
    sc->bgChk->Connect(wxEVT_COMMAND_CHECKBOX_CLICKED,wxCommandEventHandler(EditorConfigPanelElement::onCheckBox), NULL, this);

    sizer->AddSpacer(25);
    sc->boldChk = new wxCheckBox(panel,-1,wxTr("bold"));
    sizer->Add(sc->boldChk,0,wxEXPAND);

    sizer->AddSpacer(25);
    sc->italicChk = new wxCheckBox(panel,-1,wxTr("italic"));
    sizer->Add(sc->italicChk,0,wxEXPAND);

    sizer->AddSpacer(25);
    sc->underlinedChk = new wxCheckBox(panel,-1,wxTr("underlined"));
    sizer->Add(sc->underlinedChk,0,wxEXPAND);

    sizer->AddStretchSpacer(10);

    panel->SetSizer(sizer);

    mainPanel->GetSizer()->Add(panel,0,wxEXPAND|wxALIGN_LEFT);
}

void EditorConfigPanelElement::onCheckBox(wxCommandEvent & evt)
{
    TBgChkBtnMap::iterator it = this->bgChkBtnMap.find(evt.GetEventObject());
    if(it == this->bgChkBtnMap.end())
        return;

    (*it).second->Enable(static_cast<wxCheckBox *>((*it).first)->GetValue());
}
