Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Analog Clock Win 95 Style #6760

Merged
merged 3 commits into from
May 9, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
AnalogClock: Added icons, and created analog clock application
  • Loading branch information
ReasonablePanic committed May 8, 2021
commit 79a869853b627ce19d29b9502e51fde8d497f5d3
4 changes: 4 additions & 0 deletions Base/res/apps/AnalogClock.af
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[App]
Name=Analog Clock
Executable=/bin/AnalogClock
Category=Utilities
Binary file added Base/res/icons/16x16/app-analog-clock.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Base/res/icons/32x32/app-analog-clock.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
126 changes: 126 additions & 0 deletions Userland/Applications/AnalogClock/AnalogClock.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
/*
* Copyright (c) 2021, Erlend Høier <[email protected]>
*
* SPDX-License-Identifier: BSD-2-Clause
*/

#include "AnalogClock.h"
#include <LibCore/DateTime.h>
#include <LibGUI/Application.h>
#include <LibGfx/Palette.h>
#include <LibGfx/Path.h>

void AnalogClock::draw_graduations(GUI::Painter& painter, Gfx::IntRect& rect, int x, int y)
{
rect.set_x(x);
rect.set_y(y);

painter.fill_rect(rect, palette().active_window_border2());

painter.draw_line(rect.top_left(), rect.top_right(), palette().threed_highlight());
painter.draw_line(rect.bottom_left(), rect.bottom_right(), palette().active_window_border1().darkened(0.9f));
painter.draw_line(rect.bottom_right(), rect.top_right(), palette().active_window_border1().darkened(0.9f));
painter.draw_line(rect.top_left(), rect.bottom_left(), palette().threed_highlight());
}

// To create an even clock face it's necessary to mirror the graduations positions
void AnalogClock::draw_mirrored_graduations(GUI::Painter& painter, Gfx::IntRect& rect, int x, int y, int rect_center_offset)
{
auto w = this->rect().center().x() - rect_center_offset;
auto h = this->rect().center().y() - rect_center_offset;

draw_graduations(painter, rect, x + w, y + h);
draw_graduations(painter, rect, y + w, x + h);
draw_graduations(painter, rect, -x + w, y + h);
draw_graduations(painter, rect, -y + w, x + h);
draw_graduations(painter, rect, x + w, -y + h);
draw_graduations(painter, rect, y + w, -x + h);
draw_graduations(painter, rect, -x + w, -y + h);
draw_graduations(painter, rect, -y + w, -x + h);
}

void AnalogClock::draw_face(GUI::Painter& painter)
{
int x, y;
double angle = 2 * M_PI / 60;

for (int i = 0; i <= 7; ++i) {

ReasonablePanic marked this conversation as resolved.
Show resolved Hide resolved
x = sin(angle * static_cast<double>(i)) * m_clock_face_radius;
y = cos(angle * static_cast<double>(i)) * m_clock_face_radius;

draw_mirrored_graduations(painter, m_small_graduation_square, x, y, 1);

if (i % 5 == 0)
draw_mirrored_graduations(painter, m_big_graduation_square, x, y, 2);
}
}

void AnalogClock::draw_hand(GUI::Painter& painter, double angle, double length, Gfx::Color hand_color)
{
if (angle >= 2 * M_PI)
angle -= 2 * M_PI;

double cosine = cos(angle);
double sine = sin(angle);

double hand_x = (rect().center().x() + (cosine * length));
double hand_y = (rect().center().y() + (sine * length));

Gfx::IntPoint indicator_point(hand_x, hand_y);
Gfx::IntPoint tail_point(rect().center().x() + (-cosine * m_hand_tail_length), rect().center().y() + (-sine * m_hand_tail_length));
Gfx::IntPoint right_wing_point(rect().center().x() + (-sine * m_hand_wing_span), rect().center().y() + (cosine * m_hand_wing_span));
Gfx::IntPoint left_wing_point(rect().center().x() + (sine * m_hand_wing_span), rect().center().y() + (-cosine * m_hand_wing_span));

Gfx::Path hand_fill;
hand_fill.move_to(static_cast<Gfx::FloatPoint>(indicator_point));
hand_fill.line_to(static_cast<Gfx::FloatPoint>(left_wing_point));
hand_fill.line_to(static_cast<Gfx::FloatPoint>(tail_point));
hand_fill.line_to(static_cast<Gfx::FloatPoint>(right_wing_point));
hand_fill.close();

painter.fill_path(hand_fill, hand_color, Gfx::Painter::WindingRule::Nonzero);

// Draw highlight depending on the angle, this creates a subtle 3d effect.
// remember the angle value is offset by half pi.
if (angle > M_PI_2 - (M_PI / 3) && angle < M_PI + (M_PI / 3)) {
painter.draw_line(left_wing_point, indicator_point, hand_color.darkened(0.7f));
painter.draw_line(left_wing_point, tail_point, hand_color.darkened(0.7f));

painter.draw_line(right_wing_point, indicator_point, palette().threed_highlight());
painter.draw_line(right_wing_point, tail_point, palette().threed_highlight());
} else {
painter.draw_line(right_wing_point, indicator_point, hand_color.darkened(0.7f));
painter.draw_line(right_wing_point, tail_point, hand_color.darkened(0.7f));

painter.draw_line(left_wing_point, indicator_point, palette().threed_highlight());
painter.draw_line(left_wing_point, tail_point, palette().threed_highlight());
}
};

void AnalogClock::draw_seconds_hand(GUI::Painter& painter, double angle)
{
double hand_x = (rect().center().x() + (cos(angle)) * (m_clock_face_radius - 10));
double hand_y = (rect().center().y() + (sin(angle)) * (m_clock_face_radius - 10));

Gfx::IntPoint indicator_point(hand_x, hand_y);
painter.draw_line(rect().center(), indicator_point, palette().base_text());
}

void AnalogClock::paint_event(GUI::PaintEvent& event)
{
GUI::Painter painter(*this);
painter.clear_rect(event.rect(), palette().window());

draw_face(painter);

auto time = Core::DateTime::now();
auto minute = time.minute() * (2 * M_PI) / 60;
auto hour = (minute + (2 * M_PI) * time.hour()) / 12;
auto seconds = time.second() * (2 * M_PI) / 60;
auto angle_offset = M_PI_2;

draw_hand(painter, minute - angle_offset, m_minute_hand_length, palette().active_window_border2());
draw_hand(painter, hour - angle_offset, m_hour_hand_length, palette().active_window_border1());
draw_seconds_hand(painter, seconds - angle_offset);
}
48 changes: 48 additions & 0 deletions Userland/Applications/AnalogClock/AnalogClock.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* Copyright (c) 2021, Erlend Høier <[email protected]>
*
* SPDX-License-Identifier: BSD-2-Clause
*/

#pragma once

#include <LibGUI/Painter.h>
#include <LibGUI/Widget.h>

class AnalogClock : public GUI::Widget {
C_OBJECT(AnalogClock)
public:
~AnalogClock() override = default;

private:
AnalogClock()
: m_small_graduation_square(Gfx::IntRect({}, { 3, 3 }))
, m_big_graduation_square(Gfx::IntRect({}, { 5, 5 }))
{
start_timer(1000);
};
ReasonablePanic marked this conversation as resolved.
Show resolved Hide resolved

unsigned m_clock_face_radius = 70;
Gfx::IntRect m_small_graduation_square;
Gfx::IntRect m_big_graduation_square;

unsigned m_minute_hand_length = 58;
unsigned m_hour_hand_length = 42;

double m_hand_tail_length = 22;
double m_hand_wing_span = 5;
ReasonablePanic marked this conversation as resolved.
Show resolved Hide resolved

protected:
void paint_event(GUI::PaintEvent&) override;
void draw_face(GUI::Painter&);
void draw_mirrored_graduations(GUI::Painter&, Gfx::IntRect&, int x, int y, int rect_center_offset);
void draw_graduations(GUI::Painter&, Gfx::IntRect&, int x, int y);

void draw_hand(GUI::Painter&, double angle, double length, Gfx::Color hand_color);
void draw_seconds_hand(GUI::Painter&, double angle);

void timer_event(Core::TimerEvent&) override
{
update();
}
};
7 changes: 7 additions & 0 deletions Userland/Applications/AnalogClock/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
set(SOURCES
main.cpp
AnalogClock.cpp
)

serenity_app(AnalogClock ICON app-analog-clock)
target_link_libraries(AnalogClock LibGUI)
51 changes: 51 additions & 0 deletions Userland/Applications/AnalogClock/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* Copyright (c) 2021, Erlend Høier <[email protected]>
*
* SPDX-License-Identifier: BSD-2-Clause
*/

#include "AnalogClock.h"
#include <LibCore/DateTime.h>
#include <LibGUI/Application.h>
#include <LibGUI/Icon.h>
#include <LibGUI/Window.h>
#include <unistd.h>

int main(int argc, char** argv)
{

ReasonablePanic marked this conversation as resolved.
Show resolved Hide resolved
if (pledge("stdio recvfd sendfd accept rpath unix cpath wpath fattr thread", nullptr) < 0) {
ReasonablePanic marked this conversation as resolved.
Show resolved Hide resolved
perror("pledge");
return 1;
}

auto app = GUI::Application::construct(argc, argv);

if (pledge("stdio recvfd sendfd accept rpath cpath wpath thread", nullptr) < 0) {
ReasonablePanic marked this conversation as resolved.
Show resolved Hide resolved
perror("pledge");
return 1;
}

if (unveil("/res", "r") < 0) {
perror("unveil");
return 1;
}

if (unveil(nullptr, nullptr) < 0) {
perror("unveil");
return 1;
}

auto app_icon = GUI::Icon::default_icon("app-analog-clock");
auto window = GUI::Window::construct();

window->set_main_widget<AnalogClock>();
window->set_title(Core::DateTime::now().to_string("Clock %d-%m-%Y"));
ReasonablePanic marked this conversation as resolved.
Show resolved Hide resolved
window->set_icon(app_icon.bitmap_for_size(16));
window->resize(170, 170);
window->set_resizable(false);
window->set_double_buffering_enabled(true);
ReasonablePanic marked this conversation as resolved.
Show resolved Hide resolved

window->show();
return app->exec();
}
1 change: 1 addition & 0 deletions Userland/Applications/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
add_subdirectory(About)
add_subdirectory(AnalogClock)
add_subdirectory(Browser)
add_subdirectory(Calculator)
add_subdirectory(Calendar)
Expand Down