From 2163d3e9ec0505499a67656de732ab0c64faf33d Mon Sep 17 00:00:00 2001 From: sasha80 Date: Thu, 10 Aug 2023 15:38:49 +0300 Subject: [PATCH] =?UTF-8?q?=D0=A0=D0=B5=D1=84=D0=B0=D0=BA=D1=82=D0=BE?= =?UTF-8?q?=D1=80=D0=B8=D0=BD=D0=B3.=20=D0=90=D0=BD=D0=BD=D0=BE=D1=82?= =?UTF-8?q?=D0=B0=D1=86=D0=B8=D0=B8=20GDScript?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- table/table.gd | 137 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 97 insertions(+), 40 deletions(-) diff --git a/table/table.gd b/table/table.gd index 3f9532a1..4736dbb1 100644 --- a/table/table.gd +++ b/table/table.gd @@ -1,36 +1,38 @@ extends GridContainer -@export var selector_color: = Color(1.0, 1.0, 1.0, 1.0) -@export var node_gap: = Vector2(0.0, 0.0) # -@export_file var node_type_file: = 'res://table/node.tscn': get = get_node_scene, set = load_node_scene -@export_file var selector_type_file: = 'res://table/selector.tscn': set = load_selector_scene -@export var selector_key_up: Key = KEY_UP # Клавиша уменьшения индекса выбранного ряда -@export var selector_key_down: Key = KEY_DOWN # Клавиша увеличения индекса выбранного ряда +## Виджет "Таблица" -const MAX_INDEX = 99 # Максимальное значение индекса для колонки и строки. Связано с форматом индекса ключа -const INDEX_FORMAT = '%02d_%02d' # Формат индекса ключа -const NODE_PREFIX = 'NODE_' # Префикс ключа ячейки таблицы -const HEAD_PREFIX = 'HEAD_' # Префикс ключа заголовка таблицы -const DATA_PREFIX = 'DATA_' # Префикс ключа данных ячейки таблицы -const CONN_PREFIX = 'CONN_' # Префикс ключа обработчиков событий ячейки таблицы -const SLCT_PREFIX = 'SLCT_' # Префикс ключа индикатора выбранного ряда таблицы +@export var selector_color: = Color(1.0, 1.0, 1.0, 1.0) ## Окрашивающий цвет для индикатора выбранного ряда +@export var node_gap: = Vector2(0.0, 0.0) ## Зазор между ячейками, который не возможно вычислить или получить +@export_file var node_type_file: = 'res://table/node.tscn': get = get_node_scene, set = load_node_scene ## Сцена ячейки устанавливаемая по умолчанию +@export_file var selector_type_file: = 'res://table/selector.tscn': set = load_selector_scene ## Сцена индикатора для выбранного ряда +@export var selector_key_up: Key = KEY_UP ## Клавиша уменьшения индекса выбранного ряда +@export var selector_key_down: Key = KEY_DOWN ## Клавиша увеличения индекса выбранного ряда -const NODE_KEY_FORMAT = NODE_PREFIX + INDEX_FORMAT -const HEAD_KEY_FORMAT = HEAD_PREFIX + INDEX_FORMAT -const DATA_KEY_FORMAT = DATA_PREFIX + INDEX_FORMAT -const CONNECTED_KEY_FORMAT = CONN_PREFIX + INDEX_FORMAT -const ROW_SELECTOR_KEY_FORMAT = SLCT_PREFIX + INDEX_FORMAT +const MAX_INDEX = 99 ## Максимальное значение индекса для колонки и строки. Связано с форматом индекса ключа +const INDEX_FORMAT = '%02d_%02d' ## Формат индекса ключа +const NODE_PREFIX = 'NODE_' ## Префикс ключа ячейки таблицы +const HEAD_PREFIX = 'HEAD_' ## Префикс ключа заголовка таблицы +const DATA_PREFIX = 'DATA_' ## Префикс ключа данных ячейки таблицы +const CONN_PREFIX = 'CONN_' ## Префикс ключа обработчиков событий ячейки таблицы +const SLCT_PREFIX = 'SLCT_' ## Префикс ключа индикатора выбранного ряда таблицы -var nodes: = {} # Все ячейки таблицы и дополнительные элементы -var selector_color_proc: Callable # Ссылка на процедуру генератора цвета индикатора выбранного ряда -var selector_size_proc: Callable # Ссылка на процедуру генератора размера индикатора выбранного ряда -var ScnSelector: PackedScene # Прототип индикатора выбранного ряда -var ScnNode: PackedScene # Прототип ячейки таблицы -var in_focus: = false # Фокус пользовательского ввода -var header: GridContainer # Заголовок таблицы +const NODE_KEY_FORMAT = NODE_PREFIX + INDEX_FORMAT ## Формат ключа ячейки +const HEAD_KEY_FORMAT = HEAD_PREFIX + INDEX_FORMAT ## Формат ключа заголовка +const DATA_KEY_FORMAT = DATA_PREFIX + INDEX_FORMAT ## Формат ключа данных +const CONNECTED_KEY_FORMAT = CONN_PREFIX + INDEX_FORMAT ## Формат ключа подключенных обработчиков сигналов +const ROW_SELECTOR_KEY_FORMAT = SLCT_PREFIX + INDEX_FORMAT ## Формат ключа индикаторов выбранного ряда -signal row_pressed(i_row: int) # Вызывается при нажатии кнопкой мыши на строку -signal selected_changed(i_row: int) # Вызывается при изменении выбранного ряда. i_row - текущий выбранный ряд +var nodes: = {} ## Все ячейки таблицы и дополнительные элементы +var selector_color_proc: Callable ## Ссылка на процедуру генератора цвета индикатора выбранного ряда +var selector_size_proc: Callable ## Ссылка на процедуру генератора размера индикатора выбранного ряда +var ScnSelector: PackedScene ## Прототип индикатора выбранного ряда +var ScnNode: PackedScene ## Прототип ячейки таблицы +var in_focus: = false ## Фокус пользовательского ввода +var header: GridContainer ## Заголовок таблицы + +signal row_pressed(i_row: int) ## Вызывается при нажатии кнопкой мыши на строку +signal selected_changed(i_row: int) ## Вызывается при изменении выбранного ряда. i_row - текущий выбранный ряд var scroll: Control var scroll_adj: = Vector2(0, 0) @@ -40,6 +42,8 @@ func get_node_scene(): return node_type_file func _assert_meta(i_col: int, i_row: int, pname: String, node): assert(node.has_meta(pname), 'ошибка: нет мета-свойства \"%s\" у ячейки колонка:%d ряд:%d' % [pname, i_col, i_row]) +## Закрепляет заголовок таблицы. [param scrl] - Прокрутка, +## [param prnt] - Родитель прокрутки заданный в редакторе func pin_header(scrl: ScrollContainer, prnt: Control): scrl.remove_child(header) prnt.add_child(header) @@ -50,6 +54,7 @@ func pin_header(scrl: ScrollContainer, prnt: Control): scroll_adj = scrl.position +## Перемещает указатель на одну строку вверх func selector_up(): var i_rows: = [] get_selected_rows(i_rows) @@ -66,6 +71,7 @@ func selector_up(): emit_signal('selected_changed', i_row) +## Перемещает указатель на одну строку вниз func selector_down(): var i_rows: = [] get_selected_rows(i_rows) @@ -81,6 +87,7 @@ func selector_down(): emit_signal('selected_changed', i_row) +## func set_columns_alignments(alignments): assert(columns == alignments.size()) var rows_count: = get_rows_count() @@ -89,16 +96,19 @@ func set_columns_alignments(alignments): set_node_alligment(i_col, i_row, alignments[i_col]) +## func load_selector_scene(file_name: String): selector_type_file = file_name ScnSelector = load(file_name) +## func load_node_scene(file_name: String): node_type_file = file_name ScnNode = load(file_name) +## func _ready(): ScnSelector = load(selector_type_file) ScnNode = load(node_type_file) @@ -106,19 +116,20 @@ func _ready(): assert(ScnNode) +## Выравнивает по нижнему левому углу. Используется для выравнивания по заголовку func align_to_left_bottompos(hdr: Control, gap: = Vector2(0, 0)): - """ Выравнивает по нижнему левому углу. - Используется для выравнивания по заголовку """ position.x = hdr.position.x + gap.x position.y = hdr.position.y + hdr.size.y + gap.y +## [param i_col] - индекс колонки. [param i_row] - индекс ряда. func set_node_meta(i_col: int, i_row: int, pname: String, val) -> void: var key: = get_node_key(NODE_KEY_FORMAT, i_col, i_row) var node = nodes[key] node.set_meta(pname, val) +## [param i_col] - индекс колонки. [param i_row] - индекс ряда. func get_node_meta(i_col: int, i_row: int, pname: String): var key: = get_node_key(NODE_KEY_FORMAT, i_col, i_row) var node = nodes[key] @@ -126,30 +137,35 @@ func get_node_meta(i_col: int, i_row: int, pname: String): return node.get_meta(pname) +## [param i_col] - индекс колонки. [param i_row] - индекс ряда. func set_node_property(i_col: int, i_row: int, pname: String, val) -> void: var key: = get_node_key(NODE_KEY_FORMAT, i_col, i_row) var node = nodes[key] node.set(pname, val) +## [param i_col] - индекс колонки. [param i_row] - индекс ряда. func get_node_property(i_col: int, i_row: int, pname: String): var key: = get_node_key(NODE_KEY_FORMAT, i_col, i_row) var node = nodes[key] return node.get(pname) +## [param i_col] - индекс колонки. [param i_row] - индекс ряда func get_node_key(format: String, i_col: int, i_row: int) -> String: var key: String = format % [i_row, i_col] assert(nodes.has(key), 'ошибка: нет такой ячейки - колонка:%d ряд:%d' % [i_col, i_row]) return key +## func get_key_indexes(key: String) -> Array: var tokens: = key.split('_') assert(tokens.size() == 3, 'ошибка: неверный ключ: \"%s\"' % key) return [int(tokens[2]), int(tokens[1])] +## func set_columns_min_size(sizes: Array) -> void: var rows_count: = get_rows_count() for i_row in rows_count: @@ -157,6 +173,7 @@ func set_columns_min_size(sizes: Array) -> void: set_nodes_min_size(0, sizes, HEAD_KEY_FORMAT) +## func set_columns_aligment(alignments: Array) -> void: var rows_count: = get_rows_count() for i_row in rows_count: @@ -164,6 +181,7 @@ func set_columns_aligment(alignments: Array) -> void: set_node_alligment(i_col, i_row, alignments[i_col]) +## func _input(event) -> void: if event is InputEventKey: if in_focus and event.pressed: @@ -184,6 +202,7 @@ func _input(event) -> void: emit_signal('focus_exited') +## func _init() -> void: selector_color_proc = Callable(self, 'defaultselector_color_proc') assert(selector_color_proc.is_valid()) @@ -192,6 +211,7 @@ func _init() -> void: scroll = self +## func check_event_pos(event_pos: Vector2, obj: Control): return \ (event_pos.x > obj.position.x) \ @@ -200,20 +220,24 @@ func check_event_pos(event_pos: Vector2, obj: Control): and (event_pos.y < (obj.position.y + obj.size.y)) +## func defaultselector_color_proc(_i_row: int): return selector_color +## func setselector_color_proc(instance: Object, function: String) -> void: selector_color_proc = Callable(instance, function) assert(selector_color_proc.is_valid()) +## func set_selector_size_proc(instance: Object, function: String) -> void: selector_size_proc = Callable(instance, function) assert(selector_size_proc.is_valid()) +## [param i_row] - индекс ряда func default_selector_size_proc(i_row: int, rect: Array) -> void: get_row_rect(i_row, rect) rect[0] += position.x - node_gap.x / 2.0 @@ -222,12 +246,14 @@ func default_selector_size_proc(i_row: int, rect: Array) -> void: rect[3] += node_gap.y +## func clear_rows_selected(): var rows_count: = get_rows_count() for i_row in rows_count: set_row_selected(i_row, false) +## [param i_row] - индекс ряда. func set_row_selected(i_row: int, selected: bool = true) -> void: var key: = ROW_SELECTOR_KEY_FORMAT % [i_row, 0] var node = nodes[NODE_KEY_FORMAT % [i_row, 0]] @@ -248,11 +274,13 @@ func set_row_selected(i_row: int, selected: bool = true) -> void: node.add_child(selector) +## [param i_row] - индекс ряда. func is_row_selected(i_row: int) -> bool: var key: = ROW_SELECTOR_KEY_FORMAT % [i_row, 0] return nodes.has(key) +## [param i_row] - индексы рядов. func get_selected_rows(i_rows: Array) -> void: for key in nodes.keys(): if SLCT_PREFIX in key: @@ -260,6 +288,7 @@ func get_selected_rows(i_rows: Array) -> void: i_rows.append(indexes[1]) +## Возвращает количество рядов func get_rows_count() -> int: var rows_count: int = 0 for key in nodes: @@ -267,16 +296,19 @@ func get_rows_count() -> int: return rows_count / columns +## func get_node2(i_col: int, i_row: int) -> Node: var key: = get_node_key(NODE_KEY_FORMAT, i_col, i_row) return nodes[key] -func set_node_user_data(i_col: int, i_row: int, user_data: Object) -> void: +## [param i_row] - индекс ряда. +func set_node_user_data(i_col: int, i_row: int, user_data) -> void: var key: = DATA_KEY_FORMAT % [i_row, i_col] nodes[key] = user_data +## func add_row(row_types: Array) -> void: assert(row_types.size() < MAX_INDEX, 'ошибка: слишком много колонок, больше %d' % (MAX_INDEX + 1)) if columns == 1: @@ -299,17 +331,19 @@ func add_row(row_types: Array) -> void: set_node_meta(i_col, i_row, 'callable_focus_entered', conn) +## func _on_focus_entered(node): var indexes = get_key_indexes(node.name) emit_signal('row_pressed', indexes[1]) +## func set_header(header_types: Array): - assert(header_types.size() < MAX_INDEX, 'ошибка: слишком много колонок, больше %d' % (MAX_INDEX + 1)) + assert(header_types.size() < MAX_INDEX, 'ошибка: количество колонок в заголовке: %d больше допустимого: %d' % [header_types.size(), MAX_INDEX + 1]) if columns == 1: set_columns(header_types.size()) else: - assert(columns == header_types.size()) + assert(columns == header_types.size(), 'ошибка: количество колонок в заголовке %d, но ранее установлено: %d' % [header_types.size(), columns]) var do_adj: = false if not header: header = GridContainer.new() @@ -337,16 +371,19 @@ func set_header(header_types: Array): position.y += rect[3] +## func set_header_text(headers: Array): assert(columns == headers.size()) set_row_text(0, headers, 0, HEAD_KEY_FORMAT) -func get_node_user_data(i_col: int, i_row: int) -> Object: +## +func get_node_user_data(i_col: int, i_row: int): var key: = get_node_key(DATA_KEY_FORMAT, i_col, i_row) return nodes[key] +## func remove_row(i_row: int): var sel_key: String = ROW_SELECTOR_KEY_FORMAT % [i_row, 0] @@ -381,6 +418,7 @@ func remove_row(i_row: int): rehash() +## func next_index(indexes: Array) -> void: indexes[0].x += 1 if indexes[0].x == columns: @@ -388,6 +426,7 @@ func next_index(indexes: Array) -> void: indexes[0].y += 1 +## func swap_nodes(nodes_copy, node_key_format, i0, i1) -> void: var key0 = node_key_format % [i0.y, i0.x] var key1 = node_key_format % [i1.y, i1.x] @@ -395,6 +434,7 @@ func swap_nodes(nodes_copy, node_key_format, i0, i1) -> void: nodes_copy[key1].name = key1 +## Переназначает ключи в соответствии с размерами таблицы. func rehash(): var i_node: = [Vector2i()] var i_hdr: = [Vector2i()] @@ -424,20 +464,21 @@ func rehash(): nodes.merge(nodes_copy) +## Удаляет все строки таблицы func clear_rows() -> void: - """ Удаляет все строки таблицы """ var rows_count: int = get_rows_count() + print_debug(rows_count) for i_row in rows_count: remove_row(i_row) +## Настраевает обратные вызовы для колонок. +## [param dest_node] - Получатель события[br] +## [param event_name] - Имя события[br] +## [param callback] - Имя функции получателя события[br] +## [param clmns] - Индексы колонок[br] +## [param user_data] - Аргументы функции получателя события[br] func connect_columns(dest_node: Node, event_name: String, callback: String, clmns: Array, user_data: Array) -> void: - """ Настраивает обратные вызовы для колонок. - :dest_node: Получатель события - :event_name: Имя события - :callback: Имя функции получателя события - :clmns: Индексы колонок - :user_data: Аргументы функции получателя события """ var rows_count = get_rows_count() for i_row in rows_count: for i_col in clmns: @@ -454,6 +495,7 @@ func connect_columns(dest_node: Node, event_name: String, callback: String, clmn nodes[conn_key] = [callback, dest_node] +## func set_rows_text(rows: Array) -> void: for i_row in rows.size(): for i_col in columns: @@ -462,6 +504,7 @@ func set_rows_text(rows: Array) -> void: node.text = rows[i_row][i_col] +## func set_nodes_min_size(i_row: int, sizes: Array, key_format: String = NODE_KEY_FORMAT) -> void: for i_col in columns: var key: = get_node_key(key_format, i_col, i_row) @@ -470,11 +513,13 @@ func set_nodes_min_size(i_row: int, sizes: Array, key_format: String = NODE_KEY_ node.size.x = sizes[i_col] +## func set_node_text(i_col: int, i_row: int, val: String) -> void: var key: = get_node_key(NODE_KEY_FORMAT, i_col, i_row) nodes[key].text = val +## func set_rows_state(rows: Array) -> void: for i_row in rows.size(): for i_col in columns: @@ -482,11 +527,13 @@ func set_rows_state(rows: Array) -> void: nodes[key].button_pressed = rows[i_row][i_col] +## func set_node_state(i_col: int, i_row: int, val: bool) -> void: var key: = get_node_key(NODE_KEY_FORMAT, i_col, i_row) nodes[key].button_pressed = val +## [param i_col] - индекс колонки. [param i_row] - индекс ряда. func set_node_frame(i_col: int, i_row: int, node_name: String, val: int) -> void: var key: = get_node_key(NODE_KEY_FORMAT, i_col, i_row) var node = nodes[key] @@ -494,11 +541,13 @@ func set_node_frame(i_col: int, i_row: int, node_name: String, val: int) -> void sprite.frame = val +## [param i_col] - индекс колонки. [param i_row] - индекс ряда. func set_node_editable(i_col: int, i_row: int, val: bool) -> void: var key: = get_node_key(NODE_KEY_FORMAT, i_col, i_row) nodes[key].editable = val +## [param i_col] - индекс колонки. [param i_row] - индекс ряда. func set_node_alligment(i_col: int, i_row: int, val: int) -> void: var key: = get_node_key(NODE_KEY_FORMAT, i_col, i_row) if 'horizontal_alignment' in nodes[key]: @@ -507,12 +556,14 @@ func set_node_alligment(i_col: int, i_row: int, val: int) -> void: nodes[key].alignment = val +## [param i_row] - индекс ряда. func set_row_alligments(i_row: int, aligns: Array) -> void: for i_col in columns: var key: = get_node_key(NODE_KEY_FORMAT, i_col, i_row) nodes[key].align = aligns[i_col] +## [param i_row] - индекс ряда. func get_row_text(i_row: int) -> Array: var row: = [] for i_col in columns: @@ -521,6 +572,7 @@ func get_row_text(i_row: int) -> Array: return row +## func set_row_text(i_row: int, row: Array, i_begin: int = 0, key_format: String = NODE_KEY_FORMAT) -> void: assert(i_begin >= 0) assert((columns - i_begin) <= row.size()) @@ -529,6 +581,7 @@ func set_row_text(i_row: int, row: Array, i_begin: int = 0, key_format: String = nodes[key].text = row[i_col] +## Возвращает все строки таблицы в двумерном массиве func get_rows_text() -> Array: var rows_count: = get_rows_count() var rows: = [] @@ -538,6 +591,7 @@ func get_rows_text() -> Array: return rows +## Возвращает массив ячеек из ряда [param i_row] func get_row(i_row: int) -> Array: var row: = [] for i_col in columns: @@ -546,6 +600,8 @@ func get_row(i_row: int) -> Array: return row +## Возвращает прямоугольник [param rect] занимаемый ячейкой в ряду [param i_row] и колонке [param i_col]. +## [param key_format] - Формат ключа ячейки func get_node_rect(i_col: int, i_row: int, rect: Array, key_format: String = NODE_KEY_FORMAT) -> void: assert(rect.size() >= 4, 'ошибка: мало элементов для возврата результата') var key: = get_node_key(key_format, i_col, i_row) @@ -556,6 +612,7 @@ func get_node_rect(i_col: int, i_row: int, rect: Array, key_format: String = NOD rect[3] = cell.size.y +## Возвращает прямоугольник [param rect] занимаемый рядом [param i_row]. [param key_format] - Формат ключа ячейки func get_row_rect(i_row: int, rect: Array, key_format: String = NODE_KEY_FORMAT) -> void: assert(rect.size() >= 4, 'ошибка: мало элементов для возврата результата') var cell0 = nodes[get_node_key(key_format, 0, i_row)]