Blender  V2.93
spreadsheet_draw.cc
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16 
17 #include "UI_interface.h"
18 #include "UI_resources.h"
19 #include "UI_view2d.h"
20 
21 #include "GPU_immediate.h"
22 
23 #include "DNA_screen_types.h"
24 #include "DNA_userdef_types.h"
25 
26 #include "BLI_rect.h"
27 
28 #include "spreadsheet_draw.hh"
29 
30 namespace blender::ed::spreadsheet {
31 
33 {
35  top_row_height = UI_UNIT_Y * 1.1f;
37 }
38 
40 
42  const CellDrawParams &UNUSED(params)) const
43 {
44 }
45 
47  const CellDrawParams &UNUSED(params)) const
48 {
49 }
50 
52  int UNUSED(column_index),
53  const CellDrawParams &UNUSED(params)) const
54 {
55 }
56 
57 int SpreadsheetDrawer::column_width(int UNUSED(column_index)) const
58 {
59  return 5 * UI_UNIT_X;
60 }
61 
63  const ARegion *region,
64  const SpreadsheetDrawer &drawer)
65 {
67  immRecti(pos, 0, region->winy - drawer.top_row_height, drawer.left_column_width, 0);
68 }
69 
71  const int scroll_offset_y,
72  const ARegion *region,
73  const SpreadsheetDrawer &drawer)
74 {
77  BLI_assert(drawer.row_height > 0);
78  const int row_pair_height = drawer.row_height * 2;
79  const int row_top_y = region->winy - drawer.top_row_height - scroll_offset_y % row_pair_height;
80  for (const int i : IndexRange(region->winy / row_pair_height + 1)) {
81  int x_left = 0;
82  int x_right = region->winx;
83  int y_top = row_top_y - i * row_pair_height - drawer.row_height;
84  int y_bottom = y_top - drawer.row_height;
85  y_top = std::min(y_top, region->winy - drawer.top_row_height);
86  y_bottom = std::min(y_bottom, region->winy - drawer.top_row_height);
87  immRecti(pos, x_left, y_top, x_right, y_bottom);
88  }
90 }
91 
92 static void draw_top_row_background(const uint pos,
93  const ARegion *region,
94  const SpreadsheetDrawer &drawer)
95 {
97  immRecti(pos, 0, region->winy, region->winx, region->winy - drawer.top_row_height);
98 }
99 
100 static void draw_separator_lines(const uint pos,
101  const int scroll_offset_x,
102  const ARegion *region,
103  const SpreadsheetDrawer &drawer)
104 {
106 
107  immBeginAtMost(GPU_PRIM_LINES, drawer.tot_columns * 2 + 4);
108 
109  /* Left column line. */
110  immVertex2i(pos, drawer.left_column_width, region->winy);
111  immVertex2i(pos, drawer.left_column_width, 0);
112 
113  /* Top row line. */
114  immVertex2i(pos, 0, region->winy - drawer.top_row_height);
115  immVertex2i(pos, region->winx, region->winy - drawer.top_row_height);
116 
117  /* Column separator lines. */
118  int line_x = drawer.left_column_width - scroll_offset_x;
119  for (const int column_index : IndexRange(drawer.tot_columns)) {
120  const int column_width = drawer.column_width(column_index);
121  line_x += column_width;
122  if (line_x >= drawer.left_column_width) {
123  immVertex2i(pos, line_x, region->winy);
124  immVertex2i(pos, line_x, 0);
125  }
126  }
127  immEnd();
128 }
129 
130 static void get_visible_rows(const SpreadsheetDrawer &drawer,
131  const ARegion *region,
132  const int scroll_offset_y,
133  int *r_first_row,
134  int *r_max_visible_rows)
135 {
136  *r_first_row = -scroll_offset_y / drawer.row_height;
137  *r_max_visible_rows = region->winy / drawer.row_height + 1;
138 }
139 
140 static void draw_left_column_content(const int scroll_offset_y,
141  const bContext *C,
142  ARegion *region,
143  const SpreadsheetDrawer &drawer)
144 {
145  int old_scissor[4];
146  GPU_scissor_get(old_scissor);
147 
148  GPU_scissor(0, 0, drawer.left_column_width, region->winy - drawer.top_row_height);
149 
150  uiBlock *left_column_block = UI_block_begin(C, region, __func__, UI_EMBOSS_NONE);
151  int first_row, max_visible_rows;
152  get_visible_rows(drawer, region, scroll_offset_y, &first_row, &max_visible_rows);
153  for (const int row_index : IndexRange(first_row, max_visible_rows)) {
154  if (row_index >= drawer.tot_rows) {
155  break;
156  }
158  params.block = left_column_block;
159  params.xmin = 0;
160  params.ymin = region->winy - drawer.top_row_height - (row_index + 1) * drawer.row_height -
161  scroll_offset_y;
162  params.width = drawer.left_column_width;
163  params.height = drawer.row_height;
164  drawer.draw_left_column_cell(row_index, params);
165  }
166 
167  UI_block_end(C, left_column_block);
168  UI_block_draw(C, left_column_block);
169 
170  GPU_scissor(UNPACK4(old_scissor));
171 }
172 
173 static void draw_top_row_content(const bContext *C,
174  ARegion *region,
175  const SpreadsheetDrawer &drawer,
176  const int scroll_offset_x)
177 {
178  int old_scissor[4];
179  GPU_scissor_get(old_scissor);
180 
181  GPU_scissor(drawer.left_column_width + 1,
182  region->winy - drawer.top_row_height,
183  region->winx - drawer.left_column_width,
184  drawer.top_row_height);
185 
186  uiBlock *first_row_block = UI_block_begin(C, region, __func__, UI_EMBOSS_NONE);
187 
188  int left_x = drawer.left_column_width - scroll_offset_x;
189  for (const int column_index : IndexRange(drawer.tot_columns)) {
190  const int column_width = drawer.column_width(column_index);
191  const int right_x = left_x + column_width;
192 
194  params.block = first_row_block;
195  params.xmin = left_x;
196  params.ymin = region->winy - drawer.top_row_height;
197  params.width = column_width;
198  params.height = drawer.top_row_height;
199  drawer.draw_top_row_cell(column_index, params);
200 
201  left_x = right_x;
202  }
203 
204  UI_block_end(C, first_row_block);
205  UI_block_draw(C, first_row_block);
206 
207  GPU_scissor(UNPACK4(old_scissor));
208 }
209 
210 static void draw_cell_contents(const bContext *C,
211  ARegion *region,
212  const SpreadsheetDrawer &drawer,
213  const int scroll_offset_x,
214  const int scroll_offset_y)
215 {
216  int old_scissor[4];
217  GPU_scissor_get(old_scissor);
218 
219  GPU_scissor(drawer.left_column_width + 1,
220  0,
221  region->winx - drawer.left_column_width,
222  region->winy - drawer.top_row_height);
223 
224  uiBlock *cells_block = UI_block_begin(C, region, __func__, UI_EMBOSS_NONE);
225 
226  int first_row, max_visible_rows;
227  get_visible_rows(drawer, region, scroll_offset_y, &first_row, &max_visible_rows);
228 
229  int left_x = drawer.left_column_width - scroll_offset_x;
230  for (const int column_index : IndexRange(drawer.tot_columns)) {
231  const int column_width = drawer.column_width(column_index);
232  const int right_x = left_x + column_width;
233 
234  if (right_x >= drawer.left_column_width && left_x <= region->winx) {
235  for (const int row_index : IndexRange(first_row, max_visible_rows)) {
236  if (row_index >= drawer.tot_rows) {
237  break;
238  }
239 
241  params.block = cells_block;
242  params.xmin = left_x;
243  params.ymin = region->winy - drawer.top_row_height - (row_index + 1) * drawer.row_height -
244  scroll_offset_y;
245  params.width = column_width;
246  params.height = drawer.row_height;
247  drawer.draw_content_cell(row_index, column_index, params);
248  }
249  }
250 
251  left_x = right_x;
252  }
253 
254  UI_block_end(C, cells_block);
255  UI_block_draw(C, cells_block);
256 
257  GPU_scissor(UNPACK4(old_scissor));
258 }
259 
260 static void update_view2d_tot_rect(const SpreadsheetDrawer &drawer,
261  ARegion *region,
262  const int row_amount)
263 {
264  int column_width_sum = 0;
265  for (const int column_index : IndexRange(drawer.tot_columns)) {
266  column_width_sum += drawer.column_width(column_index);
267  }
268 
269  UI_view2d_totRect_set(&region->v2d,
270  column_width_sum + drawer.left_column_width,
271  row_amount * drawer.row_height + drawer.top_row_height);
272 }
273 
275  ARegion *region,
276  const SpreadsheetDrawer &drawer)
277 {
278  update_view2d_tot_rect(drawer, region, drawer.tot_rows);
279 
281 
282  View2D *v2d = &region->v2d;
283  const int scroll_offset_y = v2d->cur.ymax;
284  const int scroll_offset_x = v2d->cur.xmin;
285 
289 
290  draw_index_column_background(pos, region, drawer);
291  draw_alternating_row_overlay(pos, scroll_offset_y, region, drawer);
292  draw_top_row_background(pos, region, drawer);
293  draw_separator_lines(pos, scroll_offset_x, region, drawer);
294 
296 
297  draw_left_column_content(scroll_offset_y, C, region, drawer);
298  draw_top_row_content(C, region, drawer, scroll_offset_x);
299  draw_cell_contents(C, region, drawer, scroll_offset_x, scroll_offset_y);
300 
301  rcti scroller_mask;
302  BLI_rcti_init(&scroller_mask,
303  drawer.left_column_width,
304  region->winx,
305  0,
306  region->winy - drawer.top_row_height);
307  UI_view2d_scrollers_draw(v2d, &scroller_mask);
308 }
309 
310 } // namespace blender::ed::spreadsheet
#define BLI_assert(a)
Definition: BLI_assert.h:58
void BLI_rcti_init(struct rcti *rect, int xmin, int xmax, int ymin, int ymax)
Definition: rct.c:446
unsigned int uint
Definition: BLI_sys_types.h:83
#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:36
@ GPU_SHADER_2D_UNIFORM_COLOR
Definition: GPU_shader.h:171
@ GPU_BLEND_NONE
Definition: GPU_state.h:55
@ GPU_BLEND_ALPHA
Definition: GPU_state.h:57
void GPU_blend(eGPUBlend blend)
Definition: gpu_state.cc:55
void GPU_scissor(int x, int y, int width, int height)
Definition: gpu_state.cc:204
void GPU_scissor_get(int coords[4])
Definition: gpu_state.cc:274
@ 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:39
#define UI_UNIT_Y
@ UI_EMBOSS_NONE
Definition: UI_interface.h:108
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:278
@ TH_BACK
Definition: UI_resources.h:55
void UI_ThemeClearColor(int colorid)
Definition: resources.c:1478
void UI_view2d_totRect_set(struct View2D *v2d, int width, int height)
Definition: view2d.c:1052
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:47
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:51
float xmin
Definition: DNA_vec_types.h:85
float ymax
Definition: DNA_vec_types.h:86