/** * Open a terminal * @return pointer to the terminal window */ lv_obj_t * terminal_create(void) { static lv_style_t style_bg; lv_style_copy(&style_bg, &lv_style_pretty); style_bg.body.main_color = LV_COLOR_MAKE(0x30, 0x30, 0x30); style_bg.body.grad_color = LV_COLOR_MAKE(0x30, 0x30, 0x30); style_bg.body.border.color = LV_COLOR_WHITE; style_bg.text.color = LV_COLOR_MAKE(0xE0, 0xE0, 0xE0); win = lv_win_create(lv_scr_act(), NULL); lv_win_set_style(win, LV_WIN_STYLE_BG, &style_bg); lv_obj_set_size(win, TERMINAL_WIDTH, TERMINAL_HEIGHT); lv_win_set_sb_mode(win, LV_SB_MODE_AUTO); lv_win_add_btn(win, SYMBOL_CLOSE, win_close_action); /*Make the window's content responsive*/ lv_win_set_layout(win, LV_LAYOUT_PRETTY); /*Create a label for the text of the terminal*/ label = lv_label_create(win, NULL); lv_label_set_long_mode(label, LV_LABEL_LONG_BREAK); lv_obj_set_width(label, lv_win_get_width(win)); lv_label_set_static_text(label, txt_log); /*Use the text array directly*/ /*Create a clear button*/ clr_btn = lv_btn_create(win, NULL); lv_cont_set_fit(clr_btn, true, true); lv_btn_set_action(clr_btn, LV_BTN_ACTION_CLICK, clr_click_action); lv_obj_t * btn_label = lv_label_create(clr_btn, NULL); lv_label_set_text(btn_label, "Clear"); return win; }
/** * Called when the Clear button is click to clear the text of the terminal * @param btn pointer to the clear button * @return LV_ACTION_RES_OK because the button is not deleted */ static lv_res_t clr_click_action(lv_obj_t * btn) { txt_log[0] = '\0'; lv_label_set_static_text(label, txt_log); /*Refresh the text*/ return LV_RES_OK; }
/** * Create a label objects * @param par pointer to an object, it will be the parent of the new label * @param copy pointer to a button object, if not NULL then the new object will be copied from it * @return pointer to the created button */ lv_obj_t * lv_label_create(lv_obj_t * par, lv_obj_t * copy) { /*Create a basic object*/ lv_obj_t * new_label = lv_obj_create(par, copy); lv_mem_assert(new_label); if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_func(new_label); /*Extend the basic object to a label object*/ lv_obj_allocate_ext_attr(new_label, sizeof(lv_label_ext_t)); lv_label_ext_t * ext = lv_obj_get_ext_attr(new_label); lv_mem_assert(ext); ext->text = NULL; ext->static_txt = 0; ext->recolor = 0; ext->no_break = 0; ext->body_draw = 0; ext->align = LV_LABEL_ALIGN_LEFT; ext->dot_end = LV_LABEL_DOT_END_INV; ext->long_mode = LV_LABEL_LONG_EXPAND; ext->anim_speed = LV_LABEL_SCROLL_SPEED; ext->offset.x = 0; ext->offset.y = 0; lv_obj_set_design_func(new_label, lv_label_design); lv_obj_set_signal_func(new_label, lv_label_signal); /*Init the new label*/ if(copy == NULL) { lv_obj_set_click(new_label, false); lv_label_set_long_mode(new_label, LV_LABEL_LONG_EXPAND); lv_label_set_text(new_label, "Text"); lv_label_set_style(new_label, NULL); /*Inherit parent's style*/ } /*Copy 'copy' if not NULL*/ else { lv_label_ext_t * copy_ext = lv_obj_get_ext_attr(copy); lv_label_set_long_mode(new_label, lv_label_get_long_mode(copy)); lv_label_set_recolor(new_label, lv_label_get_recolor(copy)); lv_label_set_body_draw(new_label, lv_label_get_body_draw(copy)); lv_label_set_align(new_label, lv_label_get_align(copy)); if(copy_ext->static_txt == 0) lv_label_set_text(new_label, lv_label_get_text(copy)); else lv_label_set_static_text(new_label, lv_label_get_text(copy)); /*In DOT mode save the text byte-to-byte because a '\0' can be in the middle*/ if(copy_ext->long_mode == LV_LABEL_LONG_DOT) { ext->text = lv_mem_realloc(ext->text, lv_mem_get_size(copy_ext->text)); memcpy(ext->text, copy_ext->text, lv_mem_get_size(copy_ext->text)); } memcpy(ext->dot_tmp, copy_ext->dot_tmp, sizeof(ext->dot_tmp)); ext->dot_end = copy_ext->dot_end; /*Refresh the style with new signal function*/ lv_obj_refresh_style(new_label); } return new_label; }
/** * Add data to the terminal * @param txt_in character sting to add to the terminal */ void terminal_add(const char * txt_in) { if(win == NULL) return; /*Check if the window is exists*/ uint16_t txt_len = strlen(txt_in); uint16_t old_len = strlen(txt_log); /*If the data is longer then the terminal ax size show the last part of data*/ if(txt_len > TERMINAL_LOG_LENGTH) { txt_in += (txt_len - TERMINAL_LOG_LENGTH); txt_len = TERMINAL_LOG_LENGTH; old_len = 0; } /*If the text become too long 'forget' the oldest lines*/ else if(old_len + txt_len > TERMINAL_LOG_LENGTH) { uint16_t new_start; for(new_start = 0; new_start < old_len; new_start++) { if(txt_log[new_start] == '\n') { /*If there is enough space break*/ if(new_start >= txt_len) { /*Ignore line breaks*/ while(txt_log[new_start] == '\n' || txt_log[new_start] == '\r') new_start++; break; } } } /* If it wasn't able to make enough space on line breaks * simply forget the oldest characters*/ if(new_start == old_len) { new_start = old_len - (TERMINAL_LOG_LENGTH - txt_len); } /*Move the remaining text to the beginning*/ uint16_t j; for(j = new_start; j < old_len; j++) { txt_log[j - new_start] = txt_log[j]; } old_len = old_len - new_start; txt_log[old_len] = '\0'; } memcpy(&txt_log[old_len], txt_in, txt_len); txt_log[old_len + txt_len] = '\0'; lv_label_set_static_text(label, txt_log); lv_win_focus(win, clr_btn, TERMINAL_ANIM_TIME); }