New directions ui

* Beautiful directions list ui
* Fixed a bug where the js part would send too long strings
* Fixed a bug where the js part would send directions data although
there where to many steps
This commit is contained in:
dyedgreen
2016-06-25 16:45:02 +02:00
parent f5304468f6
commit 95bc449cfb
12 changed files with 270 additions and 84 deletions
+37
View File
@@ -27,6 +27,7 @@
"SUCCESS", "SUCCESS",
"DISTANCE", "DISTANCE",
"TIME", "TIME",
"INSTRUCTION_ICONS",
"INSTRUCTIONS[20]" "INSTRUCTIONS[20]"
], ],
"resources": { "resources": {
@@ -96,6 +97,42 @@
"name": "ICON_ERROR_OTHER", "name": "ICON_ERROR_OTHER",
"targetPlatforms": null, "targetPlatforms": null,
"type": "bitmap" "type": "bitmap"
},
{
"file": "images/step_forward.png",
"name": "ICON_STEP_FORWARD",
"targetPlatforms": null,
"type": "bitmap"
},
{
"file": "images/step_left.png",
"name": "ICON_STEP_LEFT",
"targetPlatforms": null,
"type": "bitmap"
},
{
"file": "images/step_uleft.png",
"name": "ICON_STEP_ULEFT",
"targetPlatforms": null,
"type": "bitmap"
},
{
"file": "images/step_right.png",
"name": "ICON_STEP_RIGHT",
"targetPlatforms": null,
"type": "bitmap"
},
{
"file": "images/step_uright.png",
"name": "ICON_STEP_URIGHT",
"targetPlatforms": null,
"type": "bitmap"
},
{
"file": "images/step_attr.png",
"name": "ICON_STEP_ATTR",
"targetPlatforms": null,
"type": "bitmap"
} }
] ]
} }
Binary file not shown.

After

Width:  |  Height:  |  Size: 360 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 147 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 569 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 553 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 587 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 588 B

+99 -59
View File
@@ -1,120 +1,160 @@
#include "directions_draw.h" #include "directions_draw.h"
#define SQUARE_CELL_HEIGHT_SUMMARY 64 // Draw the more indicator and return the new bounds (excluding the space occupied by the more indicator)
#define SQUARE_CELL_HEIGHT_STEP 122 GRect directions_draw_more_indicator(GContext *ctx, GRect bounds) {
// Set the colors
GColor color_bg;
GColor color_arrow = GColorBlack;
#ifdef PBL_COLOR
color_bg = GColorLightGray;
#else
color_bg = GColorWhite;
#endif
// Draw the background
graphics_context_set_fill_color(ctx, color_bg);
graphics_fill_rect(ctx, GRect(0, bounds.size.h - 17, bounds.size.w, 17), 0, GCornerNone);
// Draw the arrow (draws a path)
struct GPathInfo path_arrow_info = {
.num_points = 3,
.points = (GPoint []) { {0,0}, {6,5}, {12,0} },
};
GPath *path_arrow = gpath_create(&path_arrow_info);
gpath_move_to(path_arrow, (GPoint) {(bounds.size.w - 12) / 2, bounds.size.h - 10});
graphics_context_set_fill_color(ctx, color_arrow);
gpath_draw_filled(ctx, path_arrow);
gpath_destroy(path_arrow);
// Return the new bounds
bounds.size.h -= 15;
return bounds;
}
// Work out the height of each cell // Work out the height of each cell
int16_t directions_get_cell_height(int16_t window_height, int16_t cell_index) { int16_t directions_get_cell_height(int16_t window_height, int16_t cell_index) {
// Round watches paginate! // Each cell occupies an entire screen!
#ifdef PBL_ROUND return window_height;
return window_height;
#endif
// Square watches scroll!
switch (cell_index) {
case 0:
return SQUARE_CELL_HEIGHT_SUMMARY;
break;
default:
return SQUARE_CELL_HEIGHT_STEP;
}
} }
// Draw the title card // Draw the title card
void directions_draw_summary(GContext *ctx, GRect bounds, GColor color, int distance, int time) { void directions_draw_summary(GContext *ctx, GRect bounds, GColor color, int distance, int time, char *string_address) {
// Get the strings // Get the strings
char string_distance[10]; char string_distance[10];
char string_time[10]; char string_time[10];
snprintf(string_distance, sizeof(string_distance), "%i m", distance); snprintf(string_distance, sizeof(string_distance), "%i m", distance);
snprintf(string_time, sizeof(string_time), "%i min", time); snprintf(string_time, sizeof(string_time), "%i min", time);
// Get the colors // Get the colors
#ifdef PBL_COLOR #ifdef PBL_COLOR
GColor color_secondary = GColorDarkGray; GColor color_distance = GColorDarkGray;
#else #else
GColor color_secondary = GColorWhite; GColor color_distance = GColorWhite;
color = GColorBlack; color = GColorBlack;
#endif #endif
// Draw the background
graphics_context_set_fill_color(ctx, color); // White background
graphics_context_set_fill_color(ctx, GColorWhite);
graphics_fill_rect(ctx, bounds, 0, GCornerNone); graphics_fill_rect(ctx, bounds, 0, GCornerNone);
// Draw the more indicator and get the new bounds size
bounds = directions_draw_more_indicator(ctx, bounds);
// Draw the UI
#ifdef PBL_ROUND #ifdef PBL_ROUND
// ************ // ************
// * Round UI * // * Round UI *
// ************ // ************
// Outside ring // Header bg (takes 1/2 of screen height)
graphics_context_set_fill_color(ctx, GColorWhite); graphics_context_set_fill_color(ctx, color);
graphics_fill_radial(ctx, bounds, GOvalScaleModeFitCircle, 30, 0, TRIG_MAX_ANGLE); graphics_fill_circle(ctx, (GPoint) {bounds.size.w / 2, bounds.size.h / (-2)}, bounds.size.h);
// Time // Time
GRect time_box = GRect(4, (bounds.size.h - 46) / 2, bounds.size.w - 8, 28); GRect time_box = GRect(0, 23, bounds.size.w, 28);
graphics_context_set_text_color(ctx, GColorWhite); graphics_context_set_text_color(ctx, GColorWhite);
graphics_draw_text(ctx, string_time, fonts_get_system_font(FONT_KEY_GOTHIC_28_BOLD), time_box, GTextOverflowModeWordWrap, GTextAlignmentCenter, NULL); graphics_draw_text(ctx, string_time, fonts_get_system_font(FONT_KEY_GOTHIC_28_BOLD), time_box, GTextOverflowModeWordWrap, GTextAlignmentCenter, NULL);
// Distance // Distance
GRect distance_box = GRect(4, (bounds.size.h - 46) / 2 + time_box.size.h, bounds.size.w - 8, 18); GRect distance_box = GRect(0, 23 + time_box.size.h, bounds.size.w, 18);
graphics_context_set_text_color(ctx, color_secondary); graphics_context_set_text_color(ctx, color_distance);
graphics_draw_text(ctx, string_distance, fonts_get_system_font(FONT_KEY_GOTHIC_18_BOLD), distance_box, GTextOverflowModeWordWrap, GTextAlignmentCenter, NULL); graphics_draw_text(ctx, string_distance, fonts_get_system_font(FONT_KEY_GOTHIC_18_BOLD), distance_box, GTextOverflowModeWordWrap, GTextAlignmentCenter, NULL);
// Address
GRect address_box = GRect(0, 7 + bounds.size.h / 2, bounds.size.w, bounds.size.h / 2 - 14);
GTextAttributes *text_attributes = graphics_text_attributes_create();
graphics_text_attributes_enable_screen_text_flow(text_attributes, 7);
graphics_context_set_text_color(ctx, color);
graphics_draw_text(ctx, string_address, fonts_get_system_font(FONT_KEY_GOTHIC_18_BOLD), address_box, GTextOverflowModeTrailingEllipsis, GTextAlignmentCenter, text_attributes);
graphics_text_attributes_destroy(text_attributes);
#else #else
// ************* // *************
// * Square UI * // * Square UI *
// ************* // *************
// Header bg
GRect header_box = GRect(0, 0, bounds.size.w, 67);
graphics_context_set_fill_color(ctx, color);
graphics_fill_rect(ctx, header_box, 0, GCornerNone);
// Time // Time
GRect time_box = GRect(7, 5, bounds.size.w - 14, 28); GRect time_box = GRect(7, 7, bounds.size.w - 14, 28);
graphics_context_set_text_color(ctx, GColorWhite); graphics_context_set_text_color(ctx, GColorWhite);
graphics_draw_text(ctx, string_time, fonts_get_system_font(FONT_KEY_GOTHIC_28_BOLD), time_box, GTextOverflowModeWordWrap, GTextAlignmentLeft, NULL); graphics_draw_text(ctx, string_time, fonts_get_system_font(FONT_KEY_GOTHIC_28_BOLD), time_box, GTextOverflowModeWordWrap, GTextAlignmentLeft, NULL);
// Distance // Distance
GRect distance_box = GRect(7, time_box.size.h + 5, bounds.size.w - 14, 18); GRect distance_box = GRect(7, 7 + time_box.size.h, bounds.size.w - 14, 18);
graphics_context_set_text_color(ctx, color_secondary); graphics_context_set_text_color(ctx, color_distance);
graphics_draw_text(ctx, string_distance, fonts_get_system_font(FONT_KEY_GOTHIC_18_BOLD), distance_box, GTextOverflowModeWordWrap, GTextAlignmentLeft, NULL); graphics_draw_text(ctx, string_distance, fonts_get_system_font(FONT_KEY_GOTHIC_18_BOLD), distance_box, GTextOverflowModeWordWrap, GTextAlignmentLeft, NULL);
// Address
GRect address_box = GRect(7, 7 + header_box.size.h, bounds.size.w - 14, bounds.size.h - header_box.size.h - 14);
graphics_context_set_text_color(ctx, color);
graphics_draw_text(ctx, string_address, fonts_get_system_font(FONT_KEY_GOTHIC_18_BOLD), address_box, GTextOverflowModeTrailingEllipsis, GTextAlignmentLeft, NULL);
#endif #endif
} }
// Draw a step // Draw a step
void directions_draw_step(GContext *ctx, GRect bounds, GColor color, char *text, int16_t data_index, int16_t data_count) { void directions_draw_step(GContext *ctx, GRect bounds, GColor color, char *text, GBitmap *step_icon, int16_t data_index, int16_t data_count) {
// Get the colors // Get the colors
#ifdef PBL_COLOR #ifdef PBL_BW
GColor color_text = GColorDarkGray; color = GColorWhite;
#else
GColor color_text = GColorBlack;
color = GColorBlack;
#endif #endif
// Draw the background GColor color_text = GColorBlack;
// White background
graphics_context_set_fill_color(ctx, GColorWhite); graphics_context_set_fill_color(ctx, GColorWhite);
graphics_fill_rect(ctx, bounds, 0, GCornerNone); graphics_fill_rect(ctx, bounds, 0, GCornerNone);
// Draw the more indicator and get the new bounds size (if this is not the last cell)
if (data_index + 1 < data_count) {
bounds = directions_draw_more_indicator(ctx, bounds);
}
// Draw the UI
#ifdef PBL_ROUND #ifdef PBL_ROUND
// ************ // ************
// * Round UI * // * Round UI *
// ************ // ************
// Draw text // Draw header / icon bg (takes 60px of screen height)
GRect text_box = GRect(5, (bounds.size.w - 96) / 2, bounds.size.w - 10, 96);
GTextAttributes *text_attributes = graphics_text_attributes_create();
graphics_text_attributes_enable_screen_text_flow(text_attributes, 5);
graphics_context_set_text_color(ctx, color_text);
graphics_draw_text(ctx, text, fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), text_box, GTextOverflowModeTrailingEllipsis, GTextAlignmentCenter, text_attributes);
graphics_text_attributes_destroy(text_attributes);
// Draw more indicators
graphics_context_set_fill_color(ctx, color); graphics_context_set_fill_color(ctx, color);
if (data_index < data_count - 1) { graphics_fill_circle(ctx, GPoint(bounds.size.w / 2, -80), 140);
// Bottom // Draw icon
graphics_fill_circle(ctx, GPoint(bounds.size.w / 2, bounds.size.h), 8); graphics_context_set_compositing_mode(ctx, GCompOpSet);
} graphics_draw_bitmap_in_rect(ctx, step_icon, GRect((bounds.size.w - 24) / 2, 24, 24, 24));
if (data_index > 0) { // Draw text
// Top GRect text_box = GRect(0, 67, bounds.size.w, bounds.size.h - 74);
graphics_fill_circle(ctx, GPoint(bounds.size.w / 2, 0), 8); GTextAttributes *text_attributes = graphics_text_attributes_create();
} graphics_text_attributes_enable_screen_text_flow(text_attributes, 7);
graphics_context_set_text_color(ctx, color_text);
graphics_draw_text(ctx, text, fonts_get_system_font(FONT_KEY_GOTHIC_18_BOLD), text_box, GTextOverflowModeTrailingEllipsis, GTextAlignmentCenter, text_attributes);
graphics_text_attributes_destroy(text_attributes);
#else #else
// ************* // *************
// * Square UI * // * Square UI *
// ************* // *************
// Draw header/icon bg
GRect header_box = GRect(0, 0, bounds.size.w, 52);
graphics_context_set_fill_color(ctx, color);
graphics_fill_rect(ctx, header_box, 0, GCornerNone);
// Draw icon
graphics_context_set_compositing_mode(ctx, GCompOpSet);
graphics_draw_bitmap_in_rect(ctx, step_icon, GRect((bounds.size.w - 24) / 2, 14, 24, 24));
// Draw text // Draw text
GRect text_box = GRect(7, 3, bounds.size.w - 14, bounds.size.h - 6); GRect text_box = GRect(7, 7 + header_box.size.h, bounds.size.w - 14, bounds.size.h - header_box.size.h - 14);
graphics_context_set_text_color(ctx, color_text); graphics_context_set_text_color(ctx, color_text);
graphics_draw_text(ctx, text, fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), text_box, GTextOverflowModeTrailingEllipsis, GTextAlignmentLeft, NULL); graphics_draw_text(ctx, text, fonts_get_system_font(FONT_KEY_GOTHIC_18_BOLD), text_box, GTextOverflowModeTrailingEllipsis, GTextAlignmentLeft, NULL);
// Draw block-end indicator (if not last block)
if (data_index < data_count - 1) {
GRect line_box = GRect(7, text_box.size.h + 1, 40, 4);
graphics_context_set_fill_color(ctx, color);
graphics_fill_rect(ctx, line_box, 2, GCornersAll);
}
#endif #endif
} }
+2 -2
View File
@@ -4,5 +4,5 @@
// Return the height of a cell (this groupes layout functions in one file) // Return the height of a cell (this groupes layout functions in one file)
int16_t directions_get_cell_height(int16_t window_height, int16_t cell_index); int16_t directions_get_cell_height(int16_t window_height, int16_t cell_index);
// Draw cells // Draw cells
void directions_draw_summary(GContext *ctx, GRect bounds, GColor color, int distance, int time); void directions_draw_summary(GContext *ctx, GRect bounds, GColor color, int distance, int time, char *address);
void directions_draw_step(GContext *ctx, GRect bounds, GColor color, char *text, int16_t data_index, int16_t data_count); void directions_draw_step(GContext *ctx, GRect bounds, GColor color, char *text, GBitmap *step_icon, int16_t data_index, int16_t data_count);
+96 -3
View File
@@ -9,6 +9,7 @@
#define PROGRESS_SEARCH_SEND 50 #define PROGRESS_SEARCH_SEND 50
#define PROGRESS_DISTANCE_RECIVED 80 #define PROGRESS_DISTANCE_RECIVED 80
#define PROGRESS_TIME_RECIVED PROGRESS_DISTANCE_RECIVED #define PROGRESS_TIME_RECIVED PROGRESS_DISTANCE_RECIVED
#define PROGRESS_ICONS_RECIVED PROGRESS_DISTANCE_RECIVED
#define PROGRESS_STEP_RECIVED 95 #define PROGRESS_STEP_RECIVED 95
#define PROGRESS_SUCCESS_RECIVED 100 #define PROGRESS_SUCCESS_RECIVED 100
@@ -17,6 +18,7 @@ struct RouteData {
// Data fields // Data fields
int distance; int distance;
int time; int time;
char icons[MAX_STEP_COUNT + 1];
char steps[MAX_STEP_COUNT][MAX_STEP_CHARS]; char steps[MAX_STEP_COUNT][MAX_STEP_CHARS];
int count; int count;
}; };
@@ -28,6 +30,15 @@ static int window_height;
static MenuLayer *directions_list; static MenuLayer *directions_list;
static GColor selected_type_color; static GColor selected_type_color;
// Step icons
static GBitmap *icon_step_type;
static GBitmap *icon_step_forward;
static GBitmap *icon_step_right;
static GBitmap *icon_step_left;
static GBitmap *icon_step_uright;
static GBitmap *icon_step_uleft;
static GBitmap *icon_step_attr;
// Dictation input // Dictation input
static DictationSession *dictation_session; static DictationSession *dictation_session;
static char *address; static char *address;
@@ -58,15 +69,44 @@ static int16_t get_cell_height_callback(struct MenuLayer *menu_layer, MenuIndex
// Draw menu cell callback // Draw menu cell callback
static void draw_row_callback(GContext *ctx, const Layer *cell_layer, MenuIndex *cell_index, void *context) { static void draw_row_callback(GContext *ctx, const Layer *cell_layer, MenuIndex *cell_index, void *context) {
// Determine what row to draw TODO: implement nicer UI // Local vars
int data_index = cell_index->row - 1;
GBitmap *icon;
// Determine what row to draw
switch (cell_index->row) { switch (cell_index->row) {
// Summary // Summary
case 0: case 0:
directions_draw_summary(ctx, layer_get_bounds(cell_layer), selected_type_color, route_data->distance, route_data->time); directions_draw_summary(ctx, layer_get_bounds(cell_layer), selected_type_color, route_data->distance, route_data->time, address);
break; break;
// Step description // Step description
default: default:
directions_draw_step(ctx, layer_get_bounds(cell_layer), selected_type_color, route_data->steps[cell_index->row - 1], cell_index->row - 1, (int16_t)route_data->count); // Select the correct icon
switch (route_data->icons[data_index]) {
case 'a':
icon = icon_step_type;
break;
case 'b':
icon = icon_step_forward;
break;
case 'c':
icon = icon_step_right;
break;
case 'd':
icon = icon_step_left;
break;
case 'e':
icon = icon_step_uright;
break;
case 'f':
icon = icon_step_uleft;
break;
case 'g':
icon = icon_step_attr;
break;
default:
icon = icon_step_type;
}
directions_draw_step(ctx, layer_get_bounds(cell_layer), selected_type_color, route_data->steps[data_index], icon, data_index, (int16_t)route_data->count);
} }
} }
@@ -144,6 +184,16 @@ static void app_message_inbox_recived_callback(DictionaryIterator *iter, void *c
route_data->time = (int)message->value->int32; route_data->time = (int)message->value->int32;
} }
// Test if the recived message is fof key INSTRUCTION_ICONS
message = dict_find(iter, MESSAGE_KEY_INSTRUCTION_ICONS);
if (message) {
// Set the progress
progress_layer_set_progress(progress_layer, PROGRESS_ICONS_RECIVED, true);
// Copy the icon string
strcpy(route_data->icons, message->value->cstring);
route_data->icons[MAX_STEP_COUNT] = '\0';
}
// Test if the recived message is for key INSTRUCTIONS // Test if the recived message is for key INSTRUCTIONS
for (int i = 0; i < MAX_STEP_COUNT; i++) { for (int i = 0; i < MAX_STEP_COUNT; i++) {
message = dict_find(iter, MESSAGE_KEY_INSTRUCTIONS + i); message = dict_find(iter, MESSAGE_KEY_INSTRUCTIONS + i);
@@ -212,6 +262,11 @@ static void app_message_start() {
route_data->distance = 0; route_data->distance = 0;
route_data->time = 0; route_data->time = 0;
route_data->count = 0; route_data->count = 0;
// Initialise the icons string (has the length of MAX_STEP_COUNT + 1 for correct null termination)
for (int i = 0; i < MAX_STEP_COUNT; i ++) {
route_data->icons[i] = 'a';
}
route_data->icons[MAX_STEP_COUNT] = '\0';
// Register all callbacks // Register all callbacks
app_message_register_inbox_received(app_message_inbox_recived_callback); app_message_register_inbox_received(app_message_inbox_recived_callback);
app_message_register_inbox_dropped(app_message_inbox_dropped_callback); app_message_register_inbox_dropped(app_message_inbox_dropped_callback);
@@ -274,6 +329,15 @@ static void window_unload() {
// Destroy the window // Destroy the window
window_destroy(window); window_destroy(window);
window = NULL; window = NULL;
// Destroy the step icons
gbitmap_destroy(icon_step_type);
gbitmap_destroy(icon_step_forward);
gbitmap_destroy(icon_step_right);
gbitmap_destroy(icon_step_left);
gbitmap_destroy(icon_step_uright);
gbitmap_destroy(icon_step_uleft);
gbitmap_destroy(icon_step_attr);
} }
static void window_disappear() { static void window_disappear() {
@@ -328,6 +392,35 @@ static void window_load() {
// Create the progress layer // Create the progress layer
progress_layer = progress_layer_create(bounds); progress_layer = progress_layer_create(bounds);
// Create the step icon resources
switch (selected_type_enum) {
case 0:
// Car icon
icon_step_type = gbitmap_create_with_resource(RESOURCE_ID_ICON_CAR_BLACK);
break;
case 1:
// Bike icon
icon_step_type = gbitmap_create_with_resource(RESOURCE_ID_ICON_BIKE_BLACK);
break;
case 2:
// Train icon
icon_step_type = gbitmap_create_with_resource(RESOURCE_ID_ICON_TRAIN_BLACK);
break;
case 3:
// Walk icon
icon_step_type = gbitmap_create_with_resource(RESOURCE_ID_ICON_WALK_BLACK);
break;
default:
// Forward icon
icon_step_type = gbitmap_create_with_resource(RESOURCE_ID_ICON_STEP_FORWARD);
}
icon_step_forward = gbitmap_create_with_resource(RESOURCE_ID_ICON_STEP_FORWARD);
icon_step_right = gbitmap_create_with_resource(RESOURCE_ID_ICON_STEP_RIGHT);
icon_step_left = gbitmap_create_with_resource(RESOURCE_ID_ICON_STEP_LEFT);
icon_step_uright = gbitmap_create_with_resource(RESOURCE_ID_ICON_STEP_URIGHT);
icon_step_uleft = gbitmap_create_with_resource(RESOURCE_ID_ICON_STEP_ULEFT);
icon_step_attr = gbitmap_create_with_resource(RESOURCE_ID_ICON_STEP_ATTR);
} }
// Push the window to the window stack // Push the window to the window stack
+19 -11
View File
@@ -4,8 +4,9 @@
* About the send messages * About the send messages
* ––– * –––
* (1) Overview data is send (distance, time needed) * (1) Overview data is send (distance, time needed)
* (2) Step data array is send (each step string, max 20 entrys) -> THE LAST SEND INDEX IS THE LENGTH! * (2) Step icon data is send as a 20 char string (each char encodes one icon!)
* (3) Success value is send (terminates the transmittion; it's true/false * (3) Step data array is send (each step string, max 20 entrys) -> THE LAST SEND INDEX IS THE LENGTH!
* (4) Success value is send (terminates the transmittion; it's true/false
* value determines whether the transmition was successfull or not (E.g. * value determines whether the transmition was successfull or not (E.g.
* if false is send as the success first, no route was found) * if false is send as the success first, no route was found)
* *
@@ -21,12 +22,17 @@
* The first character is always the type selected, the rest * The first character is always the type selected, the rest
* is the written address. * is the written address.
* {selected_type} vals: 0 = Car; 1 = Bike; 2 = Train; 3 = Walk; * {selected_type} vals: 0 = Car; 1 = Bike; 2 = Train; 3 = Walk;
*
* About the step icon data string
* –––
* Chars map to the following icons: type: 'a', forward: 'b', right: 'c', left: 'd', uRight: 'e', uLeft: 'f', attr: 'g'
*/ */
// Data keys // Data keys
var keys = require('message_keys'); var keys = require('message_keys');
var maxStepCount = 20; var maxStepCount = 20;
var maxStepStringLength = 128;
var currentMessageNumber = 0; var currentMessageNumber = 0;
var messagePadding = 10; var messagePadding = 10;
@@ -55,16 +61,13 @@ function sendStepItem(stepList, index, messageNumber) {
// Build message // Build message
var key = keys.INSTRUCTIONS + index; var key = keys.INSTRUCTIONS + index;
var dict = {}; var dict = {};
dict[key] = stepList[index]; dict[key] = stepList[index].substr(0, maxStepStringLength);
// Send message to pebble // Send message to pebble
Pebble.sendAppMessage(dict, function() { Pebble.sendAppMessage(dict, function() {
// Success, send next item // Success, send next item
index ++; index ++;
if (maxStepCount > stepList.length) { if (index < stepList.length && index < maxStepCount) {
// Too many steps error
sendSuccess(2, messageNumber);
} else if (index < stepList.length && index < maxStepCount) {
// Recursive callbacks, hell yeah! // Recursive callbacks, hell yeah!
sendStepItem(stepList, index, messageNumber); sendStepItem(stepList, index, messageNumber);
} else { } else {
@@ -77,15 +80,17 @@ function sendStepItem(stepList, index, messageNumber) {
}); });
} }
function sendRoute(success, distance, time, stepList, stepIconList, messageNumber) { function sendRoute(success, distance, time, stepList, stepIconsString, messageNumber) {
// Send message to pebble if a route was found // Send message to pebble if a route was found
if (success) { if (success && maxStepCount >= stepList.length) {
// Build message // Build message
var keyDistance = keys.DISTANCE; var keyDistance = keys.DISTANCE;
var keyTime = keys.TIME; var keyTime = keys.TIME;
var keyIcons = keys.INSTRUCTION_ICONS;
var dict = {}; var dict = {};
dict[keyDistance] = +distance; dict[keyDistance] = +distance;
dict[keyTime] = +time; dict[keyTime] = +time;
dict[keyIcons] = ''.concat(stepIconsString);
// Transmit // Transmit
Pebble.sendAppMessage(dict, function() { Pebble.sendAppMessage(dict, function() {
@@ -95,6 +100,9 @@ function sendRoute(success, distance, time, stepList, stepIconList, messageNumbe
// Error // Error
console.log('Transmission failed at [OVERVIEW]'); console.log('Transmission failed at [OVERVIEW]');
}); });
} else if (maxStepCount < stepList.length) {
// Too many steps error
sendSuccess(2, messageNumber);
} else { } else {
// Send error message (route not found) // Send error message (route not found)
sendSuccess(1, messageNumber); sendSuccess(1, messageNumber);
@@ -106,9 +114,9 @@ function fetchAndSendRoute(routeType, searchText, messageNumber) {
// Log the recived data // Log the recived data
console.log('Route type:', routeType); console.log('Route type:', routeType);
console.log('Search text:', searchText); console.log('Search text:', searchText);
// Load a route from here api. Data format: { distance, time, stepList[string], stepIconList[int] } // Load a route from here api. Data format: { distance, time, stepList[string], stepIconsString }
locationService.createRoute(routeType, searchText, function(success, data) { locationService.createRoute(routeType, searchText, function(success, data) {
sendRoute(success, data.distance, data.time, data.stepList, data.stepIconList, messageNumber); sendRoute(success, data.distance, data.time, data.stepList, data.stepIconsString, messageNumber);
}); });
} }
+17 -9
View File
@@ -82,7 +82,15 @@ function loadRouteData(routeType, fromLat, fromLon, toLat, toLon, callback) {
// Transport modes, mapped to pebble ids // Transport modes, mapped to pebble ids
var modes = ['car', 'bicycle', 'publicTransport', 'pedestrian']; var modes = ['car', 'bicycle', 'publicTransport', 'pedestrian'];
// Pebble direction icons, mapped to pebble ids (type = show nav type icon, attr = show attribution icon) // Pebble direction icons, mapped to pebble ids (type = show nav type icon, attr = show attribution icon)
var icons = ['type', 'forward', 'right', 'left', 'uRight', 'uLeft', 'attr']; var icons = {
type: 'a',
forward: 'b',
right: 'c',
left: 'd',
uRight: 'e',
uLeft: 'f',
attr: 'g',
};
// Maps the direction retrived from here api to icon name // Maps the direction retrived from here api to icon name
var directionMap = { var directionMap = {
forward: 'forward', forward: 'forward',
@@ -107,14 +115,14 @@ function loadRouteData(routeType, fromLat, fromLon, toLat, toLon, callback) {
if (success) { if (success) {
// Success (will fail if expected fields are not available in response) // Success (will fail if expected fields are not available in response)
try { try {
// Our route data will go here. Format: { distance, time, stepList[string], stepIconList[int] } // Our route data will go here. Format: { distance, time, stepList[string], stepIconsString[int] }
var routeData = {}; var routeData = {};
// Get the summary // Get the summary
routeData.distance = res.response.route[0].summary.distance; /* in meters */ routeData.distance = res.response.route[0].summary.distance; /* in meters */
routeData.time = Math.ceil(res.response.route[0].summary.travelTime / 60); /* in minutes */ routeData.time = Math.ceil(res.response.route[0].summary.travelTime / 60); /* in minutes */
// Get the steps // Get the steps
routeData.stepList = []; routeData.stepList = [];
routeData.stepIconList = []; routeData.stepIconsString = '';
res.response.route[0].leg[0].maneuver.forEach(function(step, index) { res.response.route[0].leg[0].maneuver.forEach(function(step, index) {
// Add the text // Add the text
routeData.stepList[index] = step.instruction; routeData.stepList[index] = step.instruction;
@@ -122,21 +130,21 @@ function loadRouteData(routeType, fromLat, fromLon, toLat, toLon, callback) {
if (step.hasOwnProperty('direction')) { if (step.hasOwnProperty('direction')) {
// Display the specified icon // Display the specified icon
if (directionMap.hasOwnProperty(step.direction)) { if (directionMap.hasOwnProperty(step.direction)) {
routeData.stepIconList[index] = icons.indexOf(directionMap[step.direction]); routeData.stepIconsString = routeData.stepIconsString.concat(icons[directionMap[step.direction]]);
} else { } else {
// Display the travel type icon // Display the travel type icon
routeData.stepIconList[index] = icons.indexOf('type'); routeData.stepIconsString = routeData.stepIconsString.concat(icons['type']);
} }
} else { } else {
// Display the travel type icon // Display the travel type icon
routeData.stepIconList[index] = icons.indexOf('type'); routeData.stepIconsString = routeData.stepIconsString.concat(icons['type']);
} }
}); });
// Test for attribution // Test for attribution
if (res.response.hasOwnProperty('sourceAttribution')) { if (res.response.hasOwnProperty('sourceAttribution')) {
// Add attribution text as last list entry, removing all html markup from it // Add attribution text as last list entry, removing all html markup from it
routeData.stepList.push(res.response.sourceAttribution.attribution.replace(/<.+?>/g, '')); routeData.stepList.push(res.response.sourceAttribution.attribution.replace(/<.+?>/g, ''));
routeData.stepIconList.push(icons.indexOf('attr')); routeData.stepIconsString = routeData.stepIconsString.concat(icons['attr']);
} }
// We are done // We are done
callback(true, routeData); callback(true, routeData);
@@ -147,7 +155,7 @@ function loadRouteData(routeType, fromLat, fromLon, toLat, toLon, callback) {
// Error // Error
routeErrorCallback(callback); routeErrorCallback(callback);
} }
}, true); });
} }
// Performs all the steps neccessary to return a complete route (the callback takes: success / route data) // Performs all the steps neccessary to return a complete route (the callback takes: success / route data)
@@ -173,7 +181,7 @@ function createRoute(routeType, searchText, callback) {
} }
// Helper function to define createRoute error callback all in one place // Helper function to define createRoute error callback all in one place
function routeErrorCallback(callback) { function routeErrorCallback(callback) {
callback(false, { distance: 0, time: 0, stepList: [], stepIconList: [] }); callback(false, { distance: 0, time: 0, stepList: [], stepIconsString: '' });
} }