11#pragma once
22
33#include < Arduino.h>
4+ #include < GNSS.h>
45#include < cstring>
56
6- #include " ../domain/Clock.h"
7- #include " ../domain/Trip.h"
8- #include " Formatter.h"
9- #include " Mode.h"
10- #include < GNSS.h>
7+ #include " Frame.h"
118
12- template <typename ContextT > class Renderer {
9+ template <typename ScreenT > class Renderer {
1310private:
14- struct Metadata {
15- const char *title;
16- const char *unit;
17- };
18-
19- struct Frame {
20- Mode::ID modeId;
21- SpFixMode fixMode;
22- int numSatellites;
23- char value[32 ];
24-
25- bool operator ==(const Frame &other) const {
26- return modeId == other.modeId && fixMode == other.fixMode && numSatellites == other.numSatellites && strcmp (value, other.value ) == 0 ;
27- }
28- };
29-
3011 Frame lastFrame;
3112 bool firstRender = true ;
3213
@@ -35,141 +16,73 @@ template <typename ContextT> class Renderer {
3516 static constexpr int16_t FOOTER_HEIGHT = 12 ;
3617
3718public:
38- void render (ContextT &ctx, const Trip &trip, const Clock &clock, Mode::ID modeId, SpFixMode fixMode, int numSatellites) {
39- Frame currentFrame;
40- currentFrame.modeId = modeId;
41- currentFrame.fixMode = fixMode;
42- currentFrame.numSatellites = numSatellites;
43- getDisplayValue (trip, clock, modeId, currentFrame.value , sizeof (currentFrame.value ));
44-
45- if (!firstRender && currentFrame == lastFrame) return ;
19+ void render (ScreenT &screen, const Frame &frame) {
20+ if (!firstRender && frame == lastFrame) return ;
4621
4722 // Update Cache
4823 firstRender = false ;
49- lastFrame = currentFrame;
50-
51- ctx.clear ();
52- drawHeader (ctx, currentFrame.fixMode , currentFrame.numSatellites );
53- Metadata meta = getMetadata (currentFrame.modeId );
54- drawMainArea (ctx, meta.title , currentFrame.value , meta.unit );
55- drawFooter (ctx);
56- ctx.display ();
57- }
58-
59- private:
60- void getDisplayValue (const Trip &trip, const Clock &clock, Mode::ID modeId, char *buf, size_t size) {
61- switch (modeId) {
62- case Mode::ID::SPEED:
63- Formatter::formatSpeed (trip.speedometer .get (), buf, size);
64- return ;
65- case Mode::ID::MAX_SPEED:
66- Formatter::formatSpeed (trip.speedometer .getMax (), buf, size);
67- return ;
68- case Mode::ID::AVG_SPEED:
69- Formatter::formatSpeed (trip.getAvgSpeedKmh (), buf, size);
70- return ;
71- case Mode::ID::DISTANCE:
72- Formatter::formatDistance (trip.odometer .getDistance (), buf, size);
73- return ;
74- case Mode::ID::TIME: {
75- Clock::Time t = clock.getTime ();
76- Formatter::formatTime (t.hour , t.minute , buf, size);
77- return ;
78- }
79- case Mode::ID::MOVING_TIME:
80- Formatter::formatDuration (trip.stopwatch .getMovingTimeMs (), buf, size);
81- return ;
82- case Mode::ID::ELAPSED_TIME:
83- Formatter::formatDuration (trip.stopwatch .getElapsedTimeMs (), buf, size);
84- return ;
85- }
86- }
24+ lastFrame = frame;
8725
88- Metadata getMetadata (Mode::ID modeId) {
89- switch (modeId) {
90- case Mode::ID::SPEED:
91- return {" SPEED" , " km/h" };
92- case Mode::ID::MAX_SPEED:
93- return {" MAX SPEED" , " km/h" };
94- case Mode::ID::AVG_SPEED:
95- return {" AVG SPEED" , " km/h" };
96- case Mode::ID::TIME:
97- return {" TIME" , " " };
98- case Mode::ID::MOVING_TIME:
99- return {" TRIP TIME" , " " };
100- case Mode::ID::ELAPSED_TIME:
101- return {" ELAPSED TIME" , " " };
102- case Mode::ID::DISTANCE:
103- return {" DISTANCE" , " km" };
104- default :
105- return {" " , " " };
106- }
26+ screen.clear ();
27+ drawHeader (screen, frame.fixStatus , frame.satelliteCount );
28+ drawMainArea (screen, frame.title , frame.value , frame.unit );
29+ drawFooter (screen);
30+ screen.display ();
10731 }
10832
109- void drawHeader (ContextT &ctx, SpFixMode fixMode, int numSatellites) {
110- ctx.setTextSize (1 );
111- ctx.setTextColor (1 ); // WHITE
112- ctx.setCursor (0 , 0 );
113- switch (fixMode) {
114- case FixInvalid:
115- ctx.print (" WAIT" );
116- break ;
117- case Fix2D:
118- ctx.print (" 2D" );
119- break ;
120- case Fix3D:
121- ctx.print (" 3D" );
122- break ;
123- }
33+ private:
34+ void drawHeader (ScreenT &screen, const char *fixStatus, const char *numSatellites) {
35+ screen.setTextSize (1 );
36+ screen.setTextColor (1 ); // WHITE
37+ screen.setCursor (0 , 0 );
38+ screen.print (fixStatus);
12439
12540 // Right-aligned satellite count
126- char satBuf[8 ];
127- snprintf (satBuf, sizeof (satBuf), " St:%d" , numSatellites);
12841 int16_t x1, y1;
12942 uint16_t w, h;
130- ctx .getTextBounds (satBuf , 0 , 0 , &x1, &y1, &w, &h);
131- ctx .setCursor (ctx .getWidth () - w, 0 );
132- ctx .print (satBuf );
43+ screen .getTextBounds (numSatellites , 0 , 0 , &x1, &y1, &w, &h);
44+ screen .setCursor (screen .getWidth () - w, 0 );
45+ screen .print (numSatellites );
13346
13447 int16_t lineY = HEADER_HEIGHT - 2 ;
135- ctx .drawLine (0 , lineY, ctx .getWidth (), lineY, 1 ); // WHITE
48+ screen .drawLine (0 , lineY, screen .getWidth (), lineY, 1 ); // WHITE
13649 }
13750
138- void drawMainArea (ContextT &ctx , const char *title, const char *value, const char *unit) {
51+ void drawMainArea (ScreenT &screen , const char *title, const char *value, const char *unit) {
13952 int16_t contentTop = HEADER_HEIGHT;
140- int16_t contentY = ctx .getHeight () - FOOTER_HEIGHT;
53+ int16_t contentY = screen .getHeight () - FOOTER_HEIGHT;
14154
14255 // Title (Top Left of Main Area)
143- ctx .setTextSize (1 );
144- ctx .setCursor (0 , contentTop + 2 );
145- ctx .print (title);
56+ screen .setTextSize (1 );
57+ screen .setCursor (0 , contentTop + 2 );
58+ screen .print (title);
14659
14760 // Value (Large, Centered in remaining space)
148- ctx .setTextSize (2 );
61+ screen .setTextSize (2 );
14962 int16_t x1, y1;
15063 uint16_t w, h;
151- ctx .getTextBounds (value, 0 , 0 , &x1, &y1, &w, &h);
64+ screen .getTextBounds (value, 0 , 0 , &x1, &y1, &w, &h);
15265 int16_t valueY = (contentY + contentTop - h) / 2 ;
153- ctx .setCursor ((ctx .getWidth () - w) / 2 , valueY);
154- ctx .print (value);
66+ screen .setCursor ((screen .getWidth () - w) / 2 , valueY);
67+ screen .print (value);
15568
15669 // Unit (Bottom Right of Main Area)
15770 if (strlen (unit) != 0 ) {
158- ctx .setTextSize (1 );
159- ctx .getTextBounds (unit, 0 , 0 , &x1, &y1, &w, &h);
160- ctx .setCursor (ctx .getWidth () - w, contentY - h - 2 );
161- ctx .print (unit);
71+ screen .setTextSize (1 );
72+ screen .getTextBounds (unit, 0 , 0 , &x1, &y1, &w, &h);
73+ screen .setCursor (screen .getWidth () - w, contentY - h - 2 );
74+ screen .print (unit);
16275 }
16376 }
16477
165- void drawFooter (ContextT &ctx ) {
166- int16_t lineY = ctx .getHeight () - FOOTER_HEIGHT;
167- ctx .drawLine (0 , lineY, ctx .getWidth (), lineY, 1 ); // WHITE
78+ void drawFooter (ScreenT &screen ) {
79+ int16_t lineY = screen .getHeight () - FOOTER_HEIGHT;
80+ screen .drawLine (0 , lineY, screen .getWidth (), lineY, 1 ); // WHITE
16881
169- ctx .setTextSize (1 );
82+ screen .setTextSize (1 );
17083 int16_t textH = 8 ; // Approx height for size 1
17184 int16_t textY = lineY + (FOOTER_HEIGHT - textH) / 2 + 1 ;
172- ctx .setCursor (0 , textY);
173- ctx .print (" Ready" ); // Placeholder for status
85+ screen .setCursor (0 , textY);
86+ screen .print (" Ready" ); // Placeholder for status
17487 }
17588};
0 commit comments