/**********************************************************************

	Copyright (C) 2003-2004
	Hirohisa MORI <joshua@nichibun.ac.jp>
	Tomohito Nakajima <nakajima@zeta.co.jp>
	Tomoki Sekiyama <sekiyama@yahoo.co.jp>

	This program is free software; you can redistribute it
	and/or modify it under the terms of the GLOBALBASE
	Library General Public License (G-LGPL) as published by

	http://www.globalbase.org/

	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.

**********************************************************************/


#include "v/VButton.h"
#include "vobject_main.h"

class VPushButtonInfo : public VInfo
{
public:
	VPushButtonInfo(VObject *o, HWND h, int id) : VInfo(o, h, id), std_id(id) {}
	void alter_id(int id) {
		control_id = id;
		v_serialized_exec_sub(SetWindowLong, get_hwnd(), GWL_ID, id);
	}
	void revert_id() { alter_id(std_id); }
protected:
	int std_id;
};


HWND CreateButtonWindow(int exStyle, int style, HWND hwnd, int id);

VExError 
VPushButton::create_do(const VObjectStatus* s, int flags, VObject *parent, void * arg)
{
	DWORD style=WS_CHILD | BS_PUSHBUTTON | WS_TABSTOP;
	if(!s->enabled){
		style |= WS_DISABLED;
	}
	if(s->visible){
		style |= WS_VISIBLE;
	}
	
	/* find container window that will own this button.*/
	VContainerInfo *container_info = VInfo::get_container_info(parent);
	int id = container_info->get_next_control_id();
	HWND hwnd = v_serialized_exec_func(CreateButtonWindow, 0, style, container_info->get_hwnd(), id);
	info = new VPushButtonInfo(this, hwnd, s->id);
	
	/* set event handlers */
	info->add_message_handler(new OnCommand(::value_changed));
	
	return parent->add_child_do(this);
}

void
VPushButton::destroy_do(VObject *parent)
{
	VButton::destroy_do(parent);
}

VPushButton::~VPushButton()
{
}


VExError
VPushButton::get_status(VObjectStatus *s, int flags) const
{
	return VButton::get_status(s,flags);
};

VExError
VPushButton::set_status(const VObjectStatus *s, int flags)
{
	V_OP_START_EX
	VSize last_size = sts.min_size;
	VExError err = VButton::set_status(s,flags);

	if ( flags & VSF_ATTR ) {
		DWORD style = GetWindowLong(info->get_hwnd(), GWL_STYLE);

		if ( s->attr & cancel_button )
			((VPushButtonInfo*)info)->alter_id(IDCANCEL);
		else
			((VPushButtonInfo*)info)->revert_id();

		if ( s->attr & default_button ) {
			style |= BS_DEFPUSHBUTTON;
			((VPushButtonInfo*)info)->alter_id(IDOK);
			v_serialized_exec_sub(SetFocus, info->get_hwnd());
		}
		else {
			style &= ~BS_DEFPUSHBUTTON;
			if ( ! (s->attr & cancel_button) )
				((VPushButtonInfo*)info)->revert_id();
		}

		v_serialized_exec_sub(SetWindowLong, info->get_hwnd(), GWL_STYLE, style);
	}

	if ( flags & (VSF_DESC | VSF_VERTD) ) {
		sts.min_size.w += 18;
		sts.min_size.h += 8;
		
		if ( !sts.vert_desc )
			sts.min_size.w += 16;
		err.subcode1 &= ~(VSF_DESC | VSF_VERTD);
	}
	
	V_OP_END
	
	if ( (flags & (VSF_ALIGN | VSF_PADDING | VSF_VISIBLE)) ||
		 (flags & (VSF_DESC | VSF_WS | VSF_FSIZE)) &&
			(sts.min_size.w != last_size.w ||
			 sts.min_size.h != last_size.h) )
		VLayout::mark(this);
	return err;
}
