/* * Copyright (c) 2008-2009 Gerasim Troeglazov (3dEyes**). All Rights Reserved. * This file may be used under the terms of the MIT License. */ #include #include #include #include #include #include #include #include #include #include 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); }