/////////////////////////////////////////////////////////////////////////////
// Name:        wxMenuButton
// Purpose:     A button with a dropdown wxMenu
// Author:      John Labenski
// Modified by:
// Created:     11/05/2002
// Copyright:   (c) John Labenski
// Licence:     wxWidgets licence
/////////////////////////////////////////////////////////////////////////////

/*

wxMenuButton is a button that drops down an assigned wxMenu

Create the button with either a text or bitmap label.
    Create a new wxMenu and call AssignMenu and thats it. When you press the
    dropdown button the menu appears. When you press the label button the next
    wxITEM_RADIO (ie wxMenuItem::GetKind) in the menu is selected round robin.
    If there are no radio items then it really just acts like a menubar, though
    this is probably not too useful. The events sent in this case are EVT_MENUs
    either generated by the menu when you click on it or created when you click
    on the label to select the next radio item.
*/

#ifndef _WX_MENUBTN_H_
#define _WX_MENUBTN_H_

#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
#pragma interface "menubtn.h"
#endif

class wxMenu;
class wxBitmap;
class wxCustomButton;

//-----------------------------------------------------------------------------
// wxCustomButton styles
//-----------------------------------------------------------------------------

enum wxCustomButton_Style
{
	// Position of the label, use only one
	wxCUSTBUT_LEFT           = 0x0001,
	wxCUSTBUT_RIGHT          = 0x0002,
	wxCUSTBUT_TOP            = 0x0004,
	wxCUSTBUT_BOTTOM         = 0x0008,
	// Button style, use only one
	wxCUSTBUT_NOTOGGLE       = 0x0100,
	wxCUSTBUT_BUTTON         = 0x0200,
	wxCUSTBUT_TOGGLE         = 0x0400,
	wxCUSTBUT_BUT_DCLICK_TOG = 0x0800,
	wxCUSTBUT_TOG_DCLICK_BUT = 0x1000,
	// drawing styles
	wxCUSTBUT_FLAT           = 0x2000 // flat, mouseover raises if not depressed
};

//-----------------------------------------------------------------------------
// wxCustomButton
//-----------------------------------------------------------------------------

class WXDLLEXPORT wxCustomButton : public wxControl
{
public:

	wxCustomButton() : wxControl() {
		Init();
	}

	// wxToggleButton or wxButton compatible constructor (also wxTextCtrl)
	wxCustomButton(wxWindow* parent, wxWindowID id,
	               const wxString& label,
	               const wxPoint& pos = wxDefaultPosition,
	               const wxSize& size = wxDefaultSize,
	               long style = wxCUSTBUT_TOGGLE,
	               const wxValidator& val = wxDefaultValidator,
	               const wxString& name = wxT("wxCustomButton"))
		: wxControl()
	{
		Init();
		Create(parent,id,label,wxNullBitmap,pos,size,style,val,name);
	}

	// wxBitmapButton compatible constructor
	wxCustomButton(wxWindow *parent, wxWindowID id,
	               const wxBitmap& bitmap,
	               const wxPoint& pos = wxDefaultPosition,
	               const wxSize& size = wxDefaultSize,
	               long style = wxCUSTBUT_TOGGLE,
	               const wxValidator& val = wxDefaultValidator,
	               const wxString& name = wxT("wxCustomButton"))
		: wxControl()
	{
		Init();
		Create(parent,id,wxEmptyString,bitmap,pos,size,style,val,name);
	}

	// Native constructor
	wxCustomButton(wxWindow *parent, wxWindowID id,
	               const wxString& label, const wxBitmap& bitmap,
	               const wxPoint& pos = wxDefaultPosition,
	               const wxSize& size = wxDefaultSize,
	               long style = wxCUSTBUT_TOGGLE|wxCUSTBUT_BOTTOM,
	               const wxValidator& val = wxDefaultValidator,
	               const wxString& name = wxT("wxCustomButton"))
		: wxControl()
	{
		Init();
		Create(parent,id,label,bitmap,pos,size,style,val,name);
	}

	virtual ~wxCustomButton();

	bool Create(wxWindow* parent,
	            wxWindowID id,
	            const wxString& label,
	            const wxBitmap &bitmap,
	            const wxPoint& pos = wxDefaultPosition,
	            const wxSize& size = wxDefaultSize,
	            long style = 0,
	            const wxValidator& val = wxDefaultValidator,
	            const wxString& name = wxT("wxCustomButton"));

	bool GetValue() const {
		return m_down%2 != 0;
	}
	void SetValue( bool depressed );

	// Use combinations of wxCustomButton_Style(s)
	long GetButtonStyle() const {
		return m_button_style;
	}
	bool SetButtonStyle( long style );

	// Set the text label, wxEmptyString for none
	void SetLabel( const wxString &label );

	// set the bitmaps, ONLY this Label bitmap is used for calculating control size
	//   all bitmaps will be centered accordingly in any case
	//   call SetSet(GetBestSize()) if you change their size and want the control to resize appropriately
	void SetBitmapLabel(const wxBitmap& bitmap);
	void SetBitmapSelected(const wxBitmap& sel)      {
		m_bmpSelected = sel;
		CalcLayout(TRUE);
	};
	void SetBitmapFocus(const wxBitmap& focus)       {
		m_bmpFocus = focus;
		CalcLayout(TRUE);
	};
	void SetBitmapDisabled(const wxBitmap& disabled) {
		m_bmpDisabled = disabled;
		CalcLayout(TRUE);
	};
	// wxBitmapButton compatibility
	void SetLabel(const wxBitmap& bitmap)            {
		SetBitmapLabel(bitmap);
	}

	// retrieve the bitmaps
	const wxBitmap& GetBitmapLabel()    const {
		return m_bmpLabel;
	}
	const wxBitmap& GetBitmapSelected() const {
		return m_bmpSelected;
	}
	const wxBitmap& GetBitmapFocus()    const {
		return m_bmpFocus;
	}
	const wxBitmap& GetBitmapDisabled() const {
		return m_bmpDisabled;
	}

	// Creates a "disabled" bitmap by dithering it with the background colour
	wxBitmap CreateBitmapDisabled(const wxBitmap &bitmap) const;

	// set/get the margins (in pixels) around the label and bitmap
	//    if fit = TRUE then resize the button to fit
	void SetMargins(const wxSize &margin, bool fit = FALSE);

	// set/get the margins around the text label
	//    the inter bitmap/label margin is the max of either margin, not the sum
	void SetLabelMargin(const wxSize &margin, bool fit = FALSE);
	wxSize GetLabelMargin() const {
		return m_labelMargin;
	}
	// set/get the margins around the bitmap
	//    the inter bitmap/label margin is the max of either margin, not the sum
	void SetBitmapMargin(const wxSize &margin, bool fit = FALSE);
	wxSize GetBitmapMargin() const {
		return m_bitmapMargin;
	}

	// can be used to activate the focused behavior (see MenuButton)
	void SetFocused(bool focused) {
		m_focused = focused;
		Refresh(FALSE);
	}
	bool GetFocused() const {
		return m_focused;
	}

protected:
	void OnPaint(wxPaintEvent &event);
	void Redraw();
	virtual void Paint( wxDC &dc );

	virtual wxSize DoGetBestSize() const;

	virtual void SendEvent();

	void OnMouseEvents(wxMouseEvent &event);

	void OnSize( wxSizeEvent &event );

	virtual void CalcLayout(bool refresh);

	long m_down;         // toggle state if m_down%2 then depressed
	bool m_focused;     // mouse in window
	long m_button_style;

	// the bitmaps for various states
	wxBitmap m_bmpLabel,
	         m_bmpSelected,
	         m_bmpFocus,
	         m_bmpDisabled;

	// the margins around the label/bitmap
	wxSize m_labelMargin,
	       m_bitmapMargin;

	wxPoint m_bitmapPos,
	        m_labelPos;

	wxTimer *m_timer;

	wxEventType m_eventType;     // store the mouse event type

private:
	void Init();
	DECLARE_DYNAMIC_CLASS(wxCustomButton)
	DECLARE_EVENT_TABLE()
};

//-----------------------------------------------------------------------------
// wxMenuButton styles
//-----------------------------------------------------------------------------

#define wxMENUBUTTON_DROP_WIDTH  10
#define wxMENUBUTTON_DROP_HEIGHT 22

enum wxMenuButton_Styles
{
	wxMENUBUT_FLAT = wxCUSTBUT_FLAT
};

//-----------------------------------------------------------------------------
// wxMenuButton
//-----------------------------------------------------------------------------

class wxMenuButton : public wxControl
{
public:

	wxMenuButton() : wxControl() {
		Init();
	}

	// Use this constructor if you need one compatible with a wxBitmapButton
	//   setup the button later with AssignMenu
	wxMenuButton( wxWindow* parent, wxWindowID id,
	              const wxBitmap &bitmap,
	              const wxPoint& pos = wxDefaultPosition,
	              const wxSize& size = wxDefaultSize,
	              long style = 0,
	              const wxValidator& val = wxDefaultValidator,
	              const wxString& name = wxT("wxMenuButton"))
		: wxControl()
	{
		Init();
		Create(parent,id,wxEmptyString,bitmap,pos,size,style,val,name);
	}

	virtual ~wxMenuButton();

	bool Create( wxWindow* parent,
	             wxWindowID id,
	             const wxString &label,
	             const wxBitmap &bitmap,
	             const wxPoint& pos = wxDefaultPosition,
	             const wxSize& size = wxDefaultSize,
	             long style = wxNO_BORDER,
	             const wxValidator& val = wxDefaultValidator,
	             const wxString& name = wxT("wxMenuButton"));

	// Gets the id of the first selected radio item or wxNOT_FOUND (-1) if none
	int GetSelection() const;

	// This menu will be displayed when the dropdown button is pressed.
	//   if static_menu is FALSE it will be deleted when the buttton is destroyed.
	void AssignMenu(wxMenu *menu, bool static_menu = FALSE);

	wxMenu *GetMenu() const {
		return m_menu;
	}

	// get a pointer to the label button, for turning it into a toggle perhaps
	wxCustomButton *GetLabelButton() const {
		return m_labelButton;
	}
	wxCustomButton *GetDropDownButton() const {
		return m_dropdownButton;
	}

	void SetToolTip(const wxString &tip);
	void SetToolTip(wxToolTip *tip);

protected:
	void OnButton(wxCommandEvent &event);

	virtual void DoSetSize(int x, int y, int width, int height,
	                       int sizeFlags = wxSIZE_AUTO);

	virtual wxSize DoGetBestSize();

// FIXME! - in MSW the radio items don't check themselves
#ifdef __WXMSW__
	void OnMenu( wxCommandEvent &event );
#endif

	wxCustomButton *m_labelButton;
	wxCustomButton *m_dropdownButton;

	wxMenu *m_menu;
	bool m_menu_static;
	long m_style;

private:
	void Init();
	DECLARE_DYNAMIC_CLASS(wxMenuButton)
	DECLARE_EVENT_TABLE()
};

//-----------------------------------------------------------------------------
// wxMenuButtonEvents
//
// EVT_MENUBUTTON_OPEN(id, fn) - menu is about to be opened, (dis)(en)able items
//                               or call Veto() to stop menu from popping up
//                               this is a wxNotifyEvent
//-----------------------------------------------------------------------------

BEGIN_DECLARE_EVENT_TYPES()
DECLARE_LOCAL_EVENT_TYPE( wxEVT_MENUBUTTON_OPEN, 0 )
END_DECLARE_EVENT_TYPES()

#define EVT_MENUBUTTON_OPEN(id, fn) DECLARE_EVENT_TABLE_ENTRY(wxEVT_MENUBUTTON_OPEN, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) (wxCommandEventFunction) (wxNotifyEventFunction) & fn, (wxObject *) NULL ),

#endif  // _WX_MENUBTN_H_
