⛏️ index : haiku.git

/*
 * Copyright (c) 2008-2009 Gerasim Troeglazov (3dEyes**). All Rights Reserved.
 * This file may be used under the terms of the MIT License.
 */


#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#include <Bitmap.h>
#include <Catalog.h>
#include <Polygon.h>
#include <Screen.h>
#include <ScreenSaver.h>
#include <StringView.h>
#include <View.h>


class Clock : public BScreenSaver
{
public:
					Clock(BMessage *message, image_id id);
	void			StartConfig(BView *view);
	status_t		StartSaver(BView *view, bool preview);
	void			Draw(BView *view, int32 frame);	
private:
	void 			_drawBlock(BView *view, float x, float y, float alpha,
						float size);
	void 			_drawArrow(BView *view, float x0, float y0, float angle,
						float length, float coeff, float width);
	float 			centerX, centerY;
};


extern "C" _EXPORT BScreenSaver *instantiate_screen_saver(BMessage *message,
	image_id image)
{
	return new Clock(message, image);
}


Clock::Clock(BMessage *message, image_id image)
	:
	BScreenSaver(message, image)
{
	B_TRANSLATE_MARK_SYSTEM_NAME_VOID("SimpleClock");
}


void
Clock::StartConfig(BView *view)
{
	BStringView	*aboutView = new BStringView(BRect(10, 10, 200, 35),
		B_EMPTY_STRING, "Simple Clock");
	aboutView->SetFont(be_bold_font);
	aboutView->SetFontSize(15);
	view->AddChild(aboutView);
	aboutView = new BStringView(BRect(10, 40, 200, 65),
		B_EMPTY_STRING, " Ver 1.0, ©3dEyes**");
	view->AddChild(aboutView);
}


status_t
Clock::StartSaver(BView *view, bool)
{
	SetTickSize(1000000);
	return B_OK;
}


void
Clock::Draw(BView *view, int32)
{
	BScreen screenView;
	BBitmap bufferBitmap(view->Bounds(), screenView.ColorSpace(), true);
	BView offscreenView(view->Bounds(), NULL, 0, 0);
	bufferBitmap.AddChild(&offscreenView);
	bufferBitmap.Lock();

	float width = view->Bounds().Width();
	float height = view->Bounds().Height();
	float zoom = (height / 1024.0) * 0.65;
	
	time_t timeInfo;
	time(&timeInfo);
	struct tm *nowTime = localtime(&timeInfo);

	float secondVal = nowTime->tm_sec;
	float minuteVal = nowTime->tm_min + (secondVal / 60.0);
	float hourVal = nowTime->tm_hour + (minuteVal / 60.0);

	offscreenView.SetHighColor(0, 0, 0);
	offscreenView.SetLowColor(0, 0, 0);
	offscreenView.FillRect(offscreenView.Bounds());

	offscreenView.SetHighColor(200, 200, 200);
	
	centerX = width / 2.0;
	centerY = height / 2.0;

	float markAngle = 0;
	float markRadius = 510.0 * zoom;

	for(int mark = 0; mark < 60; mark++, markAngle += (2 * M_PI) / 60) {
		float x = centerX + markRadius * cos(markAngle);
		float y = centerY + markRadius * sin(markAngle);
		_drawBlock(&offscreenView, x, y, markAngle, 14.0 * zoom);
	}

	offscreenView.SetHighColor(255, 255, 255);

	markAngle = 0;
	markRadius = 500.0 * zoom;
	
	for (int mark = 0; mark < 12; mark++, markAngle += (2 * M_PI) / 12) {
		float x = centerX + markRadius * cos(markAngle);
		float y = centerY + markRadius * sin(markAngle);
		_drawBlock(&offscreenView, x, y, markAngle, 32 * zoom);
	}

	offscreenView.SetHighColor(255, 255, 255);
	_drawArrow(&offscreenView, centerX, centerY,
		((2 * M_PI / 60) * minuteVal) - (M_PI / 2), 220 * zoom, 1, 8 * zoom);

	_drawArrow(&offscreenView, centerX, centerY,
		((2 * M_PI / 12) * hourVal) - (M_PI / 2), 140 * zoom, 1, 14 * zoom);
	offscreenView.FillEllipse(BPoint(centerX, centerY),
		24 * zoom, 24 * zoom);
	
	offscreenView.SetHighColor(250, 20, 20);
	_drawArrow(&offscreenView, centerX, centerY,
		((2 * M_PI / 60) * secondVal) - (M_PI / 2), 240 * zoom, 1, 4 * zoom);
	offscreenView.FillEllipse(BPoint(centerX, centerY),
		20 * zoom, 20 * zoom);

	offscreenView.Sync();
	bufferBitmap.Unlock();
	view->DrawBitmap(&bufferBitmap);
	bufferBitmap.RemoveChild(&offscreenView);
}


void
Clock::_drawBlock(BView *view, float x, float y, float alpha, float size)
{
	float blockAngles[4] = {alpha - (M_PI / 12), alpha + (M_PI / 12),
		alpha + M_PI - (M_PI / 12), alpha + M_PI + (M_PI / 12)};
	
	BPoint blockPoints[4];
	for (int index = 0; index < 4; index++) {
		blockPoints[index].x = x + size * cos(blockAngles[index]);
		blockPoints[index].y = y + size * sin(blockAngles[index]);
	}
	view->FillPolygon(&blockPoints[0], 4);
}


void
Clock::_drawArrow(BView *view, float x0, float y0, float angle, float length,
	float coeff, float width)
{
	float alpha = width / length;

	float x = x0 + length * cos(angle);
	float y = y0 + length * sin(angle);

	float size = length * coeff;

	float blockAngles[4] = {angle - alpha, angle + alpha,
		angle + M_PI - alpha, angle + M_PI + alpha};

	BPoint blockPoints[4];
	for(int index = 0; index < 4; index++) {
		blockPoints[index].x = x + size * cos(blockAngles[index]);
		blockPoints[index].y = y + size * sin(blockAngles[index]);
	}
	view->FillPolygon(&blockPoints[0], 4);
}