// Author  : /* Your name */
// Date	  : /* Your date */
// Version : /* Your version number */

// Give your DLL file the same name as your component or change the code line
// Replace the /*ComponentName*/ tags with the name of your component via
// CTRL+S R

#include "com_server.h"
#include <owl/inputdia.h>

const int XMIN = GetSystemMetrics(SM_CXMIN)-2*GetSystemMetrics(SM_CXSIZEFRAME);

const int WindowWidth = /* Your default window width e.g. */ XMIN;
const int WindowHeight = /* Your default window height e.g. */ 3*XMIN;
const TColor BackgroundColor = /* Your default background color e.g. */ TColor::LtGray;

DEFINE_GUID(CLSID_/*ComponentName*/,
	/* Your GUID e.g. */ 0x681299f0,0x8bb4,0x11d3,0xad,0xaa,0x00,0x60,0x67,0x49,0x62,0x45);

class /*ComponentName*/Win: public TWindow {
public:
	/*ComponentName*/Win(TWindow* parent, ImpComponent* pcomp,
		/* Your connections which have influence on your window layout e.g. */
		ByteConnection& in);
	void setTitle(string t);
	/* Your public memberfunctions */
private:
	virtual void SetupWindow();
	virtual void Paint(TDC& dc, bool, TRect&);
	/* Your notification memberfunctions e.g. */ void inChanged();
	void CmConnect();
	void CmChangeTitle();
	void CmRestoreWSize();
	void CmAbout();
	/* Your other command memberfunctions for use in the pop-up menu */
	void EvSize(uint, TSize&);
	void EvKeyDown(uint key, uint repeatCount, uint flags);
	void EvSysKeyDown(uint key, uint repeatCount, uint flags);
	void EvLButtonDown(uint modKeys, TPoint& point);
	/* Your other window event memberfunctions */

	CallOnChange</* Your connection type e.g. */ BYTE, /*ComponentName*/Win>
		/* Your callOnChange objects e.g. */ coc_in;
	string title;
	ImpComponent* pComp;
	/* Your private variables */

 DECLARE_RESPONSE_TABLE(/*ComponentName*/Win);
};

DEFINE_RESPONSE_TABLE1(/*ComponentName*/Win, TWindow)
	EV_WM_SIZE,
	EV_WM_KEYDOWN,
	EV_WM_SYSKEYDOWN,
	EV_WM_LBUTTONDOWN,
	EV_COMMAND(10, CmConnect),
	EV_COMMAND(20, CmChangeTitle),
	EV_COMMAND(30, CmRestoreWSize),
	EV_COMMAND(40, CmAbout),
END_RESPONSE_TABLE;

class /*ComponentName*/: public ImpComponent {
public:
	/*ComponentName*/();
	/* Your public memberfunctions */
private:
	virtual HWND CreateComponentWindow(HWND parent);
	static int number_of_/*ComponentName*/_started;
	/* Your private memberfunctions e.g. */ void inputChanged();
	/*ComponentName*/Win* /*ComponentName*/Window;

	/* Your connection point e.g. */ ByteConnection in;
	/* Your connection point e.g. */ ByteConnection out;

	/* Your private variables */

	CallOnChange</* Your connection type e.g. */ BYTE, /*ComponentName*/>
		/* Your callOnChange objects e.g. */ coc_in;
};

/*ComponentName*/Win::/*ComponentName*/Win(TWindow* parent,
		ImpComponent* pcomp,
		/* Your connection points e.g. */ ByteConnection& in0):
			TWindow(parent, 0 , new TModule("/*ComponentName*/.dll")),
			coc_in(in0, this, &/*ComponentName*/Win::inChanged),
			pComp(pcomp) {
	pComp->SetCompWinIcon(GetModule()->LoadIcon("mainIcon"));
	Attr.W=WindowWidth;
	Attr.H=WindowHeight;
}

void /*ComponentName*/Win::setTitle(string t) {
	title=t;
	pComp->SetCompWinTitle(t.c_str());
}

void /*ComponentName*/Win::SetupWindow() {
	TWindow::SetupWindow();
	SetBkgndColor(BackgroundColor);
	Parent->SetBkgndColor(BackgroundColor);
	ContextPopupMenu = new TPopupMenu;
	// This TPopupMenu will be deleted by the TWindow destructor.
	// So don't call delete yourself!
	ContextPopupMenu->AppendMenu(MF_STRING, 10, "&Connect...");
	ContextPopupMenu->AppendMenu(MF_SEPARATOR);
	ContextPopupMenu->AppendMenu(MF_STRING, 20, "Change &Window Title...");
	ContextPopupMenu->AppendMenu(MF_STRING, 30, "Restore Window &Size");
	ContextPopupMenu->AppendMenu(MF_SEPARATOR);
	ContextPopupMenu->AppendMenu(MF_STRING, 40, "&About...");
}

void /*ComponentName*/Win::Paint(TDC& dc, bool, TRect&) {
	/* Your painting code e.g.*/
	TRect r(GetClientRect());
	r.top+=(r.bottom-r.top)*((255-coc_in->get())/255.0);
	TBrush b(TColor::LtGreen);
	dc.FillRect(r, b);
}

void /*ComponentName*/Win::EvSize(uint sizeType, TSize& size) {
	TWindow::EvSize(sizeType, size);
	Invalidate(true);
}

void /*ComponentName*/Win::EvKeyDown(uint key, uint repeatCount, uint flags) {
	switch (key) {
		case 'C': CmConnect(); break;
		case 'W': CmChangeTitle(); break;
		case 'S': CmRestoreWSize(); break;
		case 'A': CmAbout(); break;
		case VK_APPS: {
			TPopupMenu* menu(GetContextMenu());
			if (menu) {
				TPoint point(0, 0);
				ClientToScreen(point);
				menu->TrackPopupMenu(TPM_LEFTALIGN|TPM_RIGHTBUTTON, point, 0, HWindow);
			}
		}
		default:
			TWindow::EvKeyDown(key, repeatCount, flags);
			ForwardMessage(Parent->GetHandle());
	}
}

void /*ComponentName*/Win::EvSysKeyDown(uint key, uint repeatCount, uint flags) {
	if (key==VK_F10) {
		TPopupMenu* menu(GetContextMenu());
		if (menu) {
			TPoint point(0, 0);
			ClientToScreen(point);
			menu->TrackPopupMenu(TPM_LEFTALIGN|TPM_RIGHTBUTTON, point, 0, HWindow);
		}
	}
	else {
		TWindow::EvSysKeyDown(key, repeatCount, flags);
		ForwardMessage(Parent->GetHandle());
	}
}

void /*ComponentName*/Win::EvLButtonDown(uint modKeys, TPoint& point) {
	TWindow::EvLButtonDown(modKeys, point);
	/* Your code for left mouse button click e.g. */
	MessageBox("You clicked your right mouse button!", "Hello");
}

void /*ComponentName*/Win::inChanged() {
	Invalidate(true);
}

void /*ComponentName*/Win::CmConnect() {
	pComp->ConnectDialog();
}

void /*ComponentName*/Win::CmChangeTitle() {
	char buffer[256];
	strncpy(buffer, title.c_str(), 255);
	buffer[255]='\0';
	if (TInputDialog(this, "/*ComponentName*/", "Change the title:", buffer, 255, GetModule()).Execute()==IDOK) {
		setTitle(buffer);
	}
}

void /*ComponentName*/Win::CmRestoreWSize() {
	TRect wr(Parent->GetWindowRect());
	TRect pr(Parent->Parent->GetWindowRect());
	TRect cr(Parent->GetClientRect());
	int hMarge(wr.Width()-cr.Width());
	int vMarge(wr.Height()-cr.Height());
	int x(wr.left-pr.left-2);
	int y(wr.top-pr.top-2);
	TRect r(x, y, x+hMarge+WindowWidth, y+vMarge+WindowHeight);
	Parent->MoveWindow(r, true);
}

void /*ComponentName*/Win::CmAbout() {
	TDialog(this, 100).Execute();
}

int /*ComponentName*/::number_of_/*ComponentName*/_started = 0;

/*ComponentName*/::/*ComponentName*/(): /*ComponentName*/Window(0),
		coc_in(in, this, &/*ComponentName*/::inputChanged) {
	Set/*ComponentName*/("/*ComponentName*/");
	Expose(in, /* Your connection point name e.g. */"Input",
		/* Your prefered connection e.g. */"a");
	Expose(out, /* Your connection point name e.g. */"Output (NOT Input)",
		/* Your prefered connection e.g. */"b");
}

void /*ComponentName*/::inputChanged() {
	/* Your behavioral code e.g. */
	out.set(0xff-in.get());
}

HWND /*ComponentName*/::CreateComponentWindow(HWND parent){
	if (/*ComponentName*/Window==0) {
		++number_of_/*ComponentName*/_started;
		/*ComponentName*/Window = new /*ComponentName*/Win(::GetWindowPtr(parent),
			this, in);
		// This /*ComponentName*/Win will be deleted by its parent.
		// So don't call delete yourself!
		/*ComponentName*/Window->Create();
		char buffer[256];
		ostrstream o(buffer, sizeof buffer);
		o<<"/*ComponentName*/ ("<<number_of_/*ComponentName*/_started<<")"<<ends;
		/*ComponentName*/Window->setTitle(o.str());
	}
	return /*ComponentName*/Window->GetHandle();
}

void RegisterClassFactories() {
	ClassFactory* new_classfactory(
		new ComponentFactory</*ComponentName*/>(CLSID_/*ComponentName*/));
	class_factories.push_back(new_classfactory);
}


