void draw_hand_layer(Layer* l, GContext* ctx) { GColor foreground_color = gcolor_legible_over(s_background_color); GRect bounds = layer_get_frame(l); GPoint center = GPoint(bounds.size.w / 2, bounds.size.h / 2); graphics_context_set_antialiased(ctx, true); graphics_context_set_stroke_color(ctx, foreground_color); graphics_context_set_fill_color(ctx, foreground_color); graphics_context_set_stroke_width(ctx, 3); time_t ts = time(NULL); struct tm* now = localtime(&ts); GRect reduced_bounds = bounds; int arc_offset = PBL_IF_ROUND_ELSE(24, 18); reduced_bounds.origin.x += arc_offset; reduced_bounds.origin.y += arc_offset; reduced_bounds.size.w -= (arc_offset << 1); reduced_bounds.size.h -= (arc_offset << 1); // initially, angle is relative to top (wrong) int angle = TRIG_MAX_ANGLE * (now->tm_hour * 60 + now->tm_min) / 1440; // make 0 at the bottom angle = (angle + TRIG_MAX_ANGLE / 2) % TRIG_MAX_ANGLE; graphics_context_set_fill_color(ctx, s_complementary_color); int hand_length = MIN(reduced_bounds.size.h, reduced_bounds.size.w) / 2; int radial_inset = ((hand_length - 20) * inset_pct) / 100; if (angle < TRIG_MAX_ANGLE / 2) { // first draw the bottom half graphics_fill_radial(ctx, reduced_bounds, GOvalScaleModeFitCircle, radial_inset, TRIG_MAX_ANGLE / 2, TRIG_MAX_ANGLE); graphics_draw_arc(ctx, reduced_bounds, GOvalScaleModeFitCircle, TRIG_MAX_ANGLE / 2, TRIG_MAX_ANGLE); // then the rest graphics_fill_radial(ctx, reduced_bounds, GOvalScaleModeFitCircle, radial_inset, 0, angle); graphics_draw_arc(ctx, reduced_bounds, GOvalScaleModeFitCircle, 0, angle); } else { graphics_fill_radial(ctx, reduced_bounds, GOvalScaleModeFitCircle, radial_inset, TRIG_MAX_ANGLE / 2, angle); graphics_draw_arc(ctx, reduced_bounds, GOvalScaleModeFitCircle, TRIG_MAX_ANGLE / 2, angle); } graphics_context_set_stroke_width(ctx, 2); GPoint hand_end; hand_end.y = (-cos_lookup(angle) * hand_length / TRIG_MAX_RATIO) + center.y; hand_end.x = (sin_lookup(angle) * hand_length / TRIG_MAX_RATIO) + center.x; graphics_draw_line(ctx, center, hand_end); GPoint sm_end = GPoint(center.x, center.y + hand_length); GPoint sm_start = GPoint(center.x, sm_end.y - radial_inset); graphics_draw_line(ctx, sm_start, sm_end); }
static void layer_update_proc(Layer *layer, GContext *ctx) { if (!should_update) { APP_LOG(APP_LOG_LEVEL_INFO, "Skipped update"); return; } GRect bounds = layer_get_bounds(layer); // Draw battery line graphics_context_set_stroke_color(ctx, s_charge_percent <= 30 ? GColorYellow : GColorRed); graphics_context_set_stroke_width(ctx, 3); int lineSegment = (bounds.size.w - 56) * 10/100; for (int i = 0; i < s_charge_percent / 10; i+=1) { graphics_draw_line(ctx, GPoint(28 + i * lineSegment, 120), GPoint(26 + (lineSegment * (i + 1)), 120)); } // Draw arcs for each STEP_DIVS GRect inset_bounds = grect_inset(bounds,GEdgeInsets(1,3,2,2)); graphics_context_set_fill_color(ctx, color_from_active_status(check_active_status())); // Get the sum steps so far today HealthValue steps = health_service_sum_today(HealthMetricStepCount); int lapSteps = steps%STEPS_LAP; int lapSectionAngle = 360 / (STEPS_LAP / STEP_DIVS); int subLapSectionAngle = lapSectionAngle / 10; for (int i = 0; lapSteps > (STEP_DIVS / 10); i++) { if ( lapSteps > STEP_DIVS ) { int32_t add_Degrees = lapSectionAngle - 2; graphics_fill_radial(ctx, inset_bounds, GOvalScaleModeFitCircle, 9, DEG_TO_TRIGANGLE(lapSectionAngle * i), DEG_TO_TRIGANGLE(lapSectionAngle * i + add_Degrees )); lapSteps -= STEP_DIVS; } else { for (int j = 0; lapSteps > (STEP_DIVS / 10); j++) { int32_t add_Degrees = subLapSectionAngle - 1; graphics_fill_radial(ctx, inset_bounds, GOvalScaleModeFitCircle, ((j == 4) ? 13 : 9 ), DEG_TO_TRIGANGLE(lapSectionAngle * i + subLapSectionAngle * j), DEG_TO_TRIGANGLE(lapSectionAngle * i + subLapSectionAngle * j + add_Degrees )); lapSteps -= STEP_DIVS / 10; } } } GRect double_inset = grect_inset(inset_bounds, GEdgeInsets(15)); graphics_context_set_fill_color(ctx, GColorWhite); if (steps < STEPS_LAP) { steps += 150; return; } // draw step lap dots for (int i = 0; i < steps/STEPS_LAP; i++) { GRect xywh = grect_centered_from_polar(double_inset, GOvalScaleModeFitCircle, DEG_TO_TRIGANGLE(6 * i), GSize(5,5)); graphics_fill_radial(ctx, xywh, GOvalScaleModeFitCircle, 5, 0, TRIG_MAX_ANGLE); } steps += 33; }
static void countdown_layer_update_proc(Layer *layer, GContext *ctx) { uint16_t ms; time_t time; time_ms(&time, &ms); int seconds = time % 30; int units = (seconds*20) + (ms / 50); graphics_context_set_fill_color(ctx, layer_color); /* #ifdef PBL_COLOR */ if (seconds >= 24) { if (seconds % 2 == 0) graphics_context_set_fill_color(ctx, GColorRed); } /* #endif */ if (hidden && thickness > 0) thickness--; else if (!hidden && thickness < 7) thickness++; /* if (!hidden) countdown_rect.size.w = ((24 * reverse_seconds) / 5) - (ms / 208); */ // APP_LOG(APP_LOG_LEVEL_DEBUG, "S:%d MS:%d W:%d", reverse_seconds, ms, countdown_width); graphics_fill_radial(ctx, layer_get_bounds(countdown_layer), GOvalScaleModeFitCircle, thickness, 0, TIME_ANGLE(units)); }
static void offscreen_layer_update(Layer* layer, GContext *ctx) { if (data_loaded) { GRect bounds = layer_get_bounds(layer); // Draw the night slice const GRect entire_screen = GRect(0, 0, 180, 180); graphics_context_set_fill_color(ctx, GColorWhite); graphics_fill_radial( ctx, entire_screen, GOvalScaleModeFillCircle, 90, DEG_TO_TRIGANGLE(degreeify(hour_set, minute_set)), DEG_TO_TRIGANGLE(degreeify(hour_rise, minute_rise)) ); // Capture the graphics context framebuffer GBitmap *framebuffer = graphics_capture_frame_buffer(ctx); bitmap_make_transparent(stars, framebuffer); // Release the framebuffer now that we are free to modify it graphics_release_frame_buffer(ctx, framebuffer); } }
static void draw_paddle(GRect bounds, GContext *ctx, Paddle *paddle) { /* Draws the paddle. */ GRect frame = grect_inset(bounds, paddle->inset); graphics_context_set_fill_color(ctx, paddle->color); graphics_fill_radial(ctx, frame, GOvalScaleModeFitCircle, PADDLE_THICKNESS, paddle->loc, paddle->loc + paddle->len); }
static void battery_update_proc(Layer *layer, GContext *ctx) { GRect bounds = layer_get_bounds(layer); // Find the width of the bar float percent = ((float)s_battery_level / 100.0F); int width = (int)(float)(percent * bounds.size.w); // Draw the background GColor bgcolor = GColorFromHEX(persist_read_int(MESSAGE_KEY_BackgroundColor)); GColor batterycolor; //graphics_context_set_fill_color(ctx, GColorClear); //graphics_fill_rect(ctx, bounds, 0, GCornerNone); // Draw the bar int g = (255 * percent); int r = (255 * (1 - percent)); int b = 0; int rgb = createRGB(r, g, b); if (s_battery_level == 100) { r = 85; g = 255; } if (s_battery_level == 50) { rgb = 0xFFAA00; } int x = persist_read_int(MESSAGE_KEY_Battery); APP_LOG(APP_LOG_LEVEL_INFO, "Battery Preference: %d", x); if (persist_read_int(MESSAGE_KEY_Battery) != 102) { APP_LOG(APP_LOG_LEVEL_INFO, "RGB"); batterycolor = GColorFromHEX(rgb); } else { batterycolor = gcolor_legible_over(bgcolor); } PBL_IF_BW_ELSE(graphics_context_set_fill_color(ctx, batterycolor), graphics_context_set_fill_color(ctx, batterycolor)); //APP_LOG(APP_LOG_LEVEL_INFO, GColorFromHEX(rgb)); /* if (s_battery_level <= 20) { graphics_context_set_fill_color(ctx, PBL_IF_BW_ELSE(GColorBlack, GColorRed)); } else if (s_battery_level == 100) { graphics_context_set_fill_color(ctx, PBL_IF_BW_ELSE(GColorBlack, GColorBrightGreen)); } */ GRect frame = grect_inset(bounds, GEdgeInsets(10)); //graphics_context_set_fill_color(ctx, GColorBlack); PBL_IF_ROUND_ELSE(graphics_fill_radial(ctx, frame, GOvalScaleModeFitCircle, 5, DEG_TO_TRIGANGLE(125+((1-percent)*110)), DEG_TO_TRIGANGLE(235)), graphics_fill_rect(ctx, GRect(0, 0, width, bounds.size.h), 0, GCornerNone)); }
void radial_layer_update_proc(Layer *layer, GContext *ctx) { logd("%s", __func__); GRect bounds = layer_get_bounds(layer); Internal *internal = (Internal *) layer_get_data(layer); int32_t angle = TRIG_MAX_ANGLE * internal->value / internal->max; graphics_context_set_fill_color(ctx, internal->color); graphics_fill_radial(ctx, bounds, GOvalScaleModeFitCircle, internal->inset, 0, angle); }
static void draw_circle(GContext *ctx, GRect rect, GColor color, int r, int deg) { graphics_context_set_fill_color(ctx, color); graphics_fill_radial( ctx, rect, GOvalScaleModeFillCircle, r, DEG_TO_TRIGANGLE(0), deg % 360 == 0 ? TRIG_MAX_ANGLE : DEG_TO_TRIGANGLE(deg) ); }
void bipercent_draw_circle(Layer *layer, GContext *ctx) { BipercentLayerData *data = (BipercentLayerData*) layer_get_data(layer); int end_angle = data->percent * 360 / 100; GRect rect = layer_get_bounds(layer); graphics_fill_radial(ctx, rect, GOvalScaleModeFitCircle, RADIAL_R, DEG_TO_TRIGANGLE(0), DEG_TO_TRIGANGLE(end_angle)); graphics_draw_arc(ctx, rect, GOvalScaleModeFitCircle, DEG_TO_TRIGANGLE(end_angle), DEG_TO_TRIGANGLE(360)); graphics_draw_arc(ctx, grect_inset(layer_get_bounds(layer), GEdgeInsets(RADIAL_R)) , GOvalScaleModeFitCircle, DEG_TO_TRIGANGLE(end_angle), DEG_TO_TRIGANGLE(360)); }
void prv_draw_pupil(GContext *ctx, const GRect *eye_rect, const GPoint *perimeter_point) { const int16_t pupil_radius = 3; const GSize pupil_size = GSize(pupil_radius * 2, pupil_radius * 2); const GRect pupil_container_rect = grect_inset((*eye_rect), GEdgeInsets(2 * pupil_radius)); const GPoint pupil_center = grect_center_point(&pupil_container_rect); const int32_t pupil_angle = atan2_lookup(perimeter_point->y - pupil_center.y, perimeter_point->x - pupil_center.x) + DEG_TO_TRIGANGLE(90); const GRect pupil_rect = grect_centered_from_polar(pupil_container_rect, GOvalScaleModeFitCircle, pupil_angle, pupil_size); graphics_fill_radial(ctx, pupil_rect, GOvalScaleModeFitCircle, pupil_radius, 0, TRIG_MAX_ANGLE); }
static void show_round_meter(GContext *ctx, GRect *bounds) { // radial GRect frame = grect_inset((*bounds), GEdgeInsets(0)); int minute_angle = (int)(360.0 * s_meter_time.minutes / 60.0); int32_t start_break = minute_angle + 360 * (CONCENTRATION_TIME) / 60 / 60; // 150 == 360 * 25 / 60 int32_t end_break = start_break + 360 * (REST_TIME) / 60 / 60; // 30 == 360 * 5 / 60 graphics_context_set_fill_color(ctx, CONCENTRATION_COLOR); graphics_fill_radial(ctx, frame, GOvalScaleModeFitCircle, METER_THICKNESS, DEG_TO_TRIGANGLE(minute_angle), DEG_TO_TRIGANGLE(start_break)); graphics_context_set_fill_color(ctx, REST_COLOR); graphics_fill_radial(ctx, frame, GOvalScaleModeFitCircle, METER_THICKNESS, DEG_TO_TRIGANGLE(start_break), DEG_TO_TRIGANGLE(end_break)); // hour dots static int s_hour_dot_radius = 2; frame = grect_inset(frame, GEdgeInsets(5 * s_hour_dot_radius)); for(int i = 0; i < 12; i++) { int hour_angle = i * 360 / 12; GPoint pos = gpoint_from_polar(frame, GOvalScaleModeFitCircle, DEG_TO_TRIGANGLE(hour_angle)); graphics_context_set_fill_color(ctx, GColorWhite); graphics_fill_circle(ctx, pos, s_hour_dot_radius); } }
void draw_countdown_graphic(Layer **layer, GContext **ctx, bool on_screen) { time_t temp = time(NULL); struct tm *tick_time = localtime(&temp); int seconds = ((tick_time->tm_sec % 30)*1000) + time_ms(NULL, NULL); if (on_screen && thickness != 7) thickness++; else if (!on_screen && thickness > 0) thickness--; uint16_t target = (seconds*((TRIG_MAX_ANGLE*100)/30000))/100; if (target >= c_angle) c_angle += ((target-c_angle)/6)+1; else c_angle -= ((c_angle-target)/6)+1; graphics_context_set_fill_color(*ctx, fg_color); graphics_fill_radial(*ctx, layer_get_bounds(*layer), GOvalScaleModeFitCircle, thickness, 0, c_angle); }
static void dial_widget_layer_update(DialWidgetLayer *dial_widget_layer, GContext *ctx) { GRect bounds = layer_get_bounds(dial_widget_layer); DialWidgetData *data = (DialWidgetData*)layer_get_data(dial_widget_layer); uint16_t direction = data->vec->direction; // string formatting char center_text[MAX_CENTER_TEXT]; snprintf(center_text, MAX_CENTER_TEXT*sizeof(char), "%u\n%s", data->vec->magnitude, data->units); graphics_context_set_fill_color(ctx, GColorCobaltBlue); graphics_context_set_stroke_color(ctx, GColorBlack); // draw the dial outline graphics_draw_arc(ctx, grect_inset(bounds, GEdgeInsets(1)), GOvalScaleModeFitCircle, 0, DEG_TO_TRIGANGLE(360)); graphics_draw_arc(ctx, grect_inset(bounds, GEdgeInsets(8)), GOvalScaleModeFitCircle, 0, DEG_TO_TRIGANGLE(360)); // draw the arrow graphics_fill_radial(ctx, bounds, GOvalScaleModeFitCircle, 8, DEG_TO_TRIGANGLE(direction - 15), DEG_TO_TRIGANGLE(direction + 15)); // draw the center text GFont font = fonts_get_system_font(FONT_KEY_GOTHIC_14); graphics_context_set_text_color(ctx, GColorBlack); graphics_draw_text(ctx, center_text, font, grect_inset(bounds, GEdgeInsets(8)), GTextOverflowModeWordWrap, GTextAlignmentCenter, NULL); }
//----------------------------------------------------------------------------------------------------------------------- static void face_update_proc(Layer *layer, GContext *ctx) { GRect bounds = layer_get_bounds(layer); GPoint center = grect_center_point(&bounds), clock_center = GPoint(200, 200); //Draw Mask #if defined(PBL_RECT) if (CfgData.circle) graphics_draw_bitmap_in_rect(ctx, bmp_mask, bounds); #endif graphics_context_set_stroke_color(ctx, CfgData.circle || CfgData.inv ? GColorBlack : GColorWhite); graphics_context_set_text_color(ctx, CfgData.circle || CfgData.inv ? GColorBlack : GColorWhite); graphics_context_set_fill_color(ctx, CfgData.circle || CfgData.inv ? GColorBlack : GColorWhite); //TRIG_MAX_ANGLE * t->tm_sec / 60 int32_t angle = (TRIG_MAX_ANGLE * (((aktHH % 12) * 60) + (aktMM / 1))) / (12 * 60), sinl = sin_lookup(angle), cosl = cos_lookup(angle); int16_t radV = 144, radD = 175, radT = 135; GPoint sub_center, ptLin, ptDot; sub_center.x = (int16_t)(sinl * (int32_t)radV / TRIG_MAX_RATIO) + clock_center.x; sub_center.y = (int16_t)(-cosl * (int32_t)radV / TRIG_MAX_RATIO) + clock_center.y; GRect sub_rect = { .origin = GPoint(sub_center.x - bounds.size.w / 2, sub_center.y - bounds.size.h / 2), .size = bounds.size }; for (int32_t i = 1; i<=72; i++) { int32_t angleC = TRIG_MAX_ANGLE * i / 72, sinC = sin_lookup(angleC), cosC = cos_lookup(angleC); ptLin.x = (int16_t)(sinC * (int32_t)(radD) / TRIG_MAX_RATIO) + clock_center.x - sub_rect.origin.x; ptLin.y = (int16_t)(-cosC * (int32_t)(radD) / TRIG_MAX_RATIO) + clock_center.y - sub_rect.origin.y; if (ptLin.x > -40 && ptLin.x < bounds.size.w+40 && ptLin.y > -40 && ptLin.y < bounds.size.h+40) { if ((i % 6) == 0) { gpath_move_to(hour_path, ptLin); gpath_rotate_to(hour_path, angleC); gpath_draw_filled(ctx, hour_path); int16_t nHrPnt = i/6; if (clock_is_24h_style()) if ((aktHH > 9 && aktHH < 21 && nHrPnt > 0 && nHrPnt < 6) || (((aktHH > 15 && aktHH <= 23) || (aktHH >= 0 && aktHH < 3)) && nHrPnt >= 6 && nHrPnt <= 12)) nHrPnt += 12; snprintf(hhBuffer, sizeof(hhBuffer), "%d", nHrPnt); GSize txtSize = graphics_text_layout_get_content_size(hhBuffer, fonts_get_system_font(FONT_KEY_DROID_SERIF_28_BOLD), bounds, GTextOverflowModeWordWrap, GTextAlignmentCenter); ptDot.x = (int16_t)(sinC * (int32_t)radT / TRIG_MAX_RATIO) + clock_center.x - sub_rect.origin.x; ptDot.y = (int16_t)(-cosC * (int32_t)radT / TRIG_MAX_RATIO) + clock_center.y - sub_rect.origin.y; graphics_draw_text(ctx, hhBuffer, fonts_get_system_font(FONT_KEY_DROID_SERIF_28_BOLD), GRect(ptDot.x-txtSize.w/2, ptDot.y-txtSize.h/2, txtSize.w, txtSize.h), GTextOverflowModeWordWrap, GTextAlignmentCenter, NULL); } else if ((i % 3) == 0) { gpath_move_to(mins_path, ptLin); gpath_rotate_to(mins_path, angleC); gpath_draw_filled(ctx, mins_path); } else { gpath_move_to(secs_path, ptLin); gpath_rotate_to(secs_path, angleC); gpath_draw_filled(ctx, secs_path); } } } //Draw Hand Path ptLin.x = (int16_t)(sinl * (int32_t)(radV+111) / TRIG_MAX_RATIO) + clock_center.x - sub_rect.origin.x; ptLin.y = (int16_t)(-cosl * (int32_t)(radV+111) / TRIG_MAX_RATIO) + clock_center.y - sub_rect.origin.y; #ifdef PBL_COLOR graphics_context_set_fill_color(ctx, GColorOrange); #else graphics_context_set_fill_color(ctx, CfgData.circle || CfgData.inv ? GColorBlack : GColorWhite); #endif gpath_move_to(hand_path, ptLin); gpath_rotate_to(hand_path, angle); gpath_draw_filled(ctx, hand_path); //Only if no Mask... if (!CfgData.circle) { graphics_context_set_stroke_color(ctx, CfgData.inv ? GColorWhite : GColorBlack); gpath_draw_outline(ctx, hand_path); } //Draw Separator Lines graphics_context_set_stroke_color(ctx, CfgData.inv ? GColorBlack : GColorWhite); #if defined(PBL_RECT) if (CfgData.sep && !CfgData.circle) graphics_draw_line(ctx, GPoint(10, bounds.size.h-1), GPoint(bounds.size.w-10, bounds.size.h-1)); #elif defined(PBL_ROUND) //Radio & Battery graphics_context_set_fill_color(ctx, CfgData.inv ? GColorWhite : GColorBlack); if (CfgData.smart) { graphics_fill_radial(ctx, GRect(-20, center.y-20, 40, 40), GOvalScaleModeFitCircle, 20, DEG_TO_TRIGANGLE(5), DEG_TO_TRIGANGLE(175)); graphics_fill_radial(ctx, GRect(bounds.size.w-20, center.y-20, 40, 40), GOvalScaleModeFitCircle, 20, DEG_TO_TRIGANGLE(185), DEG_TO_TRIGANGLE(355)); if (CfgData.sep) { graphics_draw_arc(ctx, GRect(-20, center.y-20, 40, 40), GOvalScaleModeFitCircle, DEG_TO_TRIGANGLE(5), DEG_TO_TRIGANGLE(175)); graphics_draw_arc(ctx, GRect(bounds.size.w-20, center.y-20, 40, 40), GOvalScaleModeFitCircle, DEG_TO_TRIGANGLE(190), DEG_TO_TRIGANGLE(350)); } } //DateTime if (!CfgData.fsm) { graphics_fill_radial(ctx, GRect(center.x-100, bounds.size.h-n_bottom_margin-5, 200, 200), GOvalScaleModeFitCircle, n_bottom_margin+5, DEG_TO_TRIGANGLE(275), DEG_TO_TRIGANGLE(445)); graphics_draw_text(ctx, ddmmyyyyBuffer, digitS, GRect(0, bounds.size.h-n_bottom_margin-5, bounds.size.w, n_bottom_margin), GTextOverflowModeWordWrap, GTextAlignmentCenter, NULL); if (CfgData.sep) graphics_draw_arc(ctx, GRect(center.x-100, bounds.size.h-n_bottom_margin-5, 200, 200), GOvalScaleModeFitCircle, DEG_TO_TRIGANGLE(275), DEG_TO_TRIGANGLE(445)); } #endif } //----------------------------------------------------------------------------------------------------------------------- static void handle_tick(struct tm *tick_time, TimeUnits units_changed) { if (b_initialized) { aktHH = tick_time->tm_hour; aktMM = tick_time->tm_min; layer_mark_dirty(face_layer); } #if defined(PBL_RECT) strftime(ddmmyyyyBuffer, sizeof(ddmmyyyyBuffer), //true ? "%a %d.%b" : CfgData.datefmt == 1 ? "%d-%m-%Y" : CfgData.datefmt == 2 ? "%d/%m/%Y" : CfgData.datefmt == 3 ? "%m/%d/%Y" : CfgData.datefmt == 4 ? "%Y-%m-%d" : CfgData.datefmt == 5 ? "%d.%m.%y" : CfgData.datefmt == 6 ? "%d-%m-%y" : CfgData.datefmt == 7 ? "%d/%m/%y" : CfgData.datefmt == 8 ? "%m/%d/%y" : CfgData.datefmt == 9 ? "%y-%m-%d" : CfgData.datefmt == 10 ? "%a %d.%m." : CfgData.datefmt == 11 ? "%a %d.%b" : "%d.%m.%Y", tick_time); #elif defined(PBL_ROUND) strftime(ddmmyyyyBuffer, sizeof(ddmmyyyyBuffer), //true ? "%a %d." : CfgData.datefmt == 1 ? "%d-%m" : CfgData.datefmt == 2 ? "%d/%m" : CfgData.datefmt == 3 ? "%m/%d" : CfgData.datefmt == 4 ? "%m-%d" : CfgData.datefmt == 5 ? "%d.%m" : CfgData.datefmt == 6 ? "%d-%m" : CfgData.datefmt == 7 ? "%d/%m" : CfgData.datefmt == 8 ? "%m/%d" : CfgData.datefmt == 9 ? "%m-%d" : CfgData.datefmt == 10 ? "%a %d." : CfgData.datefmt == 11 ? "%a %d." : "%d.%m", tick_time); #endif /* snprintf(ddmmyyyyBuffer, sizeof(ddmmyyyyBuffer), CfgData.datefmt == 1 ? "%d-%d-%d" : CfgData.datefmt == 2 ? "%d/%d/%d" : CfgData.datefmt == 3 ? "%d/%d/%d" : CfgData.datefmt == 4 ? "%d-%d-%d" : "%d.%d.%d", 88, 88, 8888); */ //strcpy(ddmmyyyyBuffer, "00000"); text_layer_set_text(date_layer, ddmmyyyyBuffer); //Hourly vibrate if (CfgData.vibr && tick_time->tm_min == 0) vibes_enqueue_custom_pattern(vibe_pat_hr); } //----------------------------------------------------------------------------------------------------------------------- static void timerCallback(void *data) { if ((int)data == TIMER_ANIM_FACE && !b_initialized) { time_t temp = time(NULL); struct tm *t = localtime(&temp); if ((aktHH % 12) != (t->tm_hour % 12) || aktMM != t->tm_min) { int16_t nStep = (aktHH % 12) != (t->tm_hour % 12) ? 5 : 1; if ((t->tm_hour % 12) < 6) { //Initial Value? Set correct initial if (aktHH == 0 && aktMM == 0) { aktHH = t->tm_hour >= 12 ? 12 : 0; aktMM = 0; } if (aktMM < 60-nStep) aktMM += nStep; else { aktMM = 0; aktHH++; } } else { //Initial Value? Set correct initial if (aktHH == 0 && aktMM == 0) { aktHH = t->tm_hour > 12 ? 23 : 11; aktMM = 60; } if (aktMM > nStep) aktMM -= nStep; else { aktMM = 60; aktHH--; } //Little workaround if time is close to the 12 o'clock if ((aktHH % 12) == (t->tm_hour % 12) && aktMM < t->tm_min) aktMM = t->tm_min; } layer_mark_dirty(face_layer); timer_face = app_timer_register(TIMER_ANIM_FACE_MS, timerCallback, (void*)TIMER_ANIM_FACE); } else b_initialized = true; } else if ((int)data == TIMER_ANIM_BATT && b_charging) { int nImage = 10 - (aktBattAnim / 10); bitmap_layer_set_bitmap(battery_layer, NULL); gbitmap_destroy(bmp_batt); bmp_batt = gbitmap_create_as_sub_bitmap(batteryAll, GRect(10*nImage, 0, 10, 20)); bitmap_layer_set_bitmap(battery_layer, bmp_batt); aktBattAnim += 10; if (aktBattAnim > 100) aktBattAnim = aktBatt; timer_batt = app_timer_register(TIMER_ANIM_BATT_MS, timerCallback, (void*)TIMER_ANIM_BATT); } } //----------------------------------------------------------------------------------------------------------------------- void battery_state_service_handler(BatteryChargeState charge_state) { int nImage = 0; aktBatt = charge_state.charge_percent; if (charge_state.is_charging) { if (!b_charging) { nImage = 10; b_charging = true; aktBattAnim = aktBatt; timer_batt = app_timer_register(TIMER_ANIM_BATT_MS, timerCallback, (void*)TIMER_ANIM_BATT); } } else { nImage = 10 - (aktBatt / 10); b_charging = false; } bmp_batt = gbitmap_create_as_sub_bitmap(batteryAll, GRect(10*nImage, 0, 10, 20)); bitmap_layer_set_bitmap(battery_layer, bmp_batt); }
static void draw_debug_arc(GRect bounds, GContext *ctx, int32_t theta) { GRect frame = grect_inset(bounds, GEdgeInsets(25)); graphics_fill_radial(ctx, frame, GOvalScaleModeFitCircle, 1, 0, theta); }
// Chalk Circle Battery Line void RoundBatteryLayer_update_callback(Layer *RoundBatteryLayer, GContext* Roundctx) { graphics_context_set_antialiased(Roundctx, true); graphics_context_set_fill_color(Roundctx, GColorBlack); graphics_fill_radial(Roundctx, GRect(0, 0, 180, 180), GOvalScaleModeFillCircle, 10 /*thickness*/, 0, TRIG_MAX_ANGLE); if (batterycharging == 1) { graphics_context_set_fill_color(Roundctx, GColorBlue); graphics_fill_radial(Roundctx, GRect(0, 0, 180, 180), GOvalScaleModeFillCircle, 8 /*thickness*/, 0, TRIG_MAX_ANGLE); } else if (batterychargepct > 20) { graphics_context_set_fill_color(Roundctx, GColorGreen); graphics_fill_radial(Roundctx, GRect(0, 0, 180, 180), GOvalScaleModeFillCircle, 8 /*thickness*/, 0, batterychargepct * 0.01 * TRIG_MAX_ANGLE); } else { graphics_context_set_fill_color(Roundctx, GColorRed); graphics_fill_radial(Roundctx, GRect(0, 0, 180, 180), GOvalScaleModeFillCircle, 8 /*thickness*/, 0, batterychargepct * 0.01 * TRIG_MAX_ANGLE); } //Battery % indicators graphics_context_set_fill_color(Roundctx, GColorWhite); graphics_fill_radial(Roundctx, GRect(0, 0, 180, 180), GOvalScaleModeFillCircle, 8, (TRIG_MAX_ANGLE / 11.0), (TRIG_MAX_ANGLE / 10) * 1); //10% graphics_fill_radial(Roundctx, GRect(0, 0, 180, 180), GOvalScaleModeFillCircle, 8, (TRIG_MAX_ANGLE / 5.25), (TRIG_MAX_ANGLE / 10) * 2); //20% graphics_fill_radial(Roundctx, GRect(0, 0, 180, 180), GOvalScaleModeFillCircle, 8, (TRIG_MAX_ANGLE / 3.43), (TRIG_MAX_ANGLE / 10) * 3); //30% graphics_fill_radial(Roundctx, GRect(0, 0, 180, 180), GOvalScaleModeFillCircle, 8, (TRIG_MAX_ANGLE / 2.55), (TRIG_MAX_ANGLE / 10) * 4); //40% graphics_fill_radial(Roundctx, GRect(0, 0, 180, 180), GOvalScaleModeFillCircle, 8, (TRIG_MAX_ANGLE / 2.03), (TRIG_MAX_ANGLE / 10) * 5); //50% graphics_fill_radial(Roundctx, GRect(0, 0, 180, 180), GOvalScaleModeFillCircle, 8, (TRIG_MAX_ANGLE / 1.69), (TRIG_MAX_ANGLE / 10) * 6); //60% graphics_fill_radial(Roundctx, GRect(0, 0, 180, 180), GOvalScaleModeFillCircle, 8, (TRIG_MAX_ANGLE / 1.445), (TRIG_MAX_ANGLE / 10) * 7); //70% graphics_fill_radial(Roundctx, GRect(0, 0, 180, 180), GOvalScaleModeFillCircle, 8, (TRIG_MAX_ANGLE / 1.265), (TRIG_MAX_ANGLE / 10) * 8); //80% graphics_fill_radial(Roundctx, GRect(0, 0, 180, 180), GOvalScaleModeFillCircle, 8, (TRIG_MAX_ANGLE / 1.12), (TRIG_MAX_ANGLE / 10) * 9); //90% graphics_fill_radial(Roundctx, GRect(0, 0, 180, 180), GOvalScaleModeFillCircle, 8, (TRIG_MAX_ANGLE / 1.01), TRIG_MAX_ANGLE); //100% }
static void update_proc(Layer *layer, GContext *ctx) { int padding; PBL_IF_ROUND_ELSE(padding = 16, padding = 12); HOURS_TRACK_RADIUS = (window_bounds.size.w - padding) / 2; //66 HOURS_TRACK_STROKE = 2; MINUTES_TRACK_RADIUS = HOURS_TRACK_RADIUS - 10; //56 MINUTES_TRACK_STROKE = 2; SECONDS_TRACK_RADIUS = HOURS_TRACK_RADIUS - 20; //46 SECONDS_TRACK_STROKE = 2; SECONDS_HAND_RADIUS = 2; MINUTES_HAND_RADIUS = 3; HOURS_HAND_RADIUS = 4; // Color background graphics_context_set_fill_color(ctx, GColorBlack); graphics_fill_rect(ctx, window_bounds, 0, GCornerNone); //APP_LOG(APP_LOG_LEVEL_DEBUG, "bounds: %d %d %d %d", window_bounds.origin.x, window_bounds.origin.y, window_bounds.size.h, window_bounds.size.w ); //set colour for tracks graphics_context_set_stroke_color(ctx, GColorWhite ); graphics_context_set_antialiased(ctx, ANTIALIASING); // Don't use current time while animating Time mode_time = s_last_time; // generate position of hands GPoint second_hand = (GPoint) { .x = (int16_t)(sin_lookup(TRIG_MAX_ANGLE * mode_time.seconds / 60) * (int32_t)(SECONDS_TRACK_RADIUS) / TRIG_MAX_RATIO) + s_center.x, .y = (int16_t)(-cos_lookup(TRIG_MAX_ANGLE * mode_time.seconds / 60) * (int32_t)(SECONDS_TRACK_RADIUS) / TRIG_MAX_RATIO) + s_center.y, }; float minutes, hours; if (SWEEP_MINUTES == true) { minutes = mode_time.minutes + (float)mode_time.seconds / 60; } else { minutes = mode_time.minutes; } GPoint minute_hand = (GPoint) { .x = (int16_t)(sin_lookup(TRIG_MAX_ANGLE * minutes / 60) * (int32_t)(MINUTES_TRACK_RADIUS) / TRIG_MAX_RATIO) + s_center.x, .y = (int16_t)(-cos_lookup(TRIG_MAX_ANGLE * minutes/ 60) * (int32_t)(MINUTES_TRACK_RADIUS) / TRIG_MAX_RATIO) + s_center.y, }; if( SWEEP_HOURS == true) { hours = mode_time.hours + (float)mode_time.minutes / 60; } else { hours = mode_time.hours; } GPoint hour_hand = (GPoint) { .x = (int16_t)(sin_lookup(TRIG_MAX_ANGLE * hours / 12) * (int32_t)(HOURS_TRACK_RADIUS) / TRIG_MAX_RATIO) + s_center.x, .y = (int16_t)(-cos_lookup(TRIG_MAX_ANGLE * hours / 12) * (int32_t)(HOURS_TRACK_RADIUS) / TRIG_MAX_RATIO) + s_center.y, }; graphics_context_set_fill_color(ctx, GColorWhite); GRect seconds_rect = GRect(s_center.x - SECONDS_TRACK_RADIUS, s_center.y - SECONDS_TRACK_RADIUS, SECONDS_TRACK_RADIUS * 2, SECONDS_TRACK_RADIUS * 2); GRect minutes_rect = GRect(s_center.x - MINUTES_TRACK_RADIUS, s_center.y - MINUTES_TRACK_RADIUS, MINUTES_TRACK_RADIUS * 2, MINUTES_TRACK_RADIUS * 2); GRect hours_rect = GRect(s_center.x - HOURS_TRACK_RADIUS, s_center.y - HOURS_TRACK_RADIUS, HOURS_TRACK_RADIUS * 2, HOURS_TRACK_RADIUS * 2); //---------------------------------- int seconds_start_angle, seconds_end_angle; int seconds_delta = 12; int minutes_delta = 12; int hours_delta = 12; get_angles_60(mode_time.seconds, 0, seconds_delta, &seconds_start_angle, &seconds_end_angle); //---------------------------------- //int minutes_angle = mode_time.minutes * 360 / 60; int minutes_start_angle, minutes_end_angle; get_angles_60(mode_time.minutes, (SWEEP_MINUTES == true) ? mode_time.seconds : 0, minutes_delta, &minutes_start_angle, &minutes_end_angle); //get_angles_60(mode_time.minutes, mode_time.seconds, minutes_delta, &minutes_start_angle, &minutes_end_angle); //---------------------------------- //int hours_angle = mode_time.hours * 360 / 12; int hours_start_angle, hours_end_angle; get_angles_12(mode_time.hours,(SWEEP_HOURS == true) ? mode_time.minutes : 0, hours_delta, &hours_start_angle, &hours_end_angle); //APP_LOG(APP_LOG_LEVEL_DEBUG, "seconds: %d, start: %d, end: %d", mode_time.seconds, seconds_start_angle, seconds_end_angle); //set colour for arcs and "hands" graphics_context_set_fill_color(ctx, GColorWhite ); //draw seconds arc graphics_fill_radial(ctx, seconds_rect, GOvalScaleModeFitCircle, SECONDS_TRACK_STROKE, DEG_TO_TRIGANGLE(seconds_start_angle), DEG_TO_TRIGANGLE(seconds_end_angle)); //draw minutes arc graphics_fill_radial(ctx, minutes_rect, GOvalScaleModeFitCircle, MINUTES_TRACK_STROKE, DEG_TO_TRIGANGLE(minutes_start_angle), DEG_TO_TRIGANGLE(minutes_end_angle)); //draw hours arc graphics_fill_radial(ctx, hours_rect, GOvalScaleModeFitCircle, HOURS_TRACK_STROKE, DEG_TO_TRIGANGLE(hours_start_angle), DEG_TO_TRIGANGLE(hours_end_angle)); //draw minute hand graphics_fill_circle(ctx, minute_hand, MINUTES_HAND_RADIUS); //draw hour hand graphics_fill_circle(ctx, hour_hand, HOURS_HAND_RADIUS); //draw second hand graphics_context_set_fill_color(ctx, GColorRed ); graphics_fill_circle(ctx, second_hand, SECONDS_HAND_RADIUS); update_time(); } static void window_load(Window *window) { Layer *window_layer = window_get_root_layer(window); window_bounds = layer_get_bounds(window_layer); //APP_LOG(APP_LOG_LEVEL_DEBUG, "bounds: %d %d %d %d", window_bounds.origin.x, window_bounds.origin.y, window_bounds.size.h, window_bounds.size.w ); s_center = grect_center_point(&window_bounds); s_canvas_layer = layer_create(window_bounds); layer_set_update_proc(s_canvas_layer, update_proc); layer_add_child(window_layer, s_canvas_layer); // Create time TextLayer int font_height; PBL_IF_ROUND_ELSE(font_height = 45, font_height = 36); //fudge factor to get text vertically centred s_time_layer = text_layer_create(GRect(window_bounds.origin.x, (window_bounds.size.h-font_height)/2, window_bounds.size.w, font_height)); //s_center.y - MINUTES_TRACK_RADIUS + 18 + 18; s_day_layer = text_layer_create(GRect(0, s_center.y - 18 - 18 , window_bounds.size.w, 18)); //need to calculate proper y-location s_month_layer = text_layer_create(GRect(0, s_center.y +36 , window_bounds.size.w, 18)); //need to calculate proper y-location text_layer_set_background_color(s_day_layer, GColorRed); text_layer_set_text_color(s_day_layer, GColorLightGray ); text_layer_set_text(s_day_layer, "00"); text_layer_set_background_color(s_time_layer, GColorClear); text_layer_set_text_color(s_time_layer, GColorWhite); text_layer_set_text(s_time_layer, "00:00"); text_layer_set_background_color(s_month_layer, GColorClear); text_layer_set_text_color(s_month_layer, GColorLightGray ); text_layer_set_text(s_month_layer, "XXX"); PBL_IF_ROUND_ELSE(s_custom_font = fonts_load_custom_font(resource_get_handle(RESOURCE_ID_FONT_DOSIS_SEMIBOLD_40)), s_custom_font = fonts_load_custom_font(resource_get_handle(RESOURCE_ID_FONT_DOSIS_SEMIBOLD_30))); text_layer_set_font(s_time_layer, s_custom_font); text_layer_set_text_alignment(s_time_layer, GTextAlignmentCenter); text_layer_set_font(s_day_layer, fonts_load_custom_font(resource_get_handle(RESOURCE_ID_FONT_DOSIS_SEMIBOLD_18))); text_layer_set_text_alignment(s_day_layer, GTextAlignmentCenter); text_layer_set_font(s_month_layer, fonts_load_custom_font(resource_get_handle(RESOURCE_ID_FONT_DOSIS_SEMIBOLD_18))); text_layer_set_text_alignment(s_month_layer, GTextAlignmentCenter); // Add it as a child layer to the Window's root layer layer_add_child(window_get_root_layer(window), text_layer_get_layer(s_time_layer)); layer_add_child(window_get_root_layer(window), text_layer_get_layer(s_day_layer)); layer_add_child(window_get_root_layer(window), text_layer_get_layer(s_month_layer)); // Make sure the time is displayed from the start update_time(); } static void window_unload(Window *window) { layer_destroy(s_canvas_layer); // Destroy TextLayer text_layer_destroy(s_time_layer); text_layer_destroy(s_day_layer); text_layer_destroy(s_month_layer); fonts_unload_custom_font(s_custom_font); } /*********************************** App **************************************/ static void init() { srand(time(NULL)); time_t t = time(NULL); struct tm *time_now = localtime(&t); tick_handler(time_now, SECOND_UNIT); s_main_window = window_create(); window_set_window_handlers(s_main_window, (WindowHandlers) { .load = window_load, .unload = window_unload, });