Blender  V3.3
spreadsheet_draw.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
3 #include "UI_interface.h"
4 #include "UI_resources.h"
5 #include "UI_view2d.h"
6 
7 #include "GPU_immediate.h"
8 
9 #include "DNA_screen_types.h"
10 #include "DNA_userdef_types.h"
11 
12 #include "BLI_rect.h"
13 
14 #include "spreadsheet_draw.hh"
15 
16 #define CELL_RIGHT_PADDING (2.0f * UI_DPI_FAC)
17 
18 namespace blender::ed::spreadsheet {
19 
21 {
23  top_row_height = UI_UNIT_Y * 1.1f;
25 }
26 
28 
30  const CellDrawParams &UNUSED(params)) const
31 {
32 }
33 
35  const CellDrawParams &UNUSED(params)) const
36 {
37 }
38 
40  int UNUSED(column_index),
41  const CellDrawParams &UNUSED(params)) const
42 {
43 }
44 
45 int SpreadsheetDrawer::column_width(int UNUSED(column_index)) const
46 {
47  return 5 * UI_UNIT_X;
48 }
49 
51  const ARegion *region,
52  const SpreadsheetDrawer &drawer)
53 {
55  immRecti(pos, 0, region->winy - drawer.top_row_height, drawer.left_column_width, 0);
56 }
57 
59  const int scroll_offset_y,
60  const ARegion *region,
61  const SpreadsheetDrawer &drawer)
62 {
65  BLI_assert(drawer.row_height > 0);
66  const int row_pair_height = drawer.row_height * 2;
67  const int row_top_y = region->winy - drawer.top_row_height - scroll_offset_y % row_pair_height;
68  for (const int i : IndexRange(region->winy / row_pair_height + 1)) {
69  int x_left = 0;
70  int x_right = region->winx;
71  int y_top = row_top_y - i * row_pair_height - drawer.row_height;
72  int y_bottom = y_top - drawer.row_height;
73  y_top = std::min(y_top, region->winy - drawer.top_row_height);
74  y_bottom = std::min(y_bottom, region->winy - drawer.top_row_height);
75  immRecti(pos, x_left, y_top, x_right, y_bottom);
76  }
78 }
79 
80 static void draw_top_row_background(const uint pos,
81  const ARegion *region,
82  const SpreadsheetDrawer &drawer)
83 {
85  immRecti(pos, 0, region->winy, region->winx, region->winy - drawer.top_row_height);
86 }
87 
88 static void draw_separator_lines(const uint pos,
89  const int scroll_offset_x,
90  const ARegion *region,
91  const SpreadsheetDrawer &drawer)
92 {
94 
95  immBeginAtMost(GPU_PRIM_LINES, drawer.tot_columns * 2 + 4);
96 
97  /* Left column line. */
98  immVertex2i(pos, drawer.left_column_width, region->winy);
99  immVertex2i(pos, drawer.left_column_width, 0);
100 
101  /* Top row line. */
102  immVertex2i(pos, 0, region->winy - drawer.top_row_height);
103  immVertex2i(pos, region->winx, region->winy - drawer.top_row_height);
104 
105  /* Column separator lines. */
106  int line_x = drawer.left_column_width - scroll_offset_x;
107  for (const int column_index : IndexRange(drawer.tot_columns)) {
108  const int column_width = drawer.column_width(column_index);
109  line_x += column_width;
110  if (line_x >= drawer.left_column_width) {
111  immVertex2i(pos, line_x, region->winy);
112  immVertex2i(pos, line_x, 0);
113  }
114  }
115  immEnd();
116 }
117 
118 static void get_visible_rows(const SpreadsheetDrawer &drawer,
119  const ARegion *region,
120  const int scroll_offset_y,
121  int *r_first_row,
122  int *r_max_visible_rows)
123 {
124  *r_first_row = -scroll_offset_y / drawer.row_height;
125  *r_max_visible_rows = region->winy / drawer.row_height + 1;
126 }
127 
128 static void draw_left_column_content(const int scroll_offset_y,
129  const bContext *C,
130  ARegion *region,
131  const SpreadsheetDrawer &drawer)
132 {
133  int old_scissor[4];
134  GPU_scissor_get(old_scissor);
135 
136  GPU_scissor(0, 0, drawer.left_column_width, region->winy - drawer.top_row_height);
137 
138  uiBlock *left_column_block = UI_block_begin(C, region, __func__, UI_EMBOSS_NONE);
139  int first_row, max_visible_rows;
140  get_visible_rows(drawer, region, scroll_offset_y, &first_row, &max_visible_rows);
141  for (const int row_index : IndexRange(first_row, max_visible_rows)) {
142  if (row_index >= drawer.tot_rows) {
143  break;
144  }
146  params.block = left_column_block;
147  params.xmin = 0;
148  params.ymin = region->winy - drawer.top_row_height - (row_index + 1) * drawer.row_height -
149  scroll_offset_y;
151  params.height = drawer.row_height;
152  drawer.draw_left_column_cell(row_index, params);
153  }
154 
155  UI_block_end(C, left_column_block);
156  UI_block_draw(C, left_column_block);
157 
158  GPU_scissor(UNPACK4(old_scissor));
159 }
160 
161 static void draw_top_row_content(const bContext *C,
162  ARegion *region,
163  const SpreadsheetDrawer &drawer,
164  const int scroll_offset_x)
165 {
166  int old_scissor[4];
167  GPU_scissor_get(old_scissor);
168 
169  GPU_scissor(drawer.left_column_width + 1,
170  region->winy - drawer.top_row_height,
171  region->winx - drawer.left_column_width,
172  drawer.top_row_height);
173 
174  uiBlock *first_row_block = UI_block_begin(C, region, __func__, UI_EMBOSS_NONE);
175 
176  int left_x = drawer.left_column_width - scroll_offset_x;
177  for (const int column_index : IndexRange(drawer.tot_columns)) {
178  const int column_width = drawer.column_width(column_index);
179  const int right_x = left_x + column_width;
180 
182  params.block = first_row_block;
183  params.xmin = left_x;
184  params.ymin = region->winy - drawer.top_row_height;
185  params.width = column_width - CELL_RIGHT_PADDING;
186  params.height = drawer.top_row_height;
187  drawer.draw_top_row_cell(column_index, params);
188 
189  left_x = right_x;
190  }
191 
192  UI_block_end(C, first_row_block);
193  UI_block_draw(C, first_row_block);
194 
195  GPU_scissor(UNPACK4(old_scissor));
196 }
197 
198 static void draw_cell_contents(const bContext *C,
199  ARegion *region,
200  const SpreadsheetDrawer &drawer,
201  const int scroll_offset_x,
202  const int scroll_offset_y)
203 {
204  int old_scissor[4];
205  GPU_scissor_get(old_scissor);
206 
207  GPU_scissor(drawer.left_column_width + 1,
208  0,
209  region->winx - drawer.left_column_width,
210  region->winy - drawer.top_row_height);
211 
212  uiBlock *cells_block = UI_block_begin(C, region, __func__, UI_EMBOSS_NONE);
213 
214  int first_row, max_visible_rows;
215  get_visible_rows(drawer, region, scroll_offset_y, &first_row, &max_visible_rows);
216 
217  int left_x = drawer.left_column_width - scroll_offset_x;
218  for (const int column_index : IndexRange(drawer.tot_columns)) {
219  const int column_width = drawer.column_width(column_index);
220  const int right_x = left_x + column_width;
221 
222  if (right_x >= drawer.left_column_width && left_x <= region->winx) {
223  for (const int row_index : IndexRange(first_row, max_visible_rows)) {
224  if (row_index >= drawer.tot_rows) {
225  break;
226  }
227 
229  params.block = cells_block;
230  params.xmin = left_x;
231  params.ymin = region->winy - drawer.top_row_height - (row_index + 1) * drawer.row_height -
232  scroll_offset_y;
233  params.width = column_width - CELL_RIGHT_PADDING;
234  params.height = drawer.row_height;
235  drawer.draw_content_cell(row_index, column_index, params);
236  }
237  }
238 
239  left_x = right_x;
240  }
241 
242  UI_block_end(C, cells_block);
243  UI_block_draw(C, cells_block);
244 
245  GPU_scissor(UNPACK4(old_scissor));
246 }
247 
248 static void update_view2d_tot_rect(const SpreadsheetDrawer &drawer,
249  ARegion *region,
250  const int row_amount)
251 {
252  int column_width_sum = 0;
253  for (const int column_index : IndexRange(drawer.tot_columns)) {
254  column_width_sum += drawer.column_width(column_index);
255  }
256 
257  UI_view2d_totRect_set(&region->v2d,
258  column_width_sum + drawer.left_column_width,
259  row_amount * drawer.row_height + drawer.top_row_height);
260 }
261 
263  ARegion *region,
264  const SpreadsheetDrawer &drawer)
265 {
266  update_view2d_tot_rect(drawer, region, drawer.tot_rows);
267 
269 
270  View2D *v2d = &region->v2d;
271  const int scroll_offset_y = v2d->cur.ymax;
272  const int scroll_offset_x = v2d->cur.xmin;
273 
277 
278  draw_index_column_background(pos, region, drawer);
279  draw_alternating_row_overlay(pos, scroll_offset_y, region, drawer);
280  draw_top_row_background(pos, region, drawer);
281  draw_separator_lines(pos, scroll_offset_x, region, drawer);
282 
284 
285  draw_left_column_content(scroll_offset_y, C, region, drawer);
286  draw_top_row_content(C, region, drawer, scroll_offset_x);
287  draw_cell_contents(C, region, drawer, scroll_offset_x, scroll_offset_y);
288 
289  rcti scroller_mask;
290  BLI_rcti_init(&scroller_mask,
291  drawer.left_column_width,
292  region->winx,
293  0,
294  region->winy - drawer.top_row_height);
295  UI_view2d_scrollers_draw(v2d, &scroller_mask);
296 }
297 
298 } // namespace blender::ed::spreadsheet
#define BLI_assert(a)
Definition: BLI_assert.h:46
void BLI_rcti_init(struct rcti *rect, int xmin, int xmax, int ymin, int ymax)
Definition: rct.c:417
unsigned int uint
Definition: BLI_sys_types.h:67
#define UNPACK4(a)
#define UNUSED(x)
void immUnbindProgram(void)
void immUniformThemeColor(int color_id)
void immUniformThemeColorShade(int color_id, int offset)
void immBindBuiltinProgram(eGPUBuiltinShader shader_id)
void immBeginAtMost(GPUPrimType, uint max_vertex_len)
void immVertex2i(uint attr_id, int x, int y)
GPUVertFormat * immVertexFormat(void)
void immEnd(void)
void immRecti(uint pos, int x1, int y1, int x2, int y2)
@ GPU_PRIM_LINES
Definition: GPU_primitive.h:20
@ GPU_SHADER_2D_UNIFORM_COLOR
Definition: GPU_shader.h:201
@ GPU_BLEND_NONE
Definition: GPU_state.h:60
@ GPU_BLEND_ALPHA
Definition: GPU_state.h:62
void GPU_blend(eGPUBlend blend)
Definition: gpu_state.cc:39
void GPU_scissor(int x, int y, int width, int height)
Definition: gpu_state.cc:185
void GPU_scissor_get(int coords[4])
Definition: gpu_state.cc:254
@ GPU_FETCH_INT_TO_FLOAT
uint GPU_vertformat_attr_add(GPUVertFormat *, const char *name, GPUVertCompType, uint comp_len, GPUVertFetchMode)
@ GPU_COMP_I32
#define C
Definition: RandGen.cpp:25
#define UI_UNIT_Y
@ UI_EMBOSS_NONE
Definition: UI_interface.h:109
void UI_block_end(const struct bContext *C, uiBlock *block)
void UI_block_draw(const struct bContext *C, struct uiBlock *block)
uiBlock * UI_block_begin(const struct bContext *C, struct ARegion *region, const char *name, eUIEmbossType emboss)
#define UI_UNIT_X
@ TH_ROW_ALTERNATE
Definition: UI_resources.h:262
@ TH_BACK
Definition: UI_resources.h:39
void UI_ThemeClearColor(int colorid)
Definition: resources.c:1448
void UI_view2d_totRect_set(struct View2D *v2d, int width, int height)
Definition: view2d.cc:1022
void UI_view2d_scrollers_draw(struct View2D *v2d, const struct rcti *mask_custom)
virtual void draw_top_row_cell(int column_index, const CellDrawParams &params) const
virtual int column_width(int column_index) const
virtual void draw_left_column_cell(int row_index, const CellDrawParams &params) const
virtual void draw_content_cell(int row_index, int column_index, const CellDrawParams &params) const
uint pos
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
format
Definition: logImageCore.h:38
static void draw_index_column_background(const uint pos, const ARegion *region, const SpreadsheetDrawer &drawer)
static void draw_left_column_content(const int scroll_offset_y, const bContext *C, ARegion *region, const SpreadsheetDrawer &drawer)
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)
void draw_spreadsheet_in_region(const bContext *C, ARegion *region, const SpreadsheetDrawer &drawer)
static void update_view2d_tot_rect(const SpreadsheetDrawer &drawer, ARegion *region, const int row_amount)
static void draw_top_row_content(const bContext *C, ARegion *region, const SpreadsheetDrawer &drawer, const int scroll_offset_x)
static void draw_alternating_row_overlay(const uint pos, const int scroll_offset_y, const ARegion *region, const SpreadsheetDrawer &drawer)
static void draw_cell_contents(const bContext *C, ARegion *region, const SpreadsheetDrawer &drawer, const int scroll_offset_x, const int scroll_offset_y)
static void draw_separator_lines(const uint pos, const int scroll_offset_x, const ARegion *region, const SpreadsheetDrawer &drawer)
static void draw_top_row_background(const uint pos, const ARegion *region, const SpreadsheetDrawer &drawer)
#define min(a, b)
Definition: sort.c:35
#define CELL_RIGHT_PADDING
float xmin
Definition: DNA_vec_types.h:69
float ymax
Definition: DNA_vec_types.h:70