225 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			225 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| 
 | |
| /*
 | |
|  * Copyright (C) Artsiom D.
 | |
|  * Copyright (C) shit-co.de
 | |
|  */
 | |
| 
 | |
|  
 | |
| #include <curses.h>
 | |
| #include <limits.h>
 | |
| #include <math.h>
 | |
| #include <stdio.h>
 | |
| #include <stdlib.h>
 | |
| #include <string.h>
 | |
| 
 | |
| #include "box.h"
 | |
| #include "ui.h"
 | |
| #include "util.h"
 | |
| 
 | |
| 
 | |
| static void draw_rectangle(unsigned int x, unsigned int y, unsigned int width,
 | |
|     unsigned int height);
 | |
| static void draw_chart(struct box *, unsigned int x, unsigned int y,
 | |
|     unsigned int width, unsigned int height);
 | |
| static void draw_container(struct box *, unsigned int x, unsigned int y,
 | |
|     unsigned int width, unsigned int height);
 | |
| static void draw_button(struct box *, unsigned int x, unsigned int y,
 | |
|     unsigned int width, unsigned int height);
 | |
| 
 | |
| 
 | |
| void
 | |
| append_box(struct box *parent, struct box *child)
 | |
| {
 | |
|     parent->children[parent->length++] = child;
 | |
| }
 | |
| 
 | |
| 
 | |
| static void
 | |
| draw_rectangle(unsigned int x, unsigned int y, unsigned int width,
 | |
|     unsigned int height)
 | |
| {
 | |
|     /* corners */
 | |
| 
 | |
|     ui_char(x, y, '+');
 | |
|     ui_char(x, y + height, '+');
 | |
|     ui_char(x + width, y + height, '+');
 | |
|     ui_char(x + width, y, '+');
 | |
| 
 | |
|     /* vertical borders */
 | |
| 
 | |
|     for (size_t i = 1; i < height; i++) {
 | |
|         ui_char(x, y + i, '|');
 | |
|     }
 | |
| 
 | |
|     for (size_t i = 1; i < height; i++) {
 | |
|         ui_char(x + width, y + i, '|');
 | |
|     }
 | |
| 
 | |
|     /* horizontal borders */
 | |
| 
 | |
|     for (size_t i = 1; i < width; i++) {
 | |
|         ui_char(x + i, y, '-');
 | |
|     }
 | |
| 
 | |
|     for (size_t i = 1; i < width; i++) {
 | |
|         ui_char(x + i, y + height, '-');
 | |
|     }
 | |
| }    
 | |
| 
 | |
| 
 | |
| static void
 | |
| draw_chart(struct box *chart, unsigned int x, unsigned int y,
 | |
|     unsigned int width, unsigned int height)
 | |
| {
 | |
|     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++) {
 | |
|         price = chart->chart->prices[i];
 | |
| 
 | |
|         ui_color_on(UI_BLUE);
 | |
|         ui_char(x + i, height + y - price, '@');
 | |
|         ui_color_off(UI_BLUE);
 | |
|     }
 | |
| }
 | |
| 
 | |
| 
 | |
| static void
 | |
| draw_button(struct box *b, unsigned int x, unsigned int y, unsigned int width,
 | |
|     unsigned int 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, unsigned int x, unsigned int y,
 | |
|     unsigned int width, unsigned int height)
 | |
| {
 | |
|     unsigned int   current, i, 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 (i = 0; i < b->length; i++) {
 | |
|         total_fills += b->children[i]->fills;
 | |
|     }
 | |
| 
 | |
|     pixels_per_fill = length / total_fills;
 | |
| 
 | |
|     for (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(struct chart *chart)
 | |
| {
 | |
|     struct box *box = malloc(sizeof(struct box));
 | |
| 
 | |
|     box->type = BOX_CHART;
 | |
|     box->chart = chart;
 | |
|     box->fills = 1;
 | |
|     box->color = UI_NONE;
 | |
| 
 | |
|     return box;
 | |
| }
 | |
| 
 | |
| 
 | |
| 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, unsigned int x, unsigned int y, unsigned int width,
 | |
|     unsigned int 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;
 | |
|     }
 | |
| }
 |