/* * Copyright (C) Artsiom D. * Copyright (C) shit-co.de */ #include #include #include #include #include #include #include "box.h" #include "ui.h" #include "util.h" static void draw_rectangle(double x, double y, double width, double height); static void draw_chart(struct box *, double x, double y, double width, double height); static void draw_container(struct box *, double x, double y, double width, double height); static void draw_button(struct box *, double x, double y, double width, double height); static void draw_rectangle(double fx, double fy, double fwidth, double fheight) { size_t x = llround(fx); size_t y = llround(fy); size_t w = llround(fwidth) - 1; size_t h = llround(fheight) - 1; /* corners */ ui_char(x, y, '+'); ui_char(x, y + h, '+'); ui_char(x + w, y + h, '+'); ui_char(x + w, y, '+'); /* vertical borders */ for (size_t i = 1; i < h; i++) { ui_char(x, y + i, '|'); } for (size_t i = 1; i < h; i++) { ui_char(x + w, y + i, '|'); } /* horizontal borders */ for (size_t i = 1; i < w; i++) { ui_char(x + i, y, '-'); } for (size_t i = 1; i < w; i++) { ui_char(x + i, y + h, '-'); } } static void draw_chart(struct box *chart, double x, double y, double width, double height) { char c = '@'; long int actual_diff; double diff, price; enum ui_color color; draw_rectangle(x, y, width, height); x += 1; y += 1; width -= 2; height -= 2; price = height / 2; actual_diff = 0; for (size_t i = 0; i < width; i++) { diff = (double)rand() / RAND_MAX - 0.6; actual_diff = (size_t)(height + y - price) - (size_t)(height + y - (price + diff)); if (actual_diff > 0) { color = UI_GREEN; } else if (actual_diff == 0) { color = UI_NONE; } else if (actual_diff < 0) { color = UI_RED; } ui_color_on(color); ui_char(x + i, height + y - price, c); ui_color_off(color); price += diff; } } static void draw_button(struct box *b, double x, double y, double width, double height) { ui_color_on(b->color); draw_rectangle(x, y, width, height); ui_string(x + width / 2 - strlen(b->name) / 2, y + height / 2, b->name); ui_color_off(b->color); } static void draw_container(struct box *b, double x, double y, double width, double height) { double current, length, total_fills, pixels_per_fill; struct box *child; switch (b->type) { case BOX_VERTICAL: length = height; current = y; break; case BOX_HORIZONTAL: length = width; current = x; break; } total_fills = 0; for (size_t i = 0; i < b->length; i++) { total_fills += b->children[i]->fills; } pixels_per_fill = length / total_fills; for (size_t i = 0; i < b->length; i++) { child = b->children[i]; length = child->fills * pixels_per_fill; switch (b->type) { case BOX_VERTICAL: draw_box(child, x, current, width, length); break; case BOX_HORIZONTAL: draw_box(child, current, y, length, height); break; } current += length; } } struct box * new_chart_box(void) { struct box *chart = malloc(sizeof(struct box)); chart->type = BOX_CHART; chart->prices = emalloc(sizeof(double) * 100); chart->fills = 1; chart->color = UI_NONE; return chart; } struct box * new_button_box(char *name) { struct box *button = malloc(sizeof(struct box)); button->type = BOX_BUTTON; button->name = name; button->fills = 1; button->color = UI_NONE; return button; } struct box * new_container_box(enum box_type type) { struct box *box = emalloc(sizeof(struct box)); box->type = type; box->fills = 1; box->color = UI_NONE; box->children = emalloc(sizeof(struct box *) * 100); box->length = 0; return box; } struct box * new_horizontal_box(void) { return new_container_box(BOX_HORIZONTAL); } struct box * new_vertical_box(void) { return new_container_box(BOX_VERTICAL); } void draw_box(struct box *b, double x, double y, double width, double height) { switch (b->type) { case BOX_BUTTON: draw_button(b, x, y, width, height); break; case BOX_CHART: draw_chart(b, x, y, width, height); break; case BOX_HORIZONTAL: case BOX_VERTICAL: draw_container(b, x, y, width, height); break; } }