Fix ability to permanently move icons with rapid presses
This commit is contained in:
+58
-18
@@ -36,50 +36,87 @@ static const GRect s_base_grect_rect = GRect(PBL_DISPLAY_WIDTH - ACTION_BAR_WIDT
|
||||
|
||||
static NeatBarLayer *s_current_neat_bar = NULL;
|
||||
|
||||
static Animation *s_animate_move(NeatBarLayer *neat_bar, uint8_t button_index, bool move_on_y_axis, int16_t distance) {
|
||||
BitmapLayer *bitmap_layer = NULL;
|
||||
static GRect s_get_home_frame(NeatBarLayer *neat_bar, uint8_t button_index) {
|
||||
int16_t y_offset = neat_bar->main_grect.origin.y;
|
||||
int8_t spread = neat_bar->spread;
|
||||
uint16_t width = neat_bar->main_grect.size.w;
|
||||
|
||||
switch (button_index) {
|
||||
case BUTTON_ID_UP:
|
||||
return GRect(ICON_X_OFFSET, UP_Y - spread - y_offset, width, 25);
|
||||
case BUTTON_ID_SELECT:
|
||||
return GRect(ICON_X_OFFSET, SELECT_Y - y_offset, width, 25);
|
||||
case BUTTON_ID_DOWN:
|
||||
return GRect(ICON_X_OFFSET, DOWN_Y + spread - y_offset, width, 25);
|
||||
default:
|
||||
return GRectZero;
|
||||
}
|
||||
}
|
||||
|
||||
// Performs a press or release animation for a single button, anchored to its
|
||||
// home position. Duplicate events (press when already pressed, release when
|
||||
// already released) are ignored so overlapping animations cannot accumulate
|
||||
// drift.
|
||||
static void s_animate_icon(NeatBarLayer *neat_bar, uint8_t button_index, bool is_press) {
|
||||
BitmapLayer *bitmap_layer;
|
||||
bool *pressed;
|
||||
|
||||
switch (button_index) {
|
||||
case BUTTON_ID_UP:
|
||||
bitmap_layer = neat_bar->up_layer;
|
||||
pressed = &neat_bar->up_pressed;
|
||||
break;
|
||||
case BUTTON_ID_SELECT:
|
||||
bitmap_layer = neat_bar->select_layer;
|
||||
pressed = &neat_bar->select_pressed;
|
||||
break;
|
||||
case BUTTON_ID_DOWN:
|
||||
bitmap_layer = neat_bar->down_layer;
|
||||
pressed = &neat_bar->down_pressed;
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!bitmap_layer) {
|
||||
return NULL;
|
||||
if (!bitmap_layer)
|
||||
return;
|
||||
if (is_press) {
|
||||
if (*pressed)
|
||||
return;
|
||||
*pressed = true;
|
||||
} else {
|
||||
if (!*pressed)
|
||||
return;
|
||||
*pressed = false;
|
||||
}
|
||||
|
||||
Layer *layer = bitmap_layer_get_layer(bitmap_layer);
|
||||
GRect from_frame = layer_get_frame(layer);
|
||||
GRect to_frame = from_frame;
|
||||
if (move_on_y_axis) {
|
||||
to_frame.origin.y += distance;
|
||||
GRect home = s_get_home_frame(neat_bar, button_index);
|
||||
|
||||
// off = home shifted by -distance (the "pressed" position)
|
||||
GRect off = home;
|
||||
int16_t distance = neat_bar->animations_move_distance;
|
||||
if (neat_bar->animations_move_on_y_axis) {
|
||||
off.origin.y -= distance;
|
||||
} else {
|
||||
to_frame.origin.x += distance;
|
||||
off.origin.x -= distance;
|
||||
}
|
||||
|
||||
PropertyAnimation *prop_anim = property_animation_create_layer_frame(layer, &from_frame, &to_frame);
|
||||
return property_animation_get_animation(prop_anim);
|
||||
GRect from = is_press ? home : off;
|
||||
GRect to = is_press ? off : home;
|
||||
|
||||
PropertyAnimation *prop_anim = property_animation_create_layer_frame(layer, &from, &to);
|
||||
Animation *anim = property_animation_get_animation(prop_anim);
|
||||
animation_set_duration(anim, neat_bar->animations_duration);
|
||||
animation_schedule(anim);
|
||||
}
|
||||
|
||||
static void s_icon_down_handler(NeatBarLayer *neat_bar, uint8_t button_index) {
|
||||
Animation *anim = s_animate_move(neat_bar, button_index, neat_bar->animations_move_on_y_axis, -neat_bar->animations_move_distance);
|
||||
animation_set_duration(anim, neat_bar->animations_duration);
|
||||
animation_schedule(anim);
|
||||
s_animate_icon(neat_bar, button_index, true);
|
||||
}
|
||||
|
||||
static void s_icon_up_handler(NeatBarLayer *neat_bar, uint8_t button_index) {
|
||||
Animation *anim = s_animate_move(neat_bar, button_index, neat_bar->animations_move_on_y_axis, neat_bar->animations_move_distance);
|
||||
animation_set_duration(anim, neat_bar->animations_duration);
|
||||
animation_schedule(anim);
|
||||
s_animate_icon(neat_bar, button_index, false);
|
||||
}
|
||||
|
||||
static void s_up_down_handler(ClickRecognizerRef recognizer, void *context) {
|
||||
@@ -332,6 +369,9 @@ NeatBarLayer *neat_bar_layer_create() {
|
||||
neat_bar->animations_move_on_y_axis = false;
|
||||
neat_bar->animations_move_distance = ANIM_DISTANCE;
|
||||
neat_bar->animations_duration = 144;
|
||||
neat_bar->up_pressed = false;
|
||||
neat_bar->select_pressed = false;
|
||||
neat_bar->down_pressed = false;
|
||||
neat_bar->context = NULL;
|
||||
layer_set_update_proc(neat_bar->main_layer, s_main_layer_update_proc);
|
||||
s_current_neat_bar = neat_bar;
|
||||
|
||||
@@ -21,6 +21,9 @@ typedef struct {
|
||||
int8_t animations_move_distance;
|
||||
uint8_t animations_duration;
|
||||
//bool use_legacy_animations
|
||||
bool up_pressed;
|
||||
bool select_pressed;
|
||||
bool down_pressed;
|
||||
void *context;
|
||||
} NeatBarLayer;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user