#if defined(__FLAT__)
#include <common/progress.hpp>
#include <common/rect.hpp>
#include <common/except.hpp>

char Progress::szClassName[]="ProgressControlWindow";
char Progress::szFontName[]="Helv";

Progress::Progress(GUIWindow &parentWindow)
:	mhParentWindow((HWND)parentWindow),
	mhProcessInstance(parentWindow.processInstance()),
	mhProgressControl(0), mhStaticControl(0), mhBrush(0),
	mFont(szFontName,8), mItemIndex(0L), mItemCount(0L), mCanCancel(FALSE)
{
	::InitCommonControls();
  mControlColorHandler.setCallback(this,&Progress::controlColorHandler);
	mCreateHandler.setCallback(this,&Progress::createHandler);
	mPaintHandler.setCallback(this,&Progress::paintHandler);
	mTimerHandler.setCallback(this,&Progress::timerHandler);
	mCharHandler.setCallback(this,&Progress::charHandler);
	initialPoint(parentWindow);
	insertHandlers();
	registerClass();
	createWindow();
	createControls();
}

Progress::Progress(GUIWindow &parentWindow,String captionString)
:	mhParentWindow((HWND)parentWindow),
	mhProcessInstance(parentWindow.processInstance()),
	mhProgressControl(0), mhStaticControl(0), mCaptionString(captionString),
	mhBrush(0), mFont(szFontName,8), mItemIndex(0L), mItemCount(0L), mCanCancel(FALSE)
{
	::InitCommonControls();
  mControlColorHandler.setCallback(this,&Progress::controlColorHandler);
	mCreateHandler.setCallback(this,&Progress::createHandler);
	mPaintHandler.setCallback(this,&Progress::paintHandler);
	mTimerHandler.setCallback(this,&Progress::timerHandler);
	mCharHandler.setCallback(this,&Progress::charHandler);
	initialPoint(parentWindow);
	insertHandlers();
	registerClass();
	createWindow();
	createControls();
}

Progress::Progress(GUIWindow &parentWindow,String captionString,Block<String> &iconNames)
:	mhParentWindow((HWND)parentWindow),
	mhProcessInstance(parentWindow.processInstance()),
	mhProgressControl(0), mhStaticControl(0), mCaptionString(captionString),
	mhBrush(0), mFont(szFontName,8), mItemIndex(0L), mItemCount(0L), mCanCancel(FALSE)
{
	::InitCommonControls();
  mControlColorHandler.setCallback(this,&Progress::controlColorHandler);
	mCreateHandler.setCallback(this,&Progress::createHandler);
	mPaintHandler.setCallback(this,&Progress::paintHandler);
	mTimerHandler.setCallback(this,&Progress::timerHandler);
	mCharHandler.setCallback(this,&Progress::charHandler);
	insertIcons(iconNames);
	initialPoint(parentWindow);
	insertHandlers();
	registerClass();
	createWindow();
	createControls();
}

Progress::~Progress()
{
  shutdown();
	removeHandlers();
}

void Progress::insertHandlers(void)
{
  MMTimer::insertHandler(&mTimerHandler);
	Window::insertHandler(VectorHandler::ControlColorHandler,&mControlColorHandler);
  Window::insertHandler(VectorHandler::CreateHandler,&mCreateHandler);
  Window::insertHandler(VectorHandler::PaintHandler,&mPaintHandler);
  Window::insertHandler(VectorHandler::CharHandler,&mCharHandler);
}

void Progress::removeHandlers(void)
{
  MMTimer::removeHandler();
	Window::removeHandler(VectorHandler::ControlColorHandler,&mControlColorHandler);
	Window::removeHandler(VectorHandler::CreateHandler,&mCreateHandler);
  Window::removeHandler(VectorHandler::PaintHandler,&mPaintHandler);
  Window::removeHandler(VectorHandler::CharHandler,&mCharHandler);
}

void Progress::insertIcons(Block<String> &iconNames)
{
	WORD iconCount(iconNames.size());

	mIconFrame.remove();
	for(short itemIndex=0;itemIndex<iconCount;itemIndex++)
		mIconFrame+=PureIcon(mhProcessInstance,iconNames[itemIndex]);
	return;
}

void Progress::createWindow(void)
{
	::CreateWindow(szClassName,mCaptionString,
		WS_OVERLAPPED|WS_CAPTION|WS_CLIPCHILDREN|0x04L,
		mInitialPoint.x(),mInitialPoint.y(),PWcx,PWcy,
		mhParentWindow,NULL,mhProcessInstance,(LPSTR)this);
}

void Progress::initialPoint(const GUIWindow &parentWindow)
{
	Rect windowRect;

	if(!parentWindow.width()&&!parentWindow.height())
	{
		HWND hDesktopWindow(::GetDesktopWindow());
		Rect windowRect;

		::GetWindowRect(hDesktopWindow,(RECT*)windowRect);
		mInitialPoint.x(windowRect.left()+((windowRect.right()-windowRect.left()-PWcx)/2));
    mInitialPoint.y(windowRect.top()+((windowRect.bottom()-windowRect.top()-PWcy)/2));
	}
	else
	{
		if(parentWindow.width()>PWcx&&parentWindow.height()>PWcy)
		{
			parentWindow.windowRect(windowRect);
			mInitialPoint.x(windowRect.left()+((parentWindow.width()-PWcx)/2));
			mInitialPoint.y(windowRect.top()+((parentWindow.height()-PWcy)/2));
		}
		else
		{
			mInitialPoint.x(CW_USEDEFAULT);
			mInitialPoint.y(CW_USEDEFAULT);
		}
	}
}

void Progress::registerClass(void)
{
	WNDCLASS wndClass;

	if(::GetClassInfo(mhProcessInstance,szClassName,(WNDCLASS FAR*)&wndClass))return;
	wndClass.style         =CS_HREDRAW|CS_VREDRAW;
	wndClass.lpfnWndProc   =(WNDPROC)Window::WndProc;
	wndClass.cbClsExtra    =0;
	wndClass.cbWndExtra    =sizeof(Progress*);
	wndClass.hInstance     =mhProcessInstance;
	wndClass.hIcon         =::LoadIcon(NULL,IDI_APPLICATION);
	wndClass.hCursor       =::LoadCursor(NULL,IDC_ARROW);
	wndClass.hbrBackground =(HBRUSH)::GetStockObject(LTGRAY_BRUSH);
	wndClass.lpszMenuName  =0;
	wndClass.lpszClassName =szClassName;
	::RegisterClass(&wndClass);
	if(0==::GetClassInfo(mhProcessInstance,szClassName,(WNDCLASS FAR*)&wndClass))throw(NullError());
}

void Progress::createControls(void)
{
	mhBrush=::CreateSolidBrush(RGB(bkRed,bkGreen,bkBlue));
	mhProgressControl=::CreateWindow("msctls_progress32","",WS_CHILD,PCx,PCy,PCcx,PCcy,(HWND)*this,(HMENU)ProgressBarID,mhProcessInstance,0);
	mhStaticControl=::CreateWindow("STATIC","",WS_CHILD|WS_CLIPSIBLINGS|SS_LEFTNOWORDWRAP,SCx,SCy,SCcx,SCcy,(HWND)*this,(HMENU)0,mhProcessInstance,0);
	::SendMessage(mhStaticControl,WM_SETFONT,(WPARAM)(HFONT)mFont,0L);
}

void Progress::destroyControls(void)
{
	if(mhBrush){::DeleteObject(mhBrush);mhBrush=0;}
	if(mhProgressControl){::DestroyWindow(mhProgressControl);mhProgressControl=0;}
	if(mhStaticControl){::DestroyWindow(mhStaticControl);mhStaticControl=0;}
}

void Progress::shutdown(void)
{
  stopTimer();
	destroyControls();
	destroy();
}

void Progress::show(WORD onOff)
{
	WORD showState(onOff?SW_SHOW:SW_HIDE);

	if(!isOkay())return;
	Window::show(showState);
	::ShowWindow(mhProgressControl,showState);
	::ShowWindow(mhStaticControl,showState);
	update();
	::UpdateWindow(mhProgressControl);
	::UpdateWindow(mhStaticControl);
	if(SW_SHOW==showState)
	{
		mIconFrame.drawIcon(PureDevice(*this),Point(5,5));
		startTimer(750L);
	}
	else stopTimer();
}

WORD Progress::range(DWORD itemCount)
{
	if(!isOkay())return FALSE;
	mItemIndex=1L;
	mItemCount=itemCount;
	progressMessage(SetRange,0,MAKELPARAM(0,FullRange));
	progressMessage(SetPos,0);
	return TRUE;
}

WORD Progress::operator++(void)
{
	if(!isOkay()||!mItemCount)return FALSE;
	progressMessage(SetPos,((float)mItemIndex/(float)mItemCount)*(float)FullRange);
	mItemIndex++;
	return TRUE;
}

WORD Progress::operator+=(const String &messageString)
{
	if(!isOkay())return FALSE;
	operator++();
	if(!messageString.isNull())staticMessage(messageString);
	return TRUE;
}

WORD Progress::setText(const String &messageString)
{
	if(!isOkay()||messageString.isNull())return FALSE;
	staticMessage(messageString);
	return TRUE;
}

WORD Progress::getText(String &messageString)
{
	if(!isOkay())return FALSE;
  String staticString;
	sendMessage(mhStaticControl,WM_GETTEXT,(WPARAM)String::MaxString-1,(LPARAM)(LPSTR)staticString);
	messageString=staticString;
  return TRUE;
}

WORD Progress::setPosition(DWORD position)
{
	if(!isOkay()||!mItemCount)return FALSE;
  mItemIndex=position;
	progressMessage(SetPos,((float)mItemIndex/(float)mItemCount)*(float)FullRange);
	return TRUE;
}

WORD Progress::reset(void)
{
	if(!isOkay())return FALSE;
	mItemIndex=1L;
	mItemCount=0L;
	progressMessage(SetPos,0);
	return TRUE;
}

CallbackData::ReturnType Progress::createHandler(CallbackData &/*someCallbackData*/)
{
	return (CallbackData::ReturnType)FALSE;
}

CallbackData::ReturnType Progress::charHandler(CallbackData &someCallbackData)
{
  if(canCancel()&&EscapeKey==someCallbackData.wParam())shutdown();
	return (CallbackData::ReturnType)FALSE;
}

CallbackData::ReturnType Progress::paintHandler(CallbackData &/*someCallbackData*/)
{
	return (CallbackData::ReturnType)FALSE;
}

CallbackData::ReturnType Progress::controlColorHandler(CallbackData &someCallbackData)
{
	::SetBkColor((HDC)someCallbackData.wParam(),RGB(bkRed,bkGreen,bkBlue));
	return (CallbackData::ReturnType)mhBrush;
}

CallbackData::ReturnType Progress::timerHandler(CallbackData &/*someCallbackData*/)
{
	if(isOkay())mIconFrame.drawIcon(PureDevice(*this),Point(5,5));
	return (CallbackData::ReturnType)TRUE;
}
#endif
																													 