aboutsummaryrefslogtreecommitdiff
path: root/v_windows/v/examples/clock
diff options
context:
space:
mode:
Diffstat (limited to 'v_windows/v/examples/clock')
-rw-r--r--v_windows/v/examples/clock/clock.v168
1 files changed, 168 insertions, 0 deletions
diff --git a/v_windows/v/examples/clock/clock.v b/v_windows/v/examples/clock/clock.v
new file mode 100644
index 0000000..61e4430
--- /dev/null
+++ b/v_windows/v/examples/clock/clock.v
@@ -0,0 +1,168 @@
+// An X11 clock modeled after https://en.wikipedia.org/wiki/Station_clock
+// This is a small V example that was based off of the fireworks example.
+// Written by Stefan Schroeder in 2021 for the v project examples.
+// See LICENSE for license information.
+import os
+import gg
+import gx
+import math
+import time
+
+const (
+ // All coordinates are designed for a clock size of this many pixel.
+ // You cannot change the size of the clock by adjusting this value.
+ design_size = 700
+ center = 350
+
+ // Half the width of a tic-mark.
+ tw = 9
+ // Height of a minute tic-mark. (hour is twice, 3-hour is thrice)
+ th = 25
+ // Padding of tic-mark to window border
+ tp = 10
+
+ tic_color = gx.Color{
+ r: 50
+ g: 50
+ b: 50
+ }
+ hand_color = gx.black
+ second_hand_color = gx.red
+)
+
+struct App {
+ minutes_tic []f32 = [f32(center - tw), tp, center + tw, tp, center + tw, tp, center + tw,
+ tp +
+ 1 * th, center - tw, tp + 1 * th]
+ hours_tic []f32 = [f32(center - tw), tp, center + tw, tp, center + tw, tp, center + tw, tp + 2 * th,
+ center - tw, tp + 2 * th]
+ hours3_tic []f32 = [f32(center - tw), tp, center + tw, tp, center + tw, tp, center + tw, tp + 3 * th,
+ center - tw, tp + 3 * th]
+
+ hour_hand []f32 = [f32(329), 161, 350, 140, 371, 161, 371, 413, 329, 413]
+ minute_hand []f32 = [f32(334.25), 40.25, 350, 24.5, 365.75, 40.25, 365.75, 427, 334.25, 427]
+ second_hand []f32 = [f32(345.8), 38.5, 350, 34.3, 354.2000, 38.5, 358.75, 427, 341.25, 427]
+mut:
+ gg &gg.Context = 0
+ draw_flag bool = true
+ dpi_scale f32 = 1.0
+}
+
+fn on_frame(mut app App) {
+ if !app.draw_flag {
+ return
+ }
+ app.gg.begin()
+
+ for i in 0 .. 60 { // draw minute tics
+ draw_convex_poly_rotate(mut app.gg, app.dpi_scale, app.minutes_tic, tic_color,
+ i * 6)
+ }
+ for i in 0 .. 12 { // hours
+ draw_convex_poly_rotate(mut app.gg, app.dpi_scale, app.hours_tic, tic_color, i * 30)
+ }
+ for i in 0 .. 4 { // 3 hours
+ draw_convex_poly_rotate(mut app.gg, app.dpi_scale, app.hours3_tic, tic_color,
+ i * 90)
+ }
+
+ n := time.now()
+
+ // draw hour hand
+ i := f32(n.hour) + f32(n.minute) / 60.0
+ draw_convex_poly_rotate(mut app.gg, app.dpi_scale, app.hour_hand, hand_color, i * 30)
+
+ // draw minute hand
+ mut j := f32(n.minute)
+ if n.second == 59 { // make minute hand move smoothly
+ j += f32(math.sin(f32(n.microsecond) / 1e6 * math.pi / 2.0))
+ }
+ draw_convex_poly_rotate(mut app.gg, app.dpi_scale, app.minute_hand, hand_color, j * 6)
+
+ // draw second hand with smooth transition
+ k := f32(n.second) + f32(math.sin(f32(n.microsecond) / 1e6 * math.pi / 2.0))
+ draw_convex_poly_rotate(mut app.gg, app.dpi_scale, app.second_hand, second_hand_color,
+ 0 + k * 6)
+
+ app.gg.end()
+}
+
+// Rotate a polygon round the centerpoint
+fn draw_convex_poly_rotate(mut ctx gg.Context, dpi_scale f32, points []f32, c gx.Color, angle f32) {
+ sa := math.sin(math.pi * angle / 180.0)
+ ca := math.cos(math.pi * angle / 180.0)
+
+ mut rotated_points := []f32{}
+ for i := 0; i < points.len / 2; i++ {
+ x := points[2 * i]
+ y := points[2 * i + 1]
+ xn := f32((x - center) * ca - (y - center) * sa)
+ yn := f32((x - center) * sa + (y - center) * ca)
+ rotated_points << (xn + center) * dpi_scale
+ rotated_points << (yn + center) * dpi_scale
+ }
+ ctx.draw_convex_poly(rotated_points, c)
+}
+
+fn (mut app App) resize() {
+ size := gg.window_size()
+ // avoid calls when minimized
+ if size.width < 2 && size.height < 2 {
+ return
+ }
+ w := f32(size.width) / design_size
+ h := f32(size.height) / design_size
+ app.dpi_scale = if w < h { w } else { h }
+}
+
+fn on_event(e &gg.Event, mut app App) {
+ match e.typ {
+ .resized, .resumed {
+ app.resize()
+ }
+ .iconified {
+ app.draw_flag = false
+ }
+ .restored {
+ app.draw_flag = true
+ app.resize()
+ }
+ else {
+ if e.typ == .key_down {
+ match e.key_code {
+ .q {
+ println('Good bye.')
+ // do we need to free anything here?
+ exit(0)
+ }
+ else {}
+ }
+ }
+ }
+ }
+}
+
+// is needed for easier diagnostics on windows
+[console]
+fn main() {
+ println("Press 'q' to quit.")
+ mut font_path := os.resource_abs_path(os.join_path('../assets/fonts/', 'RobotoMono-Regular.ttf'))
+ $if android {
+ font_path = 'fonts/RobotoMono-Regular.ttf'
+ }
+
+ mut app := &App{}
+
+ app.gg = gg.new_context(
+ width: design_size
+ height: design_size
+ window_title: 'Clock!'
+ bg_color: gx.white
+ user_data: app
+ frame_fn: on_frame
+ event_fn: on_event
+ font_path: font_path
+ )
+
+ app.gg.run()
+}