Добавление таблицы в настройках
This commit is contained in:
714
table/table.gd
714
table/table.gd
@@ -57,94 +57,94 @@ func defaultselector_color_proc(_i_row: int): return selector_color
|
||||
## [param scrl] - Прокрутка родитель таблицы.[br]
|
||||
## [param prnt] - Родитель прокрутки.[br]
|
||||
func pin_header(scrl: ScrollContainer, prnt: Control):
|
||||
scrl.remove_child(header)
|
||||
prnt.add_child(header)
|
||||
var v_separation = get_theme_constant('v_separation')
|
||||
header.position = scrl.position - Vector2(0, header.size.y + v_separation)
|
||||
scroll = scrl
|
||||
scroll_adj = scrl.position
|
||||
scrl.remove_child(header)
|
||||
prnt.add_child(header)
|
||||
var v_separation = get_theme_constant('v_separation')
|
||||
header.position = scrl.position - Vector2(0, header.size.y + v_separation)
|
||||
scroll = scrl
|
||||
scroll_adj = scrl.position
|
||||
|
||||
|
||||
## Перемещает указатель на одну строку вверх
|
||||
func selector_up():
|
||||
var i_rows: = []
|
||||
get_selected_rows(i_rows)
|
||||
for i in i_rows:
|
||||
set_row_selected(i, false)
|
||||
var rows_count: = get_rows_count()
|
||||
if not (i_rows.size() and (rows_count > 1)):
|
||||
return
|
||||
var i_row = i_rows[0]
|
||||
i_row -= 1
|
||||
if i_row < 0:
|
||||
i_row = rows_count - 1
|
||||
set_row_selected(i_row, true)
|
||||
var node = get_node2(0, i_row)
|
||||
if scroll is ScrollContainer:
|
||||
scroll.ensure_control_visible(node)
|
||||
emit_signal('selected_changed', i_row)
|
||||
var i_rows: = []
|
||||
get_selected_rows(i_rows)
|
||||
for i in i_rows:
|
||||
set_row_selected(i, false)
|
||||
var rows_count: = get_rows_count()
|
||||
if not (i_rows.size() and (rows_count > 1)):
|
||||
return
|
||||
var i_row = i_rows[0]
|
||||
i_row -= 1
|
||||
if i_row < 0:
|
||||
i_row = rows_count - 1
|
||||
set_row_selected(i_row, true)
|
||||
var node = get_node2(0, i_row)
|
||||
if scroll is ScrollContainer:
|
||||
scroll.ensure_control_visible(node)
|
||||
emit_signal('selected_changed', i_row)
|
||||
|
||||
|
||||
## Перемещает указатель на одну строку вниз
|
||||
func selector_down():
|
||||
var i_rows: = []
|
||||
get_selected_rows(i_rows)
|
||||
for i in i_rows:
|
||||
set_row_selected(i, false)
|
||||
var rows_count: = get_rows_count()
|
||||
if not (i_rows.size() and (rows_count > 1)):
|
||||
return
|
||||
var i_row = i_rows[0]
|
||||
i_row += 1
|
||||
i_row %= rows_count
|
||||
set_row_selected(i_row, true)
|
||||
var node = get_node2(0, i_row)
|
||||
if scroll is ScrollContainer:
|
||||
scroll.ensure_control_visible(node)
|
||||
emit_signal('selected_changed', i_row)
|
||||
var i_rows: = []
|
||||
get_selected_rows(i_rows)
|
||||
for i in i_rows:
|
||||
set_row_selected(i, false)
|
||||
var rows_count: = get_rows_count()
|
||||
if not (i_rows.size() and (rows_count > 1)):
|
||||
return
|
||||
var i_row = i_rows[0]
|
||||
i_row += 1
|
||||
i_row %= rows_count
|
||||
set_row_selected(i_row, true)
|
||||
var node = get_node2(0, i_row)
|
||||
if scroll is ScrollContainer:
|
||||
scroll.ensure_control_visible(node)
|
||||
emit_signal('selected_changed', i_row)
|
||||
|
||||
|
||||
## Делает ряд [param i_row] видимым.
|
||||
func ensure_row_visible(i_row: int):
|
||||
assert(scroll is ScrollContainer, 'Таблица должна быть дочерней к ScrollContainer')
|
||||
var key: = get_node_key(NODE_KEY_FORMAT, 0, i_row)
|
||||
var node = nodes[key]
|
||||
scroll.ensure_control_visible(node)
|
||||
assert(scroll is ScrollContainer, 'Таблица должна быть дочерней к ScrollContainer')
|
||||
var key: = get_node_key(NODE_KEY_FORMAT, 0, i_row)
|
||||
var node = nodes[key]
|
||||
scroll.ensure_control_visible(node)
|
||||
|
||||
|
||||
## Устанавливает выравнивание из массива [param alignments] для всех колонок.
|
||||
func set_columns_alignments(alignments: Array):
|
||||
assert(columns == alignments.size())
|
||||
var rows_count: = get_rows_count()
|
||||
for i_row in rows_count:
|
||||
for i_col in alignments.size():
|
||||
set_node_alligment(i_col, i_row, alignments[i_col])
|
||||
assert(columns == alignments.size())
|
||||
var rows_count: = get_rows_count()
|
||||
for i_row in rows_count:
|
||||
for i_col in alignments.size():
|
||||
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)
|
||||
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)
|
||||
node_type_file = file_name
|
||||
ScnNode = load(file_name)
|
||||
|
||||
|
||||
##
|
||||
func _ready():
|
||||
ScnSelector = load(selector_type_file)
|
||||
ScnNode = load(node_type_file)
|
||||
assert(ScnSelector is PackedScene)
|
||||
assert(ScnNode is PackedScene)
|
||||
ScnSelector = load(selector_type_file)
|
||||
ScnNode = load(node_type_file)
|
||||
assert(ScnSelector is PackedScene)
|
||||
assert(ScnNode is PackedScene)
|
||||
|
||||
|
||||
## Выравнивает по нижнему левому углу. Используется для выравнивания по заголовку.
|
||||
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
|
||||
position.x = hdr.position.x + gap.x
|
||||
position.y = hdr.position.y + hdr.size.y + gap.y
|
||||
|
||||
|
||||
## Устанавливает пользовательские данные для ячейки.[br]
|
||||
@@ -153,9 +153,9 @@ func align_to_left_bottompos(hdr: Control, gap: = Vector2(0, 0)):
|
||||
## [param pname] - Имя пользовательских данных.[br]
|
||||
## [param val] - Значение пользовательских данных.[br]
|
||||
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)
|
||||
var key: = get_node_key(NODE_KEY_FORMAT, i_col, i_row)
|
||||
var node = nodes[key]
|
||||
node.set_meta(pname, val)
|
||||
|
||||
|
||||
## Возвращает пользовательские данные для ячейки.[br]
|
||||
@@ -163,10 +163,10 @@ func set_node_meta(i_col: int, i_row: int, pname: String, val) -> void:
|
||||
## [param i_row] - Индекс ряда.[br]
|
||||
## [param pname] - Имя пользовательских данных.[br]
|
||||
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]
|
||||
assert_meta(i_col, i_row, pname, node)
|
||||
return node.get_meta(pname)
|
||||
var key: = get_node_key(NODE_KEY_FORMAT, i_col, i_row)
|
||||
var node = nodes[key]
|
||||
assert_meta(i_col, i_row, pname, node)
|
||||
return node.get_meta(pname)
|
||||
|
||||
|
||||
## Устанавливает свойство ячейки.[br]
|
||||
@@ -176,9 +176,9 @@ func get_node_meta(i_col: int, i_row: int, pname: String):
|
||||
## [param val] - Значение свойства.[br]
|
||||
## [i]Свойство[/i] [param pname] [i]ячейки должно существовать.[/i]
|
||||
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)
|
||||
var key: = get_node_key(NODE_KEY_FORMAT, i_col, i_row)
|
||||
var node = nodes[key]
|
||||
node.set(pname, val)
|
||||
|
||||
|
||||
## Возвращает значение поля ячейки.[br]
|
||||
@@ -186,9 +186,9 @@ func set_node_property(i_col: int, i_row: int, pname: String, val) -> void:
|
||||
## [param i_col] - Индекс колонки.[br]
|
||||
## [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)
|
||||
var key: = get_node_key(NODE_KEY_FORMAT, i_col, i_row)
|
||||
var node = nodes[key]
|
||||
return node.get(pname)
|
||||
|
||||
|
||||
## Возвращает ключ для существующей ячейки. Если ячейки с заданными индексами нет,
|
||||
@@ -196,313 +196,313 @@ func get_node_property(i_col: int, i_row: int, pname: String):
|
||||
## [param i_col] - Индекс колонки.[br]
|
||||
## [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
|
||||
var key: String = format % [i_row, i_col]
|
||||
assert(nodes.has(key), 'ошибка: нет такой ячейки - колонка:%d ряд:%d' % [i_col, i_row])
|
||||
return key
|
||||
|
||||
|
||||
## Возвращает массив с индексом ячейки:[br]
|
||||
## [b][0][/b] - индекс колонки,[br]
|
||||
## [b][1][/b] - индекс строки.
|
||||
func get_key_indexes(key: String) -> Array:
|
||||
var tokens: = key.split('_')
|
||||
assert(tokens.size() == 3, 'ошибка: неверный ключ: \"%s\"' % key)
|
||||
return [int(tokens[2]), int(tokens[1])]
|
||||
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:
|
||||
assert((columns == 1) or (columns == sizes.size()))
|
||||
columns = sizes.size()
|
||||
var rows_count: = get_rows_count()
|
||||
columns_min_size.clear()
|
||||
for sz in sizes:
|
||||
columns_min_size.append(sz)
|
||||
for i_row in rows_count:
|
||||
set_nodes_min_size(i_row, sizes, NODE_KEY_FORMAT)
|
||||
if nodes.has(HEAD_KEY_FORMAT % [0, 0]):
|
||||
set_nodes_min_size(0, sizes, HEAD_KEY_FORMAT)
|
||||
assert((columns == 1) or (columns == sizes.size()))
|
||||
columns = sizes.size()
|
||||
var rows_count: = get_rows_count()
|
||||
columns_min_size.clear()
|
||||
for sz in sizes:
|
||||
columns_min_size.append(sz)
|
||||
for i_row in rows_count:
|
||||
set_nodes_min_size(i_row, sizes, NODE_KEY_FORMAT)
|
||||
if nodes.has(HEAD_KEY_FORMAT % [0, 0]):
|
||||
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:
|
||||
for i_col in alignments.size():
|
||||
set_node_alligment(i_col, i_row, alignments[i_col])
|
||||
var rows_count: = get_rows_count()
|
||||
for i_row in rows_count:
|
||||
for i_col in alignments.size():
|
||||
set_node_alligment(i_col, i_row, alignments[i_col])
|
||||
|
||||
|
||||
##
|
||||
func _input(event) -> void:
|
||||
if not is_visible_in_tree(): return
|
||||
if event is InputEventKey:
|
||||
if event.pressed and in_focus:
|
||||
if event.keycode == selector_key_up:
|
||||
selector_up()
|
||||
elif event.keycode == selector_key_down:
|
||||
selector_down()
|
||||
elif event is InputEventMouseButton:
|
||||
if not event.pressed:
|
||||
return
|
||||
if check_event_pos(event.position, scroll):
|
||||
if not in_focus:
|
||||
in_focus = true
|
||||
emit_signal('focus_entered')
|
||||
elif not check_event_pos(event.position, scroll):
|
||||
if in_focus:
|
||||
in_focus = false
|
||||
emit_signal('focus_exited')
|
||||
if not is_visible_in_tree(): return
|
||||
if event is InputEventKey:
|
||||
if event.pressed and in_focus:
|
||||
if event.keycode == selector_key_up:
|
||||
selector_up()
|
||||
elif event.keycode == selector_key_down:
|
||||
selector_down()
|
||||
elif event is InputEventMouseButton:
|
||||
if not event.pressed:
|
||||
return
|
||||
if check_event_pos(event.position, scroll):
|
||||
if not in_focus:
|
||||
in_focus = true
|
||||
emit_signal('focus_entered')
|
||||
elif not check_event_pos(event.position, scroll):
|
||||
if in_focus:
|
||||
in_focus = false
|
||||
emit_signal('focus_exited')
|
||||
|
||||
|
||||
##
|
||||
func _init() -> void:
|
||||
selector_color_proc = Callable(self, 'defaultselector_color_proc')
|
||||
assert(selector_color_proc.is_valid())
|
||||
selector_size_proc = Callable(self, 'default_selector_size_proc')
|
||||
assert(selector_size_proc.is_valid())
|
||||
scroll = self
|
||||
selector_color_proc = Callable(self, 'defaultselector_color_proc')
|
||||
assert(selector_color_proc.is_valid())
|
||||
selector_size_proc = Callable(self, 'default_selector_size_proc')
|
||||
assert(selector_size_proc.is_valid())
|
||||
scroll = self
|
||||
|
||||
|
||||
##
|
||||
func check_event_pos(event_pos: Vector2, obj: Control):
|
||||
return \
|
||||
(event_pos.x > obj.position.x) \
|
||||
and (event_pos.x < (obj.position.x + obj.size.x)) \
|
||||
and (event_pos.y > obj.position.y) \
|
||||
and (event_pos.y < (obj.position.y + obj.size.y))
|
||||
return \
|
||||
(event_pos.x > obj.position.x) \
|
||||
and (event_pos.x < (obj.position.x + obj.size.x)) \
|
||||
and (event_pos.y > obj.position.y) \
|
||||
and (event_pos.y < (obj.position.y + obj.size.y))
|
||||
|
||||
|
||||
##
|
||||
func setselector_color_proc(instance: Object, function: String) -> void:
|
||||
selector_color_proc = Callable(instance, function)
|
||||
assert(selector_color_proc.is_valid())
|
||||
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())
|
||||
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
|
||||
rect[1] += position.y - node_gap.y / 2.0
|
||||
rect[2] += node_gap.x
|
||||
rect[3] += node_gap.y
|
||||
get_row_rect(i_row, rect)
|
||||
rect[0] += position.x - node_gap.x / 2.0
|
||||
rect[1] += position.y - node_gap.y / 2.0
|
||||
rect[2] += node_gap.x
|
||||
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)
|
||||
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:
|
||||
call_deferred('_set_row_selected', i_row, selected)
|
||||
call_deferred('_set_row_selected', i_row, selected)
|
||||
|
||||
|
||||
## [param i_row] - Индекс ряда.
|
||||
func _set_row_selected(i_row: int, selected: bool = true) -> void:
|
||||
var selector_key: = SELECTOR_KEY_FORMAT % [i_row, 0]
|
||||
var node_key: = NODE_KEY_FORMAT % [i_row, 0]
|
||||
if not nodes.has(node_key):
|
||||
push_error('ошибка: нет такого ряда: %d' % i_row)
|
||||
return
|
||||
if nodes.has(selector_key) and (not selected):
|
||||
var node = nodes[node_key]
|
||||
var selector = nodes[selector_key]
|
||||
node.remove_child(selector)
|
||||
selector.queue_free()
|
||||
nodes.erase(selector_key)
|
||||
elif (not nodes.has(selector_key)) and selected:
|
||||
var selector = ScnSelector.instantiate()
|
||||
var rect: = [0, 0, 0, 0]
|
||||
selector_size_proc.call(i_row, rect)
|
||||
selector.size.x = rect[2]
|
||||
selector.size.y = rect[3]
|
||||
selector.modulate = selector_color_proc.call(i_row)
|
||||
selector.z_index = z_index + 1
|
||||
nodes[selector_key] = selector
|
||||
var node = nodes[node_key]
|
||||
node.add_child(selector)
|
||||
var selector_key: = SELECTOR_KEY_FORMAT % [i_row, 0]
|
||||
var node_key: = NODE_KEY_FORMAT % [i_row, 0]
|
||||
if not nodes.has(node_key):
|
||||
push_error('ошибка: нет такого ряда: %d' % i_row)
|
||||
return
|
||||
if nodes.has(selector_key) and (not selected):
|
||||
var node = nodes[node_key]
|
||||
var selector = nodes[selector_key]
|
||||
node.remove_child(selector)
|
||||
selector.queue_free()
|
||||
nodes.erase(selector_key)
|
||||
elif (not nodes.has(selector_key)) and selected:
|
||||
var selector = ScnSelector.instantiate()
|
||||
var rect: = [0, 0, 0, 0]
|
||||
selector_size_proc.call(i_row, rect)
|
||||
selector.size.x = rect[2]
|
||||
selector.size.y = rect[3]
|
||||
selector.modulate = selector_color_proc.call(i_row)
|
||||
selector.z_index = z_index + 1
|
||||
nodes[selector_key] = selector
|
||||
var node = nodes[node_key]
|
||||
node.add_child(selector)
|
||||
|
||||
|
||||
## [param i_row] - Индекс ряда.
|
||||
func is_row_selected(i_row: int) -> bool:
|
||||
var key: = SELECTOR_KEY_FORMAT % [i_row, 0]
|
||||
return nodes.has(key)
|
||||
var key: = 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:
|
||||
var indexes = get_key_indexes(key)
|
||||
i_rows.append(indexes[1])
|
||||
for key in nodes.keys():
|
||||
if SLCT_PREFIX in key:
|
||||
var indexes = get_key_indexes(key)
|
||||
i_rows.append(indexes[1])
|
||||
|
||||
|
||||
## Возвращает количество рядов
|
||||
func get_rows_count() -> int:
|
||||
var nodes_count: int = 0
|
||||
for key in nodes:
|
||||
nodes_count += int(NODE_PREFIX in key)
|
||||
return nodes_count / columns
|
||||
var nodes_count: int = 0
|
||||
for key in nodes:
|
||||
nodes_count += int(NODE_PREFIX in key)
|
||||
return nodes_count / columns
|
||||
|
||||
|
||||
## [param i_col] - Индекс колонки. [param i_row] - Индекс ряда.
|
||||
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]
|
||||
var key: = get_node_key(NODE_KEY_FORMAT, i_col, i_row)
|
||||
return nodes[key]
|
||||
|
||||
|
||||
## Добавляет ряд. [param row_types] - Массив типов ячеек ряда
|
||||
func add_row(row_types: Array) -> void:
|
||||
assert(row_types.size() < MAX_INDEX, 'ошибка: слишком много колонок, больше %d' % (MAX_INDEX + 1))
|
||||
if columns == 1:
|
||||
set_columns(row_types.size())
|
||||
else:
|
||||
assert(columns == row_types.size(), 'ошибка: %s количество колонок установлено ранее - %d, но требуется %d' % [self, columns, row_types.size()])
|
||||
var i_row: int = get_rows_count()
|
||||
assert(i_row < MAX_INDEX, 'ошибка: слишком много рядов, больше %d' % (MAX_INDEX + 1))
|
||||
var allow_set_size = columns_min_size.size() >= row_types.size()
|
||||
for i_col in columns:
|
||||
var node_type = row_types[i_col]
|
||||
var node = node_type.instantiate()
|
||||
assert(node.name == node.name, 'ошибка: экземпляр не имеет поля \"name\"')
|
||||
var node_key: String = NODE_KEY_FORMAT % [i_row, i_col]
|
||||
node.name = node_key
|
||||
add_child(node)
|
||||
if allow_set_size:
|
||||
node.custom_minimum_size.x = columns_min_size[i_col]
|
||||
node.set_deferred('size.x', columns_min_size[i_col])
|
||||
nodes[node_key] = node
|
||||
var conn = Callable(self, '_on_focus_entered').bind(node)
|
||||
node.connect('focus_entered', conn)
|
||||
set_node_meta(i_col, i_row, 'callable_focus_entered', conn)
|
||||
assert(row_types.size() < MAX_INDEX, 'ошибка: слишком много колонок, больше %d' % (MAX_INDEX + 1))
|
||||
if columns == 1:
|
||||
set_columns(row_types.size())
|
||||
else:
|
||||
assert(columns == row_types.size(), 'ошибка: %s количество колонок установлено ранее - %d, но требуется %d' % [self, columns, row_types.size()])
|
||||
var i_row: int = get_rows_count()
|
||||
assert(i_row < MAX_INDEX, 'ошибка: слишком много рядов, больше %d' % (MAX_INDEX + 1))
|
||||
var allow_set_size = columns_min_size.size() >= row_types.size()
|
||||
for i_col in columns:
|
||||
var node_type = row_types[i_col]
|
||||
var node = node_type.instantiate()
|
||||
assert(node.name == node.name, 'ошибка: экземпляр не имеет поля \"name\"')
|
||||
var node_key: String = NODE_KEY_FORMAT % [i_row, i_col]
|
||||
node.name = node_key
|
||||
add_child(node)
|
||||
if allow_set_size:
|
||||
node.custom_minimum_size.x = columns_min_size[i_col]
|
||||
node.set_deferred('size.x', columns_min_size[i_col])
|
||||
nodes[node_key] = node
|
||||
var conn = Callable(self, '_on_focus_entered').bind(node)
|
||||
node.connect('focus_entered', conn)
|
||||
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])
|
||||
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 больше допустимого: %d' % [header_types.size(), MAX_INDEX + 1])
|
||||
if columns == 1:
|
||||
set_columns(header_types.size())
|
||||
else:
|
||||
assert(columns == header_types.size(), 'ошибка: количество колонок в заголовке %d, но ранее установлено: %d' % [header_types.size(), columns])
|
||||
var do_adj: = false
|
||||
if not header:
|
||||
header = GridContainer.new()
|
||||
var parent = scroll.get_parent()
|
||||
parent.add_child(header)
|
||||
header.position = position
|
||||
header.columns = header_types.size()
|
||||
do_adj = true
|
||||
else:
|
||||
var childrens = header.get_children()
|
||||
for node in childrens:
|
||||
childrens.erase(node.name)
|
||||
childrens.remove_child(node)
|
||||
node.queue_free()
|
||||
for i_col in columns:
|
||||
var node = header_types[i_col].instantiate()
|
||||
var key: String = HEAD_KEY_FORMAT % [0, i_col]
|
||||
node.name = key
|
||||
nodes[key] = node
|
||||
header.add_child(node)
|
||||
if do_adj:
|
||||
var rect = [0, 0, 0, 0]
|
||||
get_node_rect(0, 0, rect, HEAD_KEY_FORMAT)
|
||||
position.y += rect[3]
|
||||
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(), 'ошибка: количество колонок в заголовке %d, но ранее установлено: %d' % [header_types.size(), columns])
|
||||
var do_adj: = false
|
||||
if not header:
|
||||
header = GridContainer.new()
|
||||
var parent = scroll.get_parent()
|
||||
parent.add_child(header)
|
||||
header.position = position
|
||||
header.columns = header_types.size()
|
||||
do_adj = true
|
||||
else:
|
||||
var childrens = header.get_children()
|
||||
for node in childrens:
|
||||
childrens.erase(node.name)
|
||||
childrens.remove_child(node)
|
||||
node.queue_free()
|
||||
for i_col in columns:
|
||||
var node = header_types[i_col].instantiate()
|
||||
var key: String = HEAD_KEY_FORMAT % [0, i_col]
|
||||
node.name = key
|
||||
nodes[key] = node
|
||||
header.add_child(node)
|
||||
if do_adj:
|
||||
var rect = [0, 0, 0, 0]
|
||||
get_node_rect(0, 0, rect, HEAD_KEY_FORMAT)
|
||||
position.y += rect[3]
|
||||
|
||||
|
||||
##
|
||||
func set_header_text(headers: Array):
|
||||
assert(columns == headers.size())
|
||||
set_row_text(0, headers, 0, HEAD_KEY_FORMAT)
|
||||
assert(columns == headers.size())
|
||||
set_row_text(0, headers, 0, HEAD_KEY_FORMAT)
|
||||
|
||||
|
||||
## [param i_row] - индекс ряда.
|
||||
func remove_row(i_row: int):
|
||||
var sel_key: String = SELECTOR_KEY_FORMAT % [i_row, 0]
|
||||
var sel_key: String = SELECTOR_KEY_FORMAT % [i_row, 0]
|
||||
|
||||
if nodes.has(sel_key):
|
||||
var selector = nodes[sel_key]
|
||||
var prnt = selector.get_parent()
|
||||
prnt.remove_child(selector)
|
||||
selector.queue_free()
|
||||
nodes.erase(sel_key)
|
||||
if nodes.has(sel_key):
|
||||
var selector = nodes[sel_key]
|
||||
var prnt = selector.get_parent()
|
||||
prnt.remove_child(selector)
|
||||
selector.queue_free()
|
||||
nodes.erase(sel_key)
|
||||
|
||||
for i_col in columns:
|
||||
for i_col in columns:
|
||||
|
||||
var node_key: String = NODE_KEY_FORMAT % [i_row, i_col]
|
||||
var node = nodes[node_key]
|
||||
var node_key: String = NODE_KEY_FORMAT % [i_row, i_col]
|
||||
var node = nodes[node_key]
|
||||
|
||||
var conn = get_node_meta(i_col, i_row, 'callable_focus_entered')
|
||||
node.disconnect('focus_entered', conn)
|
||||
var conn = get_node_meta(i_col, i_row, 'callable_focus_entered')
|
||||
node.disconnect('focus_entered', conn)
|
||||
|
||||
if node.has_meta(META_CALLABLE):
|
||||
conn = node.get_meta(META_CALLABLE)
|
||||
var event_name = node.get_meta(META_EVENT_NAME)
|
||||
node.disconnect(event_name, conn)
|
||||
if node.has_meta(META_CALLABLE):
|
||||
conn = node.get_meta(META_CALLABLE)
|
||||
var event_name = node.get_meta(META_EVENT_NAME)
|
||||
node.disconnect(event_name, conn)
|
||||
|
||||
remove_child(node)
|
||||
nodes.erase(node_key)
|
||||
node.queue_free()
|
||||
rehash()
|
||||
remove_child(node)
|
||||
nodes.erase(node_key)
|
||||
node.queue_free()
|
||||
rehash()
|
||||
|
||||
|
||||
##
|
||||
func next_index(indexes: Array) -> void:
|
||||
indexes[0].x += 1
|
||||
if indexes[0].x == columns:
|
||||
indexes[0].x = 0
|
||||
indexes[0].y += 1
|
||||
indexes[0].x += 1
|
||||
if indexes[0].x == columns:
|
||||
indexes[0].x = 0
|
||||
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]
|
||||
nodes_copy[key1] = nodes[key0]
|
||||
nodes_copy[key1].name = key1
|
||||
var key0 = node_key_format % [i0.y, i0.x]
|
||||
var key1 = node_key_format % [i1.y, i1.x]
|
||||
nodes_copy[key1] = nodes[key0]
|
||||
nodes_copy[key1].name = key1
|
||||
|
||||
|
||||
## Переназначает ключи в соответствии с размерами таблицы.
|
||||
func rehash():
|
||||
var i_node: = [Vector2i()]
|
||||
var i_hdr: = [Vector2i()]
|
||||
var i_slct: = [Vector2i()]
|
||||
var nodes_copy = {}
|
||||
for key in nodes:
|
||||
var iv = get_key_indexes(key)
|
||||
var i0 = Vector2(iv[0], iv[1])
|
||||
if HEAD_PREFIX in key:
|
||||
swap_nodes(nodes_copy, HEAD_KEY_FORMAT, i0, i_hdr[0])
|
||||
next_index(i_hdr)
|
||||
elif NODE_PREFIX in key:
|
||||
swap_nodes(nodes_copy, NODE_KEY_FORMAT, i0, i_node[0])
|
||||
next_index(i_node)
|
||||
elif SLCT_PREFIX in key:
|
||||
swap_nodes(nodes_copy, SELECTOR_KEY_FORMAT, i0, i_slct[0])
|
||||
next_index(i_slct)
|
||||
nodes.clear()
|
||||
nodes.merge(nodes_copy)
|
||||
var i_node: = [Vector2i()]
|
||||
var i_hdr: = [Vector2i()]
|
||||
var i_slct: = [Vector2i()]
|
||||
var nodes_copy = {}
|
||||
for key in nodes:
|
||||
var iv = get_key_indexes(key)
|
||||
var i0 = Vector2(iv[0], iv[1])
|
||||
if HEAD_PREFIX in key:
|
||||
swap_nodes(nodes_copy, HEAD_KEY_FORMAT, i0, i_hdr[0])
|
||||
next_index(i_hdr)
|
||||
elif NODE_PREFIX in key:
|
||||
swap_nodes(nodes_copy, NODE_KEY_FORMAT, i0, i_node[0])
|
||||
next_index(i_node)
|
||||
elif SLCT_PREFIX in key:
|
||||
swap_nodes(nodes_copy, SELECTOR_KEY_FORMAT, i0, i_slct[0])
|
||||
next_index(i_slct)
|
||||
nodes.clear()
|
||||
nodes.merge(nodes_copy)
|
||||
|
||||
|
||||
## Удаляет все строки таблицы
|
||||
func clear_rows() -> void:
|
||||
var rows_count: int = get_rows_count()
|
||||
for i_row in range(rows_count - 1, -1, -1):
|
||||
remove_row(i_row)
|
||||
var rows_count: int = get_rows_count()
|
||||
for i_row in range(rows_count - 1, -1, -1):
|
||||
remove_row(i_row)
|
||||
|
||||
|
||||
## Настраевает обратные вызовы для колонок.[br]
|
||||
@@ -512,57 +512,57 @@ func clear_rows() -> void:
|
||||
## [param clmns] - Индексы колонок[br]
|
||||
## [param user_data] - Аргументы функции получателя события[br]
|
||||
func connect_columns(dest_node: Node, event_name: String, callback: String, clmns: Array, user_data: Array = []) -> void:
|
||||
var rows_count = get_rows_count()
|
||||
for i_row in rows_count:
|
||||
for i_col in clmns:
|
||||
assert(i_col >= 0 and i_col < columns, 'ошибка: нет такой колонки: %d' % i_col)
|
||||
var node = get_node2(i_col, i_row)
|
||||
if node.has_meta(META_CALLABLE):
|
||||
var conn_prev = node.get_meta(META_CALLABLE)
|
||||
node.disconnect(event_name, conn_prev)
|
||||
var conn = Callable(dest_node, callback).bind([node] + user_data)
|
||||
var rc = node.connect(event_name, conn)
|
||||
if rc == Error.OK:
|
||||
node.set_meta(META_CALLABLE, conn)
|
||||
node.set_meta(META_EVENT_NAME, event_name)
|
||||
else:
|
||||
var es = error_string(rc)
|
||||
push_error('ошибка: событие \"%s\" не может быть подключено к %s: %s' % [event_name, node, es])
|
||||
var rows_count = get_rows_count()
|
||||
for i_row in rows_count:
|
||||
for i_col in clmns:
|
||||
assert(i_col >= 0 and i_col < columns, 'ошибка: нет такой колонки: %d' % i_col)
|
||||
var node = get_node2(i_col, i_row)
|
||||
if node.has_meta(META_CALLABLE):
|
||||
var conn_prev = node.get_meta(META_CALLABLE)
|
||||
node.disconnect(event_name, conn_prev)
|
||||
var conn = Callable(dest_node, callback).bind([node] + user_data)
|
||||
var rc = node.connect(event_name, conn)
|
||||
if rc == Error.OK:
|
||||
node.set_meta(META_CALLABLE, conn)
|
||||
node.set_meta(META_EVENT_NAME, event_name)
|
||||
else:
|
||||
var es = error_string(rc)
|
||||
push_error('ошибка: событие \"%s\" не может быть подключено к %s: %s' % [event_name, node, es])
|
||||
|
||||
|
||||
##
|
||||
func set_rows_text(rows: Array) -> void:
|
||||
for i_row in rows.size():
|
||||
for i_col in columns:
|
||||
var key: = get_node_key(NODE_KEY_FORMAT, i_col, i_row)
|
||||
var node = nodes[key]
|
||||
node.text = rows[i_row][i_col]
|
||||
for i_row in rows.size():
|
||||
for i_col in columns:
|
||||
var key: = get_node_key(NODE_KEY_FORMAT, i_col, i_row)
|
||||
var node = nodes[key]
|
||||
node.text = rows[i_row][i_col]
|
||||
|
||||
|
||||
## [param i_row] - Индекс ряда.
|
||||
func set_nodes_min_size(i_row: int, sizes: Array, key_format: String = NODE_KEY_FORMAT) -> void:
|
||||
columns_min_size.clear()
|
||||
for sz in sizes:
|
||||
columns_min_size.append(sz)
|
||||
for i_col in columns:
|
||||
var key: = get_node_key(key_format, i_col, i_row)
|
||||
var node = nodes[key]
|
||||
node.custom_minimum_size.x = sizes[i_col]
|
||||
node.set_deferred('size.x', sizes[i_col])
|
||||
columns_min_size.clear()
|
||||
for sz in sizes:
|
||||
columns_min_size.append(sz)
|
||||
for i_col in columns:
|
||||
var key: = get_node_key(key_format, i_col, i_row)
|
||||
var node = nodes[key]
|
||||
node.custom_minimum_size.x = sizes[i_col]
|
||||
node.set_deferred('size.x', sizes[i_col])
|
||||
|
||||
|
||||
## [param i_col] - Индекс колонки.[br][param i_row] - Индекс ряда.
|
||||
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
|
||||
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:
|
||||
var key: = get_node_key(NODE_KEY_FORMAT, i_col, i_row)
|
||||
nodes[key].button_pressed = rows[i_row][i_col]
|
||||
for i_row in rows.size():
|
||||
for i_col in columns:
|
||||
var key: = get_node_key(NODE_KEY_FORMAT, i_col, i_row)
|
||||
nodes[key].button_pressed = rows[i_row][i_col]
|
||||
|
||||
|
||||
## Устанавливает состояние ячейки.
|
||||
@@ -571,59 +571,59 @@ func set_rows_state(rows: Array) -> void:
|
||||
## [param val] - Новое состояние.[br]
|
||||
## [i]Ячейка должна иметь свойство[/i] [param button_pressed]
|
||||
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
|
||||
var key: = get_node_key(NODE_KEY_FORMAT, i_col, i_row)
|
||||
nodes[key].button_pressed = val
|
||||
|
||||
|
||||
## [param i_col] - Индекс колонки.[br]
|
||||
## [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]
|
||||
var sprite = node.get_node(node_name)
|
||||
sprite.frame = val
|
||||
var key: = get_node_key(NODE_KEY_FORMAT, i_col, i_row)
|
||||
var node = nodes[key]
|
||||
var sprite = node.get_node(node_name)
|
||||
sprite.frame = val
|
||||
|
||||
|
||||
## Разрешает редактирование ячейки. Ячейка должна иметь свойство [param editable].[br]
|
||||
## [param i_col] - Индекс колонки.[br]
|
||||
## [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
|
||||
var key: = get_node_key(NODE_KEY_FORMAT, i_col, i_row)
|
||||
nodes[key].editable = val
|
||||
|
||||
|
||||
## Разрешает редактирование ряда. Ячейки ряда должны иметь свойство [param editable].[br]
|
||||
## [param i_row] - Индекс ряда.
|
||||
func set_row_editable(i_row: int, val: bool) -> void:
|
||||
for i_col in columns:
|
||||
var key: = get_node_key(NODE_KEY_FORMAT, i_col, i_row)
|
||||
nodes[key].editable = val
|
||||
for i_col in columns:
|
||||
var key: = get_node_key(NODE_KEY_FORMAT, i_col, i_row)
|
||||
nodes[key].editable = val
|
||||
|
||||
|
||||
## [param i_col] - Индекс колонки.[br]
|
||||
## [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]:
|
||||
nodes[key].horizontal_alignment = val
|
||||
elif 'alignment' in nodes[key]:
|
||||
nodes[key].alignment = val
|
||||
var key: = get_node_key(NODE_KEY_FORMAT, i_col, i_row)
|
||||
if 'horizontal_alignment' in nodes[key]:
|
||||
nodes[key].horizontal_alignment = val
|
||||
elif 'alignment' in nodes[key]:
|
||||
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]
|
||||
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:
|
||||
var key: = get_node_key(NODE_KEY_FORMAT, i_col, i_row)
|
||||
row.append(nodes[key].text)
|
||||
return row
|
||||
var row: = []
|
||||
for i_col in columns:
|
||||
var key: = get_node_key(NODE_KEY_FORMAT, i_col, i_row)
|
||||
row.append(nodes[key].text)
|
||||
return row
|
||||
|
||||
|
||||
## Устанавливает текст ячеек ряда.[br]
|
||||
@@ -632,51 +632,51 @@ func get_row_text(i_row: int) -> Array:
|
||||
## [param i_begin] - Начальный индекс колонки начиная с которого установить новые значения.[br]
|
||||
## [i]Ячейки ряда должны иметь свойство[/i] [param text]
|
||||
func set_row_text(i_row: int, row: Array, i_begin: int = 0, key_format: String = NODE_KEY_FORMAT) -> void:
|
||||
assert((i_begin >= 0) and (i_begin < columns))
|
||||
assert((columns - i_begin) >= row.size())
|
||||
for i_col in row.size():
|
||||
var key: = get_node_key(key_format, i_col + i_begin, i_row)
|
||||
nodes[key].text = row[i_col]
|
||||
assert((i_begin >= 0) and (i_begin < columns))
|
||||
assert((columns - i_begin) >= row.size())
|
||||
for i_col in row.size():
|
||||
var key: = get_node_key(key_format, i_col + i_begin, i_row)
|
||||
nodes[key].text = row[i_col]
|
||||
|
||||
|
||||
## Возвращает все строки таблицы в двумерном массиве
|
||||
func get_rows_text() -> Array:
|
||||
var rows_count: = get_rows_count()
|
||||
var rows: = []
|
||||
for i_row in rows_count:
|
||||
var row = get_row_text(i_row)
|
||||
rows.append(row)
|
||||
return rows
|
||||
var rows_count: = get_rows_count()
|
||||
var rows: = []
|
||||
for i_row in rows_count:
|
||||
var row = get_row_text(i_row)
|
||||
rows.append(row)
|
||||
return rows
|
||||
|
||||
|
||||
## Возвращает массив ячеек из ряда [param i_row]
|
||||
func get_row(i_row: int) -> Array:
|
||||
var row: = []
|
||||
for i_col in columns:
|
||||
var key: = get_node_key(NODE_KEY_FORMAT, i_col, i_row)
|
||||
row.append(nodes[key])
|
||||
return row
|
||||
var row: = []
|
||||
for i_col in columns:
|
||||
var key: = get_node_key(NODE_KEY_FORMAT, i_col, i_row)
|
||||
row.append(nodes[key])
|
||||
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)
|
||||
var cell = nodes[key]
|
||||
rect[0] = cell.position.x
|
||||
rect[1] = cell.position.y
|
||||
rect[2] = cell.size.x
|
||||
rect[3] = cell.size.y
|
||||
assert(rect.size() >= 4, 'ошибка: мало элементов для возврата результата')
|
||||
var key: = get_node_key(key_format, i_col, i_row)
|
||||
var cell = nodes[key]
|
||||
rect[0] = cell.position.x
|
||||
rect[1] = cell.position.y
|
||||
rect[2] = cell.size.x
|
||||
rect[3] = cell.size.y
|
||||
|
||||
|
||||
## Возвращает прямоугольник [param rect] занимаемый рядом [param i_row].[br]
|
||||
## [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)]
|
||||
var cell1 = nodes[get_node_key(key_format, columns - 1, i_row)]
|
||||
rect[0] = cell0.position.x + scroll_adj.x
|
||||
rect[1] = cell0.position.y + scroll_adj.y
|
||||
rect[2] = (cell1.position.x - cell0.position.x) + cell1.size.x
|
||||
rect[3] = cell0.size.y
|
||||
assert(rect.size() >= 4, 'ошибка: мало элементов для возврата результата')
|
||||
var cell0 = nodes[get_node_key(key_format, 0, i_row)]
|
||||
var cell1 = nodes[get_node_key(key_format, columns - 1, i_row)]
|
||||
rect[0] = cell0.position.x + scroll_adj.x
|
||||
rect[1] = cell0.position.y + scroll_adj.y
|
||||
rect[2] = (cell1.position.x - cell0.position.x) + cell1.size.x
|
||||
rect[3] = cell0.size.y
|
||||
|
||||
Reference in New Issue
Block a user