mirror of https://github.com/meshcore-dev/MeshCore
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
797 lines
23 KiB
797 lines
23 KiB
#include <Arduino.h>
|
|
|
|
#include "esp_log.h"
|
|
#include "uiDefines.h"
|
|
#include "uiVars.h"
|
|
|
|
#include "uiManager.h"
|
|
|
|
#include "../src/fonts/fonts.h"
|
|
|
|
#include <helpers/ContactInfo.h>
|
|
#include <helpers/AdvertDataHelpers.h>
|
|
|
|
#if defined(LANG_GR)
|
|
const char *UIManager::days[7] = {"Κυρ", "Δευ", "Τρι", "Τετ", "Πεμ", "Παρ", "Σαβ"};
|
|
const char *UIManager::months[12] = {"Ιαν", "Φεβ", "Μαρ", "Απρ", "Μαι", "Ιουν",
|
|
"Ιουλ", "Αυγ", "Σεπ", "Οκτ", "Νοε", "Δεκ"};
|
|
#elif defined(LANG_EN)
|
|
const char *UIManager::days[7] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
|
|
const char *UIManager::months[12] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
|
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
|
|
#endif
|
|
|
|
#define TAG "UIManager"
|
|
|
|
extern void handleCommand(char *msg);
|
|
|
|
UIManager::UIManager() {
|
|
|
|
tmp_buf = (char*)malloc(128);
|
|
|
|
lv_disp_t * dispp = lv_disp_get_default();
|
|
lv_theme_t * theme = lv_theme_default_init(dispp, lv_palette_main(LV_PALETTE_BLUE), lv_palette_main(LV_PALETTE_RED),
|
|
false, LV_FONT_DEFAULT);
|
|
lv_disp_set_theme(dispp, theme);
|
|
ui_Screen1_screen_init();
|
|
ui____initial_actions0 = lv_obj_create(NULL);
|
|
lv_disp_load_scr(ui_Screen1);
|
|
|
|
}
|
|
|
|
void UIManager::format_time(uint32_t ts, char *buf, size_t len)
|
|
{
|
|
time_t t = ts;
|
|
struct tm *tm_info = localtime(&t);
|
|
strftime(buf, len, "%H:%M:%S", tm_info);
|
|
}
|
|
|
|
void UIManager::format_datetime(char *buf, size_t size, const struct tm *timeinfo) {
|
|
char tmp[64];
|
|
strftime(tmp, sizeof(tmp), "%a, %d %b %Y", timeinfo);
|
|
|
|
int wday = timeinfo->tm_wday; // 0=Κυρ ... 6=Σαβ
|
|
int mon = timeinfo->tm_mon; // 0=Ιαν ... 11=Δεκ
|
|
|
|
// replace %a and %b with selected language
|
|
snprintf(buf, size, "%s, %02d %s %d", days[wday], timeinfo->tm_mday, months[mon], 1900 + timeinfo->tm_year);
|
|
}
|
|
|
|
void UIManager::updateDateTime(const struct tm timeinfo) {
|
|
// TODO: Add to settings "Date format"
|
|
char date_str[50];
|
|
format_datetime(date_str, sizeof(date_str), &timeinfo);
|
|
lv_label_set_text(ui_ValueDate, date_str);
|
|
|
|
// TODO: Add to settings "Hour format"
|
|
strftime(tmp_buf, 50, "%H:%M", &timeinfo); // 24h format
|
|
//strftime(tmp_buf, 50, "%I:%M %p", &timeinfo); // 12h format
|
|
lv_label_set_text(ui_ValueTime, tmp_buf);
|
|
|
|
// TODO: Add to settings "dim at night"
|
|
// TODO: Add to settings "dim hours"
|
|
// TODO: Add to settings "dim percentage"
|
|
if (timeinfo.tm_hour > 21 || timeinfo.tm_hour < 7) {
|
|
setNightMode(true);
|
|
} else {
|
|
setNightMode(false);
|
|
}
|
|
}
|
|
|
|
void UIManager::clearDateTime() {
|
|
#if defined(LANG_EN)
|
|
uiManager->updateInfo("Clock sync...", COLOR_WHITE);
|
|
#elif defined(LANG_GR)
|
|
uiManager->updateInfo("Συγχρονισμός ώρας...", COLOR_WHITE);
|
|
#endif
|
|
lv_label_set_text(ui_ValueDate, "--- --/--/----");
|
|
lv_label_set_text(ui_ValueTime, "--:--");
|
|
}
|
|
|
|
void UIManager::timestampToTime(time_t timestamp, char *buffer, size_t buffer_size) {
|
|
struct tm *time_info;
|
|
time_info = localtime(×tamp);
|
|
strftime(buffer, buffer_size, "%H:%M", time_info);
|
|
}
|
|
|
|
const char* UIManager::convertDegreesToDirection(int degrees) {
|
|
// Normalize degrees to [0, 360)
|
|
degrees = degrees % 360;
|
|
if (degrees < 0) degrees += 360;
|
|
|
|
#if defined(LANG_EN)
|
|
static constexpr const char* dirs[] = {"N", "NE", "E", "SE", "S", "SW", "W", "NW"};
|
|
#elif defined(LANG_GR)
|
|
static constexpr const char* dirs[] = {"Β", "ΒΑ", "Α", "ΝΑ", "Ν", "ΝΔ", "Δ", "ΒΔ"};
|
|
#else
|
|
#error "No Language defined!"
|
|
#endif
|
|
|
|
// Each direction covers 45°, starting at N = 0°
|
|
int index = static_cast<int>((degrees + 22.5) / 45.0) % 8;
|
|
return dirs[index];
|
|
}
|
|
|
|
|
|
int UIManager::windSpeedToBeaufort(float speed) {
|
|
static const float limits[] = {
|
|
0.5, 1.5, 3.3, 5.5, 7.9, 10.7,
|
|
13.8, 17.1, 20.7, 24.4, 28.4, 32.6
|
|
};
|
|
|
|
for (int i = 0; i < 12; ++i)
|
|
if (speed < limits[i])
|
|
return i;
|
|
return 12;
|
|
}
|
|
|
|
void UIManager::updateValues() {
|
|
lv_label_set_text(ui_ValueTime, "--:--");
|
|
}
|
|
|
|
void UIManager::updateInfo(const char *str, uint32_t color) {
|
|
// lv_label_set_text(ui_ValueLastUpdate, str);
|
|
// lv_obj_set_style_text_color(ui_ValueLastUpdate, lv_color_hex(color), LV_PART_MAIN | LV_STATE_DEFAULT);
|
|
}
|
|
|
|
void UIManager::addChatBubble(const char *time_str, const char *sender, const char *msg,bool is_self)
|
|
{
|
|
// Remove oldest
|
|
if (chat_count >= MAX_CHAT_MESSAGES) {
|
|
lv_obj_del(chat_items[0]);
|
|
memmove(&chat_items[0], &chat_items[1], sizeof(lv_obj_t*) * (MAX_CHAT_MESSAGES - 1));
|
|
chat_count--;
|
|
}
|
|
|
|
// Row container (align bubble left/right)
|
|
lv_obj_t *row = lv_obj_create(ui_ChannelMessages);
|
|
lv_obj_set_width(row, lv_pct(100));
|
|
lv_obj_set_height(row, LV_SIZE_CONTENT);
|
|
lv_obj_set_style_bg_opa(row, 0, 0);
|
|
lv_obj_set_style_pad_all(row, 0, 0);
|
|
lv_obj_set_style_border_width(row, 0, 0);
|
|
lv_obj_set_style_outline_width(row, 0, 0);
|
|
lv_obj_clear_flag(row, LV_OBJ_FLAG_SCROLLABLE);
|
|
|
|
lv_obj_set_flex_flow(row, LV_FLEX_FLOW_ROW);
|
|
lv_obj_set_flex_align(row,
|
|
is_self ? LV_FLEX_ALIGN_END : LV_FLEX_ALIGN_START,
|
|
LV_FLEX_ALIGN_START,
|
|
LV_FLEX_ALIGN_START);
|
|
|
|
// Bubble container (COLUMN)
|
|
lv_obj_t *bubble = lv_obj_create(row);
|
|
lv_obj_set_width(bubble, lv_pct(85));
|
|
lv_obj_set_height(bubble, LV_SIZE_CONTENT);
|
|
lv_obj_set_style_radius(bubble, 12, 0);
|
|
lv_obj_set_style_pad_all(bubble, 10, 0);
|
|
lv_obj_set_style_bg_color(bubble,
|
|
is_self ? lv_color_hex(0x1E88E5) : lv_color_hex(0x2C2C2C), 0);
|
|
|
|
// IMPORTANT: vertical layout inside bubble
|
|
lv_obj_set_flex_flow(bubble, LV_FLEX_FLOW_COLUMN);
|
|
lv_obj_set_flex_align(bubble,
|
|
LV_FLEX_ALIGN_START,
|
|
LV_FLEX_ALIGN_START,
|
|
LV_FLEX_ALIGN_START);
|
|
|
|
// Header row (sender + time)
|
|
lv_obj_t *hdr = lv_obj_create(bubble);
|
|
lv_obj_set_width(hdr, lv_pct(100));
|
|
lv_obj_set_height(hdr, LV_SIZE_CONTENT);
|
|
lv_obj_set_style_bg_opa(hdr, 0, 0);
|
|
lv_obj_set_style_border_width(hdr, 0, 0);
|
|
lv_obj_set_style_pad_all(hdr, 0, 0);
|
|
lv_obj_set_style_outline_width(hdr, 0, 0);
|
|
|
|
lv_obj_set_flex_flow(hdr, LV_FLEX_FLOW_ROW);
|
|
lv_obj_set_flex_align(hdr,
|
|
LV_FLEX_ALIGN_SPACE_BETWEEN,
|
|
LV_FLEX_ALIGN_START, //LV_FLEX_ALIGN_CENTER, // Ευθυγράμμιση ονόματος/ώρας στον κάθετο άξονα
|
|
LV_FLEX_ALIGN_START);
|
|
|
|
lv_obj_t *lbl_sender = lv_label_create(hdr);
|
|
lv_label_set_text(lbl_sender, sender);
|
|
lv_obj_set_style_text_color(lbl_sender,
|
|
is_self ? lv_color_hex(0xE3F2FD) : lv_color_hex(0x90CAF9), 0);
|
|
lv_obj_set_style_text_font(lbl_sender, &lv_font_arial_22, 0);
|
|
|
|
lv_obj_t *lbl_time = lv_label_create(hdr);
|
|
lv_label_set_text(lbl_time, time_str);
|
|
lv_obj_set_style_text_color(lbl_time, lv_color_hex(0xB0B0B0), 0);
|
|
lv_obj_set_style_text_font(lbl_time, &lv_font_arial_20, 0);
|
|
|
|
// Message body (below header)
|
|
lv_obj_t *lbl_msg = lv_label_create(bubble);
|
|
lv_label_set_text(lbl_msg, msg);
|
|
lv_label_set_long_mode(lbl_msg, LV_LABEL_LONG_WRAP);
|
|
lv_obj_set_width(lbl_msg, lv_pct(100));
|
|
|
|
lv_obj_set_style_text_color(lbl_msg, lv_color_hex(0xFFFFFF), 0);
|
|
lv_obj_set_style_text_font(lbl_msg, &lv_font_arial_26, 0);
|
|
|
|
// Spacing between header and text
|
|
//lv_obj_set_style_margin_top(lbl_msg, 6, 0);
|
|
lv_obj_set_style_pad_row(bubble, 6, 0);
|
|
|
|
chat_items[chat_count++] = row;
|
|
|
|
lv_obj_scroll_to_view(row, LV_ANIM_ON);
|
|
}
|
|
|
|
void UIManager::addPrivateChatBubble(const char *time_str, const char *msg, bool is_self) {
|
|
|
|
lv_obj_set_style_pad_bottom(ui_ContactMessages, 20, 0);
|
|
|
|
// 1. Row container
|
|
lv_obj_t* row = LvObj(ui_ContactMessages)
|
|
.width(lv_pct(100))
|
|
.height(LV_SIZE_CONTENT)
|
|
.bgOpa(0)
|
|
.border(0)
|
|
.padAll(4)
|
|
.scrollable(false)
|
|
.flexFlow(LV_FLEX_FLOW_ROW)
|
|
.flexAlign(
|
|
is_self ? LV_FLEX_ALIGN_END : LV_FLEX_ALIGN_START,
|
|
LV_FLEX_ALIGN_START,
|
|
LV_FLEX_ALIGN_START
|
|
);
|
|
|
|
// 2. Aligner (Column) - label and time
|
|
lv_obj_t* aligner = LvObj(row)
|
|
.width(LV_SIZE_CONTENT)
|
|
.height(LV_SIZE_CONTENT)
|
|
.bgOpa(0)
|
|
.border(0)
|
|
.padAll(0)
|
|
.scrollable(false)
|
|
.flexFlow(LV_FLEX_FLOW_ROW)
|
|
.flexAlign(
|
|
is_self ? LV_FLEX_ALIGN_END : LV_FLEX_ALIGN_START,
|
|
LV_FLEX_ALIGN_START,
|
|
LV_FLEX_ALIGN_START
|
|
);
|
|
lv_obj_set_style_pad_row(aligner, 4, 0);
|
|
|
|
// 3. Το Label-Bubble (Ενοποιημένο)
|
|
lv_obj_t *lbl_msg = lv_label_create(aligner);
|
|
|
|
// Long mode για wrap
|
|
lv_label_set_long_mode(lbl_msg, LV_LABEL_LONG_WRAP);
|
|
lv_label_set_text(lbl_msg, msg);
|
|
lv_obj_set_style_text_font(lbl_msg, &lv_font_arial_22, 0);
|
|
|
|
// Fixed max width για wrap
|
|
lv_obj_set_width(lbl_msg, 400); // max πλάτος
|
|
lv_obj_set_height(lbl_msg, LV_SIZE_CONTENT); // αυτόματο ύψος
|
|
|
|
// Bubble style
|
|
lv_obj_set_style_bg_opa(lbl_msg, LV_OPA_COVER, 0);
|
|
lv_obj_set_style_radius(lbl_msg, 12, 0);
|
|
lv_obj_set_style_pad_all(lbl_msg, 12, 0);
|
|
|
|
if(is_self) {
|
|
lv_obj_set_style_bg_color(lbl_msg, lv_color_hex(0x1E88E5), 0);
|
|
lv_obj_set_style_text_color(lbl_msg, lv_color_hex(0xFFFFFF), 0);
|
|
} else {
|
|
lv_obj_set_style_bg_color(lbl_msg, lv_color_hex(0xFFFFFF), 0);
|
|
lv_obj_set_style_text_color(lbl_msg, lv_color_hex(0x000000), 0);
|
|
}
|
|
|
|
// 4. Η Ώρα
|
|
lv_obj_t *lbl_time = lv_label_create(aligner);
|
|
lv_label_set_text(lbl_time, time_str);
|
|
lv_obj_set_style_text_color(lbl_time, lv_color_hex(0x808080), 0);
|
|
lv_obj_set_style_text_font(lbl_time, &lv_font_arial_14, 0);
|
|
|
|
lv_obj_scroll_to_view(row, LV_ANIM_ON);
|
|
}
|
|
|
|
void UIManager::getInitials(const char *name, char *out) {
|
|
out[0] = 0;
|
|
if (!name || !name[0]) return;
|
|
|
|
const char *p = name;
|
|
while (*p && !isalnum((unsigned char)*p)) {
|
|
p++;
|
|
}
|
|
|
|
char first = (*p) ? *p : name[0];
|
|
char second = 0;
|
|
const char *space = strchr(name, ' ');
|
|
|
|
if (space) {
|
|
const char *s = space + 1;
|
|
while (*s && !isalnum((unsigned char)*s)) {
|
|
s++;
|
|
}
|
|
if (*s) {
|
|
second = *s;
|
|
}
|
|
}
|
|
|
|
out[0] = toupper((unsigned char)first);
|
|
if (second) {
|
|
out[1] = toupper((unsigned char)second);
|
|
out[2] = 0;
|
|
} else {
|
|
out[1] = 0;
|
|
}
|
|
}
|
|
|
|
void UIManager::formatLastSeen(uint32_t ts, char *out, size_t len) {
|
|
if (ts == 0) {
|
|
snprintf(out, len, "Never");
|
|
return;
|
|
}
|
|
|
|
time_t t = (time_t)ts;
|
|
struct tm *tm = localtime(&t);
|
|
|
|
if (tm == nullptr) {
|
|
snprintf(out, len, "Unknown");
|
|
return;
|
|
}
|
|
|
|
snprintf(out, len, "%02d:%02d %02d/%02d/%02d",
|
|
tm->tm_hour,
|
|
tm->tm_min,
|
|
tm->tm_mday,
|
|
tm->tm_mon + 1,
|
|
(tm->tm_year + 1900) % 100); // Προσθέτουμε το 1900 και παίρνουμε τα τελευταία 2 ψηφία
|
|
}
|
|
|
|
static void onContactClick(lv_event_t *e)
|
|
{
|
|
UIManager *self = (UIManager*) lv_event_get_user_data(e);
|
|
if(self) self->handleContactClick(e);
|
|
}
|
|
|
|
void UIManager::handleContactClick(lv_event_t *e)
|
|
{
|
|
lv_obj_t *row = lv_event_get_target(e);
|
|
ContactInfo *c = (ContactInfo*) lv_obj_get_user_data(row);
|
|
|
|
Serial.printf("Clicked: %s\n", c->name);
|
|
}
|
|
|
|
void UIManager::addContactToUI(ContactInfo c)
|
|
{
|
|
const int ROW_W = 200;
|
|
const int ROW_H = 64;
|
|
const int AVATAR = 44;
|
|
const int PAD = 4;
|
|
|
|
// ============================
|
|
// List row button
|
|
// ============================
|
|
lv_obj_t* btn = lv_list_add_btn(ui_Contacts, nullptr, nullptr);
|
|
|
|
LvObj(btn, true)
|
|
.size(ROW_W, ROW_H)
|
|
.padAll(0)
|
|
.bgColor(0x000000)
|
|
.bgOpa(LV_OPA_COVER)
|
|
.noDecor()
|
|
.border(1)
|
|
.scrollable(false);
|
|
|
|
lv_obj_set_layout(btn, 0);
|
|
lv_obj_set_style_border_side(btn, LV_BORDER_SIDE_BOTTOM, 0);
|
|
lv_obj_set_style_border_color(btn, lv_color_hex(0x222222), 0);
|
|
lv_obj_set_style_bg_color(btn, lv_color_hex(0x111111), LV_STATE_PRESSED);
|
|
|
|
// Store ContactInfo
|
|
auto* store = new ContactInfo(c);
|
|
lv_obj_set_user_data(btn, store);
|
|
|
|
lv_obj_add_event_cb(btn, onContactClick, LV_EVENT_CLICKED, this);
|
|
|
|
// ============================
|
|
// Avatar container
|
|
// ============================
|
|
lv_obj_t* content = LvObj(btn)
|
|
.size(ROW_H, ROW_H)
|
|
.position(0, 0)
|
|
.padAll(0)
|
|
.bgOpa(LV_OPA_TRANSP)
|
|
.border(0)
|
|
.scrollable(false)
|
|
.raw();
|
|
|
|
// Avatar circle
|
|
lv_obj_t* avatar = LvObj(content)
|
|
.size(AVATAR, AVATAR)
|
|
.position(0, 10)
|
|
.radius(LV_RADIUS_CIRCLE)
|
|
.bgColor(0x4A90E2)
|
|
.border(0)
|
|
.raw();
|
|
|
|
// Initials
|
|
char initials[4];
|
|
if (c.type == ADV_TYPE_REPEATER) {
|
|
strcpy(initials, "(R)");
|
|
} else {
|
|
getInitials(c.name, initials);
|
|
}
|
|
|
|
LvLabel(avatar)
|
|
.text(initials)
|
|
.font(&lv_font_arial_22)
|
|
.textColor(0xFFFFFF)
|
|
.align(LV_ALIGN_CENTER);
|
|
|
|
// ============================
|
|
// Text column
|
|
// ============================
|
|
int text_x = PAD + AVATAR + PAD;
|
|
int text_w = ROW_W - text_x - PAD;
|
|
|
|
lv_obj_t* text_col = LvObj(btn)
|
|
.position(text_x, 0)
|
|
.size(text_w, ROW_H - PAD)
|
|
.padAll(0)
|
|
.bgOpa(LV_OPA_TRANSP)
|
|
.border(0)
|
|
.scrollable(false)
|
|
.raw();
|
|
|
|
// Name label
|
|
LvLabel(text_col)
|
|
.text(c.name)
|
|
.position(0, PAD + 4)
|
|
.width(text_w)
|
|
.font(&lv_font_arial_20)
|
|
.textColor(0xFFFFFF)
|
|
.wrap(false);
|
|
|
|
// Last seen
|
|
char lastSeen[32];
|
|
formatLastSeen(c.lastmod, lastSeen, sizeof(lastSeen));
|
|
|
|
LvLabel(text_col)
|
|
.text(lastSeen)
|
|
.position(0, PAD + 32)
|
|
.width(text_w)
|
|
.font(&lv_font_arial_16)
|
|
.textColor(0x888888)
|
|
.wrap(false);
|
|
|
|
// ============================
|
|
// Disable child clicks
|
|
// ============================
|
|
LvObj(avatar, true).clickable(false);
|
|
LvObj(text_col, true).clickable(false);
|
|
}
|
|
|
|
void UIManager::onShowKeyboard()
|
|
{
|
|
LvKeyboard(ui_Keyboard, true).show(true);
|
|
LvObj(ui_DimOverlay, true).clickable(true);
|
|
LvObj(ui_ChannelInput, true).positionY(channelInputBaseKeybOnY);
|
|
LvObj(ui_SendBtn, true).positionY(channelInputBaseKeybOnY);
|
|
}
|
|
|
|
void UIManager::onHideKeyboard()
|
|
{
|
|
LvKeyboard(ui_Keyboard, true).show(false);
|
|
LvObj(ui_DimOverlay, true).clickable(false);
|
|
LvObj(ui_ChannelInput, true).positionY(channelInputBaseY);
|
|
LvObj(ui_SendBtn, true).positionY(channelInputBaseY);
|
|
}
|
|
|
|
static void s_onChannelInputFocus(lv_event_t *e)
|
|
{
|
|
UIManager *self = (UIManager*) lv_event_get_user_data(e);
|
|
if(self) self->onChannelInputFocus(e);
|
|
}
|
|
|
|
void UIManager::onChannelInputFocus(lv_event_t* e)
|
|
{
|
|
lv_obj_t* ta = lv_event_get_target(e);
|
|
if(!ui_Keyboard || !ta) return;
|
|
|
|
lv_keyboard_set_textarea(ui_Keyboard, ta);
|
|
onShowKeyboard();
|
|
}
|
|
|
|
static void s_onSendClick(lv_event_t *e)
|
|
{
|
|
UIManager *self = (UIManager*) lv_event_get_user_data(e);
|
|
if(self) self->onSendClick(e);
|
|
}
|
|
|
|
void UIManager::onSendClick(lv_event_t* e)
|
|
{
|
|
|
|
char fullMessage[260];
|
|
char msgCopy[200];
|
|
|
|
const char* msg = lv_textarea_get_text(ui_ChannelInput);
|
|
if(msg == NULL || msg[0] == '\0') return;
|
|
|
|
strncpy(msgCopy, msg, sizeof(msgCopy) - 1);
|
|
msgCopy[sizeof(msgCopy) - 1] = '\0';
|
|
|
|
lv_textarea_set_text(ui_ChannelInput, "");
|
|
|
|
snprintf(fullMessage, sizeof(fullMessage), "public %s", msgCopy);
|
|
//handleCommand(fullMessage);
|
|
handleCommand(msgCopy);
|
|
|
|
char time_buf[16];
|
|
time_t now = time(NULL);
|
|
struct tm t;
|
|
localtime_r(&now, &t);
|
|
|
|
sprintf(time_buf, "%02d:%02d:%02d\n", t.tm_hour, t.tm_min, t.tm_sec);
|
|
addChatBubble(time_buf, "Me", msgCopy, true);
|
|
|
|
onHideKeyboard();
|
|
}
|
|
|
|
static void s_onKeyboardEvent(lv_event_t *e)
|
|
{
|
|
UIManager *self = (UIManager*) lv_event_get_user_data(e);
|
|
if(self) self->onKeyboardEvent(e);
|
|
}
|
|
|
|
void UIManager::onKeyboardEvent(lv_event_t* e)
|
|
{
|
|
lv_event_code_t code = lv_event_get_code(e);
|
|
|
|
if(code == LV_EVENT_READY || code == LV_EVENT_CANCEL)
|
|
{
|
|
LvKeyboard(ui_Keyboard, true).show(false);
|
|
|
|
LvObj(ui_ChannelInput, true).positionY(channelInputBaseY);
|
|
LvObj(ui_SendBtn, true).positionY(channelInputBaseY);
|
|
|
|
LvObj(ui_DimOverlay, true)
|
|
.bgOpa(0)
|
|
.clickable(false);
|
|
}
|
|
}
|
|
|
|
|
|
static void s_onDimOverlayClick(lv_event_t *e)
|
|
{
|
|
UIManager *self = (UIManager*) lv_event_get_user_data(e);
|
|
if(self) self->onDimOverlayClick(e);
|
|
}
|
|
|
|
void UIManager::onDimOverlayClick(lv_event_t* e)
|
|
{
|
|
onHideKeyboard();
|
|
}
|
|
|
|
static void onScrollBeginEvent(lv_event_t *e)
|
|
{
|
|
UIManager *self = (UIManager*) lv_event_get_user_data(e);
|
|
if(self) self->scroll_begin_event(e);
|
|
}
|
|
|
|
void UIManager::scroll_begin_event(lv_event_t *e)
|
|
{
|
|
if (lv_event_get_code(e) == LV_EVENT_SCROLL_BEGIN) {
|
|
lv_anim_t* a = (lv_anim_t*)lv_event_get_param(e);
|
|
if (a) a->time = 0;
|
|
|
|
}
|
|
}
|
|
|
|
void UIManager::ui_Screen1_screen_init(void)
|
|
{
|
|
//lv_disp_set_rotation(disp, LV_DISP_ROT_90);
|
|
//ui_Screen1 = lv_obj_create(NULL);
|
|
|
|
ui_Screen1 = LvObj(NULL)
|
|
.scrollable(false)
|
|
.bgColor(0x000000)
|
|
.bgOpa(255);
|
|
|
|
LvTabView tabView(ui_Screen1);
|
|
tabView
|
|
.size(480, 480)
|
|
.align(LV_ALIGN_CENTER)
|
|
.bgColor(0x000000)
|
|
.contentNoScroll()
|
|
.tabBtnBg(0x424242)
|
|
.tabBtnText(0xFFFFFF, &lv_font_arial_18);
|
|
|
|
ui_TabView1 = tabView.raw();
|
|
|
|
#if defined(LANG_EN)
|
|
ui_TabPageHome = ui_TabView1.addTab("Home");
|
|
ui_TabPageContacts = ui_TabView1.addTab("Contacts");
|
|
ui_TabPageChannels = ui_TabView1.addTab("Channels");
|
|
ui_TabPageSettings = ui_TabView1.addTab("Settings");
|
|
#elif defined(LANG_GR)
|
|
ui_TabPageHome = tabView.addTab("Αρχική");
|
|
ui_TabPageContacts = tabView.addTab("Επαφές");
|
|
ui_TabPageChannels = tabView.addTab("Κανάλια");
|
|
ui_TabPageSettings = tabView.addTab("Ρυθμίσεις");
|
|
#endif
|
|
|
|
LvObj(ui_TabPageHome)
|
|
.scrollable(false)
|
|
.bgOpa(0)
|
|
.bgColor(0x000000);
|
|
LvObj(ui_TabPageContacts)
|
|
.scrollable(false)
|
|
.bgOpa(0)
|
|
.bgColor(0x000000);
|
|
LvObj(ui_TabPageChannels)
|
|
.scrollable(false)
|
|
.bgOpa(0)
|
|
.bgColor(0x000000);
|
|
LvObj(ui_TabPageSettings)
|
|
.scrollable(false)
|
|
.bgOpa(0)
|
|
.bgColor(0x000000);
|
|
|
|
ui_ValueDate = LvLabel(ui_TabPageHome)
|
|
.text("--- --/--/----")
|
|
.width(LV_SIZE_CONTENT)
|
|
.height(LV_SIZE_CONTENT)
|
|
.font(&lv_font_arial_40)
|
|
.textColor(0xFFFFFF)
|
|
.opa(255)
|
|
.align(LV_ALIGN_CENTER)
|
|
.position(0, -165);
|
|
|
|
|
|
ui_ValueTime = LvLabel(ui_TabPageHome)
|
|
.text("--:--")
|
|
.width(LV_SIZE_CONTENT)
|
|
.height(LV_SIZE_CONTENT)
|
|
.font(&lv_font_arial_48)
|
|
.textColor(0xFFFFFF)
|
|
.opa(255)
|
|
.align(LV_ALIGN_CENTER)
|
|
.position(0, -100);
|
|
|
|
ui_Contacts = LvList(ui_TabPageContacts)
|
|
.width(250)
|
|
.height(400)
|
|
.align(LV_ALIGN_CENTER)
|
|
.position(-274, 0)
|
|
.transparent()
|
|
.raw();
|
|
|
|
lv_obj_set_style_bg_opa(ui_Contacts, LV_OPA_TRANSP, 0);
|
|
lv_obj_set_style_border_width(ui_Contacts, 0, 0);
|
|
lv_obj_set_style_outline_width(ui_Contacts, 0, 0);
|
|
lv_obj_set_style_shadow_width(ui_Contacts, 0, 0);
|
|
//lv_obj_set_scrollbar_mode(ui_Contacts, LV_SCROLLBAR_MODE_OFF);
|
|
lv_obj_set_style_bg_opa(ui_Contacts, LV_OPA_TRANSP, LV_PART_ITEMS);
|
|
lv_obj_set_style_border_width(ui_Contacts, 0, LV_PART_ITEMS);
|
|
|
|
ui_ContactMessages = LvList(ui_TabPageContacts)
|
|
.width(500)
|
|
.height(400)
|
|
.align(LV_ALIGN_CENTER)
|
|
.position(124, 0)
|
|
.transparent()
|
|
.raw();
|
|
|
|
lv_obj_set_style_bg_color(ui_ContactMessages, lv_color_hex(0), 0);
|
|
lv_obj_set_style_bg_opa(ui_ContactMessages, LV_OPA_TRANSP, 0);
|
|
lv_obj_set_style_border_width(ui_ContactMessages, 0, 0);
|
|
lv_obj_set_style_outline_width(ui_ContactMessages, 0, 0);
|
|
lv_obj_set_style_shadow_width(ui_ContactMessages, 0, 0);
|
|
//lv_obj_set_scrollbar_mode(ui_ContactMessages, LV_SCROLLBAR_MODE_OFF);
|
|
lv_obj_set_style_bg_opa(ui_ContactMessages, LV_OPA_TRANSP, LV_PART_ITEMS);
|
|
lv_obj_set_style_border_width(ui_ContactMessages, 0, LV_PART_ITEMS);
|
|
|
|
// LvObj(ui_TabPageContacts)
|
|
// .size(2, 400)
|
|
// .position(222, 0)
|
|
// .bgColor(0x444444)
|
|
// .border(0)
|
|
// .scrollable(false)
|
|
// .radius(0);
|
|
|
|
ui_Channels = LvDropdown(ui_TabPageChannels)
|
|
.options("Public")
|
|
.width(291)
|
|
.align(LV_ALIGN_CENTER)
|
|
.position(-243, -182)
|
|
.clickable(true)
|
|
.raw();
|
|
|
|
ui_ChannelMessages = LvList(ui_TabPageChannels)
|
|
.width(780)
|
|
.height(280)
|
|
.align(LV_ALIGN_CENTER)
|
|
.transparent()
|
|
.padRow(10)
|
|
.position(0, 0)
|
|
.bgColor(0)
|
|
.bgOpa(0)
|
|
.border(0)
|
|
.noDecor()
|
|
.raw();
|
|
|
|
//lv_obj_set_scrollbar_mode(ui_ChannelMessages, LV_SCROLLBAR_MODE_OFF);
|
|
lv_obj_set_style_bg_opa(ui_ChannelMessages, LV_OPA_TRANSP, LV_PART_ITEMS);
|
|
lv_obj_set_style_border_width(ui_ChannelMessages, 0, LV_PART_ITEMS);
|
|
|
|
ui_ChannelDivider = LvObj(ui_TabPageChannels)
|
|
.size(780, 1)
|
|
.align(LV_ALIGN_CENTER)
|
|
.position(0, 150)
|
|
.bgColor(0x444444)
|
|
.border(0)
|
|
.raw();
|
|
|
|
ui_DimOverlay = LvObj(ui_Screen1)
|
|
.size(lv_pct(100), lv_pct(100))
|
|
.align(LV_ALIGN_CENTER)
|
|
.bgColor(0x000000)
|
|
.bgOpa(0)
|
|
.bringToFront()
|
|
.onClick(s_onDimOverlayClick, this)
|
|
.scrollable(false)
|
|
.clickable(true)
|
|
.raw();
|
|
lv_obj_remove_style_all(ui_DimOverlay); // no border/padding
|
|
lv_obj_clear_flag(ui_DimOverlay, LV_OBJ_FLAG_SCROLL_CHAIN_HOR);
|
|
lv_obj_clear_flag(ui_DimOverlay, LV_OBJ_FLAG_SCROLL_CHAIN_VER);
|
|
|
|
|
|
ui_ChannelInput = LvTextArea(ui_TabPageChannels)
|
|
.size(670, 40)
|
|
.align(LV_ALIGN_CENTER)
|
|
.position(-50, channelInputBaseY)
|
|
.oneLine(true)
|
|
#if defined(LANG_EN)
|
|
.placeholder("Write message...")
|
|
#elif defined(LANG_GR)
|
|
.placeholder("Γράψε μήνυμα...")
|
|
#endif
|
|
.font(&lv_font_arial_20)
|
|
.bgColor(0x111111)
|
|
.textColor(0xFFFFFF)
|
|
.borderColor(0x444444)
|
|
.borderWidth(1)
|
|
.radius(6)
|
|
.onFocus(s_onChannelInputFocus, this)
|
|
.raw();
|
|
|
|
ui_SendBtn = LvButton(ui_TabPageChannels)
|
|
.size(90, 42)
|
|
.align(LV_ALIGN_CENTER)
|
|
.position(350, channelInputBaseY)
|
|
.bgColor(0x3A7AFE)
|
|
.onClick(s_onSendClick, this)
|
|
.raw();
|
|
|
|
iu_SendLabel = LvLabel(ui_SendBtn)
|
|
#if defined(LANG_EN)
|
|
.text("Send")
|
|
#elif defined(LANG_GR)
|
|
.text("Αποστολή")
|
|
#endif
|
|
.font(&lv_font_arial_18);
|
|
lv_obj_center(iu_SendLabel);
|
|
|
|
ui_Keyboard = LvKeyboard(lv_layer_top())
|
|
.size(480, 200)
|
|
.align(LV_ALIGN_BOTTOM_MID)
|
|
.show(false)
|
|
.onEvent(s_onKeyboardEvent, this);
|
|
}
|
|
|
|
void UIManager::setNightMode(bool night) {
|
|
|
|
if (!ui_DimOverlay) return;
|
|
if (night) {
|
|
lv_obj_set_style_bg_opa(ui_DimOverlay, 192, 0); // 75% dark
|
|
} else {
|
|
lv_obj_set_style_bg_opa(ui_DimOverlay, 0, 0); // none
|
|
}
|
|
}
|
|
|
|
|