void bluetooth_layer_create() { if (!s_bitmap_bluetooth) { s_bitmap_bluetooth = gbitmap_create_with_resource(RESOURCE_ID_IMAGE_BLUETOOTH_MARK); s_bitmap_yes_no = gbitmap_create_with_resource(RESOURCE_ID_IMAGE_YES_NO); GRect rect = gbitmap_get_bounds(s_bitmap_yes_no); rect.size.w >>= 1; s_bitmap_yes = gbitmap_create_as_sub_bitmap(s_bitmap_yes_no, rect); rect.origin.x += rect.size.w; s_bitmap_no = gbitmap_create_as_sub_bitmap(s_bitmap_yes_no, rect); }
static void textdata_init(GBitmap *bitmap, TextData *font_data) { // for each non-null letter, create a sub-bitmap in the TextData for (int i = 0; i < NUM_GLYPHS; i++) { if (!font_data[i].a) continue; TextData *d = font_data + i; GRect sub = GRect(d->x, 40 - d->t, d->w + d->l, d->h); font_data[i].b = gbitmap_create_as_sub_bitmap(bitmap, sub); } }
GBitmap* get_sprite_by_index(GBitmap* spritesheet, int x, int y) { if (x > MAX_SPRITE_X || y > MAX_SPRITE_Y) { return NULL; } GRect sub_rect = GRect(3 + (SINGLE_SPRITE_W * x) + (9 * x), 10 + (SINGLE_SPRITE_H * y) + (7 * y) , SINGLE_SPRITE_W, SINGLE_SPRITE_H); GBitmap* sub_bitmap = gbitmap_create_as_sub_bitmap(spritesheet, sub_rect); return sub_bitmap; }
static void weather_layer_set_icon(WeatherIcon icon, WeatherDisplayArea area) { WeatherLayerData *wld = layer_get_data(weather_layer); static int size = 0; static BitmapLayer *layer = NULL; static GBitmap *icons = NULL; switch (area) { case AREA_PRIMARY: size = wld->primary_icon_size; layer = wld->primary_icon_layer; icons = wld->primary_icons; break; case AREA_HOURLY1: size = wld->hourly_icon_size; layer = wld->h1_icon_layer; icons = wld->hourly_icons; break; case AREA_HOURLY2: size = wld->hourly_icon_size; layer = wld->h2_icon_layer; icons = wld->hourly_icons; break; } GBitmap *new_icon = gbitmap_create_as_sub_bitmap( icons, GRect(icon%5*size, ((int)(icon/5))*size, size, size) ); // Display the new bitmap bitmap_layer_set_bitmap(layer, new_icon); switch (area) { case AREA_PRIMARY: if (wld->primary_icon != NULL) gbitmap_destroy(wld->primary_icon); wld->primary_icon = new_icon; break; case AREA_HOURLY1: if (wld->h1_icon != NULL) gbitmap_destroy(wld->h1_icon); wld->h1_icon = new_icon; break; case AREA_HOURLY2: if (wld->h2_icon != NULL) gbitmap_destroy(wld->h2_icon); wld->h2_icon = new_icon; break; } }
GBitmap* bitmaps_get_sub_bitmap(uint32_t res_id, GRect rect) { if (! bitmaps) { return NULL; } GBitmap* parent = NULL; uint8_t count = linked_list_count(bitmaps); for (uint8_t b = 0; b < count; b += 1) { AppBitmap* bmp = (AppBitmap*)linked_list_get(bitmaps, b); if (bmp->res_id == res_id) { if (bmp->is_sub) { if (grect_equal(bmp->rect, &rect)) { return bmp->bitmap; } } else { parent = bmp->bitmap; } } } if (! parent) { parent = bitmaps_get_bitmap(res_id); if (! parent) { return NULL; } } AppBitmap* app_bmp = malloc(sizeof(AppBitmap)); if (app_bmp == NULL) { return NULL; } app_bmp->res_id = res_id; app_bmp->bitmap = gbitmap_create_as_sub_bitmap(parent, rect); if (app_bmp->bitmap == NULL) { return NULL; } app_bmp->rect = malloc(sizeof(GRect)); app_bmp->rect->origin = rect.origin; app_bmp->rect->size = rect.size; app_bmp->is_sub = true; linked_list_append(bitmaps, app_bmp); return app_bmp->bitmap; }
//----------------------------------------------------------------------------------------------------------------------- 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 update_configuration(void) { if (persist_exists(CONFIG_KEY_THEME)) { int32_t theme = persist_read_int(CONFIG_KEY_THEME); CfgData.circle = (theme == 0); } else CfgData.circle = false; if (persist_exists(CONFIG_KEY_FSM)) CfgData.fsm = persist_read_bool(CONFIG_KEY_FSM); else CfgData.fsm = false; if (persist_exists(CONFIG_KEY_INV)) CfgData.inv = !CfgData.circle && persist_read_bool(CONFIG_KEY_INV); else CfgData.inv = true; if (persist_exists(CONFIG_KEY_ANIM)) CfgData.anim = persist_read_bool(CONFIG_KEY_ANIM); else CfgData.anim = true; if (persist_exists(CONFIG_KEY_SEP)) CfgData.sep = persist_read_bool(CONFIG_KEY_SEP); else CfgData.sep = true; if (persist_exists(CONFIG_KEY_DATEFMT)) CfgData.datefmt = (int16_t)persist_read_int(CONFIG_KEY_DATEFMT); else CfgData.datefmt = 0; if (persist_exists(CONFIG_KEY_SMART)) CfgData.smart = persist_read_bool(CONFIG_KEY_SMART); else CfgData.smart = true; if (persist_exists(CONFIG_KEY_VIBR)) CfgData.vibr = persist_read_bool(CONFIG_KEY_VIBR); else CfgData.vibr = false; app_log(APP_LOG_LEVEL_DEBUG, __FILE__, __LINE__, "Curr Conf: circle:%d, fsm:%d, inv:%d, anim:%d, sep:%d, datefmt:%d, smart:%d, vibr:%d", CfgData.circle, CfgData.fsm, CfgData.inv, CfgData.anim, CfgData.sep, CfgData.datefmt, CfgData.smart, CfgData.vibr); gbitmap_destroy(batteryAll); batteryAll = gbitmap_create_with_resource(CfgData.inv ? RESOURCE_ID_IMAGE_BATTERY_INV : RESOURCE_ID_IMAGE_BATTERY); bitmap_layer_set_bitmap(radio_layer, NULL); gbitmap_destroy(bmp_radio); bmp_radio = gbitmap_create_as_sub_bitmap(batteryAll, GRect(110, 0, 10, 20)); bitmap_layer_set_bitmap(radio_layer, bmp_radio); Layer *window_layer = window_get_root_layer(window); GRect bounds = layer_get_bounds(window_get_root_layer(window)); window_set_background_color(window, CfgData.inv ? GColorWhite : GColorBlack); //Face Layer first on round layer_remove_from_parent(face_layer); layer_destroy(face_layer); #if defined(PBL_RECT) face_layer = layer_create(GRect(0, 0, bounds.size.w, CfgData.fsm ? bounds.size.h : bounds.size.h-n_bottom_margin)); layer_set_update_proc(face_layer, face_update_proc); #elif defined(PBL_ROUND) face_layer = layer_create(GRect(0, 0, bounds.size.w, bounds.size.h)); layer_set_update_proc(face_layer, face_update_proc); layer_add_child(window_layer, face_layer); #endif //Bottom Layer next, then Radio and Battery layer_remove_from_parent(text_layer_get_layer(date_layer)); layer_remove_from_parent(bitmap_layer_get_layer(radio_layer)); layer_remove_from_parent(bitmap_layer_get_layer(battery_layer)); #if defined(PBL_RECT) if (!CfgData.fsm) #endif { #if defined(PBL_RECT) layer_add_child(window_layer, text_layer_get_layer(date_layer)); #ifdef PBL_COLOR text_layer_set_text_color(date_layer, CfgData.inv ? GColorDarkGray : GColorLightGray); #else text_layer_set_text_color(date_layer, CfgData.inv ? GColorBlack : GColorWhite); #endif text_layer_set_background_color(date_layer, CfgData.inv ? GColorWhite : GColorBlack); #endif if (CfgData.smart) { layer_add_child(window_layer, bitmap_layer_get_layer(radio_layer)); layer_add_child(window_layer, bitmap_layer_get_layer(battery_layer)); } } //On Rect later #if defined(PBL_RECT) layer_add_child(window_layer, face_layer); #endif //Get a time structure so that it doesn't start blank time_t temp = time(NULL); struct tm *t = localtime(&temp); //Manually call the tick handler when the window is loading aktHH = t->tm_hour; aktMM = t->tm_min; handle_tick(t, MINUTE_UNIT); //Set Battery state BatteryChargeState btchg = battery_state_service_peek(); battery_state_service_handler(btchg); //Set Bluetooth state bool connected = bluetooth_connection_service_peek(); bluetooth_connection_handler(connected); }
GBitmap* get_digit_bitmap(uint8_t position, uint8_t digit) { if (!sprite) sprite = gbitmap_create_with_resource(RESOURCE_ID_SPRITE); return gbitmap_create_as_sub_bitmap(sprite, digit_sprite_bounds(position, digit)); }
void init(void) { snprintf(app_version,APP_VERSION_LENGTH,"%d.%d",__pbl_app_info.process_version.major, __pbl_app_info.process_version.minor); main_load_data(); bitmap_matrix=gbitmap_create_with_resource(RESOURCE_ID_IMAGE_ICON_MATRIX); bitmap_pause=gbitmap_create_as_sub_bitmap(bitmap_matrix, ICON_RECT_PAUSE); bitmap_play=gbitmap_create_as_sub_bitmap(bitmap_matrix, ICON_RECT_PLAY); bitmap_add=gbitmap_create_as_sub_bitmap(bitmap_matrix, ICON_RECT_ADD); bitmap_settings=gbitmap_create_as_sub_bitmap(bitmap_matrix, ICON_RECT_SETTINGS); bitmap_delete=gbitmap_create_as_sub_bitmap(bitmap_matrix, ICON_RECT_DELETE); bitmap_edit=gbitmap_create_as_sub_bitmap(bitmap_matrix, ICON_RECT_EDIT); bitmap_adjust=gbitmap_create_as_sub_bitmap(bitmap_matrix, ICON_RECT_ADJUST); bitmap_reset=gbitmap_create_as_sub_bitmap(bitmap_matrix, ICON_RECT_RESET); bitmap_minus=gbitmap_create_as_sub_bitmap(bitmap_matrix, ICON_RECT_MINUS); bitmap_tick=gbitmap_create_as_sub_bitmap(bitmap_matrix, ICON_RECT_TICK); bitmap_export=gbitmap_create_as_sub_bitmap(bitmap_matrix, ICON_RECT_EXPORT); app_message_register_inbox_received(inbox_received_handler); app_message_open(app_message_inbox_size_maximum(), app_message_outbox_size_maximum()); main_menu_show(); }