void button_draw(BUTTON *b, int x, int y, int width, int height) { if(b->nodraw) { return; } if(b->updatecolor) { b->updatecolor(b); } // Ensure that font is set before calculating position and width. setfont(FONT_SELF_NAME); setcolor(WHITE); int w = width; calculate_pos_and_width(b, &x, &w); uint32_t color = b->mousedown ? b->c3 : (b->mouseover ? b->c2 : b->c1); if(b->bm) { drawalpha(b->bm, x, y, width, height, color); } else { drawrectw(x, y, w, height, b->disabled ? LIST_MAIN : color); //setfont(FONT_TEXT_LARGE); //setcolor(b->mouseover ? 0x222222 : 0x555555); //drawtext(x + 5, y, b->text, b->text_length); } if(b->bm2) { int bx = w / 2 - b->bw * SCALE / 2, by = height / 2 - b->bh * SCALE / 2; drawalpha(b->bm2, x + bx, y + by, b->bw * SCALE, b->bh * SCALE, WHITE); } if(maybe_i18nal_string_is_valid(&b->button_text)) { if(b->bm) { while(w > width) { // The text didn't fit into the original width. // Fill the rest of the new width with the image // and hope for the best. drawalpha(b->bm, x - width + w, y, width, height, color); w -= width / 2 + 1; } } STRING* s = maybe_i18nal_string_get(&b->button_text); drawtext(x + 3 * SCALE, y + SCALE, s->str, s->length); } }
void dropdown_drawactive(void) { DROPDOWN *b = active; if(!b) { return; } int x = active_x, y = active_y, w = active_width, h = active_height; setfont(FONT_TEXT); setcolor(COLOR_TEXT); int i, sign = 1; // Increase width if needed, so that all menu items fit. for(i = 0; i != b->dropcount; i++) { STRING* e = b->ondisplay(i, b); int needed_w = textwidth(e->str, e->length) + 4 * SCALE; if(w < needed_w) { w = needed_w; } } if(y + h * b->dropcount > height) { y -= h * (b->dropcount - 1); sign = -1; } drawrect(x, y, x + w, y + h * b->dropcount, WHITE); framerect(x, y, x + w, y + h * b->dropcount, BLUE); if(sign == -1) { y += h * (b->dropcount - 1); } for(i = 0; i != b->dropcount; i++) { int j = index(b, i); STRING* e = b->ondisplay(j, b); if(j == b->over) { drawrectw(x + 1, y + 1, w - 2, h - 2, C_GRAY); } drawtext(x + 2 * SCALE, y + 2 * SCALE, e->str, e->length); y += sign * h; } }
void button_draw(BUTTON *b, int x, int y, int width, int height) { uint32_t color = b->mousedown ? b->c3 : (b->mouseover ? b->c2 : b->c1); if(b->bm) { drawalpha(b->bm, x, y, width, height, color); } else { drawrectw(x, y, width, height, b->disabled ? LIST_MAIN : color); //setfont(FONT_TEXT_LARGE); //setcolor(b->mouseover ? 0x222222 : 0x555555); //drawtext(x + 5, y, b->text, b->text_length); } if(b->bm2) { int bx = width / 2 - b->bw / 2, by = height / 2 - b->bh / 2; drawalpha(b->bm2, x + bx, y + by, b->bw, b->bh, WHITE); } }
static void drawtexth(int x, int y, char_t *str, uint16_t length, int d, int h, int hlen, uint16_t lineheight) { h -= d; if(h + hlen < 0 || h > length) { drawtext(x, y, str, length); return; } else if(hlen == 0) { drawtext(x, y, str, length); int w = textwidth(str, h + hlen); drawvline(x + w, y, y + lineheight, BLACK); return; } if(h < 0) { hlen += h; h = 0; if(hlen < 0) { hlen = 0; } } if(h + hlen > length) { hlen = length - h; } int width; width = drawtext_getwidth(x, y, str, h); uint32_t color = setcolor(TEXT_HIGHLIGHT); int w = textwidth(str + h, hlen); drawrectw(x + width, y, w, lineheight, TEXT_HIGHLIGHT_BG); drawtext(x + width, y, str + h, hlen); width += w; setcolor(color); drawtext(x + width, y, str + h + hlen, length - (h + hlen)); }
/** Formats all messages from self and friends, and then call draw functions * to write them to the UI. * * accepts: messages struct *pointer, int x,y positions, int width,height */ void messages_draw(MESSAGES *m, int x, int y, int width, int height) { // Do not draw author name next to every message uint8_t lastauthor = 0xFF; // Message iterator void **p = m->data->data; MSG_IDX i, n = m->data->n; // Go through messages for(i = 0; i != n; i++) { MESSAGE *msg = *p++; // Empty message if(msg->height == 0) { return; } //! NOTE: should not be constant 0 if(y + msg->height <= 0) { y += msg->height; continue; } //! NOTE: should not be constant 100 if(y >= height + 50 * SCALE) { break; } // Draw timestamps { char timestr[6]; STRING_IDX len; len = snprintf(timestr, sizeof(timestr), "%u:%.2u", msg->time / 60, msg->time % 60); if (len >= sizeof(timestr)) { len = sizeof(timestr) - 1; } setcolor(COLOR_MAIN_SUBTEXT); setfont(FONT_MISC); drawtext(x + width - TIME_WIDTH, y, (char_t*)timestr, len); } // Draw the names for groups or friends if(m->type) { // Group message authors are all the same colour setcolor(COLOR_MAIN_CHATTEXT); setfont(FONT_TEXT); drawtextwidth_right(x, MESSAGES_X - NAME_OFFSET, y, &msg->msg[msg->length] + 1, msg->msg[msg->length]); } else { FRIEND *f = &friend[m->data->id]; // Always draw name next to action message if(msg->msg_type == MSG_TYPE_ACTION_TEXT) lastauthor = 0xFF; if(msg->author != lastauthor) { // Draw author name // If author is current user setfont(FONT_TEXT); if(msg->msg_type == MSG_TYPE_ACTION_TEXT) setcolor(COLOR_MAIN_ACTIONTEXT); else if(msg->author) setcolor(COLOR_MAIN_SUBTEXT); else setcolor(COLOR_MAIN_CHATTEXT); if(msg->author) drawtextwidth_right(x, MESSAGES_X - NAME_OFFSET, y, self.name, self.name_length); else drawtextwidth_right(x, MESSAGES_X - NAME_OFFSET, y, f->name, f->name_length); lastauthor = msg->author; } } // Draw message contents switch(msg->msg_type) { case MSG_TYPE_TEXT: case MSG_TYPE_ACTION_TEXT: { // Normal message STRING_IDX h1 = STRING_IDX_MAX, h2 = STRING_IDX_MAX; if(i == m->data->istart) { h1 = m->data->start; h2 = ((i == m->data->iend) ? m->data->end : msg->length); } else if(i == m->data->iend) { h1 = 0; h2 = m->data->end; } else if(i > m->data->istart && i < m->data->iend) { h1 = 0; h2 = msg->length; } if((m->data->istart == m->data->iend && m->data->start == m->data->end) || h1 == h2) { h1 = STRING_IDX_MAX; h2 = STRING_IDX_MAX; } if(msg->author) { setcolor(COLOR_MAIN_SUBTEXT); } else { setcolor(COLOR_MAIN_CHATTEXT); } if (msg->msg_type == MSG_TYPE_ACTION_TEXT) { setcolor(COLOR_MAIN_ACTIONTEXT); } setfont(FONT_TEXT); int ny = drawtextmultiline(x + MESSAGES_X, x + width - TIME_WIDTH, y, y, y + msg->height, font_small_lineheight, msg->msg, msg->length, h1, h2 - h1, 1); if(ny < y || (uint32_t)(ny - y) + MESSAGES_SPACING != msg->height) { debug("error101 %u %u\n", ny -y, msg->height - MESSAGES_SPACING); } y = ny; break; } // Draw image case MSG_TYPE_IMAGE: { MSG_IMG *img = (void*)msg; int maxwidth = width - MESSAGES_X - TIME_WIDTH; draw_message_image(img->image, x + MESSAGES_X, y, img->w, img->h, maxwidth, img->zoom, img->position); y += (img->zoom || img->w <= maxwidth) ? img->h : img->h * maxwidth / img->w; break; } // Draw file transfer case MSG_TYPE_FILE: { MSG_FILE *file = (void*)msg; int dx = MESSAGES_X; /* Mouse Positions */ _Bool mo = (m->iover == i); _Bool mouse_over = (mo && m->over) ? 1 : 0; _Bool mouse_tbtn = (mo && m->over == 1) ? 1 : 0; _Bool mouse_bbtn = (mo && m->over == 2) ? 1 : 0; /* Old var kept for bug hunting int xx = x + dx; int xxx = xx + BM_FTM_WIDTH + SCALE; */ /* File transfer bar */ int ftbar_x = x + dx; int ftbar_y = y; int ftbar_w = BM_FT_WIDTH; int ftbar_sw = BM_FTM_WIDTH; int ftbar_h = BM_FT_HEIGHT; /* Button Background */ int btn_bg_x = ftbar_x + BM_FTM_WIDTH + SCALE; int btn_bg_w = BM_FTB_WIDTH; /* Button Background heights */ int tbtn_bg_y = y; int bbtn_bg_y = y + BM_FTB_HEIGHT + SCALE * 2; int tbtn_bg_h = BM_FTB_HEIGHT + SCALE; int bbtn_bg_h = BM_FTB_HEIGHT; /* Top button info */ int btnx = ((x + dx) + BM_FTM_WIDTH + SCALE) + (BM_FTB_WIDTH - BM_FB_WIDTH) / 2; int tbtn_y = y + SCALE * 4; int bbtn_y = y + BM_FTB_HEIGHT + SCALE * 5; int btnw = BM_FB_WIDTH; int btnh = BM_FB_HEIGHT; char_t size[16]; STRING_IDX sizelen = sprint_bytes(size, sizeof(size), file->size); uint64_t progress = file->progress; if(progress > file->size) { progress = file->size; } char_t size_text[16]; STRING_IDX size_text_len = sprint_bytes(size_text, sizeof(size_text), file->speed); size_text[size_text_len++] = '/'; size_text[size_text_len++] = 's'; uint64_t etasec = 0; if(file->speed) { etasec = (file->size - progress) / file->speed; } char_t text2[16]; STRING_IDX len2 = snprintf((char*)text2, sizeof(text2), "%us", (uint32_t)etasec); if (len2 >= sizeof(text2)) { len2 = sizeof(text2) - 1; } // progress rectangle uint32_t w = (file->size == 0) ? 0 : (progress * (uint64_t)106 * SCALE) / file->size; setfont(FONT_MISC); setcolor(COLOR_MAIN_BACKGROUND); switch (file->status){ case FILE_TRANSFER_STATUS_COMPLETED: { /* If mouse over use hover color */ setcolor((mouse_over) ? COLOR_BUTTON_SUCCESS_HOVER_TEXT : COLOR_BUTTON_SUCCESS_TEXT); drawalpha(BM_FT, ftbar_x, ftbar_y, ftbar_w, ftbar_h, (mouse_over) ? COLOR_BUTTON_SUCCESS_HOVER_BACKGROUND : COLOR_BUTTON_SUCCESS_BACKGROUND); drawalpha(BM_YES, btnx, tbtn_y, btnw, btnh, (mouse_over) ? COLOR_BUTTON_SUCCESS_HOVER_TEXT : COLOR_BUTTON_SUCCESS_TEXT); if(file->inline_png){ drawstr(x + dx + 5 * SCALE, y + 17 * SCALE, CLICKTOSAVE); } else { drawstr(x + dx + 5 * SCALE, y + 17 * SCALE, CLICKTOOPEN); } break; } case FILE_TRANSFER_STATUS_KILLED:{ setcolor(COLOR_BUTTON_DANGER_TEXT); drawalpha(BM_FT, ftbar_x, ftbar_y, ftbar_w, ftbar_h, COLOR_BUTTON_DANGER_BACKGROUND); drawalpha(BM_NO, btnx, tbtn_y, btnw, btnh, COLOR_BUTTON_DANGER_TEXT); drawstr(x + dx + 5 * SCALE, y + 17 * SCALE, TRANSFER_CANCELLED); break; } case FILE_TRANSFER_STATUS_BROKEN: { setcolor(COLOR_BUTTON_DANGER_TEXT); drawalpha(BM_FT, ftbar_x, ftbar_y, ftbar_w, ftbar_h, COLOR_BUTTON_DANGER_BACKGROUND); drawalpha(BM_NO, btnx, tbtn_y, btnw, btnh, COLOR_BUTTON_DANGER_TEXT); drawstr(x + dx + 5 * SCALE, y + 17 * SCALE, TRANSFER_BROKEN); break; } case FILE_TRANSFER_STATUS_NONE: { /* ↑ used for incoming transfers */ setcolor(COLOR_BUTTON_DISABLED_TRANSFER); drawalpha(BM_FTM, ftbar_x, ftbar_y, ftbar_sw, ftbar_h, COLOR_BUTTON_DISABLED_BACKGROUND); drawalpha(BM_FTB1, btn_bg_x, tbtn_bg_y, btn_bg_w, tbtn_bg_h, (mouse_tbtn ? COLOR_BUTTON_SUCCESS_HOVER_BACKGROUND : COLOR_BUTTON_SUCCESS_BACKGROUND)); drawalpha(BM_NO, btnx, tbtn_y, btnw, btnh, (mouse_tbtn ? COLOR_BUTTON_SUCCESS_HOVER_TEXT : COLOR_BUTTON_SUCCESS_TEXT)); drawalpha(BM_FTB2, btn_bg_x, bbtn_bg_y, btn_bg_w, bbtn_bg_h, (mouse_bbtn ? COLOR_BUTTON_SUCCESS_HOVER_BACKGROUND : COLOR_BUTTON_SUCCESS_BACKGROUND)); drawalpha(BM_YES, btnx, bbtn_y, btnw, btnh, (mouse_bbtn ? COLOR_BUTTON_SUCCESS_HOVER_TEXT : COLOR_BUTTON_SUCCESS_TEXT)); framerect((x + dx) + 5 * SCALE, y + 17 * SCALE, (x + dx) + 111 * SCALE, y + 24 * SCALE, COLOR_BUTTON_DISABLED_TRANSFER); drawrectw((x + dx) + 5 * SCALE, y + 17 * SCALE, w, 7 * SCALE, COLOR_BUTTON_DISABLED_TRANSFER); break; } case FILE_TRANSFER_STATUS_ACTIVE: { setcolor(COLOR_BUTTON_INPROGRESS_TEXT); drawalpha(BM_FTM, ftbar_x, ftbar_y, ftbar_sw, ftbar_h, COLOR_BUTTON_INPROGRESS_BACKGROUND); drawalpha(BM_FTB1, btn_bg_x, tbtn_bg_y, btn_bg_w, tbtn_bg_h, (mouse_tbtn ? COLOR_BUTTON_SUCCESS_HOVER_BACKGROUND : COLOR_BUTTON_SUCCESS_BACKGROUND)); drawalpha(BM_NO, btnx, tbtn_y, btnw, btnh, (mouse_tbtn ? COLOR_BUTTON_SUCCESS_HOVER_TEXT : COLOR_BUTTON_SUCCESS_TEXT)); drawalpha(BM_FTB2, btn_bg_x, bbtn_bg_y, btn_bg_w, bbtn_bg_h, (mouse_bbtn ? COLOR_BUTTON_SUCCESS_HOVER_BACKGROUND : COLOR_BUTTON_SUCCESS_BACKGROUND)); drawalpha(BM_PAUSE, btnx, bbtn_y, btnw, btnh, (mouse_bbtn ? COLOR_BUTTON_SUCCESS_HOVER_TEXT : COLOR_BUTTON_SUCCESS_TEXT)); drawtext(x + dx + 5 * SCALE + 53 * SCALE - textwidth(size_text, size_text_len) / 2, y + 10 * SCALE, size_text, size_text_len); drawtext(x + dx + 5 * SCALE + 106 * SCALE - textwidth(text2, len2), y + 10 * SCALE, text2, len2); framerect((x + dx) + 5 * SCALE, y + 17 * SCALE, (x + dx) + 111 * SCALE, y + 24 * SCALE, COLOR_BUTTON_INPROGRESS_TEXT); drawrectw((x + dx) + 5 * SCALE, y + 17 * SCALE, w, 7 * SCALE, COLOR_BUTTON_INPROGRESS_TEXT); break; } case FILE_TRANSFER_STATUS_PAUSED_US: case FILE_TRANSFER_STATUS_PAUSED_BOTH: case FILE_TRANSFER_STATUS_PAUSED_THEM: { setcolor(COLOR_BUTTON_DISABLED_TRANSFER); drawalpha(BM_FTM, ftbar_x, ftbar_y, ftbar_sw, ftbar_h, COLOR_BUTTON_DISABLED_BACKGROUND); drawalpha(BM_FTB1, btn_bg_x, tbtn_bg_y, btn_bg_w, tbtn_bg_h, (mouse_tbtn ? COLOR_BUTTON_SUCCESS_HOVER_BACKGROUND : COLOR_BUTTON_SUCCESS_BACKGROUND)); drawalpha(BM_NO, btnx, tbtn_y, btnw, btnh, (mouse_tbtn ? COLOR_BUTTON_SUCCESS_HOVER_TEXT : COLOR_BUTTON_SUCCESS_TEXT)); if(file->status <= FILE_TRANSFER_STATUS_PAUSED_BOTH){ /* Paused by at least us */ drawalpha(BM_FTB2, btn_bg_x, bbtn_bg_y, btn_bg_w, bbtn_bg_h, (mouse_bbtn ? COLOR_BUTTON_SUCCESS_HOVER_BACKGROUND : COLOR_BUTTON_SUCCESS_BACKGROUND)); drawalpha(BM_RESUME, btnx, bbtn_y, btnw, btnh, (mouse_bbtn ? COLOR_BUTTON_SUCCESS_HOVER_TEXT : COLOR_BUTTON_SUCCESS_TEXT)); } else { /* Paused only by them */ drawalpha(BM_FTB2, btn_bg_x, bbtn_bg_y, btn_bg_w, bbtn_bg_h, COLOR_BUTTON_DISABLED_BACKGROUND); drawalpha(BM_PAUSE, btnx, bbtn_y, btnw, btnh, COLOR_BUTTON_DISABLED_TRANSFER); } framerect((x + dx) + 5 * SCALE, y + 17 * SCALE, (x + dx) + 111 * SCALE, y + 24 * SCALE, COLOR_BUTTON_DISABLED_TRANSFER); drawrectw((x + dx) + 5 * SCALE, y + 17 * SCALE, w, 7 * SCALE, COLOR_BUTTON_DISABLED_TRANSFER); break; } } drawtext(x + dx + 5 * SCALE, y + 10 * SCALE, size, sizelen); drawtextwidth(x + dx + 5 * SCALE, 106 * SCALE, y + 3 * SCALE, file->name, file->name_length); y += BM_FT_HEIGHT; break; } } y += MESSAGES_SPACING; } if(i == n) { // Last message is visible. Append typing notifications, if needed. FRIEND *f = get_typers(m); if(f) { setfont(FONT_TEXT); // @TODO: separate these colours if needed setcolor(COLOR_MAIN_HINTTEXT); drawtextwidth_right(x, MESSAGES_X - NAME_OFFSET, y, f->name, f->name_length); drawtextwidth(x + MESSAGES_X, x + width, y, S(IS_TYPING), SLEN(IS_TYPING)); } } }