/******************************************************************************
 *
 * Copyright (c) 1999	TOSHIYUKI ARAI. ALL RIGHTS RESERVED. 
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions, and the following disclaimer.
 *  
 * 2. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *
 *	CircleThread.cpp
 *
 *****************************************************************************/

// SOL++2000
// 2000.02.18


#include <sol\Semaphore.h>
#include <sol\Exception.h>
#include <sol\Stdio.h>
#include <sol\ApplicationView.h>
#include <sol\Thread.h>
#include <sol\ClientDC.h>
#include <sol\Brush.h>
#include <sol\Pen.h>
#include <sol\PaintDC.h>

class CircleThread :public Thread {
	BOOL	doing;
	int		count;
	int		radius;
	View*	view;
	int		x, y;
	int		px, py;
	int		vx, vy;
	// regin
	int		rx1, rx2;
	int		ry1, ry2;
public:
	CircleThread(View* view, int radius, int count);
	virtual void run();
	void	terminate() { doing = FALSE; }
};


CircleThread::CircleThread(View* view, int radius, int count)
	:Thread(),
	doing(TRUE)
{

	this -> view   = view;
	this -> radius = 4; //radius;
	this -> count  = count;
	vx = 3;//11;
	vy = 4; //8;
	x  = -10;
	y  = -9;
	px = -10;
	py = -9;
	rx1 = 4;
	rx2 = 100;//24;
	ry1 = 4;
	ry2 = 100;//24;
}



void CircleThread::run()
{
	int i = 0;

	while(doing) {
		sleep(100);
		ClientDC dc(view);
		int r = radius;

		px = x;
		py = y;
		x += vx;
		y += vy;
		// right
		if(vx > 0 && x +r > rx2) {
			x = 2* rx2 - x;
			vx = -vx;
		}

		//left
		else if(vx < 0 && x -r < rx1) {
			x = 2*rx1 - x;
			vx = -vx;
		}
		// 
		if(vy > 0 && y +r >ry2) {
			y = 2* ry2 - y;
			vy = -vy;
		}
		else if( vy < 0 && y -r < ry1){
			y = 2*ry1 - y;
			vy = -vy;
		}
	 		
		Pen pen(PS_INSIDEFRAME, 10, RGB(255,100, 255));
		
		HGDIOBJ prev = dc.select(&pen);
				
		dc.setROP2(R2_XORPEN);

		dc.ellipse(px + r, py + r, px- r, py -r);

		dc.ellipse(x + r, y + r, x- r, y -r);
		dc.select(prev);
		i++;
	}
}



class HelloView :public ApplicationView {
	CircleThread* thread;
  public:
	HelloView(Application& applet, const char* name, Args& args)
		:ApplicationView(applet, name, args)
	{
		thread = new CircleThread(this, 10, 100);
		thread->start();
		addEventHandler(WM_PAINT, this,
			(Handler)&HelloView::paint, null);
	}

	~HelloView() 
	{
		thread -> terminate();
		thread -> wait(INFINITE);
		delete thread;
	}

	long paint(Event& event) {
		PaintDC dc(this);
		dc.rectangle(0, 0, 104, 104);
		return 0L;
	}
};


void	Main(int argc, char** argv)
{
	const char* name = "HelloView";
	Application applet(name, argc, argv);
	try {
		Args args;
		HelloView hellov(applet, name, args);
		hellov.realize();
		applet.run();
	}
	catch (Exception& ex) {
		ex.print();
	}
}
