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

#include <math.h>

#include <wx/font.h>

#include "tclock.h"
#include "components/framework/tapplicationpanel.h"
#include "components/framework/tapplication.h"
#include "components/stdgui/tpanel.h"

#include "clock.xpm"

TBitmap * ClockPanelElement::defaultIcon = NULL;
const TBitmap * ClockPanelElement::getDefaultIcon()
{
    if(!defaultIcon)
    {
        defaultIcon = new TBitmap((const char **)clock_xpm);
    }
    return defaultIcon;
}


ClockPanelElement::ClockPanelElement(TApplicationPanel * _owner, int iID)
    : TPanelElement(_owner, iID, wxT(""), wxT("")),
    clock(NULL),
    rightClickMenu(NULL),
    tailleSubMenu(NULL),
    bDigital(false),
    bDate(true),
    bSeconds(false),
    bDecorations(true),
    bDecorationsDetail(false),
    bNumbers(false),
    bNumbersDetail(false),
    iClockSize(100)
{
    this->setTooltip(wxTr("A clock"));
    this->setExtensivity(0);
    this->setBitmap(getDefaultIcon());
}

ClockPanelElement::~ClockPanelElement()
{
}

/** construit le panneau conteneur et son contenu (appell�automatiquement par getContentPanel et d�ruit automatiquement par le destructeur) */
TPanel * ClockPanelElement::buildContentPanel()
{
    TPanel * contentPanel = new TPanel(this->getOwner()->getContentPanel());
    wxBoxSizer * sizer = new wxBoxSizer( wxVERTICAL);
    contentPanel->SetSizer(sizer);

    this->clock = new TClock(contentPanel);
    wxFont font = this->clock->GetFont();
    font.SetFaceName(wxT("Arial"));
    font.SetPointSize(10);
    this->clock->SetFont(font);
    this->clock->setClockType(this->bDigital ? TClock::Digital : TClock::Analogical);
    this->setClockSize(this->iClockSize);
    this->clock->setDisplayDate(this->bDate);
    this->clock->setDisplaySeconds(this->bSeconds);
    this->clock->setNumbersProperties( this->bNumbers, this->bNumbersDetail );
    this->clock->setDecorationsProperties( this->bDecorations, this->bDecorationsDetail );

    sizer->Add(this->clock,0,wxEXPAND);
    sizer->Show(this->clock,true);

    this->clock->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler(ClockPanelElement::onMouseRightDown), NULL, this );

    return contentPanel;
}

/** d�fini la taille de l'horloge et de la police de la date */
void ClockPanelElement::setClockSize(int iSize)
{
    this->iClockSize = iSize;
    this->clock->setClockSize(this->iClockSize);
    wxFont font = this->clock->GetFont();
    font.SetPointSize(int(log(iSize*2)*2));
    this->clock->SetFont(font);
}


wxMenu * ClockPanelElement::getPopupMenu()
{
    this->buildMenu();

    this->rightClickMenu->Check(Menu_Digital,this->bDigital);
    this->rightClickMenu->Check(Menu_Date,this->bDate);
    this->rightClickMenu->Check(Menu_Seconds,this->bSeconds);
    this->rightClickMenu->Enable(Menu_Decorations,!this->bDigital);
    this->rightClickMenu->Check(Menu_Decorations,this->bDecorations);
    this->rightClickMenu->Enable(Menu_DecDetails,(!this->bDigital) && this->bDecorations );
    this->rightClickMenu->Check(Menu_DecDetails,this->bDecorationsDetail);
    this->rightClickMenu->Enable(Menu_Numbers,!this->bDigital);
    this->rightClickMenu->Check(Menu_Numbers,this->bNumbers);
    this->rightClickMenu->Enable(Menu_NumDetails,(!this->bDigital) && this->bNumbers);
    this->rightClickMenu->Check(Menu_NumDetails,this->bNumbersDetail);

    switch(this->iClockSize)
    {
        case 50 :
            this->tailleSubMenu->Check(Menu_Size_50,true);
            break;
        case 100 :
            this->tailleSubMenu->Check(Menu_Size_100,true);
            break;
        case 150 :
            this->tailleSubMenu->Check(Menu_Size_150,true);
            break;
        case 200 :
            this->tailleSubMenu->Check(Menu_Size_200,true);
            break;
    }

    return this->rightClickMenu;
}

void ClockPanelElement::onMouseRightDown(wxMouseEvent & evt)
{
    this->clock->PopupMenu(this->getPopupMenu(),evt.GetPosition());
}

void ClockPanelElement::buildMenu()
{
    if(this->rightClickMenu)
        return;

    this->clock->Connect( wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(ClockPanelElement::onMenuClick), NULL, this );

    this->tailleSubMenu = new wxMenu();
    tailleSubMenu->AppendRadioItem(Menu_Size_50, wxT("50"));
    tailleSubMenu->AppendRadioItem(Menu_Size_100, wxT("100"));
    tailleSubMenu->AppendRadioItem(Menu_Size_150, wxT("150"));
    tailleSubMenu->AppendRadioItem(Menu_Size_200, wxT("200"));

    this->rightClickMenu = new wxMenu();
    this->rightClickMenu->Append( new wxMenuItem(this->rightClickMenu, -1, wxTr("Size"), wxT(""), wxITEM_NORMAL, this->tailleSubMenu ));
    this->rightClickMenu->AppendCheckItem( Menu_Digital,wxTr( "Digital display" ) );
    this->rightClickMenu->AppendCheckItem( Menu_Date, wxTr( "Date" ) );
    this->rightClickMenu->AppendCheckItem( Menu_Seconds, wxTr( "Seconds" ) );
    this->rightClickMenu->AppendCheckItem( Menu_Decorations, wxTr( "Decorations" ) );
    this->rightClickMenu->AppendCheckItem( Menu_DecDetails, wxTr( "All decorations" ) );
    this->rightClickMenu->AppendCheckItem( Menu_Numbers, wxTr( "Numbers" ) );
    this->rightClickMenu->AppendCheckItem( Menu_NumDetails, wxTr( "All numbers" ) );
}

void ClockPanelElement::onMenuClick(wxCommandEvent& evt)
{
    switch(evt.GetId())
    {
        case Menu_Digital:
            this->bDigital = this->rightClickMenu->IsChecked(Menu_Digital);
            this->clock->setClockType(this->bDigital ? TClock::Digital : TClock::Analogical);
            break;
        case Menu_Date:
            this->bDate = this->rightClickMenu->IsChecked(Menu_Date);
            this->clock->setDisplayDate(this->bDate);
            break;
        case Menu_Seconds:
            this->bSeconds = this->rightClickMenu->IsChecked(Menu_Seconds);
            this->clock->setDisplaySeconds(this->bSeconds);
            break;
        case Menu_Decorations:
            this->bDecorations = this->rightClickMenu->IsChecked(Menu_Decorations);
            this->clock->setDecorationsProperties( this->bDecorations, this->bDecorationsDetail );
            break;
        case Menu_DecDetails:
            this->bDecorationsDetail = this->rightClickMenu->IsChecked(Menu_DecDetails);
            this->clock->setDecorationsProperties( this->bDecorations, this->bDecorationsDetail );
            break;
        case Menu_Numbers:
            this->bNumbers = this->rightClickMenu->IsChecked(Menu_Numbers);
            this->clock->setNumbersProperties( this->bNumbers, this->bNumbersDetail );
            break;
        case Menu_NumDetails:
            this->bNumbersDetail = this->rightClickMenu->IsChecked(Menu_NumDetails);
            this->clock->setNumbersProperties( this->bNumbers, this->bNumbersDetail );
            break;
        case Menu_Size_50:
        case Menu_Size_100:
        case Menu_Size_150:
        case Menu_Size_200:
            if(this->tailleSubMenu->IsChecked(Menu_Size_50))
                this->iClockSize = 50;
            else if(this->tailleSubMenu->IsChecked(Menu_Size_100))
                this->iClockSize = 100;
            else if(this->tailleSubMenu->IsChecked(Menu_Size_150))
                this->iClockSize = 150;
            else if(this->tailleSubMenu->IsChecked(Menu_Size_200))
                this->iClockSize = 200;
            this->setClockSize(this->iClockSize);
        default:
            break;
    }
    this->clock->Refresh();
}

#define XML_PARAM_NODE_MAIN "Main"
#define XML_PARAM_MAIN_SIZE "size"
#define XML_PARAM_MAIN_DIGITAL "digital"
#define XML_PARAM_MAIN_DATE "date"
#define XML_PARAM_MAIN_SECONDS "seconds"
#define XML_PARAM_MAIN_DECO "decorations"
#define XML_PARAM_MAIN_SUBDECO "decorationDetails"
#define XML_PARAM_MAIN_NUMBERS "numbers"
#define XML_PARAM_MAIN_SUBNUMBERS "numbersDetails"

/** charge les parametres du composant a partir des informations contenues dans le noeud pass� en param�tre */
bool ClockPanelElement::loadParameters(TiXmlElement * parametersNode)
{
    TiXmlElement * elt = parametersNode->FirstChildElement(XML_PARAM_NODE_MAIN);
    if(!elt)
        return false;

    int iSize = 0;
    if(elt->QueryIntAttribute( XML_PARAM_MAIN_SIZE , & iSize ) != TIXML_SUCCESS )
        return false;

    int bDigital = 0;
    if(elt->QueryIntAttribute( XML_PARAM_MAIN_DIGITAL , & bDigital ) != TIXML_SUCCESS )
        return false;

    int bDate = 0;
    if(elt->QueryIntAttribute( XML_PARAM_MAIN_DATE , & bDate ) != TIXML_SUCCESS )
        return false;

    int bSeconds = 0;
    if(elt->QueryIntAttribute( XML_PARAM_MAIN_SECONDS , & bSeconds ) != TIXML_SUCCESS )
        return false;

    int bDecorations = 0;
    if(elt->QueryIntAttribute( XML_PARAM_MAIN_DECO , & bDecorations ) != TIXML_SUCCESS )
        return false;

    int bDecDetails = 0;
    if(elt->QueryIntAttribute( XML_PARAM_MAIN_SUBDECO , & bDecDetails ) != TIXML_SUCCESS )
        return false;

    int bNumbers = 0;
    if(elt->QueryIntAttribute( XML_PARAM_MAIN_NUMBERS , & bNumbers ) != TIXML_SUCCESS )
        return false;

    int bNumDetails = 0;
    if(elt->QueryIntAttribute( XML_PARAM_MAIN_SUBNUMBERS , & bNumDetails ) != TIXML_SUCCESS )
        return false;

    this->bDigital = bDigital;
    this->clock->setClockType(this->bDigital ? TClock::Digital : TClock::Analogical);
    this->bDate = bDate;
    this->clock->setDisplayDate(this->bDate);
    this->bSeconds = bSeconds;
    this->clock->setDisplaySeconds(this->bSeconds);
    this->bDecorations = bDecorations;
    this->clock->setDecorationsProperties( this->bDecorations, this->bDecorationsDetail );
    this->bDecorationsDetail = bDecDetails;
    this->clock->setDecorationsProperties( this->bDecorations, this->bDecorationsDetail );
    this->bNumbers = bNumbers;
    this->clock->setNumbersProperties( this->bNumbers, this->bNumbersDetail );
    this->bNumbersDetail = bNumDetails;
    this->clock->setNumbersProperties( this->bNumbers, this->bNumbersDetail );
    this->iClockSize = iSize;
    this->setClockSize(this->iClockSize);

    this->clock->Refresh();

    return true;
}

/** renvoie les parametres du composant sous la forme d'un noeud xml */
TiXmlElement * ClockPanelElement::getParameters()
{
    TiXmlElement * root = TPanelElement::getParameters();
    TiXmlElement * elt = new TiXmlElement(XML_PARAM_NODE_MAIN);

    elt->SetAttribute( XML_PARAM_MAIN_SIZE , this->iClockSize );
    elt->SetAttribute( XML_PARAM_MAIN_DIGITAL , this->bDigital);
    elt->SetAttribute( XML_PARAM_MAIN_DATE , this->bDate);
    elt->SetAttribute( XML_PARAM_MAIN_SECONDS , this->bSeconds);
    elt->SetAttribute( XML_PARAM_MAIN_DECO , this->bDecorations);
    elt->SetAttribute( XML_PARAM_MAIN_SUBDECO , this->bDecorationsDetail);
    elt->SetAttribute( XML_PARAM_MAIN_NUMBERS , this->bNumbers);
    elt->SetAttribute( XML_PARAM_MAIN_SUBNUMBERS , this->bNumbersDetail);

    root->LinkEndChild( elt );

    return root;
}

