You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
143 lines
3.3 KiB
143 lines
3.3 KiB
extends Tree
|
|
|
|
|
|
const TEXT_COLUMN := 0
|
|
|
|
|
|
# section == 0 if dropping on item
|
|
# section == -1 if dropping above item
|
|
# section == +1 if dropping below item
|
|
signal item_moved(item, to_item, section)
|
|
|
|
|
|
var invite_text = "+"
|
|
|
|
|
|
func _ready():
|
|
setup()
|
|
setup_dummy_items()
|
|
append_item_invitation()
|
|
|
|
|
|
func setup():
|
|
var root := create_item()
|
|
root.set_text(TEXT_COLUMN, "Candidates")
|
|
|
|
var _c
|
|
_c = connect("item_edited", self, "__on_item_edited")
|
|
_c = connect("item_moved", self, "__on_item_moved")
|
|
|
|
|
|
func setup_dummy_items():
|
|
create_candidate_item("Candidate A")
|
|
create_candidate_item("Candidate B")
|
|
create_candidate_item("Candidate C")
|
|
|
|
|
|
func create_candidate_item(__name:String):
|
|
var candidate_item := create_item()
|
|
candidate_item.set_editable(TEXT_COLUMN, true)
|
|
candidate_item.set_text(TEXT_COLUMN, __name)
|
|
|
|
|
|
func append_item_invitation():
|
|
var root = get_root()
|
|
var items = __get_children_items(root)
|
|
|
|
if items and items.back().get_text(TEXT_COLUMN) == invite_text:
|
|
return
|
|
|
|
var invite = create_item(root)
|
|
invite.set_editable(TEXT_COLUMN, true)
|
|
invite.set_text(TEXT_COLUMN, invite_text)
|
|
invite.move_to_bottom() # superfluous
|
|
|
|
|
|
func prune_empty_items():
|
|
for item in __get_children_items(get_root()):
|
|
if item.get_text(TEXT_COLUMN) == '':
|
|
if item.get_next():
|
|
item.get_next().select(TEXT_COLUMN)
|
|
ensure_cursor_is_visible()
|
|
item.free()
|
|
|
|
|
|
func prune_extra_items():
|
|
for item in __get_children_items(get_root()):
|
|
if item.get_text(TEXT_COLUMN) == invite_text:
|
|
if item.get_next():
|
|
item.free()
|
|
|
|
|
|
func __on_item_edited():
|
|
append_item_invitation()
|
|
|
|
var selected = get_next_selected(null)
|
|
if selected and selected.get_next():
|
|
selected.get_next().select(TEXT_COLUMN)
|
|
ensure_cursor_is_visible()
|
|
|
|
prune_empty_items() # after, since it may change item selection
|
|
|
|
|
|
func __on_item_moved(item, to_item, section):
|
|
if not to_item:
|
|
printerr("No item unto which to drop. Weird.")
|
|
var offset = 0 if section <= 0 else 1
|
|
var new_item = create_item(get_root(), __get_item_index(to_item)+offset)
|
|
new_item.set_text(TEXT_COLUMN, item.get_text(TEXT_COLUMN))
|
|
new_item.set_editable(TEXT_COLUMN, true)
|
|
new_item.select(TEXT_COLUMN)
|
|
item.free()
|
|
prune_extra_items()
|
|
append_item_invitation()
|
|
ensure_cursor_is_visible()
|
|
|
|
|
|
func __get_children_items(parent:TreeItem) -> Array:
|
|
var items := Array()
|
|
var item = parent.get_children()
|
|
while (item):
|
|
items.append(item)
|
|
item = item.get_next()
|
|
return items
|
|
|
|
|
|
func __get_item_index(of_item:TreeItem):
|
|
var parent = of_item.get_parent()
|
|
assert(parent) # or return … what, zero?
|
|
var index := 0
|
|
var item : TreeItem = parent.get_children()
|
|
while (item):
|
|
if item == of_item:
|
|
return index
|
|
item = item.get_next()
|
|
index += 1
|
|
assert(false, "Item not found")
|
|
return -1
|
|
|
|
|
|
func get_drag_data(_position) -> TreeItem:
|
|
set_drop_mode_flags(DROP_MODE_INBETWEEN)
|
|
|
|
var item_preview = Label.new()
|
|
item_preview.text = get_selected().get_text(TEXT_COLUMN)
|
|
set_drag_preview(item_preview)
|
|
|
|
return get_selected()
|
|
|
|
|
|
func can_drop_data(_position, data):
|
|
return data is TreeItem
|
|
|
|
|
|
func drop_data(position, item):
|
|
var to_item = get_item_at_position(position)
|
|
var section = get_drop_section_at_position(position)
|
|
if not to_item or section == -100:
|
|
#printerr("Dropping in the void")
|
|
to_item = get_root().get_children()
|
|
section = 0
|
|
|
|
emit_signal('item_moved', item, to_item, section)
|