[Bf-blender-cvs] [1a7eeb4fef] uiTable: Initial implementation of a uiTable API

Julian Eisel noreply at git.blender.org
Sun Feb 5 17:18:54 CET 2017


Commit: 1a7eeb4feff0c5b4117010e34fb231c27526590e
Author: Julian Eisel
Date:   Wed Feb 1 21:43:59 2017 +0100
Branches: uiTable
https://developer.blender.org/rB1a7eeb4feff0c5b4117010e34fb231c27526590e

Initial implementation of a uiTable API

This adds an initial (and already working), generic API for defining, handling and drawing of table UIs.

It supports two types of tables:
* Vertical flow: Rows are all in a vertical stack.
* Horizontal flow: Rows are stacked vertically, until some threshold height is reached. The table is then split into another vertical stack that is drawn next to the former one. Such drawing could be used for the file browser in non-thumbnail mode.

A table is built out of - guess what - rows and columns. The API allows defining new collumns (identified by an id-name) and inserting new rows at any point. When drawing, we draw a cell for each column/row combination, using a custom cell-drawing callback.
The uiTable API will probably get some support for drawing buttons (uiBut) into custom layouts (uiLayout).

The API is written with big data sets in mind. In future we may get a spreadsheet view where data like all vertices of a mesh is displayed. That would result in thousands of rows, the uiTable API should be ready for this.

===================================================================

M	source/blender/editors/include/UI_interface.h
A	source/blender/editors/include/UI_table.h
M	source/blender/editors/interface/CMakeLists.txt
A	source/blender/editors/interface/table.c
M	source/blender/editors/util/CMakeLists.txt

===================================================================

diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index d48cfbee41..701f8e3d17 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -997,7 +997,7 @@ void uiItemsFullEnumO(
         struct IDProperty *properties, int context, int flag);
 void uiItemsFullEnumO_items(
         uiLayout *layout, struct wmOperatorType *ot, PointerRNA ptr, PropertyRNA *prop,
-        IDProperty *properties, int context, int flag,
+        struct IDProperty *properties, int context, int flag,
         const EnumPropertyItem *item_array, int totitem);
 
 void uiItemL(uiLayout *layout, const char *name, int icon); /* label */
diff --git a/source/blender/editors/include/UI_table.h b/source/blender/editors/include/UI_table.h
new file mode 100644
index 0000000000..ca1220198d
--- /dev/null
+++ b/source/blender/editors/include/UI_table.h
@@ -0,0 +1,68 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * 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.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file UI_table.h
+ *  \ingroup editorui
+ */
+
+#ifndef __UI_TABLE_H__
+#define __UI_TABLE_H__
+
+#include "BLI_compiler_attrs.h"
+
+struct rcti;
+
+typedef struct uiTable uiTable;
+typedef struct uiTableColumn uiTableColumn;
+typedef struct uiTableRow uiTableRow;
+typedef struct uiTableSize uiTableSize;
+
+typedef void (*uiTableCellDrawFunc)(void *rowdata, struct rcti drawrect);
+
+enum uiTableColumnAlignemt {
+	TABLE_COLUMN_ALIGN_LEFT,
+	TABLE_COLUMN_ALIGN_RIGHT,
+};
+
+
+uiTable *UI_table_horizontal_flow_create(void) ATTR_WARN_UNUSED_RESULT;
+uiTable *UI_table_vertical_flow_create(void) ATTR_WARN_UNUSED_RESULT;
+void UI_table_free(uiTable *table) ATTR_NONNULL();
+
+void UI_table_max_width_set(uiTable *table, const unsigned int max_width) ATTR_NONNULL();
+void UI_table_horizontal_flow_max_height_set(uiTable *table, const unsigned int max_height) ATTR_NONNULL();
+void UI_table_draw(uiTable *table) ATTR_NONNULL();
+
+/* *** Columns *** */
+uiTableColumn *UI_table_column_add(uiTable *table, const char *idname, const char *drawname,
+                                   uiTableCellDrawFunc cell_draw) ATTR_NONNULL(1, 2);
+void UI_table_column_remove(uiTable *table, uiTableColumn *column) ATTR_NONNULL();
+uiTableColumn *UI_table_column_lookup(uiTable *table, const char *idname) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT;
+void UI_table_column_width_set(uiTableColumn *col, const uiTableSize width, const int min_width_px) ATTR_NONNULL();
+void UI_table_column_alignment_set(uiTableColumn *column, enum uiTableColumnAlignemt alignment) ATTR_NONNULL();
+/* *** Rows *** */
+uiTableRow *UI_table_row_add(uiTable *table, void *rowdata) ATTR_NONNULL(1);
+void UI_table_row_height_set(uiTable *table, uiTableRow *row, unsigned int height) ATTR_NONNULL();
+
+uiTableSize UI_table_size_px(const int value);
+uiTableSize UI_table_size_percentage(const int value);
+unsigned int UI_table_get_rowcount(const uiTable *table);
+
+#endif /* __UI_TABLE_H__ */
diff --git a/source/blender/editors/interface/CMakeLists.txt b/source/blender/editors/interface/CMakeLists.txt
index c57f8d5c7a..de63bf67df 100644
--- a/source/blender/editors/interface/CMakeLists.txt
+++ b/source/blender/editors/interface/CMakeLists.txt
@@ -55,6 +55,7 @@ set(SRC
 	interface_utils.c
 	interface_widgets.c
 	resources.c
+	table.c
 	view2d.c
 	view2d_ops.c
 
diff --git a/source/blender/editors/interface/table.c b/source/blender/editors/interface/table.c
new file mode 100644
index 0000000000..514af17131
--- /dev/null
+++ b/source/blender/editors/interface/table.c
@@ -0,0 +1,437 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * 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.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/interface/table.c
+ *  \ingroup edinterface
+ */
+
+#include <limits.h>
+#include <string.h>
+
+#include "BLI_listbase.h"
+#include "BLI_math.h"
+#include "BLI_mempool.h"
+#include "BLI_rect.h"
+
+#include "DNA_userdef_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "UI_interface.h"
+#include "UI_table.h"
+
+
+typedef struct uiTable {
+	BLI_mempool *row_pool;
+	ListBase columns;
+
+	enum {
+		TABLE_FLOW_VERTICAL,
+		TABLE_FLOW_HORIZONTAL,
+	} flow_direction;
+	unsigned int max_width;
+
+	char flag;
+} uiTable;
+
+enum eTableFlags {
+	/* All rows have the same height. In this case we can avoid iterating
+	 * over rows for calculations like intersection checks. */
+	TABLE_ROWS_CONSTANT_HEIGHT = (1 << 0),
+};
+
+typedef struct TableHorizontalFlow {
+	uiTable table;
+
+	/* if this height is reached, we split the table */
+	unsigned int max_height;
+} TableHorizontalFlow;
+
+/**
+ * This struct allows using either relative or absolute scales
+ * for size properties (only column widths right now).
+ */
+typedef struct uiTableSize {
+	enum {
+		TABLE_UNIT_PX,
+		TABLE_UNIT_PERCENT,
+	} unit;
+	int value;
+} uiTableSize;
+
+typedef struct uiTableRow {
+	void *rowdata;
+
+	unsigned int height;
+} uiTableRow;
+
+typedef struct uiTableColumn {
+	struct uiTableColumn *next, *prev;
+
+	const char *idname;
+	const char *drawname;
+
+	uiTableSize width;
+	unsigned int min_width;
+	enum uiTableColumnAlignemt alignment;
+
+	uiTableCellDrawFunc cell_draw;
+} uiTableColumn;
+
+
+/* -------------------------------------------------------------------- */
+
+struct TableColumnDrawInfo {
+	/* Total width of all columns. */
+	unsigned int totwidth_columns;
+
+	/* While drawing: Total width of the already drawn columns depending on alignment (left of right). */
+	unsigned int totwidth_left;
+	unsigned int totwidth_right;
+
+	/* Total width of all non-fixed width columns (having size in px instead of percent). */
+	unsigned int totwidth_nonfixed;
+};
+
+/**
+ * Iterate over all columns in \a table. Supports removing columns while iterating.
+ */
+#define TABLE_COLUMNS_ITER_BEGIN(table, column_name) \
+	for (uiTableColumn *column_name = (table)->columns.first, *column_name##_next; \
+	     column_name; \
+	     column_name = column_name##_next) \
+		{ \
+			column_name##_next = column_name->next;
+#define TABLE_COLUMNS_ITER_END } (void)0
+
+
+static void table_init(uiTable *table)
+{
+	table->row_pool = BLI_mempool_create(sizeof(uiTableRow), 0, 64, BLI_MEMPOOL_ALLOW_ITER);
+	table->flag |= TABLE_ROWS_CONSTANT_HEIGHT;
+}
+
+static void table_column_free(uiTableColumn *column)
+{
+	MEM_freeN(column);
+}
+
+static void table_columns_free(uiTable *table)
+{
+	TABLE_COLUMNS_ITER_BEGIN(table, column)
+	{
+		table_column_free(column);
+	}
+	TABLE_COLUMNS_ITER_END;
+}
+
+static void table_row_height_set(uiTable *table, uiTableRow *row, unsigned int height)
+{
+	row->height = height;
+
+	/* Figure out if the new height breaks the 'every row has the same height' state. If so, unset flag.
+	 * To avoid any additional iterations, we just check if we need to set it again on drawing */
+	if (table->flag & TABLE_ROWS_CONSTANT_HEIGHT) {
+		uiTableRow *row_first = BLI_mempool_findelem(table->row_pool, 0);
+
+		if (row_first->height != row->height) {
+			table->flag &= ~TABLE_ROWS_CONSTANT_HEIGHT;
+		}
+	}
+}
+
+static unsigned int table_get_tot_width_unfixed_columns(const uiTable *table)
+{
+	unsigned int nonfixed_width = table->max_width;
+
+	TABLE_COLUMNS_ITER_BEGIN(table, column)
+	{
+		if (column->width.unit == TABLE_UNIT_PX) {
+			BLI_assert(nonfixed_width - column->width.value > 0);
+			nonfixed_width -= column->width.value;
+		}
+	}
+	TABLE_COLUMNS_ITER_END;
+
+	return nonfixed_width;
+}
+
+static struct TableColumnDrawInfo table_column_drawinfo_init(const uiTable *table)
+{
+	struct TableColumnDrawInfo drawinfo = {};
+
+	drawinfo.totwidth_nonfixed = table_get_tot_width_unfixed_columns(table);
+	BLI_assert(drawinfo.totwidth_nonfixed <= table->max_width);
+
+	return drawinfo;
+}
+
+static unsigned int table_column_calc_width(const uiTableColumn *column, const struct TableColumnDrawInfo *drawinfo)
+{
+	unsigned int width = column->width.value;
+
+	if (column->width.unit == TABLE_UNIT_PERCENT) {
+		width = iroundf(width * 0.01f * drawinfo->totwidth_nonfixed);
+	}
+	width = MAX2(column->min_width, width);
+
+	return width;
+}
+
+/**
+ * Calculate the table-flow relative x-coordinates, meaning we don't account for horizontal-flow
+ * yet, the first column aligned to the left will just always be at xmin = 0.
+ */
+static void table_column_calc_x_coords(const uiTableColumn *column, const float max_width,
+                                       struct TableColumnDrawInfo *io_drawinfo,
+                                       int *r_xmin, int *r_xmax)
+{
+	const unsigned int width = table_column_calc_width(column, io_drawinfo);
+
+	if (column->alignment == TABLE_COLUMN_ALIGN_LEFT) {
+		*r_xmin = io_drawinfo->totwidth_left;
+		*r_xmax = *r_xmin + width;
+
+		io_drawinfo->totwidth_left +=

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list