#define HAND_HOURS_LENGTH_RATIO 0.55
#define HAND_MINUTES_LENGTH_RATIO 0.80
#define HAND_SECONDS_LENGTH1_RATIO 0.80 /* Main hand */
-#define HAND_SECONDS_LENGTH2_RATIO 0.30 /* Small hand on opposite side */
+#define HAND_SECONDS_LENGTH2_RATIO 0.25 /* Small extension on opposite side */
#define HAND_HOURS_WIDTH_RATIO 0.100
#define HAND_MINUTES_WIDTH_RATIO 0.070
#define CLOCK_DIGITS_FONTS_SIZE_RATIO 0.30
-#define CALENDAR_FONTS_SIZE 8.0
-
/* Manual tweak for '11' oclock position */
-#define ELEVENTH_OCLOCK_FIRST_DIGIT_XOFFSET 1.99
-#define TENTH_OCLOCK_FIRST_DIGIT_XOFFSET 1.75
+#define ELEVENTH_OCLOCK_FIRST_DIGIT_XOFFSET_RATIO 0.04
+#define TENTH_OCLOCK_FIRST_DIGIT_XOFFSET_RATIO 0.04
/* Offset between digits of '10', '11' and '12' oclock positions */
#define SECOND_DIGIT_XOFFSET 1.0
/* Radius of small dots near each digit */
#define DIGITS_DOTS_RADIUS_RATIO 0.04
+#define CALENDAR_TEXT_FONTS_SIZE_RATIO 0.15
+#define CALENDAR_DIGITS_FONTS_SIZE_RATIO (3.5 * CALENDAR_TEXT_FONTS_SIZE_RATIO)
+
+#define CALENDAR_WEEKDAY_Y_POSITION_RATIO 0.20
+#define CALENDAR_MONTH_Y_POSITION_RATIO 0.40
+#define CALENDAR_DAYOFMONTH_Y_POSITION_RATIO 0.92
+
struct hvclock_gtk_t {
GtkDrawingArea parent;
};
/* Starting mode is clock mode */
static int hvclock_mode = CLOCK_MODE;
+static double
+get_clock_face_radius(GtkWidget *clock)
+{
+ /* Compute clock face radius */
+ return (MIN(clock->allocation.width, clock->allocation.height) / 2) - 1;
+}
+
+static struct tm *
+clock_get_time(void)
+{
+ time_t now; /* Current system time */
+
+ /* Get the current time */
+ now = time(NULL);
+
+ /* Format and print the time, "ddd yyyy-mm-dd hh:mm:ss zzz" */
+ return localtime(&now);
+}
+
static void
draw_clock_background(GtkWidget *clock, cairo_t *cr)
{
center_x = clock->allocation.width / 2;
center_y = clock->allocation.height / 2;
- /* Clock face radius */
- radius = MIN(clock->allocation.width / 2, clock->allocation.height / 2)
- - 1;
+ radius = get_clock_face_radius(clock);
/* Position of digits as a radius ratio */
radius_numbers = radius * DIGITS_POSITION_RATIO;
/* Draw clock background and outer rim */
cairo_set_line_width(cr, 1.5);
cairo_arc(cr, center_x, center_y, radius, 0, 2 * M_PI);
- cairo_set_source_rgb(cr, 1, 1, 1);
+ cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
cairo_fill_preserve(cr); /* White background */
- cairo_set_source_rgb(cr, 0, 0, 0);
+ cairo_set_source_rgb(cr, 0.0, 0.0, 0.0);
cairo_stroke(cr); /* Black rim */
/* Draw clock tick marks on outer circle */
/* Manual tweak for '10' and '11' oclock position */
if (digit == 11)
first_digit_xoffset =
- ELEVENTH_OCLOCK_FIRST_DIGIT_XOFFSET;
+ ELEVENTH_OCLOCK_FIRST_DIGIT_XOFFSET_RATIO;
else if (digit == 10)
first_digit_xoffset =
- TENTH_OCLOCK_FIRST_DIGIT_XOFFSET;
-
+ TENTH_OCLOCK_FIRST_DIGIT_XOFFSET_RATIO;
}
xx = extents.width / divisor + extents.x_bearing;
yy = extents.height / 2 + extents.y_bearing;
text_start_x = center_x + radius_numbers * cos(angle) - xx +
- first_digit_xoffset;
+ (first_digit_xoffset * radius);
text_start_y = center_y - radius_numbers * sin(angle) - yy;
cairo_move_to(cr, text_start_x, text_start_y);
cairo_restore(cr);
}
-static struct tm *
-clock_get_time(void)
+static void
+draw_clock_hand_common(GtkWidget *clock, cairo_t *cr, double angle,
+ double len_main_ratio, double len_ext_ratio, double width_ratio)
{
- time_t now; /* Current system time */
+ gint center_x, center_y;
+ double sin_x, cos_y;
+ double radius, length;
- /* Get the current time */
- now = time(NULL);
+ radius = get_clock_face_radius(clock);
- /* Format and print the time, "ddd yyyy-mm-dd hh:mm:ss zzz" */
- return localtime(&now);
+ center_x = clock->allocation.width / 2;
+ center_y = clock->allocation.height / 2;
+
+ sin_x = sin(angle);
+ cos_y = cos(angle);
+
+ cairo_set_line_width(cr, radius * width_ratio);
+
+ length = radius * len_ext_ratio;
+ /*
+ * If optional extension len is non null, starting position is at the
+ * outer end of extension. Otherwise, starting position is at center.
+ */
+ cairo_move_to(cr, center_x - length * sin_x,
+ center_y - length * -cos_y);
+ length = radius * len_main_ratio;
+ cairo_line_to(cr, center_x + length * sin_x,
+ center_y + length * -cos_y);
+
+ cairo_stroke(cr);
}
static void
{
gint center_x, center_y;
double angle = M_PI / 3; /* Starting angle at '12' oclock position */
- double radius, length;
+ double radius;
int hours, minutes, seconds;
- double sin_x, cos_y;
struct tm *ts;
ts = clock_get_time();
center_x = clock->allocation.width / 2;
center_y = clock->allocation.height / 2;
- /* Clock face radius */
- radius = MIN(clock->allocation.width / 2, clock->allocation.height / 2)
- - 1;
+ radius = get_clock_face_radius(clock);
cairo_save(cr);
hours = ts->tm_hour;
minutes = ts->tm_min;
+ seconds = ts->tm_sec;
cairo_set_source_rgb(cr, 0.15, 0.15, 0.15);
cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND);
* 1/2 a degree (pi/360 r) per minute
*/
angle = M_PI / 6 * hours + M_PI / 360 * minutes;
- cairo_set_line_width(cr, radius * HAND_HOURS_WIDTH_RATIO);
- cairo_move_to(cr, center_x, center_y);
- length = radius * HAND_HOURS_LENGTH_RATIO;
- cairo_line_to(cr, center_x + length * sin(angle),
- center_y + length * -cos(angle));
- cairo_stroke(cr);
+ draw_clock_hand_common(clock, cr, angle,
+ HAND_HOURS_LENGTH_RATIO, 0, /* No extension */
+ HAND_HOURS_WIDTH_RATIO);
/* minute hand:
* the minute hand is rotated 6 degrees (pi/30 r) per minute
*/
angle = M_PI / 30 * minutes;
- cairo_move_to(cr, center_x, center_y);
- cairo_set_line_width(cr, radius * HAND_MINUTES_WIDTH_RATIO);
- length = radius * HAND_MINUTES_LENGTH_RATIO;
- cairo_line_to(cr, center_x + length * sin(angle),
- center_y + length * -cos(angle));
- cairo_stroke(cr);
+ draw_clock_hand_common(clock, cr, angle,
+ HAND_MINUTES_LENGTH_RATIO, 0, /* No extension */
+ HAND_MINUTES_WIDTH_RATIO);
/* seconds hand:
* operates identically to the minute hand
*/
if (hvclock_infos.show_seconds) {
- seconds = ts->tm_sec;
angle = M_PI / 30 * seconds;
- cairo_set_line_width(cr, radius * HAND_SECONDS_WIDTH_RATIO);
- sin_x = sin(angle);
- cos_y = cos(angle);
- length = radius * HAND_SECONDS_LENGTH2_RATIO;
- cairo_move_to(cr, center_x - length * sin_x,
- center_y - length * -cos_y);
- length = radius * HAND_SECONDS_LENGTH1_RATIO;
- cairo_line_to(cr, center_x + length * sin_x,
- center_y + length * -cos_y);
- cairo_stroke(cr);
+ draw_clock_hand_common(clock, cr, angle,
+ HAND_SECONDS_LENGTH1_RATIO,
+ HAND_SECONDS_LENGTH2_RATIO, /* Draw small extension */
+ HAND_SECONDS_WIDTH_RATIO);
}
/* Draw clock center circle */
}
static void
-draw_calendar(GtkWidget *clock, cairo_t *cr)
+calendar_display_test(GtkWidget *clock, struct tm *ts, cairo_t *cr,
+ char *format, double y_ratio, double font_ratio)
{
- gint center_x, center_y;
- char str[32];
- double x, y;
cairo_text_extents_t extents;
- struct tm *ts;
+ double x;
+ gint center_x, start_y;
+ double diameter;
+ char str[32];
+ diameter = 2 * get_clock_face_radius(clock);
center_x = clock->allocation.width / 2;
- center_y = clock->allocation.height / 2;
+ start_y = (clock->allocation.height / 2) - (diameter / 2);
- cairo_save(cr);
+ cairo_set_font_size(cr, diameter * font_ratio);
- cairo_select_font_face(cr, "sans-serif", CAIRO_FONT_SLANT_NORMAL,
- CAIRO_FONT_WEIGHT_BOLD);
- cairo_set_font_size(cr, CALENDAR_FONTS_SIZE);
- cairo_set_source_rgb(cr, 0, 0, 0);
-
- ts = clock_get_time();
+ /* Obtain ASCII reprentation of time format specified. */
+ strftime(str, 256, format, ts);
- /* Weekday */
- strftime(str, 256, "%A", ts);
/* Get text dimensions */
cairo_text_extents(cr, str, &extents);
x = center_x - extents.width / 2;
- cairo_move_to(cr, x, 11);
+ cairo_move_to(cr, x, start_y + (diameter * y_ratio));
cairo_show_text(cr, str);
+}
- strftime(str, 256, "%B", ts);
- /* Get text dimensions */
- cairo_text_extents(cr, str, &extents);
- x = center_x - extents.width / 2;
- cairo_move_to(cr, x, 25);
- cairo_show_text(cr, str);
+static void
+draw_calendar(GtkWidget *clock, cairo_t *cr)
+{
+ struct tm *ts;
- /* Day of month */
- cairo_set_font_size(cr, 30);
- strftime(str, 256, "%d", ts);
+ cairo_save(cr);
- fprintf(stderr, "TIME=[%s]\n", str);
+ cairo_select_font_face(cr, "sans-serif", CAIRO_FONT_SLANT_NORMAL,
+ CAIRO_FONT_WEIGHT_BOLD);
+ cairo_set_source_rgb(cr, 0.0, 0.0, 0.0); /* Black */
- if (str[0] == '0') {
- /* Remove leading zero */
- str[0] = str[1];
- str[1] = '\0';
- }
+ ts = clock_get_time();
- fprintf(stderr, "TIME=[%s]\n", str);
+ /* Weekday */
+ calendar_display_test(clock, ts, cr, "%A",
+ CALENDAR_WEEKDAY_Y_POSITION_RATIO,
+ CALENDAR_TEXT_FONTS_SIZE_RATIO);
- /* Get text dimensions */
- cairo_text_extents(cr, str, &extents);
- x = center_x - extents.width / 2;
- y = clock->allocation.height - 7;
- cairo_move_to(cr, x, y);
- cairo_show_text(cr, str);
+ /* Month */
+ calendar_display_test(clock, ts, cr, "%B",
+ CALENDAR_MONTH_Y_POSITION_RATIO,
+ CALENDAR_TEXT_FONTS_SIZE_RATIO);
+
+ /* Day of month */
+ /* Minus sign in format -> No leading zero */
+ calendar_display_test(clock, ts, cr, "%-d",
+ CALENDAR_DAYOFMONTH_Y_POSITION_RATIO,
+ CALENDAR_DIGITS_FONTS_SIZE_RATIO);
cairo_restore(cr);
}
cairo_paint(cr);
}
- cairo_rectangle(cr,
- event->area.x, event->area.y,
+ cairo_rectangle(cr, event->area.x, event->area.y,
event->area.width, event->area.height);
cairo_clip(cr);