#include "muscles.h"
#include "ui.h"
void Box::draw(Workspace& ws, Camera& view, bool held, Point *inside, bool hovered, bool focussed) {
if (!visible)
return;
Rect_Int r = view.to_screen_rect(box);
int brd = edge_size * view.scale + 0.5;
Rect_Int edge_rect = {
r.x - brd, r.y - brd, r.w + 2*brd, r.h + 2*brd
};
sdl_draw_rect(edge_rect, edge_color, nullptr);
sdl_draw_rect(r, back_color, nullptr);
for (auto& e : ui) {
if (e->visible) {
bool elem_hovered = !dd_menu_hovered && inside && e->pos.contains(*inside);
e->draw(view, r, elem_hovered, hovered, focussed);
}
}
for (auto& e : ui) {
if (e->visible && e->use_post_draw) {
Rect_Int back = make_int_ui_box(r, e->pos, view.scale);
bool elem_hovered = !dd_menu_hovered && inside && e->pos.contains(*inside);
e->post_draw(view, back, elem_hovered, hovered, focussed);
}
}
if (current_dd)
current_dd->draw_menu(nullptr, view);
}
void Box::require_redraw() {
for (auto& elem : ui)
elem->needs_redraw = true;
}
void Box::select_edge(Camera& view, Point& p) {
edge = 0;
float gap = 6 / view.scale;
if (p.x >= -gap && p.x < box.w + gap && p.y >= -gap && p.y < box.h + gap) {
if (p.x < 0)
edge |= 1;
if (p.x >= box.w)
edge |= 2;
if (p.y < 0)
edge |= 4;
if (p.y >= box.h)
edge |= 8;
}
}
void Box::move(float dx, float dy, Camera& view, Input& input) {
if (!edge) {
box.x += dx;
box.y += dy;
return;
}
Point p = view.to_screen(box.x, box.y);
float w = box.w * view.scale;
float h = box.h * view.scale;
float min_w = min_width * view.scale;
float min_h = min_height * view.scale;
if (edge & 2) {
if (input.mouse_x - min_w >= (int)p.x)
box.w += dx;
else
box.w = min_w / view.scale;
}
else if (edge & 1) {
if (input.mouse_x + min_w < p.x + w) {
box.x += dx;
box.w -= dx;
}
else {
box.x = view.to_world_x(p.x + w - min_w);
box.w = min_w / view.scale;
}
}
if (edge & 8) {
if (input.mouse_y - min_h >= (int)p.y)
box.h += dy;
else
box.h = min_h / view.scale;
}
else if (edge & 4) {
if (input.mouse_y + min_h < p.y + h) {
box.y += dy;
box.h -= dy;
}
else {
box.y = view.to_world_y(p.y + h - min_h);
box.h = min_h / view.scale;
}
}
}
void Box::set_dropdown(Drop_Down *dd) {
if (current_dd && dd != current_dd)
current_dd->cancel();
current_dd = dd;
if (current_dd)
current_dd->dropped = true;
}
void Box::update_hovered(Camera& view, Input& input, Point& inside) {
if (!moving)
select_edge(view, inside);
CursorType ct = CursorDefault;
if (edge == 5 || edge == 10)
ct = CursorResizeNWSE;
else if (edge == 6 || edge == 9)
ct = CursorResizeNESW;
else if (edge & 3)
ct = CursorResizeWestEast;
else if (edge & 12)
ct = CursorResizeNorthSouth;
if (ct != CursorDefault) {
sdl_set_cursor(ct);
parent->cursor_set = true;
}
if (!ui_held && (edge > 0 || (!edge && parent->selected == this))) {
if (input.lmouse && input.held == move_start) {
moving = true;
parent->box_moving = true;
}
}
}
void Box::update_active_elements(Camera& view, Input& input, Point& inside, Box *hover) {
if (input.lclick) {
active_edit = nullptr;
}
if (current_dd && input.action && (!hover || hover == this)) {
current_dd->base_action(view, inside, input);
if (current_dd->action)
current_dd->action(current_dd, view, input.double_click);
if (current_dd->hl >= 0) {
set_dropdown(nullptr);
input.action = false;
}
}
}
void Box::update_element_actions(Camera& view, Input& input, Point& inside, Box *hover) {
for (auto& elem : ui) {
if (!elem->visible)
continue;
elem->mouse_handler(view, input, inside, this == hover);
elem->key_handler(view, input);
if (input.action && elem->active && elem->pos.contains(inside)) {
Workspace *ws = parent;
ws->box_expunged = false;
elem->base_action(view, inside, input);
if (elem->action) {
elem->action(elem, view, input.double_click);
input.action = false;
}
if (ws->box_expunged)
return;
}
}
}
void Box::update(Workspace& ws, Camera& view, Input& input, Box *hover, bool focussed) {
this->parent = &ws;
if (!visible)
return;
if (moving) {
float dx = (input.mouse_x - input.prev_x) / view.scale;
float dy = (input.mouse_y - input.prev_y) / view.scale;
move(dx, dy, view, input);
}
else
edge = 0;
Point cursor = view.to_world(input.mouse_x, input.mouse_y);
Point inside = {cursor.x - box.x, cursor.y - box.y};
if (ticks % refresh_every == 0)
refresh(&inside);
ticks++;
dd_menu_hovered = false;
if (current_dd) {
current_dd->highlight(view, inside, input);
dd_menu_hovered = current_dd->hl >= 0;
}
bool was_dd = current_dd != nullptr;
if (!parent->box_moving && !dd_menu_hovered && (!hover || this == hover))
update_hovered(view, input, inside);
if (focussed) {
update_active_elements(view, input, inside, hover);
if (!dd_menu_hovered)
update_element_actions(view, input, inside, hover);
}
if (ws.box_expunged) {
ws.box_expunged = false;
return;
}
if (!dd_menu_hovered) {
for (auto& elem : ui) {
elem->parent = this;
if (!elem->visible)
continue;
if ((!hover || this == hover) && !moving) {
if (elem->pos.contains(inside)) {
Point p = {inside.x - elem->pos.x, inside.y - elem->pos.y};
elem->scroll_handler(view, input, p);
if (!elem->use_default_cursor && !parent->cursor_set) {
sdl_set_cursor(elem->cursor_type);
parent->cursor_set = true;
}
}
elem->highlight(view, inside, input);
}
if (this != hover)
elem->deselect();
}
if (input.lclick && was_dd && current_dd) {
current_dd->dropped = false;
current_dd = nullptr;
}
}
update_ui(view);
}