This repository has been archived on 2023-10-09. You can view files and clone it, but cannot push or open issues or pull requests.
Files
blender-archive/source/blender/editors/space_spreadsheet/spreadsheet_draw.cc
Julian Eisel 5ea113a555 Fix missing header & footer toggle chevrons in Spreadsheet
The little chevron tab to open a hidden region wouldn't show up in the
Spreadsheet editor. Cause was an incorrect GPU-scissor usage:
While drawing regions, the scissors should be kept enabled, just the
scissor rectangle should be updated - and afterwards reset to what it
was before.
2021-05-04 20:20:15 +02:00

311 lines
11 KiB
C++

/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "UI_interface.h"
#include "UI_resources.h"
#include "UI_view2d.h"
#include "GPU_immediate.h"
#include "DNA_screen_types.h"
#include "DNA_userdef_types.h"
#include "BLI_rect.h"
#include "spreadsheet_draw.hh"
namespace blender::ed::spreadsheet {
SpreadsheetDrawer::SpreadsheetDrawer()
{
left_column_width = UI_UNIT_X * 2;
top_row_height = UI_UNIT_Y * 1.1f;
row_height = UI_UNIT_Y;
}
SpreadsheetDrawer::~SpreadsheetDrawer() = default;
void SpreadsheetDrawer::draw_top_row_cell(int UNUSED(column_index),
const CellDrawParams &UNUSED(params)) const
{
}
void SpreadsheetDrawer::draw_left_column_cell(int UNUSED(row_index),
const CellDrawParams &UNUSED(params)) const
{
}
void SpreadsheetDrawer::draw_content_cell(int UNUSED(row_index),
int UNUSED(column_index),
const CellDrawParams &UNUSED(params)) const
{
}
int SpreadsheetDrawer::column_width(int UNUSED(column_index)) const
{
return 5 * UI_UNIT_X;
}
static void draw_index_column_background(const uint pos,
const ARegion *region,
const SpreadsheetDrawer &drawer)
{
immUniformThemeColorShade(TH_BACK, 11);
immRecti(pos, 0, region->winy - drawer.top_row_height, drawer.left_column_width, 0);
}
static void draw_alternating_row_overlay(const uint pos,
const int scroll_offset_y,
const ARegion *region,
const SpreadsheetDrawer &drawer)
{
immUniformThemeColor(TH_ROW_ALTERNATE);
GPU_blend(GPU_BLEND_ALPHA);
BLI_assert(drawer.row_height > 0);
const int row_pair_height = drawer.row_height * 2;
const int row_top_y = region->winy - drawer.top_row_height - scroll_offset_y % row_pair_height;
for (const int i : IndexRange(region->winy / row_pair_height + 1)) {
int x_left = 0;
int x_right = region->winx;
int y_top = row_top_y - i * row_pair_height - drawer.row_height;
int y_bottom = y_top - drawer.row_height;
y_top = std::min(y_top, region->winy - drawer.top_row_height);
y_bottom = std::min(y_bottom, region->winy - drawer.top_row_height);
immRecti(pos, x_left, y_top, x_right, y_bottom);
}
GPU_blend(GPU_BLEND_NONE);
}
static void draw_top_row_background(const uint pos,
const ARegion *region,
const SpreadsheetDrawer &drawer)
{
immUniformThemeColorShade(TH_BACK, 11);
immRecti(pos, 0, region->winy, region->winx, region->winy - drawer.top_row_height);
}
static void draw_separator_lines(const uint pos,
const int scroll_offset_x,
const ARegion *region,
const SpreadsheetDrawer &drawer)
{
immUniformThemeColorShade(TH_BACK, -11);
immBeginAtMost(GPU_PRIM_LINES, drawer.tot_columns * 2 + 4);
/* Left column line. */
immVertex2i(pos, drawer.left_column_width, region->winy);
immVertex2i(pos, drawer.left_column_width, 0);
/* Top row line. */
immVertex2i(pos, 0, region->winy - drawer.top_row_height);
immVertex2i(pos, region->winx, region->winy - drawer.top_row_height);
/* Column separator lines. */
int line_x = drawer.left_column_width - scroll_offset_x;
for (const int column_index : IndexRange(drawer.tot_columns)) {
const int column_width = drawer.column_width(column_index);
line_x += column_width;
if (line_x >= drawer.left_column_width) {
immVertex2i(pos, line_x, region->winy);
immVertex2i(pos, line_x, 0);
}
}
immEnd();
}
static void get_visible_rows(const SpreadsheetDrawer &drawer,
const ARegion *region,
const int scroll_offset_y,
int *r_first_row,
int *r_max_visible_rows)
{
*r_first_row = -scroll_offset_y / drawer.row_height;
*r_max_visible_rows = region->winy / drawer.row_height + 1;
}
static void draw_left_column_content(const int scroll_offset_y,
const bContext *C,
ARegion *region,
const SpreadsheetDrawer &drawer)
{
int old_scissor[4];
GPU_scissor_get(old_scissor);
GPU_scissor(0, 0, drawer.left_column_width, region->winy - drawer.top_row_height);
uiBlock *left_column_block = UI_block_begin(C, region, __func__, UI_EMBOSS_NONE);
int first_row, max_visible_rows;
get_visible_rows(drawer, region, scroll_offset_y, &first_row, &max_visible_rows);
for (const int row_index : IndexRange(first_row, max_visible_rows)) {
if (row_index >= drawer.tot_rows) {
break;
}
CellDrawParams params;
params.block = left_column_block;
params.xmin = 0;
params.ymin = region->winy - drawer.top_row_height - (row_index + 1) * drawer.row_height -
scroll_offset_y;
params.width = drawer.left_column_width;
params.height = drawer.row_height;
drawer.draw_left_column_cell(row_index, params);
}
UI_block_end(C, left_column_block);
UI_block_draw(C, left_column_block);
GPU_scissor(UNPACK4(old_scissor));
}
static void draw_top_row_content(const bContext *C,
ARegion *region,
const SpreadsheetDrawer &drawer,
const int scroll_offset_x)
{
int old_scissor[4];
GPU_scissor_get(old_scissor);
GPU_scissor(drawer.left_column_width + 1,
region->winy - drawer.top_row_height,
region->winx - drawer.left_column_width,
drawer.top_row_height);
uiBlock *first_row_block = UI_block_begin(C, region, __func__, UI_EMBOSS_NONE);
int left_x = drawer.left_column_width - scroll_offset_x;
for (const int column_index : IndexRange(drawer.tot_columns)) {
const int column_width = drawer.column_width(column_index);
const int right_x = left_x + column_width;
CellDrawParams params;
params.block = first_row_block;
params.xmin = left_x;
params.ymin = region->winy - drawer.top_row_height;
params.width = column_width;
params.height = drawer.top_row_height;
drawer.draw_top_row_cell(column_index, params);
left_x = right_x;
}
UI_block_end(C, first_row_block);
UI_block_draw(C, first_row_block);
GPU_scissor(UNPACK4(old_scissor));
}
static void draw_cell_contents(const bContext *C,
ARegion *region,
const SpreadsheetDrawer &drawer,
const int scroll_offset_x,
const int scroll_offset_y)
{
int old_scissor[4];
GPU_scissor_get(old_scissor);
GPU_scissor(drawer.left_column_width + 1,
0,
region->winx - drawer.left_column_width,
region->winy - drawer.top_row_height);
uiBlock *cells_block = UI_block_begin(C, region, __func__, UI_EMBOSS_NONE);
int first_row, max_visible_rows;
get_visible_rows(drawer, region, scroll_offset_y, &first_row, &max_visible_rows);
int left_x = drawer.left_column_width - scroll_offset_x;
for (const int column_index : IndexRange(drawer.tot_columns)) {
const int column_width = drawer.column_width(column_index);
const int right_x = left_x + column_width;
if (right_x >= drawer.left_column_width && left_x <= region->winx) {
for (const int row_index : IndexRange(first_row, max_visible_rows)) {
if (row_index >= drawer.tot_rows) {
break;
}
CellDrawParams params;
params.block = cells_block;
params.xmin = left_x;
params.ymin = region->winy - drawer.top_row_height - (row_index + 1) * drawer.row_height -
scroll_offset_y;
params.width = column_width;
params.height = drawer.row_height;
drawer.draw_content_cell(row_index, column_index, params);
}
}
left_x = right_x;
}
UI_block_end(C, cells_block);
UI_block_draw(C, cells_block);
GPU_scissor(UNPACK4(old_scissor));
}
static void update_view2d_tot_rect(const SpreadsheetDrawer &drawer,
ARegion *region,
const int row_amount)
{
int column_width_sum = 0;
for (const int column_index : IndexRange(drawer.tot_columns)) {
column_width_sum += drawer.column_width(column_index);
}
UI_view2d_totRect_set(&region->v2d,
column_width_sum + drawer.left_column_width,
row_amount * drawer.row_height + drawer.top_row_height);
}
void draw_spreadsheet_in_region(const bContext *C,
ARegion *region,
const SpreadsheetDrawer &drawer)
{
update_view2d_tot_rect(drawer, region, drawer.tot_rows);
UI_ThemeClearColor(TH_BACK);
View2D *v2d = &region->v2d;
const int scroll_offset_y = v2d->cur.ymax;
const int scroll_offset_x = v2d->cur.xmin;
GPUVertFormat *format = immVertexFormat();
uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
draw_index_column_background(pos, region, drawer);
draw_alternating_row_overlay(pos, scroll_offset_y, region, drawer);
draw_top_row_background(pos, region, drawer);
draw_separator_lines(pos, scroll_offset_x, region, drawer);
immUnbindProgram();
draw_left_column_content(scroll_offset_y, C, region, drawer);
draw_top_row_content(C, region, drawer, scroll_offset_x);
draw_cell_contents(C, region, drawer, scroll_offset_x, scroll_offset_y);
rcti scroller_mask;
BLI_rcti_init(&scroller_mask,
drawer.left_column_width,
region->winx,
0,
region->winy - drawer.top_row_height);
UI_view2d_scrollers_draw(v2d, &scroller_mask);
}
} // namespace blender::ed::spreadsheet