#include <numeric>#include "muscles.h" Table::Table() : arena(&get_default_arena()) {} Table::Table(const Table& t) : headers(t.headers), arena(t.arena ? t.arena : &get_default_arena()){ int n_cols = t.column_count(); int n_rows = t.row_count(); if (!n_cols || !n_rows) return; columns = std::make_unique<std::vector<void*>[]>(n_cols); for (int i = 0; i < n_cols; i++) { columns[i].resize(n_rows, nullptr); std::copy(t.columns[i].begin(), t.columns[i].end(), columns[i].begin()); }} Table::Table(Table&& t) : headers(std::move(t.headers)), columns(std::move(t.columns)), arena(t.arena ? t.arena : &get_default_arena()){} Table::~Table() { clear_data();} void Table::resize(int n_rows) { int n_cols = column_count(); for (int i = 0; i < n_cols; i++) { columns[i].resize(n_rows, nullptr); if (headers[i].count_per_cell > 0) { if (headers[i].type == ColumnString) { for (int j = 0; j < n_rows; j++) { if (columns[i][j]) continue; columns[i][j] = arena->allocate(headers[i].count_per_cell); ((char*)(columns[i][j]))[0] = 0; } } else if (headers[i].type == ColumnElement) { for (int j = 0; j < n_rows; j++) { if (columns[i][j]) continue; columns[i][j] = allocate_ui_element(*arena, headers[i].count_per_cell); if (element_init_func) element_init_func(this, i, j); } } } }} void Table::init(Column *headers, Arena *a, void *tag, void (*elem_init)(Table*, int, int), int n_cols, int n_rows) { element_tag = tag; element_init_func = elem_init; if (a) arena = a; this->headers.resize(n_cols); memcpy(this->headers.data(), headers, n_cols * sizeof(Column)); for (auto& h : this->headers) { if (h.type == ColumnElement) has_ui_elements = true; } columns = std::make_unique<std::vector<void*>[]>(n_cols); if (n_rows > 0) resize(n_rows);} void Table::clear_filter() { list.clear(); filtered = -1;} void Table::clear_data() { clear_filter(); int n_cols = column_count(); for (int i = 0; i < n_cols; i++) columns[i].clear();} inline void lowify(char *str) { for (int i = 0; str[i]; i++) str[i] = str[i] >= 'a' && str[i] <= 'z' ? str[i] - 0x20 : str[i];} void Table::update_filter(std::string& filter) { list.clear(); if (!filter.size()) { filtered = -1; return; } char sub[100] = {0}; strncpy(sub, filter.c_str(), 99); lowify(sub); char cell[200]; int n_rows = row_count(); int n_cols = column_count(); filtered = 0; for (int i = 0; i < n_cols; i++) { ColumnType type = headers[i].type; if (headers[i].type == ColumnString || headers[i].type == ColumnFile) { for (int j = 0; j < n_rows; j++) { char *name = type == ColumnFile ? ((File_Entry*)columns[i][j])->name : (char*)columns[i][j]; if (!name) continue; strncpy(cell, name, 199); lowify(cell); if (strstr(cell, sub)) { auto res = list.insert(j); filtered += res.second ? 1 : 0; } } } }} void Table::update_tree(std::vector<Branch> *new_branches) { if (new_branches) { branches.resize(new_branches->size()); std::copy(new_branches->begin(), new_branches->end(), branches.begin()); } int n_rows = row_count(); int n_branches = branches.size(); tree.clear(); tree.reserve(n_rows); int b = 0; for (int i = 0; i < n_rows; i++) { if (b < n_branches && branches[b].row_idx == i) { if (branches[b].closed) i = branches[b].row_idx + branches[b].length; tree.push_back(-b - 1); b++; i--; continue; } tree.push_back(i); }} int Table::get_table_index(int view_idx) { if (view_idx < 0) return view_idx; int idx = -1; int tree_size = tree.size(); if (tree_size > 0) { if (view_idx < tree_size) idx = tree[view_idx]; } else if (view_idx < row_count()) idx = view_idx; return idx;} void Table::release() { int n_cols = column_count(); for (int i = 0; i < n_cols; i++) { if (headers[i].type != ColumnImage) continue; for (auto& t : columns[i]) sdl_destroy_texture(&t); }}