/////////////////////////////////////////////////////////////////////////////
// Name:        choice.h
// Purpose:     
// Author:      César Mauri Loba
// Modified by: 
// Created:     26/05/2011 21:44:47
// 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/>.    
/////////////////////////////////////////////////////////////////////////////

#ifndef _CHOICE_H_
#define _CHOICE_H_


/*!
 * Includes
 */

////@begin includes
////@end includes
#include "base_widget.h"
#include <wx/panel.h>
#include <wx/choice.h>
#include <wx/icon.h>
#include <wx/stattext.h>

#include <boost/thread/mutex.hpp>

/*!
 * Forward declarations
 */

////@begin forward declarations
////@end forward declarations

/*!
 * Control identifiers
 */

////@begin control identifiers
#define ID_CHOICEPANEL 10009
#define ID_CHOICE 10010
#define SYMBOL_CHOICEPANEL_STYLE wxTAB_TRAVERSAL
#define SYMBOL_CHOICEPANEL_TITLE _("Choice")
#define SYMBOL_CHOICEPANEL_IDNAME ID_CHOICEPANEL
#define SYMBOL_CHOICEPANEL_SIZE wxSize(400, 300)
#define SYMBOL_CHOICEPANEL_POSITION wxDefaultPosition
////@end control identifiers

namespace mod_widgets {

class ChoiceComponent;


/*!
 * ChoicePanel class declaration
 */

class ChoicePanel: public wxPanel
{    
    DECLARE_DYNAMIC_CLASS( ChoicePanel )
    DECLARE_EVENT_TABLE()

public:
    /// Constructors
    ChoicePanel();
    ChoicePanel( wxWindow* parent, wxWindowID id = SYMBOL_CHOICEPANEL_IDNAME, const wxPoint& pos = SYMBOL_CHOICEPANEL_POSITION, const wxSize& size = SYMBOL_CHOICEPANEL_SIZE, long style = SYMBOL_CHOICEPANEL_STYLE );

    /// Creation
    bool Create( wxWindow* parent, wxWindowID id = SYMBOL_CHOICEPANEL_IDNAME, const wxPoint& pos = SYMBOL_CHOICEPANEL_POSITION, const wxSize& size = SYMBOL_CHOICEPANEL_SIZE, long style = SYMBOL_CHOICEPANEL_STYLE );

    /// Destructor
    ~ChoicePanel();

	// Set destruction callback. NULL removes.
	void SetComponent(ChoiceComponent* component) { m_component= component; }

	// Notify changes
	void ValueChanged();

private:
    /// Initialises member variables
    void Init();

    /// Creates the controls and sizers
    void CreateControls();

////@begin ChoicePanel event handler declarations

    /// wxEVT_COMMAND_CHOICE_SELECTED event handler for ID_CHOICE
    void OnChoiceSelected( wxCommandEvent& event );

////@end ChoicePanel event handler declarations
	void OnValueChanged( wxCommandEvent& event );

////@begin ChoicePanel member function declarations

    /// Retrieves bitmap resources
    wxBitmap GetBitmapResource( const wxString& name );

    /// Retrieves icon resources
    wxIcon GetIconResource( const wxString& name );
////@end ChoicePanel member function declarations

    /// Should we show tooltips?
    static bool ShowToolTips();

////@begin ChoicePanel member variables
    wxStaticText* m_staLabel;
    wxChoice* m_theChoice;
////@end ChoicePanel member variables
	ChoiceComponent* m_component;
};

/**
	widget_choice component

	Input pins:
		options (any)	List of strings to show
		selection (int)	Index to select (-1 is none)
		enable (bool)	Enable/disable control

	Output pins:
		selection (int)	Index selected when changed
		selection_string (string)	String selected when changed

	Command line:
		[-e [0|1|false|true]]	Enabled. Control will be initially enabled (def. 1)
		[-l <label> ]	Label. If empty, no label is shown.
		[-o <options>]	Initial options list separeted by '|'
		[-v <num> ]		Option number initially selected.
*/
class ChoiceComponent : public BaseWidgetComponent<ChoicePanel,ChoiceComponent> {
public:
	static const char* getTypeName() { return "widget_choice"; };
	virtual const char* GetTypeName() const { return ChoiceComponent::getTypeName(); };

	//
	// Component methods
	//
	ChoiceComponent(const char * name, int argc, const char * argv[]);
	
	virtual int DoInitialize();

	// 
	// Called from GUI
	//	

	void GetOptionsAndSelection(std::vector<std::string>& op, int& selection) const;
	
	// Return true if a new item has been selected
	bool SetSelection(int s);

private:
	//
	// Data members
	//
	int m_selection;
	mutable boost::mutex m_mutex;
	std::vector<std::string> m_options;
	
	SmartPtr<spcore::IOutputPin> m_oPinSelection;
	SmartPtr<spcore::IOutputPin> m_oPinSelectionString;

	//
	// Private methods
	//
	void OnPinOptions (const spcore::CTypeAny & msg);
	void OnPinSelect (const spcore::CTypeInt & msg);

	//
	// Input pin classes
	//
	class InputPinOptions
		: public spcore::CInputPinWriteOnly<spcore::CTypeAny, ChoiceComponent> {
	public:
		InputPinOptions (ChoiceComponent & component)
		: spcore::CInputPinWriteOnly<spcore::CTypeAny, ChoiceComponent>("options", component) { }

		virtual int DoSend(const spcore::CTypeAny & msg) {
			m_component->OnPinOptions(msg);
			return 0;
		}
	};

	class InputPinSelect
		: public spcore::CInputPinWriteOnly<spcore::CTypeInt, ChoiceComponent> {
	public:
		InputPinSelect (ChoiceComponent & component)
		: spcore::CInputPinWriteOnly<spcore::CTypeInt, ChoiceComponent>("selection", component) { }

		virtual int DoSend(const spcore::CTypeInt & msg) {
			m_component->OnPinSelect(msg);
			return 0;
		}
	};
};

typedef spcore::ComponentFactory<ChoiceComponent> ChoiceComponentFactory;

};	// namespace

#endif
    // _CHOICE_H_
