/////////////////////////////////////////////////////////////////////////////
// Name:        checkbox.cpp
// Purpose:     
// Author:      César Mauri Loba
// Modified by: 
// Created:     15/05/2011 19:42:16
// RCS-ID:      
// Copyright:   (C) 2011 Cesar Mauri Loba - CREA Software Systems
// 
//  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 3 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, see <http://www.gnu.org/licenses/>.   
/////////////////////////////////////////////////////////////////////////////

////@begin includes
////@end includes

#include "checkbox.h"
#include <wx/sizer.h>
#include <wx/bitmap.h>

////@begin XPM images
////@end XPM images

using namespace spcore;
using namespace std;

namespace mod_widgets {

CheckboxComponent::CheckboxComponent(const char * name, int argc, const char * argv[])
: CComponentAdapter(name, argc, argv)
, m_panel(NULL)
{
	// Create pins and storage
	m_iPin= SmartPtr<IInputPin>(new InputPinValue(*this), false);
	m_oPin= CTypeBool::CreateOutputPin("value");		
	m_value= CTypeBool::CreateInstance();
	RegisterInputPin (*m_iPin);
	RegisterOutputPin (*m_oPin);		
	
	// Process arguments
	if (argc) {
		for (int i= 0; i< argc; ++i) {
			if (strcmp ("-v", argv[i])== 0) {
				// Value
				bool err= false;
				
				++i;
				if (i< argc) {
					if (strcmp("1", argv[i])== 0 || strcmp("true", argv[i])== 0) m_value->setValue(true);
					else if (strcmp("0", argv[i])== 0 || strcmp("false", argv[i])== 0) {  }
					else err= true;
				}
				else err= true;
				if (err) throw std::runtime_error("widget_checkbox. Wrong value for option --v");
			}
			else if (strcmp ("-l", argv[i])== 0) {
				// Label
				++i;

				if (i== argc) throw std::runtime_error("widget_checkbox. Missing value for -l argument");
				m_label= argv[i];
			}			
			else if (strlen(argv[i])) {
				string error_msg("widget_checkbox. Unknown option:");
				error_msg+= argv[i];
				throw std::runtime_error(error_msg);
			}
		}
	}
}

int CheckboxComponent::DoInitialize()
{
	m_oPin->Send(m_value);

	return 0;
}

wxWindow* CheckboxComponent::GetGUI(wxWindow * parent) {
	assert (wxIsMainThread());
	if (m_panel) {
		// Already created
		assert (false);
		getSpCoreRuntime()->LogMessage(ICoreRuntime::LOG_ERROR, "panel alredy open", "checkbox");
		return NULL;
	}
	else {
		m_panel= new CheckboxPanel();
		m_panel->SetComponent(this);
		m_panel->Create(parent);
	}

	return m_panel;
}

// 
// Called from GUI
//	

void CheckboxComponent::SetCheckboxValue (bool v)
{
	if (m_value->getValue()!= v) {
		m_value->setValue(v);
		m_oPin->Send(m_value);
	}
}

bool CheckboxComponent::GetCheckboxValue() const
{
	return m_value->getValue();
}

void CheckboxComponent::OnPanelDestroyed ()
{
	assert (wxIsMainThread());
	m_panel= NULL;
}

// 
// Private methods
//	

void CheckboxComponent::OnPinValue (const CTypeBool & msg)
{
	m_value->setValue(msg.getValue());
	if (m_panel) m_panel->ValueChanged();
}

CheckboxComponent::~CheckboxComponent()
{
	assert (wxIsMainThread());
	if (m_panel) {
		m_panel->SetComponent(NULL);
		m_panel->Close();
		m_panel= NULL;
	}
}

//////////////////////////////////////////////////////////////////////////////

/*!
 * CheckboxPanel type definition
 */

IMPLEMENT_DYNAMIC_CLASS( CheckboxPanel, wxPanel )

// New event to comunicate updates to GUI
DECLARE_LOCAL_EVENT_TYPE(wxEVT_SPCHECKBOX_VALUE_CHANGE, -1)
DEFINE_LOCAL_EVENT_TYPE(wxEVT_SPCHECKBOX_VALUE_CHANGE)

/*!
 * CheckboxPanel event table definition
 */

BEGIN_EVENT_TABLE( CheckboxPanel, wxPanel )

////@begin CheckboxPanel event table entries
    EVT_CHECKBOX( ID_CHECKBOX, CheckboxPanel::OnCheckboxClick )

////@end CheckboxPanel event table entries

	EVT_COMMAND  (wxID_ANY, wxEVT_SPCHECKBOX_VALUE_CHANGE, CheckboxPanel::OnValueChanged)	

END_EVENT_TABLE()


/*!
 * CheckboxPanel constructors
 */

CheckboxPanel::CheckboxPanel()
{
    Init();
}

CheckboxPanel::CheckboxPanel( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name )
{
    Init();
    Create(parent, id, pos, size, style, name);
}


/*!
 * CheckboxPanel creator
 */

bool CheckboxPanel::Create( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name )
{
////@begin CheckboxPanel creation
    SetExtraStyle(wxWS_EX_BLOCK_EVENTS);
    wxPanel::Create( parent, id, pos, size, style, name );

    CreateControls();
    if (GetSizer())
    {
        GetSizer()->SetSizeHints(this);
    }
    Centre();
////@end CheckboxPanel creation
    return true;
}


/*!
 * CheckboxPanel destructor
 */

CheckboxPanel::~CheckboxPanel()
{
	if (m_component!= NULL) {
		m_component->OnPanelDestroyed();
		m_component= NULL;
	}
////@begin CheckboxPanel destruction
////@end CheckboxPanel destruction
}


/*!
 * Member initialisation
 */

void CheckboxPanel::Init()
{
	m_component= NULL;
////@begin CheckboxPanel member initialisation
    m_theCheckbox = NULL;
////@end CheckboxPanel member initialisation
}


/*!
 * Control creation for CheckboxPanel
 */

void CheckboxPanel::CreateControls()
{    
////@begin CheckboxPanel content construction
    CheckboxPanel* itemPanel1 = this;

    wxBoxSizer* itemBoxSizer2 = new wxBoxSizer(wxVERTICAL);
    itemPanel1->SetSizer(itemBoxSizer2);

    m_theCheckbox = new wxCheckBox;
    m_theCheckbox->Create( itemPanel1, ID_CHECKBOX, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
    m_theCheckbox->SetValue(false);
    m_theCheckbox->SetName(_T("Checkbox"));
    itemBoxSizer2->Add(m_theCheckbox, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5);

////@end CheckboxPanel content construction

	assert (m_component);

	// Label
	if (m_component->GetLabel().size()) {
		wxString label(m_component->GetLabel().c_str(), wxConvUTF8);
		m_theCheckbox->SetLabel(label);
	}

	m_theCheckbox->SetValue(m_component->GetCheckboxValue());
}


/*!
 * Should we show tooltips?
 */

bool CheckboxPanel::ShowToolTips()
{
    return true;
}

/*!
 * Get bitmap resources
 */

wxBitmap CheckboxPanel::GetBitmapResource( const wxString& name )
{
    // Bitmap retrieval
////@begin CheckboxPanel bitmap retrieval
    wxUnusedVar(name);
    return wxNullBitmap;
////@end CheckboxPanel bitmap retrieval
}

/*!
 * Get icon resources
 */

wxIcon CheckboxPanel::GetIconResource( const wxString& name )
{
    // Icon retrieval
////@begin CheckboxPanel icon retrieval
    wxUnusedVar(name);
    return wxNullIcon;
////@end CheckboxPanel icon retrieval
}


/*!
 * wxEVT_COMMAND_CHECKBOX_CLICKED event handler for ID_CHECKBOX
 */

void CheckboxPanel::OnCheckboxClick( wxCommandEvent& event )
{
	if (m_component)
		m_component->SetCheckboxValue(event.IsChecked());
	
    event.Skip(false);
}

void CheckboxPanel::ValueChanged()
{
	wxCommandEvent event(wxEVT_SPCHECKBOX_VALUE_CHANGE);
		
	if (!wxIsMainThread()) wxPostEvent(this, event);
	else OnValueChanged( event );
}

void CheckboxPanel::OnValueChanged( wxCommandEvent& )
{
	if (m_component)
		m_theCheckbox->SetValue(m_component->GetCheckboxValue());
}

};
