RosettaCodeData/Task/Draw-a-clock/Ada/draw-a-clock.ada

100 lines
4.0 KiB
Ada

with Ada.Numerics.Elementary_Functions;
with Ada.Calendar.Formatting;
with Ada.Calendar.Time_Zones;
with SDL.Video.Windows.Makers;
with SDL.Video.Renderers.Makers;
with SDL.Events.Events;
procedure Draw_A_Clock is
use Ada.Calendar;
use Ada.Calendar.Formatting;
Window : SDL.Video.Windows.Window;
Renderer : SDL.Video.Renderers.Renderer;
Event : SDL.Events.Events.Events;
Offset : Time_Zones.Time_Offset;
procedure Draw_Clock (Stamp : Time)
is
use SDL.C;
use Ada.Numerics.Elementary_Functions;
Radi : constant array (0 .. 59) of int := (0 | 15 | 30 | 45 => 2,
5 | 10 | 20 | 25 | 35 | 40 | 50 | 55 => 1,
others => 0);
Diam : constant array (0 .. 59) of int := (0 | 15 | 30 | 45 => 5,
5 | 10 | 20 | 25 | 35 | 40 | 50 | 55 => 3,
others => 1);
Width : constant int := Window.Get_Surface.Size.Width;
Height : constant int := Window.Get_Surface.Size.Height;
Radius : constant Float := Float (int'Min (Width, Height));
R_1 : constant Float := 0.48 * Radius;
R_2 : constant Float := 0.35 * Radius;
R_3 : constant Float := 0.45 * Radius;
R_4 : constant Float := 0.47 * Radius;
Hour : constant Hour_Number := Formatting.Hour (Stamp, Offset);
Minute : constant Minute_Number := Formatting.Minute (Stamp, Offset);
Second : constant Second_Number := Formatting.Second (Stamp);
function To_X (A : Float; R : Float) return int is
(Width / 2 + int (R * Sin (A, 60.0)));
function To_Y (A : Float; R : Float) return int is
(Height / 2 - int (R * Cos (A, 60.0)));
begin
SDL.Video.Renderers.Makers.Create (Renderer, Window.Get_Surface);
Renderer.Set_Draw_Colour ((0, 0, 150, 255));
Renderer.Fill (Rectangle => (0, 0, Width, Height));
Renderer.Set_Draw_Colour ((200, 200, 200, 255));
for A in 0 .. 59 loop
Renderer.Fill (Rectangle => (To_X (Float (A), R_1) - Radi (A),
To_Y (Float (A), R_1) - Radi (A), Diam (A), Diam (A)));
end loop;
Renderer.Set_Draw_Colour ((200, 200, 0, 255));
Renderer.Draw (Line => ((Width / 2, Height / 2),
(To_X (5.0 * (Float (Hour) + Float (Minute) / 60.0), R_2),
To_Y (5.0 * (Float (Hour) + Float (Minute) / 60.0), R_2))));
Renderer.Draw (Line => ((Width / 2, Height / 2),
(To_X (Float (Minute) + Float (Second) / 60.0, R_3),
To_Y (Float (Minute) + Float (Second) / 60.0, R_3))));
Renderer.Set_Draw_Colour ((220, 0, 0, 255));
Renderer.Draw (Line => ((Width / 2, Height / 2),
(To_X (Float (Second), R_4),
To_Y (Float (Second), R_4))));
Renderer.Fill (Rectangle => (Width / 2 - 3, Height / 2 - 3, 7, 7));
end Draw_Clock;
function Poll_Quit return Boolean is
use type SDL.Events.Event_Types;
begin
while SDL.Events.Events.Poll (Event) loop
if Event.Common.Event_Type = SDL.Events.Quit then
return True;
end if;
end loop;
return False;
end Poll_Quit;
begin
Offset := Time_Zones.UTC_Time_Offset;
if not SDL.Initialise (Flags => SDL.Enable_Screen) then
return;
end if;
SDL.Video.Windows.Makers.Create (Win => Window,
Title => "Draw a clock",
Position => SDL.Natural_Coordinates'(X => 10, Y => 10),
Size => SDL.Positive_Sizes'(300, 300),
Flags => SDL.Video.Windows.Resizable);
loop
Draw_Clock (Clock);
Window.Update_Surface;
delay 0.200;
exit when Poll_Quit;
end loop;
Window.Finalize;
SDL.Finalise;
end Draw_A_Clock;